/* ==========================================================================
   POKIT DESIGN SYSTEM
   --------------------------------------------------------------------------
   Source of truth: pokit-ui.html

   This file is purely additive. It introduces the Pokit tokens as CSS
   custom properties, a small `pk-*` component vocabulary used by the
   restyled templates, and a layer of global polish that upgrades existing
   markup without renaming a single hook that JavaScript or htmx relies on.

   All global element rules are written with :where() so they carry zero
   specificity and can never out-rank a Tailwind utility that a template
   deliberately applied.
   ========================================================================== */

:root {
  --pk-coral: #F4845F;
  --pk-coral-600: #E26A43;
  --pk-coral-50: #FEF4EF;
  --pk-coral-100: #FDE5DA;
  --pk-coral-200: #FAC8B4;
  --pk-sand: #C9A487;
  --pk-sand-50: #FAF6F2;
  --pk-mint: #7ECBB4;
  --pk-mint-600: #5BB298;
  --pk-mint-50: #EFF9F6;
  --pk-ink: #262626;
  --pk-ink-700: #454545;
  --pk-ink-500: #6B6B6B;
  --pk-ink-400: #8E8E8E;
  --pk-ink-300: #BDBDBD;
  --pk-ink-200: #E4E4E2;
  --pk-ink-100: #F1F1EF;
  --pk-canvas: #FCFCFA;
  --pk-gradient: linear-gradient(90deg, #F4845F 0%, #C9A487 50%, #7ECBB4 100%);
  --pk-shadow-soft: 0 1px 2px rgba(38, 38, 38, .04), 0 4px 16px rgba(38, 38, 38, .06);
  --pk-shadow-lift: 0 2px 4px rgba(38, 38, 38, .04), 0 12px 32px rgba(38, 38, 38, .10);
  --pk-shadow-glow: 0 0 0 4px rgba(244, 132, 95, .15);

  /* DaisyUI-compatible surface tokens, consumed by the `base-*` Tailwind colours
     as `rgb(var(...) / <alpha-value>)`. Stored as bare RGB triplets for that to
     work. ~60 legacy `bg-base-*` / `text-base-content` usages resolve through
     these, and they flip automatically in dark mode. */
  --pk-base-100: 255 255 255;      /* card surface      */
  --pk-base-200: 252 252 250;      /* canvas            */
  --pk-base-300: 228 228 226;      /* border / raised   */
  --pk-base-content: 38 38 38;     /* body text         */
}

.dark {
  --pk-base-100: 38 38 38;         /* ink-900           */
  --pk-base-200: 26 26 24;         /* ink-950           */
  --pk-base-300: 70 70 68;         /* border / raised   */
  --pk-base-content: 228 228 226;  /* ink-200           */
}

/* Native <dialog> safety net.
   The browser hides a closed dialog with `dialog:not([open]) { display: none }`
   from its UA stylesheet, but that is only a UA rule: any author utility such as
   `flex` or `grid` on the dialog element out-ranks it and leaves the closed modal
   permanently painted over the page. This restores the expected behaviour with
   higher specificity (0,1,1) than a plain `.flex` (0,1,0), so a dialog is hidden
   until it is actually opened. `showModal()`, the `open` attribute and inline
   `style.display` all keep working.
   Note: no `dialog[open]` rule is set on purpose - several dialogs lay themselves
   out with margin auto / their own display, and forcing flex on all of them would
   change their geometry. Dialogs that want flex centering opt in with `open:flex`. */
dialog:not([open]) {
  display: none;
}

/* --------------------------------------------------------------------------
   Global polish
   -------------------------------------------------------------------------- */

/* NOTE: `html { scroll-behavior: smooth }` is deliberately NOT set globally.
   The style guide has it, but applying it here would change how every existing
   programmatic scroll in the app behaves (chat auto-scroll, scrollIntoView on
   validation errors, anchor jumps). The chat pane already opts in on its own. */

:where(body) {
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection {
  background: var(--pk-coral-100);
  color: var(--pk-ink);
}

/* Warm, thin scrollbars everywhere (replaces the browser default grey).
   Pseudo-elements cannot live inside :where(), so these stay plain. */
:where(*) {
  scrollbar-width: thin;
  scrollbar-color: var(--pk-ink-200) transparent;
}

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--pk-ink-200);
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--pk-ink-300);
}

