/* public/css/ask-oracle.css
   ════════════════════════════════════════════════════════════════════
   Ask the Oracle — A1 dock + A2-A7 panel states.
   Lives alongside oracle-kit.css; namespaces under .ao-* (ask-oracle).
   Uses Sacred Acid tokens + the kit's shared ring/sigil animations
   defined in oracle-kit.css. Reduced-motion gate at the bottom of
   the file disables every infinite loop in one block per kit flag #3.

   Architecture:
     .ao-dock           A1 at-rest sigil-as-handle, fixed bottom
     .ao-scrim          backdrop dim + blur when panel open
     .ao-panel          slide-up panel (the OracleChat shell, ours)
       .ao-panel__head  grip, sigil header, close ×, hairline
       .ao-panel__sub   subtitle + italic "The Oracle sees you."
       .ao-panel__ctx   context pill (A6 only)
       .ao-panel__body  scrollable conversation
       .ao-panel__foot  composer OR limit message
     .ao-msg            individual message bubbles
     .ao-composer       input + send button + counter
     .ao-banner         the one-time "your allowance refreshed" chip
   ──────────────────────────────────────────────────────────────────── */

/* ═══════════════════════════════════════════════════════════════════
   A1 — At-rest dock (eye-as-handle summon affordance)
   ═══════════════════════════════════════════════════════════════════ */

.ao-dock {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 1200;                    /* under push-drawer (1500) but over content */
  flex-direction: column; align-items: center;
  gap: 6px;
  padding: 18px 0 max(14px, env(safe-area-inset-bottom));
  /* Solid black bar behind the dock so the button reads cleanly over
     ANY content scrolling beneath, including chamber cards with their
     own dark gradients. Hairline at the top edge gives a clean cut
     between the dock and the page above. */
  background: linear-gradient(180deg,
    rgba(0,0,0,0.85) 0%,
    rgba(0,0,0,0.96) 30%,
    rgba(0,0,0,1) 100%);
  border-top: 1px solid rgba(247, 209, 172, 0.08);
  pointer-events: none;             /* only the button is tappable */
  /* Hidden by default; controller toggles .ao-dock--mounted on the
     screens where Ask the Oracle is summonable (library, transits feed,
     transits detail, time-travel). NOT account, NOT home/loader/share. */
  display: none;
}
.ao-dock--mounted { display: flex; }

/* Grabber hairline — widens on hover/active per kit. */
.ao-dock__grab {
  width: 32px; height: 1.5px;
  background: rgba(247, 209, 172, 0.55);
  border-radius: 1px;
  transition: width 240ms var(--ease-ritual), background 240ms ease;
  pointer-events: none;
}
.ao-dock__btn:hover .ao-dock__grab,
.ao-dock__btn:focus-visible .ao-dock__grab { width: 40px; }

/* The button wraps the row + grabber. Column flex so grabber sits above. */
.ao-dock__btn {
  background: none; border: none; padding: 4px 8px;
  display: flex; flex-direction: column; align-items: center;
  gap: 6px;
  cursor: pointer;
  pointer-events: auto;
  font-family: var(--font-body);
  border-radius: 9999px;
  transition: background 240ms ease;
}
.ao-dock__btn:hover,
.ao-dock__btn:focus-visible { background: rgba(247, 209, 172, 0.04); }

/* The horizontal row — eye + label side-by-side. */
.ao-dock__row {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 14px;
  transition: transform 280ms var(--ease-ritual);
}
.ao-dock__btn:hover .ao-dock__row,
.ao-dock__btn:focus-visible .ao-dock__row { transform: translateY(-1px); }

/* Sigil holder. Bumped 36 → 48px per Krysta: the at-rest eye was
   too small to read clearly even after the contrast pass. The eye
   inside is 44px now; the wrapper carries the extra 4px breathing
   room. */
.ao-dock__sigil {
  position: relative;
  width: 48px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}

/* The eye itself — 44px now (was 32). Still small enough to read as
   a button glyph rather than a hero element, but legible. */
.ao-dock__eye {
  position: relative; z-index: 2;
  width: 44px; height: auto;
  mix-blend-mode: screen;
  filter: contrast(1.04) drop-shadow(0 1px 6px rgba(0,0,0,0.85));
  animation: ao-breathe 4200ms ease-in-out infinite;
}

