/* =============================================================================
   Neurotech Studio — site.css
   "The Methods Section / The Anti-Pitch Deck."
   Black on white, typography + proportion over decoration. No framework.
   Tokens → base → typography → layout (Tufte side-notes) → elements → nav/footer
   → components → print. See planning/site/ARCHITECTURE.md §5.
   ========================================================================== */

/* --- Tokens --------------------------------------------------------------- */
:root {
  /* Ink on paper, thin rules, one sparing accent (a quiet slate blue). */
  --ink:        #111111;
  --ink-soft:   #5b5b5b;   /* captions, side-notes, secondary text */
  --paper:      #ffffff;
  --rule:       #dddddd;    /* thin hairline rules */
  --rule-firm:  #111111;    /* table header underline, major rules */
  --accent:     #2b4a6f;    /* used sparingly: links-on-hover, section #s, focus */
  /* --washu-red: #a51417 — official WashU brand red. TRIED on the footnote
     asterisks (R18.5) and REVERTED to black by Ben 2026-08-21 (R18.6); kept
     here commented for the pre-launch victory-lap aesthetics round. */
  --accent-bg:  #f3f5f8;    /* faintest accent wash for notice blocks */

  /* One quiet text face (Charter/ET-Book spirit) + a mono for labels. */
  --serif: Charter, "Charter BT", "Bitstream Charter", "Sitka Text", Cambria,
           "Source Serif 4", "Source Serif Pro", Georgia, "Times New Roman", serif;
  --mono:  "SF Mono", "JetBrains Mono", "IBM Plex Mono", ui-monospace,
           "Cascadia Code", Menlo, Consolas, monospace;

  /* Modular type scale (~1.26). */
  --text-xs:   0.78rem;
  --text-sm:   0.875rem;
  --text-base: clamp(1.02rem, 0.99rem + 0.18vw, 1.125rem);
  --text-lg:   1.27rem;
  --text-xl:   1.6rem;
  --text-2xl:  2.05rem;
  --text-3xl:  clamp(2.1rem, 1.7rem + 1.6vw, 2.85rem);

  /* Proportion. */
  --measure:    66ch;        /* prose measure cap */
  --side-width: 15rem;       /* Tufte margin-note column at wide widths */
  --gutter:     clamp(1.1rem, 4vw, 2.5rem);
  --shell-max:  78rem;
  --leading:    1.6;
}

/* --- Reset-ish base ------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--text-base);
  line-height: var(--leading);
  font-kerning: normal;
  font-feature-settings: "kern" 1, "liga" 1, "onum" 1;   /* old-style numerals */
  text-rendering: optimizeLegibility;
}

img, svg, figure { max-width: 100%; height: auto; }

/* Visible, calm focus for keyboard users. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Skip link — accessible, hidden until focused. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 0.5rem 0.9rem;
  z-index: 10;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

/* --- Typography ----------------------------------------------------------- */
h1, h2, h3, h4 {
  font-weight: 600;
  line-height: 1.18;
  margin: 0 0 0.4em;
  text-wrap: balance;
}
h1 { font-size: var(--text-3xl); letter-spacing: -0.01em; margin-top: 0; }
h2 { font-size: var(--text-xl); margin-top: 2.2rem; }
h3 { font-size: var(--text-lg); margin-top: 1.6rem; }
h4 { font-size: var(--text-base); margin-top: 1.3rem; }

p { margin: 0 0 1rem; }

a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--rule);
  text-underline-offset: 0.14em;
}
a:hover, a:focus {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

/* A submit button that reads as an inline link (R16 W1: the division-access
   "click here" inside a sentence — a state change, so a POST, not an <a>). */
button.linklike {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--rule);
  text-underline-offset: 0.14em;
  cursor: pointer;
}
button.linklike:hover, button.linklike:focus {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

strong { font-weight: 600; }
em { font-style: italic; }

small, .text-sm { font-size: var(--text-sm); }

/* Mono label / eyebrow — the "small label" device. */
.label {
  display: inline-block;
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 0.5rem;
}

code, kbd, samp { font-family: var(--mono); font-size: 0.92em; }

/* Lead paragraph under a page title. */
.lead {
  font-size: var(--text-lg);
  line-height: 1.45;
  color: var(--ink);
  max-width: var(--measure);
}

/* --- Layout shell --------------------------------------------------------- */
.shell {
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

main { padding-block: clamp(2rem, 5vw, 3.75rem); }

/* The reading column. Prose is capped at the measure. */
.page { max-width: var(--measure); margin-inline: auto; }
.page > * { max-width: var(--measure); }
/* Contain trailing floats (W8-2): a margin note that ENDS a page used to
   float past the article's bottom edge and strike the footer rule (upload
   page File-rules note). The clearfix keeps every float inside the column. */
.page::after { content: ""; display: block; clear: both; }

/* Margin-notes — default (narrow) appearance: an inline set-off block with a
   left rule. This BASE MUST precede the min-width:64rem block below: at wide
   widths both rules match at equal specificity, so source order decides which
   wins. Keeping this first lets the wide Tufte-gutter override (float into the
   reserved margin, borderless) win. (R14 F-1: this block used to sit AFTER the
   media query, so the narrow styling leaked into wide widths and the notes
   never moved into the gutter.) */
.marginnote, .sidenote {
  display: block;
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--ink-soft);
  border-left: 2px solid var(--rule);
  padding-left: 0.9rem;
  margin: 0.7rem 0 1.1rem;
}
/* --- R20: upload intake ---------------------------------------------------- */
/* The file input is visually hidden; its <label class="button"> is the
   control (native "No file chosen" UI gone in both JS modes). The staged
   list (.dropzone, built by upload.js) is THE drop target: quiet dashed
   frame at rest, inviting empty state, and a drag affordance — a second
   offset outline + the faint accent wash — whenever a file drag is over
   the window (drag-active, soft) or the zone itself (drag-over, full). */
.field--upload { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.9rem; }
.field--upload .help { font-size: var(--text-sm); color: var(--ink-soft); }
/* R69 (#81): the file-units pick, one quiet row of radios. */
/* R72 (Ben): units per file, a select in the files table's Units column; the
   inch nudge is a short line under the file's name. */
/* A-26 (reviewer, WebKit): drop the native pill menulist so the select takes
   the shared padding and border and sits level with the copies box; the
   chevron is two CSS gradients (no image). R76 (#92): the State select too. */
.input-units, .input-state {
  -webkit-appearance: none; appearance: none;
  padding-right: 1.9rem; border-radius: 0;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%),
                    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 0.95rem) 50%, calc(100% - 0.6rem) 50%;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
}
.input-units { width: auto; }   /* R72.1: as narrow as "mm" / "in" */
.units-nudge { display: block; font-size: var(--text-sm); color: var(--accent); margin-top: 0.15rem; }
.field--upload .errorlist { flex-basis: 100%; }
.dropzone {
  border: 1px dashed var(--ink-soft);
  padding: 0.9rem 1.1rem;
  margin: 0.9rem 0;
}
/* Drag affordances (reviewer round-1 spec): a window-level file drag tints
   the zone (soft cue, NEUTRAL gray — deliberately not the notice-blue wash);
   dragover on the zone itself doubles the border. Padding compensates the
   2px border growth so the geometry never shifts. */
