/* Falaq Pulse — live agent canvas.
   Component-scoped colour variables keep the richer prototype palette local;
   spacing and typography still inherit from the site's shared token system.

   ── Scope ──────────────────────────────────────────────────────────────────
   This file styles what is INSIDE the console. It does not state the shell's
   grid, the panel column split, the viewport height, or any breakpoint that
   moves them — assets/agent-stage.css owns all of that, and owning it in one
   place is what removed the 225px overlap between the conversation and the
   diagram. If a rule here needs to know how wide the page is, it is in the
   wrong file; ask the shell with a @container query instead. */

.console-wrap { width: min(1480px, calc(100% - 40px)); max-width: none; }

.ac {
  --ac-bg: #070708;
  --ac-surface: #101112;
  --ac-surface-2: #141516;
  --ac-line: rgba(233, 231, 236, .12);
  --ac-line-hi: rgba(233, 231, 236, .2);
  --ac-text: #e9e7ec;
  --ac-text-2: #a9a5b3;
  --ac-text-3: #6f6b79;
  --ac-cyan: #4da3ff;
  --ac-violet: #1a6dff;
  --ac-gold: #8dd6ff;
  --ac-coral: #8dd6ff;
  --ac-mint: #4ade80;
  position: relative;
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--ac-line);
  border-radius: 20px;
  background:
    radial-gradient(circle at 52% -20%, rgba(26, 109, 255, .13), transparent 36%),
    linear-gradient(145deg, #08080a, #070708 68%);
  color: var(--ac-text);
  box-shadow: 0 28px 80px rgba(0, 0, 0, .24), inset 0 1px rgba(255,255,255,.035);
  isolation: isolate;
}

.ac::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  opacity: .08;
  pointer-events: none;
  background-image: radial-gradient(rgba(255,255,255,.55) .45px, transparent .65px);
  background-size: 3px 3px;
  mix-blend-mode: soft-light;
}

.ac button, .ac textarea { font: inherit; }
.ac button { color: inherit; }
.ac button:focus-visible, .ac textarea:focus-visible { outline: 2px solid var(--ac-cyan); outline-offset: 2px; }
.ac svg { display: block; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.6; }
.ac-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

.ac-topbar {
  display: flex;
  min-height: 64px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px var(--x3);
  padding: 8px 20px;
  border-bottom: 1px solid var(--ac-line);
  background: rgba(8, 10, 16, .82);
}

.ac-brand, .ac-runtime, .ac-live { display: flex; align-items: center; min-width: 0; }
.ac-runtime { flex-wrap: wrap; justify-content: flex-end; }
.ac-brand { gap: 12px; }
.ac-brand-mark {
  display: grid;
  width: 36px;
  height: 36px;
  place-items: center;
  border: 1px solid rgba(141, 214, 255, .28);
  border-radius: 12px;
  background: linear-gradient(145deg, rgba(141,214,255,.14), rgba(26,109,255,.08));
  box-shadow: inset 0 1px rgba(255,255,255,.08), 0 0 20px rgba(141,214,255,.08);
}
.ac-brand-mark img { width: 22px; height: 22px; object-fit: contain; }
.ac-brand > span:last-child { display: grid; gap: 2px; }
.ac-brand small, .ac-session, .ac-overline, .ac-node-top em, .ac-statusbar, .ac-section-label small {
  font-family: var(--f-data);
  letter-spacing: .08em;
}
.ac-brand small { color: var(--ac-text-3); font-size: .52rem; }
.ac-brand b { font-size: .84rem; font-weight: 700; color: #ffffff; }
.ac-runtime { gap: 12px; }
.ac-live {
  gap: 7px;
  padding: 6px 12px;
  border: 1px solid rgba(77,163,255,.2);
  border-radius: 999px;
  background: rgba(77,163,255,.07);
  color: #d6f0ff;
  font-size: .65rem;
  font-weight: 600;
}
.ac-live b { font-weight: 600; }

.ac-live i, .ac-statusbar > span:first-child i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ac-cyan);
  box-shadow: 0 0 0 4px rgba(77,163,255,.12), 0 0 10px var(--ac-cyan);
  animation: acPulse 2s ease-out infinite;
}
.ac-session { color: var(--ac-text-3); font-size: .52rem; text-transform: uppercase; }

