/* ============================================================================
   shared/slide-datums-view.css — the ONE stylesheet for the "Drawer slide
   positions" dialog (shared/slide-datums-view.js renders the markup; both
   modules/festool-systainer-cabinet-width/systainer-bank.html's #slideDatumPanel
   and modules/cut-list-optimizer/cut-list-optimizer.html's #cloSlideDatumsPanel
   load this one file via <link rel="stylesheet">).

   WHY THIS MOVED OUT OF TWO PAGE-LOCAL <style> BLOCKS (P2020, his order,
   2026-09-09: "the tables are really basic and really difficult to follow...
   make it much cleaner and easier to read... add some graphics to it"). Before
   this pass, each page carried its OWN COPY of this CSS (systainer-bank.html's
   own comment on the old block said so out loud: "copied rather than shared
   because every tool in this suite is a no-build HTML page with its own
   page-local <style>") — two copies is exactly the drift shared/job-notes.js's
   own header names as the defect this repo already paid for once. Since the
   renderer already lives in ONE shared module (shared/slide-datums-view.js),
   its stylesheet now does too; each page's own <style> keeps only what is
   genuinely page-specific (nothing, for this component).

   LITERAL rem VALUES, NEVER var(--fs-md)/var(--fs-sm): those are the PLANNER's
   own page-local tokens (systainer-bank.html only, 0.8125rem / 0.75rem) — a
   shared file loaded by cut-list-optimizer.html too would have them resolve to
   nothing on that page (that page's own former copy of this CSS already said
   so, and already inlined the literal values for exactly that reason). The
   literal numbers below equal what --fs-md/--fs-sm compute to today, so this
   is byte-identical in appearance, not a value change.

   THEME TOKENS ONLY for every colour (both pages load shared/theme.css, so
   --ink/--ink-soft/--cream-line/--cream-card/--gold-deep/--text/--accent-deep/
   --surface-2/--text-faint/--surface-hi are all live on both pages — the ink
   and cream family and the text, accent and surface family are the SAME
   tokens under two alias sets, shared/theme.css:186-194). The chrome below
   (panel, table) keeps the ink and cream family it already shipped with; the
   NEW side-elevation SVG at the bottom uses the text, accent and surface
   family, matching shared/tray-art.js's own vocabulary (this lane's brief
   named those literal tokens). NEVER write an asterisk directly followed by
   a forward slash anywhere in this file's own comments, in any spelling,
   including inside a quoted example of the mistake itself (round-4 review,
   P1): typing a token name with a trailing wildcard star right up against
   the slash that follows it — the exact glob-style shorthand this comment
   used to use for "every token starting with -accent" — closes the
   surrounding comment block early, on that very pair of characters. The CSS
   parser then reads the rest of the comment's own prose as CSS, corrupts
   recovery, and the next real rule (dialog.sd-datum-panel) never parses at
   all. Measured on the live bug this caused: the dialog rendered at 1402px
   instead of 960px, with its padding, radius, border and shadow gone and its
   background fallen to the UA default Canvas — a silent failure with no
   console error, because the broken text is valid to a human eye reading it
   as prose and invalid only to the parser reading it as syntax. Write out
   "asterisk" and "slash" as words, or separate the two characters with a
   space, whenever this file's own comments need to refer to either one.

   P2028 (2026-09-09, his screenshot + words: "the formatting is absolutely
   horrible... images all over the screen, not aligned... no proper
   categories... make this world-class"). Redesigned as one categorised
   sheet: a sticky action sub-row for the story-stick button, the Spacer cut
   list first (a shop cuts spacers before any tray goes in) with a big-number
   tile per height, then one section per tier ("Lower cabinets", "Upper
   cabinets") holding one card per cabinet — a name plus a quiet metadata
   line, then its table LEFT and its drawing RIGHT, `flex-wrap: nowrap` now
   (never below each other at the dialog's own 960 px shell) rather than the
   P2020 wrap that let the drawing land in three different places on one
   sheet. Full account, including why there is no third "Groups" category:
   docs/design-system/stackdesign-slide-datums.md's own P2028 section.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   THE DIALOG SHELL (moved verbatim from systainer-bank.html's own
   dialog.sd-datum-panel block, 2026-09-08 — see that commit for the "native
   <dialog>, opened with showModal()" design history; unchanged here).
   --------------------------------------------------------------------------- */
/* P2033 (his words, 2026-09-09: "you need to adjust the window size so that you don't have a
   slider anymore" — the horizontal scrollbar under every cabinet card on both the planner and
   the cut-list optimizer). 960px was sized for the table ALONE, before P2020 added the side
   elevation beside it — once both live in one nowrap row, the pair needs table(>=640px) + gap
   (16px) + elevation(<=380px, shared/slide-datums-view.js#cabinetElevationSvg's own on-screen
   contract) + this dialog's own 40px of left+right padding = 1076px, and a 960px shell forced
   the leftover ~116px into the .sd-datum-cab-body overflow-x:auto "safety net" below on every
   card — which is exactly the scrollbar he saw. Widened to fit that sum with room to spare;
   1180px is a round number above 1076px, not a re-derivation of it. */
dialog.sd-datum-panel {
  width: min(1180px, 96vw);
  max-height: calc(100vh - 48px);
  margin: auto;
  background: var(--cream-card); border: 1px solid var(--cream-line);
  border-radius: 14px; box-shadow: 0 18px 48px rgba(0,0,0,0.30);
  padding: 16px 20px 20px; color: var(--ink); text-align: left;
}
dialog.sd-datum-panel[open] { display: flex; flex-direction: column; }
.sd-datum-panel::backdrop { background: rgba(20, 16, 12, 0.45); }
.sd-datum-panel-head { display: flex; align-items: baseline; gap: 10px; margin: 0 0 8px; padding-bottom: 9px; border-bottom: 1px solid var(--cream-line); flex: 0 0 auto; }
.sd-datum-panel-title { font-size: 0.8125rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.13em; color: var(--ink); }
.sd-datum-panel-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
/* Copy / Print, matching the planner's own .ctrl-btn look — cut-list-optimizer.html
   has no .ctrl-btn of its own to reuse (that class lives outside this file's scope,
   on the planner only), so the SAME rendered result is reproduced under this
   page-neutral name instead; the planner's own dialog markup uses .ctrl-btn
   directly and simply never matches this selector, which is harmless. */
