/* The look (desk v2 spec › 3, Decision 118: dense-desk's frame and page shapes, portal-panel's bottom bar; DESIGN 1
   to 18): the site's own stylesheet, the only one the base loads. Every rule lives here: the Content-Security-Policy
   allows only this file, no inline style, and only the site's own script files (js/desk.js and its modules, which
   set no style). A frame (the header across the top, the navigation down the left) in the scheme's colours, white with
   hairlines in light and the darkest surface in dark (DESIGN 10), round a canvas of white panels, one accent, the
   system font. Computer first (Decision 102): the
   desk layout from 960 CSS pixels; below 960 the navigation is a bar at the bottom, below 760 a grid's rows are
   cards, the phone the floor at 375. Rests on WCAG 2.2 (SC 1.4.3 and 1.4.11 contrast, 1.4.10 reflow, 2.4.1 bypass
   blocks, 2.4.7 and 2.4.11 focus, 2.5.5 and 2.5.8 target size), the Web Interface Guidelines (tabular figures,
   reduced motion, a skip link) and MDN on `position: sticky`, `:has()` and `<details>`. */

/* --- The tokens: the one place the look lives (desk v2 Task 19, Charlie 13 Oct 21:2x: "an airbnb-like aesthetics in
   terms of font, colours, design hierarchy, emphasis on important stuff ... and a dark version too", the grid "like a
   very nice excel template"). Airbnb's hierarchy: one typeface on a real scale (a large 600 title, the body at 400,
   small muted labels), near-black text on white with a grey for what is secondary, hairline borders, 8 and 12 px
   radii, generous room round the grid and tight inside it, one accent for the primary action and the marks only;
   emphasis by weight and size, never by more colour. The fine spreadsheet's: banded rows, a tinted header band, a
   totals bar at the foot. The typeface is the system's (SF on the Apple devices the co-founders use, Segoe UI on
   Windows): it carries the same hierarchy at no download, no flash of unstyled text and no font licence to vendor;
   a self-hosted Inter was weighed and not taken (tests/test_look.py pins that no font is loaded).

   Every colour a six-digit hex so tests/test_look.py measures each pair with the WCAG relative-luminance formula:
   text, muted text and the accent at least 4.5:1 on every surface a row or panel takes; white on the accent fill
   6.75:1; the control border, the focus ring and the mark at least 3:1; the frame's words 4.5:1 on it; each chip's
   words 4.5:1 on its tint; a grid's link 4.5:1 on every row tone and, in light, 3:1 against the row's text, so it
   may drop its underline at rest (WCAG 1.4.1, G183; in dark no colour meets both, so the customer's link carries its
   weight as the second cue). In dark the surfaces step up in tone with elevation (Material 3's surface tones; Apple's
   base and elevated backgrounds; Decision 121): the frame darkest, then the canvas, the panels and rows, the stripe,
   the header band and the inputs' field; text and borders lighten and the accent softens; the mark (a set filter,
   the open row, a button's edge) is the accent at reduced strength, so nothing set reads as a stuck focus ring. */
:root {
  color-scheme: light dark;
  /* type: one family, a scale of six sizes and three weights (DESIGN 15 and 16) */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --fs-title: 1.75rem;
  --fs-h2: 1.125rem;
  --fs-body: 0.9375rem;
  --fs-table: 0.875rem;
  --fs-small: 0.8125rem;
  --fs-label: 0.75rem;
  --fw-body: 400;
  --fw-medium: 500;
  --fw-strong: 600;
  /* room, corners and lines */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2rem;
  --radius: 8px;
  --radius-lg: 12px;
  --radius-sm: 6px; /* the legacy's md: buttons, badges, menu rows */
  --radius-xs: 4px; /* the legacy's sm */
  --radius-pill: 999px; /* a chip, a progress bar */
  --z-menu: 20; /* the layers, low to high: a menu, a floating panel, a popover, the popup (the legacy's 40 and 60) */
  --z-float: 30;
  --z-popover: 40;
  --z-modal: 60;
  --row-h: 2rem;
  --chev-w: 1.625rem;
  --cell-y: 0.375rem; /* a table cell: 6 px above and below, 8 px at the sides (slice 5e; the header the same at the sides) */
  --cell-x: 0.5rem;
  --row-dense: 2.5rem; /* the Lines row: the legacy's dense 40 px as the floor; Comfortable is --row-comfy */
  --row-comfy: 3.25rem;
  --head-h: 2.28rem;
  --fn-slot: 1.25rem; /* the header's funnel: a 12 px glyph in a 20 px slot, 4 px from the label, beside the resize handle at the edge */
  --rz-w: 0.5rem; /* the resize handle's hit area, a strip at each header cell's right edge */
  --cols-w: 78rem; /* the Lines table's fixed columns together (1,248 px); the description takes the rest, from --desc-min */
  --desc-min: 27.5rem;
  --shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 4px 12px rgb(0 0 0 / 0.06);
  --shadow-menu: 0 8px 24px rgb(0 0 0 / 0.3); /* a menu or panel that floats over the page */
  --shadow-pop: 0 20px 25px -5px rgb(0 0 0 / 0.4), 0 8px 10px -6px rgb(0 0 0 / 0.4); /* a popover (the legacy's shadow-xl) */
  --shadow-search: 0 10px 15px -3px rgb(0 0 0 / 0.2), 0 4px 6px -4px rgb(0 0 0 / 0.2); /* the search box and its list (shadow-lg) */
  --shadow-lift: 0 8px 16px -4px rgb(0 0 0 / 0.25); /* a banner stuck over the table */
  --shadow-modal: 0 25px 50px -12px rgb(0 0 0 / 0.5); /* the popup (shadow-2xl) */
  --scrim: rgb(0 0 0 / 0.6); /* behind a popup */
  --press: rgb(0 0 0 / 0.15); /* a button under the pointer */
  --side-head-h: 3.53rem; /* the navigation's head, the legacy's 56.5 px */
  --above-box: 7rem; /* what stands above a grid's box (the search row, its counts): the box ends at the window's foot */
  --nav-w: 14rem;
  --rail-w: 3.5rem;
  --bar-h: 3.5rem;
  /* colours, light: near-black on white, two greys, hairlines; the frame white with a hairline */
  --bg: #ffffff;
  --canvas: #f7f7f7;
  --surface: #f2f2f2;
  --field: #ffffff;
  --text: #222222;
  --muted: #6a6a6a;
  --rule: #ebebeb;
  --control: #858585;
  --zebra: #ffffff;
  --hover: #f0f4fc;
  --accent: #2453c4;
  --accent-fill: #2453c4;
  --accent-soft: #e8eefb;
  --on-accent: #ffffff;
  --focus: #2453c4;
  --mark: #2453c4;
  --link: #3966d0;
  --chrome: #ffffff;
  --chrome-2: #f2f2f2;
  --on-chrome: #222222;
  --chrome-muted: #6a6a6a;
  --chrome-accent: #2453c4;
  --dealer: #5b3fc4;
  --dealer-bg: #ede9fe;
  --end-user: #0f766e;
  --end-user-bg: #ccfbf1;
  --tyre: #24532a;
  --tyre-bg: #e4f3e6;
  --recon: #3d6e45;
  --recon-bg: #f4faf5;
  --check: #6b4f00;
  --check-bg: #fff4cc;
  --wrong: #9b1c1c;
  --wrong-bg: #fde8e8;
  --text-2: #3d3d3d;
  --faint: #8a8a8a;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --shadow: 0 1px 2px rgb(0 0 0 / 0.4), 0 4px 12px rgb(0 0 0 / 0.3);
    --bg: #0f1626;
    --canvas: #030712;
    --surface: #182033;
    --field: #0f1626;
    --text: #f3f4f6;
    --muted: #9ca3af;
    --rule: #1f2937;
    --control: #6b7280;
    --zebra: #0f1626;
    --hover: #182033;
    --accent: #93c5fd;
    --accent-fill: #2563eb;
    --accent-soft: #162645;
    --on-accent: #ffffff;
    --focus: #93c5fd;
    --mark: #3b82f6;
    --link: #93c5fd;
    --chrome: #0f1626;
    --chrome-2: #182033;
    --on-chrome: #f3f4f6;
    --chrome-muted: #9ca3af;
    --chrome-accent: #93c5fd;
    --dealer: #c4b5fd;
    --dealer-bg: #25234b;
    --end-user: #5eead4;
    --end-user-bg: #103039;
    --tyre: #9fd6a6;
    --tyre-bg: #1f4528;
    --recon: #8fcc9a;
    --recon-bg: #2a3d31;
    --check: #f0d36b;
    --check-bg: #463c0e;
    --wrong: #f4a3a3;
    --wrong-bg: #5c2828;
  --text-2: #d1d5db;
  --faint: #6b7280;
  }
}

/* A chosen theme (the header's control, desk v2 Task 19): Light keeps the light tokens above whatever the device;
   Dark takes the same dark values as the block above (tests/test_look.py pins the copy equal), and the browser's
   own controls and scrollbars follow through `color-scheme`. Auto sets nothing and follows the device. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] {
  color-scheme: dark;
  --shadow: 0 1px 2px rgb(0 0 0 / 0.4), 0 4px 12px rgb(0 0 0 / 0.3);
  --bg: #0f1626;
  --canvas: #030712;
  --surface: #182033;
  --field: #0f1626;
  --text: #f3f4f6;
  --muted: #9ca3af;
  --rule: #1f2937;
  --control: #6b7280;
  --zebra: #0f1626;
  --hover: #182033;
  --accent: #93c5fd;
  --accent-fill: #2563eb;
  --accent-soft: #162645;
  --on-accent: #ffffff;
  --focus: #93c5fd;
  --mark: #3b82f6;
  --link: #93c5fd;
  --chrome: #0f1626;
  --chrome-2: #182033;
  --on-chrome: #f3f4f6;
  --chrome-muted: #9ca3af;
  --chrome-accent: #93c5fd;
  --dealer: #c4b5fd;
  --dealer-bg: #25234b;
  --end-user: #5eead4;
  --end-user-bg: #103039;
  --tyre: #9fd6a6;
  --tyre-bg: #1f4528;
  --recon: #8fcc9a;
  --recon-bg: #2a3d31;
  --check: #f0d36b;
  --check-bg: #463c0e;
  --wrong: #f4a3a3;
  --wrong-bg: #5c2828;
  --text-2: #d1d5db;
  --faint: #6b7280;
}

/* --- The page and the type scale (DESIGN 15 and 16): the tokens' family, nothing loaded; body --fs-body, tables
   --fs-table, small --fs-small, labels --fs-label, h1 --fs-title; weights 400, 500 and 600. */
*,
*::before,
*::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { line-height: 1.25; margin: var(--space-4) 0 var(--space-2); text-wrap: balance; overflow-wrap: anywhere; font-weight: var(--fw-strong); }
h1 { font-size: var(--fs-title); letter-spacing: -0.01em; }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-body); }
small { font-size: var(--fs-small); }
p, ul, ol, dl, form, fieldset, details, article { margin: 0 0 var(--space-3); }
ul, ol { padding-left: 1.25rem; }
main > p { max-width: 75ch; }
main > :first-child { margin-top: 0; }
.muted { color: var(--muted); }
a { color: var(--accent); text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 2px; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.875em; }
/* a long refusal message wraps at 375 rather than pushing the page sideways (DESIGN 1) */
mark { color: var(--check); background: var(--check-bg); padding: 0 0.2em; border-radius: 2px; overflow-wrap: anywhere; }
del { color: var(--muted); }
del a { text-decoration-line: line-through; color: var(--muted); } /* a decoration never reaches an inline-flex box
   (CSS Text Decoration 3, 2.1), so a struck linked description is struck here */
hr { border: 0; border-top: 1px solid var(--rule); }
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
/* An icon from the sprite (screens/static/screens/icons.svg), drawn in its text's colour beside the words it stands
   for, so it is hidden from assistive technology. */
.icon { flex: none; width: 1.125rem; height: 1.125rem; vertical-align: -0.2em; }

/* The skip link (SC 2.4.1): the keyboard's first stop, out of sight until focused, to `<main id="main">`. */
.skip { position: absolute; left: var(--space-2); top: -4rem; z-index: var(--z-float); padding: var(--space-2) var(--space-3); color: var(--accent); background: var(--bg); border-radius: var(--radius); }
.skip:focus { top: var(--space-2); }
main:focus:not(:focus-visible) { outline: none; } /* the skip link moves focus here; a mouse never rings the page */

/* --- The frame (DESIGN 10 and 17; spec › 3; slice 5e): the navigation down the left and the bottom bar hold everything the
   header across the top held (it is gone, Charlie 14 Oct 18:5x); only a signed-out page has a slim header with the name. */
body > header {
  display: flex;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--chrome);
  color: var(--on-chrome);
  border-bottom: 1px solid var(--rule); /* a hairline: the white frame against the page (desk v2 Task 19) */
}
body > header .name { display: inline-flex; align-items: center; gap: var(--space-2); font-weight: 600; font-size: 1.0625rem; color: var(--on-chrome); text-decoration: none; }
/* The mark: a letter in the accent's fill, its alternative text empty, so a screen reader reads the name once. */
body > header .name::before { content: "A" / ""; display: inline-grid; place-items: center; width: 1.625rem; height: 1.625rem; border-radius: var(--radius); background: var(--accent-fill); color: var(--on-accent); font-size: 0.875rem; font-weight: 600; }
.side :focus-visible,
.bottom-bar :focus-visible,
body > header :focus-visible { outline-color: var(--chrome-accent); }

/* The left navigation from 960 pixels, the legacy page's (the study's 1.2; Charlie 14 Oct 2026: "copy it exactly"): the
   brand "Aexus Search" and the collapse chevron in a 56.5 px head, the entries 14 px medium in 6 px-rounded rows (the
   page shown in the accent's tint with a 2 px bar at the left, aria-current), then Work and Admin as before, the role and
   address and "All prices pre-GST" at the foot. Collapsed to a 56 px rail of icons the words stay as each link's accessible
   name and tooltip; the width moves over 150 ms (the script flips the class, the server renders it the same). */