.ac-reset-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  border: 1px solid var(--ac-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, .04);
  color: var(--ac-text-2);
  font: inherit;
  font-size: .68rem;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s ease;
}
.ac-reset-btn:hover {
  border-color: rgba(77, 163, 255, .45);
  background: rgba(26, 109, 255, .14);
  color: #ffffff;
}

/* Mobile Tabs (Hidden on Desktop) */
.ac-mobile-tabs {
  display: none;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--ac-line);
  background: rgba(10, 13, 20, .9);
}
.ac-tab-btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--ac-line);
  border-radius: 10px;
  background: transparent;
  color: var(--ac-text-2);
  font: inherit;
  font-size: .78rem;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s ease;
}
.ac-tab-btn.is-active {
  border-color: rgba(77, 163, 255, .5);
  background: rgba(26, 109, 255, .15);
  color: #ffffff;
}
/* icon("graph") is emitted without width/height attributes, and nothing sized
   it, so it fell back to the replaced-element default and rendered at 64px —
   which is why the architecture tab was 82px tall while the conversation tab
   (whose svg carries the attributes) was 42px. */
.ac-tab-btn svg { width: 15px; height: 15px; flex: none; }
.ac-tab-btn span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ac-tab-count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--ac-cyan);
  color: #05070a;
  font-size: .62rem;
  font-weight: 800;
}

/* Workspace — surfaces only. The grid, the column split, the min-heights and
   the breakpoints that used to live here now live in agent-stage.css; this
   file kept its own copy of them, graph-canvas.css kept a third, and the file
   that happened to load last decided the page. */
.ac-workspace {
  direction: inherit;
}

.ac-chat-panel, .ac-canvas-panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.ac-chat-panel {
  background: rgba(12, 15, 24, .7);
  border-inline-end: 1px solid var(--ac-line);
}
.ac-canvas-panel {
  background: #06070a;
}

.ac-panel-head {
  display: flex;
  min-height: 72px;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--ac-line);
  background: rgba(10, 13, 20, .4);
}
.ac-panel-head h3 { margin: 0; color: var(--ac-text); font-size: .95rem; font-weight: 700; letter-spacing: -.02em; }
.ac-panel-head p { margin: 3px 0 0; color: var(--ac-text-3); font-size: .65rem; line-height: 1.5; }
.ac-overline { display: block; margin-bottom: 4px; color: var(--ac-text-3); font-size: .5rem; direction: ltr; text-align: start; }

.ac-chat-head { justify-content: flex-start; gap: 14px; }
.ac-avatar {
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(26, 109, 255, .15);
  border: 1px solid rgba(77, 163, 255, .3);
  flex-shrink: 0;
}
.ac-avatar-core img { width: 20px; height: 20px; object-fit: contain; }

.ac-channels { display: flex; gap: 4px; direction: ltr; }
.ac-channels button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 28px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--ac-text-3);
  font-size: .56rem;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s ease;
}
.ac-channels button i { width: 4px; height: 4px; border-radius: 50%; background: currentColor; }
.ac-channels button:hover { color: var(--ac-text-2); background: rgba(255,255,255,.04); }
.ac-channels button.is-active { border-color: rgba(77,163,255,.3); background: rgba(77,163,255,.1); color: var(--ac-cyan); }
.ac.is-busy .ac-channels { opacity: .45; pointer-events: none; }

/* Conversation Stream — the one scroll region on the live phase.
   `min-height: 0` rather than the old 300px floor: the floor is what stopped
   the flex chain from shrinking, so a long conversation grew the stream, then
   the panel, then the document (4422px against a 900px viewport) and pushed
   the composer off the bottom of the screen. With the floor gone and the
   stage owning a fixed region, the stream is the only thing that moves. */
.ac-stream {
  display: flex;
  flex: 1;
  min-height: 0;
  flex-direction: column;
  gap: 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px;
  scrollbar-width: thin;
  scrollbar-color: rgba(77, 163, 255, .25) transparent;
}

/* A bubble is a box that text fills, never a box text sizes.
   `min-width: 0` defeats the flex/grid automatic minimum — without it a single
   unbroken token sets the bubble's floor and the floor sets the panel's, which
   is how one pasted URL stretched the stream's scrollWidth to 19663px and hid
   everything but the first screenful of it. `overflow-wrap: anywhere` is the
   half people remember; on its own it does not help, because the automatic
   minimum is computed before wrapping is considered. Both, or neither. */