/* P1-5 (Opus web-design-auditor round 2, control-surface contrast — the standing P2027 rule:
   "a control never shares its container's surface") — both buttons filled with the SAME
   var(--cream-card) the dialog itself fills with (or transparent, which reads as the same
   thing), with only a 1px var(--cream-line-2) border: measured 1.56:1 Linen / 1.63:1 Midnight,
   nowhere near WCAG 1.4.11's 3:1. --surface-2 (the brief's own first suggestion) does NOT fix
   this — it is deliberately close in luminance to --cream-card/--surface within this palette's
   own "soft"/"surface" family (measured by hand: white vs #ebe8e0 in Linen tops out under
   1.25:1), so a fill swap alone cannot clear the floor here. The BORDER moves to --ink-soft
   instead: 6.65:1 Linen (#565d66 on #ffffff), 7.34:1 Midnight (#a3b0bd on #1a212a) — both
   comfortably over 3:1, and --ink-soft already IS this dialog's own secondary-text colour, so
   the border reads as intentional chrome rather than a new hue. */
/* P3-I (round 3, Opus web-design-auditor) — Copy/Print/"Print story stick" and Close sit in
   the SAME .sd-datum-panel-actions row, but only Close ever declared an explicit height (30px);
   the other three's own box height was whatever 6px 10px padding plus their 0.75rem line-height
   happened to compute to, measured 31.4px on a real Chromium render against Close's own 30.0px
   — a 1.4px row-mate mismatch on two different y-values, both pages. FIX: the same explicit
   30px height (box-sizing: border-box is this dialog's own page-wide reset, both host pages —
   the border is INSIDE the 30px, matching Close's own arithmetic exactly), horizontal-only
   padding so the icon/label pair still breathes sideways. */
.sd-datum-panel-actionbtn {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  border: 1px solid var(--ink-soft); border-radius: 8px; background: var(--cream-card);
  color: var(--ink-soft); font: inherit; font-size: 0.75rem; font-weight: 700;
  height: 30px; padding: 0 10px; cursor: pointer;
}
.sd-datum-panel-actionbtn:hover { background: var(--cream-line); color: var(--ink); }
.sd-datum-panel-actionbtn:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; }
.sd-datum-panel-close {
  flex: 0 0 auto; width: 30px; height: 30px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink-soft); border-radius: 8px; background: transparent;
  color: var(--ink-soft); font: inherit; font-size: 1rem; line-height: 1; cursor: pointer;
}
.sd-datum-panel-close:hover { color: var(--ink); border-color: var(--gold-deep); }
.sd-datum-panel-close:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; }
/* N9 (round 4, Opus web-design-auditor) — on the PLANNER page, Copy/Print in this same
   .sd-datum-panel-actions row are page-owned `.ctrl-btn` markup (systainer-bank.html's own
   dialog, not this module's .sd-datum-panel-actionbtn class — checked directly: the cut-list
   optimizer's OWN Copy/Print already use .sd-datum-panel-actionbtn and already ring the same as
   Close), so .sd-datum-panel-actionbtn:focus-visible above never even matches them — they inherit
   the planner page's own `.ctrl-btn:focus-visible` (3px var(--gold)) instead, while Close right
   beside them rings 2px var(--gold-deep): two different focus rings in ONE row on ONE page. FIX,
   scoped to this row only (the planner's `.ctrl-btn:focus-visible` stays exactly as-is everywhere
   ELSE it appears on that page — this is not a global `.ctrl-btn` retune): a rule with strictly
   higher specificity than `.ctrl-btn:focus-visible` (0,1,1), written here so it wins regardless of
   the two stylesheets' own load order, unifies every button in this row — both pages — on the
   SAME 2px var(--gold-deep) ring Close and the cut-list optimizer's Copy/Print already carry.
   `.sd-datum-panel .ctrl-btn` (not a bare `.ctrl-btn`) keeps this scoped to the dialog the brief
   named, never touching `.ctrl-btn` anywhere else on the planner page. */
.sd-datum-panel-actions .sd-datum-panel-actionbtn:focus-visible,
.sd-datum-panel-actions .sd-datum-panel-close:focus-visible,
.sd-datum-panel .sd-datum-panel-actions .ctrl-btn:focus-visible {
  outline: 2px solid var(--gold-deep); outline-offset: 2px;
}
.sd-datum-panel-intro { margin: 0 0 10px; font-size: 0.75rem; line-height: 1.5; color: var(--ink-soft); flex: 0 0 auto; }
.sd-datum-panel-body { min-height: 0; overflow-y: auto; overflow-x: hidden; font-size: 0.86rem; line-height: 1.45; }
.sd-datum-panel-empty { margin: 0; font-size: 0.8125rem; color: var(--ink-soft); }
/* P1-4 (Opus web-design-auditor round 2) — the rendered markup wraps this dialog's own content
   in `<section class="job-notes sd-datum-list">` (shared/slide-datums-view.js#html()), and
   cut-list-optimizer.html carries its OWN page-local `.job-notes { background: var(--cream-2) }`
   rule (its run-level notes block, elsewhere on that page) which collides here by class name
   alone — the dialog's own tiles/borders were all tuned against --cream-card (what the planner's
   own dialog already resolves to, since it declares no competing `.job-notes` rule), so on the
   optimizer they measured down to 1.03:1 borders and the sticky table header's own hard-coded
   --cream-card (css, .sd-datum-table thead th above) painted a visible stripe against the
   mismatched --cream-2 underneath it. ONE fix, in the shared file both pages load, at higher
   specificity (0-2-0) than the page-local `.job-notes` (0-1-0) it overrides: forces --cream-card
   here regardless of which host page's own generic `.job-notes` rule would otherwise apply —
   this dialog now renders identically on both pages, and the sticky header's own background
   matches its surroundings again. */
.sd-datum-panel .sd-datum-list { background: var(--cream-card); }

/* ---- P2028 — the category sections. ---- */
/* fix round (Opus web-design review, P1, css:122-126) — the story-stick button used to sit
   in its own sticky sub-header band (.sd-datum-subhead), whose z-index (2) sat ABOVE the
   per-cabinet table's own sticky <thead> (z-index 1) once the panel scrolled ~900px, covering
   the column headers a shop needs while reading down a tall sheet. THE BAND ITSELF IS GONE —
   shared/slide-datums-view.js#html() now emits a bare button, moved by a document-level
   observer (wired near the bottom of that file, "STORY-STICK BUTTON PLACEMENT") into the
   page-owned .sd-datum-panel-actions row, before Copy — no z-index stacking to get wrong
   because there is no longer a second banded row for it to be wrong ON. */