.dark ::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .12);
}

/* Form controls: Pokit rounding + coral focus glow.
   :where() keeps specificity at zero so any Tailwind utility still wins. */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="submit"]):not([type="button"]),
  select,
  textarea) {
  border-radius: 0.75rem;
}

:where(input, select, textarea):focus {
  outline: none;
}

:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"])):focus,
:where(select):focus,
:where(textarea):focus {
  border-color: var(--pk-coral);
  box-shadow: var(--pk-shadow-glow);
}

/* The chat composer opts out of the rule above entirely. Its textarea sits inside a
   surface that draws its own border, so the app-wide coral focus ring landed as a
   second orange ring right around the caret. Excluding it by selector is deliberate:
   an override declared later loses the specificity fight against `focus:ring-*`
   utilities, whereas never matching cannot. */
:where(textarea.pk-plain-focus):focus,
:where(input.pk-plain-focus):focus {
  border-color: inherit !important;
  box-shadow: none !important;
}

:where(input, textarea)::placeholder {
  color: var(--pk-ink-300);
}
/* Native controls pick up the brand colour. */
:where(input[type="checkbox"], input[type="radio"], input[type="range"], progress) {
  accent-color: var(--pk-coral);
}

/* Keyboard focus stays visible for accessibility, in brand colour. */
:where(a, button, [role="button"], summary):focus-visible {
  outline: 2px solid var(--pk-coral);
  outline-offset: 2px;
  border-radius: 0.5rem;
}

/* Smooth, restrained motion on interactive chrome. */
:where(button, a, [role="button"]) {
  transition-property: background-color, border-color, color, box-shadow, opacity, transform;
  transition-duration: 150ms;
  transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}

/* Anchors default to the brand colour when a template didn't style them. */
.dark :where(a) {
  color: inherit;
}

/* --------------------------------------------------------------------------
   Brand helpers
   -------------------------------------------------------------------------- */

.text-pokit {
  background: var(--pk-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.bg-pokit {
  background: var(--pk-gradient);
}

.border-pokit {
  border: 1.5px solid transparent;
  background:
    linear-gradient(#fff, #fff) padding-box,
    var(--pk-gradient) border-box;
}

.dark .border-pokit {
  background:
    linear-gradient(#262626, #262626) padding-box,
    var(--pk-gradient) border-box;
}

.shadow-soft {
  box-shadow: var(--pk-shadow-soft);
}

.shadow-lift {
  box-shadow: var(--pk-shadow-lift);
}

.shadow-glow {
  box-shadow: var(--pk-shadow-glow);
}

@keyframes pk-blob {

  0%,
  100% {
    transform: translate(0, 0) scale(1);
  }

  50% {
    transform: translate(1px, -1px) scale(1.05);
  }
}

.animate-blob {
  animation: pk-blob 4s ease-in-out infinite;
}

@keyframes pk-dots {

  0%,
  80%,
  100% {
    opacity: .25;
  }

  40% {
    opacity: 1;
  }
}

.typing span {
  animation: pk-dots 1.2s infinite;
}

.typing span:nth-child(2) {
  animation-delay: .15s;
}

.typing span:nth-child(3) {
  animation-delay: .3s;
}

/* --------------------------------------------------------------------------
   Transient notifications: #toast-container and #llm-status
   --------------------------------------------------------------------------
   Both slots live inside one fixed "notification rail" in base.html (see the
   markup there). They are styled by *id* here because several callers rewrite
   the element's own class attribute - #llm-status in particular is written to
   from dozens of streaming status paths.

   #toast-container uses display:contents so its toasts become direct children of
   the shared rail; that way toasts and status messages stack in one column and
   can never sit on top of each other. */

#toast-container {
  display: contents;
}

#llm-status {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
  min-width: 0;
}

/* Collapse completely when there is nothing to show, so the rail is inert. */
#llm-status:empty {
  display: none;
}

#toast-container>*,
#llm-status>* {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  pointer-events: auto;
}