.side {
  display: none;
  flex-direction: column;
  padding: 0;
  border-right: 1px solid var(--rule);
  background: var(--chrome);
  color: var(--on-chrome);
}
.side-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); height: var(--side-head-h); flex: none; padding: 0 0.75rem; border-bottom: 1px solid var(--rule); }
.side .brand { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1rem; font-weight: 700; color: var(--text); text-decoration: none; }
.side .brand:hover { color: var(--accent); }
.side ul { list-style: none; margin: 0; padding: 0.5rem 0.5rem 0; display: flex; flex-direction: column; gap: 0.25rem; }
.nav-h { margin: var(--space-3) 1.25rem 0; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--chrome-muted); }
.side a,
.side summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
}
.side .icon { color: inherit; width: 1.125rem; height: 1.125rem; }
.side a:hover,
.side summary:hover { background: var(--chrome-2); color: var(--text); }
.side a[aria-current=page] { background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--mark); color: var(--accent); }
.side details { margin: var(--space-2) 0.5rem 0; padding: 0; border: 0; background: none; }
.side summary { list-style: none; cursor: pointer; }
.side summary::-webkit-details-marker { display: none; }
.side summary::after { content: "▾" / ""; margin-left: auto; font-size: 0.75rem; color: var(--chrome-muted); }
.side details:not([open]) > summary::after { content: "▸" / ""; }
.side details ul { margin: 2px 0 0; padding: 0 0 0 1.75rem; }
.side details a { padding-block: 0.25rem; font-weight: 400; color: var(--chrome-muted); }
.side details a:hover,
.side details a[aria-current=page] { color: var(--text); }
.side-foot { margin-top: auto; padding: 0.75rem; border-top: 1px solid var(--rule); font-size: 0.75rem; color: var(--chrome-muted); }
.side .who { margin: 0 0 var(--space-2); overflow-wrap: anywhere; }
.side .who span { color: var(--on-chrome); }
.side .note { margin: var(--space-2) 0 0; }
/* The account strip (`_account.html`), in the navigation's foot and the bottom bar's Account menu: the as-of time, then the
   theme control and Sign out side by side, small; a collapsed rail stacks their icons, the words kept as tooltips. */
.asof { display: flex; align-items: center; gap: 0.375rem; margin: 0 0 var(--space-2); font-size: 0.75rem; color: var(--chrome-muted); }
.asof time { color: var(--on-chrome); }
.acts { display: flex; align-items: center; gap: var(--space-2); }
.acts form { margin: 0; }
.acts :is(details.theme > summary, .signout button) { display: inline-flex; align-items: center; gap: 0.375rem; min-height: 1.75rem; padding: 0 0.5rem; color: var(--on-chrome); background: transparent; border: 1px solid var(--control); border-radius: var(--radius-sm); font-size: 0.75rem; font-weight: var(--fw-medium); white-space: nowrap; box-shadow: none; }
.acts .icon { width: 0.875rem; height: 0.875rem; }
.side .acts details.theme > summary::after { content: none; } /* the navigation's own caret is for its disclosures */
.side .nav-admin,
.side .nav-pop { display: none; } /* the rail's Admin menu, shown below with `.narrow` */
main { flex: 1 0 auto; min-width: 0; padding: var(--space-3); }

/* From 960 pixels the desk: the navigation sticky at the left at the viewport's height, the content using the remaining
   width, its first row the page's own (no strip above it, slice 5e). */
.bottom-bar { display: none; }
@media (min-width: 960px) {
  body.desk {
    display: grid;
    grid-template-columns: var(--nav-w) minmax(0, 1fr);
  }
  body.desk > .side { display: flex; grid-column: 1; grid-row: 1 / -1; position: sticky; top: 0; align-self: start; height: 100vh; overflow-y: auto; z-index: 11; }
  body.desk > main { grid-column: 2; grid-row: 1; padding: var(--space-3) 1.25rem var(--space-5); } /* the legacy's 16 px above the page's first row */
}
@media (min-width: 960px) and (prefers-reduced-motion: no-preference) {
  body.desk { transition: grid-template-columns 150ms cubic-bezier(0.4, 0, 0.2, 1); }
}

/* Below 960 pixels the navigation is a bar at the bottom of the screen (from portal-panel), in thumb reach (DESIGN 1):
   an icon over a word per screen, the page shown in the frame's accent; Admin a menu whose list opens above the bar.
   The page keeps the bar's height free at its foot, so its last line is never under the bar. */
@media (max-width: 959.98px) {
  body.desk > main { padding-bottom: calc(var(--bar-h) + var(--space-4) + env(safe-area-inset-bottom)); }
  /* A focused control scrolled into view clears the bottom bar (SC 2.4.11; WCAG Technique C43). */
  html { scroll-padding-bottom: calc(var(--bar-h) + env(safe-area-inset-bottom)); }
  .desk > .bottom-bar {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-menu);
    padding: 0 0 env(safe-area-inset-bottom);
    background: var(--chrome);
    border-top: 1px solid var(--chrome-2);
  }
  .bottom-bar > ul { list-style: none; margin: 0; padding: 0; display: flex; }
  .bottom-bar > ul > li { flex: 1 1 0; min-width: 0; }
  .bottom-bar > ul > li > a,
  .bottom-bar summary {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: var(--bar-h);
    padding: 0.25rem 0.125rem;
    color: var(--chrome-muted);
    font-size: 0.6875rem;
    font-weight: 500;
    text-decoration: none;
    list-style: none;
    cursor: pointer;
  }
  .bottom-bar summary::-webkit-details-marker { display: none; }
  .bottom-bar .icon { width: 1.375rem; height: 1.375rem; }
  .bottom-bar span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bottom-bar a[aria-current=page],
  .bottom-bar details[open] > summary,
  .bottom-bar details:has([aria-current=page]) > summary { color: var(--on-chrome); box-shadow: inset 0 2px 0 var(--chrome-accent); }
  .bottom-bar a[aria-current=page] .icon,
  .bottom-bar details:has([aria-current=page]) > summary .icon { color: var(--chrome-accent); }
  .bottom-bar details { margin: 0; padding: 0; border: 0; background: none; }
  .bottom-bar details[open] > ul {
    position: fixed;
    right: var(--space-2);
    bottom: calc(var(--bar-h) + var(--space-2) + env(safe-area-inset-bottom));
    width: min(16rem, calc(100vw - 2 * var(--space-2)));
    margin: 0;
    padding: var(--space-1);
    list-style: none;
    background: var(--chrome);
    border: 1px solid var(--chrome-2);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-menu);
  }
  .bottom-bar details[open] > .acct-panel { /* the Account menu (`_account.html`): the same box as the Admin list */
    position: fixed; right: var(--space-2); bottom: calc(var(--bar-h) + var(--space-2) + env(safe-area-inset-bottom));
    width: min(16rem, calc(100vw - 2 * var(--space-2))); padding: var(--space-3); font-size: 0.8125rem;
    background: var(--chrome); border: 1px solid var(--chrome-2); border-radius: var(--radius-lg); box-shadow: var(--shadow-menu);
  }
  .acct-panel .acts { flex-wrap: wrap; }
  .acct-panel details.theme { flex: 1 1 100%; }
  .acct-panel details.theme > summary { flex-direction: row; min-height: 2.75rem; padding: 0 0.75rem; font-size: 0.8125rem; color: var(--on-chrome); box-shadow: none; }
  .acct-panel details.theme[open] > summary { box-shadow: none; }
  .acct-panel .theme-form { position: static; min-width: 0; margin-top: var(--space-1); box-shadow: none; }
  .acct-panel .signout { flex: 1 1 100%; }
  .acct-panel .signout button { width: 100%; min-height: 2.75rem; justify-content: center; }
  .bottom-bar details[open] > ul a { display: flex; align-items: center; min-height: 2.75rem; padding: 0 0.75rem; border-radius: var(--radius); color: var(--on-chrome); text-decoration: none; }
  .bottom-bar details[open] > ul a[aria-current=page] { background: var(--chrome-2); box-shadow: inset 3px 0 0 var(--chrome-accent); }
}

/* --- A page's head (spec › 3): a breadcrumb, the title and a line of facts; the customer's figures as tiles; the
   invoice and the Questions' groups as panels. */
.crumbs ol { list-style: none; margin: 0 0 var(--space-1); padding: 0; display: flex; flex-wrap: wrap; font-size: 0.8125rem; color: var(--muted); }
.crumbs li + li::before { content: "/" / ""; margin: 0 0.375rem; }
.crumbs a { color: var(--muted); }
.page-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-3); margin: 0 0 var(--space-3); }
.page-head h1 { margin: 0; }
.page-head p { margin: 0; }
.page-head .totals { flex: 1 1 100%; font-size: var(--fs-small); }
/* The Lines summary (Task 18's live region, `#grid-summary`, read aloud when the grid updates in place) shows only its
   muted sentence under the title: its counts are in the totals bar at the grid's foot (Task 19), so they are kept for
   a screen reader alone; with no line on the page, and so no totals bar, the sentence goes too (review m-7). */
#grid-region > .page-head:has(> #grid-summary.totals) { margin: 0; } /* the Lines page's head holds only words for a screen reader: no gap above the search row */
#grid-summary.totals > span:first-child { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.grid-region:not(:has(tfoot)) #grid-summary.totals > .muted { display: none; }
dl.facts { display: flex; flex-wrap: wrap; gap: var(--space-2) 2rem; margin: 0 0 var(--space-3); }
dl.facts dt { font-size: 0.75rem; color: var(--muted); }
dl.facts dd { margin: 0; overflow-wrap: anywhere; }
dl.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--space-2); max-width: 50rem; margin: 0 0 var(--space-3); }
dl.stats > div,
.tiles > li { padding: 0.625rem 0.875rem; background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius-lg); }
dl.stats dt { font-size: 0.75rem; color: var(--muted); }
dl.stats dd { margin: 0; font-size: 1.125rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.panel,
.hero { padding: var(--space-3) 1.25rem; background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius-lg); margin: 0 0 var(--space-3); }
.panel > :last-child,
.hero > :last-child { margin-bottom: 0; }
.panel > h2:first-child { margin-top: 0; }
.panel .page-head .btn .icon { width: 1rem; height: 1rem; }
ul.flags { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.q-actions { align-items: center; margin: 0 0 var(--space-3); }
.q-actions p { margin: 0; }

/* Home: the greeting and the search in a panel, the record's state as tiles, the questions open as links. */
.hero h1 { margin: 0 0 var(--space-3); }
.hero [role=search] input,
.hero [role=search] button { min-height: 2.5rem; }
.tiles { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--space-2); margin: 0 0 var(--space-3); }
.tiles > li { display: flex; flex-direction: column; gap: 2px; }
.tiles strong { font-size: 1.125rem; white-space: nowrap; font-weight: 600; font-variant-numeric: tabular-nums; order: 1; }
.tiles span { font-size: 0.8125rem; color: var(--muted); order: 0; }
.tiles strong + span { order: 2; }

/* --- Tables (DESIGN 5 and 16): each in its own scroll box, so the page never scrolls sideways (SC 1.4.10); from 960
   pixels the box is bounded by the viewport and scrolls both ways, so its header rows stick inside it; dense rows,
   zebra stripes, numbers right-aligned in tabular figures, long text cut to one line (the full text in its title). */
.table-box {
  overflow-x: auto;
  width: max-content;
  max-width: 100%;
  margin: 0 0 var(--space-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  /* A shadow at the right edge while there is more to the right (DESIGN 1): the cover travels with the content
     (local) and hides the shadow once the end is reached; CSS only, as the CSP allows no script. */
  background-color: var(--bg);
  background-image: linear-gradient(to left, var(--bg) 30%, transparent),
    radial-gradient(farthest-side at 100% 50%, var(--control), transparent);
  background-position: right center, right center;
  background-size: 2.5rem 100%, 0.75rem 100%;
  background-repeat: no-repeat;
  background-attachment: local, scroll;
}
.table-box.wide { width: 100%; } /* a record grid uses the width, not its content's (the look panel, plan C) */
.table-box :focus { scroll-margin-top: 4.5rem; } /* SC 2.4.11: a focused control clears the sticky header rows */
@media (min-width: 960px) {
  .table-box { overflow: auto; max-height: calc(100vh - var(--above-box) - 1rem); }
}
table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 0.875rem; line-height: 1.35; }
th, td { padding: 0.375rem 0.625rem; text-align: left; vertical-align: top; border-bottom: 1px solid var(--rule); }
thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  font-weight: 600;
  white-space: nowrap;
  border-bottom: 2px solid var(--control);
}
thead th a { color: var(--text); text-decoration: none; }
.grid thead th { font-size: var(--fs-label); font-weight: var(--fw-strong); letter-spacing: 0.01em; } /* small labels, so no
   label widens a number's column */
.grid thead th a { color: var(--muted); }
.grid thead th[aria-sort] a { color: var(--accent); }
thead th a:hover { color: var(--accent); text-decoration: underline; }
/* The sorted column says so beside its label, in the accent; aria-sort carries it for a screen reader, so the arrow's
   own alternative text is empty. */
thead th[aria-sort] a { color: var(--accent); }
thead th[aria-sort=ascending] a::after { content: " ▲" / ""; font-size: 0.75em; }
thead th[aria-sort=descending] a::after { content: " ▼" / ""; font-size: 0.75em; }
/* The stripes count a table's rows but a lines table's opened rows (`tr.more`, desk v2 spec › 4.4), so they alternate
   line by line whether a row is open or not; every other table keeps its stripes (the `of S` form: Baseline 2023). */
tbody tr:nth-child(even of :not(.more)) { background: var(--zebra); }
tbody tr:last-child > * { border-bottom: 0; }
tfoot th, tfoot td { border-top: 1px solid var(--rule); border-bottom: 0; }
tfoot tr.total > * { font-weight: 600; border-top: 2px solid var(--control); }
td.date { white-space: nowrap; font-variant-numeric: tabular-nums; } /* dates align, as numbers do */
/* The totals bar (desk v2 Task 19, a fine spreadsheet's): the count and the totals under their columns, in the header
   band's tint, pinned at the grid's foot while its rows scroll in the box. */
