/* STARNET — app.css : screens for the REAL harness (title · connect · game).
   Reuses the v7 phosphor/CRT design language from style.css (vars + body::before/after).
   No "web app" softness — 2px hard lines, inverted-block headers, heavy bloom. */

/* ---------- screen scaffolding ---------- */
.screen { position: fixed; inset: 0; display: none; z-index: 10; }
.screen.active { display: flex; }

/* boot veil — the neutral holding-card shown during init()'s async gap before the boot router picks a
   real screen. Solid ink so there's never a flash of the wrong screen (the old #screen-connect .active
   bug); reuses the phosphor vars so it matches whatever theme is about to load. */
#screen-boot { background: var(--ink); align-items: center; justify-content: center; }
.boot-veil { text-align: center; opacity: .82; animation: boot-fade 2.4s ease-in-out infinite; }
.boot-mark { color: var(--ph-bright); font-size: 30px; letter-spacing: 8px; text-shadow: 0 0 14px var(--ph-glow), 0 0 3px var(--ph-glow); }
.boot-line { color: var(--ph-dim); font-size: 14px; letter-spacing: 3px; text-transform: uppercase; margin-top: 12px; }
.boot-dots::after { content: '…'; animation: cc-blink 1.1s steps(1) infinite; }
@keyframes boot-fade { 0%, 100% { opacity: .62; } 50% { opacity: .9; } }
@media (prefers-reduced-motion: reduce) { .boot-veil { animation: none; } .boot-dots::after { animation: none; } }
#screen-connect.active { align-items: center; justify-content: center; }
#screen-game.active {
  display: grid;
  grid-template-rows: 64px 1fr 44px;
  /* COMMS width is a live var so the user can drag the stage/COMMS divider (chatresize.js) */
  grid-template-columns: 232px 1fr var(--chat-w, 360px);
  grid-template-areas: "top top top" "left center chat" "bot bot bot";
  padding: 11px; gap: 9px;
}
.hidden { display: none !important; }

/* visually-hidden but exposed to assistive tech (screen-reader-only live regions / labels) */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.dim { color: var(--ph-dim); }
.dimb { color: var(--ph-dim); font-weight: normal; }
.pos { color: var(--gold); }
.muted { color: var(--text); opacity: 0.82; }

/* ---------- shared inputs / buttons ---------- */
.btn, .btn-xl, .btn-sm, .prov {
  font-family: inherit; color: var(--ph);
  background: linear-gradient(180deg, color-mix(in srgb, var(--ph) 8%, var(--panel2)), var(--panel2));
  border: 1px solid var(--ph-dim); border-radius: 5px; padding: 7px 15px; cursor: pointer;
  text-transform: uppercase; letter-spacing: 1px; line-height: 1;
  text-shadow: 0 0 6px var(--ph-glow2);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb), .12), 0 1px 0 rgba(0,0,0,.4);
  transition: color .12s, border-color .12s, background-color .12s, box-shadow .12s, transform .12s;
}
.btn:hover, .btn-xl:hover, .btn-sm:hover, .prov:hover {
  border-color: var(--ph); background: var(--ph-faint); color: var(--ph-bright);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb), .18), 0 0 10px var(--ph-glow2), 0 1px 0 rgba(0,0,0,.4);
}
.btn:active, .btn-xl:active, .btn-sm:active, .prov:active { transform: translateY(1px); box-shadow: inset 0 1px 3px rgba(0,0,0,.35); }
.btn:focus-visible, .btn-xl:focus-visible, .btn-sm:focus-visible, .prov:focus-visible { outline: 2px solid var(--ph-bright); outline-offset: 2px; }
.btn-xl { font-size: 26px; padding: 13px 27px; border-color: var(--ph); box-shadow: inset 0 1px 0 rgba(var(--ph-rgb), .16), 0 0 0 2px rgba(0,0,0,.85), 0 0 18px var(--ph-glow2); }
.btn-sm { font-size: 15px; padding: 5px 10px; }
.prov.sel {
  background: linear-gradient(180deg, var(--ph-bright) -40%, var(--ph) 60%); color: var(--ink); border-color: var(--ph);
  text-shadow: none; box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 0 10px var(--ph-glow2);
}

input[type=text], input[type=password], input[type=url], input[type=search], input:not([type]), textarea.key-input {
  width: 100%; font-family: inherit; font-size: 19px; color: var(--ph-bright);
  background: linear-gradient(180deg, #000, color-mix(in srgb, var(--ph) 3%, #000));
  border: 1px solid var(--ph-dim); border-radius: 4px; padding: 8px 11px; outline: none;
  text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 2px 6px rgba(0,0,0,.7), inset 0 -1px 0 rgba(var(--ph-rgb),.06);
  transition: border-color .12s, box-shadow .12s;
}
input:focus, textarea.key-input:focus {
  border-color: var(--ph);
  box-shadow: inset 0 2px 6px rgba(0,0,0,.7), inset 0 -1px 0 rgba(var(--ph-rgb),.08), 0 0 12px var(--ph-glow2);
}
/* solid --ph-dim (no opacity multiplier) keeps placeholder hint text >=4.5:1 (WCAG AA) on --bg across every theme; .7 opacity dropped it to ~3.2:1 */
input::placeholder, textarea.key-input::placeholder { color: var(--ph-dim); opacity: 1; }

/* (The standalone TITLE screen was removed — boot auto-resumes into the station, or opens CREATE/RESUME
   directly. The data-status line that used to live there now sits in the connect-screen footer.) */
.title-status { color: var(--ph-dim); font-size: 14px; letter-spacing: 1px; }

/* ---------- FIRST-BOOT SPLASH — the key-art boot card (first run only) ----------
   Layers, back to front: star canvas · nebula haze · perspective grid floor · HUD brackets ·
   the wordmark + PRESS ANY KEY. Everything rides the theme phosphor vars so a re-tint later
   still matches; default amber IS the key art. */
#screen-splash { background: #050302; overflow: hidden; cursor: pointer; }
#screen-splash.active { display: block; }
#sp-stars { position: absolute; inset: 0; width: 100%; height: 100%; }
.sp-nebula {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 42% 30% at 72% 22%, rgba(var(--ph-rgb),.10), transparent 70%),
    radial-gradient(ellipse 34% 26% at 14% 78%, rgba(var(--ph-rgb),.07), transparent 70%),
    radial-gradient(ellipse 60% 42% at 50% 52%, rgba(var(--ph-rgb),.06), transparent 72%);
}
/* the grid floor: a plane of phosphor graph lines pitched away from the camera, faded into the horizon */
.sp-floor {
  position: absolute; left: -18%; right: -18%; bottom: 0; height: 46vh;
  perspective: 340px; perspective-origin: 50% 0%; pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 34%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 34%, #000 100%);
}
.sp-grid {
  position: absolute; inset: 0; transform: rotateX(62deg); transform-origin: 50% 0%;
  background:
    repeating-linear-gradient(90deg, rgba(var(--ph-rgb),.30) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(0deg, rgba(var(--ph-rgb),.30) 0 1px, transparent 1px 56px);
  box-shadow: inset 0 0 120px rgba(0,0,0,.75);
  animation: sp-scroll 9s linear infinite;
}
@keyframes sp-scroll { from { background-position: 0 0, 0 0; } to { background-position: 0 0, 0 56px; } }
@media (prefers-reduced-motion: reduce) { .sp-grid { animation: none; } }
.sp-tl { top: 10px; left: 14px; } .sp-tr { top: 10px; right: 16px; }
.sp-bl { bottom: 10px; left: 14px; } .sp-br { bottom: 10px; right: 16px; }
.sp-center {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 10px; padding-bottom: 8vh; pointer-events: none;
}
.sp-logo {
  width: min(58vw, 640px); height: auto; image-rendering: auto; user-select: none;
  filter: drop-shadow(0 0 18px var(--ph-glow)) drop-shadow(0 0 60px var(--ph-glow2));
  animation: sp-breathe 4.2s ease-in-out infinite;
}
@keyframes sp-breathe {
  0%, 100% { filter: drop-shadow(0 0 18px var(--ph-glow)) drop-shadow(0 0 60px var(--ph-glow2)); }
  50%      { filter: drop-shadow(0 0 26px var(--ph-glow)) drop-shadow(0 0 84px var(--ph-glow2)); }
}
.sp-tag { color: var(--ph-dim); letter-spacing: 7px; font-size: 15px; text-transform: uppercase; text-shadow: 0 0 8px var(--ph-glow2); }
.sp-press {
  margin-top: 9vh; pointer-events: auto; cursor: pointer;
  font-family: inherit; font-size: 24px; letter-spacing: 4px; text-transform: uppercase;
  color: var(--ph-bright); background: none; border: none; padding: 8px 18px;
  text-shadow: 0 0 12px var(--ph-glow), 0 0 3px var(--ph-glow);
  animation: sp-blink 1.5s steps(1) infinite;
}
.sp-press:focus-visible { outline: 2px solid var(--ph); outline-offset: 4px; }
@keyframes sp-blink { 0%, 62% { opacity: 1; } 62.01%, 100% { opacity: .18; } }
.sp-stamp {
  position: absolute; left: 0; right: 0; bottom: 14px; display: flex; justify-content: center;
  gap: 18px; font-size: 13px; letter-spacing: 2px; color: var(--ph-dim); pointer-events: none;
}
.sp-rec { color: var(--ok); animation: cc-blink 1.4s steps(1) infinite; }   /* a live-local heartbeat, not a fake "REC" */

/* ---------- generic panel (reuses v7 bezel look) ---------- */
.panel {
  position: relative; background:
    radial-gradient(ellipse 130% 100% at 50% 0%, var(--ph-glow2), transparent 42%), var(--panel);
  border: 1px solid rgba(0,0,0,.85); border-radius: var(--r-lg);
  box-shadow: var(--bezel);
  padding: 20px 22px;
}
.panel h2 { color: var(--ink); background: var(--ph); display: inline-block; padding: 2px 12px; margin-bottom: 12px; letter-spacing: 2px; }

/* ---------- CONNECT / COMMISSION CONSOLE ----------
   Desktop-first: a wide terminal that lays BRAIN+IDENTITY beside VOICE instead of one tall scroll.
   Heavier chrome (corner brackets, an ASCII titlebar, a faux boot stamp) so it reads as a premium
   piece of station hardware, not a web form. Collapses to one column under 860px. */
.connect-panel {
  width: min(1060px, 95vw); padding: 0;            /* the header/body manage their own insets */
  position: relative; overflow: hidden;            /* clip the corner brackets + scanline to the bezel */
}
.connect-panel label { display: block; color: var(--ph); letter-spacing: 1px; margin: 8px 0 3px; font-size: 15px; }
.provider-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.provider-row .prov { flex: 0 1 auto; min-width: 0; padding-inline: 10px; }

/* ===== two-tier genesis provider pick: ChatGPT hero card up top, BYOK chips in a compact grid below.
   (declared AFTER .prov / .prov.sel so equal-specificity ties resolve to these on the hero + grid) ===== */
.ov-prov { flex-direction: column; align-items: stretch; gap: 9px; }
.ov-prov .prov-hero {
  display: block; width: 100%; text-align: left; padding: 12px 15px 13px;
  border: 1px solid var(--ph-dim); border-radius: 7px; text-transform: none; letter-spacing: normal;
  background: linear-gradient(180deg, rgba(var(--ph-rgb),.10), rgba(var(--ph-rgb),.03)); line-height: 1.2;
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.12), 0 1px 0 rgba(0,0,0,.4);
}
.ov-prov .prov-hero:hover { border-color: var(--ph); color: var(--ph); background: linear-gradient(180deg, rgba(var(--ph-rgb),.16), rgba(var(--ph-rgb),.05)); }
.ov-prov .prov-hero.sel {
  border-color: var(--ph); color: var(--ph); text-shadow: 0 0 6px var(--ph-glow2);
  background: linear-gradient(180deg, rgba(var(--ph-rgb),.18), rgba(var(--ph-rgb),.06));
  box-shadow: inset 0 0 0 1px var(--ph), 0 0 20px var(--ph-glow2);
}
.prov-hero-badge { display: block; color: var(--gold); font-size: 11px; letter-spacing: 2px; margin-bottom: 7px; }
.prov-hero-row { display: flex; align-items: center; gap: 12px; }
.prov-hero-ic { flex: 0 0 auto; font-size: 27px; line-height: 1; color: var(--ph-bright); text-shadow: 0 0 12px var(--ph-glow); }
.prov-hero-body { min-width: 0; }
.prov-hero-title { display: block; color: var(--ph-bright); font-size: 18px; letter-spacing: 1.5px; }
.prov-hero-sub { display: block; color: var(--ph-dim); font-size: 12px; letter-spacing: .2px; line-height: 1.25; margin-top: 3px; text-shadow: none; }
.prov-byok-lab { text-align: center; color: var(--ph-dim); font-size: 11px; letter-spacing: 2px; opacity: .8; margin: 0; }
.prov-grid { display: flex; flex-wrap: wrap; gap: 7px; }
.prov-grid .prov { flex: 0 1 auto; min-width: 0; font-size: 13px; padding: 5px 11px; }

/* corner brackets — the in-game cam-HUD framing, reused so the create screen feels like the same machine */
.cc-bracket { position: absolute; font-size: 22px; color: var(--ph); opacity: .5; z-index: 4; pointer-events: none; text-shadow: 0 0 8px var(--ph-glow); }
.cc-tl { top: 4px; left: 8px; } .cc-tr { top: 4px; right: 10px; } .cc-bl { bottom: 4px; left: 8px; } .cc-br { bottom: 4px; right: 10px; }

/* ===== ASCII console header ===== */
.cc-console-head { padding: 12px 22px 0; }
.cc-titlebar {
  display: flex; align-items: center; gap: 10px; font-size: 14px; letter-spacing: 2px;
  color: var(--ph-dim); text-transform: uppercase;
}
.cc-tb-tag { color: var(--ink); background: var(--ph); padding: 1px 9px; letter-spacing: 3px; text-shadow: none; }
.cc-tb-rule { flex: 1; height: 0; border-top: 1px dashed var(--ph-faint); }
.cc-tb-mode { color: var(--ph); letter-spacing: 3px; }
.cc-tb-rec { color: var(--ok); letter-spacing: 2px; animation: cc-blink 1.4s steps(1) infinite; }   /* live-local session dot */
/* PHOSPHOR tint selector — lives in the titlebar as console hardware (zero added panel height). Each
   swatch recolours the WHOLE station live and persists (app.js → StationUI.setTheme). */
.cc-tb-phosphor { display: flex; align-items: center; gap: 7px; }
.cc-tb-plabel { color: var(--ph-dim); letter-spacing: 2px; }
.phosphor-swatches { display: flex; gap: 5px; }
.phosphor-swatches .swatch {
  width: 14px; height: 14px; padding: 0; cursor: pointer; border-radius: 50%;
  background: var(--sw); border: 1px solid rgba(0,0,0,.6);
  box-shadow: 0 0 5px var(--sw); opacity: .6; transition: none;
}
.phosphor-swatches .swatch:hover { opacity: 1; }
.phosphor-swatches .swatch.sel { opacity: 1; outline: 1px solid var(--ph-bright); outline-offset: 2px; box-shadow: 0 0 9px var(--sw); }
.phosphor-swatches .swatch:focus-visible { outline: 2px solid var(--ph-bright); outline-offset: 2px; }
.cc-title-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.cc-title-row h2 { margin: 4px 0 0; }      /* the inverted-block h2 keeps its global look */
@keyframes cc-blink { 0%,50% { opacity: 1; } 50.01%,100% { opacity: 0; } }   /* used by .sp-rec + .cc-tb-rec */

/* .cc-grid is the CONNECTORS catalog grid (stationui.js), NOT genesis — genesis uses .ov-grid. Kept here;
   the old genesis two-column body (cc-col, cc-emblem, cc-ascii, cc-stamp, cc-cursor, lead-banner) is deleted. */
.cc-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  padding: 10px 22px 2px;
}

/* recommended-model quick picks (OpenRouter): one-tap slugs for newcomers — premium + beginner-friendly */
.model-picks { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 2px; }
.model-picks:empty { display: none; }
.mp-chip {
  font-family: inherit; font-size: 13px; letter-spacing: .5px; color: var(--ph);
  background: var(--panel2); border: 1px solid var(--ph-dim); border-radius: 4px;
  padding: 3px 9px; cursor: pointer; text-shadow: 0 0 6px var(--ph-glow2); white-space: nowrap;
}
.mp-chip:hover { border-color: var(--ph); background: var(--ph-faint); color: var(--ph-bright); }
.mp-chip.sel { background: var(--ph); color: var(--ink); border-color: var(--ph); text-shadow: none; }
.mp-chip b { color: var(--gold); font-weight: normal; }
.mp-chip.sel b { color: var(--ink); }

@media (max-width: 860px) {
  .cc-grid { grid-template-columns: 1fr; padding: 12px 18px 4px; }
}

/* ChatGPT-subscription (Codex OAuth) sign-in block on the connect screen */
.codex-signin {
  border: 1px solid var(--ph-dim); border-radius: 6px; padding: 13px;
  background: linear-gradient(180deg, rgba(var(--ph-rgb),.04), rgba(0,0,0,.35));
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.08);
  display: flex; flex-direction: column; gap: 10px;
}
.codex-status { color: var(--ph-bright); font-size: 16px; min-height: 20px; }
.codex-status.ok { color: var(--gold); }
.codex-status.bad { color: var(--bad); }
.codex-status .conn-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 7px; vertical-align: middle; }
.codex-code {
  font-size: 30px; letter-spacing: 6px; text-align: center; color: var(--ink);
  background: var(--ph); padding: 8px 6px; border-radius: 5px; user-select: all;
  text-shadow: none;}
.codex-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.hint { font-size: 15px; margin-top: 4px; min-height: 18px; }
.connect-actions {
  display: flex; align-items: center; gap: 12px; margin: 10px 0 0; padding: 12px 22px 14px;
  border-top: 1px solid var(--ph-faint);
}
.cc-actions-ascii { color: var(--ph-dim); font-size: 17px; opacity: .7; }
.connect-actions #btn-wake { margin-left: auto; }   /* WAKE anchors right; BACK sits by the ASCII tick on the left */
.msg { min-height: 20px; color: var(--bad); font-size: 16px; margin: 6px 22px 0; }
.msg:empty { min-height: 0; margin: 0; }
.msg.ok { color: var(--gold); }
/* the "get a key" deep-link in a cold-start connect message — reads as an actionable link, not error text */
.connect-link { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
.connect-link:hover { filter: brightness(1.2); }

/* (deleted: the .adv-toggle/.adv-caret/.adv-body "FINE-TUNE THE VOICE" reveal — the voice fine-tune UI was
   removed from genesis 2026-07-09; the archetype chip is the whole voice choice now.) */

/* ---------- GAME ---------- */
#game-top {
  display: flex; align-items: center; gap: 14px; padding: 0 14px; height: 52px; flex: 0 0 auto;
  background: var(--panel); border-radius: 9px;
  box-shadow: 0 0 0 2px var(--ph), 0 0 0 3.5px rgba(0,0,0,.9), inset 0 0 40px rgba(0,0,0,.8);
}
.gt-logo { color: var(--ph-bright); letter-spacing: 2px; }
.gt-sep { color: var(--ph-dim); }
.gt-field { color: var(--ph-dim); font-size: 15px; letter-spacing: 1px; }
.gt-field b { color: var(--ph-bright); font-weight: normal; margin-left: 4px; }
.gt-spacer { flex: 1; }

#game-main { flex: 1; display: flex; gap: 9px; min-height: 0; }

#stage-wrap {
  flex: 1; position: relative; min-width: 0; border-radius: 9px; overflow: hidden;
  background: var(--bg);
  box-shadow: 0 0 0 2px var(--ph), 0 0 0 3.5px rgba(0,0,0,.9), inset 0 0 60px rgba(0,0,0,.9);
}
/* the live feed graded into the terminal (warms/tints the world so it reads as a
   security-cam picture inside the CRT, not a flat canvas). --cam-grade is themed. */
#stage { display: block; width: 100%; height: 100%; image-rendering: pixelated; filter: var(--cam-grade); }

/* KEYLESS-BRAIN CTA — the honest standing banner shown after an awakening that finished with no key.
   Sits low-center over the feed, above the cam HUD (z3) so it reads clearly; the world stays visible behind
   it. Only the banner itself takes pointer events. Rendered/hidden purely from Harness.hasStoredCredential. */
.key-cta {
  position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 4;
  display: flex; align-items: center; gap: 10px; max-width: 88%;
  padding: 9px 12px; pointer-events: auto;
  color: var(--warn); font-size: 13px; line-height: 1.4;
  background: rgba(4, 8, 5, 0.92); border: 1px solid var(--warn); border-radius: 4px;
  box-shadow: 0 0 12px rgba(0,0,0,.7), 0 0 10px color-mix(in srgb, var(--warn) 35%, transparent);
  animation: keyctaIn .5s ease both;
}
@keyframes keyctaIn { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.key-cta[hidden] { display: none; }
.key-cta-glyph { flex: 0 0 auto; }
.key-cta-txt { min-width: 0; }
.key-cta-act {
  flex: 0 0 auto; cursor: pointer; padding: 5px 9px; font: inherit; font-size: 11px; color: var(--ink); background: var(--warn); border: 0; border-radius: 3px; white-space: nowrap;
}
.key-cta-act:hover { filter: brightness(1.12); }

/* ---- CRT TUBE FACE: a curved-glass overlay so the feed reads as a convex tube.
   Pure overlay (specular sweep + bowed corner vignette + edge rim) — the pixel
   canvas underneath stays crisp; only the glass implies the bulge. Sits above the
   canvas but UNDER .cam-hud (z3) so REC/FEED labels stay legible. Toggle off with
   body.no-curve. True geometric barrel-warp would need a shader pass, not CSS. */
#stage-wrap::before {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none; border-radius: 9px;
  background:
    radial-gradient(ellipse 72% 52% at 32% 3%, rgba(255,247,228,0.17), transparent 52%),   /* bright specular sweep across the top of the glass */
    radial-gradient(ellipse 142% 136% at 50% 48%, transparent 50%, rgba(0,0,0,0.34) 82%, rgba(0,0,0,0.82) 100%);  /* deep bowed corner vignette → strong convex tube */
  box-shadow: inset 0 0 30px rgba(0,0,0,0.6), inset 0 2px 1px rgba(255,243,220,0.11), inset 0 0 0 1px rgba(255,238,210,0.04);   /* tube rim + top edge glass highlight */
}
body.no-curve #stage-wrap::before { background: none; box-shadow: none; }

/* NOTE: scanlines are painted IN-CANVAS now (world.js drawCRT — device-px integer lines, drawn OVER
   the warped feed). They are NOT a CSS overlay anymore: the old #stage-wrap::after gradient rasterised
   against the display grid and beat into wide moiré stripes. Don't re-add a CSS scanline layer here. */

/* camera HUD overlay (reused v7 idiom) */
.cam-hud { position: absolute; inset: 0; pointer-events: none; font-size: 14px; color: var(--ph); z-index: 3; }
.cam-c { position: absolute; font-size: 20px; opacity: .55; }
.cam-tl { top: 6px; left: 8px; } .cam-tr { top: 6px; right: 8px; } .cam-bl { bottom: 6px; left: 8px; } .cam-br { bottom: 6px; right: 8px; }
.cam-label { position: absolute; top: 9px; left: 24px; letter-spacing: 1px; opacity: .8; }
.cam-rec { position: absolute; top: 9px; right: 26px; color: var(--bad); }
.cam-feed { position: absolute; bottom: 9px; left: 24px; opacity: .65; }

/* chat panel */
#chat-panel {
  flex: 0 0 360px; display: flex; flex-direction: column; min-height: 0; border-radius: 9px;
  background: var(--panel);
  box-shadow: 0 0 0 2px var(--ph), 0 0 0 3.5px rgba(0,0,0,.9), inset 0 0 40px rgba(0,0,0,.8);
  isolation: isolate;
}
#chat-panel h3 {
  display: flex; justify-content: space-between; align-items: baseline;
  color: var(--ink); background: var(--ph); padding: 4px 12px; letter-spacing: 2px; border-radius: 7px 7px 0 0;
}
#chat-panel h3 .dim { color: var(--ink); opacity: .7; font-size: 14px; }
#chat-panel h3::after { display: none; }   /* the global engraved-rule ::after doesn't belong on the solid amber COMMS header */
#chat-log {
  position: relative; z-index: 1;
  flex: 1; min-height: 0; overflow-y: auto; padding: 12px;
  display: flex; flex-direction: column; gap: 3px;
  background: rgba(5, 3, 1, 0.58);
}
#chat-log > * { position: relative; z-index: 1; flex: 0 0 auto; }
#chat-log > .choice-row { z-index: 2; }
#chat-log > .cmsg.consent, #chat-log > .cmsg.turnin, #chat-log > .cmsg.nudge { z-index: 3; }
/* COMMS scrollbar — scoped to #chat-log so it cleanly beats the global .scrolly rules on both engines */
#chat-log { scrollbar-color: var(--ph-dim) transparent; }
#chat-log::-webkit-scrollbar { width: 8px; }
#chat-log::-webkit-scrollbar-track { background: transparent; }
#chat-log::-webkit-scrollbar-thumb { background: var(--ph-dim); border-radius: 4px; }
#chat-log::-webkit-scrollbar-thumb:hover { background: var(--ph); }

/* ===== COMMS as a CONVERSATION (not a stack of boxes) =====
   De-boxed + grouped by speaker: consecutive turns from the same speaker collapse under ONE
   name header (the repeated label is hidden), tied together by a thin side rail — agent on the
   left, Commander on the right. Every turn is a plain grouped message; the live streaming row is
   just the newest one. Per-message HH:MM stamps come from each turn's REAL recorded ts (comms.css
   .cmsg-ts) — a legacy turn with no stored ts renders no stamp rather than a fabricated one. */
.cmsg { font-size: 16px; line-height: 1.4; min-width: 0; max-width: 100%; position: relative; }   /* min-width:0 lets long tokens wrap instead of stretching the column; position anchors the copy button */
.cmsg .who { font-size: 12px; letter-spacing: 1.5px; color: var(--ph-dim); display: block; margin: 9px 0 3px; text-transform: uppercase; }
.cmsg .body { white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; }

/* SELECTABLE TRANSCRIPT — the log is real text: mouse-select + copy anywhere in it, like any terminal
   (overrides the game chrome's body { user-select: none }). Controls and labels stay unselectable so a
   drag-select never smears button captions / speaker chips / timestamps into the copied prose. */
#chat-log { user-select: text; }
#chat-log .cmsg .body { cursor: text; }
#chat-log button, #chat-log .who, #chat-log .cmsg-ts { user-select: none; }

/* COPY — a hover-revealed ⧉ button at the top-right of an agent MESSAGE row (CSS keeps it off the work-log
   beats, which aren't prose). Flashes to ✓ on a successful copy. Touch/keyboard-focus reveal it too. */
.cmsg-copy {
  position: absolute; top: 1px; right: 0; z-index: 1;
  border: 1px solid var(--ph-dim); background: var(--panel2); color: var(--ph-dim);
  font-size: 12px; line-height: 1; padding: 2px 5px; border-radius: 4px; cursor: pointer;
  opacity: 0; transition: opacity .12s, color .12s, border-color .12s;
}
.cmsg.agent:hover > .cmsg-copy, .cmsg.user:hover > .cmsg-copy, .cmsg-copy:focus-visible { opacity: .85; }
.cmsg-copy:hover { color: var(--ph-bright); border-color: var(--ph); opacity: 1; }
.cmsg-copy.copied { color: var(--ph); border-color: var(--ph); opacity: 1; }
/* the work-log beats are not "messages" → no copy button */
.cmsg.tool > .cmsg-copy, .cmsg.consent > .cmsg-copy, .cmsg.turnin > .cmsg-copy,
.cmsg.nudge > .cmsg-copy, .cmsg.deliverable > .cmsg-copy { display: none; }