@media (min-width: 640px) {

  #toast-container>*,
  #llm-status>* {
    width: auto;
  }
}

/* --------------------------------------------------------------------------
   pk-* COMPONENTS
   Used by the restyled templates. Everything here is opt-in.
   ========================================================================== */

/* ── Cards & surfaces ───────────────────────────────────────────────────── */

.pk-card {
  background: #fff;
  border: 1px solid var(--pk-ink-200);
  border-radius: 1rem;
  box-shadow: var(--pk-shadow-soft);
}

.pk-card-lg {
  border-radius: 1.5rem;
}

.pk-card-hover {
  transition: border-color .2s, box-shadow .2s, transform .2s;
}

.pk-card-hover:hover {
  border-color: var(--pk-coral-200, #FAC8B4);
  box-shadow: var(--pk-shadow-lift);
}

.pk-surface {
  background: var(--pk-canvas);
  border: 1px solid var(--pk-ink-200);
  border-radius: 1rem;
}

.dark .pk-card,
.dark .pk-surface {
  background: #262626;
  border-color: rgba(255, 255, 255, .08);
}

/* ── Buttons ────────────────────────────────────────────────────────────── */

.pk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .625rem 1rem;
  border-radius: .75rem;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  color: var(--pk-ink);
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, transform .15s;
}

.pk-btn:active {
  transform: scale(.98);
}

.pk-btn:disabled,
.pk-btn[disabled] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
}

.pk-btn-primary {
  background: var(--pk-coral);
  color: #fff;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-btn-primary:hover {
  background: var(--pk-coral-600);
}

.pk-btn-grad {
  background: var(--pk-gradient);
  color: #fff;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-btn-grad:hover {
  filter: brightness(1.04);
}

.pk-btn-secondary {
  background: #fff;
  border-color: var(--pk-ink-200);
  color: var(--pk-ink);
}

.pk-btn-secondary:hover {
  background: var(--pk-ink-100);
}

.dark .pk-btn-secondary {
  background: transparent;
  border-color: rgba(255, 255, 255, .12);
  color: #E4E4E2;
}

.dark .pk-btn-secondary:hover {
  background: rgba(255, 255, 255, .06);
}

.pk-btn-ghost {
  color: var(--pk-ink-700);
}

.pk-btn-ghost:hover {
  background: var(--pk-ink-100);
}

.dark .pk-btn-ghost {
  color: #BDBDBD;
}

.dark .pk-btn-ghost:hover {
  background: rgba(255, 255, 255, .06);
}

.pk-btn-deploy {
  background: var(--pk-mint);
  color: #fff;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-btn-deploy:hover {
  background: var(--pk-mint-600);
}

.pk-btn-danger {
  background: #fff;
  border-color: #FECACA;
  color: #DC2626;
}

.pk-btn-danger:hover {
  background: #FEF2F2;
}

.pk-btn-icon {
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border-radius: .75rem;
  border-color: var(--pk-ink-200);
}

.pk-btn-sm {
  padding: .4rem .7rem;
  font-size: .75rem;
  border-radius: .6rem;
}

.pk-btn-lg {
  padding: .75rem 1.25rem;
  font-size: .875rem;
}

/* ── Inputs ─────────────────────────────────────────────────────────────── */