.grid tfoot tr.sum > * { position: sticky; bottom: 0; z-index: 1; padding-block: 0.5rem; background: var(--surface); border-top: 1px solid var(--control); border-bottom: 0; font-weight: var(--fw-strong); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: left; }
.grid tfoot tr.sum > .num { text-align: right; }
th.num,
td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.wrap { overflow-wrap: anywhere; min-width: 12rem; }
.cut { max-width: 24rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:not(td, th).cut { display: inline-block; vertical-align: bottom; } /* beats `td a`, so a cut link shows its "…" */
/* A record grid's columns: each cell on one line, narrower padding, a wrong line's reason cut short, each full text
   in its title (a re-saved copy's link to the counted copy stays whole beside its cut words). Below 1280 the
   description and the customer's name are capped, so the box fits at 960 with the navigation open; from 1280 (desk
   v2 Task 19) a lines grid's Customer and Description share the free width instead (a cell's `max-width: 0` takes
   it out of the columns' content widths, so the two take what the other columns leave, each by its share), and a
   name or a description is cut only when the window is narrower than it; a floor keeps a few words of each beside
   the free width. From 1500 the reason takes the room there is. */
.wide th, .wide td { padding-inline: 0.35rem; white-space: nowrap; }
.wide .cut { max-width: 11rem; }
.wide .cut.why { max-width: 4rem; }
@media not all and (min-width: 1280px) {
  .wide .cut.desc { max-width: 11rem; } /* with its sales arrow beside it */
  .wide .cut.name { max-width: 8rem; }
}
@media (min-width: 1280px) {
  .grid td.c-customer:has(.name) { width: 28%; max-width: 0; min-width: 7rem; }
  .grid td.c-description:has(.desc) { width: 72%; max-width: 0; min-width: 9rem; }
  .grid .cut.name,
  .grid .cut.desc { max-width: 100%; }
}
/* The Customers and Items grids' five or six columns leave their name or description the room of a plain cut, so two
   labels that share their first 11rem still tell apart; at phone width they are cards. */
@media (min-width: 960px) {
  .wide .cut.label { max-width: 24rem; }
}
@media (min-width: 1440px) {
  .wide .cut.why { max-width: 10rem; } /* a wrong line's reason reads from 1440, where the description has room (m-1) */
}
@media (min-width: 1500px) {
  .wide .cut { max-width: 20rem; }
  .wide .cut.why { max-width: 20rem; }
}

/* --- A description and the row that opens (desk v2 spec › 4.4, 4.9, 4.10; plan Task 1). A description is text in its
   lines (`.lines`, never on a cut element: a grid cell keeps one line); its item's sales link is left out of a drag,
   so a drag inside the text selects the text alone: in a grid a quiet arrow at the cell's right edge, held out of the
   text's box (desk v2 Task 19), on the invoice page "sales ›" after the text. A lines table's first column holds a chevron, a native
   disclosure (`<details name="row">`, one open at a time; the APG Disclosure pattern), and the row beneath each line
   shows only while the line's disclosure is open. Its cell wraps within the table (`contain: inline-size` gives the
   panel no width of its own), so no column moves when it opens; where the table scrolls in its box, the panel stays
   at the box's left at the box's width (a container query unit), so its text reads without scrolling sideways. */
.lines { white-space: pre-line; }
.sales { font-size: 0.75rem; white-space: nowrap; -webkit-user-select: none; user-select: none; }
.wide .cut.desc,
.wide .sales { vertical-align: top; } /* level with the row's other cells, whatever the link's height */
/* The "sales ›" link is 24 pixels tall on a mouse (DESIGN 12; SC 2.5.8) and 44 on a touch screen (SC 2.5.5) without
   moving its line: a 1rem line and padding above and below, which a matching negative margin takes back out of the
   line box, so a row stays one line tall and a description's last line keeps its height. */
td a.sales { display: inline-block; min-height: 0; line-height: 1rem; padding-block: 4px; margin-block: -4px; }
/* A grid's arrow: 24 by 24 at the cell's right edge, centred on the row, muted at rest and in the link's colour on
   a hover or a focus; the cell keeps its room, so the text never runs under it. */
.grid td.c-description:has(> .sales) { position: relative; padding-right: 1.625rem; }
.grid tbody tr:not(.more) > td:not([colspan]) > a.sales { position: absolute; top: 50%; right: 0; display: inline-grid; place-items: center; width: 24px; height: 24px; margin: -12px 0 0; padding: 0; line-height: 1; font-size: 0.875rem; color: var(--muted); border-radius: var(--radius); }
.grid tbody tr:not(.more) > td:not([colspan]) > a.sales:hover,
.grid tbody tr:not(.more) > td:not([colspan]) > a.sales:focus-visible { color: var(--link); background: var(--hover); }
/* At rest on a mouse the arrow waits for its row (review I-2: from 1280 a column of arrows beside Qty read as stray
   glyphs): shown while the row is hovered or holds the focus, so a keyboard's Tab still lands on it and shows it, as
   Airtable reveals a row's icons; on a touch screen it always shows, having no hover. */
@media (hover: hover) and (pointer: fine) {
  .grid tbody tr:not(.more, :hover, :focus-within) > td:not([colspan]) > a.sales { opacity: 0; }
}
.grid { container-type: inline-size; }
.grid .c-x { width: 1.625rem; padding-inline: 0.125rem 0; text-align: center; }
.grid td.c-x details,
.grid td.c-x details[open] { margin: 0; padding: 0; border: 0; min-width: 0; background: none; }
.grid td.c-x summary { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; color: var(--muted); border-radius: var(--radius); list-style: none; }
.grid td.c-x summary::-webkit-details-marker { display: none; }
.grid td.c-x summary:hover { color: var(--text); background: var(--rule); }
.grid td.c-x details[open] summary { color: var(--accent); }
.chev { width: 1rem; height: 1rem; }
.grid td.c-x details[open] .chev { transform: rotate(90deg); }
@media (prefers-reduced-motion: no-preference) {
  .grid td.c-x .chev { transition: transform 120ms ease-out; }
}
.grid tbody tr.row:hover { background: var(--hover); }
/* A grid's rows are dense on a fine pointer (DESIGN 16; desk v2 Task 19): 2.25rem at 0.875rem type, every cell
   centred on the row; a coarse pointer's 44 px targets make its rows taller (below). Its links are quiet at rest: no
   underline, the link's colour (above, the tokens), the customer's name a little heavier; a hover or a keyboard focus
   underlines one; the invoice's number keeps its underline, the row's anchor. A struck row's links stay struck. */
@media (min-width: 760px) { /* the table's rows (below 760 they are cards); a cut name or description is a block of
     one line, centred with the row's other cells */
  .grid tbody tr:not(.more) > td:not([colspan]) { height: var(--row-h); vertical-align: middle; }
  .grid tbody tr .cut:is(.name, .desc, .label) { display: block; }
  .grid tbody tr a.cut:is(.name, .label) { line-height: 24px; } /* 24 px tall (SC 2.5.8) */
}
@media (min-width: 1280px) { /* the free width goes to the customer and the description (above) */
  .grid th,
  .grid td { padding-inline: 0.2rem; } /* a spreadsheet's tight cells */
  .grid :is(th, td):last-child { padding-right: var(--space-2); } /* the last cell clear of the box's edge (m-1) */
}
.grid tbody tr:not(.more) > td:not([colspan]) a { color: var(--link); text-decoration: none; }
.grid tbody tr:not(.more) > td:not([colspan]) a:hover,
.grid tbody tr:not(.more) > td:not([colspan]) a:focus-visible { text-decoration-line: underline; }
.grid tbody tr:not(.more) > td:not([colspan]).c-invoice a { text-decoration-line: underline; }
.grid tbody tr:not(.more) > td:not([colspan]) a.cut { font-weight: var(--fw-medium); } /* a customer's or an item's name */
/* In dark no link colour is both AA on every row tone and 3:1 against the text (G183; measured, and confirmed by the
   review), so a name's link carries a real weight step as its non-colour cue (WCAG 1.4.1: bold, review I-5): under
   the device's dark scheme unless Light was chosen, and under a chosen Dark. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .grid tbody tr:not(.more) > td:not([colspan]) a.cut { font-weight: var(--fw-strong); }
}
:root[data-theme="dark"] .grid tbody tr:not(.more) > td:not([colspan]) a.cut { font-weight: var(--fw-strong); }
.grid tbody tr:not(.more) > td:not([colspan]) del a,
.grid tbody tr:not(.more) > td:not([colspan]).c-invoice del a { color: var(--muted); text-decoration-line: line-through; } /* the
   anchor's own underline rule outweighs the first (review I-1) */
.grid tbody tr.row:has(details[open]) { background: var(--accent-soft); }
.grid tr.more { display: none; }
.grid tr.row:has(details[open]) + tr.more { display: table-row; }
.grid tr.more > td { white-space: normal; padding: 0; background: var(--surface); box-shadow: inset 3px 0 0 var(--mark); }
.grid .more-panel { contain: inline-size; position: sticky; left: 0; max-width: 100cqi; padding: var(--space-1) var(--space-3) var(--space-2); }
.grid tbody tr.row:nth-last-child(2):not(:has(details[open])) > * { border-bottom: 0; } /* the last line, its panel shut */
/* The grid in place (desk v2 Task 18): while a sort, page or filter loads, the rows dim, a tone and nothing moved;
   the region takes focus to be announced, never ringed for a mouse. */
.grid-region[aria-busy=true] tbody { opacity: 0.55; }
.grid-region:focus:not(:focus-visible) { outline: none; }
.grid-region > p { max-width: 75ch; } /* a message and the hidden sentence keep main > p's measure */
.more-panel p { margin: 0; }
.more-panel .actions { display: flex; align-items: center; }
@media not all and (min-width: 760px), (pointer: coarse) {
  .more-panel a.btn { min-height: 44px; padding-inline: 1.25rem; } /* "Open invoice" is a touch target (DESIGN 12) */
}
.lines-grid tbody tr.row { cursor: pointer; } /* the whole row opens it (js/rows.js); a link in it keeps its own */

/* --- Chips (DESIGN 13 and 16): a small label per meaning, always holding its words, so colour never carries the
   meaning alone; the Kind chip says "dealer" or "end user" (desk v2 spec › 3). Quiet (desk v2 Task 19): a squared
   tag of medium weight; Kind and Class hold the body's text on their column's tint, one hue a column (Kind blue,
   Class green), the first word filled and the second outlined, so "dealer" and "end user", "tyre" and "recon" read
   apart at a glance; a flag (check, wrong, credit note) keeps its own colour, the row's one alert. A "check" chip is
   the link to its invoice's PDF, its icon saying where it goes. */
.chip {
  display: inline-block;
  padding: 0 0.4em;
  border-radius: var(--radius-xs);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.25rem;
  white-space: nowrap;
}
.chip:not([class*=" chip-"]) { color: var(--text); background: var(--bg); box-shadow: inset 0 0 0 1px var(--control); }
del .chip { text-decoration-line: line-through; } /* a chip is an atomic box: a struck row's decoration skips it */
.chip-dealer { color: var(--text); background: var(--dealer-bg); }
.chip-end-user { color: var(--text); background: var(--end-user-bg); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--end-user) 55%, transparent); }
.chip-tyre { color: var(--text); background: var(--tyre-bg); }
.chip-recon { color: var(--text); background: var(--recon-bg); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--recon) 55%, transparent); }
.chip-check { color: var(--check); background: var(--check-bg); }
.chip-wrong { color: var(--wrong); background: var(--wrong-bg); }
a.chip { display: inline-flex; align-items: center; gap: 0.25rem; min-height: 24px; text-decoration: none; }
a.chip .icon { width: 0.875rem; height: 0.875rem; }
.grid tbody tr:not(.more) > td:not([colspan]) a.chip { color: var(--check); }
.grid tbody tr:not(.more) > td:not([colspan]) a.chip:hover,
.grid tbody tr:not(.more) > td:not([colspan]) a.chip:focus-visible { text-decoration-line: underline; box-shadow: inset 0 0 0 1px var(--check); }

/* A grid's pager: a row of links with a gap, the page shown marked (aria-current). */
nav.pager { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); margin: 0 0 var(--space-3); font-size: 0.875rem; }
nav.pager [aria-current=page] { font-weight: 600; }

/* The run log's counts: one short line, its parts separated by a dot, the full record one click away. */
.counts > span + span::before { content: " · "; }
.counts { white-space: nowrap; }
td pre { margin: var(--space-1) 0 0; font-size: 0.8rem; white-space: pre-wrap; overflow-wrap: anywhere; max-width: 40rem; }

/* --- The toolbar (desk v2 spec › 3 and 4.1): the grid's one GET form (From and To, Apply, Clear), each control
   keeping its own width, so a date input shows its whole year (#167); on the phone the Filters disclosure. Under it
   the filters in force as chips, each a link that drops its own filter. */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0 0 var(--space-2); }
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); margin: 0; }
.filter-bar { align-items: center; }
.filter-bar label { flex: 0 0 auto; display: flex; align-items: center; gap: 0.375rem; margin: 0; font-size: 0.8125rem; color: var(--muted); }
.filter-bar label > input { margin: 0; color: var(--text); }
.filter-bar label > input[type=date] { width: auto; }
details.filters { display: none; }
.chips { list-style: none; margin: 0 0 var(--space-2); padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); font-size: 0.8125rem; }
.fchip { display: inline-flex; align-items: center; gap: 0.375rem; min-height: 24px; padding: 0 0.625rem; border: 1px solid var(--mark); border-radius: var(--radius-pill); background: var(--accent-soft); color: var(--accent); text-decoration: none; }
.fchip:hover { text-decoration: underline; }
/* The search box (the Lines page v3, R-L6): one wide box in the filter bar, the count of lines and invoices and a chip a
   word beside it (each a link that drops its word, its own count in bold), the two switches as chips in the accent when
   on and outlined when off; a match in a cell is a <mark class="hit"> in the amber the check chip uses, 4.5:1 both ways. */
.fchip .count { font-weight: 600; font-variant-numeric: tabular-nums; }
.fchip.neg { border-style: dashed; }
.fchip.switch.off { border-color: var(--control); background: transparent; color: var(--muted); }
.hint { margin: 0 0 var(--space-2); font-size: 0.8125rem; } /* how a number filter reads (the look panel's M-1) */
/* The toolbar's buttons (desk v2 Task 19): Apply the one filled button; Clear and Columns one secondary
   style, an outline in the accent's words; every control 2rem tall on a fine pointer, so the row reads as one line. */
.toolbar button { min-height: 2rem; }
.toolbar .filter-bar label > input { min-height: 2rem; padding-block: 0; }
.toolbar .filter-bar > a,
details.columns > summary {
  display: inline-flex;
  align-items: center;
  min-height: 2rem;
  padding: 0 0.75rem;
  border: 1px solid var(--control);
  border-radius: var(--radius);
  background: transparent;
  color: var(--text); /* near-black words in a grey outline: the accent is Apply's and the marks' alone (review I-4) */
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.35;
  text-decoration: none;
}
.toolbar .filter-bar > a:hover,
details.columns > summary:hover { background: var(--hover); }
/* From 760 on a mouse the number filters' hint leaves the page: each number filter's title says it on hover and a
   screen reader hears it as the filter's description (review m-2: a note floating over the toolbar hid its buttons).
   On a touch screen, which shows no title, it stays in the flow; below 760 the Filters panel shows it (below). */
@media (min-width: 760px) and (pointer: fine) {
  .hint { display: none; }
}
@media (min-width: 1440px) { /* generous room round the grid where the width allows it */
  body.desk > main { padding: var(--space-3) var(--space-5) 3rem; }
}
/* The filter row under a grid's headers (desk v2 spec › 4.1): one small control a column, joined to the toolbar's
   form by `form="grid"`; each takes its column's width, from a floor that still shows a few characters, so the row
   widens no column but the Customers grid's dates, which stack From over To. A filter holding a value carries the
   accent's edge. The Kind select reads its choice whole once the column is as wide as its "end user" chip. */
thead .filters td { background: var(--surface); padding: 0.2rem; border-bottom: 2px solid var(--control); }

