/**
 * Layout, and the few things specific to this application.
 *
 * Controls are not styled here — that is `ui.css`. This file positions things and
 * nothing else, which is why it stays short as features arrive: a new panel is a
 * new region, not a new set of button, input and chip rules.
 */

/* -------------------------------------------------------------------- shell */

body { display: flex; flex-direction: column; }

.bar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  min-height: var(--bar-h);
  padding: var(--s-2) var(--s-4);
  background: var(--c-surface);
  border-bottom: var(--border);
  flex: 0 0 auto;
}

.brand {
  font-weight: var(--w-medium);
  letter-spacing: -0.01em;
  white-space: nowrap;
  flex: 0 0 auto;
}

/*
 * The one context chip (which session / which machine) takes the slack in the
 * middle of the bar and truncates instead of pushing the pane switcher off the
 * edge — so the bar holds its shape from a phone to a wide monitor without a
 * spacer or a wrap.
 */
.bar__context {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
}
.bar__context > .chip { min-width: 0; }

/* --------------------------------------------------------------- sidebar */

/*
 * The site picker (MODEL.md §37) — an overlay at every width rather than a
 * persistent third column, so it never fights the two-pane split for space
 * and behaves identically on desktop and mobile. `hidden` cannot be used
 * here (display:none cannot transition), so open/closed is a class, and the
 * element stays in the DOM at all times, offscreen and non-interactive when
 * closed.
 */
.sidebar-backdrop {
  position: fixed;
  inset: 0;
  z-index: 79;
  background: rgb(0 0 0 / 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--m-base) var(--m-ease);
}
.sidebar-backdrop.is-open { opacity: 1; pointer-events: auto; }

.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 80;
  width: min(320px, 88vw);
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  border-right: var(--border);
  transform: translateX(-100%);
  transition: transform var(--m-base) var(--m-ease);
}
.sidebar.is-open { transform: translateX(0); }

.sidebar__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--bar-h);
  padding: var(--s-2) var(--s-3) var(--s-2) var(--s-4);
  border-bottom: var(--border);
  flex: 0 0 auto;
}

.sidebar__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--s-3);
}

.sidebar-section + .sidebar-section { margin-top: var(--s-5); }

.sidebar-section__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-2);
  font-size: var(--t-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
  color: var(--c-ink-fainter);
}
.sidebar-section__count { color: var(--c-ink-fainter); font-weight: var(--w-normal); }

.sidebar-section__add {
  margin-left: auto;
  color: var(--c-ink-faint);
  background: none;
  border: 0;
  cursor: pointer;
  padding: var(--s-1);
  border-radius: var(--r-sm);
  line-height: 1;
}
.sidebar-section__add:hover { color: var(--c-ink); background: var(--c-raise); }

.sidebar-empty {
  padding: var(--s-2);
  font-size: var(--t-xs);
  color: var(--c-ink-fainter);
  font-style: italic;
}

/* One row — a site, or a project's own header row. Shared so a pinned site
   and a listed site look identical; only which section it's in differs. */
.sidebar-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 100%;
  padding: var(--s-2);
  border: 0;
  border-radius: var(--r-md);
  background: none;
  color: var(--c-ink);
  font: inherit;
  font-size: var(--t-sm);
  text-align: left;
  cursor: pointer;
}
.sidebar-row:hover { background: var(--c-raise); }
.sidebar-row.is-active { background: var(--c-accent-soft); color: var(--c-accent); }

.sidebar-row__icon {
  flex: 0 0 auto;
  color: var(--c-ink-fainter);
  display: flex;
}
.sidebar-row__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-row__meta {
  flex: 0 0 auto;
  font-size: var(--t-xs);
  color: var(--c-ink-fainter);
}

.sidebar-pin {
  flex: 0 0 auto;
  color: var(--c-ink-fainter);
  background: none;
  border: 0;
  cursor: pointer;
  padding: var(--s-1);
  border-radius: var(--r-sm);
  line-height: 1;
  opacity: 0;
}
.sidebar-row:hover .sidebar-pin,
.sidebar-pin.is-pinned { opacity: 1; }
.sidebar-pin.is-pinned { color: var(--c-accent); }
.sidebar-pin:hover { background: var(--c-raise); }

.sidebar-project__sites {
  display: flex;
  flex-direction: column;
  padding-left: var(--s-5);
  border-left: 1px solid var(--c-line);
  margin-left: var(--s-4);
}

.sidebar-more {
  width: 100%;
  padding: var(--s-2);
  border: 0;
  background: none;
  color: var(--c-ink-faint);
  font: inherit;
  font-size: var(--t-xs);
  text-align: left;
  cursor: pointer;
  border-radius: var(--r-md);
}
.sidebar-more:hover { background: var(--c-raise); color: var(--c-ink); }

@media (pointer: coarse) {
  .sidebar { width: min(340px, 90vw); }
  .sidebar-pin { opacity: 1; } /* no hover on touch — always visible */
}

/*
 * The layout, in one place.
 *
 * Two rules decide everything and neither of them mentions a phone:
 *
 *   1. A pane below --pane-min is not worth showing, so the number of panes that
 *      fit is a function of the width and that minimum. Above --stack-at two fit;
 *      below it, one does.
 *   2. Any pane can be collapsed to a rail at any width, because "I want the
 *      other one bigger" is a thing people want on a 27-inch screen too.
 *
 * CSS decides; the script only records which pane you chose. Layout that lives in
 * JavaScript disagrees with the viewport the moment anything resizes.
 */
.split {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: minmax(var(--pane-min), var(--pane-pct)) 1fr;
  min-height: 0;
  min-width: 0;
}

/* A collapsed pane keeps its rail; the other takes what is left. */
.split[data-collapsed="thread"] { grid-template-columns: var(--rail) 1fr; }
.split[data-collapsed="side"]   { grid-template-columns: 1fr var(--rail); }

@media (max-width: 54rem) {
  /*
   * One pane at a time. Not stacked halves — two half-height panes on a phone
   * gives you two things you cannot use instead of one you can.
   */
  .split,
  .split[data-collapsed="thread"],
  .split[data-collapsed="side"] { grid-template-columns: 1fr; }
  .split[data-single] > .pane[data-showing="false"] { display: none; }
}

.pane {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

/* ------------------------------------------------------------------ the rail */

/*
 * What a collapsed pane leaves behind: a strip with the pane's name running up
 * it, and the whole strip is the control that brings it back. A collapse you
 * cannot visibly undo is a disappearance.
 */
.rail {
  display: none;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3) 0;
  border: 0;
  background: var(--c-surface);
  color: var(--c-ink-soft);
  font: inherit;
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  writing-mode: vertical-rl;
  cursor: pointer;
}

.rail:hover { color: var(--c-ink); background: var(--c-raise); }

.split[data-collapsed="thread"] .pane--thread > :not(.rail),
.split[data-collapsed="side"] .pane--preview > :not(.rail),
.split[data-collapsed="side"] .pane--local > :not(.rail),
.split[data-collapsed="side"] .pane--method2 > :not(.rail) { display: none; }

.split[data-collapsed="thread"] .pane--thread > .rail,
.split[data-collapsed="side"] .pane--preview > .rail,
.split[data-collapsed="side"] .pane--local > .rail,
.split[data-collapsed="side"] .pane--method2 > .rail { display: flex; }

.pane--thread {
  background: var(--c-surface);
  border-right: var(--border);
}

/* ------------------------------------------------------------------- thread */

.thread {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--s-3) var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

/*
 * A turn reads as a document, not a card.
 *
 * Claude Code renders a conversation with whitespace and a marker rather than a
 * bordered box per message, and it is right: boxes turn a conversation into a
 * log. The prompt gets a rule and slight emphasis; everything after it flows.
 */
.turn {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-bottom: var(--s-3);
  border-bottom: var(--border);
}

.turn:last-child { border-bottom: 0; }

.ask {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding-left: var(--s-3);
  border-left: 2px solid var(--c-line-strong);
}

.ask__who {
  font: var(--w-medium) var(--t-label) / 1 var(--f-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-ink-faint);
}

.ask__text { margin: 0; white-space: pre-wrap; font-weight: var(--w-medium); font-size: var(--t-sm); }

.body { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }

/* ------------------------------------------------------------------- lines */

/*
 * The transcript runs denser than the rest of the interface, on purpose.
 *
 * It is a log of work — tool calls, paths, output — and the value is in seeing a
 * lot of it at once. Body copy comfort is the wrong target here; a terminal is
 * closer to the right one. Everything below is one step down from the app scale.
 */

.ln { margin: 0; min-width: 0; font-size: var(--t-sm); }

/* What Claude says. The only thing set at full reading colour. */
.ln--say { color: var(--c-ink); }

.ln--say .md-p { margin: 0 0 var(--s-2); line-height: 1.5; }
.ln--say .md-p:last-child { margin-bottom: 0; }

.ln--say .md-h {
  margin: var(--s-3) 0 var(--s-1);
  font-size: var(--t-md);
  font-weight: var(--w-medium);
}

.ln--say .md-list { margin: 0 0 var(--s-2); padding-left: var(--s-5); }
.ln--say .md-list li { margin: 1px 0; }

.ln--say .md-quote {
  margin: 0 0 var(--s-2);
  padding-left: var(--s-3);
  border-left: 2px solid var(--c-line);
  color: var(--c-ink-soft);
}

.ln--say a { color: var(--c-accent); text-underline-offset: 2px; }

/* Inline code as a translucent overlay, the way Claude Code does it — it sits on
   whatever is beneath instead of needing a colour picked per surface. */
.md-inline {
  font: var(--t-xs) var(--f-mono);
  background: var(--c-raise);
  border-radius: var(--r-sm);
  padding: 1px 3px;
}

.md-code {
  margin: 0 0 var(--s-2);
  padding: var(--s-2) var(--s-3);
  background: var(--c-sunk);
  border: var(--border);
  border-radius: var(--r-md);
  overflow-x: auto;
  font: var(--t-xs) / 1.5 var(--f-mono);
  color: var(--c-ink-soft);
}

.md-code code { font: inherit; background: none; padding: 0; }

/* Reasoning: present, recessive. There when you look for it. */
.ln--think {
  white-space: pre-wrap;
  color: var(--c-ink-fainter);
  font-size: var(--t-xs);
  padding-left: var(--s-3);
  border-left: 1px solid var(--c-line);
}

/* A tool firing: what it is, then what it touches. One line, always. */
.ln--tool {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  min-width: 0;
  font: var(--t-xs) / 1.5 var(--f-mono);
  color: var(--c-ink-faint);
}

.ln__name { color: var(--c-accent); flex: none; }
.ln__arg { color: var(--c-ink-fainter); }

/* What it returned. Capped and scrollable so one long result cannot bury the
   turn that follows it. */
.ln--out {
  max-height: 9rem;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--s-2);
  background: var(--c-sunk);
  border-radius: var(--r-sm);
  font: var(--t-xs) / 1.45 var(--f-mono);
  color: var(--c-ink-fainter);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.ln--out-bad { color: var(--c-bad); background: var(--c-bad-soft); }

/* The platform's own lines, on the same stream. Set apart by a rule and colour
   rather than a box, so they narrate rather than interrupt. */
.ln--meta {
  font-size: var(--t-xs);
  color: var(--c-ink-faint);
  padding-left: var(--s-3);
  border-left: 2px solid var(--c-line);
}