/* The label sits alongside the eye now */
.ao-dock__label {
  color: rgba(247, 209, 172, 0.72);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  font-weight: 500;
  transition: color 200ms ease;
}
.ao-dock__btn:hover .ao-dock__label,
.ao-dock__btn:focus-visible .ao-dock__label { color: rgba(247, 209, 172, 0.92); }

/* A7a — at-rest variant when the cycle's used up: chartreuse ring
   indicator + "0" badge over the sigil. */
.ao-dock--limited .ao-dock__sigil::after {
  content: '0';
  position: absolute; top: -4px; right: 4px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--oracle);
  color: #0B0A0A;
  font-family: var(--font-body);
  font-weight: 700; font-size: 11px;
  box-shadow: 0 0 14px rgba(224, 242, 81, 0.6);
  z-index: 3;
}
.ao-dock--limited .ao-dock__glow {
  background: radial-gradient(circle at 50% 50%, rgba(224, 242, 81, 0.4) 0%, rgba(224, 242, 81, 0.1) 50%, transparent 75%);
}

/* ═══════════════════════════════════════════════════════════════════
   Scrim — dim + blur backdrop when panel is open
   A2: blur 3px / dim 0.35 (waking)
   A3+: blur 6px / dim 0.55 (awake)
   ═══════════════════════════════════════════════════════════════════ */

.ao-scrim {
  position: fixed; inset: 0;
  z-index: 1300;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 320ms var(--ease-ritual), backdrop-filter 320ms ease;
  pointer-events: none;
}
.ao-scrim--waking {
  background: rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 1;
  pointer-events: auto;
}
.ao-scrim--awake {
  opacity: 1;
  pointer-events: auto;
}

/* Backdrop-filter fallback for browsers that don't support it (old
   Android WebViews per kit flag #1) — solid darker scrim, no blur. */
@supports not (backdrop-filter: blur(6px)) {
  .ao-scrim,
  .ao-scrim--waking,
  .ao-scrim--awake { background: rgba(0, 0, 0, 0.7); }
}

/* ═══════════════════════════════════════════════════════════════════
   Panel — slide-up, the OracleChat shell
   A2 (waking): 30% height
   A3-A7 (awake): 80% height (or 86% for long scrollback)
   ═══════════════════════════════════════════════════════════════════ */

.ao-panel {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 1400;
  display: flex; flex-direction: column;
  height: 80%;
  max-height: 80dvh;
  background: linear-gradient(180deg, #0B0A0A 0%, #050505 100%);
  border-top: 1px solid rgba(201, 169, 109, 0.32);
  border-radius: 24px 24px 0 0;
  box-shadow: 0 -20px 60px -20px rgba(0, 0, 0, 0.9);
  transform: translateY(100%);
  transition: transform 400ms var(--ease-ritual), height 320ms var(--ease-ritual);
  color: var(--parchment);
  font-family: var(--font-body);
}
.ao-panel--waking {
  height: 30%;
  max-height: 30dvh;
  transform: translateY(0);
}
.ao-panel--awake {
  /* Bumped 80% → 92% per Krysta — closer to the top of the screen
     gives the conversation room to breathe and the empty-state prompt
     more vertical space without crowding. */
  height: 92%;
  max-height: 92dvh;
  transform: translateY(0);
}

/* Long-scrollback variant — 86% per kit's long-thread reference. The
   controller toggles this when the conversation grows past N messages. */
.ao-panel--tall {
  height: 86%;
  max-height: 86dvh;
}

/* ── Grip handle ─────────────────────────────────────────────────── */
.ao-panel__grip {
  align-self: center;
  width: 40px; height: 4px;
  margin: 10px 0 6px;
  border-radius: 2px;
  background: rgba(247, 209, 172, 0.35);
  flex-shrink: 0;
}

/* ── Header row ──────────────────────────────────────────────────── */
.ao-panel__head {
  display: grid; grid-template-columns: 36px 1fr 36px;
  align-items: center;
  padding: 0 18px 14px;
  border-bottom: 1px solid rgba(201, 169, 109, 0.18);
  flex-shrink: 0;
}
.ao-panel__head-spacer { width: 36px; }

/* Awake sigil at panel header — sized generously so the outer pulse
   rings have room to expand without colliding with the close button. */
.ao-panel__sigil {
  grid-column: 2;
  justify-self: center;
  position: relative;
  width: 110px; height: 110px;
  display: flex; align-items: center; justify-content: center;
}

/* Outer soft glow — sits behind the disc, halos the whole composition. */
.ao-panel__sigil-glow {
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%,
    rgba(224, 242, 81, 0.42) 0%,
    rgba(224, 242, 81, 0.15) 40%,
    rgba(224, 242, 81, 0.04) 65%,
    transparent 82%);
  filter: blur(4px);
  pointer-events: none;
  z-index: 1;
  /* Slowed 3.2s → 5s alongside the pulse rings for an overall calmer
     presence. The Oracle is sitting with the user, not pacing. */
  animation: ao-sphere-pulse 5000ms ease-in-out infinite;
}