/* ONE category section per tier ("Lower cabinets", "Upper cabinets" — no third "Groups"
   section: shared/slide-datums-view.js#html()'s own block comment on why). Each carries a
   heading and a one-line lede; the spacer section reuses the same heading style. fix round
   (Opus web-design review, P2 hierarchy item) — the category title now sits ABOVE the
   cabinet name in both size and weight, unambiguously: 1.05rem/800 with tracked letter-
   spacing (a section title, read once per category) against the cabinet name's 0.86rem/700
   (read once per card) — see .sd-datum-cab-name below. */
.sd-datum-panel .sd-datum-category { margin: 0 0 18px; }
.sd-datum-panel .sd-datum-category:last-child { margin-bottom: 0; }
.sd-datum-panel .sd-datum-category-title {
  margin: 0 0 2px; padding-bottom: 6px; border-bottom: 1px solid var(--cream-line);
  font-size: 1.05rem; font-weight: 800; letter-spacing: 0.02em; color: var(--ink);
}
.sd-datum-panel .sd-datum-category-lede { margin: 6px 0 10px; font-size: 0.8rem; color: var(--ink-soft); }
/* a cabinet with nothing to measure (adjustable shelves, a refused config, a SYS-AZ bay, an
   ordinary cabinet whose positions could not be computed) — one quiet row INSIDE its own
   category, never a loose sentence floating outside every section (his own complaint, item 4). */
.sd-datum-panel .sd-datum-quiet-row {
  margin: 0 0 6px; padding: 8px 10px; border-radius: 8px;
  background: var(--surface-hi); font-size: 0.82rem; color: var(--ink-soft);
}
/* fix round (Opus web-design review, P2 copy item) — this used to print inline after
   whichever cabinet drew the first svg, a full-width paragraph wedged BETWEEN two cards on
   the sheet (indistinguishable from a card boundary). shared/slide-datums-view.js#html() now
   builds it once, as the second LINE of the Lower cabinets category's own lede (his own
   complaint, item 6: "the drawings share one job-wide scale but nothing says so") — `display:
   block` is what actually makes it a second line rather than running on from the lede's own
   sentence, since the two now share one <p>. */
.sd-datum-panel .sd-datum-scale-note { display: block; margin: 4px 0 0; font-size: 0.74rem; font-style: italic; color: var(--ink-soft); }

/* fix round (Opus web-design review, hierarchy item) — .sd-datum-cab gets a visible border +
   padding now ("so one card per cabinet is visible" — before this, only the disclosure
   marker and a 6px margin separated one cabinet from the next, easy to misread as one
   continuous block on a tall sheet).
   P1-D (round 3, Opus web-design-auditor) — --surface-hi turned out to be the wrong choice: the
   card paints no background of its own (it reads through to the sheet's own --cream-card, a
   1.00:1 match by construction), so the BORDER is the card's only visible boundary, and
   --surface-hi against that same --cream-card measured 1.17:1 Linen / 1.34:1 Midnight — nowhere
   near WCAG 1.4.11's 3:1, and this card's own <summary> IS a real, clickable disclosure control
   (P2027's own standing rule: a control never shares its container's surface). --ink-soft is
   this dialog's own already-proven fix for exactly this pairing (the action buttons directly
   above, P1-5 round 2): 6.65:1 Linen (#565d66 on #ffffff), 7.34:1 Midnight (#a3b0bd on
   #1a212a) — both comfortably over 3:1, and reusing it here (rather than a third hand-picked
   token) keeps one border colour for "this dialog's own interactive chrome", not two. */
.sd-datum-panel .sd-datum-cab {
  margin: 0 0 12px; padding: 12px; border: 1px solid var(--ink-soft); border-radius: 10px;
}
.sd-datum-panel .sd-datum-cab > summary {
  display: flex; align-items: flex-start; gap: 6px; list-style: none;
  margin-bottom: 4px; cursor: pointer; border-radius: 6px;
}
.sd-datum-panel .sd-datum-cab > summary::-webkit-details-marker { display: none; }
/* fix round (Opus web-design review, P2 copy item, css:157-160) — a 10px --ink-soft triangle
   read as a stray mark rather than a control once the summary grew a second (meta) line
   beneath the name: bumped to .9em / --ink (matches the name's own ink, not the muted meta
   line) and pinned to the TOP of the two-line block (align-self: start — the flex row's
   default `center` put it beside the meta line, not the name, once the block grew a second
   line) with a small top nudge so it optically lines up with the name's own cap-height. */
.sd-datum-panel .sd-datum-cab > summary::before {
  content: '\25B8'; display: inline-block; align-self: flex-start; margin-top: 2px;
  font-size: 0.9em; color: var(--ink); transition: transform 0.15s ease;
}
.sd-datum-panel .sd-datum-cab[open] > summary::before { transform: rotate(90deg); }
.sd-datum-panel .sd-datum-cab > summary:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; }
/* a hover/open affordance beyond the marker's own rotation — a real <summary> IS a button,
   and this shell had no visual signal that it is one until the pointer already clicked. */
.sd-datum-panel .sd-datum-cab > summary:hover { background: var(--surface-hi); }
.sd-datum-panel .sd-datum-cab[open] > summary { margin-bottom: 10px; }
/* P2028 — the consistent per-cabinet heading row: the cabinet's own name, then a quiet
   metadata line underneath it (inside height, and the derivable half of "slide model" — side-
   mount vs undermount, off row.provisional). Stacked in their own wrapper rather than left as
   two direct children of the flex `summary`, so the second line drops UNDER the first instead
   of racing it along one row when a shop-typed name runs long (the standing no-truncation /
   no-wrap-surprise rule — a name and its metadata must never fight for the same line).
   fix round (hierarchy item) — the name is now an explicit 0.86rem/700 (was inherited
   0.86rem/800, indistinguishable in weight from the category title above it). */
.sd-datum-panel .sd-datum-cab-head { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.sd-datum-panel .sd-datum-cab-name { font-size: 0.86rem; font-weight: 700; color: var(--ink); }
.sd-datum-panel .sd-datum-cab-meta { font-weight: 400; font-size: 0.72rem; color: var(--ink-soft); }
.sd-datum-panel .job-notes-title { margin: 0 0 4px; font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-soft); }
.sd-datum-panel .job-notes-title:not(:first-child) { margin-top: 12px; }
.sd-datum-panel .job-notes-body { margin: 0 0 6px; }

/* the spacer cut list's own big-number tiles — one per DISTINCT height, ahead of the
   reference table (his order, P2020 rewrite under P2028: "add some graphics... so someone
   could follow it visually", applied here to the section a shop reads FIRST at the saw). */