.ln--good { color: var(--c-good); border-left-color: color-mix(in oklab, var(--c-good) 60%, transparent); }
.ln--warn { color: var(--c-warn); border-left-color: color-mix(in oklab, var(--c-warn) 60%, transparent); }
.ln--bad  { color: var(--c-bad);  border-left-color: color-mix(in oklab, var(--c-bad) 60%, transparent); }

.ln--error {
  font-size: var(--t-xs);
  color: var(--c-bad);
  padding-left: var(--s-3);
  border-left: 2px solid var(--c-bad);
}

.turn__foot { font-size: var(--t-xs); color: var(--c-ink-fainter); }

.turn--live .ask { border-left-color: var(--c-accent); animation: pulse 1.6s ease-in-out infinite; }

@keyframes pulse {
  0%, 100% { border-left-color: var(--c-accent); }
  50% { border-left-color: var(--c-line-strong); }
}

@media (prefers-reduced-motion: reduce) { .turn--live .ask { animation: none; } }

/* ---------------------------------------------------------------- composer */

/*
 * One container, controls beneath the input — Claude Code's arrangement. The
 * border belongs to the container, not the textarea, so the whole thing reads as
 * a single object.
 */
.composer {
  flex: 0 0 auto;
  padding: var(--s-3);
  border-top: var(--border);
}

.composer__box {
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
  background: var(--c-sunk);
  transition: border-color var(--m-fast) var(--m-ease);
}

.composer__box:focus-within { border-color: color-mix(in oklab, var(--c-accent) 55%, var(--c-line)); }
.composer__box.is-busy { opacity: 0.7; }

/* The textarea gives up its own chrome to the container. */
.composer__box .input {
  border: 0;
  background: transparent;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  min-height: 3.5rem;
  font-size: var(--t-md);
}

.composer__box .input:focus-visible { outline: none; }

.composer__attached { padding: var(--s-2) var(--s-2) 0; }

/*
 * The controls under the prompt.
 *
 * Wraps rather than scrolls: these decide what a prompt costs — which model,
 * which plan, whether Claude asks first — and on a phone none of them may be the
 * one that falls off the end of a scroller nobody notices is scrollable.
 *
 * The status is the flexible element, so the controls stay left-anchored in the
 * same order on every draw and only the message gives up room.
 */
.composer__controls {
  padding: var(--s-1) var(--s-2) var(--s-2);
  min-height: 26px;
  row-gap: var(--s-1);
}

/* The plus: square, so it reads as one control rather than a short word. */
.composer__controls .btn--bare {
  min-width: 1.75rem;
  padding-inline: var(--s-2);
  font-size: var(--t-md);
  line-height: 1;
}

/* A finger needs more than a cursor does, and the row has the room once it wraps. */
@media (pointer: coarse) {
  .composer__controls { row-gap: var(--s-2); }
  .composer__controls .chip,
  .composer__controls .btn--bare {
    min-height: 2rem;
    padding-block: var(--s-1);
  }
}

.status { font-size: var(--t-xs); color: var(--c-ink-faint); }
.status--bad { color: var(--c-bad); }
.status--warn { color: var(--c-warn); }

.hint { font-size: var(--t-label); color: var(--c-ink-fainter); white-space: nowrap; }

/* ----------------------------------------------------------------- preview */

.previewbar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--bar-h);
  padding: var(--s-2) var(--s-4);
  background: var(--c-surface);
  border-bottom: var(--border);
  flex: 0 0 auto;
}

.segmented {
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  padding: 2px;
  gap: 2px;
}

.segmented .btn.is-on {
  background: var(--c-ground);
  color: var(--c-ink);
}

/*
 * Desktop is full-bleed: no padding, no frame, no backdrop.
 *
 * Lovable gets this right and it matters more than it sounds — a bordered card
 * floating on a checkerboard reads as a mockup of a site. Flush to the pane, it
 * reads as the site. The backdrop and the frame exist only for mobile, where the
 * viewport genuinely is narrower than the pane and the gap has to be something.
 */
.route {
  height: var(--control-h);
  width: 10rem;
  min-width: 0;
  padding: 0 var(--s-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: var(--c-sunk);
  color: var(--c-ink-faint);
  font: var(--w-normal) var(--t-sm) / 1 var(--f-mono);
}

.route:hover:not(:disabled) { background: var(--c-raise); }
.route:focus-visible { color: var(--c-ink); border-color: var(--c-accent); }
.route:disabled { opacity: 0.4; }

.stage {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: stretch;
  overflow: hidden;
  position: relative; /* anchor the step panel overlay */
}

/* The gated step panel, overlaid on the preview stage. Full-cover while a step
   builds (nothing to preview yet); a docked controls bar at each gate. */
.steppanel {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-5);
  overflow: auto;
  text-align: center;
  background: var(--c-surface);
}
.steppanel .stepgate { width: min(560px, 100%); }
.steppanel--bar {
  inset: auto 0 0 0;
  align-items: stretch;
  justify-content: flex-start;
  text-align: left;
  padding: var(--s-3);
  max-height: 60%;
  background: var(--c-surface);
  border-top: 1px solid var(--c-line);
  box-shadow: 0 -10px 28px rgb(0 0 0 / 0.18);
}
.steppanel--bar .stepgate { width: 100%; }

.stage--mobile {
  place-items: center;
  padding: var(--s-4);
  overflow: auto;
  background:
    repeating-conic-gradient(
      color-mix(in oklab, var(--c-line) 30%, transparent) 0% 25%,
      transparent 0% 50%
    ) 50% / 18px 18px;
}

/*
 * No background here, deliberately.
 *
 * Painting white behind the iframe made the preview lie: a site declaring
 * color-scheme light-dark renders light text in a dark-preferring browser, and
 * white-on-white showed a blank pane. The site paints itself; anything we put
 * underneath is a claim about how it looks that we are not entitled to make.
 */
.frame {
  width: 100%;
  height: 100%;
  overflow: hidden;
  transition: width var(--m-base) var(--m-ease), max-height var(--m-base) var(--m-ease);
}

/* A thin outline and a phone radius. No bezel, no shadow — it is the site, at
   a phone's width, not a picture of a phone. */
.frame--mobile {
  width: 390px;
  max-height: 844px;
  border: 1px solid var(--c-line-strong);
  border-radius: 20px;
}

.frame iframe { width: 100%; height: 100%; border: 0; display: block; }

/* -------------------------------------------------- element picker (facelift) */

/* The highlight box + tag label, drawn in Forge's layer over the same-origin
   preview iframe. Positioned absolutely within the stage. */
.stage.is-picking iframe { cursor: crosshair; }
.pickhl {
  position: absolute;
  pointer-events: none;
  z-index: 20;
  border: 2px solid var(--c-accent);
  background: var(--c-accent-soft);
  border-radius: 2px;
}
.picklabel {
  position: absolute;
  pointer-events: none;
  z-index: 21;
  font-family: var(--f-mono);
  font-size: 11px;
  line-height: 1.3;
  white-space: nowrap;
  background: var(--c-accent);
  color: #fff;
  padding: 1px 5px;
  border-radius: 4px;
  max-width: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The Pick toggle in its active state. */
.previewbar .btn.is-picking { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }

/* The drill breadcrumb: the hovered element's ancestor chain, docked to the bottom of
   the stage while picking. The snapped "meaningful block" (slice 1's default) is the
   active crumb; clicking any other crumb widens or narrows the pick to that ancestor
   and finalizes it immediately — same as clicking the page, just at a different level. */
.pickcrumbs {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 22;
  display: flex;
  align-items: center;
  gap: 2px;
  overflow-x: auto;
  white-space: nowrap;
  padding: var(--s-1) var(--s-2);
  background: var(--c-surface);
  border-top: 1px solid var(--c-line);
  font-family: var(--f-mono);
  font-size: 11px;
}
.pickcrumb {
  flex: 0 0 auto;
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid transparent;
  background: none;
  color: var(--c-ink-faint);
  cursor: pointer;
}
.pickcrumb:hover { background: var(--c-accent-soft); color: var(--c-accent); border-color: var(--c-accent); }
.pickcrumb.is-active { color: var(--c-accent); font-weight: var(--w-medium); border-color: var(--c-accent); }
.pickcrumb-sep { color: var(--c-line); flex: 0 0 auto; }

.builderr {
  flex: 0 0 auto;
  max-height: 34%;
  overflow: auto;
  margin: 0;
  padding: var(--s-3) var(--s-4);
  border-top: var(--border);
  background: var(--c-bad-soft);
  color: var(--c-bad);
  font: var(--t-sm) / var(--lh-body) var(--f-mono);
  white-space: pre-wrap;
}

/* ------------------------------------------------------------------ sheets */

.modes {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  border: var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3);
}

.mode {
  display: flex;
  gap: var(--s-2);
  align-items: flex-start;
  cursor: pointer;
}

.mode strong { display: block; font-weight: var(--w-medium); }
.mode small { display: block; font-size: var(--t-sm); }

.history {
  display: flex;
  flex-direction: column;
  max-height: 50vh;
  overflow-y: auto;
}

.history__row {
  padding: var(--s-2) 0;
  border-top: var(--border);
}

.history__row:first-child { border-top: 0; }

/* ----------------------------------------------------------------- palette */

/*
 * The slash palette. Anchored above the composer rather than centred, because it
 * is a continuation of typing — it should appear where your eyes already are,
 * not pull them to the middle of the screen.
 */
.pal__wrap {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  align-items: end;
  justify-items: start;
  padding: 0 var(--s-3) 5.5rem var(--s-3);
}

.pal {
  width: min(30rem, calc(var(--pane-pct) + 6rem));
  max-width: calc(100vw - var(--s-5));
  background: var(--c-surface);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sheet);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.pal__crumb {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-bottom: var(--border);
}

.pal__here {
  font: var(--w-medium) var(--t-label) / 1 var(--f-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-ink-faint);
}

.pal__back {
  border: 0;
  background: transparent;
  color: var(--c-ink-faint);
  font: var(--w-normal) var(--t-xs) / 1 var(--f-sans);
  cursor: pointer;
  padding: 0;
}

.pal__back:hover { color: var(--c-ink); }

.pal__filter {
  border: 0;
  border-bottom: var(--border);
  background: transparent;
  color: inherit;
  font: var(--w-normal) var(--t-md) / 1 var(--f-sans);
  padding: var(--s-3);
  outline: none;
}

.pal__filter::placeholder { color: var(--c-ink-fainter); }

.pal__list {
  max-height: 15rem;
  overflow-y: auto;
  padding: var(--s-1);
}

.pal__row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: var(--t-sm);
}

/* One highlight, driven by the cursor — hover and arrow keys move the same
   thing, so there is never a second, competing "selected" row. */
.pal__row.is-on { background: var(--c-raise); }

.pal__label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pal__tick { color: var(--c-accent); }
.pal__more { color: var(--c-ink-fainter); }

.pal__none {
  padding: var(--s-3);
  color: var(--c-ink-fainter);
  font-size: var(--t-sm);
}

/* Fixed height, so arrowing through a list does not make the panel jump. */
.pal__detail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-2) var(--s-3);
  border-top: var(--border);
  background: var(--c-sunk);
  min-height: 3.25rem;
}