thead .filters input,
thead .filters select { display: block; width: 100%; min-width: 2rem; min-height: 24px; padding: 0 0.2rem; font-size: 0.75rem; }
thead .filters select { min-width: 2.25rem; padding-inline: 0; } /* "any" and its arrow */
.filters select[name=kind],
.filters select[name=class],
.filters select[name=flags] { min-width: 3.5rem; } /* "any" reads whole, a page of unflagged lines too */
thead tr:has(+ tr.filters) th { border-bottom-width: 1px; } /* one heavy rule, under the filters (review M-3) */
.filters input[type=date] { width: auto; }
.filters input[type=date] + input[type=date] { margin-top: 2px; }
.grid tr.filters td.c-apply { display: none; } /* the phone's Filters panel's own Apply, below 760 */
.filters .set,
.filter-bar .set { border-color: var(--mark); box-shadow: inset 0 0 0 1px var(--mark); }
.totals { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0 0 var(--space-2); font-variant-numeric: tabular-nums; }
.answers { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.answers form { margin: 0; }
/* In a wide table a row's answers wrap inside their cell, the why box on its own line when the row is full, and a
   row's flags wrap too, so the buttons stay in the box at 1280; the cut columns keep their one line (review I-1). */
.wide td .answers { white-space: normal; min-width: 12rem; }
.wide td.flags { white-space: normal; min-width: 8rem; }  /* a row's flag chips wrap, a long one inside itself */
.wide td.flags .chip { white-space: normal; border-radius: var(--radius); }
.answers input[name=why] { width: 12rem; }

/* --- Elements styled one by one, since no framework does it: forms, buttons, disclosures, fieldsets, cards. */
label { display: block; margin: 0 0 0.75rem; }
input,
select,
textarea,
button { font: inherit; }
input:not([type=checkbox], [type=radio], [type=hidden]),
select,
textarea {
  max-width: 100%;
  padding: var(--space-1) var(--space-2);
  color: var(--text);
  background: var(--field);
  border: 1px solid var(--control);
  border-radius: var(--radius);
  min-height: 24px;
}
label > input:not([type=checkbox], [type=radio]),
label > select,
label > textarea { display: block; width: 100%; max-width: 32rem; margin-top: var(--space-1); }
[type=checkbox],
[type=radio] { width: 1rem; height: 1rem; margin: 0; accent-color: var(--accent-fill); }
button,
[role=button],
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  min-height: 24px;
  min-width: 24px;
  padding: 0.3125rem 0.875rem;
  color: var(--on-accent);
  background: var(--accent-fill);
  border: 1px solid var(--mark); /* dark mode's edge in #6d93e3, 4.82:1 on a panel, the fill being 2.16:1 */
  border-radius: var(--radius);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.35;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
}
/* A secondary button (Find, Filter, sign-out) is an outline; a destructive one (Remove, Revoke) an outline in the
   wrong pair (6.94:1 light, 8.06:1 dark), so neither reads as the page's main action. */
.signout button,
button.secondary { background: transparent; color: var(--accent); border-color: var(--control); }
button.danger { color: var(--wrong); background: var(--wrong-bg); border-color: var(--wrong); }
button:hover,
a.btn:hover { box-shadow: inset 0 0 0 100vmax var(--press); }
form.inline { display: inline; margin: 0; }
form > button + button { margin-left: var(--space-1); }
header a,
nav a,
td a,
.way a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  min-width: 24px;
}
details { border: 1px solid var(--rule); border-radius: var(--radius); padding: 0 0.75rem; background: var(--bg); }
details[open] { padding-bottom: var(--space-2); }
summary { padding-block: var(--space-1); cursor: pointer; }
details.panel > summary { font-weight: 600; }
/* A disclosure in a cell (the chevron's, the customer page's): the row stays one line until it is opened. */
td details { margin: 0; border: 0; padding: 0; white-space: nowrap; background: none; } /* a row stays one line tall */
td details[open] { white-space: normal; min-width: 14rem; padding-bottom: 0; }
td details form { margin: var(--space-1) 0 0; }
td details label { margin-bottom: var(--space-1); }
fieldset { border: 1px solid var(--rule); border-radius: var(--radius); padding: var(--space-2) 0.75rem; }
legend { padding: 0 var(--space-1); font-weight: 600; }
/* A radio or checkbox and its label are one target; a count after the text (the customer's names) its own line. */
fieldset label {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: var(--space-2);
  min-height: 24px;
  margin: 0;
}
fieldset label > small { grid-column: 2; }
article { padding: 0.75rem var(--space-3); background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius-lg); }
article > :last-child { margin-bottom: 0; }

/* A search form (the header's and home's): the field and the button side by side; the button keeps its width, since a
   min-width replaces a flex item's automatic minimum (it read "Sea / rch" at 375). */
[role=search] { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2); }
[role=search] label { flex: 0 1 32rem; margin: 0; }
[role=search] button { flex: none; }

/* --- Focus is always visible (DESIGN 14; SC 2.4.7): a solid ring in the focus token, 6.75:1 light and 8.35:1 dark;
   on the frame its own accent (above). */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* --- Below 760 pixels a grid's rows are cards (DESIGN 1 as amended; spec › 3), so nothing scrolls sideways: a lines
   card holds the invoice, the date and the amount on its first line, then the customer, the description over two
   lines at most, the chips, quantity and price, and the chevron at its lower right, its opened row beneath it; the
   Customers' and Items' cards their name first. The roles table, row and cell in the markup keep the table's meaning
   once its display changes [assumed: holds in VoiceOver on iOS; plan Task 15 checks by hand]. The header row becomes
   a strip of sort pills that scrolls in its own box; the filter row shows when the Filters disclosure is open. An
   invoice's lines become a list, so its amount is never off-screen. */
@media (max-width: 759.98px) {
  .grid.table-box { overflow: visible; max-height: none; border: 0; background: none; }
  .wide.grid > table,
  .wide.grid > table > thead,
  .wide.grid > table > tbody { display: block; }
  .wide.grid thead tr:first-child { display: flex; gap: var(--space-1); overflow-x: auto; padding: 0 0 var(--space-2); }
  .wide.grid thead th { position: static; display: block; padding: 0; background: none; border: 0; }
  .wide.grid thead th.c-x { display: none; }
  .wide.grid thead th a { display: inline-flex; align-items: center; min-height: 2rem; padding: 0 0.75rem; border: 1px solid var(--rule); border-radius: var(--radius-pill); background: var(--bg); font-weight: 500; font-size: 0.8125rem; white-space: nowrap; }
  .wide.grid thead th[aria-sort] a { border-color: var(--mark); background: var(--accent-soft); }
  .wide.grid tr.filters { display: none; }
  main:has(details.filters[open]) .wide.grid tr.filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); margin: 0 0 var(--space-2); padding: var(--space-2); background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius-lg); }
  .wide.grid tr.filters td { display: block; padding: 0; border: 0; background: none; white-space: normal; } /* a long label wraps */
  .wide.grid tr.filters td:empty { display: none; }
  .wide.grid tr.filters input[type=date] { width: 100%; min-width: 0; } /* a 16 px date box keeps to its column */
  .wide.grid tr.filters td[data-label]::before { content: attr(data-label); display: block; margin-bottom: 2px; font-size: 0.75rem; color: var(--muted); } /* the control's name, seen (its aria-label is heard) */
  .wide.grid tr.filters input,
  .wide.grid tr.filters select { min-height: 2.5rem; font-size: max(1rem, 16px); padding-inline: var(--space-2); }
  details.filters { display: block; margin: 0; padding: 0; border: 0; background: none; }
  details.filters > summary { display: inline-flex; align-items: center; gap: 0.375rem; min-height: 2rem; padding: 0 0.75rem; border: 1px solid var(--control); border-radius: var(--radius); background: var(--bg); font-size: 0.875rem; list-style: none; }
  details.filters > summary::-webkit-details-marker { display: none; }
  details.filters[open] > summary { border-color: var(--mark); background: var(--accent-soft); color: var(--accent); }
  /* From and To and the number filters' hint show while Filters is open, so the first purchase or sale on a customer
     or item page sits higher (a date in force still shows as its chip; the look panel's M-2). Apply shows in the
     toolbar only where its form holds a control of its own (the form, not the toolbar: the Columns menu beside it
     holds a checkbox per column) and while Filters is closed; the panel ends in its own Apply, the one Apply while it
     is open (M-4). */
  main:not(:has(details.filters[open])) .filter-bar label:has(> input[type=date]),
  main:not(:has(details.filters[open])) .hint { display: none; }
  .filter-bar:not(:has(label > input)) > button,
  main:has(details.filters[open]) .filter-bar > button { display: none; }
  .wide.grid tr.filters td.c-apply { grid-column: 1 / -1; }
  .wide.grid tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.625rem;
    margin: 0 0 var(--space-2);
    padding: 0.625rem 0.75rem;
    background: var(--bg);
    border: 1px solid var(--rule);
    border-radius: var(--radius-lg);
  }
  .wide.grid tbody tr > td { display: block; padding: 0; border: 0; white-space: normal; }
  .wide.grid tbody .cut { max-width: none; white-space: normal; }
  .wide.grid tbody .cut.desc { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
  .wide.grid tbody tr > .c-invoice,
  .wide.grid tbody tr > .c-name { font-weight: 600; }
  .wide.grid tbody tr > .c-invoice { order: 1; }
  .wide.grid tbody tr > .c-date { order: 2; color: var(--muted); font-size: 0.8125rem; }
  .wide.grid tbody tr > .c-revenue { order: 3; margin-left: auto; font-weight: 600; font-size: 0.9375rem; }
  .wide.grid tbody tr > .c-name,
  .wide.grid tbody tr > .c-customer,
  .wide.grid tbody tr > .c-description { order: 4; flex: 1 1 100%; } /* a Customers card's name heads it, alone on its line */
  .wide.grid tbody tr > .c-name { order: 1; }
  .wide.grid tbody td.num { text-align: left; }
  .wide.grid tbody tr > .c-kind,
  .wide.grid tbody tr > .c-seg,
  .wide.grid tbody tr > .c-category,
  .wide.grid tbody tr > .c-type,
  .wide.grid tbody tr > .c-class,
  .wide.grid tbody tr > .c-flags { order: 5; }
  .wide.grid tbody tr.row::after { content: ""; order: 6; flex: 1 1 100%; } /* quantity and price start a line */
  .wide.grid tbody tr > .c-ton,
  .wide.grid tbody tr > .c-qty,
  .wide.grid tbody tr > .c-price,
  .wide.grid tbody tr > .c-discount,
  .wide.grid tbody tr > .c-net,
  .wide.grid tbody tr > .c-invoices,
  .wide.grid tbody tr > .c-first,
  .wide.grid tbody tr > .c-last,
  .wide.grid tbody tr > .c-size,
  .wide.grid tbody tr > .c-brand,
  .wide.grid tbody tr > .c-sold,
  .wide.grid tbody tr > .c-questions,
  .wide.grid tbody tr > .c-completed,
  .wide.grid tbody tr > .c-job_category,
  .wide.grid tbody tr > .c-tyre_size,
  .wide.grid tbody tr > .c-tyre_brand,
  .wide.grid tbody tr > .c-condition,
  .wide.grid tbody tr > .c-forklift,
  .wide.grid tbody tr > .c-serial,
  .wide.grid tbody tr > .c-wheel,
  .wide.grid tbody tr > .c-repair,
  .wide.grid tbody tr > .c-context,
  .wide.grid tbody tr > .c-queue,
  .wide.grid tbody tr > .c-status,
  .wide.grid tbody tr > .c-payment { order: 7; color: var(--muted); }
  .wide.grid tbody tr > .c-year { order: 8; color: var(--muted); }
  .wide.grid tbody tr > td.c-x { order: 9; margin-left: auto; width: auto; padding: 0; }
  .wide.grid tbody td.c-ton::before { content: "Ton " / ""; }
  .wide.grid tbody td.c-qty::before { content: "Qty " / ""; }
  .wide.grid tbody td.c-price::before { content: "at " / ""; }
  .wide.grid tbody td.c-discount::before { content: "Disc " / ""; }
  .wide.grid tbody td.c-net::before { content: "Net " / ""; }
  .wide.grid tbody td:has(> .nil) { display: none; } /* a blank cell says nothing on a card (the grid's dash is for the table) */
  .wide.grid tbody td.c-tyre_size:not(:empty)::before { content: "Size " / ""; }
  .wide.grid tbody td.c-tyre_brand:not(:empty)::before { content: "Brand " / ""; }
  .wide.grid tbody td.c-condition:not(:empty)::before { content: "Condition " / ""; }
  .wide.grid tbody td.c-forklift:not(:empty)::before { content: "Forklift " / ""; }
  .wide.grid tbody td.c-serial:not(:empty)::before { content: "Serial " / ""; }
  .wide.grid tbody td.c-wheel:not(:empty)::before { content: "Wheel " / ""; }
  .wide.grid tbody td.c-repair:not(:empty)::before { content: "Repair " / ""; }
  .wide.grid tbody td.c-invoices::before { content: "Invoices " / ""; }
  .wide.grid tbody td.c-first::before { content: "First " / ""; }
  .wide.grid tbody td.c-last::before { content: "Last " / ""; }
  .wide.grid[aria-label=Items] tbody td.c-last::before { content: "Last sold " / ""; }
  .wide.grid tbody td.c-sold::before { content: "Sold " / ""; }
  .wide.grid tbody td.c-questions:not(:empty)::before { content: "Questions " / ""; }
  /* set B's job columns (Task B2): named, as quantity and price are; a workbook line's are empty and say nothing */
  .wide.grid tbody td.c-completed:not(:empty)::before { content: "Completed by " / ""; }
  .wide.grid tbody td.c-job_category:not(:empty)::before { content: "Job category " / ""; }
  .wide.grid tbody td.c-queue:not(:empty)::before { content: "Queue " / ""; }
  .wide.grid tbody td.c-status:not(:empty)::before { content: "Job status " / ""; }
  .wide.grid tbody td.c-payment:not(:empty)::before { content: "Payment " / ""; }
  .wide.grid td.c-x summary { width: 2.25rem; height: 2.25rem; border: 1px solid var(--rule); }
  .wide.grid tbody tr.row:has(details[open]) { margin-bottom: 0; border-color: var(--mark); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .wide.grid tbody tr.more { display: none; margin: 0; padding: 0; }
  .wide.grid tbody tr.row:has(details[open]) + tr.more { display: block; margin: 0 0 var(--space-2); border: 1px solid var(--mark); border-top: 0; border-radius: 0 0 var(--radius-lg) var(--radius-lg); overflow: hidden; }
  .wide.grid tbody tr.more > td { display: block; }
  .wide.grid tbody tr > td[colspan]:not(.c-x) { flex: 1 1 100%; }
  /* the totals bar under the cards: one band, the count, then each total named */
  .wide.grid > table > tfoot { display: block; }
  .wide.grid tfoot tr.sum { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; padding: 0.75rem; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius-lg); }
  .wide.grid tfoot tr.sum > * { position: static; display: block; padding: 0; border: 0; background: none; }
  .wide.grid tfoot tr.sum > :empty { display: none; }
  .wide.grid tfoot td.c-qty::before { content: "Qty " / ""; font-weight: var(--fw-body); color: var(--muted); }
  .wide.grid tfoot td.c-revenue::before { content: "Revenue " / ""; font-weight: var(--fw-body); color: var(--muted); }
  /* An invoice's lines: the description full width, then quantity, price and amount at the right, each labelled; the
     totals a line each; the header row visually hidden, read as before. */
  .table-box:has(> table.invoice-lines) { overflow: visible; border: 0; background: none; width: 100%; }
  table.invoice-lines,
  table.invoice-lines > tbody { display: block; }
  table.invoice-lines > thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  table.invoice-lines tr { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: baseline; gap: 0 0.75rem; padding: 0.5rem; border-bottom: 1px solid var(--rule); background: none; }
  table.invoice-lines tr > * { display: block; padding: 0; border: 0; }
  table.invoice-lines td.desc { flex: 1 1 100%; }
  table.invoice-lines td:empty { display: none; }
}