/* the agent: a left rail + phosphor name */
.cmsg.agent { align-self: stretch; border-left: 2px solid var(--ph-faint); padding-left: 11px; }
.cmsg.agent .who { color: var(--ph); }
.cmsg.agent .body { color: var(--text); }
.cmsg.agent.err .body { color: var(--bad); }
/* the de-emphasized raw technical detail under a plain-language error headline: dim, smaller, on its own
   line. Kept for debugging (also mirrored into its title tooltip) without competing with the readable lead. */
.cmsg.agent.err .err-detail {
  display: block; margin-top: 3px; font-size: 12.5px; line-height: 1.4;
  color: var(--ph-dim); opacity: .8; word-break: break-word;
}

/* the Commander: right-aligned with a gold right rail — a party opposite the agent, no heavy box.
   min-width keeps a one-word message ("hi") from collapsing to a cramped sliver against the rail. */
.cmsg.user { align-self: flex-end; min-width: 4.5em; max-width: 86%; text-align: left; border-right: 2px solid var(--gold); padding-right: 11px; }
.cmsg.user .who { color: var(--gold); text-align: right; }
.cmsg.user .body { color: var(--ph-bright); }

/* GROUPING — hide the repeated name when the SAME speaker continues; add air on a speaker change */
.cmsg.agent + .cmsg.agent .who,
.cmsg.user + .cmsg.user .who { display: none; }
.cmsg.user + .cmsg.agent, .cmsg.agent + .cmsg.user { margin-top: 8px; }

.cmsg .caret { display: inline-block; width: .5em; margin-left: 1px; color: var(--ph); text-shadow: 0 0 6px var(--ph-glow); animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* (The `.cmsg.agent.reply` lit-headline treatment was retired: chat.js never tags a row `.reply` — every turn,
   live or replayed, is a plain grouped message and the streaming caret marks the newest one. Rules deleted.) */

/* first-run / empty stream: a single dim hint instead of a blank void */
.cmsg-empty { color: var(--ph-dim); font-size: 14px; line-height: 1.5; text-align: center; padding: 18px 10px; opacity: .85; }

/* tool-activity lines: the agent's actions, interleaved with its prose (classic harness flow).
   Dim subordinate micro-lines that read as "what it's doing" between what it's saying. */
.cmsg.tool { font-size: 13.5px; padding-left: 11px; }
.cmsg.tool .who { display: none; }
.cmsg.tool .body { color: var(--ph-dim); letter-spacing: 0.3px; }
.cmsg.tool.err .body { color: var(--bad); }
.cmsg.deliverable .body { color: var(--ph); }
.deliverable-link { color: var(--gold); text-decoration: underline; cursor: pointer; }
.deliverable-link:hover { color: var(--ph-bright); }
/* an inline image the agent generated: a small clickable thumbnail; click opens the full image in a new tab */
.deliverable-thumb { display: inline-block; vertical-align: middle; margin-top: 4px; line-height: 0; border: 1px solid var(--gold); border-radius: 4px; overflow: hidden; cursor: pointer; }
.deliverable-thumb img { display: block; max-width: 168px; max-height: 128px; }
.deliverable-thumb:hover { border-color: var(--ph-bright); box-shadow: 0 0 6px var(--ph-glow); }
/* an inline video/audio clip the agent produced — a seekable player (Range-streamed from /api/file) */
.media-name { display: block; color: var(--ph-dim); font-size: 12px; margin: 2px 0 4px; letter-spacing: 0.3px; }
.deliverable-video { display: block; max-width: 340px; max-height: 240px; width: 100%; border: 1px solid var(--gold); border-radius: 5px; background: #000; }
.deliverable-audio { display: block; max-width: 340px; width: 100%; margin-top: 2px; }
.media-fallback { display: inline-block; margin-top: 5px; }
/* a clickable URL the agent typed in its prose — match the gold deliverable-link affordance */
.cmsg.agent .body a { color: var(--gold); text-decoration: underline; }
.cmsg.agent .body a:hover { color: var(--ph-bright); }

/* END-OF-RUN RECAP (work-visibility): a passive work-log REPORT in the .tool register — what the run
   produced (files/images/channel sends) + cost/duration/model. Never a beat: it stays in the log like a
   tool line (no vanish), and only shows when there ARE artifacts or the run ended abnormally. */
.cmsg.recap .recap-line { display: block; line-height: 1.55; min-width: 0; overflow-wrap: anywhere; }
.cmsg.recap .recap-head { color: var(--gold); letter-spacing: .4px; }
.cmsg.recap .recap-foot { font-size: 12px; opacity: .85; }
.recap-copy {
  font: inherit; font-size: 12px; cursor: pointer;
  color: var(--ph-dim); background: transparent; border: none;
  margin-left: 6px; padding: 0 2px; opacity: .75;
}
.recap-copy:hover { color: var(--ph-bright); opacity: 1; }

/* OPEN-FOLDER affordance on a file deliverable (Theme 4 — outputs are findable). Quiet inline
   control reusing the phosphor language; desktop reveals the folder, browser copies the path. */
.deliverable-folder {
  font: inherit; font-size: 11px; letter-spacing: .3px; cursor: pointer;
  color: var(--ph-dim); background: transparent;
  border: 1px solid rgba(var(--ph-bright-rgb), .28); border-radius: 3px;
  margin-left: 8px; padding: 0 6px; opacity: .85; white-space: nowrap;
}
.deliverable-folder:hover { color: var(--ph-bright); border-color: rgba(var(--ph-bright-rgb), .55); opacity: 1; }

/* live consent prompt — the agent paused for approval, INLINE in the flow where it happened (this
   replaced the always-on top APPROVALS panel). A clear gold frame so it reads as "act on me now". */
.cmsg.consent { font-size: 15px; border-left: 2px solid var(--gold); background: rgba(var(--gold-rgb),.06); padding: 8px 11px; border-radius: 0 5px 5px 0; margin: 5px 0; }
.cmsg.consent .body { color: var(--ph-bright); }
.consent-btns { display: inline-flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.consent-btn {
  font: inherit; font-size: 13px; letter-spacing: 0.5px; cursor: pointer;
  color: var(--ph); background: linear-gradient(180deg, rgba(var(--ph-rgb),.07), rgba(var(--ph-rgb),.02));
  border: 1px solid var(--ph-dim); padding: 5px 11px; border-radius: 4px; text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.1), 0 1px 0 rgba(0,0,0,.35);
  transition: background-color .1s, color .1s, border-color .1s, box-shadow .1s, transform .1s;
}
.consent-btn:active { transform: translateY(1px); }
.consent-btn:hover { color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); }
.consent-btn:focus-visible { outline: none; color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); box-shadow: 0 0 8px var(--ph-glow2); }
.consent-btn.danger { color: var(--gold); border-color: var(--gold); }
.consent-btn.danger:hover { color: var(--ph-bright); background: rgba(var(--gold-rgb), 0.12); }
.consent-btn.deny { color: var(--bad); border-color: var(--bad); }
.consent-btn.deny:hover { color: var(--ph-bright); background: rgba(255, 90, 90, 0.12); }
.consent-result { font-size: 13px; letter-spacing: 0.5px; color: var(--ph); }
.consent-result.err { color: var(--bad); }

/* Cortex turn-in beat: reflection proposed durable memories — Keep / Edit / Discard (the formation loop) */
.cmsg.turnin {
  font-size: 15px; margin: 7px 0; padding: 9px 11px 10px;
  border-left: 2px solid var(--gold); border-radius: 0 5px 5px 0;
  background: linear-gradient(180deg, rgba(var(--gold-rgb),.08), rgba(var(--gold-rgb),.035));
  box-shadow: inset 0 1px 0 rgba(var(--ph-bright-rgb),.08), 0 0 10px rgba(var(--gold-rgb),.08);
}
.cmsg.turnin .body {
  display: flex; flex-direction: column; gap: 7px;
  color: var(--ph-bright);
}
.turnin-title { display: block; line-height: 1.35; }
.turnin-queue {
  align-self: flex-start; color: var(--gold); font-size: 11px; letter-spacing: 0.6px;
  border: 1px solid rgba(var(--gold-rgb),.55); border-radius: 2px; padding: 1px 5px;
  background: rgba(var(--gold-rgb),.06);
}
.turnin-queue[hidden] { display: none; }
.turnin-slot { display: block; min-width: 0; }
/* "rate the work" — the primary leveling beat: a gold label + the shared consent buttons (reused styling). */
.turnin-rate { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin: 5px 0 9px; }
.work-rate-label { color: var(--gold); font-size: 12px; letter-spacing: .4px; opacity: .95; }
/* one-time explainer above the very first rate control (chat.js WORKRATE_COACH_KEY) — a quiet full-width
   line so it reads as coaching, not part of the label. flex-basis 100% breaks it onto its own row in the
   .turnin-rate / consent-btns flex hosts. */
.work-rate-hint { flex-basis: 100%; width: 100%; color: var(--ph); font-size: 11px; letter-spacing: .3px; opacity: .8; margin-bottom: 2px; }
.turnin-rate .consent-btns, .cmsg.work-rate .consent-btns { margin-top: 0; }
/* FLAT item row — the card is the only box. A second bordered box inside the gold inset read as
   stacked popups; the item is now a quiet row: soft kind pill + text, evidence + buttons below. */
.turnin-item {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 6px 8px;
  margin-top: 1px; padding: 1px 0; border-radius: 0;
  background: transparent; border-left: 0;
}
.turnin-kind {
  font-size: 10px; letter-spacing: 1px; color: var(--gold);
  background: rgba(var(--gold-rgb), .13); border: none; border-radius: 2px;
  padding: 2px 6px; flex: 0 0 auto; margin-top: 1px; opacity: 0.95;
}
/* provenance / evidence line ("↳ you said …", "↳ 3 approvals in a row") — a dim aside above the
   buttons, never a bordered chip (that read as ANOTHER nested box). */
.turnin-evidence {
  grid-column: 1 / -1; justify-self: start; min-width: 0; overflow-wrap: anywhere;
  color: var(--ph-dim); font-size: 12px; line-height: 1.4; letter-spacing: .2px;
}
/* buttons inside a post-run beat card are secondary controls — compact, 1px chrome (the full-size
   2px consent buttons stay reserved for real approval prompts outside the turn-in family). */
.cmsg.turnin .consent-btn { font-size: 12px; padding: 2px 9px; border-width: 1px; }
.turnin-text {
  min-width: 0; color: var(--ph-bright); font-size: 14px; line-height: 1.35;
  overflow-wrap: anywhere; word-break: break-word;
}
.turnin-item .consent-btns { grid-column: 1 / -1; margin-top: 1px; display: flex; flex-wrap: wrap; gap: 6px; }
/* anything chat.js appends INTO the item grid AFTER the kind/text pair (the ↳ evidence line on
   study/trust cards, the verdict flash, an in-place rate control) must claim a full row. Auto-placed
   they land in the `auto` first column — a long evidence string then blows that column out to the
   container width and crushes the minmax(0,1fr) text column to ~1ch, wrapping the belief text one
   character per line down the window edge (and stretching the card to fill the whole panel). */
.turnin-item > .turnin-queue { grid-column: 1 / -1; justify-self: start; min-width: 0; overflow-wrap: anywhere; }
.turnin-item > .consent-result { grid-column: 1 / -1; min-width: 0; overflow-wrap: anywhere; }
.turnin-item > .turnin-rate { grid-column: 1 / -1; min-width: 0; }
.turnin-edit {
  grid-column: 1 / -1; width: 100%; box-sizing: border-box; min-width: 0;
  font: inherit; font-size: 14px; color: var(--ph-bright);
  background: var(--ink); border: 1px solid var(--ph-dim); border-radius: 2px; padding: 2px 6px;
}
.turnin-edit:focus { outline: none; border-color: var(--ph); }

/* W3 — THE DELIVERY CARD (rendered inside the deliverable's OWN session, 2026-07-15). Rides the gold-inset
   turn-in family (.cmsg.turnin.workshop-return); a flat stack — headline, verify line, what/how lines, the
   Open-it action, the files pane, and one action row (optional message + Implement / Later / Discard). */
.ws-verline { display:block; font-size:12px; letter-spacing:.3px; margin-top:-2px; }
.ws-verline.ok { color:var(--gold); }
.ws-verline.dim { color:var(--ph-dim); }
/* the flat delivery card (2026-07-15, premium pass 2026-07-16): labeled sections in the dossier grammar —
   a gold uppercase micro-label over a bright value (the same ws-k/ws-v voice the config cards speak). */
.workshop-return .ws-line { display:block; margin-top:2px; font-size:13px; line-height:1.4; overflow-wrap:anywhere; }
.workshop-return .ws-k { display:block; color:var(--gold); font-size:10px; letter-spacing:1.2px; text-transform:uppercase; opacity:.92; margin-bottom:1px; }
.workshop-return .ws-v { display:block; color:var(--ph-bright); }
.workshop-return .ws-how .ws-v, .workshop-return .ws-notver .ws-v, .workshop-return .ws-because .ws-v { color:var(--ph-dim); font-size:12.5px; }
.workshop-return .ws-because .ws-v { font-style:italic; }   /* provenance reads as a quoted aside, not a claim */
/* honest-brevity furniture (2026-07-17): verbose legacy manifests FOLD instead of walling — a quiet
   inline "+ more" reveal, and one gold-marked row per check-yourself item (the old semicolon join). */
.workshop-return .ws-more { background:none; border:0; padding:0; margin-left:2px; font:inherit; font-size:11px;
  letter-spacing:.5px; color:var(--gold); cursor:pointer; opacity:.85; }
.workshop-return .ws-more:hover { opacity:1; text-shadow:0 0 6px var(--ph-glow); }
.workshop-return .ws-nvitem { display:block; padding-left:11px; position:relative; }
.workshop-return .ws-nvitem::before { content:'▸'; position:absolute; left:0; color:var(--gold); opacity:.7; }
/* honest kind chip beside the headline — cf-badge vocabulary, gold edge */
.ws-kindchip { margin-left:8px; font-size:10px; letter-spacing:1px; text-transform:uppercase; color:var(--gold);
  border:1px solid rgba(var(--gold-rgb),.55); border-radius:2px; padding:0 5px; background:rgba(var(--gold-rgb),.06);
  vertical-align:2px; white-space:nowrap; }
.ws-pane { min-width:0; background:var(--ph-faint); border:1px solid var(--ph-glow2);
  border-radius:3px; padding:7px 8px; box-sizing:border-box; margin-top:7px; }
/* disk-proven input-capture notice (validateWorkshopManifest.capturesInput) — shown above the Open-it action */
.ws-capture-warn { display:block; margin-top:6px; font-size:12px; line-height:1.35; color:var(--gold);
  background:rgba(var(--gold-rgb),.07); border:1px solid rgba(var(--gold-rgb),.35); border-radius:3px; padding:4px 7px; }
.ws-try { margin-top:7px; }
/* the HERO action — the one click that runs the deliverable. Gold, bloomed, unmistakably primary. */
.consent-btn.ws-openit { color:var(--gold); border-color:var(--gold); font-size:13px; padding:4px 14px;
  background:rgba(var(--gold-rgb),.07); box-shadow:0 0 10px rgba(var(--gold-rgb),.16);
  transition:box-shadow var(--t-fast) var(--ease-soft), background var(--t-fast) var(--ease-soft), color var(--t-fast) var(--ease-soft); }
.consent-btn.ws-openit:hover { color:var(--ph-bright); border-color:var(--gold); background:rgba(var(--gold-rgb),.16);
  box-shadow:0 0 16px rgba(var(--gold-rgb),.34); }
/* the ACCEPT action — gold means "this really implements"; a fallback save stays neutral by design */
.consent-btn.ws-primary { color:var(--gold); border-color:var(--gold); background:rgba(var(--gold-rgb),.06);
  box-shadow:0 0 8px rgba(var(--gold-rgb),.12); }
.consent-btn.ws-primary:hover { color:var(--ph-bright); background:rgba(var(--gold-rgb),.15); box-shadow:0 0 12px rgba(var(--gold-rgb),.28); }
.ws-fhead { color:var(--gold); font-size:10px; letter-spacing:1px; text-transform:uppercase; margin-bottom:4px; }
.ws-flist { display:flex; flex-direction:column; gap:2px; margin-bottom:6px; }
.ws-filerow { display:flex; align-items:center; gap:6px; }
.ws-file { flex:1 1 auto; text-align:left; background:none; border:1px solid transparent; border-radius:2px; color:var(--ph);
  font-family:inherit; font-size:12px; padding:2px 5px; cursor:pointer; overflow-wrap:anywhere; }
.ws-file:hover { border-color:var(--ph-glow2); color:var(--ph-bright); }
.ws-file.sel { border-color:var(--gold); color:var(--ph-bright); background:rgba(var(--gold-rgb),.06); }
/* W7: "view source" is the demoted, opt-in code reader — small and dim beside the primary open action. */
.ws-viewsrc { flex:0 0 auto; background:none; border:none; color:var(--ph-glow2); font-family:inherit;
  font-size:10px; letter-spacing:.5px; padding:2px 4px; cursor:pointer; opacity:.75; }
.ws-viewsrc:hover { color:var(--ph-bright); opacity:1; text-decoration:underline; }
.ws-fview { margin:0; max-height:180px; overflow:auto; background:var(--ink); border:1px solid var(--ph-glow2);
  border-radius:2px; padding:6px 7px; color:var(--ph-bright); font-size:12px; line-height:1.4; white-space:pre-wrap;
  overflow-wrap:anywhere; }
/* the decide row — separated from the evidence above by a gold hairline; it is the card's consent moment */
.workshop-return .ws-acts { margin-top:9px; padding-top:9px; border-top:1px solid rgba(var(--gold-rgb),.22);
  gap:6px 8px; align-items:center; flex-wrap:wrap; }
.ws-acts { margin-top:8px; gap:6px 8px; align-items:center; flex-wrap:wrap; }
/* the optional tell-the-agent message — rides the decision as a real user turn in the delivery session */
.ws-msg { flex:1 1 200px; min-width:160px; width:auto; max-width:100%; }
/* the pre-click consequence line ("implement → applies to a new branch in …") — an inset gold consent strip,
   the same left-edge voice as .cmsg.consent: this line IS the consent copy */
.workshop-return .ws-plan { color:var(--gold); font-size:12px; line-height:1.4; margin-top:7px;
  border-left:2px solid var(--gold); border-radius:0 3px 3px 0; padding:5px 8px;
  background:rgba(var(--gold-rgb),.07); }
/* copy-path / open-folder chips on the decided outcome line */
.ws-destchips { display:inline-flex; gap:6px; margin-left:8px; vertical-align:middle; }
/* per-command verification detail: the actual commands run + each one's pass/fail from the manifest */
.ws-verdetail { margin-top:6px; }
.ws-verdetail > .ws-k { display:block; color:var(--gold); font-size:10px; letter-spacing:1px; text-transform:uppercase; margin-bottom:3px; }
.ws-vcmd { display:flex; align-items:baseline; gap:6px; font-size:12px; line-height:1.4; overflow-wrap:anywhere; }
.ws-vcmd .ws-vmark { flex:0 0 auto; }
.ws-vcmd.ok  .ws-vmark { color:var(--gold); }
.ws-vcmd.bad .ws-vmark { color:var(--bad); }
.ws-vcmdtext { color:var(--ph-bright); font-family:inherit; }
.ws-vexit { color:var(--bad); font-size:11px; }

/* SILENT-SAVE receipt: a PASSIVE log of memories reflection auto-saved — one compact "◈ remembered: …" line per
   memory, kind tag, and a small ✕ to veto (undo the save). Non-blocking: no buttons demand action, it stays as a
   quiet stream line (no auto-collapse). Shares the gold-inset turn-in family but reads calmer (thinner border,
   softer fill) — it's a notice, not a prompt. .receipts drops the deck's flex-gap so lines stack tight. */
.cmsg.turnin.receipts {
  border-left-color: rgba(var(--gold-rgb), .55);
  background: linear-gradient(180deg, rgba(var(--gold-rgb),.04), rgba(var(--gold-rgb),.015));
  box-shadow: none;
}
.cmsg.turnin.receipts .body { gap: 3px; }
/* one small caps header owns the "remembered" claim; the lines below are just the memories. */
.receipt-head {
  color: var(--gold); font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase;
  opacity: .9; margin-bottom: 1px;
}
.receipt-item {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: start; gap: 4px 8px;
  padding: 1px 0; border-radius: 0; background: transparent; border-left: 0;
}
.receipt-text {
  min-width: 0; color: var(--ph); font-size: 13px; line-height: 1.4;
  overflow-wrap: anywhere; word-break: break-word;
}
.receipt-veto {
  flex: 0 0 auto; align-self: center; cursor: pointer; font: inherit; font-size: 12px; line-height: 1;
  color: var(--ph-dim); background: transparent; border: none; border-radius: 2px;
  padding: 1px 5px; opacity: .6; transition: color .12s ease, opacity .12s ease, background .12s ease;
}
.receipt-veto:hover { color: var(--bad); opacity: 1; background: rgba(255,90,90,.08); }
.receipt-veto:disabled { opacity: .35; cursor: default; }
.receipt-item.vetoed { opacity: .55; }
.receipt-item.vetoed .receipt-text { color: var(--ph-dim); text-decoration: line-through; }
.receipt-item.vetoed .turnin-kind { color: var(--ph-dim); background: var(--ph-faint); }

/* JUST-IN-TIME CURIOSITY nudge — a QUIET aside, not a second lit reply. It used to reuse .cmsg.agent.reply
   (the glowing headline), so it read as a duplicate answer competing with the real one. Now it shares the
   soft gold-inset language of the consent / turn-in beats: clearly "the station is asking", visually subordinate
   to the live reply above it. One post-run beat at a time (chat.js retires a nudge if a turn-in claims the moment). */
.cmsg.agent.nudge {
  border-left: 2px solid var(--gold); background: rgba(var(--gold-rgb),.05);
  padding: 8px 11px; margin: 6px 0 2px; border-radius: 0 5px 5px 0;
}
.cmsg.agent.nudge .who { display: none; }
.cmsg.agent.nudge .body { color: var(--ph-bright); font-size: 14.5px; }

/* RETIRING A SETTLED BEAT (chat.js vanish()): a decided memory card / answered nudge fades and collapses to
   nothing, then drops from the DOM — so the COMMS feed only ever holds the conversation and PENDING prompts,
   never a graveyard of "✕ discarded" husks. overflow:hidden lets max-height clip padding for a clean collapse. */
.turnin-item, .cmsg.turnin, .cmsg.nudge {
  overflow: hidden;
  transition: opacity .16s ease, max-height .26s ease, margin .26s ease, padding .26s ease, border-width .26s ease;
}
.beat-vanish {
  opacity: 0 !important;
  margin-top: 0 !important; margin-bottom: 0 !important;
  padding-top: 0 !important; padding-bottom: 0 !important;
  border-top-width: 0 !important; border-bottom-width: 0 !important;
}

/* Cortex MEMORY CORE (M-mem.6): the provenance panel — every belief, traceable, with pin/edit/forget */
.mc-note { font-size: 12px; color: var(--ph-dim); line-height: 1.4; margin: 2px 0 10px; }
.mc-note b { color: var(--ph); }
.mc-list { display: flex; flex-direction: column; gap: 8px; }
.mc-empty { padding: 10px 4px; }   /* dim grade + size via the grouped empty rule (motion.css) */
.mc-rec {
  padding: 8px 10px; border-radius: 3px; background: var(--ph-faint);
  border: 1px solid var(--ph-faint); border-left: 2px solid var(--ph-dim);
}
.mc-rec.pinned { border-left-color: var(--gold); }
/* the declined reject-list: dimmer + a muted red edge so it reads as "set aside, never proposed" (not an active belief) */
.mc-rec.mc-declined { opacity: 0.78; border-left-color: var(--bad); background: transparent; }
.mc-rec.mc-declined .mc-body { color: var(--ph-dim); }
.mc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.mc-rectitle { color: var(--ph-bright); font-size: 13px; }
.mc-scope { color: var(--ph-dim); font-size: 10px; letter-spacing: 0.5px; border: 1px solid var(--ph-dim); border-radius: 2px; padding: 0 4px; opacity: 0.85; }
.mc-pinflag { margin-left: auto; color: var(--gold); font-size: 11px; letter-spacing: 0.5px; }
.mc-body { color: var(--ph-bright); font-size: 14px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; }
.mc-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-top: 7px; font-size: 11px; color: var(--ph-dim); letter-spacing: 0.3px; }
.mc-prov { cursor: default; }
.mc-trust { display: inline-flex; align-items: center; gap: 6px; }
.mc-trk { display: inline-block; width: 54px; height: 5px; border-radius: 3px; background: var(--ph-faint); border: 1px solid var(--ph-dim); overflow: hidden; vertical-align: middle; }
.mc-fill { display: block; height: 100%; background: var(--gold); }
.mc-acts { margin-top: 8px; }
.mc-edit {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; color: var(--ph-bright);
  background: var(--ink); border: 1px solid var(--ph-dim); border-radius: 2px; padding: 4px 6px; min-height: 48px; resize: vertical;
}
.mc-edit:focus { outline: none; border-color: var(--ph); }

/* COMMANDER DOSSIER (Phase A): the station-wide glass box — one model of the user, every belief editable */
.cd-fam { display: inline-flex; align-items: center; gap: 7px; }
.cd-fk { display: inline-block; width: 120px; height: 6px; border-radius: 3px; background: var(--ph-faint); border: 1px solid var(--ph-dim); overflow: hidden; vertical-align: middle; }
.cd-ff { display: block; height: 100%; background: var(--gold); }
.cd-fpct { color: var(--ph-bright); font-size: 12px; letter-spacing: 0.5px; }
.cd-sub { font-size: 12px; color: var(--ph-dim); margin: 8px 0 6px; letter-spacing: 0.3px; }
.cd-sub b { color: var(--ph); }
/* STATION RECORD (G3a pride layer): the durable lifetime counters — a compact grid of honest numbers.
   Reads PrideStore.snapshot(); a counter with no real sample yet shows "—" (never a fabricated 0). */
.cd-record { margin: 12px 0 4px; padding: 9px 11px; background: var(--ph-faint); border-left: 2px solid var(--gold); border-radius: 0 5px 5px 0; }
.cd-record-h { font-family: inherit; font-size: 10px; letter-spacing: .16em; color: var(--gold); opacity: .9; margin-bottom: 8px; }
.cd-record-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px 14px; }   /* 4-up in the widened (760px) dossier; collapses via the narrow fallback below */
.cd-stat { display: flex; flex-direction: column; gap: 2px; }
.cd-stat-n { font-size: 21px; line-height: .95; color: var(--ph-bright); letter-spacing: .5px; text-shadow: 0 0 10px var(--ph-glow2); }
.cd-stat-n.dim { color: var(--ph-dim); text-shadow: none; }
.cd-stat-l { font-size: 10px; letter-spacing: .1em; color: var(--ph-dim); text-transform: uppercase; }
.cd-founded { margin-top: 9px; font-size: 11px; color: var(--ph-dim); letter-spacing: .3px; }
.cd-founded b { color: var(--ph); }
/* AGENT BRIEFING — the verbatim Commander block agents receive (the panel's practical payoff): a recessed
   terminal well in the CRT vocabulary; the text glows softly because it IS live prompt material. */