.pal__dname { font: var(--w-medium) var(--t-xs) / 1.4 var(--f-mono); color: var(--c-ink); }
.pal__ddesc { font-size: var(--t-xs); color: var(--c-ink-faint); line-height: 1.4; }

/* ------------------------------------------------------------------- setup */

.setup__kind {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3);
  border: var(--border);
  border-radius: var(--r-md);
}

.setup__why { margin: 0; font-size: var(--t-sm); }

/* Numbered because these are steps in an order, and the person performs them. */
.setup__how {
  margin: 0;
  padding-left: var(--s-5);
  font-size: var(--t-xs);
  color: var(--c-ink-faint);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.setup__one {
  padding: var(--s-1) var(--s-2);
  background: var(--c-sunk);
  border-radius: var(--r-sm);
  font-size: var(--t-xs);
}

/* ------------------------------------------------------------------ corpus */

/*
 * The method-2 corpus panel. A hierarchical tree — skills, principles,
 * process, library — with per-folder Add and per-file Delete. Nothing else,
 * because the owner's stated primitives are add and delete; anything richer
 * lives in the next iteration when Mohid's prompt-based interface arrives.
 */
.corpus__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  max-height: 60vh;
  overflow-y: auto;
}
.corpus__dir {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
.corpus__dirrow {
  padding: var(--s-1) 0;
  border-top: var(--border);
}
.corpus__dir:first-child > .corpus__dirrow { border-top: 0; }
.corpus__dirname {
  font-size: var(--t-sm);
  color: var(--c-ink);
  font-weight: var(--w-medium);
}
.corpus__children {
  padding-left: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  border-left: 1px dashed var(--c-line);
  margin-left: var(--s-2);
}
.corpus__file {
  padding: 2px 0;
}
.corpus__filename {
  font-size: var(--t-xs);
  color: var(--c-ink);
}
.corpus__size {
  font-size: var(--t-xs);
  font-variant-numeric: tabular-nums;
}

/* -------------------------------------------------------------- local mode */

/* The attribute must win over the display, or a hidden pane still holds a
   column — which is exactly what it did the first time. */
.pane--local[hidden],
.pane--preview[hidden],
.pane--method2[hidden] {
  display: none;
}

.pane--local { display: flex; flex-direction: column; }

/* -------------------------------------------------------------- method-2 */

/*
 * Method-2 sites replace the live preview with a workspace showing the
 * artifact of the current phase. §31 D31.3: the sandbox is empty during
 * intake/research/spine, so nothing meaningful renders through an iframe.
 * The spine is the deliverable and it renders here as a design document.
 */
.pane--method2 { display: flex; flex-direction: column; }
.pane--method2[hidden] { display: none; }

.method2bar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--bar-h);
  padding: var(--s-2) var(--s-4);
  background: var(--c-surface);
  border-bottom: var(--border);
}

.method2bar .phasechip {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--c-raise);
  color: var(--c-ink);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.method2body {
  flex: 1;
  overflow-y: auto;
  padding: var(--s-6) var(--s-5);
  background: var(--c-surface);
}

/*
 * The spine renders like a design document, not JSON. Typography does most of
 * the work — page name as display, beat number as marker, field labels as
 * uppercase tracked meta, argument as body reading type. The left rail on
 * each beat visually chains beats into a single argument.
 */
.spine-page {
  max-width: 62rem;
  margin: 0 auto var(--s-7);
}

.spine-page__head {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--c-line);
  margin-bottom: var(--s-5);
}

.spine-page__name {
  font-size: var(--t-xl);
  font-weight: 500;
  color: var(--c-ink);
  letter-spacing: -0.02em;
}

.spine-page__slug {
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  color: var(--c-ink-soft);
}

.spine-endpoint {
  margin-bottom: var(--s-5);
}

.spine-endpoint__label,
.spine-field__label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--c-ink-soft);
  margin-bottom: var(--s-2);
}

.spine-endpoint__text {
  font-size: var(--t-md);
  line-height: 1.5;
  color: var(--c-ink);
  max-width: 60ch;
}

.spine-beats__label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--c-ink-soft);
  margin: var(--s-6) 0 var(--s-4);
}

.spine-beat {
  display: grid;
  grid-template-columns: 3rem 1fr;
  gap: var(--s-3);
  padding-left: var(--s-1);
  margin-bottom: var(--s-5);
  border-left: 2px solid var(--c-line);
  padding-block: var(--s-2);
  padding-inline-start: var(--s-4);
  position: relative;
}

.spine-beat__ordinal {
  font-family: var(--f-mono);
  font-size: var(--t-md);
  font-weight: 500;
  color: var(--c-ink-soft);
  line-height: 1;
  padding-top: 2px;
}

.spine-beat__body { display: flex; flex-direction: column; gap: var(--s-3); }

.spine-field { display: flex; flex-direction: column; }

.spine-field__text {
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--c-ink);
  max-width: 60ch;
}

.spine-field--handoff .spine-field__label::before {
  content: "↓  ";
  color: var(--c-ink-fainter);
}

.spine-field--handoff .spine-field__text {
  color: var(--c-ink-soft);
  font-style: italic;
}

/* The intake and research views — same document feel, simpler shape. */
.m2doc {
  max-width: 62rem;
  margin: 0 auto;
}

.m2doc__title {
  font-size: var(--t-xl);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--c-ink);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--c-line);
  margin-bottom: var(--s-5);
}

.m2doc__field { margin-bottom: var(--s-4); }
.m2doc__label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--c-ink-soft);
  margin-bottom: var(--s-1);
}
.m2doc__value {
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--c-ink);
  max-width: 68ch;
  white-space: pre-wrap;
}
.m2doc__value--mono {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--c-ink-soft);
}
.m2doc__empty {
  color: var(--c-ink-fainter);
  font-style: italic;
  font-size: var(--t-sm);
}

/* The business-profile block — what the research fan-out actually found,
   set apart from the psychology fields derived from it. */
.m2doc__section {
  padding: var(--s-4);
  margin-bottom: var(--s-5);
  background: var(--c-sunk);
  border-radius: var(--r-md);
}
.m2doc__section .m2doc__field:last-child { margin-bottom: 0; }
.m2doc__pagehead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--c-line);
}
.m2doc__pagehead h3 { font-size: var(--t-md); font-weight: 600; color: var(--c-ink); margin: 0; }
.m2doc__sublabel {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--c-ink-fainter);
  margin-bottom: var(--s-3);
}

.localhead {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.localhead .path {
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  color: var(--c-ink);
  word-break: break-all;
}

.localhead .sub {
  font-size: var(--t-xs);
  color: var(--c-ink-soft);
}

/* Each thing that was checked, and how it came out. The point of this pane is
   that a person can see the join was validated rather than assume it. */
.checks {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.check {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  font-size: var(--t-sm);
  line-height: var(--lh-tight);
}

.check .mark {
  flex: none;
  width: 1rem;
  text-align: center;
  font-weight: var(--w-medium);
}

.check--ok .mark { color: var(--c-good); }
.check--bad .mark { color: var(--c-bad); }
.check .what { color: var(--c-ink); }
.check .detail { color: var(--c-ink-soft); }

.dirlist {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  max-height: 15rem;
  overflow-y: auto;
}

.dirlist button {
  display: flex;
  gap: var(--s-2);
  align-items: baseline;
  justify-content: space-between;
  padding: var(--s-2) var(--s-3);
  border: 0;
  border-bottom: 1px solid var(--c-line);
  background: none;
  color: var(--c-ink);
  font: inherit;
  font-size: var(--t-sm);
  text-align: left;
  cursor: pointer;
}

.dirlist button:last-child { border-bottom: 0; }
.dirlist button:hover { background: var(--c-raise); }
.dirlist .name { font-family: var(--f-mono); }
.dirlist .note { color: var(--c-ink-soft); font-size: var(--t-xs); flex: none; }

.crumbs {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  color: var(--c-ink-soft);
  word-break: break-all;
}

/* Small print inside sheets and the local pane: true but secondary. */
.note {
  font-size: var(--t-xs);
  line-height: var(--lh-tight);
  color: var(--c-ink-soft);
  margin: 0;
}

.note--bad { color: var(--c-bad); }

/* Gated step protocol — the Approve / Rework / Retry gate that stops the composer
   after each bounded step so the person judges it against the preview first. */
.stepgate { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-3); min-width: 0; max-width: 100%; }
.gate__head { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; min-width: 0; }
.gate__head strong { font-size: var(--t-md); overflow-wrap: anywhere; }
.gate__note { color: var(--c-warn); font-size: var(--t-label); line-height: var(--lh-tight); margin: 0; }
.gate__result { font-size: var(--t-xs); line-height: var(--lh-tight); max-height: 12em; overflow-y: auto; overflow-wrap: anywhere; margin: 0; }
.gate__result * { max-width: 100%; overflow-wrap: anywhere; }
.gate__rework { border-top: 1px solid var(--c-line); padding-top: var(--s-3); margin-top: var(--s-1); }
.gate__prompt { width: 100%; box-sizing: border-box; }

/* Empty-sandbox composer: the whole action list as buttons. */
.actions-empty { width: 100%; display: flex; flex-direction: column; gap: var(--s-2); }
.action-btn {
  display: flex; flex-direction: column; gap: var(--s-1); align-items: flex-start;
  text-align: left; width: 100%; box-sizing: border-box; padding: var(--s-3);
  border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-surface); cursor: pointer;
}
.action-btn:hover { border-color: var(--c-line-strong); }
.action-btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 1px; }
.action-btn__name { font-size: var(--t-md); max-width: 100%; overflow-wrap: anywhere; }
.action-btn__desc { line-height: var(--lh-tight); max-width: 100%; overflow-wrap: anywhere; white-space: normal; }

.sheet__section {
  font-size: var(--t-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-ink-soft);
  font-weight: var(--w-medium);
  margin: 0;
}

.sess__title {
  font-size: var(--t-sm);
  line-height: var(--lh-tight);
  color: var(--c-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ------------------------------------------------------------------- gate */

.gate {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  background: var(--c-ground);
}

.gate[hidden] { display: none; }

.gate__card {
  width: min(22rem, calc(100vw - var(--s-6)));
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.gate__brand {
  font-size: var(--t-xl);
  font-weight: var(--w-medium);
  letter-spacing: -0.01em;
  color: var(--c-ink);
}

.gate__why {
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  color: var(--c-ink-soft);
  margin: 0;
}

/* ------------------------------------------------------------------ usage */

.meter {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.meter__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-2);
  font-size: var(--t-xs);
}

.meter__label { color: var(--c-ink); }
.meter__value { color: var(--c-ink-soft); font-variant-numeric: tabular-nums; }

.meter__track {
  height: 4px;
  border-radius: var(--r-full);
  background: var(--c-sunk);
  overflow: hidden;
}

.meter__fill {
  height: 100%;
  background: var(--c-accent);
  border-radius: var(--r-full);
}

/* Colour carries the same information as the number, for a glance rather than
   a read. Warn and bad are the semantic pair already in the tokens. */
.meter--warn .meter__fill { background: var(--c-warn); }
.meter--bad .meter__fill { background: var(--c-bad); }

.usage__plan {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--c-line);
}

.usage__plan:last-child { border-bottom: 0; }

/* ----------------------------------------------------------------- skills */

.skill {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--c-line);
  font-size: var(--t-sm);
}

