/* KitchenBASE Handover — phone-first, one-handed, kitchen-floor legible.
 *
 * Themed to the KitchenBASE Design Guidebook (2026):
 *   - yellow #FFE600 is the ONE action signal (primary CTA, active pill,
 *     active nav) — never scattered decoration;
 *   - large fields of ink and off-white carry the structure; muted color
 *     fields replace shadows;
 *   - headlines gain impact through scale and tight leading, not weight;
 *   - panels stay square-ish, buttons are pills (9999px);
 *   - black text on yellow, always; focus = 2px blue ring, 3px offset;
 *   - motion 180ms buttons / 280ms menus; reduced-motion respected;
 *   - AA 4.5:1 small text, ≥44px targets.
 * Type: Inter variable (self-hosted) standing in for Roobert.
 */

@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --yellow: #FFE600;
  --ink: #000000;
  --bright: #FAFAFA;
  --paper: #F2F2F2;
  --text: #3D3D3D;
  --muted: #6E6E6E;          /* guide's #777 nudged to 4.5:1 on bright */
  --line: #E4E4E4;
  --field-edge: #828282;     /* a text field's border: 3:1 or better on paper,
                                sheet, white and the desk ground (WCAG 1.4.11) */
  --acc-blue: #596E98;
  --acc-wine: #93565F;
  --acc-gold: #AF9351;
  --acc-olive: #A98C65;
  --focus: #596E98;
  --radius: 12px;            /* panels squarer than buttons */
  --pill: 9999px;
  --pad: 20px;               /* guide mobile margin */
  --speed: 180ms;            /* buttons */
  --speed-menu: 280ms;       /* sheets, menus */

  /* Redesign foundation (5 Oct 2026): one type scale, a 4-pt spacing scale,
     radii, elevation and control heights. Schedule and catering build on
     these; see the redesign SPEC for where each one is used. */
  --fs-display: 27px;        /* hero h1 */
  --fs-title: 20px;          /* sheet title, section title */
  --fs-head: 17px;           /* card title, group header, step heading */
  --fs-body: 16px;           /* body, values, buttons */
  --fs-sub: 14px;            /* card meta, sheet facts, field labels */
  --fs-meta: 13px;           /* secondary meta, hints */
  --fs-caps: 12px;           /* uppercase section headers (0.07em) */
  --fs-badge: 12px;          /* badges, tags, counts */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s8: 32px; --s10: 40px;
  --r-sm: 8px;
  --r-lg: 16px;
  --r-sheet: 20px;
  --shadow-sheet: 0 -6px 28px rgba(0, 0, 0, 0.16);
  --shadow-bar: 0 -1px 0 var(--line), 0 -8px 20px rgba(0, 0, 0, 0.05);
  --shadow-thumb: 0 1px 2px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
  --h-control: 48px;         /* text field, select, date, time, stepper */
  --h-btn: 52px;             /* full-width button */
  --h-btn-sm: 44px;          /* compact button, chip, segment */
}

/* Times, dates, money, portions and counts line up in columns. */
.tnum { font-variant-numeric: tabular-nums; }

.badge.void { background: #6E6E6E; color: #fff; }

/* Carried to assistive tech, never painted. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

* { box-sizing: border-box; }
/* A double tap is a tap, never a zoom (Ernest, 1 Oct 2026): quick taps on
 * chips and +/- zoomed the page. Pinch zoom stays, for anyone who needs it. */
html, body { margin: 0; padding: 0; touch-action: manipulation; }
/* View as: a yellow bar that stays at the top while the master account sees
   someone else's CrewBASE, so nobody forgets whose screen this is. */
.viewas-bar {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: calc(8px + env(safe-area-inset-top)) var(--pad) 8px;
  background: var(--yellow); color: var(--ink);
  font-size: 14px; font-weight: 700;
}
.viewas-bar .btn { width: auto; flex: none; margin-top: 0; min-height: 36px; padding: 0 18px; background: var(--ink); color: var(--bright); border-color: var(--ink); }
/* Pull-to-refresh reloads the page and loses anything typed. The lists keep
   it; app.js sets .hold-pull only while a sheet is up or the Log form has
   text. On both elements: Chrome reads the root's value, older builds took
   it from body. y only, so a sideways back-swipe is untouched. */
html.hold-pull, html.hold-pull body { overscroll-behavior-y: contain; }
/* Status bar on an iPhone Home Screen app (Ernest, 5 Oct 2026). With
   apple-mobile-web-app-status-bar-style black-translucent, iOS 26 drew a
   light blur over the top of the hero that no CSS removed; without that meta
   it does not (tested on his iPhone with kitchenbase.org/toptest/, a copy of
   this page's top: no meta and "black" were clean, black-translucent was
   not). iOS reads that meta only when the app is added to the Home Screen,
   so index.html has none. The ink root (body and .screen still paint paper
   over all of it, .screen being at least a screen tall) and #sb-fill, a
   fixed full-width ink strip at the top edge, are part of what was tested:
   keep them, and keep #sb-fill hit-testable (no pointer-events: none).
   Nothing tappable sits under it (a sheet is at most 86dvh tall). Below the
   View as bar (60), which paints the top yellow. */
html { background: var(--ink); }
#sb-fill {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  height: env(safe-area-inset-top, 0px);
  background: var(--ink);
}
/* With iOS's own status bar the page starts below it and the inset is 0,
   which would leave #sb-fill 0 px tall, and WebKit skips a box 10 px or
   thinner when it picks the top edge's colour. 12 px more ends where the
   Schedule tabs begin (hero padding 20 - 8); the test ran with it. iOS
   standalone only: Android and desktop never drew the blur. */