.sd-datum-panel .sd-spacer-tiles { display: flex; flex-wrap: wrap; gap: 10px; margin: 8px 0 12px; }
/* N8 (round 4, Opus web-design-auditor) — --cream-line measured 1.32:1 Linen / 1.26:1 Midnight
   against this tile's own --surface-hi fill, nowhere near WCAG 1.4.11's 3:1, while the cabinet
   cards right below this section (.sd-datum-cab, further down) already carry --ink-soft at
   6.65:1 / 7.34:1 (P1-D, round 3) — two container borders on the SAME sheet reading at wildly
   different strengths is not one container language. FIX: the same --ink-soft border the cards
   already use, so every bordered surface on this sheet reads as one consistent chrome vocabulary
   rather than the tiles looking unintentionally faint beside the cards.
   P99 idx 188 (polish sweep, 2026-09-15) — a bare `min-width: 132px` on a flex-wrap child with
   no grow (the implicit `flex: 0 1 auto` default) sizes every tile to its own content and never
   spends any leftover row width, so whenever the tile count does not divide evenly into a row
   the LAST row falls short of the dialog's own content edge, a visible dead gap on the right
   (content-fills-its-container violation; measured on a 10-tile fixture at 1440px: a 6-tile row
   reached 87% of the 1140px content width, a trailing 4-tile row only 58%). FIX: the SAME
   pattern this file's own P1-A comment already uses for the table/drawing gap (a bounded
   `flex-grow`, never an unbounded one) — every tile grows to help fill ITS OWN row (flex-wrap
   runs each row as its own independent flex line, so a short trailing row absorbs all of its
   own leftover space without touching a full row above it, which has none to absorb), capped by
   max-width so a row with very few tiles cannot balloon a single tile to an absurd width. The
   floor moves from `min-width` to `flex-basis` (128) so every tile starts from the SAME number
   regardless of its own content's natural width — content-driven width previously produced
   subtly uneven columns row to row; a shared basis reads as one deliberate grid. */