/* SOLID chartreuse disc — the "green circle behind the icon" Krysta
   called for. The eye sits centered on top of this. Box-shadow gives
   it a soft inner highlight + an outer ambient glow. */
.ao-panel__sigil-disc {
  position: absolute;
  width: 84px; height: 84px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%,
    #EAFA68 0%,
    #E0F251 50%,
    #C2D33D 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.25),
    0 0 24px rgba(224, 242, 81, 0.45);
  pointer-events: none;
  z-index: 2;
}

/* Continuous pulse rings expanding outward from the disc edge — always
   animated while the panel is open (NOT gated on thinking state).
   Two staggered rings give the "ring that pulses from the outside of
   the circle" effect Krysta specified. */
.ao-panel__sigil-pulse {
  position: absolute;
  width: 84px; height: 84px;
  border-radius: 50%;
  border: 1.5px solid rgba(224, 242, 81, 0.6);
  pointer-events: none;
  z-index: 3;
  /* Slowed 2.4s → 4.5s per Krysta — "calm and present, not REALLY
     awake." Reads as the Oracle's breath rather than her pulse. */
  animation: ao-pulse-out 4500ms ease-out infinite;
}
.ao-panel__sigil-pulse--2 {
  animation: ao-pulse-out 4500ms ease-out infinite;
  /* Stagger by half the duration so there's always one mid-pulse. */
  animation-delay: 2250ms;
}

/* Eye sits on top of the disc with NORMAL blending (no mix-blend-mode
   here — we want the dark eye ridges visible against the chartreuse,
   not screened out). Drop-shadow grounds it on the disc. */
.ao-panel__sigil-img {
  position: relative; z-index: 4;
  width: 72px; height: auto;
  filter: contrast(1.05) drop-shadow(0 1px 6px rgba(0, 0, 0, 0.5));
}

/* Sharp concentric rings — these still only fire during A5 (thinking).
   They sit OUTSIDE the continuous pulse rings, signaling a different
   kind of activity (deep meditation vs. ambient presence). */
.ao-panel__sigil-ring {
  position: absolute; inset: -4px;
  border: 1px solid rgba(224, 242, 81, 0.85);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  z-index: 5;
}
.ao-panel--thinking .ao-panel__sigil-ring {
  animation: ao-pulse-ring 1800ms ease-out infinite;
}
.ao-panel--thinking .ao-panel__sigil-ring--2 {
  animation: ao-pulse-ring 1800ms ease-out infinite;
  animation-delay: 900ms;
}

/* Close × */
.ao-panel__close {
  grid-column: 3;
  background: none; border: none;
  width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  color: var(--rose);
  font-size: 24px; cursor: pointer;
  padding: 0; line-height: 1;
  border-radius: 50%;
  transition: background 200ms ease;
}
.ao-panel__close:hover { background: rgba(247, 209, 172, 0.08); }

/* ── Subtitle band ───────────────────────────────────────────────── */
.ao-panel__sub {
  /* Bottom padding increased so "The Oracle sees you" doesn't crowd
     the conversation/empty-state below. Reads as a complete header
     band ending in the italic phrase, with breathing room before
     the body content starts. */
  padding: 14px 22px 22px;
  text-align: center;
  flex-shrink: 0;
}
.ao-panel__sub-prompt {
  color: var(--moonstone);
  font-size: 12.5px;
  font-family: var(--font-body);
  margin: 0 0 6px;
}
.ao-panel__sub-tag {
  color: var(--rose);
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  font-size: 13.5px;
  margin: 0;
  line-height: 1.4;
}