@media (display-mode: standalone) {
  @supports (-webkit-touch-callout: none) {
    #sb-fill { height: calc(env(safe-area-inset-top, 0px) + 12px); }
  }
}
body {
  font-family: "Inter", -apple-system, "Helvetica Neue", Roboto, sans-serif;
  font-size: 16px; line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  -webkit-tap-highlight-color: transparent;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

button { font: inherit; cursor: pointer; }
button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, a:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* The licensee list expands inside the form it belongs to, so it gets its own
   scroll rather than pushing the amount field off the screen. */
.picker {
  margin-top: 8px; max-height: 44vh; overflow-y: auto;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 10px;
}
.picker .picklist { margin-top: 8px; }

/* A quotation can be a PDF, which has no thumbnail — the tile says so in
   words rather than showing a broken image frame. */
.mtile.doc {
  display: flex; align-items: center; justify-content: center;
  background: var(--paper); border: 1px solid var(--line);
}
.mtile.doc .doclabel {
  font-size: 12px; font-weight: 750; letter-spacing: 0.08em; color: var(--text);
}
/* Second line inside a picker row: the kitchen a contract names, or the fact
   that it names none. */
.picklist .sub {
  display: block; margin-top: 2px;
  font-size: 12px; font-weight: 500; color: var(--muted);
}

/* ---- layout ------------------------------------------------------------ */
.screen { min-height: 100dvh; padding: var(--pad); padding-bottom: 104px; }
.screen:not(.withnav) { padding-bottom: var(--pad); }
.screen, #nav .nav-inner { max-width: 560px; margin-inline: auto; }
@media (min-width: 1024px) { .screen, #nav .nav-inner { max-width: 640px; } }

/* ---- type: scale and tight leading first ------------------------------- */
/* One heading size. The old 26px never rendered (every h1 sits in a hero),
   and 27 vs 28 is a 3.7% step — below what anyone can perceive as a level,
   so it read as drift. Login jumps a real step instead, once per session. */
h1 { font-size: 27px; line-height: 1.08; font-weight: 750; letter-spacing: -0.015em; margin: 0; }
h2 { font-size: 20px; line-height: 1.15; font-weight: 700; letter-spacing: -0.01em; margin: 12px 0 8px; }
label { display: block; margin: var(--s5) 0 6px; font-weight: 650; font-size: var(--fs-sub); line-height: 1.35; color: var(--ink); }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.center { text-align: center; }
.bigmsg { font-size: 20px; line-height: 1.2; font-weight: 700; letter-spacing: -0.01em; text-align: center; margin: 28px 12px 12px; }

/* ---- inputs ------------------------------------------------------------ */
/* The border is the only edge a white field has on the off-white page:
   --line measured 1.14:1 there, and an empty field without its placeholder
   (or with it read as filled in) could not be told from the page. */
input, textarea, select {
  width: 100%; min-height: var(--h-control); padding: 10.5px 16px; font: inherit;
  border: 1.5px solid var(--field-edge); border-radius: var(--radius);
  background: #fff; color: var(--ink);
  transition: border-color var(--speed) ease;
}
input::placeholder, textarea::placeholder { color: var(--muted); }
/* Only drop the outline for pointer focus. :focus-visible has the same
   specificity, so the later `none` used to win and the search box became the
   one control on the page with no ring. */
input:focus, textarea:focus, select:focus { border-color: var(--ink); }
input:focus:not(:focus-visible), textarea:focus:not(:focus-visible),
select:focus:not(:focus-visible) { outline: none; }
input.pin {
  padding: 13px 16px;
  font-size: 30px; font-weight: 700; letter-spacing: 16px;
  font-variant-numeric: tabular-nums;
  text-align: center; max-width: 240px;
  display: block; margin: 8px auto;
}
/* iOS draws a date or time field in its own box: an empty one collapses to a
   sliver and a filled one centres its value. Same height and alignment as
   every other field here (--h-control: 16px x 1.5 line + 21px padding + 3px
   border = 48px). The engine pads its own date parts 1px top and bottom, which
   measured 55px beside a 53px text field until that padding went. Time
   fields (arranging a cleaning) are the same control and need the same. */
input[type="date"], input[type="time"] {
  -webkit-appearance: none; appearance: none;
  display: block; min-height: var(--h-control); text-align: left;
}
input[type="date"]::-webkit-date-and-time-value,
input[type="time"]::-webkit-date-and-time-value { text-align: left; }
input[type="date"]::-webkit-datetime-edit-fields-wrapper,
input[type="time"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }
/* A list to choose from (the schedule names). The engine's own select is a
   grey pill on iOS and something else on Android; this is the same 48px
   field as the inputs, with a chevron that says it opens. Until a choice
   is made it reads like a placeholder; the options keep the ink colour. */
select {
  -webkit-appearance: none; appearance: none;
  display: block; min-height: var(--h-control); padding-right: 44px;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5l6 6 6-6' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 18px center;
}
select.unset { color: var(--muted); }
select option { color: var(--ink); }
/* The typed name under the list sits with it, not a field apart. */
select + input { margin-top: 8px; }

/* ---- buttons: pills; yellow = the action signal ------------------------- */
.btn {
  display: block; width: 100%; min-height: var(--h-btn); margin-top: var(--s4);
  font-size: var(--fs-body); font-weight: 650; letter-spacing: -0.005em;
  border-radius: var(--pill); border: 1.5px solid var(--ink);
  background: #fff; color: var(--ink);
  transition: background var(--speed) ease, transform var(--speed) ease;
}
.btn:hover { background: var(--paper); }
.btn.primary { background: var(--yellow); border-color: var(--yellow); color: var(--ink); }
.btn.primary:hover { background: #F5DE00; }
.btn.ghost { border-color: var(--line); background: none; }
.btn.ghost:hover { background: rgba(0, 0, 0, 0.04); }
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn:disabled { opacity: 0.45; cursor: default; transform: none; }
/* Compact: an inline action beside text or in a row of its own kind. */
.btn.sm { width: auto; min-height: var(--h-btn-sm); padding: 0 18px; font-size: 15px; }

.linkbtn, .linkback {
  border: 0; background: none; color: var(--ink); text-decoration: underline;
  text-underline-offset: 3px; padding: 10px 0; min-height: 48px; font-weight: 600;
  transition: opacity var(--speed) ease;
}
.linkbtn:hover, .linkback:hover { opacity: 0.7; }
.linkback { text-decoration: none; }
.linkback::before { content: "‹ "; }

/* ---- registration approvals (managers only) ----------------------------- */
/* The banner reads as a task, not an alarm: gold accent, ink text, one line.
   It sits with the stat tiles and is the only control of its kind. */
.approvals {
  display: block; width: 100%; margin: 10px 0 0;
  padding: 13px 16px; text-align: left;
  background: #fff; color: var(--ink);
  border: 1.5px solid var(--acc-gold); border-radius: var(--radius);
  font-size: 14.5px; font-weight: 650;
  transition: background var(--speed) ease;
}
.approvals:hover { background: var(--paper); }
/* One ask, then it goes away. Ink border: it is a decision, not an alarm. */
.pushcard {
  margin: 10px 0 0; padding: 14px 16px;
  background: #fff; border: 1.5px solid var(--ink); border-radius: var(--radius);
}
.pushcard-t { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.pushcard .muted { margin-top: 6px; }
.pushcard-acts { display: flex; gap: 8px; margin-top: 10px; }
.pushcard-acts .btn { width: auto; min-height: 44px; margin-top: 0; padding: 0 18px; font-size: 14.5px; }

/* Nobody waiting: the entry stays, the colour goes. */
.approvals.quiet {
  border-color: var(--line); color: var(--muted); font-weight: 600;
}
.appr-list { margin-top: 6px; }
.appr-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.appr-row:last-child { border-bottom: 0; }
.appr-info { flex: 1; min-width: 0; }
.appr-name { margin: 0; font-size: 15px; font-weight: 700; overflow-wrap: anywhere; }
.appr-acts { display: flex; gap: 8px; flex: none; }
.appr-acts .btn {
  width: auto; min-height: 44px; margin-top: 0;
  padding: 0 16px; font-size: 14px;
}

/* ---- hero header: a large ink field ------------------------------------- */
.hero-head {
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 0;
  padding: calc(var(--pad) + env(safe-area-inset-top)) var(--pad) 40px;
  background: var(--ink);
  color: var(--bright);
}
.hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
/* Today's date is context, not an action. It used to be yellow, which put
   three yellow marks in the first viewport — date, active site chip,
   active nav — and a signal that appears three times signals nothing. */
.hero-date {
  margin: 0 0 6px; font-size: 12.5px; font-weight: 650;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.hero-head h1 { color: #fff; }
.hero-head h1 .hello {
  display: block; font-size: 15px; font-weight: 500; letter-spacing: 0;
  color: rgba(255, 255, 255, 0.72); margin-bottom: 3px;
}
/* A name is never cut off with an ellipsis (LAB.md). One too long for the
   line wraps between its words; only a single word wider than the line
   breaks inside itself. */
.hero-head h1 .gname { display: block; overflow-wrap: anywhere; }
.hero-head #greet-sub, .hero-head .hero-sub {
  margin: 6px 0 0; font-size: 13.5px; color: rgba(255, 255, 255, 0.72);
}
/* A manager's own sites fill the chip row, so All lives here instead:
   13.5px to the eye, 44px to the thumb. The negative margin keeps the
   subtitle on the same baseline it had as plain text. */
.hero-head #greet-sub .sublink {
  border: 0; background: none; font: inherit; font-weight: 650;
  color: rgba(255, 255, 255, 0.92);
  text-decoration: underline; text-underline-offset: 3px;
  padding: 13px 6px; margin: -13px -6px; min-height: 44px;
}
.hero-head #greet-sub .sublink:hover { color: #fff; }
.hero-head.tight { padding-bottom: 18px; margin-bottom: 8px; }
.hero-head.tight .hero-chips { margin-top: 12px; }
.hero-head .who { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.hero-head .avatar { width: 42px; height: 42px; font-size: 15px; }
/* Small to the eye, full-size to the thumb: the visible link stays 12.5px
   but the tappable box is 44px tall (negative margin keeps the layout as
   if it were still 2px padding). It sits alone at the hero edge, so the
   oversized hit area cannot overlap a neighbour. */
.hero-head .linkbtn { color: rgba(255, 255, 255, 0.8); font-size: 12.5px;
  padding: 12px 0 12px 12px; margin: -10px 0 -10px -12px; min-height: 44px;
  white-space: nowrap; }
.hero-head .linkbtn:hover { color: #fff; opacity: 1; }
/* View as under Log out (master account only): the two enlarged hit areas
   must not overlap, or a tap on the bottom of "Log out" opens View as. */
.hero-head .who .linkbtn + .linkbtn { margin-top: 8px; }
/* The site row never scrolls and never wraps: it holds the sites this
   person actually works at, and renderSiteChips moves the rest into a
   sheet. Tighter than a normal chip (13px, not 18px) so five sites plus
   the overflow control clear 335px on a 375px phone — the narrowest chip,
   "S1", still measures 45x44px. Scoped to .hero-chips because the plain
   .chip is shared with urgency, the segmented control, register, the
   handover name list and the update sheet. */
/* .chips is declared further down this file with wrap and an 8px gap, and
   it matches at the same specificity — so this must be .chips.hero-chips
   or the later rule silently wins and the row goes back to wrapping. */
.chips.hero-chips { margin-top: 16px; flex-wrap: nowrap; gap: 6px; }
/* A person with one site gets no row at all; without this the hero keeps
   16px of margin and a 44px gap where the control would have been. */
.chips.hero-chips:empty { display: none; }
/* Today's stat tiles float 24px up into the ink field. With a chip row above
   them that leaves 82px under the greeting; without one it left 16px, and
   the tiles crowded the line they are meant to hang below. The other heroes
   are .tight and sit above a form, so they keep their own spacing. */
.hero-head.norow:not(.tight) { padding-bottom: 56px; }
.hero-chips .chip {
  /* 0.28 measured 2.27:1 against the ink field — under the 3:1 WCAG asks
     for a control's visual boundary, and this outline is the only thing
     saying "tappable" on a black hero. 0.40 measures 4.02:1. */
  background: transparent; border-color: rgba(255, 255, 255, 0.40);
  color: rgba(255, 255, 255, 0.85); min-height: 44px; padding: 9px 13px;
  /* Never shrink: renderSiteChips measures these widths to decide what
     fits, and a flex item squeezed by its own overflow measures short. */
  flex: 0 0 auto;
}
/* How many sites a person has is an accident of their job, so a fixed chip
   width leaves four sites stranded beside a third of an empty row while
   five sit shoulder to shoulder. Once the fit is decided, the site chips
   share out whatever is left and the row reads as one deliberate band at
   any count. Applied after measuring, never during. Capped, because two
   sites would otherwise stretch to 138px each and the active one is
   yellow — that much of the action colour for a passive state marker
   shouts louder than the button it is supposed to lose to. */
.chips.hero-chips.fill .chip { flex: 1 0 auto; max-width: 120px; }
.chips.hero-chips.fill .chip.more-chip { flex: 0 0 auto; }
/* The overflow control is a peer, not a site: quieter until touched. Three
   dots are narrower than any site code, so it carries its own floor —
   without it the one control everyone needs is the one under 44px. */
.hero-chips .chip.more-chip {
  color: rgba(255, 255, 255, 0.6); padding: 9px 11px;
  min-width: 44px;
}
.hero-chips .chip.more-chip:hover { color: #fff; }
.hero-chips .chip:hover { border-color: #fff; color: #fff; }
.hero-chips .chip.on {
  background: var(--yellow); border-color: var(--yellow); color: var(--ink);
}

/* stat tiles float over the ink field's edge */
.stats { display: flex; gap: 8px; margin: 8px 0 4px; }
.stats.float { margin-top: -24px; position: relative; z-index: 2; }
.stat {
  flex: 1; background: var(--bright);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 6px 10px; text-align: center;
}
.stat .num {
  display: block; font-size: 24px; font-weight: 750; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.stat .lbl { display: block; font-size: 12px; font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); margin-top: 4px; }
.stats .stat { min-width: 0; }
.stat .num.long { font-size: 19px; line-height: 1.35; overflow-wrap: anywhere; }
.stat.s-stale .num { color: var(--acc-wine); }
.stat.s-undated .num { color: var(--acc-blue); }
/* The old #8A8A8A measured 3.31:1 on the tile. At 24px that is WCAG "large"
   text, so it did pass AA-large — this is a tightening to the 4.5:1 small-text
   bar, not the repair of a failure. The zero stays subordinate by weight
   (650 against the live figures' 750), not by dropping contrast. */
.stat.zero .num { color: var(--muted); font-weight: 650; }

/* ---- toolbar: pill search ------------------------------------------------ */
.toolbar { margin: 16px 0 4px; }
.searchwrap { position: relative; }
.searchwrap svg {
  position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; color: var(--muted); pointer-events: none;
}
.searchwrap input { padding-left: 44px; border-radius: var(--pill); background: #fff; }

/* ---- chips --------------------------------------------------------------- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; }
.chip {
  min-height: 48px; padding: 9px 18px; border-radius: var(--pill);
  border: 1.5px solid var(--line); background: #fff;
  font-size: 15px; font-weight: 600; color: var(--text); white-space: nowrap;
  transition: background var(--speed) ease, border-color var(--speed) ease, color var(--speed) ease;
}
.chip:hover { border-color: var(--ink); color: var(--ink); }
.chip.on { background: var(--ink); border-color: var(--ink); color: var(--bright); }

/* segmented control: one joined field */
.chips.seg { gap: 0; background: #E8E8E8; border-radius: var(--pill); padding: 3px; width: max-content; max-width: 100%; }
.chips.seg .chip { border: 0; background: none; border-radius: var(--pill); min-height: var(--h-btn-sm); font-weight: 650; }
.chips.seg .chip.on { background: var(--ink); color: var(--bright); box-shadow: var(--shadow-thumb); }

/* DN/CN and Quotations keep the pill switcher they had before the Schedule
   redesign (5 Oct 2026): the tab strip below is the Schedule's alone
   (.sched-tabs), and these two screens are not part of that redesign. */
.hero-head .chips.sched-segs {
  background: rgba(255, 255, 255, 0.14); margin-bottom: 14px;
  display: flex; flex-wrap: nowrap; width: max-content; max-width: 100%;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
}
.hero-head .chips.sched-segs::-webkit-scrollbar { display: none; }
.hero-head .chips.sched-segs.more-r {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
}
.hero-head .chips.sched-segs.more-l {
  -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent);
          mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent);
}
.hero-head .chips.sched-segs.more-l.more-r {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent);
          mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent);
}
.hero-head .chips.sched-segs .chip {
  flex: 0 0 auto; padding-left: 14px; padding-right: 14px;
  display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
}
/* Inside the pill, so a scroll container can never cut the ring off. */
.hero-head .chips.sched-segs .chip:focus-visible { outline-offset: -4px; }
.hero-head .chips.sched-segs .chip .segn { margin-left: 7px; }
@media (max-width: 360px) { .hero-head .chips.sched-segs .chip { font-size: 13.5px; padding-left: 12px; padding-right: 12px; } }
.hero-head .chips.sched-segs .chip { color: rgba(255, 255, 255, 0.85); }
.hero-head .chips.sched-segs .chip:hover { color: #fff; }
.hero-head .chips.sched-segs .chip.on,
.hero-head .chips.sched-segs .chip.on:hover { background: var(--bright); color: var(--ink); }

/* Schedule: Moves, Cleaning, Maintenance, Catering and Checklists share one
   tab (redesign, 5 Oct 2026). The switcher is the hero's tab strip: text
   tabs on the ink field with a white bar under the one on screen, so it
   reads as navigation and never competes with the yellow site chip below.
   On a phone the strip runs edge to edge and scrolls: a tab cut by the
   screen's edge is how a native tab bar says "more this way", where a pill
   cut inside a rounded track read as broken. drawSchedSegs scrolls the one
   on screen into the middle (no scroll snapping: a snap point re-aligned the
   row after a redraw and cut the tab on screen), a fade marks only an edge
   that has more, and
   where all five fit (a desk) they share the width. The count sits inside
   its tab: a scroll container clips whatever hangs off it. */
.hero-head .chips.sched-segs.sched-tabs {
  display: flex; flex-wrap: nowrap; gap: 0;
  width: auto; max-width: none;
  margin: calc(var(--s2) * -1) calc(var(--pad) * -1) var(--s4);
  padding: 0 calc(var(--pad) - var(--s3));
  background: none; border-radius: 0;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.16);
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
}
.hero-head .chips.sched-segs.sched-tabs::-webkit-scrollbar { display: none; }
.hero-head .chips.sched-segs.sched-tabs.more-r {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent);
}
.hero-head .chips.sched-segs.sched-tabs.more-l {
  -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 44px), transparent);
          mask-image: linear-gradient(to left, #000 calc(100% - 44px), transparent);
}
.hero-head .chips.sched-segs.sched-tabs.more-l.more-r {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 44px, #000 calc(100% - 44px), transparent);
          mask-image: linear-gradient(to right, transparent, #000 44px, #000 calc(100% - 44px), transparent);
}
.hero-head .chips.sched-segs.sched-tabs .chip {
  position: relative; flex: 1 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--h-btn-sm); padding: 0 var(--s3);
  border: 0; border-radius: 0; background: none; box-shadow: none;
  font-size: var(--fs-sub); font-weight: 650; letter-spacing: 0; white-space: nowrap;
  color: rgba(255, 255, 255, 0.66);
}
/* The bar under the tab on screen: inset to the label's own width. */
.hero-head .chips.sched-segs.sched-tabs .chip::after {
  content: ""; position: absolute; left: var(--s3); right: var(--s3); bottom: 0;
  height: 3px; border-radius: 3px 3px 0 0; background: transparent;
  transition: background var(--speed) ease;
}
/* Inside the tab, so a scroll container can never cut the ring off. */
.hero-head .chips.sched-segs.sched-tabs .chip:focus-visible { outline-offset: -4px; }
.hero-head .chips.sched-segs.sched-tabs .chip:hover { color: #fff; border: 0; }
.hero-head .chips.sched-segs.sched-tabs .chip.on,
.hero-head .chips.sched-segs.sched-tabs .chip.on:hover { background: none; box-shadow: none; color: #fff; }
.hero-head .chips.sched-segs.sched-tabs .chip.on::after { background: var(--bright); }
.hero-head .chips.sched-segs.sched-tabs .chip .segn {
  margin-left: 6px; min-width: 20px; padding: 0 6px; line-height: 20px; font-size: var(--fs-badge);
}
/* A count that is news rather than work: a quiet field on the ink. */
.hero-head .chips.sched-segs.sched-tabs .chip .segn.quiet { background: rgba(255, 255, 255, 0.2); color: #fff; }
/* A desk is wide enough for all five: no bleed past the hero's own edge. */
@media (min-width: 900px) and (min-height: 600px) {
  .hero-head .chips.sched-segs.sched-tabs { margin-inline: calc(var(--s3) * -1); padding-inline: 0; }
}
/* The schedule's heroes: the tab strip, the title, one line on what the list
   is, then the sites. */
:is(#scr-moves, #scr-cleaning, #scr-maint, #scr-kitchen, #scr-catering) .hero-head .hero-sub {
  margin-top: var(--s2); font-size: var(--fs-sub); line-height: 1.45; text-wrap: pretty;
}
/* A two-line title breaks between words, never after "move-" with "outs"
   left alone on the second line (280 px). */
:is(#scr-moves, #scr-cleaning, #scr-maint, #scr-kitchen, #scr-catering) .hero-head h1 { text-wrap: balance; }
.mt-act { margin-top: 10px; min-height: 44px; }   /* compact, not under the 44px floor */
.mt-problems { margin: 4px 0 10px; }
.chip .segn {
  display: inline-block; margin-left: 7px; min-width: 20px; padding: 0 7px;
  border-radius: var(--pill); background: var(--acc-wine); color: #fff;
  font-size: 12px; font-weight: 700; line-height: 20px; text-align: center;
  font-variant-numeric: tabular-nums;
}
/* A count that is news rather than work (everyone else's catering orders
   this week): grey, not the alarm colour. */
.chip .segn.quiet { background: #D9D9D9; color: var(--ink); }
/* Something under Schedule needs someone: a dot on the tab itself. */
#nav button { position: relative; }
#nav button.alert::after {
  content: ""; position: absolute; top: 10px; left: calc(50% + 7px);
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--acc-wine); box-shadow: 0 0 0 2px var(--bright);
}
@media (min-width: 900px) and (min-height: 600px) {
  #nav button.alert::after { top: 7px; left: 25px; box-shadow: 0 0 0 2px var(--ink); }
}

/* ---- login: ink hero + off-white sheet ----------------------------------- */
.screen.login { padding: 0; display: flex; flex-direction: column; }
.login-hero {
  padding: calc(48px + env(safe-area-inset-top)) 24px 34px;
  text-align: center; color: var(--bright);
  background: var(--ink);
}
.login-logo {
  width: 76px; height: 76px; margin: 0 auto 16px; display: block;
  border-radius: 20px;
}
.login-hero h1 { color: #fff; font-size: 32px; }
/* Same reason as .hero-date: a standing subtitle is not something you can
   press, so it must not wear the colour of the thing you press. */
.login-sub {
  margin: 6px 0 0; font-size: 13px; font-weight: 650;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.login-by {
  margin: 10px 0 0; font-size: 12px; font-weight: 550;
  color: rgba(255, 255, 255, 0.55);
}
#login-install { margin: 0 2px 16px; }
.login-card {
  flex: 1; margin-top: -18px; position: relative; z-index: 2;
  background: var(--paper); border-radius: 24px 24px 0 0;
  padding: 24px var(--pad) calc(24px + env(safe-area-inset-bottom));
}
.field-label {
  font-size: 12.5px; font-weight: 650; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--muted); margin: 4px 0 10px;
}

.namelist { list-style: none; margin: 12px 0; padding: 0; }
.namelist button {
  width: 100%; min-height: 56px; padding: 8px 16px; margin-bottom: 8px;
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bright); font-size: 16.5px; font-weight: 600;
  transition: border-color var(--speed) ease, background var(--speed) ease;
}
.namelist button:hover { border-color: var(--ink); background: #fff; }
.namelist .tag { margin-left: auto; font-size: 12px; font-weight: 650; color: var(--muted); letter-spacing: 0.02em; }

/* "Continue as" — the shortcut past the name list. The first row is the one
 * a personal phone will always show, so it carries the weight; the other two
 * exist for a tablet that gets passed around and stay quieter. */
.recentlist { list-style: none; margin: 10px 0 22px; padding: 0; }
.recentlist li { position: relative; margin-bottom: 8px; }
.recentlist button.recent {
  width: 100%; min-height: 60px; padding: 10px 46px 10px 14px;
  display: flex; align-items: center; gap: 12px; text-align: left;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bright);
  transition: border-color var(--speed) ease, background var(--speed) ease;
}
.recentlist button.recent:hover { border-color: var(--ink); background: #fff; }
.recentlist li.lead button.recent { min-height: 68px; border-color: #D4D4D4; }
.recent-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* The name wraps, never ends in "...": two colleagues on a shared tablet
   can share a first name and differ only at the end. */
.recent-name {
  font-size: 16.5px; font-weight: 700; color: var(--ink);
  overflow-wrap: anywhere;
}
.recentlist li.lead .recent-name { font-size: 18px; }
.recent-meta {
  font-size: 12.5px; font-weight: 550; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Its own button, outside the tappable card, so a thumb aiming at the name
 * can never forget the person by accident. */
.recent-x {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border: 0; background: none; color: var(--muted); border-radius: 50%;
  transition: color var(--speed) ease, background var(--speed) ease;
}
.recent-x svg { width: 17px; height: 17px; }
.recent-x:hover { color: var(--ink); background: var(--paper); }

/* Neutral by default. Yellow is this app's one action signal, and a roster
   of a dozen yellow discs spends it on nothing — every row shouted equally,
   so no row said anything. The only yellow avatar left is the first
   "Continue as" card, which is the thing the person almost certainly came
   to tap. */
.avatar {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  background: #E8E8E8; color: var(--text);
  font-size: 13.5px; font-weight: 700; letter-spacing: 0.01em;
  display: flex; align-items: center; justify-content: center;
}
.recentlist li.lead .avatar { background: var(--yellow); color: var(--ink); }

/* ---- cards: flat panels, accent edge, no shadows -------------------------- */
.cards { list-style: none; margin: 10px 0; padding: 0; }
.cards li { margin-bottom: 8px; }
.card {
  width: 100%; text-align: left; display: block; position: relative;
  background: var(--bright); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px 14px 19px;
  overflow: hidden;
  transition: border-color var(--speed) ease, transform var(--speed) ease;
}
.card::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 4px;
  background: var(--accent, transparent);
}
.card.acc-fresh   { --accent: #C9C9C9; }
.card.acc-warn    { --accent: var(--acc-gold); }
.card.acc-stale   { --accent: var(--acc-wine); }
.card.acc-undated { --accent: var(--acc-blue); }
.card.acc-hold    { --accent: var(--acc-olive); }
/* A handover note: every other accent means age, deadline or hold, and a
   note has none of those. Ink says "read this", not "this is late". */
.card.acc-note    { --accent: var(--ink); }
/* The note text is the whole card and is never cut short. */
.card.acc-note .title { overflow-wrap: anywhere; }
button.card:hover { border-color: var(--ink); }
button.card:active { transform: scale(0.99); }

.row1 { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.loc-meta { color: var(--muted); font-size: 12.5px; font-weight: 650; letter-spacing: 0.03em; }
/* A long unbroken token (a URL, a serial number, a key held down) wraps: the
   card is overflow:hidden and used to cut it off without a sign. */
.card .title { margin: 0 0 6px; font-size: 17px; font-weight: 700; line-height: 1.3; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.card .last {
  color: var(--muted); font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card .last .by { color: var(--text); font-weight: 650; }

/* badges: muted color fields; black on gold/olive, white on wine/blue ------- */
.badge {
  margin-left: auto; padding: 4px 12px; border-radius: var(--pill);
  font-size: 12.5px; font-weight: 700; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.badge.fresh   { background: var(--paper); color: var(--text); }
.badge.warn    { background: var(--acc-gold); color: var(--ink); }
.badge.stale   { background: var(--acc-wine); color: #fff; }
.badge.undated { background: var(--acc-blue); color: #fff; }
.badge.hold    { background: var(--acc-olive); color: var(--ink); }
/* "Until 20 Sep" on a note is a date, not a warning: the quiet field. */
.badge.note    { background: var(--paper); color: var(--text); }
.mine, .cardmeta { font-size: 12px; font-weight: 600; color: var(--muted); margin-top: 5px; }

/* skeleton loading */
.skel {
  height: 96px; border-radius: var(--radius); margin-bottom: 8px;
  background: linear-gradient(100deg, #E6E6E6 40%, #F0F0F0 50%, #E6E6E6 60%);
  background-size: 200% 100%;
  animation: shimmer 1.4s infinite linear;
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* empty state */
.empty { text-align: center; margin: var(--s10) var(--s4); color: var(--muted); font-size: var(--fs-sub); line-height: 1.45; }
.empty svg {
  display: block; width: 72px; height: 72px; margin: 0 auto var(--s3); padding: 18px;
  border-radius: 50%; background: #EAEAEA; color: var(--ink);
}

/* ---- bottom navigation ------------------------------------------------------ */
#nav {
  position: fixed; inset: auto 0 0 0; z-index: 20;
  background: var(--bright);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
#nav[hidden] { display: none; }
/* The nav is fixed over the foot of the page, and over the foot of what is
   left above the keyboard while one is up, so a field scrolled into view
   could land underneath it (WCAG 2.2 "Focus Not Obscured"). Reserve its
   height: 64px buttons, a 1px top border and 10px to spare. */
html { scroll-padding-bottom: calc(75px + env(safe-area-inset-bottom)); }
#nav button[hidden] { display: none; }
#nav .nav-inner { display: flex; }
#nav button {
  flex: 1; min-height: 64px; border: 0; background: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.01em; color: var(--muted);
  transition: color var(--speed) ease;
}
#nav button svg { width: 22px; height: 22px; }
#nav button:hover { color: var(--ink); }
#nav button span:last-child { padding: 2px 12px; border-radius: var(--pill); transition: background var(--speed) ease; }
#nav button.on { color: var(--ink); font-weight: 700; }
#nav button.on span:last-child { background: var(--yellow); }

/* ---- bottom sheet ------------------------------------------------------------ */
/* A drag that starts on the backdrop, or runs past the end of the sheet's
   own scroll, must not move the list underneath. A tap still closes. */
#sheet-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.55); z-index: 30; cursor: pointer; touch-action: none; }
#sheet {
  position: fixed; inset: auto 0 0 0; z-index: 31;
  max-height: 86dvh; overflow-y: auto; overscroll-behavior: contain;
  overflow-wrap: anywhere;   /* the same token in a title or trail: no sideways scroll */
  background: var(--bright); border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  box-shadow: var(--shadow-sheet);
  padding: 16px var(--pad) calc(18px + env(safe-area-inset-bottom));
}
/* The sheet takes focus so a screen reader starts at its title; it is not a
   control, so it draws no ring of its own. Its controls keep theirs. */
#sheet:focus { outline: none; }
/* A grabber says "this is a sheet over the page", as a native one does. */
#sheet::before {
  content: ""; display: block; width: 36px; height: 5px; margin: -6px auto 12px;
  border-radius: var(--pill); background: #D2D2D2;
}
/* Close, appended to every sheet by openSheet: the quiet last row, never a
   peer of the sheet's own actions. */
#sheet > .btn.ghost:last-child { border-color: transparent; color: var(--text); font-weight: 600; margin-top: var(--s3); }
#sheet > .btn.ghost:last-child:hover { background: rgba(0, 0, 0, 0.04); color: var(--ink); }
@media (min-width: 768px) {
  #sheet { max-width: 560px; margin-inline: auto; border-radius: var(--r-sheet); inset: auto 0 4vh 0; }
  #sheet::before { display: none; }
}
#sheet h2 { margin-top: 0; font-size: var(--fs-title); line-height: 1.2; }
#sheet .trail {
  background: var(--paper); border-radius: var(--radius);
  padding: 12px 14px; margin: 8px 0;
  font-size: 13.5px; line-height: 1.55; color: var(--text);
  font-variant-numeric: tabular-nums;
}
#sheet .trail p { margin: 4px 0; }
#sheet .actions { display: flex; gap: 10px; }
#sheet .actions .btn { flex: 1; white-space: nowrap; }
/* One line in the pill, cut with an ellipsis rather than running past it. */
.btn.hist-btn { padding: 0 18px; min-width: 0; }
.btn-label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Three pills need a 351 px screen. Narrower, Update takes its own row and the
   other two share the next, instead of wrapping "Hand over" or clipping
   "Complete". */
@media (max-width: 360px) {
  #sheet .actions:has(> .btn:nth-child(3)) { flex-wrap: wrap; row-gap: 0; }
  #sheet .actions:has(> .btn:nth-child(3)) > .btn:first-child { flex-basis: 100%; }
}
/* A licensee issue's "Mark in progress" and "Mark resolved" need 286 px side
   by side. Where they do not fit (no pill shrinks below its words), each
   takes a row of its own; where they do, they share it equally. */
#sheet .actions.kb-acts { flex-wrap: wrap; row-gap: 0; }
/* A cleaning request's sheet: Arrange (or Move), the one primary, takes the
   full width; Cancel and Turn down share the row under it at every width,
   so "Cancel request" never presses against its pill's ends. */
#sheet .actions.cl-acts { flex-wrap: wrap; row-gap: 0; }
#sheet .actions.cl-acts > .btn.primary { flex-basis: 100%; }

/* The title, and when its wording can still be fixed, a quiet pencil beside it. */
.title-row { display: flex; align-items: flex-start; gap: 8px; }
.title-row h2 { flex: 1; min-width: 0; }
.title-edit {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  min-height: 44px; margin: -9px -8px 0 0; padding: 0 8px;
  border: 0; border-radius: var(--pill); background: none;
  color: var(--muted); font-size: 14px; font-weight: 650; cursor: pointer;
}
.title-edit svg { width: 16px; height: 16px; }
.title-edit:hover { color: var(--ink); }

/* ---- toast --------------------------------------------------------------------- */
/* width:max-content, or left:50% leaves shrink-to-fit only half the screen
   and max-width never comes into it: a long notice wrapped at ~188px. */
#toast {
  position: fixed; left: 50%; bottom: 110px; transform: translateX(-50%);
  z-index: 40; width: max-content; max-width: 88vw;
  background: var(--ink); color: var(--bright);
  font-size: 14.5px; font-weight: 550;
  padding: 12px 20px; border-radius: var(--pill);
}
/* Between messages the live region stays in the page (a hidden one is not
   announced when it reappears) as a box with no size, so nothing shows. */
#toast:empty { padding: 0; }

/* ---- urgency ------------------------------------------------------------------ */
/* One word, one line. A sheet lets text break anywhere (a serial number with
   no spaces), and a pill beside a long place was squeezed to ME / DIU / M. */
.u-tag {
  font-size: 11px; font-weight: 750; letter-spacing: 0.05em;
  text-transform: uppercase; padding: 2px 8px; border-radius: var(--pill);
  white-space: nowrap;
}
.u-tag.u-critical { background: var(--acc-wine); color: #fff; }
.u-tag.u-high     { background: var(--acc-gold); color: var(--ink); }
.u-tag.u-medium   { background: var(--acc-blue); color: #fff; }
.u-tag.u-low      { background: var(--paper); color: var(--text); }
/* Sits where an issue's urgency tag would. Ink, never yellow: it says what
   the row is, not what to press. */
.u-tag.k-note     { background: var(--ink); color: #fff; }

.badge.u-critical { background: var(--acc-wine); color: #fff; }
.badge.u-high     { background: var(--acc-gold); color: var(--ink); }
.badge.u-medium   { background: var(--acc-blue); color: #fff; }
.badge.u-low      { background: var(--paper); color: var(--text); }

.card.acc-u-critical { --accent: var(--acc-wine); }
.card.acc-u-high     { --accent: var(--acc-gold); }
.card.acc-u-medium   { --accent: var(--acc-blue); }
.card.acc-u-low      { --accent: #C9C9C9; }

.chip.u-critical.on { background: var(--acc-wine); border-color: var(--acc-wine); color: #fff; }
.chip.u-high.on     { background: var(--acc-gold); border-color: var(--acc-gold); color: var(--ink); }
.chip.u-medium.on   { background: var(--acc-blue); border-color: var(--acc-blue); color: #fff; }
.chip.u-low.on      { background: var(--ink); border-color: var(--ink); color: var(--bright); }

.u-line { font-weight: 650; font-size: 14px; margin: 4px 0 2px; }
.u-line.u-critical { color: var(--acc-wine); }
.u-line.u-high     { color: #7A6636; }
.u-line.u-medium   { color: var(--acc-blue); }
.u-line.u-low      { color: var(--muted); }

/* ---- location field with a keypad trigger ------------------------------------- */
.locwrap { position: relative; }
.locwrap input { padding-right: 54px; }
.locbtn {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; border: 0; border-radius: 10px;
  background: none; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
  transition: color var(--speed) ease, background var(--speed) ease;
}
.locbtn:hover { color: var(--ink); background: var(--paper); }
.locbtn svg { width: 22px; height: 22px; }

/* kitchen keypad grid (rendered inside the bottom sheet) */
.kgrid {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px;
  margin: 6px 0;
}
.kgrid.sheetgrid { grid-template-columns: repeat(5, 1fr); gap: 8px; margin: 12px 0 4px; }
.kgrid.sheetgrid .kcell { min-height: 50px; font-size: 15.5px; }
.kgrid .kcell {
  min-height: 44px; border: 1.5px solid var(--line); border-radius: 10px;
  background: #fff; font-size: 14.5px; font-weight: 650; color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: background var(--speed) ease, border-color var(--speed) ease;
}
.kgrid .kcell:hover { border-color: var(--ink); color: var(--ink); }
.kgrid .kcell.on { background: var(--ink); border-color: var(--ink); color: var(--bright); }

/* ---- list section headers ------------------------------------------------------ */
.listhead {
  margin: var(--s6) 4px var(--s2); font-size: var(--fs-caps); font-weight: 650; line-height: 1.2;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
/* One quiet line under the Done list: where the older completions are. */
.listfoot { margin: 14px 2px 4px; font-size: 13px; color: var(--muted); }
/* "Coming up (n)": notes that start later stay folded under one line so the
   list leads with what is true today. Reads as a section heading, works as a
   button; the chevron turns when it is open. Focus ring: the global
   button:focus-visible rule. */
.comingup {
  display: flex; align-items: center; gap: 6px;
  width: 100%; min-height: 44px; margin: 0; padding: 0 2px;
  border: 0; background: none; text-align: left;
  font-size: 12px; font-weight: 650;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.comingup:hover { color: var(--ink); }
.comingup svg { width: 16px; height: 16px; flex: none; transition: transform var(--speed) ease; }
.comingup[aria-expanded="true"] svg { transform: rotate(180deg); }

/* freshness dot: something changed here since your last visit */
.newdot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--acc-blue); flex: none;
}

/* attach row on the log form */
.attachrow {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 52px; padding: 13px 16px;
  border: 1.5px dashed var(--line); border-radius: var(--radius);
  background: #fff; color: var(--muted); font-size: 15px; font-weight: 600;
  transition: border-color var(--speed) ease, color var(--speed) ease;
}
.attachrow:hover { border-color: var(--ink); color: var(--ink); }
.attachrow.has { border-style: solid; border-color: var(--ink); color: var(--ink); }
.attachrow svg { width: 20px; height: 20px; flex: none; }

/* media grid in the detail sheet */
.mediagrid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 8px 0;
}
.mtile {
  position: relative; display: block; aspect-ratio: 1;
  border-radius: 10px; overflow: hidden; border: 1px solid var(--line);
  background: var(--paper);
}
.mtile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mtile .playmark {
  position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; font-size: 22px; color: #fff;
  background: rgba(0, 0, 0, 0.55);
}
button.mtile { padding: 0; cursor: pointer; }

/* kitchen history: the same cards as Today, stacked inside a sheet */
.histlist { display: grid; gap: 8px; margin-top: 12px; }

/* ---- photo viewer: over the sheet (31) and the toast (40) -------------------- */
.viewer {
  position: fixed; inset: 0; z-index: 61;   /* above the View as bar: its Close sits where Exit is */
  display: flex; align-items: center; justify-content: center;
  padding: calc(env(safe-area-inset-top) + 76px) 12px calc(env(safe-area-inset-bottom) + 88px);
  background: rgba(0, 0, 0, 0.97);   /* near-solid: the sheet's text must not read through a photo's surround */
}
.viewer img, .viewer video { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 6px; }
.viewer video { width: 100%; background: #000; }
.viewer .btn { width: auto; margin-top: 0; }
.viewer .vclose {
  position: absolute; right: 12px; top: calc(env(safe-area-inset-top) + 12px);
  padding: 0 22px;
}
.viewer .vbar {
  position: absolute; left: 0; right: 0; bottom: calc(env(safe-area-inset-bottom) + 18px);
  display: flex; align-items: center; justify-content: center; gap: 18px;
}
.viewer .vstep { width: 64px; font-size: 26px; line-height: 1; }
.viewer .vcount {
  min-width: 64px; text-align: center; color: #fff;
  font-weight: 650; font-variant-numeric: tabular-nums;
}
.viewer .vstate { position: absolute; margin: 0; color: #fff; font-size: 15px; }

button.addtile {
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; font-weight: 600; color: var(--muted);
  border: 1.5px dashed var(--line); background: #fff; cursor: pointer;
  transition: border-color var(--speed) ease, color var(--speed) ease;
}
button.addtile:hover { border-color: var(--ink); color: var(--ink); }

/* a new cleaning request's own photos: take one back out, or watch it upload.
   The circle is 26px to the eye; a transparent 9px border around it makes
   the button 44px to the thumb. The photo under it is not a control. */
.mtile .rm {
  position: absolute; top: 0; right: 0; width: 44px; height: 44px;
  border: 9px solid transparent; border-radius: 50%; padding: 0; line-height: 26px;
  background: rgba(0, 0, 0, 0.65); background-clip: padding-box;
  color: #fff; font-size: 16px; cursor: pointer;
}
.mtile.busy { opacity: 0.6; }

/* an open cleaning request opens its actions */
.cl-card.tap { cursor: pointer; }
.cl-card.tap:hover { border-color: var(--ink); }

/* ---- catering orders (catering.js) -------------------------------------------- */
/* The card: the move card's date block with its weekday, the order's id,
   what it is, and how much of it has a kitchen. */
.ct-card.tap { cursor: pointer; }
.ct-card.tap:hover { border-color: var(--ink); }
.card[role="button"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.ct-date .wd {
  display: block; margin-bottom: 3px; font-size: 10.5px; font-weight: 650;
  letter-spacing: 0.07em; color: var(--muted);
}
.ct-card .row1 { flex-wrap: wrap; row-gap: 4px; }
.mv-tag.ct-rev { background: #fff; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); white-space: nowrap; }
.ct-cover { margin-top: 8px; }
/* One segment a line, as wide as its portions: solid once the kitchen has
   confirmed, hatched while it has not, outlined while there is none. */
.ct-bar { display: flex; gap: 3px; height: 9px; }
.ct-seg { flex: 1 1 0; min-width: 6px; border-radius: 3px; border: 1.5px solid var(--ink); }
.ct-seg.done { background: var(--ink); }
.ct-seg.held { background: repeating-linear-gradient(135deg, var(--ink) 0 2px, transparent 2px 5px); }
.ct-seg.open { background: transparent; }
.ct-cover-text { margin-top: 5px; font-size: 13px; font-weight: 650; color: var(--text); }
.ct-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ct-chip {
  padding: 3px 9px; border-radius: var(--pill); font-size: 12px; font-weight: 650;
  background: var(--paper); color: var(--text); white-space: nowrap;
}
.ct-chip.halal { background: #fff; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
/* Allergies are outlined in the alert colour and carry an icon and words:
   never colour alone. */
.ct-chip.allergy {
  display: inline-flex; align-items: center; gap: 5px; white-space: normal;
  background: #fff; color: var(--acc-wine); box-shadow: inset 0 0 0 1.5px var(--acc-wine);
}
.ct-chip.allergy svg { width: 14px; height: 14px; flex: none; }
.ct-dayhead { margin: 12px 2px 6px; font-size: 14px; font-weight: 700; color: var(--ink); }
.ct-attn-t { font-size: 15px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.ct-quiet { color: var(--muted); font-weight: 600; text-align: center; }
.ct-card.cl-done .title { color: var(--muted); }

/* One order's sheet */
.ct-sheethead .row1 { flex-wrap: wrap; row-gap: 4px; }
.ct-fact { margin: 4px 0; font-size: 15px; overflow-wrap: anywhere; }
.ct-fact.strong, .ct-sec .strong, .ct-need .strong, .ct-mixed .strong, .ct-closeline .strong { font-weight: 700; }
/* What the shared sheet could not say, and why: a problem, not an aside. */
.ct-fact.fault { color: var(--acc-wine); font-weight: 650; }
.ct-client { font-weight: 650; }
.ct-pre { white-space: pre-wrap; }
.ct-banner {
  margin: 10px 0; padding: 10px 14px; border-radius: var(--radius);
  background: #F4EFDF; box-shadow: inset 4px 0 0 var(--acc-gold);
  font-size: 14px; font-weight: 600; color: var(--ink);
  white-space: pre-line;          /* the change summary is one version a line */
}
.ct-banner.quiet { background: var(--paper); box-shadow: inset 4px 0 0 var(--muted); }
.ct-allergy {
  margin: 12px 0; padding: 12px 14px; border-radius: var(--radius);
  background: #fff; box-shadow: inset 0 0 0 2px var(--acc-wine);
}
.ct-allergy p { margin: 4px 0; }
.ct-allergy-h { display: flex; align-items: center; gap: 8px; font-weight: 750; color: var(--acc-wine); }
.ct-allergy-h svg { width: 18px; height: 18px; flex: none; }
.ct-mixed ul, .ct-need ul { margin: 6px 0 0; padding-left: 20px; }
.ct-mixed li, .ct-need li { margin: 3px 0; }
.btn.ct-maps {
  display: inline-flex; align-items: center; justify-content: center; width: auto;
  min-height: 44px; margin-top: 10px; padding: 0 22px; color: var(--ink); text-decoration: none;
}
.ct-lines { display: grid; gap: 8px; }
.ct-lrow {
  display: block; width: 100%; padding: 12px 14px; text-align: left;
  font: inherit; color: var(--ink); background: #fff;
  border: 1px solid var(--line); border-radius: var(--radius);
}
button.ct-lrow:hover { border-color: var(--ink); }
.ct-lrow.gone { background: var(--paper); color: var(--muted); }
/* The status tag never shrinks, so on a narrow phone it takes a line of its
   own rather than squeezing the title to one letter a line. */
.ct-lrow-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.ct-lrow-top > .u-tag { margin-left: auto; }
.ct-letter {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff; font-size: 13px; font-weight: 750;
}
.ct-lrow-t { flex: 1 1 9em; min-width: 0; font-weight: 700; overflow-wrap: anywhere; }
.ct-lrow-m { margin-top: 4px; font-size: 13.5px; color: var(--text); overflow-wrap: anywhere; }
.ct-lrow-m.late { color: var(--acc-wine); font-weight: 650; }
.ct-hint.late { color: var(--acc-wine); font-weight: 650; }
/* A line a refused booking names, on the Food step it opens. */
.ct-fline.ct-attn { box-shadow: inset 0 0 0 2px var(--acc-wine); }
.ct-fixnote { color: var(--acc-wine); font-weight: 650; }
.ct-foot .ct-savehere { width: 100%; margin: 0 0 10px; }
/* What the server refused a booking for, in its own words. */
.ct-refused { margin: 8px 0 4px; font-size: 16px; line-height: 1.45; overflow-wrap: anywhere; }
.ct-lrow-k { margin-top: 6px; font-size: 14px; font-weight: 650; overflow-wrap: anywhere; }
.ct-lrow-k.none { color: var(--acc-wine); }
.ct-steps { list-style: none; display: flex; flex-wrap: wrap; gap: 4px 6px; margin: 8px 0 2px; padding: 0; }
.ct-steps li { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; color: var(--muted); }
.ct-steps li + li::before { content: "\2192"; margin-right: 1px; }
.ct-steps .dot { width: 10px; height: 10px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--muted); }
.ct-steps li.on { color: var(--ink); }
.ct-steps li.on .dot { background: var(--ink); box-shadow: none; }
.ct-files-h { margin: 8px 0 0; font-size: 13px; font-weight: 650; color: var(--text); }
.ct-kv { display: flex; gap: 10px; margin: 6px 0; font-size: 14px; }
.ct-kv .k { flex: 0 0 38%; color: var(--muted); font-weight: 600; }
.ct-kv .v { flex: 1; min-width: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
.ct-trail {
  list-style: none; margin: 4px 0; padding: 10px 14px;
  background: var(--paper); border-radius: var(--radius); font-size: 13.5px;
}
.ct-trail li { margin: 6px 0; }
.ct-trail-h { display: block; font-size: 12.5px; font-weight: 650; color: var(--muted); }
.ct-trail-t { display: block; overflow-wrap: anywhere; }
.ct-acts .btn { margin-top: 10px; }
.ct-copybox { margin-top: 10px; font-size: 14px; }

/* A line's sheets */
.ct-klist { display: grid; gap: 8px; margin-top: 10px; }
.ct-krow {
  display: block; width: 100%; min-height: 52px; padding: 12px 14px; text-align: left;
  font: inherit; color: var(--ink); background: #fff;
  border: 1.5px solid var(--line); border-radius: var(--radius);
}
.ct-krow:hover { border-color: var(--ink); }
.ct-krow.on { border-color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); }
.ct-krow:disabled { cursor: not-allowed; background: var(--paper); color: var(--muted); }
.ct-krow-t { display: block; font-weight: 700; overflow-wrap: anywhere; }
.ct-krow .sub, .ct-krow-w, .ct-krow-b { display: block; margin-top: 2px; font-size: 12.5px; }
.ct-krow .sub { color: var(--muted); }
.ct-krow-w { color: #7A6636; font-weight: 600; }
.ct-krow-b { color: var(--acc-wine); font-weight: 700; }
/* Who applied in the KitchenBase app: one card each, in queue order. The
   place number never shrinks, and the give buttons wrap their words rather
   than run past a narrow phone's edge. */
.ct-apps { display: grid; gap: 8px; margin-top: 8px; }
.ct-app { padding: 12px 14px; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-app-top { display: flex; align-items: baseline; gap: 8px; }
.ct-app-n { flex: none; font-weight: 750; font-variant-numeric: tabular-nums; }
.ct-app-t { flex: 1 1 auto; min-width: 0; font-weight: 700; overflow-wrap: anywhere; }
.ct-app .sub, .ct-app .ct-krow-w, .ct-app .ct-krow-b { display: block; margin-top: 3px; font-size: 13px; overflow-wrap: anywhere; }
.ct-app .sub { color: var(--muted); }
.ct-app .btn { min-height: 48px; margin-top: 10px; padding: 8px 16px; line-height: 1.25; }
.ct-kb .ct-files-h { margin-top: 14px; }
.ct-cell { margin-top: 8px; }
.ct-consume { margin: 16px 0 4px; font-size: 28px; font-weight: 750; line-height: 1.1; letter-spacing: -0.015em; }
.ct-closeline { margin-top: 12px; padding: 4px 14px 12px; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }

/* ---- catering views, the redesign (5 Oct 2026) ------------------------------------
   The list, an order's sheet and its action sheets on the foundation's tokens.
   Scoped to the catering classes (and #ct-tools), so the move cards and the
   order form these share classes with are left as they are. */

/* New order is the one yellow; Full form a compact secondary beside it. */
#ct-tools { display: flex; align-items: center; gap: var(--s2); margin: var(--s4) 0 0; }
#ct-tools[hidden] { display: none; }
#ct-tools .btn { margin-top: 0; }
#ct-tools .btn.primary { flex: 1 1 auto; min-width: 0; min-height: var(--h-btn); }
#ct-tools .btn.ghost {
  flex: none; width: auto; min-height: var(--h-btn-sm); padding: 0 var(--s4);
  font-size: var(--fs-sub); color: var(--ink); border-color: var(--line); background: #fff;
}
@media (min-width: 768px) { #ct-tools .btn.primary { flex: 0 1 320px; } }

/* Needs attention: one card an order, its issues as rows with a wine dot. */
.card.ct-attn {
  display: grid; grid-template-columns: minmax(0, 1fr) 20px; column-gap: var(--s3); align-items: center;
  padding: var(--s4) var(--s3) var(--s4) calc(var(--s4) + 4px);
}
.ct-attn-o { grid-column: 1; display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.ct-attn-what { min-width: 0; font-size: var(--fs-meta); font-weight: 600; line-height: 1.35; color: var(--muted); }
.ct-attn-list { grid-column: 1; display: grid; gap: var(--s2); margin-top: var(--s3); }
.ct-attn .ct-attn-t {
  position: relative; display: block; padding-left: var(--s4);
  font-size: 15px; font-weight: 650; line-height: 1.35; color: var(--ink);
}
.ct-attn .ct-attn-t::before {
  content: ""; position: absolute; left: 0; top: 0.5em; width: 8px; height: 8px;
  border-radius: 50%; background: var(--acc-wine);
}
.ct-attn-t .nowrap { white-space: nowrap; }
.card.ct-attn > svg { grid-column: 2; grid-row: 1 / span 2; width: 20px; height: 20px; color: var(--muted); }

/* The order card: a 48 px date rail, then the card anatomy. */
.card.ct-card { align-items: stretch; gap: var(--s3); padding: var(--s4) var(--s4) var(--s4) calc(var(--s4) + 2px); }
.card.acc-none { --accent: transparent; }
.ct-card .mv-date.ct-date {
  align-self: stretch; width: 48px; padding: 2px var(--s3) 0 0;
  display: flex; flex-direction: column; align-items: center;
}
.ct-card .ct-date .wd, .ct-card .ct-date .mo {
  margin: 0; font-size: 11px; font-weight: 650; letter-spacing: 0.07em; line-height: 1.2; color: var(--muted);
}
.ct-card .ct-date .d { margin: 3px 0; font-size: var(--fs-title); font-weight: 750; line-height: 1; font-variant-numeric: tabular-nums; }
.ct-card .row1 { gap: 6px; margin-bottom: var(--s2); }
.ct-card .mv-body .title { margin: 0; font-size: var(--fs-head); line-height: 1.3; }
.ct-card .mv-session.none { margin-top: var(--s1); font-size: var(--fs-sub); font-weight: 500; line-height: 1.4; color: var(--muted); font-variant-numeric: tabular-nums; }
.ct-card .ct-cover { margin-top: var(--s3); }
.ct-card .ct-bar, .ct-detail .ct-bar { gap: 2px; height: 6px; }
.ct-bar .ct-seg { min-width: 4px; border: 0; border-radius: var(--pill); background: var(--line); }
.ct-bar .ct-seg.done { background: var(--ink); }
.ct-bar .ct-seg.held { background: repeating-linear-gradient(135deg, var(--ink) 0 2px, var(--line) 2px 4px); }
.ct-cover .ct-cover-text { margin-top: 6px; font-size: var(--fs-meta); font-weight: 600; font-variant-numeric: tabular-nums; }
.ct-card .ct-chips { gap: 6px; margin-top: var(--s3); }
.ct-chips .ct-chip { padding: 3px 10px; border-radius: var(--radius); font-size: var(--fs-badge); line-height: 1.35; white-space: normal; overflow-wrap: anywhere; }
.ct-card .ct-chips + .mv-session.none, .ct-card .ct-cover + .mv-session.none { margin-top: var(--s2); font-size: var(--fs-meta); }
.ct-dayhead { margin: var(--s4) 4px var(--s2); font-size: var(--fs-sub); font-weight: 700; color: var(--ink); }
/* A narrow phone gives the words the card's whole width: the date rail
   becomes one line over the card ("THU 15 OCT"). */
@media (max-width: 340px) {
  .card.ct-card { flex-direction: column; gap: var(--s2); }
  .ct-card .mv-date.ct-date {
    flex-direction: row; align-items: baseline; align-self: flex-start; gap: 6px;
    width: auto; padding: 0; border-right: 0;
  }
  .ct-card .ct-date .d { margin: 0; font-size: var(--fs-sub); font-weight: 700; }
}

/* An order's sheet: id, version and state over the title; the client and
   when it changed as its meta line; then one callout style (white, a 4 px
   edge in its meaning colour), then the facts as grouped lists. */
.ct-sheethead .row1 { gap: 6px; margin-bottom: var(--s3); }
.ct-sheethead .u-tag.u-low { padding: 0 2px; background: none; color: var(--muted); }
.ct-detail { display: flex; flex-direction: column; gap: var(--s3); }
.ct-detail > * { margin-top: 0; margin-bottom: 0; }
.ct-detail > .ct-meta { order: -1; margin-top: calc(var(--s2) * -1); font-size: var(--fs-sub); line-height: 1.45; }
.ct-meta .ct-fact { display: inline; margin: 0; font-size: var(--fs-sub); }
.ct-meta .ct-client { font-weight: 600; color: var(--text); }
.ct-meta .ct-fact + .ct-fact::before { content: "\00a0\00b7\0020"; color: var(--muted); }
.ct-detail .ct-next, .ct-detail .ct-banner, .ct-detail .ct-allergy, .ct-detail .ct-notes {
  margin: 0; padding: var(--s4); background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); font-size: var(--fs-sub); line-height: 1.45; color: var(--ink);
}
.ct-detail .ct-next { box-shadow: inset 4px 0 0 var(--acc-gold); }
.ct-detail .ct-banner { box-shadow: inset 4px 0 0 var(--acc-gold); font-weight: 500; }
.ct-detail .ct-banner.quiet { box-shadow: inset 4px 0 0 var(--muted); }
.ct-detail .ct-allergy { box-shadow: inset 4px 0 0 var(--acc-wine); }
.ct-detail .ct-notes { box-shadow: inset 4px 0 0 var(--acc-gold); }
.ct-next > p, .ct-allergy > p, .ct-notes > p { margin: var(--s1) 0 0; }
.ct-next > p:first-child, .ct-allergy > p:first-child, .ct-notes > p:first-child { margin-top: 0; }
.ct-next > p.strong:first-child, .ct-banner-h, .ct-allergy .ct-allergy-h, .ct-notes > p.strong {
  font-size: var(--fs-body); font-weight: 700; line-height: 1.35;
}
.ct-banner-h { color: var(--ink); }
.ct-allergy .ct-allergy-h { gap: var(--s2); }
.ct-next .ct-next-item { min-height: 44px; padding: var(--s2) 0; font-size: var(--fs-sub); }
.ct-next .btn.primary { margin-top: var(--s3); }
.ct-next .btn.ct-next-see { display: inline-flex; align-items: center; margin-top: var(--s3); }
.ct-next .ct-warns { margin-top: var(--s3); }

.ct-detail .ct-sec .listhead { margin: var(--s3) 4px var(--s2); }
.ct-detail .ct-fact { font-size: var(--fs-sub); line-height: 1.45; }
.ct-facts { padding: 0 var(--s4); background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-facts > * { margin: 0; padding: 10px 0; font-size: var(--fs-sub); line-height: 1.45; font-variant-numeric: tabular-nums; }
.ct-facts > * + :not(.btn):not(.lead) { border-top: 1px solid var(--line); }
.ct-facts > .ct-fact.strong:first-child { padding: 14px 0 var(--s1); font-size: var(--fs-head); font-weight: 700; line-height: 1.3; }
.ct-facts > .ct-fact.strong:first-child:last-child { padding-bottom: 14px; }
.ct-facts > .ct-fact.lead { padding: 0 0 var(--s3); font-size: var(--fs-head); font-weight: 600; color: var(--text); }
.ct-facts > .ct-fact.strong:first-child + :not(.lead) { border-top: 0; padding-top: var(--s1); }
.ct-facts > .ct-kv { display: flex; gap: var(--s3); }
.ct-facts > .ct-kv .k { flex: 0 0 38%; font-size: var(--fs-meta); font-weight: 600; color: var(--muted); }
@media (max-width: 340px) { .ct-facts > .ct-kv { flex-direction: column; gap: 2px; } .ct-facts > .ct-kv .k { flex-basis: auto; } }
.ct-facts > .ct-facts-note { padding: var(--s3) 0; font-size: var(--fs-meta); }
.ct-facts > .btn.ct-maps { display: inline-flex; margin: var(--s1) 0 var(--s3); padding: 0 var(--s4); }

/* Lines: a letter disc, the line, its status on the right; the row that opens
   the line's own sheet ends in a chevron. */
.ct-detail .ct-lines, .ct-kb .ct-apps { gap: var(--s2); }
.ct-lrow { padding: var(--s3) var(--s4); }
button.ct-lrow {
  padding-right: 40px;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='14' viewBox='0 0 8 14'%3E%3Cpath d='M1.5 1.5l5 5.5-5 5.5' fill='none' stroke='%236E6E6E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 16px center;
}
.ct-lrow .ct-lrow-t { font-size: var(--fs-body); line-height: 1.35; }
.ct-lrow-top > .u-tag { text-transform: none; letter-spacing: 0; }
.ct-lrow-top > .ct-lrow-t { flex-basis: 5em; }
.ct-lrow-top > .u-tag, .ct-sheethead .badge, .ct-card .badge {
  display: inline-flex; align-items: center; min-height: 24px; padding: 0 10px;
  font-size: var(--fs-badge); line-height: 1;
}
.ct-sheethead .u-tag.u-low { min-height: 0; }
.ct-lrow .ct-lrow-m { font-size: var(--fs-meta); line-height: 1.4; font-variant-numeric: tabular-nums; }
.ct-lrow .ct-lrow-k { font-size: var(--fs-sub); }

/* Who applied: the place number in a disc; the give buttons compact. */
.ct-app { padding: var(--s4); }
.ct-app .ct-app-top { align-items: center; }
.ct-app .ct-app-n {
  min-width: 28px; height: 28px; padding: 0 6px; border-radius: var(--pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--paper); font-size: var(--fs-badge);
}
.ct-app .sub, .ct-app .ct-krow-w, .ct-app .ct-krow-b { font-size: var(--fs-meta); line-height: 1.4; }
.ct-app .btn {
  display: inline-flex; align-items: center; justify-content: center; width: auto; max-width: 100%;
  min-height: var(--h-btn-sm); margin: var(--s3) var(--s2) 0 0; padding: 6px var(--s4);
  font-size: 15px; line-height: 1.25; text-align: center;
}
.ct-kb > .ct-facts > .ct-fact.applied { font-weight: 650; }
.ct-detail .ct-mixed { margin: 0; padding: var(--s4); font-size: var(--fs-sub); }
.ct-detail .ct-mixed > p.strong { margin: 0 0 var(--s2); font-size: var(--fs-body); }
.ct-detail .ct-mixed ul { margin: 0; }
.ct-kb .ct-files-h { margin: var(--s4) 4px var(--s2); font-size: var(--fs-sub); font-weight: 700; color: var(--ink); }

/* The timeline, as a grouped list. */
.ct-detail .ct-trail { margin: 0; padding: 0 var(--s4); background: #fff; border: 1px solid var(--line); font-size: var(--fs-sub); }
.ct-detail .ct-trail li { margin: 0; padding: 10px 0; }
.ct-detail .ct-trail li + li { border-top: 1px solid var(--line); }
.ct-detail .ct-trail-h { font-size: var(--fs-meta); font-variant-numeric: tabular-nums; }
.ct-detail .ct-files-h { margin-top: var(--s2); }

/* Actions: the main one full width (yellow, or a secondary when the sheet's
   yellow is above it), the rest compact and side by side, wrapping.
   Only an order's, a line's and the KitchenBase section's: the form's own
   .ct-acts (a postal code's buildings) keeps its rows. */
:is(.ct-orderacts, #sheet > .ct-acts, .ct-kb .ct-acts) { display: flex; flex-wrap: wrap; gap: var(--s2); }
:is(.ct-orderacts, #sheet > .ct-acts, .ct-kb .ct-acts) > .btn { margin-top: 0; }
:is(.ct-orderacts, #sheet > .ct-acts, .ct-kb .ct-acts) > .btn:not(.ghost) { flex: 1 1 100%; }
:is(.ct-orderacts, #sheet > .ct-acts, .ct-kb .ct-acts) > .btn.ghost {
  flex: 1 1 auto; width: auto; min-width: 0; min-height: var(--h-btn-sm); padding: 6px var(--s4);
  font-size: 15px; line-height: 1.25; background: #fff;
}
.ct-kb .ct-acts { margin-top: var(--s3); }
.ct-detail .ct-orderacts { margin-top: var(--s2); padding-top: var(--s4); border-top: 1px solid var(--line); }
#sheet > .ct-acts { margin-top: var(--s4); }

/* Action sheets: one sentence of what happens, the choices, and the action in
   the bar that stays under the thumb. */
#sheet .ct-lede { margin: var(--s1) 0 var(--s4); font-size: var(--fs-sub); line-height: 1.45; color: var(--text); }
.ct-foot.ct-actfoot { margin-top: var(--s6); }
.ct-foot.ct-actfoot > .btn { margin: 0; }
.ct-krow { position: relative; min-height: var(--h-control); padding: var(--s3) 44px var(--s3) var(--s4); }
.ct-krow.on::after {
  content: ""; position: absolute; right: 14px; top: 50%; width: 20px; height: 20px; transform: translateY(-50%);
  border-radius: 50%; background: var(--ink) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='10' viewBox='0 0 12 10'%3E%3Cpath d='M1.5 5.2l3 3 6-6.4' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
}
.ct-krow .ct-krow-t { font-size: var(--fs-body); line-height: 1.35; }
.chips.ct-pick .chip { max-width: 100%; white-space: normal; line-height: 1.25; text-align: left; }
.ct-krow .sub, .ct-krow .ct-krow-w, .ct-krow .ct-krow-b { font-size: var(--fs-meta); line-height: 1.4; }

.ct-stars .chip { min-width: 48px; }

/* The order form: four steps and a review in one sheet */
/* Its head: the title, the progress under it, "Step 2 of 5" under that (the
   step's name is its heading's to say), then the step's heading. */
.ct-where { margin: var(--s2) 0 0; font-size: var(--fs-meta); font-weight: 650; color: var(--muted); font-variant-numeric: tabular-nums; }
.ct-where-name { display: none; }
.ct-prog { list-style: none; display: flex; gap: var(--s1); margin: var(--s3) 0 0; padding: 0; }
.ct-prog li { flex: 1; height: 4px; border-radius: var(--pill); background: var(--line); }
.ct-prog li.on { background: var(--ink); }
.ct-steph { margin: var(--s6) 0 0; font-size: var(--fs-title); line-height: 1.2; font-weight: 700; letter-spacing: -0.01em; }
.ct-steph:focus { outline: none; }
.ct-restored {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0 10px;
  padding: 2px 14px; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); font-size: 14px;
}
/* The desk's next step, first on an order's sheet. */
.ct-next {
  margin: 10px 0 14px; padding: 10px 14px; background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: inset 4px 0 0 var(--acc-gold); font-size: 14px;
}
.ct-next p { margin: 4px 0; }
.ct-next .strong { font-weight: 700; }
.ct-next .ct-next-item { display: block; text-align: left; margin: 4px 0; }
.ct-next .btn.primary { width: 100%; margin-top: 8px; }
/* An edit this phone kept, offered beside the order as saved. */
.ct-offer {
  margin: 10px 0; padding: 8px 14px; background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); font-size: 14px;
}
.ct-offer p { margin: 4px 0; }
.ct-offer-acts { display: flex; flex-wrap: wrap; gap: 0 16px; }
/* Someone else saved the order under the form: what they did, and what
   happened to this person's changes. Gold, like the change banner. */
.ct-conflict {
  margin: 10px 0; padding: 8px 14px; border-radius: var(--radius);
  background: #F4EFDF; box-shadow: inset 4px 0 0 var(--acc-gold); font-size: 14px; color: var(--ink);
}
.ct-conflict p { margin: 4px 0; }
.ct-conflict .strong { font-weight: 700; }
.ct-conflict .ct-trail { background: #fff; }
/* The same gold box on an order's sheet, listing what a save answered with. */
.ct-notes ul { margin: 4px 0; padding-left: 20px; }
.ct-notes li { margin: 3px 0; overflow-wrap: anywhere; }
/* minmax(0, 1fr): a time field's own minimum width would otherwise push a
   two-column row past a 320 px screen. */
.ct-row2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s3); margin-top: var(--s2); }
.ct-row2 input { min-width: 0; }
.ct-mini { display: block; margin: 0 0 6px; font-size: var(--fs-meta); line-height: 1.35; font-weight: 650; color: var(--text); }
.ct-hint { margin: 6px 0 0; }
.ct-stepper { display: flex; gap: var(--s2); }
.ct-stepper .btn { flex: none; width: var(--h-control); min-height: var(--h-control); margin-top: 0; padding: 0; font-variant-numeric: tabular-nums; }
.ct-stepper input { min-width: 0; text-align: center; font-variant-numeric: tabular-nums; }
.ct-switch {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: 56px; margin-top: var(--s5); padding: var(--s3) var(--s3) var(--s3) var(--s4);
  font: inherit; text-align: left; color: var(--ink); background: #fff;
  border: 1.5px solid var(--field-edge); border-radius: var(--radius);
}
.ct-switch-t { font-weight: 650; }
.ct-switch-s {
  flex: none; min-width: 48px; padding: 6px var(--s3); border-radius: var(--pill); text-align: center;
  background: var(--paper); color: var(--text); font-size: var(--fs-badge); line-height: 1; font-weight: 700;
}
.ct-switch.on { border-color: var(--ink); }
.ct-switch.on .ct-switch-s { background: var(--ink); color: #fff; }
.ct-group { margin-top: var(--s6); padding: 0 var(--s4) var(--s4); background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-group-h { margin: var(--s4) 0 0; font-size: var(--fs-head); line-height: 1.3; font-weight: 700; letter-spacing: -0.01em; }
.ct-sel {
  display: block; width: 100%; min-height: var(--h-control); padding: 10.5px 16px; font: inherit;
  color: var(--ink); background: #fff;
  border: 1.5px solid var(--field-edge); border-radius: var(--radius);
}
.ct-sel:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.ct-flines { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); margin-top: var(--s3); }
.ct-fline { padding: var(--s2) var(--s4) var(--s4); background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-fline.gone { background: var(--paper); }
.ct-fline-top { display: flex; align-items: center; gap: var(--s2); min-height: var(--h-btn-sm); margin-top: 0; }
.ct-fline-t { flex: 1; min-width: 0; margin: var(--s2) 0 0; font-size: var(--fs-head); line-height: 1.3; font-weight: 700; overflow-wrap: anywhere; }
.ct-fline-top .ct-fline-t { margin: 0; }
.ct-rm { flex: none; padding-left: 8px; padding-right: 8px; }
.comingup.ct-more { margin-top: 12px; }
.ct-split { margin-top: var(--s5); }
/* Back and Next stay under the thumb while a step scrolls. The sheet's own
   bottom padding is taken back so no line of the form shows under them. */
.ct-foot {
  position: sticky; bottom: calc(-18px - env(safe-area-inset-bottom)); z-index: 2;
  margin: 18px calc(var(--pad) * -1) 0;
  padding: var(--s3) var(--pad) calc(var(--s3) + env(safe-area-inset-bottom));
  background: var(--bright); border-top: 0; box-shadow: var(--shadow-bar);
}
.ct-foot-row { display: flex; gap: 10px; }
.ct-foot-row .btn { flex: 1 1 0; min-width: 0; margin-top: 0; }
.ct-foot > .btn { margin: 0 0 10px; }
.ct-tally { margin: 0 0 var(--s2); font-weight: 700; font-variant-numeric: tabular-nums; }
.ct-tally.short { color: var(--acc-wine); }
/* The review: what the order is, one card, then what it still needs, one
   row each, each a way to the step that fixes it. */
.ct-sum { margin-top: var(--s3); padding: 0 var(--s4); background: #fff; border: 1px solid var(--line); border-radius: var(--radius); font-size: var(--fs-sub); font-variant-numeric: tabular-nums; }
.ct-sum-g { padding: var(--s1) 0 var(--s3); }
.ct-sum-g + .ct-sum-g { border-top: 1px solid var(--line); }
.ct-sum-h { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 44px; }
.ct-sum-t { min-width: 0; font-size: var(--fs-caps); font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); }
.ct-sum-edit { flex: none; min-width: 44px; min-height: 44px; margin-right: calc(var(--s1) * -1); padding: 0 var(--s1); font-size: var(--fs-sub); text-align: right; }
.ct-sum p { margin: 0 0 var(--s1); line-height: 1.45; overflow-wrap: anywhere; }
.ct-sum p.ct-sum-title { font-size: var(--fs-head); line-height: 1.3; font-weight: 700; color: var(--ink); }
.ct-need { margin-top: var(--s3); padding: var(--s3) var(--s4) var(--s1); background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-need > .strong { margin: 0 0 var(--s1); font-size: var(--fs-sub); }
.ct-need ul { list-style: none; margin: 0; padding: 0; }
.ct-need li + li { border-top: 1px solid var(--line); }
.ct-need .linkbtn {
  display: flex; align-items: center; gap: var(--s3); width: 100%; min-height: var(--h-btn-sm); padding: var(--s2) 0;
  text-align: left; text-decoration: none; font-size: var(--fs-sub); font-weight: 600; line-height: 1.35;
}
.ct-need .linkbtn::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--acc-wine); }
.ct-need .linkbtn::after {
  content: ""; flex: none; width: 7px; height: 7px; margin: 0 4px 0 auto;
  border: solid var(--muted); border-width: 2px 2px 0 0; transform: rotate(45deg);
}
.ct-warns { list-style: none; display: grid; gap: 8px; margin: 12px 0 0; padding: 0; }
.ct-warns li {
  padding: 10px 14px; font-size: 14px; background: #fff;
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: inset 4px 0 0 var(--line);
}
.ct-warns li.warn { font-weight: 600; box-shadow: inset 4px 0 0 var(--acc-gold); }
.ct-mixed { margin-top: 12px; padding: 10px 14px; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-formbody .ct-warns li, .ct-q-body .ct-warns li, .ct-formbody .ct-mixed { padding: var(--s3) var(--s4); }

/* The form's foot: Back and Next under the thumb, the one yellow; Save as
   tentative (and Food's portions tally) a quiet line above them. Only the
   form's foot: an order's own sheets keep theirs. */
.ct-formbody + .ct-foot { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s2) var(--s3); }
.ct-formbody + .ct-foot > * { grid-column: 1 / -1; }
.ct-formbody + .ct-foot > .ct-tally { grid-column: 1; margin: 0; font-size: var(--fs-sub); }
.ct-formbody + .ct-foot > .btn { margin: 0; }
.ct-formbody + .ct-foot > .btn.ct-savehere {
  grid-column: 2; width: auto; min-height: var(--h-btn-sm); padding: 0 var(--s1);
  border: 0; background: none; font-size: var(--fs-sub); text-decoration: underline; text-underline-offset: 3px;
}
.ct-formbody + .ct-foot .ct-foot-row > .btn:first-child:not(:last-child) { flex: 0 0 auto; width: auto; padding: 0 var(--s5); }
.ct-formbody + .ct-foot .ct-foot-row > .btn:last-child { flex: 1 1 0; }
.ct-formbody + .ct-foot > .btn.primary + .ct-foot-row .btn { min-height: var(--h-btn-sm); font-size: 15px; }
@media (max-width: 340px) {
  .ct-formbody + .ct-foot .ct-foot-row > .btn { font-size: 15px; }
  .ct-formbody + .ct-foot .ct-foot-row > .btn:first-child:not(:last-child) { padding: 0 var(--s3); }
}

/* Choices on the form: an even grid, two across (three from 414 px), every
   chip one width; two or four choices stay two across, and a long list of
   short words (allergens, cuisines) goes three across from 360 px. */
.ct-formbody .chips:not(.seg) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); margin: 0; }
@media (min-width: 360px) {
  .ct-formbody .chips:not(.seg):has(> :nth-child(10)) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 414px) {
  .ct-formbody .chips:not(.seg) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ct-formbody .chips:not(.seg):has(> :nth-child(2):last-child),
  .ct-formbody .chips:not(.seg):has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ct-formbody .chips:not(.seg) .chip {
  min-width: 0; min-height: var(--h-btn-sm); padding: 6px var(--s3);
  font-size: var(--fs-sub); line-height: 1.25; white-space: normal; text-align: center;
}
@media (max-width: 400px) { .ct-formbody .chips:not(.seg) .chip { padding: 6px var(--s2); } }

/* ---- the quick order: New order (Ernest, 5 Oct 2026, direction C) ---------------
   Two short screens over the full form's own form. Every field booking needs
   carries a wine dot that turns into a tick once it is done; the bar under the
   thumb says what is left, and becomes the yellow Book order when nothing is. */
.ct-q-tools { display: flex; gap: 10px; }
.ct-q-tools .btn { margin-top: 0; }
.ct-q-tools .btn.primary { flex: 1 1 auto; min-width: 0; }
.ct-q-tools .btn.ghost { flex: 0 0 auto; width: auto; padding: 0 18px; }
.ct-q-head { display: flex; align-items: center; justify-content: space-between; gap: 0 12px; margin-top: -4px; }
.ct-q-head .ct-where { margin: 0; }
.ct-q-head .ct-where:focus { outline: none; }
.ct-q-full { flex: none; min-height: 44px; padding: 0 2px; font-size: 14px; }
/* The two bars are 5px to the eye and 44px to the thumb; the row's margins
   take the difference back. */
.ct-q-prog { display: flex; align-items: center; gap: 6px; margin: -12px 0 -6px; }
.ct-q-pbar { flex: 1 1 0; min-width: 0; min-height: 44px; padding: 0; border: 0; background: none; }
.ct-q-pbar::before { content: ""; display: block; height: 5px; border-radius: var(--pill); background: var(--line); }
.ct-q-pbar.on::before { background: var(--ink); }
.ct-q-legend { flex: none; display: inline-flex; align-items: center; gap: 5px; margin-left: 6px; font-size: 12px; color: var(--muted); white-space: nowrap; }
.ct-q-legend::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--acc-wine); }
.ct-q-test { margin: var(--s2) 0 0; padding: var(--s2) var(--s3); font-weight: 650; background: #fff; border-radius: var(--radius); box-shadow: inset 4px 0 0 var(--ink); }
.ct-q-body > :first-child { margin-top: var(--s3); }

/* a field: the label row (mark, label, then a summary or a link), then its control */
.ct-q-fld { position: relative; margin-top: var(--s5); border-radius: var(--radius); }
.ct-q-mini { display: flex; align-items: center; min-height: 20px; margin: 0 0 6px; font-size: var(--fs-sub); line-height: 20px; font-weight: 650; color: var(--ink); }
.ct-q-opt > .ct-q-mini { color: var(--ink); }
.ct-q-lbl { flex: none; }
.ct-q-mark { flex: none; width: 14px; height: 14px; margin-right: 6px; display: inline-grid; place-items: center; }
.ct-q-mark::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--acc-wine); }
.ct-q-fld.ok > .ct-q-mini .ct-q-mark::before {
  width: 5px; height: 10px; border-radius: 0; background: none;
  border: solid var(--ink); border-width: 0 2px 2px 0; transform: translateY(-2px) rotate(45deg);
}
.ct-q-aside {
  flex: 1 1 auto; min-width: 0; margin-left: var(--s2); text-align: right;
  font-size: var(--fs-meta); font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums;
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
.ct-q-tally.short { color: var(--acc-wine); font-weight: 700; }
.ct-q-tsum { margin: var(--s2) 0 0; font-variant-numeric: tabular-nums; }
/* A link in a label row keeps a 44px target without making the row taller. */
.ct-q-mini .ct-q-link { flex: none; min-width: 44px; min-height: 0; margin: -12px -4px -12px var(--s2); padding: 12px 4px; font-size: var(--fs-sub); line-height: 20px; font-weight: 650; text-align: center; }
.ct-q-issue { margin: 6px 0 0; font-size: var(--fs-meta); font-weight: 650; color: var(--acc-wine); }
/* Where the bar took the desk: a wine ring that eases in once. */
.ct-q-attn { background: #FBF4F5; box-shadow: 0 0 0 3px var(--acc-wine), 0 0 0 7px rgba(147, 86, 95, 0.14); animation: ct-q-attn 1.2s ease-out; }
@keyframes ct-q-attn {
  0% { box-shadow: 0 0 0 14px rgba(147, 86, 95, 0); }
  35% { box-shadow: 0 0 0 3px var(--acc-wine), 0 0 0 10px rgba(147, 86, 95, 0.3); }
  100% { box-shadow: 0 0 0 3px var(--acc-wine), 0 0 0 7px rgba(147, 86, 95, 0.14); }
}
/* Two fields side by side where they fit, one above the other where not:
   below 375 px a pax stepper beside the service would leave its number
   field too narrow to read. */
.ct-q-row2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0 var(--s3); }
.ct-q-fld .ct-stepper input { padding: 10.5px 4px; }

/* one choice of a few, as one joined field across the width */
/* 48 tall in all, as a field is: a pax stepper and a service choice side by
   side meet at the top and the bottom. */
.chips.seg.ct-q-seg { display: flex; flex-wrap: nowrap; width: 100%; min-height: var(--h-control); margin: 0; padding: 2px; }
.chips.seg.ct-q-seg .chip {
  flex: 1 1 0; min-width: 0; min-height: var(--h-btn-sm); padding: 4px 8px;
  font-size: var(--fs-sub); font-weight: 650; line-height: 1.15; white-space: normal; overflow-wrap: normal;
}
/* Three halal choices across a 280px phone: a word never splits in two. */
@media (max-width: 340px) { .chips.seg.ct-q-seg .chip { padding: 4px; font-size: 13px; } }
/* a row that scrolls sideways inside the sheet, never the page */
.chips.ct-q-strip {
  flex-wrap: nowrap; gap: var(--s2); margin: 0 calc(var(--pad) * -1); padding: 2px var(--pad) 4px;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  scroll-padding: 0 var(--pad);
}
/* The fade says there is more to the right, and goes once the end is in view. */
.chips.ct-q-strip.ct-q-fade {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 40px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 40px), transparent);
}
.chips.ct-q-strip::-webkit-scrollbar { display: none; }
.chips.ct-q-strip > * { flex: none; }
.chips.ct-q-strip > :last-child { margin-right: var(--pad); }
.chips.ct-q-strip .chip { min-height: var(--h-btn-sm); padding: 0 var(--s4); font-size: var(--fs-sub); }
/* The date: a tile per day, 56 square, the weekday in capitals over the day. */
.ct-q-day {
  width: 56px; min-height: 56px; padding: 4px 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: 1.5px solid var(--line); border-radius: var(--radius); background: #fff; color: var(--ink); line-height: 1.1;
}
.ct-q-day.ct-q-wide { width: auto; padding: 4px var(--s4); }
.ct-q-wd { font-size: var(--fs-caps); font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); }
.ct-q-dn { font-size: var(--fs-head); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ct-q-wide .ct-q-dn:only-child { font-size: var(--fs-sub); font-weight: 650; }
.ct-q-day:hover, .ct-q-meal:hover { border-color: var(--ink); }
.ct-q-day.on, .ct-q-meal.on { background: var(--ink); border-color: var(--ink); color: var(--bright); }
.ct-q-day.on .ct-q-wd, .ct-q-meal.on .ct-q-mn { color: #D6D6D6; }
.ct-q-meals { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); }
@media (max-width: 340px) { .ct-q-meals { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ct-q-meal {
  min-height: 56px; padding: 4px 2px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: 1.5px solid var(--line); border-radius: var(--radius); background: #fff; color: var(--ink); line-height: 1.1;
}
.ct-q-mn { font-size: var(--fs-meta); font-weight: 600; color: var(--text); }
.ct-q-mt { font-size: var(--fs-head); font-weight: 700; font-variant-numeric: tabular-nums; }
/* Before a service is chosen: a quiet note in the field's place, not a box
   that reads as somewhere to drop something. */
.ct-q-wait {
  min-height: var(--h-control); display: flex; align-items: center; margin: 0; padding: var(--s3) var(--s4);
  background: var(--paper); border-radius: var(--radius); font-size: var(--fs-sub); line-height: 1.4; color: var(--muted);
}

/* what the postal code found */
.ct-q-look p { margin: 6px 0 0; }
.ct-q-found { display: flex; gap: 6px; align-items: flex-start; font-size: var(--fs-sub); line-height: 1.4; }
.ct-q-found svg { flex: none; width: 15px; height: 15px; margin-top: 2px; }
.ct-q-addr { font-weight: 650; }
.ct-q-src { color: var(--muted); }
.ct-q-picks .btn { margin-top: var(--s2); min-height: var(--h-control); padding: var(--s2) var(--s4); line-height: 1.25; }

/* More details (optional) */
.ct-q-fold {
  display: flex; align-items: center; gap: var(--s2); width: 100%; min-height: 56px; margin-top: var(--s6); padding: var(--s2) 2px;
  border: 0; border-top: 1px solid var(--line); background: none; color: var(--ink); text-align: left;
}
.ct-q-fold-w { flex: 1 1 auto; min-width: 0; }
.ct-q-fold-t { display: block; font-size: var(--fs-caps); font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); }
.ct-q-fold-s { display: block; margin-top: 2px; font-size: var(--fs-meta); color: var(--text); }
.ct-q-fold:hover .ct-q-fold-t { color: var(--ink); }
.ct-q-fold svg { flex: none; width: 18px; height: 18px; transition: transform var(--speed) ease; }
.ct-q-fold[aria-expanded="true"] svg { transform: rotate(180deg); }
.ct-q-more .ct-group { margin-top: var(--s4); }

/* screen 2: the food */
.ct-q-sum {
  display: flex; align-items: center; gap: 6px; width: 100%; min-height: var(--h-btn-sm); padding: 4px var(--s4) 4px var(--s2);
  border: 1px solid var(--line); border-radius: var(--pill); background: #fff; color: var(--text);
  text-align: left; font-size: var(--fs-sub); font-weight: 600; font-variant-numeric: tabular-nums;
}
.ct-q-sum:hover { border-color: var(--ink); }
.ct-q-sum span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ct-q-sum svg { flex: none; width: 16px; height: 16px; }
.ct-q-lines { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); margin-top: var(--s3); }
.ct-q-line { padding: var(--s2) var(--s4) var(--s4); background: #fff; border: 1px solid var(--line); border-radius: var(--radius); }
.ct-q-line .ct-q-fld { margin-top: var(--s3); }
/* A line's card is narrower than the sheet: portions and payout share a row
   where the stepper keeps a number field wide enough to read (414 px up). */
.ct-q-line .ct-q-row2 { grid-template-columns: repeat(auto-fit, minmax(164px, 1fr)); }
.ct-q-ltop { display: flex; align-items: center; gap: var(--s2); min-height: var(--h-btn-sm); }
.ct-q-badge {
  flex: none; width: 28px; height: 28px; border-radius: 50%; display: inline-grid; place-items: center;
  background: var(--ink); color: #fff; font-size: 13px; font-weight: 750;
}
/* The cuisine reads as a word with a chevron; the list sits over it, unseen. */
label.ct-q-cpick {
  position: relative; flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; margin: 0; padding: 0 4px 0 2px; border-radius: var(--r-sm); font-size: var(--fs-head); font-weight: 700; color: var(--ink);
}
.ct-q-cword { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ct-q-cpick svg { flex: none; width: 16px; height: 16px; }
.ct-q-cpick select {
  position: absolute; inset: 0; width: 100%; height: 100%; min-height: 0; padding: 0;
  opacity: 0; cursor: pointer; font-size: 16px;
}
.ct-q-cpick:focus-within { outline: 2px solid var(--focus); outline-offset: 2px; }
.ct-q-rm { flex: none; min-height: 44px; padding: 0 4px; font-size: var(--fs-sub); }
.ct-q-money {
  display: flex; align-items: center; min-height: var(--h-control); padding-left: var(--s3);
  border: 1.5px solid var(--field-edge); border-radius: var(--radius); background: #fff;
}
.ct-q-money:focus-within { border-color: var(--ink); outline: 2px solid var(--focus); outline-offset: 3px; }
.ct-q-money span { flex: none; white-space: nowrap; color: var(--muted); font-weight: 650; }
.ct-q-money input { flex: 1 1 auto; min-width: 0; min-height: 0; padding-left: 6px; border: 0; background: transparent; font-variant-numeric: tabular-nums; }
.ct-q-money input:focus-visible { outline: none; }
.ct-q-ltot { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s3); font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; }
.ct-q-ltot:not(:empty) { margin-top: var(--s1); }
.ct-q-ltot .ct-q-link { min-height: 44px; padding: 0 2px; font-size: var(--fs-meta); }
/* Halal: its label beside the choices where they fit, above them where not. */
.ct-q-inline { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s3); }
.ct-q-inline > .ct-q-mini { flex: none; margin: 0; }
.ct-q-inline > .chips.seg { flex: 1 1 220px; }
.ct-q-inline > p { flex-basis: 100%; }
.ct-q-warns { margin-top: var(--s5); }

/* The bar: what is left, under the thumb, and the sheet's own bottom padding
   taken back as the full form's foot does. */
.ct-q-bar {
  position: sticky; bottom: calc(-18px - env(safe-area-inset-bottom)); z-index: 2;
  display: flex; align-items: center; gap: 8px;
  margin: 18px calc(var(--pad) * -1) 0;
  padding: var(--s3) var(--pad) calc(var(--s3) + env(safe-area-inset-bottom));
  background: var(--bright); border-top: 0; box-shadow: var(--shadow-bar);
}
/* What is scrolled into view on the quick order (a line just added, where
   the bar took the desk) stops above the bar, not under it. */
#sheet:has(.ct-q-bar) { scroll-padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
.ct-q-bar .btn { flex: none; width: auto; min-width: 0; margin: 0; padding: 0 var(--s6); }
.ct-q-bar .btn.ghost { padding: 0 var(--s4); }
.ct-q-bar .ct-q-book { flex: 1 1 auto; }
/* What is left: a text button, the count over the fields it counts, and a
   chevron. The button beside it carries the weight. */
.ct-q-left {
  flex: 1 1 auto; min-width: 0; min-height: var(--h-btn); display: flex; align-items: center; gap: 10px;
  padding: 4px 4px 4px 2px; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--ink); text-align: left; line-height: 1.3;
}
.ct-q-left:hover .ct-q-lefttext b { text-decoration: underline; text-underline-offset: 3px; }
.ct-q-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--acc-wine); }
.ct-q-lefttext { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.ct-q-lefttext b { color: var(--ink); font-size: var(--fs-sub); font-weight: 700; font-variant-numeric: tabular-nums; }
.ct-q-leftnames {
  min-width: 0; font-size: var(--fs-meta); color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ct-q-left svg { flex: none; width: 18px; height: 18px; color: var(--muted); }
.ct-q-allset { flex: 1 1 auto; min-width: 0; margin: 0; font-size: var(--fs-sub); font-weight: 650; line-height: 1.3; }

/* ---- moves dashboard ----------------------------------------------------------- */
.mvcard { display: flex; gap: 14px; align-items: center; cursor: default; }
.mv-date {
  flex: none; width: 52px; text-align: center;
  border-right: 1px solid var(--line); padding-right: 12px;
}
.mv-date .d { display: block; font-size: 22px; font-weight: 750; line-height: 1; font-variant-numeric: tabular-nums; }
.mv-date .mo { display: block; font-size: 10.5px; font-weight: 650; letter-spacing: 0.07em; color: var(--muted); margin-top: 3px; }
.mv-body { flex: 1; min-width: 0; }
/* Licensee names never truncate. This was the last ellipsis on one. */
.mv-body .title { margin-bottom: 0; overflow-wrap: anywhere; }
/* Booked reads as a fact, in ink. Not booked stays quiet: the badge beside
 * the kitchen already says how soon the date is. */
.mv-session { margin-top: 5px; font-size: 13px; font-weight: 650; color: var(--text); overflow-wrap: anywhere; }
.mv-session .by { font-weight: 500; color: var(--muted); }
.mv-session.none { font-weight: 550; color: var(--muted); }
.mv-clean { margin-top: 3px; font-size: 13px; font-weight: 650; color: var(--text); overflow-wrap: anywhere; }
.mv-clean.late { color: var(--acc-wine); }
.mv-clean.done { font-weight: 550; color: var(--muted); }
/* The request id never breaks across lines, however long the place beside it. */
.mv-tag.cl-id { background: var(--ink); color: #fff; white-space: nowrap; flex: 0 0 auto; }
.cl-card .title { overflow-wrap: anywhere; }
.cl-card.cl-done .title { color: var(--muted); }
.mv-note { margin: 10px 2px 0; }
/* Same component as .u-tag on a Today card — matched, not approximated. */
.mv-tag {
  font-size: 11px; font-weight: 750; letter-spacing: 0.05em;
  padding: 2px 8px; border-radius: var(--pill);
}
.mv-tag.t-in  { background: var(--acc-gold); color: var(--ink); }
.mv-tag.t-out { background: var(--acc-wine); color: #fff; }
.stat.s-in .num { color: #7A6636; }
.mv-ren { margin: 6px 2px; font-size: 13px; color: var(--muted); }

/* ---- schedule lists: one card anatomy (redesign, 5 Oct 2026) ---------------
   Moves, Cleaning, Maintenance and Checklists (.sched-list). Catering's
   order cards share the base classes above and are styled with catering.
   A 48 px date rail (weekday, day, month) behind a hairline that runs the
   card's height; then the content: tag, place and status on one line that
   never wraps (the place gives way with an ellipsis, never the id), the
   title, and the facts under it in one size. */
.sched-list .card { padding: var(--s4) var(--s4) var(--s4) var(--s5); }
.sched-list .mvcard { gap: var(--s3); align-items: stretch; }
.sched-list .kc-card { cursor: pointer; }   /* a checklist card opens it */
.sched-list .mv-date {
  width: 48px; padding: 1px var(--s3) 0 0;
  display: flex; flex-direction: column; align-items: center;
}
.sched-list .mv-date .wd,
.sched-list .mv-date .mo {
  display: block; font-size: 11px; font-weight: 650; line-height: 1.2;
  letter-spacing: 0.06em; color: var(--muted);
}
.sched-list .mv-date .d {
  display: block; margin: 3px 0 2px; font-size: var(--fs-title); font-weight: 750;
  line-height: 1; letter-spacing: -0.01em; color: var(--ink);
}
.sched-list .mv-date .mo { margin-top: 0; }
/* Tag, place and status share one line; the place gives way first. On a
   280-340 px phone, where the place would vanish, the tag and the status
   keep the line and the place takes the next one, whole. */
.sched-list .row1 { flex-wrap: nowrap; gap: 6px; min-height: 24px; margin-bottom: 6px; }
.sched-list .row1 .loc-meta {
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-meta); letter-spacing: 0.01em;
}
.sched-list .row1 .mv-tag,
.sched-list .row1 .badge {
  flex: none; display: inline-flex; align-items: center; height: 24px; padding: 0 9px;
  font-size: var(--fs-badge); line-height: 1; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* Ids keep proportional figures: tabular ones widened the hyphen in "CR-1042". */
.sched-list .row1 .mv-tag { font-weight: 750; letter-spacing: 0.03em; font-variant-numeric: normal; }
.sched-list .row1 .mv-tag.cl-id { letter-spacing: 0.01em; }
/* 280-340 px: a slimmer card frame and rail, so the title keeps its width. */
@media (max-width: 340px) {
  .sched-list .card { padding: var(--s3) var(--s3) var(--s3) var(--s4); }
  .sched-list .mvcard { gap: 10px; }
  .sched-list .mv-date { width: 42px; padding-right: var(--s2); }
  .sched-list .row1 { flex-wrap: wrap; row-gap: 2px; }
  .sched-list .row1 .loc-meta { order: 3; flex-basis: 100%; }
  /* As on the catering card: the date rail becomes one line over the card
     ("FRI 9 OCT"), so the title keeps the card's whole width. */
  .sched-list .mvcard { flex-direction: column; gap: var(--s2); }
  .sched-list .mv-date {
    flex-direction: row; align-items: baseline; align-self: flex-start; gap: 6px;
    width: auto; padding: 0; border-right: 0;
  }
  .sched-list .mv-date .d { margin: 0; font-size: var(--fs-sub); font-weight: 700; }
}
.sched-list .row1 .badge { margin-left: auto; font-weight: 700; }
.sched-list .card .title { margin: 0; font-size: var(--fs-head); line-height: 1.3; }
.sched-list .mv-session,
.sched-list .mv-clean { margin-top: var(--s1); font-size: var(--fs-sub); line-height: 1.45; }
.sched-list .card .title + .mv-session,
.sched-list .card .title + .mv-clean { margin-top: 6px; }
.sched-list .mv-session { font-weight: 600; }
.sched-list .mv-session.none { font-weight: 500; }
.sched-list .cardmeta { margin-top: 6px; font-size: var(--fs-sub); font-weight: 500; line-height: 1.45; }
/* Set next date: a compact secondary under the facts, never a full-width pill. */
.sched-list .mt-act { width: auto; margin-top: var(--s3); padding: 0 var(--s4); font-size: var(--fs-sub); }
/* The quiet lines under a list: what it leaves out. Clear of the cards, and
   the page keeps its room above the bottom nav. */
#mv-renewals .mv-note, #cl-foot .mv-note {
  margin: var(--s6) var(--s1) 0; font-size: var(--fs-meta); line-height: 1.45;
}
#mv-renewals .mv-ren { margin: var(--s2) var(--s1); font-size: var(--fs-sub); color: var(--text); }
/* An empty schedule list: a calendar in a quiet disc over one calm line,
   the app's empty state, not a 20 px shout. */
:is(#mv-empty, #cl-empty, #mt-empty, #kc-empty) {
  margin: var(--s10) var(--s4); font-size: var(--fs-head); font-weight: 650; line-height: 1.35;
  letter-spacing: -0.005em; color: var(--text); text-align: center;
}
:is(#mv-empty, #cl-empty, #mt-empty, #kc-empty)::before {
  content: ""; display: block; width: 72px; height: 72px; margin: 0 auto var(--s3);
  border-radius: 50%;
  background: #EAEAEA url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.5' y='5' width='17' height='15' rx='2.5'/%3E%3Cpath d='M3.5 10h17M8 3v4M16 3v4'/%3E%3C/svg%3E") no-repeat center / 32px;
}
/* A schedule sheet's meta row under its title: the request's id, place and
   site, one size up from a hint and tucked under the heading it belongs to. */
#sheet .sched-meta { margin: calc(var(--s1) * -1) 0 var(--s4); font-size: var(--fs-sub); line-height: 1.45; }
/* The first section header sits closer under the stat tiles than the next. */
#cl-list > li:first-child .listhead { margin-top: var(--s5); }
.sched-list > li > .listhead { margin-bottom: var(--s2); }

/* ---- licensee issues (the KitchenBase app) ---------------------------------- */
/* Today's card is the approvals banner's twin (gold edge when something waits,
   quiet when nothing does), with a chevron: it opens a page, not a sheet. */
.kbcard { display: flex; align-items: center; gap: 12px; }
.kbcard .kbcard-t { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.kbcard .kbcard-go { flex: none; font-size: 22px; line-height: 1; color: var(--muted); }
/* The server could not answer (a tab of the shared sheet lost a column): a
   wine edge, and its words on a line of their own. */
.kbcard.problem { border-color: var(--acc-wine); }
.kbcard .kbcard-why {
  display: block; margin-top: 4px;
  font-size: 13.5px; font-weight: 500; color: var(--text);
}
/* The page's way back sits in the ink hero, so it takes the hero's light text. */
.hero-head .linkback {
  display: block; margin: -10px 0 4px -2px; padding: 10px 2px;
  color: rgba(255, 255, 255, 0.8); font-size: 14px;
}
.hero-head .linkback:hover { color: #fff; opacity: 1; }
/* Demo is a label, not a signal: an ink outline, never a colour field. */
.mv-tag.kb-demo {
  background: #fff; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink);
  white-space: nowrap; flex: 0 0 auto;
}
.card.kb-item { cursor: pointer; }
.card.kb-item:hover { border-color: var(--ink); }
.card.kb-item.kb-done .title { color: var(--muted); }
/* What a licensee typed keeps its line breaks and never runs off the side. */
.kb-text { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.kb-status { margin: 12px 0 2px; font-weight: 650; }
/* The conversation: the licensee on the left on white, the team on the right
   on the paper field, so whose words are whose is plain without reading. */
.kb-thread { list-style: none; margin: 8px 0 4px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.kb-msg {
  max-width: 88%; padding: 10px 14px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
}
.kb-msg.team { align-self: flex-end; background: var(--paper); border-color: var(--paper); }
.kb-msg .kb-who { margin: 0 0 4px; font-size: 12.5px; font-weight: 650; color: var(--muted); }
.kb-msg .kb-text { font-size: 15px; }
.kb-msg .mediagrid { margin-top: 8px; }

/* ---- kitchen work requests (WO-12) ------------------------------------------- */
/* "Kitchen work · 15A isolator" on a request's card and sheet: a quiet paper
   label, as KitchenBase review's kind is, and the line above the title, so it
   never shares a row with the place and the status on a narrow phone. */
.kb-kind {
  display: inline-block; max-width: 100%; margin: 8px 0 0; padding: 3px 10px;
  border-radius: var(--pill); background: var(--paper); color: var(--ink);
  font-size: 12.5px; font-weight: 700; overflow-wrap: anywhere;
}
#sheet .kb-kind { margin: 4px 0 0; }
.kb-terms { margin: 8px 0 0; font-size: 14.5px; font-weight: 650; color: var(--ink); }
/* The originals of the marked photos: one link each, side by side while they fit. */
.kb-originals { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.kb-originals .btn {
  display: inline-flex; align-items: center; justify-content: center; width: auto;
  min-height: 44px; margin-top: 0; padding: 0 18px; font-size: 15px; text-decoration: none;
}
/* A quotation to add to the reply: a chip that may wrap, so a long total
   never runs off a narrow phone. */
.kb-tips .muted { margin: 8px 0 0; }
.kb-tips .chip { white-space: normal; text-align: left; min-height: 44px; overflow-wrap: anywhere; }

/* All · Issues · Kitchen work, and the quotations' All · To sign · Signed: one
   joined row even on a 280 px phone, where the chips draw a little tighter
   (wrapped, the pill split in two rows). */
.chips.seg.seg-tight { flex-wrap: nowrap; }
@media (max-width: 360px) {
  .chips.seg.seg-tight .chip { padding-left: 12px; padding-right: 12px; font-size: 13.5px; }
}

/* ---- quotations (the Ops Bot's, view only) ------------------------------------- */
/* The cards and the sheet are the licensee requests' own (kb-item, kb-status,
   sq-details, sq-open). The figures as printed: label left, amount right. */
.qt-sums {
  display: grid; grid-template-columns: 1fr auto; gap: 4px 16px; margin: 12px 0 4px;
  font-variant-numeric: tabular-nums;
}
.qt-sums dt { margin: 0; color: var(--text); }
.qt-sums dd { margin: 0; text-align: right; font-weight: 650; color: var(--ink); }
.qt-sums dt:last-of-type, .qt-sums dd:last-of-type { font-weight: 750; color: var(--ink); }
.qt-lines { margin: 4px 0 8px; padding-left: 18px; }
.qt-lines li { margin: 3px 0; overflow-wrap: anywhere; }
#sheet .cards.qt-kitchen { margin-top: 12px; }

/* ---- signed quotations (the KitchenBase app) --------------------------------- */
/* Today's card, the list and the sheet are the licensee issues' own (kbcard,
   kb-item, kb-status). The details line holds a 64-character hash, which
   wraps anywhere rather than run off a narrow phone. */
.sq-details p {
  margin: 2px 0; font-size: 13.5px; color: var(--muted);
  overflow-wrap: anywhere; font-variant-numeric: tabular-nums;
}
/* ---- KitchenBase review (Ernest only) ----------------------------------------- */
/* The cards are the list page's own (kbcard on Today, card rows on the page),
   with the question and its answers on the card: no sheet to open. */
.card.rv-item .rv-why { margin: 8px 0 6px; font-size: 15px; line-height: 1.4; overflow-wrap: anywhere; }
.card.rv-item .rv-file { overflow-wrap: anywhere; }
.mv-tag.rv-kind { background: var(--paper); color: var(--ink); white-space: nowrap; flex: 0 0 auto; }
a.btn.rv-open {
  display: flex; align-items: center; justify-content: center; margin-top: 10px; padding: 8px 18px;
  color: var(--ink); text-decoration: none; text-align: center;
}
/* Side by side where both fit on one line; on a narrow phone each takes its
   own row rather than break "Show to licensee" in two. */
.rv-acts { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.rv-acts .btn { flex: 1 1 150px; margin-top: 0; white-space: nowrap; padding-left: 14px; padding-right: 14px; }
.rv-acts .btn.on { box-shadow: inset 0 0 0 2px var(--ink); }
.rv-foot { display: flex; justify-content: center; padding: 4px 16px 24px; }
a.btn.sq-open {
  display: flex; align-items: center; justify-content: center; padding: 8px 22px;
  color: var(--ink); text-decoration: none; text-align: center;
}

/* ==== DESKTOP =============================================================
 * Everything below exists only at ≥900px, and it adds no markup and renames
 * no class — the phone layout above is untouched, which is the point: the
 * app that lives in a kitchen must not move because a manager wanted a
 * wider view of it.
 *
 * Same shape Smart GMV takes at this width: dark bands run edge to edge
 * while their CONTENT stays locked to a centred column, figure tiles
 * straddle the seam below the headline, and the stacked phone cards
 * re-form as aligned table rows. A phone reads one item at a time; a
 * desktop is being used to compare them, so the columns have to line up.
 * ========================================================================= */
@media (min-width: 900px) and (min-height: 600px) {

  /* The desk masthead owns the top edge; the View as bar takes the bottom. */
  .viewas-bar { position: fixed; inset: auto 0 0 0;
    padding: 8px var(--pad) calc(8px + env(safe-area-inset-bottom)); }
  html.viewing body { padding-bottom: 56px; }

  /* ---------- 0 · TOKENS -------------------------------------------------- */
  :root {
    --nav-h: 56px;
    --dpad: 26px;              /* padding inside panels */
    --gut: 20px;               /* gap between table columns */
    --panel-r: 16px;
    --row-h: 58px;
    --ground: #EAE8E3;         /* deeper than --paper so white panels lift */
    --chip-bg: #F1EFEB;
    /* The phone's #6E6E6E was picked to clear 4.5:1 on #F2F2F2. This ground
       is darker, which drops the same grey to 4.16 — so it is nudged here,
       and only here, to keep every muted line on the page background at AA. */
    --muted: #656565;
    --lift: 0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 8px rgba(0, 0, 0, 0.05);
    /* the quieter step for reference panels; was referenced but undefined,
       which CSS answers with box-shadow:none and no error */
    --lift-2: 0 1px 2px rgba(0, 0, 0, 0.04), 0 2px 6px rgba(0, 0, 0, 0.04);
    /* One shell width shared by Today and the masthead, so the tabs stay on
       the same line as the headline when the shell widens for the desk. */
    --shell: 1100px;
  }
  body { background: var(--ground); }
  /* The masthead is fixed, so a row tabbed to from below would scroll up
     underneath it and take the focus ring with it (WCAG 2.2 "Focus Not
     Obscured"). Reserve its height against every scroll-into-view. It is
     the nav moved to the top, so the phone's room at the foot goes. */
  html { scroll-padding-top: calc(var(--nav-h) + 10px); scroll-padding-bottom: 0; }

  /* ---------- 1 · PAGE ----------------------------------------------------
     One named-line grid per screen. `full` spans the window so the ink band
     can paint corner to corner; `main` is the measure everything else obeys.
     --rail-x is that same inset expressed as padding, so a full-bleed band's
     text starts exactly where the column starts. */
  .screen {
    --main: 1100px;
    --rail-x: max(28px, calc((100% - var(--main)) / 2));
    max-width: none;
    padding: 0 0 72px;
    display: grid;
    align-content: start;
    grid-template-columns:
      [full-start] minmax(28px, 1fr)
      [main-start] minmax(0, var(--main)) [main-end]
      minmax(28px, 1fr) [full-end];
  }
  .screen > * { grid-column: main; min-width: 0; }
  .screen.withnav { padding-top: var(--nav-h); }

  /* Each screen is a different job, so each gets its own measure. A log form
     at 1100px would run a 16px input across a metre of glass. */
  #scr-today { --main: var(--shell); }
  #scr-moves { --main: 900px; }
  #scr-log   { --main: 620px; }
  #scr-login { --main: 460px; }
  #scr-notes { --main: 620px; }
  #scr-qt    { --main: 620px; }   /* its sibling under DN/CN: no jump between the two */

  /* ---------- 2 · MASTHEAD ------------------------------------------------
     The bottom tab bar becomes the top masthead. A thumb reaches the bottom
     of a phone; a cursor starts at the top of a window, and every other
     desktop tool this team uses puts its tabs there. */
  #nav {
    inset: 0 0 auto 0;
    background: var(--ink);
    border-top: 0;
    padding-bottom: 0;
    height: var(--nav-h);
  }
  #nav .nav-inner {
    max-width: none;
    height: var(--nav-h);
    /* less the pill's own 14px inset, so the first tab's TEXT — not the
       highlight behind it — starts on the same line as the headline below */
    padding: 0 calc(max(28px, (100% - var(--shell)) / 2) - 14px);
    align-items: center;
    gap: 4px;
  }
  #nav button {
    flex: 0 0 auto;
    min-height: 40px;
    flex-direction: row;
    gap: 9px;
    padding: 0 14px;
    border-radius: var(--pill);
    font-size: 13.5px;
    color: rgba(255, 255, 255, 0.62);
    transition: background var(--speed) ease, color var(--speed) ease;
  }
  #nav button svg { width: 17px; height: 17px; }
  #nav button:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
  /* The phone marks the active tab by putting yellow behind its LABEL only,
     because the icon sits above it. Side by side that would underline half a
     control, so the whole pill lights instead. */
  #nav button span:last-child { padding: 0; border-radius: 0; }
  #nav button.on,
  #nav button.on:hover { background: var(--yellow); color: var(--ink); }
  #nav button.on span:last-child { background: none; }

  /* ---------- 3 · HEADLINE BAND ------------------------------------------ */
  .hero-head {
    grid-column: full;
    margin: 0;
    padding: 26px var(--rail-x) 72px;   /* tiles straddle the lower space */
  }
  .hero-head.tight { padding-bottom: 30px; }
  .hero-head.norow:not(.tight) { padding-bottom: 84px; }
  .hero-top { align-items: flex-start; }
  .hero-head h1 { font-size: 32px; letter-spacing: -0.022em; }
  .hero-head #greet-sub,
  .hero-head .hero-sub { font-size: 14px; max-width: 62ch; }
  .hero-head .who { flex-direction: row; align-items: center; gap: 12px; }
  /* Masthead: product | tabs | account. Three small tabs alone at the far
     left of a 1500px black bar is what made the top read as empty — the
     account block is moved up here by Desk.mount() rather than restyled. */
  #nav .nav-inner { display: flex; align-items: center; gap: 6px; }
  .desk-brand {
    flex: none; margin-right: 26px;
    font-size: 16px; font-weight: 750; letter-spacing: -0.02em; color: #fff;
  }
  #nav .who {
    margin-left: auto; display: flex; flex-direction: row; align-items: center;
    gap: 12px; flex: none;
  }
  #nav .who .avatar { width: 32px; height: 32px; font-size: 12.5px; }
  #nav .who .linkbtn {
    color: rgba(255, 255, 255, 0.75); font-size: 13px; white-space: nowrap;
    padding: 10px 0; margin: 0; min-height: 44px;
  }
  #nav .who .linkbtn:hover { color: #fff; opacity: 1; }
  .hero-head .avatar { width: 40px; height: 40px; font-size: 14.5px; }
  /* Site chips never fill on desktop: the fill rule exists to make a short
     row look deliberate on a 375px screen, and at 1100px it stretches four
     chips into four yellow-bordered slabs. */
  .chips.hero-chips.fill .chip { flex: 0 0 auto; max-width: none; }
  .hero-chips { margin-top: 18px; }

  /* The desk's rail lists every site with live counts; the phone chip row
     directly above it said the same thing a second time, in yellow. Today
     only — Moves and DN/CN have no rail and keep their chips. */
  #scr-today .hero-chips { display: none; }

  /* ---------- 4 · FIGURE TILES (straddle the band) ----------------------- */
  .stats { gap: 16px; margin: 0; }
  .stats.float { margin-top: -60px; }
  .stat {
    background: #fff;
    border: 0;
    border-top: 3px solid transparent;
    border-radius: var(--panel-r);
    box-shadow: var(--lift);
    padding: 17px 20px 16px;
    text-align: left;
  }
  .stat .num { font-size: 28px; letter-spacing: -0.025em; }
  /* Kept at the phone's 12px rather than shrunk to fit a desktop's idea of a
     micro-label: this is the word that says what the number means, and the
     type scale in this file has no step below 12. */
  .stat .lbl { letter-spacing: 0.085em; margin-top: 5px; }
  .stat.s-stale   { border-top-color: var(--acc-wine); }
  .stat.s-undated { border-top-color: var(--acc-blue); }
  .stat.s-in      { border-top-color: var(--acc-gold); }
  .stat.zero      { border-top-color: transparent; }
  /* Fourth tile, desktop only: the share of closed items that made their own
     deadline. It carries a second line naming the denominator, because a bare
     percentage invites a question the tile should already have answered. */
  .stat.s-ontime  { border-top-color: var(--acc-blue); }
  .stat .sub {
    display: block; margin-top: 3px;
    font-size: 11.5px; line-height: 1.35; color: var(--muted);
    font-variant-numeric: tabular-nums;
  }

  /* ---------- 5 · CONTROLS ROW -------------------------------------------
     Search and the Open/On hold/Done segments share one row. Both are given
     a definite column and left to auto-place: the segments land beside the
     search because that cell is the first one free. Deliberately NOT an
     explicit `grid-row` — numbering the rows would make the whole screen
     depend on how many siblings happen to render above it. */
  .toolbar { margin: 26px 0 0; }
  /* The two inner columns must sum to exactly --main, or the controls row
     stops lining up with the band above it: the outer gutters are 1fr, so
     anything that changes the inner total moves them. Hence a fixed width
     for the segments column and no column-gap — not `auto`, which would let
     a longer word in copy.js quietly drag the whole column out of line. */
  #scr-today {
    grid-template-columns:
      [full-start] minmax(28px, 1fr)
      [main-start] minmax(0, calc(var(--main) - 300px)) [mid] 300px [main-end]
      minmax(28px, 1fr) [full-end];
    column-gap: 0;
  }
  #scr-today > * { grid-column: main-start / main-end; }
  #scr-today > .hero-head { grid-column: full; }
  #scr-today > .toolbar { grid-column: main-start / mid; max-width: 460px; }
  #scr-today > #today-segs {
    grid-column: mid / main-end;
    align-self: center;
    justify-self: end;
    margin: 26px 0 0;
  }

  /* ---------- 6 · THE LIST BECOMES A PANEL ------------------------------- */
  .cards {
    margin: 22px 0 0;
    background: #fff;
    border-radius: var(--panel-r);
    box-shadow: var(--lift);
    /* `clip` not `hidden`: hidden makes this a scroll container, which kills
       position:sticky on the column header inside it. clip still rounds the
       corners off the first and last row. */
    overflow: clip;
  }
  .cards li { margin-bottom: 0; }
  /* The section labels are list items among the rows, so on desktop they
     read as the table's own subheads rather than captions floating above it. */
  .cards .listhead {
    margin: 0;
    padding: 15px var(--dpad) 11px;
    background: #FBFAF8;
    border-bottom: 1px solid var(--line);
    letter-spacing: 0.085em;
  }
  .cards li:not(:first-child) .listhead { border-top: 1px solid var(--line); }

  /* ---------- 7 · THE DESK ------------------------------------------------
     Three columns: every site you cover, the queue, and the full record of
     whichever row the cursor is on. The phone has the data for all of this
     and room for none of it. Markup is built by Desk.mount() in app.js and
     removed again below 900px, so index.html carries no trace of it. */
  /* WCAG 2.2 AA "focus not obscured": the masthead and the queue's column
     header are both sticky, so a row scrolled to by keyboard would otherwise
     land underneath them. Reserve their combined height on every scroll. */
  html { scroll-padding-top: calc(var(--nav-h) + 48px); }

  #desk-work {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    column-gap: 20px;
    align-items: start;
    margin-top: 22px;
  }
  #desk-pane { display: none; }
  /* The record pane appears at 1280, not 1440: a 13" laptop in a windowed
     browser sits below 1440, and that is the machine the managers carry.
     Today's shell widens with it — three columns inside 1100px leaves the
     queue 484px, which is narrower than its own columns and squeezes the
     names it is forbidden to truncate. */
  @media (min-width: 1280px) {
    :root { --shell: min(1560px, calc(100vw - 64px)); }
    #desk-work {
      grid-template-columns: 210px minmax(0, 1fr) 320px;
      column-gap: 16px;
    }
    #desk-pane { display: block; }
  }
  @media (min-width: 1560px) {
    #desk-work {
      grid-template-columns: 236px minmax(0, 1fr) 380px;
      column-gap: 20px;
    }
  }

  #desk-work .cards { margin: 0; }
  #desk-mid .approvals { margin: 0 0 14px; }
  #desk-mid .pushcard  { margin: 0 0 14px; }
  .desk-head {
    margin: 0; padding: 15px var(--dpad) 4px;
    font-size: 12px; font-weight: 650; letter-spacing: 0.085em;
    text-transform: uppercase; color: var(--muted);
  }
  .desk-hint {
    margin: 0; padding: 0 var(--dpad) 12px;
    font-size: 12.5px; line-height: 1.5; color: var(--muted);
  }

  /* ---- rail ---- */
  #desk-rail, #desk-pane {
    /* These scroll once a manager covers enough sites. Without the padding a
       focus ring on the row flush with the top edge is sliced by the clip. */
    scroll-padding: 6px 0;
    position: sticky; top: calc(var(--nav-h) + 20px);
    max-height: calc(100dvh - var(--nav-h) - 40px);
    overflow-y: auto; overscroll-behavior: contain;
    background: #fff; border-radius: var(--panel-r); box-shadow: var(--lift);
  }
  .desk-sites { list-style: none; margin: 0; padding: 0 10px 10px; }
  .desk-site {
    width: 100%; display: block; text-align: left;
    padding: 9px 12px; margin-bottom: 2px;
    border: 0; border-radius: 10px; background: none;
    transition: background var(--speed) ease;
  }
  .desk-site:hover { background: var(--paper); }
  /* Selection is an ink field, never yellow — yellow is the action signal and
     a list of sites is not an action. */
  .desk-site.on { background: var(--ink); }
  .desk-site.on .desk-site-code { color: #fff; }
  .desk-site.on .desk-n { color: rgba(255, 255, 255, 0.9); }
  .desk-site.on .desk-n.nil { color: rgba(255, 255, 255, 0.5); }
  .desk-site.on .desk-site-sub { color: rgba(255, 255, 255, 0.6); }
  /* One labelled numeric column. Its header sits above the rail rows so the
     figure is never a bare number in a box. */
  .desk-site-colhead {
    display: flex; justify-content: space-between; align-items: baseline;
    padding: 2px 12px 6px; margin-bottom: 2px;
    border-bottom: 1px solid var(--line);
    font-size: 10.5px; font-weight: 650; letter-spacing: 0.085em;
    text-transform: uppercase; color: var(--muted);
  }
  .desk-site-top { display: flex; align-items: baseline; gap: 6px; }
  .desk-site-code {
    flex: 1; min-width: 0; font-size: 14px; font-weight: 700; color: var(--ink);
    overflow-wrap: anywhere;
  }
  .desk-n {
    flex: none; min-width: 26px; text-align: right;
    font-size: 15px; font-weight: 700; color: var(--ink);
    font-variant-numeric: tabular-nums;
  }
  /* A zero is de-emphasised by weight, not by a paler grey: #9A9A9A measured
     2.81:1 and this dash still has to be read as "none". */
  .desk-n.nil  { color: var(--muted); font-weight: 500; }
  .desk-site-sub {
    margin: 3px 0 0; font-size: 11.5px; line-height: 1.4; color: var(--muted);
    font-variant-numeric: tabular-nums;
  }

  /* ---- queue ---- */
  /* Four columns, not five: "quiet for" rides under the person's name rather
     than claiming a column of its own. One column set at every desktop width,
     so there is no responsive rule to get wrong. */
  .desk-colhead, .desk-row {
    display: grid;
    /* Track floor must clear the middle column at EVERY width the desk is
       mounted, including its own entry width. .cards is overflow:clip (so the
       sticky header survives), which means an overflowing row is cut off, not
       scrolled — at 900px the Deadline column used to render as "2d le". */
    grid-template-columns: 96px minmax(180px, 1fr) 124px 100px;
    column-gap: 16px;
  }
  /* 900-1023: two columns, middle = viewport - 296. Floor here is
     104+140+112+88 + 36 gaps + 32 padding = 512, against 604 available. */
  @media (max-width: 1023px) {
    .desk-colhead, .desk-row {
      grid-template-columns: 84px minmax(140px, 1fr) 108px 88px;
      column-gap: 12px;
      padding-left: 16px;
      padding-right: 16px;
    }
  }
  .desk-colhead span:nth-child(4) { display: none; }   /* "Quiet for" */
  /* Group rows: "Handed to you (2)" / "Open items". Ink, not yellow —
     it is where you are, not what to press. */
  .desk-grouphead {
    padding: 11px var(--dpad) 7px; background: #fff;
    border-bottom: 1px solid var(--line-soft, var(--line));
    font-size: 12.5px; font-weight: 700; letter-spacing: 0.02em; color: var(--ink);
  }
  .tag-handed {
    display: inline-block; margin: 0 8px 4px 0; padding: 2px 8px;
    border-radius: var(--pill); background: var(--ink); color: #fff;
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  }
  /* A handover note. An ink outline beside the filled "Handed to you" chip:
     it says what the row is, not what to press, so it is never yellow. The
     1px border takes the place of 1px of padding, so both chips are the same
     size. */
  .tag-note {
    display: inline-block; margin: 0 8px 4px 0; padding: 1px 7px;
    border: 1px solid var(--ink); border-radius: var(--pill); color: var(--ink);
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  }
  .desk-pane-meta .tag-note { margin: 0; }
  /* "Coming up (n)": a group row that is also the button that unfolds it.
     The whole band is the target; the chevron turns when it is open. */
  .desk-grouphead.desk-soon { padding: 0; }
  .desk-soon button {
    display: flex; align-items: center; gap: 6px;
    width: 100%; min-height: 44px; margin: 0; padding: 0 var(--dpad);
    border: 0; background: none; text-align: left;
    font: inherit; letter-spacing: inherit; color: var(--ink);
    transition: background var(--speed) ease;
  }
  .desk-soon button:hover { background: #FAF9F6; }
  .desk-soon button:active { background: #F4F3EF; }
  /* .cards clips its overflow, so the ring goes inside, as on the rows */
  .desk-soon button:focus-visible { outline-offset: -3px; }
  .desk-soon svg { width: 16px; height: 16px; flex: none; transition: transform var(--speed) ease; }
  .desk-soon button[aria-expanded="true"] svg { transform: rotate(180deg); }
  .desk-where, .desk-item, .desk-due { grid-row: 1 / span 2; }
  .desk-by { grid-column: 3; grid-row: 1; }
  .desk-quiet { grid-column: 3; grid-row: 2; }
  .desk-colhead {
    position: sticky; top: var(--nav-h); z-index: 3;
    align-items: center; height: 36px; padding: 0 var(--dpad);
    background: #FBFAF8; border-bottom: 1px solid var(--line);
    font-size: 12px; font-weight: 650; letter-spacing: 0.085em;
    text-transform: uppercase; color: var(--muted);
  }
  .desk-colhead span:nth-child(4),
  .desk-colhead span:nth-child(5) { text-align: right; }

  .desk-row {
    align-items: start;
    min-height: var(--row-h); padding: 12px var(--dpad);
    background: none; border: 0; border-bottom: 1px solid var(--line);
    border-radius: 0; text-align: left; position: relative;
    box-shadow: inset 3px 0 0 var(--accent, transparent);
    transition: background var(--speed) ease;
  }
  #today-list li:last-child .desk-row { border-bottom: 0; }
  .desk-row::before { content: none; }
  .desk-row:hover { background: #FAF9F6; }
  .desk-row:active { transform: none; background: #F4F3EF; }
  .desk-row:focus-visible { outline-offset: -3px; }
  /* The row the pane is showing. Ink marker, not yellow. */
  .desk-row.on { background: #F4F3EF; box-shadow: inset 3px 0 0 var(--ink); }
  /* A note row. The phone edges a note in ink, but on the desk an ink edge
     already means "the row the pane is showing": a queue of ink-edged notes
     would read as several selected rows. So a note takes the grey step, and
     the NOTE chip says what it is. Selected, it turns ink like any row. */
  .desk-row.acc-note { --accent: var(--muted); }

  .desk-where { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .desk-site-tag {
    align-self: flex-start; padding: 2px 8px; border-radius: 7px;
    background: var(--chip-bg); color: var(--text);
    font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  }
  /* Kitchens and licensees wrap. They are never clipped — this is the column
     a person scans to find their own room. */
  .desk-kitchen {
    font-size: 12.5px; font-weight: 600; color: var(--text);
    line-height: 1.35; overflow-wrap: anywhere;
  }
  .desk-item { min-width: 0; }
  .desk-item .newdot { display: inline-block; margin: 0 6px 2px 0; }
  .desk-task {
    font-size: 15px; font-weight: 700; line-height: 1.35; color: var(--ink);
    overflow-wrap: anywhere;
  }
  /* next_action has never been printed in any list, on any device. It is the
     one line that says what happens next without opening anything. */
  .desk-next {
    margin-top: 5px; font-size: 12.5px; line-height: 1.45; color: var(--text);
    overflow-wrap: anywhere;
  }
  /* Same reason — #8A8A8A was 3.45:1 on a real sentence. */
  .desk-next.none { color: var(--muted); font-style: italic; }
  .desk-next-k {
    display: inline-block; margin-right: 6px;
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em;
    text-transform: uppercase; color: var(--muted);
  }
  .desk-by {
    font-size: 12.5px; font-weight: 600; color: var(--text);
    line-height: 1.35; overflow-wrap: anywhere;
  }
  .desk-quiet {
    margin-top: 2px; font-size: 11.5px; color: var(--muted);
    font-variant-numeric: tabular-nums;
  }
  .desk-due {
    display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
  }
  .desk-due .badge { margin-left: 0; }

  /* ---- pane ---- */
  .desk-empty {
    margin: 0; padding: 28px var(--dpad); color: var(--muted);
    font-size: 13.5px; line-height: 1.55;
  }
  .desk-pane-head { padding: 18px var(--dpad) 14px; border-bottom: 1px solid var(--line); }
  .desk-pane-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .desk-pane-head h2 {
    margin: 9px 0 0; font-size: 20px; line-height: 1.3;
    overflow-wrap: anywhere;
  }
  .desk-pane-next {
    margin: 14px var(--dpad) 0; padding: 11px 13px;
    background: var(--paper); border-radius: 10px;
  }
  .desk-pane-next p { margin: 0; font-size: 14px; line-height: 1.5; overflow-wrap: anywhere; }
  .desk-pane-next .desk-next-k { display: block; margin-bottom: 4px; }

  .desk-facts {
    margin: 0; padding: 0 var(--dpad) 6px;
    display: grid; grid-template-columns: auto 1fr; gap: 5px 14px;
    font-size: 13px;
  }
  .desk-facts dt { color: var(--muted); }
  .desk-facts dd { margin: 0; color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }

  /* The whole signed history, oldest first. The phone card shows the last
     line only; on a five-entry item that is four invisible entries. */
  .desk-trail { list-style: none; margin: 0; padding: 0 var(--dpad) 8px; }
  .desk-trail li {
    display: grid; grid-template-columns: 62px 1fr; gap: 10px;
    padding: 9px 0; border-top: 1px solid var(--line);
  }
  .desk-trail li:first-child { border-top: 0; }
  .desk-trail li.last .desk-trail-b { box-shadow: inset 2px 0 0 var(--ink); padding-left: 9px; }
  .desk-trail-d {
    font-size: 11.5px; color: var(--muted); line-height: 1.5;
    font-variant-numeric: tabular-nums;
  }
  .desk-trail-b p { margin: 2px 0 0; font-size: 13.5px; line-height: 1.5; overflow-wrap: anywhere; }
  .desk-trail-by { font-size: 12.5px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
  .desk-handed {
    display: inline-block; margin-top: 6px; padding: 3px 9px;
    border: 1px solid var(--ink); border-radius: var(--pill);
    font-size: 12px; font-weight: 600;
  }
  .desk-handed .desk-next-k { margin-right: 4px; }

  .desk-media {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
    padding: 0 var(--dpad) 12px;
  }
  .desk-media .mtile { width: auto; }

  /* Up to five buttons: a note's four plus a manager's "Mark as issue", or an
     issue's four plus "Mark as note". Stacked one per line that was 280px of
     sticky footer, over half the pane on a 600px-tall screen. Two to a row
     with the primary alone on top is three rows; an odd one out fills its
     row rather than sitting at half width. A label never breaks inside its
     pill: "Raise a DN / CN" did, in a 320px pane with a scrollbar. Unwrapped,
     it takes the few pixels it needs from its neighbour instead. */
  .desk-acts {
    position: sticky; bottom: 0;
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 12px var(--dpad) 16px;
    background: #fff; border-top: 1px solid var(--line);
  }
  .desk-acts .btn { flex: 1 1 40%; margin-top: 0; min-height: 44px; font-size: 15px; white-space: nowrap; min-width: 0; }
  .desk-acts .btn.primary { flex-basis: 100%; }
  .desk-acts .btn.hist-btn { flex-basis: 100%; }   /* the place name needs the room */


  /* ---- deadline spread, filter pills, and the two reference panels -------
     Colour rule held here: gold and olive measure under 4.5:1 on white, so
     they are used as FILLS in the bar only. Every legend figure is ink,
     muted or wine, all of which carry text. */
  .desk-mid { min-width: 0; }
  #desk-spread {
    background: #fff; border-radius: var(--panel-r); box-shadow: var(--lift-2);
    padding: 0 0 12px; margin-bottom: 16px;
  }
  #desk-spread:empty { display: none; }
  .desk-spread-bar {
    display: flex; gap: 2px; height: 10px; margin: 2px var(--dpad) 10px;
    border-radius: 999px; overflow: hidden;
  }
  .desk-spread-bar .sp { display: block; min-width: 2px; }
  .sp.s-over { background: var(--acc-wine); }
  .sp.s-d3   { background: var(--acc-gold); }
  .sp.s-d7   { background: var(--acc-olive); }
  .sp.s-d20  { background: var(--acc-blue); }
  .sp.s-d45  { background: #C4C4C4; }
  .sp.s-none { background: #DEDEDE; }

  .desk-spread-keys {
    display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 6px; padding: 0 var(--dpad);
  }
  .spk {
    display: flex; flex-direction: column; gap: 1px; align-items: flex-start;
    padding: 7px 9px; border: 1px solid var(--line); border-radius: 9px;
    background: none; text-align: left;
    transition: background var(--speed) ease, border-color var(--speed) ease;
  }
  .spk:hover { background: var(--paper); }
  /* Selected is an ink outline, never yellow — a filter is not the action. */
  .spk.on { border-color: var(--ink); background: var(--paper); }
  .spk-n {
    font-size: 16px; font-weight: 700; color: var(--ink);
    font-variant-numeric: tabular-nums; line-height: 1.1;
  }
  .spk.s-over .spk-n { color: var(--acc-wine); }
  .spk.nil .spk-n { color: var(--muted); font-weight: 650; }
  .spk-l { font-size: 10.5px; line-height: 1.25; color: var(--muted); overflow-wrap: anywhere; }

  /* The only desk text on the page field (#EAE8E3) rather than a white panel.
     --muted is #656565 here and measures 4.76:1; the root #6E6E6E would give
     4.03 and fail. Do not let this inherit the root value. */
  #desk-count {
    margin: 0 0 10px; font-size: 12.5px; color: var(--muted);
    font-variant-numeric: tabular-nums;
  }
  #desk-count:empty { display: none; }
  /* The desk writes its message into the empty state's <p> and shows it as
     plain text, as it always has here. The icon and the <p> stay in the DOM
     for the phone list that a resize brings back. */
  #desk-mid #today-empty svg { display: none; }
  #desk-mid #today-empty .bigmsg { font: inherit; letter-spacing: inherit; }
  #desk-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
  .desk-pill {
    display: inline-flex; align-items: center; gap: 7px;
    min-height: 34px; padding: 6px 12px;
    border: 1px solid var(--ink); border-radius: var(--pill);
    background: #fff; font-size: 13px; font-weight: 600; color: var(--ink);
    transition: background var(--speed) ease;
  }
  .desk-pill:hover { background: var(--paper); }
  .desk-pill .x { font-size: 15px; line-height: 1; color: var(--muted); }
  .desk-pill.clearall { border-style: dashed; color: var(--text); }

  #desk-strip {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px; margin-top: 16px; align-items: start;
  }
  .desk-panel {
    background: #fff; border-radius: var(--panel-r); box-shadow: var(--lift-2);
    padding-bottom: 8px;
  }
  .desk-panel:empty { display: none; }
  .desk-mini { list-style: none; margin: 0; padding: 0 10px; }
  .desk-mini-row {
    display: block; width: 100%; text-align: left;
    padding: 9px 10px; margin-bottom: 2px;
    border: 0; border-radius: 9px; background: none;
    transition: background var(--speed) ease;
  }
  .desk-mini-row:hover { background: var(--paper); }
  .desk-mini-row.on { background: var(--ink); }
  .desk-mini-row.on .desk-person,
  .desk-mini-row.on .desk-mini-task { color: #fff; }
  .desk-mini-row.on .desk-mini-sub { color: rgba(255, 255, 255, 0.72); }
  .desk-mini-row.on .desk-mini-sub .over { color: #E9AEB6; }
  .desk-mini-top { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-bottom: 3px; }
  /* Two lines. This is a summary panel, and one real entry — a paragraph
     about a gas supply call — was long enough to push everything else off
     the screen. The full text is one click away in the record pane.
     NOTE: this clamps a fault DESCRIPTION, never a kitchen, licensee or
     person name; those still wrap in full everywhere. */
  .desk-mini-task {
    margin: 0; font-size: 13.5px; font-weight: 650; line-height: 1.35;
    color: var(--ink); overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden;
  }
  .desk-person {
    margin: 0; font-size: 14px; font-weight: 700; color: var(--ink);
    line-height: 1.3; overflow-wrap: anywhere;
  }
  .desk-mini-sub {
    margin: 3px 0 0; font-size: 11.5px; line-height: 1.4; color: var(--muted);
    font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
  }
  .desk-mini-sub .over { color: var(--acc-wine); font-weight: 650; }

  /* ---------- 8 · MOVES --------------------------------------------------- */
  #mv-list .card.mvcard {
    display: flex; align-items: center; gap: 18px;
    margin: 0; padding: 13px var(--dpad);
    background: none; border: 0; border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: inset 3px 0 0 var(--accent, transparent);
  }
  #mv-list .card.mvcard::before { content: none; }
  #mv-list li:last-child .card.mvcard { border-bottom: 0; }
  #mv-list .mv-body .title { font-size: 15px; }
  #mv-renewals { margin-top: 22px; }
  /* Catering reads as the Moves table does: one row per order in a panel.
     The inset shadow is the accent edge; the card's own stripe goes. */
  #scr-catering { --main: 900px; }
  #ct-list .card {
    margin: 0; padding: 14px var(--dpad);
    background: none; border: 0; border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: inset 3px 0 0 var(--accent, transparent);
  }
  #ct-list .card::before { content: none; }
  #ct-list li:last-child .card { border-bottom: 0; }
  #ct-list .ct-dayhead { margin: 0; padding: 12px var(--dpad) 6px; }
  #ct-list .comingup { padding: 0 var(--dpad); min-height: 48px; }

  /* ---------- 9 · FORMS AND SHEETS --------------------------------------- */
  /* The log form and every bottom sheet keep a reading measure. A sheet that
     spans 1100px puts its Cancel button a screen-width from its Save. Every
     screen that carries a button is already ≤620px wide, so the buttons need
     no cap of their own — one tried here made Close narrower than the action
     row directly above it, which read as a mistake rather than a hierarchy. */
  #sheet { max-width: 620px; inset: auto 0 6vh 0; }

  /* ---------- 10 · LOGIN -------------------------------------------------- */
  .screen.login { display: grid; padding-bottom: 0; }
  .login-hero {
    grid-column: full;
    padding: 64px var(--rail-x) 46px;
  }
  .login-card {
    margin-top: -18px;
    border-radius: 24px;
    padding: 26px 26px 34px;
    box-shadow: var(--lift);
    background: #fff;
  }
  .namelist button, .recentlist button.recent { background: #fff; }
  .namelist button:hover, .recentlist button.recent:hover { background: var(--paper); }
}

/* The [hidden] attribute must always win — twice now a display rule on a
 * specific selector has outranked the UA default and resurrected a
 * hidden screen. Never again. */
[hidden] { display: none !important; }

/* ---- pressed states: a phone has no hover -------------------------------- */
/* Feedback inside 150ms of the finger landing, before any network answers.
   transform+background only, so nothing around the control moves. */
/* Colour keeps the theme's 180ms; only the press transform is faster, so a
   tap answers inside 150ms while hovers fade at the pace the guide set. */
.chip, .card, .namelist button, .recentlist button.recent, .btn, #nav button, .comingup {
  transition: background var(--speed) ease, border-color var(--speed) ease,
              color var(--speed) ease, transform 120ms ease;
}
.chip:active { transform: scale(0.97); }
.card:active { background: #F4F4F4; transform: scale(0.99); }
.comingup:active { transform: scale(0.99); }
.namelist button:active, .recentlist button.recent:active { background: #ECECEC; transform: scale(0.99); }
.btn:active { transform: scale(0.97); }
#nav button:active span:first-child { transform: scale(0.9); }
#nav button span:first-child { transition: transform 120ms ease; }

/* ---- pick list: one tap per row, used by the site sheet and the
       handover sheet. Both answer the same question — which one? --- */
.picklist { list-style: none; margin: 0 0 4px; padding: 0; }
.picklist .grouphead {
  font-size: 12px; font-weight: 650; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--muted);
  padding: 14px 0 6px;
}
.picklist button {
  width: 100%; display: block; min-height: 52px; padding: 14px; text-align: left;
  border: 0; background: none; border-radius: var(--radius);
  font-size: 16px; font-weight: 600; color: var(--text);
}
.picklist button:hover { background: var(--paper); }
.picklist button.on { background: var(--ink); color: var(--bright); }

/* A zero is always muted, whichever accent family the tile belongs to.
   (.stat.s-in .num used to repaint "0 Moving in" gold from later in the
   sheet.) Stated last so source order decides. */
.stat.zero .num { color: var(--muted); }

/* ---- kitchen on/offboarding checklists (js/kitchen.js) --------------------- */
/* A checklist's own screens (redesign, 5 Oct 2026): the way back sits in the
   ink hero, as on the licensee pages, and is 44 px to the thumb. */
:is(#kcn-back, #kcf-back, #kcd-back) { min-height: 44px; }
/* New checklist: one form anatomy. The kind is one joined control across
   the width; the kitchen, picked from a sheet, is drawn as the field it is,
   with the select's chevron; Start is the one primary, clear of the fields. */
#kcn-kind.chips.seg { display: flex; width: 100%; }
#kcn-kind.chips.seg .chip { flex: 1 1 0; min-width: 0; }
#kcn-sites .chip { min-width: 64px; }
#kcn-kitchen {
  display: flex; align-items: center; min-height: var(--h-control); margin-top: 0;
  padding: 0 44px 0 16px; text-align: left;
  font-size: var(--fs-body); font-weight: 500; letter-spacing: 0; color: var(--ink);
  border: 1.5px solid var(--field-edge); border-radius: var(--radius);
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5l6 6 6-6' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 18px center;
}
#kcn-kitchen.unset { color: var(--muted); }
#kcn-kitchen:active:not(:disabled) { transform: none; }
#kcn-hint { margin: 6px 0 0; font-size: var(--fs-meta); line-height: 1.45; }
#kcn-go { margin-top: var(--s6); }
.kc-sec { margin-top: 12px; }
.kc-sec h2 {
  margin: 0 0 4px; font-size: 12.5px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.kc-note {
  margin: 12px 0 0; padding: 10px 12px; font-size: 14px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
}
/* A kitchen's floor plans: one link, or one per drawing of joined kitchens. */
.kc-plans { display: grid; gap: 8px; margin-top: 16px; }
.kc-plans .kc-note, .kc-plans a.btn { margin: 0; }
.kc-plans a.btn { padding: 6px 14px; }   /* one line from 360 px; two at 280 px keep clear of the pill's ends */
/* The PDF and the survey link are anchors: centred like the buttons beside them. */
#kcf-body a.btn, #kcd-body a.btn {
  display: flex; align-items: center; justify-content: center;
  color: var(--ink); text-decoration: none; text-align: center;
}
.kc-hint { margin: 6px 0 0; }
.kc-tilewrap { margin-top: 18px; }
.kc-tile {
  display: block; width: 100%; padding: 0; text-align: left;
  background: var(--bright); border: 1.5px dashed #BDBDBD; border-radius: var(--radius);
  overflow: hidden; font: inherit; color: inherit;
}
.kc-tile.failed { border-color: var(--acc-wine); }
.kc-tile-img { position: relative; aspect-ratio: 16 / 9; background: var(--paper); display: grid; place-items: center; }
.kc-tile.sig .kc-tile-img { aspect-ratio: 3 / 1; background: #fff; }
.kc-tile-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.kc-tile.sig .kc-tile-img img { object-fit: contain; }
.kc-tile-img img[hidden] { display: none; }
.kc-tile-icon { font-size: 28px; color: var(--muted); }
.kc-tile-cap { padding: 8px 12px 0; font-weight: 650; font-size: 15px; }
.kc-tile-state { padding: 2px 12px 9px; font-size: 13px; color: var(--muted); }
.kc-tile.failed .kc-tile-state { color: var(--acc-wine); }
.kc-sig {
  display: block; width: 100%; height: 220px; margin-top: 10px; background: #fff;
  border: 1.5px solid var(--line); border-radius: var(--radius); touch-action: none;
}
.kc-acts { display: flex; gap: 8px; }
.kc-acts .btn { margin-top: 12px; }
.kc-dl { margin: 0; }
.kc-dl dt { margin-top: 8px; font-size: 13px; color: var(--muted); }
.kc-dl dd { margin: 0; font-weight: 650; overflow-wrap: anywhere; }
.kc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; }
.kc-thumb {
  padding: 0; text-align: left; font: inherit; color: inherit;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
}
.kc-thumb .kc-tile-img { aspect-ratio: 4 / 3; }
.kc-cap { padding: 6px 8px; font-size: 12.5px; color: var(--muted); }
.kc-thumb .playmark {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 22px; color: #fff; background: rgba(0, 0, 0, 0.35);
}
/* A photos/video field: the cleaning request's tiles, each opening the viewer. */
.kc-list .mediagrid { margin-top: 4px; }
.kc-count { margin: 2px 0 0; }
.mtile .kc-open { position: absolute; inset: 0; padding: 0; border: 0; background: none; cursor: pointer; }
/* A checklist's photos come three to a row with the remove button in the
   corner: four to a row with the cleaning request's 44px button, a tap on the
   middle of a photo on a 320-390px phone hit "remove" (review, 1 Oct 2026). */
.kc-list .mediagrid { grid-template-columns: repeat(3, 1fr); }
.kc-list .mtile .rm { width: 32px; height: 32px; border-width: 5px; line-height: 22px; font-size: 14px; }
.mtile .kc-open img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* A condition's answers ("Working condition", "Damage found") are longer than
   Yes/No: two halves of the row, each wrapping inside itself, never the pill. */
.chips.seg.kc-choice { display: flex; flex-wrap: nowrap; width: 100%; }
.chips.seg.kc-choice .chip { flex: 1 1 0; min-width: 0; white-space: normal; line-height: 1.2; text-align: center; }
/* A select's reminder ("raise it with M&R") and a returned card's tally.
   Wine, not yellow: yellow is the theme's one signal for an action to tap. */
.kc-warn {
  margin: 8px 0 0; padding: 8px 12px; font-size: 14px; font-weight: 600; color: var(--acc-wine);
  background: var(--paper); border-left: 4px solid var(--acc-wine); border-radius: 4px;
}
.kc-ok { color: var(--muted); }
.kc-bad { color: var(--acc-wine); font-weight: 600; }
/* Complete's preview: the report's own page on white paper, as tall as it is. */
.kc-paper { margin-top: 12px; }
.kc-report {
  display: block; width: 100%; min-height: 60vh; border: 1px solid var(--line);
  border-radius: var(--radius); background: #fff;
}
/* On a move card: one line, tappable, the only way in from the schedule.
   A row of its own under a hairline (redesign, 5 Oct 2026): the state on
   the left, the way in on the right with its chevron, 44 px to the thumb. */
.kc-mvline {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  width: 100%; min-height: 44px; margin: var(--s3) 0 calc(var(--s2) * -1); padding: 0;
  border: 0; border-top: 1px solid var(--line); background: none; text-align: left;
  font: inherit; font-size: var(--fs-sub); font-weight: 600; line-height: 1.3; color: var(--text);
}
.kc-mvline .kc-mvgo { flex: none; color: var(--ink); font-weight: 700; white-space: nowrap; }
.kc-mvline:not(:disabled):hover .kc-mvgo { text-decoration: underline; text-underline-offset: 3px; }

/* ---- CrewBASE Lab · monthly utilities ---------------------------------- */
#scr-lab #lab-segs { width: 100%; margin: 16px 0 14px; }
#scr-lab #lab-segs .chip { flex: 1; }
#scr-lab #lab-segs a.chip { display: flex; align-items: center; justify-content: center; text-decoration: none; }
#scr-lab #lab-segs .chip.on { background: var(--yellow); color: var(--ink); }
#scr-lab #lab-body { padding-bottom: 8px; }
#scr-lab .lab-util-intro { margin: 18px 0 14px; }
#scr-lab .lab-eyebrow {
  margin: 0 0 3px; color: var(--muted); font-size: 11px; font-weight: 750;
  letter-spacing: 0.08em; text-transform: uppercase;
}
#scr-lab .lab-util-title { margin: 0 0 5px; font-size: 24px; }
#scr-lab .lab-state .btn { max-width: 220px; margin-inline: auto; }
#scr-lab .lab-filter-card,
#scr-lab .lab-chart-card {
  margin-top: 12px; padding: 16px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
}
#scr-lab .lab-section-title { margin: 0; font-size: 17px; line-height: 1.2; }
#scr-lab .lab-filter-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 10px; margin-top: 13px;
}
#scr-lab .lab-utility-type {
  grid-column: 1 / -1; min-width: 0; margin: 0; padding: 0; border: 0;
}
#scr-lab .lab-date-range {
  grid-column: 1 / -1; display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
}
#scr-lab .lab-selected-month { grid-column: 1 / -1; }
#scr-lab .lab-field { min-width: 0; }
#scr-lab .lab-utility-type legend,
#scr-lab .lab-field label {
  margin: 0 0 5px; color: var(--muted); font-size: 11px; font-weight: 700;
  letter-spacing: 0.055em; text-transform: uppercase;
}
#scr-lab .lab-utility-type legend { padding: 0; }
#scr-lab .lab-utility-tabs {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  padding: 3px; background: var(--paper); border-radius: 12px;
}
#scr-lab .lab-utility-tabs button {
  min-width: 0; min-height: 46px; padding: 9px 5px;
  border: 0; border-radius: 9px; background: transparent; color: var(--ink);
  font-size: 13px; font-weight: 650;
}
#scr-lab .lab-utility-tabs button.on { background: var(--yellow); }
#scr-lab .lab-utility-tabs button:disabled { color: var(--muted); opacity: 0.48; cursor: not-allowed; }
#scr-lab .lab-utility-tabs button:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
#scr-lab .lab-field select {
  display: block; width: 100%; min-width: 0; min-height: 48px; padding: 10px 11px;
  border: 1.5px solid var(--line); border-radius: 10px;
  background: var(--bright); color: var(--ink); font: inherit; font-size: 14px;
}
#scr-lab .lab-field select:focus { border-color: var(--ink); }
#scr-lab .lab-field select:focus:not(:focus-visible) { outline: none; }
#scr-lab .lab-field select:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
#scr-lab .lab-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
#scr-lab .lab-card-head .small { margin: 3px 0 0; }
#scr-lab .lab-unit {
  flex: none; padding: 4px 9px; border-radius: var(--pill);
  background: var(--paper); color: var(--muted); font-size: 11px; font-weight: 750;
}
#scr-lab .lab-legend { display: flex; flex-wrap: wrap; gap: 7px 14px; margin-top: 13px; }
#scr-lab .lab-legend-item {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0;
  color: var(--text); font-size: 11px; font-weight: 650;
}
#scr-lab .lab-legend-item i { width: 15px; height: 3px; border-radius: var(--pill); background: currentColor; }
#scr-lab .lab-chart-scroll {
  width: 100%; margin-top: 8px; padding-bottom: 3px; overflow-x: auto; overflow-y: hidden;
  overscroll-behavior-inline: contain; scrollbar-width: thin;
}
#scr-lab .lab-chart { display: block; width: 100%; max-width: none; height: auto; overflow: visible; }
#scr-lab .lab-gridline { stroke: var(--line); stroke-width: 1; }
#scr-lab .lab-axis-y,
#scr-lab .lab-axis-x { fill: var(--muted); font-family: inherit; font-size: 9px; font-weight: 600; }
#scr-lab .lab-axis-x.selected { fill: var(--ink); font-weight: 800; }
#scr-lab .lab-value-guide { stroke: #B8B8B8; stroke-width: 0.8; stroke-dasharray: 3 3; }
#scr-lab .lab-value-label {
  fill: var(--ink); font-family: inherit; font-size: 10px; font-weight: 720;
  font-variant-numeric: tabular-nums;
}
#scr-lab .lab-value-label.selected { font-weight: 850; }
#scr-lab .lab-month-mark { fill: var(--yellow); opacity: 0.16; rx: 5px; }
#scr-lab .lab-line { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
#scr-lab .lab-point { fill: #fff; stroke: currentColor; stroke-width: 1.8; }
#scr-lab .lab-point.selected { fill: var(--yellow); stroke: var(--ink); stroke-width: 2; }
#scr-lab .lab-month-hit { fill: transparent; cursor: pointer; }
#scr-lab .lab-month-hit:focus { outline: none; stroke: var(--focus); stroke-width: 2; stroke-dasharray: 4 3; }

@media (max-width: 359px) {
  #scr-lab .lab-filter-grid { grid-template-columns: 1fr; }
  #scr-lab .lab-date-range { grid-template-columns: 1fr; }
}