.skill:last-child { border-bottom: 0; }
.skill__name { font-family: var(--f-mono); color: var(--c-ink); flex: none; }
.skill__desc { color: var(--c-ink-soft); flex: 1 1 auto; min-width: 0; }
/* A trailing tag chip (e.g. a skill's method) keeps its own content — the
   wrapping description column gives up the space instead, so a tag like
   "spine-first" never gets squeezed down to "spin…" (2026-08-22 sweep). */
.skill > .chip { flex: 0 0 auto; }

/* A repository being read: the agent's own transcript, boxed so it reads as
   the platform's evidence rather than as part of the page around it. */
.repo-skill__log {
  max-height: 14rem;
  overflow-y: auto;
  padding: var(--s-2);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-sunk);
}

.repo-skill__body {
  max-height: 20rem;
  overflow: auto;
  padding: var(--s-3);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-sunk);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* A string somebody has to read off a screen and type somewhere else. */
.codeblock {
  font-family: var(--f-mono);
  font-size: var(--t-lg);
  letter-spacing: 0.08em;
  text-align: center;
  padding: var(--s-4);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-sunk);
  color: var(--c-ink);
  user-select: all;
}

/* The pane body inside the local panel, so the rail can be its sibling. */
.pane__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

/* ------------------------------------------------------- responsive detail */

/*
 * The rest of it, grouped by what is actually being responded to — the pointer,
 * the notch, the motion preference — rather than by guessed device widths.
 */

/* Notched phones and gesture bars. Zero everywhere else, so it costs nothing. */
.bar { padding-left: max(var(--s-4), env(safe-area-inset-left)); }
.composer {
  padding-bottom: max(var(--s-3), env(safe-area-inset-bottom));
}

@media (max-width: 54rem) {
  /*
   * The bar holds one row at every width now: the context chip truncates and the
   * rest is a menu, so nothing has to wrap or be squeezed off-screen. It only
   * grows to clear the notch.
   */
  .bar {
    gap: var(--s-2);
    padding-top: max(var(--s-2), env(safe-area-inset-top));
  }
  /* The brand is decorative and the menu icon already says "Forge" — drop it on a
     phone so the context chip and the pane toggle (core nav) always fit. */
  .bar .brand { display: none; }
  /* Never let the toggle get squeezed off — it's how you reach the other pane. */
  .bar .segmented { flex: 0 0 auto; }

  /*
   * A sheet on a phone is a screen, not a card floating on one. Cards that
   * nearly fill the viewport leave a rim of unusable background and a scroll
   * that fights the page's.
   */
  .sheet {
    width: 100%;
    max-width: 100%;
    height: 100%;
    max-height: 100%;
    border-radius: 0;
    margin: 0;
  }
  .sheet__body { max-height: none; }

  .thread { padding: var(--s-3); }

  /*
   * The two pane toolbars carry a field and a handful of buttons. On a phone
   * they wrap to a second row rather than push a control off the edge; the route
   * field takes the first row and the buttons fall in under it.
   */
  .previewbar,
  .method2bar {
    flex-wrap: wrap;
    row-gap: var(--s-2);
    padding-inline: var(--s-3);
  }
  .previewbar .spacer { display: none; }
  .previewbar .route { flex: 1 1 8rem; width: auto; }

  .method2body { padding: var(--s-4) var(--s-3); }

  /*
   * Workbench on a phone. The tab strip (Blocks…Dependencies) scrolls sideways so
   * every vocabulary stays reachable instead of clipping off the edge; the action
   * buttons wrap below it; the body drops its wide desktop padding. The block grid
   * already collapses to a single column via its auto-fill minmax.
   */
  .wb__nav { flex-wrap: wrap; row-gap: var(--s-2); padding: var(--s-3); }
  .wb__nav .spacer { display: none; }
  /* Wrap the tab strip so every vocabulary is visible at once — a browse tool
     shouldn't hide half its sections behind a sideways scroll. */
  .wb__nav .segmented { flex-wrap: wrap; }
  .wb__body { padding: var(--s-4) var(--s-3); }
  .wb__list,
  .wb__groups { max-width: 100%; }
  /* Ribbon: search takes its own row, facets/sort wrap and share the width below. */
  .wb__ribbon { padding: var(--s-2) var(--s-3); gap: var(--s-1) var(--s-2); }
  .wb__search { flex-basis: 100%; }
  .wb__facet { flex: 1 1 8rem; max-width: none; min-width: 0; }
  .wb__ribboncount { margin-left: 0; }
}

/*
 * Touch, not screen size. A mouse is precise on a small screen and a finger is
 * blunt on a large one, so the thing to ask about is the pointer.
 * 44px is the long-standing floor for a reliable touch target.
 */
@media (pointer: coarse) {
  .btn,
  .rail,
  .chip--action,
  .dirlist button,
  .pal__item,
  .menu__item {
    min-height: 44px;
  }
  .btn--sm { min-height: 40px; }
  /* iOS zooms the page when a focused field is under 16px. */
  input, textarea, select { font-size: max(16px, var(--t-sm)); }
}

/* Long unbroken strings — paths, URLs, tokens — must not widen the layout. */
.path, .crumbs, .skill__name, .codeblock { overflow-wrap: anywhere; }

/* -------------------------------------------------- work items (layer 2) */

/* The can't-miss blocker banner: sticky at the top of the thread, so it stays in
   view while the conversation scrolls under it. */
.work-banner {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 100%;
  min-width: 0;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--c-warn);
  border-radius: var(--r-md);
  background: var(--c-warn-soft);
  color: var(--c-warn);
  font-weight: var(--w-normal);
  text-align: left;
  cursor: pointer;
  overflow-wrap: anywhere;
}
.work-banner__dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c-warn);
}

.work-card {
  min-width: 0;
  max-width: 100%;
  padding: var(--s-3);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-surface);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.work-card.is-closed { opacity: 0.62; }
.work-card__title { font-weight: 600; overflow-wrap: anywhere; }
.work-card__body { color: var(--c-ink-faint); white-space: pre-wrap; overflow-wrap: anywhere; }
.work-card__meta { font-size: 0.85em; }
.work-card__reply {
  padding: var(--s-1) var(--s-2);
  border-left: 2px solid var(--c-line);
  overflow-wrap: anywhere;
}
.work-reply { margin-top: var(--s-1); }
.work-composer { padding-top: var(--s-2); }
.work-modality { font-size: 0.85em; }
.work-rule { border: 0; border-top: 1px solid var(--c-line); margin: var(--s-3) 0 0; }
.work-closed > summary { cursor: pointer; color: var(--c-ink-faint); padding: var(--s-1) 0; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* -------------------------------------------------- calendar month view (§50b) */
.cvw { display: flex; flex-direction: column; gap: var(--s-2); }
.cvw-head { display: flex; align-items: center; justify-content: center; gap: var(--s-3); }
.cvw-title { min-width: 11rem; text-align: center; }
.cvw-wd { display: grid; grid-template-columns: repeat(7, 1fr); }
.cvw-wd__d { text-align: center; font-size: var(--t-sm); color: var(--c-ink-faint); padding-bottom: var(--s-1); }
.cvw-weeks { display: flex; flex-direction: column; }
.cw { position: relative; }
.cw-days { display: grid; grid-template-columns: repeat(7, 1fr); min-height: inherit; }
.cw-cell {
  min-height: inherit;
  padding: 2px 4px;
  border-top: 1px solid var(--c-line);
  border-left: 1px solid var(--c-line);
}
.cw-days > .cw-cell:last-child { border-right: 1px solid var(--c-line); }
.cvw-weeks > .cw:last-child .cw-cell { border-bottom: 1px solid var(--c-line); }
.cw-date { font-size: var(--t-sm); color: var(--c-ink-soft); }
.cw-cell--out .cw-date { color: var(--c-ink-fainter); }
.cw-cell--today .cw-date {
  background: var(--c-accent); color: var(--c-ground);
  border-radius: 999px; padding: 0 6px;
}
.cw-bars { position: absolute; inset: 0; pointer-events: none; }
.cw-bar {
  position: absolute;
  height: 17px;
  border-radius: 4px;
  padding: 0 5px;
  display: flex; align-items: center;
  pointer-events: auto;
  overflow: hidden;
}
.cw-bar__t {
  font-size: var(--t-sm);
  color: var(--c-ground);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cw-bar--work-item { background: var(--c-warn); }
.cw-bar--opportunity { background: var(--c-good); }
.cw-bar--checkout { background: var(--c-accent); }

/* -------------------------------------------------- opportunity details (§50a) */
.oppd { display: flex; flex-direction: column; gap: var(--s-4); }
.oppd__group { display: flex; flex-direction: column; gap: var(--s-2); }
.oppd__row { display: flex; gap: var(--s-2); align-items: center; flex-wrap: wrap; }
.oppd__swatch {
  width: 1.4rem; height: 1.4rem; border-radius: var(--r-sm, 4px);
  border: 1px solid var(--c-line); flex: 0 0 auto;
}
.oppd__asset {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-2); border: 1px solid var(--c-line); border-radius: var(--r-md);
}
.oppd__asset img { height: 2rem; width: auto; max-width: 6rem; object-fit: contain; }

/* Queue panel (§52) — the shared input queue, between the thread and the composer. */
.queue { border-top: var(--border); padding: var(--s-2) var(--s-3); max-height: 34vh; overflow-y: auto; flex: 0 0 auto; }
.queue__head { display: flex; align-items: baseline; gap: var(--s-2); margin-bottom: var(--s-1); }
.queue__head .faint { font-size: 0.82em; }
.queue__item { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-1) 0; min-width: 0; }
.queue__who { font-weight: 600; font-size: 0.85em; opacity: 0.8; white-space: nowrap; flex: 0 0 auto; }
.queue__text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.9; }
.queue__item--held .queue__text { opacity: 0.65; }

/* ============================================================ Workbench area
   The content-block library (Mason 2026-08-29) — a full-area sibling of .split,
   shown in its place when the ribbon area is "Workbench". */