.ac-message {
  max-width: 90%;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
  animation: acMessageIn .35s cubic-bezier(.16, 1, .3, 1) both;
}
.ac-message > div, .ac-message p { min-width: 0; overflow-wrap: anywhere; }
.ac-message p { margin: 0; font-size: .84rem; line-height: 1.72; }
.ac-message > span, .ac-message div > span { display: block; margin-top: 6px; color: var(--ac-text-3); font-family: var(--f-data); font-size: .75rem; }
.ac-message.in {
  align-self: flex-start;
  padding: 12px 16px;
  border: 1px solid rgba(77, 163, 255, .28);
  border-radius: 18px 18px 4px 18px;
  background: linear-gradient(145deg, rgba(26, 109, 255, .25), rgba(26, 109, 255, .12));
  color: #ffffff;
}
html[dir="ltr"] .ac-message.in { border-radius: 18px 18px 18px 4px; }

.ac-message.out {
  display: flex;
  align-self: flex-end;
  gap: 10px;
  max-width: 94%;
}
.ac-message.out > div {
  flex: 1;
  padding: 13px 16px;
  border: 1px solid var(--ac-line);
  border-radius: 18px 18px 18px 4px;
  background: rgba(255, 255, 255, .04);
  line-height: 1.72;
}
html[dir="ltr"] .ac-message.out > div { border-radius: 18px 18px 4px 18px; }

.ac-agent-avatar {
  display: grid !important;
  width: 28px;
  height: 28px;
  place-items: center;
  align-self: end;
  border: 1px solid rgba(141,214,255,.25);
  border-radius: 9px;
  background: rgba(141,214,255,.1);
  flex-shrink: 0;
}
.ac-agent-avatar img { width: 16px; height: 16px; object-fit: contain; }
.ac-message.is-pending p { color: var(--ac-text-3); }
.ac-message.is-pending p::after {
  content: "";
  display: inline-block;
  width: 18px;
  height: 4px;
  margin-inline-start: 6px;
  border-radius: 9px;
  background: linear-gradient(90deg, transparent, var(--ac-cyan), transparent);
  animation: acThinking 1.2s ease-in-out infinite;
}
.ac-message.is-error > div { border-color: rgba(252, 211, 77, .35); }
.ac-message.is-error p { color: #fcd34d; }

/* Chat Dock (Suggestions + Composer inside chat column) */
.ac-chat-dock {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 14px 14px;
  border-top: 1px solid var(--ac-line);
  background: rgba(8, 10, 16, .75);
}

.ac-suggestions { padding: 0 2px 4px; }
.ac-suggestions > span { display: block; margin-bottom: 5px; color: var(--ac-text-3); font-size: .52rem; font-weight: 500; }
.ac-suggestions > div { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; }
.ac-suggestions button {
  display: flex;
  max-width: 240px;
  flex: none;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  overflow: hidden;
  border: 1px dashed rgba(77,163,255,.3);
  border-radius: 999px;
  background: rgba(26,109,255,.06);
  color: #8dd6ff;
  font-size: .56rem;
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: all .2s ease;
}
.ac-suggestions button span { color: var(--ac-cyan); font-family: var(--f-data); font-size: .5rem; }
.ac-suggestions button:hover { border-color: rgba(77,163,255,.6); background: rgba(26,109,255,.14); color: #ffffff; }
.ac.is-busy .ac-suggestions { opacity: .45; pointer-events: none; }

.ac-composer {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 6px 8px 6px 12px;
  border: 1px solid var(--ac-line-hi);
  border-radius: 14px;
  background: rgba(14, 18, 28, .85);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .25);
  transition: border-color .2s ease, box-shadow .2s ease;
}
html[dir="ltr"] .ac-composer { padding: 6px 12px 6px 8px; }
.ac-composer:focus-within {
  border-color: rgba(77,163,255,.6);
  box-shadow: 0 4px 22px rgba(0, 0, 0, .4), 0 0 16px rgba(77,163,255,.18);
}
.ac-composer textarea {
  flex: 1;
  min-width: 0;
  max-height: 104px;
  padding: 8px 4px;
  resize: none;
  overflow-y: auto;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ac-text);
  font-size: .84rem;
  line-height: 1.5;
}
.ac-composer textarea::placeholder { color: var(--ac-text-3); }
.ac-composer button {
  display: flex;
  width: 38px;
  height: 38px;
  min-width: 38px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--ac-cyan), #1a6dff);
  color: #ffffff;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(77,163,255,.25);
  transition: transform .2s ease, box-shadow .2s ease, opacity .2s ease;
  flex-shrink: 0;
}
.ac-composer button span { display: none; }
.ac-composer button:hover { transform: scale(1.05); box-shadow: 0 8px 24px rgba(77,163,255,.45); }
.ac-composer button:disabled { cursor: wait; opacity: .5; transform: none; }
.ac-composer button svg { width: 16px; height: 16px; }
html[dir="rtl"] .ac-composer button svg { transform: scaleX(-1); }