.cd-brief { margin: 12px 0 2px; padding: 10px 12px; background: var(--ink); border: 1px solid var(--ph-dim); border-radius: 5px; box-shadow: inset 0 0 18px rgba(var(--ph-rgb), .06); }
.cd-brief-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 7px; }
.cd-brief-h { font-size: 10px; letter-spacing: .16em; color: var(--ph-bright); }
.cd-brief-meter { font-size: 10px; color: var(--ph-dim); letter-spacing: .08em; white-space: nowrap; cursor: help; }
.cd-brief-text { margin: 0; font: inherit; font-size: 13px; line-height: 1.45; color: var(--ph); white-space: pre-wrap; word-break: break-word; max-height: 190px; overflow-y: auto; text-shadow: 0 0 4px var(--ph-glow2); }
.cd-brief-empty { font-style: italic; color: var(--ph-dim); font-size: 12px; }
.cd-brief-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 9px; flex-wrap: wrap; }
.cd-flows { display: flex; flex-wrap: wrap; gap: 5px; }
.cd-flow { font-size: 10px; letter-spacing: .06em; color: var(--ph-dim); border: 1px solid var(--ph-faint); border-radius: 3px; padding: 1px 7px; cursor: help; }
.cd-flow:hover { color: var(--ph); border-color: var(--ph-dim); }
.cd-brief-copy { white-space: nowrap; }
/* a belief the char cap shortened/dropped from the composed briefing — gold = "needs your attention" */
.cd-trim-tag { display: inline-block; margin-right: 6px; padding: 0 5px; font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--gold); border: 1px dashed rgba(var(--gold-rgb), .6); border-radius: 2px; cursor: help; }
/* the dimension sections: a two-column grid in the widened window (single column of short cards wasted it) */
.cd-dims { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 22px; align-items: start; }
.cd-sec { margin-top: 14px; min-width: 0; }
.cd-sec.known .cd-sech { border-bottom-color: var(--ph-dim); }
@media (max-width: 820px) { .cd-dims { grid-template-columns: 1fr; } .cd-record-grid { grid-template-columns: repeat(2, 1fr); } }
.cd-sech { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; border-bottom: 1px solid var(--ph-faint); padding-bottom: 3px; }
.cd-dim { color: var(--ph-bright); font-size: 13px; letter-spacing: 0.5px; text-transform: uppercase; }
.cd-dn { color: var(--ph-dim); font-size: 11px; }
.cd-empty { font-style: italic; padding: 4px 2px 6px; }   /* dim grade + size via the grouped empty rule (motion.css) */
/* the curiosity question-state readout for a blank dimension: a quiet aside + the re-enable escape hatch */
.cd-curio { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 0 2px 6px; }
.cd-curio:empty { display: none; }
.cd-curio-lbl { color: var(--ph-dim); font-size: 11px; letter-spacing: 0.3px; }
.cd-reenable { font: inherit; font-size: 11px; color: var(--ph); background: transparent; border: 1px dashed var(--ph-dim); border-radius: 3px; padding: 2px 8px; cursor: pointer; letter-spacing: 0.4px; }
.cd-reenable:hover { border-color: var(--ph); border-style: solid; }
.cd-rec { padding: 7px 10px; border-radius: 3px; background: var(--ph-faint); border: 1px solid var(--ph-faint); border-left: 2px solid var(--ph-dim); margin-bottom: 7px; }
.cd-rec.pinned { border-left-color: var(--gold); }
.cd-rec.cd-observed { border-left-color: var(--ph-mid, var(--ph-dim)); border-left-style: dashed; }   /* GROWTH Tier 1: a station-observed (study) belief reads distinct from a Commander-authored one */
.cd-body { color: var(--ph-bright); font-size: 14px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; }
.cd-meta { margin-top: 6px; font-size: 11px; color: var(--ph-dim); letter-spacing: 0.3px; }
.cd-observed-tag { display: inline-block; margin-right: 6px; padding: 0 5px; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink); background: var(--ph-dim); border-radius: 2px; vertical-align: 1px; }
.cd-acts { margin-top: 8px; }
/* guided starter chips (empty dims + the add editor): tap → the editor opens with the sentence started */
.cd-starters { display: flex; flex-wrap: wrap; gap: 5px; margin: 2px 0 7px; }
.cd-starter { font: inherit; font-size: 11px; letter-spacing: 0.4px; cursor: pointer; color: var(--ph-dim); background: transparent; border: 1px dashed var(--ph-faint); border-radius: 3px; padding: 2px 8px; }
.cd-starter:hover { color: var(--ph); border-color: var(--ph-dim); border-style: solid; }
.cd-add { margin: 2px 0 4px; }
.cd-addbtn { font: inherit; font-size: 12px; color: var(--ph-dim); background: transparent; border: 1px dashed var(--ph-dim); border-radius: 3px; padding: 3px 10px; cursor: pointer; letter-spacing: 0.5px; }
.cd-addbtn:hover { color: var(--ph); border-color: var(--ph); }
.cd-edit { width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; color: var(--ph-bright); background: var(--ink); border: 1px solid var(--ph-dim); border-radius: 2px; padding: 4px 6px; min-height: 44px; resize: vertical; }
.cd-edit:focus { outline: none; border-color: var(--ph); }
.cd-actions-row { margin: 10px 0 2px; }
.cd-interview { width: 100%; font: inherit; font-size: 13px; letter-spacing: 0.6px; cursor: pointer; color: var(--ink); background: var(--ph); border: 1px solid var(--ph); border-radius: 3px; padding: 8px 12px; }
.cd-interview:hover { background: var(--ph-bright); border-color: var(--ph-bright); box-shadow: 0 0 10px var(--ph-glow2); }

/* THE AWAKENING — tappable suggestion chips in COMMS (the gamified first-meeting onboarding) */
.choice-row {
  display: flex; flex-wrap: wrap; gap: 6px; margin: 3px 0 6px;
  position: relative; z-index: 2; max-width: 100%;
}
.choice {
  font: inherit; font-size: 14px; letter-spacing: 0.5px; cursor: pointer;
  color: var(--ph); background: linear-gradient(180deg, rgba(var(--ph-rgb),.07), rgba(var(--ph-rgb),.02));
  border: 1px solid var(--ph-dim); padding: 5px 11px; border-radius: 4px; text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.1), 0 1px 0 rgba(0,0,0,.35);
  transition: background-color .1s, color .1s, border-color .1s, box-shadow .1s, transform .1s;
}
.choice:hover, .choice:focus-visible {
  color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); outline: none;
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.15), 0 0 9px var(--ph-glow2), 0 1px 0 rgba(0,0,0,.35);
}
.choice:active { transform: translateY(1px); }
/* T3.9 — the SECONDARY bug-report affordance under a failed turn: subdued so it never competes with the primary
   recovery chip (dashed, dimmer, smaller). Brightens to a normal chip on hover so it stays discoverable. */
.choice.quiet { font-size: 12px; letter-spacing: 0.3px; border-style: dashed; border-color: var(--ph-faint); color: var(--ph-dim); text-shadow: none; padding: 3px 8px; background: transparent; box-shadow: none; }
.choice.quiet:hover, .choice.quiet:focus-visible { color: var(--ph-bright); border-color: var(--ph-dim); border-style: solid; }
.choice.quiet:disabled { cursor: default; opacity: 0.7; }
/* TASK BRIEF — the host-validated recommended default on a task question: gold-marked so one tap accepts
   the suggestion. Rendered ONLY when the durable brief carries a REAL recommendation (the brief_ask path);
   marker-path questions have none and stay plain chips. Accent via --gold-rgb, never a literal amber. */
.choice.suggested { color: var(--gold); border-color: var(--gold); text-shadow: 0 0 5px rgba(var(--gold-rgb), .45); }
.choice.suggested:hover, .choice.suggested:focus-visible {
  color: var(--gold); border-color: var(--gold); background: rgba(var(--gold-rgb), .08);
  box-shadow: inset 0 1px 0 rgba(var(--gold-rgb),.15), 0 0 9px rgba(var(--gold-rgb), .35), 0 1px 0 rgba(0,0,0,.35);
}
.tq-reason { font-size: 12px; color: var(--ph-dim); letter-spacing: 0.3px; margin-top: 3px; }

/* TASTE EXTRACTION "my read" card (chat.js briefReadCard) — the mid-run announce-and-act read.
   The assumption chips are CORRECTABLE guesses, so they wear the quiet dashed chip look (never the
   bright primary .choice — tapping one starts a correction, it doesn't accept anything). */
.tb-read-head { font-size: 13px; letter-spacing: 0.4px; color: var(--ph-bright); text-shadow: 0 0 5px var(--ph-glow2); }
.tb-read-meta { font-size: 12px; color: var(--ph-dim); letter-spacing: 0.3px; margin-top: 2px; }
.tb-read-assumps { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; max-width: 100%; }
.tb-read-assump {
  font: inherit; font-size: 12px; letter-spacing: 0.3px; cursor: pointer;
  color: var(--ph-dim); background: transparent; text-shadow: none;
  border: 1px dashed var(--ph-faint); border-radius: 4px; padding: 3px 8px;
  transition: color .1s, border-color .1s, background-color .1s;
}
.tb-read-assump:hover, .tb-read-assump:focus-visible {
  color: var(--ph-bright); border-color: var(--ph-dim); border-style: solid; background: var(--ph-faint); outline: none;
}
.tb-read-fix { margin-top: 6px; }
.tb-read-in { width: 100%; font-size: 13px; padding: 4px 8px; }
.tb-read-ack { font-size: 12px; color: var(--ph); letter-spacing: 0.3px; }
.tb-read-ack.err { color: var(--bad, #d66); }

/* ===== THE DIALOGUE MODE (dialogue.js) — Fallout-style focused first-run conversation =====
   Mounts as a child overlay of #chat-panel, covering COMMS while the awakening/tutorial runs. One short
   line, selectable options, and a custom-text box — typed input is captured deterministically. */
#chat-panel.fnv-host { position: relative; }
.fnv-dialogue {
  position: absolute; inset: 0; z-index: 30; display: flex; flex-direction: column;
  padding: 18px 18px 16px; gap: 12px; box-sizing: border-box;
  background:
    radial-gradient(ellipse 130% 90% at 50% 0%, var(--ph-glow2), transparent 55%),
    linear-gradient(180deg, rgba(0,0,0,.94), rgba(0,0,0,.97));
  border-left: 2px solid var(--ph-dim);
  opacity: 0; transition: opacity .35s ease;
}
.fnv-dialogue.show { opacity: 1; }
.fnv-dialogue.no-anim { transition: none; }
.fnv-floating { position: fixed; right: 18px; bottom: 18px; width: min(440px, 92vw); height: auto; max-height: 70vh; border: 2px solid var(--ph-dim); border-radius: var(--r-lg); }
.fnv-speaker {
  color: var(--ph-bright); font-size: 13px; letter-spacing: 3px; text-transform: uppercase;
  text-shadow: 0 0 8px var(--ph-glow2); padding-bottom: 8px; border-bottom: 1px solid var(--ph-dim); flex: 0 0 auto;
}
.fnv-line {
  flex: 1 1 auto; overflow-y: auto; color: var(--ph-bright); font-size: 18px; line-height: 1.5;
  text-shadow: 0 0 6px var(--ph-glow2); white-space: pre-wrap; min-height: 2.4em;
  display: flex; align-items: center;
}
.fnv-opts { flex: 0 0 auto; display: flex; flex-direction: column; gap: 7px; }
.fnv-opt {
  display: flex; align-items: baseline; gap: 9px; width: 100%; text-align: left;
  font: inherit; font-size: 16px; letter-spacing: 0.4px; cursor: pointer;
  color: var(--ph); background: linear-gradient(180deg, rgba(var(--ph-rgb),.06), rgba(var(--ph-rgb),.015));
  border: 1px solid var(--ph-dim); padding: 9px 13px; border-radius: 5px; text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.09), 0 1px 0 rgba(0,0,0,.35);
  transition: background-color .1s, color .1s, border-color .1s, box-shadow .1s;
}
.fnv-opt:hover, .fnv-opt:focus-visible {
  color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); outline: none;
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.14), 0 0 10px var(--ph-glow2), 0 1px 0 rgba(0,0,0,.35);
}
.fnv-opt .fnv-num { color: var(--ph-dim); font-size: 14px; flex: 0 0 auto; min-width: 16px; }
.fnv-opt:hover .fnv-num { color: var(--ph); }
.fnv-opt.custom { border-style: dashed; }
.fnv-opt.skip { color: var(--ph-dim); }
.fnv-opt.skip:hover { color: var(--ph); }
.fnv-custom { display: flex; align-items: center; gap: 6px; }
.fnv-custom-in { flex: 1 1 auto; width: auto; min-width: 0; font-size: 16px; }
.fnv-custom-send {
  font-family: inherit; font-size: 18px; color: var(--ink);
  background: linear-gradient(180deg, var(--ph-bright) -40%, var(--ph) 60%);
  border: 1px solid var(--ph-bright); border-radius: 5px; padding: 7px 13px; cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 rgba(0,0,0,.45);
  transition: background-color .12s, box-shadow .12s;
}
.fnv-custom-send:hover { background: var(--ph-bright); border-color: var(--ph-bright); box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 0 12px var(--ph-glow); }
.fnv-custom-back { font-family: inherit; font-size: 14px; color: var(--ph-dim); background: transparent; border: 1px solid var(--ph-dim); border-radius: 5px; padding: 7px 11px; cursor: pointer; transition: color .12s, border-color .12s; }
.fnv-custom-back:hover { color: var(--ph); border-color: var(--ph); }

#chat-inputrow {
  display: flex; align-items: center; gap: 6px; padding: 8px; border-top: 2px solid var(--ph-dim);
  position: relative; z-index: 4; background: var(--panel);
}   /* position anchors the slash palette above the row */
#chat-inputrow .prompt { color: var(--ph); }

/* SLASH COMMANDS — a filterable palette floating directly above the input. Phosphor list, selected row lit. */
.chat-slash {
  position: absolute; left: 6px; right: 6px; bottom: calc(100% + 4px); z-index: 30;
  max-height: 244px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--ph); border-radius: 6px;
  box-shadow: 0 -6px 20px rgba(0,0,0,.6), 0 0 0 2px rgba(0,0,0,.5);
}
.chat-slash[hidden] { display: none; }
.slash-head { padding: 4px 10px; color: var(--ph-dim); font-size: 11px; letter-spacing: 1.5px; border-bottom: 1px solid var(--ph-faint); position: sticky; top: 0; background: var(--panel); }
.slash-item { display: flex; align-items: baseline; gap: 9px; padding: 5px 10px; cursor: pointer; }
.slash-item .slash-name { color: var(--ph-bright); white-space: nowrap; flex: 0 0 auto; }
.slash-item .slash-desc { color: var(--ph-dim); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.slash-item.sel { background: var(--ph-faint); }
.slash-item.sel .slash-desc { color: var(--ph); }
#chat-input { flex: 1; width: auto; min-width: 0; border: none; background: transparent; padding: 4px 2px; }
#chat-input:focus { box-shadow: none; }

/* TYPE-AHEAD queue — follow-ups typed while the agent is working, shown as pills above the input row and
   auto-sent in order as the stream frees. The strip collapses (no padding) when nothing is queued. */
.chat-queued { display: flex; flex-wrap: wrap; gap: 5px; padding: 0 8px; }
.chat-queued:empty { display: none; }
.chat-queued:not(:empty) { padding-top: 7px; }
.queued-pill {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  font-size: 13px; color: var(--ph); background: var(--panel2);
  border: 1px solid var(--ph-dim); border-radius: 4px; padding: 2px 5px 2px 7px;
}
.queued-pill .queued-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 210px; opacity: .9; }
/* .queued-x composes .x-btn (danger hover) — ghost delta only */
.queued-x { border: none; background: transparent; color: var(--ph-dim); font-size: 12px; padding: 0 2px; border-radius: 3px; }

/* INTERRUPT — the ⏹ Stop chip: matched to the voice chips but red, with a soft pulse so the live-stop reads
   at a glance. Shown only while the displayed stream is running (chat.js toggles [hidden] via updateControls). */
.chat-stop {
  flex: 0 0 auto; font-size: 16px; line-height: 0; color: var(--bad);
  background: transparent; border: none; border-radius: 0;
  width: 38px; height: 34px; padding: 0; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; justify-content: center;
  transition: none;
  animation: stop-pulse 1.2s ease-in-out infinite;
}
.chat-stop[hidden] { display: none; }
.chat-stop svg { width: 1em; height: 1em; display: block; pointer-events: none; }
.chat-stop:hover { background: var(--bad); color: var(--ink); }
@keyframes stop-pulse { 0%, 100% { box-shadow: 0 0 2px var(--bad); } 50% { box-shadow: 0 0 11px var(--bad); } }
@media (prefers-reduced-motion: reduce) { .chat-stop { animation: none; } }

/* ---------- voice controls: a matched set of bordered phosphor chips in the COMMS input row.
   Defined dark boxes (not bare glyphs) so they punctuate the amber UI and read as real controls;
   active states invert/recolor so the live one stands out at a glance. ---------- */
/* ROBCO INVERT register (FNV terminal) — the controls are bare phosphor glyphs drawn ON the
   console glass, not widgets. "Selected" is the terminal selection block: an INSTANT solid
   phosphor invert (ink glyph on lit phosphor) with bloom. No borders, no rounding, no easing —
   RobCo terminals snap. Persistent active states (voice-mode live, dock open) hold the block. */
.mic-btn, .voice-toggle, .model-dock-toggle {
  flex: 0 0 auto; font-size: 16px; line-height: 0; color: var(--ph);
  background: transparent; border: none; border-radius: 0;
  width: 38px; height: 34px; padding: 0; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; justify-content: center;
  transition: none;
}
.mic-btn svg, .voice-toggle svg { width: 1em; height: 1em; display: block; pointer-events: none; filter: drop-shadow(0 0 3px var(--ph-glow2)); }
.mic-btn:hover, .voice-toggle:hover, .model-dock-toggle:hover {
  color: var(--ink); background: var(--ph);
  box-shadow: 0 0 16px var(--ph-glow);
  text-shadow: none;
}
.mic-btn:hover svg, .voice-toggle:hover svg { filter: none; }
.mic-btn:active, .voice-toggle:active, .model-dock-toggle:active { background: var(--ph-bright); }
.mic-btn:focus-visible, .voice-toggle:focus-visible, .model-dock-toggle:focus-visible { outline: 1px solid var(--ph-bright); outline-offset: 2px; }

.model-dock-toggle {
  width: auto; min-width: 54px; max-width: 148px; height: 34px; padding: 0 9px; gap: 6px;
  font-size: 13px; line-height: 1; letter-spacing: 0; text-shadow: 0 0 5px var(--ph-glow2);
  position: relative; overflow: visible;
}
/* hover invert swallows the chip's inner readouts too — everything goes ink on the block */
.model-dock-toggle:hover .model-dock-model-name,
.model-dock-toggle:hover .model-dock-effort-chip,
.model-dock-toggle:hover .model-dock-effort-chip::before { color: var(--ink); text-shadow: none; }
.model-dock-toggle.on {
  color: var(--ink); background: var(--ph);
  box-shadow: 0 0 16px var(--ph-glow);
  text-shadow: none;
}
.model-dock-sigil {
  display: inline-grid; place-items: center; width: 16px; height: 16px; opacity: .9;}
.model-dock-sigil svg { width: 100%; height: 100%; display: block; }
.model-dock-effort-chip {
  display: inline-block; max-width: 40px; overflow: hidden; text-overflow: clip;
  white-space: nowrap; font-size: 10px; letter-spacing: 0.6px; color: var(--ph-bright);
}
/* resting-state model short-name: legible at rest (full phosphor, not dimmed) so the chip reads
   "MODEL · TIER" without a click. Capped + truncated so the composer never grows. */
.model-dock-model-name {
  display: inline-block; max-width: 62px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 10px; letter-spacing: 0.5px;
  color: var(--ph); line-height: 1;
}
.model-dock-model-name.empty { color: var(--ph-dim); opacity: 0.7; }
.model-dock-toggle.on .model-dock-model-name,
.model-dock-toggle.on .model-dock-effort-chip { color: var(--ink); }
.model-dock-toggle .model-dock-effort-chip::before {
  content: '·'; color: var(--ph-dim); margin: 0 3px 0 1px; font-weight: 400;
}
.model-dock-toggle.on .model-dock-effort-chip::before { color: var(--ink); opacity: .6; }
/* CRT tooltip — a molded phosphor card above the chip. pointer-events:none so it never eats
   the click that opens the dock; shown on hover AND keyboard focus (a11y); killed on open. */
.model-dock-tip {
  position: absolute; right: 0; bottom: calc(100% + 9px); z-index: 90;
  width: max-content; max-width: 244px; pointer-events: none;
  padding: 8px 11px; text-align: left; cursor: default;
  color: var(--ph); background: var(--panel);
  border: 2px solid var(--ph); border-radius: 4px;
  box-shadow: 0 0 0 2px var(--ink), 0 0 18px var(--ph-glow2);
  opacity: 0; transform: translateY(3px);
  transition: opacity .12s var(--ease-out), transform .12s var(--ease-out);
}
.model-dock-tip[hidden] { display: none; }
.model-dock-tip.show { opacity: 1; transform: translateY(0); }
.model-dock-tip::after {
  content: ''; position: absolute; right: 16px; top: 100%;
  border: 6px solid transparent; border-top-color: var(--ph);
}
.mdt-row { font-size: 12px; line-height: 1.35; white-space: normal; }
.mdt-model { color: var(--ph-bright); font-size: 13px; }
.mdt-prov { color: var(--gold); font-size: 10px; letter-spacing: 0.5px; margin-top: 1px; }
.mdt-sep { height: 1px; background: var(--ph-dim); opacity: 0.5; margin: 6px 0; }
.mdt-tier { color: var(--ph); }
.mdt-tier b { color: var(--ph-bright); }
.mdt-mean { color: var(--ph-dim); font-size: 11px; margin-top: 1px; }
.mdt-hint { color: var(--ph-dim); font-size: 10px; letter-spacing: 0.5px; margin-top: 6px; opacity: 0.85; }
.model-dock {
  position: absolute; right: 8px; bottom: calc(100% + 8px); z-index: 80;
  width: min(322px, calc(100vw - 34px)); max-height: min(70vh, 414px);
  display: flex; flex-direction: column; gap: 7px; padding: 9px;
  color: var(--ph); background: var(--panel);
  border: 2px solid var(--ph); border-radius: 4px;
  box-shadow: 0 0 0 2px var(--ink), 0 0 22px var(--ph-glow2);
}
.model-dock[hidden] { display: none !important; }
.model-dock-head {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; align-items: center;
  border-bottom: 1px solid var(--ph-dim); padding-bottom: 6px; min-width: 0;
}
.model-dock-provider {
  color: var(--gold); font-size: 11px; white-space: nowrap;
}
.model-dock-current-model {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ph-bright); font-size: 13px; text-align: right;
}
.model-dock-search {
  width: 100%; min-width: 0; box-sizing: border-box; padding: 7px 9px;
  color: var(--ph-bright); background: var(--ink); border: 1px solid var(--ph-dim);
  border-radius: 4px; outline: none; font: inherit;
  box-shadow: inset 0 2px 5px rgba(0,0,0,.5);
  transition: border-color .12s, box-shadow .12s;
}
.model-dock-search:focus { border-color: var(--ph); box-shadow: inset 0 2px 5px rgba(0,0,0,.5), 0 0 9px var(--ph-glow2); }
.model-dock-search::placeholder { color: var(--ph-dim); opacity: 1; }
.model-dock-efforts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(42px, 1fr)); gap: 4px;
}
.model-dock-effort {
  min-width: 0; height: 28px; padding: 0 3px; cursor: pointer;
  color: var(--ph); background: transparent; border: 1px solid var(--ph-dim);
  border-radius: 3px; font: inherit; font-size: 10px; overflow: hidden; text-overflow: clip; white-space: nowrap;
}
.model-dock-effort:hover { color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); }
.model-dock-effort.sel { color: var(--ink); background: var(--ph); border-color: var(--ph); }
.model-dock-list {
  min-height: 126px; max-height: 236px; overflow: auto; padding-right: 2px;
  border-top: 1px solid var(--ph-faint); border-bottom: 1px solid var(--ph-faint);
}
.model-dock-group {
  color: var(--gold); font-size: 11px; padding: 8px 3px 3px;
  border-bottom: 1px solid var(--ph-faint);
}
.model-dock-row {
  width: 100%; min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px; align-items: center; padding: 7px 6px; cursor: pointer; text-align: left;
  color: var(--ph); background: transparent; border: 0; border-bottom: 1px solid var(--ph-faint);
  font: inherit;
}
.model-dock-row:hover { color: var(--ph-bright); background: var(--ph-faint); }
.model-dock-row.sel { color: var(--ink); background: var(--ph); }
/* E4: offline fallback — the live catalog was unreachable, these are a built-in unverified seed list.
   Amber group tag + dimmed rows so they never read as a verified live catalog. */
.model-dock-group-offline { color: var(--warn); font-size: 10px; font-style: normal; letter-spacing: 0.5px; }
.model-dock-row.fallback .model-dock-row-name { color: var(--ph-dim); }
.model-dock-row.fallback.sel .model-dock-row-name { color: var(--ink); }
.model-dock-row-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px;
}
.model-dock-row-effort {
  min-width: 38px; text-align: right; font-size: 10px;}
.model-dock-empty {   /* dim grade + size via the grouped empty rule (motion.css) */
  padding: 18px 6px; text-align: center;
}
/* inline no-key warning inside the dock — one tap opens SETTINGS. Only rendered when the active provider
   truly has no stored credential (truthful telemetry), so it can't lie about a connection that exists. */
.model-dock-keywarn {
  width: 100%; display: flex; gap: 7px; align-items: flex-start; text-align: left; cursor: pointer;
  margin: 2px 0 6px; padding: 7px 8px; font: inherit; font-size: 12px; line-height: 1.35;
  color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent);
  border: 1px solid var(--warn); border-radius: 3px;
}
.model-dock-keywarn:hover { background: color-mix(in srgb, var(--warn) 22%, transparent); }
.model-dock-keywarn .mdw-glyph { flex: 0 0 auto; }
.model-dock-keywarn .mdw-txt { min-width: 0; }
/* resting chip flags a missing key by burning warn-amber so it's noticeable before the dock is even opened */
.model-dock-toggle.needs-key { color: var(--warn); text-shadow: 0 0 6px color-mix(in srgb, var(--warn) 50%, transparent); }
.model-dock-toggle.needs-key .model-dock-model-name { color: var(--warn); }
.model-dock-foot {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
}
.model-dock-foot button {
  min-width: 0; padding: 7px 5px; cursor: pointer;
  color: var(--ph); background: linear-gradient(180deg, color-mix(in srgb, var(--ph) 7%, var(--panel2)), var(--panel2));
  border: 1px solid var(--ph-dim);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.1), 0 1px 0 rgba(0,0,0,.35);
  border-radius: 4px; font: inherit; font-size: 11px;}
.model-dock-foot button:hover { color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); }

@media (max-width: 780px) {
  .model-dock-toggle { width: auto; min-width: 44px; max-width: 118px; padding: 0 5px; gap: 3px; }
  .model-dock-sigil { width: 14px; height: 14px; font-size: 10px; }
  .model-dock-effort-chip { max-width: 30px; font-size: 10px; }
  /* on the narrow composer the model short-name is redundant with the tooltip — drop it, keep MODEL·TIER glyphs */
  .model-dock-model-name { display: none; }
  .model-dock-toggle .model-dock-effort-chip::before { display: none; }
  .model-dock-tip { max-width: min(74vw, 244px); }
  .model-dock { position: fixed; left: 8px; right: 8px; bottom: 120px; width: auto; max-height: min(62vh, 410px); }
  .model-dock-list { max-height: 220px; }
}

/* mic listening: red border + glow pulse so it's unmistakable the mic is hot */
/* mic HOT = the held selection block in red: solid inverted --bad with a breathing bloom */
.mic-btn.rec {
  color: var(--ink); background: var(--bad);
  animation: mic-pulse 1s infinite;
}
.mic-btn.rec svg { filter: none; }
@keyframes mic-pulse { 0%,100% { box-shadow: 0 0 4px var(--bad); } 50% { box-shadow: 0 0 16px var(--bad); } }