.workbench { flex: 1 1 auto; min-height: 0; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
.workbench[hidden] { display: none; }
.wb { display: flex; flex-direction: row; height: 100%; min-height: 0; }
.wb__nav {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-bottom: var(--border);
  flex: 0 0 auto;
}
/* left data-nav + main panel (task #131) */
.wb__side {
  flex: 0 0 216px; width: 216px; overflow-y: auto; min-height: 0;
  border-right: var(--border);
  padding: var(--s-3) var(--s-2);
  display: flex; flex-direction: column; gap: 2px;
}
.wb__navhead {
  font-size: var(--t-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  color: var(--c-ink-faint); font-weight: var(--w-medium);
  padding: var(--s-4) var(--s-2) var(--s-1);
}
.wb__navhead:first-child { padding-top: var(--s-1); }
.wb__navitem { justify-content: flex-start; text-align: left; width: 100%; }
.wb__navitem.is-on { background: var(--c-sunk); color: var(--c-ink); font-weight: var(--w-medium); }
.wb__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.wb__topbar {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-4); border-bottom: var(--border); flex: 0 0 auto;
}
.wb__viewtitle { font-weight: var(--w-medium); font-size: var(--t-md); }
.wb__body { flex: 1 1 auto; overflow: auto; padding: var(--s-5); }

/* build pipeline (task #133) */
.wb__buildrow { cursor: pointer; }
.wb__buildrow:hover { background: var(--c-sunk); }
.wb__stagedots { display: flex; gap: 6px; margin-top: var(--s-1); }
.wb__dot { width: 9px; height: 9px; border-radius: var(--r-full); background: var(--c-ink-faint); display: inline-block; flex: 0 0 auto; }
.wb__dot--locked { background: color-mix(in oklab, var(--c-ink-faint) 55%, transparent); }
.wb__dot--ready { background: var(--c-accent); }
.wb__dot--running { background: var(--c-warn); }
.wb__dot--awaiting { background: var(--c-warn); }
.wb__dot--done { background: var(--c-good); }
.wb__dot--failed { background: var(--c-bad); }
.wb__pill { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--ls-label); padding: 1px var(--s-2); border-radius: var(--r-full); background: var(--c-sunk); color: var(--c-ink-soft); }
.wb__pill--active { color: var(--c-accent); background: var(--c-accent-soft); }
.wb__pill--done { color: var(--c-good); background: color-mix(in oklab, var(--c-good) 14%, transparent); }
.wb__pipeline { display: flex; flex-direction: column; gap: var(--s-3); max-width: none; }
.wb__pipeline--wide .wb__stagepanel { border: none; padding: 0; min-height: 0; }
/* collapsible left nav */
.wb__side--rail { flex: 0 0 40px; width: 40px; align-items: center; padding: var(--s-2) 0; }
.wb__navtop { display: flex; justify-content: flex-end; padding: 0 0 var(--s-1); }
/* build timeline (steps across the top, not a left column) */
.wb__timeline { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; padding-bottom: var(--s-2); border-bottom: var(--border); }
.wb__tlsteps { display: flex; align-items: center; gap: var(--s-1); flex-wrap: wrap; }
.wb__tlstep { display: inline-flex; align-items: center; gap: 6px; padding: var(--s-1) var(--s-2); border: var(--border); border-radius: var(--r-full); background: transparent; cursor: pointer; color: inherit; }
.wb__tlstep:hover { background: var(--c-sunk); }
.wb__tlstep.is-viewing { border-color: var(--c-accent); background: var(--c-accent-soft); }
.wb__tlstep.is-current .wb__tlnum { color: var(--c-accent); font-weight: var(--w-medium); }
.wb__tlnum { font-family: var(--f-mono); font-size: var(--t-xs); color: var(--c-ink-faint); }
.wb__tllabel { font-size: var(--t-sm); }
.wb__tlstep--locked .wb__tllabel { color: var(--c-ink-faint); }
.wb__buildhead { display: flex; align-items: center; gap: var(--s-3); }
.wb__buildtitle { font-weight: var(--w-medium); font-size: var(--t-md); }
.wb__pipebody { display: grid; grid-template-columns: 264px 1fr; gap: var(--s-5); align-items: start; }
.wb__rail { display: flex; flex-direction: column; gap: var(--s-1); }
.wb__railstage {
  display: grid; grid-template-columns: auto auto 1fr; align-items: center; gap: var(--s-1) var(--s-2);
  padding: var(--s-2) var(--s-3); border: var(--border); border-radius: var(--r-md);
  background: transparent; text-align: left; cursor: pointer; width: 100%; color: inherit;
}
.wb__railstage:hover { background: var(--c-sunk); }
.wb__railstage.is-viewing { border-color: var(--c-accent); background: var(--c-accent-soft); }
.wb__railstage.is-current .wb__railnum { color: var(--c-accent); font-weight: var(--w-medium); }
.wb__railnum { font-family: var(--f-mono); font-size: var(--t-xs); color: var(--c-ink-faint); }
.wb__raillabel { font-size: var(--t-sm); }
.wb__railstatus { grid-column: 3; font-size: var(--t-xs); }
.wb__railstage--locked .wb__raillabel { color: var(--c-ink-faint); }
.wb__stagepanel { border: var(--border); border-radius: var(--r-md); padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); min-height: 220px; }
.wb__stagehead { display: flex; align-items: center; gap: var(--s-2); }
.wb__stagetitle { font-weight: var(--w-medium); font-size: var(--t-md); }
.wb__stagenote { font-size: var(--t-sm); line-height: var(--lh-body); margin: 0; }
.wb__stageacts { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: auto; }
.wb__stagework { display: flex; flex-direction: column; gap: var(--s-3); }
.wb__donorprev { border: var(--border); border-radius: var(--r-md); overflow: hidden; background: #fff; }
.wb__donorprev .wb__viewframe { height: 300px; }
.wb__reskinframe { width: 100%; height: 520px; border: var(--border); border-radius: var(--r-md); background: #fff; }
.wb__pipeline--wide { max-width: none; }
.wb__pipeline--wide .wb__reskinframe { height: min(640px, calc(100vh - 320px)); }
.wb__reskinframe--site { height: min(780px, calc(100vh - 210px)); }
.wb__popout { position: fixed; inset: 0; z-index: 200; background: var(--c-sunk); display: flex; flex-direction: column; }
.wb__popbar { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-4); border-bottom: var(--border); flex: 0 0 auto; }
.wb__poptitle { font-weight: var(--w-medium); font-size: var(--t-md); }
.wb__popframe { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
/* research profile */
.wb__profile { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--s-3); align-items: start; }
.wb__pcard { border: var(--border); border-radius: var(--r-md); padding: var(--s-3); display: flex; flex-direction: column; gap: var(--s-2); }
.wb__pcardh { margin: 0; font-size: var(--t-label); text-transform: uppercase; letter-spacing: var(--ls-label); color: var(--c-ink-soft); font-weight: var(--w-medium); }
.wb__kv { display: flex; gap: var(--s-2); font-size: var(--t-sm); align-items: baseline; }
.wb__kv dt { color: var(--c-ink-faint); min-width: 82px; flex: 0 0 auto; }
.wb__kv dd { margin: 0; overflow-wrap: anywhere; }
.wb__plist { margin: 0; padding-left: var(--s-4); font-size: var(--t-sm); display: flex; flex-direction: column; gap: 2px; }
.wb__badge--soft { color: var(--c-ink-soft); background: var(--c-sunk); text-transform: none; letter-spacing: 0; }
.wb__swatch { display: inline-block; border-radius: var(--r-sm); border: 1px solid rgba(128, 128, 128, 0.3); }
.wb__assets { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.wb__assetcell { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.wb__assetimg { width: 76px; height: 50px; object-fit: contain; border: var(--border); border-radius: var(--r-sm); background: #fff; }
.wb__assetimg--none { display: flex; align-items: center; justify-content: center; color: var(--c-ink-faint); }
/* design-language theme gallery */
.wb__themegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); gap: var(--s-4); }
.wb__themecard { border: var(--border); border-radius: var(--r-md); overflow: hidden; padding: 0; background: transparent; cursor: pointer; text-align: left; display: flex; flex-direction: column; color: inherit; }
.wb__themecard:hover { border-color: var(--c-accent); }
.wb__themecard.is-on { border-color: var(--c-accent); box-shadow: 0 0 0 2px var(--c-accent-soft); }
.wb__themethumb { width: 100%; height: 236px; object-fit: cover; object-position: top; display: block; background: #fff; }
.wb__themename { padding: var(--s-2) var(--s-3); font-size: var(--t-sm); font-weight: var(--w-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb__prevlabel { padding: var(--s-1) var(--s-2); font-size: var(--t-xs); color: var(--c-ink-soft); }
/* composed-sections list (the arc, section by section) */
.wb__seclist { display: flex; flex-direction: column; gap: var(--s-2); max-width: 760px; }
.wb__secrow { display: grid; grid-template-columns: auto 96px 1fr auto; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-3); border: var(--border); border-radius: var(--r-md); }
.wb__secnum { font-family: var(--f-mono); font-size: var(--t-xs); color: var(--c-ink-faint); }
.wb__secthumb { width: 96px; height: 60px; object-fit: cover; object-position: top; border-radius: var(--r-sm); background: #fff; border: 1px solid rgba(128,128,128,0.2); }
.wb__secthumb--none { display: flex; align-items: center; justify-content: center; font-size: var(--t-xs); }
.wb__secmain { min-width: 0; }
.wb__seceffect { font-size: var(--t-sm); font-weight: var(--w-medium); }
.wb__secblock { font-size: var(--t-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb__empty { padding: var(--s-6); text-align: center; max-width: 46ch; margin: var(--s-6) auto; }

/* Blocks — a card grid. */
.wb__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--s-4); align-items: start; }
.wb__card {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-4);
  border: var(--border); border-radius: var(--r-lg);
  background: var(--c-surface);
}
.wb__cardtitle { font-weight: var(--w-medium); font-size: var(--t-md); }
.wb__carddesc { font-size: var(--t-sm); line-height: var(--lh-body); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.wb__cardmeta { font-size: var(--t-xs); }
.wb__chiprow { display: flex; flex-wrap: wrap; gap: var(--s-1); }

/* Categories + templates — a plain list. */
.wb__list { display: flex; flex-direction: column; gap: var(--s-2); max-width: 920px; }
.wb__row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: var(--border); border-radius: var(--r-md);
  background: var(--c-surface);
}
.wb__rowmain { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.wb__rowtitle { font-weight: var(--w-medium); }
.wb__slug { font-family: var(--f-mono); font-size: var(--t-xs); color: var(--c-ink-faint); }
.wb__rowdesc { font-size: var(--t-sm); overflow-wrap: anywhere; }
/* A row's header line: title + inline badges + count, wrapping as one structured
   line rather than a vertical dump. Fixes badges stretching full-width (they sat
   as stretched children of the flex-column rowmain). */
.wb__rowhead { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-2); min-width: 0; }
.wb__rowtitle { overflow-wrap: anywhere; }
.wb__count { font-size: var(--t-xs); color: var(--c-ink-faint); white-space: nowrap; }
/* Safety net for any badge still sitting directly in the flex-column rowmain
   (e.g. the Design list): keep it content-width instead of stretched. */
.wb__rowmain > .wb__badge { align-self: flex-start; }
.wb__badge.wb__badge--mode { color: var(--c-ink-soft); background: var(--c-sunk); }
.wb__swatchrow { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); }
.wb__swatchcell { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.wb__swatch--lg { width: 26px; height: 26px; }
.wb__swatchlbl { font-size: 10px; line-height: 1.2; max-width: 8ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Block form — category checkboxes + a code-file editor. */
.wb__cats { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s-1) var(--s-3); }
.wb__catopt { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-sm); }
.wb__files { display: flex; flex-direction: column; gap: var(--s-3); }
.wb__file { display: flex; flex-direction: column; gap: var(--s-1); padding: var(--s-2); border: var(--border); border-radius: var(--r-md); }
.wb__fcode { font-family: var(--f-mono); font-size: var(--t-xs); }

/* Viewing a block's code. */
.wb__viewfile { margin-top: var(--s-3); }
.wb__fname { font-family: var(--f-mono); font-size: var(--t-xs); color: var(--c-ink-soft); margin-bottom: var(--s-1); }
.wb__code { max-height: 340px; overflow: auto; background: var(--c-sunk); border-radius: var(--r-md); padding: var(--s-3); font-family: var(--f-mono); font-size: var(--t-xs); white-space: pre; }

/* Template spine — display + builder. */
.wb__spine { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-top: var(--s-1); }
.wb__spineslot { display: inline-flex; align-items: center; gap: var(--s-1); padding: 2px var(--s-2); border-radius: var(--r-full); background: var(--c-sunk); font-size: var(--t-xs); }
.wb__spinenum { color: var(--c-ink-faint); font-family: var(--f-mono); }
.wb__spinebuilder { display: flex; flex-direction: column; gap: var(--s-1); margin-bottom: var(--s-2); }
.wb__spinerow { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-1) var(--s-2); border: var(--border); border-radius: var(--r-md); }
.wb__spinename { flex: 1 1 auto; }

/* Grouped categories (view + block-form checkboxes). */
.wb__groups { display: flex; flex-direction: column; gap: var(--s-5); max-width: 920px; }
.wb__group { display: flex; flex-direction: column; gap: var(--s-2); }
.wb__grouphead { font-size: var(--t-label); text-transform: uppercase; letter-spacing: var(--ls-label); color: var(--c-ink-soft); font-weight: var(--w-medium); }
.wb__catgroups { display: flex; flex-direction: column; gap: var(--s-3); max-height: 44vh; overflow: auto; padding-right: var(--s-2); }
.wb__catgroup { display: flex; flex-direction: column; gap: var(--s-1); }

/* Blueprint extraction — the live run log. */
.wb__bplogwrap { margin-top: var(--s-2); }
.wb__bplog { max-height: 300px; overflow: auto; background: var(--c-sunk); border-radius: var(--r-md); padding: var(--s-3); font-family: var(--f-mono); font-size: var(--t-xs); white-space: pre-wrap; line-height: var(--lh-body); color: var(--c-ink-soft); }

/* Temlis ingest + method switcher (Mason 2026-08-30) */
.wb__methodsw { display: inline-flex; }
.wb__ingeststatus { font-size: var(--t-label); margin-top: var(--s-2); line-height: var(--lh-body); color: var(--c-ink-faint); }
.wb__ingeststatus.ok { color: var(--c-good); }
.wb__ingeststatus.warn { color: var(--c-warn); }
.wb__ingeststatus.bad { color: var(--c-bad); }
.wb__cardaes { font-size: var(--t-xs); color: var(--c-ink-faint); font-style: italic; }
.wb__aesthetic { font-style: italic; }
.wb__badge { display: inline-block; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--ls-label); color: var(--c-warn); background: var(--c-warn-soft); border-radius: var(--r-sm); padding: 0 var(--s-1); }

/* Block/template previews + design axis (Mason 2026-09-01) */
.wb__cardhead { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s-1) var(--s-2); }
.wb__cardhead .wb__cardtitle { margin-right: auto; }
.wb__badge--parsed { color: var(--c-warn); background: var(--c-warn-soft); }
.wb__badge--approved { color: var(--c-good); background: color-mix(in oklab, var(--c-good) 14%, transparent); }
/* Approval (independent of provenance) + have-code/extracted badges (Mason 2026-09-04). */
.wb__badge--candidate { color: var(--c-warn); background: var(--c-warn-soft); }
.wb__badge--code { color: var(--c-accent); background: var(--c-accent-soft); }
.wb__badge--extracted { color: var(--c-ink-soft); background: var(--c-sunk); }
/* Ribbon: search + facet filters + sort, above every entity list/grid. */
.wb__shell { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.wb__ribbon { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); padding: var(--s-3) var(--s-5); border-bottom: 1px solid var(--c-line); }
.wb__search { flex: 1 1 18rem; min-width: 9rem; padding: var(--s-1) var(--s-2); font: inherit; font-size: var(--t-sm); color: var(--c-ink); background: var(--c-sunk); border: 1px solid var(--c-line); border-radius: var(--r-md); }
.wb__search:focus { outline: none; border-color: var(--c-accent); }
.wb__facet { padding: var(--s-1) var(--s-2); font: inherit; font-size: var(--t-sm); color: var(--c-ink); background: var(--c-sunk); border: 1px solid var(--c-line); border-radius: var(--r-md); max-width: 13rem; }
.wb__facet:focus { outline: none; border-color: var(--c-accent); }
.wb__ribboncount { margin-left: auto; font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
/* Reference-site extraction queue (Mason 2026-09-04). */
.wb__tmplwrap { display: flex; flex-direction: column; gap: var(--s-4); }
.wb__queue { border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-sunk); padding: var(--s-3); display: flex; flex-direction: column; gap: var(--s-2); }
.wb__queuehead { display: flex; align-items: baseline; gap: var(--s-2); }
.wb__queuetitle { font-weight: var(--w-medium); }
.wb__queuehead .faint { margin-left: auto; font-size: var(--t-sm); }
.wb__queuelist { display: flex; flex-direction: column; gap: var(--s-1); }
.wb__qrow { display: flex; align-items: baseline; gap: var(--s-2); padding: var(--s-1) 0; border-top: 1px solid color-mix(in oklab, var(--c-line) 60%, transparent); }
.wb__qrow:first-child { border-top: 0; }
.wb__qhost { font-weight: var(--w-medium); }
.wb__qmeta { margin-left: auto; font-size: var(--t-xs); text-align: right; }
.wb__qstatus { flex: 0 0 auto; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--ls-label); border-radius: var(--r-sm); padding: 0 var(--s-1); min-width: 4.5rem; text-align: center; }
.wb__qstatus--staged { color: var(--c-ink-soft); background: var(--c-sunk); border: 1px solid var(--c-line); }
.wb__qstatus--running { color: var(--c-accent); background: var(--c-accent-soft); animation: pulse 1.6s ease-in-out infinite; }
.wb__qstatus--done { color: var(--c-good); background: color-mix(in oklab, var(--c-good) 14%, transparent); }
.wb__qstatus--error { color: var(--c-bad); background: color-mix(in oklab, var(--c-bad) 14%, transparent); }
/* Assembly (Build view): each slot = a chosen block + its effect/form + a swap. */
.wb__asmslots { display: flex; flex-direction: column; gap: var(--s-2); margin-top: var(--s-2); }
.wb__asmslot { display: flex; gap: var(--s-3); align-items: flex-start; border-top: 1px solid color-mix(in oklab, var(--c-line) 60%, transparent); padding-top: var(--s-2); }
.wb__asmslot:first-child { border-top: 0; padding-top: 0; }
.wb__asmslot .wb__thumb { flex: 0 0 9rem; width: 9rem; }
.wb__asmmeta { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; flex: 1 1 auto; }
.wb__asmhead { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); }
.wb__asmeffect { font-weight: var(--w-medium); }
.wb__asmblock { font-size: var(--t-sm); }
.wb__asmmeta .wb__facet { max-width: 20rem; }
.wb__carddesign { font-size: var(--t-xs); color: var(--c-accent); font-weight: var(--w-medium); }
/* Theme strip on a block card (Mason 2026-09-02): palette swatches, vibe tags, deps. */
.wb__theme { display: flex; flex-direction: column; gap: var(--s-1); margin-top: var(--s-1); }
.wb__swatches { display: flex; flex-wrap: wrap; gap: 3px; }
.wb__swatch { width: 16px; height: 16px; border-radius: 3px; border: 1px solid var(--c-line); flex: 0 0 auto; }
.wb__themetags { font-size: var(--t-xs); color: var(--c-ink-faint); }
.wb__deps { display: flex; flex-wrap: wrap; gap: 4px; }
.wb__depchip { font-size: 10px; line-height: 1.6; padding: 0 6px; border-radius: var(--r-sm); background: var(--c-sunk); border: 1px solid var(--c-line); color: var(--c-ink-soft); font-family: var(--font-mono, monospace); }
.wb__thumb { width: 100%; aspect-ratio: 16 / 10; overflow: hidden; border-radius: var(--r-md); background: var(--c-sunk); border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; }
.wb__thumbimg { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }
.wb__thumb--code { background: var(--c-sunk); }
.wb__thumbtag { font-family: var(--f-mono); font-size: var(--t-xs); color: var(--c-ink-fainter); }
/* Live code thumbnails: the block renders into a 1280x800 viewport pinned top-left
   and is scaled down to the 16:10 box (--wb-thumb-scale = boxWidth/1280). Inert. */
