/* Configurator page styles (v1.5 ADR-038/039, v1.5.1 ADR-068). Loaded per page through
   layout(..., { styles: ['css/configurator.css'] }), never through pageAssets(). It loads AFTER site.css and overrides its
   old `.cfg*` block (site.css, "Configurator"), which is left in place this round and listed for cleanup — I61:
   test/backdrop.test.js parses site.css, so this build does not edit it. */

:root { --cfg-bar-h: 60px; }

/* ─── Layout (v1.5.1 §4.6, visual 1) ──────────────────────────────────────────────────────────────────────────────
   The left rail is retired at every width: its job (where am I, what is done) moved into the summary card's parts
   list. Two tracks from 1100 px: the builder column gets 688 px at 1100 and 868 px from 1280, which the four or five
   option-table tracks fit without a hidden horizontal scroll (measured 622 px and 744–813 px tables in 1.5). */
.cfg { display: grid; gap: var(--s-5); grid-template-columns: minmax(0, 1fr); }
.cfg > * { min-width: 0; }
.cfg__rail { display: none; }
@media (min-width: 1100px) {
  .cfg { grid-template-columns: minmax(0, 1fr) 340px; align-items: start; }
  /* Sticky, and never taller than the screen: a summary longer than the viewport would hide its own end until the
     builder column scrolled out. It scrolls inside itself instead. */
  .cfg__summary { position: sticky; top: calc(var(--header-h) + 16px); max-height: calc(100vh - var(--header-h) - 32px); overflow-y: auto; overscroll-behavior: contain; }
}
.cfg-section, #sec-summary, #quote { scroll-margin-top: calc(var(--header-h) + 8px); }
.cfg-count { margin: calc(-1 * var(--s-3)) 0 var(--s-4); }
.cfg-count select { width: auto; }
.cfg-update { margin-top: var(--s-2); }

/* ─── Option tables (§4.1): Select | Part | Availability | Qty | Fit ─────────────────────────────────────────── */
.opt-table td.pick { width: 44px; }
.opt-table .part label { display: block; }
.opt-mpn { color: var(--text-muted); }
/* A part number is one unbreakable token; `anywhere` lets the table's min-content shrink instead of overflowing. */
.opt-table .mono { overflow-wrap: anywhere; }
.opt-specs { margin-top: 2px; }
.opt-table td.avail { white-space: nowrap; }
.opt-table .qty input { width: 70px; min-height: 36px; padding: 4px 8px; }
/* 36px is a desktop density; it only started applying when base.css stopped out-specifying it (v1.7 fix round), so a
   touch screen keeps the 44px target DESIGN.md §4 commits to. Height only — the 70px width is what stops the box
   filling the column on a 400px phone. */
@media (pointer: coarse) { .opt-table .qty input { min-height: 44px; } }
@media (min-width: 700px) {
  .opt-table td.part { min-width: 220px; }
  .cfg-fit { min-width: 16ch; max-width: 24ch; }
}
.opt-group th { background: var(--surface-2); color: var(--text-2); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; padding: 8px 12px; text-align: left; position: static; }

/* The Fit column. A part that fits prints nothing, so the column is quiet until it has something to say. */
.cfg-fit { color: var(--text-muted); font-size: var(--fs-xs); }
.cfg-fit--unverified { color: var(--warning); }
.cfg-fit--unfit { color: var(--danger); }

/* A row we cannot confirm is still selectable; a row that cannot work is disabled by the markup, not by CSS.
   The tint is on the ROW, not on its cells: in the stacked phone layout the cells do not cover the row, and the tint
   was patchy with dark gaps at the edges (visual 9). */
.opt-row.is-unverified { background: var(--warning-bg); }
/* --text-muted is 4.31:1 on the warning tint; the part number moves up to --text-2 there (7.47:1). */
.opt-row.is-unverified .opt-mpn { color: var(--text-2); }
/* Visual 4: no opacity. Over the composite of --danger-bg on --surface-solid (#302539): --text-2 8.22:1, --text-muted
   4.74:1, --danger 5.29:1 — test/configurator-ui.test.js recomputes these from tokens.css. */
.opt-row.is-unfit { background: var(--danger-bg); color: var(--text-2); }
.opt-row.is-unfit strong { color: var(--text-2); }
.opt-row.is-unfit .opt-mpn { color: var(--text-muted); }
.opt-row.is-unfit input[disabled] { cursor: not-allowed; }
.opt-row.is-unfit > td, .opt-row.is-unverified > td { background: transparent; }