.dropzone.drag-active { background: #f5f5f5; }
.dropzone.drag-over {
  border: 3px double var(--ink-soft);
  background: #f5f5f5;
  padding: calc(0.9rem - 2px) calc(1.1rem - 2px);
}
.dropzone-empty { margin: 0; color: var(--ink-soft); text-align: center; }
.dropzone-reject { margin: 0 0 0.5rem; }

/* R19 round 1 (Ben: the notes get "one last chance"): the note label gets
   its OWN LINE — the site's eyebrow-over-content rhythm (door cards, page
   headers) instead of the run-in that concatenated "FOR EXTERNAL CUSTOMERS
   Our external rates..." and clashed the first two lines' leading (.label
   is inline-block with a 0.5rem bottom margin; inside a 1.45-leaded note
   that stray margin + line-box was the gap Ben screenshotted). Body
   leading stays 1.45 untouched. Component-level: identical in gutter-float
   wide, ?notes=inline, and narrow. */
.marginnote .label,
.sidenote .label {
  display: block;
  margin: 0 0 0.25rem;
  line-height: 1.3;
}

/* Wide widths: reserve a right gutter and float margin-notes into it. */
@media (min-width: 64rem) {
  .page {
    max-width: calc(var(--measure) + var(--side-width) + 2.5rem);
    padding-right: calc(var(--side-width) + 2.5rem);
    /* FW-1 v2 — frozen 2026-08-20 per Ben's live approval ("those lines are
       starting to feel right"); victory-lap aesthetics round pending
       pre-launch. The single FW-1 edge hairlines hugged the H1 on the left
       and left a bare void on the right; each side is now a fading
       triple-rule bracket: three 1px bars, tallest + strongest INNERMOST,
       stepping shorter and fainter going outward, all vertically centered on
       the article midline. GEOMETRY: inter-bar spacing 1.1rem = the
       innermost bar's clearance from the content edge (left cluster at
       -1.1 / -2.2 / -3.3rem from the text edge; right cluster grows outward
       from the annotation column's outer edge at +0 / +1.1 / +2.2rem, so
       margin notes are never crossed). Clusters stay inside the free shell
       space at the 64rem breakpoint (>=4.25rem available) -> no horizontal
       overflow. Painted on ONE absolutely positioned ::before spanning both
       sides (::after is the W8-2 clearfix), z-index -1 + pointer-events
       none -> behind content, no layout shift, no interaction (html is
       background-free so body's white propagates to the canvas and the
       negative-z pseudo stays visible). Wide-only; medium/narrow untouched. */
    position: relative;
  }
  .page::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -3.3rem;
    right: -2.2rem;
    z-index: -1;
    pointer-events: none;
    background-image:
      linear-gradient(#f1f1f1, #f1f1f1),
      linear-gradient(#ebebeb, #ebebeb),
      linear-gradient(#e4e4e4, #e4e4e4),
      linear-gradient(#e4e4e4, #e4e4e4),
      linear-gradient(#ebebeb, #ebebeb),
      linear-gradient(#f1f1f1, #f1f1f1);
    background-repeat: no-repeat;
    background-position:
      0 50%, 1.1rem 50%, 2.2rem 50%,
      right 2.2rem center, right 1.1rem center, right 0 center;
    background-size:
      1px 64%, 1px 82%, 1px 100%,
      1px 100%, 1px 82%, 1px 64%;
  }
  .msg-page::before { content: none; }
  .page > * { max-width: var(--measure); }
  /* The transient messages wrapper is not the article — no edge rules on it,
     so a one-line flash above the content doesn't read as a second framed box. */
  .msg-page { background-image: none; }
  .marginnote, .sidenote {
    float: right;
    clear: right;
    width: var(--side-width);
    margin-right: calc(-1 * (var(--side-width) + 2.5rem));
    margin-top: 0.3rem;
    margin-bottom: 0.9rem;
    border-left: 0;
    padding-left: 0;
    /* The note's border-box right edge lands on FW-1's right frame rule (via the
       negative margin-right); on full-measure lines the text otherwise abuts the
       hairline (reviewer Range-measured 0-2px). A hair of right padding insets
       the text ~8px for clean breath; the box edge stays on the rule (R14 F-1). */
    padding-right: 0.5rem;
  }
}

/* --- Sections (R18.9: D1 RESOLVED — Ben promoted the ?sections=plain look
   to the DEFAULT; the CSS-counter numbering device and its preview toggle
   are REMOVED. The .numbered class name stays on templates as the
   section-spacing hook — identifiers, not copy). ------------------------- */
.numbered > section { margin-bottom: 2rem; }
.numbered > section > h2 { margin-top: 0; }

/* R18.8/R21 PROTOTYPE — ?notes=inline previews the D9 candidate on the live
   site at WIDE widths: margin notes flow inline with their medium/narrow
   set-off styling, the reserved gutter is freed so content centers at the
   measure, and (R21, Ben's emerging D9 direction) the FW-1 v2 triple-rail
   brackets STAY ON — repositioned to hug the centered measure symmetrically.
   Default rendering is byte-identical without the param. D9:
   remove-or-promote at pre-launch (D1 resolved 2026-08-21 — plain sections
   promoted; this toggle remains the only preview machinery). */
@media (min-width: 64rem) {
  body.notes-inline .page {
    max-width: var(--measure);
    padding-right: 0;
  }
  body.notes-inline .page::before {
    /* R21: rails KEPT in the centered candidate. The frozen FW-1 v2
       background lists are already symmetric inside the pseudo (bars at
       0/1.1/2.2rem from each pseudo edge, heights 64/82/100 inward, grays
       fading outward) — the ONLY asymmetry was the pseudo's extents (the
       right one reached into the old gutter). Mirroring the right extent to
       the left's -3.3rem makes both clusters hug the measure identically:
       innermost bars 1.1rem clear of the text on each side, outermost at
       3.3rem. Steps, heights, and grays inherit from the frozen design
       untouched. Overflow-safe: >=9.6rem of shell free per side at the
       64rem boundary. */
    right: -3.3rem;
  }
  body.notes-inline .marginnote,
  body.notes-inline .sidenote {
    float: none;
    clear: none;
    width: auto;
    margin: 0.7rem 0 1.1rem;
    border-left: 2px solid var(--rule);
    padding-left: 0.9rem;
    padding-right: 0;
  }
  /* The homepage row sized itself against the framed block; with the gutter
     gone it re-centers at the measure with the medium 2fr/3fr split. */
  body.notes-inline .door-row--home {
    max-width: var(--measure);
    margin-right: 0;
    grid-template-columns: 2fr 3fr;
  }
}

/* --- Lists ---------------------------------------------------------------- */
ul, ol { margin: 0 0 1rem; padding-left: 1.3rem; }
li { margin: 0.25rem 0; }

/* "What you can do here" — a plain list, not cards. */
.plainlist { list-style: none; padding-left: 0; }

/* Order note thread (W9-2; R68 tidy): rows between hairlines, a small
   label line (who · when) over the body. No boxes, no side bars. */
.notes { list-style: none; padding-left: 0; margin: 0 0 1.5rem; border-top: 1px solid var(--rule); }
.notes > li { margin: 0; padding: 0.7rem 0 0.75rem; border-bottom: 1px solid var(--rule); }
.notes-meta { margin: 0 0 0.2rem; font-size: var(--text-sm); color: var(--ink-soft); }
.notes-meta .notes-who { color: var(--ink); font-variant: small-caps; letter-spacing: 0.04em; }
.notes-meta time { font-variant-numeric: tabular-nums; }
.notes-body { margin: 0; max-width: var(--measure); }
.notes-form label { font-size: var(--text-sm); color: var(--ink-soft); }
/* Operator dashboard note blocks (W9-2 vocabulary). */
.note {
  border-left: 2px solid var(--rule);
  padding-left: 0.9rem;
  margin: 0 0 1.1rem;
}
.note p { margin-bottom: 0.3rem; }
.plainlist > li {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--rule);
}
.plainlist > li:first-child { border-top: 1px solid var(--rule); }

/* --- Rules ---------------------------------------------------------------- */
hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 2.25rem 0;
}
hr.major { border-top: 1px solid var(--rule-firm); }

/* --- Tables (clean, no zebra; thin rules; firm header underline) ----------- */
table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.2rem 0 1.5rem;
  font-size: var(--text-sm);
}
caption {
  caption-side: top;
  text-align: left;
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
}
th, td {
  text-align: left;
  vertical-align: top;
  padding: 0.5rem 1rem 0.5rem 0;
  border-bottom: 1px solid var(--rule);
}
/* Policy (R6-1): table cells NEVER break words mid-word by default — prose
   wraps at spaces. Cells that genuinely carry long unbroken tokens (filenames,
   a 36-char order uuid, tracking numbers) opt in with .cell-break so a phone
   viewport can still wrap them. */
.cell-break { overflow-wrap: anywhere; }
thead th {
  border-bottom: 1px solid var(--rule-firm);
  font-weight: 600;
}
td.num, th.num { font-variant-numeric: tabular-nums; font-family: var(--mono); }

/* Phones: reclaim horizontal room in dense (3–4 column) tables — the upload
   file list and the per-file check report (R1-3). */
@media (max-width: 34rem) {
  th, td { padding-right: 0.55rem; }
}

/* Dense many-column tables (upload file list, check report) scroll horizontally
   on phones instead of crushing columns — the flowfig precedent (R3.1 F2). */
.table-scroll { overflow-x: auto; }
table.timeline th { font-weight: normal; }   /* R66 (U-55): the history rows read as a list */
.table-scroll table { min-width: 30rem; }

/* --- Figures & captions --------------------------------------------------- */
figure { margin: 1.5rem 0; }
figcaption {
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--ink-soft);
  margin-top: 0.45rem;
}

/* --- Blockquote (used sparingly, e.g. the brief's example sentences) ------- */
blockquote {
  margin: 1.25rem 0;
  padding-left: 1rem;
  border-left: 2px solid var(--rule-firm);
  color: var(--ink);
  font-style: italic;
}

/* --- Masthead / nav ------------------------------------------------------- */
.masthead { border-bottom: 1px solid var(--rule-firm); }
.masthead .shell {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  padding-block: 0.9rem;
}
.wordmark {
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--ink);
  white-space: nowrap;
}
.wordmark:hover, .wordmark:focus { color: var(--ink); text-decoration: none; }
/* The Division mark beside the wordmark (Ben, 2026-09-14: exact mark, 24 px, ink). Height sets
   the size (the viewBox is tight, 1.17:1); vertical-align centres it on the wordmark's CAP-HEIGHT
   midline (Charter caps ≈ 0.70em) rather than the baseline; the gap is ≈ half the cap height.
   fill="currentColor" → it takes the link's colour (--ink), so hover/focus stay ink and print's
   --ink:#000 makes it black. It sits inside the existing line box: the masthead does not grow. */
.wordmark .mark {
  height: 24px;
  width: auto;
  vertical-align: calc(0.35em - 12px);
  margin-right: 0.35em;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 1.1rem;
  font-size: var(--text-sm);
}
.nav a { text-decoration: none; color: var(--ink); }
.nav a:hover, .nav a:focus { color: var(--accent); }
.nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.35em;
  text-decoration-color: var(--ink);
}
.nav .signin {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* CSS-only "Account" dropdown (W2): a <details> whose <summary> is the nav item
   and whose menu is absolutely positioned so it never shifts the bar. No JS. */
.nav-account { position: relative; }
.nav-account > summary {
  cursor: pointer;
  list-style: none;                 /* hide the default disclosure triangle */
  /* R18.7 (Ben): the Account control sat 1px high of the nav baseline;
     nudged down. translateY = no layout/flow impact, dropdown unaffected
     (the menu anchors to .nav-account, not the summary). */
  transform: translateY(1px);
}
.nav-account > summary::-webkit-details-marker { display: none; }
.nav-account > summary::marker { content: ""; }
.nav-account > summary:hover, .nav-account[open] > summary { color: var(--accent); }
.nav-account .nav-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 0.55rem);
  z-index: 20;
  display: flex;
  flex-direction: column;
  min-width: 9rem;
  background: var(--paper);
  border: 1px solid var(--rule-firm);
  padding: 0.3rem 0;
}
.nav-account .nav-menu a {
  padding: 0.4rem 0.9rem;
  white-space: nowrap;
  font-size: var(--text-sm);
}