.sd-datum-panel .sd-spacer-tile {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  flex: 1 1 128px; min-width: 128px; max-width: 240px; padding: 10px 12px;
  background: var(--surface-hi); border: 1px solid var(--ink-soft); border-radius: 10px;
}
.sd-datum-panel .sd-spacer-tile-height { font-size: 1.35rem; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.sd-datum-panel .sd-spacer-tile-mm { font-size: 0.72rem; color: var(--ink-soft); }
.sd-datum-panel .sd-spacer-tile-pieces { font-size: 0.78rem; font-weight: 700; color: var(--ink); }
.sd-datum-panel .sd-spacer-tile-used { font-size: 0.72rem; color: var(--ink-soft); }

/* P2020 ROUND 2 (2026-09-09): the table stretched to ~1200px with its numbers
   marooned far from Slide, and the drawing was "a 60 px sliver at the far
   right". Round 1 made the table the flexible item (flex: 1 1 240px), which
   is exactly backwards — a table that GROWS to fill the row is a table that
   stretches however wide the row happens to be, with nothing to fill the
   stretch except dead space between columns. Neither item grows: the table
   sizes to its own CONTENT (width: auto, capped at the panel width), and the
   drawing keeps the real, fixed px size shared/slide-datums-view.js#
   cabinetElevationSvg computes (300-420 px wide at the panel's own 960 px
   shell, height scaling with the cabinet up to ~360 px — see that function's
   own header for why).

   P2028 (his own complaint, item 1: the drawings sit in three different
   places on one sheet — two floated right of their table, a third dropped
   BELOW its table). That is exactly what flex-wrap: wrap did the moment the
   pair's combined width crossed the panel: it is the mechanism this card
   asks removed, not a size to retune. `flex-wrap: nowrap` now, at the
   dialog's own widened shell (desktop/tablet only, per the standing width
   floor — nothing narrower is a defect class here) — table and drawing are
   top-aligned and never wrap below each other, measured at both 1280 px and
   1440 px viewports (the dialog itself is capped at min(1180px, 96vw), so
   both already render the SAME 1180 px shell; see dialog.sd-datum-panel
   above).

   P2033 (his words, 2026-09-09 — see dialog.sd-datum-panel's own comment
   above for the full complaint and the arithmetic that produced 1180px):
   `overflow-x: auto` used to be the "safety net" for a row wide enough to
   overflow — that safety net is what he was actually seeing as a horizontal
   scrollbar under every card. REMOVED: overflow is now impossible BY
   CONSTRUCTION instead of caught after the fact — the table below sizes to
   its own content (no forced min-width; see .sd-datum-table's own comment
   further down for why a fixed floor would be wrong here) and simply never
   needs more room than the dialog's own widened shell provides, and the
   media query just below this rule wraps the drawing UNDER its table (never
   a scrollbar) on any viewport narrower than the point where 1180px/96vw
   can no longer hold table +
   gap + drawing + the dialog's own 40px of padding side by side — the same
   640 + 16 + 380 + 40 = 1076px sum named above, solved for vw at 96vw. */
/* P2-8 (Opus web-design-auditor round 2) — a card is its own full row width (the
   card is the block; the table+drawing pair inside it is a flex row that only ever
   sizes to its OWN content, `flex: 0 0 auto` on both children — see their own
   comments below), so a short table (the "saws" cabinet) or a table shorter than
   its own drawing left an L-shaped dead zone: a horizontal strip right of the pair
   (table 597 + gap 16 + drawing 302 in a measured 1054px card), and a vertical
   strip under a 2-row table once the drawing is the taller of the two.
   P1-A (round 3, Opus web-design-auditor, "P2-8 reopened") — `justify-content:
   space-between` did not remove the dead zone, it just MOVED it: the leftover
   width became one single, undivided GAP between the table and the drawing
   (22-389px measured across real cards, 35 percent of the card's own width on
   his own Tools card at 1440px) — a wide, empty CENTRE strip instead of a wide,
   empty TRAILING one, still dead space either way. FIX: the gap is FIXED now
   (24px, never distributed), and the drawing itself grows to spend the leftover
   width instead of leaving it blank — `flex: 1 1 auto` on the drawing (below),
   never `justify-content` doing the distributing. The table stays `flex: 0 0
   auto` (its own content decides its width, unchanged — the P2033 comment just
   below still rules out forcing it wider); the drawing is the ONE flexible
   item in this row, so 100 percent of whatever width the table does not need
   goes into making the drawing bigger — legible, useful pixels, never blank
   paper. */
/* N5 (round 4, Opus web-design-auditor) — align-items was flex-start: the row's own cross-axis
   size is the taller of the table/drawing pair (the S+S long-code pair's own drawing, with its
   numbered-key badges and taller wrapped Holds text), but flex-start pins the SHORTER item
   (usually the table) to the top and leaves the rest of the row's own height as a blank void
   under it — measured 128-315px, up to 32 percent of the card, at 1440px on a real long-code
   cabinet. FIX (round 4): align-items: stretch made every flex item's own box fill the row's
   full cross-axis size, so the card's own height was exactly the taller of the two, no void
   beneath the shorter one.
   P1 stretch (round 5, Opus web-design-auditor) — stretch fixed the void UNDER the table but
   poured it INTO the table instead: a stretched <table> distributes its extra height across
   its own rows (auto table layout is allowed to grow row height to fill a forced box height),
   measured on the saws cabinet (two data rows): table box 143px to 342px, rows landing 135px
   apart instead of their natural ~40px. FIX: align-items: center on the row (this rule) plus
   align-self: center on .sd-datum-table (below) — the row's own cross size is still the
   taller item (the drawing, which keeps its explicit align-self: center so it is never
   re-centred oddly), but the table is now CENTRED in that height rather than stretched to
   fill it, so the blank space the height mismatch creates sits split evenly above and below
   the table's own natural-height rows, never inside them. */
.sd-datum-panel .sd-datum-cab-body { display: flex; align-items: center; gap: 24px; flex-wrap: nowrap; }
/* P2033 — the breakpoint solved from dialog.sd-datum-panel's own 96vw factor:
   96vw >= 1076px (table 640 + gap 16 + drawing 380 + dialog padding 40) at
   vw >= 1076/0.96 = 1120.8px. Below that, 96vw can no longer fit the pair
   side by side even though the 1180px cap never binds there — so this is
   the one CSS number this file derives from the fact stated above it,
   not an independent guess. Below it, the row wraps (the drawing moves
   under its table, keeping its own on-screen size) instead of overflowing;
   above it — which covers both proof widths (1280px, 1440px) — the row
   never wraps and never scrolls. */
@media (max-width: 1120px) {
  .sd-datum-panel .sd-datum-cab-body { flex-wrap: wrap; }
  /* N4 (round 4, Opus web-design-auditor) — wrapped, the drawing kept its own row-context
     max-width: 380px even though it now has the card's FULL width to itself. FIX moved below
     the unconditional base .sd-elev-svg rule (round 5): both rules share specificity (0,3,0),
     so whichever sits LATER in the file wins regardless of the @media condition — this block
     put the override FIRST, so the unconditional 380px rule further down always overrode it at
     every width, measured (round 5, real Chromium): drawing stuck at 380px, 318px of the card's
     own full-width row left dead, at 768/1024/1120px. The active override now lives right after
     that base rule instead of here. */
}
/* fix round (Opus web-design review, P1, measured) — `align-items: flex-start` aligns the
   two flex items' own box tops, but .sd-datum-table still carried its own `margin-top: 6px`
   (needed only when this table stood alone, before P2028 deleted the one context where it
   ever did — the spacer reference table). Left in place, the table's rendered content sat a
   real, measured 6px below the drawing's own top edge even though both "start" at the same
   flex line. Zeroed here, scoped to the paired context only — every remaining .sd-datum-table
   IS this pairing now, so this is not a special case, it is the only case. */
/* P2033 — deliberately NO min-width here: a small table (the "saws" cabinet
   in his own screenshot, two rows) staying narrow is correct, not a bug —
   forcing every table to the worst-case 640px the dialog's own width budgets
   for would leave dead space beside a short table, which the standing
   "content fills its container" rule bars. `flex: 0 0 auto` already refuses
   to shrink the table below its OWN content's width; the dialog width above
   is sized for the widest real table (Tools, four rows) plus the drawing,
   so nothing this wide-or-narrower ever needs to shrink or scroll. */
.sd-datum-panel .sd-datum-cab-body .sd-datum-table { flex: 0 0 auto; margin-top: 0; align-self: center; }
/* P2-8 — centred in the row's own height track (align-items: flex-start on the row itself
   stays, for the table; this one item overrides it) rather than pinned to the top, so a
   drawing taller than a short table's own 2-3 rows reads as framed, not overflowing downward
   past the table into blank space.
   P1-A (round 3, Opus web-design-auditor) — `flex: 0 0 auto` is what let the P2-8 dead zone
   exist in the first place: a rigid item never grows, so the row's own leftover width had
   nowhere to go but the (space-between) gap. `flex: 1 1 auto` makes the drawing the row's ONE
   flexible item — it grows to consume whatever width the table (still `flex: 0 0 auto`, still
   sized to its own content) does not need, shrinks if the table is wide. `width: auto;
   height: auto` override the JS-declared width/height ATTRIBUTES (a stylesheet rule always
   outranks a presentation attribute) so the flex algorithm is free to size this element instead
   of being pinned to its own JS-computed px value; the `viewBox` (untouched) still supplies the
   drawing's own aspect ratio, so growing it never distorts it — `preserveAspectRatio=
   "xMinYMin meet"` (set in the markup itself, unchanged) keeps that scaling proportional the
   same way it already does at the JS-declared size.
   ROUND 6 (Opus web-design-auditor verification) — max-width used to be a FIXED 380px (matching
   shared/slide-datums-view.js#SD_ELEV_MAX_SCREEN_WIDTH_PX's own on-screen ceiling), which was
   the ACTUAL cause of OPEN 1: measured 110.7px of dead space between the drawing's own right
   edge and the card's, at 1280/1440px, on the planner's own "Tools" card — the ceiling existed
   to protect against an oversized FONT once fontMm scaled with a wider viewBox (round 3/4/5's
   own positive-feedback history, above), never because 380px was itself the "right" width. Now
   that the annotation font is fixed in RENDERED px, independent of the drawing's own CSS width
   (see sdElevFixupFontSize() in shared/slide-datums-view.js — a post-layout pass that scales
   every label back to the table body's own font-size regardless of how wide flex-grow makes
   this element), a wider drawing can never again produce an oversized label — so the ceiling
   that existed only to prevent that is gone. `max-width: 100%` is a real ceiling (flex-grow can
   never exceed the flex line's own available width regardless of what max-width says), never a
   no-op — it is the SAME budget "fill the drawing column, never leave a stub" already asks for,
   stated directly instead of through a since-decoupled JS constant. */
.sd-datum-panel .sd-datum-cab-body .sd-elev-svg { flex: 1 1 auto; width: auto; height: auto; max-width: 100%; align-self: center; }
/* N4 fix (round 5, Opus web-design-auditor) — the wrap-mode override used to sit HERE (after
   the unconditional rule above, so at equal specificity (0,3,0) it was the later rule and won
   whenever the @media condition was true), capped at min(100%, 560px): measured 662/915/1007px
   wrapped row widths at 768/1024/1120px against a 560px cap, leaving 102/355/447px dead — the
   SAME "protect against an oversized font" reasoning the unwrapped 380px cap above carried, and
   the same reasoning that is now retired by sdElevFixupFontSize() (see that rule's own ROUND 6
   comment). The unconditional base rule above is now already `max-width: 100%` — identical to
   what this override would say — so this block is deleted rather than kept as a no-op that
   would only invite the SAME "which rule actually wins" confusion N4 itself already spent one
   round debugging. Wrap mode's own drawing width is governed by the base rule alone now. */

/* ---------------------------------------------------------------------------
   THE TABLES — ported from table.cutlist's own five conventions
   (modules/cut-list-optimizer/cut-list-optimizer.html:1285-1296), the founder's
   own "really basic and really difficult to follow" note against the ONE table
   this suite already got right (docs/research/pre-placement-preferences-build-
   notes-windows-and-slide-elevation-graphics-2026-09-09.md §3.1): tabular-nums
   on every numeric cell, a row hover highlight, 8px 11px cell padding (was
   3px 10px 3px 0 — the old rule zeroed the right edge on every column, not
   only the ones that needed it), a heavier 2px header rule, and a header that
   actually recedes against the body (0.68rem vs 0.86rem, was 0.72rem vs
   0.86rem). ONE shared table class for BOTH the per-cabinet Slide/Height/Holds
   table and the spacer cut list table below — "cleaner tables" means one
   table language, not two.
   --------------------------------------------------------------------------- */
/* ROUND 2 — width: auto (was 100%): a table that owns its own width can only
   still size sensibly with per-column MINIMUMS, so the number columns don't
   collapse to their header's own width the moment the table stops being
   forced wide. fix round (Opus web-design review, P1, css:242) — the OLD
   full-width .sd-spacer-table modifier is gone with the reference table it
   styled (shared/slide-datums-view.js#html() now folds that table's own
   fact into the spacer tiles instead — see that file's own comment); every
   remaining .sd-datum-table on this sheet is a per-cabinet table now, so
   there is only ONE table grid to keep consistent, not two. */
.sd-datum-panel .sd-datum-table { width: auto; max-width: 100%; border-collapse: collapse; margin: 6px 0 4px; }
.sd-datum-panel .sd-datum-table th,
.sd-datum-panel .sd-datum-table td { padding: 8px 11px; border-bottom: 1px solid var(--cream-line); vertical-align: middle; }
.sd-datum-panel .sd-datum-table thead th {
  position: sticky; top: 0; z-index: 1; background: var(--cream-card);
  text-align: left; font-size: 0.68rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--ink-soft); border-bottom: 2px solid var(--cream-line);
  white-space: nowrap;
}
/* fix round (Opus web-design review, P1, css:245-261, MEASURED SELECTOR) — the numeric
   header cells were reading LEFT-aligned over RIGHT-aligned values: `.sd-datum-table thead
   th` (a class plus two elements, 0-1-2) outranked the bare `.sd-datum-pos-h`/`.sd-datum-
   num-h` modifier classes (0-1-0) regardless of source order. Re-declared at the SAME
   0-1-2 weight, on the actual header cells, so header and value share one right edge. */