/* ── Context pill (A6 only) ──────────────────────────────────────── */
.ao-panel__ctx {
  margin: 14px 22px 0;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  background: rgba(247, 209, 172, 0.04);
  border: 1px solid rgba(201, 169, 109, 0.28);
  border-radius: 9999px;
  flex-shrink: 0;
}
.ao-panel__ctx-mark {
  color: var(--rose);
  font-size: 14px;
  flex-shrink: 0;
}
.ao-panel__ctx-label {
  color: var(--rose);
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  font-size: 12.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ao-panel__ctx-sub {
  color: var(--oracle);
  font-size: 9.5px; letter-spacing: 0.28em;
  text-transform: uppercase;
  margin-left: auto;
  flex-shrink: 0;
}
.ao-panel__ctx-x {
  background: none; border: none; padding: 0;
  color: rgba(247, 209, 172, 0.55);
  font-size: 16px; cursor: pointer;
  width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  line-height: 1;
  flex-shrink: 0;
}
.ao-panel__ctx-x:hover { color: var(--rose); }

/* ── Scrollable body ─────────────────────────────────────────────── */
.ao-panel__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 18px 22px 6px;
  display: flex; flex-direction: column; gap: 22px;
  scroll-behavior: smooth;
}

/* Centered empty state (A3) — wraps a single italic prompt */
.ao-empty {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center; padding: 32px 8px;
}
.ao-empty__prompt {
  color: var(--rose);
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  /* Bumped down from 22 to 16 per Krysta — was reading as a headline
     rather than an invitation. The Silver Editorial italic at 16px
     still feels editorial without dominating the empty state. */
  font-size: 16px;
  line-height: 1.45;
  margin: 0 0 18px;
  max-width: 280px;
  text-wrap: balance;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.85);
}
.ao-empty__sparkle {
  color: var(--gold);
  font-size: 18px;
  opacity: 0.45;
}

/* ── Message bubbles ─────────────────────────────────────────────── */
.ao-msg { display: flex; }

/* User: right-aligned, max 84%, rose tint */
.ao-msg--user { justify-content: flex-end; }
.ao-msg--user .ao-msg__bubble {
  max-width: 84%;
  padding: 13px 16px;
  background: rgba(247, 209, 172, 0.06);
  border: 1px solid rgba(247, 209, 172, 0.18);
  border-radius: 14px 14px 4px 14px;
  color: var(--rose);
  /* Bumped 16 → 18 per Krysta — Oracle reflections deserve comfortable
     reading scale. Above the 15-16 Brainstorm baseline but appropriate
     for the longer-form nature of self-reflection territory. */
  font-size: 18px;
  line-height: 1.6;
  /* 7.5aq — preserve user-typed newlines (multi-paragraph messages).
     The render path uses el(..., { text: m.content }) which sets
     textContent — pre-wrap then renders \n as line break, blank-line
     as paragraph gap. Mirrors the oracle bubble's pre-wrap further down. */
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

/* Oracle: full-width row, ✦ avatar + parchment body */
.ao-msg--oracle {
  align-items: flex-start;
  gap: 12px;
}
.ao-msg--oracle .ao-msg__avatar {
  flex-shrink: 0;
  color: var(--rose);
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  font-size: 26px;
  line-height: 1;
  filter: drop-shadow(0 0 8px rgba(201, 169, 109, 0.4));
}
.ao-msg--oracle .ao-msg__body {
  color: var(--parchment);
  /* Bumped 16 → 18 per Krysta — same reasoning as user bubble. The
     Oracle's reflections are long-form prose meant to be sat with. */
  font-size: 18px;
  line-height: 1.7;
  flex: 1 1 auto;
  white-space: pre-wrap;        /* preserve line breaks from LLM */
  word-wrap: break-word;
}
.ao-msg--oracle .ao-msg__body strong { color: var(--gold); font-weight: 500; }
.ao-msg--oracle .ao-msg__body em { color: var(--oracle); font-style: italic; }
.ao-msg--oracle .ao-msg__body .ao-greeting {
  /* ::greeting:: prefix renders in Silver Editorial italic per voice spec */
  display: block;
  margin-bottom: 8px;
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  color: #F4F1EC;
  font-size: 17px;
  line-height: 1.3;
}

/* ── Thinking indicator (A5) ─────────────────────────────────────── */
.ao-thinking {
  display: flex; gap: 8px;
  padding: 14px 0 4px 38px;        /* aligned roughly under the ✦ avatar column */
}
.ao-thinking__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: rgba(201, 169, 109, 0.6);
  animation: ao-think-dot 1400ms ease-in-out infinite;
}
.ao-thinking__dot:nth-child(2) { animation-delay: 200ms; }
.ao-thinking__dot:nth-child(3) { animation-delay: 400ms; }