/* Type specimens: a type style rendered in its own face (Type styles view, and
   inside each Theme's preview). */
.wb__specimen { color: var(--c-ink); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb__typeuses { display: flex; flex-direction: column; gap: var(--s-1); align-items: flex-start; }
.wb__typeuse { display: flex; align-items: baseline; gap: var(--s-2); max-width: 100%; min-width: 0; }
.wb__typeuse .wb__specimen { flex: 0 1 auto; min-width: 0; }
.wb__typeuselbl { font-size: var(--t-xs); white-space: nowrap; flex: 0 0 auto; }
.wb__thumb--live { position: relative; background: #fff; }
.wb__thumbframe { position: absolute; top: 0; left: 0; width: 1280px; height: 800px; border: 0; background: #fff; transform-origin: top left; transform: scale(var(--wb-thumb-scale, 0.25)); pointer-events: none; }
.wb__viewprev { width: 100%; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--c-line); background: var(--c-sunk); margin-bottom: var(--s-2); }
.wb__viewimg { width: 100%; display: block; }
.wb__viewframe { width: 100%; height: 420px; border: 0; display: block; background: #fff; }
.wb__prevlabel { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; opacity: .6; margin-bottom: var(--s-1, 6px); }
.wb__viewprev--canon { border: 0; background: transparent; overflow: visible; }
.wb__canonbar { display: flex; align-items: center; justify-content: flex-end; margin-bottom: var(--s-1, 6px); }
.wb__viewprev--canon .wb__viewframe { width: 100%; height: 78vh; border: 1px solid var(--c-line); border-radius: var(--r-md); background: #fff; display: block; }
.wb__buildcard { margin-bottom: var(--s-5, 24px); }
.wb__slotedit { margin-top: var(--s-4, 20px); }
.wb__slotedit > summary { cursor: pointer; padding: var(--s-2, 12px) 0; }
.wb__viewline { color: var(--c-accent); font-weight: var(--w-medium); margin: 0; }
.wb__row--tmpl { align-items: flex-start; gap: var(--s-3); }
.wb__tmplthumb { flex: 0 0 12rem; aspect-ratio: 16 / 10; overflow: hidden; border-radius: var(--r-md); background: var(--c-sunk); border: 1px solid var(--c-line); }

/* ---------------------------------------------------- Build V2 reference UI (§70 D70.8) */
.bv2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr); gap: var(--s-6); align-items: start; padding: var(--s-6); }
.bv2__seq { min-width: 0; display: flex; flex-direction: column; gap: var(--s-5); }
.bv2__seqhead { display: flex; align-items: baseline; gap: var(--s-4); padding-bottom: var(--s-2); }
.bv2__seqtitle { font-size: var(--t-xl); font-weight: var(--w-medium); letter-spacing: -0.01em; color: var(--c-ink); }
.bv2__seqsub { font-size: var(--t-sm); }
.bv2__cards { display: flex; flex-direction: column; gap: var(--s-6); }

.bv2__card { background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-lg); box-shadow: var(--shadow-raise); overflow: hidden; transition: border-color var(--m-base) var(--m-ease), box-shadow var(--m-base) var(--m-ease), opacity var(--m-base) var(--m-ease); }
.bv2__card.is-active { border-color: var(--c-accent); box-shadow: 0 0 0 1px var(--c-accent), var(--shadow-raise); }
.bv2__card.is-complete { border-color: color-mix(in srgb, var(--c-good) 40%, var(--c-line)); }
.bv2__card.is-locked { opacity: 0.55; }
.bv2__cardhead { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-4) var(--s-5); }
.bv2__idx { flex: none; width: 1.6rem; height: 1.6rem; display: grid; place-items: center; border-radius: var(--r-full); background: var(--c-sunk); color: var(--c-ink-faint); font: var(--w-medium) var(--t-xs)/1 var(--f-mono); }
.bv2__card.is-active .bv2__idx { background: var(--c-accent); color: var(--c-accent-ink); }
.bv2__card.is-complete .bv2__idx { background: var(--c-accent-soft); color: var(--c-good); }
.bv2__titles { min-width: 0; flex: 1; }
.bv2__title { font-size: var(--t-md); font-weight: var(--w-medium); color: var(--c-ink); }
.bv2__structure { font-size: var(--t-xs); margin-top: 1px; }
.bv2__badge { flex: none; font: var(--w-medium) var(--t-label)/1 var(--f-sans); letter-spacing: var(--ls-label); text-transform: uppercase; padding: 4px 8px; border-radius: var(--r-full); }
.bv2__badge--done { background: var(--c-accent-soft); color: var(--c-good); }
.bv2__badge--active { background: var(--c-sunk); color: var(--c-ink-faint); }
.bv2__badge--queued, .bv2__badge--running { background: var(--c-warn-soft); color: var(--c-warn); }
.bv2__badge--failed { background: var(--c-bad-soft); color: var(--c-bad); }

