/* GENERATED from rebuild/kit/components.css by rebuild/tools/sync-kit.js. Edit the kit, then re-run; never edit this copy. */
/* AIMS rebuild — components. Needs tokens.css first.
   Class names are short and prefixed with nothing on purpose: this sheet replaces styles.css, it does not
   sit beside it. Sections: base · glass · shell · logo switcher · nav · top bar · page head · buttons ·
   segmented · fields · status pills · strips · pipes & tubes · tables · cards & chips · drawer & menus ·
   special controls (slide, code, switch) · loading & empty · phone/touch breakpoints. */

/* ---------------- base ---------------- */
*, *::before, *::after { box-sizing: border-box; }
html { background: var(--bg); transition: background var(--t-wipe); }
body { margin: 0; font: var(--fw-med) var(--fs-m)/1.5 var(--font); color: var(--ink); background: transparent; -webkit-font-smoothing: antialiased; }
a { color: var(--accent-ink); text-decoration: none; }
a:hover { text-decoration: underline; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
input[type=number] { -moz-appearance: textfield; }                        /* typed numbers, no spinners */
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
[hidden] { display: none !important; }   /* any component with its own display still hides */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }

/* the coloured field behind the glass — three soft blobs, product-tinted */
.aurora { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
.aurora i { position: absolute; border-radius: 50%; filter: blur(110px); transition: background var(--t-wipe), opacity var(--t-wipe); }
.aurora i:nth-child(1) { width: 820px; height: 600px; left: 46%; top: -260px; background: var(--aura-1); opacity: var(--aura-o1); }
.aurora i:nth-child(2) { width: 680px; height: 580px; left: -220px; top: 32%; background: var(--aura-2); opacity: var(--aura-o2); }
.aurora i:nth-child(3) { width: 620px; height: 520px; left: 62%; top: 62%; background: var(--aura-3); opacity: var(--aura-o3); }

/* ---------------- glass ---------------- */
.glass { position: relative; background: linear-gradient(150deg, var(--glass-a), var(--glass-b));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  border: 1px solid var(--glass-edge); border-radius: var(--r-xl); box-shadow: var(--shadow); }
.pad { padding: var(--pad); }
.stack:not(table) { display: flex; flex-direction: column; gap: var(--gap); }   /* not a table: 2.x phone-tables.js stamps table.stack for its phone cards */

/* ---------------- icons: <svg class="i"> is 17 px; a few fixed steps for smaller and bigger spots ---------------- */
.i { width: 17px; height: 17px; flex: none; }
.i.in-text { width: 1.05em; height: 1.05em; vertical-align: -.17em; }   /* inside a line of words (↻ ↩'s icons, w21platform): the letters' size, on their line; a size class below still wins */
.i.s11 { width: 11px; height: 11px; } .i.s13 { width: 13px; height: 13px; } .i.s14 { width: 14px; height: 14px; }
.i.s15 { width: 15px; height: 15px; } .i.s16 { width: 16px; height: 16px; } .i.s21 { width: 21px; height: 21px; }

/* ---------------- shell ---------------- */
.app { display: flex; gap: var(--gap); padding: var(--gap); min-height: 100vh; align-items: stretch; }
.main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--gap); }
/* the floating Aimsly button (52px, 22px in) sits over the last right-aligned figure of a long page: leave room under it (review 10/22).
   She shows at every width now (Jordan, 2026-11-02: "persistent on all screens"); on a phone the shell's own bottom padding below
   (.main, 90px) already clears her 52 + 22. */
@media (min-width: 1181px) { body.has-aimsly .main { padding-bottom: 76px; } }
.sidebar { width: var(--sidebar); flex: none; padding: 14px 10px 10px; display: flex; flex-direction: column; gap: 12px;
  transition: width var(--t-spring); overflow: hidden; align-self: flex-start; position: sticky; top: var(--gap); max-height: calc(100vh - 2 * var(--gap)); overflow-y: auto; }
.app.folded .sidebar { width: var(--rail); }
.brand { display: flex; align-items: flex-start; justify-content: space-between; gap: 4px; padding: 4px 0 0 2px; }
.app.folded .brand { flex-direction: column; align-items: center; padding: 0; gap: 10px; }
.fold { width: 30px; height: 30px; flex: none; border-radius: 9px; border: 1px solid var(--hair-2); background: var(--glass-b); color: var(--ink-2);
  display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; }
.app.folded .fold svg { transform: rotate(180deg); }

/* ---------------- logo switcher: each letter of the real logo is a product button ----------------
   Cut from logo.png (311 x 124). A and I are slanted and touch, so the cut between them is angled
   (x 78 at the top to x 103 at the base). COMPANIES (y 92+) is hidden; the product name replaces it. */
.logo { position: relative; width: var(--logo-w); height: calc(var(--logo-w) * .3222); flex: none; }
.logo .L { position: absolute; top: 0; height: 100%; border: 0; padding: 0; margin: 0; background: none; cursor: pointer; display: block; }
.logo .L img { position: absolute; top: 0; width: var(--logo-w); max-width: none; display: block; opacity: var(--logo-dim); filter: var(--logo-ink);
  transition: opacity var(--t-std), transform var(--t-spring); }
.logo .L:hover img { opacity: .4; transform: translateY(-2px); }
.logo .L[aria-current="true"] img, .logo .L[aria-pressed="true"] img { opacity: var(--logo-on); transform: none; }
/* letter edges as fractions of the logo width (A 0-.2778, I -.4111, M -.7222, S -1) */
.logo .La { left: 0; width: calc(var(--logo-w) * .2778); }                               .logo .La img { left: 0; clip-path: polygon(0 0, 25.1% 0, 33.1% 64.5%, 33.1% 80.6%, 0 80.6%); }
.logo .Li { left: calc(var(--logo-w) * .2778); width: calc(var(--logo-w) * .1333); }     .logo .Li img { left: calc(var(--logo-w) * -.2778); clip-path: polygon(25.1% 0, 39.5% 0, 39.5% 66.1%, 33.1% 66.1%); }
.logo .Lm { left: calc(var(--logo-w) * .4111); width: calc(var(--logo-w) * .3111); }     .logo .Lm img { left: calc(var(--logo-w) * -.4111); clip-path: polygon(39.5% 0, 72.3% 0, 72.3% 66.1%, 39.5% 66.1%); }
.logo .Ls { left: calc(var(--logo-w) * .7222); width: calc(var(--logo-w) * .2778); }     .logo .Ls img { left: calc(var(--logo-w) * -.7222); clip-path: polygon(72.3% 0, 100% 0, 100% 66.1%, 72.3% 66.1%); }
.pname { height: 15px; margin-top: 3px; width: var(--logo-w); text-align: right; font: var(--fw-bold) 11px var(--font-brand); letter-spacing: .3em; color: var(--accent-ink); }
.pname span { margin-right: -.3em; }
/* folded: four plain letters */
.letters { display: none; }
.app.folded .logo, .app.folded .pname { display: none; }
.app.folded .letters { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.letters > :is(a, button) { width: 48px; height: 40px; border: 0; border-radius: 12px; background: transparent; font: var(--fw-x) 20px var(--font-brand); color: var(--faint); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; text-decoration: none;
  transition: background var(--t-std), color var(--t-std); }
.letters > :is(a, button):hover { color: var(--muted); text-decoration: none; }
.letters > :is(a, button):is([aria-pressed="true"], [aria-current="true"]) { background: var(--glass-hi); color: var(--accent-ink); box-shadow: var(--shadow-pop); }
/* in the app the letters are links to each product; one a login may not open stays in the logo, faint and inert */
.logo a.L { text-decoration: none; }
.logo .L.off { cursor: default; pointer-events: none; }
/* the side panel / phone drawer's logo a little smaller, its product name centred under the letters (Jordan, 11/3, w55: "make the AIMS
   logo a little smaller ... the wordmark centred under it, balanced with the drawer's nav items"). A mouse's narrow window draws it at
   132px (was 150); the top bar keeps its own, smaller one. The name is centred in the logo's own width, so it is centred under the picture. */
.sidebar .brand { --logo-w: 132px; }
.sidebar .logo .L img { width: var(--logo-pic, var(--logo-w)); margin-left: calc((var(--logo-w) - var(--logo-pic, var(--logo-w))) / 2); }
.sidebar .logo { height: calc(var(--logo-pic, var(--logo-w)) * .3222); }
.sidebar .pname { text-align: center; }
/* on a touch screen the letters are four equal thumbs (Jordan, 10/27, w21-touch-letters: yes). The logo is drawn at 176px,
   so the menu's switcher is four 44px tap areas side by side; each letter's picture stays where it was drawn (the same cut,
   moved by the area's own left) and lets the press through to its area, so a press lands where the area is, not where the
   letter's slant is. Asked of a finger alone: a mouse keeps the 150px logo and its cut-to-the-letter areas. The sign-in
   page's letters are a picture, not buttons, and keep their size. Folded beside the page (1181 and up), the plain letters
   are a thumb tall. */
@media (pointer: coarse) {
  .sidebar .brand { --logo-w: 176px; --logo-pic: 150px; }   /* the four 44px tap areas span 176; the picture is drawn 150 wide, centred in them (w55, 11/3): each letter's centre still falls in its own area */
  .sidebar .logo .L { width: calc(var(--logo-w) / 4); }
  .sidebar .logo .L img { pointer-events: none; }
  .sidebar .logo .La { left: 0; }                            .sidebar .logo .La img { left: 0; }
  .sidebar .logo .Li { left: calc(var(--logo-w) * .25); }    .sidebar .logo .Li img { left: calc(var(--logo-w) * -.25); }
  .sidebar .logo .Lm { left: calc(var(--logo-w) * .5); }     .sidebar .logo .Lm img { left: calc(var(--logo-w) * -.5); }
  .sidebar .logo .Ls { left: calc(var(--logo-w) * .75); }    .sidebar .logo .Ls img { left: calc(var(--logo-w) * -.75); }
  .sidebar .letters > :is(a, button) { height: var(--tap); }
  /* beside the page (1181 and up) the fold square sits 6px past the S: its reach stops where the S's area ends (45 across) */
  .sidebar .brand .fold::after { inset-inline-start: -6px; }
}

/* ---------------- nav: one sliding highlight, no extra marker ---------------- */
.nav { position: relative; }
.nav .hl { position: absolute; left: 0; right: 0; top: 0; height: var(--hl-h, 36px); border-radius: var(--r-m); background: var(--glass-hi); box-shadow: var(--shadow-pop);
  transform: translateY(var(--hl-y, 0px)); transition: transform var(--t-spring); pointer-events: none; }   /* shell.js measures the current link into --hl-y / --hl-h */
.nav .hl.off { opacity: 0; }
.nav a { position: relative; z-index: 1; display: flex; align-items: center; gap: 11px; height: 36px; margin: 0 0 2px; padding: 0 11px; border-radius: var(--r-m);
  color: var(--ink-2); font-size: var(--fs-m); font-weight: var(--fw-med); text-decoration: none; white-space: nowrap; transition: color var(--t-quick), background var(--t-quick); }
.nav a:hover { color: var(--ink); }
.nav a:hover:not([aria-current="page"]) { background: rgba(255,255,255,.35); }
.nav a[aria-current="page"] { color: var(--ink); font-weight: var(--fw-bold); }
.nav a svg, .nav a img { width: 17px; height: 17px; flex: none; }
.nav .group { height: 28px; padding: 12px 11px 0; font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: .09em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }   /* 10.5px: --faint is for 12px and up */
.app.folded .nav a { justify-content: center; padding: 0; }
.app.folded .nav a span { display: none; }
.app.folded .nav .group { height: 13px; padding: 6px 14px 0; font-size: 0; }
.app.folded .nav .group::after { content: ""; display: block; height: 1px; background: var(--hair-2); }

/* ---------------- top bar: floating islands ---------------- */
.topbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; position: relative; z-index: 20; }
.island { display: flex; align-items: center; gap: 4px; padding: 4px; border-radius: var(--r-l); }
.tb { height: var(--ctl); display: inline-flex; align-items: center; gap: 8px; padding: 0 12px; border-radius: var(--r-m); border: 0; background: transparent;
  color: var(--ink); font-size: 13px; font-weight: var(--fw-semi); cursor: pointer; white-space: nowrap; text-decoration: none; transition: background var(--t-quick); }
.glass.tb { background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); border: 1px solid var(--glass-edge); }   /* a glass button is glass: .tb above clears both */
.tb:hover { background: rgba(255,255,255,.8); text-decoration: none; }
.tb.icon { width: var(--ctl); padding: 0; justify-content: center; position: relative; }
.tb.menu-btn { width: var(--bar-h); height: var(--bar-h); border-radius: var(--r-l); }   /* touch only: as tall as the islands beside it */
.island.search { flex: 1 1 120px; }                                      /* search takes the free width */
.tb.search { flex-grow: 1; justify-content: space-between; color: var(--muted); font-weight: var(--fw-med); }
.tb.search .q { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.badge { min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--r-pill); background: var(--ink); color: var(--on-ink); font-size: 10.5px; font-weight: var(--fw-x);
  display: inline-flex; align-items: center; justify-content: center; white-space: nowrap; }
.kbd { font-size: 11px; font-weight: var(--fw-bold); padding: 1px 6px; border-radius: 6px; border: 1px solid var(--hair-2); }
.me { height: var(--bar-h); padding: 0 12px 0 5px; border-radius: var(--r-l); }
.avatar { width: 32px; height: 32px; border-radius: 10px; background: var(--av, var(--ink));   /* a person's own colour: data-vars="--av:#0F766E" */ color: var(--on-ink); display: inline-flex; align-items: center; justify-content: center; font-size: 11.5px; font-weight: var(--fw-x); flex: none; }
.avatar.round { border-radius: 50%; }
.avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }   /* a person's own picture */
.avatar.mark { background: var(--glass-hi); }   /* the AIMS mark, for someone who picked it */
.avatar.mark img { object-fit: contain; padding: 5px; }
.avatar.s { width: 24px; height: 24px; font-size: 10px; }

/* ---------------- the top bar (tn-): on a computer the menu runs across the top beside the AIMS logo (Jordan, 10/22–10/23) ----------------
   1181px and up with a mouse (a fine pointer): a 13-inch iPad Pro on its side is 1366px wide and keeps its sidebar ("keep side
   bar for ipad and iphone"); frame.js asks the same question (TOP_Q). At 1180 and under, or on touch, .tn-bar is display:contents,
   so its pieces sit in the top bar exactly as before, and the sidebar is the slide-in drawer, as before.
   frame.js fills .tn-menu from #nav, the very rows the sidebar shows this login: the rows above the first heading and the
   shortcuts as links, each heading a drop-down, and the last groups under "More" when the bar runs out of room.
   Pinned (Jordan, 10/23): the bar stays at the top while the page scrolls. --tn-stuck is the height it covers at the top of the
   window (0px with no bar): whatever else sticks to the window's top adds it to its own top, and the root's scroll-padding keeps
   anchors, scrollIntoView and the source links' landing clear of it.
   The rules key on the bar being in the page (:has(.tn-bar)), not on a switch: a branch still on the old shells keeps its sidebar.
   The branch filter and Everyone | Mine leave the bar for the page head (frame.js moves the island), or a slim row under the bar
   where the head has no room (data-filters="row": always there). Neither is pinned.
   A box that scrolls inside the page with its own sticky heads (the wide grid, Settings' access table) is sized to the
   window less --tn-stuck too, so the whole box, heads and all, fits below the bar. */
:root { --tn-stuck: 0px; }
.tn-bar { display: contents; }
.tn-brand, .tn-menu { display: none; }
/* a wide touch screen keeps today's top bar: the filter island (outside .tn-bar) between search and the bell, as before */
@media (min-width: 1181px) and (pointer: coarse), (min-width: 1181px) and (pointer: none) { .tn-bar > :is(.tn-alerts, .anchor) { order: 1; } }
@media (min-width: 1181px) and (pointer: fine) {
  /* the bar is as tall as the logo and its wordmark need (Jordan, 10/23: "Aims logo needs to be a little smaller"; again 11/3, w55: the letters 86 -> 76px and the name's line box pinned to its 13px, so the name sits fully inside the 56px bar with 8px above the letters and below the name) */
  :root:has(.tn-bar) { --tn-h: 56px; --tn-logo: 76px; --tn-top: 8px; --tn-stuck: calc(var(--tn-top) + var(--tn-h)); scroll-padding-top: calc(var(--tn-stuck) + 12px); }
  .app:has(.tn-bar) :is(.sidebar, .fold, .drawer-edge) { display: none; }
  /* pinned 8px from the window's top; the band above it frosts what scrolls under (::before), so nothing reads through the gap */
  .topbar:has(> .tn-bar) { position: sticky; top: calc(var(--tn-top) - var(--gap)); z-index: 40; margin-top: calc(-1 * var(--gap)); padding-top: var(--gap);
    flex-direction: column; flex-wrap: nowrap; align-items: stretch; }
  .topbar:has(> .tn-bar)::before { content: ""; position: absolute; z-index: -1; top: 0; left: calc(-1 * var(--gap)); right: calc(-1 * var(--gap)); height: calc(var(--gap) + var(--tn-h) / 2);
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); -webkit-mask-image: linear-gradient(#000 45%, transparent); mask-image: linear-gradient(#000 45%, transparent); pointer-events: none; }
  .tn-bar { display: flex; align-items: center; gap: 4px; min-height: var(--tn-h); padding: 0 6px 0 16px; position: relative; }
  /* the glass is painted behind the bar, not on it: a backdrop-filter on the bar itself becomes the backdrop of every
     menu that opens from it, and they showed the page through them unblurred */
  .tn-bar::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: var(--r-xl); border: 1px solid var(--glass-edge);
    background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); box-shadow: var(--shadow);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); }
  /* one sheet of glass: the islands inside it lose their own */
  .tn-bar .glass:not(.pop) { background: none; border-color: transparent; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .tn-bar .island { padding: 0; }
  .tn-bar .tb:hover { background: rgba(255,255,255,.6); }
  .tn-bar .me { height: var(--ctl); padding: 0 8px 0 2px; }
  .tn-bar .me #userName { max-width: 150px; overflow: hidden; text-overflow: ellipsis; }   /* a long name must not push the menu into More */
  .tn-bar .me + .pop { top: calc(var(--ctl) + (var(--tn-h) - var(--ctl)) / 2 + 6px); }
  /* the AIMS letters, still the product switcher, and the product's name under them */
  .tn-brand { display: block; flex: none; --logo-w: var(--tn-logo); margin-right: 12px; position: relative; }
  .tn-brand .pname { height: 13px; line-height: 13px; margin-top: 2px; font-size: 10px; letter-spacing: .28em; color: var(--egg-c, var(--accent-ink)); }   /* --egg-c: the wordmark egg's colour (frame.js) */
  .tn-brand .pname span { margin-right: -.28em; }
  .tn-brand .logo .L::after { content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: 0; }   /* each letter takes a click from the bar's edge down */
  .tn-brand .tn-egg { position: absolute; left: 0; right: 0; top: 100%; z-index: 2; }
  /* the menu: links and group buttons, one highlight that slides to the open screen's item */
  .tn-menu { display: flex; align-items: center; gap: 2px; flex: 1 1 0; min-width: 0; position: relative; }
  .tn-hl { position: absolute; left: 0; top: 50%; height: var(--ctl); margin-top: calc(var(--ctl) / -2); width: var(--hl-w, 0px); border-radius: var(--r-m);
    background: var(--glass-hi); box-shadow: var(--shadow-pop); transform: translateX(var(--hl-x, 0px)); transition: transform var(--t-spring), width var(--t-spring); pointer-events: none; }
  .tn-hl.off { opacity: 0; }
  .tn-menu > .anchor { flex: none; }
  .tn-item { position: relative; z-index: 1; flex: none; height: var(--ctl); display: inline-flex; align-items: center; gap: 5px; padding: 0 10px; border: 0; border-radius: var(--r-m);
    background: transparent; color: var(--ink-2); font-size: var(--fs-m); font-weight: var(--fw-semi); white-space: nowrap; cursor: pointer; text-decoration: none;
    transition: color var(--t-quick), background var(--t-quick); }
  .tn-item:hover { color: var(--ink); text-decoration: none; }
  .tn-item:hover:not(.on) { background: rgba(255,255,255,.35); }
  .tn-item.on, .tn-item[aria-expanded="true"] { color: var(--ink); }
  .tn-item .i { width: 13px; height: 13px; opacity: .7; transition: transform var(--t-std); }
  .tn-item[aria-expanded="true"] .i { transform: rotate(180deg); }
  /* a group's rows: icon and name, the open screen's row lit like the sidebar's */
  .tn-g > .pop.tn-pop { top: calc(var(--ctl) + (var(--tn-h) - var(--ctl)) / 2 + 6px); min-width: 232px; }   /* .pop.l's 44px is a 36px control's; the bar is taller */
  .pop.tn-pop a { gap: 11px; font-weight: var(--fw-med); color: var(--ink-2); }
  .pop.tn-pop a svg { width: 17px; height: 17px; flex: none; }
  .pop.tn-pop a[aria-current="page"] { background: var(--glass-hi); box-shadow: var(--shadow-pop); color: var(--ink); font-weight: var(--fw-bold); }
  .tn-pop .tn-sub { height: 26px; padding: 10px 10px 0; font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: .09em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
  .tn-pop .tn-sub:first-child { padding-top: 4px; height: 20px; }
  /* search: "Search ⌘K" while there is room, the magnifier alone when the menu needs it (frame.js sets .tn-tight) */
  .tn-bar .island.search { flex: 0 1 188px; min-width: 0; }
  .tn-bar .tb.search .q .phone-hide { display: none; }
  .tn-bar.tn-tight .island.search { flex: none; }
  .tn-bar.tn-tight .tb.search { width: var(--ctl); padding: 0; justify-content: center; }
  .tn-bar.tn-tight .tb.search :is(.q > span, .kbd) { display: none; }
  .tn-bar.tn-tighter .me :is(#userName, #userName + .i) { display: none; }   /* then your name: the picture stays, and opens the same menu */
  .tn-bar.tn-tighter .me { padding: 0 2px; }
  /* the branch filter and Everyone | Mine: in the page head, or a slim row under the bar at its right edge (not pinned) */
  .main > .island.filters { align-self: flex-end; }
  .topbar:has(> .tn-bar) > .island.filters { display: none; }   /* the shell's starting place: frame.js moves it out before the first paint */
  :root[data-filters="head"] .main > .island.filters:not(.tn-show) { display: none; }   /* waiting to see if the screen has a head for it */
  .island.filters.tn-in-head { margin-left: auto; align-self: flex-end; }   /* in whichever head holds the title (frame.js findHead) */
  .island.filters.tn-in-head ~ * { margin-left: 0; }   /* the head's own actions follow it at the right, not split the row with it */
  .tn-has-top { position: relative; min-height: var(--tn-top-h, 0px); }
  .tn-has-top > :has(h1) { align-self: flex-start; }   /* the title stays where every other screen's is; the actions keep to the foot */
  .tn-has-top > .island.filters.tn-in-head.tn-top { position: absolute; top: 0; right: 0; margin: 0; }   /* a head with no room in its title row: its free top right corner, above its actions (frame.js). Only in a head that has .tn-has-top: a screen that redraws its head (the Apex quote) left the island with a stale tn-top in the new head, where it sat at top 0 of the page, under the bar (r2layout) */
  [data-theme="dark"] .tn-item:hover:not(.on), [data-theme="dark"] .tn-bar .tb:hover { background: rgba(255,255,255,.06); }
}

/* ---------------- page head ---------------- */
.crumb { font-size: 12px; color: var(--muted); font-weight: var(--fw-med); }
.crumb b { color: var(--accent-ink); font-weight: var(--fw-bold); }
.crumb a { text-decoration: none; } .crumb a:hover b { text-decoration: underline; }
.crumb i { font-style: normal; color: var(--faint); margin: 0 4px; }   /* #98A2B3 was 2.0–2.2:1 on the light field (review 4, 10/22) */
h1.title { margin: 2px 0 0; font-size: var(--fs-h1); font-weight: var(--fw-bold); letter-spacing: -.02em; }
.head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------------- buttons: one family ---------------- */
.btn { height: var(--ctl); padding: 0 14px; border-radius: var(--r-m); font-size: 13px; font-weight: var(--fw-bold); display: inline-flex; align-items: center; justify-content: center; gap: 8px; line-height: 1.25;
  cursor: pointer; border: 1px solid transparent; white-space: nowrap; text-decoration: none; position: relative; overflow: hidden;
  transition: transform var(--t-quick), background var(--t-std), box-shadow var(--t-std), color var(--t-std); }
.btn:hover { text-decoration: none; }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }
.btn.primary { background: var(--ink); color: var(--on-ink); box-shadow: var(--shadow-btn); }
.btn:where(:not(.secondary, .ghost, .danger, .primary)) { background: var(--ink); color: var(--on-ink); }   /* a plain 2.x .btn: one primary look (review 10/22) */
.btn.primary:hover { transform: translateY(-1px); }
.btn.secondary { background: var(--glass-a); color: var(--ink); border-color: var(--hair-2); }
.btn.secondary:hover { background: #fff; box-shadow: var(--shadow-pop); }
[data-theme="dark"] .btn.secondary:hover { background: rgba(255,255,255,.12); }
.btn.ghost { background: transparent; color: var(--ink); }
.btn.ghost:hover { background: var(--well); }
.btn.danger { background: var(--bad-bg); color: var(--bad-ink, var(--bad)); border-color: var(--bad-line); }
.btn.danger.armed { background: var(--bad); color: #fff; border-color: var(--bad); }
.btn.lg { height: 48px; padding: 0 18px; border-radius: var(--r-l); font-size: 15px; }
.btn.sm { height: 32px; padding: 0 12px; font-size: 12.5px; }
.btn.icon { width: var(--ctl); padding: 0; justify-content: center; }   /* one icon, no label */
.btn.sm.icon { width: 32px; }
/* a small button in a row with a full-size box or switch takes their height, so one row is one height (w11design K2) */
:where(div, header, section, form, footer, fieldset, li, span):has(> :is(.select-wrap, .input, .select, .seg)) > .btn.sm { height: var(--ctl); }
:where(div, header, section, form, footer, fieldset, li, span):has(> :is(.select-wrap, .input, .select, .seg)) > .btn.sm.icon { width: var(--ctl); }
/* a status pill in a row of buttons is the row's 36px (a small button beside it is lifted to 36 by the rule above); in a
   table row it stays the 28px pill (r2layout: Settings › Crews & Skills, a person's head, a project's Rework — 28 beside
   32/36). No :has() inside :has() — a nested one throws the whole rule away. */
@media (min-width: 1181px) { :where(div, span, li, header):has(> .btn) > .select-wrap > select.status { height: var(--ctl); } }
@media (max-width: 1180px), (pointer: coarse) { :where(div, span, li, header):has(> .btn) > .select-wrap > select.status { min-height: var(--tap); } }   /* the 44px buttons beside it, in a card's row too */
/* ...and one beside a full-size button in a head's actions: "Copy link" 32 beside "Add widget" 36 (r2layout, Momentum › a dashboard) */
:where(.page-head, .pj-ph, .sc-head) > .actions:has(> .btn:not(.sm)) > .btn.sm { height: var(--ctl); }
:where(.page-head, .pj-ph, .sc-head) > .actions:has(> .btn:not(.sm)) > .btn.sm.icon { width: var(--ctl); }
.btn.with-knob { padding-right: 6px; }                                  /* the round knob sits close to the edge */
.btn .knob { width: 28px; height: 28px; margin-right: -9px; border-radius: 50%; background: var(--on-ink); color: var(--ink); display: inline-flex; align-items: center; justify-content: center; transition: transform var(--t-spring); }
.btn:hover .knob { transform: translateX(3px); }
.split { display: inline-flex; border-radius: var(--r-m); box-shadow: var(--shadow-btn); position: relative; }
.split .btn { box-shadow: none; }
.split .btn:first-child { border-radius: var(--r-m) 0 0 var(--r-m); }
.split .btn:last-child { width: 34px; padding: 0; justify-content: center; border-radius: 0 var(--r-m) var(--r-m) 0; box-shadow: inset 1px 0 0 rgba(255,255,255,.18); }
.drill { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--hair-2); background: var(--glass-b); color: var(--ink); display: inline-flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer; flex: none; transition: background var(--t-std), color var(--t-std), transform var(--t-spring); }
.drill:hover { background: var(--ink); color: var(--on-ink); transform: rotate(45deg); }
/* save that fills with water */
.btn .pour { position: absolute; inset: 0 auto 0 0; width: 0; background: linear-gradient(180deg, #38BDF8, #0369A1); }
.btn.saving .pour { animation: pour 1.2s cubic-bezier(.4,0,.2,1) forwards; }
.btn.saved .pour { width: 100%; background: linear-gradient(180deg, var(--water-ok-a), var(--water-ok-b)); }
.btn .lt { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 8px; }
.btn[data-save] { min-width: 150px; justify-content: center; }   /* keeps its width while the label changes */
@keyframes pour { to { width: 100%; } }

/* ---------------- segmented control with a sliding thumb (tabs, filters, periods) ---------------- */
.seg { position: relative; display: inline-flex; gap: 2px; padding: 3px; border-radius: 11px; background: var(--well); box-shadow: inset 0 1px 2px rgba(16,24,40,.08); max-width: 100%; overflow-x: auto; }
.seg { scrollbar-width: none; } .seg::-webkit-scrollbar { display: none; }
.seg .thumb { position: absolute; top: 3px; bottom: 3px; left: 0; width: var(--thumb-w, 0px); border-radius: 8px; background: var(--ink); box-shadow: 0 2px 6px rgba(11,18,32,.25);
  transform: translateX(var(--thumb-x, 0px)); transition: transform var(--t-spring), width var(--t-spring); pointer-events: none; }   /* shell.js measures the pressed button into --thumb-x / --thumb-w */
.seg button { position: relative; z-index: 1; border: 0; background: transparent; height: 30px; padding: 0 12px; border-radius: 8px; font-size: 12.5px; font-weight: var(--fw-semi);
  color: var(--muted); cursor: pointer; white-space: nowrap; transition: color var(--t-std); flex-shrink: 0; }   /* never narrower than its words: a strip too wide for its box scrolls (with the .more fade), it never crushes (w11design M2: a sheet's min-width: 44px let "Needs Review 31" shrink to 44px) */
.seg button[aria-pressed="true"], .seg button[aria-selected="true"] { color: var(--on-ink); }
.seg button em { font-style: normal; font-weight: var(--fw-bold); color: var(--muted); margin-left: 4px; }   /* solid: opacity .65 was 2.9:1 light, 3.6:1 dark; --faint still fell to 4.45:1 on Sentry's well (review 4, 10/22) */
.seg button[aria-pressed="true"] em, .seg button[aria-selected="true"] em { color: inherit; }
/* sub-tabs: the second row under a segmented section bar (the project page's Field › Tickets). An underline slides to
   the open tab; the script measures it into --ul-x / --ul-w. Scrolls sideways on a phone, never wraps. */
.subtabs { position: relative; display: flex; gap: 24px; padding: 0 4px; border-bottom: 1px solid var(--hair); overflow-x: auto; scrollbar-width: none; }
.subtabs::-webkit-scrollbar { display: none; }
.subtabs button, .subtabs a { flex: none; background: none; border: 0; padding: 10px 0 11px; font: var(--fw-semi) 13.5px var(--font); color: var(--muted); cursor: pointer; white-space: nowrap; text-decoration: none; transition: color var(--t-quick); }
.subtabs button:hover, .subtabs a:hover { color: var(--ink); text-decoration: none; }
.subtabs [aria-selected="true"] { color: var(--ink); }
.subtabs em { font-style: normal; font-weight: var(--fw-bold); color: var(--faint); margin-left: 4px; }
/* links as tabs (each view its own address): the current one is underlined in place */
.subtabs a { margin-bottom: -1px; border-bottom: 2px solid transparent; }
.subtabs a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--accent); }
.subtabs .n { margin-left: 5px; font-weight: 800; color: var(--warn); }
/* wider than its box: it scrolls, and a fade on the right says there is more (phone-tables.js sets .more) */
.subtabs.more, .seg.more { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent); }
/* …and one on the left once it has been scrolled (phone-tables.js sets .more-l): a strip that opens on its current tab has its first tab cut at the left, and said nothing (w26fix) */
.subtabs.more-l, .seg.more-l { -webkit-mask-image: linear-gradient(to right, transparent, #000 56px); mask-image: linear-gradient(to right, transparent, #000 56px); }
.subtabs.more.more-l, .seg.more.more-l { -webkit-mask-image: linear-gradient(to right, transparent, #000 56px, #000 calc(100% - 56px), transparent); mask-image: linear-gradient(to right, transparent, #000 56px, #000 calc(100% - 56px), transparent); }
.subtabs .ul { position: absolute; left: 0; bottom: -1px; height: 2px; width: var(--ul-w, 0px); border-radius: 2px; background: var(--accent);
  transform: translateX(var(--ul-x, 0px)); transition: transform var(--t-spring), width var(--t-spring); }
.seg.glass { background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); }

/* ---------------- fields ---------------- */
.field { display: flex; flex-direction: column; gap: 5px; }
.field label { font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.input, .select, .textarea { height: var(--ctl); width: 100%; border-radius: var(--r-m); border: 1px solid var(--hair-2); background: var(--glass-a); padding: 0 12px;
  font-size: 13px; color: var(--ink); transition: border-color var(--t-quick), box-shadow var(--t-std); }
.textarea { height: auto; min-height: 72px; padding: 10px 12px; resize: vertical; }
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(11,18,32,.10); }
.input.n { text-align: right; }
/* iOS Safari zooms the page into any text box under 16px, so on phones every box is 16px —
   the kit's and the 2.x ones the reset above would otherwise shrink to the page size. */
@media (max-width: 640px), (pointer: coarse) { :is(input:not([type=checkbox]):not([type=radio]):not([type=range]), select, textarea) { font-size: 16px; } }   /* :is() lends select and textarea the input's weight, so this beats .select, .status and 2.x's class-scoped boxes (review 10/22). A phone or any touch screen (iOS zooms into a box under 16px); not a narrowed computer window, where it made every table's status 16px (w11design S10) */
.select-wrap { position: relative; display: inline-flex; align-items: center; }
.select-wrap .select { appearance: none; -webkit-appearance: none; padding-right: 32px; }
.select-wrap svg { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); pointer-events: none; width: 14px; height: 14px; }
.select-wrap.block { display: flex; }                                   /* fills its field */
.select.bare { border-color: transparent; background: transparent; font-weight: var(--fw-semi); min-width: 150px; }   /* sits inside a glass island */

/* ---------------- status: always a dropdown, coloured, can move backward ---------------- */
.status { appearance: none; -webkit-appearance: none; height: 28px; border-radius: var(--r-pill); padding: 0 26px 0 11px; font: var(--fw-bold) 12px var(--font); cursor: pointer; border: 1px solid; width: auto; flex: none; max-width: 100%; field-sizing: content; }   /* sized to its longest status: 2.x's select { width:100% } squeezed it inside a table cell ("Reviev") */
.status.ok   { color: var(--ok);   background-color: var(--ok-bg);   border-color: var(--ok-line); }
.status.warn { color: var(--warn); background-color: var(--warn-bg); border-color: var(--warn-line); }
.status.bad  { color: var(--bad);  background-color: var(--bad-bg);  border-color: var(--bad-line); }
.status.info { color: var(--info); background-color: var(--info-bg); border-color: var(--info-line); }
.status:not(.ok, .warn, .bad, .info, .teal, .navy, .purple) { color: var(--ink-2); background-color: var(--well); border-color: var(--hair-2); }
/* the billing and hold steps, kept off the working statuses' colours: Ready to Invoice teal, Invoiced navy, the Awaiting
   holds purple (Jordan's CHANGE-LOG #1/#11, 9/29). Same recipe as select.status-sel.teal / .billed below. */
.status.teal { color: var(--teal); background-color: color-mix(in srgb, var(--teal) 12%, transparent); border-color: color-mix(in srgb, var(--teal) 32%, transparent); }
.status.navy { color: var(--navy); background-color: color-mix(in srgb, var(--navy) 10%, transparent); border-color: color-mix(in srgb, var(--navy) 30%, transparent); }
.status.purple { color: var(--purple); background-color: color-mix(in srgb, var(--purple) 10%, transparent); border-color: color-mix(in srgb, var(--purple) 30%, transparent); }   /* a neutral step (Complete, Closed): readable in both themes */
.status + svg { position: absolute; right: 9px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; pointer-events: none; }
.status.ok + svg { color: var(--ok); } .status.warn + svg { color: var(--warn); } .status.bad + svg { color: var(--bad); } .status.info + svg { color: var(--info); }
.status.teal + svg { color: var(--teal); } .status.navy + svg { color: var(--navy); } .status.purple + svg { color: var(--purple); }

/* ---------------- strips: many numbers, one panel, hairlines between ---------------- */
.strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow: hidden; }
.strip > * { padding: 14px 18px 16px; box-shadow: 1px 0 0 var(--hair), 0 1px 0 var(--hair); display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.label { font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); }
.strip .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 28px; }   /* label + drill: same height in every cell, so the numbers line up */
.value { font-size: var(--fs-num); font-weight: var(--fw-reg); letter-spacing: -.025em; line-height: 1.15; font-variant-numeric: tabular-nums; }
.value small { font-size: 14px; color: var(--faint); letter-spacing: 0; }
.value.ok { color: var(--ok); } .value.warn { color: var(--warn); } .value.bad { color: var(--bad); }
.hint { font-size: 12.5px; color: var(--muted); line-height: 1.45; letter-spacing: .008em; }   /* 1.45: a wrapped hint reads as one block (w10retire: was styles.css's) */
.grid-2, .grid-3, .grid-4 { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* a short last row fills the width, never a hole beside it (w11design K7: Mobilization's seven fields went 4 + 3, then
   2 + 2 + 2 + 1): 4 across, its last one, two or three take the row between them; 2 across, an odd last one takes both */
.grid-4 > :nth-child(4n+1):last-child { grid-column: 1 / -1; }
.grid-4 > :nth-child(4n+1):nth-last-child(2), .grid-4 > :nth-child(4n+2):last-child, .grid-4 > :nth-child(4n+3):last-child { grid-column: span 2; }
@media (max-width: 1180px) {
  .grid-4 > :is(:nth-child(4n+1):nth-last-child(2), :nth-child(4n+2):last-child, :nth-child(4n+3):last-child) { grid-column: auto; }
  .grid-4 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* ---------------- liquid: pipes and tubes ---------------- */
.pipe { height: 8px; border-radius: var(--r-pill); background: var(--well); box-shadow: inset 0 1px 2px rgba(16,24,40,.12); position: relative; overflow: hidden; }
.pipe > i { position: absolute; left: 1px; top: 1px; bottom: 1px; border-radius: var(--r-pill); display: block; width: var(--fill, 0);   /* <i data-vars="--fill:42%"> */
  background: linear-gradient(180deg, var(--water-a), var(--water-b)); box-shadow: inset 0 1px 0 rgba(255,255,255,.55); animation: fill var(--t-pour) both; }
.pipe > i.ok { background: linear-gradient(180deg, var(--water-ok-a), var(--water-ok-b)); }
.pipe > i.warn { background: linear-gradient(180deg, var(--water-warn-a), var(--water-warn-b)); }
.pipe > i.bad { background: linear-gradient(180deg, var(--water-bad-a), var(--water-bad-b)); }
.pipe .target { position: absolute; top: -3px; bottom: -3px; left: var(--at, 0); width: 2px; border-radius: 2px; background: var(--ink); }   /* <span class="target" data-vars="--at:75%"> */
.pipe.with-target { overflow: visible; }   /* the target marker stands out above and below */
.pipe.tall { height: 10px; }
.pipe.thin { height: 6px; }
.tube { width: 16px; height: 150px; border-radius: var(--r-pill); background: var(--well); box-shadow: inset 0 1px 3px rgba(16,24,40,.12); display: flex; flex-direction: column; justify-content: flex-end; padding: 2px; overflow: hidden; }
.tube > i { display: block; width: 100%; box-shadow: inset 0 1px 0 rgba(255,255,255,.5); background: linear-gradient(180deg, var(--water-a), var(--water-b)); }
.tube > i:first-child { border-radius: 99px 99px 2px 2px; } .tube > i:last-child { border-radius: 2px 2px 99px 99px; } .tube > i:only-child { border-radius: 99px; }
@keyframes fill { from { width: 0; } }

/* ---------------- tables ---------------- */
.table-wrap { overflow-x: auto; position: relative; }   /* a hidden .vh label in a heading is held inside the scroll box (Apex PFS scrolled the page 842 vs 820; review 4, 10/22) */
.glass .table-wrap { background: transparent; border: 0; border-radius: 0; box-shadow: none; }   /* a table on glass sits on the glass (2.x styles.css gives every .table-wrap a white card) */
table.t { width: 100%; border-collapse: collapse; font-size: 13px; background: transparent; }   /* glass shows through; 2.x styles.css paints every table white */
table.t th { font-size: 11.5px; font-weight: var(--fw-semi); color: var(--muted); text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--hair); white-space: nowrap; text-transform: none; letter-spacing: 0; background: transparent; }
table.t td { padding: 10px 12px; border-bottom: 1px solid rgba(16,24,40,.06); vertical-align: middle; font-variant-numeric: tabular-nums; }
table.t tr:last-child td { border-bottom: 0; }
table.t tbody tr { transition: background var(--t-quick); }
table.t tbody tr:hover { background: rgba(255,255,255,.55); }
table.t tr:hover td { background: transparent; }   /* the row lights, not 2.x's fixed light cell colour (it glared in dark) */
table.t .r { text-align: right; }
table.t a.name { font-weight: var(--fw-bold); color: var(--ink); }   /* the row's own name, linking to it */
table.t .open { opacity: 0; transform: translateX(-4px); transition: opacity var(--t-std), transform var(--t-std); }
table.t tbody tr:hover .open { opacity: 1; transform: none; }

/* ---------------- cards, chips, people ---------------- */
.card { padding: 12px 14px; border-radius: var(--r-l); background: rgba(255,255,255,.78); border: 1px solid rgba(255,255,255,.95); box-shadow: 0 8px 18px -14px rgba(16,24,40,.45); }
[data-theme="dark"] .card { background: rgba(255,255,255,.05); border-color: var(--hair); }
.chip { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px; border-radius: 6px; font-size: 11.5px; font-weight: var(--fw-semi); background: var(--well); color: var(--ink-2); white-space: nowrap; }
/* a toned chip's tint is SOLID: a see-through tint over the aurora let the field through, and No credit fell to
   4.36:1 light and 3.69:1 dark at 820 (review 4, 10/22) */
.chip.ok { background: color-mix(in srgb, var(--ok) 12%, var(--surface)); color: var(--ok); } .chip.warn { background: color-mix(in srgb, var(--warn) 12%, var(--surface)); color: var(--warn); }
.chip.bad { background: color-mix(in srgb, var(--bad) 12%, var(--surface)); color: var(--bad); } .chip.info { background: color-mix(in srgb, var(--info) 12%, var(--surface)); color: var(--info); }
.chip.teal { background: color-mix(in srgb, var(--teal) 12%, var(--surface)); color: var(--teal); } .chip.navy { background: color-mix(in srgb, var(--navy) 12%, var(--surface)); color: var(--navy); }
.chip.purple { background: color-mix(in srgb, var(--purple) 12%, var(--surface)); color: var(--purple); }
.chip.sm { height: 18px; }
.person { display: inline-flex; align-items: center; gap: 6px; height: 30px; white-space: nowrap; padding: 0 6px 0 4px; border-radius: var(--r-pill); background: rgba(255,255,255,.85); border: 1px solid var(--hair); font-size: 12.5px; font-weight: var(--fw-semi); }
.person.lead { background: var(--ink); color: var(--on-ink); border-color: var(--ink); }
.person button { width: 20px; height: 20px; border-radius: 50%; border: 0; background: transparent; color: var(--faint); display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; }
.person button:hover { background: var(--bad-bg); color: var(--bad); }
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }   /* only where it means something, with a legend */

/* ---------------- drawer (phones + touch iPads), menus, scrim ---------------- */
.menu-btn, .drop-btn, .scrim { display: none; }
.drop-btn { position: fixed; left: 22px; bottom: calc(22px + var(--fab-lift, 0px)); z-index: 50; width: 52px; height: 52px; padding: 0; border-radius: 50%;
  border: 1px solid var(--fab-edge); background: var(--fab-glass); color: var(--fab-ink); align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  box-shadow: inset 0 1px 0 var(--fab-edge), var(--shadow-pop); cursor: pointer; }   /* a plain circle, the size and glass of Aimsly's (#agent-fab); was a rotated drop */
.scrim { position: fixed; inset: 0; z-index: 55; border: 0; padding: 0; background: rgba(11,18,32,.3); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); cursor: pointer; }
/* the drawer following a thumb: the app writes how far it is out as --drawer-x and how dark the scrim is as --scrim-o */
.drawer-edge { display: none; position: fixed; left: 0; top: 0; bottom: 0; width: 14px; z-index: 45; }
@media (max-width: 640px) { .drawer-edge { width: 10px; } }   /* narrower than the page's 10px edge, so it never covers the menu button */   /* pull the drawer in from the screen's edge */
.drop-btn { transition: translate var(--t-std), scale var(--t-std), opacity var(--t-std), bottom var(--t-std), visibility 0s linear var(--t-std); }
/* hidden at the top of a page, where the top bar's own menu button is the way in: it fades and grows in once the person has scrolled
   (shared.js sets body.nav-fab-on when the page has moved on past the top; Jordan, 2026-11-02). visibility goes with it, so a hidden
   circle is not in the tab order or read out. */
.drop-btn { opacity: 0; scale: .7; visibility: hidden; pointer-events: none; }
body.nav-fab-on .drop-btn { opacity: 1; scale: 1; visibility: visible; pointer-events: auto; transition-delay: 0s; }
/* goes while the drawer, a pop-up, ⌘K or Aimsly is open (the app sets these body classes). It no longer steps aside for a control in its
   corner (w40, Jordan 11/2: always there after a scroll). body.fab-away is kept as a hook; scrolling down no longer sets it, it now BRINGS the circle in. */
body.fab-away .drop-btn, body.drawer-open .drop-btn, body.agent-maxed .drop-btn,
body:has(.modal-back) .drop-btn, body:has(.cmdk-back) .drop-btn, body:has(#agent-panel.open) .drop-btn,
body:has(> [aria-modal="true"]:not([hidden]), > * > [aria-modal="true"]:not([hidden])) .drop-btn { translate: 0 120px; opacity: 0; pointer-events: none; }
.drop-btn:active { scale: .94; }
.side-foot { display: none; margin-top: auto; }   /* the drawer's own extra rows (Ask Aimsly on a phone) */
.anchor { position: relative; }   /* wraps a button and the .pop it opens */
.pop { position: absolute; z-index: 30; min-width: 220px; max-width: calc(100vw - 16px); padding: 6px; animation: popIn var(--t-std); translate: var(--pop-dx, 0px) 0; }   /* frame.js slides a menu that would leave the window back inside it by --pop-dx (w11design M5) */
.pop.r { right: 0; top: 44px; } .pop.l { left: 0; top: 44px; }   /* under a 36 px control, from its right or left edge */
.me + .pop { top: calc(var(--bar-h) + 6px); }                      /* just under the avatar button, whatever its height */
.pop.wide { min-width: 260px; }
.pop button, .pop a { display: flex; align-items: center; gap: 10px; width: 100%; height: 38px; padding: 0 10px; border: 0; border-radius: 9px; background: transparent; color: var(--ink);
  font-size: 13px; font-weight: var(--fw-semi); text-align: left; cursor: pointer; text-decoration: none; }
.pop button:hover, .pop a:hover { background: var(--well); }
.pop .bad { color: var(--bad); }   /* Sign out, Renew links: the item that leaves or can't be undone */
@keyframes popIn { from { opacity: 0; transform: translateY(-6px) scale(.98); } }

/* ================ the frame's furniture: what 3.0 borrowed from styles.css, now the kit's own (w9shell, 10/23) ================
   2.x's names, restyled here, so every screen that calls modal(), toast() or listPage(), opens ⌘K, or draws a bare box or
   table takes the kit's look untouched — and keeps it the day styles.css is deleted: nothing below reads a 2.x token.
   The bare-element defaults stay at an element's weight (a class still wins). (styles.css itself was deleted in w10retire,
   10/23, and the block that matched its heavier dark rules with it.) They keep off the
   pages that never had styles.css on screen (the customer pages, .pub-page; the sign-in page, .li-page) and off paper (a
   printed sheet inside the app, a document page: public/print.css draws those, on the 3.0 paper — w20print, 10/26). */

/* ---------------- headings, labels and the page's rhythm ----------------
   The one vertical rhythm (CLAUDE.md "Vertical rhythm", Jordan 2026-08-17): every top-level block in #app carries the same
   16px gap below it, so a screen is evenly spaced by construction; a heading sits nearer what it introduces (22 above,
   10 below). A hidden block leaves no gap behind. Don't add ad-hoc margins to page-level blocks to "fix" spacing. */
/* not inside a printed sheet or on a document page: paper is print.css's (the 3.0 paper; Jordan 10/26, pl-scope) */
h1:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { font-size: 22px; font-weight: var(--fw-bold); letter-spacing: -.015em; margin: 0 0 16px; }
h2:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { font-size: 15.5px; font-weight: var(--fw-bold); letter-spacing: -.01em; margin: 22px 0 10px; }
h3:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { font-size: 14px; font-weight: var(--fw-bold); margin: 14px 0 8px; }
label:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { display: block; font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); margin-bottom: 3px; }
#app > *:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { margin-bottom: var(--gap); }
#app > h1:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { margin-bottom: 16px; }
#app > h2:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { margin-bottom: 10px; }
#app > h3:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { margin-bottom: 8px; }
#app > [hidden], #app > [style*="display:none"], #app > [style*="display: none"] { margin-bottom: 0; }

/* ---------------- 2.x's form rhythm, kept (w10retire, 10/23) ----------------
   The screens were laid out — and reviewed — on styles.css's spacing: a 10px foot under every .field, a muted .sub line,
   and a pop-up's .modal-acts as one wrapping row of buttons. styles.css is gone, so they live here, off paper and off the
   customer and sign-in pages like the rest of this part. A grid that spaces its fields by gap sets the foot to 0 in its own
   section (sfd-, sbe- …). */
.field:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { margin-bottom: 10px; }
.sub:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--muted); font-size: 13px; letter-spacing: .005em; }
label > .sub:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { font-size: inherit; }   /* a label's own aside stays the label's size */
.modal-acts:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

/* ---------------- a bare box: input, select, textarea without a kit class ----------------
   The kit's own (.input, .select, .textarea, .status, .mi-in …) draw themselves; any other box looks like .input, at 2.x's
   size (36px, 7px 10px) so a form not yet rebuilt keeps its shape. On a phone (≤900) and on any touch screen every box is
   44px (the touch floor); the 16px text that stops iOS zooming is in "fields" above. */
input:where(:not([type=checkbox], [type=radio], [type=range], [type=file], [type=color], [type=button], [type=submit], [type=reset], [type=image], [type=hidden], .input, .mi-in, .wg-in, .q-sheet *, .print-doc *, .ts-sheet *, [data-doc] *, .pub-page *, .li-page *)),
select:where(:not(.select, .status, .mi-in, .wg-in, .q-sheet *, .print-doc *, .ts-sheet *, [data-doc] *, .pub-page *, .li-page *)),
textarea:where(:not(.textarea, .q-sheet *, .print-doc *, .ts-sheet *, [data-doc] *, .pub-page *, .li-page *)) {
  font: inherit; width: 100%; min-height: var(--ctl); padding: 7px 12px; border: 1px solid var(--hair-2); border-radius: var(--r-m);   /* 12px in: the text starts where .input's does */
  background: var(--glass-a); color: var(--ink); transition: border-color var(--t-quick), box-shadow var(--t-std); }
textarea:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { min-height: 0; }
select[multiple]:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { padding-top: 0; padding-bottom: 0; height: auto; }   /* a list box's rows carry the padding, so none shows half */
select[multiple]:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) option { padding: 6px 10px; }
:is(input, select, textarea):not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *):focus { outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 12%, transparent); }
:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *)::placeholder { color: var(--faint); opacity: 1; }
/* the kit's own boxes are the height they say (2.x's 36px floor stood the 28px .status pill at 36) */
:is(input, select, textarea):where(.input, .select, .textarea, .status, .mi-in, .wg-in), :where(.qe, .qe-edit, .otp, .mobset-v) > input { min-height: 0; }
@media (max-width: 1180px), (pointer: coarse) {   /* the touch layout's boxes are the touch layout's buttons' height (K2: 36px boxes beside 44px buttons at 1024) */
  :is(input, select, textarea):not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { min-height: var(--tap); }
  textarea:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { min-height: 0; }
  input:is([type=checkbox], [type=radio]):not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { width: 24px; height: 24px; min-height: 0; flex: none; }
  label:has(> input:is([type=checkbox], [type=radio])):not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { min-height: var(--tap); display: flex; align-items: center; gap: 8px; }
}
input:is([type=checkbox], [type=radio]):not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { accent-color: var(--ink); }

/* ---------------- a bare table: the kit's table.t, at 2.x's density ----------------
   A table outside a glass panel sits in its own (.table-wrap), so a list not yet rebuilt is still a panel, not rows on the
   aurora. The header band is solid (--surface-2) so a sticky head never shows rows through it; a row lights solid too,
   for the same reason (a sticky first column). A printed sheet keeps its own (print.css).
   (w10retire, 10/23: this comment was never closed, so the rules below sat inside it and 2.x's styles.css drew every bare
   table and .table-wrap until it went.) */
table:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { width: 100%; border-collapse: collapse; background: transparent; font-size: 13px; }
th:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { text-align: left; font-size: 11.5px; font-weight: var(--fw-semi); color: var(--muted); text-transform: none; letter-spacing: 0;
  padding: 9px 10px; border-bottom: 1px solid var(--hair); white-space: nowrap; background: var(--surface-2); }
td:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { padding: 8px 10px; border-bottom: 1px solid var(--hair); vertical-align: middle; font-variant-numeric: tabular-nums; }
tr:last-child td:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { border-bottom: 0; }
tr:hover td:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--ink) 3%, var(--surface)); }
:is(td, th).num:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); border: 1px solid var(--glass-edge); border-radius: var(--r-xl); box-shadow: var(--shadow); }
:is(.modal, .card) .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: transparent; border: 1px solid var(--hair); border-radius: var(--r-l); box-shadow: none; }   /* a list inside a dialog or a card: a quiet frame, not a second panel */

/* ---------------- toasts: a sentence, never in the way ----------------
   Every app's toast() appends a .toast, and toastAction() a .toast.toast-action with one .toast-btn: an ink pill at the
   window's foot on a computer (z 1400: over a pop-up and ⌘K, so a failure is never hidden behind what caused it). A plain
   toast says something; it never takes a tap meant for the button under it — the tap goes through. On phones and touch
   iPads a screen's actions sit at the bottom (the action bar, a sheet's buttons, the ticket's step rail, the menu drop),
   so every toast shows at the TOP there, centred under the status bar, and never covers them. (A "Clocked in" toast sat
   on the lock-out walk's unit list.) Aimsly's round button moves it left on a computer (her section, below). */
.toast { position: fixed; right: 20px; bottom: 20px; z-index: 1400; max-width: min(460px, calc(100vw - 40px)); padding: 11px 16px;
  border-radius: var(--r-l); background: var(--ink); color: var(--on-ink); font-size: 13.5px; font-weight: var(--fw-semi); line-height: 1.4;
  box-shadow: 0 16px 36px -14px rgba(11,18,32,.6); animation: kToastIn var(--t-std) both; }
.toast:not(.toast-action) { pointer-events: none; }
.toast-action { display: flex; align-items: center; gap: 12px; }
.toast-btn { flex: none; height: 30px; padding: 0 12px; border-radius: var(--r-s); border: 1px solid color-mix(in srgb, var(--on-ink) 38%, transparent);
  background: transparent; color: inherit; font: inherit; font-weight: var(--fw-bold); cursor: pointer; transition: background var(--t-quick); }
.toast-btn:hover, .toast-btn:focus-visible { background: color-mix(in srgb, var(--on-ink) 16%, transparent); }
@keyframes kToastIn { from { opacity: 0; transform: translateY(8px); } }
@keyframes kToastDrop { from { opacity: 0; transform: translateY(-8px); } }
@media (max-width: 1180px) {
  .toast, .toast.toast-action { top: max(10px, calc(env(safe-area-inset-top, 0px) + 6px)); bottom: auto; left: 12px; right: 12px;
    width: fit-content; max-width: min(560px, calc(100vw - 24px)); margin-inline: auto; animation-name: kToastDrop; }
}
@media (max-width: 1180px), (pointer: coarse) {
  .toast-btn { height: var(--tap); padding: 0 16px; }
}
@media (max-width: 560px) { .toast.toast-action { flex-wrap: wrap; justify-content: flex-end; row-gap: 8px; } .toast.toast-action > span { flex: 1 1 100%; } }

/* ---------------- pop-ups: modal() appends .modal-back > .modal ----------------
   One frame for every app's dialogs: a solid sheet over a dimmed, softly blurred room. The stack, in one place: the
   drawer's scrim (55) and drawer (60) are page furniture; a pop-up (1200) sits over the page and over any map (Leaflet's
   panes run to 1000); ⌘K (1250) over a pop-up, since it takes the keyboard; the trip overlay (1300); a toast (1400).
   A second pop-up over the first never dims the room twice. .wide (780) holds a priced table, .xwide (1040) two columns of
   fields. On a phone (≤700) it is a sheet from the bottom edge with a grabber; a thumb on the grabber pushes it back down
   (shared.js puts the travel in --sheet-y and the room's fade in --back-o while it follows; .sheet-dragging meanwhile).
   Enter only: a dialog is removed on dismiss. `backwards`, never `both`: a held transform would make the sheet the
   containing block of anything fixed inside it. */
.modal-back { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px;
  overflow-y: auto; overscroll-behavior: contain; background: rgba(11,18,32,.34); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  animation: kScrimIn var(--t-std) backwards; }
[data-theme="dark"] .modal-back { background: rgba(0,0,0,.52); }
.modal-back ~ .modal-back, [data-theme="dark"] .modal-back ~ .modal-back { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; animation: none; }
.modal-back[style*="--back-o"] { opacity: var(--back-o); }
.modal { position: relative; width: 100%; max-width: 640px; padding: 22px; border-radius: var(--r-xl); background: var(--surface); color: var(--ink);
  border: 1px solid var(--hair); box-shadow: 0 30px 70px -26px rgba(11,18,32,.5), var(--shadow-pop); animation: kModalRise var(--t-std) backwards; }
.modal.wide { max-width: 780px; }
.modal.xwide { max-width: 1040px; }
.modal h2 { margin-top: 0; }
.modal[style*="--sheet-y"] { transform: translateY(var(--sheet-y)); }
.modal.sheet-dragging { transition: none; animation: none; }
@keyframes kScrimIn { from { background-color: rgba(11,18,32,0); -webkit-backdrop-filter: blur(0); backdrop-filter: blur(0); } }
@keyframes kModalRise { from { opacity: 0; transform: translateY(10px) scale(.985); } }
@keyframes kSheetUp { from { opacity: 0; transform: translateY(24px); } }
@media (max-width: 700px) {
  .modal-back { padding: 0; align-items: flex-end; }
  .modal { max-width: none; width: 100%; max-height: 92vh; overflow-y: auto; border-radius: var(--r-2xl) var(--r-2xl) 0 0; border-bottom: 0;
    padding: 6px 18px calc(20px + env(safe-area-inset-bottom)); animation-name: kSheetUp; }
  .modal::before { content: ""; display: block; width: 40px; height: 4px; margin: 6px auto 12px; border-radius: 3px; background: var(--hair-2); }   /* the grabber */
  /* three actions never fit one phone line: stacked full width, the primary on top where a thumb lands; and a long sheet
     keeps them in reach */
  .modal .modal-acts { flex-direction: column-reverse; align-items: stretch; position: sticky; z-index: 3; bottom: calc(-20px - env(safe-area-inset-bottom));
    margin: 12px 0 calc(-20px - env(safe-area-inset-bottom)); padding: 10px 0 calc(20px + env(safe-area-inset-bottom)); background: var(--surface); border-top: 1px solid var(--hair); }
  .modal .modal-acts .btn { width: 100%; justify-content: center; }
  .modal .modal-acts > .row { flex-direction: column-reverse; align-items: stretch; width: 100%; }
  .modal .table-wrap:has(> table.stack) { max-height: 50vh; overflow-y: auto; }
  /* a 2.x dialog's last row of buttons only (confirmModal and the like): stacked full width, the main action on top, as .sx-acts */
  .modal > .row:last-child:not(:has(> :not(.btn, button))) { flex-direction: column-reverse; align-items: stretch; }
  .modal > .row:last-child:not(:has(> :not(.btn, button))) > :is(.btn, button) { width: 100%; justify-content: center; }
}
@media (prefers-reduced-transparency: reduce) { .modal-back, .cmdk-back { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(11,18,32,.66); } }
@media (prefers-contrast: more) { .modal { border-color: var(--ink); box-shadow: none; } }

/* ---------------- ⌘K: the command palette (shared.js openCmdk) ----------------
   Over a pop-up (1250), since it takes the keyboard; it drops from the top of the window, where ⌘K lives in the mind. */
.cmdk-back { position: fixed; inset: 0; z-index: 1250; display: flex; justify-content: center; align-items: flex-start; padding: 12vh 16px 0;
  background: rgba(11,18,32,.34); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); animation: kScrimIn var(--t-std) backwards; }
[data-theme="dark"] .cmdk-back { background: rgba(0,0,0,.52); }
.cmdk { width: 100%; max-width: 560px; overflow: hidden; border-radius: var(--r-xl); border: 1px solid var(--glass-edge);
  background: color-mix(in srgb, var(--surface) 90%, transparent); -webkit-backdrop-filter: blur(22px) saturate(var(--glass-sat)); backdrop-filter: blur(22px) saturate(var(--glass-sat));
  box-shadow: 0 26px 64px -18px rgba(11,18,32,.5); transform-origin: top center; animation: kModalRise var(--t-std) backwards; }
.cmdk input { display: block; width: 100%; height: 54px; min-height: 0; padding: 0 18px; border: 0; border-bottom: 1px solid var(--hair); border-radius: 0;
  background: transparent; color: var(--ink); font-size: 15px; font-weight: var(--fw-med); }
.cmdk input:focus { border-color: var(--hair); box-shadow: none; }
.cmdk-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--hair); background: var(--well); }
.cmdk-only { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); white-space: nowrap; cursor: pointer; }
.cmdk input.cmdk-tick, .cmdk-only input { width: auto; height: auto; margin: 0; border: 0; }
.cmdk-chips { display: flex; flex-wrap: wrap; gap: 5px; flex: 1; min-width: 0; }
.cmdk-chip { height: 24px; padding: 0 9px; border-radius: var(--r-pill); border: 1px solid var(--hair-2); background: transparent; color: var(--muted);
  font: var(--fw-semi) 11.5px var(--font); cursor: pointer; transition: background var(--t-quick), color var(--t-quick), border-color var(--t-quick); }
.cmdk-chip:hover { color: var(--ink); border-color: var(--muted); }
.cmdk-chip.on { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.cmdk-clear { padding: 2px; border: 0; background: none; color: var(--muted); font: var(--fw-semi) 11.5px var(--font); text-decoration: underline; cursor: pointer; }
.cmdk-chip:focus-visible, .cmdk-clear:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.cmdk-list { max-height: 46vh; overflow-y: auto; padding: 6px; }
.cmdk-item { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 8px 12px; border-radius: var(--r-m); color: var(--ink); cursor: pointer; }
.cmdk-item > span:not(.kind):not(.sub) { flex: 0 1 auto; max-width: 70%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }   /* the name keeps its room; the address gives way */
.cmdk-item .sub { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--muted); font-size: 12.5px; white-space: nowrap; }
.cmdk-item .kind { margin-left: auto; flex: none; font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.cmdk-item:hover { background: var(--well); }
.cmdk-item.sel { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.cmdk-item svg { width: 15px; height: 15px; flex: none; color: var(--muted); }
.cmdk-empty { padding: 18px; text-align: center; color: var(--muted); }
@media (pointer: coarse) {   /* a finger's reach at any width (review 10/23) */
  .cmdk-only, .cmdk-clear, .cmdk-item { min-height: var(--tap); }
  .cmdk-clear { padding: 0 8px; }
  .cmdk-chip { height: 36px; position: relative; }
  .cmdk-chip::after { content: ""; position: absolute; inset: -4px 0; }
}
@media (max-width: 560px) {
  .cmdk-back { padding-top: max(12px, env(safe-area-inset-top, 0px)); }
  .cmdk-only { flex: 0 0 auto; min-height: var(--tap); }
  .cmdk-clear { order: 1; margin-left: auto; min-height: var(--tap); padding: 0 8px; }
  .cmdk-chips { order: 2; flex: 1 1 100%; }
  .cmdk-chip { height: 36px; padding: 0 12px; font-size: 12.5px; }
  .cmdk-item { min-height: var(--tap); }
  /* two lines on a phone, as 2.x had them: the name and its kind, then the address in full (w10retire question 4, 10/23) */
  .cmdk-item { display: grid; grid-template-columns: 15px minmax(0, 1fr) auto; grid-template-areas: "i n k" "i s s"; column-gap: 10px; row-gap: 1px; }
  .cmdk-item > svg { grid-area: i; align-self: start; margin-top: 2px; }
  .cmdk-item > span:not(.kind):not(.sub) { grid-area: n; max-width: none; }
  .cmdk-item .sub { grid-area: s; white-space: normal; overflow-wrap: anywhere; }
  .cmdk-item .kind { grid-area: k; margin-left: 0; }
}

/* ---------------- the list pager (shared.js listPage → pagerHtml): under a long list, its own top-level block ---------------- */
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.pager-count { flex: 1 1 0; font-size: 12.5px; color: var(--muted); }
.pager-count b { color: var(--ink); font-weight: var(--fw-bold); }
.pager-mid { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.pager-per { flex: 1 1 0; display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin: 0; font-size: 12.5px; font-weight: var(--fw-med); color: var(--muted); }
.pager-per select { width: auto; min-width: 72px; margin: 0; }
.pager-num, .pager-step { min-width: 34px; height: 34px; padding: 0 8px; border-radius: var(--r-s); border: 1px solid var(--hair-2); background: var(--glass-a);
  color: var(--ink); font: var(--fw-semi) 13px/1 var(--font); font-variant-numeric: tabular-nums; cursor: pointer; transition: background var(--t-quick), border-color var(--t-quick); }
.pager-num:hover, .pager-step:not([disabled]):hover { border-color: var(--muted); background: var(--glass-hi); }
.pager-num.on, .pager-num.on:hover { background: var(--ink); border-color: var(--ink); color: var(--on-ink); font-weight: var(--fw-bold); }
.pager-step { font-size: 18px; }
.pager-step[disabled] { opacity: .35; cursor: not-allowed; }
.pager-gap { color: var(--muted); padding: 0 2px; }
@media (max-width: 900px), (pointer: coarse) { .pager .pager-num, .pager .pager-step { min-width: var(--tap); height: var(--tap); } }
@media (max-width: 724px) {   /* the numbers sit right under the list, the count above them, the page size last */
  .pager { justify-content: center; text-align: center; }
  .pager-count, .pager-per { flex: 1 1 100%; justify-content: center; }
  .pager-mid { order: 2; flex: 1 1 100%; justify-content: center; flex-wrap: wrap; }
  .pager-per { order: 3; }
}

/* ---------------- 2.x's status words and status dropdowns, on the kit's tones ----------------
   .badge.<tone> is 2.x's status word (the kit's bare .badge is the top bar's count); select.status-sel is 2.x's status
   dropdown and takes the kit's .status look — a 28px pill, its tone's colours, moving both ways. Teal (Ready to Invoice),
   navy (Invoiced) and purple (the Awaiting holds) are the billing and hold steps, kept off the working statuses' colours. */
.badge:is(.ok, .warn, .bad, .info, .muted, .teal, .billed, .hold):not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { width: auto; height: 20px; padding: 0 8px; border-radius: var(--r-pill); font-size: 11.5px; font-weight: var(--fw-semi); white-space: nowrap; }
.badge.ok:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--ok) 12%, var(--surface)); color: var(--ok); }
.badge.warn:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--warn) 12%, var(--surface)); color: var(--warn); }
.badge.bad:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--bad) 12%, var(--surface)); color: var(--bad); }
.badge.info:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--info) 12%, var(--surface)); color: var(--info); }
.badge.muted:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: var(--well); color: var(--ink-2); }
.badge.teal:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--teal) 12%, var(--surface)); color: var(--teal); }
.badge.billed:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--navy) 12%, var(--surface)); color: var(--navy); }
.badge.hold:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { background: color-mix(in srgb, var(--chart-7) 12%, var(--surface)); color: var(--chart-7); }
select.status-sel:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { width: auto; max-width: 100%; height: 28px; min-height: 0; padding: 0 24px 0 11px; border-radius: var(--r-pill); border: 1px solid var(--hair-2);
  background-color: var(--well); color: var(--ink-2); font: var(--fw-bold) 12px var(--font); cursor: pointer; }
select.status-sel.ok:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--ok); background-color: var(--ok-bg); border-color: var(--ok-line); }
select.status-sel.warn:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--warn); background-color: var(--warn-bg); border-color: var(--warn-line); }
select.status-sel.bad:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--bad); background-color: var(--bad-bg); border-color: var(--bad-line); }
select.status-sel.info:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--info); background-color: var(--info-bg); border-color: var(--info-line); }
select.status-sel.muted:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--ink-2); background-color: var(--well); border-color: var(--hair-2); }
select.status-sel.teal:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--teal); background-color: color-mix(in srgb, var(--teal) 12%, transparent); border-color: color-mix(in srgb, var(--teal) 32%, transparent); }
select.status-sel.billed:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--navy); background-color: color-mix(in srgb, var(--navy) 10%, transparent); border-color: color-mix(in srgb, var(--navy) 30%, transparent); }
select.status-sel.hold:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { color: var(--chart-7); background-color: color-mix(in srgb, var(--chart-7) 12%, transparent); border-color: color-mix(in srgb, var(--chart-7) 32%, transparent); }
select.status-sel.chip:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) { height: 24px; font-size: 11.5px; padding: 0 22px 0 10px; }
@media (max-width: 640px), (pointer: coarse) { select.status-sel, select.status-sel.chip, select.status { min-height: var(--tap); } }   /* the thumb's 44px; a mouse in a narrowed window keeps the 28px pill (S10) */
@media (min-width: 641px) and (pointer: fine) { :is(td, li, .card, .sbe-gc) select:is(.status, .status-sel) { min-height: 0; } }   /* ...in a table, a card or a list row, against the 44px every box takes at 1180 and under; in a head or a row of buttons it stays their height */
@media (max-width: 900px) { select.status-sel.chip { flex: 1 1 200px; } }

/* ---------------- phone tables: below 700px a list is a column of cards (phone-tables.js stamps table.stack) ----------------
   A card is the row's title, the fields that matter (each label above its value), and the rest behind "Show all fields".
   Grids and printed documents keep scrolling (phone-tables.js opts them out). Print is untouched (screen only). */
td.stack-more { display: none; }
.stack-sort { display: none; }   /* the "Sort by" dropdown phone-tables.js puts above a sortable list: the cards have no headings to tap */
@media screen and (max-width: 700px) {
  .stack-sort { display: block; width: 100%; margin: 0 0 10px; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *):has(> table.stack) { overflow: visible; max-height: none; background: transparent; border: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack, .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack > tbody { display: block; width: 100%; min-width: 0; background: transparent; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-head { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-head.has-ctl { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 0 4px 6px; }   /* a heading row carrying a control (select-all, sort) stays, as a slim bar */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-head.has-ctl > th { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-head.has-ctl > th:has(button, input, select) { display: flex; align-items: center; gap: 8px; min-height: var(--tap); padding: 0; border: 0; background: transparent; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-head th:has(> input[type=checkbox])::after { content: 'Select all'; font-size: 13px; font-weight: var(--fw-semi); color: var(--ink); }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:not(.stack-head) { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-auto-flow: row dense; gap: 8px 14px; align-items: start;
    position: relative; margin: 0 0 10px; padding: 12px 14px; border-radius: var(--r-l); background: linear-gradient(150deg, var(--glass-a), var(--glass-b));
    border: 1px solid var(--glass-edge); box-shadow: var(--shadow); }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:hover td, .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:nth-child(n) > td { background: transparent; }   /* beats every zebra and hover rule */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td { display: block; border: 0; padding: 0; min-width: 0; width: auto; max-width: none; text-align: left; white-space: normal;
    overflow-wrap: anywhere; position: static; box-shadow: none; font-size: 13.5px; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td::before { content: attr(data-label); display: block; margin-bottom: 2px; font-size: 11px; font-weight: var(--fw-semi); color: var(--muted); }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-label=""]::before { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-blank] { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td:empty::after { content: '—'; color: var(--muted); }   /* an empty value keeps its slot, so the cards share one shape */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-wide], .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[colspan] { grid-column: 1 / -1; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td.num { text-align: left; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-title] { order: -1; padding-bottom: 6px; border-bottom: 1px solid var(--hair); font-size: 15px; font-weight: var(--fw-bold); color: var(--ink); text-align: left; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-title]::before { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-title] .sub { display: block; margin-top: 2px; font-size: 12.5px; font-weight: var(--fw-med); }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-title] a { display: inline-block; padding: 11px 0; margin: -11px 0; }   /* a 40px reach, the same look */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-title] .row > a.btn { display: inline-flex; align-items: center; justify-content: center; padding: 0; margin: 0; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td a { max-width: 100%; overflow-wrap: anywhere; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td:not([data-title]) a:not(.btn):not(.badge) { display: inline-flex; align-items: center; min-height: var(--tap); min-width: var(--tap); }   /* a thumb's 44 (40 before; w15polish K3: a phone card's quote number, customer, e-mail) */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:not(.open) > td[data-more] { display: none; }   /* the fields that wait behind the button */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td.stack-more { display: block; order: 91; grid-column: 1 / -1; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td.stack-more::before { display: none; }
  .stack-more-btn { min-height: 40px; padding: 0; border: 0; background: none; font: var(--fw-semi) 13px var(--font); color: var(--accent-ink); cursor: pointer; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td > :is(input:not([type=checkbox]):not([type=radio]), select, textarea) { width: 100%; max-width: none; min-width: 0; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-check] { display: flex; align-items: center; gap: 10px; min-height: var(--tap); cursor: pointer; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-check] > input { order: -1; flex: none; margin: 0; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-check]::before { margin: 0; font-size: 13px; color: var(--ink); }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-pick] { position: absolute; top: 4px; right: 4px; width: var(--tap); height: var(--tap); display: flex; align-items: center; justify-content: center; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-pick]::before { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:has(> td[data-pick]) > td[data-title] { padding-right: var(--tap); }
  /* a row of buttons: two to a line, an odd last one across */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-acts] { order: 90; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-acts]::before { display: none; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-acts] > :is(.btn, button) { width: 100%; margin: 0; justify-content: center; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack td[data-acts] > :last-child:nth-child(odd) { grid-column: 1 / -1; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:has(> td[data-acts]) { grid-auto-flow: row; }
  /* a note across the list, and a total */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-note { display: block; background: transparent; border: 0; box-shadow: none; padding: 8px 2px; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-note > td { color: var(--muted); text-align: center; font-weight: var(--fw-reg); }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-sum { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 10px 14px; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-sum > td { font-weight: var(--fw-bold); text-align: left; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-sum > td::before { display: none; }
  /* cards inside a panel: one frame, not two */
  :is(.glass, .card, .viz-card, .modal) .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr:not(.stack-head):not(.stack-note):not(.stack-sum) { background: transparent; border: 0;
    border-top: 1px solid var(--hair); border-radius: 0; box-shadow: none; margin: 0; padding: 12px 0; }
  :is(.glass, .card, .viz-card, .modal) .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.stack tr.stack-head + tr:not(.stack-head):not(.stack-note):not(.stack-sum) { border-top: 0; }
  /* …and a panel with no padding of its own (a bare .glass round a table) gives its rows the card's side inset, or the text runs into the frame (w30 review: Momentum Dashboards, Apex Customers, Contracts) */
  .glass:not(.pad) > .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *):has(> table.stack) { padding-inline: 14px; }
  /* narrow tables stay tables — but may wrap, and a header-less list wraps instead of scrolling */
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > :is(table.fits, table.no-head) { width: 100%; min-width: 0; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.fits :is(td, th), .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.no-head td { white-space: normal; overflow-wrap: anywhere; }
  .table-wrap:not(:where(.q-sheet, .print-doc, .ts-sheet, [data-doc], .pub-page, .li-page) *) > table.fits :is(th, td) { padding-left: 6px; padding-right: 6px; }
}

/* ---------------- print: the frame never reaches paper ----------------
   The printed documents' own sheet is public/print.css. Here the page itself becomes paper: white, no aurora, no frame, no
   pop-ups, toasts, Aimsly or menus, and the light tokens even from a dark screen (tokens.css). A printed page is ~816 CSS
   px wide, inside every phone media query, so anything fixed to a corner belongs on this list or it reaches the paper. */
@page { size: 8.5in 11in; margin: 0.45in; }
.print-only { display: none; }
@media print {
  html, body { background: #fff; }
  .aurora, .no-print, .sidebar, .topbar, .tn-bar, .drop-btn, .drawer-edge, .scrim, .menu-btn, .fold, .pager, #agent-fab, #agent-panel, #agent-root, .fr-pill,
  .cmdk-back, .viz-tip, .modal-back, .tour-back, .toast, #toast, .hist-chip, .face, .msg-av, .av-chip, .filt-toggle,
  .iv-back, .sbe-sheet-back, .tw-back, .mx-dialog-back, .sfy-c-sheet-back { display: none !important; }
  /* Any open pop-up, by the one mark every pop-up carries: a layer on the page (a child of body) that is, or holds, the
     dialog (aria-modal). A new pop-up with its own class needs no line here (w11vault-releases #2: Inventory, Settings
     sheets and the crew trip walk printed over the page). */
  body > [aria-modal="true"], body > :has(> [aria-modal="true"]) { display: none !important; }
  tr.print-only { display: table-row; }
  :is(td, th).print-only { display: table-cell; }
  :not(tr, td, th).print-only { display: block; }
  .app { display: block; padding: 0; }
  .main { padding: 0; gap: 12px; }
  .glass, .card, .table-wrap { background: none; border-color: var(--hair-2); box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .table-wrap { overflow: visible; max-height: none; }
  .table-wrap > table { width: 100%; min-width: 0; }
  a { color: inherit; text-decoration: none; }
  .grid-2, .grid2 { grid-template-columns: 1fr 1fr; }
  .grid-3, .grid3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-4, .grid4, .strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .strip.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .card, .glass, .viz, figure, tr { break-inside: avoid; }
  :is(h1, h2, h3, thead) { break-after: avoid; }
  :is(input, textarea)::placeholder { color: transparent; }
}

/* ---------------- the language switch: EN | ES (public/i18n.js switchHTML) ----------------
   Its own words are never translated. .i18n-float is the corner switch a page asks for with <html data-i18n-switch>;
   the customer pages' bar (customer-pages.css) sets its own. */
.i18n-switch { display: inline-flex; flex: none; gap: 2px; padding: 3px; border-radius: var(--r-pill); background: var(--well); vertical-align: middle; }
.i18n-switch button { all: unset; box-sizing: border-box; min-width: 36px; height: 28px; padding: 0 10px; border-radius: var(--r-pill); text-align: center; cursor: pointer;
  font: var(--fw-bold) 12px/28px var(--font); letter-spacing: .04em; color: var(--muted); transition: background var(--t-quick), color var(--t-quick); }
.i18n-switch button:hover { color: var(--ink); }
.i18n-switch button.on { background: var(--ink); color: var(--on-ink); }
.i18n-switch button:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.i18n-float { position: fixed; top: max(10px, env(safe-area-inset-top, 0px)); right: 10px; z-index: 50; border: 1px solid var(--glass-edge);
  background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur)); box-shadow: var(--shadow-pop); }
@media (pointer: coarse) { .i18n-switch button { min-width: var(--tap); height: var(--tap); line-height: var(--tap); } }
@media print { .i18n-switch { display: none !important; } }
/* ================ end of the frame's furniture ================ */

/* ================ the shared pieces (sx-): shared.js, people-picker.js, charts.js, fluid.js (w9shell, 10/23) ================
   Every product draws these: the pop-ups behind every drillable figure, the merge, the contact edit, the person card, the
   password check, the pickers, faces. Their buttons are wired in shared.js (data-sx + one listener per event). */

/* a dialog's inside: a column on the kit's gap, the buttons at its foot */
.sx-dlg { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; min-width: 0; }   /* one column that may shrink: a wide drill table scrolls in its box, not the sheet */
.sx-dlg h2 { margin: 0; font-size: var(--fs-xl); }
.sx-dlg h2 + .hint { margin: 4px 0 0; }
.sx-dlg p { margin: 0; }
.sx-dlg .field > label { margin: 0; }
.sx-dlg .field { margin: 0; }   /* 2.x gave every .field 10px below; here the dialog's gap spaces them */
.sx-h3 { margin: 4px 0 -6px; font-size: 13.5px; }
.sx-note { padding: 10px 12px; border-radius: var(--r-m); background: var(--info-bg); border: 1px solid var(--info-line); font-size: 13px; line-height: 1.5; color: var(--ink); }
.sx-note.warn { background: var(--warn-bg); border-color: var(--warn-line); }
.sx-note.bad { background: var(--bad-bg); border-color: var(--bad-line); }
.sx-note-act { margin-top: 8px; }
.sx-quote { margin: 8px 0 0; font-style: italic; }
.sx-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; }
.sx-span { grid-column: 1 / -1; }
.sx-check { display: flex; align-items: flex-start; gap: 10px; margin: 0; font-size: 13px; font-weight: var(--fw-med); color: var(--ink); cursor: pointer; }
.sx-check > input { flex: none; margin: 2px 0 0; }
.sx-check b { font-weight: var(--fw-bold); }
.sx-line { display: block; margin-top: 2px; }
.sx-grid > .sx-check:not(.sx-span) { align-self: end; min-height: var(--ctl); align-items: center; }   /* level with the box beside it */
.sx-grid > .sx-check:not(.sx-span) > input { margin: 0; }
@media (max-width: 900px), (pointer: coarse) { .sx-grid > .sx-check:not(.sx-span) { min-height: var(--tap); } }
.sx-acts { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
.sx-acts.sx-between { justify-content: space-between; }
.sx-bad { color: var(--bad); } .sx-warn { color: var(--warn); }
.sx-err { margin: 0; min-height: 1.2em; font-size: 12.5px; color: var(--bad); }
.sx-pad { padding: 10px 12px; }
.modal.sx-narrow { max-width: 420px; }
/* the password check's Face ID way (w18platform, w17-faceid-confirm): the device's own check first, the password under a rule */
.sx-pk { display: grid; gap: 12px; }
.sx-pk[hidden] { display: none; }
.sx-pk-go { width: 100%; justify-content: center; }
.sx-or { display: flex; align-items: center; gap: 12px; font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); }
.sx-or::before, .sx-or::after { content: ""; flex: 1; height: 1px; background: var(--hair-2); }
.sx-msg { white-space: pre-line; }   /* a confirm keeps its line breaks; it is always escaped text, never markup (shared.js sxConfirm) */
@media (max-width: 640px) { .sx-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 700px) { .sx-acts:not(.sx-between) { flex-direction: column-reverse; align-items: stretch; } .sx-acts:not(.sx-between) > .btn { justify-content: center; } }
@media (max-width: 900px), (pointer: coarse) { .sx-check { min-height: var(--tap); align-items: center; } .sx-check > input { margin: 0; } }

/* the merge: pick the survivor from a short list, then read what would move */
.sx-pickbox { max-height: 220px; overflow: auto; border: 1px solid var(--hair); border-radius: var(--r-l); }
.sx-pickbox:empty { display: none; }
.sx-pick { display: flex; align-items: center; gap: 10px; margin: 0; padding: 9px 12px; border-bottom: 1px solid var(--hair); font-size: 13px; font-weight: var(--fw-med); color: var(--ink); cursor: pointer; }
.sx-pick:last-child { border-bottom: 0; }
.sx-pick:hover { background: var(--well); }
.sx-pick > input { flex: none; margin: 0; }
.sx-merge { display: grid; gap: 8px; }
.sx-merge table.t :is(th, td) { padding: 6px 8px; }
.sx-merge table.t :is(th, td):first-child { padding-left: 0; } .sx-merge table.t :is(th, td):last-child { padding-right: 0; }   /* the table's text on the note's own edges */
@media (pointer: coarse) { .sx-pick { min-height: var(--tap); } }

/* the rows behind a figure (openDrill): the title and its count, a filter, the rows sortable by any heading */
.sx-drill-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
.sx-drill-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.sx-drill-tools .input { flex: 1 1 200px; max-width: 300px; }
.sx-drill-scroll { max-height: 56vh; overflow: auto; border: 1px solid var(--hair); border-radius: var(--r-l); }
.sx-id { white-space: nowrap; }   /* a record's number in a drill: one piece (K9) */
/* on a phone the drill's table is the kit's phone cards (it is a .table-wrap, so phone-tables.js stacks it; w11design K10:
   a 481–706px table scrolled sideways inside a 375px sheet, names wrapped to four lines) */
.sx-drill-scroll table.t thead th { position: sticky; top: 0; z-index: 1; background: var(--surface); box-shadow: 0 1px 0 var(--hair); }
.sx-drill-scroll table.t tfoot td { border-top: 1px solid var(--hair-2); background: var(--surface-2); }
table.t th.sx-sortable { padding: 0; }
.sx-sort { all: unset; box-sizing: border-box; display: inline-flex; align-items: center; gap: 5px; width: 100%; padding: 10px 12px; cursor: pointer; white-space: nowrap; }
th.r .sx-sort { justify-content: flex-end; }
.sx-sort:hover, th.sorted .sx-sort { color: var(--ink); }
.sx-sort:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.sx-sort-i { display: inline-flex; flex-direction: column; font-size: 8px; line-height: .62; opacity: .65; }   /* .65: 3:1 for a control's indicator */
.sx-sort-i i { font-style: normal; }
th.sorted .sx-sort-i { opacity: 1; }
th.sorted .sx-sort-i i.off { opacity: .22; }
@media (max-width: 700px) { .sx-drill-scroll { max-height: 50vh; } .sx-drill-tools .input { max-width: none; } }
/* B32 (wave 17): a drill never scrolls sideways. Headings wrap between words; a table still wider than the box is drawn as
   cards (shared.js drillFit sets .sx-cards): the sort buttons stay as a bar on top, each row a card in as many columns
   as fit, each value under its own label (the cells carry data-label), the row's name first. */
.sx-drill-scroll .sx-sort { white-space: normal; }
.sx-drill-scroll.sx-cards { overflow-x: hidden; }
.sx-drill-scroll.sx-cards > table.t, .sx-drill-scroll.sx-cards > table.t > thead, .sx-drill-scroll.sx-cards > table.t > tbody,
  .sx-drill-scroll.sx-cards > table.t > tfoot { display: block; width: 100%; }
.sx-drill-scroll.sx-cards > table.t > thead { position: sticky; top: 0; z-index: 1; background: var(--surface); box-shadow: 0 1px 0 var(--hair); }
.sx-drill-scroll.sx-cards > table.t > thead > tr { display: flex; flex-wrap: wrap; gap: 0 4px; padding: 2px 6px; }
.sx-drill-scroll.sx-cards > table.t > thead th { position: static; box-shadow: none; background: transparent; border: 0; }
.sx-drill-scroll.sx-cards > table.t > thead .sx-sort { width: auto; padding: 8px 8px; white-space: nowrap; }
.sx-drill-scroll.sx-cards > table.t > tbody { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; padding: 10px; }
.sx-drill-scroll.sx-cards > table.t > tbody > tr { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; align-content: start;
  padding: 12px 14px; border: 1px solid var(--hair); border-radius: var(--r-m); background: var(--surface); }
.sx-drill-scroll.sx-cards > table.t > tbody > tr > td { display: block; min-width: 0; padding: 0; border: 0; background: transparent; text-align: left; white-space: normal; overflow-wrap: break-word; }
.sx-drill-scroll.sx-cards > table.t > tbody > tr > td::before { content: attr(data-label); display: block; margin-bottom: 2px; font-size: 11px; font-weight: var(--fw-semi); color: var(--muted); }
.sx-drill-scroll.sx-cards > table.t > tbody > tr > td[data-title] { grid-column: 1 / -1; order: -1; padding-bottom: 6px; border-bottom: 1px solid var(--hair); font-size: 14px; font-weight: var(--fw-bold); color: var(--ink); }
.sx-drill-scroll.sx-cards > table.t > tbody > tr > td[data-title]::before { display: none; }
.sx-drill-scroll.sx-cards > table.t > tfoot > tr { display: flex; justify-content: flex-end; gap: 12px; padding: 10px 14px; }
.sx-drill-scroll.sx-cards > table.t > tfoot td { border: 0; background: transparent; }
@media (max-width: 900px), (pointer: coarse) {
  .sx-sort { min-height: var(--tap); }
  .sx-drill-scroll td a { display: inline-block; padding: 12px 0; margin: -12px 0; }   /* a 44px reach, the same look */
}

/* the customer and city pickers (customerPickerHTML, cityPickerHTML): type, and the matches drop under the box */
.cust-pick { position: relative; }
.cust-pick-list { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40; max-height: 240px; overflow-y: auto; padding: 4px;
  background: var(--surface); border: 1px solid var(--hair-2); border-radius: var(--r-m); box-shadow: var(--shadow-pop); }
.cust-pick-item { display: flex; justify-content: space-between; gap: 8px; padding: 8px 10px; border-radius: var(--r-s); font-size: 13px; color: var(--ink); cursor: pointer; }
.cust-pick-item > * { min-width: 0; overflow-wrap: anywhere; }
.cust-pick-item:hover { background: var(--well); }
.cust-pick-sub, .cust-pick-none { color: var(--muted); font-size: 12px; }
.cust-pick-none { cursor: default; }
.cust-pick-none:hover { background: none; }
@media (max-width: 900px), (pointer: coarse) { .cust-pick-item { min-height: var(--tap); align-items: center; } }

/* a filter bar's "Save as my default view" (viewControlHTML) */
.view-ctl { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
.view-ctl-a { all: unset; cursor: pointer; padding: 4px 2px; font-size: 12.5px; font-weight: var(--fw-semi); color: var(--muted); }
.view-ctl-a:hover { color: var(--ink); text-decoration: underline; }
.view-ctl-a:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
@media (pointer: coarse) { .view-ctl-a { display: inline-flex; align-items: center; min-height: var(--tap); } }

/* faces (faceHTML, facesHTML, whoHTML): a person's picture or initials on their own colour (--av, data), and the name beside it */
.face { flex: none; display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; overflow: hidden; border-radius: 50%;
  background-color: var(--surface); border: 1px solid var(--hair-2); color: #0B1220; font-weight: var(--fw-bold); letter-spacing: .02em; user-select: none; }
.face-sm { width: 22px; height: 22px; font-size: 9.5px; }
.face-md { width: 32px; height: 32px; font-size: 12.5px; }
.face-logo { background: var(--surface) url('/aims-a.png') center / 74% auto no-repeat; }
.face-ini { border-color: transparent; background: var(--av, var(--well)); }   /* dark initials: white failed on every hue */
.face-img { background-size: cover; background-position: center; background-repeat: no-repeat; }
.face[data-who], .msg-av[data-who], .pc-open { cursor: pointer; }
.face[data-who]:hover, .msg-av[data-who]:hover { outline: 2px solid var(--ink); outline-offset: 1px; }
.faces { display: inline-flex; align-items: center; vertical-align: middle; }
.faces > .face + .face, .faces > .faces-more { margin-left: -7px; }
.faces > .face, .faces > .faces-more { box-shadow: 0 0 0 2px var(--surface); }
.faces-more { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%;
  background: var(--well); color: var(--muted); font-size: 9.5px; font-weight: var(--fw-bold); user-select: none; }
.who { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; vertical-align: middle; }
.who > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* a face inside a button, a badge or a task's who: the smaller step (w10retire: was styles.css's) */
.btn .who, .badge .who { gap: 5px; }
:is(.btn, .badge, .task-who) .face-sm { width: 18px; height: 18px; font-size: 8px; }
@media (pointer: coarse) {   /* a face is a tap target: a 44px halo, except inside a stack, where the faces grow apart instead */
  .face[data-who] { position: relative; overflow: visible; }
  .face[data-who]::after { content: ''; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); border-radius: 50%; }
  .faces > .face[data-who]::after { content: none; }
}
@media (max-width: 900px) {
  .faces > .face[data-who]::after { content: none; }
  .faces > .face, .faces > .faces-more { width: 26px; height: 26px; font-size: 10.5px; }
  .faces > .face + .face, .faces > .faces-more { margin-left: 2px; }
}
/* your picture beside your name, outside the 3.0 frame (paintAvatarChip; in the frame it is the kit's .avatar) */
.av-chip { flex: none; width: 26px; height: 26px; border-radius: 50%; overflow: hidden; background-color: var(--surface); border: 1px solid var(--hair-2); }
.av-chip img, .avatar.round img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
.av-chip.av-logo { background: var(--surface) url('/aims-a.png') center / 74% auto no-repeat; }
.av-chip.av-ini { display: inline-flex; align-items: center; justify-content: center; font-size: 10px; font-weight: var(--fw-bold); color: var(--muted); }
a.av-chip { cursor: pointer; text-decoration: none; }
a.av-chip:hover, a.av-chip:focus-visible { border-color: var(--ink); }
@media (max-width: 640px) { .av-chip { display: none; } }

/* the person card (personCard): the picture large, how to reach them, and what to do next */
.pc-head { display: flex; align-items: center; gap: 16px; }
.pc-face { flex: none; width: 88px; height: 88px; border-radius: 50%; object-fit: cover; display: inline-flex; align-items: center; justify-content: center;
  background: var(--av, var(--well)); border: 2px solid var(--hair-2); font-size: 30px; font-weight: var(--fw-bold); color: #0B1220; }
.pc-face.pc-logo { background: #fff url('/aims-a.png') center / 72% auto no-repeat; }
.pc-who { min-width: 0; }
.pc-who h2 { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pc-body { padding-top: 10px; border-top: 1px solid var(--hair); }
.pc-row { display: flex; align-items: baseline; gap: 10px; padding: 4px 0; }
.pc-lbl { flex: none; min-width: 58px; font-size: 11px; font-weight: var(--fw-semi); color: var(--muted); }
.pc-row > :last-child { min-width: 0; overflow-wrap: anywhere; }
.pc-acts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.pc-acts > .btn { width: 100%; justify-content: center; }
@media (max-width: 560px) { .pc-acts { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 900px), (pointer: coarse) { .pc-row { align-items: center; padding: 0; } .pc-row > a { display: inline-flex; align-items: center; min-height: var(--tap); } }

/* a ticket's customer rating (ratingCell) */
.rt-stars-cell { white-space: nowrap; letter-spacing: 1px; font-size: 13px; color: #B7791F; }
[data-theme="dark"] .rt-stars-cell { color: #F5BF5C; }
.rt-flag { white-space: nowrap; }

/* what an import is about to change (importDiffHTML) */
.imp-diff { display: flex; flex-direction: column; gap: 10px; }
.imp-diff > * { margin: 0; }
.imp-sum { font-size: 14px; line-height: 1.6; }
.imp-cols { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.imp-note { display: grid; gap: 6px; padding: 12px 14px; border-radius: var(--r-l); background: var(--warn-bg); border: 1px solid var(--warn-line); }
.imp-note.bad { background: var(--bad-bg); border-color: var(--bad-line); }
.card.imp-note { background: var(--warn-bg); border-color: var(--warn-line); box-shadow: none; }   /* the note is a .card too: its tone, not the card's glass */
.card.imp-note.bad { background: var(--bad-bg); border-color: var(--bad-line); }
.imp-note > b { display: block; }
.imp-note ul { margin: 0; padding-left: 18px; }
.imp-note p { margin: 0; }
.imp-filter { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.imp-filter > label { margin: 0; }
.imp-filter select { width: auto; min-width: 180px; }
.imp-table { max-height: 46vh; overflow: auto; }
.imp-suspect { margin-top: 2px; font-size: 11.5px; font-weight: var(--fw-semi); color: var(--warn); }

/* a minimum measured against several items (minItemsPicker): a drop-down that opens into a tick list */
.min-items summary { cursor: pointer; padding: 7px 10px; border: 1px solid var(--hair-2); border-radius: var(--r-s); background: var(--glass-a); }
.min-items-list { max-height: 220px; overflow: auto; margin-top: 4px; padding: 6px 8px; border: 1px solid var(--hair-2); border-radius: var(--r-s); background: var(--surface); }
.min-items-list label { display: flex; align-items: center; gap: 8px; margin: 0; padding: 3px 0; font-size: 13px; color: var(--ink); cursor: pointer; }
.min-items-list label.off { opacity: .45; cursor: not-allowed; }
@media (pointer: coarse) { .min-items summary, .min-items-list label { min-height: var(--tap); display: flex; align-items: center; } }

/* revoking an approval (revokeApprovalDialog) */
.rv-dlg h2 { margin: 0 0 4px; }
.rv-dlg .rv-what { margin: 4px 0 12px; font-weight: var(--fw-semi); overflow-wrap: anywhere; }
.rv-conseq { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; padding: 10px 12px; border-radius: var(--r-m); background: var(--bad-bg); border: 1px solid var(--bad-line); font-size: 13px; }
.rv-conseq b { color: var(--bad); }
.rv-chain { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.rv-chain i { padding: 2px 9px; border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--bad-line); font-style: normal; font-weight: var(--fw-semi); }
.rv-chain em { font-style: normal; color: var(--muted); }
.rv-err { min-height: 1.2em; margin: 4px 0 8px; font-size: 13px; color: var(--bad); }
.rv-dlg textarea { width: 100%; min-height: 88px; }
.rv-dlg .rv-acts { display: flex; justify-content: flex-end; gap: 8px; }
.rv-dlg .rv-acts .btn, .rv-btn { min-height: var(--tap); }
.rv-notice { margin: 8px 0 0; padding: 8px 12px; border-radius: var(--r-m); background: var(--warn-bg); border: 1px solid var(--warn-line); font-size: 13px; line-height: 1.45; }
.rv-note { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.rv-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 10px; }
.rv-bar .rv-note { flex: 1 1 220px; min-width: 0; margin: 0; }

/* a save that fails outlines what it is missing (flagMissing) */
.field-missing, .field-missing:focus { border-color: var(--bad) !important; box-shadow: 0 0 0 3px color-mix(in srgb, var(--bad) 22%, transparent) !important; }

/* the searchable multi-select of people (people-picker.js) */
.pp { position: relative; }
.pp-box { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: var(--ctl); padding: 4px 8px; border: 1px solid var(--hair-2); border-radius: var(--r-m);
  background: var(--glass-a); cursor: text; transition: border-color var(--t-quick), box-shadow var(--t-std); }
.pp-box:focus-within { border-color: var(--ink); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 12%, transparent); }
.pp-chips { display: contents; }
.pp-box .pp-q { flex: 1 1 120px; min-width: 90px; height: 24px; min-height: 0; padding: 0; border: 0; background: transparent; box-shadow: none; }
.pp-box .pp-q:focus { box-shadow: none; }
.pp-chip { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 4px 0 9px; border-radius: var(--r-pill); background: var(--ink); color: var(--on-ink); font-size: 12px; font-weight: var(--fw-semi); white-space: nowrap; }
.pp-rm { border: 0; padding: 0 4px; background: none; color: inherit; font-size: 15px; line-height: 1; opacity: .7; cursor: pointer; }
.pp-rm:hover { opacity: 1; }
.pp-list { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40; max-height: 260px; overflow-y: auto; padding: 4px;
  background: var(--surface); border: 1px solid var(--hair-2); border-radius: var(--r-m); box-shadow: var(--shadow-pop); }
.pp-item { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: var(--r-s); font-size: 13px; color: var(--ink); cursor: pointer; }
.pp-item.sel, .pp-item:hover { background: var(--well); }
.pp-item.on { font-weight: var(--fw-bold); }
.pp-tick { width: 14px; font-weight: var(--fw-x); color: var(--ok); }
.pp-sub { margin-left: auto; font-size: 12px; color: var(--muted); }
.pp-none { color: var(--muted); cursor: default; }
@media (max-width: 900px), (pointer: coarse) { .pp-box { min-height: var(--tap); } .pp-box .pp-q { font-size: 16px; } .pp-item, .pp-rm { min-height: var(--tap); } .pp-rm { min-width: var(--tap); } .pp-chip { height: 32px; } }

/* charts (charts.js): a mark's colour rides as data (--vc); the chrome is the chart tokens */
.viz-svg { width: 100%; height: auto; display: block; }
.viz-bar { fill: var(--vc); cursor: pointer; }
.viz-line { fill: none; stroke: var(--vc); }
.viz-dot { fill: var(--vc); stroke: var(--chart-ring); }
.viz-pat { fill: var(--vc); } .viz-pat-l { stroke: var(--vc); }
.viz-grid { stroke: var(--chart-grid); }
.viz-base { stroke: var(--chart-base); }
.viz-target { stroke: var(--chart-muted); }
.viz-axis { fill: var(--chart-muted); }
.viz-end { fill: var(--chart-ink); }
.viz-ohit { stroke: transparent; }
.viz-legend-item i { background: var(--vc); }
.viz-tip.on { display: block; left: var(--tip-x, 0px); top: var(--tip-y, 0px); }

/* a filter bar of three or more dropdowns folds behind one "Filters (n)" button on a phone (shared.js; outside the query
   the dropdowns are never hidden, so a computer is untouched even though the row carries .filt-shut) */
.filt-toggle { display: none; }
@media (max-width: 700px) {
  .filt-toggle { display: inline-flex; flex: 1 1 100%; justify-content: center; }
  .filt-row > .filt-toggle { grid-column: 1 / -1; }   /* full width on a grid filter bar too (Apex), not one cell of it */
  .filt-toggle.on { border-color: var(--ink); color: var(--ink); font-weight: var(--fw-x); }
  .filt-toggle::after { content: " ▾"; }
  .filt-row:not(.filt-shut) > .filt-toggle::after { content: " ▴"; }
  .filt-row.filt-shut > :is(select, .select-wrap, .date-pair, .view-ctl) { display: none; }   /* 3.0 wraps each select in .select-wrap */
}

/* fluid.js: while a touch drag holds the finger, the browser must not also scroll */
.fl-claimed { touch-action: none; }
/* ================ end of the shared pieces ================ */

/* ---------------- special controls ---------------- */
/* slide to confirm — for the few hard-to-undo actions (Mark won, Submit pay app, Punch out). A real range input underneath. */
.slide { position: relative; height: 52px; border-radius: var(--r-pill); background: var(--well); box-shadow: inset 0 2px 4px rgba(16,24,40,.12); overflow: hidden; }
/* shell.js puts how far it has slid (0-100) in --slide; the fill and the knob follow it */
.slide .fillw { position: absolute; inset: 0 auto 0 0; width: calc(var(--slide, 0) * 1% + 26px); border-radius: var(--r-pill); background: linear-gradient(180deg, var(--water-ok-a), var(--water-ok-b)); transition: width var(--t-spring); }
.slide .knobw { position: absolute; top: 4px; left: calc(4px + (100% - 52px) * var(--slide, 0) / 100); width: 44px; height: 44px; border-radius: 50%; background: var(--ink); color: var(--on-ink); display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 14px -4px rgba(11,18,32,.6); transition: left var(--t-spring); pointer-events: none; }
.slide .text { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 13.5px; font-weight: var(--fw-bold); color: var(--ink-2); pointer-events: none; transition: opacity var(--t-quick); }
.slide.moved .text { opacity: 0; }
.slide input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; cursor: grab; }
.slide.dragging .fillw, .slide.dragging .knobw { transition: none; }
/* six-box code (.otp: a bare .code also matched Master Items' td.code and drew it as a 6-column grid, review 10/22) */
.otp { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px; max-width: 360px; }
.otp input { height: 54px; width: 100%; border-radius: var(--r-l); border: 1px solid var(--hair-2); background: var(--glass-a); text-align: center; font-size: 22px; font-weight: var(--fw-semi);
  transition: border-color var(--t-quick), box-shadow var(--t-std), transform var(--t-spring); }
.otp input:focus { outline: none; border-color: var(--ink); box-shadow: 0 0 0 4px rgba(11,18,32,.10); transform: translateY(-2px); }
.otp.done input { border-color: var(--ok-line); background: var(--ok-bg); }
/* switch */
.switch { width: 46px; height: 26px; border-radius: var(--r-pill); border: 0; padding: 0; background: var(--hair-2); position: relative; cursor: pointer; transition: background var(--t-std); }
.switch::after { content: ""; position: absolute; left: 3px; top: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform var(--t-spring); }
.switch[aria-checked="true"] { background: var(--ink); }
.switch[aria-checked="true"]::after { transform: translateX(20px); background: var(--on-ink); }   /* the knob takes the on-ink colour: in dark mode the on track is light, and a white knob vanished on it (review 10/22) */

/* ---------------- loading & empty ---------------- */
.skeleton { height: 12px; border-radius: 6px; background: linear-gradient(90deg, var(--well) 25%, var(--hair-2) 50%, var(--well) 75%); background-size: 200% 100%; animation: shimmer 1s linear infinite; }
.skeleton.title { height: 22px; } .skeleton.bar { height: 8px; }     /* a line of text by default; a heading; a pipe */
.skeleton.short { width: 40%; } .skeleton.mid { width: 70%; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.rise > * { animation: rise var(--t-std) both; }
.rise > *:nth-child(2) { animation-delay: 40ms; } .rise > *:nth-child(3) { animation-delay: 80ms; } .rise > *:nth-child(4) { animation-delay: 120ms; }
.rise > *:nth-child(5) { animation-delay: 160ms; } .rise > *:nth-child(n+6) { animation-delay: 200ms; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }
.empty { text-align: center; padding: 40px 20px; color: var(--muted); }

/* ---------------- page head: title and its words on the left, the screen's own views on the right ---------------- */
.page-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; }
.page-head h1.title { margin: 0; }
.lede { margin: 4px 0 0; max-width: 76ch; color: var(--muted); font-size: 13.5px; }
.strip.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }   /* three figures: 3 across, then 1 (never 2 + an orphan) */
@media (max-width: 980px) { .strip.three { grid-template-columns: minmax(0, 1fr); } }

/* ---------------- the wide grid (wg-): rows down the side, a year of months across ----------------
   Proved on the forecast (rebuild/kit/grid.html), built in Momentum → Forecast (3.0). Header, first column, totals row
   and totals column stay put while the months scroll; past months read, this month and later are typed or pasted. */
.wg-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 8px; }
.wg-tools .grow { flex: 1 1 200px; min-width: 0; }
.wg-tools .grow .input { width: 100%; height: 34px; }
@media (max-width: 980px) { .wg-tools .grow { flex-basis: 100%; order: 9; } }   /* the search gets its own full row instead of a squeezed 208px box */
.wg-tools .wg-legend { display: inline-flex; align-items: center; gap: 12px; padding: 0 6px; font-size: 12px; color: var(--muted); }
.wg-tools .wg-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.wg-legend .k-act { background: var(--well); border: 1px solid var(--hair-2); }
.wg-legend .k-fc { border: 1px dashed var(--hair-2); }

/* ---------------- wg: the wide grid ---------------- */
.wg { --wg-surface: var(--surface); --wg-head: var(--surface-2); --wg-row-h: 52px; --wg-in-h: 34px; --wg-first: 280px; --wg-cell: 116px; --wg-font: 13px;
  position: relative; overflow: hidden; }
.wg.compact { --wg-row-h: 36px; --wg-in-h: 28px; --wg-cell: 100px; --wg-font: 12.5px; }
.wg-scroll { overflow: auto; max-height: calc(100vh - 150px - var(--tn-stuck)); overscroll-behavior: contain; scroll-padding-left: var(--wg-first); }
table.wg-t { border-collapse: separate; border-spacing: 0; font-size: var(--wg-font); font-variant-numeric: tabular-nums; }
.wg-t th, .wg-t td { text-transform: none; letter-spacing: normal; height: var(--wg-row-h); padding: 0 8px; border-bottom: 1px solid var(--hair); white-space: nowrap; text-align: right; background: var(--wg-surface); }
.wg-t thead th { position: sticky; z-index: 2; height: 30px; background: var(--wg-head); font-size: 11.5px; font-weight: 700; color: var(--muted); }
.wg-t thead tr:first-child th { top: 0; }
.wg-t thead tr:nth-child(2) th { top: 30px; }
.wg-t thead .q { text-align: center; color: var(--ink-2); border-bottom: 0; }
.wg-t thead .q small { font-weight: 600; color: var(--faint); margin-left: 4px; }
.wg-t thead .now { color: var(--accent-ink); }
.wg-t .m { min-width: var(--wg-cell); scroll-snap-align: start; }
.wg-t .qs { border-left: 1px solid var(--hair-2); }
/* the job column stays put on the left */
.wg-t .first { position: sticky; left: 0; z-index: 1; min-width: var(--wg-first); max-width: var(--wg-first); text-align: left; padding-left: 16px; white-space: normal; box-shadow: 1px 0 0 var(--hair-2); }
.wg-t thead .first { z-index: 4; }
/* the totals column stays put on the right */
.wg-t .tot { position: sticky; right: 0; z-index: 1; min-width: 124px; font-weight: 800; box-shadow: -1px 0 0 var(--hair-2); padding-right: 16px; }
.wg-t thead .tot { z-index: 4; }
.wg-t .np { min-width: 108px; }
.wg-t tbody tr:hover td, .wg-t tbody tr:hover th { background: var(--wg-head); }
/* the totals row stays put at the foot */
.wg-t tfoot th, .wg-t tfoot td { position: sticky; bottom: 0; z-index: 2; background: var(--wg-head); font-weight: 800; border-top: 1px solid var(--hair-2); border-bottom: 0; }
.wg-t tfoot .first, .wg-t tfoot .tot { z-index: 4; }
.wg-t .grp th, .wg-t .grp td { height: 34px; font-weight: 750; color: var(--ink-2); background: var(--wg-head); }
.wg-name { all: unset; cursor: pointer; display: block; font-weight: 700; color: var(--ink); line-height: 1.25; }
.wg-name:hover, .wg-name:focus-visible { text-decoration: underline; }
.wg-meta { display: block; font-size: 11.5px; color: var(--muted); font-weight: 500; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.compact .wg-meta { display: none; }
.wg-act { color: var(--ink-2); }
.wg-act.zero, .wg-zero { color: var(--faint); }
.wg-mtd { display: block; font-size: 10.5px; font-weight: 600; color: var(--faint); line-height: 1.1; }
.wg-in { width: 100%; min-width: 0; height: var(--wg-in-h); padding: 0 8px; border-radius: 8px; border: 1px dashed var(--hair-2); background: transparent; color: var(--ink);
  font: 650 var(--wg-font) var(--font); text-align: right; font-variant-numeric: tabular-nums; transition: border-color var(--t-quick), background var(--t-quick); }
.wg-in::placeholder { color: var(--faint); font-weight: 500; }
.wg-in.set { border-style: solid; border-color: var(--hair); background: var(--well); }
.wg-in.dirty { border-style: solid; border-color: var(--accent); background: transparent; }
.wg-in:focus { outline: none; border: 1.5px solid var(--ink); background: var(--wg-surface); }
.wg-drill { all: unset; cursor: pointer; border-bottom: 1px dashed var(--hair-2); }
.wg-drill:hover, .wg-drill:focus-visible { border-bottom-color: var(--ink); }
.wg-warn { color: var(--warn); }
.wg-t td.wg-empty { height: auto; padding: 22px 16px; text-align: left; white-space: normal; color: var(--muted); font-weight: var(--fw-med); }   /* the one row an empty grid shows */
.wg-qe { display: flex; flex-direction: column; align-items: stretch; gap: 2px; }   /* a month typed over: the input, and under it the calculated figure */
.wg-qe .was { align-self: flex-end; font-size: 10.5px; }
.wg-meta a { color: inherit; font-weight: inherit; }   /* names in a row's second line are doors to their records */
.wg-meta a:hover, .wg-meta a:focus-visible { color: var(--accent-ink); text-decoration: underline; }
.wg-qe input.wg-in { width: 100%; height: var(--wg-in-h); padding: 0 8px; }   /* the quick-edit look must not narrow a grid cell's box */
.wg-t .grp .src { font-size: inherit; color: inherit; font-weight: inherit; }   /* a group's name, as a door to its record */
.wg-sheet .src { font-size: 11.5px; }

.wg-save { position: fixed; z-index: 40; left: 50%; bottom: max(16px, env(safe-area-inset-bottom, 0px)); transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 16px; border-radius: 16px; }
.wg-save b { font-variant-numeric: tabular-nums; }

.wg-sheet { position: fixed; z-index: 70; top: 10px; right: 10px; bottom: 10px; width: min(430px, calc(100vw - 20px)); display: flex; flex-direction: column; overflow: hidden;
  transform: translateX(calc(100% + 24px)); transition: transform 500ms cubic-bezier(.34, 1.12, .5, 1); }
.wg-sheet.open { transform: none; }
.wg-sheet > header { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 16px 16px 12px 18px; border-bottom: 1px solid var(--hair); }
.wg-sheet > header h2 { margin: 2px 0 0; font-size: 16px; font-weight: 800; }
.wg-sbody { flex: 1 1 auto; overflow: auto; padding: 8px 18px 18px; display: grid; gap: 14px; align-content: start; }
.wg-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.wg-kv > div { display: grid; gap: 3px; min-width: 0; align-content: start; }   /* a neighbour's source link must not push this row's figures down (review 10/22) */
.wg-kv span { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.wg-kv b { font-variant-numeric: tabular-nums; }
table.wg-list { width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; }
.wg-list th, .wg-list td { text-transform: none; letter-spacing: normal; padding: 7px 0; border-top: 1px solid var(--hair); text-align: left; }
.wg-list .r { text-align: right; }
.wg-list tfoot td, .wg-list tfoot th { font-weight: 800; border-top: 1.5px solid var(--hair-2); }
.wg-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }   /* a sheet's own fields and buttons, one wrapping row (w10retire: was 2.x's .row) */
.wg-scrim { display: none; position: fixed; inset: 0; z-index: 65; border: 0; padding: 0; background: rgba(11, 18, 32, .25); cursor: pointer; }
.wg-scrim.open { display: block; }
.wg-note { padding: 9px 11px; border-radius: 11px; background: var(--warn-bg); color: var(--warn); font-size: 12.5px; font-weight: 650; }

/* filter chips and the snapshot picker */
.wg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.wg-chip { height: 32px; padding: 0 12px; border-radius: 99px; border: 1px solid var(--hair-2); background: transparent; color: var(--ink-2); font: 650 12.5px var(--font); cursor: pointer; }
.wg-chip .n { margin-left: 4px; font-weight: 800; color: var(--faint); font-variant-numeric: tabular-nums; }   /* a colour, not opacity: .7 read 4.1:1 (review 10/22) */
.wg-chip[aria-pressed="true"] .n { color: inherit; }
.wg-chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.wg-since .select { height: 34px; font-size: 12.5px; }
/* sortable headers: one tap sorts, a second tap flips */
.wg-sort { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
.wg-sort:hover, .wg-sort:focus-visible { color: var(--ink); }
.wg-sort::after { content: ""; width: 0; height: 0; border: 4px solid transparent; opacity: 0; }
th[aria-sort="descending"] .wg-sort::after { border-top-color: currentColor; border-bottom-width: 0; opacity: 1; }
th[aria-sort="ascending"] .wg-sort::after { border-bottom-color: currentColor; border-top-width: 0; opacity: 1; }
th[aria-sort] { color: var(--ink); }
.wg-t .rem { min-width: 116px; }
/* soft backlog sits under each branch's jobs */
.wg-t .sub th, .wg-t .sub td { height: 30px; font-size: 11.5px; font-weight: 700; color: var(--muted); background: var(--wg-surface); letter-spacing: .02em; }
.wg-t .sub .first { padding-left: 28px; }
.wg-t tr.soft .first { padding-left: 28px; }
.wg-kind { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 5px; font-size: 10.5px; font-weight: 700; background: var(--info-bg); color: var(--info); vertical-align: 1px; }
/* changed since the compared week */
.wg-cell { position: relative; display: block; }
.wg-chg { all: unset; cursor: pointer; position: absolute; top: -2px; right: -2px; z-index: 1; width: 14px; height: 14px; border-radius: 50%; display: grid; place-items: center;
  font-size: 9px; font-weight: 900; line-height: 1; color: var(--on-accent); }
.wg-chg.up { background: var(--ok); }
.wg-chg.down { background: var(--bad); }
.wg-chg:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.wg-tip { position: fixed; z-index: 80; left: var(--x); top: var(--y); transform: translate(-50%, calc(-100% - 8px)); padding: 6px 10px; border-radius: 9px;
  background: var(--ink); color: var(--on-ink); font-size: 12px; font-weight: 650; white-space: nowrap; pointer-events: none; }
/* spread on the row */
.wg-np { display: inline-flex; align-items: center; gap: 6px; }
.wg-spread { height: 26px; padding: 0 9px; border-radius: 8px; border: 1px solid var(--accent); background: transparent; color: var(--accent-ink); font: 700 11.5px var(--font); cursor: pointer; }
.wg-spread:hover { background: var(--accent); color: var(--on-accent); }
.wg-toast { position: fixed; z-index: 45; left: 50%; bottom: max(76px, calc(env(safe-area-inset-bottom, 0px) + 76px)); transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px; padding: 8px 8px 8px 16px; border-radius: 14px; font-size: 13px; font-weight: 650; }
.wg-fy .pipe { margin-top: 2px; }
.wg-fy .pipe > i { width: var(--fill); }

/* Phone: only the job column stays pinned, so two whole months fit beside it at 375 px; "Next 12 months"
   becomes the last ordinary column, reached by scrolling. Months snap one at a time. */
@media (max-width: 640px) {
  .wg { --wg-first: 134px; --wg-cell: 96px; --wg-font: 12.5px; }
  .wg-scroll { scroll-snap-type: x mandatory; max-height: calc(100vh - 120px - var(--tn-stuck)); }
  .wg-t th, .wg-t td { padding: 0 6px; }
  .wg-t .first { padding-left: 12px; }
  .wg-meta { display: none; }
  .wg-t .tot { right: auto; min-width: 104px; padding-right: 12px; box-shadow: none; border-left: 1px solid var(--hair-2); scroll-snap-align: end; }
  .wg-t tbody .tot { position: static; }   /* header and footer cells keep sticking to the top and bottom, not to the right */
  .wg-t thead .tot, .wg-t tfoot .tot { z-index: 2; }
  .wg-t .grp .first, .wg-t tfoot .first { line-height: 1.25; padding-top: 6px; padding-bottom: 6px; }
  .wg-t .np, .wg-t .rem { display: none; }
  .wg-since { flex: 1 1 100%; }
  .wg-tools .wg-legend { display: none; }
}

/* ---------------- where it comes from, quick edit, why it asks ----------------
   Jordan, 2026-10-21 (AIMS Vault › Rules › Show Where It Comes From; Every Approval Says Why).
   .src      a value's source: "Settings › Pricing › Mobilization". It opens the place scrolled to the field
             (data-focus), and .flash marks the field when it lands. .src.missing: nothing set, here is where to set it.
   .qe       a value that can be quick-edited: the number, a pencil, and once changed here the source value beside it.
   .flags    the reasons an approval is asking, worst first; each may carry its own .src. Only a flag's own <li> is a
             box ("> li"): a list nested inside one (the budget's changed lines, the forecast's moves) stays plain rows. */
.src { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: var(--fw-semi); color: var(--muted);
  text-decoration: none; border-radius: 6px; padding: 1px 4px; margin: 0 -4px; }
.src .i { width: 12px; height: 12px; flex: none; }
.src:hover, .src:focus-visible { color: var(--accent-ink); background: var(--well); text-decoration: none; }
.src.missing { color: var(--warn); }
.src[aria-disabled="true"] { cursor: default; }
.src[aria-disabled="true"]:hover { color: var(--muted); background: transparent; }
@keyframes flash { 0%, 30% { box-shadow: 0 0 0 3px var(--accent), 0 0 0 7px var(--well); } 100% { box-shadow: 0 0 0 0 transparent; } }
.flash { animation: flash 1.8s ease-out; border-radius: var(--r-m); }
@media (prefers-reduced-motion: reduce) { .flash { animation: none; outline: 3px solid var(--accent); outline-offset: 2px; } }
.qe { display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.qe-btn { all: unset; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 7px; color: var(--muted); cursor: pointer; align-self: center; }
.qe-btn:hover, .qe-btn:focus-visible { background: var(--well); color: var(--ink); }
.qe-btn .i { width: 14px; height: 14px; }
.qe.changed > .v { color: var(--warn); }
.qe .v.num, .qe .was.num { white-space: nowrap; }   /* "$140.00/night" broke as "$140.00/ni ght" on a phone (w29b) */
.qe .was { font-size: 11.5px; color: var(--muted); text-decoration: line-through; }
.qe input { width: 9ch; height: 30px; padding: 0 8px; border-radius: var(--r-s); border: 1px solid var(--hair-2); background: var(--glass-a); font: inherit; font-variant-numeric: tabular-nums; }
.hint.warn { color: var(--warn); }
.tabs.ecs-tabs { margin-bottom: 14px; }   /* Settings › Estimating Costs: its parts */
.mobset-v { white-space: nowrap; }   /* Settings › Mobilization: a compact box, its unit beside it, edges in line */
.mobset-v input { width: 12ch; display: inline-block; text-align: right; }
.qe-edit { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }   /* a quick edit while open: the box, then where it applies */
.qe-edit > .btn.sm { height: var(--ctl); }   /* level with the 36px box it saves (r2layout: 32 beside 36) */
.qe-edit input { width: 11ch; height: var(--ctl); padding: 0 10px; border-radius: var(--r-s); border: 1px solid var(--hair-2); background: var(--glass-a); font: inherit; font-variant-numeric: tabular-nums; }
.flags { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.flags > li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 2px 8px; align-items: start; padding: 8px 10px; border-radius: var(--r-m);
  background: var(--warn-bg); border: 1px solid var(--warn-line); font-size: 13px; }
.flags li .i { width: 15px; height: 15px; margin-top: 2px; color: var(--warn); }
.flags > li.bad { background: var(--bad-bg); border-color: var(--bad-line); }
.flags li.bad .i { color: var(--bad); }
.flags > li.info { background: var(--info-bg); border-color: var(--info-line); }
.flags li.info .i { color: var(--info); }
.flags li b { font-weight: var(--fw-bold); }
.flags li .src { grid-column: 2; justify-self: start; }

/* ---------------- breakpoints ---------------- */
@media (max-width: 1180px) {   /* phones + touch iPads: the sidebar is a drawer */
  .main { padding-bottom: calc(90px + env(safe-area-inset-bottom, 0px)); }   /* room to scroll the last thing on a page clear of the floating menu drop (54px + its 20px + 16px; the phone's home bar too, w30k) */
  .sidebar, .app.folded .sidebar { position: fixed; left: 10px; top: 10px; bottom: 10px; width: 268px; max-height: none; z-index: 60;
    transform: translateX(calc(-100% - 24px)); transition: transform 500ms cubic-bezier(.34,1.12,.5,1); }
  .app.folded .logo, .app.folded .pname { display: block; }   /* no folding on touch */
  .app.folded .letters { display: none; }
  .app.drawer .sidebar { transform: none; }
  .app.drawer .scrim { display: block; }
  .app.dragging .sidebar { transform: translateX(var(--drawer-x, 0px)); transition: none; }
  .app.dragging .scrim { display: block; opacity: var(--scrim-o, 1); }
  .island.filters { order: 9; flex: 1 1 100%; }                 /* phones and touch iPads: the branch and Mine row drops under the bar */
  .island.filters .select-wrap { flex: 1 1 auto; min-width: 0; }
  .island.filters .seg { flex: none; }
  .drawer-edge { display: block; }
  .fold { display: none; }
  .menu-btn { display: inline-flex; }
  .drop-btn { display: flex; }
  .strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* design review 10/21: a fixed sidebar still took align-self from .sidebar, so the drawer was as tall as its menu and
     its last rows hung off a phone. Stretch it between top and bottom; it scrolls inside. */
  .sidebar, .app.folded .sidebar { align-self: stretch; }
  .island.filters .select.bare { min-width: 0; }
}
/* the thumb's sizes: at 1180 and under, and on any touch screen at any width (w21platform, 10/27). A 13-inch iPad Pro on
   its side is 1366 wide and keeps the sidebar beside the page (the frame above, frame.js), but a finger still presses
   its buttons. A mouse above 1180 matches neither half of the query, so a computer is untouched. */
@media (max-width: 1180px), (pointer: coarse) {
  .btn, .tb { min-height: var(--tap); }
  :root { --bar-h: calc(var(--tap) + 10px); }
  .tb { min-width: var(--tap); justify-content: center; }
  .tb.icon { width: var(--tap); }
  .island .seg { padding: 0 3px; }
  .seg button { height: var(--tap); }   /* every segmented control, not only the top bar's (review 10/22) */
  .seg { padding-block: 0; }   /* ...and the switch is 44 outside too, level with the boxes and buttons beside it (K2: 50px) */
  .subtabs { gap: 18px; }
  .subtabs a, .subtabs button { min-height: var(--tap); min-width: var(--tap); display: inline-flex; align-items: center; justify-content: center; padding-block: 0; }
  .btn.icon, .btn.sm.icon { width: var(--tap); }
  .split .btn:last-child { width: var(--tap); }   /* the split button's caret: 34 is a mouse's width (review 10/22) */
  .drill, .qe-btn { position: relative; }
  .drill::after { content: ""; position: absolute; inset: -9px; }       /* a 44px reach around the 28px circle: the inset counts from inside its 1px border (-8 measured 42; w15polish K3) */
  .qe-btn::after { content: ""; position: absolute; inset: -10px; }
  .pop button, .pop a { height: var(--tap); }
  .nav a { height: var(--tap); }
  .fold { position: relative; }
  .fold::after { content: ""; position: absolute; inset: -9px; }   /* the sidebar's 30px fold square: shown only beside the page (a touch screen over 1180); 44 from inside its border */
}
@media (max-width: 800px) {   /* mid-width: the avatar keeps to the bar's first row */
  .topbar .phone-hide { display: none !important; }
  .me { width: var(--bar-h); padding: 0; justify-content: center; }
}
@media (max-width: 400px) { .island.search { flex-basis: 0; } .tb.search .q > span { display: none; } }   /* the magnifier alone */
@media (max-width: 360px) { :is(.topbar, .tn-bar) > .anchor { order: 10; } .island.filters { flex: 1 1 0; } .island.filters .seg { flex: none; } .island.filters .seg button { padding: 0 8px; font-size: 12px; } }
/* Spanish at 360 and under (w26fix): "Todas las sucursales" is 157px and the select beside Todos | Míos and the avatar had 75–115. The island holds
   two rows then — the branch picker on its own line, the switch under it — and only in Spanish, which is the only language it was cut in. */
@media (max-width: 420px) { :root:lang(es) .island.filters { flex-wrap: wrap; } :root:lang(es) .island.filters .select-wrap { flex: 1 1 100%; } :root:lang(es) .island.filters .seg { flex: 1 1 100%; } :root:lang(es) .island.filters .seg button { flex: 1 1 auto; } }   /* 361–420 too (w30k): "Todas las sucursales" was cut to "…sucursa" beside "Mi trabajo" */
/* …and at 340 and under in English too: "All Branches" is 94px and the select had 57 (design review) */
@media (max-width: 340px) { .island.filters { flex-wrap: wrap; } .island.filters .select-wrap { flex: 1 1 100%; } }   /* Everyone | Mine stays whole beside the avatar (review 10/22) */
@media (max-width: 980px) { .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) {   /* phones: tables become cards, labels drop to icons */
  .app { padding: 10px; gap: 10px; }
  .phone-hide { display: none !important; }
  body.has-aimsly .side-foot { display: block; }   /* the app sets has-aimsly when Aimsly is on for this login */
  .phone-cards table.t { display: none; }
  .phone-cards .cards { display: flex !important; flex-direction: column; gap: 8px; }
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .value { font-size: 19px; }
  .strip .top { min-height: 36px; align-items: flex-start; }   /* a two-line label keeps the values level */
}
.phone-cards { overflow: hidden; }   /* the table keeps to the panel's corners */
.phone-cards .cards { display: none; padding: 10px; }   /* scoped: 2.x's own .cards is its stat-tile grid on ~130 screens, and a bare rule hid them all */

/* ---------------- dark-theme touches ---------------- */
[data-theme="dark"] .nav a:hover:not([aria-current="page"]), [data-theme="dark"] .tb:hover { background: rgba(255,255,255,.06); }
[data-theme="dark"] table.t tbody tr:hover { background: rgba(255,255,255,.04); }
/* these outweighed 2.x styles.css's dark rules while it loaded (deleted in w10retire, 10/23); the values are the kit's own */
[data-theme="dark"] table.t th { background: transparent; }
:root[data-theme="dark"]:is([data-frame], :not([data-frame])) .btn.secondary { background: var(--glass-a); color: var(--ink); border-color: var(--hair-2); }
:root[data-theme="dark"]:is([data-frame], :not([data-frame])) .btn.secondary:hover { background: var(--glass-hi); }
:root[data-theme="dark"]:is([data-frame], :not([data-frame])) .btn.danger { background: var(--bad-bg); color: var(--bad-ink, var(--bad)); border-color: var(--bad-line); }   /* B30: --bad-ink, 7:1 and up */
[data-theme="dark"] .person { background: rgba(255,255,255,.06); }
[data-theme="dark"] .person.lead { background: var(--ink); color: var(--on-ink); }
/* the menu's unread-messages count: white on dark mode's light red was 2.78:1 (the bell's dot already got this) */
:root[data-theme="dark"] #nav a .nav-msgs-n { color: var(--bg); }

/* ---------------- Master Items (mi-): Settings › Estimating › Master Items, and Apex's Master Items row ----------------
   The catalogue as rate cards: one card per subject and product family, sizes down the side, units or options across.
   The cards are built from the data, so every service gets them without anyone drawing them. */
.mi-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; }
.mi-root { display: grid; gap: var(--gap); }
.mi-head h1.title, .mi-head h2.title { margin: 0; }
.mi-lede { margin: 4px 0 0; max-width: 74ch; color: var(--muted); font-size: 13.5px; }

.mi-body { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: var(--gap); align-items: start; }
.mi-side { position: sticky; top: calc(var(--tn-stuck) + 14px); display: grid; gap: 2px; padding: 8px; max-height: calc(100vh - 28px - var(--tn-stuck)); overflow-y: auto; }   /* --tn-stuck: clear of the pinned top bar */
.mi-side h2 { margin: 8px 10px 4px; font: 700 10.5px var(--font); letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }
.mi-svc { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 8px; align-items: center; width: 100%; padding: 8px 10px; border: 0; border-radius: 11px;
  background: transparent; color: var(--ink-2); font: 600 13px var(--font); text-align: left; cursor: pointer; transition: background var(--t-quick); }
.mi-svc:hover { background: var(--hair); }
.mi-svc[aria-current="true"] { background: var(--ink); color: var(--on-ink); }
.mi-svc .n { font-size: 11.5px; font-weight: 700; color: var(--faint); font-variant-numeric: tabular-nums; }   /* solid: opacity .7 was 4.25:1 (review 4, 10/22) */
.mi-svc[aria-current="true"] .n { color: inherit; }
.mi-svc .pipe { grid-column: 1 / -1; height: 4px; box-shadow: none; }
@media (pointer: coarse) { .mi-svc { min-height: var(--tap); } }   /* a finger at any width (w21platform): a service in the list was 42 */
.mi-svc .pipe > i { width: var(--fill); animation: none; }
.mi-svc[aria-current="true"] .pipe { background: rgba(255, 255, 255, .18); }
.mi-pick { display: none; }
.mi-strip .pipe > i { width: var(--fill); }

.mi-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap); min-width: 0; }   /* one column that may shrink, or the tools never wrap */
.mi-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 8px; }
.mi-tools .grow { flex: 1 1 200px; min-width: 0; }
.mi-tools .grow .input, .mi-tools .grow .select { width: 100%; height: 34px; }
.mi-svc-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 14px; padding: 0 4px; }
.mi-svc-head h2 { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -.01em; }
.mi-svc-head b { color: var(--ink-2); }

.mi-out { display: grid; gap: var(--gap); }   /* the rate cards stacked touching, 0px (w11design K4) */
.mi-card { overflow: hidden; }
.mi-card > header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; padding: 14px 18px 10px; cursor: pointer; }
.mi-card > header .t { display: flex; align-items: center; gap: 8px; min-width: 0; }
.mi-card > header h3 { margin: 0; font-size: 14.5px; font-weight: 750; }
.mi-card > header .hint { font-size: 12px; }
.mi-card > header .mi-sum { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }   /* the count and its pipe (w10retire: was 2.x's .row) */
.mi-card .chev { width: 14px; height: 14px; color: var(--muted); transition: transform var(--t-std); }
.mi-card.closed .chev { transform: rotate(-90deg); }
.mi-card.closed .mi-card-body { display: none; }
.mi-card .pipe { width: 120px; height: 6px; }
.mi-card .pipe > i { width: var(--fill); }
.mi-opts { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 18px 10px; }
.mi-opt { height: 28px; padding: 0 11px; border-radius: 99px; border: 1px solid var(--hair-2); background: transparent; color: var(--ink-2); font: 650 12px var(--font); cursor: pointer; }
.mi-opt[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.mi-scroll { overflow-x: auto; padding-bottom: 6px; }
table.mi-rc { border-collapse: separate; border-spacing: 0; font-size: 13px; }   /* sized to its numbers, not stretched */
.mi-rc th, .mi-rc td { padding: 5px 8px; border-top: 1px solid var(--hair); white-space: nowrap; }
.mi-rc thead th { border-top: 0; padding: 6px 8px 8px; font-size: 11.5px; font-weight: 700; color: var(--muted); text-align: right; vertical-align: bottom; white-space: normal; min-width: 96px; }
.mi-rc thead th small { display: block; font-weight: 600; color: var(--faint); }
.mi-rc th.sz { position: sticky; left: 0; z-index: 1; padding-left: 18px; text-align: left; min-width: 0; }
.mi-scroll.scrolled .mi-rc th.sz { background: var(--glass-a); box-shadow: 1px 0 0 var(--hair); }
.mi-rc tbody th.sz { font-weight: 700; color: var(--ink); }
.mi-rc .sz button { all: unset; cursor: pointer; border-bottom: 1px dashed var(--hair-2); }
.mi-rc .sz button:hover, .mi-rc .sz button:focus-visible { border-bottom-color: var(--ink); }
.mi-rc td { text-align: right; }
.mi-rc th:last-child, .mi-rc td:last-child { padding-right: 18px; }
.mi-na { display: inline-block; width: 96px; color: var(--faint); text-align: center; }
.mi-in { width: 96px; height: 32px; padding: 0 8px; border-radius: 9px; border: 1px dashed var(--hair-2); background: transparent; color: var(--ink);
  font: 650 13px var(--font); text-align: right; font-variant-numeric: tabular-nums; transition: border-color var(--t-quick), background var(--t-quick); }
.mi-in::placeholder { color: var(--faint); font-weight: 500; }
.mi-in.set { border-style: solid; border-color: var(--hair); background: var(--well); }
.mi-in.dirty { border-style: solid; border-color: var(--accent); background: transparent; }
.mi-in:focus { outline: none; border: 1.5px solid var(--ink); background: var(--glass-a); }
.mi-jump { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 12px 14px; }
.mi-jump .hint { margin-right: 4px; }
.mi-jump .n { margin-left: 4px; opacity: .6; font-variant-numeric: tabular-nums; }
.mi-more { width: 100%; padding: 10px 18px 14px; border: 0; background: transparent; color: var(--accent-ink); font: 700 13px var(--font); text-align: left; cursor: pointer; }
.mi-empty { padding: 28px 18px; color: var(--muted); text-align: center; }

table.mi-list { width: 100%; border-collapse: collapse; font-size: 13px; }
.mi-list th, .mi-list td { padding: 7px 10px; border-top: 1px solid var(--hair); text-align: left; vertical-align: middle; }
.mi-list thead th { border-top: 0; font-size: 11.5px; font-weight: 700; color: var(--muted); }
.mi-list th:first-child, .mi-list td:first-child { padding-left: 18px; }
.mi-list th:last-child, .mi-list td:last-child { padding-right: 18px; }
.mi-list .r { text-align: right; }
.mi-list .code button { all: unset; cursor: pointer; font: 650 12px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--accent-ink); }
.mi-list .code button:hover { text-decoration: underline; }
.mi-list tr.grp th { padding-top: 16px; font-size: 12px; color: var(--ink); }
.mi-list td.desc { min-width: 220px; }
.mi-list td.code { white-space: nowrap; }
.mi-item .code { white-space: nowrap; }
.mi-item td:has(> .mi-pct) { white-space: nowrap; }
.mi-strip .hint a { color: var(--ink-2); text-decoration: underline; }   /* a link inside a hint reads as a link, not as an alert in the product's red */

.mi-save { position: fixed; z-index: 40; left: 50%; bottom: max(16px, env(safe-area-inset-bottom, 0px)); transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 16px; border-radius: 16px; }
.mi-save b { font-variant-numeric: tabular-nums; }

.mi-drawer { position: fixed; z-index: 70; top: 10px; right: 10px; bottom: 10px; width: min(430px, calc(100vw - 20px)); display: flex; flex-direction: column; overflow: hidden;
  transform: translateX(calc(100% + 24px)); transition: transform 500ms cubic-bezier(.34, 1.12, .5, 1); }
.mi-drawer.open { transform: none; }
.mi-drawer > header { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 16px 16px 12px 18px; border-bottom: 1px solid var(--hair); }
.mi-drawer > header h2 { margin: 2px 0 0; font-size: 16px; font-weight: 800; }
.mi-dbody { flex: 1 1 auto; overflow: auto; padding: 4px 18px 18px; }
.mi-item { display: grid; gap: 10px; padding: 14px 0; border-top: 1px solid var(--hair); }
.mi-item:first-child { border-top: 0; }
.mi-item .code { font: 700 12px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--accent-ink); }
.mi-item .desc { font-weight: 700; }
.mi-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.mi-kv > div { display: grid; gap: 3px; min-width: 0; align-content: start; }   /* a source link under one value never pushes its neighbour down */
.mi-kv span { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.mi-kv b { font-variant-numeric: tabular-nums; }
.mi-kv .mi-in { width: 100%; }
.mi-note { padding: 9px 11px; border-radius: 11px; background: var(--warn-bg); color: var(--warn); font-size: 12.5px; font-weight: 650; }
.mi-bp { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.mi-bp td { padding: 5px 0; border-top: 1px solid var(--hair); }
.mi-bp td:last-child { text-align: right; color: var(--muted); }
.mi-scrim { display: none; position: fixed; inset: 0; z-index: 65; border: 0; padding: 0; background: rgba(11, 18, 32, .25); cursor: pointer; }
.mi-scrim.open { display: block; }

/* the kit's bare table, th, td and tr:hover rules (and 2.x's styles.css until w10retire) reach these tables wherever this
   section says nothing; say it. */
table.mi-rc, table.mi-list, table.mi-bp { background: transparent; }
table.mi-rc { width: auto; }
.mi-rc th, .mi-rc td, .mi-list th, .mi-list td, .mi-bp th, .mi-bp td { background: transparent; text-transform: none; letter-spacing: normal; border-bottom: 0; }
.mi-rc tr:hover td, .mi-list tr:hover td, .mi-bp tr:hover td { background: transparent; }
/* its dark theme writes :root[data-theme="dark"] th / tr:hover td; these match that weight and, loading later, win */
.mi-root :is(.mi-rc, .mi-list, .mi-bp) :is(th, td) { background: transparent; }
.mi-root :is(.mi-rc, .mi-list, .mi-bp) tr:hover td { background: transparent; }

/* the item drawer sits over the app's floating Aimsly button (z 400) and under its pop-up windows and toasts (1200+) */
.mi-root .mi-drawer { z-index: 420; }
.mi-root .mi-scrim { z-index: 410; }

/* the live screen (public/master-items.js) adds: numbers a non-manager reads, a refused entry, the cross-service search
   pager, branch defaults, and the drawer's "where it was quoted" and bill of materials */
.mi-ro { display: inline-block; min-width: 96px; text-align: right; font: 650 13px var(--font); font-variant-numeric: tabular-nums; color: var(--ink); }
.mi-ro.follows { color: var(--muted); font-weight: 500; }
.mi-in.bad { border-style: solid; border-color: var(--bad); background: var(--bad-bg); }
.mi-in.mi-pct { width: 72px; }
.mi-list .mi-note-in { height: 32px; min-width: 220px; }
.mi-svc-head .btn { margin-left: auto; }
.mi-pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 18px 14px; }
.mi-dbody h3 { margin: 6px 0 2px; font-size: 13.5px; font-weight: 750; }
.mi-usage, .mi-bom { display: grid; gap: 8px; }
.mi-bom p { margin: 0; }
.mi-bp tr.off td:first-child { color: var(--faint); text-decoration: line-through; }
.mi-bp td .btn.sm.icon, .mi-bp td .btn.sm { height: 28px; }
.mi-bom-add { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.mi-bom-add .grow { flex: 1 1 180px; min-width: 0; }
.mi-bom-add .mi-qty { width: 76px; height: 34px; }
.mi-retire { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-top: 8px; border-top: 1px solid var(--hair); }

@media (max-width: 980px) {
  .mi-body { grid-template-columns: minmax(0, 1fr); }
  .mi-side { display: none; }
  .mi-pick { display: flex; }
}
@media (max-width: 640px) {
  .mi-in, .mi-na { width: 84px; }
  .mi-rc thead th { min-width: 84px; }
  .mi-card .pipe { display: none; }
}

/* ---------------- schedule (sc-) — Ignite › Schedule, the whiteboard ----------------
   Jobs are magnets on a week board: pick one up, it lifts under the finger, the day under it lights, and it settles
   where it lands. Every change reaches the crew on its own 30 minutes later, unless somebody presses Push sooner.
   On a phone there is no dragging: one day at a time, and a card moves through "Move to…". Moved here from
   schedule.html on 2026-10-21 so the app's schedule (rebuild-3.0) is built from the same parts. */
.sc-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; }
.sc-head h1.title { margin: 0; }
.sc-head .sub { margin-top: 3px; font-size: 13px; color: var(--muted); }
@media (max-width: 479px) { #schedUpdated { display: none; } }   /* " · updated 12:10" gives way on a narrow phone (w10retire: was styles.css's) */
.sc-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.sc-tools .spacer { flex: 1 1 auto; }
.sc-nav { display: inline-flex; gap: 4px; }
.sc-nav .btn { width: 36px; padding: 0; justify-content: center; }
.sc-count { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 99px; background: var(--on-ink); color: var(--ink); font-size: 11.5px; font-weight: 800; display: inline-grid; place-items: center; }
.btn:disabled .sc-count { opacity: .6; }
.sc-clock { display: inline-flex; align-items: center; gap: 8px; padding: 4px 4px 4px 12px; border-radius: 12px; font-size: 12.5px; color: var(--muted); }
.sc-clock b { color: var(--ink); font-variant-numeric: tabular-nums; }
.sc-auto { display: grid; gap: 10px; padding: 12px 14px; border-radius: 14px; background: var(--warn-bg); color: var(--ink-2); font-size: 13px; }
.sc-auto b { color: var(--warn); }
.sc-auto .acts { justify-content: flex-start; }
.sc-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 650; color: var(--ink-2); cursor: pointer; }

.sc-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 10px 14px; font-size: 13px; }
.sc-bar b { font-weight: 750; }
.sc-bar .lbl { font: 700 10.5px var(--font); letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }

.sc-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; font-size: 12px; color: var(--muted); padding: 0 4px; }
.sc-legend span { display: inline-flex; align-items: center; gap: 6px; }
.sc-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--faint); }
.sc-dot.sent { background: var(--ok); }
.sc-dot.changed { background: var(--warn); }
.sc-dot.new { background: transparent; box-shadow: inset 0 0 0 2px var(--faint); }

/* the week board */
.sc-board-wrap { padding: 10px; overflow-x: auto; }
.sc-board { display: grid; grid-template-columns: repeat(var(--sc-cols, 7), minmax(148px, 1fr)); gap: 8px; min-width: calc(var(--sc-cols, 7) * 156px - 8px); }
.sc-day { display: flex; flex-direction: column; gap: 6px; min-height: 360px; padding: 6px; border-radius: 14px; background: var(--well);
  transition: background var(--t-quick), box-shadow var(--t-quick); }
.sc-day.weekend { background: transparent; box-shadow: inset 0 0 0 1px var(--hair); }
.sc-day.over { background: var(--glass-a); box-shadow: inset 0 0 0 2px var(--accent); }
.sc-day.focus { box-shadow: inset 0 0 0 2px var(--ink); }
.sc-dayhead { all: unset; display: grid; gap: 1px; padding: 6px 6px 8px; border-radius: 10px; cursor: pointer; }
.sc-dayhead:hover { background: var(--hair); }
.sc-dayhead:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.sc-dayhead b { font-size: 13.5px; font-weight: 800; }
.sc-dayhead span { font-size: 11.5px; color: var(--muted); font-weight: 600; min-height: 3em; }   /* two lines held, so every day's first magnet starts level */
.sc-card { position: relative; display: grid; gap: 3px; padding: 9px 10px; border-radius: 12px; background: var(--glass-a); border: 1px solid var(--glass-edge);
  box-shadow: 0 6px 14px -10px rgba(16, 24, 40, .45); cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none;
  transition: opacity var(--t-quick), transform var(--t-spring); }
.sc-card:active { cursor: grabbing; }
.sc-card.lifted { opacity: .25; }
.sc-card.settle { animation: sc-settle 420ms cubic-bezier(.34, 1.45, .5, 1); }
@keyframes sc-settle { 0% { transform: scale(1.04); } 100% { transform: none; } }
.sc-card .t { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: 11.5px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
.sc-card .p { font-size: 13px; font-weight: 750; line-height: 1.25; color: var(--ink); overflow-wrap: anywhere; }
.sc-card .l { font-size: 12px; color: var(--ink-2); }
.sc-card .s { font-size: 11.5px; color: var(--muted); }
.sc-card .tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.sc-card .tags .chip { height: 19px; font-size: 10.5px; padding: 0 6px; }
.sc-card .more { position: absolute; top: 4px; right: 22px; width: 24px; height: 22px; border: 0; border-radius: 7px; background: transparent; color: var(--muted); cursor: pointer; display: grid; place-items: center; }
.sc-card .more:hover { background: var(--hair); color: var(--ink); }
.sc-times-only .sc-card .l, .sc-times-only .sc-card .s, .sc-times-only .sc-card .tags { display: none; }
.sc-pair { gap: 6px; }
/* the live two-jobs pair on the week and day boards (app.js tjGroups; was styles.css .tj-pair, #13 Jordan 2026-10-20): one bar down
   the left joins job 1, the drive between them and job 2 */
.sc-tj { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; position: relative; border-left: 3px solid var(--accent); border-radius: 10px; padding-left: 5px; }
.sc-pair .leg { display: grid; gap: 2px; }
.sc-pair .drive { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--muted); }
.sc-pair .drive::before, .sc-pair .drive::after { content: ""; flex: 1; height: 1px; background: var(--hair-2); }
.sc-off { display: flex; flex-wrap: wrap; gap: 4px; margin-top: auto; padding-top: 6px; }
.sc-off .chip { height: 20px; font-size: 11px; }
.sc-empty { padding: 10px 6px; font-size: 12px; color: var(--faint); text-align: center; }

/* the picked-up card: placed by custom properties only */
.sc-proxy { position: fixed; left: 0; top: 0; z-index: 1500; width: var(--w); height: var(--h); margin: 0; pointer-events: none; cursor: grabbing;
  transform: translate(var(--x), var(--y)) rotate(var(--rot, -2deg)) scale(1.04); transform-origin: var(--ox) var(--oy);
  box-shadow: 0 22px 40px -16px rgba(16, 24, 40, .55); }
.sc-proxy.person { --rot: 0deg; }

/* the focused day */
.sc-focus { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: var(--gap); align-items: start; }
.sc-focus > section { padding: 14px 16px; }
.sc-focus h2 { margin: 0; font-size: 15px; font-weight: 750; }
.sc-ptop { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; margin-bottom: 10px; }
.sc-entries { display: grid; gap: 10px; }
.sc-entry { display: grid; gap: 8px; padding: 12px 14px; border-radius: 14px; background: var(--well); transition: box-shadow var(--t-quick), background var(--t-quick); }
.sc-entry.over { background: var(--glass-a); box-shadow: inset 0 0 0 2px var(--accent); }
.sc-entry .top { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 10px; }
.sc-entry .top b { font-size: 14px; }
.sc-entry .acts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }   /* Edit the entry, and the planned-lines nudge (w10retire: was 2.x's .row) */
@media (min-width: 641px) {   /* title · job number · lead, in fixed shares, so the job numbers line up down the day */
  .sc-entry .top { display: grid; grid-template-columns: minmax(0, 3fr) 104px minmax(0, 2fr); align-items: baseline; }
  .sc-entry .top > b { grid-column: 1; }
  .sc-entry .top > .sc-no { grid-column: 2; }
  .sc-entry .top > .sub { grid-column: 3; text-align: right; }
}
.sc-entry .chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sc-day-drop { min-height: 64px; display: grid; place-items: center; padding: 12px; border-radius: 14px; border: 1.5px dashed var(--hair-2); color: var(--muted); font-size: 12.5px; text-align: center;
  transition: border-color var(--t-quick), background var(--t-quick); }
.sc-day-drop.over { border-color: var(--accent); background: var(--glass-a); }
.sc-rails { display: grid; gap: var(--gap); }
.sc-rail { padding: 12px 12px 14px; display: grid; gap: 8px; }
.sc-rail h3 { margin: 0; font-size: 13px; font-weight: 750; display: flex; justify-content: space-between; }
.sc-rail .list { display: flex; flex-wrap: wrap; gap: 6px; max-height: 320px; overflow-y: auto; }
.sc-person { cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.sc-person button { cursor: pointer; }
.sc-job { display: grid; gap: 1px; width: 100%; padding: 8px 10px; border-radius: 11px; background: var(--well); cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none; font-size: 12.5px; }
.sc-job b { font-size: 12.5px; }
.sc-job span { font-size: 11.5px; color: var(--muted); }

/* Schedule Gap, folded in as a view */
.sc-gap { padding: 0 0 6px; overflow-x: auto; }
.sc-gap table { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 820px; font-size: 13px; }
.sc-gap th, .sc-gap td { padding: 9px 10px; border-top: 1px solid var(--hair); text-align: center; }
.sc-gap thead th { border-top: 0; font-size: 11.5px; color: var(--muted); font-weight: 700; vertical-align: bottom; }
.sc-gap thead th b { display: block; font-size: 13px; color: var(--ink); }
.sc-gap th:first-child { text-align: left; padding-left: 16px; }
.sc-gap td b { font-size: 18px; font-weight: 750; font-variant-numeric: tabular-nums; }
.sc-gap td small { display: block; font-size: 11px; color: var(--muted); }
.sc-gap td.zero b { color: var(--faint); }
.sc-note { padding: 12px 16px; font-size: 12.5px; color: var(--muted); }
.sc-later { padding: 22px 18px; display: grid; gap: 6px; }
.sc-later h2 { margin: 0; font-size: 15px; }
.sc-later p { margin: 0; color: var(--ink-2); font-size: 13.5px; max-width: 70ch; }

/* phone: one day at a time */
.sc-phone { display: none; }
.sc-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; padding: 6px; }
.sc-days button { all: unset; display: grid; justify-items: center; gap: 1px; padding: 6px 0; border-radius: 10px; font-size: 11px; font-weight: 700; color: var(--muted); cursor: pointer; }
.sc-days button b { font-size: 15px; color: var(--ink); }
.sc-days button[aria-pressed="true"] { background: var(--ink); color: var(--on-ink); }
.sc-days button[aria-pressed="true"] b { color: var(--on-ink); }
.sc-days button i { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.sc-days button i.none { background: transparent; }
.sc-daylist { display: grid; gap: 8px; touch-action: pan-y; }
.sc-daylist .sc-card { cursor: pointer; }

/* sheets and the undo toast */
.sc-scrim { display: none; position: fixed; inset: 0; z-index: 80; border: 0; padding: 0; background: rgba(11, 18, 32, .3); cursor: pointer; }
.sc-scrim.open { display: block; }
.sc-sheet { position: fixed; z-index: 85; left: 50%; bottom: 0; width: min(520px, 100%); max-height: 86vh; overflow-y: auto; transform: translate(-50%, 105%);
  transition: transform 460ms cubic-bezier(.34, 1.12, .5, 1); border-radius: 22px 22px 0 0;
  padding: 10px max(18px, env(safe-area-inset-right, 0px)) max(18px, env(safe-area-inset-bottom, 0px)) max(18px, env(safe-area-inset-left, 0px)); display: grid; gap: 12px; }
.sc-sheet.open { transform: translate(-50%, 0); }
.sc-sheet .grab { justify-self: center; width: 38px; height: 5px; border-radius: 99px; background: var(--hair-2); }
.sc-sheet h2 { margin: 0; font-size: 17px; }
.sc-sheet .opts { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.sc-sheet .opts button { all: unset; display: grid; justify-items: center; gap: 2px; padding: 8px 0; border-radius: 11px; border: 1px solid var(--hair-2); font-size: 11px; font-weight: 700; color: var(--muted); cursor: pointer; }
.sc-sheet .opts button b { font-size: 15px; color: var(--ink); }
.sc-sheet .opts button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.sc-sheet .opts button[aria-pressed="true"] b { color: var(--on-ink); }
.sc-sheet .opts button:disabled { opacity: .35; cursor: default; }
.sc-sheet .acts { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.sc-sheet .pick-list { display: grid; gap: 6px; max-height: 280px; overflow-y: auto; }
.sc-sheet .pick-list button { all: unset; display: grid; gap: 1px; padding: 9px 12px; border-radius: 11px; background: var(--well); cursor: pointer; font-size: 13px; }
.sc-sheet .pick-list button span { font-size: 11.5px; color: var(--muted); }
.sc-sheet .push-days { display: grid; gap: 6px; }
.sc-sheet .push-days label { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 12px; border-radius: 11px; background: var(--well); font-size: 13px; cursor: pointer; }
.sc-toast { position: fixed; z-index: 90; left: 50%; bottom: max(18px, env(safe-area-inset-bottom, 0px)); transform: translate(-50%, 140%); display: flex; align-items: center; gap: 12px;
  padding: 8px 8px 8px 16px; border-radius: 16px; font-size: 13px; transition: transform 420ms cubic-bezier(.34, 1.25, .5, 1); max-width: calc(100vw - 32px); }
.sc-toast.show { transform: translate(-50%, 0); }

@media (max-width: 1180px) { .sc-focus { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) {
  .sc-head .actions { width: 100%; }
  .sc-head .actions #pushBtn { flex: 1 1 100%; justify-content: center; }   /* the main action takes its own full row: never a lone half-width button */
  .sc-board-wrap, .sc-legend-board { display: none; }   /* the week board has its own phone list (.sc-phone); the day board (.sc-focus) has none, so it stays and stacks — hiding it left a phone's Day view with no jobs (w9ignite, 10/23) */
  .sc-phone { display: grid; gap: 10px; }
  .sc-tools .sc-switch, .sc-tools .sc-nav { display: none; }
  .sc-clock { width: 100%; justify-content: space-between; }
}
@media (prefers-reduced-motion: reduce) {
  .sc-card, .sc-sheet, .sc-toast, .sc-day { transition: none; }
  .sc-card.settle { animation: none; }
}

/* the app's week board (2026-10-21): a magnet tray above a full-width week. The tray sticks under the top of the screen while
   the board scrolls, so any job (and, once a day's name is tapped, anybody free that day) can be dragged onto any day. */
.sc-week { display: grid; gap: 10px; }
.sc-week-main { display: grid; gap: var(--gap); min-width: 0; }   /* the tray and the week board are two panels: the 16px rhythm (K4 measured 10) */
.sc-dayrow { display: flex; align-items: flex-start; gap: 4px; }
.sc-dayrow .sc-dayhead { flex: 1 1 auto; }
.sc-day.focus .sc-dayhead { background: var(--ink); color: var(--on-ink); }
.sc-day.focus .sc-dayhead span { color: var(--on-ink); opacity: .8; }
.sc-add { all: unset; flex: none; width: 28px; height: 28px; margin-top: 4px; border-radius: 9px; display: grid; place-items: center; color: var(--muted); cursor: pointer; font-weight: 700; }
.sc-add:hover { background: var(--hair); color: var(--ink); }
.sc-add:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (pointer: coarse) { .sc-add { position: relative; } .sc-add::after { content: ""; position: absolute; inset: -8px; } }   /* a finger at any width (w21platform): the day's 28px + reaches 44; the day's name beside it gives up 4px of its edge */
.sc-drop { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; min-height: 120px; border-radius: 10px; transition: background var(--t-quick), box-shadow var(--t-quick); }
.sc-day.over .sc-drop, .sc-drop.over { background: var(--glass-a); }
.sc-day.over.conflict, .sc-card.over.conflict, .sc-entry.over.conflict { box-shadow: inset 0 0 0 2px var(--warn); }
.sc-card:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.sc-card.over { box-shadow: inset 0 0 0 2px var(--accent), 0 6px 14px -10px rgba(16, 24, 40, .45); }
.sc-card.saving { opacity: .72; }
.sc-card.saving::after { content: ""; position: absolute; left: 10px; right: 10px; bottom: 4px; height: 2px; border-radius: 2px; background: var(--accent); animation: sc-saving 900ms ease-in-out infinite alternate; }
@keyframes sc-saving { from { opacity: .25; } to { opacity: 1; } }
.sc-card.ghost { opacity: .55; border-style: dashed; }
/* how well a scheduled day is staffed, at a glance (Jordan 9/18: red dashed when nobody is on it, yellow when a required skill
   is missing, green solid when it is covered). The border carries the first half — dashed means nobody — and the colour the
   second, so the states read apart in greyscale and on a print-out; tinted from the tone tokens, so dark mode follows. app.js
   puts staff-<state> on the week board's magnets and the day board's entries; 2.x's styles.css drew it and left with it
   (W15B-P1, w15polish). The Month grid keeps its own (.scv-ment, project.css). */
.sc-card.staff-none, .sc-entry.staff-none { border: 2px dashed var(--bad-line); background: var(--bad-bg); }
.sc-card.staff-part, .sc-entry.staff-part { border: 2px solid var(--warn-line); background: var(--warn-bg); }
.sc-card.staff-ok, .sc-entry.staff-ok { border: 2px solid var(--ok-line); background: var(--ok-bg); }
.sc-card.staff-cancelled, .sc-entry.staff-cancelled { border: 2px dashed var(--hair-2); opacity: .75; }   /* a cancelled day stays on the board */
.sc-card .sc-no { font-size: 11px; font-weight: 650; color: var(--muted); white-space: nowrap; }
.sc-card a.sc-no:hover { color: var(--accent-ink); text-decoration: underline; }
.sc-card .l a { color: inherit; }
.sc-card .l a:hover { color: var(--accent-ink); }
.sc-card .chip button { all: unset; margin-left: 3px; cursor: pointer; opacity: .6; }
.sc-card .chip button:hover { opacity: 1; }
.sc-card .chip.dbl { color: var(--warn); border-color: var(--warn-line); background: var(--warn-bg); }
.sc-card .warn { font-size: 11.5px; font-weight: 700; color: var(--warn); }
.sc-card .units { font-size: 11.5px; color: var(--muted); }
.sc-card .sends { font-size: 11px; font-weight: 700; color: var(--warn); }
.sc-job.lifted, .sc-person.lifted { opacity: .25; }
/* the tray: rows of magnets that scroll sideways */
.sc-tray { position: sticky; top: calc(var(--tn-stuck) + var(--gap)); z-index: 6; display: grid; gap: 8px; padding: 10px 12px; }
.sc-tray .bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.sc-tray .bar h3 { margin: 0; font-size: 13px; font-weight: 750; display: inline-flex; align-items: center; gap: 6px; }
.sc-tray .find { width: 220px; height: var(--ctl); }   /* level with the tray's switch and buttons (K2: 32 beside 36) */
.sc-tray .note { margin: 0; font-size: 12px; color: var(--muted); }
/* The strip scrolls sideways; its chips sit in an ordinary row inside it (.sc-row). A strip that was itself the flex row
   lost a fixed scrollbar's height out of its chips in Safari and in "always show scroll bars" Macs, so the job names were
   cut through the middle (3.0 launch issue #1, 11/6) — a block scroller always adds the bar under its content. */
.sc-strip { display: block; overflow-x: auto; overflow-y: hidden; padding: 1px 1px 3px; scrollbar-width: thin; }
.sc-strip > .sc-row { display: flex; gap: 6px; width: max-content; min-width: 100%; }
.sc-strip .sc-job { flex: 0 0 210px; }
.sc-strip .sc-person { flex: none; }
.sc-strip .sep { flex: none; width: 1px; margin: 2px 4px; background: var(--hair-2); }
.sc-job.on { opacity: .62; }
.sc-job:focus-visible, .sc-person:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.sc-strip .sc-person { touch-action: pan-x; }
.sc-person.busy { opacity: .62; }
.sc-person .week { display: inline-flex; gap: 2px; }
.sc-person .week i { width: 5px; height: 5px; border-radius: 50%; background: var(--hair-2); }
.sc-person .week i.on { background: var(--accent); }
.sc-person .week i.now { box-shadow: 0 0 0 1.5px var(--ink); }
.sc-person a { color: var(--muted); }
.sc-strip .sc-job { touch-action: pan-x; }
.sc-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; font-size: 12.5px; color: var(--muted); }
/* the top of the schedule: the four figures beside the month */
.sc-top { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--gap); align-items: stretch; }
@media (max-width: 1180px) { .sc-top { grid-template-columns: minmax(0, 1fr); } .sc-top .strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* phone, the app's day strip */
.sc-week .sc-phone { display: none; }
@media (max-width: 640px) {
  .sc-week .sc-board-wrap, .sc-week .sc-legend, .sc-week .sc-tray { display: none; }
  .sc-week .sc-phone { display: grid; gap: 10px; }
  .sc-stretch { display: none; }
}
/* the stretch handle: drag a magnet's right edge across days to put the same crew on each */
.sc-stretch { position: absolute; top: 8px; bottom: 8px; right: -3px; width: 10px; border-radius: 6px; cursor: ew-resize; touch-action: none; }
.sc-stretch::after { content: ""; position: absolute; top: 50%; left: 3px; width: 4px; height: 22px; margin-top: -11px; border-radius: 2px; background: var(--hair-2); opacity: 0; transition: opacity var(--t-quick); }
.sc-card:hover .sc-stretch::after, .sc-card:focus-within .sc-stretch::after { opacity: 1; }
.sc-day.stretch-on .sc-drop { background: var(--glass-a); box-shadow: inset 0 0 0 2px var(--accent); }
/* the hint that rides with the magnet: who is already busy on the day under it */
.sc-hint { position: fixed; left: 0; top: 0; z-index: 1501; max-width: 260px; padding: 6px 10px; border-radius: 10px; background: var(--ink); color: var(--on-ink);
  font-size: 12px; font-weight: 650; pointer-events: none; transform: translate(var(--x), var(--y)); box-shadow: var(--shadow-pop); }
.sc-hint.warn { background: var(--warn); color: #fff; }
.sc-hint[hidden] { display: none; }
html.sc-dragging, html.sc-dragging * { cursor: grabbing !important; user-select: none; -webkit-user-select: none; }
.sc-nav .sc-today { width: auto; padding: 0 12px; }
@media (pointer: coarse) { .sc-nav .btn:not(.sc-today) { width: var(--tap); } }   /* a finger at any width (w21platform): the week's ‹ and › were a mouse's 36 */
.sc-entry .warn { font-size: 12px; font-weight: 700; color: var(--warn); }
.sc-entry .sc-no { font-size: 11.5px; font-weight: 650; color: var(--muted); }
.sc-entry .top .sub a { color: inherit; }
.chip.saving, .person.saving { opacity: .6; }
.sc-person.picked, .sc-job.picked { box-shadow: inset 0 0 0 2px var(--ink); }
.sc-rail .note { margin: 0; font-size: 12px; color: var(--muted); }
.sc-rail details summary { cursor: pointer; font-size: 12.5px; padding: 4px 0; }
.sc-rail .list.jobs { flex-direction: column; flex-wrap: nowrap; }
/* a magnet's double-booking links (app.js schedConflictLinks). Scoped to the magnet: spend.css's .sc-why is another component
   (an approval's reasons), loaded in all four shells, and the two bare rules restyled each other (f4tests NEW-5) */
:is(.sc-card, .sc-entry) > .sc-why { display: grid; gap: 2px; margin-top: 0; }
:is(.sc-card, .sc-entry) > .sc-why .src { color: var(--warn); }
.sc-card .chip a, .person a { color: inherit; }
.sc-card .chip a:hover, .person a:hover { color: var(--accent-ink); text-decoration: underline; }
.sc-card .units a, .sc-entry .sub a { color: inherit; }
button.src { border: 0; background: transparent; cursor: pointer; padding: 2px 4px; font: inherit; font-size: 11.5px; font-weight: var(--fw-semi); }
.sc-card .sends .src { color: var(--warn); }
/* the lifted magnet is solid, so the card underneath never shows through it */
.sc-proxy { background-color: var(--bg); background-image: linear-gradient(150deg, var(--glass-hi), var(--glass-a)); }
/* compact job chips in the tray: two lines, cut with an ellipsis */
.sc-strip .sc-job { padding: 6px 10px; gap: 0; }
.sc-strip .sc-job b, .sc-strip .sc-job span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-tray .tray-fold { margin-left: auto; }   /* not .fold: that is the sidebar's 30px square, hidden on touch */
.sc-tray.folded .sc-strip, .sc-tray.folded .people { display: none; }
/* a person on two crews (or on time off) that day */
.person.dbl { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn); }

/* ---------------- Ignite home (ih-) — the Dashboard and the projects list (3.0) ----------------
   public/ignite-home.js. Closed and Archived are views of the one list (Jordan's 3.0 decisions); the kit's strip,
   table.t → phone cards, status pills, pipes and source links do the work, these only place them. */
.ih { display: flex; flex-direction: column; gap: var(--gap); }
.ih > div:empty { display: none; }   /* a slot with nothing in it (Projects' #closeoutBox) leaves no second gap: 32 where 16 is the rule (r2layout K4) */
.ih h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.ih-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; }
.ih .flags { margin-top: 12px; }
.ih-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.ih-prog { display: grid; grid-template-columns: minmax(60px, 1fr) auto; align-items: center; gap: 8px; }
.ih-prog > b { font-size: 12.5px; font-variant-numeric: tabular-nums; }
.ih-prog > .hint { grid-column: 1 / -1; font-size: 11.5px; }
.ih th.ih-prog-h { width: 150px; }
.ih .status { min-width: 112px; }   /* "Awarded" whole: a narrow column otherwise squeezes the pill */
.ih .who, .ih #projTbody .who > span:last-child { white-space: nowrap; }   /* a name on one line (2.x wrapped #projTbody's on purpose) */
/* the projects list keeps a job number on one line, and on a computer its cells give up 2px a side so 1440 fits its card
   (DEV-06; w10retire: was styles.css's) */
#projTbody td:first-child { white-space: nowrap; }
@media (min-width: 1181px) { table:has(> #projTbody) > * > tr > * { padding-left: 8px; padding-right: 8px; } }
.ih-who { display: inline-flex; color: inherit; text-decoration: none; }
.ih-who:hover { text-decoration: none; }
.ih-who:hover .who > span:last-child { text-decoration: underline; }
.ih-cardtop { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.ih-money { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.ih-money b { color: var(--ink); font-variant-numeric: tabular-nums; }
.ih-cardact { display: flex; justify-content: flex-end; }
.ih .cards .card { display: grid; gap: 6px; }
.ih-tools { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }   /* one lane the width of the panel: a view switch wider than a phone scrolls inside it instead of widening the page (w11design M1, Schedule Gap › Manpower at 375) */
.ih-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ih-search { flex: 1 1 220px; min-width: 0; }
.ih-row .select-wrap { flex: 0 1 190px; min-width: 0; }
.ih-row .select-wrap .select { width: 100%; }
.ih-toggle { display: inline-flex; align-items: center; gap: 8px; height: var(--ctl); padding: 0 12px; border-radius: var(--r-pill); border: 1px solid var(--hair-2);
  background: var(--glass-a); font-size: 12.5px; font-weight: var(--fw-semi); cursor: pointer; white-space: nowrap; }
.ih-toggle input { width: 16px; height: 16px; margin: 0; accent-color: var(--ink); }
.ih-toggle:has(input:checked) { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn); }
.ih-view { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; }
.ih-sort { all: unset; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; border-radius: 6px; }
.ih-sort span { font-size: 10px; color: var(--faint); }
th[aria-sort] .ih-sort { color: var(--ink); }
th[aria-sort] .ih-sort span { color: var(--accent-ink); }
.ih-sort:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
th.r .ih-sort { flex-direction: row-reverse; }
.ih-link { all: unset; cursor: pointer; font-size: 12.5px; color: var(--accent-ink); font-weight: var(--fw-semi); }
.ih-link:hover { text-decoration: underline; }
.ih-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
.ih-note { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 14px; padding: 12px 16px; font-size: 13.5px; }
body:not(.has-aimsly) .ih-aimsly { display: none; }   /* Aimsly's flows need her panel, which only some logins have */
@media (max-width: 1180px) {
  .ih-row .select-wrap { flex: 1 1 calc(25% - 6px); }   /* the four filters fill one row; the toggle and view move under them, never 3 + 1 */
}
@media (max-width: 1180px), (pointer: coarse) {
  .ih-sort { min-height: var(--tap); }
  .ih-who { min-height: var(--tap); align-items: center; }   /* the PM's name on a list row is a link (review 10/22) */
  .ih-toggle { height: var(--tap); }
  .ih-link { padding: 13px 0; }   /* 17.8px of text + 26 = a 44px reach (w26fix: 12px made it 42.8) */
}
@media (max-width: 640px) {
  .ih-row .select-wrap { flex: 1 1 calc(50% - 4px); }
  /* exactly three filters (Archived has no Status) stack 3 → 1, never 2 + 1 (review 10/22) */
  .ih-row:has(> .select-wrap ~ .select-wrap ~ .select-wrap):not(:has(> .select-wrap ~ .select-wrap ~ .select-wrap ~ .select-wrap)) > .select-wrap { flex-basis: 100%; }
  .ih-row .seg { flex: 1 1 100%; }
  .ih-row .seg button { flex: 1 0 auto; }   /* share the row when they fit; never shrink below their words (M2) */
  .ih-view { margin-left: 0; flex: 1 1 100%; justify-content: flex-end; }
  .ih-toggle { flex: 1 1 100%; justify-content: center; }
}

/* ---------------- the crew's phone screens (cw-): My Schedule, Non-Billable Time, Time (3.0) ----------------
   public/crew-home.js; design: the canvas board X-Phone. Phone first: today large, then what the office asked, then
   the four asks (2 × 2, never 3 + 1), then the week. From 981px the asks and the crew member's own cards move to a side
   column. Hours and quantities only — the one dollar figure is their own equipment's replacement cost. */
.cw { display: flex; flex-direction: column; gap: var(--gap); }
.cw h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.cw h3 { margin: 0; }
.cw .lede { margin-top: 2px; }
.cw > .lede { margin-top: 0; }   /* a lede between blocks (the crew's Non-billable, under its head) keeps the 16px stack: it was 18 (r2layout K4) */
.cw .card { margin: 0; }
.cw a.name { color: var(--ink); font-weight: var(--fw-bold); }   /* 2.x styles.css spaces every .card itself; here the column's gap does */
.cw .flags li > .btn { grid-column: 2; justify-self: start; }
.cw-grid { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--gap); align-items: start; }
.cw-main, .cw-side { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
.cw-grid div:empty { display: none; }   /* a card box with nothing to say takes no room and no gap */
.cw-sech { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; }
.cw-today { display: flex; flex-direction: column; gap: 12px; }
/* a day on a job */
.cw-job { display: flex; flex-direction: column; gap: 10px; }
.cw-job.hero { padding: 16px 18px 18px; gap: 12px; }
.cw-job.late { border-color: var(--warn-line); }
.cw-kicker { font: var(--fw-bold) 11px/1.3 var(--font); letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); }
.cw-jobtop { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.cw-jobtop .chip { flex: none; }
.cw-jobname { min-width: 0; }
.cw-jobname .name { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-l); font-weight: var(--fw-x); color: var(--ink); line-height: 1.25; text-wrap: balance; }
.cw-job.hero .cw-jobname .name { font-size: 19px; letter-spacing: -.01em; }
.cw-times { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border-radius: var(--r-l); background: var(--well); overflow: hidden; }
.cw-times.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cw-times > div { padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 2px; box-shadow: 1px 0 0 var(--hair); min-width: 0; }
.cw-times > div:last-child { box-shadow: none; }
.cw-times .label { font-size: 11px; line-height: 1.3; }
.cw-times b { font-size: 20px; font-weight: var(--fw-semi); letter-spacing: -.02em; line-height: 1.15; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cw-job.hero .cw-times b { font-size: 26px; font-weight: var(--fw-reg); }
.cw-times small { font-size: 12px; color: var(--muted); font-weight: var(--fw-semi); letter-spacing: 0; }
.cw-times em { display: block; font-style: normal; font-size: 11.5px; color: var(--warn); font-weight: var(--fw-bold); letter-spacing: 0; }   /* a night shift names the morning it ends on */
.cw-notimes { margin: 0; }
.cw-addr { display: inline-flex; align-items: flex-start; gap: 6px; align-self: flex-start; font-size: 13px; font-weight: var(--fw-semi); color: var(--ink-2); }
.cw-addr .i { margin-top: 2px; color: var(--accent-ink); }
.cw-people { display: flex; flex-wrap: wrap; gap: 6px; }
.cw-people .person { padding-right: 10px; }
.cw-people .person > span { display: inline-flex; align-items: center; }
.cw-people .person em { font-style: normal; font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: .04em; text-transform: uppercase; opacity: .72; }
.cw-note { margin: 0; display: flex; gap: 8px; padding: 8px 10px; border-radius: var(--r-m); background: var(--well); font-size: 13px; color: var(--ink-2); }
.cw-note .i { margin-top: 2px; color: var(--muted); }
.cw-jobact { display: flex; justify-content: flex-end; }
.cw-job.hero .cw-jobact .btn { width: 100%; justify-content: center; }
.cw-day { display: flex; flex-direction: column; gap: 8px; }
.cw-dayh { display: flex; align-items: baseline; gap: 8px; font-size: 13.5px; font-weight: var(--fw-x); }
.cw-later, .cw-earlier { display: flex; flex-direction: column; gap: 14px; }
.cw-free { font-size: 13.5px; }
/* My Schedule, nothing scheduled: the empty card fills the column beside the four quick tiles (was a ~100px strip beside ~196px of tiles, w29d 274; w30b) */
@media (min-width: 1181px) {
  .cw-grid > .cw-main:not(:has(.cw-later, .cw-day, .cw-ask, .cw-today)) { align-self: stretch; }
  .cw-main:not(:has(.cw-later, .cw-day, .cw-ask, .cw-today)) > .cw-free { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; text-align: center; }
}
/* spend.css gives #scCrewBox display:grid, so an empty one still took a 16px gap in the side column */
.cw-side > #scCrewBox:empty { display: none; }
/* the four quick tiles are one height (row 1 was 93px, row 2 110px) */
.cw-acts { grid-auto-rows: 1fr; }
/* what the office asked */
.cw-ask { display: flex; flex-direction: column; gap: 12px; border-color: var(--warn-line); }
.cw-askitem { display: flex; flex-direction: column; gap: 6px; padding-top: 12px; border-top: 1px solid var(--hair); }
.cw-sech + .cw-askitem { padding-top: 0; border-top: 0; }
.cw-askwhat { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cw-q { margin: 2px 0; font-size: 14px; }
.cw-askfoot { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 8px; }
.cw-photos { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cw-photos img { width: 56px; height: 56px; object-fit: cover; border-radius: var(--r-s); border: 1px solid var(--hair-2); }
.cw-photo { cursor: pointer; }
/* the four asks */
.cw-acts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cw-tile { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; gap: 10px; min-height: 92px; padding: 12px 14px;
  border-radius: var(--r-l); border: 1px solid var(--glass-edge); background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); box-shadow: var(--shadow);
  color: var(--ink); font: inherit; text-align: left; text-decoration: none; cursor: pointer; transition: transform var(--t-quick), background var(--t-std), box-shadow var(--t-std); }
.cw-tile:hover { text-decoration: none; background: var(--glass-hi); box-shadow: var(--shadow-pop); }
.cw-tile:active { transform: scale(.97); }
.cw-tile .i { color: var(--accent-ink); }
.cw-tile b { display: block; font-size: 13.5px; font-weight: var(--fw-bold); line-height: 1.25; }
.cw-tile small { display: block; margin-top: 2px; font-size: 11.5px; font-weight: var(--fw-semi); color: var(--muted); }
/* their own cards */
.cw-phone { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.cw-phone > span { flex: 1 1 auto; min-width: 0; }
.cw-phone b { white-space: nowrap; }
.cw-phone > .i { color: var(--muted); }
.cw-phone > .btn { flex: none; }
.cw-phone.ask { flex-direction: column; align-items: stretch; gap: 6px; border-color: var(--warn-line); }
.cw-phone.ask .hint { margin: 0; }
.cw-phonerow { display: flex; gap: 8px; }
.cw-phonerow .input { flex: 1 1 auto; min-width: 0; }
.cw-card { display: flex; flex-direction: column; gap: 10px; }
.cw-card > .hint { margin: 0; }
.cw-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.cw-list > li { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 44px; padding: 8px 0; border-top: 1px solid var(--hair); }
.cw-list > li:first-child { border-top: 0; }
.cw-listmain { flex: 1 1 auto; min-width: 0; }
.cw-inv { align-items: flex-start; }
.cw-invside { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; }
.cw-invnote { margin-top: 4px; font-size: 12.5px; color: var(--ink-2); }
.cw-lost { color: var(--bad); }
.cw-done { display: flex; align-items: flex-start; gap: 6px; margin: 0; }
.cw-done .i { margin-top: 3px; color: var(--ok); }
.cw-formcard { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 10px; }
.cw-formcard > div { flex: 1 1 180px; min-width: 0; }
.cw-formcard > .btn { flex: none; }
/* the crew's ticket forms close the side column (a full-width table under two uneven columns left a 680px hole — review 10/22) */
.cw-formlist { display: flex; flex-direction: column; gap: 8px; padding: 0 18px 16px; }
/* forms: time off, non-billable lines */
.cw-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.cw-form .wide { grid-column: 1 / -1; }
.cw-modal h2 { font-size: var(--fs-xl); }
.cw-modal h3 { font-size: 13.5px; font-weight: var(--fw-x); }
.cw-modalacts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.cw-nb.solo { max-width: 920px; }   /* a phone form: on a wide screen it keeps a reading width, not the page's */
.cw-nbhead { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 16px; }
.cw-nbhead .field { flex: 0 1 260px; }
.cw-total { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.cw-lines { display: flex; flex-direction: column; gap: 10px; }
.cw-line { display: flex; flex-direction: column; gap: 10px; }
.cw-linetop { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 32px; }
.cw-nbacts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; }
.cw-nbacts .btn { justify-content: center; }
.cw-nbdone { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* Time */
.cw-nowrap { white-space: nowrap; }
.cw-bad { color: var(--bad); }
.cw-range { display: flex; flex-wrap: wrap; gap: 8px; }
.cw-shift { display: flex; flex-direction: column; gap: 10px; }
.cw-shift.ok { border-color: var(--ok-line); } .cw-shift.warn { border-color: var(--warn-line); } .cw-shift.bad { border-color: var(--bad-line); }
.cw-punches { display: flex; flex-wrap: wrap; gap: 6px; }
.cw-punches > div { display: flex; flex-direction: column; gap: 1px; min-width: 72px; padding: 6px 10px; border-radius: var(--r-m); background: var(--well); }
.cw-punches > .tot { background: var(--info-bg); }
.cw-punches b { font-size: 15px; font-weight: var(--fw-semi); font-variant-numeric: tabular-nums; }
.cw-punches .label { font-size: 11px; }
.cw-shift q { font-style: italic; }
.cw-perf { display: flex; flex-direction: column; gap: var(--gap); }   /* the 90-day panels (app.js perfPanels, shared with the person page) */
.cw-perf > h2 { margin: 6px 0 -6px; }
.cw-perf > :is(.row, .cards, .card) { margin: 0; }
@media (max-width: 1180px), (pointer: coarse) {
  .cw :is(.input, .select) { height: var(--tap); }
  .cw-addr { min-height: var(--tap); align-items: center; }
  .cw-addr .i { margin-top: 0; }
  .cw-jobname .name { min-height: var(--tap); }
  .cw-photo { min-height: var(--tap); }
}
@media (max-width: 980px) {   /* one column, in the order a crew needs it: today, the office's questions, the asks, the week, their cards */
  .cw-grid { display: flex; flex-direction: column; align-items: stretch; }   /* full width: the two-column grid's start alignment would shrink each card to its text */
  .cw-main, .cw-side { display: contents; }
  .cw-today, .cw-free { order: 1; } .cw-askbox { order: 2; } .cw-acts { order: 3; } .cw-main > .cw-day { order: 4; } .cw-later { order: 5; }
  .cw-side > * { order: 6; } .cw-side > .cw-acts { order: 3; } .cw-earlier { order: 7; } .cw-side > .cw-forms { order: 8; }
}
@media (max-width: 640px) {
  .cw-job.hero { padding: 14px 14px 16px; }
  .cw-nbacts { grid-template-columns: minmax(0, 1fr); }
  .cw-nbhead .field { flex: 1 1 100%; }
  .cw-total { flex: 1 1 100%; flex-direction: row; align-items: baseline; justify-content: space-between; }
  .cw-range .btn { flex: 1 1 0; justify-content: center; padding: 0 8px; }
}
@media (max-width: 520px) { .cw-form { grid-template-columns: minmax(0, 1fr); } .cw-form .wide { grid-column: auto; } }
@media (max-width: 400px) {
  .cw-job.hero .cw-times b { font-size: 22px; }
  .cw-times > div { padding: 8px 10px 10px; }
}

/* ---------------- charts (public/charts.js) — the helper draws SVG; these place its legend, tooltip and hit areas ---------------- */
.viz { margin-top: 6px; }
@media (max-width: 700px) { .viz { overflow-x: auto; -webkit-overflow-scrolling: touch; } }   /* a wide chart scrolls inside its card on a phone */
@media print { .viz { overflow: visible !important; } .viz > svg { min-width: 0 !important; } .viz.empty { padding: 10px 0 !important; } }
.viz.empty { padding: 40px 0; }   /* the inline padding charts.js wrote until w9shell; it was the look on screen */
.viz-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 8px 2px 4px; }
.viz-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.viz-legend-item i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
.viz-hit { cursor: pointer; }
.viz [data-drill]:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.viz-tip { position: fixed; z-index: 1450; display: none; background: var(--ink); color: var(--on-ink); padding: 6px 10px; border-radius: 8px;
  font-size: 12px; font-weight: var(--fw-semi); white-space: nowrap; pointer-events: none; box-shadow: var(--shadow-pop); }
/* pf-charts (Jordan, 10/26): on a phone or a touch iPad the chart is one control — a tap lists its figures in a sheet (charts.js
   openSheet), a thumb's height each, and a figure with a drill opens it. On a computer none of this is drawn. */
.viz-tap { cursor: pointer; border-radius: var(--r-m); -webkit-tap-highlight-color: transparent; }
.viz-tap:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.viz-tap:active .viz-svg { opacity: .82; }
.viz-cue { display: flex; align-items: center; gap: 6px; margin: 6px 2px 0; font-size: 12px; color: var(--muted); }
.viz-sheet h2 { margin-bottom: 4px; }
.viz-sheet > .hint { margin: 0 0 12px; }
.viz-list { display: grid; gap: 12px; }
.viz-grp { display: grid; border: 1px solid var(--hair-2); border-radius: var(--r-l); overflow: hidden; background: var(--surface); }
.viz-grp-h { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 8px 14px; background: var(--surface-2);
  font-size: 13px; font-weight: var(--fw-bold); color: var(--ink); }
.viz-grp-t { font-weight: var(--fw-semi); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.viz-li { display: flex; align-items: center; gap: 10px; width: 100%; min-height: var(--tap); padding: 8px 14px; margin: 0; border: 0; border-top: 1px solid var(--hair);
  background: none; color: var(--ink); font: inherit; font-size: 14px; text-align: left; }
.viz-grp > .viz-li:first-child { border-top: 0; }
button.viz-li { cursor: pointer; }
button.viz-li:active, button.viz-li:focus-visible { background: var(--well); outline: none; }
.viz-sw { flex: none; width: 10px; height: 10px; border-radius: 3px; background: var(--vc); }
.viz-li-k { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.viz-li-v { flex: none; font-weight: var(--fw-semi); font-variant-numeric: tabular-nums; }
.viz-li-go { color: var(--muted); }

/* ---------------- Momentum: the Overview, Reports and Dashboards (mo-) — public/momentum.js (3.0) ----------------
   The kit's strip, seg, subtabs, table.t → phone cards, flags, chips and source links do the work; these only place them. */
.mo { display: flex; flex-direction: column; gap: var(--gap); }
.mo h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.mo .lede { margin: 0; }
.mo > p.hint { margin: 0; }                 /* a summary line between blocks keeps the 16px rhythm (review 10/22) */
.mo > details.mo-more { margin-top: 0; }
@media (max-width: 1180px), (pointer: coarse) {   /* every Reports tab's head is the same height, so the tab strip under it never jumps (review 10/22) */
  .mo > .page-head { min-height: 44px; }
  .mo > .page-head .actions { height: 44px; }
}
.mo > .seg { align-self: flex-start; }   /* a view switch is as wide as its buttons, not the column */
.mo-top { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 6px 12px; margin-bottom: 10px; }
.mo-top:last-child { margin-bottom: 0; }
.mo-top .hint { margin: 2px 0 0; }
.mo-grow > div:first-child { flex: 1 1 320px; min-width: 0; }   /* the heading and its sentence take the row; the button stays right */
.mo-panel > .pad.mo-top { margin-bottom: 0; }
.mo-tools, .mo-period { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
.mo-date { display: inline-flex; align-items: center; gap: 6px; }
.mo-date .input { width: 160px; }
.mo .strip .hint { display: flex; flex-direction: column; gap: 6px; margin-top: auto; }
.strip.mo-two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.mo-ok { color: var(--ok); } .mo-bad { color: var(--bad); }
/* a count or a sum in a table that opens the rows it counted */
.mo-n { all: unset; cursor: pointer; font-variant-numeric: tabular-nums; border-radius: 4px; text-decoration: underline; text-decoration-color: var(--hair-2); text-underline-offset: 3px; }
.mo-n:hover { color: var(--accent-ink); text-decoration-color: currentColor; }
.mo-n:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
table.t tr.mo-total td { font-weight: var(--fw-bold); }
.mo-kid { display: inline-flex; padding-left: 16px; }
.mo-visit, .mo-nowrap { white-space: nowrap; }
.mo-acts { display: inline-flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }
.mo-flag { display: grid; gap: 2px; min-width: 0; }
.mo-flag-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 10px; }
.mo-gap { display: inline-flex; align-items: center; gap: 8px; font-weight: var(--fw-bold); color: var(--bad); font-variant-numeric: tabular-nums; }
.mo-chart .mo-top { min-height: 43px; }   /* two charts in a row start their plots level whether a title wraps or not */
.mo-score th, .mo-score td { white-space: nowrap; }
.mo-sc { display: grid; gap: 8px; }
.mo-sc .mo-top { margin: 0; align-items: center; }
.mo-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 12px; margin: 0; }
.mo-kv dt { font-size: 11.5px; color: var(--muted); }
.mo-kv dd { margin: 0; font-variant-numeric: tabular-nums; font-weight: var(--fw-semi); }
.mo-name { font-size: var(--fs-xl); font-weight: var(--fw-x); margin: 2px 0 0; }
.mo-title .input { font-size: var(--fs-xl); font-weight: var(--fw-x); height: auto; padding: 4px 8px; margin-top: 2px; min-width: min(420px, 100%); }
.mo-widgets { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); align-items: stretch; }   /* a row's widgets share its height (review 10/22) */
.mo-widget.mo-wide { grid-column: span 2; }
.mo-widget .value { margin-top: 2px; }
.mo-note { white-space: pre-line; margin: 0; }
.mo-widget-add { grid-column: 1 / -1; min-height: 64px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: var(--r-xl);
  border: 1.5px dashed var(--hair-2); background: transparent; color: var(--muted); font: var(--fw-semi) 13.5px var(--font); cursor: pointer; }
.mo-widget-add:hover { color: var(--ink); border-color: var(--ink); }
@media (max-width: 1180px) {
  .mo-widgets { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1180px), (pointer: coarse) {
  .mo-n { min-height: var(--tap); display: inline-flex; align-items: center; }
  .mo-kv dd { min-height: var(--tap); display: flex; align-items: center; }   /* a plain $0.00 sits level with a tappable figure beside it */
}
@media (max-width: 640px) {
  .mo-widgets { grid-template-columns: minmax(0, 1fr); }
  .mo-widget.mo-wide { grid-column: auto; }
  .mo-date { flex: 1 1 calc(50% - 4px); }
  .mo-date .input { width: 100%; }
  .mo-tools > .seg, .mo-period > .seg { flex: 1 1 100%; }
  .mo-title .input { min-width: 0; width: 100%; }
}

/* ---------------- Momentum Reports, the other views (mo-): Labor, Labor Breakdown, Resources, Backlog Tracker, Customer
   Health, Pipeline Analysis, Quotes vs matrix — public/momentum.js and public/customer-health.js (3.0) ----------------
   Same pieces as the views above; these place a strip inside a panel, a totals row, a pipe in a cell and a pop-up. */
.strip.mo-three { grid-template-columns: repeat(3, minmax(0, 1fr)); }   /* three figures stay three, then one on a phone: never two and an orphan */
.mo-panel > .table-wrap, .mo-panel > .mo-more { padding: 4px 18px 16px; }   /* --pad is two values, so spelled out */
table.t .mo-w { min-width: 200px; }   /* a name column that must not be squeezed by a long notes column beside it */
.mo-panel > .empty { margin: 0; }
.mo-panel > p.hint.pad { margin: 0; padding-top: 0; }
.mo table.t tfoot td { border-top: 1px solid var(--hair); border-bottom: 0; }   /* the totals row: the figure above it, added up */
.mo-chips { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.mo-people { display: inline-flex; flex-wrap: wrap; gap: 4px 10px; }
.mo-rel { display: inline-grid; grid-template-columns: minmax(56px, 1fr) 5.5ch; align-items: center; gap: 8px; min-width: 120px; width: 100%; }
.mo-rel > .hint { text-align: right; font-variant-numeric: tabular-nums; }   /* one width for "8%" and "100%", so every row's bar is the same length (w27hb) */
.mo-more { margin-top: 10px; }
.mo-more > summary { cursor: pointer; font-size: 12.5px; font-weight: var(--fw-semi); color: var(--muted); padding: 6px 0; }
.mo-more > summary:hover { color: var(--ink); }
.mo-sheet { display: grid; gap: 10px; min-width: 0; }
.mo-sheet h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.mo-sheet h3 { margin: 6px 0 0; font-size: 13.5px; font-weight: var(--fw-bold); }
.mo-sheet > .mo-acts { justify-content: flex-end; }
.mo-scroll { max-height: 300px; overflow-y: auto; }
.mo-warn { color: var(--warn); font-weight: var(--fw-bold); }
.mo .flags li > .mo-chips { grid-column: 2; gap: 4px 14px; }   /* a flag's source links, under its sentence */
.strip > .mo-on { box-shadow: inset 0 -3px 0 var(--accent), 1px 0 0 var(--hair), 0 1px 0 var(--hair); }   /* the figure the list below is filtered to */
.mo-sort { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; border-radius: 4px; }
.mo-sort > span { font-size: 10px; color: var(--faint); }
.mo-sort.on, .mo-sort:hover { color: var(--ink); }
.mo-sort.on > span { color: var(--accent-ink); }
.mo-sort:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
th.r .mo-sort { flex-direction: row-reverse; }
.mo-center { display: flex; justify-content: center; margin-top: 12px; }
.mo .flags li.ok { background: var(--ok-bg); border-color: var(--ok-line); }   /* a Health check that passes */
.mo .flags li.ok .i { color: var(--ok); }
.mo-formula p { margin: 8px 0 0; font-size: 13px; line-height: 1.55; max-width: 110ch; }
.mo-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: var(--fw-semi); }
/* Resources by month: one pipe per month, its share not in the bid in amber at the end (--fill and --part are data) */
table.t .mo-barcol { width: 38%; min-width: 90px; }
.pipe.mo-stack > i { background: linear-gradient(90deg, transparent calc(100% - var(--part, 0%)), var(--warn) 0), linear-gradient(180deg, var(--water-a), var(--water-b)); }
/* Labor Breakdown's "the math": a line each — what, the arithmetic in words, the total */
.mo-math { display: grid; margin: 6px 0 10px; }
.mo-line { display: grid; grid-template-columns: 160px minmax(0, 1fr) auto; gap: 4px 14px; align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--hair); }
.mo-line:last-child { border-bottom: 0; }
.mo-line-l { font-weight: var(--fw-semi); }
.mo-line-m { color: var(--muted); font-size: 13px; }
.mo-line-m .mo-chips { margin-left: 8px; gap: 4px 14px; }
.mo-line-t { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.mo-srcs { gap: 4px 14px; margin-top: 2px; }
/* a wide figures table (by day, by person): it scrolls in its panel and never wraps a number */
.mo-wide-t th, .mo-wide-t td { white-space: nowrap; padding-inline: 8px; }
@media (max-width: 1180px) {
  .mo .table-wrap:has(> .mo-wide-t) { background: var(--surface); border-radius: var(--r-m); }
  .mo-wide-t :is(th, td):first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); }   /* the date or the name stays put */
}
/* a strip of choices with a dropdown twin (moSegGo { phone: true }): the strip on a wide screen, the dropdown on a phone,
   where the strip would run off the side (review 10/22) */
.mo-segsel { display: contents; }
.mo-segsel > .seg { align-self: flex-start; }
.mo-segsel-pick { display: none; }
@media (max-width: 1180px), (pointer: coarse) { .mo p.hint .mo-n { min-height: 0; display: inline; } }
@media (max-width: 640px) {
  .mo-segsel > .seg { display: none; }
  .mo-segsel-pick { display: flex; }
  .mo-segsel-pick .select { width: 100%; }
  .mo-period .mo-segsel-pick, .mo-tools .mo-segsel-pick, .mo-tools > .mo-period { flex: 1 1 100%; }
  .mo > .mo-segsel > .mo-segsel-pick { align-self: stretch; }
}   /* a count inside a sentence keeps the line's height */
@media (max-width: 640px) {
  .mo-tools > .select-wrap { flex: 1 1 calc(50% - 4px); min-width: 0; }
  .mo-tools > .select-wrap .select { width: 100%; }
  .mo-line { grid-template-columns: minmax(0, 1fr) auto; }
  .mo-line-m { grid-column: 1 / -1; grid-row: 2; }
  .strip.mo-three { grid-template-columns: minmax(0, 1fr); }
  .mo-panel > .table-wrap, .mo-panel > .mo-more { padding: 4px 10px 10px; }
}

/* ---------------- a table wider than its card says so (w30k) ----------------
   phone-tables.js marks a .table-wrap tw-scroll while its table overflows, tw-more while there is more to the right and
   tw-scrolled once it has moved. At every width and for every pointer the right edge takes a shadow while there is more
   (and the left one once it has moved): 11 screens at 820 and 1440 scrolled in silence. --tw-x holds the box's scroll, so the
   shadow stays on the visible edge although it is drawn inside the scrolling box. The touch iPad's "more →" (below) is this
   shadow with words. */
.table-wrap.tw-scroll.tw-more::after, .table-wrap.tw-scroll.tw-scrolled::before { content: ""; position: absolute; top: 0; bottom: 0; z-index: 3; width: 36px; pointer-events: none; }
.table-wrap.tw-scroll.tw-more::after { right: 0; transform: translateX(var(--tw-x, 0px)); background: linear-gradient(to right, transparent, rgba(11, 18, 32, .16)); }
.table-wrap.tw-scroll.tw-scrolled::before { left: 0; transform: translateX(var(--tw-x, 0px)); background: linear-gradient(to left, transparent, rgba(11, 18, 32, .16)); }
[data-theme="dark"] .table-wrap.tw-scroll.tw-more::after { background: linear-gradient(to right, transparent, rgba(0, 0, 0, .42)); }
[data-theme="dark"] .table-wrap.tw-scroll.tw-scrolled::before { background: linear-gradient(to left, transparent, rgba(0, 0, 0, .42)); }
@media print { .table-wrap.tw-scroll::before, .table-wrap.tw-scroll::after { display: none !important; } }
/* the floor under a column of words: phone-tables.js marks a heading tw-words (the column's longest cell is a sentence) or
   tw-text (a name, an address): the table is allowed to be wider than its card, and scrolls, but not to fold the words into a strip */
@media (min-width: 701px) {
  .table-wrap > table th.tw-words { min-width: 15em; }
  .table-wrap > table th.tw-text { min-width: 9em; }
}

/* ---------------- 2.x list tables on a touch iPad (701–1180px), inside the 3.0 frame ----------------
   phone-tables.js keeps the busy lists' own width and scrolls them in their card, with the first column stuck. The
   stuck cell needs a solid face or the row slides through underneath; it takes the same --surface as the whole table,
   so the list reads as one even sheet instead of glass with an opaque 2.x column (design review 10/22). :root lifts
   these above styles.css's own dark hover rule. */
@media (min-width: 701px) and (max-width: 1180px) and (pointer: coarse) {
  /* the shape, which styles.css drew until w9shell: the stuck first column, its shadow once scrolled, the "more →" fade */
  .table-wrap.tw-scroll { position: relative; }
  .table-wrap.tw-scroll > table > * > tr > :first-child:not([colspan]) { position: sticky; left: 0; z-index: 2; }
  .table-wrap.tw-scrolled > table > * > tr > :first-child:not([colspan]) { box-shadow: 7px 0 8px -7px rgba(10, 20, 40, .22); }
  .table-wrap.tw-scroll.tw-more::after { content: 'more →'; position: absolute; top: 0; bottom: 0; right: 0; z-index: 3; width: 96px; display: flex;
    align-items: flex-start; justify-content: flex-end; padding: calc(var(--tw-head, 0px) + 9px) 10px 0 0; font-size: 11px; font-weight: var(--fw-bold);
    letter-spacing: .04em; text-transform: uppercase; pointer-events: none; transform: translateX(var(--tw-x, 0px)); }
  :root .table-wrap.tw-scroll { background: var(--surface); }
  :root .table-wrap.tw-scroll > table > * > tr > td:first-child:not([colspan]),
  :root .table-wrap.tw-scroll > table > * > tr:hover > td:first-child:not([colspan]),
  :root .table-wrap.tw-scroll > table > * > tr > th:first-child:not([colspan]) { background: var(--surface); }   /* the stuck heading too: the rows slid through it (w45, 11/2) */
  :root .table-wrap.tw-scroll.tw-more::after { background: linear-gradient(to right, transparent, var(--surface) 62%); color: var(--accent-ink); }
}

/* ---------------- Settings (stg-): the frame of #/settings in all four products, My Profile, and a group's page ----------------
   Six groups (Jordan's 3.0 decisions, 10/22). From 981px they run across the top (Jordan 10/22: "Can that be a top bar?"):
   row one is the groups as sub-tabs with the search at its right end, its answers in a list under the box; row two is the
   open group's tabs as a segmented strip; the page takes the whole width under them. At 980 and under the top rows are not
   drawn and the menu folds into one "All settings" row above the page (.stg-nav). The tabs still drawn in 2.x markup sit
   in .stg-body as they always did. */
.stg { display: grid; gap: var(--gap); }
.stg-lay { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap); align-items: start; }
.stg-top { display: grid; gap: 12px; min-width: 0; }
.stg-bar { display: flex; align-items: center; gap: 20px; min-width: 0; box-shadow: inset 0 -1px 0 var(--hair); }   /* one hairline under the groups and the search */
.stg-groups { flex: 1 1 auto; min-width: 0; border-bottom-color: transparent; }
.stg-groups a[aria-current="true"] { color: var(--ink); border-bottom-color: var(--accent); }   /* the group of the open tab */
.stg-find { flex: 0 0 260px; }
.stg-find .input { margin: 0; }
.stg-hits { left: 0; top: calc(100% + 6px); max-height: min(420px, calc(100vh - 220px)); overflow-y: auto; }
.stg-hits .stg-hit { height: auto; min-height: 44px; padding: 6px 10px; justify-content: space-between; }
.stg-hits .stg-hit[aria-selected="true"] { background: var(--well); }
.stg-hit-t { display: grid; gap: 1px; min-width: 0; }
.stg-hit-t b { font-size: 13px; font-weight: var(--fw-semi); }
.stg-hit-t .hint { font-size: 11.5px; font-weight: var(--fw-med); }
.stg-hits .stg-none { margin: 8px 10px; }
.stg-tabs { justify-self: start; }
/* Settings' part strip (Company, Branches, …) in Spanish was 1218px wide at 1024 and scrolled 226px inside its own pill with nothing to say so.
   Where there is room to see it, it wraps instead (w26fix); a phone still scrolls it, with the fades. */
@media (min-width: 701px) { .stg-tabs { flex-wrap: wrap; overflow: visible; -webkit-mask-image: none; mask-image: none; } }
.stg-tabs a { position: relative; display: inline-flex; align-items: center; height: 30px; padding: 0 12px; border-radius: 8px; font-size: 12.5px; font-weight: var(--fw-semi);
  color: var(--muted); white-space: nowrap; text-decoration: none; transition: color var(--t-std), background var(--t-std); }
.stg-tabs a:hover { color: var(--ink); text-decoration: none; }
.stg-tabs a[aria-current="page"] { background: var(--ink); color: var(--on-ink); box-shadow: 0 2px 6px rgba(11,18,32,.25); }
.stg-tabs .n { margin-left: 5px; font-weight: 800; color: var(--warn); }
.stg-tabs a[aria-current="page"] .n { color: inherit; opacity: .75; }
/* 981–1180: eleven English tabs needed 993px of a 992px row and left "Trash" alone on row 2 (design review) */
@media (min-width: 981px) and (max-width: 1180px) { .stg-tabs a { padding: 0 9px; } }
.stg-nav { display: none; padding: 4px; border-radius: var(--r-l); }
.stg-menu { display: none; }
.stg-list { display: grid; gap: 2px; }
.stg-q { margin-bottom: 6px; }
.stg-grp { border-radius: 12px; transition: background var(--t-std); }
.stg-grp:has(> .stg-gh[aria-expanded="true"]) { background: rgba(255,255,255,.35); padding-bottom: 6px; }
.stg-gh { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; min-height: 38px; padding: 0 10px; border: 0; border-radius: var(--r-m);
  background: transparent; font: var(--fw-bold) 12.5px var(--font); color: var(--ink); cursor: pointer; text-align: left; }
.stg-gh:hover { background: rgba(255,255,255,.5); }
.stg-gh small { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: var(--fw-bold); color: var(--muted); }
.stg-gh .i { transition: transform var(--t-std); }
.stg-gh[aria-expanded="false"] .i { transform: rotate(-90deg); }
.stg-gh[aria-expanded="true"] .badge { display: none; }   /* open, each waiting count is on its own row */
.stg-items { display: grid; gap: 2px; }
.stg-si { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 34px; padding: 6px 10px 6px 22px; border-radius: 9px;
  color: var(--ink-2); font-size: 13px; font-weight: var(--fw-med); text-decoration: none; }
.stg-si:hover { background: rgba(255,255,255,.5); color: var(--ink); text-decoration: none; }
.stg-si[aria-current="page"] { background: var(--glass-hi); color: var(--ink); font-weight: var(--fw-bold); box-shadow: var(--shadow-pop); }
.stg-none { margin: 6px 10px; }
.stg-body { min-width: 0; }
.stg-body .mi-head h2.title { display: none; }   /* Master Items in Settings: the page's own heading already names it */
/* a group's page: its tabs as rows */
.stg-rows { display: grid; padding: 6px; }
.stg-row { display: flex; align-items: center; gap: 12px; min-height: 58px; padding: 10px 12px; border-radius: var(--r-m); color: var(--ink); text-decoration: none; }
.stg-row + .stg-row { box-shadow: inset 0 1px 0 var(--hair); }
.stg-row:hover { background: rgba(255,255,255,.5); text-decoration: none; }
.stg-row-t { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.stg-row-t b { font-size: 14px; }
.stg-row > .i { color: var(--faint); transition: transform var(--t-quick); }
.stg-row:hover > .i { transform: translateX(3px); }
/* My Profile: two-up panels that share a bottom edge; .stg-wide takes the row */
.stg-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
.stg-cards > .stg-wide { grid-column: 1 / -1; }
.stg-card { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.stg-card.stg-2x { display: block; }   /* its contents are still drawn in 2.x markup, which spaces itself */
.stg-card h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.stg-card p { margin: 0; }
.stg-card-head { display: grid; gap: 4px; }
.stg-card .src { margin-left: 4px; }
.stg-bad { color: var(--bad); }
.stg-link { all: unset; cursor: pointer; color: var(--accent-ink); font-weight: var(--fw-semi); }
.stg-link:hover { text-decoration: underline; }
.stg-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
.stg-qe { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--gap); align-items: start; }
.stg-tpl { min-height: 320px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.5; }
.stg-tokens td:first-child { white-space: nowrap; }
.stg-checks { display: grid; }
.stg-wide .stg-checks { display: block; columns: 2; column-gap: 32px; }   /* the whole width: two balanced columns of switches */
.stg-wide .stg-check, .stg-wide .stg-check:first-child { break-inside: avoid; border-top: 1px solid var(--hair); padding-top: 10px; }   /* both columns start on a hairline */
.stg-check { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; align-items: start; padding: 10px 2px; border-top: 1px solid var(--hair); cursor: pointer; }
.stg-check:first-child { border-top: 0; padding-top: 0; }
.stg-check input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--ink); }
.stg-check > span { display: grid; gap: 2px; }
.stg-devs { display: grid; max-height: 340px; overflow-y: auto; }
.stg-dev { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 0; border-top: 1px solid var(--hair); }
.stg-dev:first-child { border-top: 0; padding-top: 2px; }
.stg-dev > div { min-width: 0; display: grid; gap: 2px; justify-items: start; }
.stg-dev > div > b { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.stg-dev .hint { overflow-wrap: anywhere; }
.stg-dev .btn { flex: none; }
/* your picture: the face, the eight to choose from (4 → 2, never a lone tile), the photos waiting to go, the camera */
.stg-me { display: flex; align-items: center; gap: 14px; }
.stg-me > div { display: grid; gap: 2px; min-width: 0; }
.stg-face { width: 76px; height: 76px; flex: none; border-radius: 50%; object-fit: cover; background-color: var(--well); border: 2px solid var(--hair-2); }
.stg-face.logo { background: var(--well) url('/aims-a.png') center / 74% auto no-repeat; }
.stg-face.wait { background: linear-gradient(100deg, var(--well) 30%, var(--hair-2) 50%, var(--well) 70%); background-size: 300% 100%; animation: stg-sheen 1.4s linear infinite; }
@keyframes stg-sheen { from { background-position: 100% 0; } to { background-position: -100% 0; } }
.stg-avgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.stg-avcell { display: block; padding: 0; border-radius: 12px; border: 2px solid var(--hair-2); background: var(--glass-a); overflow: hidden; cursor: pointer;
  transition: transform var(--t-quick), border-color var(--t-quick); }
.stg-avcell img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.stg-avcell span { display: flex; align-items: center; justify-content: center; min-height: 2.9em; padding: 4px; font-size: 11.5px; line-height: 1.25; color: var(--muted); text-align: center; }
.stg-avcell:hover { border-color: var(--accent); transform: translateY(-1px); }
.stg-avcell[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.stg-avcell[aria-pressed="true"] span { color: var(--ink); font-weight: var(--fw-semi); }
.stg-shots { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; min-height: 68px; }
.stg-shot { position: relative; width: 64px; height: 64px; border-radius: 10px; background: var(--shot) center / cover; border: 1px solid var(--hair-2); }
.stg-shot button { position: absolute; top: -8px; right: -8px; width: 24px; height: 24px; padding: 0; border-radius: 50%; border: 1px solid var(--hair-2);
  background: var(--surface); color: var(--ink); font-size: 15px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.stg-cam { width: 100%; max-width: 320px; border-radius: 12px; background: #000; transform: scaleX(-1); }   /* mirrored, like a mirror */
.stg-avgo { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
[data-theme="dark"] .stg-grp:has(> .stg-gh[aria-expanded="true"]) { background: rgba(255,255,255,.04); }
[data-theme="dark"] .stg-gh:hover, [data-theme="dark"] .stg-si:hover:not([aria-current="page"]), [data-theme="dark"] .stg-row:hover { background: rgba(255,255,255,.06); }
@media (max-width: 1180px), (pointer: coarse) {
  .stg-tabs a { height: var(--tap); }
  .stg-gh, .stg-si { min-height: var(--tap); }
  .stg-check { min-height: var(--tap); }
  .stg-shot button::after { content: ""; position: absolute; inset: -10px; }   /* a 44px reach around the 24px dot */
  .stg-link { padding: 12px 0; }
}
@media (max-width: 980px) {
  .stg-top { display: none; }
  .stg-cards, .stg-qe { grid-template-columns: minmax(0, 1fr); }
  .stg-wide .stg-checks { columns: 1; }
  .stg-nav { display: block; }
  .stg-menu { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: var(--tap); padding: 0 12px; border: 0; border-radius: var(--r-m);
    background: transparent; font: var(--fw-bold) 13.5px var(--font); color: var(--ink); cursor: pointer; }
  .stg-menu .i { transition: transform var(--t-std); }
  .stg-menu[aria-expanded="true"] .i { transform: rotate(180deg); }
  .stg-nav:not(.open) .stg-list { display: none; }
  .stg-nav.open .stg-list { padding: 2px 4px 4px; }
}
@media (max-width: 700px) { .stg-avgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  .stg-avact > .btn, .stg-avgo { flex: 1 1 100%; }
  .stg-avgo { margin-left: 0; }
  .stg-avgo .btn { flex: 1 1 0; }
  .stg-dev { flex-wrap: wrap; }
}

/* ---------------- tap reach on touch (review 4, 10/22) ----------------
   At ≤1180 a small control reaches 44px through a pseudo-element, so nothing on the page moves. This block sits AFTER the
   components' own rules on purpose: .mo-n, .mo-sort and Master Items' code and size buttons are `all: unset`, which
   cancelled any floor set earlier (measured: code buttons 14px tall, size buttons 18px). */
@media (max-width: 1180px), (pointer: coarse) {
  .src { position: relative; }
  .src::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) -4px; }        /* a source link was 18–19px tall */
  .mo-n { position: relative; }
  .mo-n::after { content: ""; position: absolute; inset: 0 min(0px, calc(50% - var(--tap) / 2)); }   /* a lone "0" was 8–16px wide */
  /* ...but in a table's last column it stops 8px past the figure (a cell keeps 8–10px of padding at its end), so it never
     reaches past its cell and scrolls the table sideways (w21nx, 10/27: 2px past); it reaches as much further left instead */
  .table-wrap td:last-child > .mo-n::after { inset-inline-end: max(-8px, min(0px, calc(50% - var(--tap) / 2)));
    inset-inline-start: min(0px, calc(100% - var(--tap) - max(-8px, min(0px, calc(50% - var(--tap) / 2))))); }
  .mo-sort { min-height: var(--tap); }                     /* a heading's sort was 17px tall; a reach drawn past the heading is */
  :root th:has(> .mo-sort) { padding-top: 0; padding-bottom: 0; }   /* clipped by the table's scroll box, so the button grows and the cell's padding goes */
  .switch::before { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) 0; }          /* 46×26; ::after is the knob */
  .mi-list .code button, .mi-rc .sz button { min-height: var(--tap); display: inline-flex; align-items: center; }
  .stg-find .input { height: var(--tap); }                                                             /* 36px between 981 and 1180 */
}
/* touch reach (w11design K3): the small things a thumb presses get a 44px area without moving anything on the page */
@media (max-width: 1180px), (pointer: coarse) {
  .crumb a, .cards a.name, .card a.name, a:has(> .who), button.chip, a.chip, details > summary, .i18n-switch button { position: relative; }
  .crumb a::after, .cards a.name::after, .card a.name::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) -4px; }   /* a breadcrumb was 17px, a card's own name 18–22px */
  a:has(> .who)::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) 0; }   /* a person's name: Tickets', the project's, Apex's, Settings' */
  button.chip::after, a.chip::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) 0; }   /* a chip that is a button: New project's service facets were 28px */
  details > summary::after { content: ""; position: absolute; left: 0; right: 0; top: calc(50% - var(--tap) / 2); height: var(--tap); }   /* "More", "Why": 32–39px */
  .i18n-switch button::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) 0; }   /* the crew ticket's EN | ES was 38px (ticket.css sets its height) */
  .stack-more-btn { min-height: var(--tap); }   /* "▾ Show all fields" was 40px */
  .leaflet-container.leaflet-touch .leaflet-control-zoom.leaflet-bar a { width: var(--tap); height: var(--tap); line-height: var(--tap); }   /* the map's + and − were 30px (outranks leaflet.css's own touch size) */
}
/* touch reach, second round (w15polish K3, 10/23 — re-measured on every admin screen at 375 as an iPhone, hit-testing 21.5px
   either side of each control's centre; a pop-up's links too). A link whose words are a record's name — a branch, a customer, a project, a unit, a
   person: the screens mark it data-i18n-skip (a name is never translated) or wrap the name in one, or .name, or data-focus
   (it lands on a field) —
   is that record's door, and stands alone on its line: 17–22px of text, so it gets the 44px reach the first round gave a
   card's own name. So does the link under a strip's figure (a Sentry unit's "Issues", "2 readings", "on the map"), and a
   link alone in a table cell — a quote number in a computer table on a touch iPad was 18px. min(): never smaller than the link itself; at least the 44 across a short name ("MSAs", "4747"). */
@media (max-width: 1180px), (pointer: coarse) {
  /* :where() — no weight: a link some screen positions itself keeps its own position, and a reach a screen already drew
     (.cards a.name, a face's, Apex's head) keeps its own inset */
  :where(:is(#app, .modal, [role="dialog"]) a:is([data-i18n-skip], .name, [data-focus], .sco-rec, :has(> [data-i18n-skip]:only-child)):not(.btn, .chip, .src), .strip .hint > a, #app td > a:only-child:not(.btn, .chip, .src)) { position: relative; }
  :where(:is(#app, .modal, [role="dialog"]) a:is([data-i18n-skip], .name, [data-focus], .sco-rec, :has(> [data-i18n-skip]:only-child)):not(.btn, .chip, .src), .strip .hint > a, #app td > a:only-child:not(.btn, .chip, .src))::after {
    content: ""; position: absolute; inset: min(0px, calc(50% - var(--tap) / 2)) min(-4px, calc(50% - var(--tap) / 2)); }
  /* buttons a shade under 44 across: a view tab's "All", a heading's sort, an icon-only small button with no .icon class */
  .seg > button, th .ih-sort, th .mo-sort, th > button { min-width: var(--tap); }
  .btn.sm:has(> svg:only-child) { min-width: var(--tap); }   /* only-child counts elements: a button with words is wider anyway */
  th .ih-sort { min-height: var(--tap); justify-content: flex-start; }   /* a short label stays on its column's edge (centred, it sat 3.5–7px off; w20jobs' review, 10/27) */
  th:is(.r, .num) .ih-sort { justify-content: flex-end; }
  /* element-qualified: their own rules come later in this sheet (all: unset on the buttons) and would undo a bare class */
  button.sbe-chipx { position: relative; }
  button.sbe-chipx::after { content: ""; position: absolute; inset: -14px; }   /* a quote document's tag ✕ was 16px */
  input.sbe-file { min-height: var(--tap); }   /* the file box was 39px beside 44px boxes */
  button.sbe-kname { min-height: var(--tap); align-content: center; }   /* a kit's name (its editor's door) was 40px */
  /* a strip cell's small button beside its label ("+ Reading" on a Sentry unit): the reach, not the height, so the label row
     keeps the figures level (K8) */
  .cpl-url, a.sbk-open { position: relative; }
  a.sbk-open::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) min(-4px, calc(50% - var(--tap) / 2)); }   /* a submittal's "Open" was 18px */
  .strip .top > .btn.sm { height: var(--tap); margin-block: calc((28px - var(--tap)) / 2); }   /* a .btn clips its own ::after (overflow: hidden), so the box grows instead: 44 tall in a 28px slot */
  .cpl-url::after { content: ""; position: absolute; inset: min(0px, calc(50% - var(--tap) / 2)) 0; }   /* a customer's portal link, 14px of address */
}

/* touch reach, wave 17 (w17platform, from w17ignite's re-measure): where two targets sit one over the other, each one's
   44px reach ran into its neighbour's, so neither got 44. Ignite's dashboard cards at 375 (the job's name and its "5/15
   open" chip over the customer line) get a 44px top row and 14px between rows; its table at 820 (a customer link over its
   branch link in one cell) puts the two 44px apart, centre to centre, and pads the rows so the next row's names keep
   theirs. Measured with w15polish's probe (hit-testing 21.5px either side of each centre): 0 short targets left there. */
@media (max-width: 1180px), (pointer: coarse) {
  .ih .cards .card { row-gap: 14px; }
  .ih-cardtop { min-height: var(--tap); align-items: center; }
  .ih table.t > tbody > tr > td { padding-top: 14px; padding-bottom: 14px; }
  .ih table.t td > a + .hint { margin-top: 26px; }
}

/* touch reach, wave 18 (w18platform — the site-wide sweep: every screen a census reached, opened as an iPhone at 375 and
   hit-tested from each control's centre; a tick or a radio is measured by its label, the row a thumb presses). These are
   the kinds that live in the kit and the shared pieces; the rest are listed by screen in rebuild/reports/w18platform/. */
.sco-tcl { display: inline-flex; align-items: center; justify-content: center; margin: 0; cursor: pointer; }   /* the access grid's tick, in its label */
@media (max-width: 1180px), (pointer: coarse) {
  /* a breadcrumb's one short word ("You", "Field") reached 30–36 across: 44 across now, never narrower than the word */
  .crumb a::after { inset: calc(50% - var(--tap) / 2) min(-4px, calc(50% - var(--tap) / 2)); }
  /* source links one under another (a readiness card's fixes, Crews & Skills' sources, a projection's how-to): each one's
     44px reach ran into the next one's, so neither got it — the rows open to 44 centre to centre */
  :where(div, span, p):has(> .src + .src) { row-gap: calc(var(--tap) - 19px); }
  /* the access grid's ticks were 22px: the label around each is a thumb's square (Settings › Company › Logins › Roles & access) */
  .sco-tcl { min-width: var(--tap); min-height: var(--tap); }
  /* a chip's ✕ has a 44px reach (the second round), and the chip clipped it */
  .chip:has(> button.sbe-chipx) { overflow: visible; }
  /* a bid site's address, cut short with an ellipsis: its box clipped the link's reach — the link is a thumb tall itself */
  .sbe-clip > a { display: block; padding-block: calc((var(--tap) - 20px) / 2); overflow: hidden; text-overflow: ellipsis; }
  /* a Settings card's head (its name, a chip) over the line under it: the name's reach met the next line's link — the head is
     a thumb tall and the lines stand 14px apart, as Ignite's dashboard cards (wave 17) */
  .sco-card { row-gap: 14px; }
  .sco-card-top { min-height: var(--tap); }
  /* a phone card built like Ignite's dashboard cards (a head row, then lines with links: Tickets, Pay Apps, Surveys …) gets
     their 14px between lines, so a name's 44px reach no longer meets the link on the next line (it did at 36) */
  :root .cards .card:has(> .ih-cardtop) { row-gap: 14px; }   /* :root — outranks a product sheet's own card gap, which loads after the kit */
  /* a list's tick that is only a tick (Tickets, Pay Apps, Sentry's units): its label was 40×36 — a thumb's square now */
  label:is(.tix-hit, .mn-tickhit, .sn-tickhit) { min-width: var(--tap); min-height: var(--tap); justify-content: center; }
  /* short words and figures that are buttons: a forecast row's name ("DDM" 26 across) and its total ($0), a price book
     size ("4″" 12 across). (A Schedule Gap day's "47 free" reaches from gaps-ui.css: a product's class stays in its sheet.) */
  button:is(.wg-name, .wg-drill), .mi-rc .sz > button { min-width: var(--tap); }   /* .mi-rc: outranks the button's own all: unset */
}

/* ---------------- stepper (3.0, Apex quote): where a piece of work has got to, e.g. a bid's Draft → Approval → Sent → Won / Lost ----------------
   <ol class="stepper"><li class="done|now|bad|skip|todo"><span class="stepper-dot">1</span><span class="stepper-txt"><b>Draft</b><span class="hint">…</span></span></li></ol>
   done = behind it, now = where it is (aria-current="step"), bad = stopped there (rejected, lost), skip = not needed, todo = to come.
   Side by side, joined by a line that fills behind a finished step; on a phone each step is one line down the side. */
.stepper { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-columns: minmax(0, 1fr); grid-auto-flow: column; }
.stepper > li { position: relative; display: grid; grid-template-rows: 26px auto; row-gap: 6px; padding-right: 12px; min-width: 0; }
.stepper > li::before { content: ""; position: absolute; top: 12px; left: 34px; right: 8px; height: 2px; border-radius: 2px; background: var(--hair-2); }
.stepper > li:last-child::before { display: none; }
.stepper > li.done::before { background: var(--ok); }
.stepper-dot { width: 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: var(--fw-bold);
  background: var(--well); color: var(--muted); border: 1px solid var(--hair-2); }
.stepper-dot .i { width: 14px; height: 14px; }
.stepper-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.stepper-txt b { font-size: 13px; font-weight: var(--fw-bold); color: var(--muted); }
.stepper-txt .hint { font-size: 12px; overflow-wrap: anywhere; }
.stepper .done .stepper-dot { background: var(--ok-bg); color: var(--ok); border-color: var(--ok-line); }
.stepper .now .stepper-dot { background: var(--ink); color: var(--on-ink); border-color: var(--ink); box-shadow: 0 0 0 4px var(--well); }
.stepper .bad .stepper-dot { background: var(--bad-bg); color: var(--bad); border-color: var(--bad-line); }
.stepper .skip .stepper-dot { background: transparent; border-style: dashed; }
.stepper .done b, .stepper .now b { color: var(--ink); }
.stepper .bad b, .stepper .bad .hint { color: var(--bad); }
.stepper .now .hint { color: var(--ink-2); }
@media (max-width: 640px) {
  .stepper { grid-auto-flow: row; row-gap: 10px; }
  .stepper > li { grid-template-rows: none; grid-template-columns: 26px minmax(0, 1fr); column-gap: 10px; align-items: center; padding-right: 0; }
  .stepper > li::before { top: 30px; bottom: -8px; left: 12px; right: auto; width: 2px; height: auto; }
  .stepper-txt { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 8px; }
}

/* ---------------- Ignite money (mn-) — Pay Apps, a pay app, Cost Review, and the job's Pay Apps and Costs tabs (3.0) ----------------
   public/money.js. The kit's strip, seg, table.t → phone cards, status pills, flags and source links do the work; these
   only place them. Sortable heads, filter rows and card tops reuse the projects list's .ih-sort, .ih-row, .ih-search,
   .ih-tools, .ih-top, .ih-cardtop, .ih-money, .ih-chips and .ih-who (they are not scoped to .ih). */
.mn { display: flex; flex-direction: column; gap: var(--gap); }
.mn > div:empty { display: none; }   /* a pay app's empty #mnRej left a second gap: 32 between its panels (r2layout K4) */
.mn h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.mn .ih-top .hint { margin: 2px 0 0; }
.mn .cards .card { display: grid; gap: 6px; margin: 0; }   /* the list's own 8px gap, not 2.x's .card margin on top of it */
.mn .flags { margin-top: 12px; }
.mn .ih-tools { grid-template-columns: minmax(0, 1fr); }   /* the five views scroll inside their bar on a phone instead of widening the panel */
.mn .status { min-width: 120px; }
.mn a.name { font-weight: var(--fw-bold); color: var(--ink); }   /* a row's own name, linking to it (as table.t a.name) */
.mn .ih-top > div:first-child { flex: 1 1 300px; min-width: 0; }   /* the heading and its words take the room; the buttons keep to the right */
.ih-row .select-wrap.mn-jobpick { flex: 0 1 340px; }
.mn-t { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.mn-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; margin-top: 6px; font-size: 13px; color: var(--muted); }
.mn-meta a { color: var(--ink-2); font-weight: var(--fw-semi); }
.mn-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.mn-grow { flex: 1 1 220px; min-width: 0; }
.mn-from { display: flex; flex-wrap: wrap; gap: 2px 16px; margin-top: 10px; }
.page-head .mn-from { margin-top: 0; align-self: center; }
.mn-issue, .mn-foot { margin: 0; }
.mn-tick { width: 40px; }
.mn-tick input, .mn-cardname input { width: 16px; height: 16px; margin: 0; accent-color: var(--ink); }
.mn-tickhit { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; cursor: pointer; }   /* the label round a tick box: its reach on touch */
.mn-cardname { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.mn-void td, .mn-void.card, .mn-pa.mn-void { color: var(--muted); }   /* faded (K5): see "faded rows" */
.mn-wrap { overflow-wrap: anywhere; }
.mn-nowrap { white-space: nowrap; }
.mn-flush { margin: 0; }
/* the list's Created column folds into the Date cell where the table would otherwise run out of room */
.mn-created-hint { display: none; white-space: nowrap; }
@media (max-width: 1500px) { .mn th.mn-created, .mn td.mn-created { display: none; } .mn-created-hint { display: block; } }
/* touch iPads (701–1180): the columns a row can carry as a second line under another cell move there (mn-tab-off → mn-tab-on) */
.mn-tab-on { display: none; }
@media (max-width: 1180px) {
  .mn th.mn-tab-off, .mn td.mn-tab-off { display: none; }
  .mn .mn-tab-on { display: block; }
  .mn .mn-created-hint { display: none; }   /* when a pay app was made stays on the pay app; the row keeps its date */
  .mn #crBulk > .mn-grow { flex-basis: 100%; }   /* the count on its own line; the job picker and its two buttons share the next */
}
/* Cost Review: the three queues are the strip's cells, each a door to its view */
.strip > a.mn-cell { color: inherit; text-decoration: none; transition: background var(--t-quick); }
.strip > a.mn-cell:hover { background: rgba(255,255,255,.4); }
.strip > a.mn-cell.on { box-shadow: 1px 0 0 var(--hair), 0 1px 0 var(--hair), inset 3px 0 0 var(--accent); }   /* a bar down the open queue's left edge: reads the same 3 across or stacked */
[data-theme="dark"] .strip > a.mn-cell:hover { background: rgba(255,255,255,.04); }
/* one pay app per row on the job's tab: its number, what it was, what is due (design: rebuild/kit/project.html) */
.mn-pa { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 14px 0; border-top: 1px solid var(--hair); }
.mn .ih-top + .mn-pa, .mn .ih-top + .mn-why + .mn-pa { border-top: 0; margin-top: 4px; }
.mn-no { width: 52px; height: 52px; border-radius: 14px; background: var(--well); display: grid; place-items: center; font-weight: var(--fw-x); font-size: 16px; font-variant-numeric: tabular-nums; }
.mn-no.draft { background: transparent; border: 1.5px dashed var(--hair-2); color: var(--muted); font-size: 12px; }
.mn-figs { display: flex; flex-wrap: wrap; gap: 2px 14px; margin-top: 4px; font-size: 12.5px; color: var(--muted); }
.mn-figs b { color: var(--ink-2); font-weight: var(--fw-semi); font-variant-numeric: tabular-nums; }
.mn-net { text-align: right; font-weight: var(--fw-x); font-size: 16px; font-variant-numeric: tabular-nums; }
.mn-net .hint { font-weight: var(--fw-semi); }
.mn-why { margin: 8px 0 0; }
.mn-held { margin: 0; padding: 10px 12px; border-radius: var(--r-m); background: var(--info-bg); color: var(--info); font-size: 12.5px; font-weight: var(--fw-semi); }
/* a pay app: the over-bid note, the customer's rejected lines, and the document kept to the column (it is 7.5in wide) */
.mn-note { margin-top: 12px; }
.mn-note .mn-acts { justify-content: flex-end; margin-top: 6px; }
.mn-rej { list-style: none; margin: 10px 0 0; padding: 0; display: grid; }
.mn-rej li { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px 12px; padding: 10px 0; border-top: 1px solid var(--hair); }
.mn-rej li:first-child { border-top: 0; }
.mn-rej li > div { flex: 1 1 260px; min-width: 0; }
.mn-doc { overflow-x: auto; }
/* the Costs tab's three totals: cost, earned, margin */
.mn-sums { display: grid; gap: 6px; max-width: 520px; margin-top: 10px; }
.mn-sums > div { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13.5px; }
.mn-sums > div > span { display: inline-flex; align-items: center; gap: 8px; color: var(--ink-2); }
.mn-sums b { font-variant-numeric: tabular-nums; }
.mn-sums .tot { padding-top: 8px; border-top: 1px solid var(--hair); font-weight: var(--fw-bold); }
.mn-sums .tot small { color: var(--muted); font-weight: var(--fw-semi); }
.mn-sums b.ok { color: var(--ok); } .mn-sums b.bad { color: var(--bad); }
/* pop-ups: two fields a row, a picker that scrolls inside, the buttons at the foot */
.mn-modal { gap: 12px; }
.mn-modal h2 { font-size: var(--fs-xl); }
.mn-modal > .hint { margin: 0; }
.mn-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.mn-form .wide { grid-column: 1 / -1; }
.mn-pick { max-height: 360px; overflow-y: auto; border: 1px solid var(--hair); border-radius: var(--r-m); }
.mn-modalacts { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
@media (max-width: 1180px), (pointer: coarse) {
  .mn-tick input, .mn-cardname input { width: 22px; height: 22px; }
  .mn-tickhit { width: var(--tap); height: var(--tap); margin: -11px; }   /* a 44px reach round the 22px box, the row no taller (review 4, 10/22) */
}
@media (max-width: 640px) {
  .mn-pa { grid-template-columns: 40px minmax(0, 1fr); gap: 4px 12px; }
  .mn-no { width: 40px; height: 40px; border-radius: 11px; font-size: 14px; }
  .mn-net { grid-column: 2; text-align: left; font-size: 15px; }
  .mn-net .hint { display: inline; margin-left: 6px; }
  .mn-form { grid-template-columns: minmax(0, 1fr); }
  .page-head .mn-acts { width: 100%; }
}

/* ---------------- Momentum › Forecast › Weekly review (wr-) — public/momentum.js (3.0) ----------------
   The weekly forecast meeting: the kit's strip, flags, chips, status dropdowns, the wide grid (wg-) and its side sheet do
   the work; these only place them. A month is a button that opens what makes it up (a total is never typed). */
.wr-walk h2, .mo-band h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }   /* the review sits outside .mo, so its headings are set here */
.wr-walk h2 { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.wr-walk h2 .chip .i { width: 12px; height: 12px; }
.wr-prog { display: grid; gap: 8px; margin-top: 12px; }
.wr-prog .hint { margin: 0; }
.wr-walk .flags { margin-top: 12px; }
.wr-walk .flags > li { grid-template-columns: 18px minmax(0, 1fr) auto; align-items: center; }
.wr-tools .select-wrap .select { height: 34px; font-size: 12.5px; }
.mo-band { overflow: hidden; }
.mo-band > .mo-top { margin-bottom: 0; }
.mo-band > .mo-top .hint { margin: 2px 0 0; }
.mo-wg { border-top: 1px solid var(--hair); }
.wr-t th.wr-st, .wr-t td.wr-st { min-width: 136px; text-align: left; scroll-snap-align: start; }   /* a phone's month snap must not skip past it */
.wr-t td.m { padding: 0 4px; }
.wr-c { all: unset; box-sizing: border-box; cursor: pointer; display: flex; flex-direction: column; align-items: flex-end; justify-content: center; gap: 1px;
  width: 100%; min-height: calc(var(--wg-row-h) - 10px); padding: 4px 6px; border-radius: 8px; transition: background var(--t-quick); }
.wr-c:hover { background: var(--well); }
.wr-c:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.wr-c.moved { box-shadow: inset 0 0 0 1px var(--hair-2); }
.wr-v { display: inline-flex; align-items: center; gap: 5px; font-weight: 650; color: var(--ink); }
.wr-v.zero { color: var(--faint); font-weight: 500; }
.wr-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }   /* the month has notes */
.wr-d { font-size: 11px; font-weight: 750; font-variant-numeric: tabular-nums; white-space: nowrap; }
.wr-d.up { color: var(--ok); } .wr-d.down { color: var(--bad); }
.wr-sug { font-size: 10.5px; font-weight: 700; color: var(--warn); }   /* ticketed past the forecast: a suggestion, never applied by itself */
.wr-t tr.wr-focus th, .wr-t tr.wr-focus td { background: var(--info-bg); }
.wr-t tr.wr-focus .first { box-shadow: inset 3px 0 0 var(--accent), 1px 0 0 var(--hair-2); }
.wr-notes { all: unset; cursor: pointer; color: var(--accent-ink); font-weight: 650; }
.wr-notes:hover, .wr-notes:focus-visible { text-decoration: underline; }
.wr-last { display: block; font-size: 11.5px; font-style: italic; color: var(--muted); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }   /* the latest note resurfaces on its row */
.wr-sec { display: grid; gap: 8px; }
.wr-sec h3 { margin: 0; font-size: 13.5px; font-weight: var(--fw-bold); }
.wr-sec > .hint { margin: 0; }
.mo-list { list-style: none; margin: 0; padding: 0; display: grid; }
.mo-list > li { display: grid; gap: 3px; padding: 8px 0; border-top: 1px solid var(--hair); font-size: 13px; min-width: 0; overflow-wrap: anywhere; }
.mo-list .hint { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; }
.wr-h-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.mo-list > li.wr-sys { color: var(--muted); }
.wg-sheet .wr-in { width: 112px; }
.wg-sheet .wg-list, .wg-sheet .wg-list :is(th, td) { background: transparent; }
.wg-list :is(th, td) + :is(th, td) { padding-left: 12px; }   /* two right-aligned headings never touch */   /* 2.x styles.css paints table cells white; the sheet is glass */
.wr-sec .field > .select-wrap { align-self: flex-start; }        /* a status dropdown is as wide as its words, not the sheet */
.wg-sheet .mo-line { grid-template-columns: minmax(0, 1fr) auto; }   /* the sheet is narrow: the words drop under the label */
.wg-sheet .mo-line-m { grid-column: 1 / -1; grid-row: 2; }
.wg-sheet .flags > li { grid-template-columns: 18px minmax(0, 1fr); }
.wg-sheet .flags li > .mo-chips { grid-column: 2; }
/* Present: bigger type and the menu folded, for the screen shared in the meeting */
.wr-present .mo-wg { --wg-font: 15px; --wg-row-h: 62px; --wg-first: 320px; --wg-cell: 132px; }
.wr-present .wr-d, .wr-present .mo-wg .wg-mtd { font-size: 12.5px; }
@media (max-width: 640px) {
  .wr-t th.wr-st, .wr-t td.wr-st { min-width: 120px; }
  .wr-last { display: none; }
  .wr-walk .flags > li { grid-template-columns: 18px minmax(0, 1fr); }
  .wr-walk .flags li > .mo-chips { grid-column: 2; }
  .wr-tools .wg-chips { flex: 1 1 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }   /* three chips, one row: no orphan (review 10/22) */
  .wr-tools .wg-chip { padding: 0 6px; line-height: 1.2; }
  .wr-walk .actions { width: 100%; }   /* the walk's buttons: Next across, the three small ones in a row, the close across (review 10/22) */
  .wr-walk .actions > .btn { flex: 1 1 0; justify-content: center; }
  .wr-walk .actions > [data-wr="next"], .wr-walk .actions > .btn.primary { flex-basis: 100%; }
  .wr-tools > .select-wrap { flex: 1 1 100%; }
  .wr-tools > .select-wrap .select { width: 100%; }
}
@media print { .mo-wg .wg-scroll { max-height: none; overflow: visible; } }
/* ---------------- Momentum › Pipeline (pn-) — Accounts, Bids by month, Weighted — public/momentum.js (3.0) ----------------
   The kit's strip, status dropdowns, list table → phone cards, and the wide grid (bids by month, in a .mo-band) do the work. */
.pn-t td { vertical-align: middle; }
.pn-name { min-width: 180px; max-width: 320px; white-space: normal; }
.pn-note { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 300px; }
.pn-pot { width: 13ch; height: 32px; padding: 0 8px; }
.pn-card .mo-top { align-items: flex-start; }
.pn-card .pn-pot { width: 100%; }
@media (max-width: 1180px), (pointer: coarse) { .pn-pot { height: var(--tap); } }
@media (max-width: 640px) {
  .pn-tools > .select-wrap { flex: 1 1 100%; }
  .pn-tools > .select-wrap .select { width: 100%; }
}

/* ---------------- Momentum › Budgets (bu-) — P&L workbook, Revenue targets, SG&A — public/momentum.js and spend-momentum.js (3.0) ---------------- */
.bu-year { display: inline-flex; align-items: center; gap: 4px; }
.bu-year .input { width: 76px; height: 34px; text-align: center; font-weight: var(--fw-bold); }
.bu-tools .hint a { font-weight: var(--fw-semi); }
.bu-why .input { width: min(340px, 60vw); height: 34px; }
.mo-band .bu-t td.m { min-width: 108px; }
.bu-months { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 6px; margin-top: 4px; }
.bu-month { display: grid; gap: 2px; padding: 8px 6px; border-radius: var(--r-m); border: 1px solid var(--hair); color: var(--ink); text-decoration: none; text-align: center; font-variant-numeric: tabular-nums; }
.bu-month b { font-size: 12.5px; }
.bu-month span { font-size: 11.5px; color: var(--muted); }
.bu-month:hover { background: var(--well); text-decoration: none; }
.bu-month.now { border-color: var(--accent); }
.bu-month.on { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.bu-month.on span { color: var(--on-ink); opacity: .75; }
.bu-sga { align-items: start; }
.bu-card { display: grid; gap: 10px; }
.bu-card h3 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.bu-card .mo-top { margin: 0; align-items: baseline; }
.bu-card > .hint { margin: 0; }
.bu-fields { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 150px); gap: 10px; }
.bu-cal { display: grid; gap: 4px; }
.bu-cal-h, .bu-week { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)) minmax(0, 1.2fr); gap: 4px; }
.bu-cal-h span { font-size: 11px; font-weight: var(--fw-semi); color: var(--muted); text-align: center; }
.bu-week { all: unset; box-sizing: border-box; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)) minmax(0, 1.2fr); gap: 4px; padding: 3px; border-radius: var(--r-m); }
button.bu-week { cursor: pointer; }
button.bu-week:hover { background: var(--well); }
button.bu-week:focus-visible { outline: 2px solid var(--ink); }
.bu-day { display: grid; gap: 1px; padding: 5px 4px; border-radius: 8px; background: var(--well); text-align: center; min-width: 0; }
.bu-day i { font-style: normal; font-size: 10.5px; color: var(--muted); }
.bu-day em { font-style: normal; font-size: 11.5px; font-weight: var(--fw-semi); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; }
.bu-day.out { background: transparent; }
.bu-day.wk { background: transparent; border: 1px dashed var(--hair-2); }
.bu-week.set .bu-day.wk { border-style: solid; border-color: var(--accent); }
.bu-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.bu-copy { border: 0; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.bu-tick { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; min-height: 32px; }
.bu-tick input { width: 18px; height: 18px; }
.bu-sec { margin: 6px 0 0; font-size: 13.5px; font-weight: var(--fw-bold); }
.bu-unithead { margin-top: 6px; align-items: center; }
.bu-unithead h3 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.bu-rev { grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 4px 0; }
.bu-hist { list-style: none; margin: 0; padding: 0; display: grid; }
.bu-hist > li { display: grid; gap: 4px; padding: 10px 0; border-top: 1px solid var(--hair); }
.bu-hist > li:first-child { border-top: 0; }
.bu-hist > li.on { box-shadow: inset 3px 0 0 var(--ok); padding-left: 12px; }
.bu-hist-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.bu-hist > li > p { margin: 0; }
.bu-choose { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.bu-pv { display: grid; gap: 10px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--hair); }
.bu-file { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.bu-ul { margin: 6px 0 0; padding-left: 18px; display: grid; gap: 3px; }
.bu-chg { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 2px 12px; align-items: baseline; }
.bu-note textarea.bu-need { border-color: var(--bad); box-shadow: 0 0 0 3px var(--bad-bg); }
.bu-acts { align-items: center; }
.fp-pick { align-items: flex-start; }   /* the labels level whatever control sits under each (review 10/22) */
.fp-pf { display: grid; gap: 4px; min-width: 0; }
.fp-pf .select { min-width: 220px; height: 34px; font-size: 13px; }
@media (max-width: 980px) { .bu-months { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  .bu-months { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .bu-fields { grid-template-columns: minmax(0, 1fr); }
  .bu-rev { grid-template-columns: minmax(0, 1fr); }
  .bu-chg { grid-template-columns: minmax(0, 1fr) auto; }
  .bu-chg > span:first-child { grid-column: 1 / -1; }
  .bu-copy { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fp-pf { flex: 1 1 100%; }
  .fp-pf .select { min-width: 0; width: 100%; }
  .bu-why .input { width: 100%; }
}
.bu-odd > .bu-card:last-child { grid-column: 1 / -1; }   /* an odd count of branches: the last card takes the row, never an orphan */

/* ---------------- Momentum › Hours & Costs (hc-) — public/momentum.js (3.0) ---------------- */
table.t .hc-split { width: 16%; min-width: 90px; }
.hc-form { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 12px; }
.hc-form .hc-wide { grid-column: 1 / -1; }
.hc-grid tr.hc-wknd th, .hc-grid tr.hc-wknd td { color: var(--muted); }
.hc-grid td.m { min-width: 76px; }
@media (max-width: 980px) { .hc-form { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .hc-form { grid-template-columns: minmax(0, 1fr); } }
/* Momentum › Forecast › Plan & pace (pp-), the money roles' panel under the grid */
.fc-plan { display: flex; flex-direction: column; gap: var(--gap); }
.fc-plan h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.pp-h { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
table.t tr.pp-first td { border-top: 2px solid var(--hair-2); }

/* ---------------- Company · shared (cy-, mf-) — a customer's delivery view (shared.js renderCustomer360: Ignite's customer
   page and Apex's Ignite tab) and an MSA's revenue forecast card (msa-forecast.js: Apex's MSA page and Ignite's hub). Both are
   drawn in two products, so their looks live here rather than in a product sheet (3.0, Apex rebuild 10/22). */
.cy { display: grid; gap: var(--gap); min-width: 0; }
.cy-sec { display: grid; gap: 12px; padding: 14px 16px; min-width: 0; }
.cy-sec h2, .mf h2 { margin: 0; font-size: var(--fs-l); display: inline-flex; align-items: center; gap: 8px; }
.cy-sec h2 .hint { font-weight: var(--fw-med); }
.cy-sec.cy-card { padding: 0 0 6px; gap: 0; overflow: hidden; }
.cy-sec.cy-card > .cy-pad { padding: 14px 16px 6px; }
.cy-card table.t th:first-child, .cy-card table.t td:first-child { padding-left: 16px; }
.cy-card table.t th:last-child, .cy-card table.t td:last-child { padding-right: 16px; }
.cy-sec p, .mf p { margin: 0; }
.cy-arch td { color: var(--muted); }   /* faded (K5): see "faded rows" */
.mf { display: grid; gap: 12px; padding: 14px 16px; min-width: 0; }
.mf-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px 16px; }
.mf-years { display: inline-flex; align-items: center; gap: 8px; }
.mf-form { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 12px; }
.mf-in { width: 130px; height: 32px; margin-left: auto; }
.mf-t tr.mf-now td { box-shadow: inset 3px 0 0 var(--accent); }
.mf-t tr.mf-now td + td { box-shadow: none; }
.mf-t tr.mf-tot td { border-top: 1px solid var(--hair-2); }
.mf-foot { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 10px 12px; }
.mf-foot .field { min-width: 220px; }
@media (max-width: 1180px), (pointer: coarse) { .mf-in { height: var(--tap); } }
@media (max-width: 640px) { .mf-form { grid-template-columns: minmax(0, 1fr); } .mf-in { width: 110px; } .mf-foot > .btn { flex: 1 1 100%; justify-content: center; } }

/* ---------------- Momentum › Flash P&L (fp-) — public/spend-momentum.js (3.0) ----------------
   One row per cost line. Wide: the name in its own column so every bar starts at the same x — the 100% ticks and the
   revenue markers line up down the list. The bar runs 0–200%: --spent, --pend and --rev are positions on that scale (data). */
.fp-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; font-size: 12px; color: var(--muted); margin: 4px 0 6px; }
.fp-legend > span { display: inline-flex; align-items: center; gap: 6px; }
.fp-k { display: inline-block; width: 12px; height: 10px; border-radius: 3px; flex: none; }
.fp-k-spent { background: var(--ink-2); }
.fp-k-pend { background: var(--ink-2); opacity: .3; }
.fp-k-tick { width: 2px; height: 12px; border-radius: 0; background: var(--ink); }
.fp-k-rev { width: 0; height: 14px; border-radius: 0; border-left: 2px solid var(--info); }
.fp-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.fp-row { display: grid; grid-template-columns: minmax(140px, 220px) minmax(0, 1fr) 190px; grid-template-areas: "name figs pill" "name bar pill" ". why why" ". src src";
  gap: 3px 16px; align-items: center; padding: 12px 0; border-top: 1px solid var(--hair); }
.fp-row:first-child { border-top: 0; }
.fp-name { grid-area: name; align-self: start; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.fp-namebtn { all: unset; font-weight: var(--fw-bold); color: var(--ink); cursor: pointer; }
button.fp-namebtn:hover, button.fp-namebtn:focus-visible { text-decoration: underline; }
span.fp-namebtn { cursor: default; }
.fp-pill { grid-area: pill; justify-self: end; }
.fp-figs { grid-area: figs; margin: 0; font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.fp-fig { font-weight: var(--fw-semi); }
.fp-why { grid-area: why; margin: 2px 0 0; font-size: 12.5px; color: var(--muted); }
.fp-src { grid-area: src; margin: 0; font-size: 12px; color: var(--muted); font-style: italic; }
.fp-none .fp-figs, .fp-none .fp-why { grid-column: 2 / -1; }
.fp-none { grid-template-areas: "name figs figs" "name why why"; }
.fp-bar { grid-area: bar; position: relative; height: 10px; border-radius: var(--r-pill); background: var(--well); box-shadow: inset 0 1px 2px rgba(16,24,40,.12); }
.fp-bar > .fp-s { position: absolute; left: 0; top: 1px; bottom: 1px; width: var(--spent, 0%); border-radius: var(--r-pill); background: linear-gradient(180deg, var(--water-a), var(--water-b)); }
.fp-bar.ok > .fp-s { background: linear-gradient(180deg, var(--water-ok-a), var(--water-ok-b)); }
.fp-bar.warn > .fp-s { background: linear-gradient(180deg, var(--water-warn-a), var(--water-warn-b)); }
.fp-bar.bad > .fp-s { background: linear-gradient(180deg, var(--water-bad-a), var(--water-bad-b)); }
.fp-bar > .fp-p { position: absolute; left: var(--spent, 0%); top: 1px; bottom: 1px; width: var(--pend, 0%); background: var(--ink-2); opacity: .22; border-radius: 0 var(--r-pill) var(--r-pill) 0; }
.fp-bar > .fp-t { position: absolute; left: 50%; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--ink); border-radius: 2px; }
.fp-bar > .fp-r { position: absolute; left: var(--rev, 0%); top: -5px; bottom: -5px; width: 0; border-left: 2px solid var(--info); }
.fp-bar > .fp-r.cal { border-left-style: dashed; }
.fp-over { position: absolute; right: -14px; top: 50%; transform: translateY(-50%); font-size: 14px; color: var(--bad); }
.fp-foot { margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--hair); }
table.t tr.fp-off td { color: var(--muted); }
@media (max-width: 760px) {
  .fp-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name pill" "figs figs" "bar bar" "why why" "src src"; }
  .fp-none { grid-template-areas: "name name" "figs figs" "why why"; }
  .fp-none .fp-figs, .fp-none .fp-why { grid-column: 1 / -1; }
  .fp-bar { margin: 6px 16px 4px 0; }
}
.pj-how { display: grid; gap: 6px; }   /* Projected P&L: how it is built, said once */
.flags li .pj-how > .src { grid-column: auto; }   /* .flags li .src pins a source link to the flag's text column; inside this stack it is one more line */
.cy-list { margin: 0; padding-left: 18px; display: grid; gap: 4px; font-size: 13px; }   /* Company · shared: a short list in a panel (an MSA's minimum charges) */
.ih-row.cy-filters { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }   /* Company · shared: the customer list's six filters
   sit as even cells, 3 + 3, then 2 + 2 + 2, then 1 — never five and an orphan */
.ih-row.cy-filters > * { min-width: 0; }
.ih-row.cy-filters .ih-link { grid-column: 1 / -1; justify-self: start; }
@media (max-width: 980px) { .ih-row.cy-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .ih-row.cy-filters { grid-template-columns: minmax(0, 1fr); } }

/* ---------------- Momentum planning and money screens: tap reach and small fixes (design review 10/22) ----------------
   The month cells, the cost-line names, the wide grid's names, totals and sort headings, the review's chips and notes, a
   year link: 44px on touch, reached with a ::before (the sort heading's ::after is its arrow). */
@media (max-width: 1180px), (pointer: coarse) {
  .wr-c { min-height: var(--tap); }
  .wg-chip { height: var(--tap); }
  .mo-more > summary { padding-block: 13px; }
  :is(.wg-name, .wg-drill, .wg-sort, .fp-namebtn, .wr-notes, .bu-tools .hint a) { position: relative; }
  :is(.wg-name, .wg-drill, .wg-sort, .fp-namebtn, .wr-notes, .bu-tools .hint a)::before { content: ""; position: absolute; inset: min(0px, calc(50% - var(--tap) / 2)) 0; }
  .wg-meta :is(a, button) { position: relative; z-index: 1; }
}
@media (max-width: 640px) { .fp-legend { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } }   /* four legend keys as 2 + 2, never 3 + 1 */
/* the forecast grid on touch (wave 17, w17fleetmo's call): a row of 64px, so a job's name and the line of doors under it
   (its customer, its job number, its MSA) each sit in their own 32px half with room for a thumb; phones hide that line */
@media ((max-width: 1180px) and (min-width: 641px)), ((pointer: coarse) and (min-width: 641px)) {
  .wg:not(.compact) { --wg-row-h: 64px; }
}
/* …and a group's own row (a branch, a customer — its name a door to the record) is a thumb's height on touch: at 34px
   the sticky cells above and below covered its 44px reach, and "Houston" reached 27 (wave 17) */
@media (max-width: 1180px), (pointer: coarse) { .wg-t .grp th, .wg-t .grp td { height: var(--tap); } }

/* ---------------- Settings › Company (sco-) — the Company group's tabs in public/settings.js (3.0) ----------------
   Logins (Backoffice · Branches · Roles & access · Crews), Company & Backups (Company & addresses · Backups & security ·
   Privacy requests), Export & Import, Activity Log, API Tokens, Mail, Plugins, Trash, Duplicate Accounts, Chat, Sales
   Goals. Panels are the frame's .stg-card; a list is a .phone-cards panel whose table becomes cards on a phone (the busy
   ones, .sco-c980, already at 980); a tab's parts are link tabs (.subtabs). */
.sco-parts { margin-top: -4px; }
.sco-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px 16px; }
.sco-head > .stg-card-head { flex: 1 1 320px; min-width: 0; }
.sco-head > .actions { align-items: center; }
.sco-h3 { margin: 4px 0 0; font-size: 13.5px; font-weight: var(--fw-x); }
.sco-lab { font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.sco-big { font-size: 20px; font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.sco-pre { white-space: pre-wrap; margin: 0; }
.sco-pre:empty { display: none; }
.sco-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.sco-wrap { white-space: normal; min-width: 140px; }
.sco-name { display: inline-flex; align-items: center; gap: 6px; font-weight: var(--fw-semi); }
.sco-name + .hint { display: block; margin-top: 2px; }
.sco-who { color: inherit; text-decoration: none; } .sco-who:hover > .who > span:last-child { text-decoration: underline; }
.sco-note { padding: 10px 12px; border-radius: var(--r-m); background: var(--well); border: 1px solid var(--hair-2); font-size: 13px; color: var(--ink-2); }
.sco-note.warn { background: var(--warn-bg); border-color: var(--warn-line); }
.sco-note.bad { background: var(--bad-bg); border-color: var(--bad-line); }
.sco-note.ok { background: var(--ok-bg); border-color: var(--ok-line); }
.sco-note.info { background: var(--info-bg); border-color: var(--info-line); }
.sco-note b { color: var(--ink); }
.sco-warnpanel { box-shadow: inset 4px 0 0 var(--warn), var(--shadow); }
/* rows inside a panel: a title and its line on the left, its buttons on the right */
.sco-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.sco-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 14px; padding: 12px 0; border-top: 1px solid var(--hair); }
.sco-rows > .sco-row:first-child { border-top: 0; padding-top: 0; }
.sco-row-t { flex: 1 1 280px; min-width: 0; display: grid; gap: 2px; }
/* Settings › Logins › Logins to tie (w23safety): on a phone the person picker and its Tie button share one line — the picker
   takes the room, Tie keeps its size — so Tie never wraps under the picker alone (w23safety's design review, 10/27) */
@media (max-width: 640px) {
  .sco-tiep .sco-acts:has(> .select-wrap) { flex: 1 1 100%; flex-wrap: nowrap; }
  .sco-tiep .sco-acts > .select-wrap { flex: 1 1 auto; min-width: 0; }
  .sco-tiep .sco-acts > .select-wrap > .select { width: 100%; }
}
/* lists: the table on a computer, cards on a phone (kit .phone-cards); the busy ones turn to cards at 980 */
.sco-list > .pad { padding-bottom: 6px; }
.sco-list .cards { gap: 8px; }
.sco-card { display: grid; gap: 6px; min-width: 0; }
.sco-card-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 10px; }
.sco-card .hint { overflow-wrap: anywhere; }
.sco-stat { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.sco-tag { display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.sco-chipbtn { border: 0; cursor: pointer; font: inherit; font-size: 11.5px; font-weight: var(--fw-semi); }
.sco-lgt td { vertical-align: top; }
.sco-lgt td .select-wrap { vertical-align: middle; }
@media (max-width: 980px) {
  .sco-c980 table.t { display: none; }
  .sco-c980 .cards { display: flex; flex-direction: column; gap: 8px; }
}
/* Company & addresses: each branch's letterhead is a row — its name, four boxes, Save; headings once, above the rows */
.sco-lhs, .sco-brs { list-style: none; margin: 0; padding: 0; display: grid; }
.sco-lh { display: grid; grid-template-columns: minmax(150px, 1fr) minmax(0, 4.4fr) auto; gap: 8px 14px; align-items: end; padding: 12px 0; border-top: 1px solid var(--hair); }
.sco-lhs > .sco-lh:first-child { border-top: 0; padding-top: 0; }
.sco-lh-name { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; align-self: center; min-width: 0; }
.sco-lh-f { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1.2fr); gap: 8px 10px; }
.sco-lh-warn { grid-column: 1 / -1; margin: -2px 0 0; }
@media (max-width: 1180px) {
  .sco-lh { grid-template-columns: minmax(0, 1fr) auto; }
  .sco-lh-name { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; align-items: center; }
  .sco-lh-f { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .sco-lh { grid-template-columns: minmax(0, 1fr); }
  .sco-lh-f { grid-template-columns: minmax(0, 1fr); }
  .sco-lh-go .btn { width: 100%; justify-content: center; }
}
/* Logins › Branches: one row a branch — name, code, region, family, the Branch Mgr seat, the status */
.sco-br { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, .7fr) minmax(0, .8fr) minmax(0, 1fr) minmax(0, 1.5fr) auto; gap: 8px 12px; align-items: end; padding: 12px 0; border-top: 1px solid var(--hair); }
.sco-brs > .sco-br:first-child { border-top: 0; padding-top: 0; }
.sco-br.sub .sco-br-name { padding-left: 18px; position: relative; }
.sco-br.sub .sco-br-name::before { content: "↳"; position: absolute; left: 2px; bottom: 10px; color: var(--muted); }
.sco-br-ro { display: flex; align-items: center; min-height: var(--ctl); }
.sco-seat { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-height: var(--ctl); justify-content: center; }
.sco-br .status { margin-bottom: 4px; }
@media (max-width: 1180px) {
  .sco-br { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sco-br-name { grid-column: span 2; }
}
@media (max-width: 640px) {
  .sco-br { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sco-br-name, .sco-br-seat { grid-column: 1 / -1; }
}
.sco-add { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 10px; padding-top: 12px; border-top: 1px solid var(--hair); }
.sco-add .field { flex: 0 1 300px; min-width: 0; }
@media (max-width: 640px) { .sco-add .field { flex-basis: 100%; } .sco-add .btn { width: 100%; justify-content: center; } }
.sco-ticks { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 0 14px; max-height: 260px; overflow-y: auto; padding: 4px 2px; }
.sco-ticks > b { grid-column: 1 / -1; font-size: 12.5px; padding: 4px 0; }
.sco-ticks .stg-check, .sco-ticks .stg-check:first-child { padding: 7px 2px; border-top: 0; align-items: center; }
.sco-ticks .stg-check.sub { padding-left: 18px; }
.sco-brticks { border: 1px solid var(--hair-2); border-radius: var(--r-m); padding: 4px 10px; background: var(--glass-a); }
/* the branch ticks read down each column, so a parent's sub-branches sit under it (across, "Landshark" landed beside
   "Houston CCTV" and "TGREY" on the next row), in as many columns as leave no short last row: settings.js
   SCO_branchTicks sets --sco-cols and --sco-rows from the count (14 branches: 2 × 7, where 3 across went 3+3+3+3+2 — K7) */
.sco-brticks { grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: minmax(0, 1fr); grid-template-rows: repeat(var(--sco-rows, 7), auto); max-height: none; }
@media (max-width: 640px) { .sco-brticks { grid-auto-flow: row; grid-template-rows: none; grid-template-columns: minmax(0, 1fr); max-height: 300px; } }   /* a phone: one column, read down */
/* Roles & access: a grid stays a grid — it scrolls inside its panel, the capability column held still */
.sco-access .table-wrap { max-height: calc(100vh - 220px - var(--tn-stuck)); }
.sco-access table.t th, .sco-access table.t td { padding: 8px 10px; }
.sco-access thead th { position: sticky; top: 0; z-index: 2; background: var(--surface); }
.sco-capcol { position: sticky; left: 0; z-index: 1; background: var(--surface); min-width: 240px; max-width: 320px; white-space: normal; }
.sco-access thead .sco-capcol { z-index: 3; }
.sco-capcol .hint { display: block; margin-top: 2px; font-size: 11.5px; }
.sco-tc { text-align: center; }
.sco-tc input { width: 18px; height: 18px; accent-color: var(--ink); }
.sco-access .sco-grp th { position: sticky; left: 0; background: var(--surface-2); font-size: 12px; color: var(--ink-2); }
@media (max-width: 640px) { .sco-capcol { min-width: 170px; max-width: 200px; } }
/* Logins: how logins work, in four short parts (2 + 2, then one column) */
.sco-notes h3 { margin: 0 0 4px; font-size: 13.5px; font-weight: var(--fw-x); }
.sco-notes p { margin: 0; }
/* Backups & security */
.sco-meter { display: grid; gap: 8px; }
.sco-meter-t { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; margin: 0; }
.sco-strip { border: 1px solid var(--hair); border-radius: var(--r-l); }
.sco-strip .value { font-size: 20px; }
.sco-dl { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 16px; align-items: center; padding-top: 14px; border-top: 1px solid var(--hair); }
.sco-dl p { margin: 2px 0 0; }
.sco-dl-key { grid-column: 1 / -1; }
@media (max-width: 640px) { .sco-dl { grid-template-columns: minmax(0, 1fr); } .sco-dl .sco-acts .btn { flex: 1 1 100%; justify-content: center; } }
.sco-ofs { display: grid; gap: 8px; padding-top: 12px; border-top: 1px solid var(--hair); }
.sco-ofs:empty { display: none; }
.sco-ofs p { margin: 0; }
.sco-ofs-row { display: grid; gap: 6px; }   /* where it went, then the key's fingerprint (w17-offsite-backup) */
.sco-lkd-t { display: flex; flex-direction: column; gap: 8px; }
.sco-lkd-t > p { margin: 0; }
.sco-lkd-t > p:not(:last-child) { flex: 1 1 auto; }   /* the controls and the last line sit level in all three */
.sco-lkd-t.on { border-color: var(--bad-line); box-shadow: inset 0 0 0 1px var(--bad-line); }
.sco-lkd-c { min-height: var(--ctl); display: flex; align-items: center; }
.sco-prv-out { display: grid; gap: 10px; }
.sco-prv-out:empty { display: none; }
.sco-prv-out .phone-cards { border: 1px solid var(--hair); border-radius: var(--r-l); }
.sco-prv-out p { margin: 0; }
/* pop-ups: the kit's look inside the app's .modal */
.sco-modal { display: grid; gap: 14px; }
.sco-modal h2 { margin: 0; font-size: var(--fs-xl); }
.sco-modal p { margin: 0; }
.sco-modalbox { max-width: 560px; }
.modal:has(> .sco-lgm) { max-width: 680px; }
.modal:has(> .sco-pw) { max-width: 480px; }
.sco-modalacts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.sco-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; }
.sco-form > :last-child:nth-child(odd) { grid-column: 1 / -1; }   /* an odd last field takes the row (K7: Branch defaults went 2 + 2 + 1) */
@media (max-width: 640px) { .sco-form { grid-template-columns: minmax(0, 1fr); } .sco-modalacts .btn { flex: 1 1 0; justify-content: center; } }
.sco-copy { display: flex; gap: 8px; }
.sco-copy > .btn { height: 44px; }   /* Copy beside the 44px code box, one height (r2layout: 36 beside 44) */
.sco-copy .input { flex: 1 1 auto; min-width: 0; font: var(--fw-bold) 17px ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .02em; text-align: center; height: 44px; }
.sco-danger { display: grid; gap: 8px; padding: 12px; border-radius: var(--r-m); border: 1px solid var(--hair-2); background: var(--well); }
.sco-pick { border: 0; margin: 0; padding: 0; display: grid; }
.sco-pick legend { padding: 0 0 4px; font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.sco-prev { display: grid; gap: 6px; margin-bottom: 8px; }
table.t.sco-mini th, table.t.sco-mini td { padding: 5px 8px; }
.sco-ho ul { margin: 4px 0 0; padding-left: 18px; max-height: 170px; overflow: auto; font-size: 13px; }
/* Settings › Estimating › Branch Metrics (wave 17): a branch's figures, four to a row → two → one; a changed one is marked */
.bm-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 16px; }
@media (max-width: 1100px) { .bm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .bm-grid { grid-template-columns: minmax(0, 1fr); } }
/* w46b — the step rail: the crew ticket's numbered steps as a reusable strip (the PFS's five steps and its Summary). One <ol> of
   buttons; each says its number (a tick once done, "!" when something needs a look), its name and a short count under it. Six
   steps are six across, then three and three on a phone: never five and a stray one. */
.step-rail { list-style: none; margin: 0; padding: 6px; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; }
.step-rail > li { display: flex; min-width: 0; }
.step-rail button { width: 100%; display: grid; justify-items: center; align-content: start; gap: 3px; padding: 8px 4px 7px; border: 0; border-radius: var(--r-m); background: transparent; color: var(--muted); font: inherit; cursor: pointer; transition: background var(--t-quick), color var(--t-quick); }
.step-rail button:hover { background: var(--well); }
.step-rail .step-n { width: 28px; height: 28px; border-radius: 50%; display: inline-grid; place-items: center; border: 1.5px solid var(--hair-2); font-size: 12px; font-weight: var(--fw-bold); }
.step-rail .step-n .i { width: 14px; height: 14px; }
.step-rail .step-name { font-size: 13px; font-weight: var(--fw-semi); color: var(--ink-2); text-align: center; line-height: 1.15; }
.step-rail .step-sub { font-size: 11.5px; color: var(--faint); text-align: center; line-height: 1.2; }
.step-rail button.done .step-n { background: var(--ok-bg); border-color: var(--ok-line); color: var(--ok); }
.step-rail button.warn .step-n { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn); }
.step-rail button.now { background: var(--well); }
.step-rail button.now .step-n { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.step-rail button.now .step-name { color: var(--ink); }
@media (max-width: 560px) { .step-rail { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-columns: auto; } }
/* w46b — no orphans in a figures grid. A last cell that would sit alone in its row takes the rest of it, at every width the grid has
   (4 across, 2 across, 3 across): 11 company standards read 4 · 4 · 3 with the last wide, never 4 · 4 · 3 and a hole.
   w47: each rule lives only at the widths its column count exists. The four-across spans were written bare and then "reset" under
   1100px by a rule of LOWER weight, so at 820 and below they still won: 14 cells came out 3 · 3 · 3 · 3 · 1 · 1 in a two-column
   grid, and on a phone five fields were 0px wide. A rule that only applies where it is true needs no reset. */
@media (min-width: 1101px) {
  .bm-grid > :last-child:nth-child(4n + 1) { grid-column: span 4; }
  .bm-grid > :last-child:nth-child(4n + 2) { grid-column: span 3; }
  .bm-grid > :last-child:nth-child(4n + 3) { grid-column: span 2; }
}
@media (min-width: 561px) and (max-width: 1100px) {
  .bm-grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}
/* w47 — the PFS headline: six figures, drawn once for the Summary, the job screen's peek and the approver's panel (Apex and My Approvals in every
   workspace). Three across, then two, then two on a phone: never one tall column and never an orphan. A loss (.bad) is red wherever it is drawn. */
.strip.three.six { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.strip.six .value { font-size: var(--fs-num); font-variant-numeric: tabular-nums; }
.strip.six .value.bad { color: var(--bad); }
@media (max-width: 980px) { .strip.three.six { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .strip.six .value { font-size: 20px; } .strip.six > * { padding: 12px 14px 14px; } }
/* w47 — Settings › PFS Standards: what an upload would change, the note about branches, then its buttons: one gap apart (they sat 8px from each other) */
.pfs-std-prev { display: grid; gap: 12px; }
.pfs-std-prev > p, .pfs-std-prev > ul, .pfs-std-prev > .actions { margin: 0; }
/* three across (the thresholds: three figures), then one: never two and an orphan */
.bm-grid.bm-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.bm-grid.bm-3 > :last-child { grid-column: auto; }
@media (max-width: 760px) { .bm-grid.bm-3 { grid-template-columns: minmax(0, 1fr); } }
/* a label that wraps in one cell must not lower that cell's box: boxes sit on the cell's foot, labels keep the top */
.bm-grid.bm-align > .bm-f { display: flex; flex-direction: column; justify-content: space-between; gap: 4px; }
.bm-f.bm-changed .input { border-color: var(--warn-line); background: var(--warn-bg); }
/* a long word in a strip's note (a file name) breaks inside its cell instead of running under the next */
.strip .hint { overflow-wrap: anywhere; }
/* a cell of a table that must not break (a date, a version) and one that may break anywhere (a file name) */
td.nw, th.nw { white-space: nowrap; }
td.brk, th.brk { overflow-wrap: anywhere; word-break: break-word; }
.bm-f .hint .btn { margin-left: 2px; }
/* D12 (wave 17): the hand-off's open work, one kind at a time — each with its own picker under its list */
.sco-ho-h { margin: 18px 0 8px; font-size: 15px; }
.sco-ho + .sco-ho { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hair); }
.sco-ho > .field { margin: 8px 0 0; }
@media (max-width: 1180px), (pointer: coarse) { .sco-tc input { width: 22px; height: 22px; } .sco-chipbtn { min-height: var(--tap); } }
[data-theme="dark"] .sco-access thead th, [data-theme="dark"] .sco-capcol { background: var(--surface); }
.sco-lgt .sco-acts { flex-wrap: nowrap; }
a.sco-rec { color: inherit; text-decoration: underline; text-decoration-color: var(--hair-2); text-underline-offset: 3px; }
a.sco-rec:hover { color: var(--accent-ink); text-decoration-color: currentColor; }
/* the column headings of the branch and letterhead rows: drawn once above them where the rows are one line (1181 and up),
   and each box keeps its own label (read aloud there, shown under 1181 where the row breaks up) */
.sco-colh { display: none; }
@media (min-width: 1181px) {
  .sco-br { grid-template-columns: minmax(0, 1.5fr) minmax(0, .7fr) minmax(0, .8fr) minmax(0, 1fr) minmax(0, 1.5fr) 200px; }
  .sco-colh { display: grid; padding: 0 0 6px; border-top: 0; font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); align-items: end; }
  .sco-colh .sco-lh-f { display: grid; }
  .sco-brs > .sco-colh + .sco-br, .sco-lhs > .sco-colh + .sco-lh { border-top: 0; padding-top: 4px; }
  .sco-br:not(.sco-colh) .field > :is(label, .sco-lab):first-child, .sco-lh:not(.sco-colh) .sco-lh-f .field > label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .sco-br, .sco-lh { align-items: center; }
}
.sco-br .field > .select-wrap:not(.block), .sco-lkd-c > .select-wrap { align-self: flex-start; }
:is(.sco-list, .sco-access) .stg-card-head h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
:is(.sco-list, .sco-access) .stg-card-head p { margin: 0; }
/* Export & Import */
.stg-card > .sco-foot { margin-top: auto; }   /* a panel's buttons sit on its bottom edge, level with its neighbour's */
.sco-cols { display: flex; flex-wrap: wrap; gap: 4px; }
.sco-cols code { font-size: 11.5px; padding: 2px 6px; border-radius: 6px; background: var(--well); }
.sco-cdres:empty { display: none; }
.sco-dates { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; flex: 1 1 100%; }
.sco-drop { display: grid; justify-items: center; gap: 4px; padding: 26px 16px; border: 1.5px dashed var(--hair-2); border-radius: var(--r-l); background: var(--glass-a); text-align: center; cursor: pointer;
  transition: border-color var(--t-quick), background var(--t-quick); }
.sco-drop:hover, .sco-drop.over, .sco-drop:focus-within { border-color: var(--ink); background: var(--well); }
.sco-bmi-out:empty { display: none; }
.sco-bmi { display: grid; gap: 12px; }
.sco-bmi p { margin: 0; }
.sco-boxed { border: 1px solid var(--hair); border-radius: var(--r-l); }
.sco-more > summary { cursor: pointer; font-size: 12.5px; font-weight: var(--fw-semi); color: var(--ink-2); padding: 4px 0; }
.sco-more > p { margin: 6px 0 0; }
.sco-issues { margin: 6px 0 0; padding-left: 18px; max-height: 220px; overflow-y: auto; font-size: 12.5px; }
.sco-code { max-height: 30vh; overflow: auto; margin: 0; padding: 10px; border-radius: var(--r-m); background: var(--well); font-size: 12px; }
/* Duplicate Accounts: the two accounts read across */
.sco-levels { margin: 10px 0 2px; }
.sco-dupt td { vertical-align: top; }
.sco-dupt td:first-child .hint { display: block; }
.sco-dup { display: grid; gap: 2px; min-width: 0; }
.sco-dup-n { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-height: 22px; }
.sco-card .sco-dup { padding-top: 6px; border-top: 1px solid var(--hair); }
@media (max-width: 1180px), (pointer: coarse) { .sco-drop { min-height: var(--tap); } .sco-more > summary { padding: 12px 0; } }
/* API Tokens, Sales Goals: a form row of two fields and its button */
.sco-form3 { grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) auto; align-items: start; }
.sco-form-go { justify-content: flex-start; padding-top: 22px; }
@media (max-width: 640px) { .sco-form3 { grid-template-columns: minmax(0, 1fr); } .sco-form-go { padding-top: 0; } .sco-form-go .btn { width: 100%; justify-content: center; } }
/* API Tokens (B27, wave 17): name, who it acts as, how long it lasts, and its button — 2 + 2 on a narrow screen, 1 on a phone */
.sco-form4 { grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) minmax(0, 1fr) auto; align-items: start; }
@media (max-width: 900px) { .sco-form4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .sco-form4 { grid-template-columns: minmax(0, 1fr); } }
.sco-okpanel { box-shadow: inset 4px 0 0 var(--ok), var(--shadow); }
.sco-forbid { margin: 0; padding-left: 18px; columns: 2; column-gap: 32px; font-size: 12.5px; }
@media (max-width: 640px) { .sco-forbid { columns: 1; } }
.sco-blk { display: block; }
.sco-dim { color: var(--muted); }   /* faded (K5): see "faded rows" */
.sco-nowrap { white-space: nowrap; }
.sco-grow { flex: 1 1 auto; }
.sco-goal { max-width: 160px; margin-left: auto; }
.sco-card .sco-goal { max-width: none; }
.sco-drill { border-bottom: 1px dashed var(--hair-2); cursor: pointer; font-variant-numeric: tabular-nums; }
.sco-drill:hover, .sco-drill:focus-visible { border-bottom-color: var(--ink); }
/* Mail: which environment variables are set */
.sco-mailgrp { display: grid; gap: 6px; padding-top: 10px; border-top: 1px solid var(--hair); }
.sco-mailgrp p { margin: 0; }
.sco-env { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.sco-env li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 12.5px; }
.sco-env .dot.sco-on { background: var(--ok); }
.sco-env .dot.sco-off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--bad); }
/* Activity Log: the filters, the bars, the days */
.sco-actf { display: grid; grid-template-columns: minmax(0, 1.2fr) repeat(3, minmax(0, 1fr)) minmax(0, 1.3fr) minmax(0, 1.3fr) auto; gap: 10px 12px; align-items: end; }
.sco-actq { grid-column: span 1; }
@media (max-width: 1180px) { .sco-actf { grid-template-columns: repeat(3, minmax(0, 1fr)); } .sco-actp { grid-column: 1 / -1; } }
@media (max-width: 640px) { .sco-actf { grid-template-columns: repeat(2, minmax(0, 1fr)); } .sco-actq, .sco-actf .field:first-child { grid-column: 1 / -1; } .sco-actp .btn { flex: 1 1 0; justify-content: center; } }
.sco-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.sco-bars li { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) 48px; gap: 10px; align-items: center; font-size: 13px; }
.sco-bars b { text-align: right; font-variant-numeric: tabular-nums; }
.sco-bars-l { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sco-days { display: flex; align-items: flex-end; gap: 2px; height: 56px; padding: 2px 0; border-bottom: 1px solid var(--hair); }
.sco-days i { flex: 1 1 0; min-width: 2px; max-width: 18px; height: var(--h, 6%); border-radius: 3px 3px 0 0; background: linear-gradient(180deg, var(--water-a), var(--water-b)); }
/* a branch row broken up (1180 and under): name and code, region · family · status, then the Branch Mgr seat across */
@media (max-width: 1180px) { .sco-br-seat { order: 9; grid-column: 1 / -1; } }
@media (max-width: 640px) { .sco-br-name { grid-column: 1 / -1; } }
.sco-figs .input.n { max-width: 220px; }   /* a figure's box is the size of a figure, its words under it */
:is(.sco-modal, .sco-br, .sbe-form4) :is(.input, .select, .textarea, textarea):disabled { background: var(--well); color: var(--muted); cursor: not-allowed; }   /* read here, changed elsewhere */
.sco-br > * { min-width: 0; }
.sco-br .select-wrap { max-width: 100%; }
@media (max-width: 640px) { .sco-br-par, .sco-br-st { grid-column: 1 / -1; } }   /* a long status ("Closed — history only") gets the row */

/* ---------------- Settings › Field (sfd-) — Crew Day (and its Crew texts), Time Approvals, Ticket and Take-Off Layouts,
   Dump Sites, Additional Materials, On-Site Equipment — in public/settings.js (3.0). Panels are the frame's .stg-card;
   lists are .phone-cards panels (a table on a computer, cards on a phone); a tab's parts are link tabs (.sco-parts).
   An editable list is one set of rows (.sfd-rows) rather than a table and cards drawn twice: each row is a grid that is one
   line from 1181px (its column headings drawn once above it, .sco-colh, each box's own label read aloud) and breaks into
   labelled boxes under that, two to a line on a tablet and one on a phone. */
.stg-cards > .strip { border-radius: var(--r-xl); }
.sfd-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.sfd-rows > li { display: grid; gap: 8px 12px; align-items: end; padding: 12px 0; border-top: 1px solid var(--hair); min-width: 0; }
.sfd-rows > li:first-child, .sfd-rows > .sco-colh + li { border-top: 0; }
.sfd-rows > li:first-child:not(.sco-colh) { padding-top: 0; }
.sfd-rows > li > * { min-width: 0; }
.sfd-rows > li.hint { display: block; border-top: 0; padding: 0; }
.sfd-rows > li.sco-colh { display: none; }   /* the headings row: only where the rows are one line (1181 and up, below) */
@media (min-width: 1181px) { .sfd-rows > li.sco-colh { display: grid; } }
.sfd-rows .select-wrap { max-width: 100%; }
.sfd-rowgo { display: flex; justify-content: flex-end; align-items: center; min-height: var(--ctl); }
/* the rows' shapes: On-Site Equipment, Additional Materials, a dump site's materials, a take-off field, a ticket question */
.sfd-eq { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, .9fr); }
.sfd-am { grid-template-columns: minmax(0, 2fr) minmax(0, .9fr) minmax(0, .8fr) minmax(0, 1fr) 110px; }   /* a fixed last column: each row is its own grid, so */
.sfd-mat { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr) 110px; }                    /* an auto one sized differently under the headings */
.sfd-tf { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1.8fr) 110px; }
.sfd-tq { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1.5fr) minmax(0, 1fr) 110px; }
/* 2.x gives every .field a bottom margin; in these panels the grids and the panel's own gap space them */
:is([id^="sfd-"], [id^="sfx-"], .sfd-rows, .sfd-site, .sco-list) .field { margin-bottom: 0; }
:is([id^="sfd-"], [id^="sfx-"], .sfd-site, .sco-list) .field > label { margin-bottom: 0; }
@media (min-width: 1181px) {
  .sfd-rows > li:not(.sco-colh) .field > :is(label, .sco-lab):first-child { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .sfd-rows > li { align-items: center; }
}
@media (max-width: 1180px) {
  .sfd-eq, .sfd-am, .sfd-mat, .sfd-tf, .sfd-tq { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sfd-eq > :first-child, .sfd-am > :first-child, .sfd-tf > :first-child, .sfd-tq > :first-child, .sfd-mat > :first-child { grid-column: 1 / -1; }
  .sfd-rowgo { grid-column: 1 / -1; justify-content: flex-start; min-height: 0; }
  :is(.sfd-eq, .sfd-am, .sfd-mat, .sfd-tf, .sfd-tq):not(:has(> .sfd-nochoice)) > :nth-child(even):is(:last-child, :has(+ .sfd-rowgo)) { grid-column: 1 / -1; }   /* the field left alone on the last line takes it (K7: On-Site Equipment went 1 + 2 + 1) */
}
@media (max-width: 640px) {
  .sfd-eq, .sfd-am, .sfd-mat, .sfd-tf, .sfd-tq { grid-template-columns: minmax(0, 1fr); }
  .sfd-rowgo .btn { width: 100%; justify-content: center; }
}
/* a choice that only means something for a dropdown steps back (it keeps its place, so the row keeps its shape) */
.sfd-nochoice { visibility: hidden; }
@media (max-width: 1180px) { .sfd-nochoice { display: none; } }
/* the add-a-row form: the boxes, then the button level with their bottoms */
.sfd-add { align-items: flex-end; }
.sfd-add > .btn { flex: none; }
.sco-add.sfd-add .field { flex: 1 1 180px; }   /* the boxes share the line with Add instead of pushing it to a line of its own (K7: 3 + 1 at 1024 and 1440) */
.sfd-addtop { padding-top: 0; border-top: 0; }
/* a number with its unit beside it: a figure-sized box */
.sfd-num { display: flex; align-items: center; gap: 8px; }
.sfd-num .input { max-width: 140px; }
.sfd-num .hint { white-space: nowrap; }
/* a switch row: what it does on the left, its On/Off dropdown on the right */
.sfd-switch { padding: 0; border-top: 0; flex-wrap: nowrap; align-items: flex-start; }
.sfd-switch .select-wrap { flex: none; }
.sco-rows .sco-row .src, .sfd-switch + .sco-note { flex: none; }
.sfd-fencebody { display: grid; gap: 14px; transition: opacity var(--t-std); }
.sfd-sub { display: grid; gap: 10px; padding-top: 12px; border-top: 1px solid var(--hair); }
.sfd-sub > .actions { padding-top: 2px; }
.sfd-jsa { padding-top: 12px; border-top: 1px solid var(--hair); }
/* four, three across: 4 → 2 → 1 and 3 → 1 */
.sfd-g4 { gap: 12px 14px; }
@media (max-width: 640px) { .sfd-g4 { grid-template-columns: minmax(0, 1fr); } }
.sfd-g3 { gap: 14px 16px; }
/* Dump Sites: each site a panel; the branch markups two columns of label · box, one on a phone */
.sfd-site .sco-head .actions { align-items: center; }
.sfd-mks { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 32px; }
.sfd-mk { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 0; border-top: 1px solid var(--hair); break-inside: avoid; }
.sfd-mk label { margin: 0; font-size: 13px; font-weight: var(--fw-semi); color: var(--ink); }
.sfd-mk .input { width: 96px; }
@media (max-width: 700px) { .sfd-mks { columns: 1; } }
/* Time Approvals: the reasons list's foot (the long-day box and Save) */
.sfd-ta td:nth-child(2) { width: 260px; }
.sfd-ta-foot { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 16px; border-top: 1px solid var(--hair); }
.sfd-ta-foot > .grid-2 { flex: 1 1 320px; }
@media (max-width: 640px) { .sfd-ta-foot .actions, .sfd-ta-foot .actions .btn { width: 100%; justify-content: center; } }
/* a source link under a value in a list cell; a dropdown in a list cell is the size of its words */
.sco-list td .src { margin-left: 0; }
.sco-list td .select-wrap { max-width: 320px; }
/* a short list of names, two columns from 981px */
@media (min-width: 981px) { .sco-rows.sfx-two { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 32px; }
  .sco-rows.sfx-two > .sco-row:nth-child(2) { border-top: 0; padding-top: 0; } }

/* ---------------- Settings › Fleet, safety & spend (sfx-) — the Fleet and Approval Chart tabs in public/settings.js (3.0) ---------------- */
.sfx-list { min-height: 200px; font-variant-numeric: tabular-nums; }
/* Unit statuses: two columns of statuses from 981px, each its words · its colour, with the stored key under */
.sfx-st { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
.sfx-st .field > :is(label, .sco-lab):first-child { position: static !important; width: auto !important; height: auto !important; clip: auto !important; }
.sfx-key { grid-column: 1 / -1; overflow-wrap: anywhere; }
.sfx-key code { font-size: 11.5px; }
@media (min-width: 981px) { .sfx-sts { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 32px; }
  .sfx-sts > li:nth-child(2) { border-top: 0; padding-top: 0; } }
@media (max-width: 640px) { .sfx-st { grid-template-columns: minmax(0, 1fr); } }
.sfx-save { justify-content: flex-end; }
@media (max-width: 640px) { .sfx-save .btn { width: 100%; justify-content: center; } }
.sfx-ticks { display: flex; flex-wrap: wrap; gap: 4px 28px; }
.stg-wide .sfx-ticks .stg-check, .sfx-ticks .stg-check { border-top: 0; padding: 6px 0; align-items: center; }
.sfx-run { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.sfx-detail { display: grid; gap: 6px; }
.sfx-detail:empty { display: none; }
.sfx-errs { margin: 6px 0 0; padding-left: 18px; }
.sfx-strip { border: 1px solid var(--hair); border-radius: var(--r-l); box-shadow: none; }
/* Settings › Company › Holidays (3.0, w8fleet — sn-settings): the add form's box level with its button; the federal days a
   column a year, compact, so the two panels stand about as tall as each other */
.sco-hols .sco-add .field { margin-bottom: 0; }
.sco-hols .sco-rows .sco-row { flex-wrap: nowrap; }   /* a day and its ✕ stay on one line on a phone */
.sco-hols .sco-rows .sco-row-t { flex-basis: auto; }
.sco-fed { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 24px; }
.sco-fedy { margin: 0 0 4px; font-size: 13px; font-weight: var(--fw-semi); color: var(--muted); }
.sco-fed .sco-row { padding: 7px 0; font-variant-numeric: tabular-nums; }
.sco-fed .sco-rows > .sco-row:first-child { border-top: 0; }
/* Settings › Fleet › Service tasks (3.0, w8fleet — sn-settings): one row a task, as the other editable lists (.sfd-rows);
   the count reads as a figure, level with the boxes */
.sfx-task { grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, .7fr) minmax(0, 1fr); }
.sfx-n { display: flex; align-items: center; min-height: var(--ctl); font-variant-numeric: tabular-nums; font-weight: var(--fw-semi); }
@media (min-width: 1181px) { .sfx-task .sfx-n { justify-content: flex-end; padding-right: 8px; } .sfx-task.sco-colh > :nth-child(4) { text-align: right; padding-right: 8px; } }
@media (max-width: 1180px) { .sfx-task { grid-template-columns: repeat(2, minmax(0, 1fr)); } .sfx-task > :first-child { grid-column: 1 / -1; } .sfx-n { min-height: 0; } }
/* a phone keeps two to a line (the interval beside its unit, the count beside the state): a task is not five boxes tall */
.sfx-taskadd .sfx-addgo { justify-content: flex-start; }   /* the add row's button sits where a row's State is */
@media (max-width: 1180px) { .sfx-taskadd > .sfx-n { display: none; } }

/* ---------------- Settings › Spend Control (ssp-) — public/spend-settings.js (3.0) ----------------
   Fourteen parts, each with its own address (#/settings/spend/<part>): link tabs across the top, ONE row that scrolls with
   the kit's fade like every other tab strip (B29, wave 17: two rows broke the one tab-strip rule), the open part brought
   into view (phone-tables.js centreTabs); a picker at 700 and under — fourteen tabs are no use sideways on a phone. Panels are the frame's .stg-card in .stg-cards; lists are
   .phone-cards panels (the busy ones .sco-c980); notes are .sco-note; pop-ups are .sco-modal inside the spend kit's
   .modal (.ssp-m). The matrix keeps the company PDF's document layout (.ssp-mx) and turns to cards at 760. */
.ssp-parts { margin-top: -4px; gap: 22px; }   /* one row: .subtabs scrolls it, and its .more fade says there is more */
.ssp-pick { display: none; }
@media (max-width: 700px) { .ssp-parts { display: none; } .ssp-pick { display: flex; } }
.ssp-body { display: grid; gap: var(--gap); min-width: 0; }
.ssp-body > .stg-cards { min-width: 0; }
.ssp-flash { position: relative; padding-right: 48px; display: grid; gap: 4px; }
.ssp-flash p { margin: 0; overflow-wrap: anywhere; }
.ssp-flash .ssp-x { position: absolute; top: 4px; right: 4px; }
.ssp-x .i { width: 14px; height: 14px; }
.ssp-warns { margin: 0; padding-left: 18px; display: grid; gap: 4px; }
.ssp-bad { color: var(--bad); }
.ssp-tight { margin: 0; }
.ssp-nowrap { white-space: nowrap; }
/* tiles that filter the list under them: a strip of buttons, the one pressed lit */
.ssp-tiles .strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ssp-tile { all: unset; box-sizing: border-box; display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 14px 18px 16px; cursor: pointer;
  box-shadow: 1px 0 0 var(--hair), 0 1px 0 var(--hair); transition: background var(--t-std); }   /* all: unset took the strip cell's own look; it is put back */
.ssp-tile:hover { background: rgba(255,255,255,.45); }
.ssp-tile[aria-pressed="true"] { background: var(--well); box-shadow: 1px 0 0 var(--hair), 0 1px 0 var(--hair), inset 0 -3px 0 var(--accent); }
.ssp-tile:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.ssp-tile .hint { min-height: 2.6em; }
[data-theme="dark"] .ssp-tile:hover { background: rgba(255,255,255,.05); }
@media (max-width: 1180px) { .ssp-tiles .strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* readiness: a tick, a mark or a cross before each line */
.ssp-ckline { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.ssp-ckline > span:last-child { min-width: 0; overflow-wrap: anywhere; }
.ssp-ck { flex: none; width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; margin-top: 1px; }
.ssp-ck .i { width: 12px; height: 12px; }
.ssp-ck.ok { background: var(--ok-bg); color: var(--ok); }
.ssp-ck.warn { background: var(--warn-bg); color: var(--warn); }
.ssp-ck.no { background: var(--bad-bg); color: var(--bad); }
.ssp-fixes { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 4px 0 0 28px; }
.ssp-pilot { box-shadow: inset 4px 0 0 var(--accent), var(--shadow); }
.ssp-checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.ssp-checklist li { display: flex; gap: 10px; align-items: flex-start; }
.ssp-left { font-weight: var(--fw-semi); }
.ssp-cell { display: grid; gap: 2px; min-width: 0; }
/* approvers: who holds each role */
.ssp-holder .sco-row-t { gap: 1px; }
.ssp-holder.bad { margin: 0 -8px; padding-left: 8px; padding-right: 8px; border-radius: var(--r-m); background: var(--bad-bg); }
.ssp-why > summary { cursor: pointer; font-weight: var(--fw-semi); color: var(--accent-ink); min-height: 32px; display: flex; align-items: center; }
.ssp-why ul, .ssp-why p { margin: 4px 0 0; padding-left: 18px; color: var(--ink-2); font-size: 12.5px; }
.ssp-why p { padding-left: 0; }
details.sco-note > summary { cursor: pointer; }
details.sco-note ul { margin: 8px 0 0; padding-left: 18px; display: grid; gap: 2px; }
/* the matrix, as the company's PDF prints it: a document table with a band per category; cards at 760 */
.ssp-mx-wrap { overflow-x: auto; }
.ssp-mx { width: 100%; min-width: 980px; border-collapse: collapse; font-size: 12.5px; }
.ssp-mx th, .ssp-mx td { padding: 8px 8px; border-bottom: 1px solid var(--hair); vertical-align: top; text-align: left; }
.ssp-mx thead th { font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: .03em; text-transform: uppercase; color: var(--muted); width: 9%; }
.ssp-mx .ssp-mx-item { width: 25%; min-width: 220px; }
.ssp-mx tr.ssp-mx-cat th { background: var(--ink); color: var(--on-ink); font-size: 11.5px; letter-spacing: .06em; padding: 7px 10px; }
.ssp-mx tr.ssp-off td { color: var(--muted); }   /* faded (K5): see "faded rows" */
.ssp-mx-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
.ssp-mx-cell + .ssp-mx-cell { margin-top: 8px; }
.ssp-pdf { font-weight: var(--fw-semi); color: var(--ink); }
.ssp-pdf sup { color: var(--warn); font-weight: 800; }
.ssp-band { display: block; color: var(--muted); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.ssp-signoff .ssp-pdf { font-style: italic; }
.ssp-ocol { font-size: 11px; font-weight: var(--fw-bold); color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.ssp-meta { color: var(--muted); font-size: 12px; margin-top: 3px; }
.ssp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
.ssp-chips:empty { display: none; }
.ssp-retired { margin-top: 8px; padding: 8px 10px; border-radius: var(--r-m); background: var(--well); font-size: 12px; }
.ssp-retired ul { margin: 4px 0 0; padding-left: 18px; }
.ssp-mx-cards { display: none; }
.ssp-mx-cat { margin: 6px 0 0; font-size: 11.5px; font-weight: var(--fw-bold); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.ssp-dl { display: grid; grid-template-columns: minmax(0, 38%) minmax(0, 1fr); gap: 6px 10px; margin: 0; font-size: 13px; }
.ssp-dl dt { font-weight: var(--fw-semi); overflow-wrap: anywhere; }
.ssp-dl dd { margin: 0; display: grid; gap: 1px; overflow-wrap: anywhere; }
@media (max-width: 760px) { .ssp-mx-wrap { display: none; } .ssp-mx-cards { display: grid; gap: 8px; } }
/* settings: one row a setting — its name, what it does, the box, what applies now */
.ssp-sets { display: grid; }
.ssp-set { display: grid; gap: 6px; padding: 12px 0; border-top: 1px solid var(--hair); }
.ssp-set:first-child { border-top: 0; padding-top: 0; }
.ssp-set > label:not(.ssp-check) { font-size: 13px; font-weight: var(--fw-semi); color: var(--ink); }
.ssp-set .input.n, .ssp-set .ssp-num { max-width: 200px; }
.ssp-set .ssp-txt { max-width: 340px; }
.ssp-set .select-wrap { max-width: 280px; }
.ssp-opts { display: flex; flex-wrap: wrap; gap: 0 18px; }
.ssp-savebar { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 12px; }
.ssp-savebar .hint:empty { display: none; }
@media (max-width: 640px) { .ssp-savebar .btn { flex: 1 1 100%; justify-content: center; } }
/* the change log's marks, in capitals */
.ssp-mark { display: inline-block; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; color: var(--bad); background: var(--bad-bg); border: 1px solid var(--bad-line);
  border-radius: 6px; padding: 1px 6px; margin: 1px 0; white-space: nowrap; }
.ssp-flag { background: var(--bad-bg); }
table.t tbody tr.ssp-flag:hover { background: var(--bad-bg); }
/* tick boxes and choices, a finger's reach */
.ssp-check, .ssp-radio { display: inline-flex; align-items: flex-start; gap: 8px; min-height: 36px; padding-top: 8px; cursor: pointer; font-size: 13px; }
.ssp-check input, .ssp-radio input { width: 18px; height: 18px; flex: none; margin: 0; accent-color: var(--ink); }
.ssp-check > span, .ssp-radio > span { min-width: 0; }
@media (max-width: 1180px), (pointer: coarse) { .ssp-check, .ssp-radio { min-height: var(--tap); padding-top: 12px; } }
/* pop-ups */
.modal.ssp-m { max-width: 640px; }
.modal.ssp-m.ssp-wide { max-width: 1000px; }
.ssp-hidden { visibility: hidden; }
.ssp-mhead { flex-wrap: nowrap; }
.ssp-mhead > .btn { flex: none; margin: -6px -6px 0 0; }
.ssp-msec { display: grid; gap: 10px; padding-top: 14px; border-top: 1px solid var(--hair); }
.ssp-msec:first-of-type { padding-top: 0; border-top: 0; }
.ssp-msec h3 { margin: 0; font-size: 14px; font-weight: var(--fw-x); }
.ssp-what { font-weight: var(--fw-semi); }
.ssp-reqs { margin: 6px 0 0; padding-left: 18px; }
.ssp-reqs li { overflow-wrap: anywhere; }
.ssp-logbox { border: 1px dashed var(--hair-2); border-radius: var(--r-m); padding: 8px 12px; font-size: 13px; display: grid; gap: 4px; }
.ssp-logbox p { overflow-wrap: anywhere; }
.ssp-kicker { font-size: 11px; font-weight: var(--fw-bold); letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.ssp-unitlist { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; max-height: 260px; overflow-y: auto; padding: 2px 10px 8px;
  border: 1px solid var(--hair-2); border-radius: var(--r-m); }
.ssp-unitlist[hidden] { display: none; }
@media (max-width: 560px) { .ssp-unitlist { grid-template-columns: minmax(0, 1fr); } }
.ssp-picks { display: grid; gap: 0; }
.ssp-ro { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; min-height: var(--ctl); font-size: 13px; }
/* the row editor: one box per step */
.ssp-rules { display: grid; gap: 10px; }
.ssp-rule { display: grid; gap: 8px; padding: 10px 12px; border-radius: var(--r-l); background: var(--well); border: 1px solid var(--hair); }
.ssp-rule-grid { display: grid; grid-template-columns: 72px minmax(0, 1.7fr) minmax(0, 1.2fr) minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 8px 10px; align-items: start; }
.ssp-rule-grid > * { min-width: 0; }
.ssp-rule-foot { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.ssp-rolepick { display: flex; gap: 4px; align-items: center; }
.ssp-rolepick + .ssp-rolepick { margin-top: 4px; }
.ssp-rolepick .select-wrap { flex: 1 1 auto; min-width: 0; }
.ssp-rule .input:disabled { background: var(--surface-2); color: var(--muted); cursor: not-allowed; }
@media (max-width: 820px) {
  .ssp-rule-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ssp-rule-grid > .ssp-r-roles { grid-column: 1 / -1; order: -1; }
  .ssp-rule-grid > .ssp-r-q { grid-column: 1 / -1; }
}
@media (max-width: 560px) { .ssp-rule-foot { grid-template-columns: minmax(0, 1fr); } .ssp-rule-foot .btn { justify-content: center; } }
/* text messages: the connection's facts */
.ssp-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 0; font-size: 13px; }
.ssp-facts dt { color: var(--muted); }
.ssp-facts dd { margin: 0; overflow-wrap: anywhere; }
.ssp-url { font-size: 12px; word-break: break-all; }
.ssp-words { margin: 0; padding: 10px 12px; border-left: 3px solid var(--accent); border-radius: 0 var(--r-m) var(--r-m) 0; background: var(--well); font-size: 13px; overflow-wrap: anywhere; }
.ssp-list { margin: 0; padding-left: 20px; display: grid; gap: 6px; font-size: 13px; }
@media (max-width: 560px) { .ssp-facts { grid-template-columns: minmax(0, 1fr); gap: 2px; } .ssp-facts dd { margin-bottom: 6px; } }

/* ---------------- Settings › Safety (ssa-) — public/safety-settings.js (3.0) ---------------- */
/* Drawn from the kit's own pieces (.stg-card panels, .sco-parts, .sco-note, .phone-cards, fields, chips); the form editors and the
   375 px phone preview are this screen's alone and keep their looks in public/safety-settings.css (sfy-s-), built from the tokens. */

/* ---------------- Settings › Crews & Skills (skl-) — the Settings part of public/gaps-ui.js (3.0) ---------------- */
/* Crew types · Branch overrides · Skills list · Stage chances, each its own address; lists are .phone-cards panels; a crew type's
   and a skill's state is a .status dropdown. These are the bits the kit lacked: the needs chips, the sources line, the editor. */
.skl { display: grid; gap: var(--gap); min-width: 0; }
.skl-needs { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.skl-srcs { display: flex; flex-wrap: wrap; gap: 2px 12px; margin-top: 4px; }
.skl-add { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; max-width: 460px; }
.skl-chances { max-width: 520px; }
.skl-chances .sco-row { padding: 8px 0; }
.skl-chances .sco-row-t { font-weight: var(--fw-semi); }
.skl-pct { display: inline-flex; align-items: center; gap: 6px; }
.skl-pct .input { width: 96px; }
.skl-end { justify-content: flex-end; }
.skl .input:disabled { background: var(--well); color: var(--muted); cursor: not-allowed; }   /* a chance read here, kept by an Administrator */
/* the crew type editor (inside the app's .modal, wide) */
.skl-fs { margin: 0; padding: 12px 0 0; border: 0; border-top: 1px solid var(--hair); display: grid; gap: 8px; min-width: 0; }
.skl-fs legend { padding: 0; font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.skl-skrow { display: grid; grid-template-columns: minmax(0, 1fr) 96px auto; gap: 8px; align-items: center; }
.skl-slot { display: grid; gap: 6px; padding: 8px 10px; border: 1px solid var(--hair-2); border-radius: var(--r-m); }
.skl-slot-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.skl-ticks { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 0 12px; max-height: 196px; overflow: auto; }
.skl-ticks label { display: flex; align-items: center; gap: 8px; min-height: 32px; font-size: 13px; cursor: pointer; }
.skl-ticks input { width: 18px; height: 18px; margin: 0; flex: none; accent-color: var(--ink); }
@media (max-width: 1180px), (pointer: coarse) { .skl-ticks label { min-height: var(--tap); } }
@media (max-width: 640px) { .skl-skrow { grid-template-columns: minmax(0, 1fr) 84px auto; } .skl-add { grid-template-columns: minmax(0, 1fr); } }

/* ---------------- Momentum › Purchasing (pu-) — public/spend-momentum.js (3.0) ----------------
   Card charges · Fuel · Purchase orders · Rentals & recurring · Requests · Vendors, a PO, a vendor, an agreement, and their
   pop-ups. The kit's page head, sub-tabs, wg-tools filter bar, strip, table.t → phone cards, status dropdowns, chips, flags
   and source links do the work; these place them. */
.pu-title { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.pu-h3 { margin: 14px 0 8px; font-size: 13.5px; font-weight: var(--fw-bold); }
.pu-h3:first-child { margin-top: 0; }
.pu-toggle { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: var(--fw-semi); color: var(--ink-2); }
.pu-toggle label { cursor: pointer; }
table.t.pu-t td { vertical-align: top; }
table.t.pu-t td.pu-w { min-width: 220px; }
table.t.pu-t .select-wrap { vertical-align: middle; }
.pu-who { color: inherit; text-decoration: none; }
.pu-who:hover { text-decoration: underline; }
.pu-card { display: grid; gap: 6px; min-width: 0; }
.pu-card-top { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 10px; }
.pu-card-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 10px; }
.pu-amt { font-variant-numeric: tabular-nums; white-space: nowrap; }
.pu-sugg { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 4px 0 0; }
.pu-paycell .select-wrap { max-width: 230px; }
.pu-whyd { margin-top: 6px; }
.pu-whyd > .flags { margin-top: 6px; }
.flags.pu-why li { font-size: 12.5px; }
.pu-chain { margin: 10px 0 0; }
.pu-open { all: unset; cursor: pointer; font-weight: var(--fw-bold); color: var(--ink); border-radius: 4px; }
.pu-open:hover { text-decoration: underline; }
.pu-open:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* a list of events or rows inside a panel: when, then what */
.pu-pad0 { padding-top: 0; }
.pu-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.pu-row { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 6px 14px; padding: 10px 0; border-top: 1px solid var(--hair); }
.pu-rows > .pu-row:first-child { border-top: 0; }
.pu-row-t { flex: 1 1 260px; min-width: 0; display: grid; gap: 3px; }
.pu-when { flex: 0 0 150px; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; padding-top: 1px; }
.pu-note { font-size: 13px; color: var(--ink-2); white-space: pre-line; }
.pu-off { color: var(--muted); }   /* faded (K5): see "faded rows" */
/* forms: two fields a row; a wide one takes the row */
.pu-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; align-items: start; }
.pu-form > .pu-wide, .pu-kv > .pu-wide { grid-column: 1 / -1; }
.pu-ro { min-height: var(--ctl); display: flex; align-items: center; font-size: 13px; }
.pu-filerow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.pu-macts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 4px; }
/* the draft PO's lines: a row each on a computer, a small card each on a phone */
.pu-lines { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 8px; }
.pu-line { display: grid; grid-template-columns: minmax(0, 1fr) 90px 90px 120px 110px var(--ctl); gap: 8px; align-items: end; padding-bottom: 8px; border-bottom: 1px solid var(--hair); }
.pu-l-amt b { display: flex; align-items: center; justify-content: flex-end; min-height: var(--ctl); font-variant-numeric: tabular-nums; }
.pu-l-amt .label { text-align: right; }
.pu-addrow { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 14px; margin-bottom: 12px; }
.pu-tot { margin: 0; font-size: 14px; }
.pu-tot b { font-variant-numeric: tabular-nums; }
.pu-doc { min-width: 0; overflow-x: auto; }
/* pop-ups: the kit's look inside the app's .modal */
.modal.pu-dlg { max-width: 720px; }
.pu-modal { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; min-width: 0; }   /* one column that never grows past the dialog: the export's wide sample table pushed its buttons off the right edge (w18spend) */
.pu-modal h2 { margin: 0; font-size: var(--fs-xl); }
.pu-modal p { margin: 0; }
.pu-mhead { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.pu-check { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; margin-top: 8px; }
.pu-check input { width: 18px; height: 18px; margin: 1px 0 0; flex: none; accent-color: var(--ink); }
.pu-mail.mo-kv { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pu-body { margin: 0; padding: 10px 12px; max-height: 220px; overflow: auto; white-space: pre-wrap; font: 13px/1.5 var(--font); background: var(--well); border-radius: var(--r-m); }
.pu-ex-filters { grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: end; }
.pu-ex-filters .pu-toggle { min-height: var(--ctl); }
.pu-ex-fmt { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.pu-sample { max-height: 240px; overflow: auto; border: 1px solid var(--hair); border-radius: var(--r-m); }
.pu-sample td, .pu-sample th { white-space: nowrap; }
.pu-sec { display: grid; gap: 8px; padding-top: 12px; border-top: 1px solid var(--hair); }
.pu-sum { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pu-sum > div { padding: 10px 12px 12px; }
.pu-list-plain { margin: 0; padding-left: 18px; display: grid; gap: 3px; font-size: 13px; }
.pu-preview { padding-top: 10px; border-top: 1px solid var(--hair); display: grid; gap: 8px; }
.pu-kv.mo-kv { margin-top: 2px; }
.pu-kv .src { margin-top: 2px; }
.select.pu-inline { height: 32px; min-width: 180px; }
/* Fuel: where it comes from, three cells that read across (3, then 1) */
.pu-fsrc > div { gap: 4px; }
.pu-fsrc b { font-size: 14px; }
.pu-two { align-items: start; }
.pu-one { grid-template-columns: minmax(0, 1fr); }
.pu-place { margin-top: 6px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; align-items: end; }
@media (max-width: 1180px), (pointer: coarse) {
  .pu-open { min-height: var(--tap); display: inline-flex; align-items: center; }
  .select.pu-inline { height: var(--tap); }
}
@media (max-width: 980px) {
  .pu-line { grid-template-columns: repeat(3, minmax(0, 1fr)) auto; }
  .pu-l-desc { grid-column: 1 / -1; }
  .pu-l-amt { grid-column: 1 / 4; }
  .pu-l-amt b { justify-content: flex-start; }
  .pu-l-amt .label { text-align: left; }
  .pu-ex-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pu-ex-filters .pu-toggle { grid-column: 1 / -1; }
  .pu-place { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .pu-form, .pu-mail.mo-kv { grid-template-columns: minmax(0, 1fr); }
  .pu-when { flex-basis: 100%; }
  .pu-sum { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pu-macts .btn { flex: 1 1 0; justify-content: center; }
  .pu-tools .pu-toggle { flex: 1 1 100%; }
  .pu-paycell .select-wrap { max-width: none; }
}

/* ---------------- Settings › Estimating and › Bidding documents (sbe-) — public/settings.js (3.0) ----------------
   Master Items' parts (Price sheet, Requests), Pricing, Estimating Costs (Crew kits, Cost items, Branch defaults, Mileage &
   fuel, Mobilization), Rate Books, Bid Totals, Bid Templates, Quote Documents, Submittals, Bid Site Logins, City Specs.
   Panels are the frame's .stg-card (Settings › Company's sco- pieces too); a read-only list is a .phone-cards panel. An
   EDITABLE list is .sbe-g: a heading row, then a grid row per record whose cells are fields; at 980 and under the heading row
   goes and each row breaks into labelled fields two across (.sbe-keep: only at 640, for the narrow ones). The crew-kit and
   bid-template builders are one full-screen sheet (.sbe-sheet). */
.sbe-grow { flex: 1 1 240px; min-width: 0; }
.sbe-sm { flex: 0 1 96px; min-width: 72px; }
.sbe-half { max-width: 420px; }
.sbe-span { grid-column: 1 / -1; }
.sbe-pad { padding: var(--pad); padding-top: 0; }
.sbe-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
.sbe-upper { text-transform: uppercase; }
.sbe-strong { font-weight: var(--fw-bold); }
.sbe-miss { color: var(--warn); font-weight: var(--fw-semi); }
.sbe-own { color: var(--accent-ink); font-weight: var(--fw-semi); }
.sbe-warnnum { color: var(--warn); }
.sbe-clip { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sbe-check { width: 18px; height: 18px; accent-color: var(--ink); }
.sbe-file { padding: 6px 10px; height: auto; min-height: var(--ctl); }
.sbe-unit { display: inline-flex; align-items: center; gap: 6px; }
.sbe-unit .input { width: 12ch; }
.sbe-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.sbe-chips .chip { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.sbe-chipx { all: unset; display: inline-grid; place-items: center; width: 16px; height: 16px; margin-left: 2px; border-radius: 4px; cursor: pointer; }
.sbe-chipx:hover, .sbe-chipx:focus-visible { background: var(--hair-2); }
.sbe-tagpick { height: 26px; font-size: 12px; padding: 0 28px 0 8px; width: auto; }
.sbe-tick { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: var(--fw-semi); cursor: pointer; white-space: nowrap; }
.sbe-tick input { width: 16px; height: 16px; accent-color: var(--ink); }
.sbe-scroll { max-height: 280px; overflow-y: auto; }
.sbe-kv { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 10px; }
.sbe-pw { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }   /* Bid Site Logins' Password cell: Show, then the password for a minute */
.sbe-pw > .btn { flex: none; }
/* a filter or tool row inside a panel: fields bottom-aligned, wrapping */
.sbe-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; }
.sbe-bar > .seg { align-self: flex-end; }
.sbe-bar > .hint { padding-bottom: 9px; }
.sbe-barend { margin-left: auto; }
.sbe-bar-in { margin-bottom: 8px; }
.sbe-pickrow { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px; }
/* an add row under a list: its fields, then the button */
.sbe-add { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; padding-top: 12px; border-top: 1px solid var(--hair); }
.sbe-add .field { min-width: 0; margin-bottom: 0; }
.sbe-add > .btn.sm { height: 36px; }   /* as tall as the select beside it */   /* the global .field's 10px below pushed the button 10px under the box it sits beside (w27hb) */
/* forms in panels */
.sbe-form4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 14px; }
.sbe-form2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; }
@media (max-width: 1180px) { .sbe-form4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .sbe-form4, .sbe-form2 { grid-template-columns: minmax(0, 1fr); } .sbe-add > .btn { width: 100%; justify-content: center; } }

/* the editable list */
.sbe-g { display: grid; }
.sbe-gh, .sbe-gr { display: grid; grid-template-columns: var(--sbe-cols); gap: 8px 12px; align-items: center; }
.sbe-gh { padding: 0 0 8px; border-bottom: 1px solid var(--hair); font-size: 11.5px; font-weight: var(--fw-semi); color: var(--muted); }
.sbe-gr { padding: 8px 0; border-bottom: 1px solid var(--hair); }
.sbe-gr:last-child { border-bottom: 0; padding-bottom: 0; }
.sbe-gr > *, .sbe-gh > * { min-width: 0; }
.sbe-gh .r, .sbe-gc.r { text-align: right; justify-items: end; }
.sbe-gc { display: grid; gap: 4px; align-content: center; }
.sbe-gc > .select-wrap.block { width: 100%; }
.sbe-gc > .chip { justify-self: start; max-width: 100%; height: auto; min-height: 22px; padding-block: 3px; line-height: 1.3; white-space: normal; }   /* a chip wraps inside its cell, never over the next one (M4) */
/* a status dropdown keeps to its own width wherever it sits: its chevron stays inside the pill */
:is(.field, .sbe-gc) > .select-wrap:has(> .status) { justify-self: start; align-self: flex-start; }
.sbe-gl { display: none; font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.sbe-gn { font-weight: var(--fw-semi); }
.sbe-ga { justify-items: end; }
.sbe-gr.sco-dim { color: var(--muted); }   /* faded (K5): see "faded rows" */
.sbe-rbi { --sbe-cols: minmax(110px, .9fr) minmax(200px, 2.4fr) 70px repeat(3, minmax(80px, .7fr)) minmax(120px, 1fr) 36px; }   /* State holds "Request Pricing → add at $0": 70px let it run over the ✕ and push the page sideways at 1024 (w11design M4) */
.sbe-rbf { --sbe-cols: minmax(110px, 1fr) minmax(130px, 1fr) minmax(90px, .7fr) 36px; }
.sbe-sdl { --sbe-cols: minmax(220px, 2.2fr) minmax(130px, 1fr) minmax(130px, 1fr) 54px minmax(150px, 1fr) minmax(110px, .8fr) auto; align-items: start; }
.sbe-mls { --sbe-cols: minmax(170px, 1.6fr) repeat(4, minmax(100px, 1fr)); }
.sbe-mob { --sbe-cols: minmax(180px, 1.2fr) minmax(150px, 1fr) minmax(200px, 2fr); }
.sbe-fsc { --sbe-cols: minmax(170px, 1.6fr) 70px repeat(2, minmax(110px, 1fr)) minmax(190px, 1.6fr); }
.sbe-fpx { --sbe-cols: minmax(170px, 1.5fr) repeat(3, minmax(110px, 1fr)); }
.sbe-sbr { --sbe-cols: minmax(170px, 1.2fr) minmax(170px, 200px) minmax(240px, 2fr); }   /* Pricing › Stand-by rates (w18platform, w17-standby-rate) */
.sbe-trk { --sbe-cols: minmax(140px, 1.6fr) minmax(90px, 1fr) 36px; }
.sbe-qdn { --sbe-cols: minmax(240px, 3fr) minmax(200px, 2fr) 84px 36px; align-items: start; }
.sbe-cgi { --sbe-cols: minmax(200px, 2.2fr) 90px minmax(100px, 1fr) 70px minmax(120px, .9fr); }
.sbe-cgi.sbe-cgi-br { --sbe-cols: minmax(200px, 2.2fr) 90px minmax(100px, 1fr) minmax(100px, 1fr) 70px minmax(120px, .9fr); }
.sbe-ecs { --sbe-cols: minmax(150px, 1.3fr) repeat(var(--cols, 12), minmax(64px, 1fr)); }
.sbe-hscroll { overflow-x: auto; }
.sbe-hscroll > .sbe-ecs { min-width: 980px; }
.sbe-mls .sbe-gc .hint, .sbe-ecs .sbe-gn + .hint { font-size: 11.5px; }
@media (max-width: 980px) {
  .sbe-g:not(.sbe-keep) > .sbe-gh { display: none; }
  .sbe-g:not(.sbe-keep) > .sbe-gr { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; padding: 12px 0; }
  .sbe-g:not(.sbe-keep) .sbe-gl { display: block; }
  .sbe-g:not(.sbe-keep) .sbe-gname, .sbe-g:not(.sbe-keep) .sbe-gwide { grid-column: 1 / -1; }
  .sbe-g:not(.sbe-keep) .sbe-ga { grid-column: 1 / -1; }
  .sbe-g:not(.sbe-keep) .sbe-gc.r { text-align: left; justify-items: start; }
  .sbe-g.sbe-ecs > .sbe-gr { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .sbe-hscroll > .sbe-ecs { min-width: 0; }
}
@media (max-width: 640px) {
  .sbe-keep > .sbe-gh { display: none; }
  .sbe-keep > .sbe-gr { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; padding: 12px 0; }
  .sbe-keep .sbe-gl { display: block; }
  .sbe-keep .sbe-gname { grid-column: 1 / -1; }
  .sbe-keep .sbe-gc.r { text-align: left; justify-items: start; }
  .sbe-trk > .sbe-gr { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 44px; }
  .sbe-trk .sbe-gname { grid-column: 1 / -1; }
  .sbe-g.sbe-ecs > .sbe-gr, .sbe-g.sbe-sdl > .sbe-gr { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* a folding panel: a glass card whose heading opens and shuts it */
.sbe-folds { display: grid; gap: var(--gap); }
.sbe-fold > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: var(--pad); cursor: pointer; list-style: none; border-radius: var(--r-xl); }
.sbe-fold > summary::-webkit-details-marker { display: none; }
.sbe-fold > summary h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.sbe-fold > summary .i { transition: transform var(--t-std); color: var(--muted); }
.sbe-fold:not([open]) > summary .i { transform: rotate(-90deg); }
.sbe-fold > summary:hover { background: rgba(255,255,255,.3); }
[data-theme="dark"] .sbe-fold > summary:hover { background: rgba(255,255,255,.04); }
.sbe-fold-b { padding: var(--pad); padding-top: 0; display: grid; gap: 12px; }
.sbe-flat { display: grid; }
.sbe-more > summary { cursor: pointer; font-size: 13px; font-weight: var(--fw-semi); padding: 6px 0; }
.sbe-more[open] > summary { margin-bottom: 8px; }
.sbe-more > .field, .sbe-more > .input { margin-top: 10px; }
.sbe-more-row { display: flex; justify-content: center; padding: var(--pad); padding-top: 0; }
.sbe-more-row:empty { display: none; }

/* crew kits and bid templates: one row per kit or template */
.sbe-krow { display: grid; grid-template-columns: minmax(200px, 1.2fr) minmax(0, 2fr) 140px auto; gap: 8px 16px; align-items: center; padding: 12px 0; border-top: 1px solid var(--hair); }
.sbe-fold-b > .sbe-krow:first-child, .sbe-flat > .sbe-krow:first-child, .sbe-btlist > .sbe-krow:first-child { border-top: 0; padding-top: 0; }
.sbe-btrow { grid-template-columns: minmax(200px, 1.2fr) minmax(0, 2.4fr) auto; }
.sbe-kname { all: unset; display: grid; gap: 2px; cursor: pointer; min-width: 0; border-radius: 6px; }
.sbe-kname b { color: var(--ink); }
.sbe-kname:hover b { text-decoration: underline; }
.sbe-kname:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.sbe-kcost { display: grid; justify-items: end; }
.sbe-kact { justify-content: flex-end; }
.sbe-btlist { display: grid; }
@media (max-width: 980px) {
  .sbe-krow, .sbe-btrow { grid-template-columns: minmax(0, 1fr) auto; }
  .sbe-krow .sbe-chips { grid-column: 1 / -1; order: 3; }
  .sbe-krow .sbe-kact { grid-column: 1 / -1; order: 4; justify-content: flex-start; }
}
/* Tie to Master Items: one row per kind of item */
.sbe-tie { display: grid; grid-template-columns: minmax(180px, 1.2fr) minmax(220px, 1.4fr) minmax(0, 1fr); gap: 8px 14px; align-items: center; padding: 10px 0; border-top: 1px solid var(--hair); }
.sbe-fold-b > .sbe-tie:first-child { border-top: 0; }
.sbe-tie-t { display: grid; gap: 2px; min-width: 0; }
.sbe-tie-pick { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sbe-tie-pick .select-wrap { flex: 1 1 auto; min-width: 0; }
.sbe-untied { border-color: var(--warn-line); background: var(--warn-bg); }
.sbe-prod { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.sbe-prod .input { width: 9ch; }
.sbe-tie-items { grid-column: 1 / -1; padding: 12px; border-radius: var(--r-l); background: var(--well); display: grid; gap: 8px; }
.sbe-ti-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 4px 14px; max-height: 320px; overflow-y: auto; }
.sbe-ti { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 8px; align-items: start; padding: 6px 2px; cursor: pointer; font-size: 13px; }
.sbe-ti > .hint { grid-column: 2; }
.sbe-ti:not(:has(input)) { grid-template-columns: minmax(0, 1fr); }
.sbe-ti:not(:has(input)) > .hint { grid-column: 1; }
@media (max-width: 980px) { .sbe-tie { grid-template-columns: minmax(0, 1fr); } }
/* the cost items' every-branch grid: a spreadsheet that scrolls inside its panel, its item names held at the left */
.sbe-sheetwrap { overflow: hidden; }
.sbe-sheetwrap .table-wrap { max-height: calc(100vh - 200px - var(--tn-stuck)); }
.sbe-sheettbl th, .sbe-sheettbl td { padding: 6px 8px; }
.sbe-sheettbl thead th { position: sticky; top: 0; z-index: 2; background: var(--surface); }
.sbe-sheettbl .sbe-sticky { position: sticky; left: 0; z-index: 1; background: var(--surface); min-width: 220px; white-space: nowrap; }
.sbe-sheettbl thead .sbe-sticky { z-index: 3; }
.sbe-kindrow th { font-size: 12px; font-weight: var(--fw-x); color: var(--ink); padding-top: 14px; }
.sbe-cell { width: 92px; height: 32px; }
.sbe-cell.saved { border-color: var(--ok); box-shadow: 0 0 0 2px var(--ok-bg); }
.sbe-cell.bad { border-color: var(--bad); }

/* the builder sheet: the crew kits' Kit Builder and the Bid Template builder */
.sbe-sheet-back { position: fixed; inset: 0; z-index: 70; display: flex; padding: 16px; background: rgba(11,18,32,.3); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
html.sbe-sheet-open, html.sbe-sheet-open body { overflow: hidden; }
.sbe-sheet { flex: 1 1 auto; min-width: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); overflow: hidden; background: var(--surface); }
.sbe-sh-head { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 18px; padding: var(--pad); border-bottom: 1px solid var(--hair); }
.sbe-sh-title { flex: 1 1 520px; min-width: 0; display: grid; gap: 10px; }
.sbe-sh-title h2 { margin: 0; font-size: var(--fs-xl); font-weight: var(--fw-x); }
.sbe-sh-fields { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; }
.sbe-sh-total { display: grid; justify-items: end; gap: 0; min-width: 140px; }
.sbe-sh-total b { font-size: 22px; font-weight: var(--fw-bold); }
.sbe-sh-total > span { font-size: 12.5px; color: var(--muted); }
.sbe-sh-body { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(300px, 1fr); min-height: 0; }
.sbe-sh-main { overflow-y: auto; padding: var(--pad); display: grid; align-content: start; gap: 14px; }
.sbe-sh-pal { overflow: hidden; display: grid; grid-template-rows: auto minmax(0, 1fr); border-left: 1px solid var(--hair); background: var(--well); }
.sbe-pal-head { display: grid; gap: 8px; padding: 12px; border-bottom: 1px solid var(--hair); }
.sbe-palbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.sbe-pal { overflow-y: auto; padding: 8px; display: grid; align-content: start; gap: 4px; }
.sbe-pi { all: unset; box-sizing: border-box; display: grid; grid-template-columns: minmax(0, 1fr) auto 22px; gap: 10px; align-items: center; min-height: 40px; padding: 6px 10px;
  border-radius: var(--r-m); cursor: pointer; font-size: 13px; }
.sbe-pi:hover { background: var(--glass-a); }
.sbe-pi:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.sbe-pi.in { background: var(--glass-a); box-shadow: inset 3px 0 0 var(--accent); }
.sbe-pi-name { min-width: 0; }
.sbe-pi-name > .hint { display: block; }
.sbe-pi .badge { justify-self: end; }
.sbe-create { display: grid; gap: 6px; padding: 10px; border-top: 1px solid var(--hair); margin-top: 6px; }
.sbe-typebar { display: grid; gap: 4px; }
.sbe-typebar .hint:empty { display: none; }
.sbe-sug { left: 0; right: 0; top: 40px; max-height: 320px; overflow-y: auto; }
.sbe-sugi { height: auto !important; min-height: 40px; display: grid !important; gap: 1px; padding: 6px 10px !important; }
.sbe-sugi[aria-selected="true"] { background: var(--well); }
.sbe-sugmore { margin: 6px 10px; }
.sbe-kbg { display: grid; gap: 4px; }
.sbe-kbl { display: grid; grid-template-columns: 76px minmax(0, 1fr) auto 90px 36px; gap: 8px 10px; align-items: center; padding: 6px 0; border-top: 1px solid var(--hair); }
.sbe-kbl-name { display: grid; gap: 1px; min-width: 0; }
.sbe-qty { width: 76px; }
.sbe-kbl > .select-wrap { width: 150px; }
.sbe-ext { text-align: right; }
.sbe-btl { list-style: none; margin: 0; padding: 0; display: grid; }
.sbe-btline { display: grid; grid-template-columns: 72px minmax(0, 1fr) 84px auto 36px; gap: 8px 10px; align-items: center; padding: 8px 0; border-top: 1px solid var(--hair); }
.sbe-btl > .sbe-btline:first-child { border-top: 0; }
.sbe-btline.opt .sbe-kbl-name > span:first-child { color: var(--muted); }
.sbe-move { display: inline-flex; gap: 2px; }
.sbe-togs { display: flex; flex-wrap: wrap; gap: 6px 12px; }
.sbe-pat.on { background: var(--ink); color: var(--on-ink); }
.sbe-pat.on .hint { color: inherit; }
.sbe-brdd { position: relative; }
.sbe-brdd > summary { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 200px; cursor: pointer; list-style: none; }
.sbe-brdd > summary::-webkit-details-marker { display: none; }
.sbe-brdd[inert] > summary { background: var(--well); color: var(--muted); cursor: default; }
.sbe-brlist { top: calc(var(--ctl) + 4px); left: 0; display: grid; gap: 2px; max-height: 320px; overflow-y: auto; min-width: 260px; }
.sbe-brlist .sbe-tick { min-height: 34px; padding: 0 8px; border-radius: 8px; }
.sbe-brlist .sbe-tick:hover { background: var(--well); }
.sbe-sh-paltoggle { display: none; }
.sbe-narrow { display: none; }
@media (max-width: 980px) {
  .sbe-sheet-back { padding: 0; }
  .sbe-sheet { border-radius: 0; }
  .sbe-sh-head { padding: 12px 14px; }
  .sbe-sh-head > .actions { flex: 1 1 100%; }
  .sbe-sh-total { justify-items: start; }
  .sbe-sh-body { grid-template-columns: minmax(0, 1fr); }
  .sbe-sh-main { padding: 12px 14px 84px; }
  .sbe-sh-pal { display: none; border-left: 0; }
  .sbe-sheet.pal-open .sbe-sh-pal { display: grid; }
  .sbe-sheet.pal-open .sbe-sh-main { display: none; }
  .sbe-sh-paltoggle { display: inline-flex; position: fixed; left: 14px; right: 14px; bottom: 14px; z-index: 2; justify-content: center; height: var(--tap); }
  .sbe-sheet .sbe-t-done, .sbe-sheet.pal-open .sbe-t-add { display: none; }
  .sbe-sheet.pal-open .sbe-t-done { display: inline; }
  .sbe-wide { display: none; }
  .sbe-narrow { display: inline; }
  .sbe-pal { padding-bottom: 84px; }
}
@media (max-width: 640px) {
  .sbe-sh-head > .actions .btn { flex: 1 1 0; justify-content: center; }
  .sbe-brdd > summary { min-width: 0; }
  .sbe-kbl { grid-template-columns: 64px minmax(0, 1fr) auto; }
  .sbe-kbl > .select-wrap { grid-column: 1 / 3; width: auto; }
  .sbe-kbl .sbe-ext { grid-column: 3; grid-row: 1; }
  .sbe-kbl > .btn, .sbe-kbl > span:last-child { grid-column: 3; grid-row: 2; justify-self: end; }
  .sbe-sh-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sbe-sh-fields > .sbe-grow, .sbe-sh-fields > .sbe-span { grid-column: 1 / -1; }
  .sbe-sh-fields > .sbe-grow { order: -1; }   /* the name first, then the service and hours as a pair */
  .sbe-sh-fields > .sbe-sm { min-width: 0; }
  .sbe-btline { grid-template-columns: minmax(0, 1fr) 72px 40px; }
  .sbe-btline .sbe-move { grid-column: 1 / -1; order: -1; }
  .sbe-btline .sbe-togs { grid-column: 1 / -1; }
  .sbe-qty { width: 64px; }
}

/* Submittals */
.sbe-pkgs { display: flex; flex-wrap: wrap; gap: 8px; }
.sbe-order { list-style: none; margin: 0; padding: 0; display: grid; }
.sbe-order li { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 0; border-top: 1px solid var(--hair); }
.sbe-order li:first-child { border-top: 0; }
.sbe-slhits { display: grid; gap: 8px; max-height: 280px; overflow-y: auto; }
/* the cover page preview is paper: white and dark in both themes, like the PDF it previews */
.sbe-cover { display: grid; gap: 6px; padding: 16px; border-radius: var(--r-m); border: 1px solid var(--hair-2); background: #fff; color: #16233a; }
.sbe-cover img { height: 34px; width: auto; justify-self: start; }
.sbe-cover p { margin: 0; font-size: 12.5px; color: #4a5a73; }
.sbe-cover-t { font-size: 17px; font-weight: 800; }
.sbe-cover-c { font-weight: 700; padding-bottom: 4px; border-bottom: 1px solid #d8dee8; }
.sbe-cover ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: 13px; }
.sbe-cover li { display: flex; justify-content: space-between; gap: 8px; }
.sbe-cover li > span:last-child { color: #4a5a73; white-space: nowrap; }
/* Quote Documents: a clause or a condition group */
.sbe-clauses { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gap); }   /* stacked cards, the 16px rhythm (K4 measured 10) */
.sbe-clause { display: grid; gap: 8px; }
.sbe-clause-h { display: flex; align-items: center; gap: 8px; }
.sbe-clause-h .input { flex: 1 1 auto; min-width: 0; }
.sbe-clause-h > .sco-acts { flex: none; flex-wrap: nowrap; }   /* ▲ ▼ × keep one line: the heading's box gives way (they wrapped 2 + 1 at 1440) */
/* Master Items' parts above its screen; the request queues */
.sbe-miparts { margin-bottom: var(--gap); }
.sbe-decide { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.sbe-mergebox { display: inline-flex; align-items: center; gap: 6px; }
.sbe-mergebox .input { width: 130px; height: 32px; }
.sbe-csreq { display: grid; gap: 8px; }
.modal:has(> .sbe-city) { max-width: 720px; }
@media (max-width: 640px) { .sbe-decide, .sbe-mergebox { width: 100%; } .sbe-mergebox .input { flex: 1 1 auto; } }
.pu-sline { margin: 0; font-size: 12.5px; color: var(--muted); }   /* a line of words in a strip cell (the strip's .hint is a column) */
.pu-fsrc .qe-edit .select-wrap { flex: 1 1 200px; }

/* ---------------- Momentum › Marketing (mkt-) — public/marketing-hub.js (3.0) ----------------
   The contact card beside the compose form (two up, one under 980), the texting switch with its source, the sends. */
.mkt-two { align-items: stretch; }
.mkt-panel { display: grid; gap: 12px; align-content: start; min-width: 0; }
.mkt-panel .mo-top { margin-bottom: 0; }
.mkt-vcard { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: var(--r-l); background: var(--well); }
.mkt-logo { width: 56px; height: 56px; border-radius: 14px; object-fit: cover; background: #fff; border: 1px solid var(--hair); flex: none; }
.mkt-nologo { display: block; }
.mkt-vname { display: grid; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.mkt-vname b { font-size: var(--fs-l); }
.mkt-kv dd { overflow-wrap: anywhere; }
.mkt-kv .mkt-wide, .mkt-form .mkt-wide { grid-column: 1 / -1; }
.mkt-acts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.mkt-acts .btn { justify-content: center; }
.mkt-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; }
.mkt-chan { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.mkt-toggle { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: var(--fw-semi); color: var(--ink-2); min-height: 32px; }
.mkt-toggle label { cursor: pointer; }
.mkt-strip.mkt-one { grid-template-columns: minmax(0, 1fr); }
.mkt-prev { display: grid; gap: 6px; }
.mkt-bubble { background: var(--info-bg); color: var(--ink); border-radius: 14px; padding: 10px 14px; font-size: 14px; white-space: pre-wrap; overflow-wrap: anywhere; }
.mkt-sendrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.mkt-gate { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 4px 0 8px; }
.mkt-who { color: inherit; text-decoration: none; }
.mkt-who:hover { text-decoration: underline; }
.mkt-card { display: grid; gap: 6px; min-width: 0; }
.mkt-card-top { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 10px; }
table.t.mkt-t td { vertical-align: top; }
.mkt-modal { display: grid; gap: 12px; min-width: 0; }
.mkt-modal h2 { margin: 0; font-size: var(--fs-xl); }
.mkt-modal p { margin: 0; }
.mkt-macts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
@media (max-width: 1180px), (pointer: coarse) { .mkt-toggle { min-height: var(--tap); } }
@media (max-width: 640px) {
  .mkt-form { grid-template-columns: minmax(0, 1fr); }
  .mkt-acts { grid-template-columns: minmax(0, 1fr); }
  .mkt-macts .btn, .mkt-sendrow .btn { flex: 1 1 0; justify-content: center; }
}
.mkt-slot:empty { display: none; }   /* the compose panel's live parts take no room until they have something to say */
.mkt-form p.hint, .mkt-panel > p.hint { margin: 0; }

/* ---------------- Momentum › Customer Portal (cpl-) — public/momentum.js routes.portal (3.0) ----------------
   One link per customer and the project pages inside it; the kit's strip, filter bar, table.t → phone cards and chips do
   the work. These place the link, the projects fold and the card. */
table.t.cpl-t td { vertical-align: top; }
table.t.cpl-t td.cpl-w { min-width: 220px; }
.cpl-url { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; overflow-wrap: anywhere; word-break: break-all; }
.cpl-projs { margin-top: 0; }
.cpl-projs > summary { padding-top: 0; }
.cpl-plist { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 4px; font-size: 13px; }
.cpl-plist li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.cpl-card { display: grid; gap: 8px; min-width: 0; }
.btn.cpl-off { color: var(--bad); }

/* ---------------- Submittals (sbk-) — public/submittals.js (3.0, projtabs): one tab on the Apex job page and on the Ignite
   project's Paperwork › Submittals, so its looks live here where both workspaces load them ---------------- */
.sbk { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap); min-width: 0; }
.sbk h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.sbk p { margin: 0; }
.sbk-head { display: grid; gap: 6px; }
.sbk-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; margin-bottom: 8px; }
.sbk-head .sbk-top { margin-bottom: 0; }
.sbk-pks { display: flex; flex-wrap: wrap; gap: 8px; }
.sbk-tickh { width: 44px; }
.sbk-tick { display: inline-grid; place-items: center; cursor: pointer; }
.sbk-tick input { width: 16px; height: 16px; margin: 0; accent-color: var(--ink); }
.sbk-nowrap { white-space: nowrap; }
.sbk-who { display: inline-flex; color: inherit; text-decoration: none; vertical-align: middle; }
.sbk-req { color: var(--ok); }
.sbk-card { display: grid; gap: 6px; margin: 0; }
.sbk-cardtop { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; }
.sbk-cardtop > b { flex: 1 1 auto; min-width: 0; }
.sbk-acts { display: inline-flex; gap: 2px; margin-left: auto; }
.sbk-drop { display: grid; justify-items: center; gap: 4px; padding: 18px 14px; border: 1.5px dashed var(--hair-2); border-radius: var(--r-l); background: var(--well);
  text-align: center; cursor: pointer; transition: border-color var(--t-quick), background var(--t-quick); }
.sbk-drop:hover, .sbk-drop.over, .sbk-drop:focus-within { border-color: var(--ink); background: var(--glass-a); }
.sbk-dropmain { font-weight: var(--fw-bold); font-size: 14px; }
.sbk-list { list-style: none; margin: 0; padding: 0; display: grid; }
.sbk-list li { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 8px 10px; align-items: center; padding: 8px 0; border-top: 1px solid var(--hair); }
.sbk-list li:first-child { border-top: 0; }
.sbk-n { width: 22px; height: 22px; border-radius: 50%; background: var(--well); display: inline-grid; place-items: center; font-size: 11.5px; font-weight: var(--fw-bold); }
.sbk-what { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.sbk-flags { margin-top: 10px; }
.sbk-file { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 10px; }
.sbk-go { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.sbk-modal { display: grid; gap: 12px; }
.sbk-modal h2 { margin: 0; font-size: var(--fs-xl); }
.sbk-modal p { margin: 0; }
.sbk-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.sbk-form .wide { grid-column: 1 / -1; }
.sbk-from { min-height: var(--ctl); display: flex; align-items: center; padding: 0 12px; border-radius: var(--r-m); background: var(--well); font-size: 13px; color: var(--ink-2); }
.sbk-modalacts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
@media (max-width: 1180px), (pointer: coarse) { .sbk-tick input { width: 22px; height: 22px; } .sbk-tick { min-width: var(--tap); min-height: var(--tap); } }
@media (max-width: 640px) { .sbk-go .btn, .sbk-modalacts .btn { flex: 1 1 100%; justify-content: center; } .sbk-list li { grid-template-columns: 26px minmax(0, 1fr); } .sbk-list .sbk-acts { grid-column: 2; margin-left: 0; } }
/* inside the Apex job page's own Submittals panel: flat parts under its heading, a hairline between them */
.sbk-in { gap: 0; }
.sbk-flat { border-top: 1px solid var(--hair); }
.sbk-in > .sbk-flat:first-child { border-top: 0; padding-top: 0; }
.sbk-flat.pad { padding: 14px 0; }
.sbk-flat.phone-cards > .pad { padding: 14px 0 6px; }
.sbk-flat.strip { margin: 2px 0 16px; border: 1px solid var(--hair); border-radius: var(--r-l); }   /* 16 from the words above (the head's 14 + 2) and from the hairline under it (K4: 4 and 8) */
.sbk-in > .sbk-flat.phone-cards:has(+ .sbk-flat) { padding-bottom: 6px; }   /* the library's last row is not flush on the next part's hairline (0) */
/* Purchasing's heads carry up to four buttons: on a phone they wrap to a second row, so the Reports heads' fixed 44px
   (.mo > .page-head .actions, which keeps a one-row tab strip still) would let the next block cover that row */
@media (max-width: 1180px), (pointer: coarse) { .mo.pu > .page-head .actions { height: auto; } }
@media (max-width: 640px) { .mo.pu > .page-head .actions > .btn { flex: 1 1 calc(50% - 4px); justify-content: center; } }
/* the busy Purchasing lists (seven columns, a dropdown and a fold in a row) turn to cards on a touch iPad too, not only a phone */
@media (max-width: 1180px) {
  .pu-c1180 table.t { display: none; }
  .pu-c1180 .cards { display: flex; flex-direction: column; gap: 8px; padding: 10px; }   /* one column: a list never leaves a card alone in a row */
}
@media (max-width: 640px) {   /* a phone: a filter bar's pickers share the row, two to a row, the search above them */
  .pu-tools > .select-wrap, .cpl-tools > .select-wrap { flex: 1 1 calc(50% - 4px); min-width: 0; }
  .pu-tools > .select-wrap .select, .cpl-tools > .select-wrap .select { width: 100%; }
  .pu-card-top > div { flex: 1 1 0; min-width: 0; }
}
/* a value with its source link under it: the dd stays a block (the kit's touch rule lines a dd's pieces up in a row) */
.mkt-kv dd, .pu-kv dd { display: block; }
@media (max-width: 640px) { .mkt-kv.mo-kv { grid-template-columns: minmax(0, 1fr); } }
.sbk-open { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
/* a person's photo face (shared.js faceHTML): the picture rides in as data, --face:url(…); the same .face-img element 2.x
   styles.css sizes, so this only paints it (projtabs 10/22: the inline background-image was the one look left on it) */
.face-img { background-image: var(--face); background-size: cover; background-position: center; background-repeat: no-repeat; }

/* ---------------- Ignite › Schedule › SG&A, read-only (ssg-) — public/app.js mountSga (3.0, Jordan's decision mp-sga) ----------------
   The SG&A budget and the labor burden are set in Momentum › Budgets › SG&A (bu-); this view reads them, with the same
   month strip, cards and week calendar (bu-months, bu-card, bu-cal), and each figure links to its field there. */
.ssg-head { display: grid; gap: 12px; }
.ssg-head > * { min-width: 0; }   /* the 12-month strip is a grid: without this it pushes the panel wider than the page */
.ssg-head > p { margin: 0; }
.ssg-head .ih-top h2 { margin: 0; }   /* the panel's own padding is the space above it (2.x gives an h2 22px) */
.ssg-head .ih-top .hint { margin: 4px 0 0; }
.ssg-head .ih-top > div:first-child { flex: 1 1 300px; min-width: 0; }
.ssg-yr { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ssg-yr b { font-size: var(--fs-l); font-weight: var(--fw-x); }
.ssg-figs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.ssg-fig { display: grid; gap: 3px; align-content: start; padding: 10px 12px; border-radius: var(--r-m); background: var(--well); min-width: 0; }
.ssg-fig .label { font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.ssg-fig b { font-size: var(--fs-l); font-weight: var(--fw-x); font-variant-numeric: tabular-nums; }
.ssg-fig .src { justify-self: start; }
.ssg-warn { color: var(--warn); }
.ssg-cardsrc { display: block; margin-top: 4px; }   /* the Schedule's money cards: where the loaded % gets its SG&A, on its own line */
.bu-card > p.hint { margin: 0; }
@media (max-width: 640px) { .ssg-figs { grid-template-columns: minmax(0, 1fr); } }
/* Settings › Spend Control › Quotes vs matrix (3.0 mr-matrix): only the way to the report, which is Momentum's */
.ssp-golink { align-items: center; gap: 8px 14px; }
/* Settings › Estimating › Pipeline Weights (3.0 mr-weights, public/settings.js): eight stages, 4 → 2 → 1 across.
   Scoped to its panel: a bare .sbe-pw grid also caught Bid Site Logins' Password cell (the same class) and squeezed its Show
   button into a quarter of the cell, "ʃhov" (w11design M3). */
#pwPanel .sbe-pw { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 14px; white-space: normal; }
#pwPanel .sbe-pw .field > .hint { margin: 0; }
#pwPanel > .actions { align-items: center; margin-top: 14px; }
@media (max-width: 980px) { #pwPanel .sbe-pw { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { #pwPanel .sbe-pw { grid-template-columns: minmax(0, 1fr); } }

/* ---------------- Aimsly (agent-, ac-, af-) — public/agent-widget.js and public/aimsly-flows.js (3.0, w9shell) ----------------
   Her round button, the panel (docked, expanded, a phone's full screen), the conversation, the cards she drafts (a visit,
   "which customer?", a spreadsheet) and the two guided flows (New job, Schedule a job: numbered choices, yes / no, the review
   card, the flow's own bar over the composer). Until 3.0 these were two <style> blocks the scripts injected, on 2.x tokens.
   Every name is hers alone: #agent-*, .agent-*, .af-*, and .ac-* only inside .agent-card (approval-chart.css has its own
   .ac- names, on a page she never loads). The fields inside her cards and her box carry the kit's .input / .select /
   .textarea, so they look like every other field and 2.x's dark rule for bare boxes passes them by. */

/* the round button: 52px, 22px in from the bottom right (shared.js measures exactly that to fade her out of a control's way) */
#agent-fab { position: fixed; bottom: calc(22px + var(--fab-lift, 0px)); right: 22px; z-index: 400; width: 52px; height: 52px; padding: 0; border-radius: 50%;
  border: 1px solid var(--fab-edge); background: var(--fab-glass); color: var(--fab-ink);   /* grey frosted glass, the same in all four products: the mark was lost on the product colour (Jordan, 2026-11-02) */
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  box-shadow: inset 0 1px 0 var(--fab-edge), var(--shadow-pop); cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: transform var(--t-quick), opacity var(--t-std), bottom var(--t-std); }
#agent-fab img { width: 32px; height: auto; display: block; filter: drop-shadow(0 1px 1.5px rgba(11,18,32,.45)); }   /* the mark is ~1043x1050: width only, so it never squashes */
#agent-fab .fab-mark-night, [data-theme="dark"] #agent-fab .fab-mark-day { display: none; }   /* day mode: the A is black (agent-icon-day.png); night keeps the white A (Jordan, 2026-11-04) */
[data-theme="dark"] #agent-fab .fab-mark-night { display: block; }
#agent-fab .fab-mark-day { filter: drop-shadow(0 1px 1px rgba(255,255,255,.35)); }   /* a black A wants a light lift, not the dark one */
#agent-fab:hover { transform: translateY(-2px); }
#agent-fab:active { transform: scale(.96); }
/* nothing for her to do over a dimmed page (expanded: the header's ✕ closes), an open drawer or a pop-up */
body.agent-maxed #agent-fab, body.drawer-open #agent-fab, body:has(.modal-back) #agent-fab,
body:has(> [aria-modal="true"]:not([hidden]), > * > [aria-modal="true"]:not([hidden])) #agent-fab { display: none; }   /* any pop-up by its one mark (aria-modal): Settings' sheets sat under her (w11vault-releases #2) */
/* She is persistent (Jordan, 2026-11-02: "aimsly should be persistent on all screens"), so there is no fade for a control under her
   corner (she used to vanish until the page was scrolled, by a body class shared.js set) and no phone hide (the old max-width 640 rule, from
   2026-08-25). The page clears her instead: the shell's bottom padding, and shared.js lifts her (--fab-lift) over a bar pinned to the
   bottom. The drawer's own "Ask Aimsly" row stays: a second door. */
/* easter egg (aims-pm/EASTER-EGGS.md): she perks up at a win and droops at a loss */
#agent-fab.perk { animation: agent-perk .9s cubic-bezier(.22,1.2,.36,1) 2; }
#agent-fab.droop { animation: agent-droop 1.6s ease-in-out 1; }
@keyframes agent-perk { 0% { transform: translateY(0) rotate(0); } 35% { transform: translateY(-13px) rotate(-9deg); } 60% { transform: translateY(0) rotate(6deg); } 100% { transform: translateY(0) rotate(0); } }
@keyframes agent-droop { 0% { transform: translateY(0) rotate(0); } 30%, 70% { transform: translateY(4px) rotate(11deg); } 100% { transform: translateY(0) rotate(0); } }

/* the panel: a sheet of glass over the bottom-right corner. Heights twice on purpose: vh as the floor, then dvh, which follows
   the viewport actually on screen while a phone's address bar and keyboard come and go (Jordan, 2026-08-15). */
#agent-panel { position: fixed; bottom: 86px; right: 22px; z-index: 400; width: 380px; max-width: calc(100vw - 32px);
  height: 520px; max-height: calc(100vh - 120px); max-height: calc(100dvh - 120px); display: none; flex-direction: column; overflow: hidden;
  color: var(--ink); background: linear-gradient(150deg, var(--glass-a), var(--glass-b));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  border: 1px solid var(--glass-edge); border-radius: var(--r-xl); box-shadow: var(--shadow), var(--shadow-pop); }
#agent-panel.open { display: flex; animation: popIn var(--t-std); }
/* expanded: a big centred window rather than edge to edge, which reads badly on a wide monitor; inset + margin:auto centres it */
#agent-panel.max { inset: 0; margin: auto; width: min(1080px, 94vw); height: min(880px, 90vh); height: min(880px, 90dvh); max-width: none; max-height: none; }
#agent-backdrop { position: fixed; inset: 0; z-index: 399; display: none; background: rgba(11,18,32,.3); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
#agent-backdrop.on { display: block; }

/* her head: the mark, her name (and the costume she is wearing), read aloud, expand, close */
#agent-head { flex: none; display: flex; align-items: center; gap: 6px; padding: 9px 9px 9px 14px; border-bottom: 1px solid var(--hair); font-size: var(--fs-m); font-weight: var(--fw-bold); }
#agent-head-badge { width: 26px; height: 26px; flex: none; margin-right: 2px; border-radius: 50%; background: var(--accent); display: flex; align-items: center; justify-content: center; }
#agent-head-badge img { width: 15px; height: auto; display: block; }
#agent-head-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#agent-head-title.costume { color: var(--ink-2); }   /* "Aimsly · Pirate": a costume, not a different assistant */
.agent-head-btn { position: relative; width: 32px; height: 32px; flex: none; padding: 0; border: 0; border-radius: var(--r-s); background: transparent; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background var(--t-quick), color var(--t-quick); }
.agent-head-btn:hover { background: var(--well); color: var(--ink); }
.agent-head-btn[aria-pressed="true"] { color: var(--accent-ink); }   /* reading answers aloud is on */
.agent-head-btn svg { width: 17px; height: 17px; display: block; }

/* the conversation; an empty window says what to ask */
#agent-log { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
#agent-empty { margin: auto; padding: 0 16px; text-align: center; color: var(--muted); font-size: 13px; line-height: 1.7; }
#agent-empty b { display: block; margin-bottom: 4px; color: var(--ink); font-size: var(--fs-l); }
/* one paragraph per idea, wrapped by the browser: hard <br>s left "the schedule," alone on a phone line */
#agent-empty p { margin: 0 0 4px; text-wrap: balance; }
#agent-log.has-msgs #agent-empty { display: none; }
/* the two guided flows' way in: equal pills, a thumb's width each */
#agent-empty .agent-flows { display: flex; justify-content: center; gap: 8px; margin-top: 12px; }
#agent-empty .agent-flows button { flex: 1 1 0; max-width: 170px; min-height: 40px; padding: 0 12px; border: 1px solid var(--hair-2); border-radius: var(--r-pill);
  background: var(--glass-a); color: var(--ink); font: var(--fw-semi) 13px var(--font); cursor: pointer; transition: background var(--t-quick), box-shadow var(--t-quick); }
#agent-empty .agent-flows button:hover { background: var(--glass-hi); box-shadow: var(--shadow-pop); }
.agent-msg { max-width: 88%; padding: 8px 11px; border-radius: var(--r-l); color: var(--ink); font-size: 13px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
.agent-msg.user { align-self: flex-end; border-bottom-right-radius: 6px; background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }
.agent-msg.assistant { align-self: flex-start; position: relative; padding-right: 30px; border-bottom-left-radius: 6px; background: var(--surface); border: 1px solid var(--hair); }
.agent-msg.pending { color: var(--muted); font-style: italic; }
.agent-msg strong { font-weight: var(--fw-bold); }
.agent-link { color: var(--accent-ink); font-weight: var(--fw-semi); text-decoration: underline; text-underline-offset: 2px; }
/* a hanging indent, so a wrapped bullet lines up under its own words, not under the dash */
.agent-msg .agent-list { margin: 6px 0; padding-left: 1.3em; }
.agent-msg .agent-list:first-child { margin-top: 0; }
.agent-msg .agent-list li { margin: 3px 0; padding-left: 2px; }
/* every finished answer keeps its own read-aloud button; touch has no hover, so there it stays in sight */
.agent-say { position: absolute; right: 4px; bottom: 4px; width: 22px; height: 22px; padding: 3px; border: 0; border-radius: 6px; background: none; color: var(--muted);
  cursor: pointer; opacity: 0; transition: opacity var(--t-quick), color var(--t-quick); }
.agent-msg.assistant:hover .agent-say, .agent-say:focus-visible { opacity: 1; }
.agent-say:hover { color: var(--accent-ink); }
.agent-say svg { width: 100%; height: 100%; display: block; }
@media (hover: none) { .agent-say { opacity: .6; } }
#agent-panel.max #agent-log { padding: 18px 22px; gap: 14px; }
#agent-panel.max .agent-msg { max-width: min(88%, 76ch); font-size: 14px; }   /* a wider window, but prose capped at a readable column */

/* the composer: her box (.textarea), the mic where the browser can listen, Send */
#agent-form { flex: none; display: flex; align-items: flex-end; gap: 8px; padding: 10px; border-top: 1px solid var(--hair); }
#agent-input { flex: 1; min-width: 0; height: auto; min-height: var(--ctl); max-height: 90px; padding: 8px 12px; resize: none; line-height: 1.45; field-sizing: content; }
#agent-panel.max #agent-input { max-height: 200px; }
#agent-panel.max #agent-form { padding: 14px 22px; }
#agent-mic, #agent-send { flex: none; height: var(--ctl); border-radius: var(--r-m); cursor: pointer; transition: background var(--t-quick), transform var(--t-quick); }
#agent-mic { width: 40px; padding: 0; border: 1px solid var(--hair-2); background: var(--glass-a); color: var(--ink-2); display: grid; place-items: center; }
#agent-mic:hover { background: var(--glass-hi); }
#agent-mic svg { width: 18px; height: 18px; }
#agent-mic.on { background: var(--bad); border-color: var(--bad); color: var(--on-accent); animation: agent-mic-pulse 1.2s ease-in-out infinite; }
@keyframes agent-mic-pulse { 50% { opacity: .7; } }
#agent-send { padding: 0 16px; border: 0; background: var(--ink); color: var(--on-ink); font: var(--fw-bold) 13px var(--font); box-shadow: var(--shadow-btn); }
#agent-send:active { transform: scale(.97); }
#agent-send:disabled { opacity: .5; cursor: default; transform: none; }

/* her cards, inside an answer: a drafted visit, "which customer?", a spreadsheet to download */
.agent-card { display: grid; gap: 8px; margin-top: 8px; padding: 10px 12px; border: 1px solid var(--hair-2); border-radius: var(--r-m); background: var(--surface-2);
  white-space: normal; container-type: inline-size; }
.agent-msg.assistant:has(.agent-card) { width: 100%; max-width: 100%; padding-right: 11px; padding-bottom: 32px; }
#agent-panel.max .agent-msg.assistant:has(.agent-card) { width: min(100%, 76ch); max-width: 100%; }
.agent-card .ac-h { font-weight: var(--fw-bold); }
.agent-card .ac-br { font-weight: var(--fw-reg); color: var(--muted); white-space: nowrap; }   /* the visit's branch, after its customer */
.agent-card label { display: grid; gap: 4px; margin: 0; font-size: 12px; font-weight: var(--fw-semi); color: var(--ink-2); }
.agent-card .ac-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
@container (max-width: 299px) { .agent-card .ac-row { grid-template-columns: minmax(0, 1fr); } }
.agent-card :is(.input, .select, .textarea) { min-width: 0; }
.agent-card .textarea { min-height: 84px; }
.agent-card :is(.input, .select, .textarea):disabled { background: var(--well); color: var(--muted); }
.agent-card .ac-go { justify-self: end; min-height: var(--ctl); padding: 0 14px; border: 0; border-radius: var(--r-m); background: var(--ink); color: var(--on-ink);
  font: var(--fw-bold) 13px var(--font); box-shadow: var(--shadow-btn); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  text-decoration: none; transition: transform var(--t-quick); }
.agent-card .ac-go:hover { text-decoration: none; transform: translateY(-1px); }
.agent-card .ac-go:disabled { opacity: .5; cursor: default; transform: none; }
.agent-card.saved { border-color: var(--ok-line); }
.agent-card .ac-pick { display: grid; gap: 6px; }
.agent-card .ac-choice { min-height: 40px; padding: 8px 10px; border: 1px solid var(--hair-2); border-radius: var(--r-m); background: var(--surface); color: var(--ink);
  font: var(--fw-med) 14px var(--font); text-align: left; cursor: pointer; transition: border-color var(--t-quick); }
.agent-card .ac-choice:hover:not(:disabled) { border-color: var(--ink); }
.agent-card .ac-choice:disabled { opacity: .55; cursor: default; }
.agent-card .ac-choice .ac-city { color: var(--muted); }
.agent-card .ac-choice.ac-new { color: var(--accent-ink); font-weight: var(--fw-semi); }
.agent-card .ac-newform:not([hidden]) { display: grid; gap: 8px; }
.agent-file .ac-go { justify-self: start; display: block; max-width: 100%; line-height: var(--ctl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-card .ac-sub { font-size: 12px; color: var(--muted); }
.agent-card .ac-done { color: var(--ok); font-weight: var(--fw-semi); }
.agent-card .ac-done a { color: inherit; text-decoration: underline; }

/* the guided flows (aimsly-flows.js): her prompts and what she heard, numbered choices, yes / no, the review card */
.agent-msg.af-msg { white-space: normal; }
.af-msg p { margin: 0; }
.af-msg p + p { margin-top: 6px; }
.af-said { font-weight: var(--fw-semi); overflow-wrap: anywhere; }
.af-said.af-ok { color: var(--ok); }
.af-said.af-warn { color: var(--bad); }
.af-hint { font-size: 12px; color: var(--muted); }
.agent-msg.af-msg:has(.af-opts, .af-yn, .agent-card) { width: 100%; max-width: 100%; padding-right: 11px; padding-bottom: 32px; }
#agent-panel.max .agent-msg.af-msg:has(.af-opts, .af-yn, .agent-card) { width: min(100%, 76ch); }
.af-opts { display: grid; gap: 6px; margin-top: 8px; }
.af-opt { display: flex; align-items: center; gap: 10px; width: 100%; min-height: var(--tap); padding: 8px 10px; border: 1px solid var(--hair-2); border-radius: var(--r-m);
  background: var(--surface-2); color: var(--ink); font: var(--fw-med) 14px var(--font); text-align: left; cursor: pointer; transition: border-color var(--t-quick); }
.af-opt:hover:not(:disabled) { border-color: var(--ink); }
.af-opt .af-n { flex: 0 0 26px; height: 26px; border-radius: 50%; background: var(--ink); color: var(--on-ink); font-size: 12.5px; font-weight: var(--fw-bold); display: grid; place-items: center; }
.af-opt .af-t { min-width: 0; overflow-wrap: anywhere; }
.af-opt .af-s { display: block; font-size: 12px; color: var(--muted); }
.af-yn { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 8px; }
.af-yn button, .af-links a { min-height: var(--tap); padding: 0 12px; border: 1px solid var(--hair-2); border-radius: var(--r-m); background: var(--surface-2); color: var(--ink);
  font: var(--fw-semi) 14px var(--font); cursor: pointer; transition: border-color var(--t-quick); }
.af-yn button:hover:not(:disabled), .af-links a:hover { border-color: var(--ink); text-decoration: none; }
.af-yn button:first-child { background: var(--ink); border-color: var(--ink); color: var(--on-ink); box-shadow: var(--shadow-btn); }   /* the yes */
.af-msg button:disabled { opacity: .5; cursor: default; }
.af-list { margin: 6px 0 0; padding-left: 1.2em; font-size: 13px; }
.af-list li { margin: 2px 0; }
.af-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.af-links a { display: inline-flex; align-items: center; text-decoration: none; color: var(--accent-ink); }
/* the review card (an .agent-card, so it has the visit card's fields and container query) */
.af-review .af-rows { display: grid; gap: 10px; }
.af-review .af-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; row-gap: 3px; align-items: center; }
.af-review .af-l { display: block; grid-column: 1 / -1; margin: 0; font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); }   /* block: the grid label would drop the star onto its own line */
.af-review .af-row.af-req .af-l::after { content: ' *'; color: var(--bad); }
.af-review .af-v { min-width: 0; overflow-wrap: anywhere; }
.af-review .af-v.af-empty { color: var(--muted); font-style: italic; }
.af-review .af-row > :is(input, select, textarea) { grid-column: 1 / -1; }
.af-review .af-n2 { grid-column: 1 / -1; font-size: 12px; color: var(--muted); }
.af-review .af-n2.af-need { color: var(--bad); }
.af-review .af-change { min-height: var(--ctl); padding: 0 12px; border: 1px solid var(--hair-2); border-radius: var(--r-m); background: var(--surface); color: var(--ink);
  font: var(--fw-semi) 13px var(--font); cursor: pointer; transition: border-color var(--t-quick); }
.af-review .af-change:hover:not(:disabled) { border-color: var(--ink); }
.af-review .af-fixed { padding-top: 10px; border-top: 1px dashed var(--hair-2); gap: 8px; }
/* the values v1 does not ask for: label beside value, so the defaults do not bury Create */
.af-review .af-fixed .af-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); align-items: start; }
.af-review .af-fixed .af-l { grid-column: 1; grid-row: span 2; }
.af-review .af-fixed .af-v { grid-column: 2; font-size: 13px; }
.af-review .af-fixed .af-n2 { grid-column: 2; margin-top: -2px; }
.af-review .af-warns { display: grid; gap: 4px; }
.af-review .af-warns:empty { display: none; }
.af-review .af-warns div { font-size: 13px; font-weight: var(--fw-semi); color: var(--bad); overflow-wrap: anywhere; }
.af-review .af-create { justify-self: stretch; min-height: var(--tap); font-size: 15px; }
.af-review .af-missing { font-size: 12px; color: var(--muted); text-align: center; }
.af-review .af-missing:empty { display: none; }
/* the flow's own controls, pinned over the composer while a flow runs: where it is, Back / Start over / Stop */
.af-bar { flex: none; display: grid; gap: 6px; padding: 8px 10px 0; border-top: 1px solid var(--hair); }
.af-bar .af-where { font-size: 12px; font-weight: var(--fw-semi); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.af-bar .af-ctl { display: flex; gap: 6px; }
.af-bar .af-ctl button { flex: 1 1 0; min-width: 0; min-height: 40px; padding: 0 6px; border: 1px solid var(--hair-2); border-radius: var(--r-m); background: var(--glass-a); color: var(--ink);
  font: var(--fw-semi) 13px var(--font); cursor: pointer; transition: background var(--t-quick), border-color var(--t-quick); }
.af-bar .af-ctl button:hover:not(:disabled) { border-color: var(--ink); background: var(--glass-hi); }
#agent-panel.max .af-bar { padding: 10px 22px 0; }

/* touch (phones and touch iPads): every control a thumb's reach; the head's 32px buttons reach 44 */
@media (max-width: 1180px), (pointer: coarse) {
  .agent-head-btn::after { content: ""; position: absolute; inset: -6px; }
  #agent-empty .agent-flows button, .agent-card .ac-go, .agent-card .ac-choice, .af-bar .af-ctl button, .af-review .af-change { min-height: var(--tap); }
  .agent-card :is(.input, .select) { height: var(--tap); }   /* as tall as the Change button beside them */
  .agent-file .ac-go { line-height: var(--tap); }
  #agent-mic { width: var(--tap); height: var(--tap); }
  #agent-send { height: var(--tap); }
  #agent-input { min-height: var(--tap); }
}
/* a phone: the docked panel pinned to both side margins and sized off the live viewport; expanded is the whole screen */
@media (max-width: 700px) {
  #agent-panel { left: 12px; right: 12px; width: auto; max-width: none; bottom: calc(80px + env(safe-area-inset-bottom));
    height: 70vh; height: 70dvh; max-height: calc(100vh - 150px); max-height: calc(100dvh - 150px); }
  #agent-panel.max { inset: 0; margin: 0; width: 100%; height: 100vh; height: 100dvh; max-height: none; border: 0; border-radius: 0; }
  #agent-panel.max #agent-log { padding: 14px 16px; }
  #agent-panel.max #agent-form { padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); }
  #agent-panel.max .agent-msg { max-width: 92%; }
  #agent-form { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }   /* the composer stays reachable with a keyboard up; the transcript gives way */
}
/* her box rests at two lines on a phone, so the placeholder that needs two is never cut off; typing still grows it */
@media (max-width: 900px) { #agent-input { min-height: calc(2.9em + 18px); } }
/* toasts clear her button on a computer (at 1180px and under they sit at the TOP, centred, so they are nowhere near either circle: w40 measured it
   at 375, 820, 1180, 1181 and 1440 in test-w38.js H, Jordan 11/2) */
@media (min-width: 1181px) { body.has-aimsly .toast { right: 88px; } }
@media print { #agent-fab, #agent-panel, #agent-backdrop { display: none !important; } }
@media (prefers-reduced-motion: reduce) { #agent-fab.perk, #agent-fab.droop, #agent-mic.on, #agent-panel.open { animation: none; } #agent-fab, .drop-btn { transition: none; } }
[data-theme="dark"] .agent-head-btn:hover { background: rgba(255,255,255,.06); }

/* ---------------- Celebrations (cel-) — public/celebrate.js, the eggs' own looks (EASTER-EGGS.md; 3.0, w9shell) ----------------
   The party itself is drawn on one canvas; this is the furniture round it: the canvas, the guest-star clip, the odometer,
   the camera flash, the wordmark's colours and its hunt chip, the shout bubble, and the launch (the filmed clip, the drawn
   rocket, the how-to card). What is worked out per run — a puff's place and drift, a star's twinkle, a bubble's spot, the
   flash's pulse — rides in --custom-properties; the colours of the egg art (the rocket, the dust, the moon, the gold digits,
   the white flash) are the eggs' own. Nothing here takes a tap except the clip (tap it away) and the launch card.
   The stacking order is the eggs' since 2.x: clip and odometer 9997, canvas 9998, flash 9999, bubble 99999, card 100000,
   the launch over everything. */
.cel-cv { position: fixed; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; z-index: 9998; }   /* %, not vw: no scrollbar of its own */

/* the guest-star clip (celebrate.gif / a win over $50k): framed, just above the word, faded in on load, tapped away */
.cel-gif { position: fixed; left: 50%; bottom: calc(28% + 54px); transform: translateX(-50%) scale(.9); max-width: min(400px, 66vw); max-height: 38vh;
  border-radius: var(--r-l); border: 3px solid #fff; z-index: 9997; opacity: 0; cursor: pointer; box-shadow: 0 18px 50px rgba(8,18,38,.45);
  transition: opacity .3s, transform .3s; }
.cel-gif.on { opacity: 1; transform: translateX(-50%) scale(1); }
.cel-gif.out { opacity: 0; transform: translateX(-50%) scale(.94); }

/* the odometer (a truck crossing a 100k mark): a dark reel of cells, gold digits; .on rolls each strip up four turns of
   0–9 to its own digit (the 41st row, 40 × 56px), --i places it so the roll settles left to right */
.cel-odo { position: fixed; left: 50%; top: 38%; transform: translate(-50%, -50%) scale(.86); z-index: 9997; display: flex; flex-direction: column;
  align-items: center; gap: 10px; opacity: 0; pointer-events: none; transition: opacity .35s, transform .35s; }
.cel-odo.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.cel-odo.out { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
.cel-odo-reel { display: flex; gap: 4px; padding: 14px 16px; border-radius: var(--r-l); background: rgba(11,18,32,.94); border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 18px 50px rgba(8,18,38,.5); }
.cel-odo-cell { width: 38px; height: 56px; overflow: hidden; border-radius: 7px; background: #060A12; box-shadow: inset 0 3px 8px rgba(0,0,0,.6); }
.cel-odo-strip { display: flex; flex-direction: column; font: var(--fw-x) 40px/56px var(--font); font-variant-numeric: tabular-nums; color: #FFD166; text-align: center;
  transition: transform 1.5s cubic-bezier(.16,.84,.28,1); transition-delay: calc(var(--i, 0) * 90ms); }
.cel-odo-strip > div { flex: 0 0 56px; }
.cel-odo.on .cel-odo-strip { transform: translateY(-2240px); }
.cel-odo-cap { font: var(--fw-x) 15px var(--font); letter-spacing: .1em; color: #fff; background: rgba(11,18,32,.9); padding: 7px 16px; border-radius: var(--r-pill); }

/* the camera flash (five fast theme flips): a white sheet; celebrate.js pulses --o twice, each with its own --tr / --ease.
   Two pulses, never a strobe (WCAG 2.3.1), and none at all under reduced motion — the script never makes it then. */
.cel-flash { position: fixed; left: 0; top: 0; width: 100%; height: 100%; background: #fff; pointer-events: none; z-index: 9999;
  opacity: var(--o, 0); transition: opacity var(--tr, 70ms) var(--ease, linear); }

/* the wordmark (seven taps): a plain cursor, the next product's colour from the tokens (data-product on the element; the
   page's data-theme copied onto it brings the dark shade), and the hunt's chip under it (frame.js copies it to the top bar) */
.pname[data-egg] { cursor: default; }
.cel-hunt { margin-top: 6px; padding: 5px 8px; border-radius: 7px; background: var(--ink); color: var(--on-ink); text-align: center; white-space: nowrap;
  font: var(--fw-x) 11px/1 var(--font); letter-spacing: .22em; }

/* typing a whole sentence in capitals: an ink bubble just above the box, placed by --x / --y */
.cel-shout { position: fixed; left: var(--x, 12px); top: var(--y, 8px); z-index: 99999; pointer-events: none; padding: 8px 13px; border-radius: 11px;
  background: var(--ink); color: var(--on-ink); font: var(--fw-semi) 13px/1.35 var(--font); box-shadow: var(--shadow-pop);
  opacity: 0; transform: translateY(6px); transition: opacity .18s, transform .18s; }
.cel-shout.on { opacity: 1; transform: none; }
.cel-shout.out { opacity: 0; }

/* the launch's how-to card (a major release, office logins): an ink card bottom centre, the one part of the launch you can click */
.cel-watch { position: fixed; left: 50%; bottom: max(22px, env(safe-area-inset-bottom)); z-index: 100000; display: flex; align-items: center; gap: 6px;
  width: max-content; max-width: calc(100vw - 32px); padding: 6px 6px 6px 16px; border-radius: var(--r-l); border: 1px solid var(--hair-2);
  background: var(--ink); color: var(--on-ink); box-shadow: var(--shadow-pop); font: var(--fw-semi) 15px/1.35 var(--font);
  opacity: 0; transform: translate(-50%, 20px); transition: opacity .4s, transform .4s; }
.cel-watch.on { opacity: 1; transform: translate(-50%, 0); }
.cel-watch a { color: inherit; text-decoration: none; padding: 8px 0; }
.cel-watch a:hover { text-decoration: underline; }
.cel-watch button { flex: none; width: 40px; height: 40px; padding: 0; border: 0; border-radius: var(--r-m); background: transparent; color: inherit; font-size: 16px; cursor: pointer; }
.cel-watch button:hover { background: color-mix(in srgb, var(--on-ink) 14%, transparent); }
@media (max-width: 1180px), (pointer: coarse) { .cel-watch button { width: var(--tap); height: var(--tap); } }
@media (max-width: 900px) { .cel-watch { bottom: calc(86px + env(safe-area-inset-bottom)); } }   /* clear of the menu drop and the action bars */

/* the launch (a major release): the whole screen goes to night; the filmed clip (.cel-rkv), or the drawn rocket lifting
   off its pad, its dust filling the screen, then the moon and the words out of the dust */
.cel-rk { position: fixed; inset: 0; z-index: 2147483000; pointer-events: none; overflow: hidden; opacity: 0; transition: opacity .45s ease;
  background: radial-gradient(130% 100% at 50% 100%, #1d3263 0%, #0b1631 48%, #04070f 100%); font-family: var(--font); }
.cel-rk.on { opacity: 1; }
.cel-rk.off { opacity: 0; transition: opacity 1.1s ease; }
.cel-rk-st { position: absolute; left: var(--x); top: var(--y); width: 2px; height: 2px; border-radius: 50%; background: #fff;
  animation: celTw 1.8s ease-in-out var(--d, 0s) infinite alternate; }
.cel-rk-st.big { width: 3px; height: 3px; }
@keyframes celTw { from { opacity: .2; } to { opacity: 1; } }
.cel-rk-site { position: absolute; inset: 0; transition: opacity .6s; }
.cel-rk-site.gone { opacity: 0; }
.cel-rk-ground { position: absolute; left: 0; right: 0; bottom: 0; height: 13vh; background: linear-gradient(#2a3653, #121a2b); }
.cel-rk-tower { position: absolute; left: calc(50% + 70px); bottom: 13vh; width: 16px; height: min(46vh, 360px);
  background: repeating-linear-gradient(45deg, #5a667d 0 3px, transparent 3px 12px), repeating-linear-gradient(-45deg, #5a667d 0 3px, transparent 3px 12px);
  border-left: 3px solid #6b778d; border-right: 3px solid #6b778d; }
.cel-rk-pad { position: absolute; left: 50%; bottom: 13vh; width: 190px; height: 14px; margin-left: -95px; background: #6b778d; border-radius: 3px; }
.cel-rk-ship { position: absolute; z-index: 2; left: 50%; bottom: calc(13vh + 14px - 100px); width: 150px; height: 390px; margin-left: -75px; }
.cel-rk-ship svg { overflow: visible; }
.cel-rk-ship.hide { visibility: hidden; }
.cel-rk-ship .cel-rk-fire { transform-box: fill-box; transform-origin: 50% 0; opacity: 0; transition: opacity .2s; }
.cel-rk-ship.lit .cel-rk-fire { opacity: 1; animation: celFl .07s ease-in-out infinite alternate; }
.cel-rk-ship.shake { animation: celShake .07s linear infinite; }
.cel-rk-ship.go { animation: celUp 2.6s cubic-bezier(.55,0,.8,.35) forwards; }
@keyframes celUp { 0% { transform: translateY(0); } 6% { transform: translate(1px, -.5vh); } 12% { transform: translate(-1px, -1.5vh); } 100% { transform: translateY(-135vh); } }
@keyframes celShake { 0% { transform: translate(0, 0); } 25% { transform: translate(-2px, 1px); } 50% { transform: translate(2px, 0); } 75% { transform: translate(-1px, -1px); } 100% { transform: translate(0, 0); } }
@keyframes celFl { from { transform: scaleY(.8) scaleX(.92); } to { transform: scaleY(1.25) scaleX(1.06); } }
.cel-rk-puffs { position: absolute; inset: 0; z-index: 1; transition: opacity 2.8s ease; }
.cel-rk-puffs.fade { opacity: 0; }
.cel-rk-puff { position: absolute; left: var(--x); top: var(--y); width: var(--size); height: var(--size); border-radius: 50%;
  background: radial-gradient(circle, rgba(206,198,184,.95) 0%, rgba(186,178,164,.75) 45%, rgba(170,162,150,0) 70%);
  animation: celPuff var(--t, 2.4s) ease-out forwards; }
@keyframes celPuff { from { transform: translate(-50%, -50%) scale(.25); opacity: .95; }
  to { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(var(--s, 3)); opacity: var(--o, .9); } }
.cel-rk-dust { position: absolute; inset: 0; z-index: 3; background: radial-gradient(120% 90% at 50% 60%, #cfc6b6 0%, #b3a995 55%, #8e8574 100%); opacity: 0; transition: opacity 1.2s ease; }
.cel-rk-dust.on { opacity: 1; }
.cel-rk-dust.thin { opacity: .5; transition: opacity 2.6s ease; }
.cel-rk-moon { position: absolute; z-index: 4; left: 50%; top: 9vh; width: min(26vw, 170px); height: min(26vw, 170px); margin-left: calc(min(26vw, 170px) / -2); border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fffbe8 0%, #f3e9c6 45%, #d8c99a 100%); box-shadow: 0 0 80px 26px rgba(255,244,200,.35); opacity: 0; transform: scale(.8); transition: all 2s ease; }
.cel-rk-moon.on { opacity: 1; transform: none; }
.cel-rk-moon i { position: absolute; left: var(--x); top: var(--y); width: var(--s); height: var(--s); border-radius: 50%; background: rgba(160,140,90,.35); }
.cel-rk-cd { position: absolute; z-index: 6; left: 50%; top: 40%; transform: translate(-50%, -50%); font-size: min(26vw, 190px); font-weight: var(--fw-x); color: #fff;
  text-shadow: 0 0 30px rgba(120,180,255,.8); animation: celCd .9s ease-out forwards; }
@keyframes celCd { from { transform: translate(-50%, -50%) scale(1.7); opacity: 0; } 25% { opacity: 1; } to { transform: translate(-50%, -50%) scale(.9); opacity: 0; } }
.cel-rk-say { position: absolute; z-index: 5; left: 0; right: 0; top: calc(9vh + min(26vw, 170px) + 4vh); text-align: center; padding: 0 18px; color: #fff; }
.cel-rk-say > div { opacity: 0; filter: blur(14px); transform: scale(1.08); transition: opacity 1.4s ease, filter 1.6s ease, transform 1.6s ease;
  text-shadow: 0 2px 18px rgba(20,20,30,.55), 0 0 2px rgba(20,20,30,.6); }
.cel-rk-say > div.on { opacity: 1; filter: none; transform: none; }
.cel-rk-v { font-size: min(5vw, 22px); font-weight: var(--fw-x); letter-spacing: .3em; color: #fff3c9; }
.cel-rk-a { margin-top: 10px; font-size: min(11vw, 76px); font-weight: var(--fw-x); line-height: 1.05; }
.cel-rk-b { margin-top: 18px; font-size: min(6vw, 34px); font-weight: var(--fw-semi); color: #fffaf0; }
/* the filmed launch: the clip full screen, the words low over its dust */
.cel-rkv { background: #000; }
.cel-rkv video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cel-rkv .cel-rk-say { top: auto; bottom: 16vh; }

/* ---------------- the bell, tasks, messages and a record's discussion (public/notify.js, 3.0 w9shell) ----------------
   One inbox in three tabs under the bell (Notifications · Tasks · Messages), its three pages (#/notifications, #/tasks,
   #/messages), the task dialog, a direct message, and the thread beside an Apex quote and an Ignite project.
   Built under the names notify.js has always used (they are its own); a message in a thread is .nfy-msg and a tag in it
   .nfy-mention, because a bare .msg and .mention are other screens' words. New pieces are nfy-. Every rule here names its
   parent (.notif-panel …, .thread …) so it outweighed styles.css's two-class rules on the same names (styles.css was deleted in w10retire). */

/* the count on the bell and on the messages button, ringed off the bar; notify.js empties and hides it at nought */
#notifBtn, #chatBtn { position: relative; overflow: visible; }
.tb .notif-dot, .notif-dot { position: absolute; top: 3px; right: 2px; min-width: 16px; height: 16px; padding: 0 4px; border: 0; border-radius: var(--r-pill);
  background: var(--bad); color: #fff; font-size: 9.5px; font-weight: var(--fw-x); line-height: 1; letter-spacing: 0; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 0 0 2px var(--surface); pointer-events: none; }
.notif-dot:empty { display: none; }
:root[data-theme="dark"] .notif-dot { color: var(--on-ink); border: 0; box-shadow: 0 0 0 2px var(--surface); }   /* dark text on dark mode's light red */
@media (max-width: 1180px), (pointer: coarse) { .tb .notif-dot { top: 5px; right: 4px; } }
/* the drawer's own Messages row (paintChatNav): a phone's door to /chat, where the top bar has no room for the button */
#nav a.nav-msgs { display: none; }
@media (max-width: 640px) { #nav a.nav-msgs { display: flex; } }
#nav a .nav-msgs-n { margin-left: auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-pill); box-sizing: border-box;
  background: var(--bad); color: #fff; font-size: 11px; font-weight: var(--fw-x); line-height: 20px; text-align: center; }
#nav a .nav-msgs-n[hidden] { display: none; }

/* the panel: a sheet of glass hung from the bell (notify.js writes where: --np-top, --np-right, and --np-ox, the bell's centre) */
.notif-panel, :root[data-theme="dark"] .notif-panel { position: fixed; z-index: 90; top: var(--np-top, 64px); right: var(--np-right, 12px); left: auto;
  width: 392px; max-width: calc(100vw - 16px); max-height: calc(100vh - var(--np-top, 64px) - 12px); display: flex; flex-direction: column; overflow: hidden; padding: 0;
  background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); border: 1px solid var(--glass-edge); border-radius: var(--r-xl); box-shadow: var(--shadow-pop), var(--shadow);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  transform-origin: var(--np-ox, 100%) top; animation: popIn var(--t-std); }
@media (prefers-reduced-transparency: reduce) { .notif-panel, :root[data-theme="dark"] .notif-panel { background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none; } }
.notif-panel .notif-tabs { display: flex; align-items: center; gap: 2px; padding: 4px 8px 0 10px; border-bottom: 1px solid var(--hair); flex: none; overflow-x: auto; scrollbar-width: none; flex-wrap: nowrap; }
.notif-panel .notif-tabs::-webkit-scrollbar { display: none; }
.notif-panel .notif-tab { position: relative; flex: none; display: inline-flex; align-items: center; gap: 6px; height: 40px; min-height: 0; padding: 0 9px; margin: 0 0 -1px;
  border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none; color: var(--muted); font: var(--fw-semi) 13px var(--font); white-space: nowrap; cursor: pointer;
  transition: color var(--t-quick), border-color var(--t-quick); }
.notif-panel .notif-tab:hover { color: var(--ink); }
.notif-panel .notif-tab.active { color: var(--ink); border-bottom-color: var(--accent); }
.notif-tab-n { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; margin: 0; border-radius: var(--r-pill);
  background: var(--well); color: var(--ink-2); font-size: 10.5px; font-weight: var(--fw-x); line-height: 1; font-variant-numeric: tabular-nums; }
.notif-panel .notif-tab.active .notif-tab-n { background: var(--ink); color: var(--on-ink); }
.notif-panel .notif-tabs .notif-expand { position: static; flex: none; margin-left: auto; width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--r-s); background: transparent; color: var(--muted); cursor: pointer; }
.notif-panel .notif-tabs .notif-expand:hover { background: var(--well); color: var(--ink); }
.notif-panel .notif-subhead { display: flex; justify-content: flex-end; padding: 6px 10px 0; flex: none; }
.notif-panel .notif-list { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; overscroll-behavior: contain; }
.notif-panel .notif-empty, .nfy-none { color: var(--muted); text-align: center; padding: 28px 18px; font-size: 13px; }
.notif-panel .notif-foot { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 42px; padding: 0 14px; border: 0; border-top: 1px solid var(--hair); flex: none;
  background: transparent; color: var(--accent-ink); font: var(--fw-bold) 12.5px var(--font); cursor: pointer; }
.notif-panel .notif-foot:hover { background: var(--well); }
.notif-panel .notif-foot-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px; border-top: 1px solid var(--hair); flex: none; }

/* a row: what happened, when and who — the unread ones lit by the product's colour down their edge */
:is(.notif-panel, .nfy-panel) .notif-item { position: relative; display: flex; align-items: flex-start; gap: 10px; padding: 11px 10px 11px 14px; border-bottom: 1px solid var(--hair);
  background: transparent; cursor: pointer; transition: background var(--t-quick); }
:is(.notif-panel, .nfy-panel) .notif-item:last-child { border-bottom: 0; }
:is(.notif-panel, .nfy-panel) .notif-item:hover { background: var(--well); }
:is(.notif-panel, .nfy-panel) .notif-item:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
/* unread is news, so it wears the kit's info blue in every product (Ignite's red would read as something wrong, and an
   overdue task's edge is already red) */
:is(.notif-panel, .nfy-panel) .notif-item.unread { background: color-mix(in srgb, var(--info) 6%, transparent); }
:is(.notif-panel, .nfy-panel) .notif-item.unread:hover { background: color-mix(in srgb, var(--info) 10%, transparent); }
:is(.notif-panel, .nfy-panel) .notif-item.unread::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--info); }
.notif-item .notif-i { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--muted); }
.notif-item.unread .notif-i { color: var(--info); }
.notif-item .notif-txt { min-width: 0; flex: 1; }
.notif-item .notif-title { font-size: 13px; font-weight: var(--fw-bold); line-height: 1.35; color: var(--ink); }
.notif-item .notif-body { font-size: 12.5px; color: var(--muted); margin-top: 2px; overflow-wrap: anywhere; }
.notif-item .notif-when { font-size: 11.5px; color: var(--faint); margin-top: 3px; }
/* dismiss / remove: a quiet ✕ that shows on the row a mouse is over; on touch it is always there, with a thumb's reach */
:is(.notif-item, .task-item) .notif-x { flex: none; width: 28px; height: 28px; min-width: 0; min-height: 0; padding: 0; margin: -4px -2px 0 0; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--r-s); background: transparent; color: var(--faint); cursor: pointer; opacity: 0; position: relative; transition: opacity var(--t-quick), background var(--t-quick), color var(--t-quick); }
:is(.notif-item, .task-item):is(:hover, :focus-within) .notif-x { opacity: 1; }
:is(.notif-item, .task-item) .notif-x:hover { background: var(--bad-bg); color: var(--bad); }
@media (hover: none), (max-width: 1180px) {
  :is(.notif-item, .task-item) .notif-x { opacity: 1; }
  :is(.notif-item, .task-item) .notif-x::after { content: ""; position: absolute; inset: -8px; }
  .notif-panel .notif-tab { height: var(--tap); }
  .notif-panel .notif-tabs .notif-expand { width: var(--tap); height: var(--tap); }
  .notif-panel .notif-foot { min-height: var(--tap); }
}

/* a task: tick it off where it stands; the rest is what you need to decide to */
.task-list { display: flex; flex-direction: column; }
:is(.notif-panel, .nfy-panel, .task-list) .task-item { position: relative; display: flex; align-items: flex-start; gap: 10px; padding: 11px 10px 11px 14px; border-bottom: 1px solid var(--hair);
  background: transparent; opacity: 1; transition: background var(--t-quick), opacity var(--t-std); }
:is(.notif-panel, .nfy-panel, .task-list) .task-item:last-child { border-bottom: 0; }
:is(.notif-panel, .nfy-panel, .task-list) .task-item:hover { background: var(--well); }
:is(.notif-panel, .nfy-panel, .task-list) .task-item.overdue::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--bad); }
:is(.notif-panel, .nfy-panel, .task-list) .task-item.done { color: var(--muted); }   /* faded (K5): see "faded rows" */
/* ---------------- faded rows: archived, inactive, void, lapsed, done (w11design K5) ----------------
   Whole rows at opacity .55–.65 read 2.6–2.9:1 light, 3.3–3.9:1 dark (a lapsed MSA's green "Lapsed" link 2.56:1). Their
   words stay solid now, in the muted ink (≥4.5:1 in both themes): names, links and figures take it too, so the row still
   reads as set aside; each row says what it is with its own chip (Archived, inactive, Void, Lapsed) or its tick. */
:is(.mn-void td, .mn-void.card, .mn-pa.mn-void, .cy-arch td, .sco-dim, .ssp-mx tr.ssp-off td, .pu-off, :is(.notif-panel, .nfy-panel, .task-list) .task-item.done)
  :is(a:not(.btn, .chip), b, strong, .name, .value, .who, .hint, .sub) { color: var(--muted); }
:is(.notif-panel, .nfy-panel, .task-list) .task-item.done .task-title { text-decoration: line-through; text-decoration-color: var(--faint); }
.task-item .task-check { width: 17px; height: 17px; min-height: 0; margin: 2px 0 0; flex: none; cursor: pointer; accent-color: var(--ink); }
.task-item .task-txt { min-width: 0; flex: 1; cursor: pointer; border-radius: var(--r-s); }
.task-item .task-txt:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.task-item .task-title { font-size: 13px; font-weight: var(--fw-bold); line-height: 1.35; color: var(--ink); }
.task-item.done .task-title { text-decoration: line-through; color: var(--muted); font-weight: var(--fw-semi); }
.task-item .task-pri { color: var(--bad); font-weight: var(--fw-x); margin-right: 4px; }
.task-item .task-body { font-size: 12.5px; color: var(--muted); margin-top: 2px; overflow-wrap: anywhere; }
.task-item .task-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 6px; font-size: 11.5px; color: var(--muted); }
.task-item .task-due { font-weight: var(--fw-bold); color: var(--ink-2); }
.task-item .task-due.today { color: var(--warn); }
.task-item .task-due.late { color: var(--bad); }
.task-item .task-chip { display: inline-block; max-width: 220px; height: 20px; line-height: 20px; padding: 0 7px; border-radius: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: var(--well); color: var(--ink-2); font-size: 11.5px; font-weight: var(--fw-semi); }
.task-item .task-chip.auto { background: var(--info-bg); color: var(--info); }
.task-item .task-who { min-width: 0; max-width: 100%; }   /* inline, so "done by" and a long name can wrap: in a narrow panel (the project's Discussion) a no-wrap chip widened the whole column */
.task-item .task-who .who { gap: 4px; max-width: 100%; }
.task-item .task-who .who > span:last-child { white-space: normal; overflow-wrap: anywhere; }   /* a long name wraps here; one line of it set the column's least width */
@media (max-width: 1180px), (pointer: coarse) {
  .task-item .task-check { width: 20px; height: 20px; position: relative; }
  .task-item .task-check::after { content: ""; position: absolute; inset: -12px; }
}

/* a conversation in the Messages tab and on #/messages */
:is(.notif-panel, .nfy-panel) .dm-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px 10px 14px; border-bottom: 1px solid var(--hair); background: transparent; cursor: pointer;
  transition: background var(--t-quick); }
:is(.notif-panel, .nfy-panel) .dm-row:last-child { border-bottom: 0; }
:is(.notif-panel, .nfy-panel) .dm-row:hover { background: var(--well); }
:is(.notif-panel, .nfy-panel) .dm-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.dm-row .dm-main { min-width: 0; flex: 1; }
.dm-row .dm-head { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.dm-row .dm-head b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.dm-row .dm-when { flex: none; margin-left: auto; font-size: 11.5px; color: var(--faint); }
.dm-row .dm-prev { font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dm-row .dm-you { color: var(--faint); }
.dm-row.unread .dm-prev { color: var(--ink); font-weight: var(--fw-semi); }
.dm-row .notif-tab-n { background: var(--ink); color: var(--on-ink); }

/* the three pages: the title and its words, the views as underlined links, the list on one sheet of glass */
.nfy-panel { padding: 0; overflow: hidden; }
.nfy-panel.notif-page { background: linear-gradient(150deg, var(--glass-a), var(--glass-b)); border: 1px solid var(--glass-edge); border-radius: var(--r-xl); box-shadow: var(--shadow); }
.nfy-panel .notif-item, .nfy-panel .task-item { padding: 13px 14px 13px 18px; }
.nfy-panel .dm-row { padding: 12px 14px 12px 18px; }
.nfy-panel .notif-item .notif-title, .nfy-panel .task-item .task-title { font-size: 13.5px; }
.nfy-panel .notif-x { opacity: .7; }
/* a day's heading stays put under the pinned top bar while its rows scroll by */
.nfy-panel .notif-day { position: sticky; top: var(--tn-stuck); z-index: 1; padding: 8px 18px; border-bottom: 1px solid var(--hair);
  background: color-mix(in srgb, var(--surface-2) 94%, transparent); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  font-size: 11px; font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.nfy-panel .notif-day:first-child { border-radius: var(--r-xl) var(--r-xl) 0 0; }
.nfy-panel:has(.notif-day) { overflow: visible; }   /* overflow would stop the day headings sticking */
.nfy-tabs a .badge, .page-head .actions .btn .badge { margin-left: 2px; }
.page-head .actions .btn .badge { height: 18px; min-width: 18px; padding: 0 5px; }
.nfy-strip .value.nfy-words { font-size: var(--fs-xl); font-weight: var(--fw-semi); letter-spacing: -.01em; }
.nfy-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.nfy-filters .input { width: auto; flex: 0 1 300px; min-width: 0; }
.nfy-filters .select-wrap { flex: 0 0 auto; }
.nfy-filters .select { min-width: 160px; }
.nfy-more { display: flex; justify-content: center; }
@media (max-width: 640px) {
  .nfy-filters .input { flex: 1 1 100%; }
  .nfy-filters .select-wrap { flex: 1 1 100%; }
  .nfy-panel .notif-item, .nfy-panel .task-item, .nfy-panel .dm-row { padding-left: 14px; }
  .page-head .actions { width: 100%; }
}
/* a head's row of buttons on a phone fills every line it wraps to (w11design K6: a pay app's Send sat half-width over a
   Download that left a gap, Ticket layouts went 2 + 1 with neither line full): worded buttons grow, an icon button keeps
   its 44px, so the rows read 2 + 1 with the odd one the whole width, or one main action over the rest */
@media (max-width: 640px) {
  :is(.page-head, .sc-head) > :is(.actions, .mn-acts), .stg-card > .actions, .sco-head > .actions { display: flex; flex-wrap: wrap; width: 100%; }
  :is(:is(.page-head, .sc-head) > :is(.actions, .mn-acts), .stg-card > .actions, .sco-head > .actions) > :is(.btn:not(.icon), .anchor:not(:has(> .btn.icon:only-child))) { flex: 1 1 auto; justify-content: center; }
  :is(:is(.page-head, .sc-head) > :is(.actions, .mn-acts), .stg-card > .actions, .sco-head > .actions) > .anchor > :is(.btn:not(.icon), .split) { width: 100%; justify-content: center; }
}

/* a record's task card (a quote, a project, a job): its heading and button, then the rows */
.nfy-taskhead { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 6px; }
.nfy-taskhead b { font-size: 13.5px; }
.nfy-taskhead .hint { font-weight: var(--fw-med); }
.task-list > .nfy-none { padding: 14px 6px; text-align: left; }

/* pop-ups this file opens inside the app's .modal: a direct message, a task */
.nfy-dlg { display: grid; gap: 14px; min-width: 0; }
.nfy-dlg h2 { margin: 0; font-size: var(--fs-xl); font-weight: var(--fw-x); }
.nfy-dlg > div > .hint, .nfy-dlg > div > p.hint { margin: 2px 0 0; }
.nfy-dlg .field { margin: 0; }
.nfy-dlg .field label .hint { font-weight: var(--fw-med); }
.nfy-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.nfy-dlg .nfy-three { gap: 12px; }
@media (max-width: 640px) { .nfy-acts .btn { flex: 1 1 0; justify-content: center; } }

/* the thread: messages over a box; it sits inside its host's panel, so it draws no card of its own */
.thread { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.thread .thread-list { display: flex; flex-direction: column; gap: 14px; max-height: 52vh; overflow-y: auto; overscroll-behavior: contain;
  padding: 2px 2px 4px; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
.thread .thread-list > .nfy-none { padding: 18px 6px; }
.nfy-msg { display: flex; align-items: flex-start; gap: 10px; }
.nfy-msg .msg-av, .mention-item .msg-av { width: 30px; height: 30px; flex: none; border-radius: 50%; background: var(--ink); color: var(--on-ink); object-fit: cover;
  display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: var(--fw-x); letter-spacing: .02em; }
.nfy-msg.mine .msg-av:not(img) { background: var(--accent); color: var(--on-accent); }
.nfy-msg .msg-av.msg-av-logo { background: var(--glass-hi) url('/aims-a.png') center / 70% auto no-repeat; box-shadow: inset 0 0 0 1px var(--hair-2); }
.nfy-msg .msg-av[data-who] { cursor: pointer; }
.nfy-msg .msg-av[data-who]:hover { outline: 2px solid var(--accent); outline-offset: 1px; }
.nfy-msg .msg-main { min-width: 0; flex: 1; }
.nfy-msg .msg-head { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.nfy-msg .msg-head b { font-size: 13px; font-weight: var(--fw-bold); }
.nfy-msg .msg-when { font-size: 11.5px; color: var(--faint); white-space: nowrap; }
.nfy-msg .msg-x { margin-left: auto; align-self: center; width: 24px; height: 24px; padding: 0; display: inline-flex; align-items: center; justify-content: center; position: relative;
  border: 0; border-radius: 7px; background: transparent; color: var(--faint); cursor: pointer; opacity: 0; transition: opacity var(--t-quick); }
.nfy-msg:is(:hover, :focus-within) .msg-x { opacity: 1; }
.nfy-msg .msg-x:hover { background: var(--bad-bg); color: var(--bad); }
@media (hover: none), (max-width: 1180px) { .nfy-msg .msg-x { opacity: 1; } .nfy-msg .msg-x::after { content: ""; position: absolute; inset: -10px; } }
.nfy-msg .msg-body { font-size: 13.5px; line-height: 1.55; margin-top: 2px; overflow-wrap: anywhere; color: var(--ink); }
.nfy-mention { padding: 1px 5px; border-radius: 5px; background: color-mix(in srgb, var(--accent) 13%, var(--surface)); color: var(--accent-ink); font-weight: var(--fw-bold); }
.nfy-atts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.nfy-att { display: block; border-radius: var(--r-s); overflow: hidden; box-shadow: inset 0 0 0 1px var(--hair); }
.nfy-att img { display: block; max-width: 180px; max-height: 140px; }
.nfy-file { display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 9px; border-radius: var(--r-s); background: var(--well); font-size: 12.5px; font-weight: var(--fw-semi); }
.thread .thread-compose { display: flex; flex-direction: column; gap: 8px; }
.thread .thread-box { position: relative; }
.thread .thread-box .textarea { min-height: 64px; resize: vertical; }
.thread .thread-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.thread .thread-actions .hint { flex: 1 1 200px; font-size: 12px; }
.thread .thread-actions .btn { flex: none; }
/* @mention: the people matching what you have typed, over the box */
.thread .mention-pop { position: absolute; z-index: 60; left: 0; bottom: calc(100% + 6px); min-width: 260px; max-width: 100%; padding: 6px; overflow: hidden;
  border-radius: var(--r-l); box-shadow: var(--shadow-pop); animation: popIn var(--t-std); }
.thread .mention-pop.glass { background: var(--surface); }   /* solid: it sits over the messages, and the glass let their words through */
.thread .mention-pop .mention-item { display: flex; align-items: center; gap: 9px; min-height: 38px; padding: 0 10px; border-radius: 9px; cursor: pointer; font-size: 13px; font-weight: var(--fw-semi); background: transparent; }
.thread .mention-pop .mention-item:is(.sel, :hover) { background: var(--well); }
.thread .mention-pop .mention-item.sel { box-shadow: inset 0 0 0 1px var(--hair-2); }
.mention-item .msg-av.small { width: 24px; height: 24px; font-size: 9.5px; }
.mention-item .nfy-mname { flex: 0 0 auto; max-width: 62%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mention-item .hint { flex: 0 10 auto; min-width: 0; margin-left: auto; overflow: hidden; text-overflow: ellipsis; font-size: 11.5px; font-weight: var(--fw-med); white-space: nowrap; }   /* the role gives way before the name does */
@media (max-width: 1180px), (pointer: coarse) { .thread .mention-pop .mention-item { min-height: var(--tap); } }
@media (max-width: 720px) {
  .notif-panel, :root[data-theme="dark"] .notif-panel { width: auto; left: 8px; right: 8px; max-width: none; }
  .thread .thread-list { max-height: 60vh; }
  .mention-item .hint { display: none; }
}
@media print { .nfy-msg, .task-item { break-inside: avoid; } .nfy-msg .msg-av { display: none; } }

/* ---------------- the first-login tour and What's New (public/tour.js, 3.0 w9shell) ----------------
   Its own overlay, not the app's .modal (the tour has to outlive a screen repainting under it). A step can light up the
   real control it is about — the AIMS letters and the menu across the top on a computer, the ☰ button on a phone or a
   touch iPad, your menu for Settings and the Handbook: tour.js measures it into --spot-x/-y/-w/-h, the ring dims the room
   around it, and the card hangs just under it on the ring's side (--tour-in, .tour-r). Under the app's pop-ups (1200). */
.tour-back { position: fixed; inset: 0; z-index: 1150; display: flex; align-items: center; justify-content: center; padding: 24px 16px; overflow-y: auto;
  background: rgba(11,18,32,.42); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); animation: tourFade var(--t-std); }
@keyframes tourFade { from { opacity: 0; } }
.tour-back.tour-lit { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; align-items: flex-start; justify-content: flex-start;
  padding: calc(var(--spot-y, 0px) + var(--spot-h, 0px) + 18px) 16px 24px var(--tour-in, 16px); }
.tour-back.tour-lit.tour-r { justify-content: flex-end; padding-left: 16px; padding-right: var(--tour-in, 16px); }
.tour-spot { position: fixed; left: var(--spot-x); top: var(--spot-y); width: var(--spot-w); height: var(--spot-h); border-radius: var(--r-l); pointer-events: none;
  box-shadow: 0 0 0 3px var(--accent), 0 0 0 9px color-mix(in srgb, var(--accent) 22%, transparent), 0 0 0 100vmax rgba(11,18,32,.42);
  transition: left var(--t-spring), top var(--t-spring), width var(--t-spring), height var(--t-spring); }
.tour-card { position: relative; width: 100%; max-width: 560px; padding: 26px 28px 22px; border-radius: var(--r-2xl); color: var(--ink);
  background: linear-gradient(150deg, var(--glass-a), var(--glass-b)), var(--surface); border: 1px solid var(--glass-edge); box-shadow: var(--shadow-pop), 0 30px 70px -30px rgba(11,18,32,.55);
  animation: rise var(--t-std) both; }
:root[data-theme="dark"] .tour-card { background: linear-gradient(150deg, var(--glass-a), var(--glass-b)), var(--surface); }
.tour-card .tour-art { font-size: 32px; line-height: 1; margin-bottom: 10px; }
.tour-card h2 { margin: 0 0 10px; font-size: var(--fs-xl); font-weight: var(--fw-x); letter-spacing: -.01em; }
.tour-card .tour-body { font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.tour-card .tour-body p { margin: 0 0 10px; }
.tour-card .tour-body b { color: var(--ink); }
.tour-card .tour-body ul { margin: 0 0 10px; padding-left: 20px; }
.tour-card .tour-body li { margin-bottom: 5px; }
/* the four workspaces, each in its product's own colour (the li carries data-product; tokens.css answers) */
.tour-card .tour-ws { list-style: none; padding: 0; display: grid; gap: 6px; }
.tour-card .tour-ws li { margin: 0; padding: 4px 0 4px 12px; border-left: 3px solid var(--accent); }
.tour-card .tour-ws li b { color: var(--accent-ink); }
.tour-card .tour-dots { display: flex; gap: 6px; margin: 16px 0 14px; }
.tour-card .tour-dot { width: 22px; height: 4px; border-radius: var(--r-pill); background: var(--hair-2); transition: background var(--t-std); }
.tour-card .tour-dot.done { background: color-mix(in srgb, var(--accent) 40%, var(--surface)); }
.tour-card .tour-dot.on { background: var(--accent); }
.tour-card .tour-actions { display: flex; align-items: center; gap: 8px; }
.tour-card .tour-spacer { flex: 1; }
.tour-card .tour-go { margin-top: 12px; font-size: 13px; font-weight: var(--fw-semi); text-align: right; }
.tour-card.news-card { max-width: 640px; }
.news-card .news-title { margin: -4px 0 14px; font-weight: var(--fw-bold); color: var(--accent-ink); }
.news-card .news-list { margin: 0 0 6px; padding-left: 20px; max-height: min(52vh, 460px); overflow-y: auto; font-size: 13.5px; color: var(--ink-2); }
.news-card .news-list li { margin-bottom: 9px; line-height: 1.5; }
@media (max-width: 640px) {
  .tour-card { padding: 20px 18px 18px; border-radius: var(--r-xl); }
  .tour-back.tour-lit, .tour-back.tour-lit.tour-r { padding-left: 10px; padding-right: 10px; justify-content: center; }
  .tour-card .tour-actions { flex-wrap: wrap; }
}
@media (prefers-reduced-motion: reduce) { .tour-spot { transition: none; } }
@media print { .tour-back { display: none !important; } }

/* ---------------- Settings › You: Version History, Report a Bug, the Handbook tab (shb-) — public/settings.js (3.0, w9shell) ----------------
   Version History: four figures in one strip (the kit's .strip, 4 → 2 on touch), a line on how the numbers work, then every
   release as a row in one glass panel — its number, date, Live and Replay on the left, what changed on the right; at 980 and
   under the left column folds into one line over the words.
   Report a Bug: the form and the list as two panels (.stg-cards, one column at 980), the inbox address across under them for
   a manager. The kind is a segmented control; a submission's status is the kit's dropdown that moves both ways.
   The Handbook tab: the how-to videos in a glass panel (videos-ui.js draws inside it), then the manual's panel — its line,
   Open full screen, and /sop.html?embed=1 in a frame that fills the window under the pinned top bar. */
.shb { display: grid; gap: var(--gap); min-width: 0; }
.shb > * { min-width: 0; }
.shb-code { font: var(--fw-semi) 12px ui-monospace, SFMono-Regular, Menlo, monospace; padding: 1px 6px; border-radius: 6px; background: var(--well); }
/* Version History */
.shb-run .value { color: var(--accent-ink); }
.shb-date .value { font-size: 20px; }
.shb-lede { margin: 0; max-width: 110ch; }
.shb-rels { padding: 4px 18px; }
.shb-rel { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 8px 24px; padding: 16px 0; border-top: 1px solid var(--hair); }
.shb-rel:first-child { border-top: 0; }
.shb-rel-side { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.shb-rel-v { font-size: 18px; font-weight: var(--fw-x); letter-spacing: -.01em; font-variant-numeric: tabular-nums; line-height: 1.2; }
.shb-rel.now .shb-rel-v { color: var(--accent-ink); }
.shb-rel-body { min-width: 0; }
.shb-rel-body h3 { margin: 0 0 6px; font-size: var(--fs-l); font-weight: var(--fw-x); line-height: 1.35; }
.shb-rel-body ul { margin: 0; padding-left: 18px; display: grid; gap: 4px; color: var(--ink-2); font-size: 13px; line-height: 1.55; }
@media (max-width: 980px) {
  .shb-rel { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .shb-rel-side { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
}
/* Report a Bug */
.shb-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }   /* one column no wider than its panel: an auto column took the two kind buttons' width and scrolled a 320 phone sideways (w26fix) */
.shb-form .field, .shb-mail.field { margin: 0; }   /* 2.x gives every .field and label a bottom margin; the form's own gap spaces them */
:is(.shb-form .field, .shb-mail.field) > label { margin: 0; }
.shb-kind { align-self: flex-start; }
.shb-drop { display: grid; gap: 6px; justify-items: center; padding: 16px; border: 1.5px dashed var(--hair-2); border-radius: var(--r-l); background: var(--well);
  text-align: center; font-size: 13px; color: var(--ink-2); transition: border-color var(--t-quick), background var(--t-quick); }
.shb-drop p { margin: 0; }
.shb-drop.over, .shb-drop:focus-visible { outline: none; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.shb-drop .stg-link { color: var(--accent-ink); }
.shb-shots { display: flex; flex-wrap: wrap; gap: 8px; }
.shb-shots:empty { display: none; }
.shb-shot { position: relative; display: block; width: 96px; height: 68px; flex: none; overflow: hidden; border-radius: var(--r-m); border: 1px solid var(--hair-2); background: var(--surface); }
.shb-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shb-shot-x { position: absolute; top: 4px; right: 4px; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center;
  background: rgba(11, 18, 32, .72); color: #fff; cursor: pointer; }
.shb-shot-x:hover { background: var(--bad); }
.shb-send { justify-content: center; }
.shb-list { display: grid; }
.shb-item { display: grid; gap: 8px; padding: 14px 0; border-top: 1px solid var(--hair); min-width: 0; }
.shb-item:first-child { border-top: 0; padding-top: 2px; }
.shb-ihead { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.shb-ihead > div { min-width: 0; display: grid; gap: 3px; }
.shb-ihead > .select-wrap, .shb-ihead > .chip { flex: none; }
.shb-ititle { display: flex; align-items: baseline; gap: 6px; font-weight: var(--fw-bold); overflow-wrap: anywhere; }   /* the 🐞/💡 stays on the title's first line (wrapping, it sat alone above a two-line title at 320; w26fix's design review) */
.shb-ititle > .chip { flex: none; }
.shb-ibody { font-size: 13px; color: var(--ink-2); white-space: pre-wrap; overflow-wrap: anywhere; }
.shb-res { padding: 8px 10px; border-radius: var(--r-m); background: var(--ok-bg); border: 1px solid var(--ok-line); font-size: 13px; }
.shb-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.shb-ctx { font-size: 11.5px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shb-mail { max-width: 520px; }
@media (max-width: 1180px), (pointer: coarse) {
  .shb-shot-x::after { content: ""; position: absolute; inset: -10px; }   /* a 44px reach around the 24px circle */
  .shb-ihead > .select-wrap .status { min-height: var(--tap); }
}
@media (max-width: 640px) {
  .shb-kind { align-self: stretch; }
  /* the two kinds share the row from their own widths: where both fit (an English 375) each keeps its words on one line;
     where they don't (any 320–360, Spanish at 375) each gives way down to its longest word and its words wrap to a second
     line, so neither is cut ("1 1 0" cut "Algo está descompuesto" short at 375) nor hidden in a scroll (w26fix) */
  .shb-kind button { flex: 1 1 auto; height: auto; min-height: var(--tap); padding: 4px 10px; white-space: normal; line-height: 1.25; }   /* 10px sides: English fits one line at 360 (302px of well, 300 needed) */
  .shb-ihead { flex-wrap: wrap; }
  /* Make it a task · Reply · bin: one row, the two words-buttons in two even columns beside the bin, their words wrapping
     to a second line where they must ("1 1 0" cut "Convertirla en tarea" to 99px of 133 at 320, and English at 360; a
     wrapping row left the bin alone on a line of its own at 375; w26fix's design review) */
  .shb-tools { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--tap); }
  .shb-tools > .chip { justify-self: start; }   /* "Task raised" in Make it a task's place keeps its own width */
  .shb-tools .btn:not(.icon) { justify-content: center; height: auto; min-height: var(--tap); padding: 4px 8px; white-space: normal; line-height: 1.25; text-align: center; }
}
@media (max-width: 360px) { .shb-tools .btn:not(.icon) > svg { display: none; } }   /* the + gives way on the narrowest phones, so "Convertirla" fits its half */
/* the Handbook tab */
.shb-manual { display: flex; flex-direction: column; gap: 12px; padding: 16px 18px 18px; }
.shb-manual h2 { margin: 0; font-size: var(--fs-l); font-weight: var(--fw-x); }
.shb-manual p { margin: 0; }
.shb-frame { display: block; width: 100%; height: calc(100vh - 300px - var(--tn-stuck)); min-height: 460px; border: 0; border-radius: var(--r-l); background: transparent; color-scheme: normal; }

/* ---------------- the Handbook page (sop-) — public/sop.html, written by build-sop.py (3.0, w9shell) ----------------
   The employee manual as a reading page on the kit: a glass bar (the AIMS mark and the page's name, the search with its
   count and arrows, the Word copy and Print), the contents in a glass column that stays in view, the manual on a glass
   sheet. Inside Settings › Handbook (?embed=1, .sop-embed on <html>) it drops its own field and the logo and sits on that
   panel's glass. Appendix Z, the locked appendix, keeps its lock box and passphrase form (EASTER-EGGS.md: the hunt).
   Prints as plain paper: the bar, the contents and the glass go. */
.sop-page { margin: 0; padding: var(--gap); }
.sop-bar { max-width: 1280px; margin: 0 auto var(--gap); display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; padding: 8px 10px 8px 16px; }
.sop-brand { display: inline-flex; align-items: center; gap: 12px; flex: none; font-size: var(--fs-l); }
.sop-brand img { height: 30px; width: auto; display: block; }
.sop-brand .sop-dk { display: none; }
[data-theme="dark"] .sop-brand .sop-lt { display: none; }
[data-theme="dark"] .sop-brand .sop-dk { display: block; }
.sop-brand b { font-weight: var(--fw-x); letter-spacing: -.01em; white-space: nowrap; }
.sop-find { flex: 1 1 280px; min-width: 0; max-width: 560px; display: flex; align-items: center; gap: 8px; }
.sop-find .input { flex: 1 1 auto; min-width: 0; }
.sop-hits { font-size: 12.5px; font-weight: var(--fw-semi); color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.sop-bar > .actions { margin-left: auto; }
.sop-wrap { max-width: 1280px; margin: 0 auto; display: grid; grid-template-columns: 270px minmax(0, 1fr); gap: var(--gap); align-items: start; }
.sop-nav { position: sticky; top: var(--gap); max-height: calc(100vh - 2 * var(--gap)); overflow-y: auto; padding: 10px; display: grid; gap: 1px; }
.sop-nav a { display: block; padding: 5px 10px; border-radius: 8px; font-size: 13px; line-height: 1.35; font-weight: var(--fw-semi); color: var(--ink-2); text-decoration: none;
  transition: background var(--t-quick), color var(--t-quick), opacity var(--t-quick); }
.sop-nav a.lvl2 { padding-left: 22px; font-size: 12.5px; font-weight: var(--fw-med); color: var(--muted); }
.sop-nav a:hover { background: var(--well); color: var(--ink); text-decoration: none; }
.sop-nav a.dim { opacity: .35; }
.sop-nav a.sop-locked { opacity: .65; }
.sop-doc { min-width: 0; padding: 34px 44px 44px; font-size: 14px; line-height: 1.62; color: var(--ink); }
.sop-doc :is(h1, h2, h3) { scroll-margin-top: 16px; }
.sop-doc h1 { margin: 0 0 10px; font-size: var(--fs-h1); font-weight: var(--fw-bold); letter-spacing: -.02em; line-height: 1.2; }
.sop-doc h1:not(:first-child) { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--hair); }   /* Appendix Z, after the manual */
.sop-doc h2 { margin: 30px 0 10px; padding-top: 20px; border-top: 1px solid var(--hair); font-size: 19px; font-weight: var(--fw-x); letter-spacing: -.01em; line-height: 1.3; }
.sop-doc h2:first-of-type { border-top: 0; padding-top: 0; }
.sop-doc h3 { margin: 22px 0 8px; font-size: 16px; font-weight: var(--fw-x); color: var(--accent-ink); line-height: 1.35; }
.sop-doc p { margin: 0 0 9px; }
.sop-doc ul { margin: 0 0 12px; padding-left: 22px; }
.sop-doc li { margin-bottom: 5px; line-height: 1.55; }
.sop-doc figure { margin: 16px 0 4px; text-align: center; }
.sop-doc figure img { max-width: 100%; height: auto; border: 1px solid var(--hair-2); border-radius: var(--r-m); background: #fff; }   /* the manual's pictures are paper in both themes (a see-through logo vanished on dark) */
.sop-doc p.cap { text-align: center; color: var(--muted); font-size: 12.5px; font-style: italic; margin-bottom: 18px; }
/* a search hit: a highlighter's yellow in both themes, ink-dark letters on it; the one in view inked */
mark.sop-hit { background: #FDE68A; color: #0B1220; border-radius: 3px; padding: 0 1px; }
mark.sop-hit.on { background: var(--ink); color: var(--on-ink); }
/* Appendix Z: the lock box and the passphrase */
.sop-egg-lock { display: grid; gap: 8px; margin: 18px 0; padding: 18px 20px; border: 1px dashed var(--hair-2); border-radius: var(--r-l); background: var(--well); }
.sop-doc .sop-egg-lock p { margin: 0; }
.sop-egg-hint { color: var(--muted); font-size: 13.5px; }
.sop-egg-form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; }
.sop-egg-form .input { width: 220px; flex: none; letter-spacing: .18em; text-transform: uppercase; }
/* inside Settings › Handbook: the panel's glass is the field */
:root.sop-embed { background: transparent; }
.sop-embed .aurora, .sop-embed .sop-brand { display: none; }
.sop-embed .sop-page { padding: 2px 2px 10px; }
.sop-embed .sop-bar { max-width: none; }
.sop-embed .sop-wrap { max-width: none; }
@media (max-width: 980px) {
  .sop-wrap { grid-template-columns: minmax(0, 1fr); }
  .sop-nav { position: static; max-height: 280px; }
  .sop-doc { padding: 22px 20px 28px; }
}
@media (max-width: 640px) {
  .sop-page { padding: 10px; }
  .sop-bar { gap: 8px; padding: 8px; }
  .sop-brand b { display: none; }   /* the mark, the Word copy and Print share the first row; the search takes the second */
  .sop-find { flex-basis: 100%; max-width: none; order: 2; }
  .sop-bar > .actions { order: 1; }
  .sop-bar > .actions .btn { min-height: var(--tap); }
  .sop-doc { padding: 18px 14px 24px; }
  .sop-egg-form .input { width: 100%; }
  .sop-egg-form .btn { min-height: var(--tap); }
}
@media (max-width: 1180px), (pointer: coarse) { .sop-nav a { padding-block: 9px; } }   /* a contents row a thumb can hit */
@media print {
  .sop-bar, .sop-nav, .sop-page > .aurora { display: none !important; }
  :root, body.sop-page { background: #fff; }
  .sop-page { padding: 0; }
  .sop-wrap { display: block; max-width: none; }
  .sop-doc { padding: 0; background: none; border: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .sop-egg-lock, .sop-egg-body[hidden] { display: none; }
}

/* ---------------- touch reach, wave 22 (w22touch, 10/27) ----------------
   What w21platform's sweep left short on every touch screen (rebuild/reports/w21platform/touch-sweep/left-by-sheet.md,
   re-measured with rebuild/tools/touch-sweep.js at 375, 1024 and 1366 with a finger). Asked of a finger alone — never of
   "1180 and under" — so a mouse at any width, a narrowed window included, keeps every box it had (each changed sheet swapped
   in place for its old text: 0 elements differ at 1440, 1366, 1181, 1024 and 390). A reach first; where two doors sit closer
   than 44 the space between them opens, and a reach that would run into a neighbour's is split between them, never stacked. */
.sbe-gc > label.sbe-tickhit { display: contents; }   /* a mouse: the label settings.js wraps a lone tick in has no box of its own (below: a finger's square); .sbe-gc: it outweighs the kit's "1180 and under" label-with-a-tick rule, which a mouse in a narrowed window also meets */
@media (pointer: coarse) {
  /* a button with a short word was a shade under 44 across ("Skip" 42 on a crew's rating, "Edit" 42 on a spend matrix) */
  .btn { min-width: var(--tap); }
  /* a switch is 44 across as well as tall (a customer's Multi-site switch, 36 across, reached 38) */
  .switch::before { inset-inline: min(0px, calc(50% - var(--tap) / 2)); }
  /* the week board's people: a name's ↗ (its page) was 10×20 inside a 30px chip, and the strip, which scrolls sideways, clips
     whatever reaches past it — the strip gets 7px more room above and below (and gives it back, so nothing moves), and the
     ↗ reaches 44: a fingertip tall, 9px past the chip's end (half the 6px gap to the next chip), the rest over its own dots */
  .sc-strip.people { padding-block: 8px 10px; margin-block: -7px; }
  .sc-strip .sc-person > a[href] { position: relative; }
  .sc-strip .sc-person > a[href]::after { content: ""; position: absolute; top: calc(50% - var(--tap) / 2); bottom: calc(50% - var(--tap) / 2);
    right: -9px; left: calc(100% + 9px - var(--tap)); }
  /* a source link on the line just above a table: the table's scroll box (positioned) was drawn over the bottom of its reach,
     though the table's head there is only words (Settings › Logins' "Trash" 39, Crews & Skills' sources 37, an MSA's "Kept in
     Apex" 39) — the link's reach is drawn over that head now. A head with a button, a box or a link in it keeps its own. */
  :where(div, header, p):has(+ .table-wrap):not(:has(+ .table-wrap > table > thead :is(button, a, select, input, label))) .src { z-index: 1; }
  /* a quote note's product-group chips over the "Add a product group…" box on the line under them: the chip's ✕ reached 39,
     cut by the box 16px under it — the box steps 6px further down */
  .sbe-chips > .chip ~ :is(.select-wrap, select) { margin-top: 6px; }
  /* a tick alone in a grid's cell (a quote note's "Default on") is wrapped in a label (settings.js) that is a thumb's square,
     its 10px each side given back so the row does not move */
  .sbe-gc > label.sbe-tickhit { display: inline-flex; align-items: center; justify-content: center; min-width: var(--tap); min-height: var(--tap); margin: -10px -10px -10px -6px; cursor: pointer; justify-self: start; }
  .sbe-gc > label.sbe-tickhit > input { margin-inline: 0; }   /* start, and 4px in: the tick stays exactly where the bare box sat (its own 4px left margin; centred, it sat 27px off — design review) */
  /* a figure in running words ("11 customers with not enough history…" on Customer health) reaches a fingertip tall over
     the words above and below it (it was the line's 20) */
  .mo p.hint .mo-n::after { inset-block: calc(50% - var(--tap) / 2); }
  /* a table whose cells carry a link on their second line (Bid Totals: a job over its customer) — the customer and the next
     row's job sat 38 apart: the rows get 3px more above and below */
  .sco-list table.t:has(> tbody > tr > td > .sco-blk > a) > tbody > tr > td { padding-block: 13px; }
  /* a breadcrumb with one link ("Jobs › Quote"): at 1180 and under the drawer's swipe edge lies over the page's left gutter,
     and the link's reach into it was lost (37 across) — it reaches right instead, over the "›" and the words after it */
  .crumb > a:only-of-type::after { inset-inline-start: 0; inset-inline-end: min(-4px, calc(100% - var(--tap))); }
  /* the forecast grid's "Spread" (26px tall) reaches the row's 44 */
  .wg-spread { position: relative; }
  .wg-spread::after { content: ""; position: absolute; inset: calc(50% - var(--tap) / 2) min(0px, calc(50% - var(--tap) / 2)); }
  /* the forecast grid's group row ("Houston") right under the pinned heads: its name reached 42, the heads' edge 1.5px into the
     row — the group rows are 2px taller on touch */
  .wg-t tbody .grp :is(th, td) { height: calc(var(--tap) + 2px); }
}
/* a table with a link alone in a cell (a record's name, a source) has rows a fingertip tall on touch, as Sentry's and
   Ignite's already were: at 40–42px one row's 44px reach ran into the next row's (a BDM report's projects, Settings ›
   Spend's units and seats, a job's tickets). Every body row of such a table, so its rows stay one height (design review).
   Width 701 and up: below it a stacked table is cards. :where() — no weight, so a table that sets its own row height keeps
   it; the tables that turn into cards by their own class are left out. */
@media (pointer: coarse) and (min-width: 701px) {
  :where(.table-wrap > table.t:not(.ax-ql, .ax-min-t, .ax-agst-items, .pub-stack, .wg-t):has(> tbody > tr > td > :is(a[href], .src):only-child) > tbody > tr > td) { height: var(--tap); }
}
/* the forecast grid's job row on touch is 64px (wave 17): its name over the line of doors under it (customer, job number,
   MSA, notes). Two doors one over the other in 64px have 32 each, and no more without a taller row — so each gets exactly
   its half: the name the top 32 (its reach no longer runs 6px into the line under it), each door on the second line the
   bottom 32 (they reached 15). The words sit where they sat. The name's reach starts at the row's top (above it is the row
   before, whose doors it covered) and runs 44 down over its own second line, where the doors are drawn over it — so a name
   with no door under it keeps 44, and where they meet each keeps its half. */
@media (pointer: coarse) and (min-width: 641px) {
  .wg:not(.compact) .wg-t th.first > .wg-name:has(+ .wg-meta) { display: flex; align-items: flex-end; min-height: calc(var(--wg-row-h) / 2); }
  .wg:not(.compact) .wg-t th.first > .wg-name:has(+ .wg-meta)::before { inset: 0 0 calc(100% - var(--tap)) 0; }
  .wg:not(.compact) .wg-t th.first > .wg-meta { height: calc(var(--wg-row-h) / 2 - 1px); }   /* - 1px: the cell's own bottom rule is inside the row's height (at a full half the rows grew 64 → 65) */
  .wg:not(.compact) .wg-meta :is(a, button)::after { content: ""; position: absolute; inset: calc(-1 * var(--wg-row-h) / 2) min(0px, calc(50% - var(--tap) / 2)); }   /* the line clips it (overflow, for its …) to its own half */
}

/* ---------------- touch reach, wave 23 (w23touch, 10/27) ----------------
   What a finger still met short on a phone (375) after wave 22, and on the screens the sweep used to leave out (the closed
   drawer read as a pop-up over them; rebuild/reports/w23touch/). Two doors one over the other need 44 between their middles,
   so where they sat closer the space between them opens; a reach alone where nothing else is near. Asked of a finger alone:
   a mouse at any width keeps every box it had. */
@media (pointer: coarse) {
  /* a Settings card's lines stand 14px apart on touch, as wave 18 meant: its rule came before the card's own 6px gap, which
     won (Crew Day's yards, Logins' branch, Bid Totals' quote number sat 6px over the button, the status or the job under them) */
  :root .sco-card { row-gap: 14px; }
  /* Bid Totals' card: the job and its customer share a line, and where it wrapped the customer's name broke right under the
     job (10px apart). The customer moves down whole, 14px under the job (the card's own rhythm); the job reaches up into the
     card's gap and down to the customer, the customer 2px up and down over the words under it (24 past itself) — 44 each,
     never over each other */
  .sco-card > span:is(:has(> b > a):has(> a.sco-who), :has(> .sco-sep)) { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 4px; }
  .sco-card > span:has(> b > a):has(> a.sco-who):not(:has(> .sco-sep)) { row-gap: 14px; }
  .sco-card > span:has(> a.sco-who) > b > a::after { inset: -14px -4px; }
  .sco-card > span:has(> b > a) > a.sco-who::after { inset: -2px -4px -24px; }
  /* where the " · " between them is its own element (settings.js, rebuild/reports/w23touch/settings-bidtotals-sep.patch), it is
     the line break: a line of its own, 14px tall and its dot not drawn, so every card shows its customer under its job, the
     same in each, with no dot left at a line's end */
  .sco-card > span > .sco-sep { flex-basis: 100%; height: 14px; overflow: hidden; font-size: 0; }
  /* a pay app's facts (its customer, its branch, the dates) wrap on a phone and sat 4px apart: wrapped lines stand a fingertip
     apart, centre to centre; on one line nothing moves */
  .mn-meta { row-gap: calc(var(--tap) - 19px); }
  /* a Momentum head whose words end in a source link ("Compare it on the grid"), with its buttons wrapped under it: 12px
     between them (they sat 6px apart, and the link reached 39) */
  .mo-top:has(> div > .hint .src) { row-gap: 12px; }
  /* Crews & Skills › Branch overrides: the sources under the words stand 4px clear of the button under them (41) */
  .skl-srcs { padding-bottom: 4px; }
  /* the forecast grid's group row (a branch, a customer): on a phone its name wraps with its counts, so the name's link sat on
     the cell's top line and its reach ran into the pinned heads above (36) and the row before (a job's name reached 40) —
     the link's reach is the group's whole cell, never past it */
  .wg-t .grp th.first .src { position: static; }
  .wg-t .grp th.first .src::after { inset: 0; }
}

/* phones: figures and card grids go one across, so 4 → 2 → 1 reaches 1 (Jordan's symmetry rule; 2.x's .cards did it at
   560, and DEV-09 put Sentry's figures one across too). Two across on a 375 phone was 176px a figure (w11vault-products). At the end of the sheet: the screens' own
   two-across rules (.sc-top, .ssp-tiles, .mo-two) come later and weigh the same, and took it back. */
@media (max-width: 560px) {
  .strip, .strip.mo-two, .sc-top .strip, .ssp-tiles .strip, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .strip .top { min-height: 28px; align-items: center; }   /* one figure a row: nothing beside it to keep level with */
}

/* ======================= wave 30 · w30k: the shared causes of the design review's check 6 =======================
   One fix each here, instead of one per screen. The scripts that set the classes are public/phone-tables.js and frame.js. */

/* ---- three figures: three across, then one (never two and an orphan), and at ONE width everywhere (w30k).
   .strip.three broke at 980, .strip.mo-three at 640 and a bare strip of three at 1180 (2 + 1): the same card of figures was
   three across on one screen and stacked on the next at 820. All of them now keep three until the phone's own 560. */
.strip.three, .strip.mo-three, .strip:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 560px) {
  .strip.three, .strip.mo-three, .strip:has(> :nth-child(3):last-child) { grid-template-columns: minmax(0, 1fr); }
}

/* ---- filter rows that break evenly (phone-tables.js balance(): .bal on a wrapping row of controls, --bal-c = how many a line holds) */
.bal.bal { display: grid; grid-template-columns: repeat(var(--bal-c, 2), minmax(0, 1fr)); align-items: end; }
.bal.bal > * { width: auto; min-width: 0; max-width: none; margin-inline: 0; }
.bal.bal > .select-wrap { display: flex; }
.bal.bal > .select-wrap > select, .bal.bal > .select, .bal.bal > .input { width: 100%; }
.bal.bal > [data-bal-full] { grid-column: 1 / -1; max-width: none; }

/* ---- a phone card's last half-width field, when the count is odd, takes its whole row (phone-tables.js oddFix) */
@media screen and (max-width: 700px) {
  .table-wrap > table.stack td[data-odd] { grid-column: 1 / -1; }
}

/* ---- short numbers and times stay short in a form: a quantity, a day count and a clock time do not need the whole column (w30k:
   Settings, Work Orders › New, the ticket layout). Only a field that holds ONE labelled box; a table cell keeps its own width. */
.field > input[type=number].input, .field > input[type=time].input, .field > .input.n { max-width: 12rem; }

/* ---- the kit's month box: a month and a year select (phone-tables.js monthSelect) and its file button (fileButton) */
.msel { display: inline-flex; flex-wrap: nowrap; gap: 8px; align-items: center; max-width: 100%; vertical-align: middle; }
.msel > .select-wrap { flex: 1 1 auto; min-width: 0; }
.msel > .msel-m { flex-basis: 9.5rem; } .msel > .msel-y { flex: 0 0 6rem; }
.sn-datepair:has(> .msel) { flex-basis: 100%; }   /* a pair of selects needs the row a single date box did (Sentry's From / To, 640 and under) */
.sn-datepair > .msel { flex: 1 1 auto; min-width: 0; }
.msel .select { width: 100%; }
.filebtn { display: inline-flex; align-items: center; gap: 10px; max-width: 100%; min-width: 0; position: relative; }
.filebtn > .filebtn-pick { flex: none; cursor: pointer; margin: 0; font-size: 13px; font-weight: var(--fw-bold); }   /* a label, so it must shed the field-label look */
.filebtn > .filebtn-pick.disabled { opacity: .5; pointer-events: none; }
.filebtn > .filebtn-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 0; }
.filebtn > .filebtn-name.chosen { color: var(--ink); }
.filebtn:has(> input:focus-visible) > .filebtn-pick { outline: 2px solid var(--accent); outline-offset: 2px; }
.field > .filebtn { width: 100%; }

/* ---- maps in the dark theme (w30k: the OpenStreetMap tiles stayed full-bright, a glare in a dark page, and the map's own panels
   were the Leaflet defaults). The tile pane is dimmed and cooled, the controls and credits take the kit's dark surfaces. */
[data-theme="dark"] .leaflet-tile-pane { filter: brightness(.58) contrast(1.05) saturate(.75); }
/* the panels a map carries over its tiles are the smoked glass of the dark theme, not a see-through grey over bright streets */
[data-theme="dark"] :is(.sn-map .sn-fl.glass, .sn-map .sn-fl > .glass, .sn-map .sn-status, .ax-terr-mapcol .glass, .leaflet-container ~ .glass) { background: linear-gradient(150deg, color-mix(in srgb, var(--surface) 94%, transparent), color-mix(in srgb, var(--surface-2) 94%, transparent)); }
[data-theme="dark"] .leaflet-bar a, [data-theme="dark"] .leaflet-bar a:hover { background-color: var(--surface); color: var(--ink); border-bottom-color: var(--hair-2); }
[data-theme="dark"] .leaflet-bar { border: 1px solid var(--hair-2); box-shadow: none; }
[data-theme="dark"] .leaflet-container .leaflet-control-attribution, [data-theme="dark"] .leaflet-container .leaflet-control-scale-line { background: color-mix(in srgb, var(--surface) 82%, transparent); color: var(--muted); }
[data-theme="dark"] .leaflet-control-attribution a { color: var(--accent-ink); }
[data-theme="dark"] .leaflet-popup-content-wrapper, [data-theme="dark"] .leaflet-popup-tip { background: var(--surface); color: var(--ink); box-shadow: 0 6px 20px rgba(0, 0, 0, .5); }
[data-theme="dark"] .leaflet-popup-close-button { color: var(--muted); }
[data-theme="dark"] .leaflet-tooltip { background: var(--surface); color: var(--ink); border-color: var(--hair-2); }

/* ---- a name link in a table cell that wraps to two lines: an inline box's ::after reach is measured from its first and last
   line, so the middle of a wrapped name was not under the thumb's 44px (test-w17platform-browser, 820: "Bear Creek — Call-In").
   As an inline-block it is one box, and the reach is round all of it. Only a link that has wrapped (a one-line name keeps its reach as it is), touch widths only: the sentences' own links stay inline. */
@media (max-width: 1180px), (pointer: coarse) {
  #app td > a.wraps:not(.btn, .chip, .src) { display: inline-block; max-width: 100%; vertical-align: top; }   /* phone-tables.js marks a link that has wrapped */
}
