/* ============================================================
   Brad O'Haire portfolio - Lab page styles
   Scoped to /lab. Reuses the design tokens from site.css
   (--bg, --panel, --panel2, --line, --ink, --muted, --dim,
   --accent, --accent2, --ok, --radius). Does NOT redefine tokens.
   Build 1 covers the intro, the Orchestrator Console, and the
   two empty section shells (#rollout, #triage) for Build 2.
   ============================================================ */

/* ---- Intro ---- */
.lab-lede{color:var(--muted);font-size:clamp(16px,2.1vw,18px);max-width:720px;margin:-8px 0 0}

/* ---- "Coming in this build" placeholder marker (shared by #rollout + #triage) ---- */
.lab-soon{display:flex;align-items:center;gap:12px;flex-wrap:wrap;color:var(--dim);font-size:14px;
  background:var(--panel);border:1px dashed var(--line);border-radius:12px;padding:16px 18px;margin:4px 0 0}
.lab-soon-tag{flex:0 0 auto;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--accent);background:rgba(110,168,254,.1);border:1px solid rgba(110,168,254,.25);
  border-radius:999px;padding:4px 11px}

/* ============================================================
   The Orchestrator Console
   ============================================================ */
.console{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 24px 22px}

/* honesty caption: prominent, sits first inside the console */
.console-honesty{display:block;color:var(--muted);font-size:13px;line-height:1.6;margin:0 0 22px;
  max-width:860px;padding:14px 16px;background:var(--panel2);border:1px solid var(--line);border-radius:12px}
.console-honesty-tag{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--accent);border:1px solid rgba(110,168,254,.3);border-radius:5px;padding:2px 8px;margin-right:10px;
  vertical-align:middle}

/* ---- "What you are seeing" key: honest annotations naming the real mechanics.
   Static content (no interactive elements), styled to match the honesty caption.
   Reuses existing tokens only; the term/desc contrast clears AA. ---- */
.console-key{margin:0 0 22px;padding:16px 18px;background:var(--panel2);border:1px solid var(--line);border-radius:12px}
.console-key-head{color:var(--muted);font-size:13px;line-height:1.6;margin:0 0 14px;max-width:860px}
.console-key-tag{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--accent2);border:1px solid rgba(157,123,255,.35);border-radius:5px;padding:2px 8px;margin-right:10px;
  vertical-align:middle}
/* 5 items: even by construction. auto-fit left a lonely 2 around 900-1100px,
   so this uses explicit column counts that always fill the row evenly: 5-up on
   desktop, then straight to 1-up. 5 is prime, so 5 and 1 are the only orphan-free
   counts; the in-between bands are handled in the media queries below. */
.console-key-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
.console-key-item{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:12px 14px;min-width:0}
.ck-term{display:block;color:var(--ink);font-size:12.5px;font-weight:700;letter-spacing:.2px;margin:0 0 5px}
.ck-desc{display:block;color:var(--muted);font-size:12.5px;line-height:1.55;overflow-wrap:anywhere}

/* ---- Controls ---- */
/* 4 blocks (mission, autonomy, authority, actions). auto-fit dropped to 3 cols in
   a band and left a 3+1 orphan; explicit counts keep it even: 4-up on desktop,
   2-up on tablet (2+2), 1-up on mobile. */
.console-controls{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;
  padding-bottom:20px;margin-bottom:20px;border-bottom:1px solid var(--line)}
.ctrl-block{display:flex;flex-direction:column;min-width:0}
.ctrl-label{color:var(--ink);font-weight:600;font-size:13.5px;margin:0 0 3px}
.ctrl-hint{color:var(--dim);font-size:12px;line-height:1.4;margin:0 0 10px}

/* native select, themed to match the panels */
.con-select{appearance:none;-webkit-appearance:none;width:100%;cursor:pointer;
  background:var(--panel) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%239aa3b2' stroke-width='1.6' stroke-linecap='round'/></svg>") no-repeat right 14px center;
  color:var(--ink);font:inherit;font-size:14px;font-weight:600;border:1px solid var(--line);border-radius:11px;
  padding:11px 38px 11px 14px;min-height:44px}
.con-select:hover{border-color:#37405a}
.con-select:focus-visible,.trow-select:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:11px}