/* Phones (table--stack, base.css): the choice sits in its own column beside the part; the part cell takes the whole
   row with no "Item" label, so the name and part number are never squeezed into a narrow right column (visual 9). */
@media (max-width: 699px) {
  .cfg-fit:empty { display: none; }
  .opt-table.table--stack tr.opt-row, .opt-table.table--stack tr.opt-none { display: grid; grid-template-columns: 28px minmax(0, 1fr); column-gap: var(--s-3); }
  .opt-table.table--stack tr > td { grid-column: 2; }
  /* width:auto — the desktop `td.pick{width:44px}` (here and in site.css) is wider than this 28 px track, so the cell
     spilled into the part column and the box sat 4 px over the part name on every phone row (review 2026-09-17). */
  .opt-table.table--stack tr > td.pick { grid-column: 1; grid-row: 1 / span 4; display: block; width: auto; min-width: 0; padding-top: 2px; }
  .opt-table.table--stack td.pick input { margin: 0; }
  .opt-table.table--stack td.pick::before, .opt-table.table--stack td.part::before { content: none; }
  .opt-table.table--stack td.part { display: block; text-align: left; }
  .opt-table.table--stack tr.opt-group { display: block; }
  .opt-table.table--stack tr.opt-group th { display: block; }
}

/* Section wrapper: the fieldset exists to name the group for screen readers, not to draw a box. */
.cfg-section__group { border: 0; margin: 0; padding: 0; min-width: 0; }
.cfg-section__issues { margin: 0 0 var(--s-3); padding: 0; }

/* "Nothing on the tested list is in stock" (I65), "no tested-part list" (§4.7) and the quote path out of an empty
   section (ADR-039). */
.cfg-widened, .cfg-untested { color: var(--warning); margin: 0 0 var(--s-3); }
.cfg-empty { border: 1px dashed var(--border-strong); border-radius: var(--r-md); padding: var(--s-4); margin-bottom: var(--s-3); }
.cfg-empty p { margin: 0 0 var(--s-2); }
.cfg-empty p:last-child { margin-bottom: 0; }

/* ─── Summary card (§4.1): heading, verdict, the one action, then the parts ─────────────────────────────────── */
.cfg__summary-title { font-size: var(--fs-xl); margin-bottom: var(--s-1); }
.cfg__summary-sub { margin-bottom: var(--s-3); }
.cfg-verdict { margin: 0 0 var(--s-3); padding: 10px 12px; border-radius: var(--r-md); border: 1px solid var(--border); background: var(--surface-2); color: var(--text); font-size: var(--fs-sm); font-weight: 600; }
.cfg-verdict--ok { background: var(--success-bg); border-color: rgba(59,232,176,.3); }
.cfg-verdict--warn { background: var(--warning-bg); border-color: rgba(255,194,75,.3); }
.cfg-verdict--error { background: var(--danger-bg); border-color: rgba(255,107,129,.4); }
.cfg__summary > .btn--primary { margin-bottom: var(--s-3); }
.cfg__summary .cfg-parts { list-style: none; margin: 0 0 var(--s-3); padding: 0; }
.cfg__summary .cfg-parts li { display: grid; grid-template-columns: minmax(7.5em, 38%) minmax(0, 1fr); gap: var(--s-2); padding: 6px 0; border-bottom: 1px solid var(--divider); font-size: var(--fs-sm); }
.cfg-parts li > a, .cfg-parts__name { color: var(--text-2); }
/* site.css's old `.cfg__summary li span:last-child` sets nowrap for prices; a part name must wrap. */
.cfg__summary .cfg-parts li span { white-space: normal; font-variant-numeric: normal; }
.cfg-parts li > span:last-child { color: var(--text); overflow-wrap: anywhere; }
.cfg-parts__quoted { color: var(--text-2); }
.cfg__capacity, .cfg__power, .cfg__lead { margin: 0 0 var(--s-2); }
.cfg__summary .issues { margin: var(--s-3) 0 0; padding: 0; }
.cfg__summary .issues a, .cfg-quote .issues a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.cfg-notes, .cfg-share { margin-top: var(--s-3); font-size: var(--fs-sm); }
.cfg-notes > summary, .cfg-share > summary { color: var(--text-link); display: inline-flex; align-items: center; gap: 6px; min-height: 32px; }
.cfg-notes > summary::before, .cfg-share > summary::before { content: "▸"; color: var(--text-muted); }
.cfg-notes[open] > summary::before, .cfg-share[open] > summary::before { content: "▾"; }
/* The whole share link is readable and selectable without JavaScript (visual 9: an <input> cut it to "http://127.0.0"). */
/* field-sizing grows the box to the whole link where supported (Chromium); elsewhere rows="3" scrolls natively. */
.cfg-share textarea { display: block; width: 100%; min-height: 0; max-height: 20em; field-sizing: content; margin: var(--s-2) 0; resize: none; overflow-wrap: anywhere; word-break: break-all; line-height: 1.4; }