/* agent-voice MUTED: red so "the agent is silenced" is impossible to miss — a molded red-tinted
   chip (same bevel register as the rest of the cluster), not a bare red outline */
/* agent-voice MUTED: the glyph itself burns red on the glass; hover = red selection block */
.voice-toggle.off { color: var(--bad); }
.voice-toggle.off svg { filter: drop-shadow(0 0 3px color-mix(in srgb, var(--bad) 35%, transparent)); }
.voice-toggle.off:hover {
  color: var(--ink); background: var(--bad);
  box-shadow: 0 0 14px color-mix(in srgb, var(--bad) 55%, transparent);
}
.voice-toggle.off:hover svg { filter: none; }
/* agent-voice speaking: amber glow pulse on the chip */
.voice-toggle.speaking { animation: chip-spk .8s infinite; }
@keyframes chip-spk { 0%,100% { box-shadow: 0 0 2px var(--ph-glow2); } 50% { box-shadow: 0 0 12px var(--ph-glow); } }

/* hands-free LIVE: filled phosphor (inverted) so the active mode clearly pops out of the row */
/* hands-free LIVE = the held selection block: this control IS selected until toggled off */
.voice-mode.on {
  color: var(--ink); background: var(--ph);
  box-shadow: 0 0 16px var(--ph-glow);
}
.voice-mode.on svg { filter: none; }
.voice-mode.on:hover { color: var(--ink); background: var(--ph-bright); border-color: var(--ph-bright); }
/* hands-free was on last session but a refresh dropped it → pulse the chip to invite a one-tap resume */
.voice-mode.resume { animation: chip-resume 1.3s ease-in-out infinite; }
@keyframes chip-resume { 0%,100% { box-shadow: 0 0 0 0 var(--ph-glow2); border-color: var(--ph-dim); } 50% { box-shadow: 0 0 12px 1px var(--ph-glow); border-color: var(--ph); } }

/* ---------- onboarding / save additions ---------- */
/* (title-screen rules removed with the title screen; #data-status now styled by .title-status at the top of this file) */
/* (deleted: .lead-banner — the old create-screen orchestrator framing banner, unused since the ov-* redesign) */
/* section subheads dominate the field labels they group (labels are 16px). A trailing dashed rule runs
   the head out to the column edge — terminal-readout texture without another heavy border. */
.cc-head {
  display: flex; align-items: center; gap: 9px;
  margin: 12px 0 4px; color: var(--ph); letter-spacing: 2px; font-size: 17px;
  text-shadow: 0 0 8px var(--ph-glow2);
}
.cc-head::after { content: ''; flex: 1; height: 0; border-top: 1px dashed var(--ph-faint); }
.cc-head .dim { letter-spacing: .5px; font-size: 14px; flex: 0 0 auto; }
.byok-note { font-size: 12px; margin-top: 6px; line-height: 1.28; opacity: .9; }
/* progressive-disclosure toggle for the key-safety note — a quiet inline link, expands the note on demand */
.byok-disclose { margin-top: 6px; }
.byok-toggle { display: inline-block; font: inherit; font-size: 12px; letter-spacing: .4px; color: var(--ph-dim); background: none; border: none; padding: 2px 0; cursor: pointer; text-align: left; }
.byok-toggle:hover { color: var(--ph); }
.byok-toggle:focus-visible { outline: 2px solid var(--ph); outline-offset: 2px; }
.byok-disclose .byok-note { margin-top: 5px; }

/* SKIN picker — thumbnail grid on the LEFT, a LIVE preview stage on the RIGHT. At 40px a
   chunky pixel sprite is unreadable, so the stage plays the picked (or hovered) skin's real
   walk cycle big enough to actually tell a bear from a capybara before committing. */
.connect-panel { max-height: 96vh; overflow-y: auto; }   /* desktop console: a touch taller cap so the two-column body lands without a scrollbar */

/* ===== CREATE YOUR OVERSEER (v4) — a FULL-SCREEN console: hero pod | identity | brain =====
   The genesis moment owns the whole display. Three numbered columns read left→right as the three
   decisions: 01 APPEARANCE · 02 IDENTITY · 03 THE BRAIN (the only required one, beside WAKE).
   The forward-version gate (#screen-future) keeps the old centered 980px card — scoped below. */
#screen-connect.active { padding: 14px; }
#screen-connect .ov-panel {
  max-width: 1780px; width: 100%; height: 100%; max-height: none;
  display: flex; flex-direction: column; margin: 0 auto;
}
#screen-connect .ov-grid { flex: 1; min-height: 0; overflow-y: auto; }
#screen-future .ov-panel { max-width: 980px; align-self: center; margin: auto; }
.ov-head { padding: 12px 22px 0; }
.ov-title-row { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-top: 8px; }
.ov-title-row h2 { margin: 0; }
.ov-sub { color: var(--ph-dim); font-size: 14px; letter-spacing: .4px; }
.ov-sub b { color: var(--ph-bright); }

.ov-grid {
  display: grid; grid-template-columns: minmax(340px, 430px) 1fr 1fr;
  grid-template-areas: "hero id brain";
}
.ov-hero {
  grid-area: hero; display: flex; flex-direction: column;
  position: relative; padding: 14px 22px 16px; border-right: 1px solid var(--ph-faint);
  background: radial-gradient(ellipse 90% 60% at 50% 22%, var(--ph-glow2), transparent 62%);
}
.ov-col-id { grid-area: id; border-right: 1px solid var(--ph-faint); }
.ov-col-brain { grid-area: brain; display: flex; flex-direction: column; }
.ov-col-brain .ov-field-brain { flex: 1; }

/* numbered step heads — the eye's rail across the three columns */
.ov-step {
  display: flex; align-items: center; gap: 9px; margin: 0 0 10px;
  color: var(--ph); letter-spacing: 2px; font-size: 16px; text-transform: uppercase;
  text-shadow: 0 0 8px var(--ph-glow2); flex-wrap: wrap;
}
.ov-step b {
  color: var(--ink); background: var(--ph); padding: 0 7px; letter-spacing: 1px;
  text-shadow: none; font-weight: normal;
}
.ov-step .dim { font-size: 13px; letter-spacing: .4px; text-transform: none; }
.ov-step::after { content: ''; flex: 1; min-width: 12px; height: 0; border-top: 1px dashed var(--ph-faint); }
.ov-step .ov-req { order: 9; }   /* the REQUIRED tag rides at the rule's far end */
.ov-leadtag {
  display: inline-flex; align-items: center; gap: 7px; color: var(--gold); font-size: 12px; letter-spacing: 2px;
  border: 1px solid var(--ph-dim); border-radius: 20px; padding: 2px 11px; margin-bottom: 12px; background: rgba(var(--ph-rgb),.05);
}
.ov-pod {
  position: relative; flex: 1 1 auto; min-height: 208px; border: 1px solid var(--ph-dim); border-radius: 8px; overflow: hidden;
  background: radial-gradient(ellipse 75% 60% at 50% 52%, var(--ph-glow2), transparent 60%), #060403;
  box-shadow: inset 0 0 60px rgba(0,0,0,.9), 0 0 0 1px rgba(0,0,0,.8), 0 0 24px var(--ph-glow2);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
}
.ov-pod::before { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(0deg, transparent 0 22px, rgba(var(--ph-rgb),.04) 22px 23px); pointer-events: none; }
.ov-stage { margin: 0 0 20px; display: flex; align-items: flex-end; justify-content: center; z-index: 1; }
.ov-stage-frame { display: flex; align-items: flex-end; justify-content: center; filter: drop-shadow(0 0 14px var(--ph-glow)); }
.ov-stage-frame img { height: clamp(136px, 26vh, 260px); width: auto; image-rendering: pixelated; image-rendering: crisp-edges; }
.ov-platform { position: absolute; bottom: 16px; width: 150px; height: 14px; border-radius: 50%; background: radial-gradient(ellipse, var(--ph-glow), transparent 70%); opacity: .55; }

.ov-nameplate { margin-top: 12px; text-align: center; }
.ov-np-name { color: var(--ph-bright); font-size: 30px; letter-spacing: 4px; text-shadow: 0 0 12px var(--ph-glow); line-height: 1.1; }
.ov-np-role { color: var(--gold); font-size: 14px; letter-spacing: 2px; margin-top: 2px; }
.ov-np-role .ov-dot { color: var(--ph-dim); }
.ov-skinname { color: var(--ph-dim); font-size: 12px; letter-spacing: 1px; margin-top: 3px; }

.ov-pickrow { margin-top: 12px; display: flex; align-items: center; gap: 10px; }
.ov-pick-lab { color: var(--ph-dim); font-size: 13px; letter-spacing: 1.5px; min-width: 42px; }
.ov-skins { flex: 1; }

.ov-cfg { padding: 16px 22px 18px; min-width: 0; }
.ov-field { margin-bottom: 14px; }
.ov-field:last-child { margin-bottom: 0; }
.ov-cfg label { display: block; }
.ov-nm-in { letter-spacing: 3px; }
.ov-req { color: var(--gold); font-size: 11px; letter-spacing: 1px; vertical-align: 1px; margin-left: 8px; }

.ov-cards { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.ov-cards.ov-approve { grid-template-columns: 1fr 1fr; }
.ov-approve .ov-card { padding: 11px 13px 10px; }
.ov-approve .ov-card-ds { font-size: 12.5px; margin-top: 3px; }
.ov-card {
  font: inherit; position: relative; border: 1px solid var(--ph-faint); border-radius: 6px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--ph) 6%, var(--panel2)), var(--panel2));
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.08), 0 1px 0 rgba(0,0,0,.35);
  padding: 10px 11px 9px; cursor: pointer; text-align: left;
  transition: border-color .12s, background-color .12s, box-shadow .12s;
}
.ov-card:hover { border-color: var(--ph-dim); background: var(--ph-faint); box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.12), 0 0 10px var(--ph-glow2), 0 1px 0 rgba(0,0,0,.35); }
.ov-card.sel { border-color: var(--ph); background: rgba(var(--ph-rgb),.07); box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.14), 0 0 16px var(--ph-glow2); }
.ov-card-ic { color: var(--ph); font-size: 19px; line-height: 1; text-shadow: 0 0 8px var(--ph-glow); }
.ov-card.sel .ov-card-ic { color: var(--ph-bright); }
.ov-card-nm { color: var(--ph-bright); font-size: 15px; letter-spacing: 1px; margin-top: 5px; }
.ov-card-ds { color: var(--ph-dim); font-size: 12px; letter-spacing: .2px; line-height: 1.12; margin-top: 2px; }
.ov-card-pick { position: absolute; top: 6px; right: 8px; color: var(--gold); font-size: 13px; opacity: 0; }
.ov-card.sel .ov-card-pick { opacity: 1; }
.ov-crewnote { margin-top: 8px; color: var(--ph-dim); font-size: 12px; letter-spacing: .3px; }
.ov-crewnote b { color: var(--ph); }

.ov-vchips { display: flex; flex-wrap: wrap; gap: 7px; }
.ov-vchip {
  font-family: inherit; font-size: 14px; color: var(--ph);
  background: linear-gradient(180deg, color-mix(in srgb, var(--ph) 7%, var(--panel2)), var(--panel2));
  border: 1px solid var(--ph-faint); border-radius: 999px; padding: 5px 15px; cursor: pointer;
  letter-spacing: .6px; text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.1), 0 1px 0 rgba(0,0,0,.35);
  transition: background-color .1s, color .1s, border-color .1s, box-shadow .1s;
}
.ov-vchip:hover { border-color: var(--ph-dim); color: var(--ph-bright); box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.14), 0 0 9px var(--ph-glow2), 0 1px 0 rgba(0,0,0,.35); }
.ov-vchip.sel {
  background: linear-gradient(180deg, var(--ph-bright) -40%, var(--ph) 60%); color: var(--ink); border-color: var(--ph);
  text-shadow: none; box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 0 9px var(--ph-glow2);
}
/* the UNHINGED chip's armed state (two-press confirm — it swears for real): warn tint until the second press */
.ov-vchip.arm {
  color: var(--warn); border-color: var(--warn);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.1), 0 0 9px color-mix(in srgb, var(--warn) 40%, transparent), 0 1px 0 rgba(0,0,0,.35);
}
.ov-vpreview { margin-top: 8px; }

.ov-field-brain { margin-bottom: 0; }
.ov-brain { border: 1px solid var(--ph-dim); border-radius: 7px; background: linear-gradient(180deg, rgba(var(--ph-rgb),.06), rgba(var(--ph-rgb),.025)); box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.08); padding: 11px 13px; }
/* (deleted: .ov-vtune + .ov-brain-lead — the voice fine-tune well and the brain lead-in paragraph are both
   gone; the hero ChatGPT card now carries the beginner message, so the lead-in was redundant.) */
.ov-brain .provider-row { margin: 0 0 8px; }
.ov-brain input { margin-bottom: 8px; }
.ov-brain .model-picks { margin: 2px 0 6px; }
.ov-brain .byok-note { margin-bottom: 0; }
.ov-model-lab label { margin-top: 2px; }

/* ===== themed grouped model popover (#model-pop) — replaces the native <datalist>. position:fixed so it
   escapes the .ov-grid overflow clip; app.js positions it under (or above) #in-model. Reuses the model-dock
   listbox vocabulary so the two model surfaces read the same. ===== */
.ov-mdl-wrap { margin-bottom: 8px; }
.ov-mdl-wrap input { margin-bottom: 0; }
.ov-mdl-pop {
  position: fixed; z-index: 60; max-height: 306px; overflow-y: auto; overscroll-behavior: contain;
  background: var(--panel); border: 2px solid var(--ph); border-radius: 4px;
  box-shadow: 0 0 0 2px var(--ink), 0 0 22px var(--ph-glow2);
}
.ov-mdl-pop[hidden] { display: none; }
.ov-mdl-group {
  position: sticky; top: 0; z-index: 1; color: var(--gold); font-size: 12px; letter-spacing: 1px;
  padding: 7px 10px 3px; background: var(--panel); border-bottom: 1px solid var(--ph-faint);
}
.ov-mdl-off { color: var(--warn); font-size: 11px; font-style: normal; letter-spacing: .4px; }
.ov-mdl-row {
  display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 10px; align-items: baseline;
  padding: 6px 10px; cursor: pointer; border-bottom: 1px solid var(--ph-faint);
}
.ov-mdl-row:last-child { border-bottom: 0; }
.ov-mdl-row.hi, .ov-mdl-row:hover { background: var(--ph-faint); }
.ov-mdl-row.sel { background: var(--ph); }
.ov-mdl-row.sel .ov-mdl-name, .ov-mdl-row.sel .ov-mdl-meta { color: var(--ink); text-shadow: none; }
.ov-mdl-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ph-bright); font-size: 15px; letter-spacing: .3px; }
.ov-mdl-meta { color: var(--ph-dim); font-size: 12px; letter-spacing: .3px; white-space: nowrap; }
.ov-mdl-none { color: var(--ph-dim); font-size: 13px; padding: 12px 10px; line-height: 1.3; }

.ov-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 22px; border-top: 1px solid var(--ph-faint); background: rgba(0,0,0,.32); flex-wrap: wrap; }
.ov-foot-data { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ov-foot-cap { color: var(--ph-dim); font-size: 12px; letter-spacing: .3px; }
.ov-actions { display: flex; align-items: center; gap: 12px; }

/* ===== RESUME / RECOVERY banner — shown when re-entering an existing station whose creds went missing.
   Phosphor-styled (gold inset rule + bloom), it reassures the Commander the agent is safe and locks the
   identity fields below so a resume can't silently re-spec the agent. ===== */
.ov-recovery {
  margin: 10px 22px 0; padding: 9px 14px; font-size: 16px; letter-spacing: .4px;
  color: var(--ph-bright); border: 1px solid var(--gold);
  border-left: 4px solid var(--gold); border-radius: 3px;
  background: rgba(var(--ph-rgb),.07); text-shadow: 0 0 6px var(--ph-glow2);
  box-shadow: inset 0 0 22px rgba(0,0,0,.5), 0 0 12px var(--ph-glow2);
}
.ov-recovery b { color: var(--gold); }

/* read-only identity fields in RESUME mode: visibly muted + inert, but kept in the DOM (onWake still reads
   the seeded values). The skin/voice/approval pickers are non-text containers, so block pointer events too. */
.field-locked { opacity: .42; filter: grayscale(.35); pointer-events: none; }
input.field-locked { opacity: .55; filter: none; cursor: not-allowed; background: #0a0805; }
#screen-connect.recovery .ov-leadtag { opacity: .5; }

/* footer-resident validation: sits BESIDE the WAKE button it explains */
.ov-actions .msg { margin: 0; text-align: right; max-width: 520px; }
.ov-actions .msg:empty { min-height: 0; }

/* the MORE reveal on the provider row — dashed, quieter than a real provider chip */
.prov-more {
  font-family: inherit; font-size: 14px; color: var(--ph-dim); background: none;
  border: 2px dashed var(--ph-faint); padding: 6px 12px; cursor: pointer;
  letter-spacing: 1px; text-transform: uppercase; line-height: 1;
}
.prov-more:hover { color: var(--ph); border-color: var(--ph-dim); }
.provider-row.collapsed .prov.tail { display: none; }

/* short displays (720p-class windows): tighten the vertical rhythm so all three columns land
   without the grid scrolling — the genesis screen should never need a scrollbar to see WAKE */
@media (max-height: 800px) {
  .ov-cfg { padding: 10px 18px 12px; }
  .ov-hero { padding: 10px 18px 12px; }
  .ov-field { margin-bottom: 9px; }
  .ov-step { margin-bottom: 7px; }
  .ov-pod { min-height: 148px; }
  .ov-np-name { font-size: 24px; }
  .ov-leadtag { margin-bottom: 8px; }
  .vp-quote { font-size: 15px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .ov-crewnote { display: none; }   /* the approval cards' own descriptions carry the meaning on short displays */
  .byok-note { line-height: 1.2; }
  .ov-brain { padding: 8px 10px; }
  .ov-crewnote, .ov-brain-lead { line-height: 1.2; }
  .ov-approve .ov-card { padding: 8px 11px 7px; }
  .ov-foot { padding: 8px 22px; }
  #screen-connect input[type=text], #screen-connect input[type=password], #screen-connect input:not([type]) { padding: 5px 10px; font-size: 18px; }
  .ov-vpreview, .ov-vtune { margin-top: 5px; }
  .ov-cfg label { margin: 6px 0 3px; }
}

@media (max-width: 1240px) {
  .ov-grid { grid-template-columns: minmax(320px, 400px) 1fr; grid-template-areas: "hero id" "brain brain"; }
  .ov-hero { border-bottom: 1px solid var(--ph-faint); }
  .ov-col-id { border-right: none; }
  .ov-col-brain { border-top: 1px solid var(--ph-faint); }
}
@media (max-width: 900px) {
  .ov-grid { grid-template-columns: 1fr; grid-template-areas: "hero" "id" "brain"; }
  .ov-hero { border-right: none; border-bottom: 1px solid var(--ph-faint); }
  .ov-col-brain { border-top: none; }
  .ov-cards { grid-template-columns: 1fr 1fr; }
}
.skin-picker {
  flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px;
  align-content: flex-start; max-height: 156px; overflow-y: auto; padding-right: 2px;
}
.skin-thumb {
  width: 44px; height: 44px; padding: 2px; cursor: pointer; border-radius: 5px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--ph) 6%, var(--panel2)), var(--panel2));
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.08), 0 1px 0 rgba(0,0,0,.35);
  border: 1px solid var(--ph-dim); display: flex; align-items: center; justify-content: center;
}
.skin-thumb img {
  width: 100%; height: 100%; object-fit: contain;
  image-rendering: pixelated; image-rendering: crisp-edges;
}
.skin-thumb:hover { border-color: var(--ph); background: var(--ph-faint); }
.skin-thumb.sel { border-color: var(--ph-bright); box-shadow: 0 0 10px var(--ph-glow); }

/* (deleted: the genesis .skin-stage/.skin-stage-frame preview — the ov-hero pod now uses .ov-stage/.ov-stage-frame;
   the Recruitment Bay's SUMMON preview is the separate mkt-skin-stage* in marketplace.css.) */
.skin-stage-name { color: var(--ph-bright); letter-spacing: 1px; font-size: 14px; text-align: center; }

/* NOTE: the Recruitment Bay's SUMMON skin bar (.mkt-skinbar / .mkt-skin-section / .mkt-skin-stage) is styled
   in marketplace.css — a self-contained bespoke picker with its own large wells + live SkinStage preview.
   The earlier orphan .mkt-skin-section rules that used to sit here (never emitted by any JS) were removed. */

/* (deleted: the archetype/arch-name card grid — genesis personality is the .ov-vchip chip row now; the live
   .voice-preview below is still used by renderVoicePreview.) */
.voice-preview {
  margin-top: 9px; border: 1px dashed var(--ph-dim); border-radius: 5px;
  padding: 8px 10px; background: rgba(0,0,0,.3);
}
.vp-quote { color: var(--ph-bright); font-size: 15px; line-height: 1.25; }
.vp-meta { color: var(--ph-dim); font-size: 12px; letter-spacing: .5px; margin-top: 4px; text-transform: uppercase; }

/* (deleted: the whole FINE-TUNE voice UI — voice-traits, the dial-row/dial-cell segments, voice-toggles,
   vtoggle and voice-custom. The voice fine-tune dials + free-text note were removed from genesis 2026-07-09;
   the archetype chip is the entire voice choice now. Resumed agents keep saved voiceTraits/customVoice.) */

/* ============================================================
   STATION HUD — top bar · crew manifest · bottom bar · panels.
   The phosphor/CRT chrome (#topbar/#left/#bottombar bezels, .bb,
   .term, .crew-*, .kb-*, .ag-*, .set-*, .nf, .perk-*) is reused
   verbatim from the v7 style.css already loaded above; this block
   only positions the game-screen grid and adds the few new bits.
   ============================================================ */
#topbar { grid-area: top; }
#left { grid-area: left; }
#stage-wrap { grid-area: center; position: relative; z-index: 0; }
#chat-panel { grid-area: chat; position: relative; z-index: 8; }
#bottombar { grid-area: bot; }

/* ---------- COMMS / stage divider: drag left to widen COMMS (chatresize.js) ----------
   A thin handle living in the 9px grid gap on the COMMS panel's left edge. Invisible until
   hovered/dragged, then a phosphor grip lights up so it reads as a real control. */
.col-resizer {
  position: absolute; top: 0; bottom: 0; left: -10px; width: 12px; z-index: 25;
  cursor: col-resize; display: flex; align-items: center; justify-content: center;
  touch-action: none;
}
.col-resizer-grip {
  width: 2px; height: 46px; border-radius: 2px; background: var(--ph-dim); opacity: 0;
  transition: opacity .12s, background .12s, box-shadow .12s;
}
.col-resizer:hover .col-resizer-grip,
body.col-resizing .col-resizer-grip {
  opacity: 1; background: var(--ph); box-shadow: 0 0 8px var(--ph-glow2);
}
/* while dragging: column-resize cursor everywhere + no text selection + canvas ignores the pointer */
body.col-resizing { cursor: col-resize; user-select: none; }
body.col-resizing #stage { pointer-events: none; }

/* the v7 screen-flicker animation targets #app (which this app doesn't
   have) — re-point it at the live station so the SETTINGS toggle works */
body:not(.no-flicker) #screen-game.active { animation: flick 7s infinite; }

/* top bar: reuse the v7 logo (#logo, .logo-*) and .tb-stat; subtitle fit */
#topbar .logo-sub { white-space: nowrap; }

/* CREW header — the same solid ink-on-phosphor bar COMMS (#chat-panel h3) and the
   SESSIONS rail head (.ws-head) wear; the old engraved-rule h3 read as leftover v7 chrome */
#left h3 {
  justify-content: space-between; align-items: baseline; flex-shrink: 0;
  color: var(--ink); background: var(--ph); padding: 4px 12px; letter-spacing: 2px;
  border-radius: 7px 7px 0 0;
}
#left h3::after { display: none; }   /* the global engraved-rule ::after doesn't belong on a solid bar */
#left h3 .h3-aux { color: var(--ink); opacity: .7; text-shadow: none; font-size: 12px; letter-spacing: 1px; order: 0; }   /* order reset: the global .h3-aux order:2 would shove the count past the ◂ button */
/* right cluster: agent count + the hide control, so space-between keeps them together */
.crew-h3-right { display: inline-flex; align-items: center; gap: 7px; }
/* ◂ hide — same ink-bordered button vocabulary as the SESSIONS head's + NEW */
.crew-hide {
  font-family: inherit; font-size: 12px; line-height: 1.2; color: var(--ink);
  background: transparent; border: 1px solid rgba(0,0,0,.45); border-radius: 3px;
  cursor: pointer; padding: 1px 6px;
}
.crew-hide:hover { background: rgba(0,0,0,.2); }
/* ▸ CREW restore — a slim phosphor drawer handle on the stage's left edge while the rail is hidden.
   Sits at z4, above the tube-face overlay (z2) and cam HUD (z3, pointer-events:none). */
.crew-show {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%); z-index: 4;
  writing-mode: vertical-rl; text-orientation: mixed;
  font-family: inherit; font-size: 12px; letter-spacing: 2px; color: var(--ph);
  background: rgba(5,3,1,.82); border: 1px solid var(--ph-dim); border-left: 0;
  border-radius: 0 5px 5px 0; padding: 10px 3px; cursor: pointer;
  text-shadow: 0 0 6px var(--ph-glow2);
  transition: color .12s, border-color .12s, box-shadow .12s;
}
.crew-show:hover { color: var(--ph-bright); border-color: var(--ph); box-shadow: 0 0 10px var(--ph-glow2); }
.crew-show[hidden] { display: none; }

/* crew manifest empty state */
.crew-empty { padding: 14px 10px; font-size: 13px; color: var(--ph-dim); }

/* bottom-bar right cluster status pill (honest activity light, not a number) */
#status-pill {
  background: linear-gradient(180deg, rgba(var(--ph-rgb),.07), rgba(0,0,0,.5));
  color: var(--ph); font-size: 14px; letter-spacing: 2px;
  padding: 2px 13px; border: 1px solid var(--ph); border-radius: 999px; text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 1px 0 rgba(var(--ph-rgb),.14), 0 0 12px var(--ph-glow2), inset 0 0 10px rgba(0,0,0,0.6);
}
#status-pill.working { color: var(--gold); border-color: var(--gold); box-shadow: 0 0 12px rgba(var(--gold-rgb),0.35); }
#status-pill.thinking { color: var(--ph-bright); }
/* E1: LINK DOWN — the pill can only read ONLINE while the sidecar bridge is actually up. When the
   link dies it flips to a red-phosphor OFFLINE, matching the canvas LINK DOWN marker (#ff6a4c) with
   a slow breathing pulse so it reads as a live fault, never a frozen label. */
#status-pill.down {
  color: var(--link-down); border-color: rgba(255,80,60,0.6);
  text-shadow: 0 0 6px rgba(255,80,60,0.9);
  box-shadow: 0 0 12px rgba(255,80,60,0.35), inset 0 0 10px rgba(0,0,0,0.6);
  animation: pill-down-breathe 2.2s ease-in-out infinite;
}
@keyframes pill-down-breathe { 0%,100% { opacity: 0.62; } 50% { opacity: 1; } }
/* STANDBY: the bridge isn't proven up yet — a dim, neutral pill (never the confident ONLINE green). */
#status-pill.standby {
  color: var(--ph-dim); border-color: var(--ph-dim);
  text-shadow: none; box-shadow: inset 0 0 10px rgba(0,0,0,0.6);
}