/* --- Targets fit the pointer (DESIGN 12, Decision 102): at least 24 by 24 CSS pixels everywhere (SC 2.5.8, AA),
   above; on a coarse pointer (a phone or a touch screen) buttons, inputs and links that stand alone at least 44 by 44
   (SC 2.5.5), the phone's sort pills and the filter chips among them. A link inside a sentence keeps its line, so no
   rule sizes a bare a. */
@media (pointer: coarse) {
  button,
  [role=button],
  a.btn,
  header a,
  nav a,
  td a,
  th a,
  .way a,
  .fchip {
    display: inline-flex;
    min-height: 44px;
    min-width: 44px;
  }
  input:not([type=checkbox], [type=radio], [type=hidden]),
  select,
  summary,
  fieldset label { min-height: 44px; }
  .grid td.c-x summary,
  .wide.grid td.c-x summary { width: 44px; height: 44px; } /* DESIGN 12; the cards' 2.25rem has this weight, so the
     later rule wins (review I-1) */
  .wide.grid thead th a { min-height: 44px; } /* the phone's sort pills, past the cards' 2rem (spec › 3) */
  .wide.grid tr.filters input,
  .wide.grid tr.filters select { min-height: 44px; } /* the Filters panel's controls, past the cards' 2.5rem */
  .toolbar a,
  .chips a { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; } /* Clear, Clear all */
  td a.sales { padding-block: 14px; margin-block: -14px; }
  /* desk v2 Task 19's heavier toolbar and grid rules, named again so the coarse 44 wins at equal weight: the toolbar's
     buttons and fields, the grid's sales arrow (its cell keeps the room), the check chip's hit area past its tag */
  .toolbar button,
  .toolbar .filter-bar > a,
  .toolbar .filter-bar label > input { min-height: 44px; }
  .grid td.c-description:has(> .sales) { padding-right: 2.875rem; }
  .grid tbody tr:not(.more) > td:not([colspan]) > a.sales { width: 44px; height: 44px; margin-top: -22px; }
  .grid tbody tr:not(.more) > td:not([colspan]) a.chip { position: relative; }
  .grid tbody tr:not(.more) > td:not([colspan]) a.chip::after { content: ""; position: absolute; inset: -10px -4px; }
  details.filters > summary { min-height: 44px; }
  th, td { padding-block: 0.5rem; }
  /* A form control is at least 16 pixels on a touch screen, so iOS Safari never zooms the page when one takes focus
     (the look panel's S-1); the viewport never blocks zoom (SC 1.4.4). The rules that size a control smaller are
     named here, after them, so at equal weight this one wins. */
  input:not([type=checkbox], [type=radio], [type=hidden]),
  select,
  textarea,
  .filter-bar label > input,
  thead .filters input,
  thead .filters select,
  .wide.grid tr.filters input,
  .wide.grid tr.filters select { font-size: max(1rem, 16px); }
}

/* --- Forced colours (Windows High Contrast): box-shadow and the author's colours are dropped, so the page shown in
   the navigation and a filter holding a value keep a mark of their own, an outline in the system's Highlight. */
@media (forced-colors: active) {
  .side a[aria-current=page],
  .bottom-bar a[aria-current=page],
  .bottom-bar details:has([aria-current=page]) > summary,
  .filters .set,
  .filter-bar .set { outline: 2px solid Highlight; outline-offset: -2px; }
}

/* --- Task 13, same words (desk v2 spec › 4.3): the badge beside its switch while it is on, in the accent so it reads
   apart from the line chips; its words say it, so colour never carries it alone (DESIGN 13). */
.filter-bar .badge { color: var(--accent); box-shadow: inset 0 0 0 1px var(--mark); }

/* --- Desk v2 Task 8 (spec › 4.7, 4.8): the Columns menu, a disclosure under the toolbar holding one POST form, and
   the header's switch that narrows the navigation to an icon rail from 960 pixels: each word kept as the link's
   accessible name and tooltip (the template marks it `sr`), Admin a popover menu beside the rail (the Popover API,
   no script). Below 960 the navigation is the bottom bar, so the switch is not offered. */
details.columns, details.columns[open] { margin: 0; padding: 0; border: 0; background: none; } /* a button that opens a panel, not the bordered disclosure */
details.columns > summary { cursor: pointer; } /* its look is the toolbar's secondary style (above) */
@media (pointer: coarse) { details.columns > summary { min-height: 44px; } } /* DESIGN 12: the site's coarse rule, which the line above outranks */
details.columns form { width: max-content; max-width: 100%; margin: var(--space-1) 0 0; padding: var(--space-2) var(--space-3); border: 1px solid var(--rule); border-radius: var(--radius); background: var(--bg); }
details.columns fieldset { margin: 0 0 var(--space-2); padding: 0; border: 0; }
details.columns ol { list-style: none; margin: 0; padding: 0; }
details.columns li { display: flex; align-items: center; gap: var(--space-1); }
details.columns li label { flex: 1 1 auto; margin: 0 var(--space-2) 0 0; }
details.columns li button { padding-inline: var(--space-2); }
details.columns li button:disabled { opacity: 0.4; cursor: default; box-shadow: none; } /* the first can go no higher, the last no lower */
/* The chevron at the navigation's top (Charlie, 14 Oct: as the legacy): at the head's right pointing left, centred in the
   rail pointing right; 32 px on a mouse, 44 on touch (the coarse rule); the form is its own, so it works without a script. */