/* --- Footer --------------------------------------------------------------- */
.site-footer {
  margin-top: 3.5rem;
  border-top: 1px solid var(--rule);
  font-size: var(--text-sm);
  color: var(--ink-soft);
}
.site-footer .shell { padding-block: 1.5rem 2.5rem; }
.site-footer a { color: var(--ink-soft); }
.site-footer a:hover, .site-footer a:focus { color: var(--accent); }
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  list-style: none;
  padding: 0;
  margin: 0 0 0.6rem;
}
.footer-stamp { font-family: var(--mono); font-size: var(--text-xs); }

/* --- Buttons / CTAs (task-oriented, never begging) ------------------------ */
.button {
  display: inline-block;
  font-family: var(--serif);
  font-size: var(--text-base);
  line-height: 1.2;
  padding: 0.55rem 1.1rem;
  border: 1.5px solid var(--ink);
  color: var(--ink);
  text-decoration: none;
  background: var(--paper);
}
.button:hover, .button:focus { background: var(--ink); color: var(--paper); }
.button--primary {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.button--primary:hover, .button--primary:focus {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--paper);
}
/* R84 (#103): the pressed button reads "Checking…", disabled (static/js/busy.js). */
.button:disabled { cursor: default; }
/* Quiet small action — table row actions (e.g. remove-a-file), not page CTAs. */
.button--small {
  font-size: var(--text-sm);
  padding: 0.15rem 0.55rem;
  border-width: 1px;
  color: var(--ink-soft);
  border-color: var(--ink-soft);
}
.button--small:hover, .button--small:focus {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

/* --- Door (front-door block: label, heading, blurb, action) --------------- */
/* Doors are full-measure BORDERED blocks, so they must not collide with the
   floated margin-note column: clear any preceding float (same fix family as
   `.page form { clear: right }`), and render a margin note placed *inside* a
   door as a contained set-off block instead of a float that would strike
   through the box border / overlap the gap to the next door (fixup F1). */
.door {
  border: 1px solid var(--rule-firm);
  padding: 1.3rem 1.4rem;
  margin: 1.5rem 0;
  clear: right;
}
.door h2 { margin-top: 0; }
.door p { color: var(--ink); }
/* R18.3 (lead-ruled GLOBAL fix): `.door p` (0,1,1) silently outweighed
   `.muted` (0,1,0), so every muted-classed paragraph inside ANY door
   rendered full-ink — a specificity bug, not a style choice. Make the
   class honest everywhere; the visibly-affected door notes are enumerated
   on Ben's look-list (they now render lighter, per the class's intent). */
.door p.muted { color: var(--ink-soft); }
.door .button { margin-top: 0.5rem; }

/* Door row — the homepage fork. Cards sit side by side once there's room
   (W7-2) and stack on phones. Grid, not floats: the bordered boxes stretch to
   equal height and never interact with the margin-note float column. */
.door-row {
  display: grid;
  gap: 1.5rem;
  margin: 1.5rem 0;
  clear: right;
}
.door-row .door { margin: 0; }
@media (min-width: 48rem) {
  .door-row { grid-template-columns: 1fr 1fr; align-items: stretch; }
}

/* Quiet companion link tucked directly under a door headline (W7-3). */
.door .doorsub {
  margin: -0.35rem 0 0.9rem;
  font-size: var(--text-sm);
}

/* --- R18.2: homepage card layout (reviewer-led refinement) ----------------- */
/* Scoped to the HOMEPAGE row only (.door-row--home) — the login page's
   .door-row keeps its symmetric layout. Seeds: asymmetric columns with the
   general-services card wider (Ben); ONE internal spacing scale via a
   flow rule; the door list as structured two-line units; button+descriptor
   bound as a unit; the proceeds footer pinned to the card's bottom edge so
   the row closes on a shared baseline. Mobile stacking order unchanged. */
.door-row--home { --door-gap: 0.9rem; }
@media (min-width: 48rem) {
  .door-row--home { grid-template-columns: 2fr 3fr; }
}
@media (min-width: 64rem) {
  /* Round 2 (reviewer): at wide widths the row ESCAPES the prose measure
     and spans the FW-1-framed block — max-width released past the
     `.page > *` cap, negative right margin reaching into the reserved
     annotation gutter (side-width + 2.5rem of .page padding). GEOMETRY,
     verified against the frozen rails: the innermost RIGHT bar sits exactly
     ON the .page border-box right edge (::before right:-2.2rem, bars at
     right 2.2/1.1/0 stepping OUTWARD), so holding the row 0.75rem short of
     the full padding leaves 0.75rem of daylight between the card border and
     that bar — token-derived, identical at 1440 and 1920. Below 64rem
     nothing changes (the 48rem asymmetric grid stands; medium's two-line h2
     break after "(SLS)" is deliberate per review). */
  .door-row--home {
    max-width: none;
    margin-right: calc(-1 * (var(--side-width) + 2.5rem) + 0.75rem);
    /* R18.7 (Ben whip-through): the General card holds ~410px at the wide
       reference; the freed space goes to the DIVISION card (chosen over
       shrinking the row: the frame-spanning composition + 12px rail
       daylight from R18.2 stay intact, only the fulcrum moves). px as
       dictated. Medium keeps the 48rem 2fr/3fr; 390 stacking untouched. */
    grid-template-columns: minmax(0, 1fr) 410px;
  }
}
.door-row--home .door { display: flex; flex-direction: column; }
.door-row--home .door > * { margin-block: 0; }
.door-row--home .door > * + * { margin-top: var(--door-gap); }
.door-row--home .door > h2 { margin-top: 0.15rem; }        /* tight under the eyebrow */
.door-row--home .door > .doorsub { margin-top: 0.25rem; }  /* companion link hugs the h2 */
.door-row--home .door > .door-footer {
  margin-top: auto;
  padding-top: var(--door-gap);
}

/* Structured door list (reviewer round-1 spec b): no discs; hanging rows —
   the door name STRONG at a fixed left edge over its muted descriptor, every
   wrapped line aligning to the same text edge (block spans in one column =
   nothing ever falls back to a bullet gutter). Same treatment in all states,
   member links included. Identical words. */
.door-list {
  list-style: none;
  padding-left: 0;
  margin: 0;
}
.door-list li + li { margin-top: 0.6rem; }
.door-list .door-name { display: block; font-weight: 600; }
.door-list .door-desc { display: block; font-size: var(--text-sm); }

/* Cross-card rhythm (spec c): the left card's "...for:" lead sits in the
   same tight band under its h2 as the right card's doorsub, so the two
   cards' tops align across the row. */
.door-row--home .door > .door-lead { margin-top: 0.25rem; }
.door-lead p { margin: 0; }

/* (R18.3 item 2 — the muted-inside-door fix Ben's descriptor mismatch
   exposed — lives GLOBALLY next to the .door p rule above; the home-scoped
   duplicate was dropped as redundant per the lead's ruling.) */

/* Button + descriptor bind as one unit (spec d): descriptor tight under its
   button, clear air between groups, and both track buttons share ONE width
   sized to the longest label (min-width knob; not full-width). */
.order-option p,
.order-option form { margin: 0; }
.order-option .button {
  margin-top: 0;
  min-width: 14.5rem;
  max-width: 100%;
  text-align: center;
}
.order-option .order-desc { margin-top: 0.35rem; }

/* External signed-in homepage card (R41, Ben's pick A): the shop front, then the three most recent
   orders as quiet ruled rows, the orders link, the proceeds footnote. */
.door--ext .orders-label { margin-top: 1.2rem; }
.orders { list-style: none; padding: 0; margin: 0.5rem 0 0; }
.orders li { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
             padding: 0.42rem 0; border-top: 1px solid var(--rule); }
.orders li:last-child { border-bottom: 1px solid var(--rule); }
.orders .o-name { font-weight: 600; }
.orders .o-when { color: var(--ink-soft); font-size: var(--text-sm); margin-left: 0.6rem; }
.orders .o-status { color: var(--ink-soft); font-size: var(--text-sm); white-space: nowrap; }
.orders-more { margin: 0.6rem 0 0; font-size: var(--text-sm); }
.door--ext .door-footer { margin-top: 1.1rem; }
/* The quiet WashU-Key note under the card (ruled note treatment). */
.washu-note { margin-top: 2.6rem; padding-top: 0.9rem; border-top: 1px solid var(--rule);
              font-size: var(--text-sm); color: var(--ink-soft); max-width: var(--measure); }
.washu-note p { margin: 0; }
.door-row--home .door > .order-option + .order-option { margin-top: 1.25rem; }

/* Track buttons rendered as zero-JS forms sit flush in the CTA row. */
.cta-row form { margin: 0; }

@media (min-width: 64rem) {
  .door .marginnote, .door .sidenote {
    float: none;
    clear: none;
    width: auto;
    margin-right: 0;
    border-left: 2px solid var(--rule);
    padding-left: 0.9rem;
  }
}

/* CTA row — button + quiet secondary link; wraps as a unit, no &nbsp; hacks. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem 1.3rem;
  margin: 0.9rem 0 0.2rem;
}
.cta-row p { margin: 0; }

/* --- Flow figure (axis-style sequence diagram; inline SVG, no JS) ---------- */
.flowfig { margin: 1.3rem 0 0.5rem; }
.flowfig svg { display: block; width: 100%; height: auto; }
/* Phones (R50 #7, flowfig-spec-01 option a): a second, two-row SVG of the same
   seven steps replaces the one-row figure at or below 48rem, so the type never
   drops under ~10 px and nothing scrolls (the R1-3 scroller is gone, and with
   it the R4-6 BFC-vs-float note). One figure, one caption, one accessible
   name at any width: the hidden SVG is display:none. */
.flowfig svg.flowfig-phone { display: none; }
@media (max-width: 48rem) {
  .flowfig { overflow-x: visible; }
  .flowfig svg { min-width: 0; }
  .flowfig svg.flowfig-wide { display: none; }
  .flowfig svg.flowfig-phone { display: block; max-width: 26rem; }
}
/* Wide screens: never let gutter floats narrow the figure — start it below any
   active margin-note float (same fix family as .door / .page form). */
@media (min-width: 64rem) {
  .flowfig { clear: right; }
}
.flowfig .axis   { stroke: var(--ink); stroke-width: 1.25; fill: none; }
.flowfig .arrow  { fill: var(--ink); }
.flowfig .tick   { fill: var(--ink); }
.flowfig .leader { stroke: var(--rule-firm); stroke-width: 0.75; }
.flowfig text {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.07em;
  fill: var(--ink-soft);
}

/* --- Notice block (member-only / coming-soon stubs) ----------------------- */
.notice {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  background: var(--accent-bg);
  padding: 1rem 1.2rem;
  margin: 1.5rem 0;
}
.notice .label { color: var(--accent); }
.notice p:last-child { margin-bottom: 0; }

/* --- Operator / behind-the-scenes pages (R12 W0) -------------------------- */
/* The minimalist reading-measure is LIFTED for staff pages so wide queue tables
   and multi-button action cells fit at any width (no h-scroll / clipped cells).
   PUBLIC pages keep the full brief; this is scoped to body.operator-area, which
   the operator templates set via the body_class block. */
body.operator-area .shell { max-width: 100%; }
body.operator-area .page,
body.operator-area .page > * { max-width: none; padding-right: 0; }
/* No FW-1 article-edge rules behind the operator gate (relaxed brief, full-width
   tables — the centered-block framing device is a PUBLIC-page concern). */
body.operator-area .page { background-image: none; }
body.operator-area .page::before { content: none; }  /* FW-1 v2: no rails behind the gate */
/* Collapsed, re-openable resolved-notes group on the dashboard (W12-1/D). */
.resolved-notes { margin: 0.5rem 0 1.5rem; }
.resolved-notes > summary { cursor: pointer; color: var(--ink-soft); }
/* Inline no-reload action feedback + help/filters (W12-5/W12-2/W12-8). */
.op-flash:empty { display: none; }
.op-flash-item { margin: 0.5rem 0; }
.op-flash-item--error { border-left-width: 4px; border-left-color: #b00020; }
.op-help { margin: 0.5rem 0 1rem; }
.op-help > summary { cursor: pointer; color: var(--ink-soft); }
.op-filters a[aria-current] { font-weight: 700; }
/* Refunds-owed panel (W2/E): a prominent action list of cancelled paid orders. */
.refunds-owed { border-left: 4px solid #b00020; padding-left: 1rem; margin: 1rem 0 1.5rem; }
.refund-row { margin-bottom: 1.2rem; }
/* W3 returned-deliveries operator panel; disposal-ready rows (past the hold) get
   a subtle amber tint so the safe-to-discard ones stand out. */
.returned-deliveries { border-left: 4px solid #9a6700; padding-left: 1rem; margin: 1rem 0 1.5rem; }
.returned-row { margin-bottom: 0.9rem; }
.returned-row.disposal-ready { background: #fff7e6; padding: 0.4rem 0.6rem; }
.refund-body { width: 100%; max-width: 42rem; font-family: var(--mono); font-size: var(--text-sm); }

/* --- Forms (plain; no clever UI) ------------------------------------------ */
/* Forms drop below any floated margin-note: full-width inputs can't share a
   line with the float, which would otherwise orphan a label above the gap. */
.page form { clear: right; }
form .field { margin-bottom: 1.1rem; }
label { display: block; font-weight: 600; margin-bottom: 0.25rem; }
/* Checkbox / radio rows read as one line — the small native control inline with
   its label, not the block-label default that strands the control on its own
   line (R14 F-2). Allauth's element templates render <input> THEN <label> (e.g.
   the email-management radios); this catches that order. Our own forms render
   the label first, so the long ToS / attestation checkboxes (label, then box)
   are deliberately NOT caught and keep their stacked layout. The login
   "remember me" row is handled in its template with .field--check. */
input[type="checkbox"] + label,
input[type="radio"] + label {
  display: inline;
  font-weight: 400;
  margin: 0 0 0 0.4rem;
}
/* Inline checkbox+label row (login "remember me"; R15 W1 checkout ToS +
   attestation): control first, statement beside it. flex-start (not baseline)
   so a LONG statement that wraps to several lines still hangs beside the box —
   consistent with a short one — instead of dropping below it. */
.field--check {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.4rem;
  margin-bottom: 1.1rem;
}
/* The label fills the row and may shrink below its content width (min-width:0),
   so a LONG statement (checkout ITAR/EAR attestation) wraps its TEXT beside the
   box, not as a whole item dropped below it by flex-wrap (reviewer nit #2). */
/* My-orders: the Order column holds an optional name (W2), so give it room. */
.orders-table td:first-child, .orders-table th:first-child { min-width: 9rem; }
/* R68 (U-30): the Unsubmitted table sits under Orders; its Delete is a quiet row link. */
.orders-table--unsubmitted { margin-top: 2rem; }
.orders-table .row-action { font-size: var(--text-sm); color: var(--ink-soft); white-space: nowrap; }
.orders-table td:nth-child(2) { white-space: nowrap; }   /* dates never break mid-date */
/* Emphasized "find me" link (W6): a more findable treatment for a key link
   (e.g. the design guidelines from the SLS page), inside the one-accent palette.
   Prototype for Ben's review -- he floated WashU red as an alternative. */
.link-strong { color: var(--accent); font-weight: 600; text-underline-offset: 0.2em; }
.link-strong:hover, .link-strong:focus { color: var(--ink); }
.field--check label { display: inline; font-weight: 400; margin: 0; flex: 1 1 0; min-width: 0; }
/* R50 (#12, required-spec-01): a required field is marked by a 5 px dot hanging
   in the left margin (label or checkbox row) and one legend per form; the
   marker is never inside the label text (accessible name unchanged). The
   submit is blocked natively (no novalidate), so only a touched-and-empty
   control colours its border; no post-submit red lines on a normal path. */
:root { --req: #ba0c2f; }
.field { position: relative; }
.field.req > label::before, .field--check.req::before {
  content: ""; position: absolute; left: -0.9rem; top: 0.55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--req);
}
.field--check.req::before { top: 0.5em; }
.req-legend { margin: 0 0 1.1rem; }
.req-legend::before {
  content: ""; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--req); margin-right: 0.45em; vertical-align: 0.15em;
}
input:user-invalid, textarea:user-invalid, select:user-invalid { border-color: #8a1f1f; }
input[type="checkbox"]:user-invalid { outline: 1.5px solid #8a1f1f; outline-offset: 2px; }
/* R50 (#55, quote-spec-01): the address block closes with a hairline so the
   attestations start below a rule; the verified email is shown, not asked;
   the mesh-repair notice is collapsed with its checkbox inside. */
.address { padding-bottom: 0.4rem; margin-bottom: 1.4rem; border-bottom: 1px solid var(--rule); }
.address .field--check { margin: -0.2rem 0 0.6rem; }
.field--static { margin-bottom: 1.1rem; }
.field--static .val { display: block; }
.notice details { margin: 0.2rem 0 0.6rem; }
.notice summary { cursor: pointer; font-size: var(--text-sm); color: var(--ink-soft); list-style: none; }
.notice summary::-webkit-details-marker { display: none; }
.notice summary::before { content: "\25B8"; display: inline-block; width: 1.1em; }
.notice details[open] summary::before { content: "\25BE"; }
.notice details ul { margin: 0.3rem 0 0 1.1em; }
.notice .field--check { margin: 0.8rem 0 0; }
/* R68 (#84): the confirm step's ship-to reads as an address (one line per
   postal line), its small label in the notice's own label voice, then the button. */
.confirm .ship-to-label { margin: 1rem 0 0.15rem; font-size: var(--text-sm); color: var(--ink-soft); }
.confirm address.ship-to { font-style: normal; margin: 0 0 1rem; line-height: 1.45; }
.confirm .change-address { margin: -0.6rem 0 1rem; }   /* R84 (#104): quiet, right under the ship-to */
.confirm .cta-row { margin-bottom: 0.5rem; }
.confirm .confirm-note { margin: 0 0 0.6rem; max-width: var(--measure); }
.attest { margin-top: 0.2rem; }
/* R50 (U-03): under 48rem the staged-files table (server-rendered or built by
   upload.js) becomes two-line rows: the file name across the row, then size,
   copies and Remove on one line. No horizontal scroll, nothing off-screen
   (iOS draws no scrollbar, so a clipped Copies box was an unsignalled trap). */
@media (max-width: 48rem) {
  .files-scroll, .staged { overflow-x: visible; }
  table.files { min-width: 0; display: block; }
  table.files caption, table.files tbody { display: block; }
  table.files thead { display: none; }
  table.files tr {
    /* R72: line 1 = the name and its size; line 2 = copies, units, Remove. */
    display: grid; grid-template-columns: auto auto 1fr auto; gap: 0.3rem 0.6rem;
    grid-template-areas: "name name name size" "qty units . remove";
    align-items: center; padding: 0.55rem 0; border-top: 1px solid var(--rule);
  }
  table.files tr:last-child { border-bottom: 1px solid var(--rule); }
  table.files td { display: block; padding: 0; border: 0; min-width: 0; }
  table.files td:nth-child(1) { grid-area: name; }
  table.files td:nth-child(2) { grid-area: size; text-align: right; }
  table.files td:nth-child(3) { grid-area: qty; }
  table.files td:nth-child(4) { grid-area: units; }
  table.files td:nth-child(5) { grid-area: remove; }
  table.files td.num { text-align: left; }
  table.files .input-qty { width: 4rem; }
  /* R72: four controls on the second line at 390: the size keeps one line. */
  table.files td.num { white-space: nowrap; font-size: var(--text-sm); color: var(--ink-soft); }
}
.field--check input { width: auto; flex: 0 0 auto; }
/* A help line or errors under an inline checkbox row (e.g. the checkout ToS /
   export-control links, R15 W1) drop to their own full-width line. */
.field--check .help, .field--check .errorlist { flex-basis: 100%; margin-top: 0.15rem; }
.field .help { font-size: var(--text-sm); color: var(--ink-soft); font-weight: 400; }
/* All text-like inputs share one treatment. `password` matters because allauth's
   login/signup/reset widgets render it — without it those fields fall back to an
   unstyled browser box (reviewer R1-5). tel/number/search are listed for the same
   reason (any allauth or future widget). */
input[type="text"], input[type="email"], input[type="url"],
input[type="password"], input[type="search"], input[type="tel"],
input[type="number"], textarea, select {
  width: 100%;
  max-width: 100%;
  font-family: var(--serif);
  font-size: var(--text-base);
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
}
textarea { resize: vertical; }
/* (W8-1's styled file-input drop target was RETIRED at R20: the input is
   visually hidden behind the Choose Files label and the staged list is the
   drop zone; the dead block + its entry in the shared text-input selector
   were stripped on reviewer direction.) */
input[type="file"]::file-selector-button {
  font-family: var(--serif);
  font-size: var(--text-sm);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 0.3rem 0.8rem;
  margin-right: 0.9rem;
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover,
input[type="file"]::file-selector-button:focus {
  background: var(--ink);
  color: var(--paper);
}
/* Narrow per-file quantity input (the upload table). */
.input-qty { width: calc(4ch + 1.6rem); text-align: center; }
.errorlist { color: #8a1f1f; font-size: var(--text-sm); list-style: none; padding: 0; margin: 0.2rem 0; }
/* Honeypot: hide the anti-spam field from people. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* --- Utilities ------------------------------------------------------------ */
.muted { color: var(--ink-soft); }
/* Keep a value and its unit together AND tight: a normal (narrow) space that
   will not break, instead of &nbsp; which the serif renders with a loose gap
   (R14 F-3, same quirk as the old "SLS 3D" spacing). */
.nowrap { white-space: nowrap; }
.stack-sm > * + * { margin-top: 0.5rem; }
.mt-0 { margin-top: 0; }
/* Present to screen readers, invisible on screen. Also the form-sentinel
   pattern (W8-3): a hidden FIRST submit button pins Enter-key implicit
   submission to a safe action. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Address labels (W10-3): print-friendly cards, one per page on paper.
   ADDRESS labels only — postage is mail & receiving's job, so no barcodes,
   no postage marks, nothing machine-readable. */
/* Packing sheets (W2/C; replaced the old address-only label). */
.packing-sheet {
  border: 1px solid var(--rule);
  padding: 1.2rem 1.4rem;
  margin: 1.2rem 0;
  max-width: 40rem;
}
.packing-sheet .ps-grid {
  display: flex;
  gap: 2rem;
  flex-wrap: wrap;
  margin-bottom: 0.8rem;
}
.packing-sheet table { margin-top: 0.3rem; }
.shipping-sheet table.kv th { text-align: left; font-weight: normal; width: 9rem; }   /* R62: the carrier form's rows */
.shipping-sheet .signoff { margin-top: 1rem; }
/* Visible placeholders (e.g. [no address on file]) must stand out on paper. */
.tktk { color: #8a1f1f; font-weight: 600; }

/* Quiet zero-JS disclosure for one line of fine print (W8-4 setup-fee
   explainer): closed it reads as a footnote, open it stays small and soft. */
.footnote {
  margin: 0.6rem 0 1rem;
  font-size: var(--text-sm);
  color: var(--ink-soft);
}
.footnote summary { cursor: pointer; }
.footnote summary:hover, .footnote summary:focus { color: var(--accent); }
.footnote p { margin: 0.4rem 0 0; max-width: var(--measure); }

/* --- Print: a clean handout ----------------------------------------------- */
@media print {
  :root { --ink: #000; --ink-soft: #333; --accent: #000; }
  body { font-size: 11pt; line-height: 1.4; }
  .masthead, .site-footer, .skip-link, .nav .signin, .button { display: none; }
  a { color: #000; text-decoration: underline; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; color: #333; }
  main { padding: 0; }
  .page, .page > * { max-width: none; padding-right: 0; }
  .page { background-image: none; }  /* no FW-1 edge rules on paper */
  .page::before { content: none; }   /* FW-1 v2: no rails on paper */
  .marginnote, .sidenote {
    float: none; width: auto; margin: 0.5rem 0;
    border-left: 2px solid #999; padding-left: 0.8rem;
  }
  .notice, .door { border: 1px solid #999; background: transparent; }
  h2, h3 { page-break-after: avoid; }
  /* Packing sheets (W2/C): one sheet per page; screen chrome drops away. */
  .screen-only { display: none; }
  .packing-sheet {
    border: none;
    page-break-after: always;
    page-break-inside: avoid;
    max-width: none;
  }
  /* No trailing blank page after the last sheet of a batch (R10.1 pattern):
     :last-of-type, not :last-child — a screen-only back-link <p> follows the
     last sheet in the DOM (display:none doesn't affect selector matching),
     and the sheets are the article's only <div>s. */
  .packing-sheet:last-of-type { page-break-after: auto; }
}

/* R42: Washington University Terms and Conditions page. Eleven OGC clauses
   reproduced verbatim: clause headings step down one size (eleven of them),
   lettered sub-items are real lists. */
.terms .terms-preamble { max-width: var(--measure); }
.terms .clause h2 { font-size: var(--text-lg); }
.terms .clause p, .terms .clause li { max-width: var(--measure); }
.terms .clause-items { padding-left: 1.6rem; margin: 0.6rem 0 0; }
.terms .clause-items li { margin-bottom: 0.7rem; }

/* R48 (#9): the checks page leads with the failing files in plain words. */
.check-file h2 { font-size: var(--text-lg); margin-top: 1.6rem; }
.check-problems { list-style: none; padding: 0; margin: 0.4rem 0 0; max-width: var(--measure); }
.check-problems li { padding: 0.55rem 0; border-top: 1px solid var(--rule); }
.check-problems li:last-child { border-bottom: 1px solid var(--rule); }
.check-problems .label { display: block; margin-bottom: 0.15rem; }
/* R48.2: one action-first sentence per hard-stop file; the other files as one
   ruled line each (passed / will be repaired automatically). */
.check-sentence { max-width: var(--measure); margin: 0.4rem 0 0; }
/* R57: an awaiting-payment row whose confirmation is stuck past the window. */
.awaiting-payment td.chase { color: #8a1f1f; font-weight: 600; }

/* R64 (U-63): touch targets on the tablet / phone keep the small type but reach ≥ 36 px. */
@media (max-width: 75rem) {
  .button--small { padding: 0.5rem 0.8rem; min-height: 2.4rem; }
}

/* R64 (U-58/U-59/U-49): under 48rem each operator row is a card: the label from
   data-label, the ref as the title, the actions as full-width buttons. Nothing
   scrolls sideways by construction (the scroller is turned off for card tables).
   Above 48rem these rules do nothing; the attributes are inert. */
@media (max-width: 48rem) {
  body.operator-area .table-scroll:has(> table.cards) { overflow-x: visible; }
  table.cards { min-width: 0; display: block; }
  table.cards thead { display: none; }
  table.cards tbody { display: block; }
  table.cards tr { display: block; border: 1px solid var(--rule); padding: 0.6rem 0.75rem; margin: 0 0 0.75rem; }
  table.cards td { display: block; padding: 0.2rem 0; border: 0; text-align: left; min-width: 0; }
  table.cards td.num { text-align: left; }
  table.cards td::before { content: attr(data-label); display: block; font-family: var(--mono, monospace); font-size: var(--text-xs, 0.75rem); letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft); }
  table.cards td:first-child::before { content: none; }
  table.cards td:first-child { font-size: 1.1rem; font-weight: 600; }
  table.cards td[data-label="Actions"] form { display: flex; flex-direction: column; gap: 0.5rem; }
  table.cards td[data-label="Actions"] .button { display: block; width: 100%; text-align: center; margin: 0; }
  table.cards td[data-label="Actions"] .button--primary { order: -1; }
  body.operator-area input[type="text"], body.operator-area input[type="number"], body.operator-area textarea { font-size: 16px; }
}

/* R64 (#74): the packing checklist (tablet-first). */
.checklist .progress { width: 100%; height: 0.6rem; margin: 0 0 1rem; }
.check-row { padding: 0.9rem 0; }
.check-row.ok { background: #f2f8f2; }
.check-row.prob { background: #fff4f4; }
.check-head { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.check-expected { white-space: nowrap; }
.check-controls { display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; align-items: center; }
.stepper { display: inline-flex; align-items: center; gap: 0.25rem; }
.stepper .step { min-width: 3.4rem; min-height: 3.4rem; font-size: 1.4rem; padding: 0; margin: 0; }
.stepper .count { width: 4.5rem; min-height: 3.4rem; text-align: center; font-size: 1.3rem; font-variant-numeric: tabular-nums; }
.stepper .count.short { color: #b00020; border-color: #b00020; }
.toggle { display: inline-flex; align-items: center; gap: 0.5rem; min-height: 3.4rem; padding: 0 0.9rem; border: 1px solid var(--ink-soft); cursor: pointer; }
.toggle input { width: 1.4rem; height: 1.4rem; margin: 0; }
.toggle:has(input:checked) { background: var(--ink); color: var(--paper); }
.check-note textarea { font-size: 16px; width: 100%; }
.checklist-bar { position: sticky; bottom: 0; display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.75rem 0; background: var(--paper); border-top: 1px solid var(--rule); }
.checklist-bar .button { min-height: 2.75rem; display: inline-flex; align-items: center; justify-content: center; }   /* reviewer: the bar's link is a 44 px control at every width */
.checklist-bar .button.is-disabled { opacity: 0.45; pointer-events: none; }
.check-others { list-style: none; padding: 0; margin: 1.6rem 0 0; max-width: var(--measure); }
.check-others li { padding: 0.45rem 0; border-top: 1px solid var(--rule); }
.check-others li:last-child { border-bottom: 1px solid var(--rule); }