.pk-input {
  width: 100%;
  padding: .625rem .875rem;
  border-radius: .75rem;
  border: 1px solid var(--pk-ink-200);
  background: #fff;
  color: var(--pk-ink);
  font-size: .875rem;
}

.pk-input::placeholder {
  color: var(--pk-ink-300);
}

.pk-input:focus {
  outline: none;
  border-color: var(--pk-coral);
  box-shadow: var(--pk-shadow-glow);
}

.dark .pk-input {
  background: #1A1A18;
  border-color: rgba(255, 255, 255, .10);
  color: #F1F1EF;
}

.pk-label {
  display: block;
  font-size: .8125rem;
  font-weight: 500;
  color: var(--pk-ink);
  margin-bottom: .375rem;
}

.dark .pk-label {
  color: #E4E4E2;
}

.pk-hint {
  font-size: .75rem;
  color: var(--pk-ink-400);
  margin-top: .25rem;
}

/* ── Badges / status pills ──────────────────────────────────────────────── */

.pk-badge {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: .25rem .625rem;
  border-radius: 999px;
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.pk-badge-live {
  background: var(--pk-mint-50);
  color: #428C76;
}

.pk-badge-build {
  background: var(--pk-sand-50);
  color: #8A6A52;
}

.pk-badge-draft {
  background: var(--pk-coral-50);
  color: #BC5332;
}

.pk-badge-fail {
  background: #FEF2F2;
  color: #DC2626;
}

.pk-badge-muted {
  background: var(--pk-ink-100);
  color: var(--pk-ink-500);
}

/* Dark mode: pastel 50-shade backgrounds are far too bright on an ink surface,
   so the pills switch to a translucent tint of their accent colour. */
.dark .pk-badge-live {
  background: rgba(126, 203, 180, .16);
  color: #9AD7C5;
}

.dark .pk-badge-build {
  background: rgba(201, 164, 135, .18);
  color: #DCC4AF;
}

.dark .pk-badge-draft {
  background: rgba(244, 132, 95, .16);
  color: #F9B49A;
}

.dark .pk-badge-fail {
  background: rgba(239, 68, 68, .16);
  color: #FCA5A5;
}

.dark .pk-alert-success {
  background: rgba(126, 203, 180, .12);
  border-color: rgba(126, 203, 180, .30);
  color: #DAF1EA;
}

.dark .pk-alert-warn {
  background: rgba(201, 164, 135, .12);
  border-color: rgba(201, 164, 135, .30);
  color: #F2E9E0;
}

.dark .pk-alert-error {
  background: rgba(239, 68, 68, .12);
  border-color: rgba(239, 68, 68, .30);
  color: #FEE2E2;
}

.dark .pk-alert-info {
  background: rgba(244, 132, 95, .12);
  border-color: rgba(244, 132, 95, .30);
  color: #FDE5DA;
}

.dark .pk-badge-muted {
  background: rgba(255, 255, 255, .08);
  color: #BDBDBD;
}

.pk-dot {
  width: .375rem;
  height: .375rem;
  border-radius: 999px;
  flex-shrink: 0;
}

.pk-dot-live {
  background: var(--pk-mint);
}

.pk-dot-build {
  background: var(--pk-sand);
}

.pk-dot-draft {
  background: var(--pk-coral);
}

.pk-dot-fail {
  background: #EF4444;
}

.pk-chip {
  display: inline-flex;
  align-items: center;
  padding: .125rem .5rem;
  border-radius: .375rem;
  background: var(--pk-ink-100);
  color: var(--pk-ink-700);
  font-size: .75rem;
}

.dark .pk-chip {
  background: rgba(255, 255, 255, .08);
  color: #E4E4E2;
}

.pk-kbd {
  display: inline-flex;
  align-items: center;
  padding: .125rem .5rem;
  border-radius: .375rem;
  border: 1px solid var(--pk-ink-200);
  color: var(--pk-ink-500);
  font-size: .75rem;
  font-family: "JetBrains Mono", ui-monospace, monospace;
}

/* ── Avatars ────────────────────────────────────────────────────────────── */

.pk-avatar {
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-weight: 700;
  color: #fff;
  background: var(--pk-gradient);
  flex-shrink: 0;
}

.pk-avatar-soft {
  background: var(--pk-mint-100);
  color: #428C76;
}

/* ── Alerts ─────────────────────────────────────────────────────────────── */

.pk-alert {
  display: flex;
  gap: .75rem;
  padding: .875rem;
  border-radius: .75rem;
  font-size: .8125rem;
  border: 1px solid transparent;
}

.pk-alert-success {
  background: var(--pk-mint-50);
  border-color: #B6E3D5;
}

.pk-alert-warn {
  background: var(--pk-sand-50);
  border-color: #E5D3C2;
}

.pk-alert-error {
  background: #FEF2F2;
  border-color: #FECACA;
}

.pk-alert-info {
  background: var(--pk-coral-50);
  border-color: #FAC8B4;
}

/* ── Empty states ───────────────────────────────────────────────────────── */

.pk-empty {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 2rem 1.5rem;
}

.pk-empty-mark {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 1rem;
  background: var(--pk-ink-100);
  display: grid;
  place-items: center;
  margin: 0 auto .75rem;
}

.dark .pk-empty-mark {
  background: rgba(255, 255, 255, .08);
}

/* ── Skeleton / loading ─────────────────────────────────────────────────── */

.pk-skel {
  background: var(--pk-ink-100);
  border-radius: .375rem;
  animation: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
}

.dark .pk-skel {
  background: rgba(255, 255, 255, .08);
}

.pk-progress {
  height: .375rem;
  border-radius: 999px;
  background: var(--pk-ink-100);
  overflow: hidden;
}

.pk-progress>span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--pk-gradient);
}