.sd-datum-panel .sd-datum-table th.sd-datum-pos-h,
.sd-datum-panel .sd-datum-table th.sd-datum-num-h { text-align: right; }
/* fix round (Opus web-design re-confirm, P2) — the SAME specificity bug, missed on the
   Slide column in the first pass: it stayed left-aligned over its own centred values. */
.sd-datum-panel .sd-datum-table th.sd-datum-slide-h { text-align: center; }
.sd-datum-panel .sd-datum-table tbody tr:last-child td { border-bottom: none; }
.sd-datum-panel .sd-datum-table tbody tr:hover td { background: var(--surface-hi); }
/* ROUND 2 per-column widths (the orchestrator's own numbers): Slide ~4ch
   CENTRED (round 1 right-aligned it, which read oddly for a bare 1/2/3
   count) so a one- or two-digit slide number sits under its own header
   instead of drifting to the far edge of a narrow column; Height ~14ch
   right-aligned (now ALWAYS a number, "0 mm" included — see
   shared/slide-datums-view.js#rowHeightText); Holds ~10ch left. */
.sd-datum-panel .sd-datum-slide-h, .sd-datum-panel .sd-datum-slide { text-align: center; min-width: 4ch; }
.sd-datum-panel .sd-datum-pos-h, .sd-datum-panel .sd-datum-pos,
.sd-datum-panel .sd-datum-num-h, .sd-datum-panel .sd-datum-num { text-align: right; color: var(--ink); }
.sd-datum-panel .sd-datum-pos-h, .sd-datum-panel .sd-datum-pos { min-width: 14ch; }
.sd-datum-panel .sd-datum-slide, .sd-datum-panel .sd-datum-pos,
.sd-datum-panel .sd-datum-num { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Holds / Used in — a comma- or plus-joined list of names, never truncated
   (the standing no-truncation rule): left-aligned prose, not a number.
   P0-1 (round 3, Opus web-design-auditor) — a floor (min-width) with no ceiling let a real S+S
   paired code (SYSTAINERS147DBF + SYSTAINERS147DBF) render on one unbroken line wide enough to
   drive .sd-datum-cab-body's own scrollWidth past its clientWidth (measured 1161px vs 1112px
   planner / 1054px cut-list-optimizer) — with .sd-datum-panel-body's own overflow-x:hidden and
   no scrollbar, the drawing's own right edge was silently amputated. max-width forces the
   browser's normal word-wrap to engage at the space either side of " + " (never mid-word — no
   overflow-wrap/word-break is set here, so a single token that still does not fit stays whole
   and simply runs past the column, the standing no-truncation rule, rather than being cut). */