/* ============================================================
   GROUPED BOTTOM-BAR DOCKS (navdock.js) — the flat panel
   buttons folded into 4 labelled triggers (CREW/WORK/BUILD/SYSTEM),
   each opening an upward popover of its items. Kills the cryptic
   one-row glyph wall. Two DISTINCT trigger signals (never one
   overloaded dot): a gold underline = "a panel from this group is
   open"; the SYSTEM trigger's warn chip = the unread NOTIFS count.
   ============================================================ */
#bottombar { gap: 4px; }
.bb-group { position: relative; display: flex; align-items: center; }
.bb-grp {
  font-family: inherit; color: var(--ph); background: transparent;
  border: 1px solid var(--ph-faint); padding: 0 16px; cursor: pointer;
  letter-spacing: 2px; font-size: 16px; text-shadow: inherit;
  display: inline-flex; align-items: center; gap: 8px;
  /* FIXED trigger box: the four group glyphs render from different fallback fonts with
     different intrinsic heights, so line-height:normal made the buttons 32/33/35/33px tall
     and visibly misaligned. A hard height + line-height:1 pins every trigger to one box. */
  height: 32px; line-height: 1;
}
/* the trigger glyph in its own fixed cell so uneven glyph advance widths can't shove labels around */
.bb-gi { display: inline-block; width: 18px; text-align: center; flex: 0 0 auto; }
.bb-grp:hover { color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); }
.bb-group.open .bb-grp { color: var(--ink); background: var(--ph); border-color: var(--ph); text-shadow: none; }

/* "panel open here" = gold underline engraved into the trigger's bottom edge */
.bb-group.has-active .bb-grp { box-shadow: inset 0 -3px 0 var(--gold), 0 0 10px rgba(var(--gold-rgb),.25); }
.bb-group.open.has-active .bb-grp { box-shadow: inset 0 -3px 0 var(--ink); }

/* unread NOTIFS count mirrored onto the SYSTEM trigger (navdock.syncGroupState) */
.bb-grp-badge {
  min-width: 16px; padding: 0 4px; border-radius: 8px; flex: 0 0 auto;
  font-size: 11px; line-height: 15px; letter-spacing: 0; text-align: center;
  color: var(--ink); background: var(--warn); text-shadow: none;
  box-shadow: 0 0 8px var(--warn); animation: bb-alert 1.4s ease-in-out infinite;
}
.bb-group.open .bb-grp-badge { animation: none; box-shadow: none; }
@keyframes bb-alert { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

/* the popover: opens UPWARD from the trigger, styled as a small CRT panel.
   Items are TWO-LINE (.bb-i glyph cell · .bb-tx name + dim description) so the menu
   explains each destination instead of listing bare nouns. */
.bb-menu {
  display: none; position: absolute; left: 0; bottom: calc(100% + 7px); z-index: 60;
  min-width: 300px; flex-direction: column; gap: 2px; padding: 6px;
  background: rgba(4,2,1,.98); border: 2px solid var(--ph); border-radius: 7px;
  box-shadow: 0 0 0 3px rgba(0,0,0,.9), 0 -6px 26px rgba(0,0,0,.75), 0 0 20px var(--ph-glow2);
}
.bb-group.open .bb-menu { display: flex; }
.bb-menu-h {
  padding: 5px 10px 7px; margin-bottom: 3px;
  font-size: 12px; letter-spacing: 2px; color: var(--ph-dim);
  border-bottom: 1px solid var(--ph-faint); white-space: nowrap;
}
.bb-menu .bb {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  border: 1px solid transparent; padding: 6px 10px; font-size: 15px; letter-spacing: 1.5px;
}
.bb-menu .bb .bb-i { flex: 0 0 20px; width: 20px; text-align: center; font-size: 15px; }
.bb-menu .bb .bb-tx { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.bb-menu .bb .bb-tx b { font-weight: inherit; font-size: 15px; letter-spacing: 1.5px; }
.bb-menu .bb .bb-tx small {
  font-size: 12px; letter-spacing: .4px; color: var(--ph-dim); text-shadow: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bb-menu .bb:hover { background: var(--ph-faint); color: var(--ph-bright); border-color: var(--ph-dim); }
.bb-menu .bb:hover .bb-tx small, .bb-menu .bb:focus-visible .bb-tx small { color: var(--ph); }
.bb-menu .bb:hover::before, .bb-menu .bb:hover::after { content: none; }  /* no pip-boy [..] brackets inside the menu */
.bb-menu .bb.active { background: var(--ph-faint); color: var(--ph-bright); box-shadow: inset 0 0 0 2px var(--ph); }

/* one-time "what now" coach pointing at the new docks */
.nav-coach {
  position: fixed; left: 14px; bottom: 58px; z-index: 70; max-width: 470px;
  display: flex; align-items: center; gap: 12px; padding: 9px 13px;
  font-size: 14px; color: var(--text); letter-spacing: .4px; line-height: 1.35;
  background: rgba(4,2,1,.97); border: 2px solid var(--ph); border-radius: 7px;
  box-shadow: 0 0 0 3px rgba(0,0,0,.9), 0 6px 24px rgba(0,0,0,.7), 0 0 20px var(--ph-glow2);
  animation: coach-in .35s ease-out;
}
.nav-coach[hidden] { display: none; }
.nav-coach b { color: var(--ph-bright); font-weight: normal; }
.nav-coach-x {
  flex: 0 0 auto; font-family: inherit; font-size: 12px; letter-spacing: 1px; cursor: pointer;
  color: var(--ink); background: var(--ph); border: none; border-radius: 3px; padding: 4px 10px;
}
.nav-coach-x:hover { background: var(--ph-bright); }
.nav-coach-arrow { position: absolute; left: 32px; bottom: -15px; color: var(--ph); font-size: 17px; text-shadow: 0 0 7px var(--ph-glow); }
@keyframes coach-in { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }

/* TASK BOARD — add-row + per-card actions (new controls over v7 .kb-* cards) */
.kb-add { display: flex; gap: 8px; margin-bottom: 10px; }
.kb-add input { flex: 1; font-size: 15px; padding: 5px 8px; }
.kb-acts { display: flex; gap: 5px; margin-top: 5px; flex-wrap: wrap; }
.kb-acts button {
  font-family: inherit; background: transparent; color: var(--ph-dim);
  border: 1px solid var(--ph-faint); cursor: pointer; font-size: 12px; padding: 1px 7px; letter-spacing: 1px;
}
.kb-acts button:hover { color: var(--ph-bright); border-color: var(--ph); background: var(--ph-faint); }
.kb-acts .assign { color: var(--gold); border-color: var(--ph-dim); }
/* empty-state wrapper: NO dimming — the .empty-state component (glyph + copy + CTA) is already designed at the
   right strength; the old opacity:0.4 ghosted even the + ADD ONE call-to-action. */
.kb-empty-col { padding: 6px 2px; }
/* bound-agent chip on a board card — a colored dot (the agent's roster color) + its name. Truthful telemetry:
   sourced from the stream's real agentId resolved against the live roster. */
.kb-agent { display: inline-flex; align-items: center; gap: 4px; color: var(--ph); }
.kb-agent-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; box-shadow: 0 0 5px currentColor; }
.kb-deliv { color: var(--gold); }
/* IN-PROGRESS run-state chip — truthful: RUNNING only while Channels.isBusy, else DONE — REVIEW & SHIP.
   Reuses the rail's live pulse (.ws-dot.running / @keyframes wsPulse) so the world speaks one visual language. */
.kb-state { display: flex; align-items: center; gap: 5px; margin-top: 4px; font-size: 11px; letter-spacing: 1px; }
.kb-state.running { color: var(--ph-bright); }
.kb-state.done { color: var(--gold); }
.kb-live { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--ph-bright); animation: wsPulse 1.15s ease-in-out infinite; }

/* SKILLS — honest capability readout (reuses v7 .perk-grid/.perk) */
.term.skills-term { max-height: calc(100vh - 96px); }
.term.skills-term .term-body { flex: 1 1 auto; min-height: 0; }
.sk-note { font-size: 12px; opacity: 0.62; margin-top: 12px; line-height: 1.45; }
/* the locked status line ("○ NO CABINET AT DESK") reads at --ph, not --ph-dim: at the perk's 0.65 opacity a dim
   grey vanished — this is the honest "why it's off", it has to be readable. */
.perk-stat { font-size: 10px; color: var(--ph); margin-top: 2px; letter-spacing: 1px; }
.perk.on .perk-stat { color: var(--ok); }
.perk.on .perk-stat.ask { color: var(--warn); }   /* granted, but pauses for one-click consent */
/* a locked capability card is a live deep-link into REFIT to place its missing prop — show it, and surface the
   affordance so the click is discoverable (it brightens on hover). */
.perk-locked { cursor: pointer; transition: opacity var(--t-fast, .12s) ease, border-color var(--t-fast, .12s) ease; }
.perk-locked:hover, .perk-locked:focus-visible { opacity: 0.9; outline: none; border-color: var(--ph-dim); }
.perk-place { font-size: 10px; color: var(--gold); letter-spacing: 1px; margin-top: 3px; opacity: 0.72; transition: opacity var(--t-fast, .12s) ease; }
.perk-locked:hover .perk-place, .perk-locked:focus-visible .perk-place { opacity: 1; }

/* SKILL LIBRARY — pre-installed, capability-gated recipe packs (the browser in the SKILLS panel) */
.sk-lib-intro { margin-top: 4px; }
.sk-lib { margin-top: 8px; }
.sk-loading { font-size: 12px; opacity: 0.6; padding: 10px 2px; }
.sk-lib-sum { font-size: 11px; letter-spacing: 0.5px; color: var(--ph-dim); margin: 2px 0 8px; }
.sk-lib-sum b { color: var(--ok); }
.sk-cat { font-size: 10px; letter-spacing: 2px; color: var(--gold); opacity: 0.85; margin: 13px 0 5px; text-transform: uppercase; }
.sk-card { border: 1px solid var(--ph-faint); border-radius: var(--r-sm); margin-bottom: 6px; background: var(--panel2); box-shadow: var(--raise); overflow: hidden; transition: border-color 0.15s; }
.sk-card.on { border-color: var(--ph-dim); box-shadow: var(--raise), inset 0 0 14px var(--ph-glow2); }
.sk-card.want { border-color: var(--warn); }
.sk-card-head { display: flex; align-items: flex-start; gap: 9px; padding: 8px 9px; }
.sk-toggle { flex: 0 0 auto; width: 26px; height: 26px; border: 1px solid var(--ph-dim); border-radius: 50%; background: transparent; color: var(--ph-dim); font-size: 15px; cursor: pointer; line-height: 1; padding: 0; transition: all 0.15s; }
.sk-card.on .sk-toggle { color: var(--ok); border-color: var(--ok); box-shadow: 0 0 8px var(--ph-glow2); }
.sk-card.want .sk-toggle { color: var(--warn); border-color: var(--warn); }
.sk-toggle:hover { background: var(--ph-faint); }
.sk-toggle.busy { opacity: 0.4; pointer-events: none; }
.sk-card-main { flex: 1 1 auto; min-width: 0; }
.sk-name-row { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.sk-name { font-size: 13px; color: var(--ph-bright); }   /* emphasis via bright phosphor, not synthesized bold (VT323 is single-weight) */
.sk-reqs { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.sk-badge { font-size: 10px; letter-spacing: 0.5px; padding: 1px 5px; border-radius: 2px; border: 1px solid var(--ph-faint); color: var(--ph-dim); white-space: nowrap; }
.sk-badge.have { color: var(--ok); border-color: var(--ok); }
.sk-badge.miss { color: var(--warn); border-color: var(--warn); }
.sk-badge.free { opacity: 0.5; }
.sk-badge.cat { color: var(--ph); border-color: var(--ph-dim); opacity: 0.85; }   /* A4: category tag (also makes category searchable) */
.sk-desc { font-size: 11.5px; opacity: 0.78; margin-top: 3px; line-height: 1.4; }
.sk-stat { font-size: 10.5px; letter-spacing: 1px; margin-top: 5px; color: var(--ph-dim); }
.sk-stat.on { color: var(--ok); }
.sk-stat.want { color: var(--warn); }
.sk-expand { flex: 0 0 auto; background: transparent; border: none; color: var(--ph-dim); font-size: 14px; cursor: pointer; padding: 2px 4px; line-height: 1; }
.sk-expand:hover { color: var(--gold); }
.sk-body { display: none; border-top: 1px solid var(--ph-faint); padding: 8px 10px; background: rgba(0, 0, 0, 0.25); }
.sk-card.open .sk-body { display: block; }
.sk-body pre { white-space: pre-wrap; word-wrap: break-word; font-size: 11px; line-height: 1.45; color: var(--text); opacity: 0.92; margin: 0; font-family: inherit; max-height: 340px; overflow-y: auto; }
.sk-attr { font-size: 10.5px; opacity: 0.5; margin-top: 8px; font-style: italic; }

/* SKILLS redesign (legibility) — a real ON/OFF pill SWITCH (the user's choice) + a SEPARATE readiness chip (the
   floor's grant), so the two axes never collapse into one ambiguous string. State sections group the library by
   READY / NEEDS GEAR / OFF; the PLACE button deep-links a locked card's missing gear into the real REFIT surface. */
/* the one-line mental-model strip at the top of CAPABILITIES: the causal chain, in the panel's eerie sk-note voice. */
.sk-chain { font-size: 10px; letter-spacing: 2px; color: var(--ph-dim); opacity: 0.8; margin: 0 0 10px; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.sk-chain-arr { color: var(--gold); opacity: 0.7; }
.sec.sk-state-sec { margin-top: 12px; }
.sec.sk-state-sec:first-child { margin-top: 4px; }
/* the pill switch — unmistakably a control, not a status dot. Track slides a knob; the ON/OFF word is the label. */
.sk-switch { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; background: transparent; border: none; padding: 2px 0; cursor: pointer; line-height: 1; }
.sk-sw-track { position: relative; width: 30px; height: 16px; border-radius: 9px; border: 1px solid var(--ph-dim); background: rgba(0,0,0,0.3); transition: all 0.15s; }
.sk-sw-knob { position: absolute; top: 1px; left: 1px; width: 12px; height: 12px; border-radius: 50%; background: var(--ph-dim); transition: all 0.15s; }
.sk-switch.on .sk-sw-track { border-color: var(--ok); box-shadow: 0 0 8px var(--ph-glow2); }
.sk-switch.on .sk-sw-knob { left: 15px; background: var(--ok); }
.sk-sw-label { font-size: 10px; letter-spacing: 1.5px; color: var(--ph-dim); min-width: 20px; }
.sk-switch.on .sk-sw-label { color: var(--ok); }
.sk-switch:hover .sk-sw-track { border-color: var(--ph); }
.sk-switch.busy { opacity: 0.4; pointer-events: none; }
/* readiness chip — the floor's grant, held apart from the switch. READY = green, NEEDS <GEAR> = amber. */
.sk-ready { font-size: 10px; letter-spacing: 1px; padding: 1px 6px; border-radius: 2px; border: 1px solid var(--ph-faint); color: var(--ph-dim); white-space: nowrap; }
.sk-ready.ok { color: var(--ok); border-color: var(--ok); }
.sk-ready.gear { color: var(--warn); border-color: var(--warn); }
/* PLACE button — lands the user in the real REFIT placement surface for the missing object. */
.sk-place-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.sk-place { font-size: 10.5px; letter-spacing: 0.5px; padding: 3px 8px; border-radius: var(--r-sm); border: 1px solid var(--warn); background: transparent; color: var(--warn); cursor: pointer; transition: all 0.15s; }
.sk-place:hover { background: var(--warn); color: var(--bg, #000); box-shadow: 0 0 8px var(--warn); }
.sk-reqs { margin-top: 5px; }

/* CONNECTIONS — PROVIDERS + API KEYS sections inside the SETTINGS panel.
   Real BYOK state: a green dot/glow means actually connected; dim cards are
   honestly-locked "coming soon" transports (same treatment as locked SKILLS). */
.prov-list, .key-list { display: flex; flex-direction: column; gap: 6px; }
.prov-card, .key-row {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--ph-dim); background: rgba(0, 0, 0, 0.3); padding: 7px 10px;
  border-radius: var(--r-sm); box-shadow: var(--raise);
}
.prov-card.soon { opacity: 0.45; border-color: var(--ph-faint); }          /* not-yet-shipped: fully locked */
.prov-card.avail { opacity: 0.8; border-color: var(--ph-dim); }            /* live but keyless: actionable, not locked */
.prov-card.conn { box-shadow: var(--raise), inset 0 0 12px var(--ph-glow2); }
.conn-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ph-dim); flex: none; }
.prov-card.conn .conn-dot, .key-row .conn-dot { background: var(--ok); box-shadow: 0 0 8px rgba(123, 200, 138, 0.7); }
.prov-main, .key-main { flex: 1; min-width: 0; }
.prov-name { font-size: 14px; color: var(--ph-bright); letter-spacing: 1px; display: flex; align-items: center; gap: 8px; }
.prov-badge, .key-stat.on {
  font-size: 10px; letter-spacing: 1px; color: var(--ink); background: var(--gold);
  padding: 0 5px; text-shadow: none;
}
.prov-ep { font-size: 11px; color: var(--ph-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prov-stat { font-size: 11px; color: var(--ph); text-align: right; letter-spacing: 1px; white-space: nowrap; }
.prov-card.soon .prov-stat { color: var(--ph-dim); }                       /* locked: muted */
.prov-card.avail .prov-stat { color: var(--gold); }                        /* "NO KEY" is an action prompt, not a disabled state */
.prov-stat i { display: block; font-style: normal; color: var(--ph-dim); font-size: 10px; }

.key-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.key-prov { font-size: 12px; color: var(--ph); letter-spacing: 1px; }
.key-mask {
  font-family: inherit; font-size: 13px; color: var(--ph-bright); letter-spacing: 1px;
  background: rgba(0, 0, 0, 0.4); border: 1px solid var(--ph-faint); padding: 0 6px;
}
.key-meta { font-size: 11px; color: var(--ph-dim); margin-top: 2px; }
.key-meta b { color: var(--ph); font-weight: normal; }
.key-stat { font-size: 11px; color: var(--ph-dim); letter-spacing: 1px; }
.key-acts { display: flex; flex-direction: column; gap: 4px; flex: none; }
.key-edit { display: flex; gap: 6px; margin-top: 4px; }
.key-edit[hidden] { display: none; }
.key-input { flex: 1; font-size: 13px; padding: 4px 8px; }
.key-empty { font-size: 13px; color: var(--ph); padding: 4px 2px; display: flex; flex-direction: column; gap: 6px; }
.key-empty p { margin: 0; font-size: 12px; color: var(--text); opacity: 0.75; }

/* settings-truth: a KNOWN-dead ChatGPT sign-in (the sidecar recorded a consumed/invalid refresh token).
   --bad is the sole semantic red; the card/row must read as a fault demanding RECONNECT, never as SIGNED IN. */
.prov-card.expired { opacity: 1; border-color: var(--bad); }
.prov-card.expired .prov-stat { color: var(--bad); }
.prov-card.expired .conn-dot, .key-row.expired .conn-dot { background: var(--bad); box-shadow: 0 0 8px rgba(200, 90, 80, 0.7); }
.key-stat.bad { color: var(--bad); }
.key-mask.key-mask-dead { color: var(--bad); border-color: var(--bad); }
.key-edit.codex-inline { flex-wrap: wrap; align-items: center; font-size: 12px; }
.key-edit.codex-inline code { font-size: 15px; letter-spacing: 2px; }

/* ============================================================
   CANONICAL DANGER-ARMED SKIN — the ONE "click again to confirm" look.
   Every destructive arm/confirm button inverts to a filled --bad chip
   (ink on red). --bad stays the sole semantic red so it reads correctly
   in every theme. !important so the armed state always wins over the
   button's resting/hover skin regardless of source file. The gold
   consent-armed (.mkt-cta*) and the .bb.danger.armed pulse animation
   (motion.css) are intentionally separate; per-button extras (the
   .ws-menu glyph tint, .ag-del glow, .q-dismiss padding) sit below.
   ============================================================ */
.mkt-del.armed, .mkt-recipe-del.armed, .mkt-fam-forget.armed,
.bb.sm.danger.armed, .ws-menu-item.danger.armed, .ag-del.armed, .q-dismiss.armed,
.mkt-del.armed:hover, .mkt-recipe-del.armed:hover, .mkt-fam-forget.armed:hover,
.bb.sm.danger.armed:hover, .ws-menu-item.danger.armed:hover, .ag-del.armed:hover, .q-dismiss.armed:hover {
  color: var(--ink) !important; background: var(--bad) !important;
  border-color: var(--bad) !important; text-shadow: none !important;
}
.key-row.rm-armed { border-color: var(--bad); box-shadow: var(--raise), inset 0 0 0 1px var(--bad); }
.key-row.rm-armed .key-main { opacity: 0.72; }
.rm-hint { font-size: 10px; letter-spacing: 1px; color: var(--bad); text-align: right; margin-top: 2px; }

/* settings-truth: inline "+ ADD KEY" on a NO-KEY provider card — a collapsible paste-and-save row that reuses the
   same Harness.setKey path as the key list, so a beginner never hunts for where keys live. The card wraps so the
   editor sits on its own full-width line below the name/status; gold accent = actionable, matching "NO KEY". */
.prov-card { flex-wrap: wrap; }
.prov-addkey { margin-top: 4px; margin-left: 12px; }  /* breathing room between the status text and the inline action */
.prov-key-edit { flex-basis: 100%; margin-top: 6px; }
.prov-key-edit[hidden] { display: none; }

/* settings-truth: per-field source badge (BUDGET) — is this limit a value you SAVED here, or the environment default
   it currently follows? Honest, non-blocking. Env default is a neutral gold-inset chip (it is NOT "ignored" — env is
   the fallback, and a saved value always wins); a saved value reads calmer. Never a literal amber — --gold-rgb only. */
.src-badge {
  font-size: 10px; letter-spacing: 1px; text-transform: uppercase; padding: 0 5px; border-radius: 2px;
  border: 1px solid var(--ph-faint); color: var(--ph-dim); vertical-align: middle; white-space: nowrap;
}
.src-badge[hidden] { display: none; }
.src-badge.src-env { color: var(--gold); border-color: rgba(var(--gold-rgb), .55); background: rgba(var(--gold-rgb), .06); }
.src-badge.src-saved { color: var(--ph); border-color: var(--ph-faint); background: rgba(0, 0, 0, .25); }

/* ---------- WORKSTREAMS rail (left) ---------- */
#ws-wrap { margin-top: 12px; display: flex; flex-direction: column; min-height: 0; }
.ws-head {
  display: flex; align-items: center; justify-content: space-between;
  color: var(--ink); background: var(--ph); padding: 3px 10px; letter-spacing: 1px;
  font-size: 14px; border-radius: 6px 6px 0 0;
}
#ws-new {
  font-family: inherit; font-size: 12px; letter-spacing: 1px; color: var(--ink);
  background: transparent; border: 1px solid rgba(0,0,0,.45); cursor: pointer; padding: 0 6px;
}
#ws-new:hover { background: rgba(0,0,0,.2); }
/* RAIL SEARCH — search lives ON the rail (the SESSION TOOLS window is retired; its .ws-tools-* CSS is
   gone with it). type=search misses the base themed-input rule (which covers text/password/untyped
   only), so without this skin the input renders as a raw white browser default in the middle of the
   phosphor rail. Compact to sit between the SESSIONS head and the session rows. */
.ws-rail-search { padding: 5px 0 0; }
#ws-search {
  -webkit-appearance: none; appearance: none;
  box-sizing: border-box; width: 100%; min-width: 0;
  font: inherit; font-size: 13px; letter-spacing: 1px; color: var(--ph-bright);
  background: linear-gradient(180deg, #000, color-mix(in srgb, var(--ph) 3%, #000));
  border: 1px solid var(--ph-dim); border-radius: 3px; padding: 4px 8px; outline: none;
  text-shadow: 0 0 5px var(--ph-glow2);
  box-shadow: inset 0 2px 6px rgba(0,0,0,.7);
  transition: border-color .12s, box-shadow .12s;
}
/* id selector outranks the global input:focus rule, so restate the full focus shadow here */
#ws-search:focus { border-color: var(--ph); box-shadow: inset 0 2px 6px rgba(0,0,0,.7), 0 0 10px var(--ph-glow2); }
#ws-search::placeholder { color: var(--ph-dim); opacity: 1; }
#ws-search::-webkit-search-cancel-button { -webkit-appearance: none; }  /* Esc clears; the gray UA ✕ breaks the CRT look */
#ws-search-results { list-style: none; margin: 0; padding: 0; max-height: 150px; overflow-y: auto; }
#ws-search-results:empty { display: none; }
.ws-search-hit { display: flex; flex-direction: column; gap: 1px; padding: 4px 7px; cursor: pointer; border-left: 2px solid var(--ph-dim); }
.ws-search-hit:hover, .ws-search-hit:focus { color: var(--ph); background: var(--ph-faint); border-left-color: var(--ph); outline: 0; }
.ws-search-hit b { color: var(--ph); font-weight: normal; }
.ws-search-hit small { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* Diagnostics on-screen report block (Settings → SYSTEM, clipboard-failure fallback): the raw <pre>
   and its button bar previously rendered with browser defaults. Same well + border language as the
   other settings panels; buttons are the shared .bb.sm skin. */
.diag-block { margin-top: 8px; }
.diag-pre { font-family: inherit; font-size: 11px; line-height: 1.4; color: var(--ph); margin: 0;
  padding: 8px 10px; border: 1px solid var(--ph-dim); border-radius: 2px; background: rgba(0,0,0,.25); }
.diag-block-bar { display: flex; gap: 8px; margin-top: 6px; }
#workstreams {
  list-style: none; margin: 0; padding: 6px 0 0; overflow-y: auto; max-height: 40vh;
  display: flex; flex-direction: column; gap: 4px;
}
/* display:flex above beats the UA [hidden] rule — without this, the PROJECTS tab couldn't actually
   hide the sessions list (both lists rendered stacked, so PROJECTS "showed the same sessions"). */
#workstreams[hidden] { display: none; }
.ws-row {
  display: flex; align-items: center; gap: 8px; padding: 5px 8px; cursor: pointer;
  border-left: 2px solid var(--ph-dim); background: rgba(0,0,0,.28);
}
.ws-row:hover { background: var(--ph-faint); border-left-color: var(--ph); }
.ws-row.sel { border-left-color: var(--ph-bright); background: var(--ph-faint); }
.ws-row.busy { border-left-color: var(--ph-bright); }
.ws-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--ph-dim); }
.ws-dot.lane-active { background: var(--ph-bright); box-shadow: 0 0 6px var(--ph-glow); }
.ws-dot.lane-shipped { background: var(--gold); }
/* LIVE: a run is in flight on this stream (phosphor pulse), or it is paused awaiting your approval (gold pulse) */
.ws-dot.running { background: var(--ph-bright); animation: wsPulse 1.15s ease-in-out infinite; }
.ws-dot.attn { background: var(--gold); animation: wsPulse 1.15s ease-in-out infinite; }
/* an idle-built deliverable awaiting review — gold, steady (a decision owed, not a live run) */
.ws-dot.review { background: var(--gold); box-shadow: 0 0 7px rgba(var(--gold-rgb), .6); }
.ws-dot.review ~ .ws-meta { color: var(--gold); letter-spacing: .5px; text-shadow: 0 0 6px rgba(var(--gold-rgb), .45); }
@keyframes wsPulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 7px var(--ph-glow); }
  50% { opacity: .3; box-shadow: 0 0 2px var(--ph-glow); }
}
.ws-title { flex: 1; min-width: 0; font-size: 14px; color: var(--ph); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-row.sel .ws-title { color: var(--ph-bright); }
/* UNREAD: the stream did real work since the Commander last had it open (lastActiveAt > lastReadAt) —
   a small gold spark beside the meta + a lit title. Clears the moment the row is opened. */
.ws-unread { display: none; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 6px rgba(var(--gold-rgb), .55); }
.ws-row.unread .ws-unread { display: inline-block; }
.ws-row.unread .ws-title { color: var(--ph-bright); }
/* compact right-edge meta: live elapsed while busy (bright / gold when it needs you), a dim "last worked" stamp when idle */
.ws-meta { flex: 0 0 auto; font-size: 11px; line-height: 1; color: var(--ph-dim); letter-spacing: .3px; font-variant-numeric: tabular-nums; }
.ws-meta:empty { display: none; }
.ws-row.busy .ws-meta { color: var(--ph-bright); }
.ws-row.attn .ws-meta { color: var(--gold); }

/* ---- SESSIONS ↔ PROJECTS view toggle (NS-5c): a segmented control in the rail head, ink-on-phosphor ---- */
.ws-view { display: inline-flex; align-items: center; gap: 0; }
.ws-tab {
  font-family: inherit; font-size: 12px; letter-spacing: 1px; color: var(--ink);
  background: transparent; border: 1px solid rgba(0,0,0,.45); cursor: pointer; padding: 1px 8px;
  opacity: .55;
}
.ws-tab:first-child { border-radius: 3px 0 0 3px; border-right-width: 0; }
.ws-tab:last-child { border-radius: 0 3px 3px 0; }
.ws-tab:hover { background: rgba(0,0,0,.2); opacity: .8; }
.ws-tab.on { background: rgba(0,0,0,.34); opacity: 1; }
#ws-addproject {
  font-family: inherit; font-size: 12px; letter-spacing: 1px; color: var(--ink);
  background: transparent; border: 1px solid rgba(0,0,0,.45); cursor: pointer; padding: 0 6px;
}
#ws-addproject:hover { background: rgba(0,0,0,.2); }
#ws-addproject[hidden] { display: none; }

