/* rail.css — The run-sheet rail: .step, .hint, .field.
   Cascade position 11 of 18. Order is load-bearing and is asserted by
   verify-fixtures.mjs; index.html links these explicitly (never @import) because Caddy's
   try_files turns a missing file into a 200 text/html SPA shell.
   Owner after Step 1: section (f). */

/* ══ The three steps ═══════════════════════════════════════════════════════════════
   REFERENCE-STUDY §14.1: GitHub draws a file list's separator as a `border-top` on the
   CELL rather than on the row, which is what lets the first row sit flush under its
   header with no doubled line. Same trick between steps. MEASURED before: every `.step`
   carried a `border-bottom`, so step 3 drew a trailing hairline across the rail with
   nothing under it, and `#resultPanel`'s own `border-bottom` sat below that. The rule is
   now on `.step + .step`, so it exists strictly BETWEEN steps: none above step 1, none
   after the last one, and no doubling wherever a panel that carries its own line follows.

   Geometry is DESIGN-SPEC §4.8: the header is its own 48px row with the step's horizontal
   padding on it, and the body carries the same padding, instead of one padding box around
   both. That is what makes the header a full-width hit target and lets its focus ring sit
   inside the step's bounds. */
.step + .step { border-top: 1px solid var(--line); }
.step__head {
  display: flex; align-items: center; gap: var(--sn-space-3); width: 100%;
  height: 48px; padding: 0 var(--sn-space-4);
  border: 0; background: none; color: inherit; font: inherit; text-align: left;
}
button.step__head { cursor: pointer; border-radius: var(--sn-radius-sm); }
/* Hover changes fill/colour and nothing else (REFERENCE-STUDY §18.4); the header's
   `getBoundingClientRect()` is byte-identical at rest and on hover (§18.10). */
button.step__head:hover .step__chev { color: var(--sn-ink); }
/* DESIGN-SPEC §4.8 and §9: `outline-offset: -2px` so the ring sits INSIDE the step's own
   bounds and never straddles the separator above it. The radius is re-declared because
   css/base.css's shared ring sets `border-radius: inherit`, which on a header inside a
   square-cornered `.step` would draw a square ring around an 8px button. */
button.step__head:focus-visible {
  outline: 2px solid var(--sn-focus); outline-offset: -2px;
  border-radius: var(--sn-radius-sm);
}
.step__n {
  width: 24px; height: 24px; border-radius: var(--sn-radius-sm);
  display: grid; place-items: center;
  font-size: var(--sn-text-xs); font-weight: 700; font-family: var(--sn-font-display);
  background: var(--sn-surface-2); color: var(--sn-ink-mute);
  box-shadow: inset 0 0 0 1px var(--sn-line);
  flex: 0 0 auto;
}
.step.is-live .step__n {
  background: var(--sn-accent-tint); color: var(--sn-accent);
  box-shadow: inset 0 0 0 1px var(--sn-accent-edge);
}
.step.is-done .step__n {
  background: var(--sn-accent); color: transparent; box-shadow: none;
  position: relative;
}
/* DESIGN-SPEC §4.8: a finished step wears a tick, not its number. index.html is frozen,
   so the digit stays in the DOM (and in the accessibility tree) and is only replaced
   visually — an overlay, not a layout change, so nothing reflows when a step completes. */
.step.is-done .step__n::after {
  content: '✓'; position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--sn-accent-ink); font-size: var(--sn-text-xs); font-weight: 700;
}
.step__head h3 { font-size: var(--sn-text-md); letter-spacing: -.01em; }
/* The step's meta slot (DESIGN-SPEC §4.8 `.step__meta`): right-aligned, muted, truncating.
   It is an `<em>` because index.html is frozen; `font-style: normal` undoes the italic. */
.step__head em {
  margin-left: auto; font-style: normal;
  font-size: var(--sn-text-xs); color: var(--sn-ink-mute);
  max-width: 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.step__chev {
  flex: 0 0 auto; color: var(--sn-ink-mute); font-size: var(--sn-text-2xs); line-height: 1;
  transition: transform var(--sn-dur-base) var(--sn-ease-out),
              color var(--sn-dur-fast) var(--sn-ease-out);
  display: none;
}
.step.is-done .step__chev { display: block; }
.step.is-collapsed .step__chev { transform: rotate(-90deg); }
/* One line, always: the gate is `scrollWidth === clientWidth` at 1440, 1280 and 1024, and
   the single-file summary ("60 x 31 x 48 mm · 15.6 cm3 · 225,706 tris · 1 piece") is long
   enough to wrap in a 392px rail without the ellipsis. */
.step__summary {
  display: none; margin: 0; padding: 0 var(--sn-space-4) var(--sn-space-4);
  font-size: var(--sn-text-xs); color: var(--sn-ink-dim); line-height: var(--sn-lh-xs);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.step.is-collapsed .step__summary { display: block; }
.step__body { padding: 0 var(--sn-space-4) var(--sn-space-4); }
.step.is-collapsed .step__body { display: none; }
/* ── item 132 ────────────────────────────────────────────────────────────────────────
   The file list is the only place a customer can confirm which files were accepted and
   remove one, and it used to disappear in the same frame it became useful. When step 1
   collapses with rows in it, the rows and their aggregate line survive the collapse;
   everything else in the body folds away. `:has()` keeps this out of the JS, so no state
   machine has to remember it. When there are no rows (fixture mode, a whole-selection
   refusal that cleared them) the body collapses as before. */
#step1.is-collapsed .step__body:has(.file-row) { display: block; }
#step1.is-collapsed .step__body:has(.file-row) > :not(#modelFileList):not(#fileAggregate) {
  display: none;
}
/* ── item 96 ─────────────────────────────────────────────────────────────────────────
   `pointer-events: none` used to be the mechanism, and it is not one: it hid 19 controls
   from the mouse while leaving every one of them in the tab order and in the accessibility
   tree. The mechanism is now the `inert` attribute that js/steps.js keeps in sync with
   this class (DESIGN-SPEC §4.8, §9 "anything visually inert is `inert`, never
   `pointer-events: none`"). What is left here is decoration, and it must never be the
   only signal. */
.step.is-idle .step__body { opacity: .45; }
/* PB-02: js/progress.js makes steps 1 and 2 `inert` while a preparation runs; same decoration as idle. */
.step[inert] .step__body { opacity: .45; }
.hint { font-size: var(--sn-text-sm); color: var(--sn-ink-mute); }
/* Choices use a dense sheet: clean labels, with explainers on demand. */
.field { margin-bottom: 11px; }
.field__head {
  display: flex; align-items: center; gap: 6px; margin-bottom: 6px; min-height: 20px;
}
.field__head label {
  font-size: var(--sn-text-xs); font-weight: 600; color: var(--sn-ink); margin: 0;
}
.field__meta { font-weight: 400; color: var(--sn-ink-mute); font-size: 11.5px; margin-left: 2px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sn-space-2); margin-bottom: 11px; }
.field-row .field { margin-bottom: 0; }