.sd-datum-panel .sd-datum-holds-h, .sd-datum-panel .sd-datum-holds { text-align: left; color: var(--ink); min-width: 10ch; max-width: 22ch; }
/* P1 key badge (round 5, Opus web-design-auditor) — a numbered Holds row USED TO read as bare
   text ("2  SYS3 M137"), which measured as a QUANTITY at a glance (it sits directly under a
   Slide column that IS a plain count, "1, 2, 3...") and, worse, only showed up on SOME rows of
   a cabinet (see shared/slide-datums-view.js's own P1-key-badge comment for why it is now every
   row or none). FIX: a real pill, the SAME solid accent-filled "step number" pattern
   shared/theme.css's own --on-accent-fill/--on-accent pair already defines for exactly this
   shape ("step numbers" is named in that token's own comment) — verified WCAG AA >=4.5:1 text-
   on-fill in both themes by tests/site-lint/theme-contrast.cjs, and a solid accent fill against
   this table's cream row background clears the 3:1 CONTROL SURFACE RULE (P2027) by a wide
   margin (re-measured, tests/control-surface-contrast.audit.cjs). The digit itself is what the
   SAME number drawn inside the tray bar shows, so the pill's fill IS the drawing's own "same
   fill/ink" this finding asked for — an accent circle reads as a cross-reference marker, never
   a count, which the bare-numeral text version could not tell apart from the Slide column. */
.sd-datum-panel .sd-datum-key { display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.3em; height: 1.3em; padding: 0 0.25em; margin-right: 6px; border-radius: 999px;
  font-size: 0.78em; font-weight: 700; line-height: 1; background: var(--on-accent-fill);
  color: var(--on-accent); vertical-align: -0.05em; }
/* ROUND 2 — the Note column replaces BOTH round 1's inline d=0 fine print
   (which used to squat inside the Height cell, left-aligned prose in an
   otherwise right-aligned number column — "reads as a mistake") AND its
   dedicated footnote-marker column for a provisional row. One column,
   always present, muted, empty when a row has nothing to say
   (shared/slide-datums-view.js#rowNoteText's own contract) — wraps rather
   than truncating (the standing no-truncation rule), since a note can run a
   full sentence long. */
.sd-datum-panel .sd-datum-remark-h, .sd-datum-panel .sd-datum-remark { text-align: left; color: var(--ink-soft); font-size: 0.82rem; white-space: normal; }
.sd-datum-panel .sd-datum-note {
  text-align: left; border-bottom: none; border-top: 1px solid var(--cream-line);
  padding: 8px 11px 2px; font-size: 0.8rem; color: var(--ink-soft);
}
.sd-datum-panel .sd-datum-note + .sd-datum-note { padding-top: 4px; border-top: none; }

/* dead in the browser today (the drag-yield hook — see shared/slide-datums-view.js's
   own history) but kept: beginDrag()/finishDragVisuals() on the planner still toggle
   it on every drag start/end, outside this file's scope. */
.sd-datum-panel.sd-datum-panel-yield { opacity: 0.35; pointer-events: none; }

/* PRINT: the dedicated Print button opens its own standalone popup document
   (shared/slide-datums-view.js#printHtml) — an accidental Ctrl+P of the LIVE
   page while this dialog happens to be open must never print the dialog chrome
   mixed in with the busy planner page behind it. cut-list-optimizer.html folds
   this SAME rule into its own larger print block instead of repeating it here
   a second time (its own comment explains why: tests/p769-p771-print-frame.test.cjs
   reads that page's print stylesheet as one block) — this copy still applies
   there too, harmlessly redundant with an identical rule. */
@media print {
  dialog.sd-datum-panel { display: none !important; }
}

/* ============================================================================
   THE SIDE ELEVATION — P2020 (his order, 2026-09-09): "I would also add some
   graphics to it to make it so someone could follow it visually." One drawing
   per cabinet, drawn by shared/slide-datums-view.js#cabinetElevationSvg from
   the SAME rows the table beside it prints — see that function's own header
   comment for the millimetre-scale and no-live-DOM reasoning. Tokens match
   shared/tray-art.js's own vocabulary (this lane's brief named these
   literally): --text, --text-faint, --accent-deep, --accent-soft, --surface,
   --surface-2, --surface-hi. Every stroke carries vector-effect: non-scaling-
   stroke so a line reads the same width regardless of the drawing's own scale
   (MDN: "the stroke width is not dependent on the transformations of the
   element... and zoom level").

   ROUND 2 (2026-09-09, same day): general strokes are 1.25 px (the
   orchestrator's own number, replacing round 1's inconsistent 1.5/2); the
   datum line stays visibly bolder (2 px) so it still reads as the one line
   that matters against the rest of the drawing. Three new classes: the
   leader tick from a dimension label to its own datum line
   (.sd-elev-dim-tick), the light top-clearance band and its label
   (.sd-elev-clearance / .sd-elev-clearance-label), and the once-per-drawing
   "Inside bottom" baseline label (.sd-elev-baseline-label).
   ============================================================================ */