/* the PROJECTS list reuses the SESSIONS rail row vocabulary (.ws-row / .ws-dot / .ws-title / .ws-meta /
   .ws-kebab) but each project is a TWO-LINE card: name line + the honest path line (the path used to hide
   in a tooltip, which read as a bare, cheap row). Sessions preview as an indented phosphor thread. */
#projects {
  list-style: none; margin: 0; padding: 6px 0 0; overflow-y: auto; max-height: 40vh;
  display: flex; flex-direction: column; gap: 0;
}
#projects[hidden] { display: none; }
.ws-row.proj-row { align-items: flex-start; padding: 6px 8px 7px; margin-top: 5px; }
#projects > .proj-row:first-child { margin-top: 0; }
.proj-row > .ws-dot { margin-top: 5px; }
.proj-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.proj-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* line 2 — the full folder path, always visible (LTR ellipsis: the parent dirs are the distinctive part;
   the tail is already the row's name). A dim "N sessions" count sits at its right edge. */
.proj-path {
  flex: 1 1 auto; min-width: 0; font-size: 10px; letter-spacing: .3px; color: var(--ph-dim); opacity: .8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.proj-sess-n { flex: 0 0 auto; font-size: 10px; letter-spacing: .5px; color: var(--ph-dim); }
/* the dot doubles as a git badge: a blessed git repo glows phosphor; a plain blessed folder is a soft dim dot */
.ws-dot.proj-git { background: var(--ph-bright); box-shadow: 0 0 6px var(--ph-glow); }
.ws-dot.proj-plain { background: var(--ph-dim); }
/* REVOKED (blessed:false) — truthful telemetry: the remembered root is shown, not hidden, and reads as un-trusted */
.ws-row.proj-revoked { opacity: .5; }
.ws-row.proj-revoked .ws-dot { background: var(--ph-dim); box-shadow: none; }
.ws-row.proj-revoked:hover { opacity: .85; }
.proj-tag {
  flex: 0 0 auto; font-size: 10px; letter-spacing: 1px; color: var(--warn);
  border: 1px solid currentColor; border-radius: 2px; padding: 0 3px; line-height: 1.3;
}
.proj-git-badge {
  flex: 0 0 auto; font-size: 9px; letter-spacing: 1px; text-transform: uppercase; line-height: 1.5;
  color: var(--ph); border: 1px solid var(--ph-faint); border-radius: 2px; padding: 0 4px;
  background: rgba(0,0,0,.25);
}
/* Hermes-parity drill-in: breadcrumb back-row + entered-project header + full session rows */
.proj-crumb { padding: 0 0 3px; }
.proj-back {
  font-family: inherit; font-size: 11px; letter-spacing: 1px; color: var(--ph-dim);
  background: transparent; border: 0; cursor: pointer; padding: 2px 7px; border-radius: 3px;
}
.proj-back:hover { color: var(--ph); background: var(--ph-faint); }
.ws-row.proj-head {
  margin-top: 0; cursor: default; padding: 7px 8px 8px;
  background: linear-gradient(180deg, rgba(0,0,0,.4), rgba(0,0,0,.22)); border-left: 2px solid var(--ph);
}
.ws-row.proj-head .ws-title { color: var(--ph-bright); letter-spacing: .5px; text-shadow: 0 0 6px var(--ph-glow2); }
/* full session rows inside an entered project: indented, otherwise the sessions rail's own vocabulary.
   These rows carry no ⋯ button, so the shared hover rule (meta hides to yield the kebab's slot) would
   just blank the time stamp — keep it visible here. */
.ws-row.proj-sess-full { margin-left: 14px; margin-top: 4px; }
.ws-row.proj-sess-full:hover .ws-meta, .ws-row.proj-sess-full:focus-within .ws-meta { display: block; }
/* sessions attached to a project — an indented thread under the card (the REAL w.projectRoot link);
   a faint left rule replaces the old '└' glyph. */
.proj-sess {
  display: flex; align-items: center; gap: 6px; margin-left: 16px; padding: 2px 8px 2px 10px;
  cursor: pointer; font-size: 12px; color: var(--ph-dim); border-left: 1px solid var(--ph-faint);
}
.proj-sess:hover { color: var(--ph); background: var(--ph-faint); border-left-color: var(--ph-dim); }
.proj-sess.on { color: var(--ph); border-left-color: var(--ph); }
.proj-sess .ws-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: inherit; }
.proj-sess .ws-meta { flex: 0 0 auto; font-size: 10px; }
/* the ">3 previews" overflow row — entering the project shows the rest */
.proj-sess.proj-more { font-size: 10px; letter-spacing: 1px; }
/* the empty states + the inline "add a folder" editor card */
.proj-empty { padding: 10px 8px; }   /* dim grade + size via the grouped empty rule (motion.css) */
.proj-empty-hero { text-align: center; padding: 18px 10px 16px; }
.proj-empty-hero .pe-glyph { display: block; font-size: 20px; opacity: .55; margin-bottom: 6px; text-shadow: 0 0 8px var(--ph-glow2); }
.proj-empty-hero b { display: block; font-weight: normal; color: var(--ph); font-size: 13px; letter-spacing: 1px; margin-bottom: 3px; }
.proj-empty-hero span { display: block; font-size: 11px; line-height: 1.45; }
/* gold accent = actionable (the settings vocabulary): blessing a folder is a trust decision.
   Layout: label + ✕ head row, full-width path input, then BROWSE… ↔ ADD button row — never a
   single crammed line, and no emoji glyphs (CRT chrome is text-only). */
.proj-add {
  display: flex; flex-direction: column; gap: 6px; padding: 8px 9px 9px; margin-bottom: 6px;
  background: rgba(var(--gold-rgb), .05); border-left: 2px solid var(--gold); border-radius: 0 3px 3px 0;
}
.proj-add-head { display: flex; align-items: center; justify-content: space-between; }
.proj-add-lbl { font-size: 10px; letter-spacing: 1.5px; color: var(--gold); opacity: .9; }
.proj-add-row { display: flex; gap: 8px; align-items: center; justify-content: space-between; }
.proj-add input {
  width: 100%; box-sizing: border-box; min-width: 0; font-family: inherit; font-size: 13px; color: var(--ph-bright);
  background: linear-gradient(180deg, #000, color-mix(in srgb, var(--ph) 3%, #000));
  border: 1px solid var(--ph-dim); outline: none; padding: 5px 8px; border-radius: 3px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,.7);
}
.proj-add input:focus { border-color: var(--ph); box-shadow: inset 0 2px 6px rgba(0,0,0,.7), 0 0 10px var(--ph-glow2); }
.proj-add input::placeholder { color: var(--ph-dim); opacity: .7; }
.proj-add button {
  font-family: inherit; font-size: 11px; letter-spacing: 1px; color: var(--ph);
  background: transparent; border: 1px solid var(--ph-dim); cursor: pointer; padding: 3px 10px; border-radius: 3px;
}
.proj-add button:hover { border-color: var(--ph); color: var(--ph-bright); }
/* ADD = the primary action, in the card's own gold voice */
.proj-add button.proj-add-go {
  color: var(--gold); border-color: rgba(var(--gold-rgb), .55); background: rgba(var(--gold-rgb), .06);
}
.proj-add button.proj-add-go:hover { color: var(--gold); border-color: var(--gold); box-shadow: 0 0 8px rgba(var(--gold-rgb), .35); }
/* the head ✕ is a quiet bare glyph, not a boxed button */
.proj-add button.proj-add-cancel { border: 0; padding: 0 2px; font-size: 11px; color: var(--ph-dim); }
.proj-add button.proj-add-cancel:hover { color: var(--ph-bright); }
.proj-add-hint { font-size: 11px; color: var(--ph-dim); line-height: 1.3; }
.proj-add-hint.err { color: var(--warn); }

/* ---- session row actions: pin marker · hover ⋯ · archived state · in-place rename ---- */
.ws-head-acts { display: inline-flex; align-items: center; gap: 6px; }
/* archived reveal — a QUIET footer line at the end of the sessions list, never a header button
   (the rail head stays SESSIONS/PROJECTS + NEW, nothing else). Shown only when ≥1 archived exists. */
.ws-arch-row {
  padding: 3px 8px 4px; cursor: pointer; font-size: 11px; letter-spacing: 1px;
  color: var(--ph-dim); background: transparent; border-left: 2px solid transparent;
}
.ws-arch-row:hover { color: var(--ph); background: var(--ph-faint); }
.ws-arch-row.on { color: var(--ph); }
/* pinned rows sort to the top AND carry a small gold star so the "kept" state is legible at a glance */
.ws-pin { flex: 0 0 auto; font-size: 10px; line-height: 1; color: var(--gold); text-shadow: 0 0 6px rgba(var(--gold-rgb),.5); }
/* the ⋯ button is the discoverable twin of right-click: hidden until the row is hovered, where it takes the meta slot */
.ws-kebab {
  display: none; flex: 0 0 auto; font-family: inherit; font-size: 15px; line-height: 1; letter-spacing: 1px;
  color: var(--ph-dim); background: transparent; border: 0; cursor: pointer; padding: 0 2px;
}
.ws-row:hover .ws-meta, .ws-row:focus-within .ws-meta { display: none; }
.ws-row:hover .ws-kebab, .ws-row:focus-within .ws-kebab { display: inline-block; }
.ws-kebab:hover { color: var(--ph-bright); text-shadow: 0 0 6px var(--ph-glow); }
.ws-row.renaming .ws-kebab, .ws-row.renaming .ws-meta { display: none; }
/* archived (put-away) streams show dimmed only while the ARCHIVED toggle is on */
.ws-row.archived { opacity: .5; }
.ws-row.archived .ws-title { font-style: italic; }
.ws-row.archived:hover { opacity: .85; }
/* rename-in-place: the title becomes a compact phosphor input inside the same row */
.ws-rename {
  flex: 1; min-width: 0; font-family: inherit; font-size: 14px; color: var(--ph-bright);
  background: var(--panel2); border: 1px solid var(--ph); outline: none; padding: 1px 4px; border-radius: 3px;
}

/* ---- the floating actions menu (phosphor chrome, never the native context menu) ---- */
.ws-menu {
  position: fixed; z-index: 140; min-width: 170px; padding: 4px; border-radius: 6px;
  background: var(--panel); border: 1px solid var(--ph);
  box-shadow: 0 0 0 1px var(--ph-dim), 0 8px 24px rgba(0,0,0,.7), 0 0 18px var(--ph-glow2);
  display: flex; flex-direction: column; gap: 1px; animation: wsMenuIn .09s ease-out;
}
@keyframes wsMenuIn { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
.ws-menu-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; border-radius: 4px;
  font-family: inherit; font-size: 13px; letter-spacing: .3px; color: var(--ph);
  background: transparent; border: 0; cursor: pointer; padding: 7px 10px;
}
.ws-menu-item:hover { background: var(--ph-faint); color: var(--ph-bright); }
.ws-menu-glyph { flex: 0 0 auto; width: 14px; text-align: center; font-size: 12px; color: var(--ph-dim); }
.ws-menu-item:hover .ws-menu-glyph { color: var(--ph-bright); }
.ws-menu-item.danger { color: var(--bad); }
.ws-menu-item.danger .ws-menu-glyph { color: var(--bad); }
.ws-menu-item.danger:hover { background: rgba(255,92,77,.14); color: var(--bad); }
/* danger-armed skin is the canonical rule above; only the glyph tint is a per-button extra */
.ws-menu-item.danger.armed .ws-menu-glyph { color: var(--ink); }
.ws-menu-sep { height: 1px; margin: 3px 6px; background: var(--ph-dim); opacity: .5; }

#chat-panel h3 .h3-right { display: inline-flex; align-items: baseline; gap: 8px; min-width: 0; flex: 0 1 auto; overflow: hidden; }
#chat-panel h3 #chat-status { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
#chat-status.status-thinking { color: var(--ph-bright); text-shadow: 0 0 7px var(--ph-glow2); }
/* pre-confirmation: the sidecar hasn't acknowledged the run yet — dimmer than thinking (an honest "in transit") */
#chat-status.status-connecting { color: var(--ph); opacity: .8; }
#chat-status.status-working, #chat-status.status-approval { color: var(--gold); text-shadow: 0 0 7px rgba(var(--gold-rgb),.4); }
#chat-status.status-stopping { color: var(--bad); text-shadow: 0 0 7px rgba(255,74,61,.35); }
/* F2: bridge provably dead (World.linkState E1 — same predicate as the topbar LINK DOWN / canvas marker):
   the idle label can't honestly read 'online', so it reads 'station unreachable' in the fault palette. */
#chat-status.status-down { color: #ff6a4c; text-shadow: 0 0 7px rgba(255,106,76,.35); }

/* COMMS PROCESSING TIMER — a small engraved readout in the amber header that counts a turn's REAL
   wall-clock (thinking → working → done). Monospace with a fixed min-width so the ticking seconds
   never jog the layout, and a pulsing dot that stands in for the harness "spinner". Stays empty
   between turns (:empty → display:none), so it simply appears when a run starts and vanishes when it ends. */
.chat-elapsed {
  display: none; align-items: center; gap: 5px; flex: 0 0 auto;
  font-family: 'VT323', 'Courier New', monospace; font-size: 15px; line-height: 1; letter-spacing: .5px;
  color: var(--ink); padding: 1px 7px 0; border-radius: 4px;
  background: rgba(0,0,0,.16); box-shadow: inset 0 1px 2px rgba(0,0,0,.32);
  font-variant-numeric: tabular-nums;
}
.chat-elapsed:not(:empty) { display: inline-flex; }
.chat-elapsed > .ce-num { min-width: 30px; text-align: right; }
.chat-elapsed::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--ink);
  animation: chat-elapsed-pulse 1.1s ease-in-out infinite;
}
@keyframes chat-elapsed-pulse { 0%, 100% { opacity: .3; transform: scale(.82); } 50% { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .chat-elapsed::before { animation: none; opacity: .8; } }

/* ============ AGENT DOSSIER — redesigned character sheet ============ */

/* hero header: bigger portrait + info block side by side */
.ag-hero {
  display: flex; gap: 14px; align-items: flex-start;
  padding-bottom: 10px; margin-bottom: 2px;
  border-bottom: 1px solid var(--ph-faint);
}
.ag-portrait-wrap { flex: 0 0 88px; }
/* recessed portrait WELL (Phase-2 dossier hero): a dark inset floor the body glows out
   of, corner ticks, and a slow scan-sweep. Cosmetic overlays are pointer-events:none. */
.ag-portrait-well {
  position: relative; width: 88px; height: 112px; border-radius: var(--r-sm); overflow: hidden;
  background: linear-gradient(180deg, #0a0602, #050301);
  box-shadow: var(--well), 0 0 11px var(--ph-glow2);
}
.ag-portrait-well canvas { image-rendering: pixelated; display: block; position: relative; z-index: 1; }
.ag-ptick { position: absolute; width: 8px; height: 8px; border: 1px solid var(--ph); opacity: 0.65; z-index: 3; pointer-events: none; }
.ag-ptick.a { top: 3px; left: 3px; border-right: 0; border-bottom: 0; }
.ag-ptick.b { top: 3px; right: 3px; border-left: 0; border-bottom: 0; }
.ag-ptick.c { bottom: 3px; left: 3px; border-right: 0; border-top: 0; }
.ag-ptick.d { bottom: 3px; right: 3px; border-left: 0; border-top: 0; }
.ag-psweep {
  position: absolute; left: 0; right: 0; height: 20px; z-index: 2; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(255, 205, 130, 0.16), transparent);
  animation: ag-psweep 2.8s linear infinite;
}
@keyframes ag-psweep { 0% { top: -20px; } 100% { top: 112px; } }
.ag-info { flex: 1; min-width: 0; }

/* live status line with pulsing dot */
.ag-role-line {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--ph); letter-spacing: 1.5px;
  margin: 3px 0 6px;
}
.ag-sdot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--ph-dim); flex: none;
}
.ag-sdot.on { background: var(--ok); box-shadow: 0 0 5px rgba(123,200,138,.55); }
.ag-sdot.working { background: var(--gold); box-shadow: 0 0 7px rgba(var(--gold-rgb),.7); animation: sdot-pulse 1.1s infinite; }
.ag-sdot.thinking { background: var(--ph-bright); box-shadow: 0 0 6px var(--ph-glow); animation: sdot-pulse .7s infinite; }
/* E2: link down → OFFLINE dot, red-phosphor breathing, matching the canvas LINK DOWN marker */
.ag-sdot.down { background: var(--link-down); box-shadow: 0 0 6px rgba(255,80,60,.75); animation: sdot-pulse 2.2s infinite; }
@keyframes sdot-pulse { 0%,100%{ opacity:1; } 50%{ opacity:.3; } }