/* segmented control: three real radio buttons */
.segmented{display:inline-flex;background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:4px;gap:4px}
.seg{flex:1;min-height:36px;padding:8px 10px;border:none;border-radius:8px;cursor:pointer;
  background:transparent;color:var(--muted);font:inherit;font-size:13px;font-weight:600;
  transition:background .18s ease,color .18s ease;white-space:nowrap}
.seg:hover{color:var(--ink)}
.seg[aria-checked="true"]{background:rgba(110,168,254,.14);color:var(--ink);
  box-shadow:inset 0 0 0 1px rgba(110,168,254,.45)}

/* run / reset / continue buttons */
.ctrl-actions{justify-content:flex-end}
.console-buttons{display:flex;gap:10px;flex-wrap:wrap}
.con-run{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;
  padding:11px 24px;border-radius:11px;font-weight:700;font-size:14px;cursor:pointer;
  background:linear-gradient(90deg,var(--accent),var(--accent2));color:#0a0b0f;border:none}
.con-run:hover{transform:translateY(-1px)}
.con-run[disabled]{opacity:.5;cursor:not-allowed;transform:none}
.con-reset,.con-continue{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;min-height:44px;
  padding:11px 18px;border-radius:11px;font-weight:600;font-size:13.5px;cursor:pointer;
  background:transparent;color:var(--muted);border:1px solid var(--line)}
.con-reset:hover,.con-continue:hover{border-color:var(--accent);color:var(--ink)}
/* Continue is the active control in Manual mode: give it the accent tint */
.con-continue{color:var(--ink);border-color:rgba(110,168,254,.45);background:rgba(110,168,254,.1)}
.con-continue:hover{border-color:var(--accent)}
/* the [hidden] attribute must win over the display rule above, or the button
   stays visible when the engine hides it (e.g. in Full mode, which never pauses) */
.con-continue[hidden]{display:none}
.ctrl-tier-note{color:var(--dim);font-size:12px;line-height:1.45;margin:10px 0 0;min-height:1px}

/* ---- Run meta strip ---- */
.console-meta{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:0 0 20px}
.meta-cell{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px}
.meta-k{display:block;color:var(--dim);font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 6px}
.meta-v{color:var(--muted);font-size:14px;font-variant-numeric:tabular-nums}
.meta-v b{color:var(--ink);font-weight:700;font-size:20px;font-variant-numeric:tabular-nums}
/* state colors itself by data-state so PASS/BLOCK read at a glance */
#meta-state{color:var(--ink)}
.console[data-state="running"] #meta-state{color:var(--accent)}
.console[data-state="paused"] #meta-state{color:#f6c454}
.console[data-state="blocked"] #meta-state{color:#ff6b6b}
.console[data-state="done"] #meta-state{color:var(--ok)}

/* ---- Stage: DAG + log side by side ---- */
.console-stage{display:grid;grid-template-columns:1.25fr 1fr;gap:16px}
/* stack DAG + log below tablet width (768px, matched to the tablet band below) */
@media (max-width:768px){ .console-stage{grid-template-columns:1fr} }
.con-pane-cap{color:var(--dim);font-size:12px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 12px}
.con-dag-wrap,.con-log-wrap{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:16px;min-width:0}

/* ---- Wave DAG ---- */
.con-dag{display:flex;flex-direction:column;gap:0}
.con-dag-empty,.con-log-empty{color:var(--dim);font-size:13px;line-height:1.5;margin:2px 0 0}
/* once a run starts, lab.js hides the empty hints and reveals the panes */
.console.is-running .con-dag-empty,
.console.is-running .con-log-empty,
.console.has-run .con-dag-empty,
.console.has-run .con-log-empty{display:none}

/* a wave row: header (label + state stamp) then the agent node grid */
.wave{opacity:.4;transition:opacity .4s ease;padding:0 0 4px}
.wave.is-active,.wave.is-done{opacity:1}
/* connector rail between waves */
.wave + .wave{margin-top:6px;padding-top:14px;position:relative}
.wave + .wave::before{content:"";position:absolute;left:13px;top:-6px;width:2px;height:20px;
  background:var(--line);transition:background .4s ease}
.wave.is-active::before,.wave.is-done::before{background:linear-gradient(180deg,var(--accent),var(--accent2))}

.wave-head{display:flex;align-items:center;gap:10px;margin:0 0 10px}
.wave-dot{flex:0 0 auto;width:26px;height:26px;border-radius:50%;border:1.5px solid var(--line);
  display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;
  color:var(--dim);background:var(--panel);transition:border-color .35s ease,color .35s ease}
.wave.is-active .wave-dot,.wave.is-done .wave-dot{border-color:var(--accent);color:var(--ink)}
.wave-title{flex:1;min-width:0;color:var(--ink);font-size:13.5px;font-weight:600}
.wave-title .wave-sub{display:block;color:var(--dim);font-size:11.5px;font-weight:400;margin-top:1px}

/* gate stamp: animates in when the wave is gated */
.gate-stamp{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;
  letter-spacing:.5px;text-transform:uppercase;border-radius:999px;padding:4px 11px;border:1px solid transparent;
  opacity:0;transform:scale(.82);transition:opacity .3s ease,transform .3s cubic-bezier(.22,1.4,.4,1)}
.gate-stamp.show{opacity:1;transform:none}
.gate-stamp .gdot{width:7px;height:7px;border-radius:50%}
.gate-pass{color:var(--ok);background:rgba(67,214,146,.12);border-color:rgba(67,214,146,.4)}
.gate-pass .gdot{background:var(--ok)}
.gate-warn{color:#f6c454;background:rgba(246,196,84,.12);border-color:rgba(246,196,84,.4)}
.gate-warn .gdot{background:#f6c454}
.gate-block{color:#ff6b6b;background:rgba(255,107,107,.13);border-color:rgba(255,107,107,.45)}
.gate-block .gdot{background:#ff6b6b}
.gate-floor{color:#ff6b6b;background:rgba(255,107,107,.16);border-color:rgba(255,107,107,.6)}
.gate-floor .gdot{background:#ff6b6b}

/* agent nodes: light up in parallel within a wave */
.wave-agents{display:flex;flex-wrap:wrap;gap:8px;padding-left:36px}
.agent-node{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);
  background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:7px 11px;
  opacity:.55;transition:opacity .3s ease,border-color .3s ease,color .3s ease}
.agent-node .an-pulse{width:8px;height:8px;border-radius:50%;background:var(--line);flex:0 0 auto;transition:background .3s ease}
.agent-node.dispatched{opacity:1;border-color:rgba(110,168,254,.4);color:var(--ink)}
.agent-node.dispatched .an-pulse{background:var(--accent);animation:an-pulse 1.1s ease-in-out infinite}
.agent-node.complete{opacity:1;border-color:rgba(67,214,146,.35);color:var(--ink)}
.agent-node.complete .an-pulse{background:var(--ok);animation:none}
@keyframes an-pulse{0%,100%{box-shadow:0 0 0 0 rgba(110,168,254,.5)}50%{box-shadow:0 0 0 5px rgba(110,168,254,0)}}

/* the re-run badge on a wave that was routed back and retried */
.wave-retry{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;
  color:var(--accent2);border:1px solid rgba(157,123,255,.4);border-radius:5px;padding:2px 7px;margin-left:8px;
  opacity:0;transition:opacity .3s ease}
.wave-retry.show{opacity:1}

/* ---- Run log ---- */
.con-log{list-style:none;margin:0;padding:0;max-height:360px;overflow-y:auto;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.5}
.con-log-illus{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;
  color:var(--dim);border:1px solid var(--line);border-radius:5px;padding:2px 7px;margin-left:8px;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,sans-serif;vertical-align:middle}
.log-line{display:flex;gap:10px;padding:5px 2px;border-bottom:1px solid rgba(38,42,54,.5);color:var(--muted);
  opacity:0;transform:translateY(4px);transition:opacity .25s ease,transform .25s ease}
.log-line.show{opacity:1;transform:none}
.log-line:last-child{border-bottom:none}
.log-tick{flex:0 0 auto;color:var(--dim);font-variant-numeric:tabular-nums}
.log-txt{flex:1;min-width:0}
/* log line accents by kind */
.log-line.k-gate .log-txt{color:var(--ink)}
.log-line.k-pass .log-txt{color:var(--ok)}
.log-line.k-warn .log-txt{color:#f6c454}
.log-line.k-block .log-txt{color:#ff6b6b}
.log-line.k-floor .log-txt{color:#ff6b6b;font-weight:600}
.log-line.k-done .log-txt{color:var(--ok);font-weight:600}

/* ============================================================
   Tablet bands: keep every console + triage grid filling its row
   evenly so no orphan cell is left over between desktop and mobile.
   Ordered widest-first so the narrower mobile block below overrides.
   ============================================================ */
/* The 5-item key list is even only at 5-up or 1-up (5 is prime). Hold 5-up on
   desktop; below 900px the cards would crowd, so drop straight to a clean 1-up
   column rather than a lopsided 4+1 or 3+2. */
@media (max-width:900px){
  .console-key-list{grid-template-columns:1fr;gap:8px}
}
/* At tablet width the 4 controls go 2+2 and the 4 triage summary cells go 2+2,
   both even. The 3-cell meta strip stays 3-up (it divides cleanly). */
@media (max-width:768px){
  .console-controls{grid-template-columns:repeat(2,1fr)}
  .triage-summary{grid-template-columns:repeat(2,1fr)}
}

/* ============================================================
   Mobile: <=480px. The DAG and log stack; nothing overflows.
   ============================================================ */
@media (max-width:480px){
  .console{padding:20px 14px 18px}
  .console-honesty{padding:13px 13px;font-size:12.5px}
  .console-key{padding:13px 13px}
  .console-key-list{grid-template-columns:1fr;gap:8px}
  /* controls collapse to a single column so the selects, segmented controls,
     and action buttons each get the full width on a phone */
  .console-controls{grid-template-columns:1fr;gap:14px}
  .console-meta{grid-template-columns:1fr;gap:10px}
  .meta-cell{display:flex;align-items:baseline;justify-content:space-between;padding:11px 14px}
  .meta-k{margin:0}
  .segmented{display:flex;width:100%}
  .seg{padding:9px 6px;font-size:12.5px}
  .ctrl-actions{justify-content:flex-start}
  .con-run{flex:1 1 auto}
  /* agent nodes can wrap freely; reduce the indent so they never push past the edge */
  .wave-agents{padding-left:0;margin-left:36px}
  .con-log{font-size:12px}
  .lab-soon{padding:14px 14px}
}

/* very narrow: let agent indent collapse entirely so a long node label still fits */
@media (max-width:360px){
  .wave-agents{margin-left:0}
  .agent-node{font-size:11.5px;padding:6px 9px}
}

/* ============================================================
   The real rollout: an explorable, depth-on-demand timeline.
   Reuses the console's wave vocabulary (numbered dot, title +
   role sub, and the SAME .gate-stamp / .gate-pass / .gate-warn /
   .gdot pills defined above). Each wave is a native <details>, so
   expand/collapse is keyboard- and screen-reader-operable with no
   JS and collapsed by default. lab.js adds a scroll-reveal stagger
   and stat chips on top; both have static fallbacks.
   ============================================================ */
.rollout-howto{display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap;color:var(--muted);font-size:13.5px;
  line-height:1.6;max-width:820px;margin:0 0 22px;padding:14px 16px;background:var(--panel2);
  border:1px solid var(--line);border-radius:12px}
.rollout-howto-tag{flex:0 0 auto;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--accent);border:1px solid rgba(110,168,254,.3);border-radius:5px;padding:2px 8px;
  margin-top:1px}

/* the timeline: a single connector rail down the numbered dots */
.rollout{list-style:none;margin:0;padding:0;position:relative}
/* vertical rail: sits under the centre of the 28px dots (left:24px wrap pad is on .wrap, not here) */
.rollout-wave{position:relative;padding:0 0 14px 0}
.rollout-wave::before{content:"";position:absolute;left:13px;top:30px;bottom:-2px;width:2px;
  background:linear-gradient(180deg,var(--accent),var(--accent2));opacity:.5}
.rollout-wave:last-child::before{display:none}

/* per-wave reveal: each step rises in on scroll, staggered by lab.js via --rw-i.
   site.css owns the base .reveal on the <ol>; this adds a nested per-item lift that
   lab.js triggers by adding .rw-in. Static + reduced-motion fallbacks show all. */
.rollout-wave .rw-d{opacity:0;transform:translateY(16px);
  transition:opacity .55s ease,transform .55s cubic-bezier(.22,1,.36,1);
  transition-delay:calc(var(--rw-i, 0) * 80ms)}
.rollout-wave.rw-in .rw-d{opacity:1;transform:none}

/* the wave row (summary): the clickable header, reusing console dot + title shapes */
.rw-d{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden}
.rw-sum{cursor:pointer;list-style:none;display:flex;align-items:center;gap:12px;padding:15px 18px;min-height:44px}
.rw-sum::-webkit-details-marker{display:none}
.rw-d[open]{border-color:#37405a}
.rw-d[open] .rw-sum{border-bottom:1px solid var(--line)}
.rw-sum:hover{background:rgba(110,168,254,.04)}
/* numbered dot, same size/treatment as the console .wave-dot but lit by default
   (these waves already happened, so they read as done) */
.rw-dot{flex:0 0 auto;width:28px;height:28px;border-radius:50%;border:1.5px solid var(--accent);
  display:inline-flex;align-items:center;justify-content:center;font-size:12.5px;font-weight:700;
  color:var(--ink);background:var(--panel)}
.rw-title{flex:1;min-width:0}
.rw-name{display:block;color:var(--ink);font-size:14.5px;font-weight:600;letter-spacing:-.1px}
.rw-sub{display:block;color:var(--dim);font-size:12px;margin-top:1px}
/* the gate stamp is the console's pill; ensure it never shrinks in the flex row */
.rw-stamp{flex:0 0 auto}
/* + / x expander affordance; rotates to a x when open. aria handled by <details>. */
.rw-chev{flex:0 0 auto;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;
  color:var(--dim);font-size:18px;font-weight:400;line-height:1;border:1px solid var(--line);border-radius:7px;
  transition:transform .25s ease,color .2s ease,border-color .2s ease}
.rw-sum:hover .rw-chev{color:var(--ink);border-color:#37405a}
.rw-d[open] .rw-chev{transform:rotate(45deg);color:var(--accent);border-color:rgba(110,168,254,.45)}

/* the expanded body */
.rw-body{padding:16px 18px 18px}
.rw-body > p{color:var(--muted);font-size:14.5px;line-height:1.6;margin:0 0 12px;max-width:760px}
.rw-body > p:last-child{margin-bottom:0}
.rw-scores b{color:var(--ink);font-weight:700;font-variant-numeric:tabular-nums}

/* wave-stat chips: the rollout's OWN record (agents dispatched, gate verdict).
   lab.js re-renders these from a data array; the static markup is the fallback. */
.rw-stats{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px;padding:0}
.rw-stat{display:inline-flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);
  border-radius:9px;padding:7px 12px}
.rw-stat-k{color:var(--dim);font-size:11px;font-weight:700;letter-spacing:.4px;text-transform:uppercase}
.rw-stat-v{color:var(--ink);font-size:13px;font-weight:700;font-variant-numeric:tabular-nums}
.rw-stat-v.rw-v-pass{color:var(--ok)}
.rw-stat-v.rw-v-warn{color:#f6c454}

/* decision cards: a featured real call, expandable on its own. Nested <details>,
   so keyboard works without JS. The tag colors borrow the gate palette. */
.rw-dec{margin:12px 0 0}
.rw-dec-d{background:var(--panel2);border:1px solid var(--line);border-radius:11px;overflow:hidden}
.rw-dec-d[open]{border-color:#37405a}
.rw-dec-sum{cursor:pointer;list-style:none;display:flex;align-items:center;gap:11px;padding:12px 14px;min-height:44px}
.rw-dec-sum::-webkit-details-marker{display:none}
.rw-dec-sum:hover{background:rgba(110,168,254,.04)}
.rw-dec-h{flex:1;min-width:0;color:var(--ink);font-size:13.5px;font-weight:600;line-height:1.4}
.rw-dec-body{color:var(--muted);font-size:13.5px;line-height:1.6;margin:0;padding:0 14px 14px;max-width:720px}
/* small chevron variant for the nested decision rows */
.rw-chev.sm{width:20px;height:20px;font-size:15px}
.rw-dec-d[open] .rw-chev.sm{transform:rotate(45deg);color:var(--accent);border-color:rgba(110,168,254,.45)}
/* decision tag pills: a labeled verdict on the call. Reuse the gate palette semantics:
   verified/promoted/reframed read as green-ish "good", measured/caught as accent,
   rejected/block as red (a thing that was correctly turned down). */
.rw-dec-tag{flex:0 0 auto;font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  border-radius:999px;padding:4px 10px;border:1px solid transparent;white-space:nowrap}
.rw-dec-verify,.rw-dec-promote{color:var(--ok);background:rgba(67,214,146,.12);border-color:rgba(67,214,146,.4)}
.rw-dec-reframe{color:var(--accent2);background:rgba(157,123,255,.12);border-color:rgba(157,123,255,.4)}
.rw-dec-measure{color:var(--accent);background:rgba(110,168,254,.12);border-color:rgba(110,168,254,.4)}
.rw-dec-block{color:#ff6b6b;background:rgba(255,107,107,.13);border-color:rgba(255,107,107,.45)}

/* ---- Rollout mobile: <=480px. The row reflows so the stamp drops under the title,
   nothing overflows, and the rail/indent stays sane. ---- */
@media (max-width:480px){
  .rollout-howto{padding:13px 13px;font-size:13px}
  .rw-sum{flex-wrap:wrap;gap:10px 12px;padding:14px 14px}
  /* title takes the rest of the first row next to the dot; stamp + chev share row two */
  .rw-title{flex:1 1 auto}
  .rw-chev{order:2}
  .rw-stamp{order:3}
  .rollout-wave::before{left:13px}
  .rw-body{padding:14px 14px 16px}
  .rw-dec-sum{flex-wrap:wrap;gap:8px 10px}
  .rw-dec-h{flex:1 1 100%;order:3}
}
/* very narrow: keep the decision tag and chevron from crowding the heading */
@media (max-width:360px){
  .rw-stat{padding:6px 10px}
  .rw-dec-sum{padding:11px 12px}
}

/* ============================================================
   Reduced motion: the console renders a COMPLETE, static,
   already-resolved run. No animation, no transitions, no pulse.
   Every wave is shown in its final state with its gate stamp;
   the safety-floor block is shown. Run / Reset still work
   (lab.js re-renders the same resolved snapshot, no sequencing).
   The rollout timeline shows every wave's reveal at full strength
   and keeps the expand/collapse working (it is native <details>);
   only the motion is dropped.
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .wave,.agent-node,.gate-stamp,.log-line,.wave-retry,.wave + .wave::before,.wave-dot,.an-pulse{
    transition:none !important;animation:none !important}
  /* everything shown at full strength immediately */
  .wave{opacity:1}
  .agent-node{opacity:1}
  .gate-stamp{opacity:1;transform:none}
  .wave-retry{opacity:1}
  .log-line{opacity:1;transform:none}
  .con-run:hover,.con-reset:hover,.con-continue:hover{transform:none}
  /* pulse dots are static (no infinite keyframe) */
  .agent-node.dispatched .an-pulse{background:var(--accent);box-shadow:none}
  /* Rollout: no per-item lift, no chevron-rotate transition. Expanders still work,
     the chevron still rotates to its open state (just instantly), content readable. */
  .rollout-wave .rw-d{opacity:1;transform:none;transition:none}
  .rw-chev,.rw-chev.sm{transition:none}
  .rw-sum:hover,.rw-dec-sum:hover{background:transparent}
}

/* ============================================================
   The Triage Desk: a real, working, client-side first-pass
   labeler. Visitors paste lines; a transparent rule-based signal
   classifier proposes a category + confidence + the matched
   signals (the "show the work"); a human confirms or overrides
   every row; decisions export to CSV/JSON via a Blob. Reuses the
   console's container/honesty/control/segmented + the gate-stamp
   confidence palette. Zero new design tokens.
   ============================================================ */
.triage{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
  border-radius:var(--radius);padding:24px 24px 22px}

/* honesty caption: same treatment as the console's, sits first */
.triage-honesty{display:block;color:var(--muted);font-size:13px;line-height:1.6;margin:0 0 22px;
  max-width:860px;padding:14px 16px;background:var(--panel2);border:1px solid var(--line);border-radius:12px}
.triage-honesty-tag{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--accent);border:1px solid rgba(110,168,254,.3);border-radius:5px;padding:2px 8px;margin-right:10px;
  vertical-align:middle}

/* ---- Input ---- */
.triage-input{padding-bottom:20px;margin-bottom:20px;border-bottom:1px solid var(--line)}
.triage-label{display:block;color:var(--ink);font-weight:600;font-size:13.5px;margin:0 0 3px}
.triage-hint{color:var(--dim);font-size:12px;line-height:1.4;margin:0 0 10px}
.triage-textarea{display:block;width:100%;resize:vertical;min-height:128px;
  background:var(--panel);color:var(--ink);border:1px solid var(--line);border-radius:11px;
  padding:12px 14px;font:inherit;font-size:14px;line-height:1.55}
.triage-textarea::placeholder{color:var(--dim);opacity:.85}
.triage-textarea:hover{border-color:#37405a}
.triage-textarea:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-color:transparent}

.triage-buttons{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.triage-run{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;
  padding:11px 24px;border-radius:11px;font-weight:700;font-size:14px;cursor:pointer;
  background:linear-gradient(90deg,var(--accent),var(--accent2));color:#0a0b0f;border:none}
.triage-run:hover{transform:translateY(-1px)}
.triage-ghost{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;min-height:44px;
  padding:11px 18px;border-radius:11px;font-weight:600;font-size:13.5px;cursor:pointer;
  background:transparent;color:var(--muted);border:1px solid var(--line)}
.triage-ghost:hover{border-color:var(--accent);color:var(--ink)}
.triage-ghost.sm{min-height:38px;padding:8px 14px;font-size:13px}

/* ---- Summary strip: the tool's OWN counts ---- */
.triage-summary{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:0 0 20px}
.triage-summary[hidden]{display:none}
.tsum-cell{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px}
.tsum-k{display:block;color:var(--dim);font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;margin:0 0 6px}
.tsum-v{color:var(--muted);font-size:14px;font-variant-numeric:tabular-nums}
.tsum-v b{color:var(--ink);font-weight:700;font-size:20px;font-variant-numeric:tabular-nums}
/* the review count tints amber when nonzero (low confidence floats up) */
.triage-summary[data-review="some"] #tsum-review{color:#f6c454}

/* ---- Results header: caption + export ---- */
.triage-results-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 14px}
.triage-pane-cap{flex:1 1 auto;color:var(--dim);font-size:12px;font-weight:700;letter-spacing:.6px;
  text-transform:uppercase;margin:0}
.triage-illus{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.4px;text-transform:none;
  color:var(--dim);border:1px solid var(--line);border-radius:5px;padding:2px 7px;margin-left:8px;
  vertical-align:middle}
.triage-export{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;min-height:38px;
  padding:8px 16px;border-radius:10px;font-weight:600;font-size:13px;cursor:pointer;
  background:transparent;color:var(--muted);border:1px solid var(--line)}
.triage-export:hover{border-color:var(--accent);color:var(--ink)}
.triage-export[hidden]{display:none}
.triage-export-menu{flex:0 0 auto;display:inline-flex;gap:8px}
.triage-export-menu[hidden]{display:none}

/* ---- Results list ---- */
.triage-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.triage-empty{color:var(--dim);font-size:13px;line-height:1.5;margin:2px 0 0}
.triage.has-run .triage-empty{display:none}

/* a triage row: confidence rail + body (text, signals, decision controls) */
.trow{display:grid;grid-template-columns:auto 1fr;gap:14px;align-items:start;
  background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:14px 16px;
  opacity:0;transform:translateY(4px);transition:opacity .25s ease,transform .25s ease}
.trow.show{opacity:1;transform:none}
/* a row flagged for review (Unsure or low confidence) gets an amber left edge */
.trow.is-review{border-left:3px solid #f6c454;padding-left:13px}
.trow.is-confirmed{border-left:3px solid var(--ok);padding-left:13px}
.trow.is-overridden{border-left:3px solid var(--accent2);padding-left:13px}

/* index dot, mirrors the console wave-dot shape */
.trow-idx{flex:0 0 auto;width:26px;height:26px;border-radius:50%;border:1.5px solid var(--line);
  display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;
  color:var(--dim);background:var(--panel);font-variant-numeric:tabular-nums}

.trow-body{min-width:0}
.trow-text{color:var(--ink);font-size:14px;line-height:1.5;margin:0 0 10px;word-break:break-word;overflow-wrap:anywhere}

/* the proposal line: category pill + confidence pill (reuses gate-stamp palette) */
.trow-proposed{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 9px}
.trow-cat{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;letter-spacing:.3px;
  border-radius:999px;padding:4px 12px;border:1px solid transparent}
.trow-cat .cat-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto}
/* category colors: legible, reuse the palette already on the page */
.cat-bug{color:#ff6b6b;background:rgba(255,107,107,.13);border-color:rgba(255,107,107,.45)}
.cat-bug .cat-dot{background:#ff6b6b}
.cat-feature{color:var(--accent);background:rgba(110,168,254,.12);border-color:rgba(110,168,254,.4)}
.cat-feature .cat-dot{background:var(--accent)}
.cat-question{color:var(--accent2);background:rgba(157,123,255,.12);border-color:rgba(157,123,255,.4)}
.cat-question .cat-dot{background:var(--accent2)}
.cat-praise{color:var(--ok);background:rgba(67,214,146,.12);border-color:rgba(67,214,146,.4)}
.cat-praise .cat-dot{background:var(--ok)}
.cat-unsure{color:#f6c454;background:rgba(246,196,84,.12);border-color:rgba(246,196,84,.4)}
.cat-unsure .cat-dot{background:#f6c454}

/* confidence chip */
.trow-conf{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;letter-spacing:.4px;
  text-transform:uppercase;color:var(--muted);border:1px solid var(--line);border-radius:999px;padding:3px 10px;
  font-variant-numeric:tabular-nums}
.trow-conf.c-high{color:var(--ok);border-color:rgba(67,214,146,.4)}
.trow-conf.c-med{color:var(--accent);border-color:rgba(110,168,254,.4)}
.trow-conf.c-low{color:#f6c454;border-color:rgba(246,196,84,.4)}

/* "why": the matched signals that fired */
.trow-why{color:var(--muted);font-size:12.5px;line-height:1.5;margin:0 0 11px}
.trow-why-k{color:var(--dim);font-weight:700}
.trow-sig{display:inline-block;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:11.5px;color:var(--ink);background:var(--panel);border:1px solid var(--line);border-radius:6px;
  padding:1px 7px;margin:2px 5px 0 0}
.trow-why-none{color:var(--dim);font-style:italic}

/* the human-in-the-loop controls: confirm + an override select */
.trow-decide{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.trow-confirm{display:inline-flex;align-items:center;gap:7px;min-height:38px;padding:7px 14px;border-radius:9px;
  cursor:pointer;background:transparent;color:var(--muted);border:1px solid var(--line);font:inherit;font-size:13px;
  font-weight:600}
.trow-confirm:hover{border-color:var(--ok);color:var(--ink)}
.trow-confirm[aria-pressed="true"]{color:var(--ok);background:rgba(67,214,146,.12);
  border-color:rgba(67,214,146,.45)}
.trow-confirm .tc-check{width:8px;height:8px;border-radius:50%;background:currentColor;flex:0 0 auto;opacity:.5}
.trow-confirm[aria-pressed="true"] .tc-check{opacity:1}
.trow-override-lab{color:var(--dim);font-size:12px;font-weight:600}
.trow-select{appearance:none;-webkit-appearance:none;cursor:pointer;
  background:var(--panel) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%239aa3b2' stroke-width='1.6' stroke-linecap='round'/></svg>") no-repeat right 12px center;
  color:var(--ink);font:inherit;font-size:13px;font-weight:600;border:1px solid var(--line);border-radius:9px;
  padding:8px 32px 8px 12px;min-height:38px}
.trow-select:hover{border-color:#37405a}
/* decided-state note (Confirmed / Overridden to X) */
.trow-state{font-size:11.5px;font-weight:700;letter-spacing:.3px;text-transform:uppercase}
.trow-state.s-confirmed{color:var(--ok)}
.trow-state.s-overridden{color:var(--accent2)}

/* ---- Triage mobile: <=480px. Rows reflow to a single column, no overflow. ---- */
@media (max-width:480px){
  .triage{padding:20px 14px 18px}
  .triage-honesty{padding:13px 13px;font-size:12.5px}
  .triage-summary{grid-template-columns:1fr 1fr;gap:10px}
  .tsum-cell{display:flex;align-items:baseline;justify-content:space-between;padding:11px 13px}
  .tsum-k{margin:0}
  .triage-run{flex:1 1 auto}
  /* row drops the index column; everything stacks and wraps */
  .trow{grid-template-columns:1fr;gap:10px}
  .trow-idx{display:none}
  .triage-results-head{gap:10px}
  .triage-pane-cap{flex:1 1 100%}
  .trow-decide{gap:8px}
  .trow-select{flex:1 1 auto}
}
/* very narrow: keep pills and the select from crowding */
@media (max-width:360px){
  .trow{padding:13px 12px}
  .trow.is-review,.trow.is-confirmed,.trow.is-overridden{padding-left:11px}
  .trow-confirm,.trow-select{font-size:12.5px}
}

/* ============================================================
   Triage Desk reduced motion: the tool is fully functional with
   no animation. Rows appear at full strength immediately (no
   fade/lift), buttons do not lift on hover. Nothing about the
   classify / confirm / override / export flow depends on motion.
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .trow{opacity:1;transform:none;transition:none}
  .triage-run:hover{transform:none}
}
