/* code-chat.css — the builder's chat: the plan card, thinking, steps and turns. It lived inline in code.html,
   and /video is now built from the same chat ("make it exactly like it but the preview is video", the owner,
   2026-10-31), so both pages link it from where the inline block stood and the cascade is unchanged. */
/* ══════════════════════════════════════════════════════════════
   PLAN MODE v2 — Claude-style plan card & clarify UI
   ══════════════════════════════════════════════════════════════ */

/* --surface, --surface2 and --ink2 are read twenty-five times below
   and were never defined on this page. They live in admin.css,
   login.css and mobile.css, and code.html loads none of those — so
   every one of them fell back to its literal, and the literals are
   light.

   --ink is NOT in that group: code.css does define it, as #f5f9fc in
   dark. That mismatch is the whole bug. The card painted itself with
   a fallback white --surface and then wrote the title in the theme's
   real near-white --ink, so in dark mode the plan had an invisible
   heading on a white card in the middle of a dark page. The overview
   stayed readable only because --ink2 was undefined too and fell back
   to #666.

   Defined here rather than renamed at each use: one place to look,
   and nothing else loaded on this page reads var(--surface).

   The dark values are warm deliberately. The rest of the dark theme
   is neutral grey (--paper:#18191b, --card:#26282b), which reads cold
   beside --tint (#3d3428) and --th-dot (#f6f1e8) — both already warm.
   mobile.css reached the same conclusion on its own: its dark
   --surface is #211e1b. */
:root {
  --surface: #ffffff;
  --surface2: #f6f5f4;
  --ink2: #5c6062;
  --plan-line: var(--line, rgba(0,0,0,.12));
  --plan-line-soft: rgba(0,0,0,.08);
}
:root[data-theme="dark"] {
  --surface: #211e1b;
  --surface2: #2a2623;
  --ink2: #a49c93;
  /* Borders and separators inside these cards only. --line is a
     page-wide token and a cool #33363a; a warm card with a cold edge
     looks like two designs touching. */
  --plan-line: #3a342e;
  --plan-line-soft: rgba(255,255,255,.07);
}

.ag-plan {
  background: var(--surface, #fff);
  border: 1px solid var(--plan-line);
  border-radius: 14px;
  padding: 0;
  margin: 14px 0;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0,0,0,.06), 0 1px 3px rgba(0,0,0,.04);
  animation: sqFadeUp .25s var(--ease-snappy) both;
}
/* A shadow tuned on white does nothing on a dark page — the card needs
   depth from contrast with the surface instead, so it gets a lifted
   edge rather than a drop. */
:root[data-theme="dark"] .ag-plan {
  box-shadow: 0 1px 0 rgba(255,255,255,.04) inset, 0 8px 28px rgba(0,0,0,.45);
}
.ag-plan.done { opacity: .65; box-shadow: none; }

.pl2-think {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line, rgba(0,0,0,.08));
  font-size: .82rem;
  color: var(--ink2, #777);
  background: var(--surface2, rgba(0,0,0,.02));
}
.pl2-think-txt { margin-left: 2px; font-weight: 500; }
.pl2-think-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent, #6366f1);
  opacity: .7;
  animation: pl2-pulse 1.2s ease infinite;
}
.pl2-think-dot:nth-child(2) { animation-delay: .15s; }
.pl2-think-dot:nth-child(3) { animation-delay: .3s; }
@keyframes pl2-pulse {
  0%,80%,100% { transform: scale(1); opacity: .4; }
  40% { transform: scale(1.4); opacity: 1; }
}

.pl2-head, .pl2-section, .pl2-actions {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .3s ease, transform .3s ease;
}
.ag-plan.pl2-revealed .pl2-head { opacity: 1; transform: translateY(0); }
.ag-plan.pl2-revealed .pl2-section { opacity: 1; transform: translateY(0); }
.ag-plan.pl2-revealed .pl2-actions { opacity: 1; transform: translateY(0); }

.ag-plan.pl2-revealed .pl2-think {
  opacity: 0; height: 0; padding: 0; border: 0;
  overflow: hidden;
  transition: opacity .2s ease, height .25s ease, padding .25s ease;
}