/* ── Code / log panels ──────────────────────────────────────────────────── */

.pk-code {
  background: var(--pk-ink);
  color: rgba(255, 255, 255, .9);
  border-radius: .75rem;
  overflow: hidden;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .8125rem;
}

.pk-code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .5rem 1rem;
  background: rgba(255, 255, 255, .05);
  color: rgba(255, 255, 255, .6);
  font-size: .75rem;
}

/* ── Toast ──────────────────────────────────────────────────────────────── */

.pk-toast {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .75rem 1rem;
  border-radius: .75rem;
  background: var(--pk-ink);
  color: #fff;
  font-size: .8125rem;
  box-shadow: var(--pk-shadow-lift);
}

/* ── Chat bubbles ───────────────────────────────────────────────────────── */

.pk-bubble-user {
  background: var(--pk-coral);
  color: #fff;
  border-radius: 1rem 1rem .375rem 1rem;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-bubble-ai {
  background: #fff;
  border: 1px solid var(--pk-ink-200);
  border-radius: 1rem 1rem 1rem .375rem;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.dark .pk-bubble-ai {
  background: #262626;
  border-color: rgba(255, 255, 255, .08);
}

/* ── Section headings ───────────────────────────────────────────────────── */

.pk-eyebrow {
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--pk-ink-400);
  margin-bottom: .5rem;
}

.pk-page-title {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--pk-ink);
}

.dark .pk-page-title {
  color: #F1F1EF;
}

.pk-muted {
  color: var(--pk-ink-500);
  font-size: .8125rem;
}

/* ── Settings nav ─────────────────────────────────────────────────────────
   The style guide's account sidebar (pokit-ui.html §08): a quiet column of
   text rows on the canvas, the current one lifted onto a white card with a
   coral tick. Implemented as classes rather than a pile of toggleable
   utilities because the active row is switched from JavaScript after every
   htmx section swap, and toggling eight Tailwind classes per row (what the
   profile page used to do) is one renamed utility away from leaving two rows
   looking selected at once. */