.sd-elev-svg { display: block; }
.sd-elev-cab { fill: var(--surface-2); stroke: var(--text); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
.sd-elev-tray { fill: var(--surface); stroke: var(--text-faint); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
/* P2034 (his own words, 2026-09-09 22:10 PT: "hard to understand and read" —
   the drawing's own JS header carries the full account) — the slide's own
   datum is now a FILLED BAR (a <rect>, was a stroke-only <line>), so it
   reads as the slide itself rather than a reference tick. `fill` added;
   `stroke` kept at the SAME colour so the bar still carries a crisp edge at
   print's fixed 90mm width, where a filled area alone (no vector-effect)
   would otherwise thin out with the rest of the drawing's own geometry. */
.sd-elev-datum { fill: var(--accent-deep); stroke: var(--accent-deep); stroke-width: 0.75; vector-effect: non-scaling-stroke; }
.sd-elev-dim-tick { stroke: var(--text-faint); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
.sd-elev-spacer { fill: var(--accent-soft); stroke: var(--accent-deep); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
/* P2-H (round 3, Opus web-design-auditor) — --accent-soft against the cab's own --surface-2
   fill measures 10.15:1 in Midnight Oak (fine, unchanged below) but only 1.11:1 in Linen —
   computed straight from theme.css's own raw hex (#cfe0eb on #ebe8e0), nowhere near WCAG
   1.4.11's 3:1; the legend swatch reuses this SAME class, so it was equally invisible there.
   --accent (not --accent-deep, which is already this drawing's own "important" colour — the
   slide bar itself — and would read as the wrong shape) measures 3.60:1 in Linen against the
   same --surface-2, comfortably over the floor; the stroke (--accent-deep) already clears 3:1
   in both themes unchanged, so only the FILL needs a light-theme override. Scoped to
   linen-ink (and the light half of the no-attribute fallback, which mirrors it) — Midnight Oak
   keeps its own already-passing --accent-soft fill untouched. */
:root[data-theme="linen-ink"] .sd-elev-spacer,
:root:not([data-theme]) .sd-elev-spacer { fill: var(--accent); }
/* P1-2 (Opus web-design-auditor round 2) — the break-mark zigzag a clipped spacer block draws
   (shared/slide-datums-view.js#cabinetElevationSvg's own comment); stroked in --surface so it
   reads as a gap cut INTO the block (the tray's own background colour showing through), not a
   new shape competing for attention with it. */
.sd-elev-spacer-break { fill: none; stroke: var(--surface); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.sd-elev-clearance { fill: var(--surface-hi); opacity: 0.7; }
/* P1-3 (Opus web-design-auditor round 2) — the flat fill above measured 1.03:1 Linen / 1.11:1
   Midnight against the cab's own --surface-2 fill underneath it (WCAG 1.4.11 needs 3:1). Every
   member of this palette's own "soft"/"surface" family is deliberately close in luminance to
   every other (checked by hand: --accent-soft at any opacity over --surface-2 tops out under
   1.11:1 in BOTH themes — the brief's own first-suggested fix does not clear the floor either),
   so a flat-colour fix is not available from this palette. Real diagonal hatch lines carry the
   actual contrast instead, in --accent-deep — already this drawing's OWN "important" colour
   (.sd-elev-datum uses it) — which measures 5.95:1 Linen / 7.19:1 Midnight against --surface-2,
   comfortably over 3:1 in both themes. The fill stays (the same quiet "reserved" texture it
   always gave); sdElevHatchLines() draws the lines themselves as plain geometry, no <pattern>
   or id ever needed. */
.sd-elev-clearance-hatch { stroke: var(--accent-deep); stroke-width: 0.9; vector-effect: non-scaling-stroke; }
/* P1-6 (Opus web-design-auditor round 2) — the mirror image, for "this stack does not fit"
   (cabinetInsideHeightMm()'s own comment has the full account of why a negative reading is
   real). --danger / --danger-soft, unchanged theme tokens, so "this is a problem" reads through
   colour AND the plain-words "Overflow: N" label beside it (never colour alone, WCAG 1.4.1). */
.sd-elev-overflow { fill: var(--danger-soft); opacity: 0.85; }
.sd-elev-overflow-hatch { stroke: var(--danger); stroke-width: 0.9; vector-effect: non-scaling-stroke; }
.sd-elev-overflow-label { fill: var(--danger-text); font-weight: 700; }
/* N7 (round 4, Opus web-design-auditor) — his own measured finding: the hatch stroke above
   (--danger) reads 4.08:1 in Linen but only 1.78:1 in Midnight Oak, under WCAG 1.4.11's 3:1.
   MEASURED, not modelled, on a real Chromium render (a negative-top-clearance fixture,
   Playwright screenshot, pixels read directly off the rendered PNG — the raw-token math this
   file's own P1-D/P2-H precedent uses elsewhere is a bare alpha-blend of --danger-soft's own
   0.85 opacity, which does NOT match what the pixels actually show once the hatch's own thin
   0.9 stroke-width and anti-aliasing are in the picture — the rendered background reads far
   closer to the dialog's plain --surface than to a full-strength --danger-soft tint). Scoped to
   Midnight Oak only (Linen already clears the floor against --surface too, untouched, the same
   "only the failing theme gets an override" shape P2-H already used for .sd-elev-spacer, above)
   — --danger-text is already this drawing's own "important, on this exact tint" colour one line
   up (.sd-elev-overflow-label already uses it against the identical band), so reusing it here
   keeps hatch and label reading as the same warning rather than introducing a third red.
   Real-pixel-sampled result: 8.3-9.5:1 (the exact samples are in this lane's own report) —
   comfortably over 3:1, not a near miss. */
:root[data-theme="midnight-oak"] .sd-elev-overflow-hatch { stroke: var(--danger-text); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .sd-elev-overflow-hatch { stroke: var(--danger-text); }
}
/* ROUND 3 (staff review, P2) — .sd-elev-clearance-label sits ON the tinted
   clearance band above (--surface-hi at 0.7 opacity over --surface, NOT the
   plain dialog background), so its contrast has to clear 4.5:1 against THAT
   blend, not against the page. --text-faint measured 4.31:1 there in
   Midnight Oak (theme.css: --text-faint #8994a1 on the blended band
   #27303c, computed per shared/theme.css:96-98) — under the WCAG AA floor.
   --text clears it comfortably in both themes against the same blended
   background: Midnight Oak 11.25:1 (#e6edf3 on #27303c), Linen 13.96:1
   (#20242b on #f4f2ec, theme.css:73-75). .sd-elev-baseline-label stays on
   --text-faint: it is drawn BELOW the cabinet's own bottom edge, over the
   plain dialog surface (not the tinted band), where --text-faint already
   clears 4.5:1 in both themes (Midnight Oak 5.26:1 against plain --surface). */
.sd-elev-clearance-label { fill: var(--text); }
.sd-elev-baseline-label { fill: var(--text-faint); }
.sd-elev-dim-label { fill: var(--accent-deep); font-weight: 700; }
.sd-elev-box-label { fill: var(--text); font-weight: 600; }
/* P2034 — the Systainer's own HEIGHT, the second line inside a tray bar
   (below .sd-elev-box-label's own code line): muted against it the same way
   .sd-elev-baseline-label is muted against .sd-elev-dim-label, on the SAME
   --text-faint-clears-4.5:1-on-plain-surface reasoning immediately above —
   this label sits inside .sd-elev-tray, which fills with the SAME --surface
   token the baseline label's own background reasoning already covers. */
.sd-elev-box-sub-label { fill: var(--text-faint); font-weight: 400; }
/* N3 (round 4, Opus web-design-auditor) — round 3's own .sd-elev-key-label rule styled a
   "N  CODE" reference list this drawing no longer draws (the mapping now lives in the table's
   own Holds cell instead — see shared/slide-datums-view.js#cabinetElevationSvg's own keyByRow
   comment); removed with the markup it styled, nothing left in this file to select it. */
/* P2034 — the legend caption under the drawing (slide bar / spacer block /
   top clearance). Sits below the baseline label, on the plain dialog
   surface — the SAME --text-faint-on-plain-surface pairing already proven
   above, reused rather than a third hand-picked colour. */
.sd-elev-legend-label { fill: var(--text-faint); }
