/* Badge Studio — BRIEF §2.1 tokens verbatim, then design/Main.dc.html's component classes verbatim,
   then the layout / states / responsive rules the mockup did inline (SPEC §3). Light theme only. */

:root {
  color-scheme: light;
  --bg:#f6f4ec; --panel:#fbfaf4; --panel-2:#fdfcf8; --field:#ffffff; --sunk:#eef1f5;
  --line:#ddd8c9; --line-2:#e8e4d6; --line-3:#d5d0c1;
  --text:#1f2421; --ink-2:#44403a; --ink-3:#57534a; --muted:#8a8577; --dim:#9a9585; --faint:#b3ad9b;
  --accent:#35558a; --accent-hi:#243c66; --accent-soft:#7d97c4; --accent-line:#ccd5e4;
  --ok:#2e7d5b; --warn:#a8642a; --warn-bg:#f8ecd9; --bad:#a83232;
  --sans:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --shadow:0 2px 8px rgba(60,55,40,.10); --shadow-pop:0 6px 20px rgba(60,55,40,.18);
  /* SPEC §3.1: the one hex outside BRIEF §2.1 — the stop-note ground. */
  --bad-bg:#f6e3e3;
}

/* ---- base ------------------------------------------------------------------------------------- */

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; overflow: hidden; }
body { background: var(--bg); color: var(--text); font: 14px/1.5 var(--sans); -webkit-font-smoothing: antialiased; }
a { color: var(--accent); text-decoration: none; } a:hover { color: var(--accent-hi); text-decoration: underline; }
button { font: inherit; color: inherit; cursor: pointer; margin: 0; }
button:disabled { cursor: default; opacity: .5; }
h2, h3, p { margin: 0; }
h2 { text-wrap: balance; }
.mono { font-family: var(--mono); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
svg.ico { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* Hit-area rule (SPEC §3.1): visual sizes stay as drawn, the target grows to ≥ 36 × 36 through a pseudo. */
.hit { position: relative; }
.hit::after { content: ''; position: absolute; inset: calc((100% - 36px) / 2); }

/* ---- mockup classes (design/Main.dc.html, verbatim) ------------------------------------------- */

.appbar { display: flex; align-items: center; gap: 12px; height: 54px; padding: 0 20px; background: var(--panel); border-bottom: 1px solid var(--line); flex: none; }
.wordmark { font: 700 15.5px/1 var(--sans); color: var(--text); letter-spacing: -.01em; }
.tagline { font: 400 10.5px/1 var(--mono); color: var(--faint); border-left: 1px solid var(--line); padding-left: 12px; }
.sep { color: var(--line-3); }
.crumb { font: 500 13px/1 var(--sans); color: var(--ink-3); }
.crumb.here { font-weight: 600; color: var(--text); }
.crumb.here .brief { display: none; }
.slug { font: 400 10.5px/1 var(--mono); color: var(--faint); }
.stamp { font: 600 10px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; border: 1.5px solid currentColor; border-radius: 3px; padding: 4px 7px; transform: rotate(-1.5deg); display: inline-block; }
.facet-bar { display: flex; gap: 3px; align-items: center; padding: 6px 14px; flex: none; background: var(--panel); border-bottom: 1px solid var(--line); }
.facet-seg { font: 600 12px/1 var(--sans); color: var(--muted); background: transparent; border: 1px solid transparent; border-radius: 7px; padding: 7px 13px; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.facet-seg .n { font: 500 10.5px/1 var(--mono); color: var(--dim); }
.facet-seg.done { color: var(--ink-3); }
.facet-seg.done .n { color: var(--ok); }
.facet-seg.on { color: #fff; background: var(--accent); border-color: var(--accent); }
.facet-seg.on .n { color: #cfdbf0; }
.icon-btn { font: 500 12px/1 var(--sans); color: var(--ink-3); border: 1px solid var(--line); border-radius: 6px; padding: 7px 10px; background: #fff; display: inline-flex; align-items: center; gap: 6px; }
.icon-btn svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.side-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; font: 600 10.5px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--line-2); }
.steprow { display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px; border-radius: 6px; color: var(--ink-2); }
.steprow .k { font: 500 10.5px/18px var(--mono); color: var(--dim); width: 26px; flex: none; }
.steprow .t { font: 500 12.5px/18px var(--sans); flex: 1; min-width: 0; }
.steprow .s { width: 16px; height: 16px; flex: none; margin-top: 1px; }
.steprow.done { color: var(--ink-3); }
.steprow.done .t { text-decoration: line-through; text-decoration-color: var(--line-3); }
.steprow.on { background: var(--sunk); color: var(--text); }
.steprow.on .t { font-weight: 600; }
.steprow.on .k { color: var(--accent); }
.ws-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: #fff; }
.ws-seg-btn { font: 600 11px/1 var(--sans); color: var(--muted); background: #fff; border: 0; padding: 7px 11px; }
.ws-seg-btn + .ws-seg-btn { border-left: 1px solid var(--line); }
.ws-seg-btn.on { color: #fff; background: var(--accent); }
.legend { display: flex; gap: 14px; align-items: center; font: 500 10.5px/1 var(--mono); color: var(--ink-3); background: rgba(251, 250, 244, .9); border: 1px solid var(--line); border-radius: 6px; padding: 7px 10px; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 6px; vertical-align: -1px; }
/* Stage materials (placed / paste / pad) have no token: BRIEF §2 stage colours. The rest are tokens. */
.legend .sw-step { background: var(--accent); }
.legend .sw-placed { background: #52565c; }
.legend .sw-ghost { border: 1px dashed var(--accent); opacity: .75; }
.legend .sw-paste { background: #8f9296; }
.legend .sw-pad { background: #c9a85a; }
.legend .sw-dnp { border: 1px dashed var(--warn); }
.legend .sw-deferred { background: var(--warn-bg); border: 1px solid var(--warn); }
.legend .sw-far { border: 1px dashed var(--accent); opacity: .85; }
.eyebrow { font: 600 10.5px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
/* Guide anchors are lowercase ids; an uppercased copy is a dead link when transcribed. */
.eyebrow .anchor { text-transform: none; }
.do { display: flex; gap: 10px; align-items: flex-start; font: 400 14px/1.45 var(--sans); color: var(--text); }
.do .box { width: 18px; height: 18px; border: 1.5px solid var(--line-3); border-radius: 4px; flex: none; margin-top: 2px; background: #fff; }
.do.done .box { background: var(--ok); border-color: var(--ok); }
.tile { background: var(--panel-2); border: 1px solid var(--line-2); border-radius: 7px; padding: 9px 11px; display: flex; flex-direction: column; gap: 4px; }
.tile .l { font: 600 9.5px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
.tile .v { font: 600 13px/1.2 var(--sans); color: var(--text); }
.chip { font: 500 11px/1 var(--sans); color: var(--ink-3); background: #fff; border: 1px solid var(--line); border-radius: 999px; padding: 5px 9px; }
.note { display: flex; gap: 9px; align-items: flex-start; padding: 10px 12px; border-radius: 7px; font: 400 12.5px/1.45 var(--sans); }
.note.warn { background: var(--warn-bg); color: #6f4119; }
.note.warn svg { width: 15px; height: 15px; flex: none; margin-top: 1px; stroke: var(--warn); fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.disclosure { display: flex; align-items: center; gap: 8px; padding: 9px 0; border-top: 1px solid var(--line-2); font: 600 12.5px/1 var(--sans); color: var(--ink-2); }
.disclosure svg { width: 12px; height: 12px; stroke: var(--muted); fill: none; stroke-width: 2; }
.disclosure .pv { font: 400 12px/1 var(--sans); color: var(--dim); margin-left: auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.disclosure[aria-expanded="true"] .pv { display: none; }
.btn { font: 600 13px/1 var(--sans); border-radius: 7px; padding: 13px 16px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border: 1px solid var(--line); background: #fff; color: var(--ink-2); min-height: 44px; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.part { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--line-2); border-radius: 7px; background: var(--panel-2); }
.part .sw { width: 10px; height: 10px; border-radius: 2px; background: var(--accent); box-shadow: 0 0 0 3px #dfe7f4; flex: none; }
.part .r { font: 600 12px/1.3 var(--mono); color: var(--text); min-width: 54px; max-width: 45%; flex: none; }
.part .nm { font: 400 12px/1.3 var(--sans); color: var(--ink-3); flex: 1; }
.part .q { font: 500 10.5px/1 var(--mono); color: var(--dim); }
.tl-phase { position: relative; height: 34px; border-radius: 5px; background: var(--panel-2); border: 1px solid var(--line-2); display: flex; align-items: flex-end; padding: 0 4px 5px; gap: 3px; }
.tl-phase.done { background: #e4e9f2; border-color: #d3dbe8; }
.tl-phase.on { background: #fff; border-color: var(--accent-line); }
.tick { flex: 1; height: 10px; border-radius: 1px; background: var(--line); }
.tl-phase.done .tick { background: var(--accent-soft); }
.tl-phase.on .tick.done { background: var(--accent-soft); }
.tl-phase.on .tick.on { background: var(--accent); height: 16px; }
.tl-label { font: 500 10px/1 var(--mono); color: var(--dim); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tl-label.on { color: var(--accent); font-weight: 600; }
.kbd { font: 500 10px/1 var(--mono); color: var(--dim); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 2px 5px; background: #fff; }

/* ---- mockup classes as real controls ---------------------------------------------------------- */

.icon-btn:hover, button.chip:hover, .btn:hover, .tag.count:hover { border-color: var(--line-3); color: var(--text); }
.icon-btn.on { color: var(--accent); border-color: var(--accent-line); }
.btn.primary:hover { background: var(--accent-hi); border-color: var(--accent-hi); color: #fff; }
button.chip { cursor: pointer; }
.disclosure:hover { color: var(--text); }
.disclosure:hover svg { stroke: var(--ink-2); }
.do .box:hover { border-color: var(--accent-soft); }
.do.done .box:hover { border-color: var(--ok); }
.facet-seg:hover { color: var(--ink-2); background: var(--sunk); }
.facet-seg.on:hover { color: #fff; background: var(--accent); }
/* The bar never scrolls at ≥ 1024 (§4.2): chips shrink and their text ellipsises instead — proportionally, so a
   bar that fits truncates nothing, and the current chip is always read in full. */
.facet-seg { flex: 0 1 auto; min-width: 0; }
.facet-seg.on { flex-shrink: 0; }
.facet-seg .n { flex: none; }
.facet-seg .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* phasebar.js drops a chip to its number when the bar cannot fit every name (1024–1100 with the Steps button). */
.facet-seg.n-only { flex: none; }
.facet-seg.n-only .t { display: none; }
.ws-seg-btn:hover { color: var(--ink-2); }
.ws-seg-btn.on:hover { color: #fff; }
.ws-seg-btn:disabled { color: var(--faint); }
/* The row is a list item holding two controls (go · status), not a button with a button inside. */
.steprow .go { display: flex; align-items: flex-start; gap: 10px; flex: 1; min-width: 0; padding: 0; border: 0; background: transparent; text-align: left; color: inherit; border-radius: 4px; }
.steprow:hover { background: var(--sunk); }
.steprow .s { padding: 0; border: 0; background: transparent; border-radius: 50%; display: inline-flex; }
.steprow .s svg { width: 16px; height: 16px; }
.steprow.done .s { color: var(--ok); }
.steprow.on .s { color: var(--accent); }
.steprow:not(.done):not(.on) .s { color: var(--line-3); }
.steprow:not(.done):not(.on) .s:hover { color: var(--accent-soft); }
button.do { width: 100%; border: 0; background: transparent; text-align: left; padding: 0; }
.do .box { padding: 0; position: relative; display: inline-flex; align-items: center; justify-content: center; color: #fff; }
.do .box::after { content: ''; position: absolute; inset: -13px -26px -13px -13px; }
.do .box svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; display: none; }
.do.done .box svg { display: block; }
.do.done > span { color: var(--ink-3); }
button.disclosure { width: 100%; background: transparent; border-left: 0; border-right: 0; border-bottom: 0; text-align: left; }
.disclosure svg { transition: transform 160ms ease-out; }
.disclosure[aria-expanded="true"] svg { transform: rotate(90deg); }
.disclosure-panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 160ms ease-out; }
.disclosure-panel > div { overflow: hidden; min-height: 0; }
.disclosure-panel.open { grid-template-rows: 1fr; }
.disclosure-panel .inner { padding: 2px 0 10px 20px; font: 400 12.5px/1.5 var(--sans); color: var(--ink-2); display: flex; flex-direction: column; gap: 8px; }
.disclosure-panel ul { margin: 0; padding-left: 18px; }
.disclosure-panel .chips { display: flex; gap: 6px; flex-wrap: wrap; }
.part { position: relative; }
button.part { width: 100%; text-align: left; }
.part:hover { border-color: var(--line-3); }
.part:hover .nm { color: var(--ink-2); }
/* The row whose part is under the pointer on the stage (store.hover), so the card answers the board. */
.part.hov { border-color: var(--accent-soft); }
.part.on { border-color: var(--accent-line); background: var(--field); box-shadow: 0 0 0 1px var(--accent-line); }
.part .sw[data-side="front"] { box-shadow: 0 0 0 3px var(--accent-line), inset 0 0 0 2px var(--field); }
.part .sw[data-side="back"] { box-shadow: 0 0 0 3px var(--accent-line); }
.part .q { display: inline-flex; align-items: center; gap: 6px; }
.part .q .chip { padding: 3px 6px; font-size: 10px; }
.tick { position: relative; border: 0; padding: 0; cursor: pointer; min-width: 0; }
.tick::after { content: ''; position: absolute; top: -19px; bottom: -5px; left: -1.5px; right: -1.5px; }
.tl-phase.on .tick.on::after { top: -13px; }
.tick:hover { background: var(--line-3); }
.tl-phase.done .tick:hover, .tl-phase.on .tick.done:hover { background: var(--accent); }
.tl-phase.on .tick.on:hover { background: var(--accent-hi); }
.legend span { display: inline-flex; align-items: center; white-space: nowrap; }
.note svg { width: 15px; height: 15px; flex: none; margin-top: 1px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.note.stop { background: var(--bad-bg); color: var(--bad); }
.note.info { background: var(--sunk); color: var(--ink-2); }
.note.info svg { stroke: var(--muted); }
.note > span { min-width: 0; }
.progress { height: 6px; border-radius: 3px; background: var(--line-2); overflow: hidden; position: relative; }
.progress > i { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width 300ms ease-out; }
.progress > b { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--accent); transition: left 300ms ease-out; }
.stamp.off { color: var(--muted); }
.stamp.complete { color: var(--ok); }
.stamp.front { color: var(--accent); }
.stamp.back { color: var(--warn); }
select.crumb { appearance: none; -webkit-appearance: none; border: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2357534a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") right center / 12px no-repeat; padding: 8px 18px 8px 0; min-height: 36px; cursor: pointer; border-radius: 4px; }
select.crumb:hover { color: var(--text); }

/* ---- app shell (SPEC §3) ----------------------------------------------------------------------- */

.app { height: 100dvh; display: flex; flex-direction: column; overflow: hidden; background: var(--bg); }
.appbar > * { flex: none; white-space: nowrap; }
.appbar .slug { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.appbar .group { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.appbar .pos { font: 500 11.5px/1 var(--mono); color: var(--muted); white-space: nowrap; }
.appbar .progress { width: 140px; }
.appbar .icon-btn .txt { display: inline; }
.appbar .steps-btn { display: none; }
.facet-bar { overflow: hidden; }
.facet-bar .steps-btn { display: none; margin-right: 6px; }
.body { flex: 1; min-height: 0; display: grid; grid-template-columns: 292px minmax(0, 1fr) 372px; position: relative; }

/* left rail */
.rail { display: flex; flex-direction: column; min-height: 0; background: var(--panel); border-right: 1px solid var(--line); }
.rail-head { padding: 18px 16px 14px; border-bottom: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 8px; }
.rail-head .num { display: flex; align-items: baseline; gap: 10px; }
.rail-head .num .n { font: 600 30px/1 var(--mono); color: var(--accent); }
.rail-head .num h2 { font: 600 16px/1.2 var(--sans); color: var(--text); }
.rail-head p { font: 400 12.5px/1.45 var(--sans); color: var(--ink-3); }
.rail-head .chips { display: flex; gap: 6px; flex-wrap: wrap; }
.side-head .cnt { letter-spacing: 0; text-transform: none; font-weight: 500; }
.rail-steps { flex: 1; min-height: 0; overflow: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.rail-foot { padding: 12px 14px; border-top: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 8px; }
.rail-foot .nums { display: flex; justify-content: space-between; font: 500 12px/1 var(--mono); color: var(--ink-3); }
.rail-foot .nums .ok { color: var(--ok); }
.rail-foot .progress { height: 4px; }
.rail-foot .progress > i { background: var(--ok); }
.rail.popover { display: none; }

/* stage */
.stage { position: relative; min-width: 0; min-height: 0; overflow: hidden; background-color: #f1efe6; background-image: radial-gradient(circle, #e3dfd0 1px, transparent 1.4px); background-size: 20px 20px; background-position: 10px 10px; }
.stage-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
#stage-2d { cursor: grab; }
.webgl-off #stage-3d { display: none; }
.stage-skeleton { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.stage-skeleton .board { position: relative; width: min(72%, calc(72vh * 100 / 54)); aspect-ratio: 100 / 54; border-radius: 10px; background: var(--sunk); box-shadow: var(--shadow); }
.stage-skeleton .stage-progress { position: absolute; left: 0; bottom: 0; height: 2px; width: 0; background: var(--accent); border-radius: 1px; transition: width 300ms ease-out; }
.stage-skeleton .fail { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 12px; pointer-events: auto; font: 500 13px/1.4 var(--sans); color: var(--ink-2); }

/* HUD */
.hud { position: absolute; inset: 0; pointer-events: none; }
.hud > * { pointer-events: auto; }
/* The two top corners are one row that wraps: on a stage too narrow for controls + pills (616 px at 1280) the
   pills drop under the controls instead of covering the Labels button. Pointer events pass through the row itself. */
.hud-top { position: absolute; top: 14px; left: 16px; right: 16px; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 8px 16px; pointer-events: none; }
.hud-top > * { pointer-events: auto; }
.hud-tl { display: flex; gap: 8px; align-items: center; }
.hud-tr { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
/* The legend shares the bottom row with the 190 px mini-map; on a narrow stage it wraps instead of running under it. */
.hud-bl { position: absolute; bottom: 14px; left: 16px; display: flex; flex-direction: column; gap: 8px; max-width: calc(100% - 238px); }
.legend { flex-wrap: wrap; row-gap: 6px; }
.hud-br { position: absolute; bottom: 14px; right: 16px; }
.pill { font: 500 11px/1 var(--mono); color: var(--muted); background: rgba(251, 250, 244, .9); border: 1px solid var(--line); border-radius: 6px; padding: 7px 10px; white-space: nowrap; }
/* The mockup's hint line is one muted run; `b` only marks the key word for the markup. */
.pill.hint b { font-weight: 500; color: inherit; }
.pill.hint i { display: inline-block; width: 18px; }
.pill.notice { color: var(--warn); border-color: #e9d6bd; }
.pill.notice.quiet { color: var(--muted); border-color: var(--line); }
.minimap { width: 190px; height: 108px; background: rgba(251, 250, 244, .92); border: 1px solid var(--line); border-radius: 7px; padding: 8px; display: flex; flex-direction: column; gap: 5px; }
.minimap-head { display: flex; justify-content: space-between; font: 600 9.5px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
.minimap canvas, .minimap-shot { display: block; width: 174px; height: 78px; background: #f1efe6; border-radius: 3px; object-fit: cover; }
.minimap [hidden] { display: none; }
.hud .layer { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.hud .fig-slot { overflow: visible; }
.hud-figure { pointer-events: auto; }
.notice-narrow { display: none; }
.callout { position: relative; pointer-events: none; transition: opacity 120ms ease-out; }
.callout[hidden] { display: none; }
.callout-leader { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.callout-leader line { stroke: var(--accent); stroke-width: 1; }
.callout.far .callout-leader line { stroke-dasharray: 4 3; }
.callout-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%; background: var(--panel); border: 1.5px solid var(--accent); transform: translate(-50%, -50%); box-sizing: content-box; }
.callout-card { position: relative; pointer-events: auto; background: var(--panel); border: 1px solid var(--accent-line); border-radius: 6px; padding: 9px 12px; display: flex; flex-direction: column; gap: 5px; max-width: 300px; }
.callout-card .t { font: 600 12.5px/1.2 var(--sans); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* hud.js: a name that still overflows once its qualifiers are trimmed takes two lines rather than an ellipsis. */
.callout-card .t.wrap { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.callout-card .d { font: 400 10.5px/1.35 var(--mono); color: var(--ink-3); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.callout.far .callout-card { border-style: dashed; }
/* A paste or reflow step has one callout for the whole set; a leader to the middle of the board would point at nothing. */
.callout.summary .callout-leader, .callout.summary .callout-dot { display: none; }
.callout.far .callout-card .d { color: var(--accent); }
.tag { position: absolute; transform: translate(-50%, -100%); font: 600 9.5px/1 var(--mono); letter-spacing: .06em; text-transform: uppercase; padding: 4px 7px; border-radius: 4px; white-space: nowrap; pointer-events: none; transition: opacity 120ms ease-out; }
.tag.deferred { background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn); }
.tag.dnp { background: var(--warn-bg); color: var(--warn); border: 1px dashed var(--warn); }
.tag.count { position: static; transform: none; pointer-events: auto; cursor: pointer; background: #fff; color: var(--ink-3); border: 1px solid var(--line); align-self: flex-end; }
.label { position: absolute; transform: translate(-50%, -50%); font: 500 10px/1 var(--mono); color: var(--ink-2); background: rgba(251, 250, 244, .85); padding: 1px 3px; border-radius: 2px; pointer-events: none; white-space: nowrap; }
.callouts { position: absolute; right: 16px; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; pointer-events: none; }
.scalebar { position: absolute; display: flex; flex-direction: column; gap: 3px; align-items: flex-start; pointer-events: none; }
.scalebar i { display: block; height: 1.5px; background: var(--muted); }
.scalebar i::before, .scalebar i::after { content: ''; position: absolute; top: -3px; width: 1.5px; height: 6px; background: var(--muted); }
.scalebar i { position: relative; }
.scalebar i::before { left: 0; } .scalebar i::after { right: 0; }
.scalebar span { font: 500 10px/1 var(--mono); color: var(--muted); }
.hud-figure { position: absolute; left: 50%; bottom: var(--hud-lift, 14px); transform: translateX(-50%); max-width: 46%; max-height: 52%; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow-pop); padding: 12px 14px 10px; display: flex; flex-direction: column; gap: 6px; overflow: hidden; margin: 0; }
.hud-figure .icon-btn { position: absolute; top: 8px; right: 8px; padding: 6px; }
.hud-figure .art { flex: none; }
.hud-figure .art svg { max-height: calc(52vh - 70px); }
.hud-figure .figcap { flex: 0 1 auto; min-height: 0; overflow-y: auto; }

/* step card */
.stepcard { display: flex; flex-direction: column; min-height: 0; background: var(--panel); border-left: 1px solid var(--line); position: relative; }
/* The outgoing card, cloned by stepcard.js for the cross-fade: an opaque layer over the incoming body, gone in 180 ms. */
.card-body.ghost { position: absolute; top: 0; left: 0; right: 0; z-index: 2; overflow: hidden; background: var(--panel); pointer-events: none; }
.card-body.ghost.out { animation: fade-out 180ms ease-out forwards; }
.card-body { flex: 1; min-height: 0; overflow: auto; padding: 18px 18px 12px; display: flex; flex-direction: column; gap: 14px; }
.card-body .head { display: flex; flex-direction: column; gap: 8px; }
.card-body .eyebrow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.card-body .eyebrow .n { color: var(--accent); }
.card-body h2 { font: 600 20px/1.2 var(--sans); color: var(--text); }
.dos { display: flex; flex-direction: column; gap: 10px; }
/* The hover ground grows 2 px past the glyphs without moving them: a padded ref opened a gap before "'s" and ",". */
.do .ref { font: 600 .95em var(--mono); color: var(--accent); cursor: pointer; border-radius: 3px; padding: 0 2px; margin: 0 -2px; }
.do .ref:hover { background: var(--accent-line); }
.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.tiles[data-n="1"] { grid-template-columns: minmax(0, 1fr); }
.tiles[data-n="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tiles[data-n="4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tile.wide { grid-column: 1 / -1; }
/* Tiles sit in a 2 × 2 grid of numbers; the fallback sans has proportional figures (Plex is tabular by default). */
.tile .v { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-variant-numeric: tabular-nums; }
.notes { display: flex; flex-direction: column; gap: 8px; }
.disclosures { display: flex; flex-direction: column; border-bottom: 1px solid var(--line-2); }
.parts { display: flex; flex-direction: column; gap: 8px; }
.parts .eyebrow { display: flex; justify-content: space-between; align-items: center; }
.parts .eyebrow .chip { letter-spacing: 0; text-transform: none; }
.parts .more { align-self: flex-start; }
/* The folded form of the part rows (stepcard.js FOLDS): every group as a ref chip, the name on hover. */
.parts .strip { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.part.mini { width: auto; display: inline-flex; gap: 6px; padding: 4px 9px 4px 7px; border-radius: 999px; }
.part.mini .sw { width: 8px; height: 8px; box-shadow: 0 0 0 2px #dfe7f4; }
.part.mini .sw[data-side="front"] { box-shadow: 0 0 0 2px var(--accent-line), inset 0 0 0 2px var(--field); }
.part.mini .sw[data-side="back"] { box-shadow: 0 0 0 2px var(--accent-line); }
.part.mini .r { min-width: 0; max-width: none; font-size: 11.5px; }
.part.mini .nm { display: none; }
.part.mini .q { font-size: 10px; }
/* A recorded value (data[].field): the bench's own number, typed into the tile and kept per board. */
.tile .rec, .disclosure-panel li .rec { font: 600 13px/1.2 var(--mono); color: var(--text); background: transparent; border: 0; border-bottom: 1px dashed var(--line-3); border-radius: 0; padding: 3px 0; width: 100%; min-width: 0; font-variant-numeric: tabular-nums; }
.tile .rec::placeholder, .disclosure-panel li .rec::placeholder { color: var(--faint); font-weight: 400; }
.tile .rec:focus-visible, .disclosure-panel li .rec:focus-visible { outline: none; border-bottom-color: var(--accent); }
.tile.rec .v { color: var(--ink-3); font-weight: 500; }
.disclosure-panel li .rec { display: inline-block; width: 9em; margin-left: 6px; }
/* Dense (stepcard.js FOLDS): the compact vocabulary for a 504 px budget — the same card, 30 % shorter, and the
   disclosure rows as one chip row with their panels stacked beneath. */
.card-body.dense { gap: 10px; padding: 14px 14px 10px; }
.card-body.dense .head { gap: 6px; }
.card-body.dense h2 { font-size: 18px; }
.card-body.dense .dos { gap: 7px; }
.card-body.dense .do { font-size: 13px; line-height: 1.4; }
.card-body.dense .do .box { margin-top: 1px; }
.card-body.dense .tile { padding: 6px 9px; gap: 2px; }
.card-body.dense .note { padding: 8px 10px; font-size: 12px; line-height: 1.4; }
.card-body.dense .parts { gap: 6px; }
.card-body.dense .part { padding: 6px 10px; }
.disclosures.dense { border-bottom: 0; }
.disc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip.disc { font-weight: 600; color: var(--ink-2); }
.chip.disc[aria-expanded="true"] { color: var(--accent); border-color: var(--accent-line); background: var(--sunk); }
.chip.disc.warn { color: #6f4119; background: var(--warn-bg); border-color: #e9d6bd; }
.chip.disc.stop { color: var(--bad); background: var(--bad-bg); border-color: #e6c4c4; }
.disclosures.dense .disclosure-panel .inner { padding: 8px 0 4px; }
.card-foot { padding: 12px 18px 16px; border-top: 1px solid var(--line-2); display: grid; grid-template-columns: 1fr 2fr; gap: 8px; background: var(--panel); }
/* Done — next step's beat: the label yields to a check for 220 ms, then the step advances (stepcard.js). */
.btn.primary { position: relative; }
.btn.primary.beating { color: transparent; }
.btn.primary .beat { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; pointer-events: none; }
.btn.primary .beat svg { width: 18px; height: 18px; stroke-width: 2.4; }
.btn.primary.beating .beat svg { animation: beat-pop 220ms ease-out both; }
.card-nudge { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px; border-radius: 7px; background: var(--sunk); font: 500 12.5px/1.3 var(--sans); color: var(--ink-2); }
.card-nudge .btn { min-height: 36px; padding: 8px 12px; }

/* timeline */
.timeline { flex: none; height: 96px; background: var(--panel); border-top: 1px solid var(--line); padding: 12px 20px 10px; display: flex; flex-direction: column; gap: 6px; position: relative; }
.tl-grid { display: grid; gap: 6px; position: relative; }
.tl-labels { display: grid; gap: 6px; align-items: center; }
.tl-playhead { position: absolute; top: -12px; bottom: -4px; width: 2px; background: var(--accent); pointer-events: none; transition: left 200ms ease-out; }
.tl-pill { position: absolute; top: -26px; background: var(--accent); color: #fff; font: 600 10px/1 var(--mono); padding: 4px 7px; border-radius: 4px; white-space: nowrap; cursor: grab; user-select: none; transition: left 200ms ease-out; touch-action: none; z-index: 1; }
.tl-grid.scrubbing .tl-playhead, .tl-grid.scrubbing .tl-pill { transition: none; }
.tl-grid.scrubbing .tl-pill { cursor: grabbing; }
.tl-grid.scrubbing .tick { transition: none; }
.tl-keys { position: absolute; right: 20px; bottom: 14px; display: flex; gap: 6px; align-items: center; font: 400 10px/1 var(--mono); color: var(--faint); }
.tl-keys i { display: inline-block; width: 8px; }
.tl-track { display: none; }

/* drawers */
.scrim { position: fixed; inset: 0; background: rgba(31, 36, 33, .22); opacity: 0; transition: opacity 180ms ease-out; pointer-events: none; z-index: 30; }
.scrim.open { opacity: 1; pointer-events: auto; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: 480px; max-width: 100%; background: var(--panel); border-left: 1px solid var(--line); box-shadow: var(--shadow-pop); transform: translateX(100%); transition: transform 220ms ease-out; display: flex; flex-direction: column; z-index: 31; }
.drawer.open { transform: none; }
.drawer[hidden] { display: none; }
.drawer-head { display: flex; align-items: flex-start; gap: 12px; padding: 16px 18px 12px; border-bottom: 1px solid var(--line-2); }
.drawer-head .titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.drawer-head h2 { font: 600 18px/1.25 var(--sans); color: var(--text); }
.drawer-head .sub { font: 400 12.5px/1.4 var(--sans); color: var(--muted); }
.drawer-head .eyebrow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.drawer-head .eyebrow a { display: inline-flex; align-items: center; gap: 4px; letter-spacing: .06em; }
.drawer-head .icon-btn { padding: 6px; }
.drawer-body { flex: 1; min-height: 0; overflow: auto; padding: 16px 18px 24px; display: flex; flex-direction: column; gap: 12px; }
.drawer-foot { padding: 12px 18px 16px; border-top: 1px solid var(--line-2); display: flex; gap: 8px; justify-content: flex-end; }
.drawer-tabs { display: flex; gap: 3px; padding: 8px 18px 0; border-bottom: 1px solid var(--line-2); }
.drawer-tabs .facet-seg { border-radius: 7px 7px 0 0; }
.drawer .pmeta { font: 500 11px/1.5 var(--mono); color: var(--muted); }
.drawer .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.drawer .tile .note-s { font: 400 11px/1.3 var(--sans); color: var(--muted); }
.drawer .list { display: flex; flex-direction: column; gap: 6px; }
.drawer .row { display: flex; gap: 10px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--line-2); border-radius: 7px; background: var(--panel-2); font: 400 12.5px/1.4 var(--sans); color: var(--ink-2); }
.drawer .row .r { font: 600 12px/1.4 var(--mono); color: var(--text); min-width: 54px; }
.drawer .row .mpn { font: 400 11px/1.4 var(--mono); color: var(--muted); }
.drawer .row .hint { font: 400 11.5px/1.4 var(--sans); color: var(--muted); }
.drawer .row .grow { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.drawer .row .why { font: 400 11.5px/1.4 var(--sans); color: var(--muted); }
.drawer .row .more { font: 400 11.5px/1.4 var(--sans); color: var(--dim); }
.drawer-head h2:focus { outline: none; }
.disclosure-panel .note-s { color: var(--muted); }
.drawer .row .box { width: 18px; height: 18px; border: 1.5px solid var(--line-3); border-radius: 4px; flex: none; margin-top: 1px; background: #fff; padding: 0; position: relative; display: inline-flex; align-items: center; justify-content: center; color: #fff; }
.drawer .row .box::after { content: ''; position: absolute; inset: -9px; }
.drawer .row .box svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; display: none; }
.drawer .row .box[aria-checked="true"] { background: var(--ok); border-color: var(--ok); }
.drawer .row .box[aria-checked="true"] svg { display: block; }
.drawer .row .box:disabled { opacity: .6; }
.drawer .row.checked .item { color: var(--ink-3); text-decoration: line-through; text-decoration-color: var(--line-3); }
.drawer .group-head { display: flex; justify-content: space-between; align-items: baseline; margin-top: 6px; }
.drawer .group-head .cnt { font: 500 10.5px/1 var(--mono); color: var(--dim); }
.drawer .summary { font: 500 11px/1.4 var(--mono); color: var(--muted); padding: 2px 10px; }
.drawer ol.rules { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; font: 400 13.5px/1.5 var(--sans); color: var(--ink-2); }
.drawer ol.rules li::marker { font: 600 11px var(--mono); color: var(--accent); }
.drawer table.keys { border-collapse: collapse; width: 100%; }
.drawer table.keys td { padding: 7px 4px; border-bottom: 1px solid var(--line-2); font: 400 12.5px/1.4 var(--sans); color: var(--ink-2); vertical-align: top; }
/* The key column hugs its widest chord (Shift ← →) so the descriptions start beside the keys, not at mid-drawer. */
.drawer table.keys td:first-child { white-space: nowrap; width: 1%; padding-right: 20px; }
.drawer table.keys .kbd { margin-right: 4px; }
.drawer .trap { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border-radius: 7px; background: var(--bad-bg); color: var(--bad); font: 400 12.5px/1.45 var(--sans); }
.drawer .trap .n { font: 600 10.5px/1.4 var(--mono); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.drawer .trap .grow { flex: 1; display: flex; flex-direction: column; gap: 6px; }
.drawer .trap .links { display: flex; gap: 6px; flex-wrap: wrap; }
/* Term and definition sit as a pair: a uniform gap made every line equidistant and the list read as one column. */
.drawer dl.glossary { margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; }
.drawer dl.glossary dt { font: 600 13px/1.3 var(--sans); color: var(--text); }
.drawer dl.glossary dt:not(:first-child) { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-2); }
.drawer dl.glossary dd { margin: 0; font: 400 12.5px/1.45 var(--sans); color: var(--ink-2); }
.drawer .symptom .inner { padding-left: 20px; }
.drawer .symptom .refs { display: flex; gap: 6px; flex-wrap: wrap; }
.drawer .symptom .chip.ref { font-family: var(--mono); font-weight: 600; color: var(--accent); }
.drawer .symptom .k { font: 600 10px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--dim); margin-bottom: 4px; }
.drawer .disclosures { border-bottom: 0; }
.drawer .disclosure .pv { max-width: 200px; }
.popover-actions { display: flex; gap: 6px; margin-top: 8px; }
.popover-actions .btn { min-height: 32px; padding: 6px 10px; font-size: 12px; }
/* The Kit foot: a line of context on the left, the Reset button on the right (SPEC §4.10). */
.drawer-foot .foot-note { margin-right: auto; align-self: center; font: 400 11.5px/1.4 var(--sans); color: var(--muted); }

/* confirm popover (SPEC §4.10): the ghost popover's card with a heading and the app's one destructive button. It
   lives inside the drawer (its host, z-index 31), above everything the drawer holds; the sheet under it is the
   modal's outside — transparent, the whole viewport, scrim and page included — and takes the dismissing press and
   the click that follows, so nothing underneath reacts. Fades in like a callout (§3.3). */
.popover-backdrop { position: fixed; inset: 0; z-index: 40; touch-action: none; }
.popover { position: fixed; z-index: 41; width: 320px; max-width: calc(100vw - 8px); background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow-pop); padding: 14px 16px 12px; white-space: normal; animation: fade-in 120ms ease-out; }
.popover h2 { font: 600 14px/1.3 var(--sans); color: var(--text); margin: 0 0 6px; }
.popover p { font: 400 12.5px/1.5 var(--sans); color: var(--ink-2); margin: 0; }
.popover .popover-actions { justify-content: flex-end; margin-top: 14px; gap: 8px; }
.popover .popover-actions .btn { min-height: 36px; padding: 8px 14px; font-size: 12.5px; }
/* Destructive primary. Hover darkens through an inset shade rather than a second red (one token, BRIEF §2.1). */
.btn.danger { background: var(--bad); border-color: var(--bad); color: #fff; }
.btn.danger:hover, .btn.danger:active { background: var(--bad); border-color: var(--bad); color: #fff; box-shadow: inset 0 0 0 99px rgba(0, 0, 0, .12); }

/* figures (SPEC §4.7): the guide's palette lives only inside .figure-scope; figures.css is rescoped at runtime */
.figure-scope { --ground: #F1F3EE; }
#fig-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
figure.figure { margin: 0; padding: 12px; border: 1px solid var(--line-2); border-radius: 8px; background: #FAFBF7; display: flex; flex-direction: column; gap: 8px; }
figure.figure .art svg { width: 100%; height: auto; display: block; }
.figcap { font: 400 11.5px/1.45 var(--sans); color: var(--muted); }
.figcap b { font-weight: 600; color: var(--ink-2); }
.figcap .s { font-family: var(--mono); font-size: 10.5px; }

/* detail_html grammar (data/README.md) */
.drawer-body p, .drawer-body li { font: 400 13.5px/1.55 var(--sans); color: var(--ink-2); }
.drawer-body p + p { margin-top: 0; }
.drawer-body ul, .drawer-body ol { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; }
.drawer-body strong { color: var(--text); }
.drawer-body .note { display: block; font: 400 13px/1.5 var(--sans); }
.drawer-body .note p { font-size: 13px; margin-top: 6px; color: inherit; }
.drawer-body .note.warn, .drawer-body .note.caution { background: var(--warn-bg); color: #6f4119; }
.drawer-body .note.stop, .drawer-body .note.trap { background: var(--bad-bg); color: var(--bad); }
.drawer-body .note.info { background: var(--sunk); color: var(--ink-2); }
.drawer-body .note.check { background: var(--sunk); color: var(--ok); }
.drawer-body .note .note-label, .drawer-body .note strong.note-label { display: block; color: inherit; font: 600 12.5px/1.4 var(--sans); margin-bottom: 4px; }
.drawer-body p.why { border-left: 2px solid var(--accent-line); padding: 2px 0 2px 12px; color: var(--ink-3); }
.drawer-body p.fold { font: 600 13px/1.4 var(--sans); color: var(--text); letter-spacing: .01em; margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--line-2); }
.drawer-body p.conseq { font-size: 12.5px; color: inherit; opacity: .9; }
.drawer-body dd.dont { margin: 0; padding: 8px 10px; border-radius: 6px; background: var(--bad-bg); color: var(--bad); font: 400 12.5px/1.45 var(--sans); }
.drawer-body span.ref, .drawer .refs .ref { font: 600 .92em var(--mono); color: var(--accent); cursor: pointer; padding: 0 2px; border-radius: 3px; }
.drawer-body span.ref { margin: 0 -2px; }
.drawer-body span.ref:hover, .drawer-body span.ref.hov { background: var(--accent-line); }
.drawer-body a.xref, .drawer-body a.xref-phase, .drawer-body a.xref-fig { text-decoration: underline dotted var(--accent-soft); text-underline-offset: 2px; }
.drawer-body abbr[title], .drawer-body abbr[data-tip], .glossary-term { text-decoration: underline dotted var(--accent-soft); text-underline-offset: 2px; cursor: help; }
.drawer-body table { border-collapse: collapse; width: 100%; font: 400 12.5px/1.4 var(--sans); }
.drawer-body th { font: 600 10px/1.4 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); }
.drawer-body td { padding: 6px 8px; border-bottom: 1px solid var(--line-2); color: var(--ink-2); vertical-align: top; font-variant-numeric: tabular-nums; }
.drawer-body .detail { display: flex; flex-direction: column; gap: 10px; }

/* tooltip */
.tooltip { position: fixed; z-index: 40; max-width: 320px; background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: 6px; box-shadow: var(--shadow-pop); padding: 8px 10px; font: 500 12px/1.4 var(--sans); pointer-events: none; opacity: 0; }
/* Fades in (after tooltip.js's 250 ms hover delay); the base rule has no transition, so hiding is instant. */
.tooltip.show { opacity: 1; transition: opacity 80ms ease-out; }
.tooltip.pinned { pointer-events: auto; }
.tooltip .l2 { font: 400 10.5px/1.4 var(--mono); color: var(--muted); margin-top: 2px; }

/* skeleton */
.skeleton { background: linear-gradient(90deg, var(--line-2) 25%, var(--panel-2) 50%, var(--line-2) 75%); background-size: 200% 100%; animation: shimmer 1.2s linear infinite; border-radius: 6px; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.sk-rail { display: flex; flex-direction: column; min-height: 0; }
/* Sized to the rendered landing step (p0-1 at 1600, fallback font): rail head 251 (p0's intent is four lines),
   one-line rows 36 (steps[].short), card head 67, do rows 41, disclosures 34 — measured, so the real content lands
   where the blocks were. */
.sk-rail .sk-head { height: 251px; margin: 0; border-radius: 0; border-bottom: 1px solid var(--line-2); }
.sk-rail .sk-row { height: 36px; margin: 2px 8px 0; }
.sk-card { display: flex; flex-direction: column; gap: 14px; padding: 18px 18px 12px; flex: 1; }
.sk-card .sk-title { height: 67px; }
.sk-card .sk-do { height: 41px; }
.sk-card .sk-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.sk-card .sk-tiles .skeleton { height: 52px; }
.sk-card .sk-disc { height: 34px; }
.sk-foot { display: grid; grid-template-columns: 1fr 2fr; gap: 8px; padding: 12px 18px 16px; border-top: 1px solid var(--line-2); }
.sk-foot .skeleton { height: 44px; }
.sk-tl { display: grid; gap: 6px; }
.sk-tl .skeleton { height: 34px; border-radius: 5px; }

/* ---- motion (SPEC §3.3) ------------------------------------------------------------------------ */

/* Rows, chips and ticks ease between their states; the current tick also grows into its 16 px. */
.steprow, .steprow .k, .steprow .s, .facet-seg, .facet-seg .n { transition: background-color 120ms ease-out, color 120ms ease-out; }
.tick { transition: background-color 120ms ease-out, height 200ms ease-out; }
.icon-btn, .btn, button.chip, .ws-seg-btn, .part, .do .box, .disclosure, .tag.count, select.crumb {
  transition: background-color 120ms ease-out, border-color 120ms ease-out, color 120ms ease-out, box-shadow 120ms ease-out, transform 80ms ease-out;
}
/* Pressed: a 1 px sink on the raised controls, a darker ground on the flat ones. */
.btn:active, .icon-btn:active, button.chip:active, .tag.count:active { transform: translateY(1px); }
.btn:active, .icon-btn:active, button.chip:active, .tag.count:active, .ws-seg-btn:active, .part:active { background: var(--sunk); }
.btn.primary:active, .ws-seg-btn.on:active, .facet-seg.on:active, .tl-phase.on .tick.on:active { background: var(--accent-hi); border-color: var(--accent-hi); }
.facet-seg:active, .steprow:active { background: var(--line-2); }
.tick:active { background: var(--accent-soft); }
.do .box:active { border-color: var(--accent); }
/* Focus rings: .ws-seg clips its children's overflow, so that ring is drawn inside; ticks are 10 px tall. */
.ws-seg-btn:focus-visible { outline-offset: -2px; }
.tick:focus-visible { outline-offset: 3px; }
.steprow .go:focus-visible { outline-offset: 0; }
/* Projected stage furniture fades in when it (re)appears; `hidden` drops it at once, which restarts the animation. */
.callout:not([hidden]), .tag:not([hidden]), .label:not([hidden]), .hud-figure { animation: fade-in 120ms ease-out; }
/* The stamp rolls edge-on (150 ms), is re-inked, and rolls back (150 ms) — appbar.js swaps the text between the halves. */
.stamp { backface-visibility: hidden; }
.stamp.roll-out { animation: stamp-out 150ms ease-in forwards; }
.stamp.roll-in { animation: stamp-in 150ms ease-out; }
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }
@keyframes stamp-out { from { transform: perspective(240px) rotate(-1.5deg) rotateX(0); } to { transform: perspective(240px) rotate(-1.5deg) rotateX(90deg); } }
@keyframes stamp-in { from { transform: perspective(240px) rotate(-1.5deg) rotateX(-90deg); } to { transform: perspective(240px) rotate(-1.5deg) rotateX(0); } }
@keyframes beat-pop { from { transform: scale(.5); opacity: 0; } 60% { transform: scale(1.15); opacity: 1; } to { transform: scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; animation: none !important; }
}

/* ---- breakpoints (SPEC §3.2) ------------------------------------------------------------------- */

@media (max-width: 1439px) {
  .appbar .tagline { display: none; }
  .appbar .progress { width: 100px; }
}

@media (max-width: 1279px) {
  /* The bar has no room for labelled buttons once the rail folds away; the labels live on in aria-label/title.
     With the slug gone the phase crumb is what gives way (ellipsis) if anything still has to. */
  .appbar .slug { display: none; }
  .appbar .icon-btn .txt { display: none; }
  .appbar .icon-btn { padding: 7px; }
  .appbar .crumb.here { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .body { grid-template-columns: minmax(0, 1fr) 372px; }
  .rail { display: none; }
  .facet-seg { padding: 7px 10px; }
  .facet-bar .steps-btn { display: inline-flex; }
}

/* The labelled Steps button is what pushes the chips into ellipsis between 1024 and ~1100; its name stays in aria-label. */
@media (max-width: 1199px) {
  .facet-bar .steps-btn .txt { display: none; }
  .rail.popover { display: flex; position: absolute; z-index: 20; top: 0; width: 292px; max-height: min(70vh, 100%); border: 1px solid var(--line); border-radius: 0 0 8px 8px; box-shadow: var(--shadow-pop); }
}

@media (max-width: 1023px) {
  .appbar { padding: 0 12px; gap: 8px; }
  .appbar .pos, .appbar .sep.wide { display: none; }
  .appbar .progress { width: 60px; }
  .appbar .group { gap: 8px; }
  .facet-bar { overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scrollbar-width: none; }
  .facet-bar::-webkit-scrollbar { display: none; }
  .facet-seg { scroll-snap-align: center; flex: none; }
  .facet-bar .steps-btn { display: none; }
  .app { overflow: auto; }
  .body { display: flex; flex-direction: column; flex: 1 0 auto; min-height: 0; }
  .rail, .rail.popover { display: none; }
  .stage { min-height: 46vh; flex: none; }
  .stepcard { border-left: 0; border-top: 1px solid var(--line); flex: none; }
  .card-body { overflow: visible; }
  .card-foot { position: sticky; bottom: 56px; z-index: 5; }
  .hud-tr, .hud-bl, .hud-br, .hud .tags, .hud .labels, .scalebar { display: none; }
  .callouts .callout:not(:first-child), .callouts .tag.count, .hud.has-notice .callouts { display: none; }
  .hud .notice-narrow { position: absolute; top: 58px; left: 16px; right: 16px; display: flex; justify-content: center; pointer-events: none; }
  /* A shrink-to-fit figure card is 195 px on a phone — the drawing is the step's workpiece, so it takes the stage's
     width (explicit: the viewBox-only SVG has no intrinsic width to fit to) and all the height under the controls. */
  .hud-figure { width: calc(100% - 32px); max-width: none; max-height: calc(100% - 70px); }
  .timeline { position: sticky; bottom: 0; z-index: 6; height: 56px; padding: 10px 12px 8px; gap: 4px; }
  .tl-keys, .tl-labels { display: none; }
  .tl-track { display: grid; gap: 4px; position: relative; }
  .tl-track .tl-phase { height: 22px; padding: 0; align-items: center; justify-content: center; cursor: pointer; border: 1px solid var(--line-2); }
  .tl-track .tl-phase .n { font: 600 9.5px/1 var(--mono); color: var(--dim); }
  .tl-track .tl-phase.on .n { color: var(--accent); }
  .tl-track .tl-playhead { top: -6px; bottom: -4px; }
  .tl-track .tl-pill { top: -24px; }
  .tl-grid { display: none; }
  .drawer { width: 100%; }
}

/* Phone widths: the progress bar goes first, then the wordmark — the stamp (which side is up) and the phase crumb
   are what the bench needs; the app's name is in the tab title. */
@media (max-width: 639px) {
  .appbar .progress { display: none; }
}

@media (max-width: 599px) {
  .appbar .wordmark, .appbar .sep { display: none; }
}

@media (max-width: 479px) {
  .appbar .icon-btn { padding: 6px; }
  /* Three gaps before the crumb: 6 px back is what kept `Place back` whole at 380 (78 px in a 76 px box, r2-polish-23). */
  .appbar { gap: 6px; }
  /* The chip bar below already names the phase by number; the crumb keeps phases[].short (the title is in `title`). */
  .appbar .crumb.here .pfx, .appbar .crumb.here .long { display: none; }
  .appbar .crumb.here .brief { display: inline; }
}

@media (pointer: coarse) {
  .tl-keys { display: none; }
}