/* ── Footer composer ─────────────────────────────────────────────── */
.ao-panel__foot {
  flex-shrink: 0;
  /* Bottom padding adds env(safe-area-inset-bottom) so iPhones with
     the home indicator don't crowd the send button. Same pattern as
     brainstorm's composer (see public/css/oracle.css line 4449). */
  padding: 14px 22px max(22px, env(safe-area-inset-bottom));
  border-top: 1px solid rgba(201, 169, 109, 0.14);
  background: linear-gradient(180deg, transparent, rgba(0,0,0,0.6) 100%);
}
.ao-composer {
  display: flex; align-items: center; gap: 10px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(201, 169, 109, 0.28);
  border-radius: 9999px;
  padding: 8px 8px 8px 18px;
}
.ao-composer__input {
  flex: 1 1 auto;
  background: transparent; border: none; outline: none;
  resize: none;
  color: var(--parchment);
  font-family: var(--font-body);
  /* MUST stay ≥ 16px — iOS Safari auto-zooms any focused input below
     16px on tap, which jolted the layout and was the root cause of
     the "screen zooms in when tapping the composer" symptom. Same
     reason Brainstorm's .bs-input is pinned at 16px (see
     public/css/oracle.css line 4480-4482). */
  font-size: 16px;
  line-height: 1.45;
  min-height: 24px; max-height: 110px;
  padding: 6px 0;
}
.ao-composer__input::placeholder {
  color: var(--moonstone-43);
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  font-size: 16px;
}
.ao-composer__send {
  flex-shrink: 0;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: linear-gradient(180deg, #E0F251 0%, #C2D33D 100%);
  border: 1px solid var(--oracle);
  color: #0B0A0A;
  font-size: 16px; line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 18px rgba(224, 242, 81, 0.35);
  transition: transform 180ms ease, box-shadow 240ms ease, opacity 200ms ease;
  padding: 0;
}
.ao-composer__send:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 0 24px rgba(224, 242, 81, 0.55);
}
.ao-composer__send:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Counter — caps, smoke color, right-aligned */
.ao-panel__counter {
  margin-top: 8px;
  text-align: right;
  color: var(--smoke);
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

/* ═══════════════════════════════════════════════════════════════════
   A7 — limit-reached panel state
   THE ORACLE RESTS · "You've spent all 200..." · "She returns on [date]"
   ═══════════════════════════════════════════════════════════════════ */

.ao-rest {
  flex: 1;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  padding: 32px 22px;
  gap: 22px;
}
.ao-rest__title {
  color: var(--gold);
  font-family: var(--font-body);
  font-size: 10.5px;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  font-weight: 600;
}
.ao-rest__body {
  color: var(--moonstone);
  font-size: 14px;
  line-height: 1.6;
  max-width: 320px;
  text-wrap: balance;
}
.ao-rest__return {
  color: var(--parchment);
  font-family: "The Silver Editorial", serif;
  font-style: italic;
  font-size: 22px;
  line-height: 1.35;
  margin: 0;
}
.ao-rest__return .ao-rest__date { color: var(--oracle); }

.ao-rest__topup {
  margin-top: 18px;
  display: inline-flex; align-items: center; gap: 10px;
}
.ao-rest__topup-link {
  color: rgba(247, 209, 172, 0.35);
  text-decoration: line-through;
  font-size: 12.5px;
  font-family: var(--font-body);
}
.ao-rest__topup-badge {
  color: var(--gold);
  font-size: 9px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  padding: 3px 8px;
  border: 1px solid rgba(201, 169, 109, 0.4);
  border-radius: 9999px;
}

/* ═══════════════════════════════════════════════════════════════════
   Upgrade banner (one-time chip — "your allowance refreshed")
   ═══════════════════════════════════════════════════════════════════ */

.ao-banner {
  position: fixed;
  /* Moved from bottom:130px (over the dock — but the Library has chamber
     cards that scroll up to that position and the banner ended up
     overlapping the Your Calling card). Now anchored to TOP, just under
     the Library top-bar, where there's empty atmospheric space. */
  left: 50%;
  top: max(calc(env(safe-area-inset-top, 0px) + 110px), 110px);
  transform: translateX(-50%) translateY(-8px);
  z-index: 1100;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  background: rgba(11, 10, 10, 0.94);
  border: 1px solid rgba(224, 242, 81, 0.45);
  border-radius: 9999px;
  box-shadow: 0 0 22px rgba(224, 242, 81, 0.25), 0 14px 40px -20px rgba(0,0,0,0.9);
  color: var(--parchment);
  font-family: var(--font-body);
  font-size: 12px;
  line-height: 1.4;
  max-width: calc(100% - 32px);
  opacity: 0;
  transition: opacity 320ms ease, transform 320ms var(--ease-ritual);
}
.ao-banner--visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.ao-banner__mark {
  color: var(--oracle);
  font-size: 14px;
  flex-shrink: 0;
}
.ao-banner__close {
  background: none; border: none; padding: 0 0 0 6px;
  color: rgba(247, 209, 172, 0.55);
  font-size: 16px; cursor: pointer;
  width: 22px; line-height: 1;
}
.ao-banner__close:hover { color: var(--rose); }

/* ═══════════════════════════════════════════════════════════════════
   Animations
   ═══════════════════════════════════════════════════════════════════ */

@keyframes ao-breathe {
  0%, 100% { opacity: 0.85; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.04); }
}