.pk-nav-item {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  padding: .5rem .75rem;
  border-radius: .75rem;
  border: 1px solid transparent;
  background: transparent;
  color: var(--pk-ink-500);
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.25rem;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s;
}

.pk-nav-item:hover {
  background: var(--pk-ink-100);
  color: var(--pk-ink);
}

.pk-nav-item .pk-nav-mark {
  width: .375rem;
  height: 1rem;
  border-radius: 999px;
  background: transparent;
  flex-shrink: 0;
  transition: background-color .15s;
}

.pk-nav-item.is-active {
  background: #fff;
  border-color: var(--pk-ink-200);
  color: var(--pk-ink);
  font-weight: 600;
  box-shadow: var(--pk-shadow-soft);
}

.pk-nav-item.is-active .pk-nav-mark {
  background: var(--pk-coral);
}

.pk-nav-item:focus-visible {
  outline: 2px solid var(--pk-coral);
  outline-offset: 2px;
}

.dark .pk-nav-item {
  color: var(--pk-ink-400);
}

.dark .pk-nav-item:hover {
  background: rgba(255, 255, 255, .06);
  color: #E4E4E2;
}

.dark .pk-nav-item.is-active {
  background: #262626;
  border-color: rgba(255, 255, 255, .10);
  color: #F1F1EF;
}

/* Below the lg breakpoint the sidebar becomes a wrapped row of pills, so five
   account sections do not push the page's actual content off-screen.
   It wraps rather than scrolls on purpose: a horizontally scrolling row cuts the
   last pill in half at phone widths, and a half-visible pill reads as a clipped
   label rather than as something to swipe. Wrapping shows every section. */
@media (max-width: 1023.98px) {
  .pk-nav-row {
    display: flex;
    flex-wrap: wrap;
    gap: .375rem;
  }

  .pk-nav-row .pk-nav-item {
    width: auto;
    flex-shrink: 0;
    padding: .4rem .7rem;
  }
}

/* The plan grid inside the profile's plan section.
   `subscription_plans.html` asks for four columns at lg, and that breakpoint
   resolves against the *viewport*, not the column the grid sits in. Four cards
   in a 3/4-width settings column are unreadable, so the profile's copy of the
   grid is two columns (one on a phone). Two ID selectors out-rank the Tailwind
   utility without needing !important, and a media query never changes
   specificity, so this holds in light and dark, at every width. */
#profile-plans #plans-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

@media (max-width: 639.98px) {
  #profile-plans #plans-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* -- Chat loader -------------------------------------------------------------
   The design's typing indicator: a gently drifting logo plus three dots that
   pulse in sequence (coral / sand / mint). Lifted verbatim from pokit-ui.html. */
@keyframes pk-blob {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50%      { transform: translate(1px, -1px) scale(1.05); }
}
.pk-animate-blob { animation: pk-blob 4s ease-in-out infinite; }

@keyframes pk-dots {
    0%, 80%, 100% { opacity: .25; }
    40%           { opacity: 1; }
}
.pk-typing span { animation: pk-dots 1.2s infinite; }
.pk-typing span:nth-child(2) { animation-delay: .15s; }
.pk-typing span:nth-child(3) { animation-delay: .3s; }

/* Focus opt-out. The rule above is deliberately global - it gives every field in the
   app a coral focus ring - but the chat composer is a special case: its textarea sits
   inside a surface that already draws the coral border on focus-within, so the extra
   coral box-shadow here shows up as a second orange ring right around the caret.
   Zero specificity, declared after the global rule, so it wins on source order. */
:where(.pk-plain-focus):focus {
  border-color: inherit;
  box-shadow: none;
}

/* The preview page has its own toolbar across the top of the workspace, so the
   notification rail drops below it rather than covering it. Toggled from
   switchRightPanel() in layout_script.js. */
#pk-notification-rail.pk-rail-below-toolbar {
    top: 4rem;
}