/* ─── Quote section ─────────────────────────────────────────────────────────────────────────────────────────── */
.cfg-quote { margin-top: var(--s-6); }
.cfg-quote__blocked, .cfg-quote__empty { margin-bottom: var(--s-4); }
.cfg-quote__blocked p { margin: 0 0 var(--s-2); }
.cfg-quote__blocked .issues { margin: 0; padding: 0; }

/* ─── Index picker (visual 6): the manufacturer select with its no-JS "Show models" button ────────────────────── */
.cfg-pick__maker { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.cfg-pick__maker select { flex: 1 1 12ch; width: auto; min-width: 0; }

/* ─── Sticky bar and phones (§4.8, owner: the summary button was cut off) ─────────────────────────────────────── */
.cfg-bar { min-height: var(--cfg-bar-h); padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
.cfg-bar__count { font-weight: 600; font-size: var(--fs-sm); }
@media (max-width: 1099px) {
  /* The fixed bar never covers the end of the page, with or without JavaScript. */
  body:has([data-cfg-bar]) { padding-bottom: calc(var(--cfg-bar-h) + env(safe-area-inset-bottom)); }
  /* …and never covers what has keyboard focus (WCAG 2.4.11): Tab scrolled a quantity box or a checkbox to the bottom
     edge, fully under the bar, at 3 of 60 focus stops on a 390 px phone (review 2026-09-17). */
  html:has([data-cfg-bar]) { scroll-padding-bottom: calc(var(--cfg-bar-h) + env(safe-area-inset-bottom) + 8px); }
}
@media (max-width: 599px) {
  .cfg__summary { padding: var(--s-4); }
  .cfg__summary-title { font-size: var(--fs-lg); }
  .cfg__summary .cfg-parts li { font-size: var(--fs-sm); padding: 4px 0; }
  .cfg-bar { padding-inline: var(--s-3); }
}

/* ─── Print (visual 11): the printed sheet is the build for sign-off ───────────────────────────────────────────
   One column; platform, chassis, the chosen parts with part numbers, the fit verdict and power. Everything that is a
   control, a choice not taken or a way to send the form is hidden. */
@media print {
  .cfg { display: block; }
  .cfg__summary { position: static; max-height: none; overflow: visible; break-inside: avoid; margin-top: 12pt; }
  .market-chooser, .market-scope, .market-cfg-more, .cfg-bar, .cfg-share, .cfg-notes, #quote, .cfg-update, .cfg-count,
  .opt-row:not(.is-selected), .opt-none, .opt-group, .cfg-empty, .cfg-widened, .cfg-untested, .cfg__summary > .btn,
  .opt-table td.pick, .opt-table thead th:first-child, .paycard:not(:has(input:checked)) { display: none !important; }
  .cfg-section:not(#sec-chassis):not(:has(.opt-row.is-selected)) { display: none !important; }
  /* A Fit column whose printed (chosen) rows say nothing printed as an empty "Fit" heading (review 2026-09-17). */
  .opt-table:has(td.cfg-fit):not(:has(.opt-row.is-selected td.cfg-fit:not(:empty))) :is(thead th:last-child, td.cfg-fit) { display: none !important; }
  .cfg-page, .cfg-page * { color: #000 !important; background: #fff !important; box-shadow: none !important; text-shadow: none !important; }
  .cfg-page .badge { border: 1px solid #000 !important; }
  .cfg-page .cfg-fit--unfit, .cfg-page .issues .error, .cfg-page .cfg-verdict--error { color: #6b1d2a !important; }
  .cfg-page .cfg-fit--unverified, .cfg-page .issues .warning, .cfg-page .cfg-verdict--warn { color: #6b4a00 !important; }
  .cfg-page .cfg-verdict { border: 1px solid #000 !important; }
  .cfg-page .meter { border: 1px solid #000; }
  .cfg-page .meter span { background: #000 !important; }
  .cfg-page .table-wrap, .cfg-page .card { border-color: #999 !important; }
}