.nav-switch { display: none; margin: 0; }
.nav-switch button { display: flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; margin: 0; padding: 0; border: 0; border-radius: var(--radius-sm); background: none; color: var(--chrome-muted); box-shadow: none; }
.nav-switch button:hover { background: var(--chrome-2); color: var(--text); box-shadow: none; }
.nav-switch .icon { width: 1.25rem; height: 1.25rem; transform: rotate(180deg); }
.nav-switch button[aria-expanded=false] .icon { transform: none; }
@media (min-width: 960px) {
  .nav-switch { display: block; }
  .narrow .side-head { justify-content: center; padding: 0; }
  .narrow .side .brand { display: none; }
}
@media (min-width: 960px) {
  /* From 960 the open menu floats under its button, so the toolbar and the table do not move. */
  details.columns { position: relative; }
  details.columns form { position: absolute; top: 100%; left: 0; z-index: var(--z-menu); max-width: none; box-shadow: var(--shadow-menu); }
  body.desk.narrow { grid-template-columns: var(--rail-w) minmax(0, 1fr); }
  .narrow .side ul { padding-inline: 0.375rem; }
  .narrow .side a,
  .narrow .side .nav-admin { justify-content: center; padding: 0.5rem 0; }
  .narrow .side .lbl,
  .narrow .side .nav-h,
  .narrow .side .who { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .narrow .side .note,
  .narrow .side .nav-admin-open { display: none; }
  .narrow .side .icon { width: 1.25rem; height: 1.25rem; }
  .narrow .side-foot { border-top: 0; padding: 0; }
  .narrow .side .nav-admin { display: flex; align-items: center; width: calc(100% - 0.75rem); margin: var(--space-2) 0.375rem 0; border: 0; border-radius: var(--radius-sm); background: none; color: var(--text-2); font: inherit; cursor: pointer; }
  .narrow .side .nav-admin:hover,
  .narrow .side .nav-admin.here { background: var(--chrome-2); box-shadow: none; color: var(--text); }
  .narrow .side .nav-admin.here .icon { color: var(--accent); }
  .side .nav-pop:not(:popover-open) { display: none; } /* `.side ul`'s flex would outrank the browser's own hiding */
  .side .nav-pop:popover-open {
    position: fixed; inset: auto; top: var(--side-head-h); left: var(--rail-w); margin: 0; min-width: 13rem; padding: var(--space-2);
    list-style: none; background: var(--chrome-2); color: var(--on-chrome); border: 1px solid var(--control); border-radius: var(--radius);
    display: flex;
  }
  .side .nav-pop a { justify-content: flex-start; padding: 0.375rem 0.625rem; color: var(--on-chrome); }
}

/* --- The invoice popup (desk v2 Task 9; spec › 4.5, DESIGN 3 and 18): the page's one modal <dialog id="sheet">,
   which js/sheet.js fills with the invoice's body part (no script, no popup: the link opens the page). From 760 CSS
   pixels a panel over the dimmed grid, at most 64rem wide, the × at its top right; below 760 it fills the screen, an
   invoice's lines a list (the phone rules above), its footer padded for the home indicator. Its body scrolls inside
   it and never chains to the grid behind (`overscroll-behavior: contain`). The dialog has no padding of its own, so a
   click on the dialog element itself is a click on the backdrop, which closes it (APG Dialog (Modal) pattern). */
#sheet { width: min(64rem, calc(100vw - 2rem)); max-width: none; max-height: calc(100dvh - 2rem); padding: 0; color: var(--text); background: var(--bg); border: 1px solid var(--rule); overflow: hidden; }
#sheet[open] { display: flex; flex-direction: column; }
#sheet .sheet-close { position: absolute; top: var(--space-2); right: var(--space-2); z-index: 1; padding: 0.125rem 0.625rem; font-size: 1.25rem; line-height: 1.2; color: var(--accent); background: var(--bg); border-color: var(--control); }
#sheet .sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
#sheet .sheet-status { margin: 0; padding: var(--space-4) 1.25rem; padding-right: 3.5rem; color: var(--muted); }
#sheet .table-box { max-height: none; }
#sheet .sheet-foot { position: sticky; bottom: 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); margin: var(--space-3) -1.25rem 0; padding: var(--space-2) 1.25rem calc(var(--space-2) + env(safe-area-inset-bottom)); background: var(--bg); border-top: 1px solid var(--rule); }
#sheet .sheet-foot p { margin: 0 auto 0 0; }
#sheet a.btn.secondary { color: var(--accent); background: transparent; border-color: var(--control); }
/* Below 760, written as "not 760 and wider" so the coarse-pointer block above stays the last rule at the cards'
   width (tests/test_look.py's 16 px pin); the sheet sets no control's size. */
@media not all and (min-width: 760px) {
  #sheet { width: 100%; height: 100%; max-height: none; margin: 0; border: 0; border-radius: 0; }
  #sheet .sheet-foot { margin-inline: calc(-1 * var(--space-3)); margin-top: auto; padding-inline: var(--space-3); } /* at the foot, in thumb reach */
}

/* --- The theme control (desk v2 Task 19; Charlie, 13 Oct 22:4x "allow us to toggle between light and dark mode"; moved from
   the header to the navigation's foot and the bottom bar's Account menu in slice 5e): a native disclosure (the APG
   Disclosure pattern; keyboard and no-script for free), its summary the state's icon and word (Auto, Light or Dark, named
   "Theme: …"), its panel one form of three buttons, the chosen one pressed and ticked, fixed beside the navigation's foot
   (inline in the phone's menu). A collapsed rail shows the icon alone, the word kept for a screen reader. */
details.theme,
details.theme[open] { position: relative; margin: 0; padding: 0; border: 0; background: none; }
details.theme > summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  min-height: 2rem;
  padding: 0 0.75rem;
  color: var(--on-chrome);
  border: 1px solid var(--chrome-muted);
  border-radius: var(--radius);
  font-size: var(--fs-table);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  list-style: none;
  cursor: pointer;
}
details.theme > summary::-webkit-details-marker { display: none; }
details.theme > summary:hover,
details.theme[open] > summary { background: var(--chrome-2); }
.theme-form {
  position: fixed; /* out of the navigation's scrolling box, beside its foot */
  bottom: var(--space-3);
  left: calc(var(--nav-w) + var(--space-2));
  z-index: var(--z-float);
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 13rem;
  margin: 0;
  padding: var(--space-1);
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.theme-form > button,
.theme-form > button + button {
  justify-content: flex-start;
  gap: 0.5rem;
  margin: 0;
  padding: 0.375rem 0.625rem;
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  font-weight: var(--fw-medium);
  text-align: left;
}
.theme-form > button small { color: var(--muted); font-weight: var(--fw-body); }
.theme-form > button:hover { background: var(--hover); box-shadow: none; }
.theme-form > button[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }
.theme-form > button[aria-pressed="true"]::after { content: "✓" / ""; margin-left: auto; }
.theme-form :focus-visible { outline-color: var(--focus); }
.narrow .theme-form { left: calc(var(--rail-w) + var(--space-2)); }
.narrow .side .acts { flex-direction: column; }
.narrow .side .asof { justify-content: center; margin: 0 0 var(--space-2); }
.narrow .side .acts :is(.word, .asof .lbl) { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.narrow .side .acts :is(details.theme > summary, .signout button) { justify-content: center; width: 2rem; min-height: 2rem; padding: 0; }
.narrow .side-foot { display: flex; flex-direction: column; align-items: center; padding-bottom: var(--space-3); }
@media (pointer: coarse) { /* DESIGN 12: the site's coarse rule, which the lines above outrank */
  .acts :is(details.theme > summary, .signout button) { min-height: 44px; min-width: 44px; }
  .theme-form button { min-height: 44px; }
}

/* --- The page's one look, "Airtable" (desk v2 Task 19's variant B, made the only look in the Lines page v3, Charlie
   14 Oct 13:4x: "i dont need both look a and b, just one will do"; the per-browser Look switch and look A's own
   rules are gone). A's tokens and hierarchy with Airtable's grid: compact 2rem rows, a line round every cell, the
   chevron and the invoice frozen at the left while the rest scrolls sideways in the box, a small type glyph before
   each header's label (A text, # number, ◷ date, ◉ a chip), and the toolbar a row of pills at the top left:
   Filters (the disclosure that shows the filter row and From and To, on the desk as on the phone), Sort (each
   column's sort link, from 760; the phone keeps its sort pills) and Columns. Every glyph's alternative text is
   empty: the label is the name. */
details.sort-menu { display: none; } /* the Sort pill, which the phone does without (its sort pills hold the same links) */
details.filters > summary,
details.sort-menu > summary,
details.columns > summary { border-radius: var(--radius-pill); }
details.sort-menu,
details.sort-menu[open] { position: relative; margin: 0; padding: 0; border: 0; background: none; }
details.sort-menu > summary { display: inline-flex; align-items: center; min-height: 2rem; padding: 0 0.75rem; border: 1px solid var(--control); background: transparent; color: var(--text); font-size: var(--fs-table); font-weight: var(--fw-medium); list-style: none; cursor: pointer; }
details.sort-menu > summary::-webkit-details-marker { display: none; }
details.sort-menu > summary::before { content: "⇅" / ""; margin-right: 0.375rem; color: var(--muted); }
details.sort-menu > summary:hover { background: var(--hover); }
details.sort-menu[open] > summary { border-color: var(--mark); background: var(--accent-soft); color: var(--accent); }
details.sort-menu ul { position: absolute; top: calc(100% + 4px); left: 0; z-index: var(--z-menu); min-width: 11rem; margin: 0; padding: var(--space-1); list-style: none; background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius); box-shadow: var(--shadow); }
details.sort-menu li a { display: flex; align-items: center; gap: 0.25rem; min-height: 2rem; padding: 0 var(--space-2); border-radius: var(--radius-sm); color: var(--text); text-decoration: none; }
details.sort-menu li a:hover { background: var(--hover); }
details.sort-menu li a[aria-current] { color: var(--accent); font-weight: var(--fw-strong); }
details.filters > summary::after { content: none; }
@media (min-width: 760px) {
  details.sort-menu { display: inline-block; }
  details.filters { display: block; margin: 0; padding: 0; border: 0; background: none; }
  details.filters > summary { display: inline-flex; align-items: center; gap: 0.375rem; min-height: 2rem; padding: 0 0.75rem; border: 1px solid var(--control); background: transparent; color: var(--text); font-size: var(--fs-table); font-weight: var(--fw-medium); list-style: none; cursor: pointer; }
  details.filters > summary:hover { background: var(--hover); }
  details.filters > summary::-webkit-details-marker { display: none; }
  details.filters[open] > summary { border-color: var(--mark); background: var(--accent-soft); color: var(--accent); }
  main:not(:has(details.filters[open])) .grid tr.filters { display: none; }
  main:not(:has(details.filters[open])) .filter-bar { display: contents; } /* no gap of its own while shut */
  main:not(:has(details.filters[open])) .filter-bar > :is(label, button, a) { display: none; } /* the chips say what is in force */
  main:not(:has(details.filters[open])) .grid thead th { border-bottom-width: 2px; }
  .grid :is(th, td) { border-right: 1px solid var(--rule); }
  .grid tbody tr:not(.more) > td:not([colspan]) { padding-block: 0.125rem; } /* A's 24 px link targets fit the 2rem row */
  .grid :is(th, td):last-child { border-right: 0; }
  .grid :is(th, td).c-x { position: sticky; left: 0; z-index: 1; width: var(--chev-w); min-width: var(--chev-w); background: inherit; }
  .grid :is(th, td).c-invoice { position: sticky; left: var(--chev-w); z-index: 1; background: inherit; }
  .grid thead :is(th, td):is(.c-x, .c-invoice) { z-index: 3; background: var(--surface); }
  .grid tbody td.c-invoice { box-shadow: inset -1px 0 0 var(--control); } /* the frozen edge */
  :where(.grid) tbody tr:not(.more) { background-color: var(--bg); }
  .grid tbody tr.more > td { background: var(--surface); } /* opaque under the frozen cells */
  .grid thead th > a::before { margin-right: 0.3rem; color: var(--muted); font-weight: var(--fw-body); font-size: 0.6875rem; }
  .grid thead th:is(.c-invoice, .c-customer, .c-description, .c-name, .c-size, .c-brand, .c-category, .c-type, .c-job_category, .c-queue, .c-status, .c-tyre_size, .c-tyre_brand, .c-condition, .c-forklift, .c-serial, .c-wheel, .c-repair, .c-context) > a::before { content: "A" / ""; }
  .grid thead th.num > a::before { content: "#" / ""; }
  .grid thead th:is(.c-date, .c-first, .c-last, .c-year, .c-completed) > a::before { content: "◷" / ""; }
  .grid thead th:is(.c-kind, .c-class, .c-seg, .c-flags) > a::before { content: "◉" / ""; }
}
@media (pointer: coarse) { /* DESIGN 12: the site's coarse rule, which B's 2rem pills above outrank on a tablet */
  details.filters > summary,
  details.sort-menu > summary,
  details.sort-menu li a { min-height: 44px; }
}

/* --- The Lines grid's columns and density (the Lines page v3, R-L2; the legacy's grid: fixed widths by the kind of
   content, a description of two lines, everything else on one). The segment is the legacy's small D or E badge, its
   words in the title; a blank cell in the legacy's columns is a dash. From 760 the table lays out fixed: the
   numbers, the year and the date narrow and right-aligned, the invoice and the segment narrow, the customer medium,
   the description taking what is left (and wrapping to two lines, the whole text kept in its cell); a box narrower
   than the columns scrolls, the chevron and invoice columns staying. The
   phone's cards above 760 are untouched. */
.nil { color: var(--muted); }
.lines-grid { position: relative; } /* the box holds its cells' visually hidden words: left to the page, a wide table's last cell widened it */
@media (min-width: 760px) {
  .lines-grid > table { table-layout: fixed; width: 100%; }
  .lines-grid :is(th, td) { overflow: hidden; text-overflow: ellipsis; }
  .lines-grid thead th:is(.c-tyre_size, .c-tyre_brand, .c-condition, .c-forklift, .c-serial, .c-wheel, .c-repair, .c-job_category, .c-completed, .c-queue, .c-status) { width: 6rem; }
  .lines-grid thead th.c-payment { width: 5rem; }
  .lines-grid thead th.c-context { width: 9rem; }
  .lines-grid :is(th, td):is(.c-year, .c-date) { text-align: right; }
  .lines-grid td.c-customer:has(.name),
  .lines-grid td.c-description:has(.desc) { width: auto; max-width: none; min-width: 0; } /* the earlier auto layout's shares */
  .lines-grid.grid tbody td .cut:not(.why) { display: block; max-width: none; }
  .lines-grid.grid tbody td .cut.desc { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; white-space: normal; overflow: hidden; }
  .lines-grid.grid tr.row:has(details[open]) .cut.desc { display: block; -webkit-line-clamp: none; line-clamp: none; } /* the opened row takes the height its whole description needs (R-L3) */
  .lines-grid tbody tr > td:not([colspan]) { padding-block: 0.1875rem; } /* below the compact rows' own rule, which keeps them tight */
  .lines-grid.grid td.c-description:has(> .sales) { padding-right: 1.625rem; }
}
/* Column widths by drag (js/widths.js; R-L1): a handle on each edge of a header cell, inside it (the cell clips what
   overflows), the column-resize cursor, a thin accent line on hover and while dragging; 20 px wide on a touch screen. The
   phone's cards have none. */
.rz, [data-reset-widths] { display: none; }
@media (min-width: 760px) {
  [data-reset-widths]:not([hidden]) { display: inline-block; }
  .lines-grid thead .rz { display: block; position: absolute; top: 0; bottom: 0; right: 0; width: var(--rz-w); cursor: col-resize; touch-action: none; user-select: none; outline: none; } /* the legacy's separator at the cell's edge (the study's 4.3), 8 px of hit area so the funnel can sit flush beside it */
  .lines-grid thead .rz:hover::after,
  .lines-grid thead .rz:focus-visible::after,
  .lines-grid thead .rz:active::after { content: ""; position: absolute; top: 0; bottom: 0; right: 0; width: 2px; background: var(--mark); } /* the 2 px accent line */
}

/* The button's line stays in view while the box is scrolled sideways: a cell that clips (the rule above) is the scrollport
   its sticky child sticks to, so this one does not. */
@media (min-width: 760px) { .lines-grid.grid tr.more > td { overflow: visible; } }
/* The opened row is the row itself, taller (Charlie, 14 Oct 2026): every cell shows its whole content, wrapping inside
   its column's width, the cells aligned at the top; numbers and dates stay on one line. The one line under it holds the
   button (`tr.more`). */
.lines-grid.grid tr.row:has(details[open]) .cut { display: block; max-width: none; overflow: visible; white-space: normal; text-overflow: clip; overflow-wrap: anywhere; }
/* Charlie, 14 Oct, 17:3x: the first line of every column sits on one line and no cell is cut, the date wrapping if its
   column is narrower than "30 Dec 2008". The selector outranks the closed rows' (`tr.row > td:not([colspan])`, which
   centres them in 52 px with no padding above or below), so the numbers and dates join the text at the top. */
.lines-grid.grid tbody tr.row:has(details[open]) > td:not([colspan]) { vertical-align: top; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
@media (min-width: 760px) { .lines-grid.grid tbody tr.row:has(details[open]) > td:not([colspan], .c-x) { padding-block: 0.5rem; } }
.lines-grid.grid tr.row:has(details[open]) .cut.desc { -webkit-line-clamp: none; line-clamp: none; }

/* --- The Lines page copied from the legacy (the Lines page v3, slice 5a; Charlie 14 Oct 2026: "try to copy it exactly";
   the study's 1.3 to 1.11, 2.2, 2.5 and 3). The top of page: one wrapping row with the search box (40 px, 8 px radius, the
   "/" key badge inside), the count, and 28 px buttons (13 px, 6 px radius) for Syntax and Settings, whose menus are native
   <details> (288 px and 384 px; fixed and centred on the phone). Then the term chips, the table's
   header (36.5 px, 11 px uppercase, a 24 px funnel at the right) and rows (52 px, 40 compact, 12 px cells, no stripes), the
   footer's expander. Colours are the tokens, the legacy's values in dark (the nearest that keep the 3:1 edges in light). */
.lbar { gap: 0.5rem; margin: 0 0 0.5rem; }
.lbar details { margin: 0; padding: 0; border: 0; background: none; position: relative; }
.lform { flex: 1 1 18rem; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0; }
.lsearch { position: relative; display: block; flex: 1 1 14rem; min-width: 0; margin: 0; }
.lsearch > .icon { position: absolute; left: 0.75rem; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.lsearch > input { display: block; width: 100%; max-width: none; height: 2.5rem; margin: 0; padding: 0 2.25rem 0 2.5rem; border-radius: var(--radius); background: var(--field); border-color: var(--control); font-size: 0.875rem; box-shadow: var(--shadow-search); }
.lsearch > input::placeholder { color: var(--muted); opacity: 1; }
.lsearch > input:focus { border-color: var(--mark); }
.lsearch kbd { position: absolute; right: 0.75rem; top: 50%; transform: translateY(-50%); padding: 2px 6px; border: 1px solid var(--control); border-radius: var(--radius-sm); background: var(--surface); color: var(--muted); font: 0.6875rem/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; pointer-events: none; }
.lcount { padding: 0 0.375rem; font-size: 0.8125rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.lcount .n { font-weight: 600; color: var(--text); }
.lcount .dot { color: var(--faint); }
.lbar .lbtn, .lbar details.filters > summary.lbtn { display: inline-flex; align-items: center; gap: 0.375rem; height: 1.75rem; min-height: 1.75rem; padding: 0 0.625rem; border: 1px solid var(--control); border-radius: var(--radius-sm); background: var(--surface); color: var(--text-2); font-size: 0.8125rem; font-weight: 500; line-height: 1; list-style: none; cursor: pointer; }
.lbar .lbtn::-webkit-details-marker { display: none; }
.lbar .lbtn:hover { background: color-mix(in srgb, var(--surface) 92%, var(--text)); }
.lbar details[open] > .lbtn, .lbar details.filters[open] > summary.lbtn { border-color: var(--mark); background: var(--accent-soft); color: var(--accent); }
.lbar .lbtn .icon { width: 0.9375rem; height: 0.9375rem; }
.lbar details.filters { display: block; }
.lbar details.filters > summary.lbtn::after { content: none; }
@media (min-width: 760px) { .lbar details.sort-menu { display: none; } } /* the legacy sorts by its headers on the desk */
.menu .pop { position: absolute; right: 0; top: calc(100% + 4px); z-index: var(--z-popover); width: 24rem; max-width: 92vw; padding: 1rem; border: 1px solid var(--control); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-pop); text-align: left; }
.menu.settings .pop { width: 18rem; padding: 0.75rem; max-height: 78vh; overflow-y: auto; }
.pop h2, .pop .eh { margin: 0 0 0.5rem; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.pop .eh { margin-top: 0.75rem; }
.tries { list-style: none; margin: 0; padding: 0; }
.tries a { display: flex; align-items: baseline; gap: 0.5rem; padding: 0.25rem 0.5rem; border-radius: var(--radius-sm); color: var(--muted); font-size: 0.75rem; text-decoration: none; }
.tries a:hover { background: color-mix(in srgb, var(--surface) 92%, var(--text)); }
.tries code { color: var(--accent); font-size: 0.75rem; }
.tries.pills { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.tries.pills a { padding: 0.125rem 0.5rem; border: 1px solid var(--control); border-radius: var(--radius-pill); background: var(--bg); }
.tries.pills code { color: var(--text-2); }
.pop .keys { margin: 0.75rem 0 0; padding-top: 0.5rem; border-top: 1px solid var(--rule); font-size: 0.75rem; color: var(--muted); }
.pop .keys .kw { font-weight: 500; color: var(--text-2); }
kbd { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: inherit; color: var(--text-2); }
.tilde { color: var(--accent); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
/* The Legend (slice 5c): a term and its meaning, two columns; the sample sits in the term's column in its own real style. */
.menu.legend-menu .pop { width: 28rem; padding: 0.75rem; max-height: 78vh; overflow-y: auto; }
.lg { display: grid; grid-template-columns: minmax(4.5rem, max-content) 1fr; gap: var(--space-1) var(--space-3); margin: 0; font-size: 0.75rem; color: var(--muted); }
.lg dt { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem; margin: 0; font-weight: 500; color: var(--text-2); }
.lg dd { margin: 0; }
.lg .icon { width: 0.75rem; height: 0.75rem; }
.lg .red { font-weight: 600; color: var(--wrong); }
.pop .note { margin: 0 0 var(--space-1); font-size: 0.75rem; color: var(--muted); }
.setting { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin: 0; padding: 0.375rem 0; }
.setting .sl { display: block; font-size: 0.875rem; color: var(--text-2); }
.setting small { display: block; font-size: 0.75rem; color: var(--muted); }
.setting form, form.setting { margin: 0; }
.sw, .seg2 button { display: inline-flex; align-items: center; justify-content: center; min-height: 24px; margin: 0; padding: 0 0.5rem; border: 1px solid var(--control); border-radius: var(--radius-sm); background: var(--bg); color: var(--muted); font-size: 0.75rem; font-weight: 400; line-height: 1.2; text-decoration: none; cursor: pointer; }
.sw.on, .seg2 button[aria-pressed=true] { border-color: var(--mark); background: var(--accent-soft); color: var(--accent); }
.sw:disabled { opacity: 0.5; cursor: default; }
.seg2 { display: inline-flex; gap: 0.25rem; }
.seg2 button + button { margin-left: 0; }
.columns-in { margin: 0.5rem 0 0; }
.columns-in .ch { display: flex; align-items: center; justify-content: space-between; }
.columns-in .ch .eh { margin: 0 0 0.25rem; }
.columns-in form { margin: 0; }
.columns-in fieldset { height: 15rem; overflow-y: auto; margin: 0 0 0.5rem; padding: 0.25rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); background: var(--bg); }
.columns-in legend { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); }
.columns-in ol { margin: 0; padding: 0; list-style: none; }
.columns-in li label { font-size: 0.8125rem; color: var(--text-2); }
button.linkish { min-height: 24px; padding: 0 0.25rem; border: 0; background: none; color: var(--accent); font-size: 0.75rem; }
button.linkish:hover { box-shadow: none; text-decoration: underline; }
/* the term chips (the study's 1.5): one pill a word, a count of what it alone finds, the x; a word that finds nothing red */
.tchips { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.375rem 0.75rem; margin: 0 0 0.5rem; }
.tchips .chips { margin: 0; gap: 0.375rem; }
.tchips .fchip { min-height: 1.5rem; padding: 0 0.625rem; font-size: 0.75rem; }
.tchips .fchip.term { border-color: var(--control); background: var(--surface); color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; text-decoration: none; }
.tchips .fchip.term .count { font-family: var(--font); font-weight: 400; color: var(--muted); }
.tchips .fchip.zero { border-color: var(--wrong); background: var(--wrong-bg); color: var(--wrong); }
.tchips .fchip.zero .count { font-weight: 600; color: var(--wrong); }
.tchips .fchip.mode { text-decoration: none; }
.order { display: inline-flex; gap: 0.375rem; }
.obtn { display: inline-flex; align-items: center; gap: 0.25rem; min-height: 1.5rem; padding: 0 0.5rem; border: 0; border-radius: var(--radius-sm); background: var(--surface); color: var(--text-2); font-size: 0.75rem; text-decoration: none; }
.obtn.on { background: color-mix(in srgb, var(--surface) 92%, var(--text)); }
.obtn.soon { opacity: 0.6; }
.obtn .icon { width: 0.75rem; height: 0.75rem; }
.clearall { flex: 1 1 100%; font-size: 0.8125rem; color: var(--muted); }
/* The foot of the segmented Lines table (slice 5c): what is loaded, the way to load more, and the banner (the one `.banner`
   component, with a progress bar) while a segment arrives. */
.lmore { margin: var(--space-2) 0; }
.lmore-live .banner { margin: 0; }
.lmore-live { position: sticky; bottom: var(--space-2); z-index: 4; margin-top: var(--space-2); box-shadow: var(--shadow-lift); border-radius: var(--radius); } /* seen while it arrives, wherever the reader is in the list */
@media (max-width: 959.98px) { .lmore-live { bottom: calc(var(--bar-h) + var(--space-2) + env(safe-area-inset-bottom)); } } /* above the bottom bar */
.js .lmore:not([data-failed]) .lmore-link { display: none; } /* the script loads the next segment as the reader nears the end */
.lmore-link { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0; font-size: 0.8125rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.ltop { margin: 0 0 var(--space-2); font-size: 0.8125rem; color: var(--muted); }
.banner progress { display: block; width: 100%; height: 0.25rem; margin-top: 0.375rem; border: 0; border-radius: var(--radius-pill); background: color-mix(in srgb, var(--check) 25%, transparent); accent-color: var(--check); appearance: none; }
.banner progress::-webkit-progress-bar { background: color-mix(in srgb, var(--check) 25%, transparent); border-radius: var(--radius-pill); }
.banner progress::-webkit-progress-value { background: var(--check); border-radius: var(--radius-pill); }
.banner progress::-moz-progress-bar { background: var(--check); border-radius: var(--radius-pill); }
/* the table (the study's 1.7 to 1.9) */
.lines-grid.table-box { border-radius: var(--radius-lg); }
@media (min-width: 760px) {
  .lines-grid > table { min-width: calc(var(--cols-w) + var(--desc-min)); } /* the fixed columns and the description's floor: a box narrower scrolls in itself */
  /* The default widths: each is at least its label + the sort arrow (16 px) + the funnel's slot, the handle and a gap (32 px) + the padding, which tests/browser/test_widths.py checks at 1280, so no default label is ever cut; the numbers are as wide as "99,999.00" needs; the description is the one auto column */
  .lines-grid thead th.c-year { width: 6.25rem; }
  .lines-grid thead th.c-invoice { width: 7.5rem; }
  .lines-grid thead th.c-date { width: 5.75rem; }
  .lines-grid thead th.c-customer { width: 10.625rem; }
  .lines-grid thead th.c-seg { width: 5.5rem; }
  .lines-grid thead th.c-category { width: 8.25rem; }
  .lines-grid thead th.c-type { width: 6rem; }
  .lines-grid thead th.c-ton { width: 5.25rem; }
  .lines-grid thead th.c-qty { width: 3.75rem; }
  .lines-grid thead th.c-price, .lines-grid thead th.c-net { width: 4.75rem; }
  .lines-grid thead th.c-discount { width: 4.5rem; }
  .lines-grid thead th.c-revenue { width: 6.25rem; }
  .lines-grid thead th.c-flags { width: 5.5rem; }
  .lines-grid thead th.c-description { width: auto; } /* the one auto column: what the box leaves, from --desc-min (440 px) up */
  .lines-grid.grid thead th { position: sticky; height: var(--head-h); padding: 0; border-bottom: 1px solid var(--control); border-right: 1px solid var(--rule); background: var(--surface); font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
  .lines-grid.grid thead th[aria-sort] { background: var(--accent-soft); }
  .lines-grid.grid thead th > a:not(.fn) { display: flex; align-items: center; gap: 0.25rem; min-height: var(--head-h); padding: 0 calc(var(--fn-slot) + var(--rz-w) + var(--space-1)) 0 var(--cell-x); color: var(--muted); } /* the label's cell: the funnel's slot (20 px, beside the 8 px resize handle at the edge) and a 4 px gap are always reserved, so label and funnel never meet */
  .lines-grid thead .lbl { min-width: 0; white-space: nowrap; } /* never an ellipsis: a default width holds the whole label */
  .lines-grid thead .sa { flex: none; }
  .lines-grid.grid thead th.num:not(:has(.fn)) > a:not(.fn), .lines-grid.grid thead th:not(:has(.fn)) > a:not(.fn) { padding-right: var(--cell-x); }
  .lines-grid.grid thead th.num > a:not(.fn) { justify-content: flex-end; }
  .lines-grid.grid thead th > a::before { content: none; } /* the Airtable type marks are not the legacy's */
  .lines-grid.grid thead th > a::after { content: none; }
  .lines-grid.grid thead th > a:not(.fn):hover { color: var(--text); text-decoration: none; }
  .lines-grid.grid thead th[aria-sort] > a:not(.fn) { color: var(--accent); }
  .lines-grid thead .sa { width: 0.75rem; height: 0.75rem; }
  .lines-grid thead .fn { position: absolute; top: calc(50% - var(--fn-slot) / 2); right: var(--rz-w); display: flex; align-items: center; justify-content: center; width: var(--fn-slot); height: var(--fn-slot); min-width: 0; min-height: 0; margin: 0; padding: 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--muted); opacity: 0.8; cursor: pointer; } /* the funnel: a button in the cell's slot, just inside the resize handle at the cell's right edge */
  .lines-grid thead .fn:hover, .lines-grid thead .fn:focus-visible, .lines-grid thead .fn[aria-expanded=true], .lines-grid thead .fn.on { opacity: 1; background: color-mix(in srgb, var(--surface) 92%, var(--text)); color: var(--text); } /* muted at rest, full on hover and focus */
  .lines-grid thead .fn.on { color: var(--accent); background: var(--accent-soft); }
  .lines-grid thead .fn.on::after { content: ""; position: absolute; top: 1px; right: 1px; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); } /* the small dot of an applied filter */
  .lines-grid thead .fn:focus-visible { outline: 2px solid var(--mark); outline-offset: 1px; }
  .lines-grid thead .fn .icon { width: 0.75rem; height: 0.75rem; }
  .lines-grid.grid tbody tr.row > td:not([colspan]) { height: var(--row-dense); padding: var(--cell-y) var(--cell-x); border-bottom: 1px solid var(--rule); border-right: 1px solid var(--rule); vertical-align: middle; font-size: 0.75rem; line-height: 1.35; color: var(--text-2); }
  .lines-grid.comfortable.grid tbody tr.row > td:not([colspan]) { height: var(--row-comfy); padding-block: 0; } /* the earlier look, kept as a setting */
  .lines-grid.grid tbody tr.row > td.c-x { padding: 0; }
  .lines-grid.grid tbody tr.row > td:is(.c-net, .c-revenue) { color: var(--text); }
  .lines-grid.grid tbody td.c-invoice a { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.75rem; }
  .lines-grid.grid tbody tr.row:hover { background-color: var(--hover); }
  .lines-grid.grid tbody td .cut.desc { line-height: 1.375; }
}
.seg { display: inline-block; padding: 2px 6px; border-radius: var(--radius-sm); font-size: 0.6875rem; font-weight: 500; line-height: 1.3; text-align: center; } /* the segment badge, the legacy's: D or E, its words in the title */
.seg-d { color: var(--dealer); background: var(--dealer-bg); }
.seg-e { color: var(--end-user); background: var(--end-user-bg); }
mark.hit { color: var(--check); background: var(--check-bg); border-radius: 3px; padding: 0; }
@media not all and (min-width: 760px) { /* the phone: the box over the full width, its words short, the menus fixed and centred (the study's 1.3, 2.2) */
  .lform { flex-basis: 100%; }
  .lsearch > input { height: 2.25rem; font-size: max(1rem, 16px); }
  .lbar .lbtn .word { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .lbar details { position: static; }
  .menu .pop, .menu.settings .pop, .menu.legend-menu .pop { position: fixed; left: 50%; right: auto; top: 5rem; transform: translateX(-50%); width: min(92vw, 24rem); max-height: 72dvh; overflow-y: auto; }
}
@media (pointer: coarse) {
  .lbar .lbtn, .lbar details.filters > summary.lbtn, .sw, .seg2 button, .obtn, .tries a, .clearall, button.linkish { min-height: 44px; min-width: 44px; }
}
@media (forced-colors: active) {
  .sw.on, .seg2 button[aria-pressed=true] { outline: 2px solid Highlight; }
}
@media (min-width: 760px) {
  .lines-grid :is(th, td):is(.c-year, .c-date) { text-align: left; } /* only Qty, Unit, Disc, Net and Revenue are right-aligned (the study's 1.9) */
}
.columns-in li { display: flex; align-items: center; gap: 0.25rem; padding: 0 0.375rem; border-radius: var(--radius-xs); }
.columns-in li:hover { background: color-mix(in srgb, var(--bg) 92%, var(--text)); }
.columns-in li label { flex: 1 1 auto; margin: 0; padding: 0.25rem 0; }
.columns-in li button { min-height: 24px; min-width: 24px; padding: 0 0.25rem; border-radius: var(--radius-xs); font-size: 0.75rem; line-height: 1; }
.columns-in form > button { min-height: 24px; padding: 0 0.625rem; font-size: 0.75rem; }
/* the empty result (the study's 1.7): a card in place of the table, with the legacy's title, line and button, and the examples to try */
.empty-card { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; padding: 2rem 1rem; border: 1px solid var(--rule); border-radius: var(--radius-lg); background: var(--bg); text-align: center; }
.empty-card .card { max-width: 32rem; padding: 1rem 1.5rem; border: 1px solid var(--control); border-radius: var(--radius-lg); background: var(--surface); }
.empty-card h2 { margin: 0 0 0.25rem; font-size: 1rem; }
.empty-card p { margin: 0 0 0.5rem; overflow-wrap: anywhere; }
.empty-card code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.875rem; }
.empty-card .try { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.375rem; margin: 0; font-size: 0.75rem; color: var(--muted); }
.empty-card .try a { padding: 0.125rem 0.5rem; border: 1px solid var(--control); border-radius: var(--radius-pill); background: var(--bg); color: var(--text-2); text-decoration: none; }
@media (pointer: coarse) { .empty-card .try a, .empty-card .btn { min-height: 44px; } }

/* --- The header filter menus (the Lines page v3, slice 5b; the study's 4.2): a funnel on each of nine headers is a native
   <details>; its popover is the legacy's: 280 px wide, at most 72vh high, above the sticky header (z 60), surface-2 with the
   default line and an 8 px radius, padding 8 px; the column's name in 11 px capitals with Clear at the right, two segmented
   tabs (radios and their labels, the panes shown by CSS, so no script is needed), the Values list of checkboxes with their
   lines at the right (28 px rows), the Condition pane's operator, value (and for between its upper end) and a full-width
   Apply. Fixed, so a header cell's clipping never cuts it; with no script it sits under its funnel (the right-hand
   columns open leftwards), and `js/menus.js` places it by the funnel and keeps it on the screen. */
.fpop { width: 17.5rem; max-width: calc(100vw - 1rem); max-height: 72vh; margin: 0; overflow-y: auto; padding: 0.5rem; background: var(--surface); border: 1px solid var(--control); border-radius: var(--radius); box-shadow: var(--shadow-modal); text-align: left; color: var(--text); font-size: 0.8125rem; }
.fpop:not(:popover-open):not(.shown) { display: none; }
.fpop.shown:not(:popover-open) { position: fixed; z-index: var(--z-modal); inset: 6rem auto auto 50%; transform: translateX(-50%); } /* the address asked for it open (no script): the same box, over the page */
.fpop[popover]:popover-open { inset: 6rem auto auto 50%; transform: translateX(-50%); } /* where nothing places it: centred under the header */
@supports (position-area: bottom) { /* a browser with anchor positioning puts it under its funnel, flipping to the side with room */
  .fpop { position-try-fallbacks: flip-inline; }
  .fpop[popover]:popover-open { inset: auto; transform: none; margin: 4px 0 0; position-area: bottom span-left; }
  .fpop[data-col=year] { position-anchor: --fn-year; } .fpop[data-col=invoice] { position-anchor: --fn-invoice; } .fpop[data-col=date] { position-anchor: --fn-date; }
  .fpop[data-col=customer] { position-anchor: --fn-customer; } .fpop[data-col=seg] { position-anchor: --fn-seg; } .fpop[data-col=category] { position-anchor: --fn-category; }
  .fpop[data-col=type] { position-anchor: --fn-type; } .fpop[data-col=description] { position-anchor: --fn-description; } .fpop[data-col=ton] { position-anchor: --fn-ton; }
  .fn[data-col=year] { anchor-name: --fn-year; } .fn[data-col=invoice] { anchor-name: --fn-invoice; } .fn[data-col=date] { anchor-name: --fn-date; }
  .fn[data-col=customer] { anchor-name: --fn-customer; } .fn[data-col=seg] { anchor-name: --fn-seg; } .fn[data-col=category] { anchor-name: --fn-category; }
  .fn[data-col=type] { anchor-name: --fn-type; } .fn[data-col=description] { anchor-name: --fn-description; } .fn[data-col=ton] { anchor-name: --fn-ton; }
}
.fhead { display: flex; align-items: center; justify-content: space-between; margin: 0 0 0.5rem; }
.fname { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.fclear { padding: 0.125rem 0.375rem; border-radius: var(--radius-xs); font-size: 0.75rem; font-weight: 500; text-transform: none; letter-spacing: normal; color: var(--accent); }
.fclear.off { color: var(--faint); }
.ftabs { position: relative; display: flex; gap: 2px; margin: 0 0 0.5rem; padding: 2px; background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius-sm); }
.ftabs input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.ftabs label { flex: 1 1 0; margin: 0; padding: 0.25rem 0.5rem; border-radius: var(--radius-xs); text-align: center; font-size: 0.75rem; font-weight: 500; color: var(--muted); cursor: pointer; }
.ftabs input:checked + label { background: var(--accent-soft); color: var(--accent); }
.ftabs input:focus-visible + label { outline: 2px solid var(--mark); outline-offset: 1px; }
.fpop:has(.t-v:checked) .fcond, .fpop:has(.t-c:checked) .fvals { display: none; }
.fform { margin: 0; }
.fsearch { display: block; width: 100%; height: 2rem; margin: 0 0 0.375rem; padding: 0 0.5rem; font-size: 0.8125rem; border-color: var(--control); background: var(--field); }
.fsearch:focus { border-color: var(--mark); }
.fsearch[hidden], .fhint[hidden], .fapply[hidden] { display: none; }
.fhint { margin: 0 0 0.375rem; font-size: 0.75rem; color: var(--muted); }
.flist { list-style: none; margin: 0 0 0.5rem; padding: 0; max-height: 14rem; overflow-y: auto; }
.flist label { display: flex; align-items: center; gap: 0.5rem; min-height: 28px; margin: 0; padding: 0 0.375rem; border-radius: var(--radius-xs); font-size: 0.75rem; color: var(--text-2); cursor: pointer; }
.flist label:hover { background: color-mix(in srgb, var(--surface) 92%, var(--text)); }
.flist .fv { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flist .fc { color: var(--muted); font-variant-numeric: tabular-nums; }
.fcond { display: grid; gap: 0.5rem; }
.fcond select, .fcond input:not([type=checkbox]) { display: block; width: 100%; max-width: none; height: 2rem; margin: 0; padding: 0 0.5rem; font-size: 0.8125rem; }
.fin { display: grid; gap: 0.5rem; }
.fto { display: none; align-items: center; gap: 0.375rem; color: var(--muted); }
.fto input { flex: 1 1 auto; }
.fcond:has(option[value=between]:checked) .fto { display: flex; }
.fsame { display: flex; align-items: center; gap: 0.5rem; margin: 0; font-size: 0.75rem; color: var(--text-2); }
button.fapply { width: 100%; min-height: 2rem; padding: 0 0.75rem; font-size: 0.8125rem; border-radius: var(--radius-sm); }
button.fapply:not(.primary) { background: transparent; color: var(--accent); border-color: var(--control); }
.fchip.menu { border-color: var(--mark); }
@media (pointer: coarse) {
  .fclear, .ftabs label, .fcond select, .fcond input:not([type=checkbox]), .fsearch, button.fapply { min-height: 44px; }
  .flist label { min-height: 44px; }
  .fclear { display: inline-flex; align-items: center; }
}
@media not all and (min-width: 760px) { /* the phone: the pill strip holds a funnel after each sort pill; the popover is centred under the header as the Settings menu is */
  .wide.grid thead th:has(.fn) { display: flex; align-items: center; gap: 0.25rem; }
  .lines-grid thead .fn { display: inline-flex; align-items: center; justify-content: center; position: static; min-width: 44px; min-height: 44px; padding: 0; border: 1px solid var(--rule); border-radius: var(--radius-pill); background: var(--bg); color: var(--muted); cursor: pointer; }
  .lines-grid thead .fn.on, .lines-grid thead .fn[aria-expanded=true] { border-color: var(--mark); background: var(--accent-soft); color: var(--accent); }
  .lines-grid thead .fn .icon { width: 0.875rem; height: 0.875rem; }
  .fpop, .fpop[popover]:popover-open { width: min(92vw, 20rem); max-height: 72dvh; inset: 5rem auto auto 50%; transform: translateX(-50%); margin: 0; position-area: none; }
}
@media (forced-colors: active) { .lines-grid thead .fn.on { outline: 2px solid Highlight; } }

/* The selected row (the study's 1.9: the accent tint and a 2 px accent bar at the left; `js/keys.js` marks it with the arrow keys) */
.lines-grid.grid tr.row[aria-selected=true] > td { background-color: var(--accent-soft); }
.lines-grid.grid tr.row[aria-selected=true] > td:first-child { box-shadow: inset 2px 0 0 var(--mark); }
.lines-grid.grid tr.row:focus-visible { outline: 2px solid var(--mark); outline-offset: -2px; }
/* The typeahead under the search box (the study's 2.4: the box's width, surface-2, the default line, an 8 px radius, a shadow;
   a letter glyph, the word in mono, a muted count; the foot's 11 px capitals) */
.lform { position: relative; }
.sugg { position: absolute; top: 2.75rem; z-index: var(--z-popover); overflow: hidden; background: var(--surface); border: 1px solid var(--control); border-radius: var(--radius); box-shadow: var(--shadow-pop); }
.sugg ul { list-style: none; margin: 0; padding: 0.25rem; }
.sugg li { display: flex; align-items: center; gap: 0.5rem; min-height: 28px; padding: 0 0.5rem; border-radius: var(--radius-sm); font-size: 0.8125rem; color: var(--text); cursor: pointer; }
.sugg li[aria-selected=true], .sugg li:hover { background: var(--accent-soft); }
.sugg .sg-g { width: 1rem; text-align: center; font: 0.75rem ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--muted); }
.sugg .sg-w { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.8125rem; }
.sugg .sg-n { font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sugg .sfoot { display: flex; justify-content: space-between; gap: 0.5rem; margin: 0; padding: 0.375rem 0.75rem; border-top: 1px solid var(--rule); font-size: 0.6875rem; color: var(--muted); }
.sugg .sfoot span:first-child { text-transform: uppercase; letter-spacing: 0.05em; }
@media (pointer: coarse) { .sugg li { min-height: 44px; } }

/* The invoice popup in the legacy modal's look (the Lines page v3, slice 5b; the study's 1.12): a dialog of 12 px radius with the
   default line and the large shadow over a dimmed, blurred page; the title in bold mono 18 px with the customer, date and
   line count in muted type under it; "Copy (Excel)" beside the ×; the line it was opened from marked as a selected row. */
#sheet { border-color: var(--control); border-radius: var(--radius-lg); box-shadow: var(--shadow-modal); }
#sheet::backdrop { background: var(--scrim); backdrop-filter: blur(4px); }
#sheet .sheet-head h2 { margin: 0; font: 700 1.125rem/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
#sheet .sheet-sub { margin: 0.125rem 0 0; font-size: 0.8125rem; color: var(--muted); }
#sheet .sheet-copy { position: absolute; top: var(--space-2); right: 3.25rem; z-index: 1; min-height: 28px; padding: 0 0.625rem; font-size: 0.8125rem; border-radius: var(--radius-sm); background: var(--surface); color: var(--text-2); border-color: var(--control); }
#sheet .sheet-copy[hidden] { display: none; }
#sheet .copycol { min-height: 24px; min-width: 24px; margin-left: 0.25rem; padding: 0 0.25rem; border-radius: var(--radius-xs); font-size: 0.75rem; line-height: 1; color: var(--muted); background: transparent; border-color: transparent; }
#sheet .copycol:hover { color: var(--text); border-color: var(--control); }
.invoice tr.here > * { background-color: var(--accent-soft); }
.invoice tr.here > :first-child { box-shadow: inset 2px 0 0 var(--mark); } /* the line it was opened from, on the page and in the popup */
@media (pointer: coarse) { #sheet .sheet-copy, #sheet .copycol { min-height: 44px; min-width: 44px; } }


/* The invoice in the popup, the legacy modal's content (the Lines page v3, slice 5b; the study's 1.12): Bill to and Deliver to
   side by side, a line of small fields, the note banner, the lines' table with the marked line, the totals right-aligned,
   the original invoice below (a PDF the height of a page, or the sheet's cells), the footnote. Eyebrows, banners and chips are
   the site's; the tokens are the root's. */
.eyebrow { margin: 0 0 0.375rem; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.sheetbody { padding: 1rem 1.25rem; }
.sheetbody .sheet-head { margin: 0 0 0.75rem; padding-right: 13rem; }
.sheetbody .parties { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 0.75rem 2rem; margin: 0 0 0.75rem; }
.sheetbody .parties p { margin: 0 0 0.125rem; overflow-wrap: anywhere; }
.sheetbody .pname { font-weight: 600; }
.sheetbody .fields { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; margin: 0 0 0.75rem; font-size: 0.8125rem; }
.sheetbody .fields .muted { margin-right: 0.25rem; }
.banner { margin: 0 0 0.75rem; padding: 0.5rem 0.75rem; border: 1px solid var(--check); border-radius: var(--radius); background: var(--check-bg); color: var(--text); font-size: 0.8125rem; overflow-wrap: anywhere; white-space: pre-line; }
.sheetbody .invoice-lines th { font-size: 0.6875rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.sheetbody .invoice-lines .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.75rem; white-space: nowrap; }
.sheetbody dl.totals { display: block; margin: 0.75rem 0 0 auto; width: fit-content; max-width: 100%; }
.sheetbody .totals div { display: flex; justify-content: space-between; gap: 2rem; padding: 0.125rem 0; font-variant-numeric: tabular-nums; }
.sheetbody .totals dt { color: var(--muted); }
.sheetbody .totals dd { margin: 0; text-align: right; }
.sheetbody .totals .total { border-top: 1px solid var(--rule); font-weight: 600; }
.sheetbody .totals .total dt { color: var(--text); }
.sheetbody .original { margin: 1rem 0 0; }
.sheetbody .orig-pdf { display: block; width: 100%; height: 70vh; min-height: 24rem; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface); }
.sheetbody .orig-sheet { max-height: 70vh; overflow: auto; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--bg); }
.orig { border-collapse: collapse; width: auto; min-width: 100%; font-size: 0.75rem; }
.orig td { padding: 0.125rem 0.375rem; border: 0; vertical-align: top; white-space: pre-wrap; color: var(--text); background: none; }
.orig .b { font-weight: 700; } .orig .ac { text-align: center; } .orig .ar { text-align: right; }
.orig .bt { border-top: 1px solid var(--control); } .orig .bb { border-bottom: 1px solid var(--control); }
.orig .bl { border-left: 1px solid var(--control); } .orig .br { border-right: 1px solid var(--control); }
.sheetbody .sheet-note { margin: 1rem 0 0; font-size: 0.75rem; }
/* The customer in the popup (slice 5e): the same dialog and head, narrower, its name in the page's sans, the segment badge beside it,
   the other spellings and the contacts as short lists, the two actions in the foot. */
#sheet:has(.customer-card) { width: min(32rem, calc(100vw - 2rem)); }
.customer-card .sheet-head { padding-right: 2.5rem; }
#sheet .customer-card .sheet-head h2 { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; font: 700 1.125rem/1.3 var(--font); overflow-wrap: anywhere; }
.customer-card section { margin: 0 0 0.75rem; }
.customer-card .spellings { margin: 0; padding: 0; list-style: none; font-size: 0.8125rem; overflow-wrap: anywhere; }
.customer-card .spellings li { padding: 0.125rem 0; }
#sheet .customer-card { padding-bottom: 0; }
#sheet .customer-card .sheet-foot { margin-top: 0.5rem; }
@media not all and (min-width: 760px) { #sheet:has(.customer-card) { width: calc(100vw - 2rem); height: fit-content; max-height: calc(100dvh - 2rem); margin: auto; border: 1px solid var(--control); border-radius: var(--radius-lg); } #sheet .customer-card .sheet-foot { margin-top: 0.5rem; margin-inline: calc(-1 * var(--space-3)); } #sheet .customer-card .sheet-head { padding-right: 2.5rem; } }
@media not all and (min-width: 760px) { /* the phone: the lines are cards of a line id and category, the description, then five labelled figures */
  .sheetbody { padding: 0.75rem var(--space-3); }
  .sheetbody .sheet-head { padding-right: 9.5rem; }
  .sheetbody .invoice-lines, .sheetbody .invoice-lines tbody { display: block; }
  .sheetbody .invoice-lines thead { display: none; }
  .sheetbody .invoice-lines tr { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.125rem 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid var(--rule); }
  .sheetbody .invoice-lines td { display: block; padding: 0; border: 0; min-width: 0; }
  .sheetbody .invoice-lines td:nth-child(1) { grid-column: 1 / 4; }
  .sheetbody .invoice-lines td:nth-child(2) { grid-column: 4 / 6; text-align: right; }
  .sheetbody .invoice-lines td:nth-child(4) { grid-column: 1 / -1; grid-row: 2; }
  .sheetbody .invoice-lines td[data-label]::before { display: block; content: attr(data-label); font-size: 0.6875rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
  .sheetbody .invoice-lines td:nth-child(2)::before { display: none; }
  /* the card is the marked row, not each cell of it: one tint and one bar, with no gaps between the grid's cells */
  .invoice tbody tr.here { padding-left: 0.25rem; background-color: var(--accent-soft); box-shadow: inset 2px 0 0 var(--mark); }
  .invoice tr.here > *, .invoice tr.here > :first-child { background-color: transparent; box-shadow: none; }
}
/* The same sheet as the invoice page's one panel (polish slice 1): no × or Copy in its head to clear, the title the page's h1
   in the popup's mono, its foot a plain row under the original invoice. */
.invoice.panel .sheet-head { padding-right: 0; }
.invoice.panel .sheet-sub { margin: 0.125rem 0 0; font-size: 0.8125rem; color: var(--muted); }
.invoice.panel .table-box { width: 100%; max-height: none; } /* the lines fill the panel and never scroll inside the page */
.invoice.panel .sheet-head h1 { margin: 0; font: 700 1.125rem/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; overflow-wrap: anywhere; }
.invoice.panel .sheet-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); margin: var(--space-3) 0 0; }
.invoice.panel .sheet-foot p { margin: 0 auto 0 0; }