.ac-statusbar {
  display: flex;
  min-height: 30px;
  align-items: center;
  /* At a readable 12px these five facts no longer fit one line on a phone.
     Wrapping is the honest answer; truncating would drop whichever fact
     happened to be last, and one of them is whether the agent is reachable. */
  flex-wrap: wrap;
  gap: 4px 16px;
  padding: 4px 16px;
  border-top: 1px solid var(--ac-line);
  color: #555a69;
  font-size: .44rem;
  direction: ltr;
}
.ac-statusbar > span { display: flex; align-items: center; gap: 5px; }
.ac-statusbar > span:first-child { color: #80b7ac; }
.ac-statusbar b { color: var(--ac-text-3); font-weight: 600; }

/* No viewport breakpoints in this file. The two that used to be here — 1024px
   for a narrower chat column and 900px for the single-column switch — were
   the direct cause of the cliff: they were overridden by graph-canvas.css's
   own copy at the same widths, and neither knew what the shell had actually
   been given. agent-stage.css now switches on the shell's own inline size.
   What is left here is the console's internal response to its own width. */
/* ── Narrow shell ──────────────────────────────────────────────────────────
   Raising fourteen rules to a 12px floor cost vertical space, and on a phone
   vertical space is the conversation. Measured at 390px before this block: the
   top bar took 155px, the tabs 103px and the panel head 103px, leaving the
   stream 186px of a 747px console — the chrome had more room than the content.

   The answer is to drop chrome, not to shrink type back below the floor. What
   goes is what the visitor can infer or does not need twice: the product
   kicker above a title that says the same thing, the panel subtitles, the
   numbered overlines, and the reset button's word (it keeps an accessible name
   — see agent-console.js). What stays is every sentence that makes a claim,
   including the readiness pill, because that is the one thing on this bar the
   contract says has to be legible. */
@container agent-shell (max-width: 759.98px) {
  .ac-topbar { padding: 6px 12px; min-height: 0; row-gap: 6px; }
  .ac-brand small { display: none; }
  .ac-brand { gap: 9px; }
  .ac-brand-mark { width: 30px; height: 30px; }
  /* The runtime row takes a line of its own rather than being squeezed into
     what the brand leaves over — at 390px that was 179px for 343px of content,
     so all three controls stacked and the bar grew to 155px tall. Given a full
     line they sit side by side and the bar is 82px. */
  /* nowrap is load-bearing: a wrapping flex line never shrinks its items, it
     breaks to a new line instead, so the reset button kept dropping to a third
     row while .ac-channels sat at its full 200px refusing to give any of it up. */
  .ac-runtime { flex: 1 0 100%; flex-wrap: nowrap; gap: 6px; justify-content: space-between; }
  /* The channel switcher is the only one of the three that can afford to be
     clipped: its state is also painted in the status bar and on the composer.
     The readiness pill and the reset button never shrink. */
  .ac-channels { flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
  .ac-channels::-webkit-scrollbar { display: none; }
  .ac-live, .ac-reset-btn { flex: none; }
  .ac-reset-btn span { display: none; }
  .ac-reset-btn { padding: 6px 9px; }
  .ac-channels button { padding: 0 7px; }

  .ac-tab-btn { padding: 7px 12px; }

  /* The head keeps its heading and loses the two lines restating it. */
  .ac-panel-head { min-height: 0; padding: 9px 14px; }
  .ac-panel-head p,
  .ac-overline { display: none; }

  .ac-chat-dock { padding: 8px 12px 12px; }
  .ac-suggestions > span { display: none; }
  .ac-stream { padding: 14px; gap: 12px; }

  /* Two of these five are said better elsewhere on a narrow shell — the
     language by the page itself, the channel by the switcher directly above,
     the node count by the badge on the architecture tab. The readiness state
     and the provider have nowhere else to appear, so they stay. */
  .ac-statusbar { padding: 3px 12px; }
  .ac-statusbar > span:nth-child(2),
  .ac-statusbar > span[data-footer-channel],
  .ac-statusbar > span[data-footer-nodes] { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  /* The delay has to go with the duration.
     The wake sequence staggers its panels with animation-delay — the canvas
     column waits 250ms — and those animations start from opacity 0 with
     fill-mode `both`. Collapsing only the duration leaves the delay intact, so
     somebody who asked for less motion still gets a quarter-second of blank
     panel before everything appears at once. Zeroing both is what "no motion"
     was meant to say. */
  .ac *, .ac *::before, .ac *::after {
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

/* ── Choreography (assets/agent-choreo.js) ─────────────────────────────────
   Three reveals sharing one timeline: the reply types itself, extracted fields
   light one at a time, and the workflow assembles step by step. */

/* A caret while the reply is still writing. It rides the end of the text
   rather than sitting in a fixed spot, so it reads as a cursor, not a dot. */
.ac-message p.is-typing::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-inline-start: 2px;
  border-radius: 1px;
  background: var(--ac-cyan);
  vertical-align: -.15em;
  animation: acCaret .9s steps(2, end) infinite;
}
@keyframes acCaret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.ac-message p.is-typing { cursor: pointer; }

/* A field that just arrived gets one sweep of the accent, then settles. The
   glow is on a pseudo-element so the value's own colour never shifts. */
.ac-variable.just-lit { animation: acFieldIn .5s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes acFieldIn {
  0%   { opacity: .35; transform: translateX(-6px); box-shadow: inset 0 0 0 1px rgba(77, 163, 255, .55); }
  60%  { box-shadow: inset 0 0 0 1px rgba(77, 163, 255, .3); }
  100% { opacity: 1; transform: none; box-shadow: inset 0 0 0 1px transparent; }
}
@keyframes acFieldInLtr {
  0%   { opacity: .35; transform: translateX(6px); box-shadow: inset 0 0 0 1px rgba(77, 163, 255, .55); }
  60%  { box-shadow: inset 0 0 0 1px rgba(77, 163, 255, .3); }
  100% { opacity: 1; transform: none; box-shadow: inset 0 0 0 1px transparent; }
}

/* Workflow steps wait their turn. The connector grows with the node so the
   line appears to draw itself down the page. */
.fx > li.is-pending { opacity: 0; }
.fx > li.is-in { animation: acStepIn .42s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes acStepIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.fx > li.is-pending::before { transform: scaleY(0); }
.fx > li.is-in::before { transform-origin: top; animation: acLineIn .42s ease both; }
@keyframes acLineIn { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* While the agent is working the visor brightens; it settles when the reply
   lands. The artwork carries the state instead of a separate spinner. */
.ac[data-stage="signal"] .ac-brand-mark,
.ac[data-stage="variables"] .ac-brand-mark {
  animation: acThinkGlow 1.4s ease-in-out infinite;
}
@keyframes acThinkGlow {
  0%, 100% { box-shadow: inset 0 1px rgba(255,255,255,.05), 0 0 20px rgba(141,214,255,.05); }
  50%      { box-shadow: inset 0 1px rgba(255,255,255,.05), 0 0 26px rgba(77,163,255,.34); }
}

@media (prefers-reduced-motion: reduce) {
  .ac-message p.is-typing::after,
  .ac-variable.just-lit,
  .fx > li.is-in,
  .ac[data-stage] .ac-brand-mark { animation: none; }
  .fx > li.is-pending { opacity: 1; }
  .fx > li.is-pending::before { transform: none; }
}


/* ── Step annotations ──────────────────────────────────────────────────────
   What used to be a third column of rules, events and node detail. Each note
   now hangs off the step it describes, so the reasoning sits beside the thing
   it is reasoning about instead of in a list the eye has to cross-reference. */

.fx > li { position: relative; }

.fx-note {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px dashed var(--ac-line);
  opacity: .4;
  transition: opacity .3s ease;
}
.fx-note.is-on { opacity: 1; }

/* The dot is the "satisfied" signal: hollow until the step is met, then filled
   and haloed. It is the smallest possible way to say the check passed. */
.fx-note > i {
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 5px;
  border: 1px solid var(--ac-line-hi);
  border-radius: 50%;
}
.fx-note.is-on > i {
  border-color: var(--ac-cyan);
  background: var(--ac-cyan);
  box-shadow: 0 0 0 3px rgba(77, 163, 255, .14);
}

.fx-note span { display: grid; gap: 1px; min-width: 0; }
.fx-note b {
  color: var(--ac-text-3);
  font-family: var(--f-data);
  font-size: .62rem;
  font-weight: 600;
  letter-spacing: .08em;
}
.fx-note.is-on b { color: var(--ac-cyan); }
.fx-note em { color: var(--ac-text-2); font-size: .68rem; font-style: normal; line-height: 1.5; }

/* One sweep as the note lands, then it stays put. */
.fx-note.just-on { animation: fxNoteIn .42s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes fxNoteIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .fx-note.just-on { animation: none; }
}

/* ── Console Build-up Effect ─────────────────────────────────────────────
   When the stage enters the live phase, the inner panels cascade in.
   This provides a satisfying "powering up" or "constructing" visual 
   before the first message is sent. */

.stage[data-phase="live"] .ac-topbar { animation: acBuildUp .5s ease-out both; }
.stage[data-phase="live"] .ac-chat-panel { animation: acBuildUp .6s ease-out .1s both; }
.stage[data-phase="live"] .ac-canvas-panel { animation: acBuildUp .6s ease-out .25s both; }
.stage[data-phase="live"] .ac-statusbar { animation: acBuildUp .5s ease-out .4s both; }

@keyframes acBuildUp {
  0% { opacity: 0; transform: translateY(12px); }
  100% { opacity: 1; transform: none; }
}

@keyframes acMessageIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ── Legibility floor ──────────────────────────────────────────────────────
   The console was drawn as an instrument panel, and instrument panels are
   drawn small. Fourteen rules here set text below 12px — the status bar ran
   at .44rem (7px) and the overlines at .5rem (8px) — and the muted ink
   (#6f6b79) measured 3.9:1 against the console's ground while the status bar's
   own #555a69 measured 2.9:1. Neither is readable, and neither is a matter of
   taste: 12px and 4.5:1 are the floor.

   The look survives it. What made this panel read as an instrument was the
   monospace face, the letter-spacing and the restraint of the palette, none of
   which change here. Collected in one block rather than edited in place so the
   floor is a single thing to check, and stated with the same selectors as the
   originals so it wins purely on order.

   The Readiness block below must stay last — see its own note. */

.ac { --ac-text-3: #8a8695; }        /* was #6f6b79 — 3.9:1. Now 5.5:1. */

.ac-brand small,
.ac-session,
.ac-live,
.ac-reset-btn,
.ac-tab-count,
.ac-panel-head p,
.ac-overline,
.ac-channels button,
.ac-suggestions > span,
.ac-suggestions button,
.ac-suggestions button span,
.ac-statusbar,
.fx-note b,
.fx-note em { font-size: .75rem; }

/* The overline is a label, not a heading; at 12px its tracking is what stops
   it competing with the h3 underneath, so it keeps the tracking and loses the
   size trick it was using instead. */
.ac-overline { letter-spacing: .14em; }

/* #555a69 on #0a0c12 was 2.9:1 — the footer said AGENT OFFLINE in text almost
   nobody could read. The readiness colours below override this per state. */
.ac-statusbar { color: var(--ac-text-3); }
.ac-statusbar b { color: var(--ac-text-2); }

/* ── Readiness ──────────────────────────────────────────────────────────────
   Colour is part of the claim, not decoration. A cyan pulse beside "the agent
   is unavailable" still reads as healthy at a glance, so the pill and the
   footer light track exactly the same evidence the text does — and stop
   pulsing when there is nothing alive to pulse about.

   Kept at the end of the file deliberately: these must win over the default
   `.ac-live i` and `.ac-statusbar > span:first-child` rules above, which they
   tie with on specificity. */
.ac-live[data-readiness="degraded"] {
  border-color: rgba(229,172,51,.28);
  background: rgba(229,172,51,.08);
  color: #f6e2b0;
}
.ac-live[data-readiness="offline"] {
  border-color: rgba(255,117,102,.3);
  background: rgba(255,117,102,.08);
  color: #ffd2cb;
}
.ac-live[data-readiness="unverified"] {
  border-color: rgba(160,166,180,.22);
  background: rgba(160,166,180,.06);
  color: #c2c7d2;
}
.ac-live[data-readiness="degraded"] i { background: #e5ac33; box-shadow: 0 0 0 4px rgba(229,172,51,.12); animation: none; }
.ac-live[data-readiness="offline"] i { background: #ff7566; box-shadow: 0 0 0 4px rgba(255,117,102,.12); animation: none; }
.ac-live[data-readiness="unverified"] i { background: #9aa1b0; box-shadow: none; animation: none; }

.ac-statusbar > span[data-readiness="degraded"] { color: #e5ac33; }
.ac-statusbar > span[data-readiness="offline"] { color: #ff7566; }
.ac-statusbar > span[data-readiness="unverified"] { color: var(--ac-text-3); }
.ac-statusbar > span[data-readiness="degraded"] i { background: #e5ac33; box-shadow: none; animation: none; }
.ac-statusbar > span[data-readiness="offline"] i { background: #ff7566; box-shadow: none; animation: none; }
.ac-statusbar > span[data-readiness="unverified"] i { background: #9aa1b0; box-shadow: none; animation: none; }

/* ── Handover ───────────────────────────────────────────────────────────────
   Appears only when the server says the conversation has reached the point of
   being worth a proposal, and shows only what the server proved: a reference it
   issued, a ticket it raised, and a per-channel delivery state that says
   "sending" until the outbox reports otherwise. */
.ac-handover {
  margin: 0 20px 16px;
  padding: 16px 18px;
  border: 1px solid rgba(77,163,255,.28);
  border-radius: 14px;
  background: rgba(77,163,255,.06);
}
.ac-handover[hidden] { display: none; }
.ac-handover-head b { display: block; font-size: .92rem; color: var(--ac-text); }
.ac-handover-head p { margin: 4px 0 14px; font-size: .74rem; color: var(--ac-text-2); line-height: 1.6; }

.ac-handover-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.ac-handover-form label { display: grid; gap: 5px; min-width: 0; }
.ac-handover-form label span { font-size: .64rem; color: var(--ac-text-3); font-weight: 600; }
.ac-handover-form input {
  min-width: 0;
  padding: 9px 11px;
  border: 1px solid var(--ac-line);
  border-radius: 9px;
  background: rgba(0,0,0,.28);
  color: var(--ac-text);
  font: inherit;
  font-size: .8rem;
}
.ac-handover-form input:focus-visible { outline: 2px solid var(--ac-cyan); outline-offset: 1px; }
.ac-handover-form input:disabled { opacity: .55; }
.ac-handover-form button {
  grid-column: 1 / -1;
  padding: 11px 18px;
  border: 0;
  border-radius: 10px;
  background: var(--ac-cyan);
  color: #05070a;
  font: inherit;
  font-size: .8rem;
  font-weight: 700;
  cursor: pointer;
}
.ac-handover-form button:disabled { cursor: default; opacity: .6; }
.ac-handover-error:empty { display: none; }
.ac-handover-error {
  grid-column: 1 / -1;
  margin: 0;
  color: #ff7566;
  font-size: .72rem;
  line-height: 1.5;
}

.ac-handover-done b { display: block; margin-bottom: 10px; font-size: .92rem; color: var(--ac-text); }
.ac-handover-done dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; margin: 0 0 14px; font-size: .74rem; }
.ac-handover-done dt { color: var(--ac-text-3); }
.ac-handover-done dd { margin: 0; font-family: var(--f-data); color: var(--ac-text); }
.ac-handover-download {
  display: inline-block;
  padding: 10px 18px;
  border-radius: 10px;
  background: var(--ac-cyan);
  color: #05070a;
  font-size: .78rem;
  font-weight: 700;
  text-decoration: none;
}

.ac-delivery { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0; padding: 0; list-style: none; }
.ac-delivery li {
  display: flex;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--ac-line);
  border-radius: 999px;
  font-size: .64rem;
}
.ac-delivery li span { color: var(--ac-text-3); }
.ac-delivery li b { font-weight: 700; color: var(--ac-text-2); }
.ac-delivery li.is-delivered { border-color: rgba(74,222,128,.3); }
.ac-delivery li.is-delivered b { color: var(--ac-mint); }
.ac-delivery li.is-failed { border-color: rgba(255,117,102,.3); }
.ac-delivery li.is-failed b { color: #ff7566; }