.bv2__mainwrap { position: relative; display: block; width: 100%; min-height: min(58vh, 560px); background: var(--c-sunk); border-top: 1px solid var(--c-line); border-bottom: 1px solid var(--c-line); overflow: hidden; }
.bv2__mainwrap.is-empty { cursor: pointer; display: grid; place-items: center; }
.bv2__mainwrap.is-empty:not(.is-locked):hover { background: var(--c-raise); }
.bv2__mainwrap.is-over { box-shadow: inset 0 0 0 2px var(--c-accent); background: var(--c-accent-soft); }
.bv2__mainwrap.is-locked { cursor: default; }
.bv2__main { width: 100%; height: min(58vh, 560px); object-fit: contain; display: block; background: var(--c-sunk); }
.bv2__droph { display: grid; place-items: center; gap: var(--s-3); text-align: center; padding: var(--s-6); pointer-events: none; }
.bv2__dropicon { width: 3rem; height: 3rem; display: grid; place-items: center; border-radius: var(--r-full); border: 1px dashed var(--c-line-strong); font-size: var(--t-xl); color: var(--c-ink-fainter); }
.bv2__droptext { font-size: var(--t-sm); color: var(--c-ink-faint); }

.bv2__thumbs { display: flex; flex-wrap: wrap; gap: var(--s-3); padding: var(--s-4) var(--s-5); }
.bv2__thumb { position: relative; width: 3.5rem; height: 3.5rem; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--c-line); background: var(--c-sunk); cursor: grab; }
.bv2__thumb.is-main { border-color: var(--c-accent); box-shadow: 0 0 0 1px var(--c-accent); }
.bv2__thumbmedia { width: 100%; height: 100%; object-fit: cover; display: block; }
.bv2__thumbx { position: absolute; top: 2px; right: 2px; width: 16px; height: 16px; border: 0; border-radius: var(--r-full); background: rgb(0 0 0 / 0.55); color: #fff; font-size: 11px; line-height: 1; cursor: pointer; display: grid; place-items: center; padding: 0; opacity: 0; transition: opacity var(--m-fast) var(--m-ease); }
.bv2__thumb:hover .bv2__thumbx { opacity: 1; }
.bv2__thumbadd { width: 3.5rem; height: 3.5rem; border: 1px dashed var(--c-line-strong); border-radius: var(--r-md); background: transparent; color: var(--c-ink-fainter); font-size: var(--t-lg); cursor: pointer; }
.bv2__thumbadd:hover { background: var(--c-sunk); color: var(--c-ink-faint); }

.bv2__cardfoot { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-4) var(--s-5); border-top: 1px solid var(--c-line); }
.bv2__cardbtns { display: flex; align-items: center; gap: var(--s-2); margin-left: auto; flex-shrink: 0; }
.scrape__bulkbtns { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; justify-content: flex-end; }
/* Scrape v2 (§72) */
.scrape__list { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-5); }
.scrape__listhead { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; }
.scrape__listtitle { font-size: var(--t-lg); font-weight: 600; }
.scrape__newrow { display: flex; align-items: center; gap: var(--s-2); }
.scrape__newname { padding: var(--s-2) var(--s-3); border: 1px solid var(--c-line); border-radius: var(--r-2, 8px); color: var(--c-ink); background: var(--c-sunk); font: inherit; min-width: 16rem; }
.scrape__newname::placeholder { color: var(--c-faint, #8a8a8a); }
.scrape__cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--s-4); }
.scrape__listcard { border: 1px solid var(--c-line); border-radius: var(--r-3, 12px); padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-2); cursor: pointer; transition: border-color .15s; }
.scrape__listcard:hover { border-color: var(--c-accent, #4b5563); }
.scrape__listcardtitle { font-weight: 600; }
.sv2__intake { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-3); }
.sv2__intaketitle { font-size: var(--t-md, 15px); font-weight: 600; }
.sv2__stages { display: flex; flex-direction: column; gap: var(--s-2); margin: var(--s-3) 0; }
.sv2__stage { display: flex; align-items: center; gap: var(--s-2); }
.sv2__stagelabel { font-size: var(--t-sm, 14px); }
.sv2__stagenote { font-size: var(--t-xs); }
.sv2__body { display: flex; flex-direction: column; gap: var(--s-5); }
.sv2__status { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); }
.bv2__hint { font-size: var(--t-xs); }

/* Scrape v3 embedded session (§73): the Canvas two-pane, inside the Scrape v3 view. Fixed height so the
   composer stays pinned at the bottom, the thread scrolls, and the preview fills its pane. */