/* Awake sigil sphere — soft chartreuse glow that breathes behind the
   header sigil. Distinct from the thinking-state pulse rings (those
   are sharp + infrequent; this is soft + continuous). */
@keyframes ao-sphere-pulse {
  0%, 100% { opacity: 0.6; transform: scale(1);    filter: blur(4px); }
  50%      { opacity: 1;   transform: scale(1.12); filter: blur(5px); }
}

/* Outward pulse ring — expands from the disc edge to ~1.45x its size
   while fading to transparent. The two rings are staggered by half
   the duration so there's always one mid-pulse, giving the awake
   sigil a continuous "breathing-outward" presence. */
@keyframes ao-pulse-out {
  0%   { opacity: 0.7; transform: scale(1);    border-width: 1.5px; }
  100% { opacity: 0;   transform: scale(1.55); border-width: 0.5px; }
}

@keyframes ao-pulse-ring {
  0%   { opacity: 0.7; transform: scale(1); }
  100% { opacity: 0;   transform: scale(2.2); }
}

@keyframes ao-think-dot {
  0%, 100% { opacity: 0.3; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(-3px); }
}

/* Body class added by the controller to lock background scroll while
   the panel is open. Mirrors body.brainstorm-active's full-viewport
   lock so iOS Safari can't rubber-band the underlying page when the
   on-screen keyboard opens/closes — without this, the composer can
   end up under the iOS keyboard + the predictive-text bar's submit
   glyph looks like a "second commit place" beside our send button. */
body.ao-locked {
  overflow: hidden;
  height: 100dvh;
  position: fixed;
  width: 100%;
  inset: 0;
}

/* ═══════════════════════════════════════════════════════════════════
   Reduced motion — disable all infinite loops per kit flag #3.
   Panel slide transition is intentionally preserved (it's a single-
   shot transform, not an infinite animation, and removing it makes
   the open/close feel jarring).
   ═══════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .ao-dock__eye,
  .ao-panel__sigil-ring,
  .ao-panel__sigil-glow,
  .ao-panel__sigil-pulse,
  .ao-panel__sigil-pulse--2,
  .ao-panel--thinking .ao-panel__sigil-ring,
  .ao-panel--thinking .ao-panel__sigil-ring--2,
  .ao-thinking__dot {
    animation: none !important;
  }
  /* Thinking dots — keep them visible but static so the user can see
     the indicator is there without the bouncing motion. */
  .ao-thinking__dot { opacity: 0.7; }
  /* Awake glow — keep it visible as a static halo */
  .ao-panel__sigil-glow { opacity: 0.7; }
  /* Pulse rings — keep one as a static ring at the disc edge so the
     awake state still reads as alive rather than dormant. */
  .ao-panel__sigil-pulse { opacity: 0.4; }
  .ao-panel__sigil-pulse--2 { display: none; }
}