/* 3-cell RPG stat grid */
.stat-grid {
  display: grid; grid-template-columns: 1fr 1fr 1fr;
  gap: 6px; margin: 10px 0 8px;
}
.stat-cell {
  background: linear-gradient(180deg, #0a0602, #050301); box-shadow: var(--well);
  padding: var(--s-3) var(--s-2); text-align: center; border-radius: var(--r-sm);
}
.stat-val { font-size: var(--fs-4); color: var(--ph-bright); letter-spacing: 1px; line-height: 1; text-shadow: 0 0 12px var(--ph-glow2); }
.stat-val.pos { color: var(--gold); }
.stat-lbl { font-size: 10px; color: var(--ph-dim); letter-spacing: 2px; margin-top: 4px; }

/* mission block */
.ag-mission {
  border-left: 2px solid var(--ph); padding: 6px 10px;
  margin: 0 0 8px; background: rgba(0,0,0,.22);
}
.ag-mission-lbl { font-size: 10px; color: var(--ph-dim); letter-spacing: 2px; margin-bottom: 4px; }
.ag-mission-text { font-size: 13px; color: var(--text); line-height: 1.5; user-select: text; }
.ag-mission-cta { font-size: 12px; color: var(--ph-dim); font-style: italic; line-height: 1.45; }

/* footer row */
.ag-foot-row { font-size: 11px; color: var(--ph-dim); letter-spacing: .4px; margin-top: 4px; }
.ag-foot-row b { color: var(--ph); font-weight: normal; }

/* COMMANDER CONTROLS — dossier BRIEF: change skin + delete agent */
.ag-command { margin: 10px 0 8px; display: flex; flex-direction: column; gap: 12px; }
.ag-cmd-sec { border-top: 1px solid var(--hair, rgba(255,255,255,.08)); padding-top: 8px; }
.ag-cmd-lbl { font-size: 10px; color: var(--ph-dim); letter-spacing: 2px; margin-bottom: 6px; }
.ag-skin-row { max-height: 108px; }   /* reuse .skin-picker/.skin-thumb; a shorter well in the narrower dossier pane */
.ag-cmd-danger .ag-cmd-lbl { color: var(--bad); }
.ag-del-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ag-del { border-color: var(--bad) !important; color: var(--bad) !important; }
.ag-del:hover:not(:disabled) { background: rgba(var(--bad-rgb),.12) !important; }
.ag-del:disabled { opacity: .4; cursor: not-allowed; border-color: var(--ph-dim) !important; color: var(--ph-dim) !important; }
/* danger-armed skin is the canonical rule above; only the danger glow is a per-button extra */
.ag-del.armed { box-shadow: 0 0 12px rgba(var(--bad-rgb), .5); }
.ag-del-why { font-size: 11px; color: var(--ph-dim); font-style: italic; }

/* ============ PREMIUM GROWTH DOSSIER — the GROWTH tab ============
   Tactical-ops grid discipline, refined with hairline rules + engraved labels and breathing room.
   Honest gauges (confidence reads "—" while calibrating). Theme-aware: every colour rides the
   --ph / --gold / --ink vars so the green/blue/white themes hold; all VT323 (one house typeface). */
.gx { margin: 4px 0 2px; }
.gx-mono { font-family: inherit; }

.gx-head { display:flex; align-items:flex-start; justify-content:space-between;
  border-bottom:1px solid var(--ph-glow2); padding-bottom:11px; margin-bottom:15px; }
.gx-kicker { font-family:inherit; font-size:10px; letter-spacing:.16em; color:var(--ph-dim); opacity:.85; margin-bottom:5px; }
.gx-name { font-size:26px; line-height:.9; color:var(--ph-bright); letter-spacing:1px; text-shadow:0 0 12px var(--ph-glow2); }
.gx-clear { display:inline-flex; align-items:baseline; gap:7px; background:var(--ph-faint);
  border:1px solid var(--gold); border-radius:2px; padding:4px 10px; }
.gx-clear .k { font-family:inherit; font-size:11px; letter-spacing:.14em; color:var(--gold); }
.gx-clear .v { font-family:inherit; font-size:23px; line-height:1; color:var(--gold); text-shadow:0 0 10px rgba(var(--gold-rgb),.45); }

.gx-2 { display:grid; grid-template-columns:1fr 1fr; gap:18px; margin-bottom:16px; }

.gx-sec { display:flex; align-items:center; gap:7px; height:18px; border-bottom:1px solid var(--ph-glow2); margin-bottom:11px; }
.gx-ref { font-family:inherit; font-size:11px; letter-spacing:.1em; color:var(--ink); background:var(--ph); padding:1px 6px; border-radius:2px; }
.gx-ref.gold { background:var(--gold); }
.gx-title { font-family:inherit; font-size:12px; letter-spacing:.16em; color:var(--ph); text-transform:uppercase; }
.gx-tag { margin-left:auto; font-family:inherit; font-size:10px; letter-spacing:.1em; color:var(--ph-dim); }

.gx-lbl { font-family:inherit; font-size:10px; letter-spacing:.12em; color:var(--ph-dim); text-transform:uppercase; }
.gx-val { font-family:inherit; color:var(--ph-bright); }
.gx-row { display:flex; align-items:baseline; justify-content:space-between; }
.gx-dim { color:var(--ph-dim); }

.gx-trk { position:relative; height:13px; background:var(--ph-faint); border:1px solid var(--ph-glow2); border-radius:2px; overflow:hidden; box-shadow:inset 0 1px 2px rgba(0,0,0,.55); }
.gx-fill { position:absolute; top:0; left:0; bottom:0; background:var(--ph); opacity:.9; box-shadow:0 0 8px var(--ph-glow); }
.gx-gfill { position:absolute; top:0; left:0; bottom:0; background:var(--gold); box-shadow:0 0 8px rgba(var(--gold-rgb),.4); }
.gx-mark { position:absolute; top:-3px; bottom:-3px; width:2px; background:var(--ph-bright); box-shadow:0 0 0 1px rgba(0,0,0,.45); }

.gx-confnum { font-family:inherit; font-size:32px; line-height:.8; color:var(--ph-bright); text-shadow:0 0 12px var(--ph-glow2); }
.gx-confnum.cal { color:var(--ph-dim); }
.gx-band { font-family:inherit; font-size:11px; letter-spacing:.14em; color:var(--ink); background:var(--ph); padding:2px 7px; border-radius:2px; align-self:center; }
.gx-band.cal { color:var(--ph-dim); background:transparent; border:1px solid var(--ph-glow2); }
.gx-gauge { position:relative; }
.gx-zones { display:grid; grid-template-columns:45fr 20fr 20fr 15fr; height:12px; background:var(--ph-faint); border:1px solid var(--ph-glow2); border-radius:2px; overflow:hidden; box-shadow:inset 0 1px 2px rgba(0,0,0,.55); }
.gx-zones > i { display:block; background:var(--ph); }
.gx-zones > i:nth-child(1){ opacity:.16; }
.gx-zones > i:nth-child(2){ opacity:.34; border-left:1px solid var(--bg); }
.gx-zones > i:nth-child(3){ opacity:.58; border-left:1px solid var(--bg); }
.gx-zones > i:nth-child(4){ opacity:.95; border-left:1px solid var(--bg); }
.gx-marknum { position:absolute; top:-14px; transform:translateX(-50%); font-family:inherit; font-size:10px; color:var(--ph-bright); }
.gx-zlabels { display:grid; grid-template-columns:45fr 20fr 20fr 15fr; font-family:inherit; font-size:10.5px; letter-spacing:.03em; color:var(--ph-dim); text-align:center; margin-top:4px; }
.gx-zlabels .hot { color:var(--ph); }

.gx-well { display:flex; align-items:center; justify-content:space-between; border:1px solid var(--ph-glow2); border-radius:2px; padding:8px 11px; margin-top:11px; background:rgba(0,0,0,.2); }
.gx-well.gold { border-color:var(--gold); background:var(--ph-faint); }
.gx-well .v { font-family:inherit; font-size:19px; color:var(--ph-bright); }
.gx-well.gold .v { color:var(--gold); }

.gx-trohead { display:flex; align-items:baseline; justify-content:space-between; margin:18px 0 9px; }
.gx-tros { display:grid; grid-template-columns:repeat(4,1fr); gap:7px; }
.gx-tro { border:1px solid var(--ph-glow2); border-radius:2px; padding:8px 9px; background:rgba(0,0,0,.18); }
.gx-tro.on { border-color:var(--gold); background:var(--ph-faint); }
.gx-tro .gl { font-size:13px; line-height:1; }
.gx-tro.on .gl { color:var(--gold); text-shadow:0 0 7px rgba(var(--gold-rgb),.55); }
.gx-tro.off .gl { color:var(--ph-dim); opacity:.5; }
.gx-tro .nm { font-family:inherit; font-size:11px; letter-spacing:.03em; margin-top:5px; }
.gx-tro.on .nm { color:var(--gold); }
.gx-tro.off .nm { color:var(--ph-dim); opacity:.75; }
.gx-tro .sub { font-family:inherit; font-size:10px; letter-spacing:.04em; margin-top:3px; color:var(--ph-dim); opacity:.7; }

/* G1a — quest-log dynamics: the dismiss ✕ on get-to-know-you quests + the completion flourish.
   The flourish is a MOMENT (one ~2.4s gold flash, bold not subtle), never a lingering state. */
/* .q-dismiss composes .x-btn (bright hover) — ghost + opacity delta */
.q-dismiss { margin-left:auto; background:none; border:1px solid transparent; border-radius:2px;
  color:var(--ph-dim); opacity:.55; font-size:11px; padding:1px 4px; }
.q-dismiss:hover { border-color:var(--ph-glow2); opacity:1; }
/* Slice 5: armed (2-step) state — the ✕ becomes an explicit, dangerous "dismiss forever — sure?" until the
   confirming click (or ~4s auto-disarm). Danger skin is the canonical rule above; only the widen + opacity
   (so the longer label fits and reads as a warning, not a passive glyph) is a per-button extra. */
.q-dismiss.armed { opacity:1; white-space:nowrap; padding:1px 6px; }
/* W3 — "build this while I'm away" affordance on an open, buildable quest. Sits before the dismiss ✕; the
   ◈ marks the away-workshop lane. Gold on hover (it opens the sandbox lane, an amber/consent action). */
.q-queue { margin-left:auto; flex:0 0 auto; background:none; border:1px solid transparent; border-radius:2px;
  color:var(--ph-dim); opacity:.7; font-family:inherit; font-size:12px; line-height:1; padding:1px 4px; cursor:pointer; }
.q-queue + .q-dismiss { margin-left:2px; }
.q-queue:hover { color:var(--gold); border-color:var(--gold); opacity:1; }
.q-queue:disabled { opacity:.4; cursor:default; }
/* §C — the GO ▸ chip: routes to the real surface this quest is done on (task board / dossier / REFIT).
   A quiet phosphor chip in the header row, never a raw browser button; nowrap so the label can't
   fold into the title. First of the header's right-aligned trio (GO ▸ · ◈ queue · ✕ dismiss). */
.q-go { margin-left:auto; flex:0 0 auto; background:none; border:1px solid var(--ph-glow2); border-radius:2px;
  color:var(--ph-dim); opacity:.8; font-family:inherit; font-size:9px; letter-spacing:.08em;
  text-transform:uppercase; white-space:nowrap; line-height:1.5; padding:1px 6px; cursor:pointer; }
.q-go:hover { color:var(--gold); border-color:var(--gold); opacity:1; }
.q-go + .q-queue, .q-go + .q-dismiss { margin-left:2px; }
/* shared quest-row vocabulary (F-lane hygiene): the inline styles the rows used to carry, hoisted to classes so the
   markup reads structural and every row speaks one visual language. No behavior change — geometry is identical. */
.q-hd { display:flex; align-items:center; gap:6px; }        /* the glyph + title header row */
.q-gl-gold { color:var(--gold); }                           /* an amber quest glyph (goal / proposal) */
.q-goalbar { border-left:2px solid var(--gold); }           /* the amber left rail on goal + proposal cards */
.q-indent { margin-left:10px; }                             /* a milestone step nested under its goal header */
.q-mt { margin-top:5px; }                                   /* consent-btn cluster / accept button spacing */
.q-bar { height:5px; border-radius:3px; background:var(--well,rgba(0,0,0,.35)); margin-top:5px; overflow:hidden; }
.q-bar-fill { height:100%; background:var(--gold); }        /* width set inline (the live pct) */
.gx-tro .q-cw { opacity:.82; margin-top:3px; }              /* "✓ completes when:" line */
.gx-tro .q-attest-line { margin-top:4px; color:var(--gold); }   /* "⏳ awaiting your confirmation" */
.gx-tro .q-note { opacity:.7; margin-top:3px; }             /* a prior "not yet" decline note */
.gx-tro.q-celebrate { border-color:var(--gold); animation:q-celebrate 2.4s ease-out 1; }
@keyframes q-celebrate {
  0%   { box-shadow:0 0 18px rgba(var(--gold-rgb),.85), inset 0 0 14px rgba(var(--gold-rgb),.45); background:rgba(var(--gold-rgb),.22); }
  55%  { box-shadow:0 0 9px rgba(var(--gold-rgb),.45), inset 0 0 6px rgba(var(--gold-rgb),.22); }
  100% { box-shadow:none; }
}

/* QUEST V3 — the DIRECTION card: north star + standing-refresh status + the REFRESH QUESTS action.
   Reuses the CRT card language (phosphor border, gold accent for the goal); nothing bespoke that would
   drift from the panel's vocabulary. Every value here maps to real engine state (truthful telemetry). */
.q-refresh-card { border:1px solid var(--ph-glow2); border-radius:2px; background:rgba(0,0,0,.18); padding:9px 11px; margin-bottom:12px; }
.q-northstar { border-left:2px solid var(--gold); padding-left:9px; margin-bottom:9px; }
.q-ns-eyebrow { display:block; font-family:inherit; font-size:9px; letter-spacing:.16em; text-transform:uppercase; color:var(--ph-dim); opacity:.8; }
.q-ns-src { color:var(--ph); opacity:.95; }
.q-ns-tag, .q-nstag { display:inline-block; font-size:8px; letter-spacing:.08em; text-transform:uppercase; padding:0 4px; margin-left:5px; border-radius:2px; }
.q-unconf { color:var(--ink); background:var(--gold); opacity:.9; }
.q-ns-text { font-family:inherit; font-size:13px; letter-spacing:.02em; color:var(--gold); text-shadow:0 0 8px rgba(var(--gold-rgb),.35); margin-top:4px; }
.q-ns-text.dim { color:var(--ph-dim); text-shadow:none; }
.q-ns-why { opacity:.7; margin-top:2px; }
.q-refresh-row { display:flex; align-items:center; gap:10px; margin:8px 0 6px; }
.q-refresh-btn { flex:0 0 auto; }
.q-refresh-due { margin:0; }
.q-refresh-last { margin-top:4px; opacity:.85; }
.q-outcome { display:inline-block; font-size:9px; letter-spacing:.06em; text-transform:uppercase; padding:0 5px; border-radius:2px; border:1px solid var(--ph-glow2); color:var(--ph-dim); }
.q-oc-minted { color:var(--gold); border-color:var(--gold); }
.q-oc-none   { color:var(--ph); border-color:var(--ph-glow2); }
.q-oc-skipped, .q-oc-rejected { color:var(--ph-dim); }
.q-oc-error  { color:#e88; border-color:#e88; }

/* TROPHY CASE card header — the kind tag (DOSSIER / MILESTONE / n× LIFETIME) pins to the top-right
   corner and never shrinks, so a long title wraps cleanly under it instead of jamming the tag
   mid-text in the narrow grid columns. */
.gx-tro .tro-hd { display:flex; align-items:flex-start; gap:6px; }
.tro-hd .nm { min-width:0; }
.tro-hd .gx-tag { margin-left:auto; flex:0 0 auto; white-space:nowrap; }

.gx-station { border:1px solid var(--gold); border-radius:2px; background:var(--ph-faint); padding:12px 14px; margin-top:6px; }
.gx-station .hd { display:flex; align-items:center; gap:8px; margin-bottom:11px; }
.gx-station .badge { font-family:inherit; font-size:11px; letter-spacing:.1em; color:var(--ink); background:var(--gold); padding:1px 6px; border-radius:2px; }
.gx-station .ttl { font-family:inherit; font-size:12px; letter-spacing:.16em; color:var(--gold); }
.gx-station .agents { margin-left:auto; font-family:inherit; font-size:10px; letter-spacing:.1em; color:var(--ph-dim); }
.gx-station .body { display:flex; align-items:flex-end; gap:16px; }
.gx-station .lv { flex:0 0 auto; text-align:center; border-right:1px solid var(--ph-glow2); padding-right:16px; }
.gx-station .lv .n { font-family:inherit; font-size:28px; line-height:.85; color:var(--gold); text-shadow:0 0 10px rgba(var(--gold-rgb),.4); }

.ag-lv { font-family:inherit; font-size:11px; letter-spacing:.08em; color:var(--gold); border:1px solid var(--gold); border-radius:2px; padding:0 5px; margin-left:7px; }

.tb-stat.station { border:1px solid var(--gold); border-radius:2px; padding:1px 8px; }
.tb-stat.station b { color:var(--gold); }
.tb-stat.station.lvup { animation: gx-stationpulse 1.5s ease-out; }
@keyframes gx-stationpulse { 0%{ box-shadow:0 0 0 0 rgba(var(--gold-rgb),.55); } 100%{ box-shadow:0 0 16px 2px rgba(var(--gold-rgb),0); } }

/* narrow-window fallback: the GROWTH dossier collapses gracefully if the term is squeezed */
@media (max-width: 560px) {
  .gx-2 { grid-template-columns: 1fr; }
  .gx-tros { grid-template-columns: repeat(2, 1fr); }
}

/* responsive: degrade the game layout gracefully as the desktop window narrows.
   Hard breakpoints (no soft transitions) to match the CRT chrome. Stage stays the
   priority all the way down; controls wrap rather than clip. Phone/app not targeted. */

/* 1120px: keep all three columns, just tighten the side columns */
@media (max-width: 1120px) {
  #screen-game.active { grid-template-columns: 200px 1fr var(--chat-w, 300px); }
}

/* 1000px: squeeze gaps/padding + side columns further so the stage keeps room */
@media (max-width: 1000px) {
  #screen-game.active {
    grid-template-columns: 176px 1fr 264px;
    padding: 8px; gap: 6px;
  }
}

/* 860px: reflow — crew + stage share the top content row, COMMS drops to its own
   full-width row beneath so the stage stays wide. Stage gets a sensible min-height. */
@media (max-width: 860px) {
  #screen-game.active {
    grid-template-rows: 60px minmax(300px, 1fr) 200px minmax(44px, auto);
    grid-template-columns: 168px 1fr;
    grid-template-areas:
      "top top"
      "left center"
      "chat chat"
      "bot bot";
  }
  /* dragged COMMS width is meaningless once it spans the full row */
  #chat-panel { flex: initial; }
  /* let the bottom-bar docks wrap onto a second line instead of clipping off-screen */
  #bottombar { flex-wrap: wrap; row-gap: 4px; overflow: visible; }
}

/* Short desktop windows need an explicit vertical path to every major region. */
@media (max-width: 860px) and (max-height: 680px) {
  #screen-game.active {
    grid-template-rows: 50px minmax(180px, 1fr) minmax(180px, 1fr) minmax(44px, auto);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* ---- CREW rail hidden (leftrail.js): the left column leaves the grid entirely and the stage
   absorbs the space; the ▸ CREW drawer tab (.crew-show) is the only way back. The body-class
   selector out-specifies every breakpoint's #screen-game.active rule, so each override below
   mirrors its breakpoint's remaining columns. ---- */
body.crew-rail-off #left { display: none; }
body.crew-rail-off #screen-game.active {
  grid-template-columns: 1fr var(--chat-w, 360px);
  grid-template-areas: "top top" "center chat" "bot bot";
}
@media (max-width: 1120px) {
  body.crew-rail-off #screen-game.active { grid-template-columns: 1fr var(--chat-w, 300px); }
}
@media (max-width: 1000px) {
  body.crew-rail-off #screen-game.active { grid-template-columns: 1fr 264px; }
}
@media (max-width: 860px) {
  body.crew-rail-off #screen-game.active {
    grid-template-columns: 1fr;
    grid-template-areas: "top" "center" "chat" "bot";
  }
}

/* ============================================================
   REFIT MODE — the diegetic full-screen station builder (build.js).
   Sits above the HUD + floating windows but UNDER the global CRT
   scanline/vignette layers (z 940/950) so it stays behind the glass.
   ============================================================ */
.refit-overlay {
  position: fixed; inset: 0; z-index: 80; overflow: hidden;
  background: var(--bg); color: var(--ph); user-select: none;
}
.refit-canvas { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; cursor: crosshair; touch-action: none; }

.refit-top {
  position: absolute; top: 0; left: 0; right: 0; height: 46px; z-index: 2;
  display: flex; align-items: center; gap: 12px; padding: 0 14px;
  background: linear-gradient(180deg, rgba(3,2,1,.92), rgba(3,2,1,.4) 78%, transparent);
}
.refit-title { color: var(--ink); background: var(--ph); padding: 3px 14px; letter-spacing: 3px; font-size: 18px; text-shadow: none; box-shadow: 0 0 14px var(--ph-glow2); }
.refit-sub { color: var(--ph-dim); letter-spacing: 2px; font-size: 13px; }
.refit-spacer { flex: 1; }

/* The build panel — a full-height left sidebar in the station's premium window chrome.
   MODE (tool grid) is fixed at the top, OPTIONS is the ONE scroll region (the palette can
   grow forever — room kinds, the whole prop gallery), the hint is pinned at the foot. */
.refit-dock {
  position: absolute; left: 14px; top: 54px; z-index: 2;
  display: flex; flex-direction: column; align-items: stretch;
  width: min(306px, calc(100vw - 28px)); max-height: calc(100vh - 68px);
  padding: 0; border-radius: 9px; overflow: hidden;
  background: var(--panel);
  box-shadow: 0 0 0 2px var(--ph), 0 0 0 3.5px rgba(0,0,0,.9), 0 0 22px var(--ph-glow2), inset 0 0 40px rgba(0,0,0,.85);
}
.refit-dock-section {
  display: flex; flex-direction: column; align-items: stretch; gap: 6px;
  padding: 9px 10px 10px; min-height: 0;
}
.refit-mode-section { flex: 0 0 auto; border-bottom: 1px solid var(--ph-faint); }
.refit-option-section { flex: 1 1 auto; overflow: hidden; }
.refit-option-section.is-empty { display: none; }
.refit-section-label {
  flex: 0 0 auto; color: var(--ph-dim); font-size: 11px; letter-spacing: 2px;
  text-shadow: none; white-space: nowrap; padding-bottom: 2px;
  border-bottom: 1px dashed rgba(120,200,255,.10);
}
.refit-tools {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: stretch; gap: 5px; min-width: 0;
}
/* THE scroll fix: the palette owns the panel's remaining height and scrolls as one column —
   nothing in the options region is ever clipped again. */
