  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
  :root {
    --bg:#f6f8fc;--surface:#fff;--surface2:#f8fafc;--border:#e9edf4;--border-strong:#cdd5e1;
    --text:#0f172a;--text2:#475569;--text3:#64748b;--text-faint:#94a3b8;
    --accent:#2563eb;--accent-light:#eff5ff;--accent2:#1e3a8a;--accent2-light:#dbeafe;
    --accent-bright:#3b82f6;--accent-hover:#1d4ed8;
    --green:#15803d;--green-light:#dcfce7;--amber:#b45309;--amber-light:#fef3c7;
    --red:#dc2626;--red-light:#fee2e2;
    --font:'Inter',system-ui,sans-serif;--mono:var(--font);  /* unified on Inter; tabular figures via font-variant-numeric */
    /* ── 2026 refresh tokens ─────────────────────────────── */
    --num:var(--font);                 /* numeric/data cells: Inter + tabular-nums (was mono) */
    --radius-xs:6px;--radius-sm:8px;--radius:11px;--radius-lg:14px;--radius-xl:18px;
    --th-bg:#f4f6fb;--th-text:#64748b; /* light, airy table headers */
    --shadow-xs:0 1px 2px rgba(15,23,42,.05);
    --shadow-sm:0 1px 2px rgba(15,23,42,.04),0 2px 6px rgba(15,23,42,.05);
    --shadow:0 2px 8px rgba(15,23,42,.06),0 10px 28px rgba(15,23,42,.06);
    --shadow-lg:0 16px 40px rgba(15,23,42,.14);
    --ring:0 0 0 3px rgba(37,99,235,.18);  /* focus ring */
    --ease:cubic-bezier(.4,0,.2,1);
  }
  :root{--pz-cell:108px;--pz-frz:160px;--pz-h:64px;--pz-font:12px}
  /* --vchrome = the sticky chrome above .main. It was header(56) + the tab
     bar(39); with the modules in a left rail it is the header alone, so every
     "fill the rest of the viewport" height below gains those 39px — and the
     next chrome change is one edit rather than twelve. */
  :root{--vchrome:56px}
  *{box-sizing:border-box;margin:0;padding:0}
  /* Safari renders input[type=date]/[type=time] with an internal display:inline-flex
     box whose default min-width:auto is set by its own content (the calendar icon +
     "mm/dd/yyyy"/"--:--" placeholder) — that beats any width:100%/max-width:100% an
     author sets, so the control silently renders wider than its container and can
     overflow the whole page horizontally. Chromium doesn't have this behavior, so it
     was invisible in every headless test run in this sandbox (Chromium-only, no
     WebKit) until confirmed live on a real iPhone (2026-08-06). Global + universal
     since the bug can occur on ANY date/time input in the app, not just Forms.
     min-width:0 is a no-op everywhere it isn't needed — it only removes an
     oversized floor, never shrinks a control that already fits. */
  input[type=date],input[type=time]{min-width:0}
  body{font-family:var(--font);background:var(--bg);color:var(--text);min-height:100vh;font-size:14px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}
  /* ── Inline SVG icon system (replaces emoji) ─────────────── */
  .ic{width:1em;height:1em;display:inline-block;vertical-align:-0.14em;flex-shrink:0;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  .ic-lg{width:1.2em;height:1.2em}
  .ic-gap{margin-right:6px;vertical-align:-0.16em}
  .btn .ic,.abtn .ic,.tab .ic,.res-panel-title .ic,.sct .ic,.admin-section-title .ic,.nav-btn .ic{margin-right:5px}
  .nav-btn .ic{margin-right:0}
  .tab .ic{vertical-align:-0.16em}
  /* Tabular figures everywhere numbers line up (replaces the old monospace) */
  table td,table th,.day-label,.email-badge,.plan-zoom-lbl{font-variant-numeric:tabular-nums}
  /* ── Accessibility ─────────────────────────────── */
  a:focus-visible,button:focus-visible,select:focus-visible,summary:focus-visible,[tabindex]:not([tabindex="-1"]):focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--radius-xs)}
  input:focus-visible,textarea:focus-visible{outline:none;box-shadow:var(--ring)}
  /* JS-rendered cell inputs set inline outline:none — layer a visible focus ring via box-shadow */
  table.mx td input:focus-visible,.li input:focus-visible,.ri input:focus-visible,.ipanel input:focus-visible,#issuesList input:focus-visible,#issuesSectionBody input:focus-visible,#issuesSectionBody textarea:focus-visible{box-shadow:inset 0 0 0 2px var(--accent)}
  @media (pointer:coarse){
    .nav-btn{width:40px;height:40px}
    .btn{min-height:38px}
    .rmv,.boq-row-btn,.boq-iact,.boq-sec-btn,.boq-exp-btn,.boq-grip,.mic-btn{min-width:30px;min-height:30px}
    .boq-item-acts,.boq-sec-acts{opacity:1!important}
  }
  @media (prefers-reduced-motion: reduce){
    *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  }
  /* ── Motion ─────────────────────────────── */
  @keyframes modalIn{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
  @keyframes tpFade{from{opacity:0}to{opacity:1}}
  .mo.open .md{animation:modalIn .2s var(--ease)}
  #planModal.active .pm-box{animation:modalIn .2s var(--ease)}
  .tp.active{animation:tpFade .2s var(--ease)}

  /* AUTH — a split landing (owner-asked 2026-09-19) ─────────────────────────
     Left: a full-height panel in the app icon's OWN background navy, with the
     mark itself large and centred — the tile's ground and the panel are the
     same colour, so what you see is the pulse and the hat, not a badge stuck
     on a field. Right: a light column holding nothing but the form.
     All five pre-auth screens use the same shell — .auth-screen and
     .pending-screen differ only in their default display, which showAuth()/
     showPending()/… overwrite with an inline `flex` anyway.
     The form keeps the app's own LIGHT field and button styling (.fl/.abtn are
     shared with the signature dialog inside the app), so the scoped rules below
     only change size and rhythm, never colour. */
  :root{
    /* Sampled from icon-192.png, not guessed: its modal pixel is rgb(7,28,53)
       and its four corners run 4,23,46 → 12,31,54, so a flat #071c35 leaves at
       most ~5/255 between the tile and the panel behind it — no visible seam,
       and no need to strip the radius the e2e pins. */
    --au-panel:#0e223c;--au-panel2:#0e223c;
    --au-main:#f7f9fc;                         /* the form column's ground */
    /* The mark's own size, named once: the negative margin under it is derived
       from it, because the artwork inside the square stops at 68% of its
       height — 32% of dead tile below the hat that would otherwise read as a
       gap nobody chose. */
    --au-logo:clamp(150px,17vw,256px);--au-logo-sm:clamp(120px,11vw,168px);
    --au-h:#fff;
  }
  .auth-screen,.pending-screen{align-items:stretch;justify-content:flex-start;
    min-height:100vh;min-height:100dvh;background:var(--au-main);color:var(--text)}
  .auth-screen{display:flex}
  .pending-screen{display:none}

  /* ── the brand panel ───────────────────────────────────────────────────── */
  .auth-side{flex:1 1 52%;position:relative;overflow:hidden;display:flex;
    align-items:stretch;padding:clamp(36px,5vh,60px) clamp(28px,4vw,64px);
    background:var(--au-panel);isolation:isolate}
  /* The faint concentric rings. A repeating radial gradient draws them at any
     panel size without a single path or asset, and ::before keeps them behind
     the copy without needing a stacking context on every child. */
  .auth-side::before{content:'';position:absolute;inset:0;pointer-events:none;
    background:repeating-radial-gradient(circle at 6% 116%,rgba(120,170,255,.10) 0 1px,transparent 1px 64px)}
  /* Mark hard against the top, the headline and its three lines LOW and LEFT,
     the small print on the floor (owner-asked 2026-09-19: "The logo needs to
     move much higher and the Main text and slogans lower … I like how the main
     text is lower and to the left").
     Three rules do all of it and none of them is a magic number: the brand has
     no top margin, `.auth-hero` takes `margin-top:auto` so every pixel of slack
     above it collapses there, and `.auth-copy` takes another — two autos split
     what is left, so the headline lands around the middle and the copyright on
     the floor at any panel height. */
  .auth-side-in{position:relative;width:100%;max-width:560px;margin:0 auto;
    display:flex;flex-direction:column;align-items:flex-start;text-align:left}
  /* The lockup sits at the very top of the panel's padding box. It had a
     clamped top offset, then was asked higher still — `margin:0` is as high as
     it goes without eating the padding, and the artwork's own 23% of empty tile
     above the pulse already reads as breathing room. */
  /* margin:0 — the mark sits on the panel's padding edge, as high as it goes.
     A NEGATIVE top margin was tried first, to pull the tile's own dead 23.4%
     of empty space above the pulse back up so the ARTWORK met the padding
     edge; the probe refused it (`the panel clips its own content`, box top
     -12px) because .auth-side is overflow:hidden for the ring texture. Nothing
     visible was being cut — the clipped rows are transparent-looking tile —
     but a box hanging outside its panel would cut real artwork the day the
     icon changes, which is not a trade worth 57px. */
  .auth-brand{display:flex;flex-direction:column;align-items:flex-start;gap:0;margin:0}
  .auth-wm{margin-top:calc(14px - .318 * var(--au-logo))}
  .lean .auth-wm{margin-top:calc(14px - .318 * var(--au-logo-sm))}
  .auth-wm{font-size:clamp(24px,2.3vw,31px);font-weight:700;letter-spacing:-.025em;color:#fff}
  /* margin-top:auto is what drops it down the panel. text-wrap:balance is gone
     with the centring: a left-aligned headline should break where the measure
     runs out, not into two artificially even lines. */
  .auth-hero{font-size:clamp(22px,2.1vw,30px);line-height:1.25;font-weight:700;
    letter-spacing:-.022em;color:#fff;margin:auto 0 0;max-width:20ch}
  .auth-feats{list-style:none;margin:34px 0 0;display:flex;flex-direction:column;gap:16px;text-align:left}
  .auth-feats li{display:flex;align-items:flex-start;gap:13px;font-size:14px;
    line-height:1.5;color:rgba(255,255,255,.78);max-width:40ch}
  .auth-feat-ic{flex:0 0 auto;width:32px;height:32px;border-radius:10px;display:flex;
    align-items:center;justify-content:center;background:rgba(255,255,255,.09);
    border:1px solid rgba(255,255,255,.14);color:#dbe8ff}
  .auth-feat-ic .ic{width:16px;height:16px;stroke-width:1.9}
  .auth-copy{margin-top:auto;padding-top:40px;font-size:11.5px;letter-spacing:.02em;color:rgba(255,255,255,.45)}
  /* The secondary screens (pending / setup / invite / reset) carry `lean`:
     the mark and the headline, no feature list — they are transactional, and
     five copies of the same three selling lines is a drift hazard. */

  /* THE APP'S OWN MARK, not a tenant's. Before sign-in we do not know which
     organisation this person belongs to, so the honest logo here is the one
     already on their home screen — the same PWA icon site.webmanifest installs.
     The founding company's wordmark used to sit on every one of these screens,
     which is what everybody signing up for their OWN organisation saw first.
     (The header logo after sign-in is a different thing and stays org-driven,
     through orgLogoUrl().)
     The icon is a full square with no alpha — its corners are painted, not
     transparent. On the panel above that is the POINT: the painted ground and
     the panel are the same navy, so the mark reads as artwork rather than as a
     tile. The radius stays (the e2e pins it, and it costs nothing when the two
     grounds match) but the drop shadow is gone — a shadow is what would give
     an invisible square its edges back. */
  .auth-logo-img{width:var(--au-logo);height:var(--au-logo);
    display:block;flex:0 0 auto;border-radius:22%;mix-blend-mode:lighten}
  .auth-logo-img.sm{width:var(--au-logo-sm);height:var(--au-logo-sm)}
  .auth-logo-img.mid{margin-left:auto;margin-right:auto}

  /* ── the form column ───────────────────────────────────────────────────── */
  .auth-main{flex:1 1 48%;display:flex;align-items:center;justify-content:center;
    padding:56px clamp(24px,4vw,64px);background:var(--au-main)}
  .auth-form{width:100%;max-width:380px}
  .auth-form h2{font-size:27px;font-weight:700;letter-spacing:-.028em;color:var(--text);margin-bottom:7px}
  .auth-form p{color:var(--text3);font-size:13.5px;line-height:1.6;margin-bottom:6px}
  .auth-form>p:first-of-type{margin-bottom:26px}
  .auth-form .auth-fine{font-size:12px;color:var(--text-faint)}
  .auth-panel{display:none}.auth-panel.active{display:block}
  .auth-alt{margin-top:18px;font-size:13px;color:var(--text3);text-align:center}
  .auth-link{background:none;border:none;padding:0;font-family:var(--font);font-size:inherit;
    font-weight:600;color:var(--accent);cursor:pointer;text-decoration:none}
  .auth-link:hover{text-decoration:underline}
  .fl-row{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
  .fl-row label{margin-bottom:4px}
  .fl-row .auth-link{font-size:12px;font-weight:500;margin-bottom:4px}

  .fl{margin-bottom:14px}
  .fl label{display:block;font-size:12px;font-weight:500;color:var(--text2);margin-bottom:4px}
  .fl input{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:10px 12px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface);transition:border-color 0.15s,box-shadow 0.15s}
  .fl input:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .abtn{display:block;width:100%;font-family:var(--font);font-size:13px;font-weight:600;padding:11px;border-radius:var(--radius-xs);border:1px solid transparent;cursor:pointer;text-align:center;margin-bottom:8px;transition:all 0.15s}
  .abtn-accent{background:var(--accent);color:#fff}.abtn-accent:hover{background:var(--accent-hover)}
  .abtn-outline{background:var(--surface);border-color:var(--border-strong);color:var(--text2)}.abtn-outline:hover{background:var(--surface2)}
  /* Size and rhythm only — the colours are the app's own, so the signature
     dialog that shares .fl/.abtn is unaffected either way. */
  .auth-screen .fl label,.pending-screen .fl label{margin-bottom:6px;letter-spacing:.01em}
  .auth-screen .fl input,.pending-screen .fl input{font-size:14px;padding:12px 13px;border-radius:9px;min-height:44px}
  .auth-screen .abtn,.pending-screen .abtn{font-size:14px;padding:13px;border-radius:9px;min-height:46px;margin-bottom:0}
  .auth-screen .abtn+.abtn,.pending-screen .abtn+.abtn{margin-top:8px}
  .auth-screen .abtn-accent,.pending-screen .abtn-accent{box-shadow:0 6px 16px rgba(37,99,235,.24)}
  .amsg{font-size:12px;padding:10px 13px;border-radius:6px;margin-top:10px;display:none;line-height:1.6}
  .amsg.err{background:var(--red-light);color:var(--red);display:block;border:1px solid #f5c0b8}
  .amsg.ok{background:var(--green-light);color:var(--green);display:block;border:1px solid #b0d8bf}
  .amsg.warn{background:var(--amber-light);color:var(--amber);display:block;border:1px solid #e8c88a}
  .auth-screen .amsg,.pending-screen .amsg{margin-top:14px;border-radius:9px;font-size:12.5px}
  .domain-note{font-size:11px;color:var(--text3);margin-top:6px;text-align:center}
  .auth-screen .domain-note{margin-top:12px;text-align:left;line-height:1.55}
  .org-seg-row{display:flex;gap:0;border:1px solid var(--border-strong);border-radius:6px;overflow:hidden}
  .org-seg{flex:1;font-family:var(--font);font-size:12px;font-weight:600;padding:9px 8px;background:var(--surface);color:var(--text3);border:none;cursor:pointer;transition:all .15s;min-height:38px}
  .org-seg+.org-seg{border-left:1px solid var(--border-strong)}
  .org-seg.active{background:var(--accent);color:#fff}
  .org-seg:hover:not(.active){color:var(--accent)}
  .auth-screen .org-seg-row,.pending-screen .org-seg-row{border-radius:9px}
  .auth-screen .org-seg,.pending-screen .org-seg{min-height:44px}

  /* PENDING / SETUP / INVITE / RESET — same shell, same column */
  .pending-icon{margin-bottom:14px}
  .email-badge{background:var(--accent-light);color:var(--accent);border:1px solid #cfe0ff;
    font-size:12.5px;padding:6px 11px;border-radius:8px;display:inline-block;margin:10px 0 14px;
    overflow-wrap:anywhere}
  .auth-form strong{color:var(--text);font-weight:600}

  /* Phone / narrow: the panel becomes a band above the form rather than a
     column beside it. The mark stays the whole point of that band — big enough
     to read as artwork — and the feature list goes, since it would push the
     Sign in button below the fold on a 390px screen. */
  @media (max-width:900px){
    .auth-screen,.pending-screen{flex-direction:column}
    .auth-side{flex:0 0 auto;padding:26px 22px 24px}
    .auth-side::before{background:repeating-radial-gradient(circle at 8% 175%,rgba(120,170,255,.10) 0 1px,transparent 1px 46px)}
    .auth-side-in{max-width:none}
    .auth-brand{gap:12px;margin:0}
    .auth-logo-img,.auth-logo-img.sm{width:112px;height:112px}
    .auth-wm,.lean .auth-wm{margin-top:-24px}
    .auth-wm{font-size:21px}
    .auth-hero{font-size:15px;line-height:1.4;margin-top:10px;max-width:34ch}
    .auth-feats,.auth-copy{display:none}
    .auth-main{flex:1 1 auto;padding:28px 22px 44px;align-items:flex-start}
    .auth-form{max-width:440px;margin:0 auto}
    .auth-form h2{font-size:23px}
  }
  @media (max-width:420px){
    .auth-side{padding:22px 18px 20px}
    .auth-logo-img,.auth-logo-img.sm{width:96px;height:96px}
    .auth-wm,.lean .auth-wm{margin-top:-20px}
    .auth-main{padding:24px 18px 40px}
    .auth-wm{font-size:19px}
    .auth-hero{font-size:14px}
  }

  /* LOADING — the brand panel's own ground, since it is the moment before it */
  .loading-screen{display:none;align-items:center;justify-content:center;min-height:100vh;min-height:100dvh;flex-direction:column;gap:12px;background:var(--au-panel);isolation:isolate}
  .spinner{width:36px;height:36px;border:2px solid rgba(255,255,255,0.18);border-top-color:var(--accent-bright);border-radius:50%;animation:spin 0.7s linear infinite}
  @keyframes spin{to{transform:rotate(360deg)}}
  .loading-text{font-size:13px;color:rgba(255,255,255,0.68)}
  /* The wordmark needed a width cap to stay inside a phone; a 112px square
     never can, so the cap is gone. object-fit stays as insurance against a
     future icon that is not square — it would letterbox rather than stretch. */
  .loading-logo{width:176px;height:176px;object-fit:contain;border-radius:22%;
    margin-bottom:-30px;mix-blend-mode:lighten}

  /* APP */
  .app-screen{display:none}
/* A WHITE header, ACC-style (owner-asked 2026-09-18). Every company has a
   version of its logo on white, and almost none have one that sits well on a
   dark navy bar - so the bar itself stops being the thing with a colour and
   becomes a hairline under a white strip. The accent colour still appears, on
   the controls rather than behind them.

   Everything that used to sit on this bar was written light-on-dark - the
   project selector, both indicators, the role and user badges, and .btn-ghost
   (which is used in FOUR places, all of them this header, so restyling it here
   reaches nothing else). They are all restated for a light ground below. */
  .header{background:#fff;color:var(--text);height:56px;display:flex;align-items:center;padding:0 20px;gap:14px;position:sticky;top:0;z-index:100;border-bottom:1px solid var(--border);box-shadow:0 1px 2px rgba(15,23,42,0.04)}
  /* The header carries the APP's own mark — the Site Diary icon the sign-in
     screen wears — and its name, as Atlas does (owner-asked 2026-09-27: "use the
     Site Diary logo, not Org logo"). The org's logo stays on every export. */
  .hdr-mark{width:32px;height:32px;border-radius:8px;flex-shrink:0;display:block}
  .hdr-wm{font-size:15.5px;font-weight:700;letter-spacing:-.015em;color:#18181b;white-space:nowrap}
  .hsep{width:1px;height:22px;background:var(--border)}
  /* A button, not a <select>: the native popup is drawn by the OS, so it can
     carry no project number, no client, no search, and it truncates a long
     name to whatever the platform decides. jobPickOpen() is the app's own. */
  .job-sel{display:flex;align-items:center;gap:7px;background:var(--surface);border:1px solid var(--border-strong);color:var(--text);font-family:var(--font);font-size:13px;font-weight:600;padding:6px 11px;border-radius:var(--radius-sm);cursor:pointer;min-width:180px;max-width:300px;text-align:left}
  .job-sel:hover{background:var(--surface2);border-color:var(--accent)}
  .job-sel-nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .job-sel-cv{width:13px;height:13px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;opacity:.5}
  /* The picker itself. One list, one search box, the same at every width. */
  /* A quiet list (2026-10-07, owner: "it feels too busy"). Every row used to be
     its own bordered card with a gap round it, rows changed height with whether a
     number existed, and a full scrollbar ran beside them — seven boxes inside a
     box. Now: one surface, rows split by a hairline instead of boxed, each with
     an initials tile (owner picked "option B", 2026-10-08), the number and client
     muted under the name, the open project the one tinted row. */
  .md.jobpick-md{width:440px;max-width:100%;padding:16px 12px calc(10px + env(safe-area-inset-bottom));display:flex;flex-direction:column}
  .jobpick-hd{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:0 4px 0 10px;margin-bottom:12px}
  .md .jobpick-hd h3{margin:0}
  .jobpick-x{width:32px;height:32px;flex-shrink:0;display:grid;place-items:center;border:0;background:none;border-radius:8px;color:var(--text3);cursor:pointer}
  .jobpick-x:hover{background:var(--surface2);color:var(--text)}
  .jobpick-x svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
  .jobpick-srch{position:relative;margin:0 4px 8px}
  .jobpick-srch svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);width:15px;height:15px;fill:none;stroke:var(--text-faint);stroke-width:2;stroke-linecap:round;pointer-events:none}
  /* Restated at .md input's own specificity (0,2,1) — a bare .jobpick-q is
     0,1,0 and loses to the generic modal-field rule. Known Mistake #7. */
  .md input.jobpick-q{margin:0;padding-left:34px;background:var(--surface2);border-color:transparent}
  .md input.jobpick-q:focus{background:var(--surface);border-color:var(--accent)}
  .jobpick-list{max-height:min(52vh,420px);overflow-y:auto;display:flex;flex-direction:column;padding:2px 0 0;scrollbar-width:thin;scrollbar-color:var(--border-strong) transparent}
  .jobpick-list::-webkit-scrollbar{width:6px}.jobpick-list::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:3px}
  .jobpick-list::-webkit-scrollbar-button{display:none;height:0}
  .jobpick-it{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:none;border:0;border-bottom:1px solid var(--border);border-radius:0;padding:9px 10px;cursor:pointer;font-family:var(--font);min-height:52px;color:var(--text)}
  .jobpick-it:last-child{border-bottom:0}
  .jobpick-it:hover,.jobpick-it.kb{background:var(--surface2)}
  .jobpick-it.kb{box-shadow:inset 0 0 0 1px var(--border-strong)}
  .jobpick-it:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
  .jobpick-it.on{background:var(--accent-light)}
  .jobpick-tx{flex:1;min-width:0}
  .jobpick-nm{display:block;font-size:13.5px;font-weight:500;color:var(--text);overflow-wrap:anywhere;line-height:1.35}
  .jobpick-it.on .jobpick-nm{color:var(--accent);font-weight:650}
  .jobpick-sub{display:block;font-size:11.5px;color:var(--text3);margin-top:1px;overflow-wrap:anywhere;line-height:1.35}
  /* The initials tile: white on a 600/700 shade, so the letters clear AA. */
  .jobpick-av{flex-shrink:0;width:30px;height:30px;border-radius:8px;display:grid;place-items:center;color:#fff;font-size:11px;font-weight:700;letter-spacing:.02em;line-height:1}
  .jobpick-av-org{background:#334155}
  .jobpick-av-org svg{width:16px;height:16px;fill:none;stroke:#fff;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
  .jobpick-tick{flex-shrink:0;width:16px;height:16px;fill:none;stroke:var(--accent);stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}
  .jobpick-none{padding:22px 4px;text-align:center;color:var(--text3);font-size:12.5px}
  @media(max-width:600px){.jobpick-x{width:44px;height:44px;margin:-6px -6px -6px 0}}
  .sp{flex:1}
  .btn{font-family:var(--font);font-size:12px;font-weight:600;padding:6px 13px;border-radius:var(--radius-sm);border:1px solid transparent;cursor:pointer;white-space:nowrap;transition:background .15s var(--ease),color .15s var(--ease),border-color .15s var(--ease),box-shadow .15s var(--ease),transform .15s var(--ease)}
  .btn:active{transform:translateY(1px)}
  .btn-ghost{background:transparent;border-color:var(--border-strong);color:var(--text2)}.btn-ghost:hover{background:var(--surface2);color:var(--text);border-color:var(--accent)}
  .btn-accent{background:var(--accent-light,#eff6ff);color:var(--accent);border-color:var(--accent);font-weight:600}.btn-accent:hover{background:var(--accent);color:#fff}
  .btn-outline{background:transparent;border-color:var(--border-strong);color:var(--text2)}.btn-outline:hover{background:var(--surface2);color:var(--text)}
  .btn-blue{background:var(--accent);color:#fff;font-weight:600}.btn-blue:hover{background:var(--accent-hover)}
  .btn-danger{background:var(--red);color:#fff;font-weight:600}.btn-danger:hover{background:#b91c1c}
  .btn-green{background:var(--green);color:#fff;font-weight:600}.btn-green:hover{background:#166534}
  .btn-amber{background:var(--amber);color:#fff;font-weight:600}
  /* All Diaries entry point — bright orange so it reads at a glance against the toolbar */
  .btn-diary{background:#f97316;color:#fff;font-weight:600;border:1px solid #ea580c;box-shadow:0 1px 2px rgba(234,88,12,.25)}
  .btn-diary:hover{background:#ea580c;border-color:#c2410c}
  .btn-diary svg{stroke:#fff}
  .btn-sm{padding:4px 10px;font-size:11px}
  .role-badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:6px;letter-spacing:0.05em;text-transform:uppercase}
  .rb-admin{background:#fef3c7;color:#92400e;border:1px solid #fcd34d}
  .rb-user{background:var(--surface2);color:var(--text3);border:1px solid var(--border)}
  .user-badge{font-size:11.5px;color:var(--text3);font-family:var(--font);max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .user-badge:hover{color:var(--text);text-decoration:underline}
  .admin-name-inp{width:100%;border:1px solid var(--border);border-radius:6px;padding:5px 7px;font-family:var(--font);font-size:13px;font-weight:500;color:var(--text);background:var(--surface)}
  .admin-name-inp:hover{border-color:var(--border-strong)}
  .admin-name-inp:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light)}
  /* The header carries no standing status pill any more (2026-09-18, owner-asked:
     "remove this on the top bar"). "Saved" and "Live" were permanent green chips
     reporting the normal case, which is the case nobody needs told. The element is
     still rendered — its onclick is the only route to diaryResolveConflict() and
     .si-err is the only place a failed save is reported — so it is hidden in every
     state EXCEPT the error/conflict one, which is when it earns the space. */
  /* Build with AI — the panel, and the strip that carries what it could not do.
     The note is deliberately IN the builder rather than a toast: it is the list
     you work down while reviewing, and a toast is gone in six seconds. */
  .frm-ai-lead{font-size:12.5px;line-height:1.55;color:var(--text2);margin:-2px 0 14px}
  .frm-ai-brief{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:8px;padding:9px 11px;font-family:var(--font);font-size:13px;line-height:1.5;color:var(--text);background:var(--surface);resize:vertical;min-height:84px}
  .frm-ai-brief:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light)}
  .frm-ai-list{display:flex;flex-direction:column;gap:5px;margin-top:8px}
  .frm-ai-file{display:flex;align-items:center;gap:8px;background:var(--surface2);border:1px solid var(--border);border-radius:7px;padding:6px 8px;font-size:12px;min-width:0}
  .frm-ai-file .nm{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
  .frm-ai-file .sz{flex:0 0 auto;color:var(--text3);font-size:11px}
  .frm-ai-msg{display:none;margin-top:10px;font-size:12px;line-height:1.5;border-radius:7px;padding:8px 10px}
  .frm-ai-msg.info{background:var(--accent-light,#eff6ff);color:var(--accent);border:1px solid var(--accent)}
  .frm-ai-msg.warn{background:#fef3c7;color:#92400e;border:1px solid #fcd34d}
  .frm-ai-note{display:flex;align-items:flex-start;gap:9px;background:#fef3c7;border:1px solid #fcd34d;color:#92400e;border-radius:8px;padding:10px 12px;margin:0 0 12px;font-size:12.5px;line-height:1.55}
  .frm-ai-note b{flex:0 0 auto}
  .frm-ai-note span{flex:1 1 0;min-width:0}
  .frm-ai-note{flex-wrap:wrap}
  .frm-ai-undo{flex:0 0 auto;align-self:center}
  /* Above / below — two real choices, so two big targets. Scoped two classes
     deep: a bare <label> inside .md is the generic field caption (Known Mistake #7). */
  .md .frm-ai-pos{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 14px}
  .md .frm-ai-posopt{flex:1 1 200px;display:flex;align-items:center;gap:9px;min-height:44px;margin:0;padding:8px 12px;border:1px solid var(--border-strong);border-radius:10px;cursor:pointer;font-size:13px;font-weight:400;color:var(--text);text-transform:none;letter-spacing:normal}
  .md .frm-ai-posopt:has(input:checked){border-color:var(--accent);background:var(--accent-light)}
  .md .frm-ai-posopt input{margin:0;flex:0 0 auto}
  .frm-fld.frm-ai-new{box-shadow:0 0 0 2px var(--accent)}
  /* Change with AI — the review list. Each row is a <label> inside .md, so it is
     scoped two classes deep to beat `.md label` (Known Mistake #7). */
  .frm-ai-revnote{background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:8px 10px;margin:0 0 12px;font-size:12px;line-height:1.5;color:var(--text2);overflow-wrap:anywhere}
  .md .frm-ai-chgs{display:flex;flex-direction:column;gap:6px;margin:0 0 4px}
  .md .frm-ai-chgs .frm-ai-chg{display:flex;align-items:flex-start;gap:10px;margin:0;padding:9px 11px;min-height:44px;box-sizing:border-box;border:1px solid var(--border);border-radius:9px;cursor:pointer;font-size:13px;font-weight:400;color:var(--text);text-transform:none;letter-spacing:normal;min-width:0}
  .md .frm-ai-chgs .frm-ai-chg:has(input:checked){border-color:var(--accent);background:var(--accent-light)}
  .md .frm-ai-chgs .frm-ai-chg.gone{opacity:.6;cursor:default}
  .md .frm-ai-chgs .frm-ai-chg input{margin:3px 0 0;flex:0 0 auto;width:16px;height:16px}
  .frm-ai-chg-b{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 0}
  .frm-ai-chg-h{display:flex;align-items:center;gap:7px;min-width:0;flex-wrap:wrap}
  .frm-ai-chg-h b{min-width:0;overflow-wrap:anywhere}
  .frm-ai-chg-d{font-size:12px;line-height:1.45;color:var(--text2);overflow-wrap:anywhere}
  .frm-ai-chg-n{font-size:11.5px;line-height:1.45;color:#92400e}
  .frm-ai-tag{flex:0 0 auto;font-size:10.5px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;border-radius:5px;padding:1px 6px;background:var(--surface2);color:var(--text2)}
  .frm-ai-tag.add{background:color-mix(in srgb,var(--green) 15%,transparent);color:var(--green)}
  .frm-ai-tag.del{background:color-mix(in srgb,var(--red) 13%,transparent);color:var(--red)}
  .frm-ai-tag.chg,.frm-ai-tag.name{background:var(--accent-light);color:var(--accent)}
  /* The minimised AI build — a card, not a modal, so the app stays usable.
     Above the page (and the phone tab bar), below every dialog (.mo is 350). */
  .frm-ai-card{position:fixed;right:20px;bottom:20px;z-index:300;width:340px;max-width:calc(100vw - 32px);box-sizing:border-box;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow-lg);padding:12px 14px;display:flex;flex-direction:column;gap:8px;animation:modalIn .2s var(--ease)}
  .frm-ai-card.done{border-color:color-mix(in srgb,var(--green) 40%,var(--border))}
  .frm-ai-card.err{border-color:color-mix(in srgb,var(--red) 40%,var(--border))}
  .frm-ai-card-h{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text);min-width:0}
  .frm-ai-card-h b{min-width:0;overflow-wrap:anywhere}
  .frm-ai-card-h .ic{flex:0 0 auto;color:var(--accent)}
  .frm-ai-card.done .frm-ai-card-h .ic{color:var(--green)}
  .frm-ai-card.err .frm-ai-card-h .ic{color:var(--red)}
  .frm-ai-card-sub{font-size:12px;line-height:1.5;color:var(--text2);overflow-wrap:anywhere;min-width:0}
  .frm-ai-card-hint{color:var(--text3);font-size:11px}
  .frm-ai-bar{height:6px;border-radius:3px;background:var(--surface2);overflow:hidden}
  .frm-ai-bar .fill{height:100%;background:var(--accent);border-radius:3px;transition:width .5s linear}
  .frm-ai-card-acts{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}
  @media(max-width:600px){
    .frm-ai-card{left:16px;right:16px;width:auto;max-width:none;bottom:calc(72px + env(safe-area-inset-bottom))}
    .frm-ai-card-acts .btn{min-height:44px}
  }
  @media (prefers-reduced-motion:reduce){.frm-ai-card{animation:none}.frm-ai-bar .fill{transition:none}}
  .save-ind{display:none;font-size:11px;padding:3px 9px;border-radius:6px;font-family:var(--font);font-weight:500}
  .save-ind.si-err{display:inline-flex;align-items:center}
  /* A thin top-of-screen progress bar for background photo uploads — deliberately
     NOT a modal: uploads can take a while on a poor site connection, and a modal
     that blocks the whole app for that duration was the reported bug (2026-08-24).
     Bare bar, no text — "small and discreet", not a second status pill fighting
     the header's own #saveInd for the same job. */
  #uploadBar{position:fixed;top:0;left:0;right:0;height:3px;z-index:360;background:transparent;pointer-events:none}
  #uploadBar .fill{height:100%;width:0;background:var(--accent);transition:width .3s ease,background-color .3s ease;box-shadow:0 0 6px var(--accent)}
  #uploadBar.err .fill{background:var(--red);box-shadow:0 0 6px var(--red)}
  #uploadBar.done .fill{width:100%!important}
  .si-ok{background:#dcfce7;color:#15803d}
  .si-saving{background:var(--surface2);color:var(--text3)}
  .si-err{background:#fee2e2;color:#b91c1c}
  #liveToast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);padding:10px 20px;border-radius:10px;font-size:12px;font-family:var(--font);font-weight:500;z-index:9999;display:none;max-width:440px;text-align:center;box-shadow:0 12px 32px rgba(15,23,42,0.32);transition:opacity 0.3s}
  #liveToast.info{background:rgba(15,23,42,0.97);color:#86efac;border:1px solid rgba(21,128,61,0.4)}
  #liveToast.warn{background:rgba(80,30,20,0.97);color:#f5a880;border:1px solid rgba(192,57,43,0.5)}
  #liveToast.neutral{background:rgba(30,30,50,0.97);color:rgba(255,255,255,0.75);border:1px solid rgba(255,255,255,0.15)}
  /* A shrink-to-fit box at left:50% can only ever use the half of the screen to
     its right, so on a phone a long toast renders as a 195px column — measured,
     190px tall for the "only a rough position came back" message, which is the
     longest the app raises. Pin it to both edges there instead. Restated after
     the base rule so it wins at equal specificity (Known Mistake #7). */
  @media(max-width:600px){#liveToast{left:12px;right:12px;transform:none;max-width:none}}

  /* ── PLAN TAB ─────────────────────────────────── */
  .plan-toolbar{padding:10px 18px;background:var(--surface);border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .plan-toolbar-group{display:flex;align-items:center;gap:2px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:2px 3px}
  .plan-hint{margin-left:auto;font-size:10px;color:var(--text3);background:var(--surface2);border:1px solid var(--border);border-radius:20px;padding:3px 12px;font-weight:500}
  .plan-legend-bar{padding:8px 18px;background:var(--surface);border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-height:38px}
  .plan-legend-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 10px 3px 7px;border-radius:20px;font-weight:600;font-size:10px;line-height:1.4}
  .plan-legend-chip.planned{border-style:dashed;border-width:2px;background-color:rgba(0,0,0,0.03)}
  .plan-legend-chip.confirmed{color:#fff;border:2px solid transparent}
  .plan-legend-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
  .plan-legend-key{display:flex;align-items:center;gap:10px;margin-left:auto;padding-left:12px;border-left:1px solid var(--border)}
  .plan-legend-key-item{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--text3);font-weight:600}
  .plan-legend-key-box{width:26px;height:13px;border-radius:3px;flex-shrink:0;display:inline-block}
  /* Two-panel layout: frozen left column + independently scrollable right grid */
  .plan-wrap{display:flex;overflow:hidden;height:calc(100vh - var(--vchrome) - 165px)}
  .plan-frozen{flex:0 0 auto;overflow-x:hidden;overflow-y:auto;scrollbar-width:none;-ms-overflow-style:none;box-shadow:4px 0 10px rgba(15,23,42,0.08);position:relative;z-index:1}
  .plan-frozen::-webkit-scrollbar{display:none}
  .plan-scroll{flex:1 1 0;overflow:auto}
  /* Frozen left-column table — explicit cell sizes guarantee row-height sync with right table */
  .plan-frz-tbl{border-collapse:separate;border-spacing:0;font-size:var(--pz-font,12px);table-layout:fixed;width:var(--pz-frz,160px)}
  .plan-frz-tbl th,.plan-frz-tbl td{border-bottom:1px solid var(--border);border-left:1px solid var(--border);border-right:4px solid var(--accent);padding:0;width:var(--pz-frz,160px);min-width:var(--pz-frz,160px);box-sizing:border-box}
  .plan-frz-tbl thead tr:first-child th{border-top:1px solid var(--border)}
  .plan-frz-week{height:32px;background:var(--accent2);color:rgba(255,255,255,0.65);font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;text-align:center;vertical-align:middle;position:sticky;top:0;z-index:3}
  .plan-frz-range{display:block;font-size:13px;font-weight:700;color:#fff;letter-spacing:0.01em;margin-bottom:1px}
  .plan-frz-day{height:26px;background:#1a4a7a;position:sticky;top:32px;z-index:3}
  .plan-frz-date{height:22px;background:var(--accent-light);position:sticky;top:58px;z-index:3}
  /* Scrollable right-grid table — header heights must match frozen table exactly */
  .plan-tbl{border-collapse:separate;border-spacing:0;font-size:var(--pz-font,12px)}
  .plan-tbl th,.plan-tbl td{border-right:1px solid var(--border);border-bottom:1px solid var(--border);padding:0}
  .plan-tbl thead tr:first-child th{border-top:1px solid var(--border)}
  .plan-week-hdr{background:var(--accent2);color:#fff;font-size:10px;font-weight:600;text-align:center;white-space:nowrap;position:sticky;top:0;z-index:3;height:32px;letter-spacing:0.06em;text-transform:uppercase;padding:0 4px}
  /* min-width mirrors .plan-cell's width so an EMPTY planner (no sections yet =
     no body cells) still opens at full column width instead of collapsing to the
     header text. With sections present the negotiated width is unchanged (both
     prefer --pz-cell, border-box). Weekend headers keep their 52px !important. */
  .plan-day-hdr{background:#1a4a7a;color:rgba(255,255,255,0.9);font-size:10px;font-weight:500;text-align:center;position:sticky;top:32px;z-index:3;white-space:nowrap;height:26px;letter-spacing:0.04em;text-transform:uppercase;padding:0 2px;min-width:var(--pz-cell,108px)}
  .plan-date-hdr{background:var(--accent-light);font-size:10px;font-family:var(--mono);text-align:center;color:var(--accent);position:sticky;top:58px;z-index:3;height:22px;font-weight:600;padding:0 2px}
  .plan-today-hdr{background:var(--green)!important;color:#fff!important}
  .plan-today-col{background:var(--green-light)!important}
  .plan-we-hdr{background:#1e2a3a!important;color:rgba(255,255,255,0.4)!important;min-width:52px!important}
  .plan-we-col{background:var(--surface2)!important;min-width:52px;max-width:52px}
  .plan-cell{width:var(--pz-cell,108px);min-width:calc(var(--pz-cell,108px) - 18px);height:var(--pz-h,64px);vertical-align:top;cursor:pointer;padding:0;position:relative;transition:background 0.12s;background:var(--surface)}
  .plan-cell:hover{background:var(--accent-light)!important}
  .plan-chip{position:absolute;top:3px;bottom:3px;left:3px;right:3px;display:flex;align-items:flex-start;border-radius:5px;padding:5px 7px;overflow:hidden;box-sizing:border-box;cursor:pointer;transition:box-shadow 0.12s}
  .plan-chip.is-planned{border-width:2px;border-style:dashed}
  .plan-chip.is-confirmed{border:2px solid transparent;box-shadow:0 2px 6px rgba(0,0,0,0.2)}
  .plan-chip-txt{font-size:10px;font-weight:600;word-break:normal;overflow-wrap:break-word;pointer-events:none;user-select:none;flex:1;line-height:1.4}
  .plan-chip-status{font-size:7px;opacity:0.7;pointer-events:none;margin-left:3px;margin-top:1px;flex-shrink:0}
  .plan-cell.drag-over,.plan-track-cell.drag-over{background:var(--accent-light)!important;outline:2px solid var(--accent)!important;outline-offset:-2px}
  /* Frozen column body cells */
  .plan-sec-cell{padding:0;vertical-align:top;background:var(--surface);height:var(--pz-h,64px)}
  .plan-frz-cont{height:var(--pz-h,64px);background:var(--surface)}
  .plan-sec-inner{padding:8px 10px 6px;display:flex;flex-direction:column;gap:3px;height:100%;overflow:hidden}
  .plan-sec-name{font-size:11px;font-weight:700;color:var(--text);cursor:text;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
  .plan-sec-btns{display:flex;gap:3px;margin-top:auto;padding-top:4px;opacity:0;transition:opacity 0.15s}
  .plan-sec-cell:hover .plan-sec-btns{opacity:1}
  .plan-sec-collapse-btn{background:none;border:none;cursor:pointer;font-size:9px;color:var(--text3);padding:0 2px;line-height:1;flex-shrink:0;transition:color 0.1s;font-weight:700}
  .plan-sec-collapse-btn:hover{color:var(--accent)}
  .plan-sec-coll-cell{padding:0;vertical-align:middle;background:var(--surface2);height:36px;cursor:pointer;border-bottom:1px solid var(--border);border-right:4px solid var(--accent)}
  .plan-sec-coll-cell:hover .plan-sec-btns{opacity:1}
  .plan-sec-coll-inner{padding:4px 10px;display:flex;align-items:center;gap:5px;height:100%}
  .plan-cell-collapsed{width:var(--pz-cell,108px);min-width:calc(var(--pz-cell,108px) - 18px);height:36px;background:var(--surface2)!important;cursor:pointer;padding:3px 5px;vertical-align:middle;border-right:1px solid var(--border);border-bottom:1px solid var(--border)}
  .plan-cell-collapsed:hover{background:var(--accent-light)!important}
  .plan-sec-move-btn{background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:1px 5px;font-size:9px;cursor:pointer;color:var(--text2);line-height:1.5;transition:all 0.12s;font-weight:700}
  .plan-sec-move-btn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
  .plan-sec-move-btn:disabled{opacity:0.3;cursor:default;pointer-events:none}
  .plan-sec-btn{background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:2px 7px;font-size:9px;cursor:pointer;color:var(--text2);line-height:1.5;transition:all 0.12s;font-weight:600}
  .plan-sec-btn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
  .plan-sec-del:hover{background:var(--red)!important;color:#fff!important;border-color:var(--red)!important}
  .plan-track-sec{padding:7px 12px;cursor:pointer;display:flex;align-items:center;color:var(--text2);font-size:10px;font-weight:600;border-right:4px solid var(--accent)!important;background:var(--surface2);letter-spacing:0.04em;text-transform:uppercase;height:var(--pz-h,64px)}
  .plan-track-sec:hover{background:var(--accent-light);color:var(--accent)}
  .plan-track-item{padding:4px 8px 4px 18px;font-size:10px;color:var(--text2);display:flex;align-items:center;border-right:4px solid var(--accent)!important;font-weight:500;background:var(--surface);height:var(--pz-h,64px)}
  .plan-track-cell{padding:0;height:var(--pz-h,64px);background:var(--surface);cursor:pointer;position:relative;transition:background 0.12s}
  .plan-track-cell:hover{background:var(--accent-light)!important}
  #planEditor{position:fixed;z-index:1000;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:0 12px 36px rgba(15,23,42,0.15),0 2px 6px rgba(0,0,0,0.05);padding:16px;width:264px;display:none}
  #planEdHeader{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
  #planEdHeader span{font-size:9px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:0.08em}
  #planEdClose{background:none;border:none;cursor:pointer;font-size:16px;color:var(--text3);padding:0;line-height:1;border-radius:4px;width:22px;height:22px;display:flex;align-items:center;justify-content:center}
  #planEdClose:hover{background:var(--surface2);color:var(--text)}
  #planEdTxt{width:100%;border:1px solid var(--border);border-radius:6px;padding:7px 9px;font-family:var(--font);font-size:12px;resize:none;color:var(--text);margin-bottom:10px;display:block;line-height:1.5}
  #planEdTxt:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light)}
  .plan-ed-label{font-size:9px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:0.07em;margin-bottom:5px}
  .plan-ed-res-list{display:flex;flex-direction:column;gap:2px;max-height:130px;overflow-y:auto;margin-bottom:10px;border:1px solid var(--border);border-radius:6px;padding:4px}
  .plan-ed-res-opt{display:flex;align-items:center;gap:7px;padding:5px 8px;border-radius:5px;cursor:pointer;font-size:11px;font-weight:500;transition:background 0.1s;color:var(--text)}
  .plan-ed-res-opt:hover{background:var(--surface2)}
  .plan-ed-res-sel{background:var(--accent-light)!important;color:var(--accent)}
  .plan-ed-btns{display:flex;gap:6px;margin-top:2px}
  #planEdStatus{flex:1;font-size:11px;padding:6px 10px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;cursor:pointer;font-family:var(--font);text-align:left;font-weight:500;transition:all 0.15s;color:var(--text2)}
  #planEdStatus:hover{border-color:var(--accent);background:var(--accent-light);color:var(--accent)}
  #planEdStatus.is-confirmed{background:var(--green-light);border-color:var(--green);color:var(--green)}
  #planCtx{position:fixed;z-index:1001;background:var(--surface);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 28px rgba(15,23,42,0.14);display:none;min-width:185px;padding:4px 0;overflow:hidden}
  .plan-ctx-item{padding:8px 16px;font-size:12px;cursor:pointer;color:var(--text);white-space:nowrap;font-weight:500;transition:background 0.1s}
  .plan-ctx-item:hover{background:var(--accent-light);color:var(--accent)}
  .plan-ctx-item.danger{color:var(--red)}.plan-ctx-item.danger:hover{background:var(--red-light);color:var(--red)}
  .plan-ctx-sep{border-top:1px solid var(--border);margin:4px 0}
  /* In-app planner modal */
  #planModal{position:fixed;inset:0;z-index:2000;background:rgba(15,23,42,0.45);display:none;align-items:center;justify-content:center}
  #planModal.active{display:flex}
  .pm-box{background:var(--surface);border-radius:12px;padding:22px;width:340px;max-width:92vw;max-height:90vh;max-height:90dvh;overflow-y:auto;overscroll-behavior:contain;box-shadow:0 20px 60px rgba(15,23,42,0.25);border:1px solid var(--border)}
  .pm-title{font-size:14px;font-weight:700;color:var(--text);margin-bottom:10px}
  .pm-msg{font-size:13px;color:var(--text2);line-height:1.55;margin-bottom:16px;white-space:pre-wrap}
  .pm-input{width:100%;border:1px solid var(--border);border-radius:7px;padding:8px 11px;font-family:var(--font);font-size:13px;color:var(--text);margin-bottom:16px;display:block;box-sizing:border-box}
  /* pmGrow() sets an explicit height from the content; min-height keeps a short value
     a comfortable writing box and overflow-y takes over once it hits pmGrow's cap. */
  .pm-area{min-height:112px;line-height:1.55;resize:vertical;overflow-y:auto}
  /* A tapped value: looks like a field at rest, but is text, so it renders on the
     type scale instead of being forced to 16px by the iOS anti-zoom rule. */
  .tapval{display:flex;align-items:center;min-height:38px;padding:7px 10px;border-radius:6px;
    cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text);
    -webkit-tap-highlight-color:transparent}
  .tapval:hover{background:var(--accent-light)}
  .tapval:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
  .tapval.tapval-ph{color:var(--text3)}
  .tapval.tapval-num{justify-content:flex-end;font-variant-numeric:tabular-nums}
  /* A bare <select> inherits the BROWSER's font, never the page's — measured at
     11px Arial (desktop) and 13px Arial (phone) on the dictation-language picker
     while everything around it was Inter. Named rather than blanket-applied to
     `select`, so nothing that deliberately styles its own picker is disturbed. */
  #wxSel,#dictLang,#newIssuePriority,.wx-sel,.dict-lang-sel{font-family:var(--font)}
  @media(max-width:600px){.tapval{min-height:44px}}
  /* ── GROUPED LIST (iOS Settings-style) ──────────────────────────────
     One consistent "this is editable" language for every phone tap-cell that
     lives OUTSIDE a data grid (resources/deliveries/inventory/issue rows —
     the matrix/BOQ/programme stay bare-text-in-a-cell, which is the native
     spreadsheet convention, not a form). A .hig-list is a card with hairline
     row separators; each .hig-row is a full-bleed 44pt tap target. NO border
     goes around individual values — the row's own boundary supplies the
     affordance, exactly like Settings.app / Contacts, so scrolling from one
     section to another never changes visual language. */
  .hig-list{background:var(--surface);border:1px solid var(--border);border-radius:8px;overflow:hidden}
  .hig-row{display:flex;align-items:center;gap:8px;padding:9px 12px;border-bottom:1px solid var(--border);min-height:44px}
  .hig-row:last-child{border-bottom:none}
  .hig-cap{font-size:11px;font-weight:600;color:var(--text3);text-transform:uppercase;letter-spacing:0.05em;padding:10px 2px 5px}
  .hig-primary{flex:1;min-width:0}
  .hig-primary .tapval{font-size:12px}
  .hig-meta{display:flex;flex-wrap:wrap;align-items:center;gap:0;font-size:11px;color:var(--text3);flex-shrink:0}
  .hig-meta .tapval{min-height:28px;padding:2px 3px;color:var(--text2)}
  .hig-sep{color:var(--border-strong);margin:0 2px}
  .hig-rmv{flex-shrink:0}
  /* A row with more than a name+value pair (deliveries: qty/unit/supplier;
     inventory: qty/unit/cost/BOQ item) reads as noise crammed onto one line
     behind middle-dots — this is the same row, just tall enough to give each
     field its own caption in a small grid. Values themselves stay borderless
     (the row boundary is still the only affordance, per the .hig-row rule
     above); a <select> gets a real border because it IS a distinct control,
     not a value — same reasoning the app already applies to date/time pickers. */
  .hig-row-fields{flex-wrap:wrap;align-items:flex-start;padding:10px 12px 11px}
  .hig-row-top{display:flex;align-items:center;gap:8px;flex:1 1 100%;min-width:0}
  .hig-fgrid{display:grid;grid-template-columns:1fr 1fr;gap:2px 12px;flex:1 1 100%;margin-top:7px}
  .hig-fld{min-width:0}
  .hig-fld-wide{grid-column:1/-1}
  .hig-fld-lbl{display:block;font-size:9.5px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:0.05em;margin:0 0 1px 1px}
  .hig-fld .tapval{min-height:36px;padding:5px 8px;font-size:12px;color:var(--text)}
  .hig-fld select{width:100%;min-height:38px;border:1px solid var(--border);border-radius:7px;padding:6px 9px;font-family:var(--font);font-size:13.5px;color:var(--accent);background:var(--surface);cursor:pointer}
  .hig-fld select:focus{outline:none;border-color:var(--accent)}
  .pm-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light)}
  .pm-btns{display:flex;gap:8px;justify-content:flex-end}
  #planResPanel,#planPlantResPanel{position:fixed;right:0;top:0;bottom:0;width:300px;background:var(--surface);border-left:1px solid var(--border);box-shadow:-8px 0 28px rgba(15,23,42,0.12);z-index:500;display:none;flex-direction:column}
  .plan-res-header{padding:14px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;background:var(--accent2)}
  .plan-res-body{flex:1;overflow-y:auto;padding:14px}
  .plan-res-item{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--border);border-radius:6px;margin-bottom:6px;background:var(--surface2);transition:box-shadow 0.15s}
  .plan-res-item:hover{box-shadow:0 2px 8px rgba(15,23,42,0.08);background:var(--surface)}
  .plan-res-swatch{width:24px;height:24px;border-radius:4px;cursor:pointer;border:1px solid rgba(0,0,0,0.1);flex-shrink:0;padding:0}

  .day-nav{background:var(--surface);border-bottom:2px solid var(--accent-light);padding:8px 20px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .nav-btn{width:32px;height:32px;border-radius:50%;border:1px solid var(--border-strong);background:var(--surface);color:var(--text);cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center;transition:all 0.15s}
  .nav-btn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
  .day-label{font-family:var(--font);font-size:12px;font-weight:600;color:var(--text);min-width:200px;text-align:center}
  .wx-sel{font-family:var(--font);font-size:12px;padding:4px 8px;border:1px solid var(--border);border-radius:var(--radius-xs);background:var(--surface);color:var(--text);cursor:pointer}

  /* ── LEFT SIDEBAR NAV (ACC-style) ──────────────────────────────
     Replaces the horizontal .tabs bar (2026-09-06). That bar had outgrown
     itself: 14 items overflowed even a 1440px viewport, and a contained
     horizontal scroll was the 2026-08-24 patch for it. A vertical rail has
     room for the modules the app keeps growing, and the grouping says what
     each one is for. .shell-main{min-width:0} is load-bearing — a flex child
     refuses to shrink below its content's min-content width without it, and
     the whole page scrolls sideways. */
  .shell{display:flex;align-items:flex-start}
  .shell-main{flex:1;min-width:0}
  /* ── Atlas style (owner-asked 2026-09-27: "make my site diary, and project
     selector in the same style" as their Atlas app). Neutral zinc greys, not
     the app's slate/blue: the active item is a quiet grey pill with darker,
     heavier text — no blue fill and no accent bar — labels are medium weight,
     icons a hair thinner. The tokens are scoped to .sidenav so nothing else in
     the app changes colour. Same block in registers.css for the satellites. */
  .sidenav{flex-shrink:0;width:214px;background:var(--surface);border-right:1px solid var(--border);position:sticky;top:var(--vchrome);height:calc(100vh - var(--vchrome));overflow-y:auto;overflow-x:hidden;padding:10px 0 0;display:flex;flex-direction:column;scrollbar-width:thin;transition:width .16s ease;
    --sn-fg:#52525b;--sn-strong:#18181b;--sn-muted:#71717a;--sn-hover:#f4f4f5;--sn-active:#ededf0}
  /* The project switcher heads the sidebar, as the workspace switcher heads
     Atlas's: the name and an up/down chevron (no initial tile — owner-asked). */
  .sn-proj{display:flex;align-items:center;gap:10px;flex-shrink:0;min-width:0;margin:0 8px 4px;padding:8px 10px;border:none;background:none;border-radius:9px;font-family:var(--font);color:var(--sn-strong);text-align:left;cursor:pointer;transition:background .13s}
  .sn-proj:hover{background:var(--sn-hover)}
  .sn-proj:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  .sn-proj-nm{flex:1;min-width:0;font-size:13.5px;font-weight:600;letter-spacing:-.005em;line-height:1.25;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere;text-overflow:ellipsis}/* a project name is long where an org name is short — two lines, then an ellipsis; the tooltip carries the rest */
  .sn-proj-cv{width:16px;height:16px;flex-shrink:0;fill:none;stroke:var(--sn-muted);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  .sn-grp{padding:0 8px}
  .sn-lbl{font-size:10.5px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--sn-muted);padding:12px 10px 5px}
  .sn-it{display:flex;align-items:center;gap:12px;padding:7px 10px;border-radius:8px;font-size:13.5px;font-weight:500;color:var(--sn-fg);cursor:pointer;white-space:nowrap;overflow:hidden;position:relative;transition:background .13s,color .13s}
  .sn-it .ic{width:18px;height:18px;flex-shrink:0;stroke-width:1.75}
  .sn-it span{overflow:hidden;text-overflow:ellipsis}
  .sn-it:hover{background:var(--sn-hover);color:var(--sn-strong)}
  .sn-it.active{background:var(--sn-active);color:var(--sn-strong);font-weight:600}
  .sn-ai svg{color:var(--accent)}
  .sn-tog{margin-top:auto;display:flex;align-items:center;gap:10px;margin:auto 8px 0;padding:8px 10px;border:none;background:none;border-radius:8px;font-family:var(--font);font-size:12px;font-weight:500;color:var(--sn-muted);cursor:pointer;white-space:nowrap;overflow:hidden}
  .sn-tog:hover{background:var(--sn-hover);color:var(--sn-strong)}
  .sn-tog .ic{width:16px;height:16px;flex-shrink:0;transition:transform .16s ease}
  /* collapsed icon rail: labels out, group captions become hairline dividers.
     The switcher shrinks to a folder icon (a name cannot fit in 60px) and
     the first group's divider has nothing above it, so it goes. */
  .sidenav.rail{width:60px}
  .sidenav.rail .sn-it span,.sidenav.rail .sn-tog span{display:none}
  .sidenav.rail .sn-it,.sidenav.rail .sn-tog{justify-content:center;padding-left:0;padding-right:0;gap:0}
  .sidenav.rail .sn-lbl{font-size:0;line-height:0;height:1px;padding:0;margin:9px 12px;background:var(--border)}
  .sidenav.rail .sn-tog .ic{transform:rotate(180deg)}
  .sidenav.rail .sn-proj + .sn-grp .sn-lbl{display:none}
  .sn-proj-ic{display:none;width:18px;height:18px;flex-shrink:0;fill:none;stroke:var(--sn-fg);stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
  .sidenav.rail .sn-proj{justify-content:center;padding:8px 0}
  .sidenav.rail .sn-proj-ic{display:block}
  .sidenav.rail .sn-proj-nm,.sidenav.rail .sn-proj-cv{display:none}
  /* ── NO TOP BAR on a desktop (owner-asked 2026-10-12, with a screenshot of the
     Programme: "move the log out and admin and jobs at the top to the left panel
     … make most of this space for the modules"). Everything the bar carried now
     has a home in the sidebar — the app's mark at its head, the project switcher
     under it, Jobs/Admin in Manage, who you are and Sign out in its foot — and
     the day's exports on the diary toolbar. So from 601px up the header takes
     NO height (--vchrome 0, which every height calc and the sidebar's own sticky
     top already read) and only one thing is still allowed to show from it: a
     failed save (.save-ind.si-err), the only place that is reported and the only
     route to diaryResolveConflict(), floated top-right. A phone keeps its header
     unchanged — logo, project, ⋯ — because it has no sidebar. registers.css
     carries the same block for the satellites. */
  .sn-brand{display:flex;align-items:center;gap:10px;flex-shrink:0;padding:2px 18px 10px;min-width:0}
  .sn-mark{width:32px;height:32px;border-radius:8px;flex-shrink:0;display:block}
  .sn-wm{font-size:15.5px;font-weight:700;letter-spacing:-.015em;color:#18181b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sidenav.rail .sn-brand{justify-content:center;padding:2px 0 10px}
  .sidenav.rail .sn-wm{display:none}
  /* The foot is sticky to the sidebar's own bottom edge, so on a short window
     the groups scroll under it and Sign out is never below the fold. */
  .sn-foot{margin-top:auto;position:sticky;bottom:0;background:var(--surface);padding:6px 8px 10px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:2px;flex-shrink:0;z-index:1}
  .sn-foot .sn-tog{margin:0}
  .sn-me{display:flex;align-items:center;gap:4px;min-width:0}
  .sn-user{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:6px 8px;border:none;background:none;border-radius:8px;font-family:var(--font);text-align:left;color:var(--sn-strong);cursor:pointer}
  div.sn-user{cursor:default}
  button.sn-user:hover{background:var(--sn-hover)}
  .sn-user:focus-visible,.sn-out:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  .sn-av{width:28px;height:28px;border-radius:50%;flex-shrink:0;display:grid;place-items:center;background:#3f3f46;color:#fff;font-size:11px;font-weight:700;letter-spacing:.02em}
  .sn-ut{flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:3px}
  .sn-un{max-width:100%;font-size:13px;font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sn-ut .role-badge{display:inline-block;font-size:9px;padding:1px 6px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sn-out{flex-shrink:0;width:34px;height:34px;display:grid;place-items:center;border:none;background:none;border-radius:8px;color:var(--sn-muted);cursor:pointer}
  .sn-out:hover{background:#fef2f2;color:var(--red)}
  .sn-out .ic{width:17px;height:17px}
  .sidenav.rail .sn-me{flex-direction:column;gap:2px}
  .sidenav.rail .sn-user{flex:none;padding:6px 0;justify-content:center}
  .sidenav.rail .sn-ut{display:none}
  @media(min-width:601px){
    body:has(#sideNav){--vchrome:0px}
    body:has(#sideNav) .header{height:0;min-height:0;padding:0;border:0;box-shadow:none;overflow:visible;z-index:150}
    body:has(#sideNav) .header>*:not(.save-ind){display:none}
    body:has(#sideNav) .header>.save-ind.si-err{position:fixed;top:10px;right:16px;box-shadow:0 4px 14px rgba(15,23,42,.14)}
  }
  /* The day's exports sit on the diary toolbar from 601px up; a phone has them
     in the header's ⋯ menu, and its toolbar has no room for two more buttons. */
  @media(max-width:600px){.dn-exp{display:none}}
  .hdr-brand{display:contents}

  .main{padding:18px 14px;max-width:100%;margin:0 auto;width:100%}
  .tp{display:none}.tp.active{display:block}

  /* MATRIX */
  /* The Hours Matrix caption + its action buttons ride the same card-content
     rail as every heading above and below, so the label lines up with the KPI
     strip and the card headings, and its buttons' right edge lines up with the
     cards' own right-hand buttons (Add note / + Add). The table itself stays
     full-width — it is a data grid that scrolls, not prose. */
  .mx-cap{padding-left:17px;padding-right:17px}
  /* padding-left puts the table's own content — the sticky first column — on
     the 17px card-content rail too, so the whole Hours Matrix block (caption,
     toolbar and grid) is one aligned unit rather than a toolbar at 23 over a
     table at the gutter. The box itself stays full gutter width like every card
     box; only the content shifts in. A scroll container honours start padding,
     and the sticky column sticks to that padded edge. */
  .twrap{overflow-x:auto;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);box-shadow:var(--shadow-sm);padding-left:16px}
  table.mx{border-collapse:collapse;min-width:100%;font-size:13px}
  table.mx th,table.mx td{border-right:1px solid var(--border);border-bottom:1px solid var(--border);padding:0}
  table.mx th{background:var(--accent2);color:#fff;font-size:10px;font-weight:700;text-align:center;white-space:nowrap;padding:8px 8px;letter-spacing:0.04em;text-transform:uppercase}
  table.mx th.thl{background:#1a5c8a}table.mx th.thp{background:var(--amber)}
  table.mx th.ths{background:var(--green)}table.mx th.thw{background:#3a3570}
  table.mx th.tht{background:var(--accent-bright)}table.mx th.tha{background:var(--accent2);color:#fff;text-align:left;font-size:12px;font-weight:700;letter-spacing:0.01em;text-transform:none}
  table.mx td.tda{min-width:190px;max-width:260px;background:var(--surface)}
  table.mx td.tda input{width:100%;border:none;outline:none;font-family:var(--font);font-size:13px;color:var(--text);padding:9px 11px;background:transparent}
  table.mx td.tda input::placeholder{color:var(--text3)}
  table.mx td.tda input:focus{background:var(--accent-light)}
  /* The diary's own free-text column, same problem and same answer as the BOQ's
     Item Description: it was an <input>, which clips, so "Material Test through
     Elzinc…" read as "Material Test through Elzinc" cut mid-word with no way to
     see the rest. Heights are set per row after render by txtColGrow. */
  table.mx td.tda textarea{display:block;box-sizing:border-box;width:100%;min-height:38px;
    border:none;outline:none;resize:none;overflow:hidden;font-family:var(--font);font-size:13px;
    line-height:1.4;color:var(--text);background:transparent;padding:9px 11px;overflow-wrap:anywhere}
  table.mx td.tda textarea::placeholder{color:var(--text3)}
  table.mx td.tda textarea:focus{background:var(--accent-light)}
  /* The handle is absolutely positioned inside this header, so the header has to be
     a containing block. At ≤900px a later rule makes it position:sticky, which is
     also one — so this is the desktop case only and the two never fight. */
  table.mx th.tha{position:relative;min-width:190px}
  /* Phone: activity description is a tappable, ellipsized cell → tapVal modal */
  table.mx td.tda .mx-desc-tap{padding:9px 11px;font-size:13px;color:var(--text);min-height:38px}
  table.mx td.tda .mx-desc-tap.tapval-ph{color:var(--text3)}
  table.mx td.tdh{width:68px;text-align:center;background:var(--surface)}
  table.mx td.tdh input{width:100%;border:none;outline:none;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:13px;color:var(--text);padding:9px 4px;text-align:center;background:transparent}
  table.mx td.tdh.labour input:focus{background:#e8edf8}
  table.mx td.tdh.plant input:focus{background:var(--amber-light)}
  table.mx td.tdh.sub input:focus{background:var(--green-light)}
  table.mx td.tdw{width:110px;background:var(--surface2)}
  table.mx td.tdw select{width:100%;border:none;outline:none;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:12px;color:var(--accent);padding:8px 4px;background:transparent;cursor:pointer}
  table.mx td.tdt{width:66px;text-align:center;background:var(--accent-light);font-family:var(--num);font-variant-numeric:tabular-nums;font-size:13px;font-weight:600;color:var(--accent);padding:9px 7px}
  table.mx tbody tr:hover td.tda,table.mx tbody tr:hover td.tdh{background:#fafcff}
  .tr-tot td{background:var(--surface2)!important;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:12px;font-weight:700;padding:9px;text-align:center;border-top:2px solid var(--border-strong)!important}
  .tr-tot td:first-child{text-align:left;color:var(--text2);font-size:10px;letter-spacing:0.04em;text-transform:uppercase}
  /* Section subtotal — deliberately a LIGHTER sibling of .tr-tot, not a clone: the
     grand total must stay the heaviest line on the table, or three similar-looking
     bands read as three grand totals. */
  .tr-sub td{background:#f1f5f9!important;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:11.5px;font-weight:600;padding:7px 9px;text-align:center;border-top:1px solid var(--border-strong)!important;color:var(--text2)}
  .tr-sub td:first-child{text-align:left;color:var(--text3);font-size:10px;letter-spacing:0.04em;text-transform:uppercase;background:#f1f5f9!important}

  .sgrid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:16px}
  .sc{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-sm)}
  .sc.fw{grid-column:1/-1}
  .sch{padding:11px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--surface2)}
  .sct{font-size:10px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--text2)}
  .scb{padding:14px 16px}
  .scb textarea{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:9px 11px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface);resize:vertical;min-height:80px;line-height:1.6;transition:border-color 0.15s,box-shadow 0.15s}
  .scb textarea:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .li{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin-bottom:7px}
  .li input,.li select{border:1px solid var(--border);border-radius:3px;padding:4px 7px;font-family:var(--font);font-size:12px;color:var(--text);background:var(--surface);min-width:0}
  .li input:focus,.li select:focus{outline:none;border-color:var(--accent)}
  .li select{cursor:pointer;color:var(--accent);font-variant-numeric:tabular-nums}
  /* Six columns and a select in a ~478px half-panel, so every width here is measured
     rather than guessed. The numeric columns carry `flex: 1 0 <basis>` — grow, NEVER
     shrink — because a money cell that does not fit CLIPS SILENTLY (`€1,475.00` read
     as `€1,4…`), the same failure the BOQ money columns hit. Description and BOQ item
     absorb the shrink instead: an <input> and a <select> both degrade honestly, and
     they are the two the user can widen the window for. */
  .lid{flex:3 1 70px;min-width:0}
  .liq{flex:1 0 42px;text-align:center}
  .liu{flex:1 0 52px}
  .lis{flex:2 1 70px;min-width:0}
  /* Line total (qty x rate). Read-only, so a span rather than a disabled input — but it
     carries a transparent border the same width as the inputs beside it, or it sits 1px
     out of true on the row's baseline. */
  .lit{flex:1 0 84px;text-align:right;padding:4px 7px;border:1px solid transparent;font-family:var(--mono);font-size:11px;color:var(--text2);font-variant-numeric:tabular-nums;white-space:nowrap}
  /* The header shares the row's OWN width classes — a caption strip sized separately
     drifts out of line with the fields under it the moment either side changes. */
  .li-h{display:flex;gap:7px;margin-bottom:5px;font-size:10px;color:var(--text3);font-weight:500;letter-spacing:.04em;text-transform:uppercase}
  .li-h span{padding:0 7px;border:1px solid transparent;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .li-h .lit{font-family:var(--font);font-size:10px;color:var(--text3)}
  .li-tot{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-top:8px;padding-top:8px;border-top:1px solid var(--border);font-size:11px;color:var(--text3);font-weight:600;letter-spacing:.03em;text-transform:uppercase}
  .li-tot b{font-family:var(--mono);font-size:12.5px;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:normal}
  .lit-card{flex:none;padding:0;border:0;text-align:left;font-size:13px;color:var(--text)}
  /* Phone: the inventory row (desc + qty + unit + €/unit + BOQ select + ×) is too
     wide for 390px — wrap the description to its own line so the rest fit below. */
  @media(max-width:600px){.li{flex-wrap:wrap}.li .lid{flex:1 1 100%}.li .lis{flex:1 1 42%}}
  /* Day cost recap. Deliberately a hairline strip with no fill or card — it is a
     reference line above the form, not a dashboard, and the figures it repeats all
     live in the matrix footer as well. */
  /* Every SECTION HEADING on the diary shares ONE left rail — the card-content
     rail. Five of the diary's sections put their heading INSIDE a padded card, so
     it sits at gutter + 17px (card border 1px + card padding 16px). The two BARE
     headings — this KPI strip and the Hours Matrix caption — must land on that same
     rail or the headings zig-zag down the page (owner-reported 2026-09-21: the
     alignment 'still doesn't look neat'; the earlier read that 'cost today is too
     far left' meant it poked LEFT of the card headings, i.e. move it RIGHT to meet
     them, not left to the gutter). 17px reproduces the card-content offset at ANY
     gutter, so this holds on phone and desktop alike. The border-bottom still spans
     the full box — an inset-content, full-width-rule divider. */
  .dsum{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 26px;padding:2px 17px 11px;margin-bottom:12px;border-bottom:1px solid var(--border)}
  .dsum-c{display:flex;flex-direction:column;gap:3px;min-width:0}
  .dsum-l{font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);white-space:nowrap}
  .dsum-v{font-size:15px;font-weight:700;line-height:1.15;color:var(--text);font-variant-numeric:tabular-nums;white-space:nowrap}
  .dsum-v.ok{color:#1a5c3a}
  .dsum-v.bad{color:#b91c1c}
  /* an allowable lower than its cost reads red (costOver in app.js) — the cells carry an inline green */
  table.mx td.over{color:#b91c1c!important}
  .dsum-v.mut{font-size:13px;font-weight:600;color:var(--text2)}
  @media(max-width:600px){.dsum{gap:4px 18px;padding-bottom:9px;margin-bottom:10px}.dsum-v{font-size:13.5px}.dsum-v.mut{font-size:12px}}
  .llbl{display:flex;gap:7px;margin-bottom:5px;font-size:10px;color:var(--text3);font-weight:500;letter-spacing:0.05em;text-transform:uppercase}
  /* The phone card layout below carries its own per-field labels — this
     desktop-style column header doesn't line up with the cards underneath it
     and is pure noise on phone (cascade note: must come AFTER the base .llbl
     rule above, or the base rule's later source position wins). */
  @media(max-width:600px){.llbl{display:none}}
  .llbl span{flex:3}.llbl span:nth-child(2){flex:1;text-align:center}.llbl span:nth-child(3){flex:1}.llbl span:nth-child(4){flex:2}
  .itabs{display:flex;border-bottom:1px solid var(--border);margin-bottom:10px}
  .itab{font-size:11px;padding:5px 11px;cursor:pointer;color:var(--text3);border-bottom:2px solid transparent}
  .itab:hover{color:var(--text)}.itab.active{color:var(--accent);border-bottom-color:var(--accent)}
  .ipanel{display:none}.ipanel.active{display:block}
  .rmv{width:18px;height:18px;border-radius:50%;border:1px solid var(--border);background:transparent;color:var(--text3);cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;transition:all 0.15s;flex-shrink:0}
  .rmv:hover{background:var(--red-light);border-color:var(--red);color:var(--red)}

  .res-panel{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-bottom:14px;box-shadow:var(--shadow-sm)}
  .res-panel-hdr{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid var(--border)}
  .res-panel-title{font-size:11px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:var(--text2)}
  /* auto-fit, not repeat(3,1fr) + a viewport breakpoint: since the modules moved
     to a left sidebar (2026-09-06) the viewport is up to 214px wider than the
     content column, so a @media(max-width:700px) rule no longer describes the
     space these cards actually get — at a 768px viewport the column is 554px
     and three min-content tracks pushed the PAGE 195px sideways. auto-fit lets
     the row wrap by its OWN width; minmax(0,…) + .rg{min-width:0} stop a long
     resource name widening a track (the grid min-content trap, again). */
  .res-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}
  .rg{background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:11px;min-width:0}
  .rgt{font-size:10px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;margin-bottom:9px;padding-bottom:7px;border-bottom:1px solid var(--border)}
  /* Each group is a disclosure: the header is the whole tap target, the body is
     hidden (never un-rendered — readResInputs scrapes those inputs) and the
     chevron rotates. The .rgt rule above is the standalone-heading look; inside
     the header it is just the label, so its rule/spacing are reset here. */
  .rg-hd{display:flex;align-items:center;gap:8px;width:100%;background:none;border:0;padding:0;
    font-family:var(--font);text-align:left;cursor:pointer;min-height:24px;color:inherit}
  .rg-hd .rgt{margin:0;padding:0;border-bottom:none;flex:1;min-width:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .rg-chev{display:flex;align-items:center;color:var(--text3);flex-shrink:0;transition:transform .15s var(--ease)}
  .rg-chev .ic{width:14px;height:14px}
  .rg.open .rg-chev{transform:rotate(90deg)}
  .rg-count{flex-shrink:0;min-width:18px;text-align:center;font-size:10px;font-weight:700;
    color:var(--text2);background:var(--surface);border:1px solid var(--border);border-radius:9px;padding:1px 6px}
  .rg-bd{display:none;margin-top:9px;padding-top:8px;border-top:1px solid var(--border)}
  .rg.open .rg-bd{display:block}
  @media(max-width:600px){.rg-hd{min-height:44px}.rg{padding:2px 11px}.rg.open{padding:11px}}
  .rgt-l{color:#1a5c8a}.rgt-p{color:var(--amber)}.rgt-s{color:var(--green)}
  .ri{display:flex;align-items:center;gap:5px;margin-bottom:5px}
  /* min-width:0 — an <input> is a flex item with min-width:auto, i.e. it refuses
     to shrink below its own intrinsic ~170px, so in a narrow resource card the
     name field and the × spilled out of the card's own border (visible at 768px
     once the left sidebar took 214px off the content column) */
  .ri input{flex:1;min-width:0;border:1px solid var(--border);border-radius:3px;padding:4px 7px;font-family:var(--font);font-size:12px;color:var(--text);background:var(--surface)}
  .ri input:focus{outline:none;border-color:var(--accent)}

  /* DASHBOARD */
  .dgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:22px}
  .dc{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px 22px;box-shadow:var(--shadow-sm);transition:box-shadow 0.18s var(--ease),transform 0.18s var(--ease)}
  .dc:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
  .dc-icon{width:38px;height:38px;border-radius:11px;display:flex;align-items:center;justify-content:center;font-size:17px;margin-bottom:13px;flex-shrink:0}
  .dcl{font-size:11px;color:var(--text3);font-weight:600;letter-spacing:0.04em;text-transform:uppercase;margin-bottom:4px}
  .dcv{font-size:29px;font-weight:800;color:var(--text);line-height:1.1;margin-bottom:3px;letter-spacing:-0.02em;font-variant-numeric:tabular-nums}
  .dcs{font-size:11px;color:var(--text3);font-weight:500}
  /* project-to-date totals — last on the page, so they name themselves */
  .dash-proj{margin-top:20px;padding-top:14px;border-top:1px solid var(--border)}
  .dash-proj-h{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text2);margin-bottom:10px}
  .dash-proj-h span{font-weight:500;letter-spacing:0;text-transform:none;color:var(--text3);margin-left:8px}
  .wtbl{width:100%;border-collapse:collapse;font-size:13px}
  .wtbl th{text-align:left;padding:11px 14px;background:var(--th-bg);color:var(--th-text);font-size:10px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;border-bottom:1px solid var(--border)}
  .wtbl td{padding:11px 14px;border-bottom:1px solid var(--border);color:var(--text);vertical-align:middle}
  .wtbl tbody tr:hover td{background:var(--accent-light)}
  .wtbl tbody tr:last-child td{border-bottom:none}
  .mono{font-family:var(--num);font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;color:var(--text2);font-size:12px}
  .over-budget{color:var(--red)!important;font-weight:700}
  .on-budget{color:var(--green)!important;font-weight:600}
  .pbar{height:6px;background:var(--border);border-radius:4px;overflow:hidden;margin-top:4px;min-width:60px}
  .pbar-fill{height:100%;border-radius:4px}
  .pf-ok{background:var(--green)}.pf-warn{background:var(--amber)}.pf-over{background:var(--red)}

  /* JOBS */
  .jlist{display:grid;gap:12px}
  .jtitle{font-size:15px;font-weight:500;color:var(--accent2);display:flex;align-items:center;gap:8px}
  .jcount{font-size:11px;font-weight:700;color:var(--text3);background:var(--surface2);border:1px solid var(--border);border-radius:9px;padding:1px 7px;line-height:16px}
  .jcount:empty{display:none}
  .jtools{display:flex}
  .jsearch{width:100%;max-width:360px;padding:8px 11px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);font:inherit;font-size:13px;color:var(--text)}
  .jsearch:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light)}
  /* The register: one grid, so every row's columns line up with the header.
     Job no. | Project | Client | actions. */
  .jtable{--jcols:minmax(92px,150px) minmax(0,2.2fr) minmax(0,1.3fr) 136px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow-sm);overflow:hidden}
  .jtable.jno-acts{--jcols:minmax(92px,150px) minmax(0,2.2fr) minmax(0,1.3fr) 0}
  .jhead,.jcard{display:grid;grid-template-columns:var(--jcols);column-gap:16px;align-items:center}
  .jhead{padding:0 17px;border-left:3px solid transparent;background:var(--surface2);border-bottom:1px solid var(--border)}
  .jhead .jh{display:flex;align-items:center;gap:4px;background:none;border:0;padding:9px 0;font:inherit;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);cursor:pointer;text-align:left}
  .jhead .jh:hover,.jhead .jh.on{color:var(--accent)}
  .jh-ar{font-size:9px;width:9px}
  .jcard{padding:12px 17px;cursor:pointer;border-top:1px solid var(--border);border-left:3px solid transparent;transition:background .14s var(--ease)}
  .jhead+.jcard,.job-arch-body>.jcard:first-child{border-top:0}
  .jcard:hover{background:var(--surface2)}
  .jcard.active-job{background:var(--accent-light);border-left-color:var(--accent)}
  .jcard[hidden]{display:none}
  .jnum{font-family:var(--mono);font-size:12px;color:var(--text2);min-width:0;overflow-wrap:anywhere}
  .jcard .jnum:not(.jempty){justify-self:start;background:var(--surface2);border:1px solid var(--border);border-radius:5px;padding:2px 7px}
  .jcard.active-job .jnum:not(.jempty){background:var(--surface)}
  .jmain{min-width:0}
  .jline{display:flex;align-items:center;gap:8px;min-width:0}
  .jname{font-weight:500;font-size:14px;min-width:0}
  .jcur{flex:0 0 auto}
  .jcli{font-size:13px;color:var(--text2);min-width:0;overflow-wrap:anywhere}
  .jempty{color:var(--text3);opacity:.7}
  .jcli-none{display:none}
  .jmeta{font-size:11px;color:var(--text3);margin-top:2px}
  .jacts{display:flex;gap:6px;flex:0 0 auto;justify-content:flex-end}
  .jempty-box{background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:24px;text-align:center;color:var(--text3);font-size:13px}
  .jtable .jempty-box{border:0;border-top:1px solid var(--border);border-radius:0}
  .jempty-box[hidden]{display:none}
  /* A phone folds each row into a card: the name beside the buttons, the job
     number and client underneath. Same cells, a different grid. */
  @media(max-width:640px){
    .jtable{background:none;border:0;box-shadow:none;overflow:visible;display:grid;gap:9px}
    .jhead{display:none}
    .jsearch{max-width:none}
    .jcard{grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"main main acts" "num cli cli";row-gap:6px;column-gap:8px;
      background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow-sm);padding:12px 14px}
    .jcard.active-job{border-color:var(--accent);border-left:4px solid var(--accent)}
    .jcard:hover{background:var(--surface)}
    .jcard.active-job:hover{background:var(--accent-light)}
    .jhead+.jcard,.job-arch-body>.jcard:first-child{border-top:1px solid var(--border)}
    .jcard.active-job{border-top-color:var(--accent)}
    .jmain{grid-area:main;align-self:center}
    .jacts{grid-area:acts;align-self:start}
    .jnum{grid-area:num;font-size:11px}
    .jnum.jempty{display:none}
    .jcli{grid-area:cli;font-size:12px;align-self:center}
    .jnum.jempty+.jmain+.jcli{grid-column:1/-1}
    .jcli-none{display:inline}.jcli-dash{display:none}
    .jtable .jempty-box{border:1px solid var(--border);border-radius:6px}
  }
  .tag{display:inline-block;font-size:10px;font-weight:600;padding:2px 7px;border-radius:10px;text-transform:uppercase;background:var(--accent-light);color:var(--accent)}
  /* A long project name must shrink and wrap rather than push the buttons off
     the row; white-space alone cannot break an unbroken run. */
  .jname,.jmeta{overflow-wrap:anywhere}
  /* Archiving is not destruction, so the control is an ordinary outline button
     — the red one it replaced said "this ends here", which is exactly what is
     no longer true. */
  .job-arch-btn:hover{border-color:var(--accent);color:var(--accent)}
  /* Archived projects — the registers' own archive section, one level out. */
  .job-arch{margin:22px 0 10px;border-top:1px solid var(--border);padding-top:10px}
  .job-arch-hd{display:flex;align-items:center;gap:8px;width:100%;background:none;border:0;padding:9px 2px;
    cursor:pointer;font:inherit;font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
    color:var(--text3);text-align:left;border-radius:6px}
  .job-arch-hd:hover{background:var(--surface2);color:var(--text2)}
  .job-arch-cv{font-size:10px;width:11px;flex:0 0 11px}
  .job-arch-n{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 6px;
    border-radius:9px;background:var(--surface2);border:1px solid var(--border);color:var(--text3);
    font-size:11px;font-weight:700;letter-spacing:0}
  /* Stated rather than left to the UA rule: a later author rule setting display
     on .job-arch-body would otherwise beat [hidden] and the section never shuts. */
  .job-arch-body[hidden]{display:none!important}
  .job-arch-body{margin-top:4px}
  .jcard-arch{cursor:default}
  .jcard-arch:hover{background:var(--surface)}
  .jcard-arch .jname{color:var(--text3)}

  /* BOQ */
  .boq-upload{border:2px dashed var(--border);border-radius:8px;padding:20px;text-align:center;cursor:pointer;transition:all 0.15s;background:var(--surface);flex:1;position:relative}
  .boq-upload:hover{border-color:var(--accent);background:var(--accent-light)}
  .boq-info-btn{position:absolute;top:8px;right:8px;width:20px;height:20px;border-radius:50%;border:1px solid var(--border-strong);background:var(--surface);color:var(--text3);font-size:12px;font-weight:700;font-style:italic;font-family:Georgia,serif;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
  .boq-info-btn:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-light)}
  /* Sits inside the .boq-upload drop-zone, which is itself clickable — the
     handler stops propagation so this never opens the file picker. */
  .boq-tpl-link{margin-top:9px;background:none;border:none;padding:6px 4px;min-height:32px;cursor:pointer;font:inherit;font-size:11.5px;font-weight:600;color:var(--accent);text-decoration:underline;text-underline-offset:2px}
  .boq-tpl-link:hover{color:var(--accent2)}
  /* The 8-column format tables do not fit a phone. They scroll in their own
     container (inline overflow, so the stress overflow scan skips them the
     same way it skips every other scroller) rather than being silently
     clipped — Level is the column these tables most need to show. */
  .boq-fmt-tbl{width:100%;min-width:500px;border-collapse:collapse;font-size:11px;margin:4px 0 2px}
  .boq-fmt-tbl th,.boq-fmt-tbl td{border:1px solid var(--border);padding:4px 7px;text-align:left}
  .boq-fmt-tbl th{background:var(--surface2);font-weight:700;color:var(--text2)}
  .boq-fmt-tbl td{color:var(--text2)}
  .boq-fmt-tbl .boq-fmt-hi{background:var(--accent-light);color:var(--accent2);font-weight:600}
  .boq-searchbar{display:flex;align-items:center;gap:12px;margin-bottom:10px}
  .boq-search{position:relative;display:flex;align-items:center;flex:0 1 420px;min-width:0}
  .boq-search .ic{position:absolute;left:10px;width:15px;height:15px;color:var(--text3);pointer-events:none}
  .boq-search input{width:100%;box-sizing:border-box;padding:8px 30px 8px 32px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);color:var(--text);font-family:var(--font);font-size:13px}
  .boq-search input:focus{outline:none;border-color:var(--accent2);box-shadow:0 0 0 3px var(--accent2-light)}
  .boq-search input::-webkit-search-cancel-button{display:none}
  .boq-search-x{position:absolute;right:7px;border:none;background:none;color:var(--text3);font-size:16px;line-height:1;cursor:pointer;padding:2px 4px;border-radius:4px}
  .boq-search-x:hover{color:var(--text);background:var(--surface2)}
  .boq-search-res{font-size:11.5px;color:var(--text2);font-weight:600;font-variant-numeric:tabular-nums}
  .boq-search-res b{color:var(--accent2)}
  .boq-tbl-wrap{overflow-x:auto;border:1px solid var(--boq-grid-strong);border-radius:var(--radius-xs);background:var(--surface)}
  /* Spreadsheet look (owner-asked 2026-10-11: "more like Excel … lines and
     formatting, very clean"). One hairline grid on every cell, a quiet grey
     header, light heading rows instead of navy bands, and tighter rows. Only the
     paint changed — every control, dropdown and drill-down is the same markup. */
  .boq-tbl-wrap,.boq-tbl{--boq-grid:#e3e7ee;--boq-grid-strong:#cfd6e1;--boq-head:#f3f5f8}
  .boq-tbl{width:100%;border-collapse:collapse;font-size:13px}
  .boq-tbl th{background:var(--boq-head);color:var(--text2);padding:7px 10px;text-align:left;font-size:10.5px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;border-bottom:1px solid var(--boq-grid-strong);border-right:1px solid var(--boq-grid);white-space:nowrap;position:sticky;top:0;z-index:2}
  .boq-tbl th.num{text-align:right}
  .boq-tbl td{padding:0;border-bottom:1px solid var(--boq-grid);border-right:1px solid var(--boq-grid);background:var(--surface);vertical-align:middle}
  .boq-main-row.alt td{background:var(--surface)}
  .boq-main-row:hover td{background:#f7f9fc}
  .boq-tbl td input{width:100%;border:none;outline:none;font-family:var(--font);font-size:12.5px;color:var(--text);background:transparent;padding:6px 10px}
  /* Phone: item description is a tappable, ellipsized cell → tapVal modal */
  .boq-tbl td[data-col="desc"] .boq-desc-tap{padding:11px 12px;font-size:12.5px;color:var(--text);min-height:40px}
  .boq-tbl td[data-col="desc"] .boq-desc-tap.tapval-ph{color:var(--text3)}
  /* Item description is the ONE free-text column in the bill, so it is the one
     that has to WRAP. It was an <input>, which clips rather than wraps, so a real
     description read as "Excavate to suitab" and the rest of it was unreachable at
     any width — the same silent failure the money columns and the unit cell already
     hit. A textarea wraps; overflow-wrap:anywhere is what breaks a run with no
     spaces in it (white-space:normal alone cannot). Heights are set per row after
     render by txtColGrow, so a cell is exactly as tall as its own text. */
  .boq-tbl td[data-col="desc"] textarea{display:block;box-sizing:border-box;width:100%;min-height:30px;
    border:none;outline:none;resize:none;overflow:hidden;font-family:var(--font);font-size:12.5px;
    line-height:1.4;color:var(--text);background:transparent;padding:6px 10px;overflow-wrap:anywhere}
  .boq-tbl td[data-col="desc"] textarea::placeholder{color:var(--text3)}
  .boq-tbl td[data-col="desc"] textarea:focus{background:var(--surface);box-shadow:inset 0 0 0 2px var(--accent)}
  /* Every other column declares a width, so the description is the only flexible
     one and absorbs ALL the squeeze — measured at 137px on a 1280px screen with
     the sidebar open, which is a five-line cell for one ordinary bill item. The
     most important column in a bill must not be the one that gets crushed, so it
     takes a floor and the table scrolls instead (it already does at that width).
     A width set by dragging the handle beats this: the injected stylesheet is
     appended to <head> after app.css, so it wins at equal specificity. */
  @media(min-width:601px){.boq-tbl th[data-col="desc"],.boq-tbl td[data-col="desc"]{min-width:260px}}
  /* …and it is the one column worth widening, so it carries the one drag handle
     (shared with the diary matrix's Activity Description — see TXTCOLS in app.js).
     The BOQ <th> is position:sticky, which is ALREADY a containing block for an
     absolutely-positioned child — do NOT add position:relative there, that would
     kill the sticky header. Width persists per device, through an injected
     stylesheet appended after this file so a dragged width beats the floor below. */
  .txtcol-rz{position:absolute;right:0;top:5px;bottom:5px;width:8px;cursor:col-resize;
    z-index:6;border-radius:2px;touch-action:none}
  .txtcol-rz:hover,.txtcol-rz.on{background:var(--accent);opacity:.45}
  /* Phone renders both descriptions through tapVal, not a textarea, and a hairline
     drag handle is not a touch target — no width to set there, so none is offered. */
  @media(max-width:600px){.txtcol-rz{display:none}}
  .boq-tb-btns{display:flex;flex-direction:column;gap:6px;padding-top:4px}
  .boq-tbl td input::placeholder{color:var(--text3)}
  .boq-tbl td input:focus{background:var(--surface);box-shadow:inset 0 0 0 2px var(--accent)}
  /* Tight rows are a pointer thing; a finger keeps the taller cell it had. */
  @media(max-width:600px){.boq-tbl td input{padding:11px 12px}}
  /* The WBS code shares its cell with the grip and the drill-down arrow, and the
     auto table layout squeezed it to "1.1." — the code a QS reads first. */
  .boq-tbl th[data-col="wbs"],.boq-tbl td[data-col="wbs"]{min-width:132px}
  .boq-tbl td[data-col="claimval"]{padding:0 10px;text-align:right;font-family:var(--num);font-variant-numeric:tabular-nums}
  .boq-tbl td input.num{text-align:right;font-family:var(--num);font-variant-numeric:tabular-nums}
  .boq-c-wbs{width:176px}.boq-c-unit{width:140px}.boq-c-num{width:102px}
  /* Unit cell: the value, plus the switch that makes the diary obey it. */
  .boq-unit-cell{display:flex;align-items:center;gap:2px}
  .boq-unit-cell input{flex:1;min-width:0}
  .boq-unitlock{flex:0 0 auto;width:22px;height:22px;display:flex;align-items:center;justify-content:center;
    padding:0;border:1px solid transparent;border-radius:5px;background:transparent;color:var(--text3);
    cursor:pointer;opacity:.45;transition:opacity .12s,color .12s,background .12s}
  .boq-unitlock:hover{opacity:1;background:var(--surface2)}
  .boq-unitlock.on{opacity:1;color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}
  /* The per-unit rate reads as money with a quiet unit after it. */
  .boq-d-per{color:var(--text3);font-size:9.5px;font-weight:400}
  .boq-detail-tbl td.boq-d-rate{white-space:nowrap}
  /* Diary: a unit the site cannot change, and a quantity it must supply. */
  .mx-unit-lock{display:flex;align-items:center;justify-content:center;gap:3px;padding:6px 4px;
    font-size:11px;color:var(--text2);white-space:nowrap}
  .mx-unit-lock svg{flex:0 0 auto;opacity:.55}
  td.mx-need{background:#fff7ed !important;box-shadow:inset 0 0 0 1px #fdba74}
  td.mx-need input,td.mx-need .tapval{color:#9a3412}
  td.mx-need input::placeholder{color:#c2410c;opacity:.8}
  /* Money columns carry a currency symbol, thousands separators and 2dp, so they need
     more room than a bare quantity — €343,240.70 clips inside a 102px cell (the value
     lives in an <input>, which clips rather than wraps, so it fails silently). */
  .boq-tbl th[data-col="rate"],.boq-tbl td[data-col="rate"],
  .boq-tbl th[data-col="total"],.boq-tbl td[data-col="total"],
  .boq-tbl th[data-col="reccost"],.boq-tbl td[data-col="reccost"],
  .boq-tbl th[data-col="recmat"],.boq-tbl td[data-col="recmat"],
  .boq-tbl th[data-col="recrate"],.boq-tbl td[data-col="recrate"]{min-width:124px}
  /* The unit sits beside the switch that enforces it, so the cell needs room for
     both — an <input> squeezed to one character shows "m" where it means "m²", and
     min-width (not width) is what the auto table algorithm honours. */
  .boq-tbl th[data-col="unit"],.boq-tbl td[data-col="unit"]{min-width:140px}
  .boq-unit-cell input{min-width:72px}
  .boq-c-chk{width:56px;text-align:center}.boq-c-act{width:112px;text-align:center;white-space:nowrap}
  .boq-c-act,.boq-tbl td.boq-c-act{padding:0 8px}
  .boq-c-chk input[type=checkbox]{width:16px;height:16px;accent-color:var(--green);cursor:pointer;vertical-align:middle}
  .boq-wbs{display:flex;align-items:center;gap:3px;padding:0 6px 0 4px}
  /* line items indent to their section depth so nesting reads under its heading */
  .boq-wbs.d1{padding-left:4px}.boq-wbs.d2{padding-left:14px}.boq-wbs.d3{padding-left:24px}.boq-wbs.d4{padding-left:34px}
  .boq-wbs input{padding:6px 0;color:var(--text);font-family:var(--num);font-variant-numeric:tabular-nums;font-size:12px;flex:1;min-width:0}
  .boq-exp-btn{width:16px;height:16px;border:none;background:none;cursor:pointer;color:var(--accent2);font-size:10px;padding:0;line-height:1;flex-shrink:0;opacity:0.6;transition:opacity 0.15s}
  .boq-exp-btn:hover{opacity:1}
  .boq-exp-btn.open{transform:rotate(90deg)}
  .boq-detail-row>td{padding:0!important;background:#f0f6ff!important;border-top:none!important}
  .boq-detail-inner{padding:0 0 12px 36px}
  .boq-detail-tbl{width:100%;border-collapse:collapse;font-size:11px}
  .boq-detail-tbl th{background:#dbeafe;color:var(--accent2);padding:5px 10px;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;text-align:left;border-bottom:1px solid #bfdbfe;white-space:nowrap}
  .boq-detail-tbl th.r{text-align:right}
  .boq-detail-tbl th.c,.boq-detail-tbl td.c{text-align:center}
  /* "Claimed upstream" tick + variation attribution select in the drill-down */
  .boq-claim-cell{white-space:nowrap;text-align:center}
  .boq-claim-lab{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;vertical-align:middle}
  .boq-claim-lab input{width:15px;height:15px;cursor:pointer;accent-color:var(--accent);margin:0}
  .boq-claim-var{margin-left:6px;max-width:150px;font-size:10px;padding:2px 4px;border:1px solid var(--border-strong);border-radius:5px;background:var(--surface);color:var(--text2);vertical-align:middle}
  .boq-detail-tbl tr.boq-claimed td{background:#f0fdf4}
  .boq-detail-tbl tr.boq-claimed:hover td{background:#dcfce7}
  .boq-detail-tbl tr.boq-claimed td:nth-child(2){color:var(--text3)}
  .boq-claim-sum{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin-top:10px;padding:8px 12px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:7px;font-size:11px;color:#166534}
  .boq-detail-tbl td{padding:4px 10px;border-bottom:1px solid #e2ecfb;color:var(--text2);font-size:11px}
  .boq-detail-tbl td.r{text-align:right;font-variant-numeric:tabular-nums}
  .boq-detail-tbl tr:last-child td{border-bottom:none}
  .boq-detail-tbl tr:hover td{background:#eff6ff}
  .boq-detail-tbl .boq-dtot td{font-weight:700;color:var(--text);background:#dbeafe!important;border-top:2px solid #93c5fd}
  .boq-inv-sum{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 16px;margin-top:10px;padding:9px 12px;background:var(--accent-light);border:1px solid #bfdbfe;border-radius:7px;font-size:11px;color:var(--text2)}
  .boq-inv-lbl{font-weight:700;text-transform:uppercase;letter-spacing:.05em;font-size:9px;color:var(--accent2)}
  .boq-inv-parts{display:flex;flex-wrap:wrap;gap:4px 14px}
  .boq-inv-parts strong{color:var(--accent2);font-variant-numeric:tabular-nums}
  .boq-inv-note{margin-left:auto;font-style:italic;color:var(--text3)}
  /* Each inventory item named, with the category totals under them (owner-reported
     2026-09-13). A rollup line said a cost landed here and nothing about what was
     bought, which is the thing you opened the drill-down to check. */
  .boq-inv-hd{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;width:100%;margin-bottom:8px}
  .boq-inv-tbl{margin:0}
  .boq-inv-tbl tfoot .r{font-variant-numeric:tabular-nums}
  .boq-inv-cat{display:inline-block;font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;padding:2px 7px;border-radius:4px;background:var(--surface2);color:var(--text2);white-space:nowrap}
  .boq-inv-cat.mat{background:var(--accent-light);color:var(--accent2)}
  .boq-inv-cat.plant{background:#fef3c7;color:#92400e}
  .boq-inv-cat.gen{background:var(--surface2);color:var(--text3)}
  /* ── CLAIMED QUANTITY ─────────────────────────────── */
  .boq-tbl th.boq-claim,.boq-tbl td.boq-claim{background:rgba(5,150,105,.035)}
  .boq-tbl th.boq-claim{color:#047857}
  .boq-tbl td.boq-claim{color:#047857;font-weight:600}
  .boq-tbl td.boq-claim input{color:#047857;font-weight:600}
  .boq-grand td.boq-claim{color:#047857!important}
  .boq-claimbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;background:rgba(5,150,105,.08);border:1px solid rgba(5,150,105,.28);border-left:4px solid #059669;border-radius:8px;padding:10px 14px;margin-bottom:12px}
  .bcb-k{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:#047857}
  .bcb-v{font-family:var(--num);font-variant-numeric:tabular-nums;font-size:19px;font-weight:800;color:#047857;line-height:1}
  .bcb-bar{flex:1;min-width:90px;max-width:240px;height:7px;border-radius:4px;background:rgba(5,150,105,.18);overflow:hidden}
  .bcb-bar>span{display:block;height:100%;background:#059669;border-radius:4px}
  .bcb-pc,.bcb-n{font-size:11px;font-weight:600;color:var(--text2);font-variant-numeric:tabular-nums}
  .bcb-n{margin-left:auto;color:var(--text3)}
  /* ── A SUB-ITEM ENTERED BY HAND ───────────────────── */
  .boq-man-add{display:inline-flex;align-items:center;gap:6px;margin-top:10px;background:var(--surface);border:1px dashed var(--accent);color:var(--accent);border-radius:var(--radius-xs);font-family:var(--font);font-size:11.5px;font-weight:700;padding:7px 12px;cursor:pointer;transition:background .12s}
  .boq-man-add:hover{background:var(--accent-light)}
  .boq-man-adds{display:flex;flex-wrap:wrap;gap:0 8px}
  /* "Add cost manually": the same record with nothing to measure, so the
     quantity, unit and the unit-lock note have no place in it. */
  #boqManModal.bm-cost .bm-qty,#boqManModal.bm-cost #bmUnitNote{display:none!important}
  /* ── BOQ tracking groups (the panel above the bill, and its editor) ── */
  .boq-grp{margin-bottom:12px}
  .boq-grp:empty{display:none}
  .boq-grp-empty,.boq-grp-hd{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 12px;border:1px dashed var(--border-strong);border-radius:8px;background:var(--surface)}
  .boq-grp-hd{border:none;background:none;padding:0 2px 8px}
  .boq-grp-t{font-size:12px;font-weight:700;color:var(--text)}
  .boq-grp-hint{flex:1 1 260px;min-width:0;font-size:11px;color:var(--text3)}
  .boq-grp-new{margin-left:auto}
  .boq-grp-card{border:1px solid var(--border);border-left:3px solid #7c3aed;border-radius:8px;background:var(--surface);margin-bottom:8px;min-width:0}
  .boq-grp-head{display:flex;align-items:center;gap:8px 10px;flex-wrap:wrap;padding:8px 10px;min-width:0}
  .boq-grp-badge{font-size:11px;font-weight:800;color:#6d28d9;background:rgba(124,58,237,.1);border-radius:5px;padding:2px 7px;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
  .boq-grp-name{flex:1 1 180px;min-width:0;font-size:12.5px;font-weight:600;color:var(--text);overflow-wrap:anywhere}
  .boq-grp-meta{font-size:11px;color:var(--text3);white-space:nowrap}
  .boq-grp-warn{font-size:10.5px;font-weight:600;color:#b45309;background:#fef3c7;border-radius:4px;padding:1px 6px}
  .boq-grp-figs{display:flex;gap:14px;flex-wrap:wrap}
  .boq-grp-figs span{display:flex;flex-direction:column;align-items:flex-end;line-height:1.2}
  .boq-grp-figs i{font-style:normal;font-size:9.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--text3)}
  .boq-grp-figs b{font-size:12px;font-variant-numeric:tabular-nums;color:var(--text)}
  .boq-grp-acts{display:flex;gap:4px}
  .boq-grp-body{border-top:1px solid var(--border);padding:8px 10px 10px;min-width:0}
  .boq-grp-sub{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text3);margin:4px 0 6px}
  .boq-grp-tw{overflow-x:auto;margin-bottom:10px}
  .boq-grp-mem td{overflow-wrap:anywhere}
  .boq-grp-mem td.r{white-space:nowrap;overflow-wrap:normal}
  .boq-grp-ld{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-width:140px;max-width:420px}
  .boq-grp-code{white-space:nowrap;font-weight:600}
  .boq-via{display:inline-block;margin-right:7px;background:rgba(124,58,237,.1);color:#6d28d9;font-size:9px;font-weight:700;padding:2px 6px;border-radius:4px;vertical-align:1px;white-space:nowrap}
  .boq-via-claim{color:var(--text3);font-weight:700}
  .wbs-pick-tag{display:inline-block;margin-left:6px;background:rgba(124,58,237,.1);color:#6d28d9;font-size:9px;font-weight:700;padding:1px 5px;border-radius:8px;vertical-align:1px}
  /* A split line's sub-items (boqSplit): indented under the line, a hair lighter,
     joined to it by an elbow — and the line's own sum cells read as figures, not inputs. */
  .boq-sub-row td{background:var(--surface2)}
  .boq-wbs.boq-sub-wbs,.boq-wbs.d1.boq-sub-wbs{padding-left:18px}.boq-wbs.d2.boq-sub-wbs{padding-left:28px}.boq-wbs.d3.boq-sub-wbs{padding-left:38px}.boq-wbs.d4.boq-sub-wbs{padding-left:48px}
  .boq-sub-elbow{flex:0 0 9px;height:12px;margin:-6px 1px 0 0;border-left:1.5px solid var(--border);border-bottom:1.5px solid var(--border);border-bottom-left-radius:3px}
  .boq-sub-wbs input{font-size:11.5px}
  .boq-sub-row textarea,.boq-sub-row input{font-size:11.5px}
  .boq-sub-sum{display:block;padding:6px 6px;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:12px;font-weight:600;color:var(--text);text-align:right;white-space:nowrap}
  .boq-split .boq-sub-sum{border-bottom:1px dotted var(--border)}
  .boq-sub-share{font-size:10.5px;color:var(--text3);font-family:var(--num);font-variant-numeric:tabular-nums}
  .boq-sub-foot td{background:var(--surface2);padding:0 8px 8px!important;border-bottom:1px solid var(--border)}
  .boq-sub-foot-in{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;padding-left:22px}
  .boq-sub-foot-in.d2{padding-left:32px}.boq-sub-foot-in.d3{padding-left:42px}.boq-sub-foot-in.d4{padding-left:52px}
  .boq-sub-foot-in .boq-man-add{margin-top:6px}
  .boq-sub-merge{border-style:solid!important;border-color:var(--border)!important;color:var(--text2)!important}
  .boq-sub-diff{margin-top:6px;font-size:11px;color:var(--text3);overflow-wrap:anywhere;min-width:0}
  .boq-sub-diff b{color:var(--text);font-family:var(--num);font-variant-numeric:tabular-nums;font-weight:700}
  .boq-sub-ok{color:var(--green,#15803d);font-weight:600}
  .boq-sub-off{color:var(--amber,#b45309);font-weight:700}
  .boq-subof{background:rgba(14,116,144,.1);color:#0e7490}
  .boq-split-btn svg{width:13px;height:13px}
  .wbs-pick-sub{padding-left:26px!important;position:relative}
  .wbs-pick-sub::before{content:'';position:absolute;left:12px;top:7px;width:7px;height:9px;border-left:1.5px solid var(--border);border-bottom:1.5px solid var(--border);border-bottom-left-radius:3px}
  .boq-wbs-opt.boq-wbs-sub{margin-left:18px;width:calc(100% - 18px)}
  /* on a phone the WBS column is narrow: the code matters more than the elbow */
  @media (max-width:600px){.boq-sub-elbow{display:none}.boq-wbs.boq-sub-wbs,.boq-wbs.d1.boq-sub-wbs,.boq-wbs.d2.boq-sub-wbs,.boq-wbs.d3.boq-sub-wbs,.boq-wbs.d4.boq-sub-wbs{padding-left:12px}}
  .boq-grp-md{width:620px}
  .boq-grp-fields{display:grid;grid-template-columns:110px 1fr;gap:8px 10px}
  .md .boq-grp-fields label{display:flex;flex-direction:column;gap:3px}
  .boq-grp-fields input,.boq-grp-search{width:100%;min-width:0;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:7px 9px;font:inherit;font-size:13px;text-transform:none;letter-spacing:normal;color:var(--text);background:var(--surface)}
  .boq-grp-note{font-size:11px;color:var(--text3);margin:8px 0 10px;line-height:1.45}
  .boq-grp-split{display:flex;align-items:center;gap:6px 14px;flex-wrap:wrap;font-size:12px;margin-bottom:8px}
  .boq-grp-split>span{font-weight:700;color:var(--text2)}
  .md label.boq-grp-rad{display:flex;align-items:center;gap:5px;margin:0;text-transform:none;letter-spacing:normal;font-weight:400;font-size:12px;color:var(--text)}
  .boq-grp-pick{border:1px solid var(--border);border-radius:8px;max-height:46vh;overflow-y:auto;margin-top:8px}
  .boq-grp-psec{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text3);padding:8px 10px 3px;background:var(--surface2,#f8fafc)}
  .md label.boq-grp-opt{display:flex;align-items:center;gap:8px;margin:0;padding:7px 10px;border-top:1px solid var(--border);cursor:pointer;text-transform:none;letter-spacing:normal;font-weight:400;font-size:12px;color:var(--text);min-width:0}
  .md label.boq-grp-opt.on{background:rgba(124,58,237,.06)}
  .boq-grp-oc{flex:0 0 auto;font-weight:600;white-space:nowrap}
  .boq-grp-od{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text2)}
  .boq-grp-ob{flex:0 0 auto;font-size:11px;color:var(--text3);font-variant-numeric:tabular-nums}
  .boq-grp-w{flex:0 0 64px;width:64px;border:1px solid var(--border-strong);border-radius:5px;padding:4px 6px;font:inherit;font-size:12px}
  .boq-grp-count{margin-right:auto;font-size:11.5px;color:var(--text3)}
  @media(max-width:600px){
    .boq-grp-fields{grid-template-columns:1fr 1fr}
    .boq-grp-fields label.wide{grid-column:1/-1}
    .boq-grp-figs{width:100%;justify-content:space-between}
    .boq-grp-figs span{align-items:flex-start}
    .boq-grp-ob{display:none}
    .boq-grp-fields input,.boq-grp-search,.boq-grp-w{font-size:16px}
  }
  .boq-man-badge{display:inline-block;margin-right:7px;background:var(--accent-light);color:var(--accent2);font-size:8.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;padding:2px 6px;border-radius:4px;vertical-align:1px}
  .boq-man-row{background:rgba(37,99,235,.035)}
  .boq-man-date{color:var(--text2)}
  .boq-detail-empty{color:var(--text3);font-size:11px;font-style:italic}
  /* A bill line's description is long by nature, and can be one unbroken run —
     which `white-space:normal` alone cannot break, so it runs straight out of the
     dialog and off the screen (measured at 2790px on a 390px phone). */
  .bm-intro{font-size:12px;color:var(--text2);line-height:1.5;margin-bottom:12px;overflow-wrap:anywhere}
  .bm-intro strong{color:var(--accent2);display:inline-block;max-width:100%;vertical-align:bottom;
    overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
  /* The role reference arrives SHUT. The heading IS the button, full width, so
     there is one target rather than a caret to hit — and a shut section still says
     how many rows are inside it. `[hidden]` is stated !important rather than left
     to the UA rule: a later author rule setting `display` on the box would
     otherwise beat it and the section could never shut (the `#admBody [data-adm]`
     precedent one section over). */
  .adm-roles-hd{display:flex;align-items:center;gap:9px;width:100%;background:none;border:0;padding:2px 0 10px;cursor:pointer;
    font-family:var(--font);font-size:13.5px;font-weight:800;color:var(--text);text-align:left}
  .adm-roles-hd .ic{width:16px;height:16px;color:var(--accent2);flex-shrink:0}
  .adm-roles-cv{width:14px;height:14px;flex-shrink:0;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;color:var(--text3);transition:transform .15s}
  .adm-roles-hd.open .adm-roles-cv{transform:rotate(90deg)}
  .adm-roles-n{margin-left:auto;font-size:10px;font-weight:800;color:var(--text3);background:var(--surface2);border-radius:20px;padding:2px 9px;letter-spacing:.03em}
  #admRolesBox[hidden]{display:none!important}
  /* A <label> inside .md inherits `.md label{display:block}` (0,1,1), which beats a
     bare class (0,1,0) — Known Mistake #7. Scope it so the field stacks as written. */
  .md .bm-f{display:flex;flex-direction:column;gap:5px;margin:0;text-transform:none;font-weight:400;letter-spacing:normal;color:var(--text)}
  .bm-grid{display:flex;flex-wrap:wrap;gap:10px}
  .bm-f{display:flex;flex-direction:column;gap:5px;flex:1 1 100%;min-width:0}
  .bm-f.bm-half{flex:1 1 calc(50% - 5px)}
  .bm-f>span{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--text3)}
  .bm-f input{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:9px 11px;font-size:13px;font-family:var(--font);color:var(--text);outline:none}
  .bm-f input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light)}
  .bm-f input[readonly]{background:var(--surface2);color:var(--text2)}
  .bm-note{margin-top:9px;font-size:11px;color:var(--text2);background:var(--surface2);border-radius:var(--radius-xs);padding:7px 10px;line-height:1.45}
  .boq-notice{background:var(--accent-light);border:1px solid var(--accent);border-left:4px solid var(--accent);border-radius:6px;padding:10px 14px;font-size:12px;color:var(--accent2);margin-bottom:14px;line-height:1.6}
  /* ── BOQ SECTION HEADINGS ─────────────────────────── */
  .boq-sec-row td{padding:0!important;border-right:none!important;border-bottom:none!important}
  .boq-sec{display:flex;align-items:center;gap:8px;padding:4px 10px;border-bottom:1px solid var(--boq-grid)}
  /* 4-level section ramp: one bold navy banner (L1), then progressively lighter
     tints + deeper indent + a slim coloured spine so nesting reads calmly. */
  .boq-sec-l1{background:#e9edf3;color:var(--text);border-top:1px solid var(--boq-grid-strong);border-bottom-color:var(--boq-grid-strong)}
  /* Two solid navy bands stacked read as ONE band with two titles in it
     (owner-reported 2026-09-13). A real break above every top-level heading
     except the very first separates them whatever precedes or follows. */
  .boq-secgap{height:10px;background:var(--surface)}
  .boq-sec-l2{background:#f3f5f8;color:var(--text);padding-left:20px}
  .boq-sec-l3{background:#f8f9fb;color:var(--text);padding-left:30px}
  .boq-sec-l4{background:var(--surface);color:var(--text);padding-left:40px}
  .boq-grip{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;cursor:grab;color:currentColor;opacity:.4;font-size:13px;line-height:1;width:16px;border-radius:4px;touch-action:none;transition:opacity .15s;user-select:none}
  .boq-grip:hover{opacity:.9}
  .boq-grip:active{cursor:grabbing}
  .boq-sec-l1 .boq-grip{color:var(--text3)}
  .boq-row-dragging td,.boq-row-dragging .boq-sec{opacity:.45}
  .boq-drop-into>td{box-shadow:inset 0 2px 0 0 var(--accent-bright)!important}
  .boq-drop-into .boq-sec{box-shadow:inset 0 2px 0 0 var(--accent-bright)}
  .boq-sec-chev{background:none;border:none;cursor:pointer;color:var(--text3);display:inline-flex;align-items:center;padding:2px;border-radius:5px;flex-shrink:0;opacity:.9;transition:transform .15s,opacity .15s}
  .boq-sec-chev:hover{opacity:1}
  .boq-sec-chev.collapsed{transform:rotate(-90deg)}
  /* The bar's contents cluster on the LEFT, not at the far end of a row as wide
     as the whole bill: with the title on flex:1 the summary pill sat ~1530px out
     at a 1440px viewport, off screen and only reachable by scrolling the table
     sideways — no way to read a section's totals. Measured on main before the
     claimed columns widened the table further, so it was already true. */
  .boq-sec-title{flex:0 1 420px;min-width:90px;background:transparent;border:1px solid transparent;border-radius:6px;font-family:var(--font);font-weight:700;font-size:13px;padding:3px 6px;outline:none;color:var(--text)}
  .boq-sec-l1 .boq-sec-title{color:var(--text);font-size:13px}
  .boq-sec-l1 .boq-sec-title::placeholder{color:var(--text3)}
  .boq-sec-l2 .boq-sec-title{color:var(--text);font-size:12.5px;font-weight:600}
  .boq-sec-l3 .boq-sec-title{color:var(--text);font-size:12.5px;font-weight:600}
  .boq-sec-l4 .boq-sec-title{color:var(--text2);font-size:12.5px;font-weight:600;font-style:italic}
  .boq-sec-l2 .boq-sec-title::placeholder,.boq-sec-l3 .boq-sec-title::placeholder,.boq-sec-l4 .boq-sec-title::placeholder{color:var(--text3)}
  /* Editing a section title flips it to a solid white box with dark text so it
     stays readable — the level-1 banner is white-on-blue at rest. */
  .boq-sec-title:focus{background:#fff;color:var(--text);border-color:var(--accent-bright);text-transform:none;letter-spacing:normal}
  .boq-sec-title:focus::placeholder{color:var(--text3)}
  .boq-sec-lvl{flex-shrink:0;font-size:10px;font-weight:600;letter-spacing:.02em;padding:0 4px;color:var(--text3);line-height:1.4}
  .boq-sec-meta{font-size:11px;font-weight:500;color:var(--text3);white-space:nowrap;flex-shrink:0}
  /* Budget over recorded over claimed, each labelled, the figures right-aligned
     in their own grid column so the eye runs straight down them. Narrower than
     the one-line version it replaces, which is what the phone bar needed. */
  .boq-sec-sub{display:grid;grid-template-columns:auto auto auto;gap:1px 8px;align-items:baseline;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:11.5px;font-weight:600;white-space:nowrap;flex-shrink:0;color:var(--text);padding:1px 4px 1px 12px;border-left:1px solid var(--boq-grid-strong);letter-spacing:.01em;line-height:1.3}
  .bss-k{font-family:var(--font);font-size:10.5px;font-weight:500;color:var(--text3);text-align:left}
  .bss-v{text-align:right}
  .bss-x{text-align:right;font-size:10.5px;font-weight:500;color:var(--text3)}
  .boq-sec-acts{display:flex;gap:3px;flex-shrink:0;opacity:0;transition:opacity .15s}
  .boq-sec-row:hover .boq-sec-acts,.boq-sec-row:focus-within .boq-sec-acts{opacity:1}
  .boq-sec-btn{background:transparent;border:1px solid transparent;color:var(--text2);cursor:pointer;font-size:11px;font-weight:700;padding:3px 6px;border-radius:5px;line-height:1;min-width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;transition:background .12s}
    .boq-sec-btn:hover{background:var(--surface);border-color:var(--boq-grid-strong);color:var(--text)}
  .boq-sec-btn.off{opacity:.3;pointer-events:none}
  .boq-main-row.in-sec td:first-child{box-shadow:none}
  .boq-item-acts{display:flex;align-items:center;justify-content:flex-end;gap:2px}
  .boq-iact{width:22px;height:22px;border:1px solid transparent;background:var(--surface);color:var(--text2);border-radius:5px;font-size:11px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;transition:all .12s}
  .boq-iact:hover{background:var(--accent2);color:#fff;border-color:var(--accent2)}
  .boq-iact.del:hover{background:var(--red);border-color:var(--red)}
  @media(min-width:601px){.boq-item-acts{opacity:0;transition:opacity .15s}.boq-main-row:hover .boq-item-acts,.boq-main-row:focus-within .boq-item-acts{opacity:1}}
  .boq-grand td{background:var(--boq-head)!important;color:var(--text)!important;font-family:var(--num);font-variant-numeric:tabular-nums;font-weight:700;font-size:12.5px;padding:8px 10px;text-align:right;border-top:3px double var(--text3)!important;border-bottom:none!important}
  .boq-grand .gl{text-align:left;font-size:12.5px}
  /* ── RECORDED ACTUALS (rolled up from the diaries) ──── */
  /* Right-aligned tabular figures, a hairline group divider before the first
     recorded column so budget-vs-actual reads instantly, and the headline
     Recorded cost gets a faint accent tint to set it apart from the hour cols. */
  .boq-tbl th.boq-rec{text-align:right}
  .boq-tbl td.boq-rec{padding:0 10px;text-align:right;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:11.5px;color:var(--text2)}
  .boq-tbl td.boq-rec-first,.boq-tbl th.boq-rec-first{border-left:1px solid var(--boq-grid-strong)}
  .boq-tbl td[data-col="reccost"]{color:var(--text);font-weight:600}
  .boq-grand td.boq-rec-first{border-left:1px solid var(--boq-grid-strong)}
  .boq-mut{color:var(--text3);font-weight:400}
  /* ── Built-in "Unassigned" bucket (diary dayworks with no WBS) ── */
  .boq-una-head{background:#fdf6e7!important;color:#92400e;border-top:1px solid #f1d9a8;border-bottom-color:#f1d9a8}
  .boq-una-badge{font-size:10px;font-weight:600;color:#b45309;border:1px solid #f1d9a8;background:var(--surface);padding:0 6px;border-radius:3px;flex-shrink:0}
  .boq-una-title{font-weight:700;font-size:13px;color:#92400e;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .boq-una-row td{background:#fffdf7}
  .boq-una-row .boq-una-code{font-weight:700;color:#b45309;font-size:12px}
  .boq-una-desc{color:var(--text3);font-size:11px;font-style:italic}
  /* ── COLUMN EDITOR (floating panel, mirrors pgColsMenu chrome) ─ */
  #boqColsPanel{position:fixed;z-index:1600;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius-sm);box-shadow:var(--shadow-lg);width:236px;max-width:92vw;max-height:70vh;display:flex;flex-direction:column;overflow:hidden}
  .boq-cols-hd{display:flex;align-items:center;justify-content:space-between;padding:10px 13px;border-bottom:1px solid var(--border);font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--text2)}
  .boq-cols-reset{background:none;border:none;color:var(--accent);cursor:pointer;font-size:11px;font-weight:600;padding:2px 4px;border-radius:4px}
  .boq-cols-reset:hover{background:var(--accent-light)}
  .boq-cols-body{overflow:auto;padding:5px}
  .boq-cols-row{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:12.5px;color:var(--text);transition:background .12s}
  .boq-cols-row:hover{background:var(--accent-light)}
  .boq-cols-row input{width:16px;height:16px;accent-color:var(--accent);cursor:pointer;flex-shrink:0}
  /* ── CHANGE-WBS on diary sub-items + reassign modal ─── */
  /* The site-inventory BOQ link is the matrix's own picker input now, so it takes
     the same look — but .lis carries the row's width, which must still win. */
  .li input.lis.wbs-pick-inp{cursor:pointer;background:var(--surface)}
  .boq-reassign-btn{background:var(--surface);border:1px solid var(--border-strong);color:var(--accent2);cursor:pointer;font-size:10px;font-weight:700;padding:4px 8px;border-radius:5px;white-space:nowrap;transition:all .12s;line-height:1}
  .boq-reassign-btn.del{color:var(--red);border-color:var(--red);margin-left:4px;padding:2px 7px}
  .boq-reassign-btn:hover{background:var(--accent2);color:#fff;border-color:var(--accent2)}
  .boq-reassign-btn.del:hover{background:var(--red);color:#fff;border-color:var(--red)}
  #boqWbsList{max-height:min(48vh,360px);overflow:auto;display:flex;flex-direction:column;gap:3px}
  .boq-wbs-opt{display:flex;align-items:baseline;gap:10px;padding:9px 11px;border:1px solid var(--border);border-radius:7px;background:var(--surface);cursor:pointer;text-align:left;width:100%;transition:all .12s}
  .boq-wbs-opt:hover{background:var(--accent-light);border-color:var(--accent)}
  .boq-wbs-opt-code{font-family:var(--num);font-variant-numeric:tabular-nums;font-weight:800;font-size:12px;color:var(--accent);flex-shrink:0;min-width:56px}
  .boq-wbs-opt-desc{font-size:12.5px;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .boq-wbs-opt.boq-wbs-cur{opacity:.5;cursor:default;background:var(--surface2)}
  .boq-wbs-opt.boq-wbs-cur:hover{background:var(--surface2);border-color:var(--border)}
  .boq-wbs-opt-cur{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);flex-shrink:0;align-self:center}
  /* ── SEARCHABLE WBS PICKER (matrix) ───────────────── */
  .wbs-pick-inp{width:100%;border:none;outline:none;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:11px;color:var(--accent);padding:8px 4px;background:transparent;cursor:pointer;text-overflow:ellipsis;text-align:left}
  .wbs-pick-inp::placeholder{color:var(--text3)}
  .wbs-pick-inp:hover{background:var(--accent-light)}
  #wbsPickerPanel{position:fixed;z-index:1600;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius-sm);box-shadow:var(--shadow-lg);width:360px;max-width:92vw;max-height:340px;display:none;flex-direction:column;overflow:hidden}
  #wbsPickerPanel.open{display:flex}
  .wbs-pick-search{padding:9px;border-bottom:1px solid var(--border);position:relative;flex-shrink:0}
  .wbs-pick-search input{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:8px 10px 8px 32px;font-size:12px;font-family:var(--font);color:var(--text);outline:none}
  .wbs-pick-search input:focus{border-color:var(--accent);box-shadow:var(--ring)}
  .wbs-pick-search .ic{position:absolute;left:19px;top:50%;transform:translateY(-50%);color:var(--text3)}
  .wbs-pick-list{overflow-y:auto;padding:5px;overscroll-behavior:contain}
  .wbs-pick-sec{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text3);padding:9px 10px 3px}
  .wbs-pick-opt{display:flex;align-items:baseline;gap:9px;padding:7px 10px;border-radius:6px;cursor:pointer;font-size:12px}
  .wbs-pick-opt:hover,.wbs-pick-opt.hl{background:var(--accent-light)}
  .wbs-pick-opt.sel{background:var(--accent-light);outline:1px solid var(--accent);outline-offset:-1px}
  .wbs-pick-code{font-family:var(--num);font-variant-numeric:tabular-nums;font-weight:700;color:var(--accent);flex-shrink:0;min-width:48px}
  .wbs-pick-desc{color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .wbs-pick-none{padding:7px 10px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--text3);font-style:italic}
  .wbs-pick-none:hover,.wbs-pick-none.hl{background:var(--surface2)}
  .wbs-pick-empty{padding:20px;text-align:center;color:var(--text3);font-size:12px}

  /* ADMIN */
  .admin-section{margin-bottom:24px}
  /* ── Administration: a category rail beside the sections ────────────────
     Explicit rather than trusting the UA's [hidden] rule — a later author
     rule setting display on .admin-section would beat it (Known Mistake #7). */
  #admBody [data-adm][hidden]{display:none!important}
  /* ── Module access ── */
  .mod-ro{display:flex;align-items:center;gap:9px;background:var(--accent-light);border:1px solid var(--accent);border-radius:9px;padding:9px 13px;margin:0 0 14px;font-size:12.5px;color:var(--text);line-height:1.45}
  .mod-ro .ic{width:17px;height:17px;flex-shrink:0;color:var(--accent)}
  .mod-ro span{flex:1;min-width:0;overflow-wrap:anywhere}
  .modp-all{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:0 0 12px}
  .modp-all-l{font-size:11.5px;font-weight:650;color:var(--text3);text-transform:uppercase;letter-spacing:.04em}
  .modp-list{max-height:min(50vh,420px);overflow-y:auto;margin:0 -3px;padding:1px 3px}
  .modp-grp{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);margin:12px 0 5px}
  .modp-grp:first-child{margin-top:0}
  .modp-row{display:flex;align-items:center;gap:10px;padding:6px 2px;border-bottom:1px solid var(--border)}
  .modp-row.off .modp-nm{color:var(--text3);text-decoration:line-through}
  .modp-nm{flex:1;min-width:0;font-size:13px;font-weight:600;color:var(--text);overflow-wrap:anywhere}
  .modp-seg{display:flex;flex-shrink:0;border:1px solid var(--border-strong);border-radius:7px;overflow:hidden}
  .modp-b{background:var(--surface);border:0;border-left:1px solid var(--border-strong);padding:0 10px;min-height:32px;font-family:var(--font);font-size:11.5px;font-weight:650;color:var(--text2);cursor:pointer;white-space:nowrap}
  .modp-b:first-child{border-left:0}
  .modp-b:hover{background:var(--surface2)}
  .modp-b.on{background:var(--accent);color:#fff}
  .modp-sum{font-size:11.5px;color:var(--text3);margin:11px 0 0}
  .modp-cell,.modp-cell-none{font-size:11px;color:var(--text3)}
  .modp-cell b{color:var(--amber,#d97706)}
  /* Where a level came from, shown ONLY on a row that actually overrides the
     role — a caption on every row is noise, and the row that differs is the
     one an admin needs to see. */
  .modp-ovr{display:block;font-size:10.5px;font-weight:500;color:var(--text3);margin-top:2px}
  .modp-ovr button{background:none;border:0;padding:0;font:inherit;color:var(--accent);cursor:pointer;text-decoration:underline}
  .modp-nmlbl{display:block;font-size:11px;font-weight:700;color:var(--text2);text-transform:uppercase;letter-spacing:.04em;margin:0 0 5px}
  .modp-nmin{width:100%;border:1px solid var(--border-strong);border-radius:6px;padding:9px 11px;
    font-family:var(--font);font-size:14px;font-weight:600;color:var(--text);background:var(--surface);margin:0 0 14px}
  .modp-nmin:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(37,99,235,.14)}
  /* ── access roles list (Admin → Users) ──────────────────────────────────
     A role name is free text up to 40 characters and the summary beside it is
     long, so the row wraps rather than pushing its buttons off the edge. */
  .arole-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 2px;border-bottom:1px solid var(--border)}
  .arole-row:last-child{border-bottom:0}
  .arole-nm{flex:1 1 200px;min-width:0;font-size:13px;overflow-wrap:anywhere}
  .arole-sub{display:block;font-size:11px;color:var(--text3);font-weight:400}
  .arole-sub b{color:var(--amber,#d97706)}
  .arole-empty{font-size:12px;color:var(--text3);line-height:1.6;padding:4px 2px}
  .adm-head{display:flex;align-items:center;gap:11px;margin-bottom:18px}
  .adm-head-ic{background:var(--accent2);color:#fff;width:36px;height:36px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
  .adm-head-ic .ic{width:19px;height:19px}
  .adm-head-t{font-size:16px;font-weight:650;color:var(--accent2)}
  .adm-head-s{font-size:12px;color:var(--text3);margin-top:1px}
  .adm-shell{display:flex;align-items:flex-start;gap:22px}
  .adm-nav{flex:0 0 208px;display:flex;flex-direction:column;gap:2px;position:sticky;top:var(--vchrome,56px);max-height:calc(100vh - var(--vchrome,56px) - 20px);overflow-y:auto}
  .adm-it{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:transparent;border:0;border-left:3px solid transparent;border-radius:0 8px 8px 0;padding:9px 12px;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:550;color:var(--text2);min-height:40px}
  .adm-it:hover{background:var(--surface2);color:var(--text)}
  .adm-it.active{background:var(--accent-light);border-left-color:var(--accent);color:var(--accent);font-weight:700}
  .adm-it .ic{width:16px;height:16px;flex-shrink:0}
  .adm-it span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* min-width:0 or the column refuses to shrink below its content and the whole
     page scrolls sideways — the trap this file has hit three times. */
  .adm-body{flex:1;min-width:0}
  /* ── What each role can do ── */
  .adm-roles-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:8px}
  /* table-layout:fixed, not auto. Under auto the browser min-content-sizes each
     column, and inside a horizontal scroller the three narrow role columns win —
     which squeezed the description column to ~55px on a phone and turned every
     sentence into a one-word-per-line ribbon. Fixed + explicit widths cannot do
     that. (The scroller is what makes a 600px minimum safe at 390px.) */
  .adm-roles{width:100%;border-collapse:collapse;font-size:12.5px;min-width:600px;table-layout:fixed}
  .adm-roles col.adm-cwhat{width:40%}
  .adm-roles col.adm-crole{width:20%}
  .adm-roles th,.adm-roles td{padding:8px 12px;border-bottom:1px solid var(--border);text-align:center;vertical-align:middle}
  .adm-roles thead th{background:var(--surface2);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--text2);white-space:nowrap;position:sticky;top:0}
  .adm-roles thead th.mine{color:var(--accent)}
  .adm-roles td.mine,.adm-roles th.mine{background:var(--accent-light)}
  .adm-rsub{display:block;font-size:10px;font-weight:500;text-transform:none;letter-spacing:0;color:var(--text3);margin-top:2px}
  .adm-you{display:inline-block;margin-left:5px;background:var(--accent);color:#fff;font-size:9px;font-weight:800;padding:1px 5px;border-radius:99px;letter-spacing:.03em}
  /* .adm-roles td is 0,1,1 and sets text-align:center — restate at 0,2,1. */
  .adm-roles td.adm-rwhat{text-align:left;color:var(--text);line-height:1.4;overflow-wrap:anywhere}
  .adm-rgrp td{text-align:left;background:var(--surface2);font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);padding:6px 12px}
  .adm-y,.adm-n{width:16px;height:16px;fill:none;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}
  .adm-y{stroke:var(--green,#16a34a)}
  .adm-n{stroke:var(--border-strong);opacity:.75}
  .adm-cq{font-size:11px;color:var(--text2);line-height:1.35;display:block;overflow-wrap:anywhere}
  .admin-section-title{font-size:13px;font-weight:700;color:var(--text);margin-bottom:12px;padding-bottom:8px;border-bottom:2px solid var(--accent-light);display:flex;align-items:center;gap:8px}
  .org-admin-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
  .org-admin-cell{background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:14px;min-width:0}
  .org-admin-lbl{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--text3);margin-bottom:6px}
  .org-brand-ramp{display:flex;gap:0;border:1px solid var(--border);border-radius:6px;overflow:hidden;height:34px}
  .org-brand-ramp .obr-sw{display:block;width:28px;height:100%}
  @media(max-width:600px){.org-brand-ramp .obr-sw{width:34px}.org-brand-ramp{height:44px}#orgBrandInp{width:56px!important;height:44px!important}}
  .org-admin-hint{font-size:11px;color:var(--text3);margin-top:8px;line-height:1.5}
  /* Task reminders. Reuses .org-admin-grid/-cell/-lbl/-hint wholesale, so this
     is only the controls that panel does not already have. Every input is a
     TYPED one — the anti-zoom floor on phone lists types, and an untyped input
     falls through to the generic 13px rule and zooms the page on every tap
     (the trap the task photo caption walked into). */
  .tm-ready{display:flex;gap:8px;align-items:flex-start;font-size:12px;line-height:1.5;border-radius:8px;padding:10px 12px;margin-bottom:14px;border:1px solid}
  .tm-ready.ok{border-color:color-mix(in srgb,var(--green,#16a34a) 40%,transparent);background:color-mix(in srgb,var(--green,#16a34a) 8%,transparent);color:var(--text2)}
  .tm-ready.warn{border-color:color-mix(in srgb,var(--amber,#f59e0b) 55%,transparent);background:color-mix(in srgb,var(--amber,#f59e0b) 10%,transparent);color:var(--text2)}
  .tm-ready .ic{flex-shrink:0;margin-top:1px}
  .tm-ready code{font-family:var(--mono);font-size:11px;background:var(--surface);border:1px solid var(--border);border-radius:4px;padding:1px 4px}
  .tm-sw{display:flex;gap:8px;align-items:center;font-size:13px;font-weight:600;color:var(--text);cursor:pointer;min-height:24px}
  .tm-sw input{accent-color:var(--accent);width:16px;height:16px;flex-shrink:0;cursor:pointer}
  .tm-sw input:disabled{cursor:default}
  .tm-sw input:disabled+span{color:var(--text3)}
  .tm-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}
  .tm-in{border:1px solid var(--border-strong);border-radius:6px;padding:7px 9px;font-family:var(--font);font-size:13px;background:var(--surface);color:var(--text);min-width:0}
  .tm-in:disabled{color:var(--text3);background:var(--surface2)}
  .tm-num{width:70px}
  .tm-unit{font-size:12px;color:var(--text2)}
  .tm-unit.tm-w{min-width:54px}
  /* Integrations (Admin). The dialog rows are <label>s inside .md, so they are
     scoped two classes deep to out-rank `.md label` (Known Mistake #7). */
  .int-hook,.int-key{border:1px solid var(--border);border-radius:8px;padding:12px;margin-bottom:10px;background:var(--surface);min-width:0}
  .int-key{display:flex;gap:10px;align-items:flex-start;justify-content:space-between}
  .int-hook.off,.int-key.off{background:var(--surface2)}
  .int-hook-top{display:flex;gap:10px;align-items:flex-start;justify-content:space-between}
  .int-hook-main{min-width:0;flex:1}
  .int-hook-lbl{font-size:13px;font-weight:700;color:var(--text)}
  .int-url{font-family:var(--mono);font-size:12px;color:var(--text2);overflow-wrap:anywhere;word-break:break-all}
  .int-on{flex-shrink:0}
  .int-evs{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
  .int-ev{font-family:var(--mono);font-size:10.5px;background:var(--accent-light);color:var(--accent);border-radius:4px;padding:2px 6px;white-space:nowrap}
  .int-line{display:flex;flex-wrap:wrap;gap:4px 10px;margin-top:6px;font-size:11.5px}
  .int-st{color:var(--text3);overflow-wrap:anywhere}
  .int-st.ok{color:var(--green,#16a34a);font-weight:600}
  .int-st.bad{color:var(--red,#dc2626);font-weight:600}
  .int-st.off{color:var(--text3);font-weight:700;text-transform:uppercase;font-size:10px;letter-spacing:.04em}
  .int-sec{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px;font-size:11.5px;color:var(--text2)}
  .int-secv,.int-code{font-family:var(--mono);font-size:11px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:1px 5px;overflow-wrap:anywhere;word-break:break-all;min-width:0}
  .int-acts{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
  .md .int-in{width:100%;border:1px solid var(--border-strong);border-radius:6px;padding:8px 10px;font-family:var(--font);font-size:13px;background:var(--surface);color:var(--text);min-width:0;box-sizing:border-box}
  .md .int-evpick{display:flex;flex-direction:column;gap:2px}
  .md .int-evpick .int-evrow{display:flex;gap:10px;align-items:flex-start;text-transform:none;letter-spacing:normal;font-weight:400;margin:0;color:var(--text);font-size:12.5px;padding:6px 4px;cursor:pointer;min-height:36px}
  .md .int-evpick .int-evrow input{accent-color:var(--accent);width:16px;height:16px;margin-top:2px;flex-shrink:0}
  .md .int-evpick .sub{font-family:var(--mono);font-size:10.5px;color:var(--text3)}
  .int-keyv{display:block;font-family:var(--mono);font-size:12px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:9px 10px;overflow-wrap:anywhere;word-break:break-all;user-select:all}
  .int-curl{font-size:11px;color:var(--text2)}
  .int-log{display:flex;flex-direction:column;gap:8px}
  .int-logrow{border:1px solid var(--border);border-radius:6px;padding:8px 10px;min-width:0}
  .int-logtop{display:flex;justify-content:space-between;gap:8px;align-items:center;font-size:11.5px}
  .int-logwhat{font-size:12px;color:var(--text);margin-top:4px;overflow-wrap:anywhere}
  .frm-send-note.warn{color:var(--red,#dc2626)}
  @media(max-width:600px){.int-acts .btn,.int-sec .btn,.int-key .btn,#adminHookSection .admin-section-title .btn,#adminKeySection .admin-section-title .btn{min-height:36px}.md .int-evpick .int-evrow{min-height:44px;align-items:center}}
  .tm-log-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:6px;margin-top:6px}
  .tm-log{font-size:12px}
  .tm-ok{color:var(--green,#16a34a);font-weight:600}
  /* Projects people watch (admin). The dialog rows are <label>s inside .md, so
     they are scoped two classes deep to out-rank `.md label` (Known Mistake #7). */
  /* `.admin-tbl.tm-wl` (0,2,1), not `.tm-wl`: the generic `.admin-tbl td` rule sits
     LATER in this sheet at 0,1,1 and would win a tie (Known Mistake #27's trap). */
  .admin-tbl.tm-wl td{vertical-align:top;color:var(--text2)}
  .admin-tbl.tm-wl td:nth-child(1){color:var(--text);font-weight:600}
  /* On a phone, each person is a card: name over their projects, Choose on the
     right — three table columns at 390px left the list a word wide, and at 768
     the sidebar leaves the table little more. */
  @media(max-width:900px){
    .admin-tbl.tm-wl thead{display:none}
    .admin-tbl.tm-wl,.admin-tbl.tm-wl tbody{display:block}
    .admin-tbl.tm-wl tr{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:10px;row-gap:3px;align-items:center;padding:10px 12px;border-bottom:1px solid var(--border)}
    .admin-tbl.tm-wl tbody tr:last-child{border-bottom:none}
    .admin-tbl.tm-wl td{display:block;padding:0;border:none;min-width:0;overflow-wrap:anywhere;background:transparent!important}
    .admin-tbl.tm-wl td:nth-child(1){grid-column:1;grid-row:1;font-weight:600}
    .admin-tbl.tm-wl td:nth-child(2){grid-column:1;grid-row:2;font-size:12px;color:var(--text2)}
    .admin-tbl.tm-wl td:nth-child(3){grid-column:2;grid-row:1/span 2}
    .admin-tbl.tm-wl td:nth-child(3) .btn{min-height:40px}
  }
  .tm-wl-names{overflow-wrap:anywhere}
  .tm-wl-none{color:var(--text3)}
  .tm-wl-more{font-size:11px;font-weight:600;color:var(--text2);white-space:nowrap}
  .tm-wl-off{display:inline-block;margin-left:6px;font-size:10.5px;font-weight:600;color:var(--amber,#b45309);background:rgba(245,158,11,.12);border-radius:10px;padding:1px 7px}
  .tm-wl-lead{font-size:12.5px;color:var(--text2);line-height:1.5;margin:0 0 10px}
  .tm-wl-warn{font-size:12px;color:#92400e;background:#fffbeb;border:1px solid #fde68a;border-radius:6px;padding:8px 10px;margin:0 0 10px}
  .tm-wl-list{display:flex;flex-direction:column;gap:2px;max-height:50vh;overflow-y:auto;border:1px solid var(--border);border-radius:6px;padding:4px}
  .md .tm-wl-list .tm-wl-row{display:flex;align-items:center;gap:10px;min-height:40px;padding:6px 8px;margin:0;border-radius:4px;cursor:pointer;
    text-transform:none;letter-spacing:normal;font-weight:400;font-size:13px;color:var(--text)}
  .md .tm-wl-list .tm-wl-row:hover{background:var(--accent-light)}
  .md .tm-wl-list .tm-wl-row input{width:18px;height:18px;flex:0 0 auto;accent-color:var(--accent);margin:0}
  .md .tm-wl-list .tm-wl-row .nm{flex:1;min-width:0;overflow-wrap:anywhere}
  .md .tm-wl-list .tm-wl-row .nm i{font-style:normal;font-family:var(--mono);font-size:11px;color:var(--text3)}
  .tm-bad{color:var(--red,#dc2626);font-weight:600}
  /* A select and a date input open a native picker and never zoom, so the rule
     for them is a 44pt TARGET, not the 16px floor. A number input is typed
     into, so it takes the floor. */
  @media(max-width:600px){
    .tm-in{min-height:44px;font-size:16px}
    .tm-num{width:84px}
    .tm-sw{min-height:44px}
    .tm-sw input{width:20px;height:20px}
  }
  .org-leave-row{display:flex;gap:14px;align-items:center;justify-content:space-between;flex-wrap:wrap;margin-top:14px;padding:12px 14px;border:1px dashed var(--border-strong);border-radius:8px;background:var(--surface2)}
  .org-leave-title{font-size:12px;font-weight:700;color:var(--text)}
  .org-leave-btn{flex-shrink:0;border-color:var(--amber);color:var(--amber)}
  .org-leave-btn:hover{background:var(--amber);color:#fff}
  .admin-tbl{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
  .admin-tbl th{background:var(--th-bg);color:var(--th-text);padding:10px 12px;text-align:left;font-size:10px;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;border-bottom:1px solid var(--border)}
  .admin-tbl td{padding:10px 12px;border-bottom:1px solid var(--border);vertical-align:middle}
  .admin-tbl tr:hover td{background:var(--accent-light)}
  .admin-tbl tbody tr:nth-child(even) td{background:var(--surface2)}
  /* Phone: the User-Management table restacks into one card per user (data-label
     captions from the header) so the 6 columns don't force a cramped horizontal
     scroll; every control stays full-width and tappable. */
  @media(max-width:600px){
    .admin-users-wrap{overflow-x:visible!important;border:none!important;border-radius:0!important}
    .admin-users-tbl,.admin-users-tbl tbody,.admin-users-tbl tr,.admin-users-tbl td{display:block;width:100%}
    .admin-users-tbl thead{display:none}
    .admin-users-tbl tr{border:1px solid var(--border);border-radius:10px;margin-bottom:10px;padding:4px 6px;background:var(--surface);box-shadow:var(--shadow-xs)}
    .admin-users-tbl tr:hover td,.admin-users-tbl tbody tr:nth-child(even) td{background:transparent}
    .admin-users-tbl td{border:none;padding:8px 6px;display:flex;align-items:center;gap:10px;border-bottom:1px solid var(--border);min-width:0;overflow-wrap:anywhere;word-break:break-word}
    .admin-users-tbl tr td:last-child{border-bottom:none}
    .admin-users-tbl td::before{content:attr(data-label);flex:0 0 88px;font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text3)}
    .admin-users-tbl .admin-name-inp,.admin-users-tbl .role-sel{flex:1;min-width:0;min-height:44px;font-size:16px}
    .admin-users-tbl td .btn{min-height:40px}
  }
  .status-badge{font-size:10px;font-weight:600;padding:2px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:0.04em}
  .sb-active{background:var(--green-light);color:var(--green)}
  .sb-pending{background:var(--amber-light);color:var(--amber)}
  .sb-blocked{background:var(--red-light);color:var(--red)}
  .role-sel{font-family:var(--font);font-size:12px;padding:3px 6px;border:1px solid var(--border);border-radius:3px;background:var(--surface);color:var(--text);cursor:pointer}
  .admin-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
  .admin-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-sm)}
  .admin-card-header{padding:11px 15px;border-bottom:1px solid var(--border);background:var(--surface2);display:flex;align-items:center;justify-content:space-between}
  .admin-card-title{font-size:11px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:var(--text2)}
  .admin-card-body{padding:12px 14px}
  .job-check-list{display:grid;gap:6px}
  .job-check-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:4px;font-size:12px;cursor:pointer;transition:background 0.1s}
  .job-check-item:hover{background:var(--accent-light)}
  .job-check-item input[type=checkbox]{accent-color:var(--accent);width:14px;height:14px;cursor:pointer}

  /* MODAL */
  /* staged-photo tray — shoot several, caption once, then commit */
  .ptray-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:8px;margin:10px 0 4px;max-height:42vh;overflow-y:auto}
  .ptray-cell{position:relative;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:var(--surface2)}
  .ptray-cell img{width:100%;aspect-ratio:1/1;object-fit:cover;display:block}
  .ptray-cell.has-own{border-color:var(--accent2);box-shadow:0 0 0 2px var(--accent2-light)}
  .ptray-x{position:absolute;top:3px;right:3px;width:26px;height:26px;border:none;border-radius:50%;background:rgba(15,23,42,.72);color:#fff;font-size:15px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
  .ptray-own{position:absolute;left:0;right:0;bottom:0;background:rgba(15,23,42,.72);color:#fff;font-size:9.5px;padding:3px 5px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* the caption row: a growing textarea beside a dictation mic */
  .ptray-caprow{display:flex;gap:8px;align-items:flex-end}
  .ptray-cap{flex:1;min-width:0;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:7px;padding:9px 11px;font-family:var(--font);font-size:13px;line-height:1.45;background:var(--surface);color:var(--text);resize:none;overflow-y:auto;min-height:40px;max-height:160px}
  .ptray-mic{flex:0 0 auto;width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border-strong);border-radius:7px;background:var(--surface);color:var(--text2);cursor:pointer;transition:background .15s,color .15s,border-color .15s}
  .ptray-mic .ic{width:18px;height:18px}
  .ptray-mic:hover{background:var(--surface2);color:var(--text)}
  .ptray-mic.recording{border-color:#e53;color:#e53;animation:mic-pulse 1s ease-in-out infinite}
  .ptray-hint{font-size:11px;color:var(--text3);margin-top:5px;line-height:1.5}
  /* Low-quality advisory (compressed copies, e.g. WhatsApp saves) — top-LEFT so
     it never collides with the remove button (top-right) or a per-photo
     caption strip (bottom). Informational only; pointer-events:none keeps the
     tap-to-caption target underneath fully usable. */
  .ptray-lowres{position:absolute;top:3px;left:3px;max-width:calc(100% - 38px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:#fef3c7;color:#92400e;border:1px solid #fcd34d;font-size:8px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;border-radius:6px;padding:1px 5px;pointer-events:none}
  .ptray-warn{display:flex;gap:7px;align-items:flex-start;background:#fef3c7;color:#92400e;border:1px solid #fcd34d;border-radius:8px;padding:8px 10px;font-size:11px;line-height:1.55;margin-top:10px}
  .ptray-warn .ic{width:13px;height:13px;flex-shrink:0;margin-top:2px}
  .ptray-acts{display:flex;gap:8px;align-items:center;margin-top:14px;flex-wrap:wrap}
  .ptray-acts .btn{min-height:40px}
  .ptray-acts .grow{margin-left:auto}
  @media(max-width:600px){.ptray-acts .btn{flex:1;min-height:44px}.ptray-acts .grow{margin-left:0;width:100%}
    .ptray-mic{width:44px;height:44px}}
  /* diary note timeline — many timestamped notes per day, alongside General Notes */
  .dnote-wrap{border-top:1px solid var(--border);margin-top:10px;padding-top:10px}
  .dnote-bar{display:flex;align-items:center;gap:9px;margin-bottom:8px}
  .dnote-title{font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text3)}
  .dnote-count{font-size:11px;color:var(--text3);font-variant-numeric:tabular-nums;margin-right:auto}
  .dnote{border:1px solid var(--border);border-left:3px solid var(--border-strong);border-radius:8px;padding:9px 11px;margin-bottom:7px;background:var(--surface)}
  .dnote.qr{border-left-color:#f97316;background:linear-gradient(90deg,rgba(249,115,22,.05),transparent 60%)}
  .dnote-head{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:4px}
  .dnote-who{font-size:11.5px;font-weight:700;color:var(--text)}
  .dnote-when{font-size:10.5px;color:var(--text3);font-variant-numeric:tabular-nums}
  .dnote-src{font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:1px 6px;border-radius:8px;background:#ffedd5;color:#c2410c;border:1px solid #fed7aa}
  .dnote-tag{font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:1px 6px;border-radius:8px;background:var(--surface2);color:var(--text2);border:1px solid var(--border)}
  .dnote-tag.delay{background:#fee2e2;color:#b91c1c;border-color:#fecaca}
  .dnote-tag.safety{background:#fef3c7;color:#92400e;border-color:#fde68a}
  .dnote-tag.progress{background:#dcfce7;color:#166534;border-color:#bbf7d0}
  .dnote-edited{font-size:9px;font-weight:700;font-style:italic;color:var(--text3);cursor:default}
  .dnote-acts{margin-left:auto;display:flex;gap:4px}
  .dnote-body{font-size:12.5px;line-height:1.55;color:var(--text);white-space:pre-wrap;overflow-wrap:anywhere}
  .dnote-orig{margin-top:5px;padding-top:5px;border-top:1px dashed var(--border);font-size:11.5px;color:var(--text2);white-space:pre-wrap;overflow-wrap:anywhere}
  .dnote-orig b{font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);display:block;margin-bottom:2px}
  .dnote-empty{font-size:11.5px;color:var(--text3);font-style:italic;padding:2px 0}
  /* .md styles inputs/selects but not textareas (this is the only modal with one) */
  #dnoteText{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:9px 11px;font-family:var(--font);font-size:13px;line-height:1.55;color:var(--text);background:var(--surface);resize:vertical;transition:border-color .15s,box-shadow .15s}
  #dnoteText:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .dnote-microw{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:-4px}
  .dnote-michint{font-size:11px;color:var(--text3);flex:1;min-width:140px}
  #dnoteMic.recording{background:var(--red);border-color:var(--red);color:#fff;animation:dnpulse 1.1s ease-in-out infinite}
  @keyframes dnpulse{0%,100%{opacity:1}50%{opacity:.55}}
  .dnote-tr{display:none}
  .dnote-tr.on{display:block;border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:8px;padding:9px 11px;background:var(--surface2)}
  .dnote-tr b{display:block;font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);margin-bottom:3px}
  .dnote-tr span{font-size:12.5px;line-height:1.5;color:var(--text);overflow-wrap:anywhere}
  /* HIG: 44pt targets on phone (docs/apple-hig-mobile.md) */
  @media(max-width:600px){.dnote-bar .btn,.dnote-acts .btn,.dnote-microw .btn{min-height:44px;min-width:44px}.dnote-bar{flex-wrap:wrap}}
  /* Contributor scoreboard */
  .contrib-row{display:flex;align-items:center;gap:12px;padding:10px 0;border-top:1px solid var(--border)}
  .contrib-row:first-child{border-top:none}
  .contrib-rank{width:30px;flex-shrink:0;text-align:center;font-size:15px;font-weight:800;color:var(--text3);font-variant-numeric:tabular-nums}
  .contrib-row.top .contrib-rank{font-size:19px}
  .contrib-who{flex:1;min-width:0}
  .contrib-name{font-size:13.5px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:6px;flex-wrap:wrap;overflow-wrap:anywhere}
  .contrib-sub{font-size:11px;color:var(--text3);margin-top:1px}
  .contrib-bar{height:5px;border-radius:3px;background:var(--surface2);margin-top:5px;overflow:hidden}
  .contrib-bar span{display:block;height:100%;border-radius:3px;background:var(--accent)}
  .contrib-row.top .contrib-bar span{background:var(--accent2)}
  .contrib-score{flex-shrink:0;min-width:52px;text-align:right;font-size:17px;font-weight:800;color:var(--accent2);font-variant-numeric:tabular-nums}
  .contrib-key{margin-top:12px;padding-top:9px;border-top:1px dashed var(--border);font-size:11px;color:var(--text3);line-height:1.6}
  @media(max-width:600px){
    .contrib-rank{width:24px}
    .contrib-score{min-width:44px;font-size:15px}
    #contribRange{flex-wrap:wrap}
    #contribRange .contrib-rng-btn{min-height:38px}
  }
  /* Site QR admin panel */
  .qr-intro{font-size:12.5px;color:var(--text2);line-height:1.6;margin-bottom:14px;max-width:760px}
  .qr-intro .dnote-src{vertical-align:1px}
  .qr-card{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap;border:1px solid var(--border);border-radius:10px;padding:14px;margin-bottom:12px;background:var(--surface)}
  .qr-code{background:#fff;border:1px solid var(--border);border-radius:8px;padding:8px;line-height:0;flex-shrink:0}
  .qr-svg{display:block;max-width:100%;height:auto}
  .qr-meta{flex:1;min-width:0}
  .qr-label{font-size:14px;font-weight:800;color:var(--text);margin-bottom:3px}
  .qr-sub{font-size:11px;color:var(--text3);margin-bottom:9px}
  .qr-url{font-family:var(--mono);font-size:10.5px;color:var(--text2);background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:7px 9px;margin-bottom:10px;overflow-wrap:anywhere}
  .qr-acts{display:flex;gap:7px;flex-wrap:wrap}
  .qr-newrow{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:6px}
  .qr-newrow input{flex:1;min-width:180px;border:1px solid var(--border-strong);border-radius:6px;padding:8px 10px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface)}
  .qr-empty{font-size:12px;color:var(--text3);font-style:italic;padding:4px 0 10px}
  .qr-dead-head{font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);margin:16px 0 6px}
  .qr-dead{font-size:11.5px;color:var(--text3);padding:4px 0;border-top:1px solid var(--border)}
  .qr-dead span{font-size:10.5px;opacity:.8}
  @media(max-width:600px){
    .qr-card{gap:12px}
    .qr-code{margin:0 auto}
    .qr-acts .btn,.qr-newrow .btn{min-height:44px}
    .qr-newrow input{min-height:44px;font-size:16px}
  }
  /* ── Every full-screen overlay is sized to the DYNAMIC viewport ───────────
     `position:fixed;inset:0` sizes a box to the LAYOUT viewport, and on iOS
     that is the TOOLBAR-HIDDEN one — so the container is taller than the
     screen and whatever it aligns to its bottom (a bottom sheet's pinned
     action row) or centres in it lands below the visible area. Reported
     2026-09-05: the project-export dialog's Cancel/Export row came up under
     the bottom tab bar. This is Known Mistake #27's vh-vs-dvh trap one level
     out — that fix capped the DIALOG in dvh but left the CONTAINER measuring
     the large viewport. `top:0` plus a height leaves `bottom` over-constrained,
     so the height wins; on any engine where dvh==vh this changes nothing.
     NOT reproducible in this sandbox (Chromium's vh is already the visible
     height) — same standing caveat as the other WebKit-only fixes. */
  .mo,#planModal,#sigOverlay,.sk-back,#frmPvO,.mobsheet,.lightbox,
  #boqPasteModal,#boqImportInfoModal{height:100vh;height:100dvh}
  .mo{position:fixed;inset:0;background:rgba(15,23,42,0.5);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);z-index:200;display:none;align-items:center;justify-content:center}
  .mo.open{display:flex}
  .md{background:var(--surface);border-radius:var(--radius-lg);padding:24px;width:480px;max-width:92vw;box-shadow:var(--shadow-lg);max-height:90vh;overflow-y:auto}
  .md h3{font-size:16px;font-weight:700;margin-bottom:16px;color:var(--text)}
  .md label{display:block;font-size:12px;color:var(--text2);margin-bottom:4px;font-weight:600}
  .md input,.md select{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:9px 11px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface);margin-bottom:12px;transition:border-color 0.15s,box-shadow 0.15s}
  .md input:focus,.md select:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .md input[type=radio],.md input[type=checkbox]{width:auto;padding:0;margin:0 0 0 0;accent-color:var(--accent);flex:0 0 auto}
  .macts{display:flex;justify-content:flex-end;gap:8px;margin-top:6px}

  @media(max-width:700px){.admin-grid{grid-template-columns:1fr}.res-groups{grid-template-columns:1fr}}
  /* .sgrid stacks far EARLIER than the old 700px, and the number is measured, not
     guessed: the sidebar takes ~220px, so at a 768px viewport a two-up .sgrid gave
     each panel 226px — narrower than the same panel gets on a phone (344px), and far
     too narrow for the Site Inventory row. It only has two half-width children, so
     auto-fit is wrong here too (it opens an empty third track past ~1400px).
     Below this it is one column, where the panel is the full content width. */
  @media(max-width:1240px){.sgrid{grid-template-columns:1fr}}

  /* WEEKLY REPORT */
  .week-report{padding:0}
  /* wraps at every width, not just phone: the team filter is a fourth control on
     this row and a tablet cannot fit range + filter + label + actions on one line */
  .week-nav{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;margin-bottom:16px;gap:12px}
  .week-title{text-align:center;flex:1}
  .week-label{font-size:15px;font-weight:600;color:var(--accent2)}
  .week-sub{font-size:12px;color:var(--text3);margin-top:3px;font-family:var(--mono)}
  .week-kpi-strip{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:16px}
  .wk{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;border-top:3px solid var(--accent);box-shadow:var(--shadow-sm)}
  .wk-l{font-size:10px;color:var(--text3);font-weight:600;letter-spacing:0.05em;text-transform:uppercase;margin-bottom:4px}
  .wk-v{font-family:var(--num);font-variant-numeric:tabular-nums;font-size:21px;font-weight:700;color:var(--accent)}
  .wk-sub{font-size:10.5px;color:var(--text3);font-weight:600;font-variant-numeric:tabular-nums;margin-top:3px}
  .ev-pos{color:var(--green)!important}.ev-neg{color:var(--red)!important}
  /* dashboard date-range control (Week / Month / All / Custom) */
  /* Team filter beside the range control. Sized to match .dash-rng-btn. */
  .dash-teamsel{border:1px solid var(--border);border-radius:9px;background:var(--surface);padding:6px 9px;font-family:var(--font);font-size:12px;font-weight:600;color:var(--text);max-width:190px}
  .dash-range,.contrib-range{display:inline-flex;background:var(--surface2);border:1px solid var(--border);border-radius:9px;padding:3px;gap:2px;flex-shrink:0}
  .dash-rng-btn,.contrib-rng-btn{border:none;background:transparent;color:var(--text2);font-size:12px;font-weight:600;padding:5px 13px;border-radius:6px;cursor:pointer;font-family:var(--font);transition:background .12s,color .12s}
  .dash-rng-btn:hover,.contrib-rng-btn:hover{color:var(--text)}
  .dash-rng-btn.active,.contrib-rng-btn.active{background:var(--accent2);color:#fff;box-shadow:var(--shadow-xs)}
  .dash-nav-side{display:flex;gap:6px;flex-shrink:0}
  .dash-custom{display:flex;align-items:center;flex-wrap:wrap;gap:10px 16px;margin:-6px 0 16px;padding:10px 14px;background:var(--surface2);border:1px solid var(--border);border-radius:8px}
  .dash-custom label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--text3);display:flex;align-items:center;gap:7px}
  .dash-custom input[type=date]{font-size:12px;padding:5px 8px;border:1px solid var(--border-strong);border-radius:6px;background:var(--surface);color:var(--text);font-family:var(--font)}
  .dash-custom-note{font-size:11px;color:var(--text3);font-style:italic}
  @media(max-width:600px){.week-nav{flex-wrap:wrap;gap:10px}.dash-range{width:100%;justify-content:space-between}.dash-rng-btn{flex:1;padding:7px 4px}.week-title{flex:1 1 auto;min-width:0;text-align:left}.week-label,.week-sub{overflow-wrap:anywhere}.dash-nav-side{flex-shrink:0}.dash-custom{margin-top:0}}
  .week-charts{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px}
  .dash-inv-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px}
  .week-wide-chart{margin-bottom:16px}
  .chart-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;box-shadow:var(--shadow-sm)}
  /* The wide quantities chart sizes by HEIGHT, not by its width (2026-09-18).
     Its canvas is the full content width, so an intrinsic aspect ratio made it
     717px tall at 1440 - taller than the laptop viewport it sat in. The box
     fixes the height and Chart.js (maintainAspectRatio:false) fills it, so the
     chart is the same shape as the two-up charts beside it at every width.
     The canvas is absolutely placed so Chart.js's own inline sizing can never
     feed back into the box it is measuring against. */
  .wbs-qty-box{position:relative;height:340px}
  .wbs-qty-box>canvas{position:absolute;left:0;top:0;width:100%!important;height:100%!important}
  .chart-title{font-size:11px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;color:var(--text2);margin-bottom:10px}
  .wbs-scrl-track{position:relative;height:8px;background:#e2e8f0;border-radius:4px;margin:10px 2px 3px;cursor:pointer;user-select:none}
  .wbs-scrl-thumb{position:absolute;top:0;height:100%;min-width:24px;background:#94a3b8;border-radius:4px;cursor:grab;transition:background 0.15s;touch-action:none}
  .wbs-scrl-thumb:hover,.wbs-scrl-thumb.dragging{background:var(--accent2);cursor:grabbing}
  /* ── PHOTOS & NOTES ──────────────────────────────────────────── */
  #genNotes{resize:vertical;overflow-y:hidden;min-height:76px;transition:height 0.1s}
  .mic-btn{background:none;border:1px solid var(--border);border-radius:50%;width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;color:var(--text2);transition:background 0.15s,color 0.15s;flex-shrink:0}
  .mic-btn:hover{background:var(--surface2)}
  .mic-btn.recording{border-color:#e53;color:#e53;animation:mic-pulse 1s ease-in-out infinite}
  @keyframes mic-pulse{0%,100%{box-shadow:0 0 0 0 rgba(238,85,51,0.4)}50%{box-shadow:0 0 0 6px rgba(238,85,51,0)}}
  .dict-lang-sel{font-size:11px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--text);padding:2px 5px;cursor:pointer;height:26px}
  .photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px;margin-top:8px}
  .photo-thumb-wrap{display:flex;flex-direction:column}
  .photo-thumb{position:relative;aspect-ratio:1;border-radius:7px;overflow:hidden;background:var(--surface2);cursor:pointer;border:1px solid var(--border)}
  .photo-thumb img{width:100%;height:100%;object-fit:cover;transition:opacity 0.2s}
  .photo-thumb:hover img{opacity:0.82}
  .pt-del{position:absolute;top:5px;right:5px;background:rgba(0,0,0,0.6);color:#fff;border:none;border-radius:50%;width:24px;height:24px;font-size:13px;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1;opacity:0;transition:opacity 0.15s;padding:0}
  .photo-thumb:hover .pt-del{opacity:1}
  .photo-cap-inp{width:100%;font-size:13px;background:transparent;border:none;border-bottom:1px solid var(--border);color:var(--text);padding:3px 0;outline:none;margin-top:5px;resize:none;overflow:hidden;line-height:1.4;min-height:22px;box-sizing:border-box;font-family:inherit}
  .photo-cap-inp:focus{border-bottom-color:var(--accent)}
  /* The phone stand-in for that textarea: the SAME underlined caption line, on
     the type scale, wrapping to its own text (a caption is a sentence, not a
     label) and never a focusable box iOS could zoom into. */
  .photo-cap-tap{width:100%;box-sizing:border-box;border-radius:0;
    border-bottom:1px solid var(--border);padding:3px 0;margin-top:5px;min-height:22px;
    white-space:normal;overflow:visible;text-overflow:clip;align-items:flex-start;
    line-height:1.4;overflow-wrap:anywhere}
  .photo-cap-tap:hover{background:transparent}
  .proj-photos-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px;padding:4px 0}
  @media(max-width:1000px){.proj-photos-grid{grid-template-columns:repeat(4,1fr)}}
  @media(max-width:600px){.proj-photos-grid{grid-template-columns:repeat(3,1fr)}}
  .ppc{display:flex;flex-direction:column;border-radius:6px;overflow:hidden;background:var(--surface2);cursor:pointer;border:1px solid var(--border)}
  .ppc-img{position:relative;aspect-ratio:1;overflow:hidden;flex-shrink:0}
  .ppc-img img{width:100%;height:100%;object-fit:cover;transition:opacity 0.2s}
  .ppc:hover .ppc-img img{opacity:0.82}
  .ppc-date{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(transparent,rgba(0,0,0,0.72));color:#fff;font-size:9px;padding:14px 5px 4px;text-align:center;letter-spacing:0.02em;cursor:pointer;transition:background 0.15s}
  .ppc-date:hover{background:linear-gradient(transparent,rgba(37,99,235,0.85));text-decoration:underline}
  /* Turn buttons on a Photos tile: a small frosted pill top-right, shown on
     hover or keyboard focus. A touch screen has no hover, so there they are
     always shown, a little quieter, at a 32px target. */
  .ppc-rot{position:absolute;top:6px;right:6px;z-index:2;display:flex;gap:2px;padding:2px;border-radius:999px;
    background:rgba(17,24,39,.55);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
    box-shadow:0 1px 3px rgba(0,0,0,.25);opacity:0;transform:translateY(-3px);
    transition:opacity .15s ease,transform .15s ease;pointer-events:none}
  .ppc:hover .ppc-rot,.ppc-rot:focus-within{opacity:1;transform:none;pointer-events:auto}
  .ppc-rot-b{width:28px;height:28px;border:0;border-radius:999px;background:transparent;color:#fff;
    display:inline-flex;align-items:center;justify-content:center;padding:0;cursor:pointer;transition:background .12s}
  .ppc-rot-b:hover{background:rgba(255,255,255,.2)}
  .ppc-rot-b:active{background:rgba(255,255,255,.32)}
  .ppc-rot-b:focus-visible{outline:2px solid #fff;outline-offset:-2px}
  @media (hover:none){
    .ppc-rot{opacity:.92;transform:none;pointer-events:auto;top:4px;right:4px}
    .ppc-rot-b{width:32px;height:32px}
  }
  .ppc-cap{padding:5px 6px;font-size:11px;color:var(--text2);line-height:1.3;word-break:break-word}
  /* Time / place overlay — both are always RECORDED on the photo; these only
     show them, and only while the matching toolbar toggle is on (data vs.
     display, kept separate). Bottom-left, stacked, clear of the .ppc-date bar
     that already owns the foot of a Photos-tab tile. `pointer-events:none` so
     the chips never swallow the click that opens the lightbox.
     The `.ts-on`/`.geo-on` selectors are SCOPED to the two containers that own
     them — a bare class teardown reaches into whatever else borrows the name
     (Known Mistake #18). */
  .ph-stamp{position:absolute;left:5px;display:flex;flex-direction:column;align-items:flex-start;gap:3px;
    pointer-events:none;max-width:calc(100% - 10px);z-index:1}
  .ppc-img .ph-stamp{bottom:26px}      /* above the date strip */
  .photo-thumb .ph-stamp{bottom:5px}   /* the diary strip has no date strip */
  /* The chips WRAP rather than truncate. A tile at phone width is ~110px and a
     full coordinate pair needs ~131px at this size, so `nowrap` clipped it to
     `-33.868…` — and a truncated coordinate is worse than no coordinate at all.
     Default word breaking splits at the space or after the comma, never inside
     a number. Measured, not eyeballed: the stress scan compares scrollWidth
     against clientWidth, because a clipped chip overflows nothing and so fails
     completely silently. */
  .ph-stamp>span{background:rgba(15,23,42,.72);color:#fff;font-size:9px;font-weight:700;
    padding:2px 6px;border-radius:5px;letter-spacing:0.02em;font-variant-numeric:tabular-nums;
    line-height:1.35;max-width:100%;white-space:normal;display:none}
  .proj-photos-grid.ts-on .ppc-ts,.photo-grid.ts-on .ppc-ts{display:block}
  .proj-photos-grid.geo-on .ppc-geo,.photo-grid.geo-on .ppc-geo{display:block}
  .lightbox{position:fixed;inset:0;background:rgba(0,0,0,0.93);z-index:9999;display:none;align-items:center;justify-content:center;flex-direction:column}
  .lightbox.open{display:flex}
  /* Sized BY the image, not to the viewport — the stamp is positioned against
     this box, so it has to be the photo's own box. An `object-fit:contain` image
     inside a larger flex wrap leaves letterbox space the stamp would float in. */
  /* 2026-09-29: the box is now sized by JS (lbLayout) from the photo's natural
     size AND its rotation, so a photo turned a quarter is framed portrait; the
     picture inside is positioned and transformed (rotate + zoom + pan), and the
     frame clips it at 1x (zoomed in, see below, it may fill the screen).
     touch-action:none is what hands a pinch to the viewer instead of the page. */
  .lb-img-wrap{position:relative;overflow:hidden;border-radius:4px;box-shadow:0 8px 40px rgba(0,0,0,0.6);touch-action:none;cursor:zoom-in}
  .lightbox.zoomed .lb-img-wrap{cursor:grab}
  .lightbox.zoomed .lb-img-wrap.panning{cursor:grabbing}
  .lb-img-wrap img{position:absolute;left:0;top:0;max-width:none;max-height:none;transform-origin:50% 50%;user-select:none;-webkit-user-drag:none;will-change:transform}
  .lightbox{touch-action:none;overflow:hidden}
  /* 2026-10-12: zoomed in, the frame stops clipping and the picture grows to the
     whole screen, like a phone's own photo viewer (lbClamp keeps it on screen).
     The caption, buttons, arrows and counter step aside until it is zoomed back
     out; the close button and the zoom chip (the way back) stay above it. */
  .lightbox.zoomed .lb-img-wrap{overflow:visible;box-shadow:none;border-radius:0}
  .lightbox.zoomed .lb-foot,.lightbox.zoomed .lb-arrow,.lightbox.zoomed .lb-counter{visibility:hidden}
  .lightbox.zoomed .lb-foot .lb-zoomchip{visibility:visible;background:rgba(0,0,0,.55);border-color:rgba(255,255,255,.45)}
  .lb-close{z-index:3}
  .lightbox.zoomed .lb-close{opacity:.9;text-shadow:0 1px 6px rgba(0,0,0,.8)}
  .lb-tools{display:flex;align-items:stretch;gap:8px;flex:0 0 auto}
  .lb-tools .lb-zoomchip{align-self:center}
  .lb-rot{color:#fff;border-color:rgba(255,255,255,.35);background:rgba(255,255,255,.08);padding:0;width:38px;min-width:38px;justify-content:center;display:inline-flex;align-items:center}
  .lb-rot:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.6)}
  .lb-zoomchip{color:#fff;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.3);border-radius:14px;font:inherit;font-size:11.5px;font-weight:700;padding:4px 10px;cursor:pointer;font-variant-numeric:tabular-nums}
  .lb-zoomchip[hidden]{display:none}
  /* zoomed in, the stamp would sit over the very detail being inspected */
  .lightbox.zoomed .lb-ovl{opacity:0;transition:opacity .15s}
  /* The foot mirrors the layout the owner sent: what the photo IS on the left,
     the capture stamp on the right, and one bar under both carrying the survey
     figures. Sized off the image so it never fights the arrows. */
  /* Above the arrows: with a small photo they would otherwise be centred over
     the stamp, and a chevron through a coordinate is unreadable. */
  .lb-foot{width:min(90vw,900px);margin-top:10px;display:flex;flex-direction:column;gap:7px;position:relative;z-index:2}
  .lb-frow{display:flex;align-items:flex-end;justify-content:space-between;gap:14px;flex-wrap:wrap}
  .lb-info{color:rgba(255,255,255,0.82);font-size:12px;flex:1 1 200px;min-width:0;text-align:left;padding:0}
  /* Saving is a real action on the photo in front of you, so it sits with the
     caption rather than hiding in a menu; light-on-dark, because the lightbox
     ground is black whatever theme the page is in. */
  .lb-save{flex:0 0 auto;color:#fff;border-color:rgba(255,255,255,.35);background:rgba(255,255,255,.08)}
  .lb-save:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.6)}
  .lb-save[disabled]{opacity:.5;cursor:default}
  /* The capture stamp, burned into the bottom-right corner OF the photo the way
     a camera app does it — that placement is the whole reason it was asked for.
     Hidden until there is a time to show: an empty stamp is worse than none.
     A photo can be any brightness, so the text carries its own shadow and sits
     on a soft gradient rather than trusting the picture underneath to be dark. */
  /* Both overlays live in ONE flex row pinned to the foot of the picture, rather
     than each being positioned into its own corner. Measured, not chosen: at a
     390px viewport the two corner boxes overlapped and the coordinate was painted
     over by the project name — and a stamp collision like that is silent, because
     nothing overflows anything. A flex row cannot overlap by construction, and at
     phone width it stacks instead (column-reverse: the stamp above, the figures
     across the full width below). */
  .lb-ovl{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:flex-end;
    justify-content:space-between;gap:8px;pointer-events:none;border-radius:0 0 4px 4px;
    background:linear-gradient(to top,rgba(0,0,0,.6),rgba(0,0,0,.34) 55%,rgba(0,0,0,0))}
  .lb-mark{display:none;flex:0 1 auto;min-width:0;max-width:72%;padding:16px 13px 10px 26px;
    text-align:right;line-height:1.35;color:#fff;font-size:11.5px;font-variant-numeric:tabular-nums;
    text-shadow:0 1px 3px rgba(0,0,0,.9),0 0 9px rgba(0,0,0,.55);
    border-radius:0 0 4px 0;pointer-events:none}
  .lb-mark.on{display:block}
  .lb-mark span{display:block}
  .lb-mark .lb-mk-p{font-weight:800;font-size:12.5px;letter-spacing:.01em}
  /* The stats bar — every figure the photo carries, on the picture itself, in
     the corner opposite the capture stamp. It reads ON the photo for the same
     reason the stamp does: it is a fact about the picture, not a caption beside
     it, and it has to survive being saved and sent on.
     WRAPS rather than truncating: a coordinate cut in half is worse than none,
     and it fails completely silently (Known Mistake, the ppc-geo measurement). */
  .lb-stats{display:none;flex:0 1 auto;min-width:0;
    flex-wrap:wrap;align-items:baseline;gap:5px 13px;padding:16px 26px 11px 13px;
    color:#fff;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;
    text-shadow:0 1px 3px rgba(0,0,0,.9),0 0 9px rgba(0,0,0,.55);
    border-radius:0 0 0 4px;pointer-events:none;overflow-wrap:anywhere}
  .lb-stats.on{display:flex}
  .lb-stat{display:inline-flex;align-items:baseline;gap:6px;min-width:0}
  .lb-stat i{font-style:normal;font-size:9px;font-weight:800;letter-spacing:.06em;color:rgba(255,255,255,.55);flex:0 0 auto}
  @media(max-width:600px){
    .lb-foot{width:94vw}
    .lb-frow{gap:8px}
    /* Not enough width for two corners — stack them, the stamp over the figures,
       each running the full width of the picture. */
    .lb-ovl{flex-direction:column-reverse;align-items:stretch;gap:0}
    .lb-mark{padding:12px 10px 2px 22px;font-size:11px;max-width:100%}
    .lb-stats{font-size:10.5px;gap:3px 9px;padding:2px 11px 9px 10px;max-width:100%}
    /* The chevrons are a mouse affordance; on a touch screen the swipe is the
       gesture, and two big chevrons over a phone-width photo cover the corners
       the stamp and the stats now live in. */
    .lb-arrow{font-size:34px;opacity:.28;padding:0 4px}
  }
  .lb-close{position:absolute;top:14px;right:18px;color:#fff;font-size:30px;cursor:pointer;opacity:0.65;background:none;border:none;line-height:1;padding:4px}
  .lb-close:hover{opacity:1}
  .lb-arrow{position:absolute;top:50%;transform:translateY(-50%);color:#fff;font-size:48px;cursor:pointer;opacity:0.4;background:none;border:none;padding:0 12px;line-height:1;user-select:none}
  .lb-arrow:hover{opacity:0.9}
  .lb-prev{left:0}.lb-next{right:0}
  .lb-counter{position:absolute;bottom:14px;left:50%;transform:translateX(-50%);color:rgba(255,255,255,0.5);font-size:11px;pointer-events:none}
  .ts-toggle-btn[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:#fff}
  /* Amber, not red: photos are still uploading and still useful — what is
     missing is the position, and the button says so rather than the app
     recording nothing and never mentioning it. */
  .ts-toggle-btn.needs-perm[aria-pressed="true"]{background:#b45309;border-color:#b45309}
  .ts-toggle-btn.needs-perm::after{content:'!';margin-left:5px;font-weight:800}
  .week-section-title{font-size:11px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--accent2);margin-bottom:8px;padding:8px 0;border-bottom:2px solid var(--accent-light)}
  @media(max-width:700px){.week-charts,.dash-inv-grid{grid-template-columns:minmax(0,1fr)}}
  @media(max-width:1100px){.wbs-qty-box{height:300px}}
  @media(max-width:700px){.wbs-qty-box{height:260px}}
  /* PHONE: the metric tiles were one full-width card each, so four of them filled
     the screen before a single number could be compared against another. They go
     two-up and lose most of their padding — the owner's ask was "much smaller
     blocks … so I can see more information". Same markup, same values. */
  @media(max-width:700px){
    /* minmax(0,…) + min-width:0: a grid track is min-content-sized by default,
       so one long figure would widen the column and push the page sideways
       rather than wrapping inside its own tile (Known Mistake, template cards) */
    .week-kpi-strip{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-bottom:12px}
    .wk{padding:9px 11px;border-top-width:2px;border-radius:var(--radius-sm);box-shadow:none;min-width:0;overflow-wrap:anywhere}
    .wk-l{font-size:9px;letter-spacing:.04em;margin-bottom:2px}
    .wk-v{font-size:18px}
    .wk-sub{font-size:9.5px;margin-top:1px}
    .dgrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-bottom:0}
    .dc{padding:10px 12px;border-radius:var(--radius);box-shadow:none;min-width:0;overflow-wrap:anywhere}
    .dc:hover{transform:none;box-shadow:none}
    .dc-icon{display:none}
    .dcl{font-size:9px;letter-spacing:.04em;margin-bottom:2px}
    .dcv{font-size:19px;margin-bottom:1px}
    .dcs{font-size:9.5px}
    /* a chart canvas keeps the inline width Chart.js gave it at the last layout,
       and a min-content grid track honours that — so the card must be free to
       shrink and the canvas capped to it, or the page scrolls sideways */
    .chart-card{padding:11px;min-width:0}
    .chart-card canvas{max-width:100%}
    .wbs-qty-box{height:230px}
    .week-section-title{margin-top:14px}
  }

  /* ── RESPONSIVE: iPad / small desktop (≤1024px) ───────────────── */
  @media(max-width:1024px){
    /* The category rail becomes a scrolling chip row. A 208px vertical rail
       beside the app's own sidebar leaves the sections too narrow to hold a
       toolbar, and the sections are the point. */
    .adm-shell{display:block}
    .adm-nav{flex:none;flex-direction:row;position:static;max-height:none;gap:6px;overflow-x:auto;overflow-y:visible;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:0 0 14px;padding-bottom:2px}
    .adm-nav::-webkit-scrollbar{display:none}
    .adm-it{width:auto;flex:0 0 auto;border:1px solid var(--border);border-left-width:1px;border-radius:99px;padding:0 14px;min-height:40px;white-space:nowrap}
    .adm-it.active{border-color:var(--accent)}
    .adm-it span{overflow:visible;text-overflow:clip}
    :root{--pz-cell:88px;--pz-frz:120px;--pz-h:56px;--pz-font:11px}
    .plan-hint{display:none}
  }

  /* ── RESPONSIVE: Tablet (≤768px) ──────────────────────────────── */
  @media(max-width:768px){
    /* Header */
    .header{height:auto;min-height:48px;padding:6px 12px;flex-wrap:wrap;gap:6px;--hdr-py:6px}
    .hdr-mark{width:28px;height:28px}
    .hsep{display:none}
    .role-badge{display:none}
    .user-badge{max-width:90px;font-size:10px}
    /* Day nav */
    .day-label{min-width:130px;font-size:11px}
    /* Main padding */
    .main{padding:10px}
    /* Planner: zoomed-out defaults for tablet */
    :root{--pz-cell:72px;--pz-frz:88px;--pz-h:48px;--pz-font:10px}
    .plan-wrap{height:calc(100vh - var(--vchrome) - 115px)}
    .plan-toolbar{padding:8px 12px;gap:5px}
    .plan-res-trigger,.plan-plant-trigger{font-size:10px;padding:4px 8px}
    /* Diary matrix */
    table.mx{font-size:11px}
    table.mx td.tda{min-width:140px;max-width:190px}
    /* BOQ */
    .boq-tbl{font-size:11px}
  }

  /* ── RESPONSIVE: Phone (≤480px) ───────────────────────────────── */
  @media(max-width:480px){
    /* Header: very compact */
    .header{padding:4px 10px;gap:5px}
    .hdr-mark{width:26px;height:26px}
    .save-ind{font-size:10px}
    .sp{display:none}
    /* Buttons: touch-friendly minimum */
    .btn.btn-sm{padding:5px 9px;font-size:10px}
    .nav-btn{width:30px;height:30px}
    /* Day nav */
    .day-label{min-width:100px;font-size:10px}
    /* Main */
    .main{padding:6px}
    /* Planner: maximum zoom-out for phone. Frozen column stays wide enough to read
       the section name + its "+ Add Section"/row buttons (64px clipped them). */
    :root{--pz-cell:54px;--pz-frz:104px;--pz-h:40px;--pz-font:9px}
    .plan-wrap{height:calc(100vh - 195px)}
    .plan-toolbar-group .btn{padding:4px 7px;font-size:10px}
    /* Diary matrix */
    table.mx{font-size:10px}
    table.mx td.tda{min-width:110px;max-width:150px}
    /* Modals: full width */
    .md{width:97vw;padding:14px}
  }

  /* ── PHONE APP SHELL (≤600px) — Apple HIG (docs/apple-hig-mobile.md) ──
     One-row header + ⋯ overflow menu, bottom tab bar (Diary/Forms/Photos/
     Programme + More sheet), 16px inputs (kills iOS focus-zoom), 44pt targets. */
  .hdr-more{display:none}
  .hdr-menu{display:none;position:fixed;top:54px;right:8px;z-index:320;background:var(--surface);border:1px solid var(--border);border-radius:14px;box-shadow:0 12px 34px rgba(15,23,42,.22);min-width:210px;padding:6px;flex-direction:column}
  .hdr-menu.open{display:flex}
  .hdr-mi{display:flex;align-items:center;gap:11px;min-height:44px;padding:6px 13px;border:none;background:none;border-radius:9px;font-family:var(--font);font-size:14px;font-weight:600;color:var(--text);cursor:pointer;text-align:left;width:100%}
  .hdr-mi:active{background:var(--surface2)}
  .hdr-mi .ic{width:17px;height:17px;flex-shrink:0}
  .hdr-mi.hm-user{color:var(--text2);font-weight:700;border-bottom:1px solid var(--border);border-radius:9px 9px 0 0}
  .hdr-mi.hm-out{color:var(--red)}
  .mobnav{display:none;position:fixed;left:0;right:0;bottom:0;z-index:290;background:var(--surface);border-top:1px solid var(--border);padding:4px 4px calc(4px + env(safe-area-inset-bottom));box-shadow:0 -6px 22px rgba(15,23,42,.08)}
  .mn-it{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:50px;border:none;background:none;font-family:var(--font);font-size:10px;font-weight:700;color:var(--text3);cursor:pointer;border-radius:10px;padding:4px 0}
  .mn-it .ic{width:22px;height:22px;stroke-width:1.9}
  .mn-it.active{color:var(--accent)}
  .mn-it:active{background:var(--surface2)}
  .mobsheet{display:none;position:fixed;inset:0;z-index:340;background:rgba(15,23,42,.45)}
  .mobsheet.open{display:block}
  .mobsheet-panel{position:absolute;left:0;right:0;bottom:0;background:var(--surface);border-radius:18px 18px 0 0;padding:14px 14px calc(18px + env(safe-area-inset-bottom));box-shadow:0 -14px 44px rgba(15,23,42,.3)}
  .mobsheet-grab{width:38px;height:4px;border-radius:2px;background:var(--border-strong);margin:0 auto 12px}
  .mobsheet-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
  .ms-it{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-height:64px;border:1px solid var(--border);background:var(--surface2);border-radius:13px;font-family:var(--font);font-size:11px;font-weight:700;color:var(--text);cursor:pointer;padding:8px 4px}
  .ms-it .ic{width:21px;height:21px;color:var(--accent)}
  .ms-it:active{background:var(--accent-light)}
  @media(max-width:1024px){
    /* iPad: the header (logo/select/indicators/Admin/Jobs/Export CSV/Day
       PDF/Sign Out) has no wrap/scroll of its own, so at tablet widths it
       ran wider than the viewport and pushed the whole page's scrollWidth
       past the window (owner-reported 2026-08-24, "menu bar extending wider
       than the content… on the iPad" — confirmed failing at 810px; the
       module bar's own fix was not enough on its own). Reuse the SAME
       collapse-to-⋯-menu the phone shell already has (`.hdr-menu` already
       duplicates every one of these actions) rather than inventing a second
       pattern — just at a wider breakpoint, and deliberately WITHOUT the
       sidebar-out/bottom-bar-in swap below: the owner didn't ask for the
       phone bottom-nav shell on iPad, only for the overflow to stop. The
       module bar itself no longer contributes to that overflow at all — it
       is a left rail now, and it defaults to its icon-only width here. */
    .header .btn:not(.hdr-more){display:none}
    .user-badge,.role-badge,.hsep{display:none}
    .job-sel{flex:1;min-width:0;font-size:13px}
    .hdr-more{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:40px;font-size:20px;letter-spacing:1px;padding:0}
  }
  @media(max-width:600px){
    /* header: logo + project + ⋯ only, one row */
    .header{flex-wrap:nowrap;min-height:50px}
    .hdr-wm{display:none}/* the mark alone on a phone — the project name needs the width */
    .header .btn:not(.hdr-more){display:none}
    .user-badge,.role-badge,.hsep{display:none}
    .job-sel{flex:1;min-width:0;max-width:none;font-size:13px}/* the desktop 300px cap would leave the row's end empty from 481px up */
    /* The header's flexible spacer stands down on a phone, so the project box
       takes the whole row up to ⋯ — on EVERY page (owner-reported 2026-09-28: on
       Tasks the spacer split the row with the box, which read half as wide as
       the diary's). The app only hid it at ≤480px, so 481-600 split too. */
    .header .sp{display:none}
    /* Touch target; the rail is already a chip row by this width (≤1024). */
    .adm-it{min-height:44px}
    /* A name plus three segments is wider than a phone — stack, and give each
       segment a real target. Measured, not assumed: at 390 the row needs 300px
       for the segments alone. */
    .modp-row{flex-direction:column;align-items:stretch;gap:7px;padding:9px 2px}
    .modp-seg{width:100%}
    /* Four buttons now, not three — min-width:0 is what lets them share the
       row instead of the last one overflowing (a flex item will not shrink
       below its content otherwise, the trap the resource row already hit). */
    .modp-b{flex:1;min-width:0;min-height:44px;padding:0 4px;font-size:11px}
    /* Four chips now, so the label goes on its own line rather than leaving
       "Full" stranded under the other three. */
    .modp-all{gap:5px}
    .modp-all-l{flex:0 0 100%;margin-bottom:-2px}
    .modp-all .btn{flex:1 1 0;min-width:0;padding:0 4px}
    .arole-row .btn{min-height:44px}
    .save-ind{flex-shrink:0}
    .hdr-more{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:40px;font-size:20px;letter-spacing:1px;padding:0}
    /* modules move to the bottom bar — the sidebar is a desktop/tablet surface;
       the phone shell (bottom bar + More sheet) is HIG-correct and unchanged.
       .shell drops out of flex too, or its one remaining child keeps a flex
       context it no longer needs. */
    .shell{display:block}
    .sidenav{display:none}
    .mobnav{display:flex}
    /* A bottom tab bar behind a modal is inert chrome — tapping it would
       navigate underneath the dialog — and it is the one thing sitting in the
       band where a bottom-sheet's action row lives. Reported 2026-09-05: the
       project-export dialog's Cancel/Export row came up half-covered by it.
       One rule covers every .mo dialog (~45 of them), whether it is a static
       one toggled by openModal or built ad-hoc and appended to the body. */
    /* #planModal (every appConfirm/appPrompt and every tap-to-edit box) is the one
       dialog that is NOT a .mo — it opens on .active — so it was left showing the
       tab bar behind its own action row. Same reasoning, same treatment. */
    body:has(.mo.open) .mobnav,body:has(.mo.open) .pfab,
    body:has(#planModal.active) .mobnav,body:has(#planModal.active) .pfab{display:none}
    .main{padding-bottom:calc(78px + env(safe-area-inset-bottom))}
    /* Planner grid uses a fixed 100vh-based height that predates the bottom tab
       bar, so its bottom rows were hidden behind the 78px .mobnav. Reserve room
       for the bar + safe-area at phone width (this rule sits after the ≤480 block,
       so it wins across all phone widths). */
    .plan-wrap{height:calc(100vh - 235px - env(safe-area-inset-bottom))}
    /* iOS: any focused input under 16px font zooms the page — never go below it.
       Stylesheet !important also beats the builder's inline 11px font-sizes. */
    /* ONLY genuine text-entry controls need 16px. iOS zooms on focus of a keyboard
       field; <select> and date/time inputs open a native picker instead and do NOT
       zoom, so they belong on the type scale like any other control.
       NOTE the bare `input` at the end: plenty of fields in this app carry no `type`
       attribute at all (programme duration/%, resource rows, BOQ section titles) and
       were therefore missed by the old typed-only selector — they render ~12px and
       zoom the page on focus today. */
    input:not([type]),input[type=text],input[type=search],input[type=number],input[type=email],
    input[type=password],input[type=tel],input[type=url],textarea,.frm-rich-ed{font-size:16px!important}
    select,input[type=date],input[type=time]{font-size:13px!important}
    /* ── ONE TYPE SCALE ─────────────────────────────────────────────
       Measured before this: NINE distinct sizes rendering text on a single
       diary screen (9, 10, 10.5, 11, 11.5, 12, 12.5, 13, 14px). Half-pixel
       neighbours are indistinguishable — they just read as sloppiness — and
       9-10px is below the ~11pt floor where text stays legible at arm's
       length on site. Collapsed to three steps:
         11px  micro labels (uppercase captions, table sub-heads) and meta
         12px  body, table cells, note text, every tap-to-edit VALUE
         15px  section headlines
       (compact buttons stay at 13px — a button label is a tap target, not
       body copy, and shrinking it makes it harder to read while reaching.)
       The body step was 15px until 2026-09-06, when the owner pointed at two
       12px surfaces already on screen (an issue card's description, the
       "No deliveries today" empty state) and asked for that size everywhere,
       INCLUDING the boxes that look like fields. That is safe precisely
       because those boxes are .tapval DIVS, not inputs — editing happens in a
       modal, so iOS has nothing to zoom into. A real focusable control keeps
       the 16px anti-zoom floor above and is deliberately untouched.
       `!important` is unavoidable here: much of the small type is inline-styled
       in generated markup (the hours-matrix headers, stat blocks), so a plain
       rule cannot reach it. Phone width only — desktop density is untouched. */
    .sct{font-size:15px!important;letter-spacing:-.2px}
    .sch .btn,.sch .btn-sm{font-size:13px!important}
    .scb{font-size:12px}
    /* A placeholder is a HINT, not something anyone types — the owner pointed at the
       General notes prompt still reading large next to 12px body text. It can take the
       body size safely: iOS decides whether to zoom the page from the CONTROL's own
       font-size, which the 16px floor above still holds, never the placeholder's. */
    input::placeholder,textarea::placeholder{font-size:12px}
    /* uppercase micro-labels: lift the 9/10px ones to the 11px floor. This also
       covers every STRUCTURAL CAPTION inside the matrix — column headers, the
       resource €/hr sub-line, the Dayworks section divider, and the footer's
       "COLUMN TOTALS"/"qty / unit" labels — so the whole table reads as ONE
       consistent two-tier system (11px captions / 12px data) instead of five
       different ad-hoc sizes fighting each other (reported: the Dayworks bar
       and the footer bar both looked like a different, unfinished component
       next to the column headers directly above/below them). */
    table.mx thead th,table.mx thead th span,table.mx .mx-th-rate,
    table.mx .mx-sec-div,table.mx .mx-sec-div span,table.mx .mx-tot-lbl,
    .dnote-title,.dnote-src,.dnote-tag,
    .contrib-sub,.contrib-key,.qr-sub,.mtag{font-size:11px!important}
    /* body-weight text */
    /* NB: inputs are deliberately EXCLUDED — the 16px anti-zoom rule above must
       keep winning, or iOS zooms the page whenever a field is focused. The one
       exception is the WBS picker cell: it's a readonly click-trigger (opens a
       picker, never takes typed input, so it can never zoom), and it was still
       catching the blanket 16px text-input rule — 4px off every other data
       cell. Pinned to match. */
    table.mx td,.tapval,
    .dnote-body,.dnote-orig{font-size:12px!important}
    table.mx td.tdw input.wbs-pick-inp{font-size:12px!important}
    /* secondary / meta */
    .dnote-when,.dnote-who,.day-label{font-size:11px!important}
    /* Everything else that was still sitting at 9-10px: small buttons, the save
       indicator, the resource-grid rate labels, issue badges and the bottom-nav
       captions. All lifted onto the scale so nothing on a phone is under 11px. */
    .btn-sm,.btn.btn-sm,.hdr-more,.save-ind,.rgt,.rgt-l,.rgt-p,.rgt-s,
    .issue-priority-badge,.issue-status-badge,.mn-it{font-size:11px!important}
    .scb .btn,.sch .btn{font-size:13px!important}

    /* Popovers anchored under a button run off the bottom of a phone and cannot be
       reached — a max-height alone does not help when the trigger sits low on the
       page. At phone width they become a bottom-anchored sheet that always sits
       above the tab bar and scrolls internally, which is the HIG pattern anyway. */
    .didx-cust-panel{position:fixed;left:12px;right:12px;width:auto;top:auto;
      bottom:calc(84px + env(safe-area-inset-bottom,0px));max-height:60vh;overflow-y:auto}
    /* The resources panel head is a long uppercase phrase plus two wide actions.
       On one row the title is squeezed into three wrapped lines beside the buttons;
       stack it — title on its own line, the two actions splitting the row below. */
    .res-panel-hdr{flex-wrap:wrap;gap:8px}
    .res-panel-hdr>.res-panel-title,.res-panel-hdr>div{flex:1 1 100%}
    .res-panel-hdr>div .btn{flex:1;justify-content:center}
    /* Diary hours matrix: pin the activity column so it stays visible while you
       scroll sideways to enter hours (the cells already carry solid backgrounds). */
    table.mx td.tda,table.mx th.tha,table.mx .tr-tot td:first-child,table.mx .tr-sub td:first-child{position:sticky;left:0;z-index:2}
    table.mx th.tha{z-index:3}
    /* …and it must not OUTGROW that pin. Measured on an iPhone screenshot the
       owner sent (2026-09-20): the description cell computed max-width:150px and
       rendered 190px, with the tap box reporting scrollWidth 1057 against a
       clientWidth of 190. `.tapval` is white-space:nowrap, so in an AUTO-layout
       table the cell's min-content is the whole unbroken string and max-width is
       only a suggestion the table overrules. The column is position:sticky;left:0,
       so those extra pixels sit ON TOP of whatever is scrolled underneath — which
       is why the screenshot reads "…today were" straight into "VBS —": the W of
       WBS was painted over by the description.
       So the description WRAPS here instead, the same `.frm-tap-wrap` shape the
       forms tap boxes already use. Min-content becomes the longest WORD, the cell
       obeys its cap, and on the screen where the description matters most it is
       actually readable rather than clipped at a third of a sentence. Clamped to
       three lines so one long entry cannot make a row taller than the phone, with
       the full text one tap away in the modal, as before. */
    /* The CAP has to bind the header too, or it is not a cap. With the cells
       wrapping, the widest min-content left in the column was the second header
       row's "describe the work carried out" — nowrap, ~150px of text plus
       padding — which alone held the column at 190px against a 150px max. Both
       header rows wrap here; they are captions, and a caption on two short lines
       costs one row of height once, at the top. */
    table.mx th.tha,table.mx td.tda{width:150px;min-width:150px;max-width:150px}
    table.mx th.tha{white-space:normal;overflow-wrap:anywhere}
    /* The pinned column must COVER everything to its left (owner-reported
       2026-09-27 from an iPhone: "the table seems to be sliding through the
       description column"). #465 put the column on the diary heading rail with
       .twrap{padding-left:16px}, and position:sticky;left:0 pins to the scroll
       container's PADDING edge — so once you scrolled, the WBS text and the
       purple header slid through that 16px strip beside the pinned column.
       Here the 16px moves off the scroller and INTO the pinned cells: the
       column's background now starts at the table's edge and hides what
       scrolls under it, while its content still starts on the same rail. The
       width grows by the same 16px, so the text keeps its 150px. */
    .twrap{padding-left:0}
    table.mx th.tha,table.mx td.tda{width:166px;min-width:166px;max-width:166px;padding-left:16px}
    table.mx tr:first-child th.tha{padding-left:24px}
    table.mx th.tha[style]{padding-left:25px!important}
    table.mx .tr-tot td:first-child,table.mx .tr-sub td:first-child{padding-left:25px}
    /* The three-line cap is the PADDING BOX, not the line-clamp, and that is a
       finding rather than a preference. `-webkit-line-clamp:3` draws its
       ellipsis on line 3 correctly, but a 4th line still lays out — and since
       `overflow:hidden` clips to the padding box, that line painted into the
       9px of bottom padding as a half-height sliver of cut-off words. Measured
       on the element's own screenshot: three lines ending "…with th…" and then
       "approved method" sliced through the middle. (`display` computes to
       `flow-root` here, not `-webkit-box`, so the clamp is only half in force;
       dropping `align-items` did not change that, and chasing the engine
       further is not worth it when the geometry can simply be made exact.)
       So the box ends where line 3 ends: no bottom padding for anything to
       bleed into, the breathing room moved to `margin-bottom`, which is outside
       the padding box and therefore cannot be painted into, and a max-height of
       exactly three lines plus the top padding. */
    table.mx td.tda .mx-desc-tap{white-space:normal;overflow-wrap:anywhere;
      text-overflow:ellipsis;align-items:flex-start;line-height:1.35;
      padding:9px 11px 0;margin-bottom:9px;max-height:calc(1.35em * 3 + 9px);
      display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
    /* Three controls were still off the type scale, found by auditing every
       control on the tab rather than by eye: the weather picker and the dictation
       language picker at 13px in the BROWSER's font (a bare <select> inherits
       neither), and the new-issue priority picker at 13px. A <select> is a native
       picker that never takes typed input, so it can sit on the 12px body step
       with the 16px anti-zoom floor untouched — the same reasoning already
       recorded above for the readonly WBS cell. */
    #wxSel,#dictLang,#newIssuePriority,.wx-sel,.dict-lang-sel{font-size:12px!important}
    /* The General Notes box on a phone: the textarea stands down and the tap box
       takes its place (see notesTapRender). It has to GROW to its own text — a
       one-line note stays a one-line box — so it overrides .tapval's
       single-line ellipsis rather than inheriting it. */
    #genNotesWrap.notes-phone>textarea{display:none}
    #genNotesWrap .notes-tap{white-space:normal;overflow:visible;text-overflow:clip;
      align-items:flex-start;line-height:1.55;overflow-wrap:anywhere;
      min-height:76px;padding:10px 12px;border:1px solid var(--border-strong);
      border-radius:var(--radius-xs,6px);background:var(--surface)}
    /* BOQ toolbar: stack the upload zone full-width over a 2-col grid of actions */
    .boq-searchbar{flex-wrap:wrap}.boq-search{min-width:100%}
    .boq-toolbar{flex-direction:column}
    .boq-toolbar .boq-upload{width:100%;box-sizing:border-box;padding:16px}
    .boq-toolbar .boq-tb-btns{width:100%;padding-top:0;display:grid;grid-template-columns:1fr 1fr;gap:8px}
    .boq-toolbar .boq-tb-btns .btn{width:100%;min-height:44px}
    /* forms fill: bottom action bar is the primary control — drop the cramped
       top-bar duplicates; fields sit flush and even */
    .frm-head.fillbar .btn-blue,.frm-head.fillbar .btn-green,.frm-head.fillbar .btn-amber{display:none}
    .frm-head.fillbar{gap:7px}
    .frm-f input[type=text],.frm-f input[type=number],.frm-f input[type=date],.frm-f input[type=time],.frm-f select,.frm-f textarea{padding:11px 12px}
    .frm-f{margin-bottom:14px}
    .frm-bottombar .btn{min-height:46px}
    /* Type scale rebalance (Apple HIG, docs/apple-hig-mobile.md): inputs went to
       16px (Body) for the anti-zoom rule, so the supporting text steps up to the
       iOS scale with it — labels ≈ Footnote 13, headings ≥ Body (Headline 17),
       captions ≥ the 11pt floor. A heading must never be smaller than the text
       it introduces. */
    .frm-heading{font-size:17px}
    .frm-title{font-size:17px}
    .frm-f-lbl{font-size:13px}
    .frm-info{font-size:14px}
    .frm-f-help{font-size:12px}
    .frm-sec-title{font-size:12.5px}
    .frm-tpl-name{font-size:15px}
    .didx-cust-title{font-size:11px}
    .md label{font-size:13px}
    .frm-chip{font-size:10px}
    .frm-reqpill{font-size:12px}
    .frm-tbl th{font-size:11px}
    .frm-tbl td.frm-tbl-fixed{font-size:15px}
    .frm-tbl td.frm-tbl-calc{font-size:15px}
    .frm-reg-tbl th{font-size:11px}
    .frm-reg-tbl{font-size:14px}
    /* form register: slide sideways instead of crushing columns */
    .frm-reg-tbl{min-width:max-content}
    .frm-reg-tbl td{overflow-wrap:normal;white-space:nowrap;max-width:230px;overflow:hidden;text-overflow:ellipsis}
    /* ...except the Actions view, whose action IS the row: it wraps, the rest slide */
    .frm-reg-tbl.frm-regacts{min-width:0}
    .frm-reg-tbl.frm-regacts td.frm-regacts-tt{white-space:normal;overflow-wrap:anywhere;max-width:none;min-width:200px}
    /* diary toolbar: two rows via a forced flex break (grid shares column
       widths across rows, which let the wide weather select crush the date).
       Row 1 is the DATE and nothing else — it is what the whole screen is about.
       Row 2 is Today · weather · ⋯. Everything that used to crowd this bar
       (All Diaries, the team switcher, who edited it last) moved into the ⋯
       sheet — see dayToolsSheet() for why nothing is removed, only relocated. */
    .day-nav{padding:5px 10px;gap:6px;row-gap:5px}
    .day-nav>.btn{padding:6px 10px;font-size:12px}
    .day-nav>.btn:first-child{display:none}   /* All Diaries  → the ⋯ sheet */
    #dTeamBtn{display:none}                   /* team switcher → the ⋯ sheet */
    #lastEdited{display:none}                 /* last edited by → the ⋯ sheet */
    .day-nav .nav-btn{width:34px;height:34px}
    .day-label{min-width:0;flex:1;text-align:center;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .dn-brk{display:block;flex-basis:100%;height:0;order:1;margin:0}
    .day-nav>.btn.dn-today{order:2}
    /* the weather select takes the slack, so the row is three even controls
       rather than two stubs and a gap */
    .day-nav>div:last-child{order:2;margin-left:0!important;flex:1;min-width:0}
    .day-nav>div:last-child>span{display:none} /* "Weather:" caption — the select says it */
    .wx-sel{font-size:16px;flex:1;min-width:0;padding:4px 6px}
    .dn-tools{order:3;display:inline-flex;align-items:center;justify-content:center;
      min-width:44px;min-height:34px;font-size:16px;line-height:1;padding:3px 10px}
    /* the day-level actions live in the ⋯ sheet on a phone. #processedChk is
       HIDDEN, never removed — loadDay writes to it and toggleProcessed reads it,
       so it has to stay in the DOM as the source of truth. */
    .day-acts{display:none!important}
  }
  .dn-brk{display:none} /* phone-only diary-toolbar line break (base precedes the media override) */
  .dn-tools{display:none} /* phone-only diary ⋯ tools button — revealed in the trailing @media, same reason */
  /* Whose diary you are looking at. A crew name is free text up to 80 characters
     and this sits in the already-crowded diary toolbar, so it truncates rather
     than widening the bar off the screen — the full name is in the tooltip. */
  #dTeamBtn{max-width:190px;overflow:hidden;text-overflow:ellipsis}
  @media(max-width:600px){#dTeamBtn{max-width:132px}}
  /* Photos add — header button on big screens, floating 56pt camera button on
     phones (base rule must precede the media override, same specificity) */
  .pfab{display:none;position:fixed;right:16px;bottom:calc(92px + env(safe-area-inset-bottom));z-index:280;width:56px;height:56px;border-radius:50%;background:var(--accent);color:#fff;border:none;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(37,99,235,.4);cursor:pointer}
  .pfab .ic{width:26px;height:26px;stroke-width:2}
  .pfab:active{transform:scale(.94)}
  @media(max-width:600px){.pfab{display:flex}.dn-brk{display:block}.dn-tools{display:inline-flex}}

  /* ── the diary day's ⋯ sheet (phone). Its own classes rather than borrowing
        .pg-sheet-*: a class is only safe to reach for when the module that owns
        it owns the teardown too (Known Mistake #18). Reuses the generic
        .mobsheet/.mobsheet-panel/.mobsheet-grab shell primitives, which are
        shared chrome by design. ── */
  .dt-panel{max-height:82vh;max-height:82dvh;overflow-y:auto;-webkit-overflow-scrolling:touch}
  .dt-h{font-size:12px;font-weight:800;letter-spacing:.04em;color:var(--text2);margin:0 2px 10px;
    text-align:center;overflow-wrap:anywhere}
  .dt-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .dt-it{display:flex;align-items:center;justify-content:center;text-align:center;min-height:52px;
    padding:8px 10px;border:1px solid var(--border-strong);border-radius:12px;background:var(--surface);
    color:var(--text);font-family:var(--font);font-size:14px;font-weight:600;cursor:pointer;
    line-height:1.3}
  /* the label wraps and breaks rather than widening past its column, and clamps
     to two lines — the full text is on the button's title attribute */
  .dt-lbl{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;
    overflow:hidden;overflow-wrap:anywhere}
  .dt-it:active{background:var(--accent-light)}
  .dt-it.on{border-color:#059669;color:#047857;background:#ecfdf5}
  .dt-it.dt-del{color:var(--red);border-color:#fca5a5}
  .dt-note{font-size:11.5px;line-height:1.5;color:var(--text3);margin-top:12px;padding:0 2px}
  .dt-note.dt-by{margin-top:4px}

  /* ── Phone: a tall dialog is a bottom sheet with a PINNED action row ──────
     `.md` is itself the scroller (there is no body wrapper element), so the
     action row pins with position:sticky rather than a flex footer — the same
     shape `.dexp-acts` already proved for the project export.
     Sized in dvh, never vh: iOS resolves vh against the TOOLBAR-HIDDEN
     viewport, so a 90vh dialog is taller than the visible screen and its last
     rows — the buttons — can never be scrolled to. Reported 2026-08-30: the
     programme Export PDF dialog was unreachable on an iPhone.
     This block must stay AFTER the ≤480 block (which sets .md width/padding)
     or that rule wins at equal specificity. */
  @media(max-width:600px){
    /* Above the phone chrome: .mobnav 290, .hdr-menu 320, .mobsheet 340.
       At 200 the opaque bottom nav painted over the foot of every modal. */
    .mo{z-index:350;align-items:flex-end;padding-top:env(safe-area-inset-top)}
    .md{width:100%;max-width:100%;border-radius:18px 18px 0 0;
        padding:14px;padding-bottom:calc(14px + env(safe-area-inset-bottom));
        max-height:100vh;max-height:100dvh;
        overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
    /* Child selector: a .macts nested inside dialog content must never pin. */
    .md>.macts{position:sticky;bottom:calc(-14px - env(safe-area-inset-bottom));
        margin:0 -14px calc(-14px - env(safe-area-inset-bottom));
        padding:12px 14px calc(12px + env(safe-area-inset-bottom));
        background:var(--surface);border-top:1px solid var(--border);z-index:2}
    .md>.macts .btn{flex:1;min-height:44px}
    /* 44pt option rows in any dialog (the bump was scoped to .dexp-md only,
       so the programme export's own radios stayed sub-44pt). The trailing
       hint wraps to its own line rather than being squeezed to the margin. */
    .md .pg-xrev{min-height:44px;padding:11px 12px}
    .md .pg-xrev span{margin-left:0;flex:1 1 100%}
    /* One scroller per sheet. These lists were capped in vh so they would fit
       inside a 90vh dialog; inside a full-height sheet with a pinned footer
       they are a second touch-scroller fighting the first — a drag near the
       list scrolls the list while the sheet itself looks frozen. Scoped under
       `.md` on purpose: .sl-pinrows and .sl-symlist are shared with the
       markers/symbol POP-OUTS, which are not dialogs and must keep their cap.
       !important is for the ones whose cap is an inline style in a template. */
    .md #pgAuditList,.md #pgActAuditList,.md #pgArchList,.md #slLinkRows,
    .md .sl-pm-photos{max-height:none!important;overflow:visible!important}
    .md #boqWbsList,.md .sl-pinrows,.md .sl-symlist{max-height:none;overflow:visible}
    /* Boxes that are NOT sheets: they run their own internal scrolling and stay
       centred. Their own max-height rules live LATER in this sheet
       (.pg-tbl-md, .pg-rc) and would beat a bare `.md` rule at equal
       specificity — Known Mistake #7 — so the dvh cap is restated here at
       0,2,0. Without the #pgTblModal exemption, .pg-tbl-md (which is
       overflow:hidden) would be bottom-anchored at 92vh and push its own
       heading off the TOP of the screen, where nothing can scroll it back. */
    .mo.frm-viewer,#pgRcM,#pgTblModal{align-items:center}
    .md.pg-tbl-md,.md.pg-rc{border-radius:var(--radius-lg);
        max-height:100vh;max-height:100dvh}
    /* #planModal is the appConfirm/appPrompt/tapVal box — same treatment, so a
       long confirm message can never bury its own OK button. */
    #planModal{align-items:flex-end}
    .pm-box{width:100%;max-width:100%;border-radius:18px 18px 0 0;
        padding:16px;padding-bottom:calc(16px + env(safe-area-inset-bottom));
        max-height:100vh;max-height:100dvh}
    .pm-box>.pm-btns{position:sticky;bottom:calc(-16px - env(safe-area-inset-bottom));
        margin:0 -16px calc(-16px - env(safe-area-inset-bottom));
        padding:12px 16px calc(12px + env(safe-area-inset-bottom));
        background:var(--surface);border-top:1px solid var(--border);z-index:2}
    .pm-box>.pm-btns .btn{flex:1;min-height:44px}
  }

  /* ── ISSUES / NCR ─────────────────────────────── */
  .issue-card{border:1px solid var(--border);border-radius:6px;padding:10px 12px;margin-bottom:8px;background:var(--surface);position:relative}
  .issue-card.priority-high{border-left:3px solid var(--red)}
  .issue-card.priority-medium{border-left:3px solid var(--amber)}
  .issue-card.priority-low{border-left:3px solid var(--green)}
  .issue-card.resolved{opacity:0.65;background:var(--surface2)}
  /* Row splits into a flexible description block + a right-aligned badge/button
     cluster. On phone the two can't share one line (long description + carried
     badge + priority + status + 3 buttons all fighting for 390px) so they stack
     into their own full-width rows instead of wrapping mid-line. */
  .issue-card-row{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}
  .issue-card-main{flex:1;min-width:0;overflow-wrap:anywhere}
  .issue-card-badges{display:flex;gap:5px;align-items:center;min-width:0;max-width:100%;flex-wrap:wrap;justify-content:flex-end}
  @media(max-width:600px){
    .issue-card-row{flex-direction:column;align-items:stretch}
    .issue-card-badges{justify-content:flex-start}
  }
  .issue-priority-badge{font-size:10px;font-weight:700;padding:2px 7px;border-radius:8px;text-transform:uppercase;letter-spacing:0.05em}
  .issue-priority-badge.high{background:var(--red-light);color:var(--red)}
  .issue-priority-badge.medium{background:var(--amber-light);color:var(--amber)}
  .issue-priority-badge.low{background:var(--green-light);color:var(--green)}
  .issue-status-badge{font-size:10px;font-weight:700;padding:2px 7px;border-radius:8px;text-transform:uppercase}
  .issue-status-badge.open{background:var(--red-light);color:var(--red)}
  .issue-status-badge.resolved{background:var(--green-light);color:var(--green)}
  .issue-carry-badge{font-size:10px;font-weight:700;padding:2px 7px;border-radius:8px;background:var(--accent-light);color:var(--accent);white-space:nowrap}

  /* ── VARIATIONS ───────────────────────────────── */
  .var-status-sel{font-size:11px;padding:3px 8px;border:1px solid var(--border);border-radius:4px;font-family:var(--font);background:var(--surface);color:var(--text)}
  .var-status-pending{background:var(--amber-light)!important;color:var(--amber)!important;border-color:var(--amber)!important}
  .var-status-approved{background:var(--green-light)!important;color:var(--green)!important;border-color:var(--green)!important}
  .var-status-rejected{background:var(--red-light)!important;color:var(--red)!important;border-color:var(--red)!important}

  /* ── ALL PROJECTS OVERVIEW ────────────────────── */
  .proj-overview-tbl{width:100%;border-collapse:collapse;font-size:12px}
  .proj-overview-tbl th{background:var(--surface2);padding:8px 12px;text-align:left;font-weight:600;font-size:11px;color:var(--text2);border-bottom:2px solid var(--border);white-space:nowrap}
  .proj-overview-tbl td{padding:8px 12px;border-bottom:1px solid var(--border);vertical-align:middle}
  .proj-overview-tbl tr:hover td{background:var(--surface2)}
  .mini-progress{height:6px;background:var(--border);border-radius:3px;overflow:hidden;min-width:60px}
  .mini-progress-fill{height:100%;border-radius:3px;transition:width 0.3s}
  .mini-progress-fill.ok{background:var(--green)}
  .mini-progress-fill.warn{background:var(--amber)}
  .mini-progress-fill.over{background:var(--red)}

  /* ── DIARY INDEX (all diaries) ─────────────────── */
  .didx-rangebar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}
  .didx-rangelbl{display:flex;flex-direction:column;line-height:1.35;min-width:0}
  .didx-rangelbl b{font-size:13px;font-weight:700;color:var(--accent2)}
  .didx-rangelbl span{font-size:11px;color:var(--text3);font-variant-numeric:tabular-nums}
  .didx-kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:14px}
  .didx-kpi{min-width:0}.didx-kpi-v{overflow-wrap:anywhere}
  .didx-kpi{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 16px;box-shadow:var(--shadow-xs)}
  .didx-kpi-l{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);margin-bottom:3px}
  .didx-kpi-v{font-size:20px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums}
  .didx-kpi-v .sub{font-size:11px;font-weight:600;color:var(--text3);margin-left:5px}
  .didx-kpi.warn .didx-kpi-v{color:var(--amber)}
  .didx-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:12px}
  .didx-seg{display:flex;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:3px;gap:2px}
  .didx-seg button{border:none;background:transparent;font-family:var(--font);font-size:12px;font-weight:600;color:var(--text2);padding:5px 12px;border-radius:6px;cursor:pointer;transition:background .15s var(--ease),color .15s var(--ease);white-space:nowrap}
  .didx-seg button.active{background:var(--accent);color:#fff}
  .didx-seg button .n{opacity:.75;font-size:10px;margin-left:3px;font-variant-numeric:tabular-nums}
  .didx-search{flex:1;min-width:150px;max-width:320px;position:relative}
  .didx-search input{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-sm);padding:7px 10px 7px 30px;font-family:var(--font);font-size:12px;color:var(--text);background:var(--surface)}
  .didx-search .ic{position:absolute;left:9px;top:50%;transform:translateY(-50%);color:var(--text3);pointer-events:none}
  .didx-sort{font-family:var(--font);font-size:12px;padding:7px 8px;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface);color:var(--text2);cursor:pointer;max-width:100%;text-overflow:ellipsis}
  /* a select is as wide as its longest option — one long template name pushed the
     forms register 243px off a 768px screen (stress, 2026-10-06) */
  .didx-cust{position:relative}
  .didx-cust-panel{position:absolute;right:0;top:calc(100% + 6px);background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);box-shadow:var(--shadow-lg);padding:12px 14px;z-index:120;width:238px;display:none;max-height:min(70vh,520px);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
  .didx-cust-panel.open{display:block}
  .didx-cust-panel label{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text);padding:5px 0;cursor:pointer}
  .didx-cust-panel input[type=checkbox],.didx-cust-panel input[type=radio]{accent-color:var(--accent);width:14px;height:14px}
  .didx-cust-title{font-size:9px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text3);margin:4px 0}
  .didx-strip{display:flex;gap:6px;align-items:center;flex-wrap:wrap;background:var(--amber-light);border:1px solid #f0d9a8;border-radius:var(--radius);padding:9px 12px;margin-bottom:14px}
  .didx-strip-l{font-size:11px;font-weight:700;color:var(--amber);text-transform:uppercase;letter-spacing:.04em;margin-right:2px}
  .didx-strip-chip{background:#fff;border:1px solid #edcf96;color:#92400e;font-size:11px;font-weight:600;padding:3px 10px;border-radius:20px;cursor:pointer;font-variant-numeric:tabular-nums;transition:all .15s var(--ease)}
  .didx-strip-chip:hover{background:var(--amber);color:#fff;border-color:var(--amber)}
  .didx-month{font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text2);margin:18px 2px 10px;display:flex;align-items:center;gap:10px}
  .didx-month::after{content:'';flex:1;height:1px;background:var(--border)}
  .didx-month .n{color:var(--text3);font-weight:600;letter-spacing:0;font-variant-numeric:tabular-nums}
  .didx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
  .didx-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;cursor:pointer;box-shadow:var(--shadow-xs);transition:box-shadow .16s var(--ease),transform .16s var(--ease),border-color .16s var(--ease);display:flex;flex-direction:column;gap:9px}
  .didx-card:hover{box-shadow:var(--shadow);transform:translateY(-2px);border-color:var(--accent)}
  .didx-card.today{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),var(--shadow-xs)}
  .didx-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
  .didx-date{font-size:15px;font-weight:800;color:var(--text);letter-spacing:-.01em}
  /* Two index rows for one date are otherwise identical — say whose diary each is. */
  .didx-team{display:inline-block;margin-left:7px;padding:1px 7px;border-radius:999px;background:var(--accent-light);color:var(--accent);font-size:10px;font-weight:800;vertical-align:middle}
  .didx-sub{font-size:11px;color:var(--text3);margin-top:1px}
  .didx-chip{font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:3px 9px;border-radius:20px;flex-shrink:0;border:none;cursor:default;font-family:var(--font)}
  .didx-chip.clickable{cursor:pointer}
  .didx-chip.ok{background:var(--green-light);color:var(--green)}
  .didx-chip.draft{background:var(--amber-light);color:var(--amber)}
  .didx-chip.empty{background:var(--surface2);color:var(--text3)}
  .didx-notes{font-size:12px;color:var(--text2);line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
  .didx-stats{display:flex;gap:16px;flex-wrap:wrap}
  .didx-stat-v{font-size:15px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}
  .didx-stat-v.ev{color:var(--green)}
  .cpi-ok{color:var(--green)}
  .cpi-bad{color:var(--red)}
  .didx-stat-l{font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);font-variant-numeric:tabular-nums}
  .didx-foot{display:flex;align-items:center;gap:12px;border-top:1px solid var(--border);padding-top:9px;margin-top:auto;font-size:11px;color:var(--text2)}
  .didx-cnt{display:inline-flex;align-items:center;gap:4px;font-variant-numeric:tabular-nums}
  .didx-cnt .ic{color:var(--text3)}
  .didx-cnt.alert{color:var(--red);font-weight:700}
  .didx-cnt.alert .ic{color:var(--red)}
  .didx-wx{margin-left:auto;font-size:11px;color:var(--text3);white-space:nowrap}
  .didx-gap{grid-column:1/-1;display:flex;align-items:center;gap:10px;background:transparent;border:1.5px dashed var(--border-strong);border-radius:var(--radius);padding:9px 14px;color:var(--text3);font-size:12px;cursor:pointer;transition:all .15s var(--ease);font-family:var(--font)}
  .didx-gap:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-light)}
  .didx-empty{text-align:center;padding:60px 20px;color:var(--text3);font-size:13px;line-height:2}
  .didx-skel{height:150px;border-radius:var(--radius);background:linear-gradient(100deg,var(--surface) 40%,var(--surface2) 50%,var(--surface) 60%);background-size:200% 100%;animation:skel 1.2s infinite;border:1px solid var(--border)}
  @keyframes skel{to{background-position:-200% 0}}
  .didx-grid.compact .didx-card{padding:10px 13px;gap:6px}
  .didx-grid.compact .didx-notes{display:none}
  /* ── diary index LIST view (rows) ── */
  .didx-list{display:flex;flex-direction:column;gap:6px}
  .didx-lrow{display:flex;align-items:center;gap:18px;background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:10px 16px;cursor:pointer;box-shadow:var(--shadow-xs);transition:border-color .14s var(--ease),box-shadow .14s var(--ease)}
  .didx-lrow:hover{border-color:var(--accent);box-shadow:var(--shadow)}
  .didx-lrow.today{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),var(--shadow-xs)}
  .didx-lmain{flex:1 1 220px;min-width:0}
  /* the row WRAPS rather than push its status chip off the screen: a tablet with
     six-figure costs, plus the selection tick, ran 196px past 768 (stress, 2026-10-06) */
  .didx-lrow{flex-wrap:wrap;row-gap:8px}
  .didx-ldate{font-size:14px;font-weight:700;color:var(--text);display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
  .didx-lsub{font-size:11px;font-weight:400;color:var(--text3)}
  .didx-lnotes{font-size:11.5px;color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px;max-width:640px}
  .didx-lstats{display:flex;gap:22px;flex-shrink:0}
  .didx-lc{display:flex;flex-direction:column;align-items:flex-end;min-width:56px}
  .didx-lc .v{font-size:14px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.2}
  .didx-lc .v.ev{color:var(--green)}
  .didx-lc .l{font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text3)}
  .didx-lfoot{display:flex;align-items:center;gap:10px;flex-shrink:0}
  .didx-lchip{flex-shrink:0;width:92px;display:flex;justify-content:flex-end}
  /* ── select days + export a ZIP of per-day PDFs ── */
  .didx-hmain{flex:1;min-width:0}
  .didx-selbtn.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .didx-selwrap{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:28px;height:28px;margin:-4px 0 -4px -6px;cursor:pointer}
  .didx-selwrap input{width:18px;height:18px;accent-color:var(--accent);pointer-events:none;margin:0}
  .didx-card.sel,.didx-lrow.sel{border-color:var(--accent);background:var(--accent-light);box-shadow:0 0 0 1px var(--accent)}
  .didx-selbar{position:sticky;top:0;z-index:30;display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--surface);border:1px solid var(--accent);border-radius:var(--radius);padding:8px 12px;margin-bottom:12px;box-shadow:var(--shadow)}
  .didx-seln{font-size:12.5px;font-weight:800;color:var(--accent);font-variant-numeric:tabular-nums;white-space:nowrap}
  .didx-selsp{flex:1}
  .didx-xlead{font-size:11.5px;color:var(--text2);margin-bottom:12px;line-height:1.6}
  .didx-xrange{margin:2px 0 4px 24px}
  .didx-xrange.off{opacity:.45}
  .didx-xcount{font-size:12px;color:var(--text2);margin:8px 0 4px;line-height:1.5;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
  .didx-xcount .warn{color:var(--amber);font-weight:700}
  .didx-xopts{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
  .didx-xprog{margin-top:12px}
  .didx-xbar{height:6px;border-radius:3px;background:var(--surface2);overflow:hidden}
  .didx-xbar i{display:block;height:100%;width:0;background:var(--accent);transition:width .25s var(--ease)}
  .didx-xmsg{font-size:11.5px;color:var(--text2);margin-top:6px;overflow-wrap:anywhere}
  @media(max-width:600px){.didx-xopts{grid-template-columns:1fr}.didx-xrange{margin-left:0}.didx-selsp{display:none}.didx-selbar{top:0}}
  @media(max-width:600px){.didx-rangebar .dash-range{width:100%}.didx-rangebar .dash-rng-btn{flex:1;padding:7px 4px}.didx-rangelbl{flex:1 1 100%}}
  @media(max-width:700px){.didx-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}.didx-grid{grid-template-columns:1fr}
    .didx-lrow{flex-wrap:wrap;gap:8px 16px;align-items:flex-start}
    .didx-lmain{flex-basis:100%}
    .didx-lstats{gap:16px}
    .didx-lchip{width:auto;margin-left:auto}}

  /* ── CUSTOM FORMS ─────────────────────────────── */
  .frm-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px}
  .frm-title{font-size:16px;font-weight:800;color:var(--text);letter-spacing:-.01em;flex:1;min-width:0;overflow-wrap:anywhere}
  .frm-sec-title{font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text2);margin:20px 2px 10px;display:flex;align-items:center;gap:10px}
  .frm-sec-title::after{content:'';flex:1;height:1px;background:var(--border)}
  .frm-tpl-finder{display:flex;flex-direction:column;gap:10px;margin-bottom:14px}
  .frm-tpl-q{width:100%;max-width:520px;border:1px solid var(--border-strong);border-radius:10px;padding:10px 14px;font-family:var(--font);font-size:14px;color:var(--text);background:var(--surface);box-shadow:var(--shadow-xs);outline:none;transition:border-color .12s var(--ease),box-shadow .12s var(--ease)}
  .frm-tpl-q:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light)}
  .frm-cat-chips{display:flex;gap:7px;flex-wrap:wrap}
  .frm-cat-chip{border:1px solid var(--border-strong);background:var(--surface);color:var(--text2);font-family:var(--font);font-size:11.5px;font-weight:700;padding:6px 13px;border-radius:20px;cursor:pointer;transition:all .12s var(--ease);white-space:nowrap}
  .frm-cat-chip:hover{border-color:var(--accent);color:var(--accent)}
  .frm-cat-chip.on{background:var(--accent);border-color:var(--accent);color:#fff}
  /* An organisation names its own categories, so a chip can be any length —
     it truncates with the full name on its title instead of widening the row. */
  .frm-cat-chips .frm-cat-chip{max-width:100%;overflow:hidden;text-overflow:ellipsis}
  .frm-cat-edit{border:1px dashed var(--border-strong);background:none;color:var(--text3);font-family:var(--font);font-size:11.5px;font-weight:700;padding:6px 12px;border-radius:20px;cursor:pointer;display:inline-flex;align-items:center;white-space:nowrap}
  .frm-cat-edit:hover{border-color:var(--accent);color:var(--accent)}
  .frm-cat-lead{font-size:12.5px;line-height:1.55;color:var(--text2);margin:-2px 0 12px}
  .frm-cat-rows{display:flex;flex-direction:column;gap:6px;margin-bottom:10px}
  .frm-cat-row{display:flex;align-items:center;gap:6px;min-width:0}
  .frm-cat-name{flex:1 1 0;min-width:0;border:1px solid var(--border-strong);border-radius:8px;padding:8px 10px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface)}
  .frm-cat-name:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light)}
  .frm-cat-used{flex:0 0 auto;font-size:11px;color:var(--text3);min-width:0;white-space:nowrap}
  .frm-cat-ico{flex:0 0 auto;width:32px;height:32px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text2);cursor:pointer;font-size:14px}
  .frm-cat-ico:disabled{opacity:.35;cursor:default}
  .frm-cat-ico.del:hover{background:var(--red-light);color:var(--red);border-color:transparent}
  .frm-cat-none{font-size:12px;color:var(--text3);padding:8px 0}
  .frm-cat-adminlist{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:12px}
  .frm-cat-adminlist .frm-cat-chip{cursor:default;max-width:100%;overflow:hidden;text-overflow:ellipsis}
  .frm-cat-src{font-size:11px;color:var(--text3)}
  @media(max-width:600px){
    .frm-cat-ico{width:44px;height:44px}
    .frm-cat-used{display:none}
  }
  .frm-tpl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:12px}
  /* Sub-categories (2026-10-06): a second, quieter chip row under the picked
     category, and a foldable heading per sub-category inside each section. */
  .frm-sub-chips{margin-top:8px;padding-left:10px;border-left:2px solid var(--border)}
  .frm-sub-chip{font-size:11px;padding:5px 11px;font-weight:600}
  .frm-sub-title{display:flex;align-items:center;gap:8px;width:100%;min-width:0;margin:16px 0 10px;padding:6px 2px;background:none;border:0;border-bottom:1px dashed var(--border);
    font-family:var(--font);font-size:12.5px;font-weight:700;color:var(--text);text-align:left;cursor:pointer}
  .frm-sub-title:hover{color:var(--accent)}
  .frm-sub-title:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
  .frm-sub-caret{flex:none;font-size:10px;color:var(--text3);transition:transform .15s var(--ease)}
  .frm-sub-title.shut .frm-sub-caret{transform:rotate(-90deg)}
  .frm-sub-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-sub-n{flex:none;font-size:10.5px;font-weight:700;color:var(--text3);background:var(--surface2);border:1px solid var(--border);border-radius:10px;padding:1px 8px}
  .frm-tpl-sub{width:180px;max-width:100%}
  .md.frm-move-md{max-width:440px}
  .frm-move-md h3{overflow-wrap:anywhere}
  .md .frm-move-lbl{display:block;font-size:11px;font-weight:700;color:var(--text2);margin:10px 0 5px;text-transform:none;letter-spacing:normal}
  .frm-move-in{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:8px;padding:9px 10px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface)}
  .frm-move-in:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light)}
  .frm-move-picks{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 4px}
  .frm-move-pick{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:1px solid var(--border-strong);background:var(--surface);color:var(--text2);font-family:var(--font);font-size:11.5px;font-weight:600;padding:5px 11px;border-radius:16px;cursor:pointer}
  .frm-move-pick:hover{border-color:var(--accent);color:var(--accent)}
  .frm-move-pick.on{background:var(--accent);border-color:var(--accent);color:#fff}
  @media(max-width:600px){.frm-move-pick{padding:9px 13px}.frm-move-in{font-size:16px}.frm-sub-title{min-height:40px}.frm-sub-chip{padding:8px 12px}}
  /* ── Company forms library (2026-10-06) ──
     body.org-lib is the Organisation view. Widened 2026-10-07 from Forms alone
     to the company-wide modules: an item is offered there when its markup
     carries `data-org`, on every nav surface — the sidebar (and a group with
     none left), the phone bar and its More sheet. The photo button that floats
     over the phone bar, and the Photos page's upload/download controls
     (.proj-only), are per project, so they go; .org-only shows only here. */
  body.org-lib .sidenav .sn-it:not([data-org]){display:none}
  body.org-lib .sidenav .sn-grp:not(:has([data-org])){display:none}
  body.org-lib .mobnav .mn-it:not([data-org]),body.org-lib .mobsheet .ms-it:not([data-org]),body.org-lib .pfab,body.org-lib .proj-only{display:none!important}
  .org-only{display:none}
  body.org-lib .org-only{display:block}
  #photoJobSel{font-size:12px;padding:5px 8px;border:1px solid var(--border);border-radius:4px;background:var(--surface);color:var(--text);max-width:220px;min-width:0}
  .ppc-job{padding:5px 6px 0;font-size:10px;font-weight:600;color:var(--accent2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .frm-lib-intro{font-size:12.5px;color:var(--text2);line-height:1.55;background:var(--surface2);border:1px solid var(--border);border-radius:9px;padding:10px 13px;margin:-4px 0 14px;max-width:820px}
  .frm-lib-where{display:inline-block;font-size:12px;font-weight:500;color:var(--text2);padding:7px 0;text-transform:none;letter-spacing:normal}
  .frm-play-chip{vertical-align:middle}
  .md.frm-dep-md{width:520px;max-width:100%}
  .frm-dep-md h3{overflow-wrap:anywhere}
  .frm-dep-bulk{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:8px 0}
  .frm-dep-n{margin-left:auto;font-size:11.5px;color:var(--text3);font-weight:600}
  .frm-dep-list{max-height:min(44vh,360px);overflow-y:auto;display:flex;flex-direction:column;gap:5px;margin:0 -3px;padding:1px 3px}
  /* <label> rows inside .md: out-specify `.md label{display:block}` (Known Mistake #7) */
  .md .frm-dep-row{flex-shrink:0;display:flex;align-items:center;gap:10px;min-height:46px;margin:0;padding:8px 11px;border:1px solid var(--border);border-radius:9px;background:var(--surface);cursor:pointer;text-transform:none;letter-spacing:normal;font-weight:400;color:var(--text);font-size:13px}
  .md .frm-dep-row:hover{border-color:var(--border-strong);background:var(--surface2)}
  .md .frm-dep-row input{flex:0 0 auto;width:18px;height:18px;margin:0}
  .frm-dep-tx{flex:1;min-width:0}
  .frm-dep-nm{display:block;font-weight:600;overflow-wrap:anywhere;line-height:1.3}
  .frm-dep-num{display:block;font-size:11px;color:var(--text3);font-family:var(--mono);overflow-wrap:anywhere}
  .frm-dep-st{flex:0 1 auto;max-width:44%;text-align:right;font-size:11px;font-weight:600;color:var(--text3);line-height:1.3}
  .frm-dep-st.st-cur{color:var(--green)}
  .frm-dep-st.st-old,.frm-dep-st.st-edit{color:var(--amber,#b45309)}
  .md .frm-dep-opt{display:flex;align-items:flex-start;gap:9px;margin:10px 0 0;font-size:12.5px;font-weight:500;color:var(--text);text-transform:none;letter-spacing:normal;line-height:1.45;cursor:pointer}
  .md .frm-dep-opt input{flex:0 0 auto;width:17px;height:17px;margin:1px 0 0}
  .md .frm-dep-opt.warn{background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:8px 10px}
  .md.frm-gal-md{width:760px;max-width:100%}
  .frm-gal-md .frm-cat-chips{margin:8px 0 2px}
  .frm-gal-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px;margin-top:10px;max-height:min(52vh,460px);overflow-y:auto;padding:1px}
  .frm-gal-card{flex-shrink:0;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);padding:12px 13px;display:flex;flex-direction:column;gap:6px;min-width:0}
  .frm-gal-hd{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0}
  .frm-gal-hd .frm-tpl-name{min-width:0;overflow-wrap:anywhere}
  .frm-gal-cat{font-size:11px;color:var(--text3);font-weight:600;overflow-wrap:anywhere}
  .frm-gal-card .frm-tpl-desc{overflow-wrap:anywhere}
  .adm-flib{display:inline-flex;align-items:center;gap:6px;margin:6px 0 0 8px;font-size:11.5px;font-weight:600;color:var(--text2);cursor:pointer;white-space:nowrap;min-height:28px}
  .adm-flib input{width:16px;height:16px;margin:0}
  @media(max-width:600px){.md .frm-dep-row{min-height:52px}.frm-gal-grid{grid-template-columns:1fr;max-height:none}.adm-flib{margin-left:0;min-height:40px}}
  .frm-tpl-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;box-shadow:var(--shadow-xs);display:flex;flex-direction:column;gap:8px;transition:box-shadow .16s var(--ease),transform .16s var(--ease),border-color .16s var(--ease)}
  .frm-tpl-card:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
  .frm-tpl-name{font-size:14px;font-weight:700;color:var(--text);overflow-wrap:anywhere;min-width:0}
  .frm-tpl-desc{font-size:11px;color:var(--text3);line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
  .frm-chip{font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:2px 8px;border-radius:20px;display:inline-block}
  .frm-chip.cat-Quality{background:var(--accent-light);color:var(--accent)}
  .frm-chip.cat-Safety{background:var(--amber-light);color:var(--amber)}
  .frm-chip.cat-Environment{background:var(--green-light);color:var(--green)}
  .frm-chip.cat-Commercial{background:#ede9fe;color:#5b21b6}
  .frm-chip.cat-General{background:var(--surface2);color:var(--text2)}
  .frm-chip.st-pub{background:var(--green-light);color:var(--green)}
  .frm-chip.st-draft{background:var(--amber-light);color:var(--amber)}
  /* An entry's chips read as a journey: amber draft -> blue awaiting signature
     -> green approved. st-sub was green when "submitted" WAS the end state; it
     no longer is, and two green chips would hide the difference that matters. */
  .frm-sigprog{display:inline-block;margin-left:6px;font-size:10px;font-weight:700;padding:2px 7px;border-radius:20px;background:var(--surface2);color:var(--text2);vertical-align:middle;font-variant-numeric:tabular-nums}
  .frm-sigprog.part{background:var(--amber-light);color:var(--amber)}
  .frm-sigprog.all{background:var(--green-light);color:var(--green)}
  /* a scheduled inspection still owed — when, and whether it is late (Tier 1.4) */
  /* Areas (review Tier 2.6) — a path can be long ("Block A › Level 2 › Zone C"),
     so every control that shows one is capped and the register cell wraps */
  .frm-area-f{max-width:240px}
  .frm-reg-tbl td.frm-reg-area{min-width:110px;max-width:240px;white-space:normal;overflow-wrap:anywhere;font-size:11.5px;color:var(--text2)}
  .frm-area-md{max-width:520px}
  .frm-area-list{border:1px solid var(--border);border-radius:var(--radius-sm);max-height:min(46vh,420px);overflow:auto;margin:10px 0}
  .frm-area-row{display:flex;align-items:center;gap:6px;padding:6px 8px;border-bottom:1px solid var(--border);min-width:0}
  .frm-area-row:last-child{border-bottom:none}
  .frm-area-row .btn{flex:none}
  .frm-area-nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}
  .frm-area-add{display:flex;gap:8px;align-items:center;margin-top:8px}
  .frm-area-add input{flex:1;min-width:0;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:8px 10px;font:inherit;font-size:13px}
  .frm-cond select.frm-cond-v{max-width:min(260px,100%)}
  @media(max-width:600px){.frm-area-f{max-width:100%;flex:1 1 100%}.frm-area-add input{font-size:16px}.frm-area-row .btn{min-height:40px}}
  /* Project data (lookup) questions (Tier 2.9) — a BOQ line or an activity can
     carry a long name, so the picker and the register filter are capped */
  .frm-lk-sel{width:100%;max-width:100%;min-width:0;text-overflow:ellipsis}
  .frm-lk-f{max-width:240px}
  @media(max-width:600px){.frm-lk-f{max-width:100%;flex:1 1 100%}}
  /* Forms insights (forms review 3.11) */
  .frm-ins-md{max-width:920px;width:100%}
  .frm-ins-ctl{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;margin-bottom:10px}
  .frm-ins-ctl .frm-cat-chips{margin:0}
  .frm-ins-ctl select{max-width:280px;min-width:0}
  .frm-ins-kpis{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;margin:6px 0 4px}
  .frm-ins-kpi{border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;background:var(--surface);min-width:0}
  .frm-ins-v{font-size:22px;font-weight:800;line-height:1.1;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
  .frm-ins-l{font-size:11px;font-weight:600;color:var(--text2);margin-top:2px}
  .frm-ins-s{font-size:11px;color:var(--text3);margin-top:4px;overflow-wrap:anywhere}
  .frm-ins-kpi.bad .frm-ins-v,.frm-ins-kpi.bad .frm-ins-s b{color:var(--red)}
  .frm-ins-trend{display:flex;align-items:flex-end;gap:6px;height:150px;padding:4px 2px 0;border-bottom:1px solid var(--border-strong);overflow-x:auto}
  .frm-ins-bar{flex:1 0 34px;max-width:64px;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:2px;min-width:34px}
  .frm-ins-col{width:70%;min-height:3px;display:flex;flex-direction:column-reverse;border-radius:4px 4px 0 0;overflow:hidden}
  .frm-ins-col i,.frm-ins-key i{display:block;min-height:2px}
  .frm-ins-col i.p,.frm-ins-key i.p{background:var(--green)}
  .frm-ins-col i.f,.frm-ins-key i.f{background:var(--red)}
  .frm-ins-col i.o,.frm-ins-key i.o{background:var(--border-strong)}
  .frm-ins-n{font-size:11px;font-weight:700;font-variant-numeric:tabular-nums;order:-1}
  .frm-ins-bl{font-size:10px;color:var(--text3);white-space:nowrap}
  .frm-ins-key{display:flex;gap:14px;flex-wrap:wrap;font-size:11px;color:var(--text2);margin:6px 0 2px}
  .frm-ins-key span{display:inline-flex;align-items:center;gap:5px}
  .frm-ins-key i{width:10px;height:10px;border-radius:2px}
  .frm-ins-fails,.frm-ins-people,.frm-ins-projs{display:flex;flex-direction:column;gap:2px}
  .frm-ins-fail{display:flex;align-items:center;gap:12px;padding:6px 0;border-bottom:1px solid var(--border);min-width:0}
  .frm-ins-fq{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
  .frm-ins-fq b{font-size:13px;overflow-wrap:anywhere}
  .frm-ins-fq span{font-size:11px;color:var(--text3);overflow-wrap:anywhere}
  .frm-ins-fr{flex:0 0 auto;display:flex;align-items:center;gap:8px}
  .frm-ins-meter{display:block;width:90px;height:8px;border-radius:4px;background:var(--surface2);border:1px solid var(--border);overflow:hidden}
  .frm-ins-meter i{display:block;height:100%;background:var(--red)}
  .frm-ins-fn{font-size:12px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;min-width:52px;text-align:right}
  .frm-ins-person{display:flex;align-items:center;gap:10px;padding:5px 0;border-bottom:1px solid var(--border);font-size:13px;min-width:0}
  .frm-ins-pn{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-ins-po{flex:0 0 auto;color:var(--text2);white-space:nowrap}
  .frm-ins-pv{flex:0 0 auto;color:var(--red);font-weight:700;white-space:nowrap}
  .frm-ins-proj{display:grid;grid-template-columns:minmax(0,2.4fr) repeat(4,minmax(0,1fr));gap:8px;align-items:center;padding:6px 0;border-bottom:1px solid var(--border);font-size:12px;font-variant-numeric:tabular-nums}
  .frm-ins-pjn{font-weight:700;font-size:13px;overflow-wrap:anywhere;min-width:0}
  .frm-ins-proj .bad{color:var(--red);font-weight:700}
  .frm-ins-proj .dim{color:var(--text3)}
  @media(max-width:760px){.frm-ins-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}.frm-ins-kpi[data-k="close"]{grid-column:1/-1}}
  @media(max-width:600px){.frm-ins-ctl select{max-width:100%;flex:1 1 100%}.frm-ins-meter{width:56px}
    .frm-ins-proj{grid-template-columns:repeat(2,minmax(0,1fr))}.frm-ins-pjn{grid-column:1/-1}}
  /* Asset QR (forms review 2.10): an asset's page, and the list labels are printed from */
  .frm-asset-md{max-width:620px;width:100%}
  .frm-asset-head{margin-bottom:6px;min-width:0}
  .frm-asset-kind{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);background:var(--accent-light);border-radius:999px;padding:2px 8px}
  .frm-asset-nm{margin:6px 0 2px;font-size:18px;line-height:1.25;overflow-wrap:anywhere}
  .frm-asset-sub{font-size:12px;color:var(--text3);overflow-wrap:anywhere}
  .frm-asset-tpls{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px;margin-bottom:6px}
  .frm-asset-tpl{display:grid;grid-template-columns:1fr auto;grid-template-rows:auto auto;align-items:center;column-gap:8px;text-align:left;min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;background:var(--surface);cursor:pointer;font:inherit;color:var(--text)}
  .frm-asset-tpl:hover:not(:disabled){border-color:var(--accent)}
  .frm-asset-tpl:disabled{opacity:.55;cursor:default}
  .frm-asset-tpl .ic{grid-row:1/3;grid-column:2;color:var(--accent)}
  .frm-asset-tn{font-weight:700;font-size:13px;min-width:0;overflow-wrap:anywhere}
  .frm-asset-tc{font-size:11px;color:var(--text3);min-width:0;overflow-wrap:anywhere}
  .frm-asset-hist{display:flex;flex-direction:column;gap:4px}
  .frm-asset-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:44px;padding:6px 10px;border:1px solid var(--border);border-radius:8px;background:var(--surface);cursor:pointer;font:inherit;color:var(--text);text-align:left}
  .frm-asset-row:hover{border-color:var(--accent)}
  .frm-asset-d{flex:0 0 auto;font-size:12px;color:var(--text2);font-variant-numeric:tabular-nums;white-space:nowrap}
  .frm-asset-t{flex:1 1 auto;min-width:0;font-size:13px;overflow-wrap:anywhere}
  .frm-asset-in{font-size:11px;color:var(--text3)}
  .frm-asset-row .frm-chip,.frm-asset-row .frm-score-pill{flex:0 0 auto}
  .frm-assets-list{display:flex;flex-direction:column;gap:2px;margin:8px 0}
  .frm-assets-g{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);margin:8px 0 2px}
  .frm-assets-row{display:flex;align-items:center;gap:8px;min-width:0;padding:4px 0;border-bottom:1px solid var(--border)}
  .md .frm-assets-pick{display:flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0;margin:0;text-transform:none;font-weight:500;letter-spacing:normal;color:var(--text);font-size:13px;cursor:pointer}
  .frm-assets-nm{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-assets-n{flex:0 0 auto;font-size:11px;color:var(--text3);white-space:nowrap}
  @media(max-width:600px){.frm-asset-row{flex-wrap:wrap}.frm-asset-t{flex-basis:calc(100% - 90px)}.frm-assets-row .btn{min-height:40px}}
  /* a hold / witness point on the form (Tier 2.7) */
  .frm-hold{border:1px solid var(--border);border-left:3px solid #dc2626;border-radius:var(--radius-sm);padding:10px 12px;background:var(--surface)}
  .frm-hold:has(.frm-hold-kind.witness){border-left-color:#d97706}
  .frm-hold:has(.frm-hold-kind.rel){border-left-color:#16a34a}
  .frm-hold-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0}
  .frm-hold-head .frm-f-lbl{flex:1;min-width:0;overflow-wrap:anywhere}
  .frm-hold-kind{flex:none;font-size:10px;font-weight:800;padding:2px 8px;border-radius:20px;background:#fee2e2;color:#b91c1c;white-space:nowrap}
  .frm-hold-kind.witness{background:#fef3c7;color:#92400e}.frm-hold-kind.rel{background:#dcfce7;color:#166534}
  .frm-hold-pick{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:6px}
  .frm-f .frm-hold-pick select{flex:1 1 220px;min-width:0;width:auto}
  .frm-hold-pick .btn{flex:none}
  .frm-hold-act,.frm-hold-rel{font-size:12.5px;margin-top:5px;overflow-wrap:anywhere}
  .frm-hold-rel{color:#166534}
  .frm-hold-undo{margin-top:7px}
  @media(max-width:600px){.frm-hold-pick .btn{min-height:44px}.frm-f .frm-hold-pick select{flex-basis:100%}}
  /* links to the rest of the project (Tier 2.8): the form's strip, the picker,
     and the forms a record shows (diary day, BOQ line, issue card) */
  .frm-links{clear:both;display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:2px 0 12px;padding:8px 10px;border:1px dashed var(--border);border-radius:var(--radius-sm);background:var(--surface2);min-width:0}
  .frm-links-lbl{display:inline-flex;align-items:center;font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text2);white-space:nowrap}
  .frm-links-none{font-size:12px;color:var(--text3);flex:1 1 200px;min-width:0}
  .frm-link{display:inline-flex;align-items:stretch;max-width:100%;min-width:0;border:1px solid var(--border);border-radius:20px;background:var(--surface);overflow:hidden}
  .frm-link-go{display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:100%;border:0;background:none;padding:4px 4px 4px 10px;font:inherit;font-size:12px;color:var(--text);cursor:pointer;text-align:left}
  .frm-link-go b{flex:none;color:var(--accent);white-space:nowrap}
  .frm-link-go span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:28ch}
  .frm-link-go:hover span{text-decoration:underline}
  .frm-link-x{flex:none;border:0;background:none;padding:0 9px;font-size:15px;line-height:1;color:var(--text3);cursor:pointer}
  .frm-link-x:hover{color:var(--red)}
  .frm-link-add{margin-left:auto}
  .frm-link-md{max-width:560px}
  .frm-link-kind-l{display:block;margin:10px 0 8px}
  .frm-link-kind-l select{display:block;width:100%;margin-top:4px}
  .frm-link-day{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end}
  .frm-link-day label{flex:1 1 160px;min-width:0;margin:0}
  .frm-link-day input,.frm-link-day select{display:block;width:100%;margin-top:4px}
  .frm-link-q{width:100%;margin-bottom:8px}
  .frm-link-list{max-height:46vh;overflow:auto;border:1px solid var(--border);border-radius:var(--radius-sm)}
  .frm-link-row{display:flex;align-items:baseline;gap:8px;width:100%;min-width:0;border:0;border-bottom:1px solid var(--border);background:var(--surface);padding:9px 10px;font:inherit;font-size:12.5px;color:var(--text);text-align:left;cursor:pointer}
  .frm-link-row:last-child{border-bottom:0}
  .frm-link-row:hover:not([disabled]){background:var(--accent-light)}
  .frm-link-row b{flex:none;white-space:nowrap;color:var(--accent)}
  .frm-link-t{flex:1;min-width:0;overflow-wrap:anywhere}
  .frm-link-s{flex:none;font-size:11px;color:var(--text3);white-space:nowrap}
  .frm-link-row.on{cursor:default;opacity:.7}
  .frm-link-on{flex:none;font-size:10px;font-weight:700;padding:1px 7px;border-radius:20px;background:#dcfce7;color:#166534}
  .frm-link-empty{padding:12px 10px;font-size:12px;color:var(--text3)}
  .frm-newlink{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:0 0 12px;padding:10px 12px;border-radius:var(--radius);background:var(--accent-light);color:var(--text);font-size:12.5px;line-height:1.45;overflow-wrap:anywhere}
  .frm-newlink>span{flex:1 1 220px;min-width:0}
  .frm-newlink .ic{flex:none;color:var(--accent)}
  .frm-linked-list{display:flex;flex-wrap:wrap;gap:6px;min-width:0}
  .frm-linked{display:inline-flex;align-items:center;gap:6px;max-width:100%;min-width:0;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);padding:5px 9px;font:inherit;font-size:12px;color:var(--text);cursor:pointer;text-align:left}
  .frm-linked:hover{border-color:var(--accent)}
  .frm-linked-n{font-weight:700;flex:none;max-width:22ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-linked-t{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text2)}
  .frm-linked .frm-chip{flex:none}
  .frm-linked-none{font-size:12px;color:var(--text3)}
  .issue-forms{margin:2px 0 6px}
  .boq-forms{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 10px;min-width:0}
  .boq-forms-l{font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text2)}
  .boq-forms .frm-linked-list{flex:0 1 auto}
  @media(max-width:600px){.frm-link-add{margin-left:0;min-height:40px}.frm-link-go{padding-top:7px;padding-bottom:7px}.frm-link-go span{max-width:16ch}.frm-link-row{padding:12px 10px}.frm-link-day .btn{min-height:44px}.frm-linked{padding:8px 10px}}
  .frm-sched{display:inline-block;margin-left:6px;font-size:10px;font-weight:700;padding:2px 7px;border-radius:20px;background:var(--accent-light);color:var(--accent);vertical-align:middle;white-space:nowrap;font-variant-numeric:tabular-nums}
  .frm-sched.od{background:var(--red-light);color:var(--red)}
  /* a form with answers still on this device (offline filling, Tier 1.5) */
  .frm-off-chip{display:inline-block;margin-left:6px;font-size:10px;font-weight:700;padding:2px 7px;border-radius:20px;background:var(--amber-light);color:var(--amber);vertical-align:middle;white-space:nowrap}
  .frm-off-chip.clash{background:var(--red-light);color:var(--red)}
  .frm-off-banner{display:flex;gap:8px;align-items:flex-start;margin:0 0 12px;padding:10px 12px;border-radius:var(--radius);background:var(--amber-light);color:var(--text);font-size:12.5px;line-height:1.45;overflow-wrap:anywhere}
  .frm-off-banner .ic{flex:none;color:var(--amber);margin-top:1px}
  .frm-sched-card{text-decoration:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-sched-card:hover{text-decoration:underline}
  .frm-chip.st-sub{background:var(--accent-light);color:var(--accent)}
  .frm-chip.st-appr{background:var(--green-light);color:var(--green)}
  .frm-chip.st-rej{background:var(--red-light);color:var(--red)}
  .frm-siglock{display:flex;align-items:flex-start;gap:9px;margin:0 auto 12px;max-width:820px;
    padding:10px 14px;border-radius:9px;font-size:12.5px;line-height:1.5;
    background:var(--accent-light);color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 25%,transparent)}
  .frm-siglock.appr{background:var(--green-light);color:var(--green);border-color:color-mix(in srgb,var(--green) 25%,transparent)}
  .frm-siglock.rej{background:var(--red-light);color:var(--red);border-color:color-mix(in srgb,var(--red) 25%,transparent)}
  /* the client's own words, quoted verbatim — never paraphrased into a summary */
  .frm-rej-quote{display:block;margin-top:8px;padding:9px 12px;background:var(--surface);
    border-radius:8px;color:var(--text);font-size:13.5px;line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere}
  .frm-rej-next{display:block;margin-top:8px;font-size:12.5px;opacity:.85}
  .frm-siglock svg{flex-shrink:0;margin-top:1px}
  .frm-siglock b{font-weight:700}
  .frm-audit{max-width:820px;margin:14px auto 0}
  .frm-audit-bar{display:flex;align-items:center;gap:8px;width:100%;background:var(--surface);
    border:1px solid var(--border);border-radius:9px;padding:10px 14px;cursor:pointer;
    font-family:var(--font);font-size:12.5px;font-weight:700;color:var(--text2);text-align:left}
  .frm-audit-bar:hover{background:var(--surface2)}
  .frm-audit-n{background:var(--surface2);color:var(--text2);border-radius:20px;padding:1px 8px;font-size:11px;font-weight:800}
  .frm-audit-caret{margin-left:auto;color:var(--text3)}
  .frm-audit-list{border:1px solid var(--border);border-top:none;border-radius:0 0 9px 9px;background:var(--surface)}
  .frm-audit-row{padding:9px 14px;border-top:1px solid var(--border);font-size:12.5px}
  .frm-audit-row.approved .frm-audit-act{color:var(--green);font-weight:700}
  .frm-audit-row.rejected .frm-audit-act,.frm-audit-row.signatures_voided .frm-audit-act{color:var(--red);font-weight:700}
  .frm-audit-act{color:var(--text);overflow-wrap:anywhere}
  .frm-audit-who{color:var(--text3);font-size:11px;margin-top:2px;overflow-wrap:anywhere}
  /* ── sketch field ── */
  .frm-sk{margin-top:2px}
  .frm-sk-img{width:100%;max-width:520px;display:block;border:1px solid var(--border);border-radius:10px;
    background:#fff;object-fit:contain}
  .frm-sk-empty{width:100%;max-width:520px;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:7px;border:1.5px dashed var(--border-strong);border-radius:10px;background:var(--surface2);
    color:var(--text3);font-size:13px}
  .frm-sk-empty svg{width:26px;height:26px;opacity:.55}
  .frm-sk-acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:9px}

  /* ── sketch editor ── */
  /* Above the phone bottom-nav (290) so the nav cannot cut into the drawing
     area, but BELOW the shared text modal (#planModal, 2000) — the Text tool
     opens that modal from inside the editor, and at 2600 it opened behind the
     overlay and could not be clicked. */
  .sk-back{position:fixed;inset:0;background:rgba(15,23,42,.72);z-index:1200;display:flex;
    align-items:center;justify-content:center;padding:0}
  @media(min-width:701px){.sk-back{padding:22px}}
  .sk-shell{background:var(--surface);width:100%;height:100%;max-width:1100px;max-height:100%;
    display:flex;flex-direction:column;overflow:hidden;
    padding-bottom:env(safe-area-inset-bottom,0px)}
  @media(min-width:701px){.sk-shell{border-radius:16px;height:min(92vh,900px)}}
  .sk-head{display:flex;align-items:center;gap:9px;padding:12px 14px;border-bottom:1px solid var(--border);
    padding-top:calc(12px + env(safe-area-inset-top,0px))}
  @media(min-width:701px){.sk-head{padding-top:12px}}
  .sk-title{flex:1;min-width:0;font-size:15px;font-weight:800;letter-spacing:-.2px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sk-bar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:9px 12px;
    border-bottom:1px solid var(--border);background:var(--surface2)}
  .sk-group{display:flex;align-items:center;gap:4px;padding:3px;border:1px solid var(--border);
    border-radius:10px;background:var(--surface)}
  .sk-right{margin-left:auto}
  .sk-t{width:38px;height:38px;display:inline-flex;align-items:center;justify-content:center;
    border:none;background:transparent;border-radius:8px;color:var(--text2);cursor:pointer;padding:0}
  .sk-t svg{width:19px;height:19px}
  .sk-t:hover{background:var(--surface2)}
  .sk-t.on{background:var(--accent);color:#fff}
  .sk-t[disabled]{opacity:.35;cursor:default}
  .sk-t[disabled]:hover{background:transparent}
  .sk-t.sk-danger:hover{background:var(--red-light);color:var(--red)}
  .sk-c{width:30px;height:30px;border-radius:50%;border:2px solid var(--border);background:var(--c);
    cursor:pointer;padding:0}
  .sk-c.on{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 45%,transparent);border-color:var(--surface)}
  .sk-w{width:38px;height:38px;display:inline-flex;align-items:center;justify-content:center;border:none;
    background:transparent;border-radius:8px;cursor:pointer;padding:0}
  .sk-w i{display:block;width:20px;border-radius:99px;background:var(--text2)}
  .sk-w:hover{background:var(--surface2)}
  .sk-w.on{background:var(--accent)}
  .sk-w.on i{background:#fff}
  .sk-fill i{display:block;width:17px;height:17px;border:2px solid currentColor;border-radius:4px}
  .sk-fill.on i{background:currentColor;opacity:.55}
  .sk-stage{flex:1;min-height:220px;display:flex;align-items:center;justify-content:center;
    padding:12px;background:var(--surface2);overflow:hidden}
  .sk-stage canvas{background:#fff;border:1px solid var(--border);border-radius:8px;
    box-shadow:var(--shadow-xs);touch-action:none;-webkit-user-select:none;user-select:none;cursor:crosshair}
  .sk-hint{padding:8px 14px;font-size:12.5px;color:var(--text3);border-top:1px solid var(--border);
    text-align:center;min-height:34px}
  @media(max-width:700px){
    /* every tool is a real target on a phone (HIG 44pt) */
    .sk-t,.sk-w{width:44px;height:44px}
    .sk-c{width:34px;height:34px}
    /* Wrap onto two or three rows rather than scroll sideways: a horizontal
       scroller pushes the COLOUR swatches off-screen, and colour is the first
       thing anyone reaches for. The canvas is width-limited on a phone anyway,
       so the rows cost no drawing area. */
    .sk-bar{gap:5px;padding:8px 10px;flex-wrap:wrap;justify-content:center}
    .sk-group{flex-shrink:0}
    .sk-right{margin-left:0}
    .sk-hint{display:none}
  }
  .frm-pdf-opt{display:flex;align-items:flex-start;gap:10px;border:1px solid var(--border);border-radius:10px;
    padding:11px 13px;cursor:pointer;text-transform:none;margin:0;font-weight:400;letter-spacing:normal;
    color:var(--text);font-size:13.5px;line-height:1.45}
  .frm-pdf-opt:hover{background:var(--surface2)}
  .frm-pdf-opt input{margin-top:2px;flex-shrink:0;width:17px;height:17px}
  .frm-pdf-opt .sub{font-size:12px;color:var(--text3)}
  .frm-send-note{font-size:12.5px;color:var(--text2);line-height:1.55;background:var(--surface2);
    border:1px solid var(--border);border-radius:9px;padding:10px 12px;margin-bottom:14px}
  .frm-send-lbl{display:block;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
    color:var(--text3);margin:0 0 6px}
  .frm-send-fields{display:flex;flex-direction:column;gap:7px;margin-bottom:14px}
  /* Scoped under .frm-send-fields so the generic `.md label` rule (display:block,
     uppercase) cannot flatten these flex rows — Known Mistake #7. */
  .frm-send-fields .frm-send-f{display:flex;align-items:flex-start;gap:10px;border:1px solid var(--border);
    border-radius:10px;padding:10px 12px;cursor:pointer;text-transform:none;margin:0;font-weight:400;
    letter-spacing:normal;color:var(--text);font-size:13.5px;line-height:1.45}
  .frm-send-fields .frm-send-f:hover{background:var(--surface2)}
  .frm-send-fields .frm-send-f.done{opacity:.6;cursor:default}
  .frm-send-fields .frm-send-f input{margin-top:2px;flex-shrink:0;width:17px;height:17px}
  .frm-send-fields .frm-send-f .sub{font-size:12px;color:var(--text3)}
  .frm-send-row{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap}
  .frm-send-row .frm-send-who{flex:1 1 180px;min-width:0}
  .frm-send-lbl .opt{font-weight:500;color:var(--text3);text-transform:none;letter-spacing:normal}
  .frm-send-ok.warn{color:var(--amber);background:var(--amber-light)}
  .frm-send-item .l .frm-send-ml{margin-left:6px}
  .frm-stg-who{display:block;font-size:12px;color:var(--text2);margin-top:2px;overflow-wrap:anywhere}
  .frm-stg-who:empty{display:none}
  /* dictation + an English copy (wfVoice) */
  .frm-langbar{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;margin:0 0 10px;font-size:12px;color:var(--text2)}
  .frm-langbar label{display:inline-flex;align-items:center;font-weight:700;color:var(--text2);margin:0}
  .frm-langbar select{width:auto;max-width:100%;min-width:0;padding:4px 8px;font-size:12px}
  .frm-langnote{flex:1 1 220px;min-width:0;color:var(--text3);overflow-wrap:anywhere}
  .frm-vin{display:flex;align-items:flex-start;gap:6px;min-width:0}
  .frm-vin>input,.frm-vin>textarea,.frm-vin>.tapval{flex:1 1 auto;min-width:0}
  .frm-mic{flex:0 0 auto;width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text2);cursor:pointer;padding:0}
  .frm-mic .ic{width:16px;height:16px;margin:0}
  .frm-mic:hover{border-color:var(--accent);color:var(--accent)}
  .frm-mic.recording{border-color:#e53;color:#e53;animation:mic-pulse 1s ease-in-out infinite}
  .frm-tren{font-size:12px;color:var(--text2);margin-top:4px;white-space:pre-wrap;overflow-wrap:anywhere}
  .frm-tren:empty{display:none}
  .frm-tren b{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);margin-right:6px}
  .frm-trq{font-size:12px;color:var(--accent);font-style:italic;margin:-2px 0 5px;overflow-wrap:anywhere}
  .frm-trq:empty{display:none}
  .frm-f-help+.frm-trq{margin:2px 0 0}
  @media (max-width:600px){.frm-mic{width:44px;height:44px}}
  .frm-mail-md{max-width:520px}
  /* a due date on one form (item 20) */
  .frm-due-row{display:flex;align-items:center;gap:6px}
  .frm-due-row input{flex:1 1 auto;min-width:0}
  .frm-due-x{flex:0 0 auto;width:36px;height:36px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text2);font-size:18px;line-height:1;cursor:pointer}
  .frm-due-st{font-size:11.5px;color:var(--text3);margin-top:4px;min-height:14px}
  .frm-due-st.od{color:var(--red,#dc2626);font-weight:700}
  .frm-due-ro{font-size:13px;padding:8px 0}
  @media(max-width:600px){.frm-due-x{width:44px;height:44px}}
  /* the ISO starter library (item 17) — rows are <label>s inside .md (Known Mistake #7) */
  .frm-start-md{max-width:620px}
  .frm-start-list{margin:6px 0 2px}
  .frm-start-std{font-size:11px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--text2);margin:14px 0 4px}
  .md .frm-start-row{display:flex;align-items:flex-start;gap:10px;margin:0;padding:9px 4px;border-bottom:1px solid var(--border);text-transform:none;letter-spacing:normal;font-weight:400;color:var(--text);cursor:pointer;min-height:44px;box-sizing:border-box}
  .md .frm-start-row input{flex:0 0 auto;width:18px;height:18px;margin:2px 0 0}
  .md .frm-start-row.here{cursor:default;opacity:.6}
  .frm-start-txt{flex:1 1 auto;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px}
  .frm-start-nm{font-weight:700;font-size:13px;overflow-wrap:anywhere}
  .frm-start-cl{font-size:11px;color:var(--text3);font-variant-numeric:tabular-nums}
  .frm-start-here{font-size:10px;font-weight:700;color:var(--text2);background:var(--surface2);border-radius:10px;padding:1px 7px}
  .frm-start-ds{flex:1 0 100%;font-size:12px;color:var(--text2);line-height:1.4;overflow-wrap:anywhere}
  .frm-start-ds i{color:var(--text3);font-style:normal;white-space:nowrap}
  /* who may start a form (item 16) — the rows are <label>s inside .md, so they
     out-specify `.md label` and reset what it leaks (Known Mistake #7) */
  .frm-fill-md{max-width:480px}
  .md .frm-fill-opt,.md .frm-fill-role{display:flex;align-items:flex-start;gap:10px;margin:0;padding:8px 2px;text-transform:none;letter-spacing:normal;font-weight:400;font-size:13px;color:var(--text);cursor:pointer;min-height:44px;box-sizing:border-box}
  .md .frm-fill-opt input,.md .frm-fill-role input{flex:0 0 auto;width:18px;height:18px;margin:1px 0 0}
  .md .frm-fill-opt span,.md .frm-fill-role span{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
  .frm-fill-roles{margin:2px 0 4px 28px;padding:4px 10px;border:1px solid var(--border);border-radius:8px;max-height:260px;overflow-y:auto}
  .frm-fill-roles.off{opacity:.5}
  .frm-fill-none{font-size:12px;color:var(--text3);padding:8px 0}
  .frm-fill-chip{max-width:100%;min-width:0;display:inline-flex;align-items:center}
  .frm-fill-cn{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .btn.frm-fill-no{opacity:.55;cursor:not-allowed}
  .frm-mail-in{min-height:96px;resize:vertical;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:13px}
  .frm-send-note.bad{color:var(--red)}
  .frm-mail-chip{display:inline-flex;align-items:center}
  .frm-send-out{display:none}
  .frm-send-out.show{display:block;margin-top:14px}
  .frm-send-ok{display:flex;align-items:flex-start;gap:8px;font-size:13px;color:var(--green);
    background:var(--green-light);border-radius:9px;padding:10px 12px;line-height:1.5}
  .frm-send-ok svg{flex-shrink:0;margin-top:1px}
  /* the label is free text a user pastes in — it can be one long unbroken
     string (an email address, a reference), so it has to be breakable */
  .frm-send-ok span{min-width:0;overflow-wrap:anywhere}
  .frm-send-link{display:flex;gap:8px;margin-top:9px;align-items:center}
  .frm-send-link input{flex:1;min-width:0;font-size:12.5px;font-family:ui-monospace,Menlo,Consolas,monospace}
  .frm-send-list{display:flex;flex-direction:column;gap:7px;max-height:230px;overflow-y:auto}
  .frm-send-item{display:flex;gap:10px;align-items:center;border:1px solid var(--border);border-radius:10px;
    padding:9px 12px;font-size:13px}
  .frm-send-item .l{flex:1;min-width:0}
  .frm-send-item .l b{font-weight:700;overflow-wrap:anywhere}
  .frm-send-item .sub{font-size:11.5px;color:var(--text3);margin-top:1px}
  .frm-send-item .r{display:flex;gap:6px;flex-shrink:0}
  .frm-send-st{font-size:9.5px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;
    border-radius:20px;padding:1px 7px;margin-left:6px;white-space:nowrap}
  .frm-send-st.live{background:var(--accent-light);color:var(--accent)}
  .frm-send-st.seen{background:var(--amber-light);color:var(--amber)}
  .frm-send-st.ok{background:var(--green-light);color:var(--green)}
  .frm-send-st.off{background:var(--surface2);color:var(--text3)}
  @media(max-width:600px){
    .frm-send-item{flex-wrap:wrap}
    .frm-send-item .r{width:100%}
    .frm-send-item .r .btn{flex:1;min-height:44px}
    .frm-send-fields .frm-send-f{min-height:44px;align-items:center}
  }
  .frm-audit-ext{background:var(--amber-light);color:var(--amber);border-radius:20px;padding:0 6px;font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.05em}
  .frm-tpl-acts{display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;padding-top:6px;border-top:1px solid var(--border)}
  .frm-reg-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
  .frm-reg-tbl th{background:var(--th-bg);color:var(--th-text);padding:9px 12px;text-align:left;font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;border-bottom:1px solid var(--border);white-space:nowrap}
  .frm-reg-tbl td{padding:9px 12px;border-bottom:1px solid var(--border);vertical-align:middle;overflow-wrap:anywhere}
  .frm-reg-tbl tbody tr{cursor:pointer}
  .frm-reg-tbl tbody tr:hover td{background:var(--accent-light)}
  .frm-colmenu{position:absolute;top:calc(100% + 6px);right:0;z-index:120;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:0 10px 28px rgba(15,23,42,.16);padding:8px;display:flex;flex-direction:column;gap:2px;min-width:140px}
  .frm-colmenu-it{display:flex;align-items:center;gap:9px;font-size:12.5px;font-weight:600;color:var(--text);padding:8px 10px;border-radius:7px;cursor:pointer;min-height:36px}
  .frm-colmenu-it:hover{background:var(--surface2)}
  .frm-colmenu-it input{accent-color:var(--accent);width:15px;height:15px}
  /* Builder */
  .frm-build{display:grid;grid-template-columns:210px 1fr;gap:14px;align-items:start}
  .frm-build.with-pv{grid-template-columns:210px minmax(0,1fr) minmax(300px,40%)}
  .frm-preview{position:sticky;top:70px;max-height:calc(100vh - 90px);overflow:auto;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);padding:12px}
  .frm-pv-title{font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text3);margin:0 0 8px 2px}
  .frm-pv-wrap{position:relative;overflow:hidden;border-radius:4px}
  #frmPvFrame,#frmPvoFrame{width:794px;border:none;transform-origin:0 0;background:#fff;box-shadow:0 2px 10px rgba(15,23,42,.18);display:block}
  @media(max-width:900px){.frm-build,.frm-build.with-pv{grid-template-columns:minmax(0,1fr)}.frm-preview{display:none}.frm-pv-tgl{display:none}}
  #frmPvO{position:fixed;inset:0;z-index:2500;background:rgba(15,23,42,.72);display:none;flex-direction:column}
  #frmPvO.open{display:flex}
  .frm-pvo-bar{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--surface);border-bottom:1px solid var(--border);flex-shrink:0}
  .frm-pvo-bar b{font-size:13px;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  @media(max-width:600px){.frm-pvo-bar{flex-wrap:wrap;gap:8px}.frm-pvo-bar b{flex-basis:100%}}
  .frm-pvo-body{flex:1;overflow:auto;padding:16px;-webkit-overflow-scrolling:touch}
  .frm-palette{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px;position:sticky;top:70px}
  .frm-palette button{display:flex;align-items:center;gap:7px;width:100%;text-align:left;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius-xs);padding:7px 10px;font-family:var(--font);font-size:12px;font-weight:600;color:var(--text2);cursor:pointer;margin-bottom:5px;transition:all .12s var(--ease)}
  .frm-palette button:hover{background:var(--accent-light);color:var(--accent);border-color:var(--accent)}
  /* one column (≤900px): a sticky palette rides down over the very field being
     edited — 800px of buttons on a phone. It stays put above the fields instead.
     After the base rule on purpose: same specificity, so order decides. */
  @media(max-width:900px){.frm-palette{position:static}}
  .frm-canvas{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:22px;max-width:820px;box-shadow:var(--shadow-sm)}
  .frm-fld{border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;margin-bottom:10px;background:var(--surface2);transition:border-color .12s var(--ease)}
  .frm-fld:hover{border-color:var(--accent)}
  .frm-fld-bar{display:flex;align-items:center;gap:8px}
  .frm-fld-grip{cursor:grab;color:var(--text-faint);font-size:14px;line-height:1;letter-spacing:-3px;padding:0 2px;flex-shrink:0;user-select:none;font-weight:900}
  .frm-fld-grip:active{cursor:grabbing}
  .frm-fld-grip:hover{color:var(--text2)}
  .frm-fld.frm-dragging{opacity:.45}
  .frm-fld.frm-drop-t{border-color:var(--accent);box-shadow:0 -2px 0 0 var(--accent) inset}
  .frm-fld-props .frm-fmt-chk{gap:5px}
  .frm-sec-chips{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:7px 12px 9px;border-top:1px dashed var(--border);background:var(--surface2)}
  .frm-sec-chips-lbl{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);margin-right:2px}
  .frm-sec-chip{font-size:11px;font-weight:600;border:1px solid var(--border-strong);background:var(--surface);color:var(--text2);border-radius:20px;padding:4px 11px;cursor:pointer;line-height:1;white-space:nowrap}
  .frm-sec-chip:hover{border-color:var(--accent);color:var(--accent)}
  .frm-sec-note{font-size:11px;color:var(--text3);line-height:1.4;min-width:0;overflow-wrap:anywhere}
  .frm-sec-note.warn{color:var(--amber);font-weight:600;display:inline-flex;align-items:center}
  .frm-sec-chip.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .frm-fld-props input[type=color]{width:34px;height:26px;border:1px solid var(--border-strong);border-radius:6px;padding:1px;background:var(--surface);cursor:pointer}
  .frm-fld-type{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);background:var(--surface);border:1px solid var(--border);border-radius:20px;padding:2px 8px;flex-shrink:0}
  .frm-fld-lbl{flex:1;border:none;background:transparent;font-family:var(--font);font-size:13px;font-weight:600;color:var(--text);outline:none;min-width:0}
  .frm-rich-ed{white-space:pre-wrap;word-break:break-word;padding:2px 4px;border-radius:6px;cursor:text}
  .frm-rich-ed:focus{background:var(--surface);box-shadow:inset 0 0 0 1px var(--border-strong)}
  .frm-rich-ed:empty:before{content:attr(data-ph);color:var(--text3);font-weight:400}
  .frm-rich-ed br{line-height:1}
  .frm-richbar{display:inline-flex;align-items:center;gap:4px}
  .frm-rbtn{width:26px;height:26px;border:1px solid var(--border-strong);background:var(--surface);border-radius:6px;cursor:pointer;color:var(--text);font-size:12px;line-height:1;display:inline-flex;align-items:center;justify-content:center}
  .frm-rbtn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
  .frm-rcol{display:inline-flex;align-items:center;gap:3px;font-weight:800;color:var(--text2)}
  .frm-rcol input[type=color]{width:26px;height:26px}
  .frm-rhint{font-size:11px;color:var(--text3);flex:1;min-width:140px}
  .frm-fld-btn{width:24px;height:24px;border:1px solid var(--border-strong);background:var(--surface);border-radius:6px;cursor:pointer;color:var(--text2);font-size:11px;line-height:1;flex-shrink:0}
  .frm-fld-btn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
  .frm-fld-btn.del:hover{background:var(--red);border-color:var(--red)}
  .frm-fld-props{display:flex;gap:12px;flex-wrap:wrap;margin-top:8px;align-items:center}
  .frm-fld-props label{font-size:11px;color:var(--text2);display:inline-flex;align-items:center;gap:5px}
  .frm-fld-props input[type=text],.frm-fld-props textarea,.frm-fld-props select{border:1px solid var(--border-strong);border-radius:6px;padding:5px 8px;font-family:var(--font);font-size:11px;color:var(--text)}
  /* Table column editor. One shared track list for the header and every row,
     so each setting sits under the word that names it. Narrower than 600px
     (a phone, or the builder beside the live preview) the header goes and
     every cell shows its own caption instead — see the container rule. */
  .frm-cols{container-type:inline-size;margin-top:4px}
  .frm-col-head,.frm-col-row{display:grid;grid-template-columns:20px minmax(0,1.7fr) minmax(0,1fr) minmax(0,1fr) 74px 82px 88px 26px;gap:6px;align-items:center}
  .frm-col-head{font-size:9.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--text3);padding:0 0 4px;border-bottom:1px solid var(--border);margin-bottom:6px}
  .frm-col-head span{cursor:help;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .frm-col-head span:empty{cursor:default}
  .frm-col-row{margin-bottom:6px}
  .frm-col-row>label{display:flex;flex-direction:column;align-items:stretch;gap:2px;min-width:0;font-size:11px;color:var(--text2)}
  .frm-col-row>label.frm-col-chk{flex-direction:row;align-items:center}
  .frm-col-row input[type=text],.frm-col-row input[type=number],.frm-col-row select{width:100%;min-width:0;border:1px solid var(--border-strong);border-radius:6px;padding:5px 7px;font-family:var(--font);font-size:11px;color:var(--text);background:var(--surface)}
  .frm-col-cap{display:none;font-size:9.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--text3)}
  .frm-col-chk{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--text2);cursor:pointer;user-select:none;white-space:nowrap}
  .frm-col-chk input{margin:0;flex-shrink:0}
  .frm-col-na{color:var(--text3);font-size:12px;padding-left:4px;cursor:help}
  /* the % sits beside the box, in the flow: no positioned child, so nothing
     here can paint over the builder's sticky palette when the page scrolls */
  .frm-col-pct{display:flex;align-items:center;gap:3px}
  .frm-col-pct i{font-style:normal;font-size:10.5px;color:var(--text3);flex-shrink:0}
  .frm-col-na-why{display:none}
  .frm-col-mv{display:flex;flex-direction:column;gap:1px}
  .frm-col-mv button{border:none;background:none;color:var(--text3);font-size:8px;line-height:1;padding:2px 3px;cursor:pointer;border-radius:3px}
  .frm-col-mv button:hover:not(:disabled){background:var(--surface2);color:var(--accent)}
  .frm-col-mv button:disabled{opacity:.25;cursor:default}
  @media(pointer:coarse){.frm-col-mv button{font-size:11px;padding:7px 5px}}
  .frm-col-row .c-del:disabled{opacity:.35;cursor:not-allowed}
  .frm-col-row .c-span{grid-column:4/7;display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
  .frm-col-spec select{width:auto!important;flex-shrink:0}
  .frm-col-row .c-sub{grid-column:2/8}
  .frm-col-row .frm-act-core.c-span{grid-column:3/8}
  .frm-col-row .c-req{grid-column:7}
  .frm-col-row .c-del{grid-column:8;grid-row:1}
  .frm-col-foot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:4px}
  .frm-col-key{font-size:10.5px;color:var(--text3);flex:1;min-width:200px;line-height:1.45}
  .frm-col-key b{color:var(--text2);font-weight:700}
  @container (max-width:600px){
    .frm-col-head{display:none}
    .frm-col-row{grid-template-columns:20px repeat(3,minmax(0,1fr)) 26px;row-gap:7px;padding:8px 0 10px;margin:0;border-bottom:1px solid var(--border)}
    .frm-col-cap{display:block}
    .frm-col-na-why{display:inline;font-size:11px}
    .frm-col-row .c-mv{grid-column:1;grid-row:1/span 3;align-self:start}
    .frm-col-row .c-name{grid-column:2/5;grid-row:1}
    .frm-col-row .c-del{grid-column:5;grid-row:1;align-self:end}
    .frm-col-row .c-type{grid-column:2/4;grid-row:2}
    .frm-col-row .c-w{grid-column:4;grid-row:2}
    .frm-col-row .c-total{grid-column:2;grid-row:3}
    .frm-col-row .c-lock{grid-column:3;grid-row:3;align-self:end;min-height:30px}
    .frm-col-row .c-req{grid-column:4;grid-row:3;align-self:end;min-height:30px;display:flex;align-items:center}
    .frm-col-row .c-span{grid-column:2/4;grid-row:3}
    .frm-col-row .c-sub{grid-column:2/5;grid-row:4}
    .frm-col-row .frm-act-core.c-span{grid-column:2/5;grid-row:2}
    .frm-cols+.frm-col-foot{margin-top:8px}
  }
  /* Preset (predefined) table rows builder */
  .frm-preset-wrap{margin-top:4px;padding-top:4px}
  .frm-preset-hint{font-weight:400;color:var(--text3);font-size:10px}
  .frm-preset-grid{display:grid;gap:5px 6px;align-items:center;margin-top:6px}
  .frm-preset-hd{font-size:9.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--text3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-preset-cell{border:1px solid var(--border-strong);border-radius:6px;padding:5px 8px;font-size:11px;font-family:var(--font);color:var(--text);background:var(--surface);min-width:0;width:100%}
  /* a calculated column has nothing to preset — it is worked out from the row */
  .frm-preset-cell.frm-preset-calc{display:flex;align-items:center;justify-content:center;border-style:dashed;background:var(--surface2,#f8fafc);color:var(--text3);font-style:italic;cursor:default}
  .frm-preset-chk{display:flex;align-items:center;justify-content:center;background:none;border:none}
  .frm-preset-del{align-self:center}
  /* Locked (read-only) table cell in the fill/PDF view — reads like printed text */
  .frm-tbl td.frm-tbl-fixed{padding:8px 9px;font-size:12px;color:var(--text);background:var(--surface2,#f8fafc);font-weight:500}
  /* ── calculated fields ──────────────────────────────────────────────────
     A derived value is never an input, so it must not look like one: no
     border, no caret, right-aligned tabular figures so a column of them lines
     up. It reads as an answer the form worked out, which is what it is. */
  .frm-calc{display:flex;align-items:center;justify-content:flex-end;min-height:38px;padding:8px 11px;font-size:14px;font-weight:700;color:var(--text);background:var(--surface2,#f8fafc);border:1px solid var(--border);border-radius:8px;font-variant-numeric:tabular-nums}
  .frm-calc.bad{color:#b91c1c;font-weight:600}
  .frm-tbl td.frm-tbl-calc{padding:8px 9px;font-size:12px;font-weight:700;text-align:right;color:var(--text);background:var(--surface2,#f8fafc);font-variant-numeric:tabular-nums}
  .frm-tbl td.frm-tbl-calc.bad{color:#b91c1c;font-weight:600}
  .frm-tbl tfoot tr.frm-tot td{padding:8px 9px;font-size:12px;font-weight:700;background:var(--surface2,#f8fafc);border-top:2px solid var(--accent);color:var(--text)}
  .frm-tbl tfoot tr.frm-tot td.frm-tot-c{text-align:right;font-variant-numeric:tabular-nums}
  .frm-tbl tfoot tr.frm-tot td.frm-tot-c.bad{color:#b91c1c}
  .frm-tbl-card.frm-tbl-card-tot .frm-tbl-card-title{font-weight:700}
  /* the builder's formula editor */
  .frm-fx-row{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
  .frm-fx-in{flex:1;min-width:180px;border:1px solid var(--border-strong);border-radius:6px;padding:6px 9px;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:var(--surface)}
  .frm-fx-pick{border:1px solid var(--border-strong);border-radius:6px;padding:5px;font-size:11px;max-width:190px;background:var(--surface)}
  .frm-fx-st{margin-top:6px;font-size:11px;color:var(--text3)}
  .frm-fx-st.bad{color:#b91c1c;font-weight:600}
  .frm-fx-help{margin-top:5px;font-size:10.5px;color:var(--text3);line-height:1.5}
  .frm-fx-help code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:var(--surface2,#f1f5f9);border-radius:4px;padding:1px 4px}
  /* Fill */
  .frm-paper{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:26px 30px;max-width:820px;box-shadow:var(--shadow-sm);margin:0 auto;display:flex;flex-wrap:wrap;column-gap:16px;align-items:flex-start}
  @media(max-width:600px){.frm-paper{padding:18px 16px}}
  .frm-f{margin-bottom:16px;flex:0 0 100%;min-width:0}
  .frm-f.half{flex:0 0 calc(50% - 8px)}
  .frm-paper>.frm-heading,.frm-paper>.frm-info,.frm-paper>hr,.frm-paper>div[style*="clear"]{flex:0 0 100%}
  @media(max-width:600px){.frm-f.half{flex-basis:100%}}
  .frm-f-lbl{display:block;font-size:12px;font-weight:700;color:var(--text);margin-bottom:5px;overflow-wrap:anywhere}
  .frm-f-lbl .req{color:var(--red)}
  .frm-f-help{font-size:11px;color:var(--text3);margin-top:3px}
  .frm-f input[type=text],.frm-f input[type=number],.frm-f input[type=date],.frm-f input[type=time],.frm-f select,.frm-f textarea{width:100%;max-width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:9px 11px;font-family:var(--font);font-size:13px;color:var(--text);background:var(--surface)}
  .frm-f input:focus,.frm-f select:focus,.frm-f textarea:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .frm-f input:disabled,.frm-f select:disabled,.frm-f textarea:disabled{background:var(--surface2);color:var(--text2)}
  /* Phone tap-to-edit stand-in for a Forms field: same box as the input/textarea it
     replaces (border/radius/padding), so the form keeps its exact look — the only
     change is that tapping opens the full-text modal instead of typing inline. */
  .frm-tap{border:1px solid var(--border-strong);border-radius:var(--radius-xs);background:var(--surface);font-size:12px;min-height:44px;padding:11px 12px}
  .frm-tap-area{min-height:70px;align-items:flex-start}
  /* .tapval's base look ellipsizes to ONE line at rest — right for a short
     single-line value (form title, a name) but wrong for anything that can
     span multiple lines: a long/multi-line value must still be fully
     readable without tapping, closed-box growing only as tall as it needs
     (not a fixed min-height, so a one-word comment stays compact). */
  /* A wrapping tap-box turns overflow back on so a long value grows the box
     instead of being clipped — but `white-space:normal` alone cannot break an
     UNBROKEN run of characters, so without overflow-wrap it spills out of the
     box and scrolls the whole page sideways on a phone. */
  .frm-tap-wrap{white-space:normal;overflow:visible;text-overflow:clip;align-items:flex-start;line-height:1.4;overflow-wrap:anywhere}
  .frm-heading{font-size:14px;font-weight:800;color:var(--accent2);border-bottom:2px solid var(--accent-light);padding-bottom:6px;margin:22px 0 14px;text-transform:uppercase;letter-spacing:.04em;overflow-wrap:anywhere}
  .frm-info{font-size:12px;color:var(--text2);background:var(--surface2);border-left:3px solid var(--border-strong);border-radius:6px;padding:9px 12px;line-height:1.6}
  .frm-yesno{display:flex;gap:6px}
  .frm-yesno button{flex:1;max-width:110px;border:1px solid var(--border-strong);background:var(--surface);border-radius:var(--radius-xs);padding:8px 0;font-family:var(--font);font-size:12px;font-weight:700;color:var(--text2);cursor:pointer;transition:all .12s var(--ease)}
  .frm-yesno button.on-yes{background:var(--green);border-color:var(--green);color:#fff}
  .frm-yesno button.on-no{background:var(--red);border-color:var(--red);color:#fff}
  .frm-yesno button.on-na{background:var(--text3);border-color:var(--text3);color:#fff}
  .frm-yesno button:disabled{cursor:default;opacity:.75}
  /* max-width:110px is fine on desktop but 3×110px+2×6px gap=342px can exceed
     a narrow phone's available content width with zero slack — drop the cap
     so flex:1 divides whatever room actually exists instead of overflowing. */
  @media(max-width:600px){.frm-yesno button{max-width:none}}
  /* table-layout:fixed + a per-column <colgroup> (from frmColW, the SAME widths
     the PDF uses) is what makes the web table size like the printed sheet: the
     columns keep their proportions and the table fits its container instead of
     giving every column a flat 96px min-width. overflow-wrap:anywhere lets a
     locked cell break a run with no spaces, exactly as the print CSS does. */
  .frm-tbl{width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed}
  .frm-tbl th{background:var(--th-bg);color:var(--th-text);padding:7px 9px;text-align:left;font-size:9.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--border)}
  .frm-tbl td{border:1px solid var(--border);padding:0;vertical-align:middle;overflow-wrap:anywhere}
  /* The typed selectors are NOT redundant: `.frm-f input[type=number]` (0,2,1) sits
     above and BEATS a bare `.frm-tbl td input` (0,1,2), so a number or date cell was
     drawing the generic bordered field box — a rounded white card inset inside its own
     cell — while every text cell rendered flat and edge to edge. Known Mistake #7's
     cascade trap; restated at 0,2,2 so the table cell wins whatever the field rule says.
     The `:focus` rule below is also 0,2,2 and comes LATER, so it still takes the tint. */
  .frm-tbl td input,.frm-tbl td input[type=text],.frm-tbl td input[type=number],.frm-tbl td input[type=date],.frm-tbl td input[type=time],.frm-tbl td select,.frm-tbl td textarea{width:100%;box-sizing:border-box;border:none;border-radius:0;outline:none;font-family:var(--font);font-size:12px;padding:8px 9px;background:transparent;color:var(--text)}
  .frm-tbl td input:focus,.frm-tbl td select:focus,.frm-tbl td textarea:focus{background:var(--accent-light)}
  .frm-tbl td textarea{resize:vertical;line-height:1.4;display:block;box-sizing:border-box;min-height:38px;overflow:hidden}
  /* Desktop table text cells are a small auto-sized textarea, not a single-line
     input — a filled-in comment must read the same in the live digital form
     (what a reviewer signs off against) as it does in the printed PDF, where
     it wraps across multiple lines instead of hiding most of it off-screen. */
  /* Phone: a table field never renders as a <table> grid at all — see
     frmTableCardsHtml(). Apple HIG has no dense multi-column grid idiom for
     iPhone; a narrow column (any table-layout strategy) either overflows or
     squeezes each cell into an illegibly small box, and that shrinkage is
     exactly what a real checklist template hit (a Comments cell rendered as a
     tiny floating pill with no visible relationship to its row). Instead every
     row becomes a self-contained card: the locked/question column is the card
     title, and every editable column is its own full-width labeled field
     below it — generalizes to any column count/type, no width budget needed.
     Desktop/PDF keep the real grid untouched. */
  /* Phone, full form: a table wider than the screen keeps readable columns and
     scrolls sideways inside .frm-tbl-wrap (min-width + px colgroup set in
     app.js), with the first column pinned so a row never loses its name. A
     sticky cell in a collapsed-border table drops its own border as it moves,
     so the divider is a shadow. The photo tier spans the whole row and is
     left alone. */
  .frm-tbl-scroll{-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
  .frm-tbl-scroll .frm-tbl th{overflow-wrap:normal;word-break:normal;hyphens:none}
  .frm-tbl-scroll .frm-tbl tr:not(.frm-tbl-r2)>:first-child{position:sticky;left:0;z-index:1;background:var(--surface);box-shadow:inset -1px 0 0 var(--border-strong,#cbd5e1)}
  .frm-tbl-scroll .frm-tbl thead tr>:first-child{background:var(--th-bg);z-index:2}
  .frm-tbl-scroll .frm-tbl tr:not(.frm-tbl-r2)>td.frm-tbl-fixed:first-child,.frm-tbl-scroll .frm-tbl tr:not(.frm-tbl-r2)>td.frm-tbl-calc:first-child,.frm-tbl-scroll .frm-tbl tfoot tr>:first-child{background:var(--surface2,#f8fafc)}
  .frm-tbl-card-stat{flex-shrink:0;align-self:center;font-size:11px;font-weight:700;color:var(--accent);background:var(--accent-light);border-radius:999px;padding:3px 9px;max-width:45%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-tbl-card-stat[hidden]{display:none}
  .frm-tbl-cards{display:flex;flex-direction:column;gap:10px}
  .frm-tbl-cards-empty{font-size:12px;color:var(--text3);padding:4px 2px}
  .frm-tbl-card{border:1px solid var(--border);border-radius:10px;background:var(--surface);overflow:hidden}
  .frm-tbl-card-head{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;background:var(--surface2)}
  .frm-tbl-card-title{flex:1;font-size:14px;font-weight:700;color:var(--text);line-height:1.4;overflow-wrap:anywhere}
  .frm-tbl-card-ctx{padding:0 14px 10px;display:flex;flex-direction:column;gap:3px;background:var(--surface2)}
  .frm-tbl-card-ctxline{font-size:11.5px;color:var(--text3);overflow-wrap:anywhere}
  .frm-tbl-card-ctxline b{color:var(--text2);font-weight:600}
  .frm-tbl-card-body{padding:13px 14px;display:flex;flex-direction:column;gap:13px;border-top:1px solid var(--border)}
  .frm-tbl-card-field{min-width:0}
  .frm-tbl-card-field select,.frm-tbl-card-field input[type=date]{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:9px 11px;font-family:var(--font);color:var(--text);background:var(--surface)}
  .frm-tbl-card-chk{display:flex;align-items:center;gap:9px;cursor:pointer;font-size:13px;color:var(--text);font-weight:700}
  .frm-tbl-card-chk input{width:18px;height:18px;accent-color:var(--accent);flex-shrink:0}
  /* a repeating section: a block per item at every width (forms review, Tier 3.15) */
  .frm-rep .frm-tbl-card-head{border-left:3px solid var(--accent)}
  .frm-rep .frm-tbl-card-body{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr));gap:13px 16px}
  .frm-rep .frm-tbl-card-body>.frm-tbl-card-field:has(textarea){grid-column:1/-1}
  .frm-rep-ta,.frm-rep .frm-tbl-card-field input[type=number]{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:8px 10px;font:inherit;font-size:13px;color:var(--text);background:var(--surface);resize:none;overflow:hidden;min-height:38px;line-height:1.45}
  .frm-rep-add{margin-top:9px;max-width:100%;white-space:normal;text-align:left;overflow-wrap:anywhere}
  .frm-rep-chk{margin:4px 0 6px}
  .frm-rep-name{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;margin:0 0 10px}
  .frm-rep-name input{width:180px;max-width:100%}
  /* Sign-off stage banner. Four states, each answering "can I work on this
     section now, and if not, why?" — colour carries the state, the sentence
     carries the reason, so it is never colour alone. */
  .frm-stgbar{flex:1;text-align:center;font-size:12px;color:var(--text2);font-weight:600;overflow-wrap:anywhere}
  .frm-stg{display:flex;align-items:flex-start;gap:9px;flex-wrap:wrap;margin:22px 0 -4px;padding:10px 13px;
    border-radius:var(--radius);border:1px solid var(--border);background:var(--surface2);
    font-size:12px;line-height:1.55;color:var(--text2);overflow-wrap:anywhere}
  .frm-stg .ic{flex-shrink:0;margin-top:1px}
  .frm-stg span{min-width:0}
  .frm-stg b{color:var(--text)}
  .frm-stg-n{font-weight:800;font-size:11px;letter-spacing:.04em;text-transform:uppercase;flex-shrink:0}
  .frm-stg.done{background:var(--green-light);color:var(--green);border-color:color-mix(in srgb,var(--green) 25%,transparent)}
  .frm-stg.now{background:var(--accent-light);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 25%,transparent)}
  .frm-stg.wait{background:var(--surface2);color:var(--text3);border-color:var(--border-strong)}
  .frm-stg.warn{background:var(--amber-light);color:var(--amber);border-color:color-mix(in srgb,var(--amber) 25%,transparent)}
  .frm-stg.done b,.frm-stg.now b,.frm-stg.warn b,
  .frm-stg.done .frm-stg-n,.frm-stg.now .frm-stg-n,.frm-stg.warn .frm-stg-n{color:inherit}
  .frm-sig{border:1.5px dashed var(--border-strong);border-radius:var(--radius);padding:14px;text-align:center;background:var(--surface2)}
  .frm-sig.signed{border-style:solid;background:var(--surface);text-align:left;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
  .frm-sig img{height:64px;max-width:240px;object-fit:contain}
  .frm-sig-meta{font-size:11px;color:var(--text2);line-height:1.6;overflow-wrap:anywhere;min-width:0}
  .frm-sig-meta b{font-size:13px;color:var(--text)}
  /* Sign-off sheet — a register the phone is passed around to build */
  .frm-so{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);overflow:hidden}
  .frm-so-list{list-style:none;margin:0;padding:0}
  .frm-so-row{display:grid;grid-template-columns:28px minmax(0,1fr) minmax(0,180px) auto;align-items:center;gap:10px;padding:8px 12px;border-bottom:1px solid var(--border)}
  .frm-so-n{font-size:11px;font-weight:700;color:var(--text3);font-variant-numeric:tabular-nums;text-align:right}
  .frm-so-who{min-width:0;display:flex;flex-direction:column;gap:1px}
  .frm-so-who b{font-size:13px;color:var(--text);overflow-wrap:anywhere}
  .frm-so-who span{font-size:11px;color:var(--text3);font-variant-numeric:tabular-nums}
  .frm-so-img{display:block;height:44px;width:100%;object-fit:contain;object-position:left center;background:#fff;border-radius:6px;padding:2px 6px;box-sizing:border-box}
  .frm-so-del{border:0;background:none;color:var(--text3);font-size:14px;width:32px;height:32px;border-radius:8px;cursor:pointer}
  .frm-so-del:hover{background:var(--red-light);color:var(--red)}
  .frm-so-empty{padding:14px 12px;font-size:12px;color:var(--text3);border-bottom:1px solid var(--border)}
  .frm-so-add{display:flex;align-items:center;justify-content:center;width:calc(100% - 24px);margin:10px 12px;min-height:44px;font-size:14px}
  @media(max-width:600px){
    .frm-so-row{grid-template-columns:22px minmax(0,1fr) auto;grid-template-areas:"n who del" "n img img";row-gap:6px}
    .frm-so-n{grid-area:n;align-self:start;padding-top:2px}
    .frm-so-who{grid-area:who}
    .frm-so-img{grid-area:img;height:52px}
    .frm-so-del{grid-area:del;width:44px;height:44px}
  }
  #sigOverlay{position:fixed;inset:0;background:rgba(15,23,42,.6);backdrop-filter:blur(2px);z-index:3000;display:none;align-items:center;justify-content:center;padding:12px}
  #sigOverlay.open{display:flex}
  .sig-box{background:var(--surface);border-radius:var(--radius-lg);padding:18px;width:640px;max-width:98vw;box-shadow:var(--shadow-lg)}
  .sig-canvas-wrap{border:1.5px dashed var(--border-strong);border-radius:var(--radius-sm);position:relative;background:#fff;touch-action:none}
  .sig-canvas-wrap canvas{display:block;width:100%;height:240px;border-radius:var(--radius-sm)}
  .sig-line{position:absolute;left:8%;right:8%;bottom:46px;border-bottom:1px solid #cbd5e1;pointer-events:none}
  .frm-photo-grid{display:grid;grid-template-columns:repeat(var(--frm-per-row,3),1fr);gap:9px;margin-top:8px}
  @media(max-width:600px){.frm-photo-grid{grid-template-columns:repeat(3,1fr)}}
  /* Photos field: link-from-catalogue picker (mirrors registers.css .reg-pick*) */
  .frm-pick-search{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--border);border-radius:6px;font-family:var(--font);font-size:13px;margin:8px 0 0}
  .frm-pick-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:12px 0;max-height:46vh;overflow-y:auto}
  .frm-pick{position:relative;border-radius:6px;overflow:hidden;border:2px solid transparent;cursor:pointer;background:var(--surface2)}
  .frm-pick img{width:100%;aspect-ratio:1;object-fit:cover;display:block}
  .frm-pick.sel{border-color:var(--accent)}
  .frm-pick.sel::after{content:'\2713';position:absolute;top:4px;right:4px;background:var(--accent);color:#fff;width:20px;height:20px;border-radius:50%;font-size:12px;display:flex;align-items:center;justify-content:center;font-weight:700}
  .frm-pick.linked{opacity:0.45;cursor:default}
  .frm-pick.linked::after{content:'linked';position:absolute;bottom:4px;left:4px;right:4px;background:rgba(15,23,42,0.72);color:#fff;font-size:9px;text-align:center;border-radius:4px;padding:1px 0}
  @media(max-width:600px){.frm-pick-grid{grid-template-columns:repeat(3,1fr)}}
  .frm-photo{position:relative;aspect-ratio:1;border-radius:8px;overflow:hidden;border:1px solid var(--border);background:var(--surface2)}
  .frm-photo img{width:100%;height:100%;object-fit:cover}
  .frm-photo .pt-del{opacity:1}
  /* mark up a copy (item 19): top-left, the delete is top-right */
  .frm-photo .pt-mk{position:absolute;top:5px;left:5px;background:rgba(0,0,0,0.6);color:#fff;border:none;border-radius:50%;width:24px;height:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
  .frm-photo .pt-mk .ic{width:13px;height:13px}
  @media(max-width:600px){.frm-photo .pt-mk,.frm-photo .pt-del{width:32px;height:32px}}
  /* A table's Photos column: a gallery tier UNDER each line, so a photo belongs
     to the item it shows. The top row carries the fields; the second row grows
     with its photos. The two rows read as one item: no rule between them, and a
     heavier rule under the pair. */
  .frm-tbl.frm-tbl-2t tr.frm-tbl-r1>td{border-bottom:none}
  .frm-tbl.frm-tbl-2t tr.frm-tbl-r2>td{border-top:none;border-bottom:2px solid var(--border-strong,#cbd5e1);padding:6px 9px 9px;background:var(--surface);vertical-align:top}
  .frm-rph{display:flex;flex-direction:column;gap:7px;min-width:0}
  .frm-rph-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
  .frm-rph-lbl{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted,#64748b);min-width:0;overflow-wrap:anywhere}
  .frm-rph-lbl svg{width:13px;height:13px;flex:none}
  .frm-rph-n{font-size:10.5px;font-weight:700;color:var(--accent);background:var(--accent-light);border-radius:999px;padding:1px 7px;font-variant-numeric:tabular-nums}
  .frm-rph-acts{display:inline-flex;gap:6px;margin-left:auto;flex-wrap:wrap}
  .frm-rph-btn{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 10px;border:1px solid var(--border);border-radius:7px;background:var(--surface);color:var(--text);font-family:var(--font);font-size:11.5px;font-weight:600;cursor:pointer;white-space:nowrap}
  .frm-rph-btn:hover{border-color:var(--accent);color:var(--accent)}
  .frm-rph-btn:focus-within,.frm-rph-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  .frm-rph-btn svg{width:13px;height:13px}
  .frm-rph-grid{display:grid;grid-template-columns:repeat(var(--rph-per-row,4),minmax(0,1fr));gap:8px;max-width:calc(var(--rph-per-row,4) * 190px)}
  .frm-rph-grid .frm-photo{border-radius:7px}
  .frm-rph-none{font-size:11.5px;color:var(--text-muted,#64748b)}
  .frm-tbl-card .frm-rph{padding:10px 14px 12px;border-top:1px solid var(--border)}
  .frm-col-phnote{font-size:11px;color:var(--text-muted,#64748b);font-style:italic;align-self:center}
  /* ── Action list: a form's actions, raised as project tasks (2026-10-10) ──
     One line per action, laid out by the width the FORM actually has rather than
     the window's: a container query, so the same list reads as a grid on the
     desktop paper, as stacked fields on a phone's "Fit to phone" view, and as a
     grid again in its "Full form" view. Every control is a real field box —
     a list of things people will be held to reads better as a form than as a
     spreadsheet, and it keeps a 44px target on a phone. */
  .frm-act-note{display:flex;gap:9px;align-items:flex-start;background:var(--accent-light);color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 22%,transparent);border-radius:8px;padding:9px 12px;font-size:11.5px;line-height:1.55;margin:0 0 11px}
  .frm-act-note .ic{flex-shrink:0;width:15px;height:15px;margin-top:1px}
  .frm-act-note b{font-weight:800}
  .frm-col-phnote.frm-act-core{font-style:normal;font-weight:600;color:var(--accent)}
  .frm-acts{container-type:inline-size}
  .frm-act-sum{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--text2);background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius-xs);padding:7px 11px;margin-bottom:8px;line-height:1.45;overflow-wrap:anywhere}
  .frm-act-sum .ic{width:15px;height:15px;flex-shrink:0;color:var(--text3)}
  .frm-act-sum b{color:var(--text);font-weight:800}
  .frm-act-sum.ok{background:var(--green-light);color:var(--green);border-color:color-mix(in srgb,var(--green) 25%,transparent)}
  .frm-act-sum.ok .ic,.frm-act-sum.ok b{color:var(--green)}
  .frm-act-sum.od{border-color:color-mix(in srgb,var(--red) 30%,transparent)}
  .frm-act-sod{color:var(--red);font-weight:700}
  .frm-act-list{border:1px solid var(--border);border-radius:var(--radius-xs);background:var(--surface);overflow:hidden}
  .frm-act-hd,.frm-act{display:grid;grid-template-columns:30px minmax(0,1fr) 32px;align-items:start}
  .frm-act-hd{background:var(--th-bg);color:var(--th-text);font-size:9.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase}
  .frm-act-hd>span{padding:7px 0;text-align:center}
  .frm-act-hd .frm-act-cells>span{padding:7px 6px 7px 16px;min-width:0;overflow-wrap:anywhere}
  .frm-act-cells{display:grid;grid-template-columns:var(--act-cols,minmax(0,2.4fr) minmax(0,1.3fr) minmax(118px,.9fr));min-width:0}
  .frm-act{border-top:1px solid var(--border)}
  .frm-act-hd+.frm-act{border-top:none}
  .frm-act-n{font-size:11px;font-weight:800;color:var(--text3);text-align:center;padding:14px 0 0;font-variant-numeric:tabular-nums}
  .frm-act.raised.s-closed .frm-act-n{color:var(--green)}
  .frm-act-main{min-width:0;display:flex;flex-direction:column;gap:7px;padding:0 0 9px}
  .frm-act-c{min-width:0;padding:5px 6px 0}
  .frm-act-cl{display:none}
  /* the author's own columns sit under the three a task is made of, so each
     carries its label (the header names only those three) */
  .frm-act-x .frm-act-cl{display:block;font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);margin:5px 0 4px 1px;overflow-wrap:anywhere}
  .frm-acts .frm-act-c textarea,.frm-acts .frm-act-c input[type=text],.frm-acts .frm-act-c input[type=number],.frm-acts .frm-act-c input[type=date],.frm-acts .frm-act-c select{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:6px;background:var(--surface);padding:7px 9px;font-family:var(--font);font-size:12.5px;color:var(--text);min-height:36px}
  .frm-acts .frm-act-c textarea{resize:none;overflow:hidden;line-height:1.45;display:block}
  .frm-acts .frm-act-c textarea:focus,.frm-acts .frm-act-c input:focus,.frm-acts .frm-act-c select:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .frm-act-chk{display:flex;align-items:center;min-height:36px;padding-left:9px}
  .frm-act-chk input{width:17px;height:17px;accent-color:var(--accent)}
  .frm-act-ro{padding:8px 10px;font-size:12.5px;color:var(--text);line-height:1.45;overflow-wrap:anywhere;white-space:pre-wrap;min-height:36px;box-sizing:border-box}
  .frm-act-was{display:block;font-size:10.5px;color:var(--text3);white-space:normal}
  .frm-act-nil{color:var(--text-faint,#94a3b8)}
  .frm-act-del{margin:14px auto 0}
  .frm-act-main>.frm-rph{padding:0 7px}
  .frm-act-st{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:0 9px;min-width:0}
  .frm-act-chip{font-size:9.5px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:3px 8px;border-radius:20px;background:var(--surface2);color:var(--text2);white-space:nowrap}
  .frm-act-chip.s-open{background:var(--accent-light);color:var(--accent)}
  .frm-act-chip.s-ongoing{background:var(--amber-light);color:var(--amber)}
  .frm-act-chip.s-closed{background:var(--green-light);color:var(--green)}
  .frm-act-chip.s-od{background:var(--red-light);color:var(--red)}
  .frm-act-chip.s-wait,.frm-act-chip.s-gone{background:transparent;color:var(--text3);border:1px dashed var(--border-strong)}
  .frm-act-tk{font-size:11px;color:var(--text3);min-width:0;overflow-wrap:anywhere}
  .frm-act-open{margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:700;color:var(--accent);text-decoration:none;padding:5px 9px;border-radius:6px;white-space:nowrap}
  .frm-act-open:hover{background:var(--accent-light)}
  .frm-act-open .ic{width:13px;height:13px}
  .frm-act-cobtn{margin-left:auto;display:inline-flex;align-items:center;gap:5px;font:inherit;font-size:11.5px;font-weight:700;color:var(--green);background:var(--green-light);border:1px solid color-mix(in srgb,var(--green) 30%,transparent);padding:5px 10px;border-radius:6px;cursor:pointer;white-space:nowrap}
  .frm-act-cobtn:hover{border-color:var(--green)}
  .frm-act-cobtn .ic{width:13px;height:13px}
  .frm-act-cobtn+.frm-act-open{margin-left:0}
  .frm-co-md{width:520px;max-width:100%}
  .frm-co-what{font-weight:700;font-size:14px;color:var(--text);margin:-4px 0 6px;overflow-wrap:anywhere}
  .frm-co-opt{font-weight:400;text-transform:none;letter-spacing:0;color:var(--text3)}
  .frm-co-phh{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:12px}
  .frm-co-add{position:relative;overflow:hidden;cursor:pointer}
  .frm-co-add input{position:absolute;inset:0;opacity:0;cursor:pointer}
  .frm-co-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(118px,1fr));gap:10px;margin-top:8px}
  .frm-co-cell{position:relative;margin:0;min-width:0}
  .frm-co-cell img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:7px;border:1px solid var(--border);display:block}
  .frm-co-rm{position:absolute;top:5px;right:5px;width:28px;height:28px;border:0;border-radius:50%;background:rgba(15,23,42,.62);color:#fff;font-size:16px;line-height:1;cursor:pointer}
  .frm-co-none{font-size:12px;color:var(--text3)}
  .frm-act-co{margin:0 9px;border:1px solid color-mix(in srgb,var(--green) 25%,transparent);background:var(--green-light);border-radius:8px;padding:8px 10px;display:flex;flex-direction:column;gap:7px;min-width:0}
  .frm-act-co-h{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--green);font-weight:600;flex-wrap:wrap}
  .frm-act-co-h .ic{width:14px;height:14px;flex-shrink:0}
  .frm-act-co-h b{font-weight:800}
  .frm-act-co-n{font-size:12.5px;color:var(--text);white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.5}
  .frm-act-co-ph{display:flex;flex-direction:column;gap:5px;min-width:0}
  .frm-act-main>.frm-act-co-ph{padding:0 9px}
  .frm-act-co-ph img{cursor:zoom-in}
  .frm-act.miss{background:color-mix(in srgb,var(--amber-light) 55%,transparent)}
  /* ── A failing answer raises an action (forms roadmap, Tier 1 item 1) ──
     The answer reads red, and the strip under the question carries the tag,
     the actions raised from it with their live status, and Raise action. */
  .frm-yesno button.on-fail{background:var(--red);border-color:var(--red);color:#fff}
  .frm-yesno button.on-pass{background:var(--green);border-color:var(--green);color:#fff}
  .frm-f.frm-failing>select{border-color:var(--red);background:var(--red-light);color:var(--red);font-weight:700}
  .frm-mc-failopt:has(input:checked){color:var(--red)!important;font-weight:700}
  .frm-fail-slot{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-top:7px;min-width:0}
  .frm-fail-slot[hidden],tr.frm-fail-slot[hidden]{display:none!important}
  tr.frm-fail-slot{display:table-row}
  tr.frm-fail-slot>td{padding:0 8px 8px!important;border-top:none!important;background:var(--red-light)}
  .frm-fail-in{display:flex;align-items:center;flex-wrap:wrap;gap:6px;min-width:0}
  .frm-tbl td.frm-fail-cell select,.frm-tbl-card-field.frm-fail-cell select{border-color:var(--red);background:var(--red-light);color:var(--red);font-weight:700}
  .frm-tbl tr:has(+tr.frm-fail-slot:not([hidden]))>td{background:var(--red-light)}
  .frm-fail-tag{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--red);white-space:nowrap}
  .frm-fail-tag .ic{width:13px;height:13px}
  .frm-fail-act{display:inline-flex;align-items:center;gap:6px;max-width:100%;min-width:0;border:1px solid var(--border-strong);background:var(--surface);border-radius:999px;padding:3px 10px 3px 4px;font-family:var(--font);font-size:11.5px;color:var(--text);cursor:pointer;min-height:28px}
  .frm-fail-act:hover{border-color:var(--accent)}
  .frm-fail-st{font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:2px 7px;border-radius:20px;background:var(--accent-light);color:var(--accent);white-space:nowrap;flex-shrink:0}
  .frm-fail-act.s-closed .frm-fail-st{background:var(--green-light);color:var(--green)}
  .frm-fail-act.s-ongoing .frm-fail-st{background:var(--amber-light);color:var(--amber)}
  .frm-fail-act.od .frm-fail-st{background:var(--red-light);color:var(--red)}
  .frm-fail-act.s-wait .frm-fail-st,.frm-fail-act.s-gone .frm-fail-st{background:transparent;color:var(--text3);border:1px dashed var(--border-strong)}
  .frm-fail-tt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-fail-raise{min-height:30px;color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent)}
  .frm-fail-raise:hover{background:var(--red-light)}
  .frm-act-src{display:flex;align-items:flex-start;gap:6px;width:100%;box-sizing:border-box;text-align:left;margin:7px 0 0;padding:6px 9px;border:none;border-left:3px solid var(--red);background:var(--red-light);color:var(--text2);font-family:var(--font);font-size:11.5px;line-height:1.45;cursor:pointer;overflow-wrap:anywhere;min-width:0}
  .frm-act-src .ic{width:13px;height:13px;flex-shrink:0;color:var(--red);margin-top:2px}
  .frm-act-src b{color:var(--text);font-weight:700}
  .frm-act-main>.frm-act-src{margin:7px 9px 0 0;width:auto}
  .frm-fu-src{cursor:default;margin:0 0 10px;border-radius:4px}
  .frm-act-flash,[data-frid].frm-act-flash,.frm-f.frm-act-flash{animation:frmActFlash 1.6s var(--ease)}
  @keyframes frmActFlash{0%,35%{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 45%,transparent)}100%{box-shadow:0 0 0 0 transparent}}
  .frm-siglock.held{background:var(--amber-light);color:var(--amber);border-color:color-mix(in srgb,var(--amber) 30%,transparent)}
  .frm-act-hold{margin-top:10px;display:flex!important;align-items:flex-start;gap:8px;line-height:1.45}
  /* builder: which answers fail the question */
  .frm-fail-pick{display:flex;align-items:center;flex-wrap:wrap;gap:6px;min-width:0}
  .frm-fail-lbl{font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);margin-right:2px}
  .frm-fail-chip{border:1px solid var(--border-strong);background:var(--surface);border-radius:999px;padding:4px 11px;font-family:var(--font);font-size:11.5px;font-weight:600;color:var(--text2);cursor:pointer;min-height:28px;max-width:100%;overflow-wrap:anywhere}
  .frm-fail-chip.on{background:var(--red);border-color:var(--red);color:#fff}
  .frm-fail-none{font-size:11px;color:var(--text3);font-style:italic}
  .frm-fail-warn{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--amber);flex-basis:100%}
  .frm-fail-warn .ic{width:13px;height:13px;flex-shrink:0}
  /* the register's Forms / Actions views */
  .frm-reg-tabs{display:inline-flex;gap:2px;background:var(--surface2);border:1px solid var(--border);border-radius:999px;padding:3px;margin:0 0 10px}
  .frm-reg-tabs button{border:none;background:transparent;border-radius:999px;padding:6px 14px;font-family:var(--font);font-size:12px;font-weight:700;color:var(--text2);cursor:pointer;min-height:32px}
  .frm-reg-tabs button.on{background:var(--surface);color:var(--text);box-shadow:var(--shadow-xs)}
  .frm-reg-tabs b{color:var(--red)}
  .frm-stat-chips[hidden]{display:none!important}
  .frm-regacts-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;font-size:12px;color:var(--text2);margin:0 0 8px}
  .frm-regacts td{vertical-align:top}
  .frm-regacts-tt{min-width:180px;overflow-wrap:anywhere}
  .frm-regacts-od{color:var(--red);font-weight:700}
  /* a finger, not a pointer: every control the failing-answer strip and the register tabs add — after their own rules, so it wins */
  @media(max-width:600px){.frm-fail-raise,.frm-fail-act,.frm-fail-chip,.frm-reg-tabs button{min-height:44px}}
  /* the score: a figure, its outcome, and how each section did */
  .frm-score{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface2);padding:10px 12px;min-width:0}
  .frm-score-top{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 10px}
  .frm-score-pct{font-size:24px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.1}
  .frm-score-pts,.frm-score-mark,.frm-score-left{font-size:12px;color:var(--text3)}
  .frm-score-out{font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:3px 10px;border-radius:999px;background:var(--surface);border:1px solid var(--border-strong);color:var(--text2)}
  .frm-score-out.pass{background:var(--green-light);border-color:transparent;color:var(--green)}
  .frm-score-out.fail{background:var(--red);border-color:transparent;color:#fff}
  .frm-score-crit{display:flex;align-items:flex-start;gap:6px;margin-top:8px;font-size:12px;color:var(--red);overflow-wrap:anywhere;min-width:0}
  .frm-score-crit .ic{width:14px;height:14px;flex-shrink:0;margin-top:1px}
  .frm-score-secs{display:grid;gap:5px;margin-top:9px}
  .frm-score-sec{display:grid;grid-template-columns:minmax(0,1fr) minmax(60px,120px) 48px;align-items:center;gap:8px;font-size:12px}
  .frm-score-sl{min-width:0;overflow-wrap:anywhere;color:var(--text2)}
  .frm-score-bar{height:6px;border-radius:3px;background:var(--border);overflow:hidden}
  .frm-score-bar i{display:block;height:100%;background:var(--accent)}
  .frm-score-sp{text-align:right;font-variant-numeric:tabular-nums;font-weight:700}
  .frm-score-left{margin-top:6px}
  .frm-score-empty{font-size:12.5px;color:var(--text3)}
  .frm-score-note{font-size:11.5px;color:var(--text3);padding:6px 0 0;display:flex;gap:5px;align-items:flex-start}
  .frm-score-note .ic{width:13px;height:13px;flex-shrink:0;color:var(--amber);margin-top:1px}
  .frm-score-w{display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap;margin-left:6px}
  .frm-score-w label{display:inline-flex!important;align-items:center;gap:5px;font-size:11.5px;color:var(--text2);text-transform:none;letter-spacing:normal;margin:0}
  .frm-score-w input[type=number]{width:58px}
  .frm-score-pill{display:inline-flex;align-items:center;font-size:11.5px;font-weight:700;padding:2px 8px;border-radius:20px;background:var(--surface2);color:var(--text2);font-variant-numeric:tabular-nums;white-space:nowrap}
  .frm-score-pill.pass{background:var(--green-light);color:var(--green)}
  .frm-score-pill.fail{background:var(--red-light);color:var(--red)}
  /* conditional questions: a hidden one with no answer is not there; one that
     was answered keeps its answer, greyed and out of reach */
  .frm-cond-hid{display:none!important}
  .frm-cond-kept{opacity:.5}
  .frm-cond-kept::before{content:'Not asked \2014  answer kept';display:block;font-size:10.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--text3);margin:0 0 4px}
  .frm-fld-cond{flex-shrink:0;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:1px 6px;border-radius:999px;background:var(--accent-light,var(--surface2));color:var(--accent);line-height:1.5}
  .frm-cond{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:4px 0 2px;font-size:12px;min-width:0}
  .frm-cond.on{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);padding:7px 9px;margin:6px 0 2px}
  .frm-cond-lbl{font-weight:700;color:var(--text2)}
  .frm-cond select,.frm-cond input{min-width:0;max-width:100%;font-size:12px}
  .frm-cond-q{max-width:min(280px,100%)}
  .frm-cond input.frm-cond-v{width:140px}
  .frm-cond-add{display:inline-flex;align-items:center;gap:4px;border:1px dashed var(--border-strong);background:none;border-radius:6px;padding:5px 9px;font-family:var(--font);font-size:12px;color:var(--text2);cursor:pointer}
  .frm-cond-add:hover{color:var(--accent);border-color:var(--accent)}
  .frm-cond-add .ic{width:13px;height:13px}
  .frm-cond-x{border:none;background:none;color:var(--text3);cursor:pointer;font-size:13px;padding:4px 6px;border-radius:5px;margin-left:auto}
  .frm-cond-x:hover{background:var(--surface);color:var(--red)}
  .frm-cond-warn,.frm-cond-note{flex-basis:100%;display:flex;align-items:flex-start;gap:5px;font-size:11.5px;color:var(--text3);overflow-wrap:anywhere;min-width:0}
  .frm-cond-warn{color:var(--amber)}
  .frm-cond-warn .ic{width:13px;height:13px;flex-shrink:0;margin-top:1px}
  @media(max-width:600px){.frm-cond select,.frm-cond input{font-size:16px;min-height:40px}.frm-cond-q,.frm-cond input.frm-cond-v{flex:1 1 100%;max-width:100%;width:auto}.frm-cond-add,.frm-cond-x{min-height:44px}}
  .frm-act-need{font-size:11px;color:var(--amber);font-weight:700;padding:0 9px}
  .frm-act-late{font-size:11px;color:var(--text3);font-style:italic;padding:0 9px;overflow-wrap:anywhere}
  .frm-act.gone .frm-act-cells{opacity:.55}
  .frm-act-empty{padding:12px 14px;font-size:12px;color:var(--text3);border-top:1px solid var(--border)}
  .frm-act-hd+.frm-act-empty{border-top:none}
  .frm-act-add{margin-top:8px}
  .frm-act-reg{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:700;padding:2px 8px;border-radius:20px;background:var(--surface2);color:var(--text2);font-variant-numeric:tabular-nums}
  .frm-act-reg.ok{background:var(--green-light);color:var(--green)}
  .frm-act-reg.od{background:var(--red-light);color:var(--red)}
  .frm-act-reg .ic{width:12px;height:12px;stroke-width:2.6}
  .frm-act-reg-od{font-weight:600}
  .frm-act-pv{position:fixed;top:0;left:0;right:0;height:100vh;height:100dvh;background:rgba(15,23,42,.88);z-index:400;display:flex;align-items:center;justify-content:center;cursor:zoom-out}
  .frm-act-pv img{max-width:94vw;max-height:90vh;max-height:90dvh;border-radius:6px;object-fit:contain}
  @container (max-width:560px){
    .frm-act-hd{display:none}
    .frm-act-hd+.frm-act,.frm-act-hd+.frm-act-empty{border-top:none}
    .frm-act-cells{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
    .frm-act-what{grid-column:1/-1}
    .frm-act-cl{display:block;font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);margin:5px 0 4px 1px;overflow-wrap:anywhere}
  }
  @container (max-width:360px){.frm-act-cells{grid-template-columns:minmax(0,1fr)}}
  @media(max-width:600px){
    .frm-acts .frm-act-c textarea,.frm-acts .frm-act-c input[type=text],.frm-acts .frm-act-c input[type=number],.frm-acts .frm-act-c input[type=date],.frm-acts .frm-act-c select{min-height:44px}
    .frm-act-hd,.frm-act{grid-template-columns:26px minmax(0,1fr) 44px}
    .frm-act-del{width:44px;height:44px;margin:6px 0 0;border-color:transparent;font-size:19px}
    .frm-act-open{min-height:40px}
    .frm-act-cobtn{min-height:40px}
    .frm-co-add,.frm-co-md .macts .btn{min-height:44px}
    .frm-co-rm{width:34px;height:34px;font-size:19px}
    .frm-act-add{min-height:44px}
  }
  @media(max-width:600px){
    .frm-rph-btn{height:44px;padding:0 14px;font-size:13px}
    .frm-rph-grid{grid-template-columns:repeat(3,minmax(0,1fr));max-width:none}
  }
  /* Location on a drawing — a tier under a table row (like the photo gallery)
     or the body of a Location field. The snippet is a window onto the sheet,
     the pin drawn by slPinGlyph, the same marker Time Slices draws. */
  .frm-loc{display:flex;flex-direction:column;gap:7px;min-width:0}
  .frm-loc-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
  .frm-loc-chip{display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:100%;font-size:12px;color:var(--text)}
  .frm-loc-chip b{font-variant-numeric:tabular-nums;flex:none}
  .frm-loc-pref{flex:none;font-size:11px;color:var(--text2);font-variant-numeric:tabular-nums}
  .frm-loc-bn{color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
  .frm-loc-crop{position:relative;overflow:hidden;width:100%;max-width:520px;background:var(--surface2);border:1px solid var(--border);border-radius:9px}
  .frm-loc-crop[role=button]{cursor:zoom-in}
  .frm-loc-crop[role=button]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .frm-loc-sheet{position:absolute}
  .frm-loc-sheet img{display:block;width:100%;height:100%;user-select:none;-webkit-user-drag:none;pointer-events:none}
  .frm-loc-sheet svg{position:absolute;left:0;top:0;width:100%;height:100%;overflow:visible;pointer-events:none}
  .frm-loc-gone{font-size:11.5px;color:var(--text3);font-style:italic}
  .frm-tbl-card .frm-loc{padding:10px 14px 12px;border-top:1px solid var(--border)}
  .frm-act-main>.frm-loc{padding:0 7px}
  .frm-flash{animation:frmFlash 2.6s ease-out}
  @keyframes frmFlash{0%,30%{box-shadow:0 0 0 3px var(--accent);background:var(--accent-light)}100%{box-shadow:0 0 0 0 transparent}}
  /* the picker — a near-full-screen dialog, the drawing gets the room */
  .md.frm-loc-md{width:min(1100px,96vw);max-width:96vw;height:min(860px,92vh);height:min(860px,92dvh);max-height:92dvh;display:flex;flex-direction:column;gap:10px;overflow:hidden}
  .frm-loc-top{display:flex;align-items:flex-start;gap:8px;flex:none}
  .frm-loc-top h3{margin:0;flex:1;min-width:0}
  .frm-loc-tt{flex:1;min-width:0}
  .frm-loc-tt h3{margin:0}
  .frm-loc-sub{display:block;font-size:12px;color:var(--text2);overflow-wrap:anywhere}
  .frm-loc-x{flex:none}
  .frm-loc-load,.frm-loc-empty{padding:28px 12px;text-align:center;color:var(--text2);font-size:13px}
  .frm-loc-tools{display:flex;gap:8px;flex:none}
  .frm-loc-tools input{flex:1;min-width:0}
  .frm-loc-new{flex:none;white-space:nowrap}
  .frm-loc-grid{flex:1;min-height:0;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px;align-content:start;padding:2px}
  .frm-loc-card{display:flex;flex-direction:column;gap:3px;text-align:left;border:1px solid var(--border);border-radius:10px;background:var(--surface);padding:8px;cursor:pointer;font-family:var(--font);min-width:0}
  .frm-loc-card:hover,.frm-loc-card:focus-visible{border-color:var(--accent)}
  .frm-loc-thumb{display:block;aspect-ratio:4/3;background:var(--surface2);border-radius:6px;overflow:hidden}
  .frm-loc-thumb img{width:100%;height:100%;object-fit:contain;display:block}
  .frm-loc-cn{font-size:13px;font-weight:700;color:var(--text);overflow-wrap:anywhere}
  .frm-loc-cm{font-size:11.5px;color:var(--text2);overflow-wrap:anywhere}
  .frm-loc-foot{font-size:11.5px;color:var(--text3);flex:none}
  .frm-loc-vp{flex:1;min-height:0;overflow:auto;border:1px solid var(--border);border-radius:9px;background:var(--surface2);cursor:crosshair;touch-action:pan-x pan-y;overscroll-behavior:contain}
  .frm-loc-vp.view{cursor:grab}
  .frm-loc-stage{position:relative}
  .frm-loc-stage .frm-loc-crop{max-width:none;border:0;border-radius:0}
  .frm-loc-zoom{display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex:none}
  .frm-loc-hint{font-size:11.5px;color:var(--text3);min-width:0}
  .frm-loc-newf{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:5px}
  .frm-loc-newf input[type=text],.frm-loc-newf select{width:100%}
  .frm-loc-md .frm-loc-modes{display:flex;flex-direction:column;gap:6px}
  .frm-loc-md label.frm-loc-mode{display:flex;align-items:flex-start;gap:9px;border:1px solid var(--border);border-radius:9px;padding:8px 10px;cursor:pointer;text-transform:none;letter-spacing:normal;font-weight:400;margin:0;color:var(--text)}
  .frm-loc-md label.frm-loc-mode input{margin-top:3px;flex:none}
  .frm-loc-mode b{display:block;font-size:13px}
  .frm-loc-mode span span{display:block;font-size:11.5px;color:var(--text2)}
  .frm-loc-md .macts{flex:none}
  @media(max-width:600px){
    .md.frm-loc-md{width:100%;max-width:100%;height:94vh;height:94dvh;max-height:94dvh}
    .frm-loc-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
    .frm-loc-crop{max-width:none}
    .frm-loc-zoom .btn{min-width:44px;min-height:40px}
  }
  /* Two people answered the same question. Both versions, one at a time. */
  .frm-cf{border:1px solid var(--border);border-radius:11px;padding:11px 12px;margin-top:11px}
  .frm-cf-k{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);margin-bottom:7px}
  .frm-cf-r{display:flex;gap:9px;align-items:baseline;font-size:14px;color:var(--text);margin-bottom:4px;overflow-wrap:anywhere}
  .frm-cf-t{flex-shrink:0;font-size:10.5px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--text3);min-width:46px}
  .frm-savechip{font-size:11px;font-weight:600;padding:3px 10px;border-radius:20px;background:var(--surface2);color:var(--text3)}
  .frm-savechip.ok{background:var(--green-light);color:var(--green)}
  .frm-savechip.saving{background:var(--amber-light);color:var(--amber)}
  /* overflow "⋯" menu on template cards */
  .frm-menu{position:relative;margin-left:auto}
  .frm-menu-btn{width:30px;height:30px;border:1px solid var(--border-strong);background:var(--surface);border-radius:var(--radius-sm);cursor:pointer;color:var(--text2);font-size:16px;line-height:1;font-weight:700}
  .frm-menu-btn:hover{background:var(--surface2);color:var(--text)}
  .frm-menu-panel{position:absolute;right:0;top:calc(100% + 5px);background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius-sm);box-shadow:var(--shadow-lg);min-width:150px;padding:4px;display:none;z-index:90}
  .frm-menu-panel.open{display:block}
  .frm-tpl-card.frm-menu-up{position:relative;z-index:200} /* lift the whole card so its open menu clears the later search bar */
  /* register PDF viewer overlay */
  .frm-viewer{align-items:stretch;justify-content:center}
  .frm-viewer-box{background:var(--surface);border-radius:var(--radius);width:min(920px,96vw);max-height:94vh;margin:3vh auto;display:flex;flex-direction:column;overflow:hidden;box-shadow:var(--shadow-lg)}
  .frm-viewer-bar{display:flex;align-items:center;gap:8px;padding:11px 14px;border-bottom:1px solid var(--border);flex-wrap:wrap}
  .frm-viewer-ttl{font-weight:700;font-size:14px;color:var(--text)}
  .frm-viewer-body{flex:1;min-height:0;overflow:auto;background:#525659;display:flex;justify-content:center;padding:14px}
  .frm-viewer-body iframe{width:794px;max-width:100%;height:1123px;border:none;background:#fff;box-shadow:0 2px 14px rgba(0,0,0,.4);border-radius:2px}
  /* Side by side: the form as submitted, and the copy that was signed on paper.
     Both panes scroll independently — a signed scan is rarely the same length as
     the form, so locking them together would just fight the reader. */
  .frm-viewer-box.cmp{width:min(1560px,98vw)}
  .frm-viewer-cmp{flex:1;min-height:0;display:flex;gap:1px;background:var(--border)}
  .frm-viewer-pane{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--surface)}
  .frm-viewer-pane.off{display:none}
  .frm-pane-cap{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text2);padding:7px 12px;background:var(--surface2);border-bottom:1px solid var(--border);display:flex;align-items:center;gap:7px}
  .frm-pane-cap .sub{text-transform:none;letter-spacing:0;font-weight:600;color:var(--text3);font-size:10.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .frm-pane-body{flex:1;min-height:0;overflow:auto;background:#525659;display:flex;justify-content:center;padding:12px}
  .frm-pane-body iframe{width:794px;max-width:100%;height:1123px;border:none;background:#fff;box-shadow:0 2px 14px rgba(0,0,0,.4);border-radius:2px}
  .frm-pane-body img{max-width:100%;align-self:flex-start;background:#fff;border-radius:2px;box-shadow:0 2px 14px rgba(0,0,0,.4)}
  .frm-vseg{display:inline-flex;border:1px solid var(--border-strong);border-radius:var(--radius-sm);overflow:hidden}
  .frm-vseg button{background:var(--surface);border:none;font-family:var(--font);font-size:11.5px;font-weight:700;color:var(--text2);padding:5px 10px;cursor:pointer;border-left:1px solid var(--border)}
  .frm-vseg button:first-child{border-left:none}
  .frm-vseg button.on{background:var(--accent);color:#fff}
  @media(max-width:600px){.frm-vseg button{min-height:36px;padding:7px 11px;font-size:12px}}
  /* register: status shortcut chips + the signed-copy marker */
  .frm-stat-chips{display:flex;flex-wrap:wrap;gap:6px;margin:-2px 0 10px}
  .frm-stat-chip{background:var(--surface);border:1px solid var(--border-strong);border-radius:999px;font-family:var(--font);font-size:11.5px;font-weight:700;color:var(--text2);padding:5px 12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;min-height:30px}
  .frm-stat-chip b{font-weight:800;color:var(--text3)}
  .frm-stat-chip:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
  .frm-stat-chip:disabled{opacity:.45;cursor:default}
  .frm-stat-chip.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .frm-stat-chip.on b{color:#fff}
  .frm-sc-mark{background:none;border:none;padding:2px;margin-left:5px;cursor:pointer;color:var(--green);vertical-align:middle;line-height:0}
  .frm-sc-mark svg{width:14px;height:14px;stroke-width:2.2}
  .frm-sc-mark:hover{color:var(--accent)}
  @media(max-width:900px){.frm-viewer-cmp{gap:0}.frm-stat-chip{min-height:36px}}
  /* the export dialog's format chips borrow .frm-cat-chip (28px); on a phone they are
     tapped, so they take the status chips' 36px */
  @media(max-width:900px){.frm-exp-fmt .frm-cat-chip{min-height:36px}}
  .frm-menu-item{display:block;width:100%;text-align:left;background:none;border:none;font-family:var(--font);font-size:12px;font-weight:600;color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer}
  .frm-menu-item:hover{background:var(--accent-light);color:var(--accent)}
  .frm-menu-item.danger{color:var(--red)}
  .frm-menu-item.danger:hover{background:var(--red-light);color:var(--red)}
  /* builder: collapsed field rows, expand one at a time */
  .frm-fld{padding:0;overflow:visible}
  .frm-fld-bar{padding:9px 12px;cursor:pointer}
  .frm-fld-bar .frm-fld-lbl{cursor:text}
  .frm-fld-chev{width:24px;height:24px;border:none;background:none;cursor:pointer;color:var(--text3);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;transition:transform .15s var(--ease)}
  .frm-fld.open .frm-fld-chev{transform:rotate(90deg);color:var(--accent)}
  .frm-fld-req-dot{width:6px;height:6px;border-radius:50%;background:var(--red);flex-shrink:0}
  .frm-fld-body{display:none;padding:2px 12px 12px;border-top:1px dashed var(--border)}
  .frm-fld.open{border-color:var(--accent)}
  .frm-fld.open .frm-fld-body{display:block}
  .frm-pal-group{font-size:9px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text3);margin:10px 2px 6px}
  .frm-pal-group:first-child{margin-top:0}
  /* fill: sticky action bar + progress + mobile bottom bar */
  .frm-head.fillbar{position:sticky;top:var(--vchrome);z-index:60;background:var(--bg);padding:10px 0;margin-bottom:10px;box-shadow:0 8px 12px -10px rgba(15,23,42,.15)}
  .frm-reqpill{font-size:11px;font-weight:700;padding:3px 11px;border-radius:20px;background:var(--surface2);color:var(--text2);font-variant-numeric:tabular-nums}
  .frm-reqpill.ok{background:var(--green-light);color:var(--green)}
  .frm-bottombar{display:none}
  /* a Sign-off button carries the STAGE'S OWN NAME, which is free text and can
     be arbitrarily long. Left to itself it pushed the action bar (and the page)
     sideways — found at 768px once the left sidebar narrowed the content column
     from 740px to 554px, i.e. real at any narrow width, just newly reachable. */
  .frm-head .btn,.frm-bottombar .btn{max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis}
  [data-fid].frm-miss .frm-f-lbl{color:var(--red)}
  [data-fid].frm-miss{outline:2px solid var(--red);outline-offset:4px;border-radius:8px}
  @media(max-width:768px){
    .frm-head.fillbar{position:static;box-shadow:none}
    .frm-head .frm-title{flex-basis:100%;order:-1;font-size:15px}
    .frm-bottombar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:95;background:var(--surface);border-top:1px solid var(--border);padding:10px 14px calc(10px + env(safe-area-inset-bottom));gap:8px;align-items:center;box-shadow:0 -6px 20px rgba(15,23,42,.1)}
    .frm-bottombar .btn{flex:1;min-height:42px}
    /* Clearance for the fixed bottom bar belongs on the SCROLL CONTAINER, not
       on the paper — the History panel now sits below the paper, so a margin
       on the paper alone would leave the last history row under the bar. */
    #frmFill{padding-bottom:76px}
    .frm-audit-bar{min-height:44px}   /* a real control gets a real target (HIG 44pt) */
  }

  /* ── TIME SLICES ─────────────────────────────── */
  .sl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
  .sl-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-xs);cursor:pointer;transition:box-shadow .16s var(--ease),transform .16s var(--ease);position:relative}
  .sl-card-arch{position:absolute;top:7px;right:7px;z-index:2;width:28px;height:28px;border-radius:7px;border:1px solid var(--border);background:rgba(255,255,255,.92);color:var(--text2);cursor:pointer;font-size:13px;line-height:1;opacity:0;transition:opacity .14s}
  .sl-card:hover .sl-card-arch{opacity:1}
  .sl-card-arch:hover{color:var(--red);border-color:var(--red)}
  .sl-archrow{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--border);border-radius:9px;margin-bottom:7px;background:var(--surface)}
  .sl-archrow .n{flex:1;font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sl-archrow .n span{color:var(--text3);font-size:11px;font-weight:400;margin-left:6px}
  .sl-card:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
  .sl-card-thumb{aspect-ratio:16/9;background:var(--surface2);display:flex;align-items:center;justify-content:center;color:var(--text-faint);overflow:hidden;border-bottom:1px solid var(--border)}
  .sl-card-thumb img{width:100%;height:100%;object-fit:cover}
  .sl-card-body{padding:11px 14px}
  .sl-card-name{font-size:13.5px;font-weight:700;color:var(--text);overflow-wrap:anywhere}
  .sl-card-meta{font-size:11px;color:var(--text3);margin-top:3px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
  .sl-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
  .sl-name-inp{border:1px solid transparent;background:transparent;font-family:var(--font);font-size:15px;font-weight:800;color:var(--text);border-radius:6px;padding:3px 8px;min-width:120px;max-width:320px}
  .sl-name-inp:hover,.sl-name-inp:focus{border-color:var(--border-strong);background:var(--surface);outline:none}
  .sl-wrap{display:grid;grid-template-columns:44px 1fr 240px;gap:10px;align-items:stretch}
  @media(max-width:900px){.sl-wrap{grid-template-columns:44px 1fr}}
  /* Full-screen editing: #slEdit fills the viewport and hides the rest of the app */
  #slEdit.sl-full{position:fixed;inset:0;z-index:150;background:var(--bg);margin:0;padding:10px 14px 12px;display:flex;flex-direction:column;overflow:hidden}
  #slEdit.sl-full .sl-top{margin-bottom:8px}
  #slEdit.sl-full .sl-wrap{flex:1;min-height:0}
  #slEdit.sl-full .sl-stage{height:100%}
  #slEdit.sl-full .sl-props{max-height:100%}
  #slEdit.sl-full .sl-time{margin-top:8px}
  .sl-rail{display:flex;flex-direction:column;gap:5px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:6px;height:fit-content}
  .sl-rail button{width:38px;height:38px;border:1px solid transparent;background:transparent;border-radius:9px;cursor:pointer;color:var(--text2);display:flex;align-items:center;justify-content:center;font-size:19px}
  .sl-rail button .ic{vertical-align:0}
  @media(max-width:600px){.sl-rail button{width:44px;height:44px;font-size:21px}}
  .sl-rail button:hover{background:var(--surface2);color:var(--text)}
  .sl-rail button.on{background:var(--accent);color:#fff}
  .sl-rail .sep{height:1px;background:var(--border);margin:3px 2px}
  .sl-stage{position:relative;background:#e8ecf3;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;height:calc(100vh - var(--vchrome) - 205px);min-height:420px;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;-webkit-user-drag:none}
  /* the Saving…/Saved flip must never reflow .sl-top mid-drag — a shifted stage
     rect makes the dragged item jump away from the pointer (slPtEv re-reads the
     rect each move while d.start was measured against the old one) */
  .sl-top .frm-savechip{min-width:58px;text-align:center}
  .sl-stage.grabbing{cursor:grabbing}
  .sl-inner{position:absolute;left:0;top:0;transform-origin:0 0}
  .sl-inner img{display:block;user-select:none;pointer-events:none}
  .sl-inner svg{position:absolute;left:0;top:0}
  .sl-zoombtns{position:absolute;right:10px;bottom:10px;display:flex;flex-direction:column;gap:4px;z-index:5}
  .sl-zoombtns button{width:30px;height:30px;border:1px solid var(--border-strong);background:var(--surface);border-radius:8px;cursor:pointer;font-weight:700;color:var(--text2)}
  .sl-empty-stage{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--text3);font-size:13px;text-align:center;padding:20px}
  .sl-keybox{position:absolute;left:10px;bottom:10px;background:rgba(255,255,255,.95);border:1px solid var(--border-strong);border-radius:var(--radius-sm);padding:8px 10px;font-size:11px;z-index:5;max-width:240px;box-shadow:var(--shadow-sm)}
  .sl-keybox .kt{font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text2);margin-bottom:5px}
  .sl-keyrow{display:flex;align-items:center;gap:7px;margin-bottom:3px}
  .sl-keyrow .sw{width:22px;height:12px;border-radius:3px;flex-shrink:0;border:1.5px solid}
  .sl-props{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px;height:fit-content;max-height:calc(100vh - var(--vchrome) - 205px);overflow-y:auto;-webkit-overflow-scrolling:touch}
  .sl-props .didx-cust-title{margin-top:10px}
  /* ── issue pins ── */
  .sl-pin-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;display:inline-block}
  .sl-pinbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;width:100%}
  .sl-pinbar-lbl{font-size:11px;color:var(--text2);font-weight:600;text-transform:uppercase;letter-spacing:.04em}
  .sl-pinseg{display:inline-flex;border:1px solid var(--border-strong);border-radius:8px;overflow:hidden}
  .sl-pinseg button{display:inline-flex;align-items:center;gap:5px;background:var(--surface);border:0;border-right:1px solid var(--border);padding:6px 10px;font-family:var(--font);font-size:11.5px;font-weight:600;color:var(--text2);cursor:pointer;min-height:32px}
  .sl-pinseg button:last-child{border-right:0}
  .sl-pinseg button.on{background:var(--accent);color:#fff}
  .sl-pinseg button.on .sl-pin-dot{box-shadow:0 0 0 1.5px rgba(255,255,255,.85)}
  .sl-pinlist{margin:-2px 0 4px}
  .sl-pinlist-hd{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text2);margin-bottom:6px}
  .sl-pinlist-hd .n{background:var(--surface2);border-radius:20px;padding:1px 7px;font-size:10px;color:var(--text2)}
  .sl-pinrows{display:flex;flex-direction:column;gap:3px;max-height:34vh;overflow-y:auto}
  .sl-pinrow{display:flex;align-items:flex-start;gap:7px;width:100%;text-align:left;background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:6px 8px;cursor:pointer;font-family:var(--font);min-height:38px}
  .sl-pinrow:hover{background:var(--surface2);border-color:var(--border-strong)}
  .sl-pinrow.on{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light)}
  .sl-pinrow .no{font-size:10.5px;font-weight:800;color:var(--text3);flex:0 0 auto;padding-top:1px}
  .sl-pinrow .ti{flex:1;min-width:0;font-size:11.5px;font-weight:600;color:var(--text);overflow-wrap:anywhere;line-height:1.35}
  /* A list row is a scan target, not the place to read a long title — clamp it
     to two lines (the full text stays in the row's title tooltip and on the
     card). Without this a worst-case unbroken title runs past the row edge. */
  .sl-pinrow .nm{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .sl-pinrow .sub{display:block;font-size:10px;font-weight:500;color:var(--text3);margin-top:1px}
  .sl-pinempty{font-size:11px;color:var(--text3);padding:8px 2px;line-height:1.5}
  /* markers pop-out: its own panel, opened from the toolbar (it used to be
     glued to the top of the properties inspector on every render) */
  .sl-pinpanel{position:fixed;z-index:1800;width:322px;max-width:calc(100vw - 16px);background:var(--surface);border:1px solid var(--border-strong);border-radius:12px;box-shadow:0 14px 40px rgba(15,23,42,.19);padding:12px}
  .sl-pinpanel-hd{display:flex;align-items:center;gap:7px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text2);margin-bottom:9px}
  .sl-pinpanel-hd .n{background:var(--surface2);border-radius:20px;padding:1px 7px;font-size:10px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--text2)}
  .sl-pinpanel-x{background:none;border:0;cursor:pointer;color:var(--text3);font-size:13px;line-height:1;padding:3px 4px;border-radius:5px}
  .sl-pinpanel-x:hover{background:var(--surface2);color:var(--text)}
  .sl-pinpanel-sw{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--text2);margin-bottom:6px;cursor:pointer}
  .sl-pinpanel-sw input{accent-color:var(--accent);width:15px;height:15px;flex:0 0 auto}
  .sl-pinpanel-lbl{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text3);margin:9px 0 5px}
  .sl-pinpanel .sl-pinseg{width:100%;flex-wrap:wrap;margin-bottom:8px}
  .sl-pinpanel .sl-pinrows{max-height:46vh}
  .sl-pinbtn-n{background:var(--accent);color:#fff;border-radius:20px;padding:0 6px;font-size:10px;font-weight:800;margin-left:2px}
  @media(max-width:600px){.sl-pinrow{min-height:44px}.sl-pinseg button{min-height:44px;padding:6px 12px}
    .sl-pinpanel{left:8px!important;right:8px;width:auto;max-height:70vh;overflow-y:auto}
    .sl-pinpanel-sw{min-height:44px}.sl-pinpanel-x{min-width:44px;min-height:44px}}
  /* pin card (modal) */
  .sl-pm-hd{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:12px}
  .sl-pm-ref{font-size:15px;font-weight:800;color:var(--text);letter-spacing:.01em}
  .sl-pm-chip{display:inline-flex;align-items:center;gap:5px;border-radius:20px;padding:3px 10px;font-size:11px;font-weight:700}
  .sl-pm-chip.ty{background:var(--surface2);color:var(--text2)}
  /* Keep Export PDF and the close button together: the header wraps on a phone,
     and without this the × drops onto a line of its own and reads as broken. */
  .sl-pm-acts{display:flex;align-items:center;gap:6px;flex:0 0 auto;margin-left:auto}
  .sl-pm-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px 12px;margin-bottom:12px}
  .sl-pm-grid label{display:flex;flex-direction:column;align-items:stretch;gap:3px;font-size:11px;color:var(--text2);margin:0}
  .sl-pm-full{grid-column:1/-1}
  .sl-pm-sec{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text2);margin:14px 0 7px;display:flex;align-items:center;gap:7px}
  .sl-pm-sec .n{background:var(--surface2);border-radius:20px;padding:1px 7px;font-size:10px;font-weight:600}
  .sl-pm-link{display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--surface2);border:1px solid var(--border);border-radius:9px;padding:9px 11px}
  .sl-pm-link .ref{font-weight:800;font-size:12px;color:var(--text)}
  .sl-pm-link .ti{flex:1;min-width:0;font-size:12px;color:var(--text2);overflow-wrap:anywhere}
  .sl-pm-note{border:1px solid var(--border);border-radius:9px;padding:8px 10px;margin-bottom:6px;background:var(--surface)}
  .sl-pm-note .meta{display:flex;align-items:center;gap:7px;font-size:10.5px;color:var(--text3);margin-bottom:3px}
  .sl-pm-note .tx{font-size:12.5px;color:var(--text);white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.5}
  .sl-pm-photos{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:7px}
  .sl-pm-ph{position:relative;aspect-ratio:4/3;border-radius:8px;overflow:hidden;border:1px solid var(--border);background:var(--surface2)}
  .sl-pm-ph img{width:100%;height:100%;object-fit:cover;display:block;cursor:zoom-in}
  .sl-pm-ph button{position:absolute;top:3px;right:3px;width:24px;height:24px;border-radius:50%;border:0;background:rgba(15,23,42,.72);color:#fff;font-size:13px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
  @media(max-width:600px){.sl-pm-grid{grid-template-columns:1fr}.sl-pm-ph button{width:32px;height:32px}}
  .sl-props label{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text2);margin-bottom:7px}
  .sl-props input[type=text],.sl-props input[type=date],.sl-props input[type=number],.sl-props select{border:1px solid var(--border-strong);border-radius:6px;padding:5px 8px;font-family:var(--font);font-size:11.5px;color:var(--text);flex:1;min-width:0}
  /* min-width:0 lets the slider SHRINK. A range input has a wide intrinsic
     min-content width, and flex items refuse to go below it by default — so
     without this, a row that also carries the typed-angle box overflows the
     panel instead of the slider giving up the space. */
  .sl-props input[type=range]{flex:1;min-width:0;accent-color:var(--accent)}
  /* linked to a programme activity — the shape's dates come from the plan */
  .sl-actlink{border:1px solid var(--accent);background:var(--accent-light);border-radius:8px;padding:8px 9px;margin-bottom:8px}
  .sl-actlink.warn{border-color:#fcd34d;background:#fffbeb}
  .sl-actlink-t{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;font-weight:700;color:var(--text);line-height:1.35}
  .sl-actlink-t svg{width:13px;height:13px;flex-shrink:0;margin-top:1px;stroke-width:2.2}
  /* a flex child will not shrink below its content width without min-width:0,
     and a long WBS+name can be one unbroken run — both are needed */
  .sl-actlink-t span{min-width:0;overflow-wrap:anywhere}
  .sl-actlink-d{font-size:11px;color:var(--text2);margin:4px 0 7px;line-height:1.45}
  /* several linked activities: one line each, with its own dates and a × */
  .sl-actlist-in{display:flex;flex-direction:column;gap:4px}
  .sl-actlink-row{align-items:center}
  .sl-actlink-row span{flex:1}
  .sl-actlink-row i{display:block;font-style:normal;font-weight:500;font-size:10.5px;color:var(--text2)}
  .sl-actx{flex:0 0 auto;width:26px;height:26px;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--text2);font-size:15px;line-height:1;cursor:pointer}
  .sl-actx:hover{color:var(--red,#dc2626);border-color:var(--red,#dc2626)}
  /* the board follows a SAVED programme: say so where the board's name is */
  .sl-srcchip{display:inline-flex;align-items:center;gap:5px;min-width:0;max-width:220px;border:1px solid #c7d2fe;background:#eef2ff;color:#3730a3;border-radius:999px;padding:3px 10px;font-size:11.5px;font-weight:600;cursor:pointer}
  .sl-srcchip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sl-srcchip svg{width:12px;height:12px;flex-shrink:0}
  .sl-srcchip.warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}
  /* A slice on a programme non-working day (slNwChipHtml): neutral when linked
     markups still show, amber once the board is hiding them. */
  .sl-nwchip{display:inline-flex;align-items:center;gap:5px;min-width:0;max-width:220px;border:1px solid var(--border-strong);background:var(--surface2,#f4f5f7);color:var(--text2);border-radius:999px;padding:3px 10px;font-size:11.5px;font-weight:600;cursor:pointer;white-space:nowrap}
  .sl-nwchip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sl-nwchip svg{width:12px;height:12px;flex-shrink:0}
  .sl-nwchip.on{border-color:#fcd34d;background:#fffbeb;color:#92400e}
  .sl-src-lead{font-size:12.5px;color:var(--text2);line-height:1.5;margin:0 0 10px}
  .sl-src-none{font-size:12px;color:var(--text3);margin-top:8px}
  .sl-srclist{display:flex;flex-direction:column;gap:2px;max-height:50vh;overflow-y:auto;border:1px solid var(--border);border-radius:6px;padding:4px}
  /* <label> rows inside .md: two classes deep to out-rank `.md label` (Known Mistake #7) */
  .md .sl-srclist .sl-srcrow{display:flex;align-items:center;gap:10px;min-height:44px;padding:6px 8px;margin:0;border-radius:4px;cursor:pointer;
    text-transform:none;letter-spacing:normal;font-weight:400;font-size:13px;color:var(--text)}
  .md .sl-srclist .sl-srcrow:hover{background:var(--accent-light)}
  .md .sl-srclist .sl-srcrow input{width:18px;height:18px;flex:0 0 auto;margin:0;accent-color:var(--accent)}
  .md .sl-srclist .sl-srcrow .nm{flex:1;min-width:0;overflow-wrap:anywhere}
  .md .sl-srclist .sl-srcrow .nm b{font-weight:600}
  .md .sl-srclist .sl-srcrow .nm i{display:block;font-style:normal;font-size:11px;color:var(--text3)}
  /* Which programme a board follows (slSrcRender / the link picker). The select
     is full width so a long team-programme name never pushes the dialog wide. */
  .md .sl-srcplbl{display:block;margin:0 0 4px}
  .sl-srcprog,.sl-actprog select{display:block;width:100%;max-width:100%;min-width:0;border:1px solid var(--border-strong);border-radius:6px;padding:7px 9px;font-size:13px;font-family:var(--font);background:var(--surface);color:var(--text);margin:0 0 10px;text-overflow:ellipsis}
  .md .sl-actprog label{display:block;margin:0 0 4px}
  .sl-actprog select{margin-bottom:8px}
  .sl-actprogtag{display:inline-block;margin-left:4px;font-size:10px;font-weight:700;color:var(--accent);background:var(--accent-light);border-radius:8px;padding:0 6px;vertical-align:1px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sl-srcbase{display:inline-block;margin-left:6px;font-size:10px;font-weight:700;color:#0f766e;background:#ccfbf1;border-radius:8px;padding:0 6px;vertical-align:1px}
  /* Date window over the programme — "what is on site today / this week".
     The chips and the two boxes drive one filter; wrapping is what keeps the
     row inside a phone, where five controls never fit on one line. */
  .sl-actfilt{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px}
  /* backdrop quality: three choices in a row. The options are <label>s inside .md,
     so every rule is scoped 0,3,0+ to beat the generic .md label (Known Mistake #7) */
  .sl-qual{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:2px 0 6px}
  .md .sl-qual .sl-qopt{display:flex;align-items:flex-start;gap:7px;margin:0;padding:8px 9px;border:1px solid var(--border-strong);
    border-radius:8px;cursor:pointer;text-transform:none;letter-spacing:normal;font-weight:400;color:var(--text);min-width:0}
  .md .sl-qual .sl-qopt:has(input:checked){border-color:var(--accent);background:var(--accent-light)}
  .md .sl-qual .sl-qopt input{margin:2px 0 0;accent-color:var(--accent);flex-shrink:0}
  .md .sl-qual .sl-qopt span{display:flex;flex-direction:column;min-width:0}
  .md .sl-qual .sl-qopt b{font-size:12.5px;font-weight:700}
  .md .sl-qual .sl-qopt i{font-style:normal;font-size:11px;color:var(--text2);overflow-wrap:anywhere}
  .sl-qhint{font-size:11px;color:var(--text3);line-height:1.45;margin:0 0 12px}
  @media(max-width:420px){.sl-qual{grid-template-columns:1fr}}
  .sl-actfilt .sl-actlbl{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;
    text-transform:uppercase;letter-spacing:.03em;color:var(--text3);margin:0}
  /* A native date control has a wide intrinsic min-width — left alone it pushes
     FROM/TO onto their own lines and the row reads as three. */
  .sl-actfilt input[type=date]{width:120px;min-width:0;padding:4px 6px;font-size:12px;border:1px solid var(--border);
    border-radius:6px;background:var(--surface);color:var(--text);font-family:inherit}
  .sl-actcount{font-size:11.5px;color:var(--text2);margin:-2px 0 2px;min-height:15px}
  /* Where the picker's dates came from and when they were read (slActSrcSync). */
  .sl-actsrc{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;font-size:11.5px;color:var(--text2);margin:8px 0 2px;min-height:26px}
  .sl-actsrc span{min-width:0;overflow-wrap:anywhere}
  .sl-actsrc .warn{color:#b45309;font-weight:600}
  .sl-actload{padding:16px;text-align:center;color:var(--text3);font-size:12px}
  .sl-actcount b{color:var(--text)}
  .sl-actlist{max-height:min(46vh,340px);overflow:auto;border:1px solid var(--border);border-radius:8px;margin:8px 0}
  .sl-actrow{display:flex;align-items:center;gap:10px;width:100%;background:none;border:none;border-bottom:1px solid var(--border);
    font-family:var(--font);text-align:left;padding:9px 11px;cursor:pointer;min-height:45px}
  .sl-actrow:last-child{border-bottom:none}
  .sl-actrow:hover{background:var(--accent-light)}
  .sl-actrow .n{flex:1;min-width:0;font-size:12px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sl-actrow .d{font-size:11px;font-weight:600;color:var(--text2);white-space:nowrap;flex-shrink:0}
  .sl-actrow .d.none{color:var(--text-faint);font-style:italic}
  /* two lines: the name gets the full width, what describes it sits under it */
  .sl-actm{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .sl-actm .n{flex:none}
  .sl-actsub{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;min-width:0}
  .sl-actsub .d{font-size:11px}
  .sl-acto{font-size:10.5px;font-weight:600;color:var(--text3);white-space:nowrap}
  /* a section is a header you can link to — a zone that follows its whole area */
  .sl-actrow.sec{background:var(--surface2)}
  .sl-actrow.sec .n{font-weight:800;letter-spacing:.01em}
  .sl-actrow.cur{box-shadow:inset 3px 0 0 var(--accent)}
  .sl-actsec{flex-shrink:0;font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
    color:var(--text2);border:1px solid var(--border-strong);border-radius:4px;padding:0 5px;line-height:15px;background:var(--surface)}
  /* how many markups point here on this board: filled when there is one, hollow when not */
  .sl-actn{flex-shrink:0;min-width:26px;height:22px;padding:0 7px;border-radius:11px;display:inline-flex;align-items:center;
    justify-content:center;font-size:11.5px;font-weight:800;font-variant-numeric:tabular-nums;
    color:var(--text3);border:1px dashed var(--border-strong);background:transparent}
  .sl-actn.on{color:#fff;background:var(--accent);border:1px solid var(--accent)}
  @media(max-width:600px){.sl-actm .n{white-space:normal}}
  /* The in-place text BOX (double-click a text callout). It is a
     contenteditable, not a textarea, because a run of the text can carry its
     own colour — a textarea holds one string in one colour. The swatch strip
     sits above it and prevents its own mousedown, so pressing a colour never
     takes the caret out of the box. */
  .sl-inline-bar{display:flex;flex-wrap:wrap;gap:4px;align-items:center;max-width:min(86vw,436px);padding:5px 6px;background:var(--surface);
    border:1px solid var(--border);border-bottom:none;border-radius:8px 8px 0 0;box-shadow:var(--shadow-lg)}
  .sl-inline-sw{width:18px;height:18px;border-radius:5px;border:1px solid rgba(0,0,0,.22);cursor:pointer;padding:0;flex:0 0 auto}
  .sl-inline-sw:hover{transform:scale(1.12)}
  .sl-inline-b{min-width:24px;height:24px;padding:0 5px;border:1px solid var(--border);border-radius:5px;background:var(--surface);
    color:var(--text);cursor:pointer;font-family:Inter,sans-serif;line-height:1;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center}
  .sl-inline-b:hover{background:var(--surface2)}
  .sl-inline-sep{width:1px;align-self:stretch;background:var(--border);margin:0 2px;flex:0 0 auto}
  #slInline{background:var(--surface);color:var(--text);border:2px solid var(--accent);border-radius:0 7px 7px 7px;
    padding:4px 8px;box-shadow:var(--shadow-lg);outline:none;overflow-wrap:anywhere;white-space:pre-wrap;max-height:50vh;overflow-y:auto}
  /* Typed angle beside the rotation slider. Fixed width and flex:0 so the
     slider keeps the room — the generic input rule above sets flex:1, which
     would otherwise split the row in half. */
  .sl-rotnum{display:inline-flex;align-items:center;gap:2px;flex:0 0 auto}
  .sl-props .sl-rotnum input[type=number]{flex:0 0 auto;width:52px;padding:4px 4px 4px 6px;text-align:right;font-variant-numeric:tabular-nums}
  .sl-rotnum i{font-style:normal;color:var(--text3);font-size:11px}
  .sl-swatches{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:7px}
  .sl-sw{width:22px;height:22px;border-radius:6px;border:1.5px solid rgba(0,0,0,.15);cursor:pointer;padding:0}
  .sl-sw.on{outline:2px solid var(--accent);outline-offset:1px}
  .sl-pick{width:30px!important;height:22px!important}
  .sl-swatches .btn.on{border-color:var(--accent);color:var(--accent);font-weight:700}
  @media(max-width:900px){
    .sl-props{position:fixed;left:0;right:0;bottom:0;z-index:96;max-height:46vh;border-radius:14px 14px 0 0;box-shadow:0 -8px 30px rgba(15,23,42,.2);display:none}
    .sl-props.open{display:block}
  }
  .sl-time{display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:8px 12px;margin-top:10px}
  .sl-time input[type=date]{border:1px solid var(--border-strong);border-radius:6px;padding:5px 8px;font-family:var(--font);font-size:12px;font-weight:700;color:var(--text)}
  .sl-time input[type=range]{flex:1;min-width:120px;accent-color:var(--accent)}
  .sl-time .cnt{font-size:11px;color:var(--text3);font-variant-numeric:tabular-nums;white-space:nowrap}
  /* the board's date window: two date boxes and an arrow on one unbreakable
     line were 3px wider than a 390px phone (measured 2026-09-30) — let it wrap */
  .sl-time .sl-win{font-size:11px;color:var(--text2);display:inline-flex;flex-wrap:wrap;gap:5px;align-items:center;min-width:0;max-width:100%}
  .sl-time .sl-win input[type=date]{min-width:0;max-width:100%}
  #slLib{position:fixed;z-index:1700;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);box-shadow:var(--shadow-lg);width:384px;max-width:94vw;max-height:560px;display:none;flex-direction:column;overflow:hidden}
  /* ── Programme (CPM planner) ── */
  /* The Programme ribbon (2026-10-11): a header row (title, save state, chips,
     Undo/Redo, Export PDF) over a tab strip whose panes hold captioned groups —
     the Office ribbon shape, so someone new reads WHERE a thing lives from the
     tab and group names. .pg-top wraps all of it; phones hide it (see the
     ≤600px block) and use .pg-mobbar instead. */
  .pg-top{display:block;margin-bottom:8px}
  .pg-head{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:6px}
  .pg-head>.btn-blue{height:28px;display:inline-flex;align-items:center}
  .pg-qat{display:inline-flex;gap:3px}
  .pg-qat .btn-outline{height:28px}
  .pg-qat .btn-outline:disabled{opacity:.35;cursor:default}
  .pg-rib{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);box-shadow:0 1px 2px rgba(15,23,42,.05);min-width:0}
  .pg-ribtabs{display:flex;align-items:flex-end;gap:2px;padding:0 8px;border-bottom:1px solid var(--border);overflow-x:auto;scrollbar-width:none;background:var(--surface2);border-radius:var(--radius) var(--radius) 0 0}
  .pg-ribtabs::-webkit-scrollbar{display:none}
  .pg-ribtab{flex-shrink:0;border:0;border-bottom:2.5px solid transparent;margin-bottom:-1px;background:none;padding:8px 13px 6px;font-family:var(--font);font-size:12.5px;font-weight:600;color:var(--text2);cursor:pointer;white-space:nowrap;border-radius:6px 6px 0 0}
  .pg-ribtab:hover{color:var(--text);background:color-mix(in srgb,var(--text) 5%,transparent)}
  .pg-ribtab.on{color:var(--accent);border-bottom-color:var(--accent);background:var(--surface)}
  .pg-ribtab:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
  .pg-ribtabs .pg-selname{margin-left:auto;align-self:center;padding-left:10px;flex-shrink:1;min-width:0}
  .pg-ribpane{display:none;flex-wrap:wrap;align-items:stretch;row-gap:6px;padding:6px 4px 4px}
  .pg-ribpane.on{display:flex}
  /* Collapsed (^ on the tab strip, or a double-click on a tab): the tab names
     alone, and the chart takes the room. A tab click while collapsed opens its
     pane OVER the chart (.peek), so nothing below moves. See pgRibMinToggle. */
  .pg-rib{position:relative}
  .pg-ribmin{flex-shrink:0;align-self:center;margin-left:6px;width:28px;height:28px;display:grid;place-items:center;border:0;background:none;border-radius:6px;color:var(--text3);cursor:pointer}
  .pg-ribmin:hover{background:color-mix(in srgb,var(--text) 7%,transparent);color:var(--text)}
  .pg-ribmin:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
  .pg-ribmin .ic{width:16px;height:16px;transition:transform .16s ease}
  .pg-rib.min .pg-ribmin .ic{transform:rotate(180deg)}
  .pg-rib.min .pg-ribtabs{border-bottom:0;border-radius:var(--radius)}
  .pg-rib.min .pg-ribpane.on{display:none}
  .pg-rib.min:not(.peek) .pg-ribtab.on{background:none}
  .pg-rib.min.peek .pg-ribpane.on{display:flex;position:absolute;left:-1px;right:-1px;top:100%;z-index:40;background:var(--surface);border:1px solid var(--border);border-radius:0 0 var(--radius) var(--radius);box-shadow:0 12px 28px rgba(15,23,42,.16)}
  /* a captioned group: the controls on top, its name underneath, a hairline
     between groups — the caption is what tells a newcomer what the cluster is */
  .pg-rib .pg-tgroup{flex-direction:column;align-items:stretch;justify-content:space-between;padding:0 8px;gap:3px;border:0;border-right:1px solid var(--border);border-radius:0;background:none;box-shadow:none}
  .pg-rib .pg-tgroup:last-child{border-right:0}
  .pg-tgb{display:flex;align-items:center;justify-content:center;gap:2px;flex:1;flex-wrap:wrap}
  .pg-rib .pg-tgroup>b{margin:0;text-align:center;font-size:10px;font-weight:600;text-transform:none;letter-spacing:.01em;color:var(--text3)}
  .pg-rib .pg-tgroup .btn-outline.pg-rbtn{flex-direction:column;justify-content:center;gap:3px;height:auto;min-height:48px;min-width:52px;padding:4px 7px;font-size:11px;font-weight:600;line-height:1.15}
  .pg-rib .pg-rbtn .ic{width:19px;height:19px}
  .pg-rbtn>span{white-space:nowrap}
  .pg-rib .pg-tgroup .btn-outline.pg-rsm{flex-direction:row;min-height:26px;height:26px;gap:5px;padding:0 9px}
  .pg-rib .pg-rsm .ic{width:13px;height:13px}
  .pg-tgseg .pg-tgb{flex-direction:column;gap:4px}
  .pg-rib .pg-linkseg button{height:26px;font-size:11px}
  .pg-rib .pg-zoom button{padding:5px 13px;font-size:11.5px}
  .pg-rib .pg-tgroup .btn-outline.pg-rdel{color:var(--red)}
  .pg-hidtag{font-size:8.5px;font-weight:800;background:#fef3c7;color:#b45309;border:1px solid #fcd34d;border-radius:6px;padding:1px 5px;letter-spacing:.04em;position:absolute;top:2px;right:2px}
  .pg-rbtn{position:relative}
  .pg-rib .pg-selcount{align-self:center;max-width:110px;white-space:normal;line-height:1.2;text-align:center}
  /* Labelled toolbar clusters (standardised 2026-08-25). The group box carries
     the chrome; the buttons INSIDE it are borderless ghosts — bordered buttons
     inside bordered boxes was double chrome and read as clutter. Every control
     in a group is the same 26px tall, every action has a stroke icon from the
     ICONS registry, and the label sits INLINE so row height never grows. */
  .pg-tgroup{display:inline-flex;align-items:center;gap:1px;padding:2px;border:1px solid var(--border);border-radius:9px;background:var(--surface);box-shadow:0 1px 2px rgba(15,23,42,.05)}
  .pg-tgroup>b{font-size:8px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:var(--text3);margin:0 5px 0 8px;user-select:none;white-space:nowrap}
  .pg-tgroup .btn-outline{border-color:transparent;background:transparent;color:var(--text2);height:26px;padding:0 9px;border-radius:7px;display:inline-flex;align-items:center}
  .pg-tgroup .btn-outline:hover{background:var(--surface2);color:var(--text)}
  .pg-tgroup .btn-outline:disabled{opacity:.35;cursor:default;background:transparent}
  /* toggled-on state inside a group: soft accent fill, not a solid blue slab */
  .pg-tgroup .btn-outline.btn-blue{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent)}
  .pg-tgroup .btn-outline.btn-blue:hover{background:color-mix(in srgb,var(--accent) 18%,transparent)}
  .pg-icbtn{width:28px;justify-content:center;padding:0!important}
  .pg-dot{width:5px;height:5px;border-radius:50%;background:currentColor;display:inline-block;margin-left:5px;flex-shrink:0}
  .pg-head .btn .ic,.pg-riskchip .ic{width:13px;height:13px}
  .pg-title{font-size:15px;font-weight:800}
  .pg-tsep{width:1px;height:18px;background:var(--border-strong);margin:0 4px}
  .pg-selname{font-size:11px;color:var(--text3);margin-left:8px;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pg-zoom{display:flex;border:1px solid var(--border);border-radius:9px;overflow:hidden;background:var(--surface);box-shadow:0 1px 2px rgba(15,23,42,.05)}
  .pg-zoom button{border:none;background:transparent;padding:6px 11px;font-family:var(--font);font-size:11px;font-weight:700;color:var(--text2);cursor:pointer}
  .pg-zoom button:hover{background:var(--surface2)}
  .pg-zoom button.on{background:var(--accent);color:#fff}
  /* Phone Programme toolbar + Tools sheet. Base display:none lives here; the
     ≤600px show-rule is in a media block placed AFTER all .pg-* base rules
     (below) so it wins the cascade — .pg-top has a later base display:flex. */
  .pg-mobbar{display:none;align-items:center;gap:6px;margin-bottom:8px;flex-wrap:nowrap}
  .pg-mobbar .pg-zoom{flex-shrink:0}
  .pg-mobpv{display:none;align-items:center;gap:8px;margin:0 0 8px;padding:6px 10px;border-radius:10px;background:#dbeafe;color:#1e40af;border:1px solid #93c5fd;font-size:12px;font-weight:700}
  .pg-mobpv span{flex:1;min-width:0}
  .pg-mobpv button{flex-shrink:0;border:1px solid #93c5fd;background:#fff;color:#1e40af;border-radius:8px;height:32px;padding:0 10px;font:inherit;cursor:pointer}
  .pg-mobbar .pg-zoom button{padding:0 10px;height:38px;min-width:34px;font-size:13px}
  .pg-vseg{display:flex;border:1px solid var(--border-strong);border-radius:8px;overflow:hidden;flex-shrink:0}
  .pg-vseg button{border:none;background:var(--surface);padding:0 12px;height:38px;font-family:var(--font);font-size:13px;font-weight:600;color:var(--text2);cursor:pointer}
  .pg-vseg button.on{background:var(--accent);color:#fff}
  /* compact variant of the segmented control for the desktop toolbar groups —
     matched to the 26px ghost-button height so nothing towers over its row */
  .pg-linkseg{border-radius:7px;border-color:var(--border)}
  .pg-linkseg button{height:24px;padding:0 9px;font-size:10.5px;font-weight:700}
  /* the status date lives inside its own labelled group like everything else */
  .pg-tgroup .pg-status input{border:none;background:transparent;height:26px;padding:0 7px;border-radius:7px;font-family:var(--font);font-size:11px;font-weight:600;color:var(--text);cursor:pointer}
  .pg-tgroup .pg-status input:hover{background:var(--surface2)}
  .pg-mob-pdf{flex-shrink:0;min-height:38px;padding:0 11px}
  .pg-mob-tools{margin-left:auto;flex-shrink:0;min-height:38px}
  .pg-sheet-panel{max-height:82vh;display:flex;flex-direction:column}
  .pg-sheet-scroll{overflow-y:auto;-webkit-overflow-scrolling:touch}
  .pg-sheet-h{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);margin:12px 2px 7px}
  .pg-sheet-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .pg-sheet-it{display:flex;align-items:center;justify-content:center;text-align:center;min-height:46px;padding:6px 10px;border:1px solid var(--border-strong);border-radius:10px;background:var(--surface);color:var(--text);font-family:var(--font);font-size:14px;font-weight:600;cursor:pointer}
  .pg-sheet-it:active{background:var(--accent-light)}
  .pg-sheet-del{color:var(--red);border-color:#fca5a5}
  .pg-sheet-date{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:13px;font-weight:600;color:var(--text2)}
  .pg-sheet-date input{flex:1;border:1px solid var(--border-strong);border-radius:10px;padding:10px 12px;font-family:var(--font);color:var(--text)}
  .pg-sheet-date .rmv{border:none;background:none;color:var(--text3);font-size:18px;cursor:pointer;padding:0 4px}
  .pg-cmpchip{display:inline-flex;align-items:center;gap:7px;background:#fef3c7;color:#92400e;border:1px solid #fcd34d;font-size:11px;font-weight:700;border-radius:14px;padding:4px 10px}
  .pg-cmpchip button{border:none;background:transparent;color:#92400e;font-size:13px;cursor:pointer;padding:0}
  /* planned view: blue, not the compare amber — a different question, and both can be on */
  .pg-cmpchip.pg-pvchip{background:#dbeafe;color:#1e40af;border-color:#93c5fd}
  .pg-cmpchip.pg-pvchip button{color:#1e40af}
  /* Programme narrative (AI): the dialog, the wait, and the written document */
  .md.pg-narr-md{width:820px;max-width:96vw}
  /* The narrative dialog outgrows a desktop screen once a narrative is showing, and
     .macts only pins at phone width — so Close / Write would scroll out of reach. */
  @media(min-width:601px){.md.pg-narr-md>.macts{position:sticky;bottom:-24px;margin:14px -24px -24px;padding:12px 24px;background:var(--surface);border-top:1px solid var(--border);z-index:2}}
  .pg-narr-intro{font-size:12px;color:var(--text2);line-height:1.5;margin:0 0 12px}
  .pg-narr-mode{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:0 0 12px}
  .md .pg-narr-mode label{display:flex;align-items:flex-start;gap:8px;margin:0;padding:9px 10px;border:1px solid var(--border);border-radius:10px;cursor:pointer;text-transform:none;letter-spacing:normal;font-size:12px;font-weight:400;color:var(--text);background:var(--surface);min-width:0}
  .md .pg-narr-mode label:has(input:checked){border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
  .pg-narr-mode input{width:16px;height:16px;accent-color:var(--accent);margin:1px 0 0;flex:none}
  .pg-narr-mode b{display:block;font-weight:700;margin-bottom:2px}
  .pg-narr-mode small{display:block;font-size:11px;line-height:1.4;color:var(--text2);overflow-wrap:anywhere}
  .pg-narr-mode span{min-width:0}
  @media (max-width:600px){.pg-narr-mode{grid-template-columns:1fr}}
  .pg-narr-sincew{margin:0 0 12px}
  .pg-narr-sincew[hidden]{display:none}
  .pg-narr-since{width:100%;max-width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:8px;padding:7px 10px;font:inherit;font-size:13px;background:var(--surface);color:var(--text)}
  .pg-narr-since-none{font-size:12px;color:var(--text2);padding:8px 10px;border:1px dashed var(--border);border-radius:8px}
  .pg-narr-lbl{display:block;font-size:11px;font-weight:700;color:var(--text);margin:0 0 4px}
  .pg-narr-lbl span{font-weight:500;color:var(--text3)}
  .pg-narr-md textarea{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:8px;padding:8px 10px;font:inherit;font-size:13px;resize:vertical}
  .md label.pg-narr-chk{display:flex;align-items:center;gap:8px;margin:10px 0 0;text-transform:none;letter-spacing:normal;font-size:12px;font-weight:500;color:var(--text)}
  .pg-narr-chk input{width:16px;height:16px;accent-color:var(--accent);margin:0;flex:none}
  .pg-narr-recent{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px;font-size:12px;color:var(--text3)}
  .pg-narr-recent[hidden]{display:none}
  .pg-narr-recent .btn{max-width:100%}
  .pg-narr-wait{display:flex;align-items:center;gap:10px;margin-top:14px;padding:12px 14px;border:1px solid var(--border);border-radius:10px;background:var(--surface2);font-size:12.5px;color:var(--text2)}
  .pg-narr-spin{width:16px;height:16px;flex:none;border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .7s linear infinite}
  /* the minimised narrative: a progress ring in the corner (owner, 2026-10-21) */
  .pg-narr-pip{position:fixed;right:20px;bottom:20px;z-index:300;display:flex;align-items:center;gap:8px;padding:6px 14px 6px 6px;border:1px solid var(--border);border-radius:999px;background:var(--surface);box-shadow:0 6px 20px rgba(15,23,42,.18);cursor:pointer;font:inherit;color:var(--text)}
  .pg-narr-pip svg{width:40px;height:40px;transform:rotate(-90deg);flex:none}
  .pg-narr-pip circle{fill:none;stroke-width:4}
  .pg-narr-pip .trk{stroke:var(--border)}
  .pg-narr-pip .bar{stroke:var(--accent);stroke-linecap:round;transition:stroke-dashoffset .8s ease}
  .pg-narr-pip[data-st=done] .bar{stroke:#16a34a}
  .pg-narr-pip[data-st=err] .bar{stroke:#dc2626}
  .pg-narr-pip .lbl{position:absolute;left:6px;width:40px;text-align:center;font-size:10.5px;font-weight:700;font-variant-numeric:tabular-nums}
  .pg-narr-pip .cap{font-size:12.5px;font-weight:600;white-space:nowrap}
  @media(max-width:600px){.pg-narr-pip{right:12px;bottom:calc(76px + env(safe-area-inset-bottom))}}
  .pg-narr-err{margin-top:14px;padding:10px 12px;border-radius:10px;background:#fef2f2;color:#991b1b;border:1px solid #fecaca;font-size:12.5px;overflow-wrap:anywhere}
  .pg-narr-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:14px}
  .pg-narr-meta{flex:1 1 200px;min-width:0;font-size:11.5px;color:var(--text3)}
  .pg-narr-doc{margin-top:10px;max-height:52vh;overflow:auto;border:1px solid var(--border);border-radius:10px;background:#fff;color:#1f2937;padding:18px 22px;font-size:13px;line-height:1.5;overflow-wrap:anywhere}
  .pg-narr-doc h1{font-size:20px;margin:0 0 6px;color:#0f172a}
  .pg-narr-doc h2{font-size:15px;margin:18px 0 6px;padding-bottom:3px;border-bottom:1px solid #cbd5e1;color:#1e3a5f}
  .pg-narr-doc h3,.pg-narr-doc h4{font-size:13.5px;margin:12px 0 4px;color:#1e3a5f}
  .pg-narr-doc p{margin:0 0 8px}
  .pg-narr-doc ul,.pg-narr-doc ol{margin:0 0 8px;padding-left:20px}
  .pg-narr-doc table{border-collapse:collapse;margin:4px 0 10px;width:100%;display:block;overflow-x:auto}
  .pg-narr-doc th,.pg-narr-doc td{border:1px solid #94a3b8;padding:4px 7px;font-size:12px;vertical-align:top;text-align:left;min-width:70px}
  .pg-narr-doc th{background:#e2e8f0}
  .pg-narr-doc blockquote{margin:8px 0;padding:6px 10px;border-left:3px solid #f59e0b;background:#fffbeb}
  .pg-narr-nr{margin-top:14px}
  .pg-narr-notes{margin-top:14px;border:1px solid #fca5a5;border-radius:10px;background:#fef2f2;padding:10px 12px}
  .pg-narr-notes>summary{cursor:pointer;font-size:12.5px;color:#7f1d1d;line-height:1.45;overflow-wrap:anywhere}
  .pg-narr-notes .pg-narr-bar{margin-top:10px}
  .pg-narr-notes .pg-narr-doc{max-height:40vh}
  @media(max-width:600px){.pg-narr-bar .btn{min-height:44px}.pg-narr-doc{padding:12px 14px;max-height:none}}
  /* Impact view: amber — it is about lateness, measured from today */
  .pg-cmpchip.pg-pvchip.pg-impchip{background:#fef3c7;color:#92400e;border-color:#fcd34d}
  .pg-cmpchip.pg-pvchip.pg-impchip button{color:#92400e}
  .pg-mobpv.pg-mobimp{background:#fef3c7;color:#92400e;border-color:#fcd34d}
  .pg-mobpv.pg-mobimp button{border-color:#fcd34d;color:#92400e}
  /* Add delays: red — the delay register's own colour on the chart */
  .pg-cmpchip.pg-pvchip.pg-dlychip{background:#fee2e2;color:#991b1b;border-color:#fca5a5}
  .pg-cmpchip.pg-pvchip.pg-dlychip button{color:#991b1b}
  .pg-cmpchip.pg-pvchip.pg-dlychip .pg-dlychip-t{border:none;background:none;font:inherit;padding:0;cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px}
  .pg-mobpv.pg-mobdly{background:#fee2e2;color:#991b1b;border-color:#fca5a5}
  .pg-mobpv.pg-mobdly button{border-color:#fca5a5;color:#991b1b}
  .pg-dly-sub{font-size:12px;color:var(--text2);line-height:1.5;margin:0 0 10px}
  .pg-dly-tot{font-size:13px;padding:8px 10px;border-radius:8px;background:#fee2e2;color:#7f1d1d;margin:0 0 10px;overflow-wrap:anywhere}
  .pg-dly-tot span{font-size:12px;color:#991b1b}
  .pg-dly-list{display:flex;flex-direction:column;gap:6px}
  .pg-dly-row{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border:1px solid var(--border);border-radius:10px;background:var(--surface)}
  .pg-dly-row.off{opacity:.7}
  .md .pg-dly-tick{display:flex;margin:2px 0 0;text-transform:none;letter-spacing:normal}
  .pg-dly-tick input{width:18px;height:18px;accent-color:#dc2626}
  .pg-dly-main{flex:1;min-width:0}
  .pg-dly-t{font-size:13px;color:var(--text);overflow-wrap:anywhere}
  .pg-dly-m{font-size:11.5px;color:var(--text3);margin-top:2px}
  .pg-dly-w{font-size:11.5px;color:#92400e;margin-top:3px;overflow-wrap:anywhere}
  .pg-dly-eff{flex-shrink:0;font-size:12px;font-weight:700;color:#991b1b;white-space:nowrap;padding-top:1px}
  .pg-dly-open{flex-shrink:0;font-size:12px;font-weight:600;color:var(--accent2);padding-top:1px}
  @media(max-width:600px){.pg-dly-row{flex-wrap:wrap}.pg-dly-eff,.pg-dly-open{min-height:32px;display:inline-flex;align-items:center}}
  .pg-dly-base{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;margin:0 0 10px}
  .md .pg-dly-sel{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0;font-size:12px;font-weight:600;color:var(--text2);text-transform:none;letter-spacing:normal;min-width:0;max-width:100%}
  .md .pg-dly-sel select{min-width:0;max-width:100%;font-size:12.5px;padding:5px 8px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text)}
  .pg-dly-note{font-size:11.5px;color:var(--text3);overflow-wrap:anywhere}
  .pg-dly-in{font-size:11.5px;color:#166534;margin-top:4px;overflow-wrap:anywhere}
  .pg-dly-in span{color:var(--text3)}
  .pg-dly-act{border:1px solid #fca5a5;background:#fff;color:#991b1b;font:inherit;font-weight:600;border-radius:6px;padding:2px 8px;cursor:pointer}
  @media(max-width:600px){.pg-dly-act{min-height:32px}.md .pg-dly-sel select{font-size:16px}}
  .pg-status{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;color:var(--text2)}
  .pg-status input{border:1px solid var(--border-strong);border-radius:7px;padding:5px 7px;font-family:var(--font);font-size:11.5px;font-weight:600;color:var(--text)}
  .pg-scroll{overflow:auto;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);height:calc(100vh - var(--vchrome) - 153px);min-height:240px;position:relative}
  .pg-canvas{position:relative;min-height:100%}
  .pg-grid{position:sticky;left:0;z-index:3;background:var(--surface);border-right:2px solid var(--border-strong);float:left}
  .pg-ghdr{display:grid;position:sticky;top:0;z-index:4;background:var(--th-bg);color:var(--th-text);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;height:46px;align-items:center;border-bottom:1px solid var(--border)}
  .pg-ghdr>div{padding:0 8px;white-space:nowrap;overflow:hidden}
  .pg-gh{position:relative;align-self:stretch;display:flex;align-items:center}
  .pg-colrz{position:absolute;right:0;top:7px;bottom:7px;width:8px;cursor:col-resize;z-index:6;border-radius:2px}
  .pg-colrz:hover{background:var(--accent);opacity:.45}
  .pg-split{position:absolute;top:0;right:-3px;bottom:0;width:8px;cursor:col-resize;z-index:7}
  .pg-split::after{content:'';position:absolute;left:2.5px;top:50%;transform:translateY(-50%);width:3px;height:30px;border-radius:3px;background:var(--border-strong);transition:background .12s}
  .pg-split:hover::after{background:var(--accent);height:46px}
  .pg-row{display:grid;height:30px;align-items:center;border-bottom:1px solid rgba(148,163,184,.14);cursor:pointer;position:relative}
  .pg-row:nth-child(odd){background:rgba(148,163,184,.05)}
  .pg-row.sel{background:var(--accent-light)}
  .pg-row.sum{font-weight:700;z-index:3}
  .pg-row.sum .pg-c,.pg-row.sum .pg-num,.pg-row.sum .ro{color:inherit}
  .pg-row.sum .ro{opacity:.9}
  .pg-row.sum .pg-num{opacity:.82;font-weight:700}
  .pg-row.sel{box-shadow:inset 0 0 0 2px var(--accent)}
  .pg-row.sel:not(.sum){background:var(--accent-light)}
  /* Copy selection. Deliberately a left marker rather than a second fill, so it
     reads as "also picked" without competing with the focused row's outline. */
  .pg-row.msel{box-shadow:inset 3px 0 0 0 var(--accent)}
  .pg-row.msel:not(.sum){background:var(--accent-light)}
  .pg-row.msel.sel{box-shadow:inset 0 0 0 2px var(--accent),inset 3px 0 0 0 var(--accent)}
  .pg-selcount{font-size:10.5px;font-weight:700;color:var(--accent);align-self:center}
  .btn.btn-dim{opacity:.5}
  .pg-name{position:relative}
  .pg-spine{position:absolute;width:4px;pointer-events:none;z-index:2}
  .pg-palrow{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--border)}
  .pg-palrow:last-of-type{border-bottom:none}
  .pg-palsw{width:20px;height:20px;border-radius:5px;flex-shrink:0;border:1px solid rgba(0,0,0,.12)}
  .pg-palrow{flex-wrap:wrap}
  .pg-pallab{flex:1;font-size:12.5px;font-weight:600;min-width:90px}
  .pg-palrow .pg-palpick,.pg-secpick .pg-palpick{width:42px;height:30px;min-width:42px;padding:0;margin:0;border:1px solid var(--border);border-radius:7px;background:none;cursor:pointer;flex:0 0 auto;box-sizing:border-box}
  .pg-palop{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text2);white-space:nowrap}
  .pg-palop input[type=range]{width:82px;min-width:82px;margin:0;padding:0;accent-color:var(--accent);flex:0 0 auto}
  .pg-palop b{min-width:36px;text-align:right;color:var(--text)}
  .pg-secpick{display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap}
  .pg-palrow .sl-swatches{margin:0;flex-wrap:wrap;justify-content:flex-end;max-width:200px}
  .pg-xrev{display:flex;align-items:center;gap:9px;padding:9px 10px;border:1px solid var(--border);border-radius:8px;margin-bottom:7px;cursor:pointer;font-size:13px}
  .pg-xrev:hover{background:var(--accent-light)}
  .pg-xrev input{accent-color:var(--accent);margin:0}
  .pg-xrev span{color:var(--text3);font-size:11.5px;margin-left:auto}
  /* ── project export dialog ── the longest dialog in the app (4 groups,
     ~14 toggles), so on phone the action row is pinned rather than sitting
     below a long scroll */
  /* Same trap as .dexp-opt below: every option row here is a <label> inside .md,
     so it needs the extra class to out-specify `.md label{display:block}`. The
     format radios would otherwise render block and read differently from the
     checkbox rows in the same dialog. */
  .dexp-md .pg-xrev{display:flex;margin-bottom:7px;font-weight:400;color:var(--text);text-transform:none;letter-spacing:normal;font-size:13px}
  .dexp-period{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:4px}
  .dexp-period label{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--text3)}
  .dexp-period input[type=date]{min-width:0;font-family:var(--font);font-size:12px;padding:6px 8px;border:1px solid var(--border-strong);border-radius:6px;background:var(--surface);color:var(--text)}
  .dexp-daycount{font-size:11px;color:var(--text3);margin-left:auto;white-space:nowrap}
  .dexp-presets{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:4px}
  .dexp-grp{display:flex;align-items:center;gap:6px;margin-top:13px}
  .dexp-grpall{border:none;background:none;cursor:pointer;color:var(--accent);font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:2px 3px}
  .dexp-grpall:hover{text-decoration:underline}
  /* Title on one line, explanation under it — these hints are full sentences and
     read as mush run on after the label.
     Scoped as `.dexp-md .dexp-opt` (0,2,0) ON PURPOSE: these rows are <label>s
     inside .md, and the generic `.md label{display:block…}` rule (0,1,1) beats a
     bare `.dexp-opt` (0,1,0) — the specificity trap in Known Mistake #7. The
     leaked label props are reset here too. */
  .dexp-md .dexp-opt{display:grid;grid-template-columns:auto 1fr;gap:1px 9px;align-items:start;
    margin:0 0 7px;font-weight:400;color:var(--text);text-transform:none;letter-spacing:normal;font-size:13px}
  .dexp-md .dexp-opt input{margin-top:2px}
  .dexp-md .dexp-opt b{font-weight:600}
  .dexp-md .dexp-opt span{grid-column:2;margin-left:0;line-height:1.45;font-size:11.5px;color:var(--text3)}
  .dexp-photos{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .dexp-photo-n{font-size:11.5px;color:var(--text3)}
  /* Phone rules sit HERE, immediately after their own base rules — a block
     earlier in the sheet would lose to them at equal specificity. */
  @media(max-width:600px){
    .dexp-md .pg-xrev{min-height:44px;padding:11px 12px}
    .dexp-md .pg-xrev span{margin-left:0;flex:1 1 100%}
    .dexp-md .pg-tblchip{min-height:38px;padding:0 14px}
    .dexp-md .dexp-grpall{min-height:32px;padding:2px 8px}
    .dexp-period label{flex:1 1 100%}
    .dexp-period input[type=date]{flex:1;min-height:44px}
    .dexp-daycount{margin-left:0;flex:1 1 100%}
    .dexp-photos .btn{min-height:44px}
    /* The sticky Export row that used to live here is now the shared
       `.md>.macts` rule (search "PINNED action row"), which every dialog gets
       — and which fixes this copy's bug: its -14px offsets assumed
       `.md{padding:14px}`, true only at <=480px, so it was 10px out in the
       481-600 band. */
  }
  .pg-editing{font-size:12px;font-weight:600;color:var(--text3);margin-left:2px}
  .pg-edited{color:#b45309}
  .pg-unedited{color:var(--text3);font-weight:400}
  .pg-edited-save{font:inherit;font-size:11px;font-weight:600;color:var(--amber);background:var(--amber-light);border:1px solid transparent;border-radius:20px;padding:1px 9px;margin-left:4px;cursor:pointer;vertical-align:1px;text-transform:none}
  .pg-edited-save:hover{border-color:var(--amber)}
  /* "save a revision first?" before a restore replaces edited work */
  .pg-revask-acts{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end}
  /* revisions modal — current-revision bar, baseline chip, history list */
  .pg-curbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px solid var(--border);border-left:3px solid var(--text3);border-radius:8px;padding:8px 11px;margin-bottom:12px;background:var(--surface2,var(--surface))}
  .pg-curbar.edited{border-left-color:#b45309}
  /* min-width floor so the status wraps to its own line before the name is
     ellipsised down to nothing — on a phone "Working…" alone tells you nothing */
  .pg-curbar .n{font-size:12.5px;color:var(--text2);flex:1 1 150px;min-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pg-curbar .s{font-size:11.5px;color:var(--text3);white-space:nowrap}
  .pg-curbar.edited .s{color:#b45309;font-weight:600}
  .pg-brow.base{border-color:var(--accent);background:var(--accent-light)}
  /* two-line revision label: each line ellipsises on its own, so a long name and
     a long author line both truncate instead of pushing the buttons off-screen */
  .pg-bname{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px;overflow:hidden}
  /* the NAME truncates, the chips never do — a BASELINE marker that vanishes
     behind a long revision name is the one thing on the row you must not lose */
  .pg-bname .l1{font-size:12.5px;display:flex;align-items:center;gap:6px;min-width:0}
  .pg-bname .l1>b{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pg-bname .l1>.pg-basechip,.pg-bname .l1>.pg-curchip{flex-shrink:0}
  .pg-bname .l2{font-size:10.5px;color:var(--text3);font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pg-bact{flex-shrink:0}
  .pg-brow .btn.pg-bact{padding:3px 12px}
  .pg-basechip{display:inline-block;font-size:9px;font-weight:800;letter-spacing:.05em;color:#fff;background:var(--accent);border-radius:4px;padding:1px 5px;vertical-align:1px}
  .pg-curchip{display:inline-block;font-size:9px;font-weight:800;letter-spacing:.05em;color:var(--text2);border:1px solid var(--border-strong);border-radius:4px;padding:0 5px;vertical-align:1px}
  .pg-audit{border-bottom:1px solid var(--border);padding:6px 0}
  .pg-audit:last-of-type{border-bottom:none}
  .pg-audit .w{font-size:10.5px;color:var(--text3);font-weight:600}
  .pg-audit .t{font-size:12px;color:var(--text2);line-height:1.5;overflow-wrap:anywhere}
  .pg-audit-empty{font-size:12px;color:var(--text3);padding:8px 0}
  .pg-dhist{border:none;background:none;cursor:pointer;color:var(--text3);font-size:15px;line-height:1;padding:2px 4px;border-radius:5px}
  .pg-dhist:hover{background:var(--accent-light);color:var(--accent)}
  .pg-row.sum.sel{background:var(--accent-light)}
  .pg-c{padding:0 8px;font-size:12px;white-space:nowrap;overflow:hidden;display:flex;align-items:center;gap:4px;height:100%}
  .pg-c.r{justify-content:flex-end}
  .pg-c .ro{color:var(--text2);font-variant-numeric:tabular-nums}
  .pg-c .ro.act{color:var(--accent);font-weight:700}
  .pg-c .ro.act b{font-size:9px;border:1px solid var(--accent);border-radius:3px;padding:0 2px;margin-left:2px}
  .pg-c.crit{color:var(--red);font-weight:700}
  .pg-c.neg{color:#991b1b;font-weight:800} /* super-critical: negative float (behind a deadline) */
  .pg-num{color:var(--text3);font-variant-numeric:tabular-nums;font-size:11px}
  .pg-pred,.pg-res{color:var(--text2);font-size:11px}
  .pg-in{border:1px solid transparent;background:transparent;font-family:var(--font);font-size:12px;color:var(--text);border-radius:5px;padding:3px 5px;width:100%;min-width:0}
  .pg-in:hover{border-color:var(--border)}
  .pg-in:focus{border-color:var(--accent);background:var(--surface);outline:none;color:var(--text)!important}
  .pg-in.b{font-weight:700}
  .pg-in.r{text-align:right}
  .pg-in.cons{color:var(--accent);font-weight:700}
  /* Phone name cell: tappable, ellipsized, looks like the input at rest (→ pgEditName modal) */
  .pg-name-tap{flex:1;min-width:0;line-height:1.3}
  .pg-chv{border:none;background:transparent;cursor:pointer;font-size:11px;color:var(--text2);padding:0 2px;flex-shrink:0;width:14px}
  .pg-chv-sp{width:14px;flex-shrink:0;display:inline-block}
  .pg-name{gap:2px}
  .pg-mi{font-size:9px;color:var(--text2);flex-shrink:0}
  .pg-chart{position:absolute;top:0}
  .pg-ts{position:sticky;top:0;z-index:2;background:var(--surface);height:46px;border-bottom:1px solid var(--border);overflow:hidden}
  .pg-ts1{position:relative;height:23px;border-bottom:1px solid var(--border)}
  .ts-m{position:absolute;top:0;font-size:10.5px;font-weight:700;color:var(--text2);border-left:1px solid var(--border);padding:4px 0 0 6px;height:23px;white-space:nowrap;overflow:hidden}
  .pg-ts2{position:relative;height:23px}
  .ts-d{position:absolute;top:0;font-size:9.5px;color:var(--text3);border-left:1px solid rgba(148,163,184,.25);padding:5px 0 0 3px;height:23px;overflow:hidden;font-variant-numeric:tabular-nums}
  .ts-wk{position:absolute;top:1px;right:2px;font-size:8px;font-weight:800;color:var(--red);line-height:1}
  .ts-wk.p{top:13px;color:var(--amber)}
  .pg-wkchip{font-size:10.5px;font-weight:800;color:var(--red);background:var(--red-light,#fee2e2);border-radius:12px;padding:3px 9px;white-space:nowrap}
  .pg-wkchip b{color:var(--amber)}
  .pg-today-tag{position:absolute;top:3px;font-size:8.5px;font-weight:800;color:#fff;background:var(--accent);padding:2px 6px;border-radius:4px;white-space:nowrap;transform:translateX(-50%);pointer-events:none;letter-spacing:.03em;z-index:3;text-transform:uppercase;box-shadow:0 1px 3px rgba(37,99,235,.35)}
  .pg-gbody{position:relative}
  .pg-gbody svg{display:block}
  /* ── sticky notes on the chart ──
     The layer is a zero-size, click-through overlay pinned to #pgGbody's origin,
     which is pixel-identical to the SVG's user-unit space. Only the cards
     themselves take pointer events, so bars underneath stay clickable. */
  .pg-nlayer{position:absolute;left:0;top:0;width:0;height:0;pointer-events:none;z-index:2}
  .pg-note-arrows{position:absolute;left:0;top:0;overflow:visible;pointer-events:none}
  .pg-note{position:absolute;pointer-events:auto;border-radius:8px;box-shadow:0 2px 8px rgba(15,23,42,.22);
    border:1px solid rgba(15,23,42,.14);overflow:hidden;line-height:1.35}
  .pg-note.sel{outline:2px solid var(--accent);outline-offset:1px}
  .pg-note.done{opacity:.62}
  .pg-note-bar{display:flex;align-items:center;gap:3px;padding:3px 4px 2px 7px;cursor:move;
    background:rgba(15,23,42,.07);min-height:20px}
  .pg-note-n{font-size:9px;font-weight:800;opacity:.65;letter-spacing:.03em}
  .pg-note-sp{flex:1}
  .pg-note-ic{border:none;background:none;cursor:pointer;color:inherit;opacity:.6;font-size:13px;line-height:1;
    padding:2px 4px;border-radius:4px}
  .pg-note-ic:hover{opacity:1;background:rgba(15,23,42,.1)}
  .pg-note-ic.del:hover{background:rgba(220,38,38,.16)}
  .pg-note-body{padding:5px 8px 3px;white-space:pre-wrap;overflow-wrap:anywhere;cursor:text;max-height:180px;overflow-y:auto}
  .pg-note-body:focus{outline:none;background:rgba(255,255,255,.45)}
  /* Placeholder for the inline editor. It must be generated content, not a real
     child element — a <span> inside contenteditable gets typed into and merged. */
  .pg-note-body[contenteditable]:empty::before{content:'Write your note…';opacity:.45;font-style:italic}
  .pg-note.done .pg-note-body{text-decoration:line-through}
  .pg-note-ph{opacity:.5;font-style:italic}
  .pg-note-meta{padding:0 8px 5px;font-size:8.5px;opacity:.6;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* A note whose corner has been dragged holds that height and scrolls its text
     inside it; an untouched one still sizes to its content. */
  .pg-note.fixh{display:flex;flex-direction:column}
  .pg-note.fixh .pg-note-bar,.pg-note.fixh .pg-note-meta{flex-shrink:0}
  .pg-note.fixh .pg-note-body{flex:1;min-height:0;max-height:none}
  /* The grip is always in the markup and revealed by CSS on selection, NOT added
     by a re-render — rebuilding the layer to show a selection outline destroys the
     node between pointerdown and click, and the click then lands on nothing
     (Known Mistakes #9/#10). Selection is a class toggle, never a render. */
  .pg-note-rz{display:none;position:absolute;right:0;bottom:0;width:15px;height:15px;cursor:nwse-resize;z-index:1;
    background:linear-gradient(135deg,transparent 50%,rgba(15,23,42,.3) 50%)}
  .pg-note.sel .pg-note-rz{display:block}
  .pg-note-dot{position:absolute;pointer-events:auto;width:26px;height:26px;border-radius:50%;
    border:1.5px solid rgba(15,23,42,.2);box-shadow:0 2px 6px rgba(15,23,42,.25);cursor:pointer;
    font-size:11px;font-weight:800;font-family:var(--font);display:flex;align-items:center;justify-content:center;padding:0}
  .pg-note-dot.sel{outline:2px solid var(--accent);outline-offset:1px}
  .pg-note-dot.done{opacity:.62}
  /* notes list panel */
  .pg-nlist{border-top:1px solid var(--border);margin-top:10px;padding-top:9px}
  .pg-nrow{display:flex;align-items:flex-start;gap:7px;border:1px solid var(--border);border-radius:7px;
    padding:6px 8px;margin-bottom:5px;font-size:11.5px;cursor:pointer;background:var(--surface)}
  .pg-nrow:hover{background:var(--accent-light)}
  .pg-nrow.done{opacity:.6}
  .pg-nrow .sw{width:11px;height:11px;border-radius:3px;flex-shrink:0;margin-top:2px;border:1px solid rgba(15,23,42,.18)}
  .pg-nrow .tx{flex:1;min-width:0}
  .pg-nrow .tx b{display:block;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pg-nrow .tx span{display:block;font-size:10px;color:var(--text3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pg-nrow .ac{display:flex;gap:2px;flex-shrink:0}
  .pg-nrow .ac button{border:none;background:none;cursor:pointer;color:var(--text3);font-size:12px;padding:2px 4px;border-radius:4px}
  .pg-nrow .ac button:hover{background:var(--accent-light);color:var(--accent)}
  @media(max-width:600px){
    /* Fewer, bigger targets on a surface you pan and pinch: the collapse button
       moves into the ⋯ menu so the one remaining control can be a true 44pt. */
    .pg-note-bar{min-height:44px}
    .pg-note-ic{min-width:44px;min-height:44px;font-size:17px;display:flex;align-items:center;justify-content:center}
    .pg-note-ic[data-nact="collapse"]{display:none}
    .pg-note-dot{width:34px;height:34px;font-size:12px}
    .pg-nrow{padding:10px 9px}
    .pg-nrow .ac button{min-width:44px;min-height:44px}
  }
  .pg-hint{font-size:10.5px;color:var(--text3);margin-top:7px}
  /* activities table view modal */
  .pg-tbl-md{width:min(1180px,96vw);max-height:92vh;display:flex;flex-direction:column;padding:0;overflow:hidden}
  .pg-tbl-head{display:flex;align-items:center;justify-content:space-between;padding:14px 18px 10px}
  .pg-tbl-head h3{margin:0}
  .pg-tbl-ctrl{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:0 18px 10px}
  .pg-tbl-ctrl label{font-size:11px;font-weight:700;color:var(--text2);display:inline-flex;align-items:center;gap:5px;text-transform:none;letter-spacing:normal}
  .pg-tbl-ctrl input[type=date]{border:1px solid var(--border-strong);border-radius:6px;padding:5px 7px;font-family:var(--font);font-size:12px}
  .pg-tbl-presets{display:inline-flex;gap:5px;flex-wrap:wrap}
  .pg-tbl-q{border:1px solid var(--border-strong);border-radius:7px;padding:6px 10px;font-family:var(--font);font-size:12px;min-width:150px;flex:1}
  .pg-tbl-inc{white-space:nowrap}
  .pg-tbl-cols{display:flex;gap:5px;flex-wrap:wrap;padding:0 18px 10px;border-bottom:1px solid var(--border)}
  .pg-tblchip{font-size:11px;font-weight:600;border:1px solid var(--border-strong);background:var(--surface);color:var(--text2);border-radius:20px;padding:3px 10px;cursor:pointer}
  .pg-tblchip.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .pg-tbl-scroll{overflow:auto;flex:1;min-height:0}
  table.pg-tbl{border-collapse:collapse;width:100%;font-size:12px}
  table.pg-tbl th,table.pg-tbl td{border-bottom:1px solid var(--border);padding:6px 10px;text-align:left;white-space:nowrap;vertical-align:top}
  table.pg-tbl th{position:sticky;top:0;background:var(--surface2,#f1f5f9);font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--text2);z-index:1}
  table.pg-tbl td.r,table.pg-tbl th.r{text-align:right}
  table.pg-tbl tr.s td{background:var(--surface2,#f1f5f9);font-weight:700}
  table.pg-tbl tbody tr:hover td{background:rgba(37,99,235,.06)}
  .pg-tbl-foot{padding:9px 18px;font-size:11.5px;color:var(--text3);border-top:1px solid var(--border)}
  .pg-histo{border-top:2px solid var(--border-strong);background:var(--surface)}
  .pg-histo svg{display:block}
  .pg-histo-axis{position:relative;height:20px;border-top:1px solid var(--border);background:var(--surface)}
  .pg-histo-empty{border-top:2px solid var(--border-strong);padding:12px;font-size:11px;color:var(--text3)}
  /* the swatch shape must follow the CHIP, not one host container — scoped to
     .pg-hleg only, the Resource Centre's copies rendered as zero-size (invisible
     colour): the class-borrowing family again, one level down */
  .pg-legbtn i,.pg-hleg i{display:inline-block;width:10px;height:10px;border-radius:3px;margin:0 3px 0 0;vertical-align:-1px}
  .pg-legbtn{border:1px solid var(--border);background:var(--surface);border-radius:12px;padding:2px 9px 2px 7px;margin:0 3px;font-family:var(--font);font-size:11px;font-weight:600;color:var(--text2);cursor:pointer;line-height:1.5}
  .pg-legbtn:hover{border-color:var(--accent);color:var(--text)}
  .pg-legbtn.off{opacity:.5;text-decoration:line-through}
  .pg-legbtn.off i{filter:grayscale(1)}
  .pg-empty{text-align:center;padding:70px 20px;max-width:460px;margin:0 auto}
  .pg-empty-icn{width:52px;height:52px;border-radius:14px;background:var(--accent-light);color:var(--accent);display:flex;align-items:center;justify-content:center;font-size:24px;margin:0 auto 16px}
  .pg-empty h3{font-size:17px;font-weight:800;margin-bottom:8px}
  .pg-empty p{font-size:12.5px;color:var(--text2);line-height:1.7;margin-bottom:18px}
  .pg-detail{position:fixed;width:322px;max-width:94vw;max-height:80vh;background:var(--surface);border:1px solid var(--border-strong);border-radius:13px;box-shadow:var(--shadow-lg);z-index:120;display:none;flex-direction:column;overflow:hidden}
  .pg-detail.open{display:flex;animation:modalIn .16s var(--ease)}
  .pg-dbar{display:flex;align-items:center;gap:8px;padding:9px 12px;background:var(--th-bg);color:var(--th-text);cursor:move;user-select:none;border-bottom:1px solid var(--border);flex:0 0 auto;touch-action:none}
  .pg-grip{font-size:12px;line-height:1;letter-spacing:-3px;opacity:.6}
  .pg-dtitle{flex:1;font-size:12px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pg-dtitle b{color:var(--accent);margin-right:5px}
  .pg-dbody{padding:14px;overflow-y:auto;flex:1 1 auto}
  .pg-drz{position:absolute;right:0;bottom:0;width:19px;height:19px;cursor:nwse-resize;z-index:5;touch-action:none;background:linear-gradient(135deg,transparent 0 55%,var(--border-strong) 55% 65%,transparent 65% 75%,var(--border-strong) 75% 85%,transparent 85%);border-bottom-right-radius:13px}
  .pg-dpin{background:none;border:0;padding:2px;cursor:pointer;color:var(--th-text);opacity:.65;display:flex;align-items:center;border-radius:5px;flex:0 0 auto}
  .pg-dpin:hover{opacity:1;background:rgba(255,255,255,.14)}
  .pg-dpin.on{opacity:1;color:var(--accent)}
  .pg-dpin svg{width:14px;height:14px}
  /* Pinned to the bottom as a full-width bar (owner-asked 2026-09-15). The
     floating card is untouched and still the default; this is the same panel
     with a different footprint. */
  .pg-detail.dock-b{left:0;right:0;bottom:0;top:auto;width:auto;max-width:none;max-height:none;
    border-radius:0;border-left:0;border-right:0;border-bottom:0;box-shadow:0 -6px 22px rgba(15,23,42,.13)}
  .pg-detail.dock-b .pg-dbar{cursor:default}
  .pg-detail.dock-b .pg-grip,.pg-detail.dock-b .pg-drz{display:none}
  /* Full width, so the body reads in columns instead of one narrow strip down
     the left of a 1440px bar — ONE COLUMN PER SECTION (owner-asked 2026-10-01:
     "make sure sections like predecessors and successors are not starting under
     other sections and always at the top of a new column"). It was a CSS
     multi-column flow, which put each heading wherever the section before it
     happened to end. Each `.pg-dsec` (pgDetailSecs) is now a column of its own
     that scrolls on its own, so a long predecessor list never pushes the next
     section down; when the sections outgrow the window the bar scrolls sideways
     rather than stacking one under another. Desktop only — below 900px the
     panel is a bottom sheet and reads top to bottom like the floating card. */
  @media(min-width:901px){
    .pg-detail.dock-b .pg-dbody{display:flex;align-items:stretch;padding:0;overflow-x:auto;overflow-y:hidden}
    .pg-detail.dock-b .pg-dsec{flex:1 0 250px;max-width:420px;min-width:0;overflow-y:auto;padding:12px 14px;border-left:1px solid var(--border)}
    .pg-detail.dock-b .pg-dsec:first-child{border-left:0;padding-left:16px}
    /* a resource row is five fixed-width fields — give that column the room */
    .pg-detail.dock-b .pg-dsec:has(.pg-lrow.res){flex-basis:300px}
    .pg-detail.dock-b .pg-dsec>.didx-cust-title:first-child{margin-top:0!important}
  }
  .pg-drzt{position:absolute;left:0;right:0;top:0;height:7px;cursor:ns-resize;z-index:6;touch-action:none}
  .pg-drzt:hover{background:var(--accent-light)}
  .pg-dname{width:100%;font-size:13.5px;font-weight:700;margin-bottom:11px;border:1px solid var(--border-strong)!important;border-radius:7px;padding:7px 9px;background:var(--surface)}
  .pg-dhead{display:flex;align-items:center;gap:7px;margin-bottom:9px}
  .pg-drow{display:flex;align-items:center;gap:6px;margin-bottom:8px;font-size:12px;flex-wrap:wrap}
  .pg-drow label{font-size:10.5px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.03em}
  .pg-adurv{flex:1;min-width:0;font-size:12px;color:var(--text)}
  .pg-adurv b{color:#1e40af}
  .pg-adurv .u{color:var(--text3);font-size:11px}
  .pg-drow input,.pg-drow select{border:1px solid var(--border-strong);border-radius:6px;padding:5px 7px;font-family:var(--font);font-size:12px;width:auto;min-width:0;flex:1}
  .pg-drow input[type=number]{width:58px;flex:0 0 auto}
  .pg-drow .u{font-size:10.5px;color:var(--text3)}
  .pg-drow .crit{color:var(--red)}
  .pg-cons{font-size:11px;background:var(--accent-light);color:var(--accent);border-radius:7px;padding:6px 9px;margin-bottom:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  /* deadline status line in the detail panel */
  .pg-dl{font-size:11px;font-weight:600;border-radius:7px;padding:6px 9px;margin:2px 0 8px;line-height:1.4}
  .pg-dl.ok{background:var(--green-light);color:var(--green)}
  .pg-drvlist{font-size:11px;line-height:1.45;border:1px solid #ddd6fe;background:#f5f3ff;border-radius:7px;padding:6px 9px;margin:0 0 8px;color:var(--text2);overflow-wrap:anywhere}
  .pg-drvlist .pg-drvwhy{color:#5b21b6}
  .pg-drvlist ol{margin:5px 0 0;padding-left:18px}
  .pg-drvlist li{margin:1px 0}
  .pg-drvlist .u{color:var(--text3);white-space:nowrap}
  .pg-drvlist .pg-drvsum{color:#b45309;margin-top:3px}
  .pg-drvlist .pg-drvact{font-size:9.5px;font-weight:700;color:#2563eb;border:1px solid #93c5fd;border-radius:3px;padding:0 3px}
  .pg-drvlist.asb{border-color:#a5f3fc;background:#ecfeff}
  .pg-drvlist.asb .pg-drvwhy{color:#155e75}
  .pg-drvlist .pg-drvnote{color:var(--text3);font-size:10.5px;margin-bottom:3px}
  .pg-drvtick{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--text2);cursor:pointer;margin:8px 0 4px;text-transform:none;letter-spacing:normal;font-weight:400}
  .pg-drvtick .u,.pg-drvothers{color:var(--text3);font-size:11px}
  .pg-drvothers{margin:2px 0 8px;display:flex;flex-wrap:wrap;align-items:center;gap:6px}
  .pg-drvlist .pg-drvslip{font-size:10px;font-weight:600;color:#b45309;background:#fef3c7;border-radius:3px;padding:0 4px;white-space:nowrap}
  .pg-dl.tight{background:var(--amber-light);color:var(--amber)}
  .pg-dl.miss{background:var(--red-light,#fee2e2);color:var(--red)}
  /* "N milestones at risk" toolbar pill + a name-cell warning badge */
  .pg-riskchip{font-size:10.5px;font-weight:800;border-radius:12px;padding:3px 10px;white-space:nowrap;cursor:pointer;border:1px solid transparent}
  .pg-riskchip.miss{background:var(--red-light,#fee2e2);color:var(--red);border-color:rgba(220,38,38,.3)}
  .pg-riskchip.tight{background:var(--amber-light);color:var(--amber);border-color:rgba(217,119,6,.3)}
  .pg-mi.miss{color:var(--red)}.pg-mi.tight{color:var(--amber)}
  /* lead-time (procurement / submittal) items */
  .pg-leadchip{display:inline-block;font-size:9.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;padding:1px 7px;border-radius:9px;color:var(--lc,#0891b2);background:color-mix(in srgb,var(--lcb,var(--lc,#0891b2)) 16%,transparent);border:1px solid color-mix(in srgb,var(--lcb,var(--lc,#0891b2)) 38%,transparent);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
  .pg-leadtgt{font-size:12px;color:var(--text2);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}
  .pg-leadtgt:hover{color:var(--accent);text-decoration:underline}
  .pg-leadlink{border:none;background:none;padding:0;font-family:var(--font);font-size:12px;color:var(--accent2);cursor:pointer;text-align:left;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pg-leadlink:hover{text-decoration:underline}
  .pg-risk-badge{font-size:10px;font-weight:800;margin-left:3px;flex-shrink:0}
  /* hold & witness points from the forms (Tier 2.7) — H open hold (it stops progress), W open witness, ✓ all released */
  .pg-hold{flex:none;width:17px;height:17px;margin-right:4px;border-radius:4px;border:none;padding:0;font:800 9.5px/17px var(--font);text-align:center;cursor:pointer;color:#fff;background:#dc2626}
  .pg-hold.wit{background:#d97706}.pg-hold.ok{background:#16a34a}
  .pg-holds{margin:8px 0 6px}
  .pg-hold-row{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid var(--border);border-left:3px solid #dc2626;border-radius:var(--radius-xs);margin-bottom:5px;min-width:0}
  .pg-hold-row.wit{border-left-color:#d97706}.pg-hold-row.ok{border-left-color:#16a34a}
  .pg-hold-st{flex:none;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--text2)}
  .pg-hold-txt{flex:1;min-width:0;font-size:11.5px;overflow-wrap:anywhere}.pg-hold-txt span{color:var(--text3);font-size:10.5px}
  .pg-hold-row .btn{flex:none}
  .pg-risk-badge.miss{color:var(--red)}.pg-risk-badge.tight{color:var(--amber)}
  /* dashboard "milestones at risk" cards */
  .dash-ms-card{display:flex;align-items:center;gap:10px;padding:9px 11px;border:1px solid var(--border);border-left-width:4px;border-radius:8px;margin-bottom:8px;background:var(--surface)}
  .dash-ms-card.miss{border-left-color:var(--red)}
  .dash-ms-card.tight{border-left-color:var(--amber)}
  .dash-ms-diamond{font-size:14px;flex-shrink:0}
  .dash-ms-card.miss .dash-ms-diamond{color:var(--red)}
  .dash-ms-card.tight .dash-ms-diamond{color:var(--amber)}
  .dash-ms-body{flex:1;min-width:0}
  .dash-ms-name{font-size:13px;font-weight:600;color:var(--text);overflow-wrap:anywhere}
  .dash-ms-meta{font-size:11px;color:var(--text2);margin-top:1px}
  .dash-ms-card .btn{flex-shrink:0}
  @media(max-width:600px){.dash-ms-card{flex-wrap:wrap}.dash-ms-card .btn{width:100%;min-height:40px}}
  .dash-tk-card{display:flex;align-items:center;gap:10px;padding:9px 11px;border:1px solid var(--border);border-left-width:4px;border-left-color:var(--border);border-radius:8px;margin-bottom:8px;background:var(--surface)}
  .dash-tk-card.od{border-left-color:var(--red)}
  .dash-tk-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:var(--text-faint)}
  .dash-tk-card.od .dash-tk-dot{background:var(--red)}
  .dash-tk-body{flex:1;min-width:0}
  /* A title runs to 300 characters and this is a summary, not a second task
     list — one of them at full length is seven lines on a phone and swallows
     the tile. Clamped to two, with the whole thing on the element's title and
     the real list one button away, so nothing is hidden without recourse. */
  .dash-tk-name{font-size:13px;font-weight:600;color:var(--text);overflow-wrap:anywhere;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden}
  .dash-tk-tag{display:inline-block;font-size:9.5px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;padding:1px 5px;border-radius:4px;background:var(--surface2);color:var(--text2);vertical-align:1px}
  .dash-tk-meta{font-size:11px;color:var(--text2);margin-top:1px}
  .dash-tk-card.od .dash-tk-meta{color:var(--red)}
  .dash-tk-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-top:2px;font-size:11px;color:var(--text2)}
  .dash-tk-foot span{min-width:0;overflow-wrap:anywhere}
  .dash-tk-foot .btn{flex-shrink:0}
  @media(max-width:600px){.dash-tk-foot .btn{width:100%;min-height:40px}}
  .pg-dnote{font-size:11px;color:var(--text3);padding:4px 0 6px}
  .pg-lrow{display:flex;align-items:center;gap:5px;margin-bottom:5px}
  .pg-lrow .n{flex:1;font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pg-lrow select,.pg-lrow input{border:1px solid var(--border-strong);border-radius:5px;padding:3px 5px;font-family:var(--font);font-size:11px}
  .pg-lrow input[type=number]{width:48px}
  /* Per-link manual visibility override — a plain "no override" state (muted,
     matches .rmv at rest) vs a hard override the user picked on purpose, which
     gets real colour so it reads as deliberate rather than incidental. */
  .pg-lvis{width:18px;height:18px;border-radius:50%;border:1px solid var(--border);background:transparent;color:var(--text3);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:11px;transition:all 0.15s;flex-shrink:0;padding:0}
  .pg-lvis:hover{border-color:var(--border-strong);color:var(--text)}
  .pg-lvis.show{border-color:var(--accent);background:var(--accent);color:#fff}
  .pg-lvis.hide{border-color:var(--red);color:var(--red)}
  .pg-reshead{margin-bottom:2px}
  .pg-reshead span{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text3)}
  /* Resource Centre — a big page, not a strip under the chart */
  .pg-rc{width:min(1240px,96vw);max-height:92vh;overflow:auto}
  .pg-rc-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
  .pg-rc-sum{font-size:11.5px;color:var(--text3);font-weight:600}
  .pg-rc-heads{margin-left:auto;display:flex;gap:6px;flex-wrap:wrap}
  .pg-rc-filters{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:12px}
  .pg-rc-filters input[type=search],.pg-rc-filters input[type=date]{border:1px solid var(--border-strong);border-radius:6px;padding:6px 9px;font-family:var(--font);font-size:12px}
  .pg-rc-filters label{font-size:10.5px;font-weight:700;color:var(--text3);display:flex;align-items:center;gap:5px}
  .pg-rc-seg{margin-left:auto;display:inline-flex;border:1px solid var(--border-strong);border-radius:7px;overflow:hidden}
  .pg-rc-seg button{border:0;background:var(--surface);padding:6px 13px;font-family:var(--font);font-size:11.5px;font-weight:700;cursor:pointer;color:var(--text2)}
  .pg-rc-seg button.on{background:var(--accent);color:#fff}
  .pg-rc-tbl,.pg-rc-plantbl{border-collapse:collapse;width:100%;font-size:12px}
  .pg-rc-tbl th,.pg-rc-plantbl th{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--text3);text-align:left;padding:7px 9px;border-bottom:2px solid var(--border-strong);white-space:nowrap}
  .pg-rc-tbl td,.pg-rc-plantbl td{padding:7px 9px;border-bottom:1px solid var(--border);white-space:nowrap}
  .pg-rc-tbl .r,.pg-rc-plantbl .r{text-align:right}
  .pg-rc-row{cursor:pointer}
  .pg-rc-row:hover td{background:var(--accent-light)}
  .pg-rc-n{font-weight:600}
  .pg-rc-caret{display:inline-block;width:14px;font-size:9px;color:var(--text3)}
  .pg-rc-overchip{font-size:9px;font-weight:800;background:var(--red-light,#fee2e2);color:#b91c1c;border-radius:4px;padding:1px 5px;letter-spacing:.05em}
  .pg-rc-sub td{background:var(--surface2)}
  .pg-rc-subtbl{border-collapse:collapse;width:100%;font-size:11.5px;margin:2px 0 4px}
  .pg-rc-subtbl th{font-size:9.5px;text-transform:uppercase;color:var(--text3);text-align:left;padding:4px 8px}
  .pg-rc-subtbl td{padding:4px 8px;border-top:1px solid var(--border);cursor:pointer}
  .pg-rc-subtbl tr:hover td{background:var(--accent-light)}
  .pg-rc-overs{background:#fef2f2;border:1px solid #fecaca;border-radius:8px;padding:9px 12px;font-size:12px;margin-bottom:12px;color:#7f1d1d}
  .pg-rc-overrow{margin-top:3px}
  .pg-rc-planwrap{overflow-x:auto}
  .pg-rc-actpill{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--border-strong);border-radius:999px;padding:2px 9px;font-size:10.5px;font-weight:700;color:var(--accent);background:var(--surface);white-space:nowrap}
  .pg-rc-row:hover .pg-rc-actpill{border-color:var(--accent)}
  .pg-rc-charts{display:flex;flex-direction:column;gap:8px}
  .pg-rc-chtitle{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text2);margin-top:8px}
  .pg-rc-chtitle span{font-weight:600;text-transform:none;letter-spacing:0;color:var(--text3);margin-left:8px}
  .pg-rc-chempty{font-size:12px;color:var(--text3);padding:10px 0}
  .pg-rc-secrow td{background:var(--surface2);border-top:2px solid var(--border-strong)}
  .pg-rc-actrow{cursor:pointer}
  .pg-rc-actrow:hover td{background:var(--accent-light)}
  .pg-rc-linerow td{color:var(--text2)}
  .pg-rc-dates{font-size:10px;color:var(--text3);margin-left:6px}
  .pg-rc-dctrl{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .pg-rc-dctrl .pg-rc-seg{margin-left:0}
  .pg-rc-dleg{display:flex;gap:5px;flex-wrap:wrap}
  .pg-rc-plantbl tfoot td{border-top:2px solid var(--border-strong)}
  @media(max-width:600px){.pg-rc{width:100vw;max-height:96vh}.pg-rc-filters input[type=search]{flex:1}.pg-rc-seg{margin-left:0;width:100%}.pg-rc-seg button{flex:1;min-height:40px}}
  .pg-lsearch{position:relative;margin:2px 0 10px}
  .pg-lsearch input{width:100%;border:1.5px dashed var(--border-strong);border-radius:7px;padding:6px 9px;font-family:var(--font);font-size:11.5px;background:transparent}
  .pg-lsearch input:focus{border-style:solid;border-color:var(--accent);outline:none;background:var(--surface)}
  .pg-lsr{position:absolute;left:0;right:0;top:calc(100% + 3px);background:var(--surface);border:1px solid var(--border-strong);border-radius:8px;box-shadow:var(--shadow-lg);z-index:30;overflow:hidden;max-height:220px;overflow-y:auto}
  .pg-lsr button{display:block;width:100%;text-align:left;border:none;background:transparent;padding:7px 10px;font-family:var(--font);font-size:11.5px;cursor:pointer;color:var(--text)}
  .pg-lsr button:hover{background:var(--accent-light)}
  .pg-lsr button b{color:var(--text3);font-variant-numeric:tabular-nums;margin-right:4px}
  .pg-lrow.res input:first-child{flex:1;min-width:0}
  .pg-notes{width:100%;border:1px solid var(--border-strong);border-radius:7px;padding:7px 9px;font-family:var(--font);font-size:12px;min-height:56px;resize:vertical}
  /* Working-days dialog: the Mon–Sun week. These <label>s are pick-chips, not
     field captions, so they out-specify `.md label{display:block}` (Known Mistake #7). */
  .pg-cal-h{font-size:12.5px;font-weight:700;color:var(--text);margin:14px 0 4px}
  .md h3+.pg-cal-h{margin-top:2px}
  .pg-wkdays{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:4px}
  .md .pg-wkdays label.pg-wkd{display:inline-flex;align-items:center;gap:6px;margin:0;text-transform:none;letter-spacing:normal;font-weight:600;font-size:12px;color:var(--text2);border:1px solid var(--border-strong);border-radius:8px;padding:6px 10px;min-height:32px;cursor:pointer;user-select:none;background:var(--surface)}
  .md .pg-wkdays label.pg-wkd.on{border-color:var(--accent);background:var(--accent-light);color:var(--text)}
  .md .pg-wkdays label.pg-wkd input{margin:0;width:15px;height:15px;accent-color:var(--accent)}
  @media(max-width:600px){.md .pg-wkdays label.pg-wkd{min-height:44px;padding:6px 12px}}
  .pg-brow{display:flex;align-items:center;gap:9px;border:1px solid var(--border);border-radius:8px;padding:7px 10px;margin-bottom:6px;font-size:12px}
  @media(max-width:900px){
    .pg-detail{left:0!important;right:0!important;top:auto!important;bottom:0!important;width:auto!important;height:auto!important;max-width:none;max-height:60vh;border-radius:14px 14px 0 0}
    /* Below 900px the panel is ALREADY a bottom sheet, so there is nothing for
       the pin to do and no top edge worth dragging — offering either would be a
       control that changes nothing. */
    .pg-drz,.pg-dpin,.pg-drzt{display:none}
    .pg-scroll{height:calc(100vh - var(--vchrome) - 205px)}
  }
  /* Programme on a phone: hide the two dense desktop toolbars, show the compact
     .pg-mobbar (zoom + Table/Chart + Export PDF + Tools). Placed AFTER every
     .pg-* base rule so these win the cascade (.pg-top has a later base display). */
  @media(max-width:600px){
    .pg-top{display:none}
    .pg-mobbar{display:flex}
    .pg-mobpv{display:flex}
    .pg-split,.pg-colrz,.pg-hint{display:none}
    .pg-scroll{height:calc(100vh - 210px);min-height:300px}
    .pg-mobbar .pg-zoom button{font-size:13px}
  }
  #slLib.open{display:flex}
  #slLib .hd{padding:9px;border-bottom:1px solid var(--border)}
  #slLib .hd input{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-xs);padding:7px 10px;font-size:12px;font-family:var(--font)}
  #slLib .bd{overflow-y:auto;padding:8px}
  /* Category jump chips. One wrapping row, capped in height so the tiles keep
     most of the panel; the strip scrolls if the list of categories grows. */
  .sl-libcats{display:flex;flex-wrap:wrap;gap:4px;margin-top:7px;max-height:120px;overflow-y:auto}
  .sl-libcats button{border:1px solid var(--border-strong);background:var(--surface);color:var(--text2);border-radius:20px;padding:3px 9px;font-size:10.5px;font-weight:700;font-family:var(--font);cursor:pointer;white-space:nowrap}
  .sl-libcats button:hover{border-color:var(--accent);color:var(--accent)}
  .sl-libcats button.on{background:var(--accent);border-color:var(--accent);color:#fff}
  /* On a phone the chips would wrap to six rows and eat the whole panel, which
     puts the later categories out of reach again. One swipeable row instead —
     the standard mobile filter-chip pattern — so every category stays
     reachable at a cost of ~30px. Placed after the base rules above so it
     wins the cascade (the .pg-top trap). */
  @media(max-width:600px){
    .sl-libcats{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;max-height:none;-webkit-overflow-scrolling:touch;scrollbar-width:none}
    .sl-libcats::-webkit-scrollbar{display:none}
    .sl-libcats button{padding:6px 11px;font-size:11.5px}
  }
  .sl-lib-cat{font-size:9px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);margin:8px 2px 4px}
  .sl-lib-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:4px}
  .sl-lib-it{border:1px solid transparent;background:transparent;border-radius:8px;font-size:21px;padding:5px 0;cursor:pointer;text-align:center;display:flex;align-items:center;justify-content:center;min-height:34px}
  .sl-lib-it:hover{background:var(--accent-light);border-color:var(--accent)}
  .sl-lib-it.on{outline:2px solid var(--accent)}
  .sl-lib-it svg{color:var(--text)}
  .sl-lib-pro{font-size:8px;font-weight:800;letter-spacing:.05em;color:var(--accent);background:var(--accent-light);border-radius:8px;padding:1px 6px;vertical-align:1px}
  /* isometric symbols carry real artwork — a 24px tile in a 6-col grid is unreadable */
  .sl-lib-pro.iso{color:#c2410c;background:#ffedd5}
  .sl-lib-grid.iso{grid-template-columns:repeat(3,1fr);gap:6px}
  /* signs are full-colour plates — 4 across at 42px so the red/blue/yellow
     actually reads, without the 3-across bulk the isometric artwork needs */
  .sl-lib-pro.sym{color:#0369a1;background:#e0f2fe}
  .sl-lib-manage{float:right;border:0;background:none;color:var(--accent);font-size:9.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;padding:0;font-family:var(--font)}
  .sl-lib-grid.sym{grid-template-columns:repeat(4,1fr);gap:5px}
  .sl-lib-it.sym{min-height:50px}
  /* deliberately NOT .sl-lib-it — it is an action, not a stamp, and must not be
     counted as one by anything that enumerates the library */
  .sl-lib-add{border:1.5px dashed var(--border-strong);background:transparent;border-radius:8px;color:var(--text3);font-size:20px;font-weight:600;cursor:pointer;min-height:50px;display:flex;align-items:center;justify-content:center;font-family:var(--font)}
  .sl-lib-add:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-light)}
  .sl-lib-it img{max-width:100%;max-height:100%;object-fit:contain}
  .sl-symlist{display:flex;flex-direction:column;gap:6px;max-height:52vh;overflow-y:auto}
  .sl-symrow{display:flex;align-items:center;gap:10px;border:1px solid var(--border);border-radius:8px;padding:6px 9px}
  .sl-symrow img{width:40px;height:40px;object-fit:contain;flex-shrink:0;background:#fff;border-radius:5px}
  .sl-symrow .nm{flex:1;min-width:0;font-size:12.5px;font-weight:700;color:var(--text);overflow-wrap:anywhere}
  /* a list row is a scan target — clamp to two lines so one long name can't
     push the row to five (the full name is in the rename dialog) */
  .sl-symrow .nm{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .sl-symrow .nm .sub{-webkit-line-clamp:1}
  .sl-symrow .nm .sub{display:block;font-size:10.5px;font-weight:500;color:var(--text3);margin-top:1px}
  .sl-lib-it.iso{min-height:60px;padding:2px 0}
  @media(max-width:600px){.sl-lib-it.iso{min-height:64px}}

  /* Print styles for PDF export */
  @media print{
    body{background:#fff!important}
    .print-page{background:#fff;color:#000;font-family:Georgia,serif;padding:20mm;max-width:none}
    .print-page h1{font-size:20pt;border-bottom:2pt solid #333;padding-bottom:8pt;margin-bottom:16pt}
    .print-page h2{font-size:14pt;margin:16pt 0 6pt;color:#1a3a8a}
    .print-page table{width:100%;border-collapse:collapse;margin-bottom:14pt;font-size:10pt}
    .print-page th{background:#1a3a8a;color:#fff;padding:5pt 8pt;text-align:left;font-size:9pt}
    .print-page td{padding:4pt 8pt;border-bottom:0.5pt solid #ccc;vertical-align:top}
    .print-page tr:nth-child(even) td{background:#f5f5f5}
    .print-page .meta-grid{display:grid;grid-template-columns:1fr 1fr;gap:8pt;margin-bottom:16pt;padding:10pt;border:1pt solid #ccc;border-radius:4pt}
    .print-page .meta-item label{font-size:8pt;text-transform:uppercase;color:#666;display:block;margin-bottom:2pt}
    .print-page .meta-item span{font-size:11pt;font-weight:bold}
    .print-page .notes-box{border:1pt solid #ccc;padding:10pt;border-radius:4pt;min-height:40pt;font-size:10pt;line-height:1.5;white-space:pre-wrap}
    .print-page .footer{margin-top:20pt;font-size:8pt;color:#999;border-top:0.5pt solid #ccc;padding-top:8pt;display:flex;justify-content:space-between}
  }
  /* ── AI Assistant tab ── */
  .tab-ai svg{color:var(--accent)}
  .ai-wrap{max-width:1180px;margin:0 auto;display:flex;flex-direction:column;height:calc(100vh - var(--vchrome) - 137px);min-height:440px}
  /* The conversation list beside the transcript. min-height:0 on both the row
     and the column is what lets the two scrollers actually scroll — a flex item
     defaults to min-height:auto, which refuses to shrink below its content and
     pushes the whole page instead. */
  .ai-body{flex:1;display:flex;gap:14px;min-height:0}
  .ai-col{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0}
  .ai-side{width:248px;flex-shrink:0;display:flex;flex-direction:column;min-height:0;
    border:1px solid var(--border);border-radius:14px;background:var(--surface2);overflow:hidden}
  .ai-side-h{display:flex;align-items:center;gap:6px;padding:11px 13px 9px;font-size:11px;font-weight:700;
    letter-spacing:.05em;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border)}
  .ai-side-n{margin-left:auto;font-weight:600;letter-spacing:0;color:var(--text-faint)}
  .ai-list{flex:1;overflow-y:auto;padding:7px}
  .ai-conv{position:relative;display:block;width:100%;text-align:left;border:1px solid transparent;
    background:none;border-radius:9px;padding:8px 26px 8px 10px;font-family:var(--font);cursor:pointer;
    color:var(--text2);transition:.12s}
  .ai-conv:hover{background:var(--surface);border-color:var(--border)}
  .ai-conv.on{background:var(--accent-light);border-color:var(--accent2-light);color:var(--text)}
  /* Two lines, then an ellipsis — a question can be a paragraph, and a list row
     that grows to fit one stops being a list. */
  .ai-conv-t{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
    font-size:12.5px;line-height:1.35;font-weight:500;overflow-wrap:anywhere}
  .ai-conv.on .ai-conv-t{font-weight:600}
  .ai-conv-w{display:block;margin-top:3px;font-size:10.5px;color:var(--text-faint);font-variant-numeric:tabular-nums}
  /* The delete affordance is a SPAN, not a nested <button> — a button inside a
     button is invalid and the browser drops the inner one, so the × would never
     receive a click at all. */
  .ai-conv-x{position:absolute;top:5px;right:5px;width:20px;height:20px;border-radius:6px;display:none;
    align-items:center;justify-content:center;font-size:15px;line-height:1;color:var(--text-faint);cursor:pointer}
  .ai-conv:hover .ai-conv-x,.ai-conv.on .ai-conv-x{display:flex}
  .ai-conv-x:hover{background:var(--red-light);color:var(--red)}
  .ai-conv-empty{padding:14px 12px;font-size:12px;line-height:1.55;color:var(--text-faint)}
  .ai-head{display:flex;gap:12px;align-items:flex-start;margin-bottom:14px}
  .ai-badge{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
  .ai-badge.lg{width:50px;height:50px;font-size:26px;border-radius:15px;margin:0 auto 14px}
  .ai-title{font-size:17px;font-weight:700;color:var(--text)}
  .ai-sub{font-size:12.5px;color:var(--text3);line-height:1.5;max-width:66ch}
  /* The two conversation controls. margin-left:auto rather than a fixed width,
     so the sub-line keeps its 66ch measure and these sit at the far edge
     whatever the header wraps to. */
  .ai-acts{display:flex;gap:6px;margin-left:auto;flex-shrink:0;align-items:center}
  /* The list is a COLUMN on a desktop and a panel on a phone, so this button
     only exists below the breakpoint. Scoped to 0,2,0 deliberately: the bare
     `.ai-act{display:inline-flex}` sits LATER in this sheet and would beat a
     0,1,0 rule at equal specificity — Known Mistake #7, one more time. */
  .ai-acts .ai-act-list{display:none}
  .ai-act{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--border-strong);
    background:var(--surface);color:var(--text2);border-radius:9px;padding:6px 10px;
    font-family:var(--font);font-size:12px;font-weight:500;cursor:pointer;
    white-space:nowrap;min-height:34px;transition:.15s}
  .ai-act:hover{border-color:var(--accent);color:var(--accent)}
  .ai-act .ic{width:13px;height:13px}
  /* A message's own time. It sits OUTSIDE the bubble so a long answer's last
     line is never re-flowed around it, and the column flips with the message so
     the stamp is always on the bubble's outer edge. */
  .ai-msg{align-items:flex-end;gap:7px}
  .ai-when{font-size:10.5px;color:var(--text-faint);white-space:nowrap;padding-bottom:3px;
    font-variant-numeric:tabular-nums;flex-shrink:0}
  .ai-msg.user .ai-when{order:-1}
  /* Day and "New chat" rules. One grid row, the label centred in a hairline. */
  .ai-rule{display:flex;align-items:center;gap:10px;margin:4px 0 2px;color:var(--text-faint);
    font-size:11px;font-weight:500;letter-spacing:.02em}
  .ai-rule::before,.ai-rule::after{content:'';flex:1;height:1px;background:var(--border)}
  .ai-rule span{flex-shrink:0}
  .ai-msgs{flex:1;overflow-y:auto;border:1px solid var(--border);border-radius:14px;background:var(--surface2);padding:16px;display:flex;flex-direction:column;gap:12px}
  .ai-empty{margin:auto;text-align:center;max-width:440px;color:var(--text3)}
  .ai-empty h3{font-size:18px;color:var(--text);margin-bottom:7px;font-weight:700}
  .ai-empty p{font-size:13px;line-height:1.6}
  .ai-msg{display:flex}
  .ai-msg.user{justify-content:flex-end}
  .ai-bubble{max-width:82%;padding:11px 14px;border-radius:15px;font-size:13.5px;line-height:1.55;word-wrap:break-word;overflow-wrap:anywhere}
  .ai-msg.user .ai-bubble{background:var(--accent);color:#fff;border-bottom-right-radius:4px}
  .ai-msg.bot .ai-bubble{background:var(--surface);border:1px solid var(--border);color:var(--text);border-bottom-left-radius:4px}
  .ai-bubble.err{background:var(--red-light);border-color:#f3c9c9;color:var(--red)}
  .ai-bubble b{font-weight:700}
  .ai-bubble code{background:var(--surface2);padding:1px 5px;border-radius:4px;font-size:12px;font-family:var(--mono,monospace)}
  .ai-bubble ul,.ai-bubble ol{margin:5px 0 5px 20px}
  .ai-bubble li{margin:2px 0}
  .ai-bubble h4{font-size:13.5px;font-weight:700;margin:8px 0 3px}
  .ai-bubble .ai-sp{height:7px}
  .ai-bubble .ai-tblwrap{max-width:100%;overflow-x:auto;margin:7px 0}
  .ai-bubble .ai-tbl{border-collapse:collapse;font-size:12.5px;font-variant-numeric:tabular-nums}
  .ai-bubble .ai-tbl th,.ai-bubble .ai-tbl td{border:1px solid var(--border);padding:5px 9px;text-align:left}
  .ai-bubble .ai-tbl th{background:var(--surface2);font-weight:700}
  .ai-bubble.thinking{display:inline-flex;gap:5px;align-items:center}
  .ai-bubble.thinking span{width:6px;height:6px;border-radius:50%;background:var(--text-faint);animation:aiBlink 1.2s infinite}
  .ai-bubble.thinking span:nth-child(2){animation-delay:.2s}
  .ai-bubble.thinking span:nth-child(3){animation-delay:.4s}
  @keyframes aiBlink{0%,60%,100%{opacity:.25}30%{opacity:1}}
  .ai-chips{display:flex;flex-wrap:wrap;gap:7px;margin-top:12px}
  .ai-chip{border:1px solid var(--border-strong);background:var(--surface);color:var(--text2);border-radius:16px;padding:6px 12px;font-family:var(--font);font-size:12px;cursor:pointer;transition:.15s}
  .ai-chip:hover{border-color:var(--accent);color:var(--accent)}
  .ai-input{display:flex;gap:8px;margin-top:12px;align-items:flex-end}
  .ai-input textarea{flex:1;resize:none;border:1px solid var(--border-strong);border-radius:11px;padding:11px 13px;font-family:var(--font);font-size:13.5px;line-height:1.4;color:var(--text);background:var(--surface);max-height:160px}
  .ai-input textarea:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
  .ai-input .btn{height:44px}
  .ai-foot{font-size:11px;color:var(--text-faint);margin-top:9px;text-align:center}
  /* Below 900px the list would leave the transcript too narrow to read, so it
     becomes a panel over it, opened by the Chats button and closed the moment a
     conversation is picked (askCloseList). */
  @media(max-width:900px){
    .ai-acts .ai-act-list{display:inline-flex}
    .ai-body{position:relative}
    .ai-side{position:absolute;left:0;top:0;bottom:0;z-index:5;width:min(280px,82%);
      background:var(--surface);box-shadow:var(--shadow-lg);display:none}
    .ai-wrap.list-open .ai-side{display:flex}
  }
  @media(max-width:640px){.ai-wrap{height:calc(100vh - 210px)}.ai-bubble{max-width:82%}
    .ai-head{flex-wrap:wrap}.ai-acts{margin-left:0;width:100%}
    .ai-when{font-size:10px}}

/* ── Tasks nav badge — how much this person owes, without opening anything.
   Amber once something is overdue rather than red: the work is late, nothing
   is broken. `margin-left:auto` pushes it to the item's trailing edge; in the
   collapsed rail the label is hidden, so it tucks onto the icon instead. ── */
.sn-badge{margin-left:auto;flex-shrink:0;min-width:18px;height:18px;padding:0 5px;border-radius:9px;
  background:var(--surface2,#e2e8f0);color:var(--text2,#475569);font-size:10.5px;font-weight:700;
  line-height:18px;text-align:center;letter-spacing:.2px}
.sn-badge.od{background:#b45309;color:#fff}
.sidenav.rail .sn-it .sn-badge{display:block;position:absolute;top:4px;right:4px;margin-left:0;min-width:16px;height:16px;line-height:16px;padding:0 4px;font-size:9.5px}
.sidenav.rail .sn-it{position:relative}
/* The phone bottom bar's Tasks item carries data-tab too, so it gets the count
   as well — and in the FLOW it would add its own 18px plus the button's 3px gap
   to a 5-item column-stacked row, making the whole bar taller. .main reserves a
   FIXED calc(78px + safe-area) for that bar, so a taller bar simply covers what
   sits at the foot of the page: the planner phone step caught it as a 3px
   overlap the moment the app started rendering the badge at all. Known Mistake
   #25's rule with the bottom nav as the victim — a thing that appears must not
   occupy layout.

   So on the bar it is a corner pip on the icon, which is the native tab-bar
   convention and the same shape the collapsed rail already uses. It takes the
   ACCENT rather than the sidebar's grey, deliberately: at 15px overlapping an
   icon, grey-on-white is not a notification, and the accent is org-derived so
   it still follows whoever's app it is. Overdue keeps the same amber the
   sidebar uses, restated here because this block out-specifies `.sn-badge.od`. */
.mobnav .mn-it{position:relative}
.mobnav .mn-it .sn-badge{position:absolute;top:2px;left:calc(50% + 5px);margin-left:0;
  min-width:15px;height:15px;line-height:15px;padding:0 4px;border-radius:8px;font-size:9px;
  background:var(--accent,#2563eb);color:#fff;box-shadow:0 0 0 2px var(--surface,#fff)}
.mobnav .mn-it .sn-badge.od{background:#b45309}

/* The text callout's Label is a paragraph, not a name — a one-line input showed
   about four words of it with no way to read the rest. It grows to its own text
   (slLblGrow), capped so it can never push the controls under it off screen. */
.sl-lblbox{width:100%;box-sizing:border-box;resize:none;min-height:38px;line-height:1.4;
  font-family:inherit;overflow-wrap:anywhere}

/* ── pending invitations (Admin → Organization) ─────────────────────────────
   An email address is long and a phone is narrow, so the row wraps rather than
   truncating: an address cut in half cannot be checked against the one the
   admin typed, which is the only thing this list is for. */
.org-inv-hd{font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--text3);margin:12px 0 6px;padding-top:10px;border-top:1px solid var(--border)}
.org-inv-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:6px 0;
  border-bottom:1px solid var(--border)}
.org-inv-row:last-child{border-bottom:0}
.org-inv-who{flex:1 1 180px;min-width:0;font-size:12.5px;overflow-wrap:anywhere}
.org-inv-sub{display:block;font-size:11px;color:var(--text3);font-weight:400}
.org-inv-chip{flex-shrink:0;font-size:10.5px;font-weight:700;padding:3px 8px;border-radius:999px;
  background:var(--surface2);color:var(--text2);border:1px solid var(--border)}
.org-inv-chip.lapsed{background:var(--amber-light,#fef3c7);color:var(--amber,#b45309);border-color:transparent}
@media(max-width:600px){.org-inv-row .btn{min-height:44px}}

  /* The page-level horizontal scrollbar, pinned to the bottom of the window.
     See sxSync() — one bar for the page, positioned over whichever wide table
     currently needs it. Below the phone nav (290) and every modal (350) on
     purpose: it is table furniture, not chrome. */
  .sx-bar{position:fixed;bottom:0;z-index:120;display:none;height:15px;
    overflow-x:auto;overflow-y:hidden;background:var(--surface);
    border-top:1px solid var(--border);box-shadow:0 -2px 10px rgba(15,23,42,.10)}
  .sx-bar.on{display:block}
  .sx-bar>div{height:1px}
  /* A touch device draws an overlay bar and scrolls a table by swiping it, so a
     permanent 15px strip there would be furniture nobody asked for. */
  @media(pointer:coarse){.sx-bar{display:none!important}}
  /* A dialog owns the screen; a bar for the table behind it would float over
     nothing the person can reach. */
  body:has(.mo.open) .sx-bar,body:has(#planModal.active) .sx-bar{display:none!important}

  /* ── Working with no signal: the bar that says what the app is working from (woBar) ── */
  .wo-bar{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:330;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
    width:max-content;max-width:calc(100vw - 32px);box-sizing:border-box;padding:8px 12px;border-radius:12px;
    background:#1e293b;color:#f8fafc;font-size:12.5px;line-height:1.4;box-shadow:0 8px 28px rgba(15,23,42,.28)}
  .wo-bar span{min-width:0;overflow-wrap:anywhere;flex:1 1 220px}
  .wo-bar .ic{flex:0 0 auto;width:16px;height:16px;stroke:currentColor}
  .wo-bar.back{background:#14532d}
  .wo-btn{flex:0 0 auto;border:1px solid rgba(255,255,255,.4);background:transparent;color:inherit;border-radius:8px;padding:5px 12px;font:inherit;font-weight:600;cursor:pointer;min-height:32px}
  .wo-bar .wo-out{flex:0 0 auto;background:rgba(255,255,255,.14);border-radius:999px;padding:3px 10px;font-weight:600;cursor:pointer;white-space:nowrap}
  .wo-fail{max-width:320px;margin:0 auto;text-align:center;line-height:1.5}
  .wo-fail .wo-btn{margin-top:12px;border-color:var(--border-strong);color:var(--text)}
  @media (max-width:600px){.wo-bar{bottom:calc(76px + env(safe-area-inset-bottom))}}
  body:has(.mo.open) .wo-bar,body:has(.mobsheet.open) .wo-bar{display:none}
  /* the outbox: photos still on this phone (woQueuedTag, woOutOpen) */
  .wo-q{position:absolute;left:4px;top:4px;z-index:2;background:rgba(15,23,42,.82);color:#fff;font-size:10.5px;font-weight:600;line-height:1;padding:4px 6px;border-radius:6px;pointer-events:none;white-space:nowrap}
  .wo-q.bad{background:#b91c1c}
  .wo-olist{display:flex;flex-direction:column;gap:8px;max-height:min(55vh,420px);overflow:auto;margin:6px 0 4px}
  .wo-orow{display:flex;align-items:center;gap:10px;border:1px solid var(--border);border-radius:10px;padding:6px}
  .wo-orow img{width:52px;height:52px;object-fit:cover;border-radius:6px;flex:0 0 auto;background:var(--surface2)}
  .wo-otx{display:flex;flex-direction:column;min-width:0;flex:1 1 auto;font-size:12px;color:var(--text2);overflow-wrap:anywhere}
  .wo-otx b{color:var(--text);font-size:12.5px}
  .wo-oerr{color:#b91c1c}
/* Programme Export PDF: options beside a live preview of the sheet (pgExportPreview).
   Below 900px there is no room for a legible sheet, so the dialog is the options alone
   and pgExportPreview skips building (the iframe has no offsetParent). */
.md.pg-xmd{width:min(1240px,96vw);max-width:96vw;display:grid;grid-template-columns:minmax(360px,440px) 1fr;grid-template-rows:minmax(0,1fr) auto;column-gap:18px;height:min(880px,92vh);height:min(880px,92dvh);overflow:hidden}
.md.pg-xmd>.pg-xset{overflow:auto;min-height:0;padding-right:6px}
.md.pg-xmd>.macts{grid-column:1/-1}
.pg-xpvw{display:flex;flex-direction:column;min-height:0;min-width:0}
.pg-xpvh{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text3);margin:2px 0 6px}
.pg-xpvh span{font-weight:400;text-transform:none;letter-spacing:0;margin-left:6px}
#pgXpv{flex:1 1 auto;min-height:0;width:100%;border:1px solid var(--border);border-radius:8px;background:#e5e7eb}
@media (max-width:900px){
  .md.pg-xmd{display:block;width:auto;height:auto;overflow:auto}
  .md.pg-xmd>.pg-xset{overflow:visible;padding-right:0}
  .pg-xpvw{display:none}
}

/* ══ Daily diary on a phone, phase 1 (2026-10-17) ═════════════════════════
   Plan: /mnt/project-files/diary-redesign/diary-phone-plan.md. Bob's word for
   the phone diary was "cluttered". Four things, all at ≤600px, the desktop
   untouched:
   1. ONE date bar: ‹ date › and ⋯, weather as a chip under the date, "Today"
      only when you are not on today (.on-today, dnTodaySync).
   2. The cost strip becomes a hero card that says in words how the day went
      (.dsum-say), the figures beneath it.
   3. Clearing resources / the matrix and refreshing WBS live in the ⋯ sheet —
      the biggest controls on the core screen were the ones that wipe it.
   4. Headings in sentence case; the new-issue form opens on demand.
   Placed last so it wins over the earlier phone toolbar rules at equal
   specificity. */
.ni-open{display:none}
.dsum-say{display:none}
@media(max-width:600px){
  .day-nav{display:grid;grid-template-columns:40px minmax(0,1fr) 40px 44px;grid-template-rows:auto auto;
    column-gap:6px;row-gap:3px;align-items:center;padding:8px 10px 9px}
  .day-nav>.nav-btn[aria-label="Previous day"]{grid-column:1;grid-row:1/3;justify-self:start}
  .day-nav>.nav-btn[aria-label="Next day"]{grid-column:3;grid-row:1/3;justify-self:end}
  .day-nav>.dn-tools{grid-column:4;grid-row:1/3;justify-self:end;min-height:40px}
  .day-nav>.dn-brk{display:none!important}
  .day-label{grid-column:2;grid-row:1;font-size:16px!important;font-weight:700;letter-spacing:-.01em}
  .day-nav>div:last-child{grid-column:2;grid-row:2;justify-self:center;flex:0 1 auto;max-width:100%}
  .day-nav>.btn.dn-today{grid-column:2;grid-row:2;justify-self:end;padding:3px 10px;min-height:30px;border-radius:999px}
  .day-nav:not(.on-today)>div:last-child{justify-self:start}
  .day-nav.on-today>.btn.dn-today{display:none}
  .day-nav .wx-sel{-webkit-appearance:none;appearance:none;flex:0 1 auto;width:auto;max-width:100%;min-height:30px;
    padding:2px 26px 2px 11px;border-radius:999px;border:1px solid transparent;background-color:var(--accent-light);
    color:var(--accent2);font-weight:500;text-overflow:ellipsis;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%231e3a8a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat:no-repeat;background-position:right 9px center}

  /* the hero: same outer edge and inner padding as the resources card, so the
     cost figure stays on the diary's one heading rail */
  .dsum{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px 18px;padding:15px 16px 16px;margin-bottom:14px;
    border:1px solid transparent;border-radius:var(--radius);color:#fff;
    background:linear-gradient(135deg,#1e3a8a 0%,#2563eb 100%);box-shadow:0 6px 18px rgba(30,58,138,.22)}
  .dsum-c:first-child{flex:1 1 100%}
  .dsum-say{display:block;flex:1 1 100%;margin-top:-6px}
  .dsum-say>span{display:inline-block;font-size:12.5px;font-weight:600;line-height:1.3;padding:4px 10px;
    border-radius:999px;background:rgba(255,255,255,.16);color:#fff}
  .dsum-say.bad>span{background:rgba(254,202,202,.22);color:#fee2e2}
  .dsum-say.warn>span{background:rgba(253,230,138,.2);color:#fef3c7}
  .dsum-say.ok>span{background:rgba(187,247,208,.2);color:#dcfce7}
  .dsum-l{text-transform:none;letter-spacing:0;font-size:11.5px;font-weight:500;color:rgba(255,255,255,.75)}
  .dsum-v{font-size:15px;color:#fff}
  .dsum-c:first-child .dsum-v{font-size:30px;letter-spacing:-.02em;line-height:1.1}
  .dsum-c:first-child .dsum-l{font-size:12px}
  .dsum-v.ok{color:#bbf7d0}
  .dsum-v.bad{color:#fecaca}
  .dsum-v.mut{color:rgba(255,255,255,.85)}

  /* clearing and refreshing → the ⋯ sheet; the formula caption → gone */
  .res-clear,.mx-formula,.mx-wbs,.mx-clear{display:none!important}

  /* sentence case — capitals with tracking read as a form, not a diary */
  .sct,.res-panel-title,.rgt,.ni-cap{text-transform:none!important;letter-spacing:normal!important}
  .res-panel-title{font-size:15px;font-weight:600;color:var(--text)}
  .rgt{font-size:13.5px;font-weight:600}

  /* the new-issue form, on demand */
  .ni-open{display:inline-flex;margin-bottom:10px}
  .ni-open.on{color:var(--text2)}
  .ni-box:not(.open){display:none}
}

/* ══ Daily diary on a phone, phase 2 (2026-10-18) — the day at a glance ═════
   Screen A of the plan. The diary opens on the hero card and a checklist
   (#dgOv, dgRender); a row opens its part of the day on its own (dgOpen →
   #tab-diary.dg-in, the section carrying .dg-on), and a back bar takes the date
   bar's place. Sections are hidden by CSS only — nothing moves in the DOM, so
   every handler and save path is the desktop's. Desktop: none of this shows. */
.dg-ov,.dg-bar{display:none}
@media(max-width:600px){
  #tab-diary:not(.dg-in) [data-dsec]{display:none!important}
  #tab-diary.dg-in [data-dsec]:not(.dg-on){display:none!important}
  body.dg-in #tab-diary .dsum,#tab-diary.dg-in .dg-ov{display:none!important}
  body.dg-in #dayNav{display:none!important}
  #tab-diary:not(.dg-in) .dg-ov{display:block}
  body.dg-in #tab-diary.dg-in .dg-bar{display:flex}

  .dg-h{display:flex;align-items:center;gap:8px;margin:2px 2px 8px}
  .dg-ht{font-size:15px;font-weight:600;color:var(--text)}
  .dg-hc{font-size:12.5px;color:var(--text3);flex:1;min-width:0}
  .dg-st{font-size:11.5px;font-weight:600;padding:3px 10px;border-radius:999px;background:var(--surface2);color:var(--text2);border:1px solid var(--border)}
  .dg-st.fin{background:#dcfce7;color:#166534;border-color:#bbf7d0}
  .dg-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
  .dg-row{display:flex;align-items:center;gap:12px;width:100%;min-height:60px;padding:11px 14px;border:0;border-top:1px solid var(--border);
    background:none;text-align:left;font:inherit;color:inherit;cursor:pointer}
  .dg-row:first-child{border-top:0}
  .dg-row:active{background:var(--surface2)}
  .dg-ic{flex:none;width:36px;height:36px;border-radius:11px;display:grid;place-items:center}
  .dg-ic .ic{width:18px;height:18px;margin:0}
  .dg-t-blue{background:#eff5ff;color:#2563eb}
  .dg-t-orange{background:#fff7ed;color:#c2410c}
  .dg-t-green{background:#f0fdf4;color:#15803d}
  .dg-t-purple{background:#fdf4ff;color:#a21caf}
  .dg-t-red{background:#fef2f2;color:#b91c1c}
  .dg-t-grey{background:#f1f5f9;color:#475569}
  .dg-m{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .dg-n{font-size:14px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}
  .dg-d{font-size:12.5px;color:var(--text3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .dg-bad{font-size:11px;font-weight:600;padding:1px 7px;border-radius:999px;background:#fee2e2;color:#b91c1c}
  .dg-ck{flex:none;width:24px;height:24px;border-radius:50%;border:1.5px solid var(--border);display:grid;place-items:center}
  .dg-ck.on{background:#16a34a;border-color:#16a34a;color:#fff}
  .dg-ck .ic{width:14px;height:14px;margin:0;stroke-width:3}
  .dg-fin{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:48px;margin:14px 0 6px;
    border-radius:var(--radius);border:1px solid #16a34a;background:#16a34a;color:#fff;font:inherit;font-size:14.5px;font-weight:600;cursor:pointer}
  .dg-fin .ic{width:18px;height:18px;margin:0}
  .dg-fin.on{background:var(--surface);color:#166534;border-color:#bbf7d0}

  .dg-bar{position:sticky;top:0;z-index:20;align-items:center;gap:8px;margin:-4px -6px 12px;padding:8px 10px;
    background:var(--surface);border-bottom:1px solid var(--border)}
  .dg-back{flex:none;width:40px;height:40px;border-radius:10px;border:1px solid var(--border);background:var(--surface);
    display:grid;place-items:center;color:var(--text);cursor:pointer}
  .dg-back .ic{width:20px;height:20px;margin:0}
  .dg-bt{flex:1;min-width:0}
  .dg-bn{font-size:16px;font-weight:700;color:var(--text);letter-spacing:-.01em}
  .dg-bs{font-size:12px;color:var(--text3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}

/* ══ Daily diary on a phone, phase 3 (2026-10-18) — work done as cards ═════
   Screens B and C of the plan. #mxCards holds one card per activity
   (mxCardsRender); a card opens #mxActSheet with a −/+ stepper per person
   (mxActOpen). #tab-diary.mxc-on = the Cards view, which hides the matrix and its
   caption; Grid brings them back. Desktop: none of this shows. */
.mxc-seg,.mxc{display:none}
@media(max-width:600px){
  #tab-diary .mxc-seg{display:flex;gap:3px;padding:3px;margin:0 0 12px;border-radius:10px;background:var(--surface2);border:1px solid var(--border)}
  .mxc-seg button{flex:1;min-height:36px;border:0;border-radius:8px;background:none;font:inherit;font-size:13.5px;color:var(--text2);cursor:pointer}
  .mxc-seg button.on{background:var(--surface);color:var(--text);font-weight:600;box-shadow:0 1px 2px rgba(15,23,42,.1)}
  #tab-diary.mxc-on .mxc{display:block}
  #tab-diary.mxc-on .mx-cap,#tab-diary.mxc-on .twrap{display:none!important}

  .mxc-card{display:block;background:var(--surface);border:1px solid var(--border);border-left:4px solid #2563eb;border-radius:var(--radius);
    padding:12px 14px;margin-bottom:10px;cursor:pointer;text-align:left}
  .mxc-card:active{background:var(--surface2)}
  .mxc-card.dw{border-left-color:#c2410c}
  .mxc-top{display:flex;align-items:flex-start;gap:10px}
  .mxc-t{flex:1;min-width:0;font-size:14.5px;font-weight:600;color:var(--text);line-height:1.35;overflow-wrap:anywhere;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  .mxc-untitled{color:var(--text3);font-weight:500}
  .mxc-tag{flex:none;font-size:11px;font-weight:600;padding:2px 8px;border-radius:999px;background:#eff5ff;color:#1e40af}
  .mxc-card.dw .mxc-tag{background:#fff7ed;color:#c2410c}
  .mxc-w{font-size:12.5px;color:var(--text3);margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxc-nolink{color:#b45309;display:flex;align-items:center;gap:5px}
  .mxc-nolink .ic{width:13px;height:13px;margin:0;flex:none}
  .mxc-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
  /* the name gives way, the hours never do: a long name ellipsizes before its figure */
  .mxc-chip{display:inline-flex;align-items:baseline;gap:5px;font-size:12px;padding:3px 9px;border-radius:999px;background:#eff5ff;color:#1e3a8a;max-width:100%;box-sizing:border-box;white-space:nowrap}
  .mxc-cn{min-width:0;overflow:hidden;text-overflow:ellipsis}
  .mxc-chip b{flex:none;font-weight:700}
  .mxc-chip.mxc-plant{background:#fff7ed;color:#9a3412}
  .mxc-chip.mxc-sub{background:#f0fdf4;color:#166534}
  .mxc-none{font-size:12px;color:var(--text3)}
  .mxc-fig{display:flex;gap:8px;margin-top:10px;padding-top:9px;border-top:1px solid var(--border)}
  .mxc-fig>span{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
  .mxc-fig i{font-style:normal;font-size:11.5px;color:var(--text3)}
  .mxc-fig b{font-size:14px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxc-fig .over b{color:var(--red)}
  .mxc-dwh{font-size:13px;font-weight:600;color:#c2410c;margin:16px 2px 8px}
  .mxc-empty{font-size:13px;color:var(--text3);background:var(--surface);border:1px dashed var(--border-strong);border-radius:var(--radius);padding:16px;margin-bottom:12px;text-align:center}
  .mxc-add{display:flex;gap:8px;margin-top:4px}
  .mxc-add .btn{flex:1;min-height:44px;justify-content:center;font-size:14px}
  .mxc-add .ic{width:16px;height:16px}
  .mxc-adddw{color:#b45309;border-color:#f3c39b}
  .mxc-copy{width:100%;min-height:44px;margin-top:8px;justify-content:center}

  .mxs{max-height:90vh;max-height:90dvh;display:flex;flex-direction:column;padding-bottom:0}
  .mxs-h{display:flex;align-items:center;gap:10px;padding:0 2px 12px;border-bottom:1px solid var(--border)}
  .mxs-hl{flex:1;min-width:0}
  .mxs-ht{font-size:16px;font-weight:700;color:var(--text)}
  .mxs-fig{font-size:12.5px;color:var(--text3);font-variant-numeric:tabular-nums}
  .mxs-fig .over{color:var(--red);font-weight:600}
  .mxs-done{min-height:44px;padding:0 18px}
  .mxs-body{overflow-y:auto;-webkit-overflow-scrolling:touch;padding:4px 2px calc(18px + env(safe-area-inset-bottom))}
  .mxs-l{display:block;font-size:12.5px;font-weight:600;color:var(--text2);margin:14px 0 6px}
  .mxs-desc,.mxs-qu input{width:100%;box-sizing:border-box;border:1px solid var(--border-strong);border-radius:10px;padding:10px 12px;font:inherit;font-size:16px;background:var(--surface);color:var(--text)}
  .mxs-desc{resize:vertical;min-height:64px}
  .mxs-wbs{display:block;width:100%;text-align:left;min-height:44px;border:1px solid var(--border-strong);border-radius:10px;padding:10px 12px;
    background:var(--surface);font:inherit;font-size:14px;color:var(--text);cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxs-wbs.none{color:#b45309;border-style:dashed}
  .mxs-qu{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .mxs-qu .mxs-l{margin-top:14px}
  .mxs-lock{display:flex;align-items:center;gap:6px;min-height:44px;padding:0 12px;border-radius:10px;background:var(--surface2);color:var(--text2);font-size:14px}
  .mxs-lock .ic{width:14px;height:14px;margin:0}
  .mxs-p{display:flex;align-items:center;gap:10px;padding:8px 0;border-top:1px solid var(--border)}
  .mxs-p.zero .mxs-pn{opacity:.55}
  .mxs-pn{flex:1;min-width:0;display:flex;flex-direction:column}
  .mxs-pnm{font-size:14px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxs-pn small{font-size:12px;color:var(--text3)}
  .mxs-stp{flex:none;display:flex;align-items:center;gap:4px}
  .mxs-stp button{width:44px;height:44px;border-radius:12px;border:1px solid var(--border-strong);background:var(--surface);font-size:22px;line-height:1;color:var(--accent2);cursor:pointer}
  .mxs-stp button:active{background:var(--accent-light)}
  .mxs-stp input{width:58px;height:44px;box-sizing:border-box;text-align:center;border:1px solid var(--border-strong);border-radius:10px;font:inherit;font-size:16px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--text);background:var(--surface)}
  .mxs-noppl{font-size:13px;color:var(--text3);padding:6px 0}
  .mxs-clear{display:flex;align-items:center;gap:6px;margin:18px auto 4px;border:0;background:none;color:var(--text3);font:inherit;font-size:13px;cursor:pointer;min-height:40px}
  .mxs-clear .ic{width:15px;height:15px;margin:0}
}

/* ══ Work done on a phone: the grid, the crew strip, the hour dock (2026-10-18)
   Option A+D of /mnt/project-files/work-done-grid/. #mxGrid (mxGridRender) is the
   Grid view: people as columns with their day total, the activity column pinned
   left and Σ pinned right while a big crew scrolls between them. #mxCell is the
   docked hour editor. .mxk-crew/.mxk-sum are shared with the Cards view. Sheet
   (#tab-diary without .mxc-on) is the full matrix, restyled light on a phone and
   on a phone turned sideways. Desktop: none of this shows. */
.mxk-sum,.mxk-crew{display:none}
.nj-hint{font-size:12px;color:var(--text3);margin:-4px 0 10px}
@media(max-width:600px){
  .mxk-crew{display:flex;gap:6px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:0 -2px 10px;padding:2px}
  .mxk-crew::-webkit-scrollbar{display:none}
  .mxk-pp{flex:none;width:68px;display:flex;flex-direction:column;align-items:center;gap:3px;padding:8px 2px 7px;border-radius:12px;background:var(--surface);border:1px solid var(--border);font-size:11.5px;color:var(--text2)}
  .mxk-pn{max-width:62px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mx-av{display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;color:#fff;font-size:11px;font-weight:600;flex:none;letter-spacing:0}
  .mx-av.lg{width:38px;height:38px;font-size:13px}
  .mx-dt{font-size:11px;font-weight:600;padding:1px 6px;border-radius:6px;font-variant-numeric:tabular-nums;white-space:nowrap}
  .mx-dt.ok{background:#e8f6ee;color:#15803d}
  .mx-dt.lo,.mx-dt.hi,.mx-dt.none{background:#fef3c7;color:#b45309}
  .mx-dt.pl{background:var(--surface2);color:var(--text2)}

  .mxk-sum{display:block;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:11px 14px 10px;margin-bottom:12px}
  .mxk-kp{display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap}
  .mxk-kp>span{display:flex;flex-direction:column}
  .mxk-kp i{font-style:normal;font-size:11.5px;color:var(--text3)}
  .mxk-kp b{font-size:17px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums}
  .mxk-kp .over b{color:var(--red)}
  .mxk-kp .mxk-flag{margin-left:auto;align-self:center;font-size:11.5px;font-weight:600;padding:4px 8px;border-radius:7px;background:#fef3c7;color:#b45309;flex-direction:row;max-width:100%;overflow-wrap:anywhere}
  .mxk-bar{height:6px;border-radius:3px;background:#f3c4c4;margin-top:9px;overflow:hidden}
  .mxk-bar:not(.over){background:#dcefe3}
  .mxk-bar i{display:block;height:100%;background:#16a34a;border-radius:3px}
  .mxk-line{font-size:12.5px;color:var(--text3);margin-top:5px}
  .mxk-line.over{color:var(--red);font-weight:600}
  .mxk-line.good{color:#15803d;font-weight:600}
  .mxc-cost{font-size:12.5px;color:var(--text3);margin-top:9px}

  /* the activity sheet: quick values under each person's stepper */
  .mxs-p{flex-wrap:wrap}
  .mxs-q{flex-basis:100%;display:flex;gap:6px;padding-bottom:2px}
  .mxs-q button{flex:1;min-width:0;height:36px;border-radius:9px;border:1px solid var(--border);background:var(--surface2);font:inherit;font-size:13.5px;font-weight:600;color:var(--text2);cursor:pointer}
  .mxs-q button.on{border-color:#2563eb;background:#eaf1ff;color:#1d4ed8}

  /* ── the grid ── */
  #tab-diary.mxg-on #mxCards{display:none}
  #tab-diary:not(.mxg-on) #mxGrid{display:none}
  #mxGrid{min-width:0;max-width:100%}
  .mxg{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);margin-bottom:6px;overscroll-behavior-x:contain}
  .mxg-in{min-width:100%;width:max-content}
  .mxg-r{display:flex;min-width:100%;border-bottom:1px solid var(--border);background:var(--surface)}
  .mxg-a{flex:1 0 132px;width:132px;max-width:168px;position:sticky;left:0;z-index:2;background:inherit;padding:8px 6px 8px 12px;
    box-shadow:4px 0 8px -6px rgba(15,23,42,.28);cursor:pointer;min-width:0;text-align:left}
  .mxg-r.dw .mxg-a{box-shadow:inset 3px 0 0 #f59e0b,4px 0 8px -6px rgba(15,23,42,.28)}
  .mxg-d{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere;font-size:13px;line-height:1.3;color:var(--text)}
  .mxg-un{color:var(--text3)}
  .mxg-m{display:block;font-size:11px;line-height:1.3;color:var(--text3);margin-top:3px;overflow-wrap:anywhere}
  .mxg-m b{font-weight:500;color:var(--text2)}
  .mxg-m .over{color:var(--red);font-weight:600}
  .mxg-lk{color:#2563eb;font-weight:500}
  .mxg-c{flex:none;width:48px;display:grid;place-items:center;padding:4px 0}
  .mxg-s{flex:none;width:48px;position:sticky;right:0;z-index:2;display:grid;place-items:center;background:var(--surface2);
    font-size:13.5px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;box-shadow:-4px 0 8px -6px rgba(15,23,42,.28)}
  .mxg-v{width:40px;height:40px;border-radius:10px;border:0;background:none;font:inherit;font-size:14.5px;font-weight:600;font-variant-numeric:tabular-nums;color:#cbd5e1;cursor:pointer;padding:0}
  .mxg-v.f{background:#eaf1ff;color:#1d4ed8}
  .mxg-v.fp{background:#fdf0e6;color:#c2410c}
  .mxg-v.fs{background:#e8f6ee;color:#15803d}
  .mxg-v.e{font-weight:400}
  .mxg-v.sel{background:#2563eb;color:#fff;box-shadow:0 0 0 3px rgba(37,99,235,.28)}
  .mxg-r.sel-r,.mxg-r.sel-r .mxg-a{background:#f7faff}
  .mxg-c.sel-c{background:#f2f7ff}
  .mxg-hd .mxg-a{display:flex;align-items:flex-end;font-size:11.5px;color:var(--text3);cursor:default;padding-bottom:10px}
  .mxg-hd .mxg-s{font-size:11px;font-weight:500;color:var(--text3)}
  .mxg-p{flex-direction:column;gap:2px;padding:8px 0 7px;font-size:10.5px;color:var(--text2);display:flex;align-items:center}
  .mxg-pn{max-width:46px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxg-p .mx-dt{font-size:10.5px;padding:1px 4px}
  .mxg-sec,.mxg-add{border-bottom:1px solid var(--border)}
  .mxg-st{position:sticky;left:0;display:flex;align-items:center;gap:8px;width:var(--mxg-w,100%);box-sizing:border-box;padding:0 12px}
  .mxg-sec{background:var(--surface2)}
  .mxg-sec .mxg-st{min-height:36px;font-size:12.5px;font-weight:600;color:var(--text2)}
  .mxg-sec em{margin-left:auto;font-style:normal;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap}
  .mxg-sec.dw{background:#fff4ea}
  .mxg-sec.dw .mxg-st{color:#c2410c}
  .mxg-add .mxg-st{min-height:44px;gap:14px}
  .mxg-add button{display:inline-flex;align-items:center;gap:5px;border:0;background:none;padding:0;min-height:40px;font:inherit;font-size:13.5px;font-weight:600;color:#2563eb;cursor:pointer}
  .mxg-add.dw button{color:#c2410c}
  .mxg-add .ic{width:15px;height:15px;margin:0}
  .mxg-add .mxg-copy{color:var(--text3);font-weight:500}

  /* ── the docked hour editor ── */
  .mxk{position:fixed;left:0;right:0;bottom:0;z-index:345;background:var(--surface);border-top:1px solid var(--border);border-radius:18px 18px 0 0;
    box-shadow:0 -10px 30px rgba(15,23,42,.16);padding:8px 16px calc(14px + env(safe-area-inset-bottom))}
  .mxk-grab{width:36px;height:4px;border-radius:2px;background:#d6dce6;margin:0 auto 10px}
  .mxk-t{display:flex;align-items:center;gap:10px}
  .mxk-tt{flex:1;min-width:0;display:flex;flex-direction:column}
  .mxk-tt b{font-size:15px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxk-tt small{font-size:12.5px;color:var(--text3)}
  .mxk-warn{color:#b45309;font-weight:600}
  .mxk-x{width:44px;height:44px;border-radius:10px;border:1px solid var(--border);background:var(--surface);display:grid;place-items:center;color:var(--text2);cursor:pointer;flex:none}
  .mxk-x .ic{width:16px;height:16px;margin:0}
  .mxk-big{display:flex;align-items:center;gap:10px;margin:12px 0 10px}
  .mxk-big>button{width:54px;height:50px;border-radius:12px;border:1px solid var(--border-strong);background:var(--surface);font-size:24px;line-height:1;color:var(--accent2);cursor:pointer;flex:none}
  .mxk-big input{flex:1;min-width:0;height:50px;border:0;text-align:right;font:inherit;font-size:30px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--text);background:none;padding:0}
  .mxk-u{flex:1;font-size:15px;color:var(--text3)}
  .mxk-q{display:flex;gap:7px}
  .mxk-q button{flex:1;min-width:0;height:44px;border-radius:10px;border:1px solid var(--border);background:var(--surface);font:inherit;font-size:15px;font-weight:600;color:var(--text2);cursor:pointer}
  .mxk-q button.on{border-color:#2563eb;background:#eaf1ff;color:#1d4ed8}
  .mxk-act{display:flex;gap:10px;margin-top:10px}
  .mxk-act .btn{min-height:46px;justify-content:center;font-size:14.5px;flex:1}
  .mxk-act .btn-blue{flex:1.5;min-width:0}
  .mxk-act .btn-blue{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mxk-act .ic{width:16px;height:16px;margin:0 0 0 2px}
  body.mxk-open #tab-diary.active{padding-bottom:330px}
  body.mxk-open .dg-fab{display:none!important}
}
/* ── Sheet: the full matrix, light, on a phone and on a phone turned sideways ── */
@media(max-width:600px){
  #tab-diary:not(.mxc-on) .mx-formula{display:none}
}
@media(max-width:600px),(orientation:landscape) and (max-height:500px){
  #tab-diary table.mx thead th{background:var(--surface)!important;color:var(--text2)!important;border-color:var(--border)!important}
  #tab-diary table.mx thead tr:first-child th{border-bottom:0!important}
  #tab-diary table.mx thead th.thl{box-shadow:inset 0 -2px 0 #93b4f5}
  #tab-diary table.mx thead th.thp{box-shadow:inset 0 -2px 0 #f5b98a}
  #tab-diary table.mx thead th.ths{box-shadow:inset 0 -2px 0 #86d3a5}
  #tab-diary table.mx thead tr:nth-child(2) th.tha{color:transparent!important}
  #tab-diary table.mx .mx-th-rate{opacity:1!important;color:var(--text3)}
  #tab-diary table.mx .mx-sec-div{background:#fff4ea!important;color:#c2410c!important;border-color:#f6d3b5!important;letter-spacing:0!important;text-transform:none!important;font-size:12px!important}
}

/* D: the phone turned sideways, in Work done — the matrix alone, full screen */
.mx-sidebar{display:none}
@media (orientation:landscape) and (max-height:500px){
  body.mx-side .mx-sidebar{display:flex;position:fixed;left:0;right:0;top:0;z-index:401;height:52px;align-items:center;gap:10px;
    padding:0 max(14px,env(safe-area-inset-right)) 0 max(14px,env(safe-area-inset-left));background:var(--surface);border-bottom:1px solid var(--border)}
  .mx-side-x{width:40px;height:40px;border-radius:10px;border:1px solid var(--border);background:var(--surface);display:grid;place-items:center;color:var(--text2);cursor:pointer;flex:none}
  .mx-side-x .ic{width:16px;height:16px;margin:0}
  .mx-side-t{font-size:13px;color:var(--text3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .mx-side-t b{font-size:15px;color:var(--text)}
  .mx-side-k{margin-left:auto;display:flex;gap:14px;font-size:12px;color:var(--text3);white-space:nowrap}
  .mx-side-k b{font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}
  .mx-side-k .over b{color:var(--red)}
  .mx-sidebar .btn{flex:none;min-height:36px}
  .mx-sidebar .btn .ic{width:14px;height:14px}
  .mx-sidebar .mx-side-dw{color:#c2410c;border-color:#f3c39b}
  body.mx-side #tab-diary .twrap{position:fixed;left:0;right:0;top:52px;bottom:0;z-index:400;border:0;border-radius:0;margin:0;overflow:auto;
    padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right);display:block!important}
  body.mx-side #tab-diary table.mx thead th{position:sticky;top:0;z-index:3}
  body.mx-side #tab-diary table.mx thead tr:nth-child(2) th{top:var(--mx-h1,38px)}
  body.mx-side #tab-diary table.mx thead th.tha{left:0;z-index:4}
  body.mx-side #tab-diary table.mx td.tda,body.mx-side #tab-diary table.mx .tr-tot td:first-child,body.mx-side #tab-diary table.mx .tr-sub td:first-child{position:sticky;left:0;z-index:2}
  body.mx-side .mobnav,body.mx-side .dg-fab{display:none!important}
}

/* ══ Daily diary on a phone, phase 4 (2026-10-18) — Add, swipe, polish ══════
   Screen D of the plan: one Add button (#dgFab → dgAddSheet), a start card on a
   day with nothing in it, a slide when the day changes by swipe (dgSwipe) and
   when a section opens. Motion is dropped for anyone who asked for less. */
.dg-fab{display:none}
@media(max-width:600px){
  #tab-diary.active .dg-fab{display:inline-flex}
  .dg-fab{position:fixed;right:16px;bottom:calc(84px + env(safe-area-inset-bottom));z-index:280;align-items:center;gap:6px;
    height:52px;padding:0 20px 0 16px;border-radius:999px;border:0;background:#2563eb;color:#fff;font:inherit;font-size:15px;font-weight:600;
    box-shadow:0 10px 26px rgba(37,99,235,.38);cursor:pointer}
  .dg-fab .ic{width:22px;height:22px;margin:0;stroke-width:2.4}
  .dg-fab:active{transform:scale(.96)}
  body:has(.mobsheet.open) .dg-fab,body:has(.mo.open) .dg-fab,body:has(#planModal.active) .dg-fab{display:none}
  /* room under the last row so the button never sits on it */
  #tab-diary.active{padding-bottom:72px}

  .dga-h{font-size:16px;font-weight:700;color:var(--text);margin:0 2px 12px}
  .dga-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
  .dga-it{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;min-height:78px;padding:10px 6px;
    border-radius:14px;border:1px solid var(--border);background:var(--surface2);font:inherit;font-size:13px;font-weight:500;color:var(--text);cursor:pointer}
  .dga-it .ic{width:22px;height:22px;margin:0;color:#2563eb}
  .dga-it[data-dga="finish"] .ic{color:#16a34a}
  .dga-it:active{background:var(--accent-light)}

  .dg-start{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-bottom:14px}
  .dg-start-t{font-size:16px;font-weight:700;color:var(--text)}
  .dg-start-d{font-size:13px;color:var(--text3);margin-top:4px;line-height:1.45}
  .dg-start-b{display:flex;gap:8px;margin-top:12px}
  .dg-start-b .btn{flex:1;min-height:44px;justify-content:center;font-size:14px}
  .dg-start-b .ic{width:16px;height:16px}

  @media (prefers-reduced-motion:no-preference){
    /* the parts, never the tab: a transform on #tab-diary would carry the fixed
       Add button with it for the length of the slide */
    #tab-diary.dg-swl :is(.dsum,.dg-ov,.dg-on){animation:dgSwL .26s ease-out}
    #tab-diary.dg-swr :is(.dsum,.dg-ov,.dg-on){animation:dgSwR .26s ease-out}
    body.dg-in #tab-diary.dg-in .dg-on{animation:dgIn .2s ease-out}
    .mobsheet.open .mobsheet-panel.mxs,.mobsheet.open .mobsheet-panel.dga-panel{animation:dgUp .22s ease-out}
  }
}
@keyframes dgSwL{from{opacity:.4;transform:translateX(28px)}to{opacity:1;transform:none}}
@keyframes dgSwR{from{opacity:.4;transform:translateX(-28px)}to{opacity:1;transform:none}}
@keyframes dgIn{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}
@keyframes dgUp{from{transform:translateY(40px);opacity:.6}to{transform:none;opacity:1}}

/* ══ Daily diary on a phone, phase 5 (2026-10-18) — week strip + All Diaries inbox ══
   Bob picked option A (date bar) and option 1 (All Diaries) from
   /mnt/project-files/diary-overview/. The bar: the short date (#dnTtl → month
   sheet), the weather as a line-icon chip (#wxChip, the real select invisible on
   top of it), the ⋯, then this week (#dnWk). All Diaries: .didx-ph header, one
   summary line, .didx-prow rows or the month grid. Desktop: none of this shows. */
.dn-ttl,.dn-wk,.wx-chip,.didx-ph,.didx-ph-sum{display:none}
@media(max-width:600px){
  .day-nav{grid-template-columns:minmax(0,1fr) auto 44px;grid-template-rows:auto auto;column-gap:8px;row-gap:8px;padding:8px 12px 10px}
  .day-nav>.nav-btn,.day-nav>.day-label,.day-nav>.btn.dn-today{display:none!important}
  .day-nav>.dn-ttl{display:inline-flex;grid-column:1;grid-row:1;justify-self:start;align-items:center;gap:4px;min-height:40px;max-width:100%;
    padding:0 6px 0 2px;border:0;background:none;font:inherit;font-size:21px;font-weight:700;letter-spacing:-.02em;color:var(--text);cursor:pointer}
  .dn-ttl span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .dn-ttl .ic{flex:none;width:16px;height:16px;margin:0;color:var(--text3);stroke-width:2.4}
  .day-nav>div:last-child,.day-nav:not(.on-today)>div:last-child{grid-column:2;grid-row:1;justify-self:end;position:relative;max-width:46vw}
  .day-nav>.dn-tools{grid-column:3;grid-row:1;justify-self:end}
  .day-nav>.dn-wk{display:block;grid-column:1/-1;grid-row:2;min-width:0;touch-action:pan-y}
  /* the weather chip: what you see; the select over it is what you tap */
  .wx-chip,.day-nav>div:last-child>.wx-chip{display:inline-flex}
  .wx-chip{align-items:center;gap:5px;max-width:100%;height:34px;padding:0 12px;border-radius:999px;
    background:var(--accent-light);color:var(--accent);font-size:13.5px;font-weight:600;white-space:nowrap;pointer-events:none}
  .wx-chip .ic{flex:none;width:17px;height:17px;margin:0}
  .wx-chip b{font-weight:700}
  .wx-chip span{color:var(--text2);font-weight:500;overflow:hidden;text-overflow:ellipsis}
  .day-nav .wx-sel,.day-nav .wx-sel:focus{position:absolute;inset:0;width:100%;height:100%;min-height:0;max-width:none;margin:0;padding:0;
    opacity:0;border:0;background:none;font-size:16px;cursor:pointer}
  .day-nav>div:last-child:focus-within .wx-chip{box-shadow:var(--ring)}
  /* the week */
  .dn-days{display:flex;gap:4px}
  .dn-d{flex:1;min-width:0;height:60px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
    border:0;border-radius:13px;background:none;font:inherit;color:var(--text);cursor:pointer;padding:0}
  .dn-d small{font-size:10.5px;font-weight:600;color:var(--text3);letter-spacing:.02em;text-transform:uppercase}
  .dn-d b{font-size:17px;font-weight:650;font-variant-numeric:tabular-nums;line-height:1.1}
  .dn-d.we b,.dn-d.we small,.dn-d.fut b{color:var(--text-faint)}
  .dn-d.tdy{box-shadow:inset 0 0 0 1.5px var(--accent)}
  .dn-d.sel{background:var(--accent);box-shadow:0 4px 12px rgba(37,99,235,.3)}
  .dn-d.sel small,.dn-d.sel b{color:#fff}
  .dn-d:not(.sel):active{background:var(--surface2)}
  .dn-dot{display:block;width:7px;height:7px;border-radius:50%;box-sizing:border-box;border:1.5px solid transparent}
  .dn-dot.p{background:#16a34a}
  .dn-dot.d{background:#f59e0b}
  .dn-d .dn-dot:not(.p):not(.d){border-color:var(--border-strong)}
  .dn-d.fut .dn-dot:not(.p):not(.d){border-color:transparent}
  .dn-d.sel .dn-dot{background:#fff;border-color:#fff}
  .dn-d.sel .dn-dot:not(.p):not(.d){background:none;border-color:rgba(255,255,255,.7)}
  .dn-sub{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:6px;min-height:22px;font-size:12.5px;color:var(--text3)}
  .dn-back{border:0;background:none;padding:2px 0;font:inherit;font-size:13px;font-weight:600;color:var(--accent);cursor:pointer;min-height:32px}
  /* the month sheet */
  .dnm-h{display:flex;align-items:center;gap:4px;margin:0 0 10px}
  .dnm-h b{font-size:17px;color:var(--text)}
  .dnm-sp{flex:1}
  .dnm-nav{width:36px;height:36px;border:0;border-radius:10px;background:none;display:grid;place-items:center;color:var(--text3);cursor:pointer}
  .dnm-nav .ic{width:18px;height:18px;margin:0}
  .dnm-today,.dnm-todo{display:inline-flex;align-items:center;gap:4px;min-height:34px;padding:0 13px;border-radius:999px;border:1px solid #d6e4ff;
    background:var(--accent-light);color:var(--accent);font:inherit;font-size:13px;font-weight:600;cursor:pointer}
  .dnm-todo{background:#fef3c7;border-color:#fde68a;color:#b45309}
  .dnm-todo .ic{width:14px;height:14px;margin:0}
  .dnm-g{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;text-align:center}
  .dnm-wd{font-size:11px;font-weight:600;color:var(--text-faint);padding-bottom:4px}
  .dnm-c{height:46px;border:0;border-radius:12px;background:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    font:inherit;font-size:15px;font-weight:600;color:var(--text);cursor:pointer;padding:0}
  .dnm-c.out{cursor:default}
  .dnm-c.we{color:var(--text-faint);font-weight:500}
  .dnm-c.fut{color:#cbd5e1}
  .dnm-c.tdy{box-shadow:inset 0 0 0 1.5px var(--accent)}
  .dnm-c.sel{background:var(--accent);color:#fff}
  .dnm-c.sel .dn-dot.p,.dnm-c.sel .dn-dot.d{background:#fff}
  .dnm-f{display:flex;align-items:center;gap:12px;margin-top:12px;font-size:12.5px;color:var(--text3)}
  .dnm-k{display:inline-flex;align-items:center;gap:5px}

  /* ── All Diaries ── */
  body:has(#tab-diary-list.active) #dayNav{display:none!important}
  #tab-diary-list #didxRangeBar,#tab-diary-list #didxKpis,#tab-diary-list .didx-toolbar,#tab-diary-list #didxStrip{display:none!important}
  .didx-ph{display:block;margin:-2px 0 4px}
  .didx-ph-sum{display:block}
  #tab-diary-list.didx-calon .didx-ph-seg,#tab-diary-list.didx-calon .didx-ph-srch,#tab-diary-list.didx-calon .didx-ph-sum{display:none}
  .didx-ph-r{display:flex;align-items:center;gap:8px}
  .didx-ph-t{flex:1;margin:0;font-size:27px;font-weight:700;letter-spacing:-.025em;color:var(--text)}
  .didx-ph-b{width:42px;height:42px;border-radius:12px;border:1px solid var(--border);background:var(--surface);display:grid;place-items:center;color:var(--text2);cursor:pointer}
  .didx-ph-b .ic{width:19px;height:19px;margin:0}
  .didx-ph-b.on{background:var(--accent-light);border-color:#d6e4ff;color:var(--accent)}
  .didx-ph-seg{display:flex;gap:3px;padding:3px;margin-top:12px;border-radius:12px;background:#eef2f8}
  .didx-ph-seg button{flex:1;min-width:0;min-height:38px;display:flex;align-items:center;justify-content:center;gap:6px;border:0;border-radius:9px;background:none;
    font:inherit;font-size:13.5px;font-weight:600;color:var(--text2);cursor:pointer;white-space:nowrap}
  .didx-ph-seg button.active{background:var(--surface);color:var(--text);box-shadow:0 1px 3px rgba(15,23,42,.1)}
  .didx-ph-seg .n{font-size:11.5px;font-weight:700;border-radius:999px;padding:1px 7px;background:#fef3c7;color:#b45309}
  .didx-ph-seg .n:empty{display:none}
  .didx-ph-srch{display:flex;align-items:center;gap:8px;height:44px;margin-top:10px;padding:0 12px;border-radius:12px;background:var(--surface);border:1px solid var(--border);color:var(--text-faint)}
  .didx-ph-srch .ic{flex:none;width:17px;height:17px;margin:0}
  .didx-ph-srch input{flex:1;min-width:0;height:100%;border:0;background:none;font:inherit;font-size:16px;color:var(--text);outline:none}
  .didx-ph-srch:focus-within{box-shadow:var(--ring);border-color:var(--accent)}
  .didx-ph-sum{margin:12px 0 2px}
  .didx-ph-per{display:flex;align-items:center;gap:4px}
  .didx-ph-pc{display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:100%;min-height:34px;padding:0 12px;border-radius:999px;border:1px solid var(--border);
    background:var(--surface);font:inherit;font-size:13px;font-weight:600;color:var(--text2);cursor:pointer}
  .didx-ph-pc span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .didx-ph-pc .ic{flex:none;width:15px;height:15px;margin:0}
  .didx-ph-nv{flex:none;width:34px;height:34px;border:0;border-radius:10px;background:none;display:grid;place-items:center;color:var(--text3);cursor:pointer}
  .didx-ph-nv .ic{width:18px;height:18px;margin:0}
  .didx-ph-tot{margin-top:8px;font-size:13px;color:var(--text3)}
  .didx-ph-tot b{color:var(--text);font-weight:650;font-variant-numeric:tabular-nums}
  #tab-diary-list .didx-month{margin-top:16px}
  .didx-plist{background:var(--surface);border:1px solid var(--border);border-radius:16px;overflow:hidden}
  .didx-prow{display:flex;align-items:center;gap:12px;padding:11px 12px 11px 14px;border-top:1px solid var(--border);cursor:pointer;min-height:70px}
  .didx-prow:first-child{border-top:0}
  .didx-prow:active{background:var(--surface2)}
  .didx-prow.sel{background:var(--accent-light)}
  .didx-plist .didx-gap{border-radius:0;border:0;border-top:1px dashed var(--border-strong);margin:0;width:100%;min-height:44px}
  .didx-plist .didx-gap:first-child{border-top:0}
  .didx-p-date{flex:none;width:46px;height:50px;border-radius:12px;background:var(--surface2);display:flex;flex-direction:column;align-items:center;justify-content:center}
  .didx-p-date small{font-size:10px;font-weight:700;color:var(--text3);letter-spacing:.05em;text-transform:uppercase}
  .didx-p-date b{font-size:19px;line-height:1.1;color:var(--text);font-variant-numeric:tabular-nums}
  .didx-p-date.todo{background:#fef3c7}
  .didx-p-date.todo small{color:#b45309}
  .didx-prow.today .didx-p-date{box-shadow:inset 0 0 0 1.5px var(--accent)}
  .didx-p-m{flex:1;min-width:0}
  .didx-p-l1{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 9px;font-size:15px}
  .didx-p-l1 b{font-weight:650;color:var(--text);font-variant-numeric:tabular-nums}
  .didx-p-l1 .didx-team{margin-left:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .didx-p-vs{font-size:12.5px;font-weight:500;color:var(--text3)}
  .didx-p-vs.neg{color:var(--red);font-weight:600}
  .didx-p-vs.pos{color:var(--green);font-weight:600}
  .didx-p-none{font-size:14px;color:var(--text3)}
  .didx-p-l2{display:flex;align-items:center;flex-wrap:wrap;gap:4px 12px;margin-top:5px;font-size:12.5px;color:var(--text3);font-variant-numeric:tabular-nums}
  .didx-p-l2>span{display:inline-flex;align-items:center;gap:3px}
  .didx-p-l2 .ic{width:14px;height:14px;margin:0}
  .didx-p-l2 .alert{color:#b45309}
  .didx-p-ok{color:#16a34a}
  .didx-p-go{flex:none;color:var(--text-faint);display:grid}
  .didx-p-go .ic{width:16px;height:16px;margin:0}
  .didx-prow .didx-selwrap{flex:none}
  /* the month grid */
  .didx-calh{display:flex;align-items:center;gap:2px;margin:6px 0 10px}
  .didx-calh b{font-size:18px;color:var(--text)}
  .didx-calc{flex:1;text-align:right;font-size:12.5px;color:var(--text3)}
  .didx-calc em{font-style:normal;font-weight:600;color:#b45309}
  .didx-calg{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;padding:10px 8px;background:var(--surface);border:1px solid var(--border);border-radius:16px}
  .didx-cwd{font-size:11px;font-weight:600;color:var(--text-faint);text-align:center;padding:2px 0 4px}
  .didx-cc{height:50px;min-width:0;border:0;border-radius:11px;background:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
    font:inherit;font-size:14px;font-weight:650;color:var(--text);cursor:pointer;padding:0;font-variant-numeric:tabular-nums}
  .didx-cc small{font-size:9.5px;font-weight:600;max-width:100%;overflow:hidden;text-overflow:clip;white-space:nowrap}
  .didx-cc.out{cursor:default}
  .didx-cc.ok{background:#dcfce7;color:#166534}
  .didx-cc.todo{background:#fef3c7;color:#92400e}
  .didx-cc.none{color:var(--text-faint);font-weight:500}
  .didx-cc.fut{color:#d5dbe5;font-weight:500}
  .didx-cc.tdy{box-shadow:inset 0 0 0 1.5px var(--accent)}
  .didx-cc.sel{box-shadow:0 0 0 2px var(--accent)}
  .didx-cp{margin-top:12px;padding:14px;background:var(--surface);border:1px solid var(--border);border-radius:16px}
  .didx-cp-h{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
  .didx-cp-h b{font-size:16px;color:var(--text)}
  .didx-cp-s{display:flex;align-items:center;gap:4px;margin-top:2px;font-size:12.5px;color:var(--text3)}
  .didx-cp-s .ic{width:14px;height:14px;margin:0}
  .didx-cp-st{flex:none;font-size:11.5px;font-weight:700;padding:3px 9px;border-radius:999px;background:var(--surface2);color:var(--text2)}
  .didx-cp-st.todo{background:#fef3c7;color:#b45309}
  .didx-cp-st.ok{background:#dcfce7;color:#15803d}
  .didx-cp-k{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin-top:12px}
  .didx-cp-k span{display:flex;flex-direction:column;font-size:11px;color:var(--text3);min-width:0}
  .didx-cp-k b{font-size:15px;color:var(--text);font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .didx-cp-k b.neg{color:var(--red)}
  .didx-cp-b{display:flex;gap:8px;margin-top:12px}
  .didx-cp-b .btn{flex:1;min-height:44px;justify-content:center;font-size:14px}
  .didx-cp-b .ic{width:15px;height:15px}
  /* the filter sheet */
  .dps-h{display:flex;align-items:center;justify-content:space-between;margin:0 2px 4px}
  .dps-h b{font-size:18px;color:var(--text)}
  .dps-reset{border:0;background:none;font:inherit;font-size:14px;font-weight:600;color:var(--accent);cursor:pointer;min-height:36px}
  .dps-l{font-size:12px;font-weight:600;color:var(--text3);margin:14px 2px 8px}
  .dps-r{display:flex;flex-wrap:wrap;gap:6px}
  .dps-c{min-height:36px;padding:0 13px;border-radius:999px;border:1px solid var(--border);background:var(--surface);font:inherit;font-size:13.5px;font-weight:600;color:var(--text2);cursor:pointer}
  .dps-c.on{background:var(--text);border-color:var(--text);color:#fff}
  .dps-cu{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:10px}
  .dps-cu label{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--text3);min-width:0}
  .dps-cu input{min-width:0;width:100%;box-sizing:border-box;min-height:42px;border:1px solid var(--border-strong);border-radius:10px;padding:0 10px;font:inherit;font-size:16px;background:var(--surface);color:var(--text)}
  .dps-acts{margin-top:14px;border-top:1px solid var(--border)}
  .dps-a{display:flex;align-items:center;gap:12px;width:100%;min-height:50px;border:0;border-bottom:1px solid var(--border);background:none;font:inherit;font-size:15px;font-weight:500;color:var(--text);cursor:pointer;padding:0 2px;text-align:left}
  .dps-a:last-child{border-bottom:0}
  .dps-a .ic{width:19px;height:19px;margin:0;color:var(--text2)}
  @media (prefers-reduced-motion:no-preference){
    .mobsheet.open .mobsheet-panel.dnm-panel,.mobsheet.open .mobsheet-panel.dps-panel{animation:dgUp .22s ease-out}
  }
}