.sv3sess { height: calc(100dvh - 9rem); align-items: stretch; }
.sv3sess__left { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: var(--s-4); }
.sv3sess__head { flex: 0 0 auto; }
.sv3sess__body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.sv3sess__intake { flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--s-3); align-items: flex-start; padding: var(--s-5) 0; max-width: 34rem; }
.sv3sess__intaketitle { font-size: var(--t-lg, 17px); font-weight: 600; }
.sv3sess__url { width: 100%; }
.sv3sess__banner { flex: 0 0 auto; display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); padding: var(--s-2) var(--s-3); border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-sunk); }
.sv3sess__thread { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--s-4); padding-right: var(--s-1); }
.sv3sess__composer { flex: 0 0 auto; }
.sv3sess__right { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.sv3sess__frame { position: relative; flex: 1 1 auto; min-height: 0; background: #fff; border: 1px solid var(--c-line); border-radius: var(--r-md); overflow: hidden; }
.sv3sess__frame .bv2__previewframe { width: 100%; height: 100%; border: 0; display: block; background: #fff; }
.sv3sess__previewmsg { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; padding: 2rem; }
@media (max-width: 900px) {
  .sv3sess { height: auto; }
  .sv3sess__thread { height: 50vh; }
  .sv3sess__frame { height: calc(100dvh - 12rem); }
}

.bv2__preview { position: sticky; top: var(--s-6); height: calc(100vh - var(--bar-h) - var(--s-7)); border: 1px solid var(--c-line); border-radius: var(--r-lg); background: var(--c-surface); overflow: hidden; display: flex; flex-direction: column; }
.bv2__previewhead { display: flex; align-items: baseline; gap: var(--s-3); padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--c-line); }
.bv2__previewtitle { font-size: var(--t-sm); font-weight: var(--w-medium); color: var(--c-ink); }
.bv2__previewurl { font-size: var(--t-xs); font-family: var(--f-mono); }
.bv2__previewbody { flex: 1; display: grid; place-items: center; padding: var(--s-6); background: var(--c-sunk); }
.bv2__previewempty { display: grid; place-items: center; gap: var(--s-4); max-width: 22rem; text-align: center; }
.bv2__previewicon { font-size: 2.5rem; color: var(--c-ink-fainter); }
.bv2__previewframe { flex: 1; width: 100%; border: 0; background: #fff; display: block; }

.bv2__msg { display: grid; place-items: center; gap: var(--s-4); padding: var(--s-7); min-height: 40vh; }
.bv2__msgtext { font-size: var(--t-sm); }
.bv2__spinner { width: 1.5rem; height: 1.5rem; border: 2px solid var(--c-line); border-top-color: var(--c-accent); border-radius: var(--r-full); animation: bv2spin 0.7s linear infinite; }
@keyframes bv2spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .bv2__spinner { animation: none; } }

@media (max-width: 60rem) {
  .bv2 { grid-template-columns: 1fr; }
  .bv2__preview { position: static; height: 50vh; }
}

/* thin top step bar (mirrors the v1 build timeline) + step placeholders */
.bv2wrap { display: flex; flex-direction: column; min-height: 100%; }
.bv2__steps { position: sticky; top: 0; z-index: 6; display: flex; align-items: center; gap: var(--s-4); padding: var(--s-3) var(--s-6); border-bottom: 1px solid var(--c-line); background: color-mix(in srgb, var(--c-ground) 82%, transparent); backdrop-filter: saturate(1.4) blur(10px); }
.bv2__steps .wb__tlsteps { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
/* the step bar as a real pipeline: numbered nodes joined by connectors, done→current→upcoming */
.bv2__pipe { display: flex; align-items: center; gap: 0; flex-wrap: wrap; }
.bv2__pstep { display: inline-flex; align-items: center; gap: var(--s-2); background: transparent; border: 0; padding: var(--s-1) var(--s-2); border-radius: var(--r-full); cursor: pointer; color: var(--c-ink-faint); transition: color var(--m-base) var(--m-ease), background var(--m-base) var(--m-ease); }
.bv2__pstep:hover { color: var(--c-ink); }
.bv2__pnode { flex: none; width: 1.4rem; height: 1.4rem; display: grid; place-items: center; border-radius: var(--r-full); border: 1px solid var(--c-line-strong); background: var(--c-surface); color: var(--c-ink-faint); font: var(--w-medium) var(--t-xs)/1 var(--f-mono); transition: background var(--m-base) var(--m-ease), border-color var(--m-base) var(--m-ease), color var(--m-base) var(--m-ease), box-shadow var(--m-base) var(--m-ease); }
.bv2__plabel { font-size: var(--t-xs); white-space: nowrap; }
.bv2__conn { flex: none; width: 1.75rem; height: 2px; border-radius: 2px; background: var(--c-line); margin: 0 2px; }
.bv2__conn.is-done { background: var(--c-accent); }
.bv2__pstep--done { color: var(--c-ink-soft); }
.bv2__pstep--done .bv2__pnode { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-accent-ink); }
.bv2__pstep--current { color: var(--c-ink); }
.bv2__pstep--current .bv2__pnode { border-color: var(--c-accent); color: var(--c-accent); box-shadow: 0 0 0 3px var(--c-accent-soft); }
.bv2__pstep.is-viewing { background: var(--c-sunk); }
.bv2__pipetag { margin-left: auto; font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase; }

/* Build v2 — builds list + thumbnail cards */
.bv2list { padding: var(--s-6); display: flex; flex-direction: column; gap: var(--s-5); }
.bv2__listhead { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.bv2__listtitle { font-size: var(--t-xl); font-weight: var(--w-medium); letter-spacing: -0.01em; color: var(--c-ink); }
.bv2__newname { max-width: 15rem; }
.bv2__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr)); gap: var(--s-5); }
.bv2__buildcard { display: flex; flex-direction: column; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-raise); cursor: pointer; transition: border-color var(--m-base) var(--m-ease), box-shadow var(--m-base) var(--m-ease), transform var(--m-base) var(--m-ease); }
.bv2__buildcard:hover { border-color: var(--c-line-strong); box-shadow: 0 6px 18px rgb(0 0 0 / 0.08); transform: translateY(-1px); }
.bv2__thumbwrap { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: var(--c-sunk); border-bottom: 1px solid var(--c-line); }
.bv2__thumbframe { position: absolute; top: 0; left: 0; width: 250%; height: 250%; border: 0; transform: scale(0.4); transform-origin: top left; pointer-events: none; background: #fff; }
.bv2__thumbempty { position: absolute; inset: 0; display: grid; place-items: center; font-size: 2rem; }
.bv2__buildmeta { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-4) var(--s-5); }
.bv2__buildtext { min-width: 0; flex: 1; }
.bv2__buildname { font-size: var(--t-md); font-weight: var(--w-medium); color: var(--c-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bv2__buildsub { font-size: var(--t-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bv2__listempty { padding: var(--s-7); text-align: center; font-size: var(--t-sm); }
.bv2 { padding-top: var(--s-5); }
.bv2__preview { top: calc(3rem + var(--s-3)); height: calc(100vh - var(--bar-h) - 3rem - var(--s-6)); }

.bv2__placeholder { display: grid; place-items: center; align-content: center; gap: var(--s-3); text-align: center; padding: var(--s-7); min-height: 55vh; max-width: 34rem; margin: 0 auto; }
.bv2__placeholdericon { width: 2.75rem; height: 2.75rem; display: grid; place-items: center; border-radius: var(--r-full); border: 1px solid var(--c-line); color: var(--c-ink-fainter); font-size: var(--t-lg); }
.bv2__placeholdertitle { font-size: var(--t-xl); font-weight: var(--w-medium); color: var(--c-ink); letter-spacing: -0.01em; }
.bv2__placeholdertext { font-size: var(--t-sm); line-height: var(--lh-body); }
.bv2__placeholdernote { font-size: var(--t-xs); }

/* ---- polish pass (§70 D70.8): the active section leads; locked ones stay quiet + scannable ---- */
.bv2__card:hover:not(.is-active):not(.is-locked) { border-color: var(--c-line-strong); box-shadow: 0 2px 10px rgb(0 0 0 / 0.06); }
.bv2__card.is-active .bv2__cardhead { background: var(--c-accent-soft); }
/* Locked (not-yet-reached) sections collapse to a slim dashed row — just the header — so the sequence
   reads at a glance and the eye lands on the one active card. */
.bv2__card.is-locked { opacity: 1; background: transparent; box-shadow: none; border-style: dashed; }
.bv2__card.is-locked .bv2__mainwrap, .bv2__card.is-locked .bv2__thumbs, .bv2__card.is-locked .bv2__cardfoot { display: none; }
.bv2__card.is-locked .bv2__cardhead { padding-block: var(--s-3); }
.bv2__card.is-locked .bv2__idx { background: transparent; box-shadow: inset 0 0 0 1px var(--c-line); color: var(--c-ink-fainter); }
.bv2__card.is-locked .bv2__title { font-weight: var(--w-normal); color: var(--c-ink-faint); }
/* Completed references show a touch shorter than the active drop zone, so the current section stays dominant. */
.bv2__card.is-complete .bv2__mainwrap, .bv2__card.is-complete .bv2__main { min-height: min(42vh, 420px); height: min(42vh, 420px); }
/* Inviting dropzone affordance */
.bv2__dropicon { transition: border-color var(--m-base) var(--m-ease), color var(--m-base) var(--m-ease); }
.bv2__mainwrap.is-empty:hover .bv2__dropicon { border-color: var(--c-accent); color: var(--c-accent); }
.bv2__thumb:hover { border-color: var(--c-line-strong); }
/* Give the current step in the bar a hair more presence without shouting */
.bv2__steps .wb__tlstep.is-current { font-weight: var(--w-medium); }

/* ---- Scrape (§71): capture step + per-page tabs (reuses the .bv2* two-pane + card styling) ---- */
.scrape__capture { display: grid; place-items: center; align-content: center; gap: var(--s-3); text-align: center; padding: var(--s-7); min-height: 55vh; max-width: 34rem; margin: 0 auto; }
.scrape__captureicon { width: 2.75rem; height: 2.75rem; display: grid; place-items: center; border-radius: var(--r-full); border: 1px solid var(--c-line); color: var(--c-ink-fainter); font-size: var(--t-lg); }
.scrape__tabs { display: flex; flex-wrap: wrap; gap: var(--s-2); padding: var(--s-2) 0 var(--s-3); border-bottom: 1px solid var(--c-line); margin-bottom: var(--s-3); }
.scrape__tab { font: inherit; font-size: var(--t-xs); color: var(--c-ink-faint); background: var(--c-sunk); border: 1px solid var(--c-line); border-radius: var(--r-full); padding: var(--s-1) var(--s-3); cursor: pointer; transition: border-color var(--m-base) var(--m-ease), color var(--m-base) var(--m-ease); }
.scrape__tab:hover { border-color: var(--c-line-strong); color: var(--c-ink); }
.scrape__tab.is-active { background: var(--c-accent-soft); border-color: var(--c-accent); color: var(--c-accent); font-weight: var(--w-medium); }
/* Preview mode toggle: Assembled (deterministic) vs Polished (loop-refined) */
.scrape__pvmode { display: flex; gap: var(--s-1); flex: none; }
.scrape__pvbtn { font: inherit; font-size: var(--t-xs); color: var(--c-ink-faint); background: var(--c-sunk); border: 1px solid var(--c-line); border-radius: var(--r-sm); padding: var(--s-1) var(--s-2); cursor: pointer; white-space: nowrap; }
.scrape__pvbtn.is-active { background: var(--c-accent-soft); border-color: var(--c-accent); color: var(--c-accent); font-weight: var(--w-medium); }

/* ---- Build V2 intake (Competitors) + blueprint chooser (§70, task #143) ---- */
.bv2__intake { display: flex; flex-direction: column; gap: var(--s-3); align-items: flex-start; max-width: 40rem; margin: 0 auto; padding: var(--s-7) var(--s-3); }
.bv2__intake .bv2__placeholdertitle { font-size: var(--t-xl); font-weight: var(--w-medium); color: var(--c-ink); letter-spacing: -0.01em; }
.bv2__compinput { width: 100%; resize: vertical; font: inherit; font-size: var(--t-sm); line-height: var(--lh-body); padding: var(--s-3); }
.bv2__complist { width: 100%; display: flex; flex-direction: column; gap: var(--s-1); margin-top: var(--s-2); }
.bv2__comprow { display: flex; justify-content: space-between; gap: var(--s-3); align-items: center; padding: var(--s-2) var(--s-3); border: 1px solid var(--c-line); border-radius: var(--r-sm); background: var(--c-sunk); font-size: var(--t-xs); }
.bv2__comprow.is-parsed { border-color: var(--c-accent); background: var(--c-accent-soft); }
.bv2__compurl { color: var(--c-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bv2__compstatus { flex: none; }
.bv2__blueprint { padding-top: var(--s-5); display: flex; flex-direction: column; gap: var(--s-4); }
/* The "working" state — the felt wait (guided-flow-ux): motion + per-URL progress, not a static form. */
.bv2__proc { display: flex; flex-direction: column; align-items: center; gap: var(--s-3); width: 100%; text-align: center; }
.bv2__proc .bv2__complist { margin-top: var(--s-2); text-align: left; }
.bv2__proc .bv2__comprow { transition: border-color var(--m-base) var(--m-ease), background var(--m-base) var(--m-ease); }
.bv2__procicon { flex: none; width: 1.15rem; display: inline-grid; place-items: center; color: var(--c-ink-fainter); }
.bv2__comprow.is-parsed .bv2__procicon { color: var(--c-accent); }
.bv2__procdone { width: 2.75rem; height: 2.75rem; display: grid; place-items: center; border-radius: var(--r-full); background: var(--c-accent-soft); color: var(--c-accent); font-size: var(--t-lg); }

.bv2__mobtabs { display: none; } /* desktop: no pane tabs — both panes show side by side */

/* ---- Phone width (≤40rem): drive Build v2 + Scrape from a mobile browser ---- */
@media (max-width: 40rem) {
  /* Stepper ribbon: numbered dots joined by connectors, label ONLY the current step, drop the name tag,
     so the whole pipeline + the back button fit one clean row instead of cramming and wrapping. */
  .bv2__steps { gap: var(--s-2); padding: var(--s-2) var(--s-3); }
  .bv2__pstep { padding: var(--s-1); gap: var(--s-1); }
  .bv2__pstep .bv2__plabel { display: none; }
  .bv2__pstep--current .bv2__plabel { display: inline; }
  .bv2__conn { width: 0.8rem; margin: 0 1px; }
  .bv2__pipetag { display: none; }
  /* Two-pane → TABS: only one pane shows, filling the screen and scrolling on its own. Switching is a
     display toggle (not a re-render), so the hidden pane keeps its scroll and the preview iframe keeps
     its scroll + nav. Which pane shows is driven by data-mobpane on .bv2 (= state.mobPane). */
  .bv2 { grid-template-columns: 1fr; padding-inline: var(--s-3); }
  .bv2__mobtabs { display: flex; gap: var(--s-2); position: sticky; top: 2.8rem; z-index: 5; padding: var(--s-2) 0; background: var(--c-ground); }
  .bv2__mobtab { flex: 1; font: inherit; font-size: var(--t-sm); font-weight: var(--w-medium); color: var(--c-ink-faint); background: var(--c-sunk); border: 1px solid var(--c-line); border-radius: var(--r-md); padding: var(--s-2); cursor: pointer; }
  .bv2__mobtab.is-active { background: var(--c-accent-soft); border-color: var(--c-accent); color: var(--c-accent); }
  .bv2__seq, .bv2__preview { height: calc(100dvh - 10rem); overflow-y: auto; -webkit-overflow-scrolling: touch; position: static; }
  .bv2[data-mobpane="left"] .bv2__preview { display: none; }
  .bv2[data-mobpane="right"] .bv2__seq { display: none; }
  .bv2__seqhead { flex-wrap: wrap; gap: var(--s-2); }
  /* Page tabs scroll sideways instead of wrapping into a tall stack. */
  .scrape__tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: var(--s-2); }
  .scrape__tab { flex: none; }
  /* Every stepped surface keeps a real side gutter and never overflows the screen. */
  .bv2__intake, .scrape__capture, .bv2list, .bv2__blueprint { padding-inline: var(--s-3); }
  .bv2__compinput { width: 100%; }
  .wb__body { padding: var(--s-3); }
}