.refit-palette {
  display: flex; align-content: flex-start; align-items: flex-start; gap: 5px; flex-wrap: wrap;
  justify-content: flex-start; min-width: 0; min-height: 0; width: 100%; flex: 1 1 auto;
  overflow-y: auto; overflow-x: hidden; padding-right: 4px;
  scrollbar-width: thin; scrollbar-color: var(--ph-dim) transparent;
}
.refit-palette::-webkit-scrollbar { width: 8px; }
.refit-palette::-webkit-scrollbar-thumb { background: var(--ph-dim); border-radius: 4px; }
.refit-palette::-webkit-scrollbar-track { background: transparent; }
.refit-palette:empty { display: none; }
.refit-dock .bb {
  border: 1px solid var(--ph-faint); min-height: 28px; line-height: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.refit-dock .bb:hover { border-color: var(--ph-dim); background: var(--ph-faint); }
.refit-tool {
  display: flex; align-items: center; justify-content: space-between; gap: 7px;
  font-size: 14px; letter-spacing: 1.5px; padding: 5px 8px;
}
.refit-kind { font-size: 12px; padding-inline: 9px; }
/* prop palette: category tabs WRAP (every tab always visible — no hidden horizontal scroll)
   above a GALLERY of live animated prop previews */
.refit-propcats {
  display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-start; width: 100%;
  min-width: 0;
}
.refit-propcats .bb { flex: 0 0 auto; }
.refit-propcat { font-size: 11px; letter-spacing: 1px; opacity: 0.7; }
.refit-propcat.active { opacity: 1; }

/* TIER toggle — the hard, obvious split: ⚙ FUNCTIONAL (props that DO something) vs ✦ COSMETIC (looks only) */
.refit-tiers { display: flex; gap: 6px; width: 100%; min-width: 0; margin-bottom: 2px; }
.refit-tier { flex: 1 1 0; justify-content: center; font-size: 12.5px; letter-spacing: 1.5px; opacity: .55; }
.refit-tier.active { opacity: 1; }
.refit-tier-functional.active { border-color: var(--ok) !important; color: #cfffe0; box-shadow: inset 0 0 0 1.5px var(--ok), 0 0 12px rgba(123,200,138,.18); }
.refit-tier-cosmetic.active { border-color: var(--ph) !important; color: var(--ph-bright); box-shadow: inset 0 0 0 1.5px var(--ph), 0 0 12px var(--ph-glow2); }

/* the gallery no longer caps/clips its own height — the .refit-palette column is the scroller */
.refit-propgrid {
  display: grid; grid-template-columns: repeat(auto-fill, 84px); gap: 6px;
  justify-content: space-between; width: 100%;
  margin-top: 4px; padding: 3px 0 2px;
}
.refit-proptile {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px;
  width: 84px; padding: 5px 2px 4px; cursor: pointer; border-radius: 5px;
  background: rgba(0,0,0,.34); border: 1.5px solid var(--ph-faint); color: var(--ph-dim);
  font-family: inherit; transition: none;
}
.refit-proptile:hover { border-color: var(--ph); color: var(--ph-bright); background: var(--ph-faint); }
.refit-proptile.active {
  border-color: var(--ph-bright); color: var(--ph-bright);
  box-shadow: 0 0 10px var(--ph-glow), inset 0 0 14px rgba(0,0,0,.55);
}
/* functional tiles read as "wired" — a faint teal cast distinct from cosmetic amber */
.refit-proptile.fn { border-color: rgba(123,200,138,.30); color: #9fd9be; }
.refit-proptile.fn:hover { border-color: var(--ok); color: #cfffe0; background: rgba(123,200,138,.07); }
.refit-proptile.fn.active { border-color: var(--ok); color: #cfffe0; box-shadow: 0 0 10px rgba(123,200,138,.30), inset 0 0 14px rgba(0,0,0,.55); }
.refit-proptile-cv {
  width: 76px; height: 50px; image-rendering: pixelated; pointer-events: none;
  background: radial-gradient(ellipse 78% 78% at 50% 62%, rgba(130,170,150,.08), transparent 75%);
}
.refit-proptile-lbl {
  font-size: 10px; letter-spacing: .5px; line-height: 1; text-align: center;
  max-width: 80px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.refit-proptile-tag { position: absolute; top: 3px; right: 5px; font-size: 10px; color: var(--ph); opacity: .6; pointer-events: none; }
/* capability prop badge — the plain POWER a prop grants (WEB/FILES/TERMINAL…), so the gallery shows at a glance which props matter */
.refit-proptile-grant { position: absolute; top: 3px; left: 4px; font-size: 10.5px; letter-spacing: .04em; color: var(--ph-bright); background: var(--ph-faint); border: 1px solid var(--ph); border-radius: 3px; padding: 1px 3px; pointer-events: none; }
.refit-hint {
  flex: 0 0 auto; border-top: 1px solid var(--ph-faint); padding: 6px 10px 8px;
  font-size: 12px; color: var(--ph-dim); letter-spacing: 1px; min-height: 25px; text-align: left;
  white-space: normal; line-height: 1.25;
}

.refit-swatch {
  width: 26px; height: 22px; cursor: pointer; border: 2px solid var(--ph-dim);
  image-rendering: pixelated; padding: 0; flex: 0 0 auto;
}
.refit-swatch:hover { border-color: var(--ph); }
.refit-swatch.active { border-color: var(--ph-bright); box-shadow: 0 0 10px var(--ph-glow); }

.refit-tip {
  position: fixed; z-index: 3; display: none; pointer-events: none;
  font-size: 13px; letter-spacing: 1px; padding: 2px 8px;
  background: rgba(3,2,1,.94); border: 1px solid var(--ph-dim); color: var(--ph-bright);
  text-shadow: 0 0 6px var(--ph-glow2); white-space: nowrap;
  box-shadow: 0 2px 10px rgba(0,0,0,.7);
}
.refit-tip.ok { border-color: var(--ok); color: #aaffc8; }
.refit-tip.bad { border-color: var(--bad); color: #ffb0a8; }

/* Fallout-style prop description card — a persistent hover panel (NOT the transient action tip). Says what a
   prop is + does, its footprint, and (for a placed functional prop) its live assignment. */
.refit-propcard {
  position: fixed; z-index: 5; display: none; pointer-events: none;
  width: 234px; max-width: 72vw; padding: 9px 12px 11px;
  background: var(--panel); border-radius: 7px;
  box-shadow: 0 0 0 1.5px var(--ph), 0 0 0 3px rgba(0,0,0,.9), 0 0 18px var(--ph-glow2), inset 0 0 30px rgba(0,0,0,.85);
  font-family: inherit;
}
.refit-propcard h4 { margin: 0 0 5px; color: var(--ink); background: var(--ph); display: inline-block; padding: 1px 9px; font-size: 14px; letter-spacing: 1.5px; font-weight: normal; }
.refit-propcard .pc-tier { display: block; font-size: 10px; letter-spacing: 1.5px; color: var(--ph-dim); margin-bottom: 5px; }
.refit-propcard .pc-tier.fn { color: var(--ok); }
.refit-propcard p { margin: 0 0 6px; color: var(--text); font-size: 13px; line-height: 1.32; }
.refit-propcard .pc-foot { color: var(--ph-dim); font-size: 11px; letter-spacing: 1px; }
.refit-propcard .pc-assign { margin-top: 7px; padding-top: 6px; border-top: 1px solid var(--ph-faint); font-size: 12px; letter-spacing: .5px; color: var(--warn); }
.refit-propcard .pc-assign.ok { color: #aaffc8; }
/* workstation/bay picker: the agent's model chip beside its name */
.ws-model { opacity: .55; font-size: 10px; letter-spacing: .5px; }

/* primary (safe) action button — inverted phosphor, NOT the danger red */
.refit-primary { background: var(--ph) !important; color: var(--ink) !important; border-color: var(--ph) !important; text-shadow: none !important; }
.refit-primary:hover { background: var(--ph-bright) !important; }

/* per-tool keyboard-shortcut hint chip on each tool button */
.refit-key { flex: 0 0 auto; font-size: 10px; opacity: .5; border: 1px solid currentColor; border-radius: 2px; padding: 0 3px; margin-left: 4px; }
.refit-tool.active { box-shadow: inset 0 0 0 2px var(--ph), 0 0 10px var(--ph-glow2); }
.refit-tool.active .refit-key { opacity: .8; }

/* narrow screens: the panel becomes a bottom sheet — same zones, same single scroll region */
@media (max-width: 760px) {
  .refit-dock { left: 10px; right: 10px; top: auto; bottom: 10px; width: auto; max-height: min(48vh, 380px); }
  .refit-dock-section { gap: 5px; padding: 7px 8px; }
  .refit-section-label { font-size: 10px; }
  .refit-tool { min-width: 0; font-size: 13px; }
  .refit-hint { min-height: 32px; }
}

/* disabled undo/redo (and any .bb) */
.bb:disabled { opacity: .32; cursor: default; pointer-events: none; }

/* a brief attention pulse (undo button after a reclaim; dock button on first run) */
@keyframes refit-pulse { 0%,100% { box-shadow: 0 0 0 0 var(--ph-glow2); } 50% { box-shadow: 0 0 0 3px var(--ph), 0 0 16px var(--ph-glow); } }
.bb.pulse { animation: refit-pulse .45s ease-in-out 0 2; }
#bb-build.refit-nudge { color: var(--ph-bright); animation: refit-pulse 2s ease-in-out infinite; }

/* first-use guide card */
.refit-guide {
  position: absolute; inset: 0; z-index: 4; display: flex; align-items: center; justify-content: center;
  background: rgba(2,1,0,.55); backdrop-filter: blur(1px);
}
.refit-guide-card {
  width: min(420px, 88vw); background: var(--panel); padding: 18px 22px 16px;
  border-radius: 9px; box-shadow: 0 0 0 2px var(--ph), 0 0 0 3.5px rgba(0,0,0,.9), 0 0 26px var(--ph-glow2), inset 0 0 44px rgba(0,0,0,.85);
}
.refit-guide-card h3 { color: var(--ink); background: var(--ph); display: inline-block; padding: 2px 12px; letter-spacing: 2px; margin-bottom: 12px; }
.refit-guide-card ul { list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.refit-guide-card li { color: var(--text); font-size: 15px; line-height: 1.3; }
.refit-guide-card b { color: var(--ph-bright); font-weight: normal; }
.refit-guide-card .g-ok { color: #aaffc8; } .refit-guide-card .g-bad { color: #ffb0a8; }
.refit-guide-card #refit-guide-go { width: 100%; }
/* connector-portal bind editor (rides the refit-guide card) */
.refit-conn-rows { display: flex; flex-direction: column; gap: 5px; margin: 4px 0 2px; max-height: 240px; overflow: auto; }
.refit-conn-rows .conn-row { text-align: left; display: flex; align-items: baseline; gap: 6px; }
.refit-conn-rows .conn-row.active { background: var(--ph-faint); border-color: var(--ph); }
.refit-conn-rows .conn-meta { margin-left: auto; color: var(--ph-dim); font-size: 10px; }
.refit-conn-note { color: var(--ph-dim); font-size: 12px; line-height: 1.4; padding: 4px 0; }

/* ---------- CONNECTORS panel (MCP) ---------- */
.mc-list { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 14px; }
.mc-row { border: 1px solid var(--ph-dim); border-radius: var(--r-sm); padding: 8px 10px; background: rgba(0,0,0,.35); box-shadow: var(--raise); }
.mc-top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.mc-top b { color: var(--ph-bright); font-weight: normal; letter-spacing: .5px; }
.mc-state { margin-left: auto; font-size: 13px; white-space: nowrap; }
.mc-url { font-size: 12px; word-break: break-all; margin-top: 2px; }
.mc-detail { font-size: 12px; color: var(--bad); margin-top: 4px; }
.mc-tools { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px; }
.mc-tools code { font-size: 11px; color: var(--ph); border: 1px solid var(--ph-dim); border-radius: 4px; padding: 1px 5px; background: rgba(0,0,0,.4); }
.mc-acts { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; }
.mc-form { display: flex; flex-direction: column; gap: 6px; }
/* ROUTINES — RUN NOW result (P0 #11): renders inline in the ACTIVE pane, spliced under the row that fired it,
   framed like a mini terminal so the paid run's output is unmissable (never streamed into the hidden CREATE pane). */
.rt-out { margin: 2px 0 8px; border: 1px solid var(--ph-dim); border-left: 2px solid var(--ph);
  border-radius: var(--r-sm); background: rgba(0,0,0,.4); box-shadow: var(--raise); padding: 7px 10px; }
.rt-out-h { display: flex; align-items: center; gap: 6px; font-size: var(--fs-0);
  color: var(--ph-dim); letter-spacing: var(--ls-2); margin-bottom: 5px; }
.rt-out-h b { color: var(--ph-bright); font-weight: normal; }
.rt-out-x { margin-left: auto; }
.rt-out-b { white-space: pre-wrap; max-height: 220px; overflow: auto; font-size: var(--fs-1); color: var(--text); }
/* per-connector ENABLE pill lives inline in the row header; align it to the title baseline row */
.mc-top { align-items: center; }
.mc-enable { flex: 0 0 auto; margin: 0; }
.mc-enable input[type=checkbox] { margin: 0; }

/* ===== TOOLSETS console: one CRT pill-switch row per capability family ===== */
.ts-core { align-items: center; gap: 8px; border: 1px dashed var(--ph-dim); border-radius: var(--r-sm);
  padding: 8px 10px; margin-bottom: 8px; background: rgba(0,0,0,.28); opacity: .85; }
.ts-core-tag { font-size: 10px; letter-spacing: 1.5px; color: var(--gold); border: 1px solid var(--gold);
  border-radius: 3px; padding: 0 4px; margin-left: 6px; vertical-align: middle; }
#ts-list { display: flex; flex-direction: column; gap: 8px; }
.ts-row { align-items: flex-start; gap: 8px; border: 1px solid var(--ph-dim); border-radius: var(--r-sm);
  padding: 8px 10px; background: rgba(0,0,0,.35); box-shadow: var(--raise);
  animation: cardIn var(--t-med) var(--ease-out) both; animation-delay: calc(var(--ci, 0) * 34ms); }
.ts-row > input[type=checkbox] { margin-top: 2px; }
.ts-glyph { font-size: 15px; color: var(--ph); line-height: 1.4; flex: 0 0 auto; }
.ts-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.ts-name { color: var(--ph-bright); letter-spacing: .5px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ts-count { font-size: 10px; letter-spacing: 1px; }
.ts-desc { font-size: 12px; }
.ts-tag { font-size: 10px; letter-spacing: 1px; color: var(--warn); border: 1px solid var(--warn);
  border-radius: 3px; padding: 0 4px; }
.ts-inert { display: block; font-size: 11px; color: var(--gold); margin-top: 3px; letter-spacing: .3px; }
.ts-tools { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px; }
.ts-tools code { font-size: 11px; color: var(--ph); border: 1px solid var(--ph-dim); border-radius: 4px;
  padding: 1px 5px; background: rgba(0,0,0,.4); }
.ts-row.ts-off { opacity: .62; }
.ts-row.ts-off .ts-name { color: var(--ph-dim); }
.ts-row.ts-inert-row .ts-glyph { color: var(--ph-dim); }
.ts-spotify { margin-top: 8px; border-top: 1px solid var(--ph-dim); padding-top: 8px; }
/* SKILLS capabilities perk dimmed when its toolset is switched off (honesty parity with the TOOLSETS console) */
.perk.ts-disabled { opacity: .55; }
.perk.ts-disabled .perk-stat { color: var(--ph-dim); }
.bb.xs { font-size: 11px; padding: 2px 7px; }
/* connector add/edit form: one-line help, transport toggle, key:value textareas, transport tag on a row */
.mc-hint { font-size: 11px; color: var(--ph-dim); margin: -2px 0 2px; line-height: 1.35; }
.mc-hint code { color: var(--ph); }
/* shared per-agent MODEL PICKER (native grouped <select> + optional effort select) — used by the dossier
   CONFIG card AND the recruitment bay, so it lives here in the global sheet. Phosphor-terminal styling. */
.mp-wrap { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.mp-model, .mp-effort {
  font-family: inherit; font-size: 13px; color: var(--ph); background: var(--panel2);
  border: 1px solid var(--ph-dim); border-radius: var(--r-sm, 4px); padding: 4px 8px; cursor: pointer; max-width: 100%;
}
.mp-model { flex: 1 1 200px; min-width: 0; }
.mp-effort { flex: 0 0 auto; color: var(--ph-dim); }
.mp-model:focus, .mp-effort:focus { outline: none; border-color: var(--ph); box-shadow: 0 0 0 1px var(--ph); }
.mp-model optgroup { color: var(--ph-dim); font-style: normal; background: var(--panel2); }
.mp-model option, .mp-effort option { color: var(--ph-bright); background: var(--panel2); }
/* the CONFIG model card: the picker row + the collapsible advanced free-text escape hatch */
.mc-pick-row { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.mc-pick-row > label { flex: 0 0 60px; color: var(--ph-dim); font-size: 12px; letter-spacing: .5px; }
.mc-pick { flex: 1; min-width: 0; }
.mc-adv { margin: 4px 0 6px; }
.mc-adv > summary { cursor: pointer; color: var(--ph-dim); font-size: 11px; letter-spacing: .5px; list-style: none; padding: 2px 0; }
.mc-adv > summary::-webkit-details-marker { display: none; }
.mc-adv > summary:hover { color: var(--ph); }
.mc-adv[open] > summary { color: var(--ph); margin-bottom: 4px; }
/* BUDGET panel — number-input phosphor styling (the base rule at top only covers text/password) + label→input row.
   Additive: new selectors only, on-theme via the same vars. */
input[type=number].key-input {
  font-family: inherit; font-size: 19px; color: var(--ph-bright);
  background: linear-gradient(180deg, #000, color-mix(in srgb, var(--ph) 3%, #000));
  border: 1px solid var(--ph-dim); border-radius: 4px; padding: 8px 11px; outline: none;
  text-shadow: 0 0 5px var(--ph-glow2); box-shadow: inset 0 2px 5px rgba(0,0,0,.65);
}
input[type=number].key-input:focus { border-color: var(--ph); box-shadow: inset 0 0 18px rgba(0,0,0,.7), 0 0 12px var(--ph-glow2); }
#budget-form .set-row { display: flex; align-items: center; gap: 10px; }
#budget-form .set-row label { flex: 0 0 108px; color: var(--ph-dim); font-size: 12px; letter-spacing: .5px; }
#budget-form .set-row .bg-cap { flex: 1; font-size: 16px; padding: 5px 9px; text-align: right; }
#budget-spend { font-size: 13px; margin: 2px 0 8px; }
#budget-spend b { color: var(--ph-bright); }
/* soft-pool CAP-HIT row + one-click RESUME — rendered ONLY when the governor is actually refusing new runs
   (truthful telemetry: no pool hit, no row). Warn vocabulary, same as the readiness chips. */
#budget-pools .bg-pool-hit { display: flex; align-items: center; gap: 10px; border: 1px solid var(--warn); background: rgba(0,0,0,.32); padding: 6px 9px; margin: 2px 0 8px; font-size: 12.5px; color: var(--warn); }
#budget-pools .bg-pool-hit b { color: var(--ph-bright); }
#budget-pools .bg-pool-hit .bb { flex: 0 0 auto; margin-left: auto; }
/* MODELS panel — the ordered fallback chain (P0-3). Additive: new selectors only, on-theme via the same vars. */
.mc-list-fb { display: flex; flex-direction: column; gap: 4px; margin: 2px 0 4px; }
.fbc-row { display: flex; align-items: center; gap: 6px; border: 1px solid var(--ph-dim); background: rgba(0,0,0,.32); padding: 4px 8px; }
.fbc-ord { flex: 0 0 auto; color: var(--ph-dim); font-size: 12px; }
.fbc-id { flex: 1; color: var(--ph-bright); font-size: 13px; text-shadow: 0 0 5px var(--ph-glow2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fbc-row .bb[disabled] { opacity: .35; cursor: default; }
select.fbc-sel {
  flex: 1; font-family: inherit; font-size: 13px; color: var(--ph);
  background: linear-gradient(180deg, #000, color-mix(in srgb, var(--ph) 3%, #000));
  border: 1px solid var(--ph-dim); border-radius: 4px; padding: 6px 9px; outline: none;
  box-shadow: inset 0 2px 5px rgba(0,0,0,.6);
  transition: border-color .12s, box-shadow .12s;
}
select.fbc-sel:focus { border-color: var(--ph); box-shadow: inset 0 2px 5px rgba(0,0,0,.6), 0 0 12px var(--ph-glow2); }
.mc-seg { display: flex; gap: 0; margin: 2px 0 4px; }
.mc-seg-btn {
  flex: 1; cursor: pointer; font-family: inherit; font-size: 12px; letter-spacing: .5px;
  color: var(--ph-dim); background: rgba(0,0,0,.32); border: 1px solid var(--ph-dim); padding: 4px 8px;
}
.mc-seg-btn + .mc-seg-btn { border-left: none; }
.mc-seg-btn:first-child { border-radius: 4px 0 0 4px; }
.mc-seg-btn:last-child { border-radius: 0 4px 4px 0; }
.mc-seg-btn:hover { color: var(--ph); }
.mc-seg-btn.active { color: var(--ph-bright); background: var(--ph-faint); box-shadow: inset 0 0 0 1px var(--ph); }
.mc-tp-fields { display: flex; flex-direction: column; gap: 6px; }
.mc-kv { resize: vertical; min-height: 40px; font-family: inherit; }
.mc-tag {
  font-size: 10px; letter-spacing: .5px; color: var(--ph); border: 1px solid var(--ph-dim);
  border-radius: 3px; padding: 0 4px; margin-right: 4px; text-transform: uppercase;
}

/* ===== CONNECTOR CATALOG: one-click, vetted MCP servers (browse-and-add cards) ===== */
/* setup-type legend — color-coded to the per-card auth chips (green no-setup · gold key · dim OAUTH). Single-weight
   font, so no faux-bold; the color carries the emphasis. */
.cc-legend .cc-lg-none { color: var(--ok); font-weight: normal; }
.cc-legend .cc-lg-key { color: var(--gold); font-weight: normal; }
.cc-legend .cc-lg-oauth { color: var(--ph-dim); font-weight: normal; letter-spacing: .5px; }
.cc-list { display: flex; flex-direction: column; gap: 14px; margin: 4px 0 10px; }
.cc-group { display: flex; flex-direction: column; gap: 8px; }
.cc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(224px, 1fr)); gap: 8px; }
.cc-card { display: flex; flex-direction: column; gap: 6px; border: 1px solid var(--ph-dim); border-radius: var(--r-sm);
  padding: 9px 11px; background: rgba(0,0,0,.35); box-shadow: var(--raise);
  animation: cardIn var(--t-med) var(--ease-out) both; animation-delay: calc(var(--ci, 0) * 28ms); }
.cc-card.cc-on { border-color: var(--ok); box-shadow: var(--raise), inset 0 0 0 1px var(--ok); }
.cc-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cc-head b { color: var(--ph-bright); font-weight: normal; letter-spacing: .5px; }
.cc-badge { font-size: 10px; letter-spacing: .5px; border-radius: 3px; padding: 0 4px; text-transform: uppercase; }
.cc-official { color: var(--ok); border: 1px solid var(--ok); }
.cc-community { color: var(--ph-dim); border: 1px solid var(--ph-dim); }
.cc-chip { margin-left: auto; font-size: 10px; letter-spacing: .5px; white-space: nowrap; }
.cc-blurb { font-size: 12px; line-height: 1.4; flex: 1; }
.cc-acts { display: flex; align-items: center; gap: 8px; margin-top: 2px; }
.cc-home { font-size: 11px; letter-spacing: .5px; text-decoration: none; }
.cc-home:hover { color: var(--ph); }
.cc-key { display: flex; flex-direction: column; gap: 3px; }
.cc-card .bb[disabled] { opacity: .5; cursor: default; }
/* "VIA <name>" jump landing: the aggregator card flashes gold — a MOMENT (same 2.4s gold-flash
   vocabulary as q-celebrate), never a lingering state. */
.cc-card.cc-jump { border-color: var(--gold); animation: q-celebrate 2.4s ease-out 1; }

.rt-agent-pick { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 5px; }
.rt-agent-btn {
  min-width: 0; display: grid; grid-template-columns: 9px minmax(0, 1fr); grid-template-rows: auto auto;
  column-gap: 6px; align-items: center; text-align: left; cursor: pointer;
  color: var(--ph); background: rgba(0,0,0,.32); border: 1px solid var(--ph-dim);
  font-family: inherit; font-size: 12px; letter-spacing: .5px; padding: 5px 7px;
}
/* selection reads through the phosphor language, NOT the agent's suit colour — the suit
   colour stays on the identity DOT only (see .rt-agent-dot). Keeps the chip on-palette
   across every theme instead of painting a stray blue/purple border for a blue/purple agent. */
.rt-agent-btn:hover, .rt-agent-btn.active { border-color: var(--ph); background: var(--ph-faint); color: var(--ph-bright); }
.rt-agent-btn.active { box-shadow: inset 0 0 0 1px var(--ph), 0 0 10px var(--ph-glow2); }
.rt-agent-dot { width: 7px; height: 7px; background: var(--rt-agent-color, var(--ph)); box-shadow: 0 0 6px var(--rt-agent-color, var(--ph)); }
.rt-agent-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rt-agent-id { grid-column: 2; min-width: 0; color: var(--ph-dim); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- accessibility: a consistent keyboard-focus ring (Finding #3) ----------
   A single, theme-agnostic :focus-visible outline so the focused control is always
   visible when tabbing through a floating .term window or a dock popover. Uses the
   phosphor accent so it reads on every theme; only shows for keyboard focus, never
   on mouse click. The .term panel itself gets focus on open (tabindex=-1) but is a
   container, so its ring is suppressed to avoid a full-window outline. */
.term:focus-visible { outline: none; }
.term:focus-within { box-shadow: inset 0 0 0 1px var(--ph-glow2); }
.term button:focus-visible,
.term input:focus-visible,
.term textarea:focus-visible,
.term select:focus-visible,
.term a:focus-visible,
.term [tabindex]:focus-visible,
.term-x:focus-visible,
.bb-menu .bb:focus-visible,
.bb-grp:focus-visible,
.btn:focus-visible, .btn-xl:focus-visible, .btn-sm:focus-visible, .prov:focus-visible {
  outline: 2px solid var(--ph-bright); outline-offset: 2px;
}
.bb-menu .bb:focus-visible { background: var(--ph-faint); color: var(--ph-bright); }

/* ---------- ui-irritants: NOTIFICATIONS panel severity (whisper, not traffic light) ----------
   The .nf base (style.css) is a bare bottom-ruled text row; add a lead glyph + a left hairline
   that colours to the severity, matching the toast language. Text-colour per severity already
   lives in style.css (.nf.good/.warn/.gold); we add the edge + glyph + the bad/info cases. */
.nf {
  display: flex; align-items: baseline; gap: 6px;
  padding-left: 8px; border-left: 2px solid var(--ph-dim);
}
.nf-sev { flex: 0 0 auto; font-size: 11px; line-height: 1.3; opacity: 0.9; }
.nf-ts { color: var(--ph-dim); font-size: 12px; letter-spacing: 0.5px; flex: 0 0 auto; }
.nf-txt { flex: 1 1 auto; min-width: 0; }
/* per-row dismiss ✕ — quiet until the row is hovered/focused, then a soft phosphor cue */
.nf-x {
  flex: 0 0 auto; align-self: center; margin-left: 4px;
  background: none; border: 0; color: var(--ph-dim); cursor: pointer;
  font-family: inherit; font-size: 12px; line-height: 1; padding: 2px 4px; opacity: 0;
  transition: opacity 120ms ease, color 120ms ease;
}
.nf:hover .nf-x, .nf:focus-within .nf-x { opacity: 0.75; }
.nf-x:hover, .nf-x:focus { opacity: 1; color: var(--bad); outline: none; }
.nf.sev-bad  { border-left-color: var(--bad); color: var(--bad); }
.nf.sev-warn { border-left-color: var(--warn); }
.nf.sev-good { border-left-color: var(--ok); }
.nf.sev-gold { border-left-color: var(--gold); }
.nf.sev-info { border-left-color: var(--ph-dim); }
.nf.sev-bad  .nf-sev { color: var(--bad); }
.nf.sev-warn .nf-sev { color: var(--warn); }
.nf.sev-good .nf-sev { color: var(--ok); }
.nf.sev-gold .nf-sev { color: var(--gold); }
.nf.sev-info .nf-sev { color: var(--ph-dim); }

/* ============================================================
   CONSOLE MODE — the large two-pane window (agent/console-windows)
   A dense panel (SETTINGS, SKILLS) opens as a big centred window: a left
   section rail + a right content pane showing ONE section at a time, with a
   cross-section search. Kills the small-window scroll tunnel. Phosphor vars
   only; motion (the .swap-in crossfade) rides motion.css.
   ============================================================ */
.term.console {
  width: min(1060px, 88vw);
  height: min(78vh, 720px);
  max-width: 88vw; max-height: min(78vh, 720px);
}
.term.console .term-body.term-console-body {
  display: flex; flex-direction: row; gap: 0;
  padding: 0; overflow: hidden;              /* the content pane owns the scroll, not the body */
  flex: 1 1 auto; min-height: 0;
}

/* ---- left: search + section rail ---- */
.con-rail {
  flex: 0 0 190px; display: flex; flex-direction: column; min-height: 0;
  border-right: 1px solid var(--ph-dim);
  background: linear-gradient(180deg, var(--ph-glow2), transparent 40%), rgba(0,0,0,0.28);
}
.con-search {
  position: relative; flex: 0 0 auto;
  padding: 10px 10px 8px; border-bottom: 1px solid var(--ph-faint);
}
.con-search-i {
  position: absolute; left: 18px; top: 50%; transform: translateY(-50%);
  color: var(--ph-dim); font-size: var(--fs-2); pointer-events: none; text-shadow: 0 0 6px var(--ph-glow2);
}
/* .con-search prefix RAISES specificity above the base `input[type=text]` rule (0,1,1) — without it
   that base padding (7px 10px) won the cascade and the ⌕ glyph overlapped the placeholder's first char. */
.con-search .con-search-in {
  width: 100%; font-family: inherit; font-size: var(--fs-1); color: var(--ph-bright);
  background: #000; border: 1px solid var(--ph-dim); border-radius: var(--r-sm);
  /* clear the ⌕ glyph (absolute at left:18px) so it never overlaps the placeholder's first character */
  padding: 6px 8px 6px 32px; outline: none; letter-spacing: var(--ls-1);
  text-shadow: 0 0 5px var(--ph-glow2); box-shadow: inset 0 2px 5px rgba(0,0,0,.6);
}
.con-search-in:focus { border-color: var(--ph); box-shadow: inset 0 0 12px rgba(0,0,0,.7), 0 0 10px var(--ph-glow2); }

/* ---------- window unsaved-close guard banner (P0 draft-loss) ---------- */
/* shown transiently when a ✕/Esc close is refused because a window holds a modified, unsaved editor. */
.term-unsaved-bar {
  position: absolute; left: 10px; right: 10px; bottom: 10px; z-index: 4;
  margin: 0; padding: 5px 10px; text-align: center; pointer-events: none;
  font-size: var(--fs-1); letter-spacing: var(--ls-1);
  color: var(--link-down); background: rgba(0,0,0,0.92);
  border: 1px solid rgba(255,80,60,0.7); border-radius: var(--r-sm);
  box-shadow: 0 0 14px rgba(255,80,60,0.35);
  animation: unsaved-pulse 1.1s ease-in-out infinite;
}
@keyframes unsaved-pulse { 0%,100% { opacity: 0.72; } 50% { opacity: 1; } }

/* ---------- per-agent window switcher (REWIND / LOGBOOK) + logbook header + transcript toggle ---------- */
.rw-switch { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 10px; }
.rw-agent {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: inherit; font-size: var(--fs-1); letter-spacing: var(--ls-1);
  color: var(--ph-dim); background: rgba(0,0,0,0.4);
  border: 1px solid var(--ph-faint); border-radius: var(--r-sm);
  padding: 3px 8px; cursor: pointer; transition: color 120ms ease, border-color 120ms ease;
}
.rw-agent:hover { color: var(--ph); border-color: var(--ph-dim); }
.rw-agent.sel { color: var(--ink); background: var(--ph); border-color: var(--ph); text-shadow: none; }
.rw-agent-dot { font-size: 10px; line-height: 1; }
.rw-agent.sel .rw-agent-dot { color: var(--ink) !important; }
.lb-agent-h { font-size: var(--fs-1); letter-spacing: var(--ls-1); color: var(--ph-dim); margin: 2px 0 8px; padding: 0 2px; }
.lb-agent-h b { color: var(--ph-bright); }
.lb-tx-btn {
  font-family: inherit; font-size: 11px; letter-spacing: var(--ls-1);
  color: var(--ph-dim); background: none; border: 0; cursor: pointer; padding: 0 2px;
}
.lb-tx-btn:hover, .lb-tx-btn:focus { color: var(--ph); outline: none; text-shadow: 0 0 5px var(--ph-glow2); }
.lb-run-open.tx-open { border-color: var(--ph-dim); }
.con-rail-list {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 8px 8px 12px;
  display: flex; flex-direction: column; gap: 3px;
  scrollbar-width: thin; scrollbar-color: var(--ph-dim) transparent;
}
.con-rail-list::-webkit-scrollbar { width: 6px; }
.con-rail-list::-webkit-scrollbar-thumb { background: var(--ph-dim); border-radius: 4px; }
.con-rail-list::-webkit-scrollbar-track { background: transparent; }
.con-rail-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  font-family: inherit; font-size: var(--fs-1); letter-spacing: var(--ls-2); color: var(--ph-dim);
  background: transparent; border: 1px solid transparent; border-radius: var(--r-sm);
  padding: 7px 9px; cursor: pointer; text-shadow: 0 0 6px var(--ph-glow2);
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.con-rail-glyph { flex: 0 0 auto; width: 15px; text-align: center; opacity: .85; }
.con-rail-label { flex: 1 1 auto; }
.con-rail-item:hover { color: var(--ph-bright); border-color: var(--ph-dim); background: var(--ph-faint); }
/* active = the inverted title-chip idiom + a phosphor edge on the left (ties into the window title chip) */
.con-rail-item.active {
  color: var(--ink); background: var(--ph); border-color: var(--ph);
  text-shadow: none; box-shadow: 0 0 12px var(--ph-glow2), inset 3px 0 0 var(--ph-bright);
}
.con-rail-item.active .con-rail-glyph { opacity: 1; }
.con-rail-item:focus-visible { outline: 2px solid var(--ph-bright); outline-offset: 1px; }
/* search dimming of rail items with zero matches */
.con-rail-item.con-rail-dim { opacity: .32; }
.con-rail-item.con-rail-hit:not(.active) { color: var(--ph-bright); }

/* ---- tabsTop: the section tabs as a horizontal strip at the top of the content pane ----
   Opted into by the AGENT DOSSIER so its left rail is purely the agent roster. The strip reuses
   .con-rail-item for base type/colour, then .con-toptab reshapes it horizontal: the active state is a
   hairline phosphor underline + inverted chip (echoes the vertical rail's inset-left edge, turned to the
   bottom). The strip is sticky so the tabs stay put while a long section pane scrolls under them. */
.con-toptabs {
  position: sticky; top: 0; z-index: 3;
  display: flex; flex-wrap: wrap; gap: 4px; align-items: stretch;
  margin: 0 0 var(--s-3); padding-bottom: 8px;
  border-bottom: 1px solid var(--ph-dim);
  /* the pane's own top padding is var(--s-3); the sticky strip masks scrolled content behind it */
  background: linear-gradient(180deg, rgba(0,0,0,0.92) 70%, transparent),
              linear-gradient(180deg, var(--ph-glow2), transparent 60%);
}
.con-rail-item.con-toptab {
  width: auto; flex: 0 1 auto; position: relative;
  padding: 8px 14px; border-radius: var(--r-sm) var(--r-sm) 0 0;
}
.con-rail-item.con-toptab .con-rail-glyph { width: auto; }
/* active top tab = inverted chip like the vertical rail, but the phosphor edge rides the BOTTOM as an
   underline (hairline) instead of the left inset — consistent CRT-console active idiom, horizontal. */
.con-rail-item.con-toptab.active {
  color: var(--ink); background: var(--ph); border-color: var(--ph);
  text-shadow: none; box-shadow: 0 0 12px var(--ph-glow2), inset 0 -3px 0 var(--ph-bright);
}

/* ---- right: content pane, one section shown ---- */
.con-pane {
  flex: 1 1 auto; min-width: 0; min-height: 0; overflow-y: auto;
  padding: var(--s-3) var(--s-4) var(--s-5);
  scrollbar-width: thin; scrollbar-color: var(--ph) transparent;
}
.con-pane::-webkit-scrollbar { width: 8px; }
.con-pane::-webkit-scrollbar-thumb { background: var(--ph-dim); border-radius: 4px; }
.con-pane::-webkit-scrollbar-thumb:hover { background: var(--ph); }
.con-pane::-webkit-scrollbar-track { background: transparent; }
.con-sec-hidden { display: none; }
.con-sec-head { margin-top: 2px; }
/* the section's one-line self-explanatory description under its header */
.con-sec-desc {
  color: var(--ph-dim); font-size: var(--fs-1); letter-spacing: var(--ls-1);
  margin: -4px 0 12px; line-height: 1.4; max-width: 62ch;
}
/* the section head is a click target only while searching (jump-to-section) */
.con-searching .con-sec-head { cursor: pointer; }
.con-searching .con-sec-head:hover .sec-l { color: var(--ph-bright); }
/* while searching: every section is shown, non-matching rows fade, empty sections collapse their body */
.con-searching .con-miss { opacity: .18; }
.con-searching .con-sec-nomatch { display: none; }
.con-searching .con-sec + .con-sec { margin-top: 18px; }

/* responsive: on a narrow viewport the rail sits on top as a horizontal strip */
@media (max-width: 720px) {
  .term.console { width: 94vw; height: 84vh; }
  .term.console .term-body.term-console-body { flex-direction: column; }
  .con-rail { flex: 0 0 auto; border-right: none; border-bottom: 1px solid var(--ph-dim); }
  .con-rail-list { flex-direction: row; flex-wrap: wrap; overflow-x: auto; }
  .con-rail-item.active { box-shadow: 0 0 12px var(--ph-glow2), inset 0 3px 0 var(--ph-bright); }
}

/* ============================================================
   F1 · FORM-CONTROL FOUNDATION (finale polish sprint 2026-07-09)
   One skin for every native <select>; no OS spinners on number
   fields; one global disabled treatment. The chevron is drawn
   with currentColor gradients (never an SVG data-uri) so it
   re-tints with every theme. The OPEN option list stays OS-native
   (unstyleable) — set what browsers honour on option/optgroup.
   `html select` boosts specificity above the legacy per-surface
   skins whose `background:` shorthands would wipe the chevron.
   .comms-agent-select keeps its own themed ▾ (excluded here).
   ============================================================ */
html select:not(.comms-agent-select) {
  -webkit-appearance: none; appearance: none;
  font-family: inherit; cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 13px top 55%, right 8px top 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 24px;
}
html select option, html select optgroup {
  color: var(--text); background: var(--panel2, #0a0a08); font-style: normal;
}
/* kill the OS number spinners app-wide — every numeric field here is a small
   typed integer (budget caps, timeouts, cooldowns); the spinner is pure chrome */
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
input[type=number] { -moz-appearance: textfield; }
/* one global disabled voice — surfaces may deepen it, never brighten it */
button:disabled, select:disabled, input:disabled, textarea:disabled {
  opacity: 0.45; cursor: not-allowed;
}

/* OUTBOX — FINISHED WORK window (accordion, 2026-07-16 round 4). Collapsed row = title + what the
   agent actually did + a dim meta line, nothing else; the whole head is the toggle. Expanded body
   holds the ask, the full output (scrolls inside itself), and the one action row. */
.ob-list { display: flex; flex-direction: column; gap: 8px; }
.ob-row { border: 1px solid var(--ph-faint); border-radius: var(--r-sm); background: var(--panel2); box-shadow: var(--raise); overflow: hidden; transition: border-color 0.15s; }
.ob-row.open { border-color: var(--ph-dim); box-shadow: var(--raise), inset 0 0 14px var(--ph-glow2); }
.ob-head { padding: 9px 12px; cursor: pointer; }
.ob-head:hover, .ob-head:focus-visible { background: rgba(255, 255, 255, 0.03); outline: none; }
.ob-title { color: var(--ph); letter-spacing: 0.5px; display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.ob-title b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.ob-caret { color: var(--ph-dim); flex: none; }
.ob-desc { margin-top: 3px; font-size: 12px; line-height: 1.45; color: var(--text); opacity: 0.78; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.ob-meta { margin-top: 5px; font-size: 10.5px; color: var(--ph-dim); letter-spacing: 1px; }
.ob-body { border-top: 1px solid var(--ph-faint); padding: 10px 12px 12px; }
.ob-sec { font-size: 10px; letter-spacing: 2px; color: var(--ph-dim); margin: 10px 0 4px; }
.ob-sec:first-child { margin-top: 0; }
.ob-ask, .ob-out { white-space: pre-wrap; word-break: break-word; max-height: 240px; overflow: auto; font-size: 12px; color: var(--text); }
/* dim helper copy inside windows — NOT .mc-detail (that's the CONNECTORS error-detail class, alarm-red) */
.win-note { font-size: 12px; color: var(--ph-dim); line-height: 1.45; }
.ob-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-top: 12px; }