.pl2-head {
  padding: 16px 20px 14px;
  border-bottom: 1px solid var(--line, rgba(0,0,0,.07));
}
.pl2-title-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 6px;
}
.pl2-icon {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent, #6366f1) 12%, transparent);
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.pl2-icon svg { width: 16px; height: 16px; stroke: var(--accent, #6366f1); }
.pl2-kicker {
  display: block;
  font-size: .67rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent, #6366f1);
  margin-bottom: 2px;
}
.pl2-title {
  display: block;
  font-size: 1.05rem;
  font-weight: 650;
  color: var(--ink, #111);
  line-height: 1.25;
}
.pl2-overview {
  font-size: .83rem;
  color: var(--ink2, #666);
  line-height: 1.55;
  margin: 0;
}

.pl2-section {
  padding: 14px 20px;
  border-bottom: 1px solid var(--line, rgba(0,0,0,.06));
}
.pl2-sec-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: .7rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink2, #888);
  margin-bottom: 10px;
}
.pl2-sec-label svg { width: 13px; height: 13px; flex: none; stroke: currentColor; }

.pl2-phases { display: flex; flex-direction: column; gap: 0; }
.pl2-phase {
  display: flex;
  gap: 12px;
  position: relative;
}
.pl2-phase-line {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: none;
  width: 14px;
}
.pl2-phase-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent, #6366f1);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #6366f1) 20%, transparent);
  flex: none;
  margin-top: 4px;
}
.pl2-phase-rail {
  width: 2px;
  flex: 1;
  background: var(--line, rgba(0,0,0,.1));
  margin: 4px 0;
  min-height: 16px;
}
.pl2-phase-body {
  flex: 1;
  padding-bottom: 14px;
}
.pl2-phase.last .pl2-phase-body { padding-bottom: 0; }
.pl2-phase-name {
  font-size: .83rem;
  font-weight: 620;
  color: var(--ink, #111);
  margin-bottom: 4px;
}
.pl2-steps {
  list-style: none;
  padding: 0; margin: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.pl2-steps li {
  font-size: .78rem;
  color: var(--ink2, #666);
  line-height: 1.5;
  padding-left: 12px;
  position: relative;
}
.pl2-steps li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 7px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--ink2, #aaa);
}

.pl2-row-section .pl2-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.pl2-chip {
  font-size: .74rem;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: 6px;
  line-height: 1.4;
  white-space: nowrap;
}
.pl2-chip-screen {
  background: color-mix(in srgb, var(--accent, #6366f1) 10%, transparent);
  color: var(--accent, #6366f1);
  border: 1px solid color-mix(in srgb, var(--accent, #6366f1) 22%, transparent);
}
.pl2-chip-tech {
  background: var(--surface2, rgba(0,0,0,.04));
  color: var(--ink2, #555);
  border: 1px solid var(--line, rgba(0,0,0,.1));
}

.pl2-assume-section {
  background: color-mix(in srgb, #f59e0b 6%, transparent);
}
.pl2-assume-label { color: #d97706; }
.pl2-assume-list {
  list-style: none;
  padding: 0; margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.pl2-assume-list li {
  font-size: .78rem;
  color: var(--ink2, #666);
  line-height: 1.45;
  padding-left: 14px;
  position: relative;
}
.pl2-assume-list li::before {
  content: "•";
  position: absolute;
  left: 4px;
  color: #d97706;
}

.pl2-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 20px;
  background: var(--surface2, rgba(0,0,0,.02));
  border-top: 1px solid var(--line, rgba(0,0,0,.07));
}
.pl2-go, .pl2-edit {
  border: 0;
  border-radius: 8px;
  padding: 8px 16px;
  font: inherit;
  font-size: .82rem;
  font-weight: 550;
  cursor: pointer;
  transition: all .15s ease;
}
.pl2-go {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #fff;
  background: var(--accent, #6366f1);
}
.pl2-go svg { width: 14px; height: 14px; }
.pl2-go:hover { filter: brightness(1.08); transform: translateY(-1px); }
.pl2-edit {
  color: var(--ink2, #666);
  background: transparent;
  border: 1px solid var(--line, rgba(0,0,0,.15));
}
.pl2-edit:hover { background: var(--surface2, rgba(0,0,0,.05)); }
.pl2-chose {
  font-size: .8rem;
  color: var(--ink2, #888);
  padding: 6px 0;
}

/* Clarifying questions card */
.ag-clarify {
  background: var(--surface, #fff);
  border: 1px solid var(--line, rgba(0,0,0,.12));
  border-radius: 14px;
  padding: 0;
  margin: 14px 0;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0,0,0,.06);
  animation: sqFadeUp .25s var(--ease-snappy) both;
}
.ag-clarify.done { opacity: .65; }
.clr-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--line, rgba(0,0,0,.07));
}
.clr-icon {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent, #6366f1) 12%, transparent);
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.clr-icon svg { width: 17px; height: 17px; stroke: var(--accent, #6366f1); }
.clr-kicker {
  display: block;
  font-size: .85rem;
  font-weight: 650;
  color: var(--ink, #111);
  margin-bottom: 2px;
}
.clr-sub {
  font-size: .78rem;
  color: var(--ink2, #888);
  margin: 0;
}
.clr-qs {
  padding: 14px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.clr-q {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: .83rem;
  color: var(--ink, #111);
  line-height: 1.45;
}
.clr-qn {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--accent, #6366f1);
  color: #fff;
  font-size: .62rem;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.clr-form {
  padding: 12px 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-top: 1px solid var(--line, rgba(0,0,0,.06));
  background: var(--surface2, rgba(0,0,0,.02));
}
.clr-input {
  width: 100%;
  font: inherit;
  font-size: .82rem;
  padding: 8px 12px;
  border: 1px solid var(--line, rgba(0,0,0,.15));
  border-radius: 8px;
  background: var(--surface, #fff);
  color: var(--ink, #111);
  outline: none;
  box-sizing: border-box;
}
.clr-input:focus { border-color: var(--accent, #6366f1); }
.clr-send {
  align-self: flex-end;
  border: 0;
  border-radius: 7px;
  padding: 7px 16px;
  font: inherit;
  font-size: .82rem;
  font-weight: 550;
  color: #fff;
  background: var(--accent, #6366f1);
  cursor: pointer;
  transition: all .15s ease;
}
.clr-send:hover { filter: brightness(1.08); }
.clr-chose {
  font-size: .8rem;
  color: var(--ink2, #888);
  padding: 8px 20px;
}

/* ---------- the agent's own question ----------
   Distinct from .ag-clarify above, which is the PLAN flow asking for
   detail before it writes a plan. This one is the running agent
   stopping mid-task because it has hit a choice it should not make for
   you — so it looks like a decision to take, not a form to fill in. */
.ag-ask {
  background: var(--surface, #fff);
  border: 1px solid var(--plan-line, rgba(0,0,0,.12));
  border-radius: 16px;
  /* Narrower than the message column. A decision card that runs the full
     width reads as a form; held in, it reads as a thing to answer. */
  max-width: 560px;
  margin: 12px 0;
  overflow: hidden;
  box-shadow: 0 2px 10px rgba(0,0,0,.05);
  animation: sqFadeUp .22s var(--ease-snappy) both;
}
.ag-ask.done { opacity: .65; box-shadow: none; }

/* THE HEADER IS THE QUESTION, not a label about the question.
   It used to be an icon, a kicker reading "One decision for you" and a
   line of apology underneath — three rows of chrome before the thing
   being asked, which was then repeated a fourth time below. The question
   is the only sentence here worth full weight. */
.ask-head { display: flex; align-items: flex-start; gap: 10px; padding: 15px 16px 11px; }
.ask-title { flex: 1; min-width: 0; font-size: .9rem; font-weight: 650; line-height: 1.4; color: var(--ink, #111); }
.ask-tools { display: flex; gap: 2px; flex: none; margin-top: -3px; }
.ask-tool {
  width: 26px; height: 26px; flex: none; display: grid; place-items: center;
  border: 0; border-radius: 7px; background: none; cursor: pointer;
  color: var(--ink2, #888); font: inherit;
  transition: background .15s ease, color .15s ease;
}
.ask-tool:hover { background: var(--surface2, rgba(0,0,0,.05)); color: var(--ink, #111); }
.ask-tool svg { width: 15px; height: 15px; }
.ask-chev { transition: transform .18s var(--ease-snappy, ease); }
.ag-ask.collapsed .ask-body, .ag-ask.collapsed .ask-actions { display: none; }
.ag-ask.collapsed .ask-head { padding-bottom: 14px; }
.ag-ask.collapsed .ask-chev { transform: rotate(-90deg); }

.ask-q { padding: 0 12px; }
/* A card carrying more than one question needs a heading per question —
   the card header can only ever be one of them. A single question has
   already been said at the top, so it does not repeat here. */
.ask-q + .ask-q { margin-top: 15px; }
.ask-q-head { display: flex; align-items: center; gap: 7px; padding: 0 4px 8px; flex-wrap: wrap; }
.ask-chip {
  font-size: .68rem; font-weight: 650; letter-spacing: .02em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 999px;
  background: color-mix(in oklch, var(--accent, #1aa6df) 12%, transparent);
  color: var(--accent, #1aa6df);
}
.ask-q-text { font-size: .86rem; font-weight: 600; color: var(--ink, #111); }
.ask-multi { font-size: .72rem; color: var(--ink2, #888); }

.ask-opts { display: flex; flex-direction: column; gap: 7px; }
/* A filled row on its own ground, not an outlined box. Outlines at this
   size stack into a ladder of rectangles; a soft fill reads as one list
   of things you can press. */
.ask-opt {
  display: flex; gap: 12px; align-items: flex-start; width: 100%;
  text-align: left; cursor: pointer; font: inherit;
  padding: 11px 13px; border-radius: 12px;
  border: 1px solid transparent;
  background: var(--surface2, #f6f5f4);
  transition: background .15s ease, border-color .15s ease;
}
.ask-opt:hover { border-color: var(--plan-line, rgba(0,0,0,.12)); }
.ask-opt.on { border-color: var(--accent, #1aa6df); background: color-mix(in oklch, var(--accent, #1aa6df) 8%, var(--surface2, #f6f5f4)); }
.ask-opt:disabled { cursor: default; }
.ask-opt-main { flex: 1; min-width: 0; }
.ask-opt-label { display: block; font-size: .85rem; font-weight: 600; line-height: 1.35; color: var(--ink, #111); }
.ask-opt-desc { margin: 2px 0 0; font-size: .78rem; line-height: 1.45; color: var(--ink2, #888); }
/* THE MARK IS ON THE RIGHT, and it is a radio unless the question takes
   more than one answer — the shape is the only thing telling you whether
   picking a second choice replaces the first. */
.ask-mark {
  width: 18px; height: 18px; flex: 0 0 18px; margin-top: 1px;
  border-radius: 50%;
  border: 1.5px solid var(--plan-line, rgba(0,0,0,.25));
  display: grid; place-items: center; color: #fff;
  transition: background .15s ease, border-color .15s ease;
}
.ask-q[data-multi="1"] .ask-mark { border-radius: 6px; }
.ask-opt.on .ask-mark { background: var(--accent, #1aa6df); border-color: var(--accent, #1aa6df); }
.ask-mark svg { width: 11px; height: 11px; opacity: 0; }
.ask-opt.on .ask-mark svg { opacity: 1; }

/* Other is an option like the others, and its input lives inside the same
   block — so choosing it and answering it are one gesture in one place. */
.ask-other { margin-top: 7px; border-radius: 12px; background: var(--surface2, #f6f5f4); overflow: hidden; border: 1px solid transparent; transition: border-color .15s ease; }
.ask-other.on { border-color: var(--accent, #1aa6df); }
.ask-other .ask-opt { background: none; border-radius: 0; border: 0; }
.ask-other .ask-opt.on { background: none; }
.ask-inwrap { padding: 0 13px 12px; }
.ask-input {
  width: 100%; box-sizing: border-box;
  padding: 9px 11px; border-radius: 9px; font: inherit; font-size: .82rem;
  min-height: 36px;
  border: 1px solid var(--plan-line, rgba(0,0,0,.12));
  background: var(--surface, #fff); color: var(--ink, #111);
  resize: vertical;
}
.ask-input:focus { outline: none; border-color: var(--accent, #1aa6df); }

/* Skip then Submit, bottom right, in that order — the destructive-ish
   choice first and the one you want under the thumb last. */
.ask-actions {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 13px 16px 15px;
}
.ask-hint { margin-right: auto; font-size: .73rem; color: var(--ink2, #888); }
.ask-skip {
  padding: 7px 15px; border-radius: 9px; cursor: pointer;
  font: inherit; font-size: .82rem; font-weight: 600;
  border: 1px solid var(--plan-line, rgba(0,0,0,.12));
  background: var(--surface, #fff); color: var(--ink, #111);
  transition: background .15s ease, border-color .15s ease;
}
.ask-skip:hover { background: var(--surface2, #f6f5f4); }
.ask-send {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 16px; border: none; border-radius: 9px; cursor: pointer;
  font: inherit; font-size: .82rem; font-weight: 640;
  background: var(--accent, #1aa6df); color: var(--on-accent, #fff);
  transition: filter .16s ease, background .16s ease;
}
.ask-send:hover { filter: brightness(1.08); }
/* Filled grey, not the accent at 40%. A faded blue button still reads as
   the blue button and invites the click it is going to refuse. */
.ask-send:disabled {
  background: color-mix(in oklch, var(--ink2, #888) 38%, var(--surface2, #f6f5f4));
  color: var(--surface, #fff); cursor: not-allowed; filter: none;
}
.ask-chose { font-size: .8rem; color: var(--ink2, #888); padding: 8px 18px 14px; display: block; }

/* ---------- the agent's terminal ----------
   Everything the run actually did, as it does it. The stage events were
   already rendered as a tidy checklist, which is the right summary and
   the wrong thing to read when something has gone sideways — it shows
   what step the agent is on and not what it TRIED. tool_start,
   tool_denied, command and context were being emitted and dropped on
   the floor entirely.

   It stays after the run ends, deliberately. A terminal whose history
   is cleared on completion answers "what is it doing" and never "what
   did it do", and the second question is the one asked after the fact. */
.ag-term {
  background: var(--term-bg, #0d1117);
  border: 1px solid var(--term-line, rgba(255,255,255,.1));
  border-radius: 12px;
  margin: 14px 0;
  overflow: hidden;
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
  animation: sqFadeUp .25s var(--ease-snappy) both;
}
.term-head {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 13px;
  border-bottom: 1px solid var(--term-line, rgba(255,255,255,.1));
  background: rgba(255,255,255,.03);
  cursor: pointer;
  user-select: none;
}
.term-dots { display: flex; gap: 5px; flex: 0 0 auto; }
.term-dot { width: 9px; height: 9px; border-radius: 50%; background: rgba(255,255,255,.18); }
.term-title {
  font-size: .76rem; font-weight: 600; letter-spacing: .01em;
  color: rgba(255,255,255,.72); flex: 1;
}
.term-meta { font-size: .7rem; color: rgba(255,255,255,.4); font-variant-numeric: tabular-nums; }
.term-caret { color: rgba(255,255,255,.4); transition: transform var(--dur-chill, .2s); }
.ag-term.collapsed .term-caret { transform: rotate(-90deg); }
.ag-term.collapsed .term-body { display: none; }

/* A live run breathes; a finished one does not. */
.term-dot.live { background: #3fb950; animation: termPulse 1.4s ease-in-out infinite; }
.term-dot.failed { background: #f85149; }
@keyframes termPulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.term-body {
  max-height: 320px; overflow-y: auto;
  padding: 10px 13px 12px;
  font-size: .76rem; line-height: 1.65;
}
.term-line { display: flex; gap: 8px; white-space: pre-wrap; word-break: break-word; }
.term-mark { flex: 0 0 auto; width: 11px; text-align: center; opacity: .85; }
.term-text { flex: 1; color: rgba(255,255,255,.8); }
.term-dim { color: rgba(255,255,255,.42); }
.term-ok { color: #3fb950; }
.term-bad { color: #f85149; }
.term-warn { color: #d29922; }
.term-cmd { color: #79c0ff; }
.term-path { color: #a5d6ff; }
/* Command output, verbatim and indented under its command. */
.term-out {
  margin: 2px 0 6px 19px; padding: 6px 9px;
  border-left: 2px solid rgba(255,255,255,.12);
  color: rgba(255,255,255,.55); font-size: .72rem; white-space: pre-wrap;
  max-height: 160px; overflow-y: auto;
}
/* The agent's own words, arriving as they are written. Brighter than
   command output because it is someone talking rather than a program
   printing, and uncapped because unlike a build log it is meant to be
   read straight through — the terminal body scrolls instead. */
.term-stream {
  color: rgba(255,255,255,.82);
  border-left-color: rgba(120,190,255,.45);
  max-height: none; overflow: visible;
}
.term-empty { color: rgba(255,255,255,.35); font-style: italic; }

/* ══════════════════════════════════════════════════════════════
   THINKING v2 — the turn narrating itself
   --------------------------------------------------------------
   The old panel was a collapsed box with a header: you got a label
   and a clock, and the steps were behind a chevron. It read as a
   receipt for work already done rather than as work happening.

   This is the same data laid out as a running account — each step a
   line as it happens, and one live status line underneath carrying
   the three things worth knowing while you wait: how long it has
   been, what it has spent, and what it is doing right now.
   ══════════════════════════════════════════════════════════════ */
.th2 { margin: 6px 0 10px; }

/* The three dots, leading. Their animation lives in code.css and is
   driven off .ag-thinking:not(.done), so it stops on its own. */
/* The header opens the thinking, as Claude's does. It used to fold the
   steps away, with the trace behind a separate "Show thinking" link
   under the live line — two controls for one panel, and the one that
   looked like the control did the less interesting thing. A panel with
   no thinking in it has nothing to open, so it shows no chevron and
   takes no click; .folded is only the older-turn placeholder now, which
   still opens to fetch its steps. */
.th2-top { display: flex; align-items: center; gap: 2px; padding: 2px 0 6px; cursor: pointer; }
.th2:not(.has-thoughts):not(.folded) .th2-top { cursor: default; }
.th2:not(.has-thoughts):not(.folded) .th2-fold { display: none; }
.th2-fold {
  width: 15px; height: 15px; flex: none; margin-left: 6px;
  color: var(--mut, #8a8f91); opacity: .7;
  /* Down when open, which is the resting state, so the folded state is
     the only one that needs a rule. Stating it the other way round meant
     a base rotation fighting a `:not()` override. */
  transform: rotate(0deg);
  transition: transform .2s var(--ease-snappy, ease), opacity .15s ease;
}
.th2-top:hover .th2-fold { opacity: 1; }
.th2.thinking-open .th2-fold { transform: rotate(180deg); }
.th2.folded .th2-fold { transform: rotate(-90deg); }
.th2.folded .th2-steps { display: none; }
.th2-title {
  font-size: 1.05rem; font-weight: 600; color: var(--ink, #1b252b);
  letter-spacing: -.01em;
}
/* While it runs, the word breathes with the dots rather than sitting
   still beside them. */
.ag-thinking:not(.done) .th2-title {
  background: linear-gradient(90deg,
    var(--ink, #1b252b) 0%, var(--ink, #1b252b) 12%, var(--mut, #8a8f91) 25%, var(--ink, #1b252b) 38%, var(--ink, #1b252b) 100%) 0 0 / 200% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: th2Sweep 2.6s linear infinite;
}
.th2-steps { display: flex; flex-direction: column; gap: 1px; padding-left: 2px; }

.th2-step {
  display: flex; align-items: baseline; gap: 7px;
  padding: 3px 0;
  font-size: .92rem; line-height: 1.5;
  color: var(--ink-2, #6b7076);
  opacity: 0; transform: translateY(3px);
  animation: th2In .34s cubic-bezier(.16,1,.3,1) forwards;
}
@keyframes th2In { to { opacity: 1; transform: none; } }
.th2-step-text { min-width: 0; }
/* The chevron is an affordance, not decoration: it marks the rows
   that carry a detail the step replaced itself with. */
.th2-step-chev { flex: none; opacity: .5; font-size: .85em; transform: translateY(-1px); }
.th2-step.busy .th2-step-text {
  /* A sweep rather than a spinner. The row IS the progress indicator,
     so a second spinning thing beside it is two answers to one
     question. */
  background: linear-gradient(90deg,
    var(--ink-2, #6b7076) 0%, var(--ink-2, #6b7076) 12%, var(--ink, #1b252b) 25%, var(--ink-2, #6b7076) 38%, var(--ink-2, #6b7076) 100%) 0 0 / 200% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: th2Sweep 1.9s linear infinite;
}
/* 200% size with a 200-point travel, and it has to be that pair.
   background-position percentages resolve against (container - image),
   not the image, so a size of S% moving by ΔP points travels
   W·ΔP/100 while the pattern repeats every W·S/100 — equal only when
   S = ΔP = 200. It was 220/220 here and 240/220 on the title, landing
   a fifth of a tile out of phase every loop, which is the highlight
   jumping back rather than arriving. */
@keyframes th2Sweep { from { background-position: 0 0; } to { background-position: -200% 0; } }
.th2-step.failed { color: #e0616d; }

/* The one word in the sentence you are actually scanning for. The rest
   is grammar; the filename is the fact. */
.th2-name { color: var(--ink, #1b252b); font-weight: 500; }

/* What the agent SAID, between the things it did.

   This is the part that explains — "that fell to the other path", "let
   me try it a different way" — and it is the only record of why a run
   went the way it did. It streamed into the terminal, which meant it
   was a console effect that scrolled away, and then vanished entirely
   once the terminal stopped opening for runs with no commands. It
   belongs in the transcript, at full contrast, and it stays. */
.th2-said {
  color: var(--ink, #1b252b);
  font-size: .95rem;
  line-height: 1.6;
  margin: 9px 0 7px;
  white-space: pre-wrap;
  animation: th2In .3s var(--ease-snappy, ease) both;
}
.th2-said:first-child { margin-top: 2px; }

/* A step that has actions inside it opens to show them. The sentence is
   the summary of a batch — "edited code.html, ran a command" — and the
   batch is the thing worth keeping, but not at the cost of never being
   able to see what it was. */
.th2-step.has-detail { cursor: pointer; }
.th2-step.has-detail .th2-step-chev { transition: transform .18s var(--ease-snappy, ease); }
.th2-step.open .th2-step-chev { transform: rotate(90deg); }
.th2-sub {
  border: 1px solid var(--line, rgba(0,0,0,.12));
  border-radius: 10px;
  margin: 5px 0 7px;
  padding: 3px 0;
  overflow: hidden;
  animation: th2In .2s var(--ease-snappy, ease) both;
}
.th2-sub .th2-step { padding: 6px 12px; cursor: default; }
.th2-sub .th2-step + .th2-step { border-top: 1px solid var(--plan-line-soft, rgba(0,0,0,.06)); }

/* How much changed, beside what changed. Tabular so the numbers do not
   shuffle as they climb, and using the diff tokens the rest of the app
   already defines for added and removed. */
.th2-diff { margin-left: 8px; font-size: .84em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.th2-add { color: var(--diff-add, #2ea043); font-weight: 600; }
.th2-del { color: var(--diff-del, #e5534b); font-weight: 600; margin-left: 5px; }
/* A step still running should not paint its counts through the shimmer's
   background-clip, which would make them transparent along with the text. */
.th2-step.busy .th2-diff { -webkit-text-fill-color: initial; }

/* The status line. */
/* ONE LINE, AND THE NUMBERS DO NOT MOVE.

   The row never wrapped — its ITEMS did. Each one is a flex child, so a
   long phase ("Almost done thinking…") squeezed the others below their
   own text width and each span broke internally: the elapsed time and the
   token count split across two lines into ragged columns, then snapped
   back into one line the moment the phase became "Done". The receipt
   reflowed under the reader twice per turn, for no reason they could see.

   So the numbers are rigid and the phase is the only thing that gives:
   it truncates instead of pushing, which keeps every figure in the same
   place from the first second of a run to the last. */
.th2-status {
  display: flex; align-items: center; gap: 9px;
  flex-wrap: nowrap; min-width: 0;
  padding: 5px 0 2px;
  font-size: .88rem; color: var(--mut, #8a8f91);
}
.th2-status > * { white-space: nowrap; }
.th2-status > .th2-num, .th2-status > .th2-sep { flex: none; }
.th2-phase { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* The Souqi bag, lit.

   Masked rather than drawn: assets/logo-mark.png IS the logo, alpha and
   all, so the silhouette is exactly the real mark and cannot drift from
   it the way a hand-traced path would. The mask takes only its alpha,
   which is what drops the background — and it means the colour is ours
   to animate, so the brand gradient sweeps through it while the turn
   runs and settles when it stops. */
.th2-spark {
  flex: none; width: 16px; height: 16px; display: block;
  -webkit-mask: url(/assets/logo-mark.png) center / contain no-repeat;
  mask: url(/assets/logo-mark.png) center / contain no-repeat;
  background: linear-gradient(115deg,
    #1aa6df 0%, #18c8a8 25%, #5cb12f 50%, #18c8a8 75%, #1aa6df 100%) 0 0 / 200% 100%;
  animation: th2Shine 2.4s linear infinite;
  /* Lit while it runs. The sweep alone was legible only if you were
     already looking at it; the glow is what makes "something is
     happening here" readable from across the message. */
  filter: drop-shadow(0 0 6px rgba(24, 200, 168, .55));
}
@keyframes th2Shine { from { background-position: 0 0; } to { background-position: -200% 0; } }
/* Stopped, and holding the brand's own three stops rather than a frame
   of the sweep — a finished run should look settled, not paused. */
/* Keyed off the status row itself, not off an ancestor: the row is moved
   out of the panel when the turn ends so it can sit under the reply, and
   a rule that needed .th2 above it stopped applying the moment it left. */
.th2-status.is-done .th2-spark {
  animation: none;
  background: linear-gradient(135deg, #1aa6df 0%, #18c8a8 55%, #5cb12f 100%);
  /* Lit, but not GLOWING. The glow belongs to the turn that is running
     and to nothing else: with it here too, a finished turn and the one
     still working shone side by side and the eye had no way to tell
     which was which. Three states, three weights — running glows, done
     holds the brand colours, and a turn from last week is grey. */
  opacity: .92;
  filter: none;
}
/* OFF, because it is over.

   A restored turn is a record, not an event: nothing is running, nothing
   is going to, and the mark sweeping its brand gradient in the scrollback
   claimed otherwise on every old message at once. Grey and unlit says
   "this already happened" without another word on the row to say it.
   Set on the row at creation rather than inherited from an ancestor, for
   the reason the rule above it gives: the row gets moved out of the
   panel, and anything keyed on .th2 stops applying the moment it does. */
.th2-status.is-past .th2-spark {
  animation: none;
  background: var(--mut, #8a8f91);
  opacity: .38;
  filter: none;
}
/* Standing on its own under the reply rather than tucked inside the
   panel, it needs its own breathing room. */
.th2-status.is-loose { margin: 2px 0 10px; }
.th2-sep { opacity: .45; }
.th2-phase { transition: opacity .2s ease; }
/* The live thought, under the heading. One line, and it truncates rather
   than wraps, so the steps below it do not jump as it changes. Empty until
   the model has thought or written something, and gone once the turn ends;
   the foot row carries the state throughout. */
.th2-live {
  margin: -3px 0 7px 1px; font-size: .88rem; color: var(--mut, #8a8f91);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.th2-live:empty, .ag-thinking.done .th2-live { display: none; }
/* The whole trace, opened from the heading. Open, it takes the live
   line's place — the line is the last sentence of this, and showing both
   printed it twice. Capped and scrolling, because a Max turn can think
   for tens of thousands of words, and set off by a rule on the left so it
   reads as the model's notes, not as the answer. */
.th2-thoughts { display: none; margin: -2px 0 8px 1px; }
.th2.thinking-open .th2-thoughts { display: block; }
.th2.thinking-open .th2-live { display: none; }
/* The agent's checklist. Quiet: it is the model's own plan, not the
   answer, so it takes the step rows' size and colour and marks state with
   a glyph rather than with colour alone. */
.th2-todos { display: flex; flex-direction: column; gap: 1px; margin: -2px 0 8px 2px; }
.th2-todos[hidden] { display: none; }
.th2-todo { display: flex; align-items: baseline; gap: 8px; font-size: .88rem; line-height: 1.45; color: var(--ink-2, #6b7076); min-width: 0; }
.th2-todo-text { min-width: 0; overflow-wrap: anywhere; }
.th2-todo-mark { flex: none; width: 11px; height: 11px; border: 1.5px solid currentColor; border-radius: 3px; transform: translateY(1px); opacity: .55; }
.th2-todo.is-doing { color: var(--ink, #1b252b); }
.th2-todo.is-doing .th2-todo-mark { opacity: 1; background: linear-gradient(currentColor, currentColor) center / 5px 5px no-repeat; }
.th2-todo.is-done .th2-todo-text { text-decoration: line-through; opacity: .6; }
.th2-todo.is-done .th2-todo-mark { opacity: .6; background: currentColor; }
.th2-thoughts-body {
  max-height: 260px; overflow-y: auto; overscroll-behavior: contain;
  padding: 2px 0 2px 11px; border-left: 2px solid var(--line, #e3e1dc);
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: .82rem; line-height: 1.5; color: var(--mut, #8a8f91);
}
.th2-num { font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════
   EXPLORE — a helper working inside the turn
   --------------------------------------------------------------
   The one part of a turn done by something other than the builder, so
   it is the one part drawn as a card rather than a line: a helper went
   off, looked, and came back with an answer, and that shape is worth
   seeing. It keeps the panel's three weights — running glows, done
   holds the brand colours, a turn from last week is grey — and folds
   itself to one line once it has handed its answer over, because the
   turn has moved on and the card is a footnote to it by then.
   ══════════════════════════════════════════════════════════════ */
.th2-agent {
  --ag-a: #1aa6df; --ag-b: #18c8a8; --ag-c: #5cb12f;
  --ag-teal: #0d8f78;
  --ag-line: color-mix(in srgb, var(--line, #cfc9c3) 78%, transparent);
  position: relative;
  margin: 8px 0 10px;
  border: 1px solid var(--ag-line);
  border-radius: 14px;
  background: var(--card, #fcfcfc);
  overflow: hidden;
  opacity: 0; transform: translateY(4px);
  animation: th2In .42s cubic-bezier(.16,1,.3,1) forwards;
  transition: box-shadow .6s ease, border-color .6s ease;
}
:root[data-theme="dark"] .th2-agent { --ag-teal: #4fd6bc; }
/* The edge. Brand gradient, flowing downward while it works — the same
   200/200 pairing as th2Sweep, for the same reason. */
.th2-agent::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, var(--ag-a), var(--ag-b), var(--ag-c), var(--ag-b), var(--ag-a)) 0 0 / 100% 200%;
}
.th2-agent.is-running {
  border-color: color-mix(in srgb, var(--ag-b) 38%, var(--ag-line));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ag-b) 9%, transparent),
              0 12px 30px -20px color-mix(in srgb, var(--ag-b) 75%, transparent);
}
.th2-agent.is-running::before { animation: th2AgentFlow 1.8s linear infinite; }
@keyframes th2AgentFlow { from { background-position: 0 0; } to { background-position: 0 -200%; } }
.th2-agent.is-failed::before { background: var(--mut, #8a8f91); opacity: .55; }
.th2-agent.is-past::before { background: var(--mut, #8a8f91); opacity: .35; }

.th2-agent-head {
  all: unset; box-sizing: border-box;
  display: flex; align-items: center; gap: 9px;
  width: 100%; padding: 10px 12px 10px 15px;
  cursor: pointer; font: inherit; color: inherit;
}
.th2-agent-head:focus-visible { outline: 2px solid var(--accent, #1aa6df); outline-offset: -3px; border-radius: 13px; }
.th2-agent.is-empty .th2-agent-head { cursor: default; }
.th2-agent.is-empty .th2-agent-chev { visibility: hidden; }

/* A compass, because it is looking for something rather than building it.
   The needle swings while it searches and comes to rest when it is done. */
.th2-agent-mark {
  flex: none; width: 24px; height: 24px; border-radius: 8px;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, var(--ag-a) 0%, var(--ag-b) 55%, var(--ag-c) 100%);
  box-shadow: 0 3px 10px -3px color-mix(in srgb, var(--ag-b) 70%, transparent), inset 0 1px 0 rgba(255,255,255,.28);
  transition: background .5s ease, box-shadow .5s ease, opacity .5s ease;
}
.th2-agent-mark svg { width: 15px; height: 15px; display: block; overflow: visible; }
.th2-agent-needle { transform-box: fill-box; transform-origin: center; }
.th2-agent.is-running .th2-agent-needle { animation: th2Needle 2.6s cubic-bezier(.45,0,.25,1) infinite; }
@keyframes th2Needle { 0%, 100% { transform: rotate(-30deg); } 50% { transform: rotate(34deg); } }
.th2-agent.is-failed .th2-agent-mark,
.th2-agent.is-past .th2-agent-mark { background: var(--mut, #8a8f91); box-shadow: none; opacity: .5; }

.th2-agent-badge {
  flex: none; padding: 2px 7px; border-radius: 99px;
  font-size: .68rem; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ag-teal); background: color-mix(in srgb, var(--ag-b) 14%, transparent);
}
.th2-agent.is-past .th2-agent-badge,
.th2-agent.is-failed .th2-agent-badge { color: var(--ink-2, #5c6062); background: color-mix(in srgb, var(--ink-2, #5c6062) 11%, transparent); }
.th2-agent-q {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: .92rem; font-weight: 500; color: var(--ink, #1b252b);
}
.th2-agent-time { flex: none; font-size: .8rem; color: var(--mut, #8a8f91); font-variant-numeric: tabular-nums; }
.th2-agent-chev {
  flex: none; width: 15px; height: 15px; color: var(--mut, #8a8f91);
  transition: transform .28s cubic-bezier(.16,1,.3,1);
}
.th2-agent.is-open .th2-agent-chev { transform: rotate(180deg); }

/* The result, once there is one. Indented to the question's edge so it
   reads as the answer to it. */
.th2-agent-foot {
  display: flex; align-items: center; gap: 7px; min-width: 0;
  margin-top: -3px; padding: 0 12px 10px 48px;
  font-size: .84rem; color: var(--ink-2, #5c6062);
  animation: th2In .3s cubic-bezier(.16,1,.3,1) both;
}
.th2-agent-foot[hidden] { display: none; }
.th2-agent-ok { flex: none; width: 14px; height: 14px; display: grid; place-items: center; color: var(--ag-teal); }
.th2-agent-ok svg { width: 14px; height: 14px; display: block; }
.th2-agent.is-failed .th2-agent-ok { color: #e0616d; }
.th2-agent.is-past .th2-agent-ok { color: var(--mut, #8a8f91); }
.th2-agent-sum { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.th2-agent-sum b { font-weight: 600; color: var(--ink, #1b252b); }
.th2-agent-sep { opacity: .45; margin: 0 6px; }

/* Open and shut by animating the row track, so the card grows to exactly
   what it holds rather than to a guessed max-height. */
.th2-agent-body {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .38s cubic-bezier(.16,1,.3,1);
}
.th2-agent.is-open .th2-agent-body { grid-template-rows: 1fr; }
.th2-agent-inner { min-height: 0; overflow: hidden; }

/* What it did, as a timeline: one node per lookup, joined by a thread.
   Capped, scrolling, and pinned to the newest while it runs; past the cap
   the oldest fade out at the top rather than being cut off by a hard edge. */
.th2-agent-steps {
  list-style: none; margin: 0; padding: 0 14px 10px 17px;
  max-height: 218px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
}
.th2-agent-steps.is-long {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 28px);
  mask-image: linear-gradient(to bottom, transparent 0, #000 28px);
}
.th2-agent-step {
  position: relative; display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 4px 0; font-size: .86rem; line-height: 1.45; color: var(--ink-2, #5c6062);
  animation: th2In .32s cubic-bezier(.16,1,.3,1) both;
}
.th2-agent-step::before {
  content: ""; position: absolute; left: 10px; top: 0; bottom: 0; width: 1px;
  background: var(--ag-line);
}
.th2-agent-step:first-child::before { top: 50%; }
.th2-agent-step:last-child::before { bottom: 50%; }
.th2-agent-step:only-child::before { display: none; }
.th2-agent-node {
  position: relative; z-index: 1; flex: none; width: 21px; height: 21px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--card, #fcfcfc); border: 1px solid var(--ag-line); color: var(--mut, #8a8f91);
}
.th2-agent-node svg { width: 11px; height: 11px; display: block; }
.th2-agent-step.is-read .th2-agent-node { color: var(--accent, #1aa6df); }
.th2-agent-step.is-search .th2-agent-node { color: var(--ag-teal); }
.th2-agent-step.is-miss { color: var(--mut, #8a8f91); }
.th2-agent-step.is-miss .th2-agent-node { color: var(--mut, #8a8f91); border-style: dashed; }
.th2-agent-step.is-refused { color: #e0616d; }
.th2-agent-step.is-refused .th2-agent-node { color: #e0616d; border-color: color-mix(in srgb, #e0616d 45%, transparent); }
.th2-agent-say { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.th2-agent-meta {
  flex: none; margin-left: auto; padding-left: 10px;
  font-size: .78rem; color: var(--mut, #8a8f91); font-variant-numeric: tabular-nums;
}
/* The lookup it is on now: a pulse in the node and the panel's own sweep
   across the words, so it reads as the same kind of "busy" as a step row. */
.th2-agent-step.is-pending .th2-agent-node { border-color: color-mix(in srgb, var(--ag-b) 45%, var(--ag-line)); }
.th2-agent-step.is-pending .th2-agent-node::after {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--ag-b); box-shadow: 0 0 8px var(--ag-b);
  animation: th2Pulse 1.3s ease-in-out infinite;
}
@keyframes th2Pulse { 0%, 100% { transform: scale(.65); opacity: .55; } 50% { transform: scale(1); opacity: 1; } }
.th2-agent-step.is-pending .th2-agent-say {
  background: linear-gradient(90deg,
    var(--ink-2, #5c6062) 0%, var(--ink-2, #5c6062) 12%, var(--ink, #1b252b) 25%, var(--ink-2, #5c6062) 38%, var(--ink-2, #5c6062) 100%) 0 0 / 200% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: th2Sweep 1.9s linear infinite;
}

/* The answer it handed the builder, word for word — the thing worth
   opening the card for. */
.th2-agent-report {
  margin: 0 14px 13px 17px; padding: 10px 13px 11px;
  border-radius: 11px;
  background: color-mix(in srgb, var(--ag-b) 6%, var(--paper, #f6f5f4));
  border: 1px solid color-mix(in srgb, var(--ag-b) 20%, transparent);
}
.th2-agent-report[hidden] { display: none; }
.th2-agent-report-h {
  margin-bottom: 6px;
  font-size: .68rem; font-weight: 650; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ag-teal);
}
.th2-agent.is-past .th2-agent-report-h { color: var(--ink-2, #5c6062); }
.th2-agent-report-body {
  max-height: 300px; overflow-y: auto; overscroll-behavior: contain;
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: .86rem; line-height: 1.6; color: var(--ink, #1b252b);
}
.th2-agent-report-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9em;
  padding: 1px 5px; border-radius: 5px;
  background: color-mix(in srgb, var(--ink, #1b252b) 7%, transparent);
}
.th2-agent-report-body strong { font-weight: 600; }

/* Helpers sent together, kept together. One card on its own is just a
   card; from the second one on, a caption says what the layout already
   shows — these ran at the same time — and the cards close ranks under it. */
.th2-agents { margin: 8px 0 10px; }
.th2-agents > .th2-agent { margin: 0; }
.th2-agents > .th2-agent + .th2-agent { margin-top: 6px; }
.th2-agents-cap {
  display: none; align-items: center; gap: 6px;
  margin: 0 0 6px 3px;
  font-size: .76rem; font-weight: 600; letter-spacing: .02em; color: var(--mut, #8a8f91);
  animation: th2In .3s cubic-bezier(.16,1,.3,1) both;
}
.th2-agents.is-many .th2-agents-cap { display: flex; }
.th2-agents-cap svg { width: 13px; height: 13px; flex: none; }
.th2-agents.is-live .th2-agents-cap svg { color: #18c8a8; }

@media (max-width: 420px) {
  .th2-agent-head { gap: 8px; padding-right: 10px; }
  .th2-agent-badge { display: none; }
  .th2-agent-foot { padding-left: 47px; }
}

.th2.done .th2-step.busy .th2-step-text {
  animation: none; -webkit-text-fill-color: currentColor; color: var(--ink-2, #6b7076);
}
@media (prefers-reduced-motion: reduce) {
  .th2-step { animation: none; opacity: 1; transform: none; }
  .th2-step.busy .th2-step-text { animation: none; -webkit-text-fill-color: currentColor; color: var(--ink-2); }
  .th2-spark { animation: none; }
  .th2-agent, .th2-agent-step, .th2-agent-foot { animation: none; opacity: 1; transform: none; }
  .th2-agent.is-running::before, .th2-agent.is-running .th2-agent-needle,
  .th2-agent-step.is-pending .th2-agent-node::after { animation: none; }
  .th2-agent-step.is-pending .th2-agent-say { animation: none; -webkit-text-fill-color: currentColor; color: var(--ink-2); }
  .th2-agent-body, .th2-agent-chev { transition: none; }
  .ag-thinking:not(.done) .th2-title {
    animation: none; -webkit-text-fill-color: currentColor; color: var(--ink);
  }
}
