/* ============================================================================
   MTG Command Center — app.css
   Two jobs:
   1. A tiny hand-rolled utility layer (the "offline fallback") so the layout
      is still legible if the Tailwind Play CDN is blocked (no network). Only
      the classes the markup actually leans on are defined here; when the CDN
      loads, Tailwind's own rules win by source order / specificity and these
      are harmless.
   2. Component styling that Tailwind utilities don't cover cleanly: the dark
      theme tokens, the chat bubbles, tool-call chips, the drawer transition,
      scrollbars, spinners and skeletons.
   ========================================================================== */

/* ═══════════════════════════════════════════════════════════════════════════
   DESIGN TOKENS — phase 0 of the light-theme migration (REQ-UI-001)

   Light is now the DEFAULT and dark is a preference, reversing the original
   dark-only palette (owner, 2026-07-25: "everything is so dark and we need
   some more lighter aesthetics").

   Why this shape:

   • Structure was INVISIBLE before. The old `--border #363b47` on
     `--panel #20242c` is 1.39:1 — the same near-nothing as Notion's 1.26:1
     hairline, but on a DARK ground, where the eye cannot resolve small
     luminance steps. On a bright ground a whisper-quiet hairline reads
     perfectly, which is what makes a dense table calm.

   • Every text token clears WCAG AA 4.5:1 on every surface it is allowed on.
     This is a deliberate DEPARTURE from Notion, whose secondary text is
     4.27:1 — fine for metadata on a document, not fine when "secondary" is a
     due date or a dollar amount.

   • The old `--bad #c0392b` on `--bg #16181d` was 3.27:1 — error text failed
     AA in the shipped dark theme. Both themes now pass.

   • LEGACY ALIASES at the bottom: all 19 original names still resolve, so this
     phase reskins the app without touching a single selector. Later phases
     migrate call sites and delete the alias block.

   Contrast ratios in comments are computed, not estimated.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;

  /* ── neutrals: warm greys next to white, the source of the "paper" feel ── */
  --n-0:   #FFFFFF;   /* paper: cards, table body, inputs, modals             */
  --n-50:  #F7F6F3;   /* ground: app background, sidebar                     */
  --n-100: #F4F2EE;   /* sunken: table header, code, zebra, inset            */
  --n-200: #E3E0D9;   /* hairline: dividers, gridlines, card edges (1.32:1)  */
  --n-300: #C9C5BB;   /* quiet control border                                */
  --n-500: #8A857A;   /* control border 3.67:1 — meets WCAG 1.4.11, NOT text */
  --n-700: #57534A;   /* secondary text — 7.66:1 on white                    */
  --n-900: #23211C;   /* primary text — 16.08:1. Never pure black.           */

  /* ── semantic surfaces ── */
  --ground:      var(--n-50);
  --surface:     var(--n-0);
  --surface-2:   var(--n-100);
  --surface-ele: var(--n-0);    /* elevated is the SAME white; a ring separates */
  --hairline:    var(--n-200);
  --line:        var(--hairline); /* legacy alias used by settings embeds */
  --border-ctl:  var(--n-500);

  /* ── text ── */
  --text-1: var(--n-900);   /* 16.08:1 */
  --text-2: var(--n-700);   /*  7.66:1 */
  --text-3: #6B665A;        /*  5.72:1 — raised above Notion's 4.27:1 */
  --text-4: var(--n-500);   /*  3.67:1 — DISABLED/DECORATIVE ONLY, never text */
  --icon:       #3A3833;
  --icon-quiet: #6B665A;

  /* ── brand gold, split into four roles ──────────────────────────────────
     #E0B64A on white is 1.92:1 and fails everything, as does white on it.
     Notion hit the identical problem with yellow and split the hue; same fix.
     Five placements only: logo, selected-row rail, one primary button per
     view, focus ring, first chart series. That restraint is the point. */
  --brand:        #E0B64A;  /* FILL & MARK ONLY. Never text on light.         */
  --brand-strong: #A07D24;  /* 3.85:1 — rails, borders, focus ring (1.4.11)   */
  --brand-text:   #7E5F18;  /* 5.94:1 — gold text, links, gold icons          */
  --brand-bg:     #FAF1D9;  /* tint fill for badges/callouts                  */
  --brand-bd:     #EBDCB4;
  --on-brand:     #23211C;  /* ink on a --brand fill — 8.39:1                 */
  --brand-rgb:    224 182 74;
  /* Triplets for alpha tints of the status hues. These must FLIP per theme:
     --good is #1F6B45 on light and #5FCB92 on dark, so a single triplet would
     tint the wrong direction in one of them. Gold needs no such pair — the
     brand hue is the same in both themes. */
  --good-rgb:     31 107 69;
  --bad-rgb:      155 35 27;
  --info-rgb:     23 95 160;

  /* ── semantic status: text / tint / border triplets ── */
  --good:        #1F6B45;  --good-bg:     #E8F2EB;  --good-bd:     #C8E0D2;
  --warn:        #7A5314;  --warn-bg:     #FAF2DD;  --warn-bd:     #EBDCB4;
  --bad:         #9B231B;  --bad-bg:      #FBEAE8;  --bad-bd:      #F0CFCB;
  --info:        #175FA0;  --info-bg:     #E8F1FA;  --info-bd:     #C9DEF2;

  /* ── interaction overlays. --ink-rgb FLIPS per theme, so one hover rule
        composites dark-over-light here and light-over-dark in the dark theme.
        This is what lets ~50 hardcoded rgba() literals collapse later. ── */
  --ink-rgb:   35 33 28;
  --hover:     rgb(var(--ink-rgb) / .045);
  --hover-row: rgb(var(--ink-rgb) / .055);  /* louder than Notion's 2.4%: you
                                               track across 9 columns of money */
  --press:     rgb(var(--ink-rgb) / .10);
  --selected:  rgb(var(--ink-rgb) / .06);
  --scrim:     rgb(15 15 15 / .45);

  /* ── elevation. In-flow content gets NOTHING; a hairline ring separates. ── */
  --sh-0: none;
  --sh-1: 0 1px 2px rgb(25 25 25 / .04), 0 0 0 1px rgb(35 33 28 / .07);
  --sh-2: 0 8px 16px -4px rgb(25 25 25 / .06), 0 2px 4px rgb(25 25 25 / .03),
          0 0 0 1px rgb(35 33 28 / .07);
  --sh-3: 0 24px 48px rgb(25 25 25 / .18), 0 4px 12px rgb(25 25 25 / .10);

  /* ── geometry. Small radii read as precision; 12-16px reads consumer app
        and fights a dense grid. ── */
  --r-xs: 3px; --r-sm2: 5px; --r-md: 7px; --r-lg2: 10px; --r-pill: 999px;
  --focus-ring: 0 0 0 1px var(--brand-strong) inset, 0 0 0 2px var(--brand-strong);

  /* ── spacing: 4px base, 8px rhythm from --sp-5 up ───────────────────────
        Deliberately NOT an exponential/golden-ratio scale: irrational ratios
        produce sub-pixel seams between adjacent bordered table cells, and a
        money table needs predictable, addable values.
        Choosing a step: pick the SMALLEST at which a pair still reads as one
        unit, and never reuse a step across a hierarchy boundary — each outer
        gap must be strictly larger than the one nested inside it. Skip a level
        at the LOW end (sp-2 → sp-4); consecutive steps read fine above sp-5. */
  --sp-px: 1px;
  /* ── Floating action stack (REQ-UI-008) ──────────────────────────────
     The AI button and the feedback button both float bottom-right. They used
     to pick their own offsets — feedback at bottom:46px, AI at bottom:20px,
     both 42px tall — so they overlapped by 16px and the feedback button (z 90)
     covered the AI button (z 65).

     airail.js tried to fix that in JavaScript by measuring the feedback
     button's live rect and sitting beside it, driven by setTimeout(0) and
     setTimeout(1200). That is a race, not a fix: app.js builds the feedback
     button only after auth resolves, which on a cold load is regularly later
     than 1200ms — the fallback branch then pinned the AI button back on top of
     the collision and nothing re-ran except on resize. It was measurably worse
     than no fix at all, because it looked handled.

     So the stack is derived here instead, and every floating control takes a
     slot. Slots cannot overlap by construction: each is one --fab-size plus one
     --fab-gap above the last, with no dependency on load order, and a test
     asserts the arithmetic. Adding a third control means adding --fab-slot-3,
     not guessing another offset.

     --fab-base clears the Terms · Privacy footer (bottom:8px), which the AI
     button was also clipping. Surfaces with a bottom nav raise the base. */
  --fab-size: 42px;
  --fab-gap: 10px;
  --fab-right: 20px;
  /* Clears the persistent Assistant bar (REQ-AGENT-005): the bar sits 10px up
     and is ~40px tall, so 62px puts the first floating control just above it
     rather than on top of it — the same collision REQ-UI-008 was created for,
     which would otherwise come straight back with a new participant. */
  --fab-base: calc(62px + env(safe-area-inset-bottom, 0px));
  /* The SLOTS are deliberately not defined here — see the body rule below. */

  --sp-1: 0.125rem;  /*  2px — optical nudge, badge inner        */
  --sp-2: 0.25rem;   /*  4px — tightest real gap                 */
  --sp-3: 0.5rem;    /*  8px — label↔field, icon↔text, dense pad */
  --sp-4: 0.75rem;   /* 12px — cell padding, control inner pad   */
  --sp-5: 1rem;      /* 16px — DEFAULT: field↔field, card pad    */
  --sp-6: 1.5rem;    /* 24px — group↔group                       */
  --sp-7: 2rem;      /* 32px — section↔section                   */
  --sp-8: 3rem;      /* 48px — region↔region                     */

  /* ── type scale: six sizes for the whole app ────────────────────────────
        There are currently 21 distinct sizes in this file and ~370 more inline
        in the JS. That, more than any colour, is why it doesn't read as
        designed. Hierarchy comes from COLOUR and WEIGHT, with size last. */
  --fs-1: 11px;   --lh-1: 14px;   /* micro: units, timestamps, axis labels  */
  --fs-2: 12px;   --lh-2: 16px;   /* meta, badges, column headers           */
  --fs-3: 13px;   --lh-3: 18px;   /* BASE: cells, fields, list rows         */
  --fs-4: 15px;   --lh-4: 22px;   /* reading prose, AI text, section titles */
  --fs-5: 20px;   --lh-5: 26px;   /* record title (serif allowed from here) */
  --fs-6: 28px;   --lh-6: 34px;   /* page title / login                     */
  /* Sizes 17px and above that are NOT on this scale are deliberate: an ICON
     GLYPH (▶ ✕ ‹ › + −, tab icons, the empty-state mark) is sized by its
     optical weight in a target, not by a text ramp, and putting it on one is a
     category error. Two WORDMARKS (.brand-mark, .t-app-name) size to their
     container. One INPUT (.t-stepper .t-input) sits above 16px, which is the
     iOS zoom floor and must not drop below it. */
  --fw-normal: 400; --fw-med: 500; --fw-semi: 600;

  /* ── motion (REQ-UI-002) ────────────────────────────────────────────────
        Static first, motion after. Every duration is a token so the
        reduced-motion block below can zero them in ONE place rather than
        relying on a blanket !important rule that a later scoped selector
        could escape. */
  --dur-0:        0ms;    /* explicit "no motion" — focus rings, table rows */
  --dur-press:   70ms;    /* :active must feel instant                     */
  --dur-hover:  120ms;
  --dur-hoverout: 180ms;  /* slower out than in — forgives cursor overshoot */
  --dur-enter:  180ms;    /* dropdown, popover, inline expand               */
  --dur-exit:   120ms;    /* dismissals are always faster than entrances    */
  --dur-modal:  220ms;
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  --ease-out:      cubic-bezier(0, 0, .2, 1);
  --ease-in:       cubic-bezier(.4, 0, 1, 1);
  --ease-emphasis: cubic-bezier(.2, 0, 0, 1);
  --t-hover: var(--dur-hover) var(--ease-standard);
  --t-press: var(--dur-press) var(--ease-out);
  --t-enter: var(--dur-enter) var(--ease-out);
  --t-exit:  var(--dur-exit)  var(--ease-in);

  /* ═══ LEGACY ALIASES — every pre-existing name, remapped ═══════════════
     Do not use these in new CSS. Deleting this block is a later phase; until
     then it is what lets the whole app reskin without editing selectors.
     Note --brand was used for BOTH fills and text, so it aliases to the
     contrast-safe --brand-strong; genuine gold TEXT should move to
     --brand-text as call sites are migrated. */
  --bg:          var(--ground);
  --bg-2:        var(--surface-2);
  --panel:       var(--surface);
  --panel-2:     var(--surface-2);
  --border:      var(--hairline);
  --border-soft: var(--hairline);
  --text:        var(--text-1);
  --text-dim:    var(--text-2);
  --text-faint:  var(--text-3);   /* raised from 3.67:1 → 5.72:1 */
  --brand-2:     var(--brand-text);
  --accent:      var(--brand);
  --bronze:      var(--brand-text);
  --bronze-dark: var(--brand-text);
  --silver:      var(--text-3);
  --chip:        var(--brand-bg);
  --on-gold:     var(--on-brand);
  --r-lg:        var(--r-md);
  --r-sm:        var(--r-sm2);
  --shadow-1:    var(--sh-1);
}

/* ── dark theme: same token NAMES, opposite direction ──────────────────────
   Note --brand-strong collapses to the raw gold here (it is already 8.80:1 on
   this ground and needs no darkening) while --brand-text LIGHTENS. Same tokens,
   inverted adjustment. Shadows are per-theme: a 4%-black shadow is invisible on
   #1E1D1A, so dark uses a stronger shadow plus a light hairline ring. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --n-0: #1E1D1A; --n-50: #171614; --n-100: #262521; --n-200: #322F2A;
  --n-300: #454138; --n-500: #767165; --n-700: #B8B3A7; --n-900: #EDEAE3;
  --text-1: #EDEAE3;  /* 14.03:1 on surface */
  --text-2: #B8B3A7;  /*  8.06:1 */
  --text-3: #9A958A;  /*  5.65:1 */
  --text-4: #767165;
  --icon: #D8D3CA; --icon-quiet: #9A958A;
  --ink-rgb: 255 253 246;              /* overlays invert: light over dark */
  --brand-strong: #E0B64A;             /* 8.80:1 here — no darkening needed */
  --good-rgb: 95 203 146; --bad-rgb: 241 118 107; --info-rgb: 111 177 240;
  --brand-text:   #E7C56A;
  --brand-bg: #2A2214; --brand-bd: #4A3D1F;
  --good: #5FCB92; --good-bg: #16281F; --good-bd: #2A4835;
  --warn: #F0A93C; --warn-bg: #2A2214; --warn-bd: #4A3D1F;
  --bad:  #F1766B; --bad-bg:  #2B1A18; --bad-bd:  #4C2A26;  /* fixes the old 3.27:1 */
  --info: #6FB1F0; --info-bg: #161F2B; --info-bd: #26384C;
  --scrim: rgb(0 0 0 / .6);
  --sh-1: 0 1px 2px rgb(0 0 0 / .4), 0 0 0 1px rgb(255 255 255 / .06);
  --sh-2: 0 8px 16px -4px rgb(0 0 0 / .5), 0 0 0 1px rgb(255 255 255 / .06);
  --sh-3: 0 24px 48px rgb(0 0 0 / .6);
}

/* OS preference, only when the user hasn't chosen explicitly. The
   [data-theme] attribute always wins in both directions. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;
    --n-0: #1E1D1A; --n-50: #171614; --n-100: #262521; --n-200: #322F2A;
    --n-300: #454138; --n-500: #767165; --n-700: #B8B3A7; --n-900: #EDEAE3;
    --text-1: #EDEAE3; --text-2: #B8B3A7; --text-3: #9A958A; --text-4: #767165;
    --icon: #D8D3CA; --icon-quiet: #9A958A;
    --ink-rgb: 255 253 246;
    --brand-strong: #E0B64A; --brand-text: #E7C56A;
    --good-rgb: 95 203 146; --bad-rgb: 241 118 107; --info-rgb: 111 177 240;
    --brand-bg: #2A2214; --brand-bd: #4A3D1F;
    --good: #5FCB92; --good-bg: #16281F; --good-bd: #2A4835;
    --warn: #F0A93C; --warn-bg: #2A2214; --warn-bd: #4A3D1F;
    --bad:  #F1766B; --bad-bg:  #2B1A18; --bad-bd:  #4C2A26;
    --info: #6FB1F0; --info-bg: #161F2B; --info-bd: #26384C;
    --scrim: rgb(0 0 0 / .6);
    --sh-1: 0 1px 2px rgb(0 0 0 / .4), 0 0 0 1px rgb(255 255 255 / .06);
    --sh-2: 0 8px 16px -4px rgb(0 0 0 / .5), 0 0 0 1px rgb(255 255 255 / .06);
    --sh-3: 0 24px 48px rgb(0 0 0 / .6);
  }
}

/* ── reduced motion ───────────────────────────────────────────────────────
   Zero the TOKENS as well as the blanket rule, so a component reading a token
   still gets the right answer even if the blanket rule is later scoped away.
   1ms rather than 0s deliberately: transitionend/animationend still fire, so
   JS that waits on them doesn't silently hang. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-press: 0ms; --dur-hover: 0ms; --dur-hoverout: 0ms;
    --dur-enter: 0ms; --dur-exit: 0ms; --dur-modal: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── hover only where hover exists (REQ-UI-003) ───────────────────────────
   iOS Safari applies :hover on tap and leaves it stuck until you tap elsewhere,
   so a hover-styled row reads as SELECTED on the field app. Any new hover rule
   belongs inside this query, and anything a hover reveals needs a persistently
   visible equivalent on touch. */
@media (hover: hover) and (pointer: fine) {
  .mtg-hoverable:hover { background-color: var(--hover); }
}

/* Press feedback is not decoration on the phone app: through gloves there is
   no tactile confirmation of a tap, and in direct sunlight a 4%-alpha tint is
   invisible. Fast and unmissable. */
.btn:active, .t-btn:active { transform: scale(.97); }
.btn, .t-btn { transition: background-color var(--t-hover),
                           border-color var(--t-hover),
                           transform var(--t-press); }

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  background:
    radial-gradient(1200px 600px at 85% -10%, rgba(212,164,55,0.09), transparent 60%),
    radial-gradient(900px 500px at -5% 110%, rgba(138,106,60,0.07), transparent 55%),
    var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
               Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
  /* Deliberately NOT tokenised. Changing the base re-bases every inheriting
     element at once — including the customer portal, which is not dense — so
     it needs its own decision with eyes on the rendered page rather than
     falling out of a sweep. Tracked as part of a later phase. */
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ----------------------------------------------------------------- fallback --
   Minimal reimplementations of the exact Tailwind classes the markup uses,
   guarded so they don't fight the CDN. These are plain enough that if the CDN
   never loads the page is still a usable dark dashboard. */
.mtg-fallback .flex        { display: flex; }
.mtg-fallback .hidden      { display: none; }
.mtg-fallback .grid        { display: grid; }
.mtg-fallback .items-center{ align-items: center; }
.mtg-fallback .justify-between { justify-content: space-between; }
.mtg-fallback .gap-2       { gap: .5rem; }
.mtg-fallback .gap-3       { gap: .75rem; }
.mtg-fallback .gap-4       { gap: 1rem; }
.mtg-fallback .p-4         { padding: 1rem; }
.mtg-fallback .p-3         { padding: .75rem; }
.mtg-fallback .mb-2        { margin-bottom: .5rem; }
.mtg-fallback .mb-3        { margin-bottom: .75rem; }
.mtg-fallback .w-full      { width: 100%; }
.mtg-fallback .text-sm     { font-size: var(--fs-3); }
.mtg-fallback .text-xs     { font-size: var(--fs-2); }
.mtg-fallback .font-semibold { font-weight: 600; }
.mtg-fallback .rounded     { border-radius: var(--r-lg); }
.mtg-fallback .col         { flex-direction: column; }
.mtg-fallback .mt-8        { margin-top: 2rem; }   /* used but was CDN-only */
.mtg-fallback .mt-12       { margin-top: 3rem; }   /* used but was CDN-only */

/* ------------------------------------------------------------------ layout -- */
.app-shell {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  grid-template-rows: 100vh;
  height: 100vh;
  overflow: hidden;
}
@media (max-width: 1180px) {
  .app-shell {
    grid-template-columns: 68px minmax(0, 1fr);
    grid-template-rows: 1fr;
  }
  /* Collapse the side nav to a clean icon rail: hide the brand text, the nav
     link labels, and the footer blurb so nothing overflows the 68px column. */
  .side-nav { padding: 18px 10px; align-items: center; }
  .side-nav .nav-collapsible { display: none; }
  .side-nav .brand-mark-mini { display: grid; }   /* the compact serif M·G mark */
  .side-nav .nav-brand-row { justify-content: center; margin-bottom: 18px; }
  .side-nav .nav-link { justify-content: center; gap: 0; padding: 10px 0; width: 44px; }
  .side-nav .nav-link .label { display: none; }
  /* icon-rail: drop the text headers, keep a hairline to separate groups */
  .side-nav .nav-group { display: none; }
  .side-nav .nav-group + .nav-link { border-top: 1px solid var(--border); padding-top: 12px; margin-top: 4px; }
  .app-shell .assistant-col { display: none; }
  .app-shell.chat-open .assistant-col {
    display: flex;
    position: fixed;
    inset: 0 0 0 auto;
    width: min(460px, 100vw);
    z-index: 60;
    box-shadow: none;
  }
}
@media (max-width: 720px) {
  .app-shell { grid-template-columns: 1fr; }
  .app-shell .side-nav { display: none; }
}

/* REQ-NAV-007: the shell's second column. Every routable screen and the topbar
   live in here now, so this is what scrolls — the rail beside it never moves and
   is never hidden by the router. Previously the views were siblings of #app and
   the router hid #app itself, which is what made the navigation disappear the
   moment you opened Billing. */
#office-main { overflow-y: auto; min-width: 0; }

.side-nav {
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 18px 14px;
  gap: 6px;
  min-width: 0;
}
.main-col {
  overflow-y: auto;
  min-width: 0;
  padding: 20px 24px 56px;
}
.assistant-col {
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100vh;
}

/* ------------------------------------------------------------------- brand -- */
.brand-mark {
  width: 36px; height: 36px;
  border-radius: var(--r-lg);
  display: grid; place-items: center;
  font-family: Georgia, "Times New Roman", serif;   /* the M·G wordmark is serif */
  font-weight: 700; font-size: 17px; letter-spacing: .5px;
  color: var(--on-gold);
  background: linear-gradient(140deg, var(--bronze-dark), var(--bronze) 45%, var(--brand) 100%);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255,255,255,.15);
  flex: 0 0 auto;
}
/* full inline MTG logo in the expanded sidebar; compact serif mark when collapsed */
.nav-logo svg, .nav-logo img { display: block; height: 34px; width: auto; }
.brand-mark-mini { display: none; }
.nav-link {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 11px;
  border-radius: var(--r-sm);
  color: var(--text-dim);
  cursor: pointer;
  font-weight: 500;
  border: 1px solid transparent;
  transition: background .12s, color .12s, border-color .12s;
  white-space: nowrap;
}
.nav-link:hover { background: var(--panel); color: var(--text); }
.nav-link.active {
  background: var(--panel-2);
  color: var(--text);
  border-color: var(--border);
}
.nav-link .ic { width: 18px; text-align: center; opacity: .9; }

/* Redesign: section headers that give the flat nav a spine (REQ-NAV-001). */
.nav-group {
  margin: 13px 8px 3px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--fs-1);
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--text-dim);
  opacity: .62;
  user-select: none;
}
/* class toggle (not inline display) so the media-query hide below still wins */
.nav-group.nav-group-empty { display: none; }

/* ------------------------------------------------------------------- cards -- */
.card {
  background: linear-gradient(180deg, var(--panel), var(--panel));
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 16px;
}
.card + .card { margin-top: 20px; }
.card-title {
  display: flex; align-items: center; gap: 9px;
  font-size: var(--fs-3); font-weight: 800; letter-spacing: .3px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0 0 12px;
}
.card-title .count {
  margin-left: auto;
  font-size: var(--fs-2); font-weight: 600;
  color: var(--text-faint);
  text-transform: none; letter-spacing: 0;
}

/* ------------------------------------------------------------------ inputs -- */
.input {
  width: 100%;
  /* 16px is the iOS zoom threshold: anything smaller makes Safari zoom the
     viewport on focus. This rule declared no size at all and inherited body's
     14px, so every field on the phone was zooming. Not a token — the value is
     a platform constant, not a design choice. */
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  font-size: 16px;
  outline: none;
  transition: border-color .12s, box-shadow .12s;
}
.input::placeholder { color: var(--text-faint); }
.input:focus {
  /* --brand-strong, not --brand: a focus indicator is non-text UI and needs
     3:1 per WCAG 1.4.11. The raw gold is 1.92:1 on white — it passed on the
     old dark ground, which is why this was invisible until the theme flipped.
     The glow is decorative; the border does the contrast work. */
  border-color: var(--brand-strong);
  box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / .16);
}

.btn {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  border-radius: var(--r-sm);
  padding: 7px 12px;
  font-size: var(--fs-3); font-weight: 600;
  cursor: pointer;
  transition: transform .06s, background .12s, border-color .12s, opacity .12s;
  white-space: nowrap;
}
.btn:hover { background: var(--hover); border-color: var(--border-ctl); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-primary {
  background: linear-gradient(135deg, var(--brand), var(--accent));
  border-color: transparent; color: var(--on-gold);
  box-shadow: var(--shadow-1);
}
.btn-primary:hover { filter: brightness(1.06); background: linear-gradient(135deg, var(--brand), var(--accent)); }
.btn-ghost { background: transparent; }
.btn-ghost:hover { background: var(--panel); }

/* --------------------------------------------------------------- list rows -- */
.row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 12px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .1s, border-color .1s;
}
.row:hover { background: var(--panel-2); border-color: var(--border-soft); }
.row .avatar {
  width: 34px; height: 34px; flex: 0 0 auto;
  border-radius: 9px;
  display: grid; place-items: center;
  font-weight: 700; font-size: var(--fs-3);
  color: var(--brand);
  background: rgb(var(--brand-rgb) / .11);
  border: 1px solid rgb(var(--brand-rgb) / .20);
}
.row .avatar.lead { color: var(--warn); background: rgb(var(--brand-rgb) / .10); border-color: rgb(var(--brand-rgb) / .20); }
/* Semantic (meaning-matched) search results — a distinct silver-ish avatar and
   a subtle section header, so they read as related-not-exact. */
.row .avatar.sem { color: var(--text-3); background: var(--surface-2); border-color: var(--hairline); }
.search-sem-hdr {
  margin: 10px 4px 4px;
  font-size: var(--fs-1); letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-faint); font-family: ui-monospace, Menlo, monospace;
}
.row .grow { min-width: 0; flex: 1 1 auto; }
.row .name { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .sub { color: var(--text-faint); font-size: var(--fs-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* -------------------------------------------------------------- watchdog -- */
.wd-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: var(--r-lg);
  border: 1px solid var(--border-soft);
  background: var(--bg-2);
}
.wd-row + .wd-row { margin-top: 10px; }
.wd-amount { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }
.wd-meta { color: var(--text-faint); font-size: var(--fs-2); }

/* ---------------------------------------------------------------- badges -- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: var(--r-sm);
  font-size: var(--fs-2); font-weight: 600;
  border: 1px solid var(--border);
  background: var(--chip); color: var(--text-dim);
}
.badge.mock { color: var(--warn); border-color: rgb(var(--brand-rgb) / .3); background: rgb(var(--brand-rgb) / .08); }
.badge.live { color: var(--good); border-color: rgb(var(--good-rgb) / .3); background: rgb(var(--good-rgb) / .08); }
.badge .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 8px currentColor; }
.badge .dot.pulse { animation: pulse 1.8s ease-in-out infinite; }

.pill {
  display: inline-block;
  padding: 2px 9px; border-radius: var(--r-sm);
  font-size: var(--fs-1); font-weight: 600;
  background: var(--chip); color: var(--text-dim);
  border: 1px solid var(--border-soft);
}
.pill.warn { color: var(--warn); }
.pill.good { color: var(--good); }
.pill.bad  { color: var(--bad); }

/* --------------------------------------------------------------- drawer -- */
.drawer-scrim {
  position: fixed; inset: 0;
  background: var(--scrim);
  backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease;
  z-index: 70;
}
.drawer-scrim.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(560px, 100vw);
  background: var(--bg-2);
  border-left: 1px solid var(--border);
  transform: translateX(100%);
  transition: transform .22s cubic-bezier(.4,0,.2,1);
  z-index: 71;
  display: flex; flex-direction: column;
  box-shadow: none;
}
.drawer.open { transform: translateX(0); }
.drawer-head {
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.drawer-body { overflow-y: auto; padding: 18px 20px 36px; flex: 1 1 auto; }

.kv { display: flex; gap: 10px; font-size: var(--fs-3); padding: 4px 0; }
.kv .k { color: var(--text-faint); min-width: 74px; }
.kv .v { color: var(--text); }

.section-label {
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .5px;
  text-transform: uppercase; color: var(--text-faint);
  margin: 22px 0 10px;
}
.mini-card {
  border: 1px solid var(--border-soft);
  background: var(--panel);
  border-radius: var(--r-lg);
  padding: 12px 13px;
}
.mini-card + .mini-card { margin-top: 9px; }

/* ----------------------------------------------------------------- chat -- */
.chat-head {
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.chat-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 18px 18px 8px;
  display: flex; flex-direction: column; gap: 14px;
}
.chat-compose {
  border-top: 1px solid var(--border);
  padding: 14px 16px 16px;
}
.msg { display: flex; gap: 10px; max-width: 100%; }
.msg .who {
  width: 28px; height: 28px; flex: 0 0 auto;
  border-radius: 8px; display: grid; place-items: center;
  font-size: var(--fs-2); font-weight: 700;
}
.msg.user { flex-direction: row-reverse; }
.msg .bubble {
  padding: 10px 13px; border-radius: var(--r-lg);
  font-size: var(--fs-3); line-height: 1.55;
  border: 1px solid var(--border-soft);
  max-width: 82%;
  white-space: pre-wrap; word-wrap: break-word;
}
.msg.assistant .who   { background: linear-gradient(140deg, var(--bronze), var(--brand)); color: var(--on-gold); }
.msg.assistant .bubble{ background: var(--panel-2); color: var(--text); border-top-left-radius: 2px; }
.msg.user .who        { background: var(--panel-2); color: var(--brand); border: 1px solid var(--border); }
.msg.user .bubble     { background: rgb(var(--brand-rgb) / .10); border-color: rgb(var(--brand-rgb) / .24); color: var(--text); border-top-right-radius: 2px; }

.trace-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.trace-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-2); font-weight: 600;
  color: var(--accent);
  background: rgb(var(--brand-rgb) / .10);
  border: 1px solid rgb(var(--brand-rgb) / .26);
  padding: 3px 9px; border-radius: var(--r-sm);
  cursor: default;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.trace-chip .glyph { opacity: .8; }

.suggest-row { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.suggest {
  font-size: var(--fs-2); color: var(--text-dim);
  border: 1px solid var(--border);
  background: var(--panel);
  padding: 6px 11px; border-radius: var(--r-sm);
  cursor: pointer;
  transition: background .1s, color .1s;
}
.suggest:hover { background: var(--panel-2); color: var(--text); }

/* --------------------------------------------------------------- states -- */
.empty {
  text-align: center;
  color: var(--text-faint);
  padding: 26px 14px;
  font-size: var(--fs-3);
}
.empty .ic { font-size: 24px; display: block; margin-bottom: 8px; opacity: .55; }

.skeleton {
  background: linear-gradient(90deg, var(--panel) 25%, var(--panel-2) 50%, var(--panel) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
  border-radius: var(--r-sm);
}
.sk-row { height: 56px; margin-bottom: 10px; }

/* The track was a WHITE border: invisible on a light ground, leaving a lone
   gold arc with no ring behind it. --ink-rgb inverts, so it stays faint on
   either theme. */
.spinner {
  width: 16px; height: 16px;
  border: 2px solid rgb(var(--ink-rgb) / .18);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  display: inline-block;
}
.typing { display: inline-flex; gap: 4px; padding: 4px 2px; }
.typing i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-faint);
  animation: blink 1.2s infinite;
}
.typing i:nth-child(2) { animation-delay: .2s; }
.typing i:nth-child(3) { animation-delay: .4s; }

/* toast */
.toast-wrap {
  position: fixed; bottom: 20px; left: 50%;
  transform: translateX(-50%);
  z-index: 90;
  display: flex; flex-direction: column; gap: 8px;
  align-items: center;
}

/* legal footer (spec A5) — quiet corner link, present in any login state */
.mtg-legal-footer {
  position: fixed; bottom: 8px; right: 12px; z-index: 5;
  font-size: var(--fs-1); color: var(--text-faint);
}
.mtg-legal-footer a { color: var(--text-faint); text-decoration: underline; }
.mtg-legal-footer a:hover { color: var(--text-dim); }
.mtg-legal-footer span { margin: 0 5px; }
.toast {
  padding: 10px 16px; border-radius: var(--r-sm);
  font-size: var(--fs-3); font-weight: 600;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  box-shadow: var(--shadow-1);
  animation: rise .2s ease;
}
.toast.good { border-color: rgb(var(--good-rgb) / .4); color: var(--good); }
.toast.bad  { border-color: rgb(var(--bad-rgb) / .4); color: var(--bad); }

@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@keyframes spin    { to { transform: rotate(360deg); } }
@keyframes blink   { 0%,60%,100% { opacity:.25; } 30% { opacity:1; } }
@keyframes pulse   { 0%,100% { opacity:1; } 50% { opacity:.35; } }
@keyframes rise    { from { transform: translateY(8px); opacity:0; } to { transform: none; opacity:1; } }

/* scrollbars */
.main-col::-webkit-scrollbar,
.chat-scroll::-webkit-scrollbar,
.drawer-body::-webkit-scrollbar { width: 9px; }
.main-col::-webkit-scrollbar-thumb,
.chat-scroll::-webkit-scrollbar-thumb,
.drawer-body::-webkit-scrollbar-thumb {
  background: var(--border); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box;
}
.main-col::-webkit-scrollbar-track { background: transparent; }

/* small helpers used inline */
.muted { color: var(--text-dim); }
.faint { color: var(--text-faint); }
.mono  { font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.tabnum { font-variant-numeric: tabular-nums; }
.stack { display: flex; flex-direction: column; }
.rowflex { display: flex; align-items: center; }
.spread { justify-content: space-between; }

/* ============================================================================
   Team Roles additions — login gate, user chip, and the six role-gated
   sections (Field Service / Purchasing / Inventory / Facilities / Documents /
   Team Roles). All lean on the existing brand tokens; nothing here overrides
   the base brand.
   ========================================================================== */

/* ---------------------------------------------------------------- login -- */
.login-gate {
  position: fixed; inset: 0;
  display: none;                 /* app.js flips to grid when no token */
  place-items: center;
  padding: 24px;
  z-index: 80;
  background:
    radial-gradient(1200px 600px at 85% -10%, rgba(212,164,55,0.10), transparent 60%),
    radial-gradient(900px 500px at -5% 110%, rgba(138,106,60,0.08), transparent 55%),
    var(--bg);
  overflow-y: auto;
}
.login-gate.show { display: grid; }
.login-card {
  width: min(400px, 100%);
  background: linear-gradient(180deg, var(--panel), var(--panel));
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 26px 24px 22px;
  box-shadow: var(--shadow-1);
}
.login-brand { text-align: center; margin-bottom: 22px; }
.login-brand .nav-logo svg, .login-brand .nav-logo img { display: inline-block; height: 40px; width: auto; }
.login-sub {
  font-size: var(--fs-1); letter-spacing: .18em; text-transform: uppercase;
  margin-top: 8px;
}
.login-label {
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .4px;
  text-transform: uppercase; color: var(--text-faint);
}
.login-error {
  font-size: var(--fs-2); font-weight: 600; color: var(--bad);
  background: rgb(var(--bad-rgb) / .10);
  border: 1px solid rgb(var(--bad-rgb) / .30);
  border-radius: var(--r-sm); padding: 8px 11px;
}
.login-hint {
  font-size: var(--fs-2); line-height: 1.6;
  margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--border-soft);
}
.login-hint .mono { color: var(--text-dim); }

/* -------------------------------------------------------------- user chip -- */
.user-chip {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-soft);
  background: var(--bg-2);
}
.user-avatar {
  width: 30px; height: 30px; flex: 0 0 auto;
  border-radius: 8px; display: grid; place-items: center;
  font-weight: 700; font-size: var(--fs-2);
  color: var(--brand);
  background: rgb(var(--brand-rgb) / .12);
  border: 1px solid rgb(var(--brand-rgb) / .22);
}
.user-name { font-weight: 600; font-size: var(--fs-3); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-role { font-size: var(--fs-1); letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); }
.user-signout { margin-left: auto; padding: 5px 8px; font-size: var(--fs-1); flex: 0 0 auto; }

/* -------------------------------------------------------------- mini form -- */
.mini-label {
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .4px;
  text-transform: uppercase; color: var(--text-faint);
}
.field-add-grid, .doc-add-grid {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;
}
.field-add-grid .stack, .doc-add-grid .stack { flex: 1 1 160px; min-width: 130px; }
select.input { appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-faint) 50%),
    linear-gradient(135deg, var(--text-faint) 50%, transparent 50%);
  background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  padding-right: 30px;
}

/* ------------------------------------------------------ data tables (rows) -- */
.data-table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  font-size: var(--fs-3);
}
.data-scroll { overflow-x: auto; }
.data-table th {
  text-align: left; font-size: var(--fs-1); font-weight: 800;
  letter-spacing: .5px; text-transform: uppercase; color: var(--text-faint);
  padding: 8px 12px; white-space: nowrap;
  border-bottom: 1px solid var(--border-soft);
}
.data-table td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--border-soft);
  color: var(--text); vertical-align: middle;
}
.data-table tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover td { background: var(--panel-2); }
.data-table .num { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.data-table input[type="checkbox"] {
  width: 16px; height: 16px; accent-color: var(--brand); cursor: pointer;
}
.data-wrap {
  border: 1px solid var(--border-soft);
  border-radius: var(--r-lg);
  background: var(--bg-2);
  overflow: hidden;
}
.data-wrap + .section-label { margin-top: 22px; }

/* ---------------------------------------------------------------- select -- */
.role-select {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--r-sm);
  padding: 6px 26px 6px 10px;
  font-size: var(--fs-2); font-weight: 600;
  cursor: pointer; appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-faint) 50%),
    linear-gradient(135deg, var(--text-faint) 50%, transparent 50%);
  background-position: calc(100% - 14px) 52%, calc(100% - 9px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.role-select:focus { outline: none; border-color: var(--brand-strong); box-shadow: 0 0 0 3px rgba(212,164,55,.16); }

/* --------------------------------------------------------- doc-type badge -- */
.doc-badge {
  display: inline-flex; align-items: center;
  padding: 2px 8px; border-radius: var(--r-sm);
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase;
  border: 1px solid var(--border-soft);
  background: var(--chip); color: var(--text-dim);
}
.doc-badge.coi      { color: var(--good);   border-color: rgb(var(--good-rgb) / .30);   background: rgb(var(--good-rgb) / .08); }
.doc-badge.w9       { color: var(--accent); border-color: rgb(var(--brand-rgb) / .30);   background: rgb(var(--brand-rgb) / .08); }
.doc-badge.check    { color: var(--silver); border-color: rgb(var(--ink-rgb) / .24);  background: rgb(var(--ink-rgb) / .06); }
.doc-badge.invoice  { color: var(--warn);   border-color: rgb(var(--brand-rgb) / .30);   background: rgb(var(--brand-rgb) / .08); }
.doc-badge.contract { color: var(--text-dim); }

/* a simple two-line list row reused by Field Service / Facilities / Documents */
.line-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 13px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-soft);
  background: var(--bg-2);
}
.line-row + .line-row { margin-top: 9px; }
.line-row .grow { min-width: 0; flex: 1 1 auto; }
.line-row .title { font-weight: 600; color: var(--text); }
.line-row .meta { color: var(--text-faint); font-size: var(--fs-2); margin-top: 2px; }
.line-row .actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.line-row.due { border-color: rgb(var(--brand-rgb) / .35); background: rgb(var(--brand-rgb) / .06); }

/* material-line state pills reuse .pill; a couple of extra state colors */
.pill.state-cart      { color: var(--text-dim); }
.pill.state-requested { color: var(--warn); }
.pill.state-ordered   { color: var(--accent); }
.pill.state-received  { color: var(--good); }
.pill.state-used      { color: var(--good); }

@media (max-width: 560px) {
  .field-add-grid, .doc-add-grid { gap: 8px; }
  .field-add-grid .btn, .doc-add-grid .btn { width: 100%; }
}

/* portal */
/* ============================================================================
   WP-B customer portal (portal.html / portal.js). Everything is prefixed
   .pt- so nothing collides with the dashboard styles above. Reuses the brand
   tokens + the shared shimmer/rise keyframes.
   ========================================================================== */
.pt-app {
  max-width: 520px;
  margin: 0 auto;
  padding: 0 16px 84px;   /* room for the fixed bottom nav */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  color: var(--text);
}

/* --- header ------------------------------------------------------------- */
.pt-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 0 10px;
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg);
  border-bottom: 1px solid var(--border-soft);
}
.pt-header-logo img { width: 34px; height: auto; display: block; }
.pt-header-title { font-weight: 600; font-size: 16px; letter-spacing: .3px; flex: 1 1 auto; }

/* --- cards + sections ----------------------------------------------------- */
.pt-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 14px;
  margin-bottom: 12px;
}
.pt-section-title {
  font-size: var(--fs-2); font-weight: 800; letter-spacing: .5px;
  text-transform: uppercase; color: var(--text-faint);
  margin: 20px 0 10px;
}
.pt-empty { text-align: center; padding: 40px 16px; color: var(--text-faint); }
.pt-meta { font-size: var(--fs-3); color: var(--text-faint); }
.pt-mt-8 { margin-top: 8px; }
.pt-mt-12 { margin-top: 12px; }

/* --- buttons -------------------------------------------------------------- */
.pt-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 18px; border-radius: var(--r-sm);
  font-size: 16px; font-weight: 600; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  min-height: 48px;
  transition: background .12s, transform .06s;
}
.pt-btn:active { transform: translateY(1px); }
.pt-btn:disabled { opacity: .55; cursor: default; }
.pt-btn-primary {
  background: linear-gradient(135deg, var(--brand), var(--accent));
  border-color: transparent; color: var(--on-gold);
  box-shadow: var(--shadow-1);
}
.pt-btn-outline { background: transparent; color: var(--text-dim); }
.pt-btn-outline:hover { background: var(--panel); color: var(--text); }
.pt-btn-small { padding: 8px 14px; font-size: var(--fs-3); min-height: 44px; }
.pt-btn-full { width: 100%; }
.pt-btn-icon {
  width: 44px; height: 44px; padding: 0;
  background: transparent; border: none; color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm); cursor: pointer;
}
.pt-btn-icon:hover { background: var(--panel); color: var(--text); }

/* --- inputs ---------------------------------------------------------------- */
.pt-input {
  width: 100%; min-height: 48px; padding: 14px 16px;
  background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--r-sm);
  color: var(--text); font-size: 16px; /* 16px stops iOS zoom-on-focus */
  outline: none;
}
.pt-input::placeholder { color: var(--text-faint); }
.pt-input:focus { border-color: var(--brand-strong); box-shadow: 0 0 0 3px rgba(212,164,55,.16); }
.pt-input-wrap { margin-bottom: 14px; }
.pt-textarea {
  width: 100%; padding: 12px; background: var(--bg-2);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  color: var(--text); font-size: 16px; resize: vertical; min-height: 80px;
}

/* --- login ------------------------------------------------------------------ */
.pt-login {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 100vh; padding: 24px 16px;
  max-width: 420px; margin: 0 auto;
}
.pt-login-logo { width: 96px; margin-bottom: 18px; }
.pt-login-title { font-size: var(--fs-5); font-weight: 700; margin: 0 0 6px; color: var(--accent); }
.pt-login-sub { font-size: var(--fs-3); color: var(--text-faint); margin: 0 0 28px; text-align: center; }
.pt-login-card {
  width: 100%; background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 20px 18px;
}
.pt-form-error { margin-top: 10px; font-size: var(--fs-3); color: var(--bad); display: none; }
.pt-confirmation { text-align: center; padding: 24px 8px; }
.pt-confirmation p { color: var(--text-dim); font-size: var(--fs-4); line-height: 1.55; margin: 14px 0; }

/* --- consent checkbox + legal footer (spec A5) -------------------------------- */
.pt-consent-check {
  display: flex; align-items: flex-start; gap: 9px; cursor: pointer;
  margin: 2px 0 16px; font-size: var(--fs-2); line-height: 1.45; color: var(--text-faint);
}
.pt-consent-check input[type="checkbox"] {
  width: 16px; height: 16px; margin-top: 1px; flex: 0 0 auto;
  accent-color: var(--brand); cursor: pointer;
}
.pt-legal-footer {
  text-align: center; padding: 18px 12px 28px; font-size: var(--fs-2); color: var(--text-faint);
}
.pt-legal-footer a { color: var(--text-faint); text-decoration: underline; }
.pt-legal-footer a:hover { color: var(--text-dim); }
.pt-legal-footer span { margin: 0 6px; }

/* --- tabs -------------------------------------------------------------------- */
.pt-tabs { display: flex; margin-bottom: 18px; background: var(--bg-2); border-radius: var(--r-lg); padding: 4px; }
.pt-tab {
  flex: 1 1 0; padding: 11px 8px; text-align: center; border: none; cursor: pointer;
  font-size: var(--fs-3); font-weight: 600; border-radius: var(--r-sm);
  color: var(--text-dim); background: transparent;
  transition: background .12s, color .12s;
}
.pt-tab.active { background: var(--brand); color: var(--on-gold); }

/* --- home: banner + job cards -------------------------------------------------- */
.pt-banner {
  width: 100%; border: none; cursor: pointer; text-align: left;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: var(--on-gold); border-radius: var(--r-lg); padding: 15px 16px;
  margin: 14px 0 4px; font-size: var(--fs-4); font-weight: 600;
  display: flex; align-items: center; gap: 10px;
}
.pt-banner-badge {
  background: rgba(0,0,0,.22); padding: 3px 10px;
  border-radius: var(--r-sm); font-size: var(--fs-3); font-weight: 700;
}
.pt-job-card {
  background: var(--panel); border: 1px solid var(--border);
  border-left: 4px solid var(--border); border-radius: var(--r-lg);
  padding: 16px; margin-top: 12px; cursor: pointer;
}
.pt-job-card.needs-approval { border-left-color: var(--brand); }
.pt-job-status { font-weight: 700; font-size: var(--fs-4); line-height: 1.35; }
.pt-job-status.gold { color: var(--accent); }
.pt-job-name { font-size: var(--fs-3); color: var(--text-dim); margin-top: 4px; }
.pt-job-meta { font-size: var(--fs-3); color: var(--text-faint); display: flex; gap: 12px; margin-top: 6px; }

/* --- job detail ------------------------------------------------------------------ */
.pt-back {
  display: inline-flex; align-items: center; gap: 6px; border: none; background: none;
  font-size: var(--fs-3); color: var(--text-dim); cursor: pointer;
  margin: 12px 0 4px; padding: 8px 0; min-height: 44px;
}
.pt-back:hover { color: var(--text); }
.pt-status-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 20px 16px; margin-bottom: 4px; text-align: center;
}
.pt-status-label { font-size: var(--fs-5); font-weight: 700; line-height: 1.35; }
.pt-lifecycle-chip {
  display: inline-block; margin-top: 10px; padding: 4px 12px;
  border-radius: var(--r-sm); font-size: var(--fs-1); font-weight: 700; letter-spacing: .4px;
  background: var(--chip); color: var(--text-dim); text-transform: uppercase;
}
.pt-doc-row { display: flex; align-items: center; gap: 10px; padding: 12px 16px; }
.pt-doc-name { flex: 1 1 auto; font-size: var(--fs-3); }

/* Portal job media (REQ-PORTAL-001) — NOTE the #fff literals below are
   deliberately theme-independent: the lightbox commits to a dark ground in
   BOTH themes because a photo viewer should get out of the way of the photo.
   These are the only sanctioned hex literals outside the token blocks. */
/* Portal job media (REQ-PORTAL-001) — the gallery the "your photos are ready"
   text has been promising customers. Sized for a phone first: a 3-up grid at
   the smallest width, growing with the viewport. */
.pt-media-count { margin: -4px 0 8px; }
.pt-media-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px; margin-bottom: 8px;
}
.pt-media-tile {
  position: relative; aspect-ratio: 1; padding: 0; overflow: hidden; cursor: pointer;
  border: 1px solid var(--border-soft); border-radius: var(--r-sm, 4px);
  background: var(--panel-2); display: block; width: 100%;
}
.pt-media-tile:hover { border-color: var(--brand); }
.pt-media-tile:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 2px; }
.pt-media-slot { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.pt-media-slot img, .pt-media-slot video { width: 100%; height: 100%; object-fit: cover; display: block; }
.pt-media-slot.pt-media-failed { color: var(--text-faint); font-size: 18px; }
.pt-media-kind {
  position: absolute; left: 4px; bottom: 4px; z-index: 1;
  font-size: var(--fs-1); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 1px 5px; border-radius: 3px; background: rgba(0,0,0,.62); color: #fff;
}
.pt-media-play {
  position: absolute; inset: 0; z-index: 1; display: flex; align-items: center; justify-content: center;
  font-size: 22px; color: #fff; text-shadow: 0 1px 6px rgba(0,0,0,.7); pointer-events: none;
}

.pt-lightbox {
  position: fixed; inset: 0; z-index: 200; background: rgba(8,8,10,.93);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.pt-lightbox-media { max-width: 100%; max-height: 84vh; object-fit: contain; border-radius: 4px; }
.pt-lightbox-close, .pt-lightbox-nav {
  position: absolute; background: rgba(255,255,255,.12); color: #fff; border: none;
  cursor: pointer; border-radius: 50%; display: flex; align-items: center; justify-content: center;
}
/* 44px targets — this is used one-handed, outdoors, on a phone. */
.pt-lightbox-close { top: 14px; right: 14px; width: 44px; height: 44px; font-size: 18px; }
.pt-lightbox-nav { top: 50%; transform: translateY(-50%); width: 44px; height: 44px; font-size: 26px; }
.pt-lightbox-nav.prev { left: 10px; }
.pt-lightbox-nav.next { right: 10px; }
.pt-lightbox-close:hover, .pt-lightbox-nav:hover { background: rgba(255,255,255,.22); }
.pt-lightbox-cap {
  position: absolute; left: 0; right: 0; bottom: 16px; text-align: center;
  color: rgba(255,255,255,.82); font-size: var(--fs-3); padding: 0 60px;
}
.pt-billing-label { font-weight: 700; font-size: var(--fs-4); }
.pt-billing-amount { font-size: var(--fs-5); font-weight: 700; margin-top: 8px; color: var(--accent); }
.pt-reschedule-area { margin-top: 20px; }

/* --- approvals ---------------------------------------------------------------------- */
.pt-approval {
  border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 14px; margin-bottom: 12px; background: var(--panel);
}
.pt-approval h4 { margin: 0 0 6px; font-size: 16px; color: var(--text); }
.pt-approval .meta { font-size: var(--fs-3); color: var(--text-faint); }
.pt-approval-actions { display: flex; gap: 10px; margin-top: 12px; }
.pt-approval-actions .pt-btn { flex: 1 1 0; }
.pt-decision-done { color: var(--good); font-weight: 600; margin: 6px 0 0; }

/* --- timeline ------------------------------------------------------------------------- */
.pt-timeline { position: relative; padding-left: 22px; margin: 4px 0; }
.pt-timeline::before {
  content: ''; position: absolute; left: 5px; top: 6px; bottom: 6px;
  width: 2px; background: var(--border);
}
.pt-timeline-item { position: relative; padding: 0 0 18px 8px; }
.pt-timeline-item:last-child { padding-bottom: 4px; }
.pt-timeline-dot {
  position: absolute; left: -22px; top: 5px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--brand); border: 2px solid var(--bg);
}
.pt-timeline-type { font-weight: 600; font-size: var(--fs-3); }
.pt-timeline-date { font-size: var(--fs-2); color: var(--text-faint); margin: 2px 0 4px; }

/* --- chips ---------------------------------------------------------------------------- */
.pt-chip {
  display: inline-flex; align-items: center; padding: 3px 10px;
  border-radius: var(--r-sm); font-size: var(--fs-2); font-weight: 600;
  background: var(--chip); color: var(--text-dim); border: 1px solid var(--border-soft);
}
.pt-chip.good { color: var(--good); border-color: rgb(var(--good-rgb) / .3); background: rgb(var(--good-rgb) / .08); }
.pt-chip.warn { color: var(--warn); border-color: rgb(var(--brand-rgb) / .3); background: rgb(var(--brand-rgb) / .08); }
.pt-chip.bad  { color: var(--bad);  border-color: rgb(var(--bad-rgb) / .3);  background: rgb(var(--bad-rgb) / .10); }

/* --- gate health ------------------------------------------------------------------------ */
.pt-warranty-kind { font-weight: 600; font-size: var(--fs-4); }
.pt-warranty-countdown { font-size: var(--fs-5); font-weight: 700; margin: 8px 0; color: var(--accent); }

/* --- bottom nav ------------------------------------------------------------------------- */
.pt-bottom-nav {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 20;
  display: flex; justify-content: center; gap: 4px;
  background: var(--panel); border-top: 1px solid var(--border);
  padding: 4px 8px calc(4px + env(safe-area-inset-bottom, 0px));
}
.pt-nav-item {
  flex: 1 1 0; max-width: 172px; min-height: 56px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  border: none; background: none; cursor: pointer;
  color: var(--text-dim); font-size: var(--fs-1); font-weight: 600;
  border-radius: var(--r-sm); position: relative;
}
.pt-nav-item.active { color: var(--accent); }
.pt-nav-badge {
  position: absolute; top: 4px; right: calc(50% - 24px);
  min-width: 18px; height: 18px; padding: 0 4px;
  background: var(--brand); color: var(--on-gold);
  border-radius: 999px; font-size: var(--fs-1); font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}

/* --- toast + skeleton ---------------------------------------------------------------------- */
.pt-toast-container {
  position: fixed; bottom: 84px; left: 50%; transform: translateX(-50%);
  z-index: 100; display: flex; flex-direction: column; gap: 8px; align-items: center;
  width: max-content; max-width: 90vw;
}
.pt-toast {
  padding: 10px 16px; border-radius: var(--r-sm); font-size: var(--fs-3); font-weight: 600;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  box-shadow: var(--shadow-1);
  animation: rise .2s ease;
}
.pt-toast.good { border-color: rgb(var(--good-rgb) / .4); color: var(--good); }
.pt-toast.bad  { border-color: rgb(var(--bad-rgb) / .4);  color: var(--bad); }
.pt-skeleton {
  background: linear-gradient(90deg, var(--panel) 25%, var(--panel-2) 50%, var(--panel) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
}
.pt-sk-row { height: 88px; border-radius: var(--r-lg); margin-top: 14px; }

/* tech */
/* ============================================================================
   MTG Tech PWA — one-thumb field app (WP-C). Everything here rides the :root
   brand tokens above and only touches t-prefixed classes on the /tech page
   (body.tech-app), so the dashboard and portal styles are never affected.
   Touch targets are >= 48px throughout — this app is used with gloves on.
   ========================================================================== */

body.tech-app {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* ── header ── */
body.tech-app .t-header {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 10px;
  min-height: 56px; padding: 8px 14px;
  background: rgba(22,24,29,0.88);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
body.tech-app .t-header[hidden] { display: none; }
body.tech-app .t-logo { width: 30px; height: 30px; object-fit: contain; }
body.tech-app .t-app-name { font-weight: 700; color: var(--brand); font-size: 17px; margin-right: auto; }
body.tech-app .t-user-chip { display: flex; align-items: center; gap: 8px; }
body.tech-app .t-user-chip .user-avatar {
  width: 32px; height: 32px; border-radius: 8px;
  display: grid; place-items: center;
  font-weight: 700; font-size: var(--fs-2); color: var(--brand);
  background: rgb(var(--brand-rgb) / 0.12); border: 1px solid rgb(var(--brand-rgb) / 0.22);
}
body.tech-app .t-user-chip .user-name { font-size: var(--fs-3); font-weight: 600; line-height: 1.2; }
body.tech-app .t-user-chip .user-role {
  font-size: var(--fs-1); letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint);
}

/* ── offline / queued banner ── */
body.tech-app .t-banner {
  background: rgb(var(--brand-rgb) / 0.12);
  border-bottom: 1px solid rgb(var(--brand-rgb) / 0.25);
  color: var(--warn);
  padding: 12px 16px; text-align: center;
  font-size: var(--fs-3); font-weight: 600; cursor: pointer;
}
body.tech-app .t-banner[hidden] { display: none; }

/* ── layout ── */
body.tech-app .t-main {
  max-width: 640px; margin: 0 auto;
  padding: 16px 14px calc(130px + env(safe-area-inset-bottom, 0px));   /* room for the bottom nav + pinned action bar */
}
body.tech-app .t-actionbar {
  position: fixed; bottom: calc(56px + env(safe-area-inset-bottom, 0px));
  left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 640px; z-index: 40;
  display: flex; gap: 10px;
  padding: 10px 14px;
  background: rgba(22,24,29,0.92);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--border);
}
body.tech-app .t-actionbar[hidden] { display: none; }
/* `min-width: 0` is what lets a flex item shrink below its content box. Without
   it a squeezed .t-btn kept its label's intrinsic width, and since .t-btn sets
   `white-space: nowrap` the text spilled straight over the neighbouring button.
   The bar is capped at three items in JS now; the ellipsis is the belt-and-
   braces so a long label degrades visibly instead of colliding. */
body.tech-app .t-actionbar .t-btn {
  flex: 1 1 0; min-width: 0;
  /* M3's 24dp button padding assumes a button sized to its own content. Three
     of them sharing a 360px phone get ~104px each, and 48px of that went to
     padding — which is why even "Call client" was clipping. */
  padding: 0 10px;
  overflow: hidden; text-overflow: ellipsis;
}
/* the "More" sheet — full-width, thumb-sized rows in the same priority order */
body.tech-app .t-more-actions { display: flex; flex-direction: column; gap: 8px; }

/* ── buttons + inputs ── */
body.tech-app .t-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 48px; min-width: 48px; padding: 0 16px;
  border-radius: var(--r-sm); border: 1px solid var(--border);
  background: var(--panel-2); color: var(--text);
  font-size: var(--fs-4); font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: background .12s, transform .06s;
}
body.tech-app .t-btn:active { transform: scale(0.97); }
body.tech-app .t-btn[disabled] { opacity: .5; pointer-events: none; }
body.tech-app .t-btn-gold {
  background: linear-gradient(135deg, var(--brand), var(--accent));
  border-color: transparent; color: var(--on-gold);
  box-shadow: var(--shadow-1);
}
body.tech-app .t-btn-ghost { background: transparent; }
body.tech-app .t-btn-block { width: 100%; }
/* Phase 3b Facility step: compact per-asset actions on the job card. */
body.tech-app .t-btn-sm { min-height: 36px; min-width: 36px; padding: 0 10px; font-size: var(--fs-3); }
body.tech-app .t-asset-row { align-items: flex-start; border-top: 1px solid var(--border); padding-top: 10px; margin-top: 4px; }
body.tech-app .t-asset-actions { display: flex; gap: 8px; margin-left: auto; }
body.tech-app #t-asset-add { margin-top: 10px; }
body.tech-app .t-back-btn { align-self: flex-start; margin-bottom: 12px; }
body.tech-app .t-input {
  width: 100%; min-height: 48px; padding: 10px 14px;
  border-radius: var(--r-sm); border: 1px solid var(--border);
  background: var(--panel); color: var(--text);
  font-size: 16px; outline: none;   /* 16px stops iOS zoom-on-focus */
  transition: border-color .12s, box-shadow .12s;
}
body.tech-app .t-input:focus { border-color: var(--brand-strong); box-shadow: 0 0 0 3px rgba(212,164,55,0.18); }
body.tech-app .t-input::placeholder { color: var(--text-faint); }
body.tech-app .t-label {
  display: block; margin: 12px 0 6px;
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-faint);
}

/* ── login ── */
body.tech-app .t-login {
  display: flex; flex-direction: column; align-items: center;
  max-width: 380px; margin: 0 auto; padding: 48px 8px 24px;
}
body.tech-app .t-login-logo { width: 96px; margin-bottom: 12px; }
body.tech-app .t-login h1 { color: var(--brand); font-size: var(--fs-6); margin: 0 0 28px; }
body.tech-app .t-login-form { width: 100%; display: flex; flex-direction: column; gap: 4px; }
body.tech-app .t-login-form .t-btn { margin-top: 16px; }
body.tech-app .t-login-error {
  margin-top: 10px; padding: 10px 12px; border-radius: var(--r-sm);
  background: rgb(var(--bad-rgb) / 0.10); border: 1px solid rgb(var(--bad-rgb) / 0.30);
  color: var(--bad); font-size: var(--fs-3); font-weight: 600;
}
body.tech-app .t-login-error[hidden] { display: none; }

/* ── today's queue ── */
body.tech-app .t-queue-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
body.tech-app .t-heading { font-size: var(--fs-5); font-weight: 800; margin: 0; }
body.tech-app .t-date { color: var(--text-dim); font-size: var(--fs-3); }
body.tech-app .t-queue-head .t-btn { margin-left: auto; min-height: 48px; }  /* M3 touch target */
body.tech-app .t-vcard {
  display: grid; grid-template-columns: 64px 1fr auto;
  gap: 10px; align-items: center;
  min-height: 76px; padding: 12px; margin-bottom: 10px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); cursor: pointer;
  transition: background .1s, border-color .1s;
}
body.tech-app .t-vcard:active { background: var(--panel-2); border-color: var(--border); }
body.tech-app .t-vcard:focus-visible {
  outline: 3px solid var(--md-primary);
  outline-offset: 2px;
}
body.tech-app .t-vcard.is-done { opacity: .55; }
body.tech-app .t-time {
  font-variant-numeric: tabular-nums; text-align: center;
  font-weight: 700; font-size: var(--fs-4); color: var(--brand);
}
body.tech-app .is-done .t-time { color: var(--text-dim); }
body.tech-app .t-vbody { min-width: 0; }
body.tech-app .t-job-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.tech-app .t-meta, body.tech-app .t-addr, body.tech-app .t-site,
body.tech-app .t-summary {
  font-size: var(--fs-2); color: var(--text-dim); overflow-wrap: anywhere;
}
body.tech-app .t-summary {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
body.tech-app .t-sync-status {
  margin: -4px 0 12px; color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
}
body.tech-app .t-conflict-warning {
  display: grid; gap: 3px; margin-bottom: 12px; padding: 14px;
  border: 2px solid var(--md-error); border-radius: var(--md-shape-md);
  background: var(--md-error-container); color: var(--md-on-error-container);
  overflow-wrap: anywhere;
}
body.tech-app .t-secondary-section {
  display: block; margin-top: 18px; padding: 12px;
  border: 1px solid var(--md-outline-variant); border-radius: var(--md-shape-md);
  background: var(--md-surface-c-low); overflow-wrap: anywhere;
}
body.tech-app .t-secondary-section > summary,
body.tech-app .t-secondary-section > h3 {
  min-height: 48px; margin: 0; font-size: var(--md-title-sm);
  line-height: 48px; font-weight: 600; cursor: pointer;
}
body.tech-app .t-attention-section {
  border-color: var(--md-tertiary);
}
body.tech-app .t-attention-section > p {
  margin: -4px 0 12px; color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
}
body.tech-app .t-secondary-list { padding-top: 8px; }

/* ── chips ── */
body.tech-app .t-chip {
  display: inline-block; padding: 3px 10px; border-radius: var(--r-sm);
  font-size: var(--fs-1); font-weight: 600; white-space: nowrap;
}
body.tech-app .tone-gold    { color: var(--accent);   background: rgb(var(--brand-rgb) / 0.12); border: 1px solid rgb(var(--brand-rgb) / 0.25); }
body.tech-app .tone-good    { color: var(--good);     background: rgb(var(--good-rgb) / 0.10); border: 1px solid rgb(var(--good-rgb) / 0.25); }
body.tech-app .tone-warn    { color: var(--warn);     background: rgb(var(--brand-rgb) / 0.10); border: 1px solid rgb(var(--brand-rgb) / 0.25); }
body.tech-app .tone-bad     { color: var(--bad);      background: rgb(var(--bad-rgb) / 0.12);  border: 1px solid rgb(var(--bad-rgb) / 0.30); }
body.tech-app .tone-neutral { color: var(--text-dim); background: var(--chip);           border: 1px solid var(--border-soft); }

/* ── job detail ── */
body.tech-app .t-job-title h2 { margin: 0; font-size: var(--fs-5); }
body.tech-app .t-job-title { margin-bottom: 14px; }
body.tech-app .t-job-meta { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
body.tech-app .t-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 12px 14px; margin-bottom: 12px;
}
body.tech-app .t-coa { border-color: rgb(var(--brand-rgb) / 0.35); }
body.tech-app .t-card-title {
  font-size: var(--fs-1); font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 10px;
}
body.tech-app .t-kv { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 6px 0; }
body.tech-app .t-k-label { color: var(--text-faint); font-size: var(--fs-2); white-space: nowrap; min-width: 74px; }
body.tech-app .t-k-value { flex: 1 1 auto; font-weight: 600; min-width: 120px; }
body.tech-app .t-card-note { font-size: var(--fs-2); color: var(--text-dim); margin-top: 8px; }
body.tech-app .t-emp-notes {
  background: var(--panel-2); border-radius: var(--r-sm); padding: 10px 12px;
  margin-top: 10px; font-size: var(--fs-3); color: var(--text-dim);
}
body.tech-app .t-tel {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 48px; padding: 0 14px; border-radius: var(--r-sm);
  border: 1px solid rgb(var(--brand-rgb) / 0.30);
  color: var(--brand); font-weight: 600; text-decoration: none;
}
body.tech-app .t-tel:active { background: rgb(var(--brand-rgb) / 0.10); }
body.tech-app .t-part-line {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0; font-size: var(--fs-3);
  border-bottom: 1px solid var(--border-soft);
}
body.tech-app .t-part-line:last-of-type { border-bottom: 0; }
body.tech-app .t-part-line > span:first-child { flex: 1 1 auto; min-width: 0; }
body.tech-app .t-qty { color: var(--text-dim); font-weight: 600; }
body.tech-app .t-price { font-variant-numeric: tabular-nums; }
body.tech-app .t-part-total { text-align: right; font-weight: 700; color: var(--brand); margin-top: 10px; }
body.tech-app .t-timeline-item {
  padding: 10px 0 10px 14px; border-left: 2px solid var(--border);
  display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center;
  font-size: var(--fs-3);
}
body.tech-app .t-timeline-item .t-note { width: 100%; color: var(--text-dim); font-size: var(--fs-2); }

/* ── bottom sheets ── */
body.tech-app .t-sheet-backdrop { position: fixed; inset: 0; background: var(--scrim); z-index: 50; }
body.tech-app .t-sheet {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 640px; z-index: 51;
  max-height: 85vh;
  max-height: 85dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  background: var(--panel); border: 1px solid var(--border); border-bottom: 0;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding: 20px 16px calc(24px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -1px 2px rgba(0,0,0,.5);
  animation: t-slide-up .22s ease;
}
@keyframes t-slide-up {
  from { transform: translate(-50%, 18%); opacity: 0; }
  to   { transform: translate(-50%, 0);   opacity: 1; }
}
body.tech-app .t-sheet-head { font-size: var(--fs-5); font-weight: 700; margin-bottom: 16px; }
body.tech-app .t-sheet-options { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
body.tech-app .t-opt {
  display: flex; align-items: center; gap: 12px;
  min-height: 52px; padding: 0 12px;
  border: 1px solid var(--border-soft); border-radius: var(--r-sm);
  font-size: var(--fs-4); font-weight: 500; cursor: pointer;
  transition: border-color .12s, background .12s;
}
body.tech-app .t-opt:has(input:checked) { border-color: var(--brand); background: rgb(var(--brand-rgb) / 0.06); }
body.tech-app .t-opt[aria-disabled] { opacity: .45; pointer-events: none; }
body.tech-app .t-opt input[type="radio"] { width: 20px; height: 20px; margin: 0; accent-color: var(--brand); }
body.tech-app .t-notes { min-height: 84px; margin: 14px 0; resize: vertical; }
body.tech-app .t-warnbox {
  background: rgb(var(--brand-rgb) / 0.08); border: 1px solid rgb(var(--brand-rgb) / 0.28);
  border-radius: var(--r-sm); padding: 10px 14px; margin-bottom: 14px;
  font-size: var(--fs-3); color: var(--warn);
}

/* need-parts sheet */
body.tech-app .t-stepper { display: grid; grid-template-columns: 56px 1fr 56px; gap: 8px; align-items: stretch; }
body.tech-app .t-stepper button {
  min-height: 48px; font-size: 24px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--text); border-radius: var(--r-sm);
}
body.tech-app .t-stepper button:active { background: var(--panel); }
body.tech-app .t-stepper .t-input { text-align: center; font-size: 18px; font-weight: 600; -moz-appearance: textfield; }
body.tech-app .t-stepper input::-webkit-outer-spin-button,
body.tech-app .t-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
body.tech-app .t-results {
  max-height: 220px; overflow-y: auto; margin-top: 6px;
  border: 1px solid var(--border-soft); border-radius: var(--r-sm); background: var(--bg-2);
}
body.tech-app .t-results[hidden] { display: none; }
body.tech-app .t-result-row {
  display: flex; align-items: center; gap: 10px;
  min-height: 48px; padding: 8px 12px; font-size: var(--fs-3); cursor: pointer;
  border-bottom: 1px solid var(--border-soft);
}
body.tech-app .t-result-row:last-child { border-bottom: 0; }
body.tech-app .t-result-row:active { background: var(--panel-2); }
body.tech-app .t-result-row > span:first-child { flex: 1 1 auto; min-width: 0; }
body.tech-app .t-sku { color: var(--text-faint); font-size: var(--fs-2); }
body.tech-app .t-result-row .t-price { color: var(--brand); font-weight: 600; }
body.tech-app .t-selected-price { font-size: var(--fs-2); color: var(--brand); margin: 6px 0 12px; min-height: 16px; }
body.tech-app .t-resultbox {
  padding: 14px 16px; border-radius: var(--r-sm); font-weight: 600;
  margin: 14px 0 10px; font-size: var(--fs-3);
}
body.tech-app .t-resultbox-good { background: rgb(var(--good-rgb) / 0.10); border: 1px solid rgb(var(--good-rgb) / 0.30); color: var(--good); }
body.tech-app .t-resultbox-warn { background: rgb(var(--brand-rgb) / 0.08); border: 1px solid rgb(var(--brand-rgb) / 0.30); color: var(--warn); }

/* text-client sheet (4c §2) */
body.tech-app .t-thread {
  max-height: 46vh; overflow-y: auto; display: flex; flex-direction: column;
  gap: 8px; margin-bottom: 12px; padding-right: 2px;
}
body.tech-app .t-msg {
  max-width: 84%; padding: 8px 12px; border-radius: var(--r-sm);
  font-size: var(--fs-3); line-height: 1.4; word-break: break-word;
}
body.tech-app .t-msg-out {
  align-self: flex-end; background: rgb(var(--brand-rgb) / 0.14);
  border: 1px solid rgb(var(--brand-rgb) / 0.30); border-bottom-right-radius: 2px;
}
body.tech-app .t-msg-in {
  align-self: flex-start; background: var(--panel-2);
  border: 1px solid var(--border-soft); border-bottom-left-radius: 2px;
}
body.tech-app .t-msg-sender { font-size: var(--fs-1); font-weight: 700; color: var(--brand); margin-bottom: 2px; }
body.tech-app .t-msg-body { white-space: pre-wrap; }
body.tech-app .t-msg-time { font-size: var(--fs-1); color: var(--text-faint); margin-top: 4px; }
body.tech-app .t-thread-compose { display: flex; gap: 8px; align-items: flex-end; }
body.tech-app .t-thread-compose .t-input { flex: 1 1 auto; resize: none; }
body.tech-app .t-thread-compose .t-btn { flex: 0 0 auto; min-height: 48px; }

/* ── toasts + odds and ends ── */
body.tech-app #t-toast-root {
  position: fixed; bottom: 96px; left: 50%; transform: translateX(-50%);
  z-index: 80; display: flex; flex-direction: column; gap: 8px; align-items: center;
  width: max-content; max-width: 92vw;
}
body.tech-app .t-toast {
  padding: 10px 16px; border-radius: var(--r-sm);
  font-size: var(--fs-3); font-weight: 600;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  box-shadow: var(--shadow-1);
  animation: t-toast-in .2s ease; transition: opacity .2s, transform .2s;
  max-width: 92vw; white-space: normal; text-align: center;
}
@keyframes t-toast-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
body.tech-app .t-toast-good { border-color: rgb(var(--good-rgb) / 0.4); color: var(--good); }
body.tech-app .t-toast-bad  { border-color: rgb(var(--bad-rgb) / 0.45); color: var(--bad); }
body.tech-app .t-toast-warn { border-color: rgb(var(--brand-rgb) / 0.4); color: var(--warn); }
body.tech-app .t-empty { text-align: center; color: var(--text-faint); padding: 22px 12px; font-size: var(--fs-3); }
body.tech-app .t-loading { color: var(--text-faint); text-align: center; padding: 18px; }

@media (max-width: 400px) {
  body.tech-app .t-main { padding: 12px 10px calc(130px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 430px) {
  body.tech-app .t-vcard { grid-template-columns: 80px 1fr auto; }
  body.tech-app .t-time { white-space: nowrap; }
}

/* portal-invoice */
/* ============================================================================
   WP-5 invoice card on the customer-portal job detail (portal.js). Rides
   .pt-card for the outer chrome and only touches pt-invoice-* classes, so
   nothing above shifts. Uses the :root brand tokens exclusively.
   ========================================================================== */
.pt-invoice-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.pt-invoice-number { font-weight: 700; font-size: var(--fs-4); letter-spacing: .3px; }

/* line items — description grows, amount stays right-aligned and tabular */
.pt-invoice-line {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 0;
}
.pt-invoice-line + .pt-invoice-line { border-top: 1px solid var(--border-soft); }
.pt-invoice-line-desc { flex: 1 1 auto; min-width: 0; font-size: var(--fs-3); }
.pt-invoice-line-meta {
  display: block;
  font-size: var(--fs-2);
  color: var(--text-faint);
  margin-top: 2px;
}
.pt-invoice-line-kind {
  font-size: var(--fs-1); font-weight: 700; letter-spacing: .5px;
  text-transform: uppercase; color: var(--text-faint);
  background: var(--panel-2);
  padding: 2px 6px; border-radius: var(--r-sm);
  white-space: nowrap; margin-top: 2px;
}
.pt-invoice-line-amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  min-width: 70px;
  white-space: nowrap;
}

/* total — separated from the lines, gold amount */
.pt-invoice-total {
  display: flex; justify-content: space-between; align-items: center;
  border-top: 1px solid var(--border);
  padding-top: 10px; margin-top: 8px;
  font-weight: 700;
}
.pt-invoice-total span:last-child { color: var(--brand); font-variant-numeric: tabular-nums; }

/* footer — the payment copy + sent/paid date */
.pt-invoice-footer {
  margin-top: 12px;
  font-size: var(--fs-3); color: var(--text-dim);
  display: flex; justify-content: space-between; align-items: baseline;
  flex-wrap: wrap; gap: 4px 8px;
}
.pt-invoice-date { color: var(--text-faint); white-space: nowrap; }

/* ══════════ WP-4 · launcher, topbar & app views (append-only) ══════════
   New classes only — the global sharpening pass (WP-6) owns restyling the
   existing rules. These are born sharp: 6px cards/tiles, 4px controls,
   crisp 1px borders, no soft blur shadows. */

/* topbar (chrome for the non-command views) */
.topbar {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; gap: 14px;
  padding: 10px 22px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.topbar-logo img { height: 26px; display: block; }
.topbar-grid {
  width: 36px; height: 36px;
  background: transparent; border: 1px solid var(--border); border-radius: var(--r-sm);
  color: var(--text-dim); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .15s, color .15s;
}
.topbar-grid:hover { border-color: var(--brand); color: var(--brand); }
.topbar-grid svg { width: 18px; height: 18px; }
.topbar-title { font-weight: 700; letter-spacing: .03em; }
.topbar-spacer { flex: 1; }
.topbar-user { display: flex; align-items: center; gap: 10px; font-size: var(--fs-3); }
.topbar-user .user-name { font-weight: 600; font-size: var(--fs-3); color: var(--text); }
.topbar-user .user-role {
  font-size: var(--fs-1); letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-faint);
}

/* view roots + the shared shell the app views render into */
.view-root { min-height: calc(100vh - 57px); }
.view-shell { max-width: 1080px; margin: auto; padding: 26px 24px 60px; }
.view-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; margin-bottom: 18px; flex-wrap: wrap;
}
.view-title { font-size: var(--fs-5); font-weight: 800; margin: 0; }

/* launcher */
.launcher { max-width: 1080px; margin: auto; padding: 40px 24px; }
.launcher-head { font-weight: 800; font-size: var(--fs-6); margin: 0; letter-spacing: -.3px; }
.launcher-sub { margin: 4px 0 26px; font-size: var(--fs-3); }
.tile-grid { display: block; }   /* sections render their own rows */
.app-tile {
  position: relative;
  display: flex; flex-direction: column; gap: 10px; align-items: flex-start;
  padding: 18px 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  cursor: pointer; color: var(--text); text-decoration: none;
  text-align: left; font: inherit;
  transition: border-color .18s ease, background .18s ease, box-shadow .18s ease, transform .18s ease;
}
/* Favorites pin — hidden until hover, always shown once pinned */
.tile-pin {
  position: absolute; top: 8px; right: 8px;
  width: 26px; height: 26px; display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--text-faint);
  opacity: 0; transition: opacity .15s ease, color .15s ease, background .15s ease;
  cursor: pointer;
}
.app-tile:hover .tile-pin, .tile-pin.pinned { opacity: 1; }
.tile-pin.pinned { color: var(--accent); }
.tile-pin:hover { color: var(--accent); background: rgb(var(--brand-rgb) / .14); }
.tile-pin svg { width: 15px; height: 15px; display: block; }
/* Activity badge — count of what's waiting behind a tile */
.tile-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 7px;
  border-radius: var(--r-sm);
  background: var(--brand); color: var(--on-brand);
  font-size: var(--fs-1); font-weight: 800; line-height: 1;
  vertical-align: middle; font-variant-numeric: tabular-nums;
}
.tile-badge[hidden] { display: none; }
.app-tile:hover,
.app-tile:focus-visible {
  /* outline:none below means this border IS the focus indicator, so it needs
     3:1 per WCAG 1.4.11 — --brand-strong, not the 1.92:1 fill gold. The depth
     shadow keeps its black: a shadow stays dark in both themes. */
  border-color: var(--brand-strong);
  background: var(--panel-2);
  box-shadow: 0 8px 22px -10px rgba(0,0,0,.55), 0 0 0 1px rgb(var(--brand-rgb) / .18);
  transform: translateY(-2px);
  outline: none;
}
.app-tile:active { transform: translateY(0); box-shadow: 0 3px 10px -6px rgba(0,0,0,.5); }
.app-tile .tile-ic { color: var(--brand); }
.app-tile .tile-ic svg { width: 26px; height: 26px; display: block; }
.tile-label { font-weight: 700; font-size: var(--fs-4); }
.tile-desc { font-size: var(--fs-2); color: var(--text-dim); line-height: 1.45; }

/* modal shared by the new app views */
.wp4-modal-overlay {
  position: fixed; inset: 0; z-index: 80;
  background: var(--scrim);
  display: flex; align-items: center; justify-content: center;
}
.wp4-modal-panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 22px; max-width: 480px; width: 92%; max-height: 90vh; overflow: auto;
}

/* timeline filter pills (360) */
.filter-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.filter-pill {
  padding: 5px 12px; border: 1px solid var(--border); border-radius: var(--r-sm);
  font-size: var(--fs-2); color: var(--text-dim); cursor: pointer;
  background: transparent;
  transition: border-color .15s, color .15s, background .15s;
}
.filter-pill.active {
  border-color: var(--brand); color: var(--brand);
  background: rgb(var(--brand-rgb) / .08);
}

/* stat chips (360 header) */
.stat-chips {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
.stat-chip {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 12px 14px;
}
.stat-chip .num { font-size: var(--fs-5); font-weight: 800; color: var(--accent); }
.stat-chip .lbl {
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-dim);
}

/* unified activity timeline (360) — square markers, crisp rail */
.tl-list {
  border-left: 2px solid var(--border-soft); margin-left: 6px; padding-left: 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.tl-item { position: relative; font-size: var(--fs-3); }
.tl-item::before {
  content: ''; position: absolute; left: -19px; top: 6px;
  width: 8px; height: 8px;
  background: var(--panel); border: 1px solid var(--brand);
}
.tl-item .tl-ts { font-size: var(--fs-1); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.tl-item .tl-title { font-size: var(--fs-3); font-weight: 600; }
.tl-item .tl-detail { font-size: var(--fs-2); color: var(--text-dim); }
.tl-item.clickable { cursor: pointer; }
.tl-item.clickable:hover .tl-title { color: var(--accent); }

/* scheduling: week rows, per-tech day lanes, slot chips */
.sched-day-row.past, .lane-slot.past { opacity: .45; }
.lane {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 12px; margin-bottom: 10px;
}
.lane-head {
  display: flex; justify-content: space-between; margin-bottom: 8px;
  font-weight: 700; gap: 10px;
}
.slot-chip {
  display: inline-flex; gap: 6px; align-items: center;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--r-sm);
  font-size: var(--fs-2);
  margin: 0 6px 6px 0;
}
.slot-chip.free {
  color: var(--good); border-color: rgb(var(--good-rgb) / .35);
  cursor: pointer;
}
.slot-chip.free:hover { background: rgb(var(--good-rgb) / .08); }
.slot-chip.booked { color: var(--text); background: var(--panel-2); cursor: pointer; }
.slot-chip.booked:hover { border-color: var(--brand); }
.slot-chip.disabled { opacity: .45; cursor: default; }

@media (max-width: 720px) {
  .launcher { padding: 24px 14px; }
  .tile-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .view-shell { padding: 18px 14px 40px; }
}

/* ══════════ WP-6 · sharpen overrides for JS-injected section styles ══════════
   properties.js appends its own <style> to <head> AFTER this stylesheet, so
   these carry one extra level of specificity (the tag) to win the cascade.
   CSS-only mandate: the class hooks already exist — only styling lives here. */
div.ptree-node { border-radius: var(--r-lg); }                 /* was 10px */
div.mtg-modal-panel { border-radius: var(--r-lg); box-shadow: var(--shadow-1); }  /* was 14px + 0 28px 70px blur */
div.partner-results { border-radius: var(--r-sm); }            /* was 10px */

/* photos */
/* tech.js — the job-detail Photos card (mirrors .t-card's own spacing) */
.t-photo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin-bottom: 10px;
}
.t-photo-thumb {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--panel-2);
}

/* properties.js — the 360 view's horizontally-scrolling photo strip */
.t360-photo-strip {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
  margin-bottom: 12px;
}
.t360-photo-thumb {
  height: 72px;
  width: 72px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: var(--r-lg);
  border: 1px solid var(--border-soft);
  background: var(--panel-2);
}

/* ── Tech PWA: crew staffing + hours verification (Art 07-16) ─────────── */
body.tech-app .t-nav { display: flex; background: var(--panel); border-bottom: 1px solid var(--border); }
body.tech-app .t-nav-tab {
  flex: 1; min-height: 48px; padding: 12px 0; background: transparent; border: none;
  color: var(--text-dim); font-size: var(--fs-4); font-weight: 600; cursor: pointer; position: relative;
}
body.tech-app .t-nav-tab.active { color: var(--accent); }
body.tech-app .t-nav-tab.active::after {
  content: ""; position: absolute; bottom: 0; left: 22%; right: 22%; height: 3px; background: var(--accent);
}
body.tech-app .t-badge[hidden] { display: none; }
body.tech-app .t-badge {
  background: var(--bad-bg); color: var(--bad); border: 1px solid var(--bad-bd);
  font-size: var(--fs-2); font-weight: 700; line-height: 18px;
  min-width: 18px; border-radius: var(--r-sm); padding: 0 5px; margin-left: 6px; display: inline-block; vertical-align: middle;
}
body.tech-app .t-crew-row {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 8px;
  padding: 10px 0; border-bottom: 1px solid var(--border-soft); flex-wrap: wrap;
}
body.tech-app .t-crew-row:last-child { border-bottom: 0; }
body.tech-app .t-crew-row.removed { opacity: 0.55; }
body.tech-app .t-crew-tag { color: var(--text-dim); font-size: var(--fs-3); }
body.tech-app .t-quick-chips { display: flex; gap: 6px; margin: 8px 0; flex-wrap: wrap; }
body.tech-app .t-quick-chip {
  min-height: 44px; min-width: 52px; padding: 0 12px; background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text);
  font-size: var(--fs-3); cursor: pointer;
}
body.tech-app .t-quick-chip.active { background: var(--accent); border-color: var(--accent); color: var(--on-gold); }
body.tech-app .t-pending-line {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 10px; margin-bottom: 8px;
}
body.tech-app .t-line-actions { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
body.tech-app .t-line-actions .t-btn { min-height: 44px; }

/* ── Tech PWA: time clock bar (decision #63) ──────────────────────────── */
body.tech-app #t-clockbar[hidden] { display: none; }
body.tech-app #t-clockbar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; background: var(--panel); border-bottom: 1px solid var(--border);
}
body.tech-app #t-clockbar .t-btn { min-height: 48px; }   /* M3 touch target */

/* ── native-feel pass (REQ-FEEL-001..004) + auto-wash strip ───────────── */
.t-main.t-view-enter { animation: t-view-in 180ms ease-out; }
@keyframes t-view-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0);   opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .t-main.t-view-enter { animation: none; }
}
body.tech-app { -webkit-tap-highlight-color: transparent; }
body.tech-app .t-btn:active,
body.tech-app .t-card:active,
body.tech-app .t-nav-tab:active {
  transform: scale(0.97);
  filter: brightness(1.12);
  transition: transform 80ms, filter 80ms;
}
/* REQ-UI-008 — the slots resolve HERE, on body, not on :root.
   var() substitutes at the element that declares it: written on :root,
   `--fab-slot-1: var(--fab-base)` computes to a literal there, descendants
   inherit that literal, and a lower override of --fab-base never re-evaluates
   it. The tech-shell override below was silently dead until a browser
   measurement caught it — 34px where 68px was intended. Declaring the slots on
   body means body.tech-app's --fab-base is what they read.
   (Same trap as the login page aliasing --brand at :root.) */
body {
  --fab-slot-1: var(--fab-base);
  --fab-slot-2: calc(var(--fab-base) + var(--fab-size) + var(--fab-gap));
}

/* The tech shell has a 56px bottom nav, so the whole stack starts above it
   rather than on top of the nav buttons. Raising the base moves every slot
   together — that is the point of deriving them. */
body.tech-app { --fab-base: calc(68px + env(safe-area-inset-bottom, 0px)); }

body.tech-app .t-nav {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 640px; z-index: 45;
  padding-bottom: env(safe-area-inset-bottom);
  min-height: 56px;
  border-top: 1px solid var(--border); border-bottom: none;
  background: rgba(22,24,29,0.96); backdrop-filter: blur(10px);
}
body.tech-app .t-nav[hidden] { display: none; }
body.tech-app .t-nav-tab {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px; min-height: 56px;
  font-size: var(--fs-1); font-weight: 600; color: var(--text-faint);
  transition: color .12s;
}
body.tech-app .t-nav-tab.active { color: var(--accent); }
body.tech-app .t-tab-icon {
  font-size: 18px; line-height: 1; padding: 2px 10px;
  border-radius: var(--r-sm, 4px); transition: background .12s;
}
body.tech-app .t-nav-tab.active .t-tab-icon { background: var(--md-secondary-container); }
body.tech-app .t-tab-label { display: flex; align-items: center; gap: 4px; }
body.tech-app .t-skel {
  height: 56px; border-radius: var(--r-sm, 4px); margin: 0 0 10px;
  background: linear-gradient(90deg, var(--panel) 25%, var(--panel-2) 50%, var(--panel) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
}
body.tech-app .t-wash-strip {
  margin-top: 6px; padding: 6px 10px; font-size: var(--fs-3);
  background: rgb(var(--brand-rgb) / 0.08);
  border: 1px solid rgb(var(--brand-rgb) / 0.25);
  border-radius: var(--r-sm, 4px);
  display: flex; align-items: center; gap: 8px;
}
body.tech-app .t-wash-strip a { color: var(--accent); font-weight: 600; text-decoration: none; }

/* The managed-phone assistant moved to one persistent dock. Its final,
   higher-specificity rules live at the end of this file so the later M3
   navigation and sheet pass cannot accidentally put the bar under a control. */

/* ── launcher sections (grouped wall, 2026-07-18) ── */
.tile-section-label {
  font-size: var(--fs-2); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--brand);
  margin: 28px 0 10px;
}
.tile-section-label:first-child { margin-top: 6px; }
.tile-grid-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
}
.launcher-date { margin: 2px 0 20px; font-size: var(--fs-2); }

/* ── feedback → developer ── */
.fb-fab {
  /* Slot 2 — above the AI button. See the --fab-* block in :root. */
  position: fixed; right: var(--fab-right); bottom: var(--fab-slot-2);
  width: var(--fab-size); height: var(--fab-size);
  border-radius: var(--r-lg);            /* sharp, on-brand — no pill */
  background: var(--panel); border: 1px solid var(--border);
  color: var(--text-dim); font-size: 17px; line-height: 1;
  cursor: pointer; z-index: 90;
  transition: border-color .15s, color .15s;
}
.fb-fab:hover { border-color: var(--brand); color: var(--text); }
.fb-scrim {
  position: fixed; inset: 0; background: var(--scrim);
  display: none; z-index: 95;
}
.fb-scrim.open { display: block; }
.fb-modal {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(480px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 18px;
  display: none; z-index: 100;
  overflow: hidden;
}
.fb-modal.open { display: flex; flex-direction: column; }
.fb-modal-body {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  padding-right: 2px;
}
.fb-actions {
  flex: 0 0 auto;
  padding-top: 12px;
  background: var(--panel);
}
.fb-modal textarea { min-height: 110px; resize: vertical; }

@media (max-width: 599px) {
  .fb-modal {
    top: max(8px, env(safe-area-inset-top, 0px));
    bottom: max(8px, env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%);
    width: calc(100vw - 16px);
    max-height: none;
    padding: 14px;
  }
}

/* ── Command Center calls + dispatch (feedback #85) ───────────────────── */
.command-dispatch-title {
  flex-wrap: wrap;
  gap: 8px;
}
.command-dispatch-title #command-calls-refresh {
  margin-left: auto;
  padding: 5px 9px;
}
.command-dispatch-title #command-open-schedule { padding: 5px 10px; }
.command-dispatch-copy { margin: -4px 0 14px; font-size: var(--fs-2); }
.command-call-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.command-call-heading { margin-top: 0; }
.command-call-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 9px 10px;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-sm);
  background: var(--panel-2);
}
.command-call-row + .command-call-row { margin-top: 7px; }
.command-call-person { min-width: 0; flex: 1 1 auto; }
.command-call-person strong,
.command-call-person small { display: block; overflow-wrap: anywhere; }
.command-call-person small { color: var(--text-faint); margin-top: 2px; }
.command-call-row .btn { flex: 0 0 auto; min-height: 40px; }
.command-call-status {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid rgb(var(--brand-rgb) / .3);
  border-radius: var(--r-sm);
  background: rgb(var(--brand-rgb) / .08);
}
.command-call-status[hidden] { display: none; }
.command-call-status-copy { min-width: 0; flex: 1 1 auto; }
.command-call-status-copy strong,
.command-call-status-copy small { display: block; }
.command-call-status-copy small { color: var(--text-faint); margin-top: 2px; }
.command-capacity-heading { margin-top: 18px; }

@media (max-width: 720px) {
  .command-call-grid { grid-template-columns: 1fr; }
  .command-dispatch-title #command-calls-refresh { margin-left: 0; }
  .command-dispatch-title #command-open-schedule { width: 100%; justify-content: center; }
}

/* ── display type + tile icon chips (de-AI pass 2, 2026-07-18) ── */
:root { --font-display: "Fraunces", Georgia, "Times New Roman", serif; }
.launcher-head,
.main-col h1,
.view-shell h1,
.topbar-title,
.login-card .login-sub {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: .1px;
}
.launcher-head { font-size: var(--fs-6); }

.app-tile .tile-ic {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  background: rgb(var(--brand-rgb) / .08);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-sm);
  color: var(--brand);
  transition: border-color .18s ease, background .18s ease;
}
.app-tile .tile-ic svg { width: 20px; height: 20px; }
.app-tile:hover .tile-ic,
.app-tile:focus-visible .tile-ic { border-color: var(--brand-strong); background: rgb(var(--brand-rgb) / .16); }
@media (prefers-reduced-motion: reduce) {
  .app-tile, .app-tile:hover, .app-tile:focus-visible, .app-tile:active { transform: none; transition: border-color .15s, background .15s; }
}

/* ── My Work home (task-first landing, 2026-07-18) ── */
.mw-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  align-items: start;
}
@media (max-width: 900px) { .mw-grid { grid-template-columns: 1fr; } }
.mw-row {
  padding: 8px 6px;
  border-top: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background .12s;
}
.mw-row:first-child { border-top: none; }
.mw-row:hover { background: var(--panel-2); }
/* REQ-NAV-006: a row with nothing to open must not offer itself as a link —
   it used to route to a bare section page with no filter and no way back. */
.mw-row-static { cursor: default; }
.mw-row-static:hover { background: transparent; }

/* ── ⌘K command palette ── */
.cmdk-scrim { position: fixed; inset: 0; background: var(--scrim);
  z-index: 200; display: none; }
.cmdk-scrim.open { display: block; }
.cmdk-panel { position: fixed; top: 14vh; left: 50%; transform: translateX(-50%);
  width: min(560px, calc(100vw - 32px)); background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: 0 12px 40px rgba(0,0,0,.5); z-index: 201; overflow: hidden; }
.cmdk-input { width: 100%; padding: 14px 16px; background: var(--bg-2);
  border: none; border-bottom: 1px solid var(--border-soft); color: var(--text);
  font-size: var(--fs-4); outline: none; }
.cmdk-results { max-height: 46vh; overflow-y: auto; padding: 6px; }
.cmdk-group-label { font-size: var(--fs-1); letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-faint); padding: 8px 10px 4px; }
.cmdk-item { padding: 9px 10px; border-radius: var(--r-sm); cursor: pointer;
  font-size: var(--fs-3); }
.cmdk-item.active { background: var(--panel-2); }
.cmdk-item .meta { font-size: var(--fs-2); color: var(--text-dim); margin-top: 1px; }
.cmdk-hint { padding: 8px 12px; border-top: 1px solid var(--border-soft);
  font-size: var(--fs-1); color: var(--text-faint); }

/* ═══════════════════════════════════════════════════════════════════════════
   MATERIAL 3 — the field app (Android), light scheme on the tenant brand
   ───────────────────────────────────────────────────────────────────────────
   Owner's call 2026-07-27: the tech app adopts Material Design 3's FORM —
   the shape scale (pill buttons), Roboto, the type ramp, tonal surfaces,
   state layers — while the COLOR stays the tenant's own, in a light scheme.
   This supersedes the MTG "sharp corners, no pills, dark" direction FOR THIS
   SURFACE ONLY; the office shell and the customer portal keep the brand
   tokens as-is, which is why every rule below is scoped to `body.tech-app`.

   Roboto is resolved from the device, never fetched — the field app is an
   offline-capable PWA and an external font request would both break offline
   boot and add a third-party origin. On Android (the target) Roboto IS the
   system face, so the literal M3 typography comes for free.

   Layered last on purpose: it re-points the legacy custom properties the
   ~750 lines of tech CSS above already consume, so components inherit the M3
   palette without every rule being rewritten, and then restyles the components
   whose FORM (not just color) M3 specifies differently.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────────
   TENANT BRAND — the only block a licensee edits.

   This platform is being built to license; More Than Gates is tenant #1, not
   the product. So the brand lives in ONE place: the three source colors below
   and the M3 role tokens derived from them. Everything downstream — every
   component rule, every state layer — reads a role token, never a brand color.
   Re-skinning for a new customer means replacing this block and nothing else.

   MTG's own identity is gold / bronze / silver (the M·G wordmark is bronze M,
   silver T-bar, gold G), so those three metals map onto M3's primary /
   secondary / tertiary. The neutrals are warmed toward the gold hue rather
   than left grey, which is what keeps a light theme reading as MTG instead of
   as default Material.
   ───────────────────────────────────────────────────────────────────────── */
body.tech-app {
  /* ── the three brand sources (a licensee replaces these) ──────────────── */
  --brand-source-primary:   #E0B64A;   /* MTG gold   */
  --brand-source-secondary: #8C7853;   /* MTG bronze */
  --brand-source-tertiary:  #9BA3A8;   /* MTG silver */

  /* ── M3 light color roles, tones derived from the sources above ───────── */
  --md-primary:              #7A5900;   /* gold @ tone 40 — passes AA on surface */
  --md-on-primary:           #FFFFFF;
  --md-primary-container:    #FFDF95;   /* gold @ tone 90 */
  --md-on-primary-container: #261A00;
  --md-secondary:            #6B5D3F;   /* bronze @ 40 */
  --md-on-secondary:         #FFFFFF;
  --md-secondary-container:  #F5E0BB;
  --md-on-secondary-container:#241A04;
  --md-tertiary:             #4A6268;   /* silver @ 40 */
  --md-on-tertiary:          #FFFFFF;
  --md-tertiary-container:   #CDE7ED;
  --md-on-tertiary-container:#051F24;
  --md-error:                #BA1A1A;
  --md-on-error:             #FFFFFF;
  --md-error-container:      #FFDAD6;
  --md-on-error-container:   #410002;

  --md-surface:              #FFF8F1;   /* warm white, not paper-grey */
  --md-on-surface:           #1F1B13;
  --md-surface-variant:      #EDE1CF;
  --md-on-surface-variant:   #4D4639;
  --md-outline:              #7F7667;
  --md-outline-variant:      #D0C5B4;

  --md-surface-c-lowest:     #FFFFFF;
  --md-surface-c-low:        #FCF2E5;
  --md-surface-c:            #F6ECDF;
  --md-surface-c-high:       #F1E7DA;
  --md-surface-c-highest:    #EBE1D4;
  --md-inverse-surface:      #34302A;
  --md-inverse-on-surface:   #F8EFE2;

  /* ── M3 type scale (sizes are tokens; the guards in tests/web/
        test_theme_tokens.py require it, and M3 defines the ramp as tokens too) ── */
  --md-headline-sm:  24px;  --md-headline-sm-lh:  32px;
  --md-title-lg:     22px;  --md-title-lg-lh:     28px;
  --md-title-sm:     14px;  --md-title-sm-lh:     20px;
  --md-title-md:     16px;  --md-title-md-lh:     24px;
  --md-body-lg:      16px;  --md-body-lg-lh:      24px;
  --md-body-md:      14px;  --md-body-md-lh:      20px;
  --md-body-sm:      12px;  --md-body-sm-lh:      16px;
  --md-label-lg:     14px;  --md-label-lg-lh:     20px;
  --md-label-md:     12px;  --md-label-md-lh:     16px;
  --md-label-sm:     11px;  --md-label-sm-lh:     16px;

  /* ── M3 shape scale ───────────────────────────────────────────────────── */
  --md-shape-xs:   4px;
  --md-shape-sm:   8px;
  --md-shape-md:  12px;
  --md-shape-lg:  16px;
  --md-shape-xl:  28px;
  --md-shape-full: 9999px;

  /* ── M3 elevation — light needs a far softer shadow than dark did ─────── */
  --md-elev-1: 0 1px 2px rgba(0,0,0,.10), 0 1px 3px 1px rgba(0,0,0,.06);
  --md-elev-2: 0 1px 2px rgba(0,0,0,.10), 0 2px 6px 2px rgba(0,0,0,.06);
  --md-elev-3: 0 4px 8px 3px rgba(0,0,0,.08), 0 1px 3px rgba(0,0,0,.12);

  /* ── re-point the legacy tokens the tech CSS above already reads ──────── */
  --bg:       var(--md-surface);
  --panel:    var(--md-surface-c-low);
  --panel-2:  var(--md-surface-c-high);
  --border:   var(--md-outline-variant);
  --text:     var(--md-on-surface);
  --text-dim: var(--md-on-surface-variant);
  --text-faint: var(--md-on-surface-variant);  /* outline is a NON-text role in M3 */
  --brand:    var(--md-primary);
  --accent:   var(--md-primary);
  --on-gold:  var(--md-on-primary);
  --r-sm:     var(--md-shape-md);

  /* tells the UA to render form controls & scrollbars light */
  color-scheme: light;
  background: var(--md-surface);
  color: var(--md-on-surface);
  font-family: Roboto, "Google Sans Text", "Noto Sans", system-ui, -apple-system, sans-serif;
  font-size: var(--md-body-lg); line-height: var(--md-body-lg-lh); letter-spacing: .5px;
}

/* ── M3 type scale ───────────────────────────────────────────────────────── */
body.tech-app .t-heading,
body.tech-app .t-job-title {                       /* headline-small */
  font-size: var(--md-headline-sm); line-height: var(--md-headline-sm-lh); font-weight: 400; letter-spacing: 0;
  color: var(--md-on-surface);
}
body.tech-app .t-card-title,
body.tech-app .t-job-name,
body.tech-app .t-sheet-head {                      /* title-medium */
  font-size: var(--md-title-md); line-height: var(--md-title-md-lh); font-weight: 500; letter-spacing: .15px;
  color: var(--md-on-surface);
}
body.tech-app .t-meta,
body.tech-app .t-addr,
body.tech-app .t-note,
body.tech-app .t-k-label {                         /* body-medium */
  font-size: var(--md-body-md); line-height: var(--md-body-md-lh); font-weight: 400; letter-spacing: .25px;
  color: var(--md-on-surface-variant);
}
body.tech-app .t-label,
body.tech-app .t-date,
body.tech-app .t-msg-time {                        /* body-small */
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh); letter-spacing: .4px;
  color: var(--md-on-surface-variant);
}
body.tech-app .t-time {                            /* title-large, the anchor */
  font-size: var(--md-title-lg); line-height: var(--md-title-lg-lh); font-weight: 400; letter-spacing: 0;
  color: var(--md-primary);
}
@media (max-width: 430px) {
  body.tech-app .t-time {
    font-size: var(--md-label-lg); line-height: var(--md-label-lg-lh); font-weight: 600;
  }
}

/* ── top app bar (M3 small, 64dp) ────────────────────────────────────────── */
body.tech-app .t-header {
  min-height: 64px; padding: 0 4px 0 16px;
  background: var(--md-surface); border-bottom: none; box-shadow: none;
}
body.tech-app .t-app-name {                        /* title-large */
  font-size: var(--md-title-lg); line-height: var(--md-title-lg-lh); font-weight: 400; letter-spacing: 0;
  color: var(--md-on-surface);
}
body.tech-app .t-user-chip {
  background: var(--md-surface-c-high); border: none;
  border-radius: var(--md-shape-full);
}
body.tech-app .t-role-mode-btn {
  min-height: 48px; padding: 0 16px;
  border: 1px solid transparent; border-radius: var(--md-shape-full);
  background: var(--md-tertiary-container); color: var(--md-on-tertiary-container);
  font-family: inherit; font-size: var(--md-label-lg); line-height: var(--md-label-lg-lh);
  font-weight: 500; letter-spacing: 0; cursor: pointer;
}
body.tech-app .t-role-mode-btn:active {
  background: color-mix(in srgb, var(--md-on-tertiary-container) 10%, var(--md-tertiary-container));
}
body.tech-app .t-role-mode-btn[hidden] { display: none !important; }
/* Feedback / Devices / Messages — REQ-PHONE-001, feedback #93.
   These read `--surface` and `--line`, which the tech app never re-points, so
   in the dark theme they resolved to the DARK neutrals (#1E1D1A / #322F2A)
   while `--text` resolved through this file's M3 block to the LIGHT ink
   (#1F1B13): near-black label on a near-black pill, with a border too dark to
   see. The field palette below is theme-stable by design (it is contrast
   tested for sunlight), so every one of these three roles now comes from it —
   surface, ink and outline move together or not at all.
   `--md-surface-c-high` on `--md-on-surface` is 12.6:1. */
body.tech-app .t-feedback-btn,
body.tech-app .t-preview-devices-btn,
body.tech-app .t-messages-btn {
  min-width: 48px;
  min-height: 48px;
  padding: 0 12px;
  border: 1px solid var(--md-outline);
  border-radius: 24px;
  background: var(--md-surface-c-high);
  color: var(--md-on-surface);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
body.tech-app .t-feedback-btn:active,
body.tech-app .t-preview-devices-btn:active,
body.tech-app .t-messages-btn:active {
  background: color-mix(in srgb, var(--md-on-surface) 10%, var(--md-surface-c-high));
}
body.tech-app .t-feedback-btn:focus-visible,
body.tech-app .t-preview-devices-btn:focus-visible,
body.tech-app .t-messages-btn:focus-visible {
  outline: 3px solid var(--md-primary);
  outline-offset: 2px;
}
/* Messages lives in the app bar because the bottom nav is full in two role
   modes. Icon + label + unread badge on one 48dp target; the label drops on a
   narrow phone (same breakpoint that hides the app name) so the bar never
   grows wider than the device. */
body.tech-app .t-messages-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
body.tech-app .t-messages-btn[hidden] { display: none !important; }
body.tech-app .t-messages-icon { font-size: 1.1rem; line-height: 1; }
body.tech-app .t-messages-btn .t-badge { margin-left: 0; }
@media (max-width: 430px) {
  body.tech-app .t-messages-label { display: none; }
}
body.tech-app .t-device-preview-banner {
  margin: 8px max(12px, env(safe-area-inset-left));
  padding: 12px 16px;
  border: 2px solid var(--md-primary);
  border-radius: var(--md-shape-lg);
  background: var(--md-primary-container);
  color: var(--md-on-primary-container);
  overflow-wrap: anywhere;
}
body.tech-app .t-device-preview-title {
  min-height: 48px;
  display: flex;
  align-items: center;
  font-size: var(--md-title-md);
  line-height: var(--md-title-md-lh);
  font-weight: 800;
}
body.tech-app .t-device-preview-disclosure {
  margin: -4px 0 10px;
  font-size: var(--md-body-md);
  line-height: var(--md-body-md-lh);
  font-weight: 650;
}
body.tech-app .t-device-preview-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 16px;
  font-size: var(--md-label-md);
  line-height: var(--md-label-md-lh);
}
body.tech-app.device-preview [aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
}

@media (max-width: 360px) {
  body.tech-app .t-device-preview-grid { grid-template-columns: 1fr; }
}

@media (min-width: 840px) {
  body.tech-app .t-device-preview-banner {
    max-width: 1120px;
    margin-inline: auto;
  }
  body.tech-app .t-device-preview-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

body.tech-app .t-role-mode-list {
  display: flex; flex-direction: column; gap: 8px;
}
body.tech-app .t-role-mode-row {
  display: grid; grid-template-columns: 18px minmax(0, 1fr) 24px;
  align-items: center; gap: 12px;
  min-height: 64px; width: 100%; padding: 8px 12px;
  border: 1px solid var(--md-outline-variant); border-radius: var(--md-shape-md);
  background: var(--md-surface-c-high); color: var(--md-on-surface);
  font-family: inherit; text-align: left; cursor: pointer;
}
body.tech-app .t-role-mode-row.active {
  background: var(--md-secondary-container); color: var(--md-on-secondary-container);
  border-color: transparent;
}
body.tech-app .t-role-mode-dot {
  width: 10px; height: 10px; border-radius: var(--md-shape-full);
  background: var(--md-primary); justify-self: center;
}
body.tech-app .t-role-mode-copy {
  display: grid; gap: 2px; min-width: 0;
}
body.tech-app .t-role-mode-copy strong {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--md-title-md); line-height: var(--md-title-md-lh);
  font-weight: 500; letter-spacing: 0;
}
body.tech-app .t-role-mode-copy span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
  color: var(--md-on-surface-variant); letter-spacing: 0;
}
body.tech-app .t-role-mode-row.active .t-role-mode-copy span {
  color: color-mix(in srgb, var(--md-on-secondary-container) 74%, transparent);
}
body.tech-app .t-role-mode-check {
  justify-self: end; font-size: var(--md-title-md); line-height: var(--md-title-md-lh);
  color: inherit;
}

body.tech-app .t-role-briefing {
  display: grid; gap: 12px; margin: 0 0 14px; padding: 12px;
  background: var(--md-surface-c-high); border-radius: var(--md-shape-md);
}
body.tech-app .t-ops-panels {
  display: grid; gap: 10px; margin: 0 0 14px;
}
body.tech-app .t-ops-panel {
  padding: 12px;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-md);
  background: var(--md-surface);
}
body.tech-app .t-ops-panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-bottom: 8px;
}
body.tech-app .t-ops-panel-title {
  font-size: var(--md-title-sm); line-height: var(--md-title-sm-lh);
  font-weight: 500; color: var(--md-on-surface);
}
body.tech-app .t-ops-count {
  display: inline-grid; place-items: center; min-width: 24px; height: 24px; padding: 0 6px;
  border-radius: var(--md-shape-full); background: var(--md-error-container);
  color: var(--md-on-error-container); font-size: var(--md-label-md); font-weight: 600;
}
body.tech-app .t-ops-list { display: grid; gap: 6px; }
body.tech-app .t-ops-row {
  display: grid; grid-template-columns: 8px minmax(0, 1fr); gap: 9px; width: 100%;
  padding: 8px 0; border: 0; border-top: 1px solid var(--md-outline-variant);
  background: transparent; color: var(--md-on-surface); text-align: left; font: inherit; cursor: pointer;
}
body.tech-app .t-ops-row:first-child { border-top: 0; }
body.tech-app .t-ops-row strong,
body.tech-app .t-ops-row small { display: block; overflow-wrap: anywhere; }
body.tech-app .t-ops-row strong {
  font-size: var(--md-label-lg); line-height: var(--md-label-lg-lh); font-weight: 500;
}
body.tech-app .t-ops-row small {
  margin-top: 2px; font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
  color: var(--md-on-surface-variant);
}
body.tech-app .t-ops-severity {
  width: 8px; height: 8px; margin-top: 5px; border-radius: 50%; background: var(--md-outline);
}
body.tech-app .t-ops-severity.high { background: var(--md-error); }
body.tech-app .t-ops-severity.medium { background: var(--md-tertiary); }
body.tech-app .t-ops-severity.low { background: var(--md-primary); }
body.tech-app .t-owner-metrics {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-bottom: 10px;
}
body.tech-app .t-owner-metric {
  display: grid; gap: 1px; min-width: 0; padding: 8px;
  background: var(--md-surface-c-low); border-radius: var(--md-shape-sm);
}
body.tech-app .t-owner-metric strong {
  font-size: var(--md-title-md); line-height: var(--md-title-md-lh); font-weight: 500;
  color: var(--md-on-surface); overflow-wrap: anywhere;
}
body.tech-app .t-owner-metric span,
body.tech-app .t-owner-metric small {
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh); color: var(--md-on-surface-variant);
}
body.tech-app .t-device-create { display: grid; gap: 6px; margin-bottom: 16px; }
body.tech-app .t-device-create-actions,
body.tech-app .t-device-controls { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
body.tech-app .t-device-create-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.tech-app .t-device-list { display: grid; gap: 8px; }
body.tech-app .t-device-row {
  display: grid; gap: 4px; padding: 10px 0; border-top: 1px solid var(--md-outline-variant);
}
body.tech-app .t-device-row:first-child { border-top: 0; }
body.tech-app .t-device-row strong { overflow-wrap: anywhere; }
body.tech-app .t-device-row small,
body.tech-app .t-device-status {
  color: var(--md-on-surface-variant); font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
  overflow-wrap: anywhere;
}
body.tech-app .t-device-controls { grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; margin-top: 2px; }
body.tech-app .t-handoff-row {
  display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--md-outline-variant);
}
body.tech-app .t-handoff-row:first-child { border-top: 0; }
body.tech-app .t-handoff-row > button:first-child {
  flex: 1 1 auto; min-width: 0; padding: 0; border: 0; background: transparent; color: var(--md-on-surface);
  font: inherit; text-align: left; cursor: pointer;
}
body.tech-app .t-handoff-row strong,
body.tech-app .t-handoff-row small { display: block; overflow-wrap: anywhere; }
body.tech-app .t-handoff-row small { color: var(--md-on-surface-variant); font-size: var(--md-body-sm); }
body.tech-app .t-ready-packet { border-color: var(--md-primary); }
body.tech-app .t-ready-address { margin: 4px 0 8px; font-weight: 500; overflow-wrap: anywhere; }
body.tech-app .t-ready-group { margin-top: 10px; overflow-wrap: anywhere; }
body.tech-app .t-ready-group strong { display: block; margin-bottom: 2px; font-size: var(--md-label-lg); font-weight: 500; }
body.tech-app .t-ready-safety {
  margin-top: 10px; padding: 7px 8px; border-radius: var(--md-shape-sm);
  background: var(--md-secondary-container); color: var(--md-on-secondary-container);
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh); overflow-wrap: anywhere;
}
@media (max-width: 390px) {
  body.tech-app .t-device-create-actions { grid-template-columns: 1fr; }
  body.tech-app .t-device-controls { grid-template-columns: minmax(0, 1fr) auto; }
  body.tech-app .t-device-controls [data-device-return] { grid-column: 2; }
}
body.tech-app .t-role-briefing-main {
  min-width: 0;
}
body.tech-app .t-role-kicker {
  font-size: var(--md-label-md); line-height: var(--md-label-md-lh);
  font-weight: 500; letter-spacing: 0; color: var(--md-primary);
}
body.tech-app .t-role-main {
  margin-top: 2px;
  font-size: var(--md-title-lg); line-height: var(--md-title-lg-lh);
  font-weight: 400; letter-spacing: 0; color: var(--md-on-surface);
  overflow-wrap: anywhere;
}
body.tech-app .t-role-sub {
  margin-top: 2px;
  font-size: var(--md-body-md); line-height: var(--md-body-md-lh);
  letter-spacing: 0; color: var(--md-on-surface-variant);
  overflow-wrap: anywhere;
}
body.tech-app .t-role-actions {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
}
body.tech-app .t-role-action {
  display: grid; align-content: center; gap: 2px;
  min-height: 64px; min-width: 0; padding: 8px 12px;
  border: 1px solid var(--md-outline-variant); border-radius: var(--md-shape-sm);
  background: var(--md-surface); color: var(--md-on-surface);
  font-family: inherit; text-align: left; cursor: pointer;
}
body.tech-app .t-role-action:active {
  background: color-mix(in srgb, var(--md-primary) 10%, var(--md-surface));
}
body.tech-app .t-role-action:disabled {
  opacity: .48; cursor: default;
}
body.tech-app .t-role-action-label,
body.tech-app .t-role-action-caption {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.tech-app .t-role-action-label {
  font-size: var(--md-label-lg); line-height: var(--md-label-lg-lh);
  font-weight: 500; letter-spacing: 0;
}
body.tech-app .t-role-action-caption {
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
  color: var(--md-on-surface-variant); letter-spacing: 0;
}
@media (min-width: 560px) {
  body.tech-app .t-role-briefing {
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.4fr);
    align-items: stretch;
  }
}

/* ── buttons: M3 common buttons are FULL-round ───────────────────────────── */
body.tech-app .t-btn {
  border-radius: var(--md-shape-full);
  min-height: 48px;                                 /* ≥ M3 48dp touch target */
  padding: 0 24px;
  font-family: inherit;
  font-size: var(--md-label-lg); line-height: var(--md-label-lg-lh); font-weight: 500; letter-spacing: .1px;
  border: 1px solid var(--md-outline);
  background: transparent; color: var(--md-primary);
  box-shadow: none; transition: background-color .1s linear, box-shadow .1s linear;
}
/* filled — the primary action */
body.tech-app .t-btn-gold {
  background: var(--md-primary); color: var(--md-on-primary);
  border-color: transparent; box-shadow: none;
}
body.tech-app .t-btn-gold:hover  { box-shadow: var(--md-elev-1); }
/* M3 state layers: 8% hover, 10% pressed, over the container color */
body.tech-app .t-btn-gold:active {
  background: color-mix(in srgb, var(--md-on-primary) 10%, var(--md-primary));
  box-shadow: none; transform: none;
}
/* outlined — secondary actions */
body.tech-app .t-btn-ghost {
  background: transparent; color: var(--md-primary);
  border: 1px solid var(--md-outline);
}
body.tech-app .t-btn-ghost:active {
  background: color-mix(in srgb, var(--md-primary) 10%, transparent);
  transform: none;
}
body.tech-app .t-btn:active { transform: none; }   /* M3 uses state layers, not scale */
body.tech-app .t-btn-block { width: 100%; }
body.tech-app .t-btn-sm {
  min-height: 48px; padding: 0 16px; font-size: var(--md-label-lg);
}

/* ── cards: M3 filled card, 12dp ─────────────────────────────────────────── */
body.tech-app .t-card,
body.tech-app .t-vcard {
  background: var(--md-surface-c-highest);
  border: none; border-radius: var(--md-shape-md);
  box-shadow: none;
}
body.tech-app .t-vcard:active {
  background: color-mix(in srgb, var(--md-on-surface) 10%, var(--md-surface-c-highest));
}

/* ── navigation bar (M3, 80dp, pill active indicator) ────────────────────── */
body.tech-app .t-nav {
  min-height: 80px;
  background: var(--md-surface-c); backdrop-filter: none;
  border-top: none; box-shadow: none;
}
body.tech-app .t-nav-tab {
  gap: 4px; padding: 12px 0 16px;
  color: var(--md-on-surface-variant);
  font-family: inherit;
}
body.tech-app .t-nav-tab.active { color: var(--md-on-surface); }
body.tech-app .t-nav-tab.active::after { content: none; }   /* kill the underline */
body.tech-app .t-nav-tab { flex: 1 1 0; min-width: 0; }
/* M3 specs a 64dp active indicator, but that assumes 3-5 destinations. This
   bar has SIX, so a fixed 64px overflows a 360px phone (6x64 = 384). The
   indicator caps at the spec width and shrinks below it instead of pushing
   the bar wider than the screen. */
body.tech-app .t-tab-icon {
  display: flex; align-items: center; justify-content: center;
  width: 100%; max-width: 64px; height: 32px;
  border-radius: var(--md-shape-full);
  background: transparent; transition: background-color .1s linear;
}
body.tech-app .t-nav-tab.active .t-tab-icon {
  background: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}
body.tech-app .t-tab-label {                       /* label-medium */
  font-size: var(--md-label-md); line-height: var(--md-label-md-lh); font-weight: 500; letter-spacing: .5px;
  /* M3 caps a navigation bar at FIVE destinations; this one carries six, so on
     a 320px phone each tab gets ~53px and "Assistant" no longer fits. Clip
     rather than push the whole document wider than the screen — the real fix
     is one fewer destination, which is a product call, not a CSS one. */
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 360px) {
  body.tech-app .t-tab-label {
    font-size: var(--md-label-sm); letter-spacing: .1px;
  }
}
body.tech-app .t-nav-tab.active .t-tab-label { font-weight: 700; }

/* ── bottom sheet (M3: 28dp top corners + drag handle) ───────────────────── */
body.tech-app .t-sheet {
  background: var(--md-surface-c-low);
  border: none;
  border-radius: var(--md-shape-xl) var(--md-shape-xl) 0 0;
  padding-top: 28px; box-shadow: var(--md-elev-3);
}
body.tech-app .t-sheet::before {                   /* the drag handle */
  content: ""; position: absolute; top: 12px; left: 50%;
  transform: translateX(-50%);
  width: 32px; height: 4px; border-radius: var(--md-shape-full);
  background: color-mix(in srgb, var(--md-on-surface-variant) 40%, transparent);
}
body.tech-app .t-sheet-backdrop { background: rgba(0,0,0,.32); }

/* ── sheets survive the software keyboard — REQ-PHONE-001 ─────────────────
   `dvh` follows browser chrome, not the keyboard, so a sheet pinned to the
   bottom of the layout viewport puts its own actions behind the keyboard the
   moment a field takes focus. tech.js publishes the two visualViewport facts
   that fix it; both fall back to the previous behavior when the variables are
   absent, so a browser without visualViewport is no worse off than before. */
body.tech-app .t-sheet {
  bottom: var(--t-keyboard-inset, 0px);
  max-height: min(85dvh, var(--t-sheet-visible-height, 85dvh));
}
/* A sheet that owns its own scrolling: fixed head, scrolling body, and an
   action row that cannot leave the screen. */
body.tech-app .t-sheet-scrolls {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-bottom: 0;
}
body.tech-app .t-sheet-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}
body.tech-app .t-sheet-actions {
  position: sticky;
  bottom: 0;
  flex: 0 0 auto;
  padding: 12px 0 calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--md-surface-c-low);
  border-top: 1px solid var(--md-outline-variant);
}
/* Touch targets stay where they were: 48dp minimum on everything in the
   scrolling body and the pinned row (REQ-PHONE-001). */
body.tech-app .t-sheet-scroll .t-btn,
body.tech-app .t-sheet-actions .t-btn,
body.tech-app .t-sheet-scroll .t-input,
body.tech-app .t-sheet-scroll summary {
  min-height: 48px;
}
body.tech-app .t-sheet-scroll .t-notes { min-height: 96px; }
body.tech-app .t-sheet-scroll summary {
  display: flex;
  align-items: center;
}

/* ── the pinned job-action bar rides the M3 surface ──────────────────────── */
body.tech-app .t-actionbar {
  background: var(--md-surface-c);
  backdrop-filter: none; border-top: none;
  box-shadow: var(--md-elev-2);
  bottom: calc(80px + env(safe-area-inset-bottom, 0px));  /* clears the 80dp nav */
}
body.tech-app .t-main {
  padding-bottom: calc(160px + env(safe-area-inset-bottom, 0px));
}

/* ── chips (M3 assist/filter, 8dp, 32dp tall) ────────────────────────────── */
body.tech-app .t-chip,
body.tech-app .t-quick-chip,
body.tech-app .t-assistant-chip {
  min-height: 32px; padding: 0 16px;
  border-radius: var(--md-shape-sm);
  border: 1px solid var(--md-outline);
  background: transparent; color: var(--md-on-surface-variant);
  font-size: var(--md-label-lg); line-height: var(--md-label-lg-lh); font-weight: 500; letter-spacing: .1px;
}
body.tech-app .t-badge {
  border-radius: var(--md-shape-full);
  background: var(--md-error); color: var(--md-on-error);
  font-size: var(--md-label-sm); font-weight: 500;
}

/* ── text fields (M3 outlined, 4dp) ──────────────────────────────────────── */
body.tech-app .t-input,
body.tech-app .t-notes {
  min-height: 56px; padding: 16px;
  border-radius: var(--md-shape-xs);
  border: 1px solid var(--md-outline);
  background: transparent; color: var(--md-on-surface);
  font-family: inherit; font-size: var(--md-body-lg); line-height: var(--md-body-lg-lh); letter-spacing: .5px;
}
body.tech-app .t-input:focus,
body.tech-app .t-notes:focus {
  outline: none; border-color: var(--md-primary); border-width: 2px; padding: 15px;
}
body.tech-app .t-input::placeholder,
body.tech-app .t-notes::placeholder { color: var(--md-on-surface-variant); }

/* ── AI closeout assist (M3 filled card + explicit interaction states) ───── */
body.tech-app .t-ai-closeout {
  display: grid; gap: 10px; margin: 0 0 16px; padding: 16px;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-md);
  background: var(--md-surface-c);
  color: var(--md-on-surface);
  box-shadow: var(--md-elev-1);
}
body.tech-app .t-ai-closeout-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: var(--md-title-md); line-height: var(--md-title-md-lh); font-weight: 500;
}
body.tech-app .t-ai-closeout-chip {
  display: inline-flex; align-items: center; min-height: 32px; padding: 0 12px;
  border-radius: var(--md-shape-sm);
  background: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
  font-size: var(--md-label-md); line-height: var(--md-label-md-lh); font-weight: 500;
}
body.tech-app .t-ai-closeout-copy {
  margin: 0; color: var(--md-on-surface-variant);
  font-size: var(--md-body-md); line-height: var(--md-body-md-lh);
}
body.tech-app .t-ai-closeout-mic {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; min-height: 48px;
  border-color: var(--md-outline);
  background: transparent; color: var(--md-primary);
}
body.tech-app .t-ai-closeout-mic-icon {
  width: 20px; height: 20px; flex: none; fill: currentColor;
}
body.tech-app .t-ai-closeout-mic:focus-visible {
  outline: 3px solid var(--md-primary);
  outline-offset: 2px;
}
body.tech-app .t-ai-closeout-mic:active {
  background: color-mix(in srgb, var(--md-primary) 10%, transparent);
}
body.tech-app .t-ai-closeout-mic.is-recording {
  border-color: var(--md-error);
  background: var(--md-error-container); color: var(--md-on-error-container);
}
body.tech-app .t-ai-closeout-mic.is-recording > [aria-hidden="true"] {
  color: var(--md-error);
  animation: t-ai-closeout-pulse 1.2s ease-in-out infinite;
}
body.tech-app .t-ai-closeout-mic.is-processing {
  border-color: transparent;
  background: var(--md-tertiary-container); color: var(--md-on-tertiary-container);
}
body.tech-app .t-ai-closeout-mic:disabled {
  opacity: .38; cursor: default; box-shadow: none;
}
body.tech-app .t-ai-closeout-status,
body.tech-app .t-ai-closeout-review {
  display: grid; gap: 8px;
  padding: 8px 10px; border-radius: var(--md-shape-sm);
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm); line-height: var(--md-body-sm-lh);
}
body.tech-app .t-ai-closeout-status.has-error {
  background: var(--md-error-container); color: var(--md-on-error-container);
}
body.tech-app .t-ai-closeout-status.has-review,
body.tech-app .t-ai-closeout-review {
  background: var(--md-secondary-container); color: var(--md-on-secondary-container);
}
body.tech-app .t-ai-closeout-status.is-disabled {
  border: 1px solid var(--md-outline-variant);
}
body.tech-app .t-ai-closeout-meter {
  width: 100%; height: 10px; overflow: hidden;
  border-radius: 999px;
  background: color-mix(in srgb, var(--md-outline) 28%, transparent);
}
body.tech-app .t-ai-closeout-meter[hidden] { display: none; }
body.tech-app .t-ai-closeout-meter > span {
  display: block; width: var(--voice-level, 0%); height: 100%;
  border-radius: inherit; background: var(--md-error);
  transition: width 80ms linear;
}
body.tech-app .t-ai-filled {
  border-color: var(--md-primary) !important;
  background: color-mix(in srgb, var(--md-secondary-container) 62%, transparent) !important;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--md-primary) 18%, transparent);
}
@keyframes t-ai-closeout-pulse {
  0%, 100% { opacity: .55; transform: scale(.82); }
  50% { opacity: 1; transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  body.tech-app .t-ai-closeout-mic,
  body.tech-app .t-ai-closeout-mic.is-recording > [aria-hidden="true"] {
    animation: none; transition: none;
  }
}

/* ── snackbar (M3: inverse surface, 4dp) ─────────────────────────────────── */
body.tech-app .t-toast {
  border-radius: var(--md-shape-xs);
  background: var(--md-inverse-surface); color: var(--md-inverse-on-surface);
  box-shadow: var(--md-elev-3);
  font-size: var(--md-body-md); line-height: var(--md-body-md-lh); letter-spacing: .25px;
  border: none;
}
body.tech-app .t-toast-bad  { background: var(--md-error-container);   color: var(--md-on-error-container); }
body.tech-app .t-toast-good { background: var(--md-secondary-container); color: var(--md-on-secondary-container); }

/* ── tonal containers for status surfaces ────────────────────────────────── */
body.tech-app .t-banner,
body.tech-app .t-warnbox {
  border-radius: var(--md-shape-md); border: none;
  background: var(--md-error-container); color: var(--md-on-error-container);
}
body.tech-app .t-resultbox {
  border-radius: var(--md-shape-md); border: none;
  background: var(--md-surface-c-high); color: var(--md-on-surface);
}
body.tech-app .t-resultbox-good { background: var(--md-secondary-container); color: var(--md-on-secondary-container); }
body.tech-app .t-resultbox-warn { background: var(--md-tertiary-container); color: var(--md-on-tertiary-container); }

/* ── assistant bubbles read as M3 tonal containers ───────────────────────── */
body.tech-app .t-assistant-bubble,
body.tech-app .t-msg-in {
  background: var(--md-surface-c-high); color: var(--md-on-surface);
  border: none; border-radius: var(--md-shape-lg);
}
body.tech-app .t-msg-out {
  background: var(--md-primary-container); color: var(--md-on-primary-container);
  border: none; border-radius: var(--md-shape-lg);
}

/* the avatar chip carried a raw translucent gold from the shared sheet, which
   composites to ~3.4:1 on a light ground — the primary-container pair is the
   M3 role for exactly this and clears AA. */
body.tech-app .t-user-chip .user-avatar {
  background: var(--md-primary-container);
  color: var(--md-on-primary-container);
}
body.tech-app .t-user-chip .user-role { color: var(--md-on-surface-variant); }

/* Directions is an <a> (it must open the nav app), so it needs the button box
   spelled out — .t-btn assumes a <button>'s default display. */
body.tech-app .t-directions {
  display: inline-flex; align-items: center; justify-content: center;
  text-decoration: none; margin-top: 12px;
}

/* The clock bar carries a sentence AND up to four buttons. On a phone those
   cannot share one row: flex squeezed the status into a one-word-per-line
   column. The status takes its own line and the buttons wrap under it. */
body.tech-app #t-clockbar { flex-wrap: wrap; }
body.tech-app #t-clockbar > .t-meta { flex: 1 0 100%; }
/* Four actions on one row at 360px: the pill padding that suits a standalone
   button is too generous when they are sharing a phone's width. */
body.tech-app #t-clockbar > .t-btn {
  flex: 1 1 0; min-width: 0; padding: 0 8px;
  font-size: var(--md-label-md);
  overflow: hidden; text-overflow: ellipsis;
}

/* The top bar holds logo + title + tracking pill + user chip + Log out. That
   fits a tablet, not a 360px phone: once the "on the clock" pill appears the
   row pushed the whole DOCUMENT to 483px wide and every screen scrolled
   sideways. The pill takes its own line and the name ellipsizes rather than
   forcing the bar wider than the device. */
body.tech-app .t-header { flex-wrap: wrap; row-gap: 4px; }
body.tech-app .t-tracking-pill { flex: 1 0 100%; order: 5; }
body.tech-app .t-user-chip { min-width: 0; }
body.tech-app .t-user-chip .user-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.tech-app .t-app-name { min-width: 0; }
@media (max-width: 430px) {
  body.tech-app .t-app-name { display: none; }
  body.tech-app .t-header { column-gap: 8px; }
}

/* Drive-in-progress strip — sits directly above the navigation bar so it is
   the first thing in reach when a tech switches back from the maps app. Tonal
   rather than loud: it is a way back, not an alarm. */
body.tech-app .t-drive-strip {
  position: fixed; bottom: calc(80px + env(safe-area-inset-bottom, 0px));
  left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 640px; z-index: 46;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  background: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
  box-shadow: var(--md-elev-2);
}
body.tech-app .t-drive-strip[hidden] { display: none; }
body.tech-app .t-drive-open {
  flex: 1 1 auto; min-width: 0;
  background: transparent; border: none; padding: 0;
  color: inherit; text-align: left; cursor: pointer;
  font-family: inherit; font-size: var(--md-label-lg); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.tech-app .t-drive-strip .t-btn { flex: 0 0 auto; }
/* The strip and the pinned action bar cannot occupy the same band. Toggled
   from JS, not a sibling selector: the strip sits AFTER the action bar in the
   document, so `~` would never match it. */
body.tech-app .t-actionbar.has-drive-strip {
  bottom: calc(132px + env(safe-area-inset-bottom, 0px));
}

/* Collapsed clock bar — one quiet line that still says the hours, so hiding
   the controls never hides the number the tech is being paid on. */
body.tech-app .t-clock-peek {
  flex: 1 1 100%; min-width: 0;
  background: transparent; border: none; padding: 4px 0;
  color: var(--md-on-surface-variant); text-align: left; cursor: pointer;
  font-family: inherit; font-size: var(--md-body-md); line-height: var(--md-body-md-lh);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* the ✕ is an icon target, not a labelled action — it should not eat a share
   of the row the way the word buttons do */
body.tech-app #t-clockbar > #t-clock-hide { flex: 0 0 auto; padding: 0 12px; }

/* `.t-nav-tab { display: flex }` beats the [hidden] attribute's UA
   `display: none`, so tabs the code had already hidden kept rendering — a
   field_tech was offered Fab and Calls and got "your role can't do that
   (comms.inbox)" for their trouble. The permission logic was right the whole
   time; the CSS was overriding it. */
body.tech-app .t-nav-tab[hidden] { display: none !important; }

/* ── the overflow sheet's rows ───────────────────────────────────────────── */
body.tech-app .t-more-actions { gap: 8px; }

/* M3 motion: standard easing, short duration */
body.tech-app .t-view-enter {
  animation-timing-function: cubic-bezier(.2, 0, 0, 1);
  animation-duration: .25s;
}

/* Owner and operations map: the browser and company-phone views read the same
   live map endpoint. The broader desktop canvas contracts to a single column
   on a phone, so names and timestamps remain easy to scan in the field. */
body.tech-app .t-main.t-main-map { max-width: 1160px; }
body.tech-app .t-live-map-view { min-width: 0; }
body.tech-app .t-live-map-header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 4px 0 12px;
}
body.tech-app .t-live-map-title { font-size: var(--md-title-lg); font-weight: 600; }
body.tech-app .t-live-map-status { color: var(--md-on-surface-variant); font-size: var(--md-body-sm); margin-top: 2px; }
body.tech-app .t-live-map-refresh {
  flex: 0 0 48px; width: 48px; height: 48px; border: 1px solid var(--border);
  border-radius: 50%; background: transparent; color: var(--brand); cursor: pointer;
  font: inherit; font-size: var(--md-title-lg); line-height: 1;
}
body.tech-app .t-live-map-refresh:hover { background: var(--panel-2); }
body.tech-app .t-live-map-body {
  display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 12px; align-items: stretch;
}
body.tech-app .t-live-map-canvas {
  height: min(62vh, 620px); min-height: 380px; border: 1px solid var(--border);
  border-radius: 8px; overflow: hidden; background: var(--panel-2);
}
body.tech-app .t-live-map-roster {
  max-height: min(62vh, 620px); overflow: auto; border: 1px solid var(--border);
  border-radius: 8px; background: var(--panel); padding: 4px;
}
body.tech-app .t-live-map-empty { color: var(--md-on-surface-variant); font-size: var(--md-body-sm); padding: 12px; }
body.tech-app .t-live-map-person {
  display: flex; align-items: center; gap: 4px; border-bottom: 1px solid var(--border);
}
body.tech-app .t-live-map-person:last-child { border-bottom: 0; }
body.tech-app .t-live-map-person-main {
  display: flex; flex: 1 1 auto; min-width: 0; align-items: center; gap: 9px; border: 0;
  background: transparent; color: inherit; cursor: pointer; padding: 10px 4px 10px 8px; text-align: left; font: inherit;
}
body.tech-app .t-live-map-person-main:hover { background: var(--panel-2); }
body.tech-app .t-live-map-person-main:disabled { cursor: default; opacity: .68; }
body.tech-app .t-live-map-person-initials,
body.tech-app .t-live-map-marker {
  display: inline-flex; flex: 0 0 32px; width: 32px; height: 32px; align-items: center; justify-content: center;
  border: 2px solid var(--bg); border-radius: 50%; background: var(--brand); color: var(--on-gold, #1a1508);
  font-size: var(--md-label-sm); font-weight: 700;
}
body.tech-app .t-live-map-marker.is-off,
body.tech-app .t-live-map-person.is-off .t-live-map-person-initials {
  background: var(--panel-2); border-color: var(--border); color: var(--md-on-surface-variant);
}
body.tech-app .t-live-map-person-copy { display: grid; flex: 1 1 auto; min-width: 0; gap: 1px; }
body.tech-app .t-live-map-person-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--md-label-lg); font-weight: 600; }
body.tech-app .t-live-map-person-role,
body.tech-app .t-live-map-person-job,
body.tech-app .t-live-map-person-status { color: var(--md-on-surface-variant); font-size: var(--md-body-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.tech-app .t-live-map-person-role { text-transform: uppercase; font-size: var(--md-label-sm); font-weight: 600; }
body.tech-app .t-live-map-job,
body.tech-app .t-live-map-popup-job { border: 0; background: transparent; color: var(--brand); cursor: pointer; font: inherit; font-size: var(--md-label-sm); font-weight: 600; padding: 4px; }
body.tech-app .t-live-map-popup-role { color: var(--md-on-surface-variant); font-size: var(--md-body-sm); margin-left: 5px; }
@media (max-width: 760px) {
  body.tech-app .t-main.t-main-map {
    max-width: 640px;
    padding-bottom: calc(116px + env(safe-area-inset-bottom, 0px));
  }
  body.tech-app .t-live-map-body { grid-template-columns: minmax(0, 1fr); }
  body.tech-app .t-live-map-canvas { height: 48vh; min-height: 330px; }
  body.tech-app .t-live-map-roster { max-height: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   M3 PRODUCT FOUNDATION TOKENS — REQ-M3-001

   Decision #75 expands Material 3 from the field app to every first-party
   surface. The tenant owns identity; components own no brand literals. These
   aliases deliberately build on the contrast-tested product palette so the
   foundation can land without recoloring legacy office and portal screens.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  /* color roles */
  --md-sys-color-primary: var(--brand-text);
  --md-sys-color-on-primary: var(--surface);
  --md-sys-color-primary-container: var(--brand-bg);
  --md-sys-color-on-primary-container: var(--brand-text);
  --md-sys-color-secondary: var(--text-2);
  --md-sys-color-on-secondary: var(--surface);
  --md-sys-color-secondary-container: var(--surface-2);
  --md-sys-color-on-secondary-container: var(--text-1);
  --md-sys-color-tertiary: var(--info);
  --md-sys-color-on-tertiary: var(--surface);
  --md-sys-color-tertiary-container: var(--info-bg);
  --md-sys-color-on-tertiary-container: var(--info);
  --md-sys-color-error: var(--bad);
  --md-sys-color-on-error: var(--surface);
  --md-sys-color-error-container: var(--bad-bg);
  --md-sys-color-on-error-container: var(--bad);
  --md-sys-color-surface: var(--surface);
  --md-sys-color-on-surface: var(--text-1);
  --md-sys-color-surface-variant: var(--surface-2);
  --md-sys-color-on-surface-variant: var(--text-2);
  --md-sys-color-surface-container-low: var(--surface);
  --md-sys-color-surface-container: var(--surface-2);
  --md-sys-color-surface-container-high: var(--n-100);
  --md-sys-color-outline: var(--border-ctl);
  --md-sys-color-outline-variant: var(--hairline);
  --md-sys-color-inverse-surface: var(--text-1);
  --md-sys-color-inverse-on-surface: var(--surface);
  --md-sys-color-scrim: var(--scrim);

  /* type roles — device-resident fonts only; no runtime font request */
  --md-sys-typescale-font: Roboto, "Google Sans Text", "Noto Sans", system-ui,
                            -apple-system, sans-serif;
  --md-sys-typescale-headline-small-size: 24px;
  --md-sys-typescale-headline-small-line-height: 32px;
  --md-sys-typescale-title-small-size: 14px;
  --md-sys-typescale-title-small-line-height: 20px;
  --md-sys-typescale-title-medium-size: 16px;
  --md-sys-typescale-title-medium-line-height: 24px;
  --md-sys-typescale-body-small-size: 12px;
  --md-sys-typescale-body-small-line-height: 16px;
  --md-sys-typescale-body-medium-size: 14px;
  --md-sys-typescale-body-medium-line-height: 20px;
  --md-sys-typescale-body-large-size: 16px;
  --md-sys-typescale-body-large-line-height: 24px;
  --md-sys-typescale-label-medium-size: 12px;
  --md-sys-typescale-label-medium-line-height: 16px;
  --md-sys-typescale-label-large-size: 14px;
  --md-sys-typescale-label-large-line-height: 20px;

  /* shape roles */
  --md-sys-shape-corner-extra-small: 4px;
  --md-sys-shape-corner-small: 8px;
  --md-sys-shape-corner-medium: 12px;
  --md-sys-shape-corner-large: 16px;
  --md-sys-shape-corner-extra-large: 28px;
  --md-sys-shape-corner-full: 9999px;

  /* elevation roles */
  --md-sys-elevation-level0: none;
  --md-sys-elevation-level1: var(--sh-1);
  --md-sys-elevation-level2: var(--sh-2);
  --md-sys-elevation-level3: var(--sh-3);

  /* interaction-state layers */
  --md-sys-state-hover-opacity: .08;
  --md-sys-state-focus-opacity: .10;
  --md-sys-state-pressed-opacity: .10;
  --md-sys-state-disabled-opacity: .38;
  --md-sys-state-scrim-opacity: .32;
}

/* M3 PRODUCT DARK ROLES — REQ-M3-002
   Restated deliberately: the contract test requires the explicit dark scheme
   to publish every role rather than relying on accidental inheritance. The
   referenced palette tokens flip in the dark block near the top of this file. */
:root[data-theme="dark"] {
  --md-sys-color-primary: var(--brand-text);
  --md-sys-color-on-primary: var(--surface);
  --md-sys-color-primary-container: var(--brand-bg);
  --md-sys-color-on-primary-container: var(--brand-text);
  --md-sys-color-secondary: var(--text-2);
  --md-sys-color-on-secondary: var(--surface);
  --md-sys-color-secondary-container: var(--surface-2);
  --md-sys-color-on-secondary-container: var(--text-1);
  --md-sys-color-tertiary: var(--info);
  --md-sys-color-on-tertiary: var(--surface);
  --md-sys-color-tertiary-container: var(--info-bg);
  --md-sys-color-on-tertiary-container: var(--info);
  --md-sys-color-error: var(--bad);
  --md-sys-color-on-error: var(--surface);
  --md-sys-color-error-container: var(--bad-bg);
  --md-sys-color-on-error-container: var(--bad);
  --md-sys-color-surface: var(--surface);
  --md-sys-color-on-surface: var(--text-1);
  --md-sys-color-surface-variant: var(--surface-2);
  --md-sys-color-on-surface-variant: var(--text-2);
  --md-sys-color-surface-container-low: var(--surface);
  --md-sys-color-surface-container: var(--surface-2);
  --md-sys-color-surface-container-high: var(--n-100);
  --md-sys-color-outline: var(--border-ctl);
  --md-sys-color-outline-variant: var(--hairline);
  --md-sys-color-inverse-surface: var(--text-1);
  --md-sys-color-inverse-on-surface: var(--surface);
  --md-sys-color-scrim: var(--scrim);
}

/* M3 FIELD COMPATIBILITY ALIASES — REQ-M3-001
   #74's field palette is already outdoor- and contrast-tested. Mapping it to
   the shared names lets new primitives work inside the PWA without changing a
   single existing .t-* component or enabling field dark mode by accident. */
body.tech-app {
  --md-sys-color-primary: var(--md-primary);
  --md-sys-color-on-primary: var(--md-on-primary);
  --md-sys-color-primary-container: var(--md-primary-container);
  --md-sys-color-on-primary-container: var(--md-on-primary-container);
  --md-sys-color-secondary: var(--md-secondary);
  --md-sys-color-on-secondary: var(--md-on-secondary);
  --md-sys-color-secondary-container: var(--md-secondary-container);
  --md-sys-color-on-secondary-container: var(--md-on-secondary-container);
  --md-sys-color-tertiary: var(--md-tertiary);
  --md-sys-color-on-tertiary: var(--md-on-tertiary);
  --md-sys-color-tertiary-container: var(--md-tertiary-container);
  --md-sys-color-on-tertiary-container: var(--md-on-tertiary-container);
  --md-sys-color-error: var(--md-error);
  --md-sys-color-on-error: var(--md-on-error);
  --md-sys-color-error-container: var(--md-error-container);
  --md-sys-color-on-error-container: var(--md-on-error-container);
  --md-sys-color-surface: var(--md-surface);
  --md-sys-color-on-surface: var(--md-on-surface);
  --md-sys-color-surface-variant: var(--md-surface-variant);
  --md-sys-color-on-surface-variant: var(--md-on-surface-variant);
  --md-sys-color-surface-container-low: var(--md-surface-c-low);
  --md-sys-color-surface-container: var(--md-surface-c);
  --md-sys-color-surface-container-high: var(--md-surface-c-high);
  --md-sys-color-outline: var(--md-outline);
  --md-sys-color-outline-variant: var(--md-outline-variant);
  --md-sys-color-inverse-surface: var(--md-inverse-surface);
  --md-sys-color-inverse-on-surface: var(--md-inverse-on-surface);
}

/* ═══════════════════════════════════════════════════════════════════════════
   M3 PRODUCT COMPONENT FOUNDATION START — REQ-M3-003

   New shared first-party UI is added inside this guarded zone and namespaced
   `.md3-*`. Color declarations here must use semantic --md-sys-color-* roles.
   Legacy selectors above migrate journey by journey; they are not silently
   restyled by this commit.
   ═══════════════════════════════════════════════════════════════════════════ */

.md3-button {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 48px;
  min-height: 48px;
  padding: 0 24px;
  overflow: hidden;
  border: 0;
  border-radius: var(--md-sys-shape-corner-full);
  background: var(--md-sys-color-primary);
  color: var(--md-sys-color-on-primary);
  box-shadow: var(--md-sys-elevation-level0);
  font-family: var(--md-sys-typescale-font);
  font-size: var(--md-sys-typescale-label-large-size);
  line-height: var(--md-sys-typescale-label-large-line-height);
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
}
.md3-button::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .md3-button:hover::before { opacity: var(--md-sys-state-hover-opacity); }
}
.md3-button:active::before { opacity: var(--md-sys-state-pressed-opacity); }
.md3-button:focus-visible {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-button:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}
.md3-button[aria-busy="true"] {
  cursor: progress;
}
.md3-button--tonal {
  background: var(--md-sys-color-secondary-container);
  color: var(--md-sys-color-on-secondary-container);
}
.md3-button--outlined {
  border: 1px solid var(--md-sys-color-outline);
  background: transparent;
  color: var(--md-sys-color-primary);
}

.md3-card {
  padding: 16px;
  border: 1px solid var(--md-sys-color-outline-variant);
  border-radius: var(--md-sys-shape-corner-medium);
  background: var(--md-sys-color-surface-container-low);
  color: var(--md-sys-color-on-surface);
  box-shadow: var(--md-sys-elevation-level0);
}
.md3-card--elevated {
  border-color: transparent;
  box-shadow: var(--md-sys-elevation-level1);
}
.md3-card:focus-within {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-card--interactive {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  cursor: pointer;
}
.md3-card--interactive::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--md-sys-color-on-surface);
  opacity: 0;
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .md3-card--interactive:hover::before {
    opacity: var(--md-sys-state-hover-opacity);
  }
}
.md3-card--interactive:active::before {
  opacity: var(--md-sys-state-pressed-opacity);
}
.md3-card--interactive:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}
.md3-card--interactive[aria-busy="true"] {
  cursor: progress;
}
.md3-card--interactive:disabled::before,
.md3-card--interactive[aria-busy="true"]::before {
  opacity: 0;
}

.md3-text-field {
  display: block;
  width: 100%;
  min-height: 56px;
  padding: 15px 16px;
  border: 1px solid var(--md-sys-color-outline);
  border-radius: var(--md-sys-shape-corner-extra-small);
  background: transparent;
  color: var(--md-sys-color-on-surface);
  font-family: var(--md-sys-typescale-font);
  font-size: var(--md-sys-typescale-body-large-size);
  line-height: var(--md-sys-typescale-body-large-line-height);
}
.md3-text-field::placeholder {
  color: var(--md-sys-color-on-surface-variant);
}
@media (hover: hover) and (pointer: fine) {
  .md3-text-field:hover:not(:disabled) {
    border-color: var(--md-sys-color-on-surface);
  }
}
.md3-text-field:focus-visible {
  outline: 0;
  border: 2px solid var(--md-sys-color-primary);
  padding: 14px 15px;
}
.md3-text-field:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}
.md3-text-field[aria-busy="true"] {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: progress;
}
.md3-text-field[aria-invalid="true"] {
  border-color: var(--md-sys-color-error);
}

.md3-chip {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 16px;
  border: 1px solid var(--md-sys-color-outline);
  border-radius: var(--md-sys-shape-corner-small);
  background: transparent;
  color: var(--md-sys-color-on-surface-variant);
  font-family: var(--md-sys-typescale-font);
  font-size: var(--md-sys-typescale-label-large-size);
  line-height: var(--md-sys-typescale-label-large-line-height);
  overflow: hidden;
  cursor: pointer;
}
.md3-chip::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
}
.md3-chip[aria-selected="true"] {
  border-color: transparent;
  background: var(--md-sys-color-secondary-container);
  color: var(--md-sys-color-on-secondary-container);
}
@media (hover: hover) and (pointer: fine) {
  .md3-chip:hover::before { opacity: var(--md-sys-state-hover-opacity); }
}
.md3-chip:active::before { opacity: var(--md-sys-state-pressed-opacity); }
.md3-chip:focus-visible {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-chip:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}
.md3-chip[aria-busy="true"] {
  cursor: progress;
}
.md3-chip:disabled::before,
.md3-chip[aria-busy="true"]::before {
  opacity: 0;
}

.md3-sheet {
  padding: 28px 24px 24px;
  border: 0;
  border-radius: var(--md-sys-shape-corner-extra-large)
                 var(--md-sys-shape-corner-extra-large) 0 0;
  background: var(--md-sys-color-surface-container-low);
  color: var(--md-sys-color-on-surface);
  box-shadow: var(--md-sys-elevation-level3);
}

.md3-navigation {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(48px, 1fr);
  gap: 4px;
  padding: 8px;
  background: var(--md-sys-color-surface-container);
  color: var(--md-sys-color-on-surface-variant);
}
.md3-navigation__item {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  min-width: 48px;
  min-height: 48px;
  align-items: center;
  justify-content: center;
  border-radius: var(--md-sys-shape-corner-full);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  cursor: pointer;
}
.md3-navigation__item::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
}
.md3-navigation__item[aria-current="page"] {
  background: var(--md-sys-color-secondary-container);
  color: var(--md-sys-color-on-secondary-container);
}
@media (hover: hover) and (pointer: fine) {
  .md3-navigation__item:hover::before {
    opacity: var(--md-sys-state-hover-opacity);
  }
}
.md3-navigation__item:active::before {
  opacity: var(--md-sys-state-pressed-opacity);
}
.md3-navigation__item:focus-visible {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-navigation__item:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}
.md3-navigation__item[aria-busy="true"] {
  cursor: progress;
}
.md3-navigation__item:disabled::before,
.md3-navigation__item[aria-busy="true"]::before {
  opacity: 0;
}
@media (min-width: 600px) and (max-width: 839px) {
  .md3-navigation {
    grid-auto-flow: row;
    grid-template-columns: 80px;
    grid-auto-rows: minmax(48px, auto);
    align-content: start;
  }
}
@media (min-width: 840px) {
  .md3-navigation {
    grid-auto-flow: row;
    grid-template-columns: minmax(220px, 360px);
    grid-auto-rows: minmax(48px, auto);
    align-content: start;
  }
  .md3-navigation__item {
    justify-content: flex-start;
    padding-inline: 24px;
  }
}

.md3-state-loading,
.md3-state-empty,
.md3-state-error {
  display: grid;
  place-items: center;
  gap: 12px;
  min-height: 96px;
  padding: 24px;
  border-radius: var(--md-sys-shape-corner-medium);
  text-align: center;
}
.md3-state-loading {
  background: var(--md-sys-color-surface-container-low);
  color: var(--md-sys-color-on-surface-variant);
}
.md3-state-empty {
  background: var(--md-sys-color-surface-container);
  color: var(--md-sys-color-on-surface);
}
.md3-state-error {
  background: var(--md-sys-color-error-container);
  color: var(--md-sys-color-on-error-container);
}
.md3-progress {
  width: 24px;
  height: 24px;
  border: 3px solid var(--md-sys-color-outline-variant);
  border-top-color: var(--md-sys-color-primary);
  border-radius: var(--md-sys-shape-corner-full);
  animation: md3-progress-spin 800ms linear infinite;
}
@keyframes md3-progress-spin {
  to { transform: rotate(1turn); }
}

/* ──────────────────────────────────────────────────────────────────────────
   M3 LOCATIONS SURFACE START — REQ-LOC-027

   Phone locations is the first office journey migrated as a whole onto the
   decision #75 contract. Every component color below is semantic; tenant
   identity remains in the role-token source block.
   ────────────────────────────────────────────────────────────────────────── */
.md3-locations {
  width: 100%;
  min-width: 0;
  color: var(--md-sys-color-on-surface);
  font-family: var(--md-sys-typescale-font);
}
.md3-locations__header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-block-end: 20px;
}
.md3-locations__heading { min-width: 0; }
.md3-locations__title {
  margin: 0;
  color: var(--md-sys-color-on-surface);
  font-size: var(--md-sys-typescale-headline-small-size);
  line-height: var(--md-sys-typescale-headline-small-line-height);
  font-weight: 400;
}
.md3-locations__supporting {
  max-width: 62ch;
  margin: 4px 0 0;
  color: var(--md-sys-color-on-surface-variant);
  font-size: var(--md-sys-typescale-body-medium-size);
  line-height: var(--md-sys-typescale-body-medium-line-height);
}
.md3-locations__segments {
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(96px, 1fr);
  overflow: hidden;
  border: 1px solid var(--md-sys-color-outline);
  border-radius: var(--md-sys-shape-corner-full);
  background: var(--md-sys-color-surface);
}
.md3-locations__segment {
  position: relative;
  min-height: 48px;
  padding: 0 24px;
  border: 0;
  border-inline-start: 1px solid var(--md-sys-color-outline);
  background: transparent;
  color: var(--md-sys-color-on-surface);
  font: inherit;
  font-size: var(--md-sys-typescale-label-large-size);
  line-height: var(--md-sys-typescale-label-large-line-height);
  font-weight: 500;
  cursor: pointer;
}
.md3-locations__segment:first-child { border-inline-start: 0; }
.md3-locations__segment[aria-selected="true"] {
  background: var(--md-sys-color-secondary-container);
  color: var(--md-sys-color-on-secondary-container);
}
@media (hover: hover) and (pointer: fine) {
  .md3-locations__segment:hover {
    background: var(--md-sys-color-surface-container);
  }
  .md3-locations__segment[aria-selected="true"]:hover {
    background: var(--md-sys-color-secondary-container);
  }
  .md3-locations__roster-main:hover {
    background: var(--md-sys-color-surface-container);
  }
}
.md3-locations__segment:active,
.md3-locations__roster-main:active {
  background: var(--md-sys-color-surface-container-high);
}
.md3-locations__segment:focus-visible,
.md3-locations__roster-main:focus-visible {
  z-index: 1;
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-locations__segment:disabled,
.md3-locations__roster-main:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
}
.md3-locations__segment[aria-busy="true"],
.md3-locations__roster-main[aria-busy="true"] {
  cursor: progress;
}
.md3-locations__body {
  min-width: 0;
  overflow: hidden;
}
.md3-locations__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  min-width: 0;
}
.md3-locations__map {
  width: 100%;
  min-width: 0;
  min-height: 360px;
  height: min(58vh, 620px);
  overflow: hidden;
  border: 1px solid var(--md-sys-color-outline-variant);
  border-radius: var(--md-sys-shape-corner-medium);
  background: var(--md-sys-color-surface-container-low);
  box-shadow: var(--md-sys-elevation-level1);
}
.md3-locations__roster {
  min-width: 0;
  max-height: min(58vh, 620px);
  overflow: auto;
  padding: 8px;
  border-radius: var(--md-sys-shape-corner-medium);
  background: var(--md-sys-color-surface-container-low);
}
.md3-locations__roster-item {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  border-block-end: 1px solid var(--md-sys-color-outline-variant);
}
.md3-locations__roster-item:last-child { border-block-end: 0; }
.md3-locations__roster-main {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 12px;
  min-width: 0;
  min-height: 56px;
  padding: 8px;
  border: 0;
  border-radius: var(--md-sys-shape-corner-small);
  background: transparent;
  color: var(--md-sys-color-on-surface);
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.md3-locations__avatar {
  display: inline-grid;
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  place-items: center;
  border-radius: var(--md-sys-shape-corner-full);
  background: var(--md-sys-color-primary-container);
  color: var(--md-sys-color-on-primary-container);
  font-size: var(--md-sys-typescale-label-large-size);
  line-height: var(--md-sys-typescale-label-large-line-height);
  font-weight: 500;
}
.md3-locations__roster-info {
  display: grid;
  min-width: 0;
}
.md3-locations__roster-name {
  overflow: hidden;
  color: var(--md-sys-color-on-surface);
  font-size: var(--md-sys-typescale-body-large-size);
  line-height: var(--md-sys-typescale-body-large-line-height);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.md3-locations__roster-role {
  margin-inline-start: 6px;
  color: var(--md-sys-color-on-surface-variant);
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: var(--md-sys-typescale-label-medium-line-height);
  font-weight: 500;
  text-transform: uppercase;
}
.md3-locations__roster-job,
.md3-locations__roster-age {
  overflow: hidden;
  color: var(--md-sys-color-on-surface-variant);
  font-size: var(--md-sys-typescale-body-small-size);
  line-height: var(--md-sys-typescale-body-small-line-height);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.md3-locations__roster-age.is-stale {
  overflow: visible;
  color: var(--md-sys-color-error);
  font-weight: 500;
  text-overflow: clip;
  white-space: normal;
}
.md3-locations__roster-item.is-off-clock .md3-locations__avatar {
  background: var(--md-sys-color-surface-container-high);
  color: var(--md-sys-color-on-surface-variant);
}
.md3-locations__job-action {
  flex: 0 0 auto;
  min-height: 48px;
  padding-inline: 16px;
}
.md3-locations__marker {
  position: relative;
  display: grid;
  width: 40px;
  height: 40px;
  place-items: center;
  border: 2px solid var(--md-sys-color-surface);
  border-radius: var(--md-sys-shape-corner-full);
  background: var(--md-sys-color-primary);
  color: var(--md-sys-color-on-primary);
  box-shadow: var(--md-sys-elevation-level2);
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: var(--md-sys-typescale-label-medium-line-height);
  font-weight: 500;
}
.md3-locations__marker.is-off-clock {
  border-color: var(--md-sys-color-outline-variant);
  background: var(--md-sys-color-surface-container-high);
  color: var(--md-sys-color-on-surface-variant);
  box-shadow: var(--md-sys-elevation-level0);
}
.md3-locations__marker.is-stale {
  border-color: var(--md-sys-color-error);
  background: var(--md-sys-color-error-container);
  color: var(--md-sys-color-on-error-container);
}
.md3-locations__marker-warning {
  position: absolute;
  inset-block-start: -6px;
  inset-inline-end: -6px;
  display: grid;
  width: 20px;
  height: 20px;
  place-items: center;
  border: 2px solid var(--md-sys-color-surface);
  border-radius: var(--md-sys-shape-corner-full);
  background: var(--md-sys-color-error);
  color: var(--md-sys-color-on-error);
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: var(--md-sys-typescale-label-medium-line-height);
  font-weight: 700;
}
.leaflet-tooltip.md3-locations__marker-label {
  padding: 2px 8px;
  border: 0;
  border-radius: var(--md-sys-shape-corner-extra-small);
  background: var(--md-sys-color-inverse-surface);
  color: var(--md-sys-color-inverse-on-surface);
  box-shadow: var(--md-sys-elevation-level1);
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: var(--md-sys-typescale-label-medium-line-height);
  font-weight: 500;
}
.leaflet-tooltip.md3-locations__marker-label::before { display: none; }
.md3-locations__popup-role {
  color: var(--md-sys-color-on-surface-variant);
  font-size: var(--md-sys-typescale-body-small-size);
  line-height: var(--md-sys-typescale-body-small-line-height);
}
.md3-locations__state {
  margin-block-end: 16px;
}
.md3-locations__state[hidden] { display: none; }
.md3-locations__state-copy {
  font-size: var(--md-sys-typescale-body-medium-size);
  line-height: var(--md-sys-typescale-body-medium-line-height);
}
.md3-locations__retry { margin-block-start: 4px; }
.md3-locations__history {
  display: grid;
  grid-template-columns: repeat(3, minmax(140px, 1fr));
  gap: 12px;
  margin-block-end: 16px;
}
.md3-locations__history-field {
  display: grid;
  gap: 4px;
  color: var(--md-sys-color-on-surface-variant);
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: var(--md-sys-typescale-label-medium-line-height);
  font-weight: 500;
}
.md3-locations__history-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  grid-column: 1 / -1;
}
.md3-locations__history-output {
  grid-column: 1 / -1;
  color: var(--md-sys-color-on-surface-variant);
  font-size: var(--md-sys-typescale-body-medium-size);
  line-height: var(--md-sys-typescale-body-medium-line-height);
}
.md3-locations__history-output.md3-state-loading,
.md3-locations__history-output.md3-state-empty,
.md3-locations__history-output.md3-state-error {
  min-height: 0;
  padding: 16px;
}
@media (max-width: 599px) {
  .md3-locations__header {
    align-items: stretch;
  }
  .md3-locations__segments {
    width: 100%;
  }
  .md3-locations__map {
    min-height: 320px;
    height: 46vh;
  }
  .md3-locations__roster {
    max-height: none;
  }
  .md3-locations__roster-item {
    align-items: stretch;
    flex-wrap: wrap;
  }
  .md3-locations__roster-main {
    flex-basis: 100%;
  }
  .md3-locations__job-action {
    width: 100%;
    margin: 0 8px 8px;
  }
  .md3-locations__history {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (min-width: 840px) {
  .md3-locations__layout {
    grid-template-columns: minmax(0, 1fr) minmax(360px, 420px);
  }
}
/* M3 LOCATIONS SURFACE END */

/* ───────────────────────────────────────────────────────────────────────────
   M3 OFFICE WORKSPACE SHELL START — REQ-WS-001

   The office navigation, reduced from ~30 launcher tiles + 14 anchor links to
   six workspaces (plus the optional Supply & Shop vertical). Rendered by
   workspaces.js into `.side-nav`; routes and permissions are unchanged — this
   layer only decides what is offered and how it adapts.

   Adaptive ladder (REQ-M3-004). Six-to-seven destinations is NOT the "small
   primary destination set" a Material navigation bar is for, and the office
   shell's bottom edge is already spoken for by the --fab-slot-* stack, so the
   compact form is a top app bar plus a modal navigation drawer — Material's
   own answer for this size of destination list — not a bottom bar:

     under 600px   top strip + modal navigation drawer (scrim, Escape, trap)
     600–839px     navigation rail, destinations in an anchored flyout
     840px and up  persistent navigation drawer, destinations inline

   The shell class is additive: without `.md3-ws-shell` on #app the legacy
   grid still applies, so a failure to boot workspaces.js degrades to the old
   shell instead of an unnavigable page.
   ─────────────────────────────────────────────────────────────────────────── */

.md3-ws {
  --md3-ws-drawer-width: 280px;
  --md3-ws-rail-width: 88px;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 4px;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

/* REQ-NAV-010: the brand/utilities and account controls stay anchored while
   this bounded middle region owns navigation scrolling. Without both
   min-height:0 boundaries, an expanded destination group grows the grid item
   past the viewport instead of activating .md3-ws__panel's scrollbar. */
.md3-ws-shell .side-nav {
  min-height: 0;
  overflow: hidden;
}

/* The scrim only ever exists in the compact modal form; at rail/drawer widths
   it is display:none, so it can never swallow a click on a wide screen. */
/* Visually hidden, still announced — this sheet had no such utility, and the
   "opens in a new tab" warning must reach a screen reader without becoming a
   hover-only tooltip. */
.md3-ws__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.md3-ws__scrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 59;   /* raised to 95 for the compact modal form, see below */
  border: 0;
  padding: 0;
  background: var(--md-sys-color-scrim);
  opacity: var(--md-sys-state-scrim-opacity);
  cursor: pointer;
}

.md3-ws__menu {
  display: none;
  min-width: 48px;
  min-height: 48px;
  padding: 0;
  border: 0;
  border-radius: var(--md-sys-shape-corner-full);
  background: transparent;
  color: var(--md-sys-color-on-surface-variant);
  cursor: pointer;
}
.md3-ws__menu svg { width: 24px; height: 24px; }
.md3-ws__menu:focus-visible {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}

.md3-ws__panel {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 2px;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  overscroll-behavior-y: contain;
}

/* Workspace row. A native <button> so `disabled` is real and focus is free —
   never aria-disabled, never pointer-events (REQ-M3-003). */
.md3-ws__workspace {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 48px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--md-sys-shape-corner-full);
  background: transparent;
  color: var(--md-sys-color-on-surface-variant);
  font-family: var(--md-sys-typescale-font);
  font-size: var(--md-sys-typescale-label-large-size);
  line-height: var(--md-sys-typescale-label-large-line-height);
  font-weight: 500;
  text-align: left;
  overflow: hidden;
  cursor: pointer;
}
.md3-ws__workspace::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .md3-ws__workspace:hover::before { opacity: var(--md-sys-state-hover-opacity); }
}
.md3-ws__workspace:active::before { opacity: var(--md-sys-state-pressed-opacity); }
.md3-ws__workspace:focus-visible {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-ws__workspace[aria-expanded="true"],
.md3-ws__workspace[data-current="true"] {
  background: var(--md-sys-color-secondary-container);
  color: var(--md-sys-color-on-secondary-container);
}
.md3-ws__workspace:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
}
.md3-ws__workspace[aria-busy="true"] { cursor: progress; }
.md3-ws__workspace:disabled::before,
.md3-ws__workspace[aria-busy="true"]::before { opacity: 0; }

.md3-ws__icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
}
.md3-ws__icon svg { width: 24px; height: 24px; display: block; }

.md3-ws__label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Count pill. Carries a visually-hidden noun as well, so the number never
   depends on colour or position alone to mean something (REQ-M3-002). */
.md3-ws__count {
  flex: 0 0 auto;
  min-width: 20px;
  padding: 0 6px;
  border-radius: var(--md-sys-shape-corner-full);
  background: var(--md-sys-color-error);
  color: var(--md-sys-color-on-error);
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: 20px;
  font-weight: 600;
  text-align: center;
}
.md3-ws__count[hidden] { display: none; }

.md3-ws__chevron {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: inherit;
}
.md3-ws__chevron svg { width: 18px; height: 18px; display: block; }

/* Destination group — the second level. Inline under its workspace at drawer
   widths, an anchored flyout at rail width. */
.md3-ws__group {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 2px 0 6px 12px;
}
.md3-ws__group[hidden] { display: none; }

.md3-ws__destination {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--md-sys-shape-corner-full);
  background: transparent;
  color: var(--md-sys-color-on-surface-variant);
  font-family: var(--md-sys-typescale-font);
  font-size: var(--md-sys-typescale-body-medium-size);
  line-height: var(--md-sys-typescale-body-medium-line-height);
  text-align: left;
  text-decoration: none;
  overflow: hidden;
  cursor: pointer;
}
.md3-ws__destination::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .md3-ws__destination:hover::before { opacity: var(--md-sys-state-hover-opacity); }
}
.md3-ws__destination:active::before { opacity: var(--md-sys-state-pressed-opacity); }
.md3-ws__destination:focus-visible {
  outline: 3px solid var(--md-sys-color-primary);
  outline-offset: 2px;
}
.md3-ws__destination[aria-current="page"] {
  background: var(--md-sys-color-secondary-container);
  color: var(--md-sys-color-on-secondary-container);
  font-weight: 600;
}
.md3-ws__destination:disabled {
  opacity: var(--md-sys-state-disabled-opacity);
  cursor: not-allowed;
}
.md3-ws__destination[aria-busy="true"] { cursor: progress; }
.md3-ws__destination:disabled::before,
.md3-ws__destination[aria-busy="true"]::before { opacity: 0; }

/* Opens in a new tab: a visible mark, not a hover-only tooltip (REQ-M3-004). */
.md3-ws__external {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  opacity: .75;
}
.md3-ws__external svg { width: 14px; height: 14px; display: block; }

/* The two utility buttons that sit above the workspaces in the shell markup
   (All apps, Ask AI). Same anatomy as a destination; the glyph is decorative
   and aria-hidden, so the accessible name is the label alone. */
.md3-ws__utility { flex: 0 0 auto; }
.md3-ws__glyph {
  flex: 0 0 auto;
  width: 24px;
  text-align: center;
  font-size: var(--md-sys-typescale-body-large-size);
  line-height: var(--md-sys-typescale-body-large-line-height);
}
/* Below the drawer breakpoint there is no room for a labelled row: the rail is
   88px and the compact strip is one line. They collapse to square icon
   buttons, still 48px and still named by their aria-label — `width` has to be
   restated because .md3-ws__destination sets 100% and min-width cannot beat
   it, which is what pushed both buttons off a 375px screen. */
@media (max-width: 839px) {
  .md3-ws-shell .md3-ws__utility {
    width: 48px;
    min-width: 48px;
    padding: 0;
    justify-content: center;
  }
  .md3-ws-shell .md3-ws__utility .md3-ws__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Data states for the badge counts the nav overlays. The nav itself always
   renders; these never blank the destination list (REQ-M3-003, REQ-M3-007). */
.md3-ws__status {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 0;
  margin: 2px 4px 0;
  padding: 8px 12px;
  border-radius: var(--md-sys-shape-corner-medium);
  font-size: var(--md-sys-typescale-body-small-size);
  line-height: var(--md-sys-typescale-body-small-line-height);
  text-align: left;
}
.md3-ws__status[hidden] { display: none; }
.md3-ws__status .md3-progress { width: 16px; height: 16px; border-width: 2px; }
/* Inherits .md3-button's 48px floor deliberately: it is a real control inside
   the navigation, and an error-recovery affordance is the last place to make
   a target hard to hit. Only the horizontal padding is tightened. */
.md3-ws__retry {
  margin-inline-start: auto;
  padding: 0 14px;
  font-size: var(--md-sys-typescale-label-medium-size);
  line-height: var(--md-sys-typescale-label-medium-line-height);
}

/* ── expanded: persistent drawer (840px and up) ─────────────────────────── */
@media (min-width: 840px) {
  .app-shell.md3-ws-shell {
    grid-template-columns: var(--md3-ws-drawer-width, 280px) minmax(0, 1fr);
    grid-template-rows: 100vh;
  }
  /* The legacy icon-rail block at max-width:1180px still matches across the
     840–1180 band, where this is a 280px drawer, not a 68px rail. Undo its
     collapsing here or the drawer arrives centred, padded for a rail, with
     the wordmark and the user chip hidden. */
  .md3-ws-shell .side-nav {
    display: flex;
    align-items: stretch;
    padding: 18px 14px;
  }
  .md3-ws-shell .nav-collapsible { display: flex; }
  .md3-ws-shell .brand-mark-mini { display: none; }
  .md3-ws-shell .nav-brand-row { justify-content: flex-start; margin-bottom: 24px; }
}

/* ── medium: navigation rail, destinations in an anchored flyout ─────────── */
@media (min-width: 600px) and (max-width: 839px) {
  .app-shell.md3-ws-shell {
    grid-template-columns: var(--md3-ws-rail-width, 88px) minmax(0, 1fr);
    grid-template-rows: 100vh;
  }
  .md3-ws-shell .side-nav {
    display: flex;
    align-items: stretch;
    padding: 12px 8px;
  }
  .md3-ws-shell .nav-collapsible { display: none; }
  .md3-ws-shell .brand-mark-mini { display: grid; }
  .md3-ws-shell .nav-brand-row { justify-content: center; }
  .md3-ws .md3-ws__workspace {
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 4px 2px;
    min-height: 62px;
    border-radius: var(--md-sys-shape-corner-large);
    font-size: var(--md-sys-typescale-label-medium-size);
    line-height: var(--md-sys-typescale-label-medium-line-height);
    text-align: center;
  }
  .md3-ws .md3-ws__label { white-space: normal; text-overflow: clip; }
  .md3-ws .md3-ws__chevron { display: none; }
  .md3-ws .md3-ws__count {
    position: absolute;
    inset-block-start: 4px;
    inset-inline-end: 10px;
  }
  /* Flyout: still in DOM order right after its workspace button, so focus and
     reading order stay together (REQ-M3-004). */
  .md3-ws .md3-ws__group {
    position: fixed;
    z-index: 61;
    inset-inline-start: var(--md3-ws-rail-width, 88px);
    inset-block-start: 0;
    width: min(300px, calc(100vw - var(--md3-ws-rail-width, 88px)));
    max-height: 100vh;
    max-height: 100dvh;
    padding: 12px;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    border-start-end-radius: var(--md-sys-shape-corner-large);
    border-end-end-radius: var(--md-sys-shape-corner-large);
    background: var(--md-sys-color-surface-container-high);
    box-shadow: var(--md-sys-elevation-level2);
  }
  .md3-ws__scrim { display: block; }
  .md3-ws__scrim[hidden] { display: none; }
}

/* ── compact: top strip + modal navigation drawer (under 600px) ──────────── */
@media (max-width: 599px) {
  .app-shell.md3-ws-shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }
  .md3-ws-shell .side-nav {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-inline-end: 0;
    overflow: visible;
  }
  .md3-ws-shell .nav-collapsible { display: none; }
  .md3-ws-shell .brand-mark-mini { display: grid; }
  /* Leading menu, then the mark, then the utilities — the Material top app bar
     order. #ws-nav is last in the markup because the workspaces belong after
     the utility links at drawer width. */
  .md3-ws-shell .nav-brand-row { margin: 0; order: 2; }
  .md3-ws-shell .md3-ws { order: 1; }
  .md3-ws-shell .md3-ws__utility { order: 3; margin-inline-start: auto; }
  .md3-ws-shell .md3-ws__utility + .md3-ws__utility { margin-inline-start: 0; }
  .md3-ws .md3-ws__menu { display: inline-flex; align-items: center; justify-content: center; }
  .md3-ws {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    overflow: visible;
  }
  /* The drawer content is the panel. CSS owns whether it is on screen — a
     missed matchMedia event must not be able to strand it open across the
     whole viewport, so the open state is one attribute, not a JS-computed
     `hidden` (which is what shipped a full-screen panel on first resize). */
  .md3-ws__scrim { z-index: 95; }
  .md3-ws:not([data-open="true"]) .md3-ws__panel { display: none; }
  .md3-ws .md3-ws__panel {
    position: fixed;
    /* Above .ai-bar (60), .ai-fab-v2 (65), .ai-dock (70) and .fb-fab (90);
       below .pt-toast-container (100) and .cmdk-scrim (200), which must still
       be able to speak over a nav drawer. */
    z-index: 96;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(320px, 86vw);
    max-height: 100vh;
    max-height: 100dvh;
    padding: 16px 12px;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    border-start-end-radius: var(--md-sys-shape-corner-large);
    border-end-end-radius: var(--md-sys-shape-corner-large);
    background: var(--md-sys-color-surface-container-low);
    box-shadow: var(--md-sys-elevation-level3);
  }
  .md3-ws .md3-ws__panel[hidden] { display: none; }
  .md3-ws__scrim { display: block; }
  .md3-ws__scrim[hidden] { display: none; }
}
/* M3 OFFICE WORKSPACE SHELL END */

/* M3 PRODUCT COMPONENT FOUNDATION END */

/* ── Managed-phone universal assistant dock (REQ-UAA-001/002/006/008) ──────
   JS updates --t-assistant-bottom from the live action/drive bars. One value
   keeps the assistant bar, page padding, and snackbars in the same clearance
   lane instead of letting three independent fixed stacks overlap. */
body.tech-app {
  --t-assistant-bottom: 88px;
}
body.tech-app.has-assistant-bar .t-main {
  padding-bottom: calc(var(--t-assistant-bottom) + 76px + env(safe-area-inset-bottom, 0px));
}
body.tech-app.has-assistant-bar #t-toast-root {
  bottom: calc(var(--t-assistant-bottom) + 64px + env(safe-area-inset-bottom, 0px));
}
body.tech-app .t-assistant-bar {
  position: fixed;
  left: 50%;
  bottom: calc(var(--t-assistant-bottom) + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 47;
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(560px, calc(100% - 24px));
  min-height: 52px;
  padding: 0 18px;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-full);
  background: var(--md-surface-c-high);
  color: var(--md-on-surface);
  box-shadow: var(--md-elev-2);
  font: inherit;
  font-size: var(--md-body-lg);
  text-align: left;
  cursor: pointer;
}
body.tech-app .t-assistant-bar[hidden] { display: none; }
body.tech-app .t-assistant-bar:focus-visible,
body.tech-app .t-assistant-icon-btn:focus-visible,
body.tech-app .t-assistant-attachment-remove:focus-visible,
body.tech-app .t-assistant-media-open:focus-visible {
  outline: 3px solid var(--md-primary);
  outline-offset: 2px;
}
body.tech-app .t-assistant-bar-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--md-on-surface-variant);
}
body.tech-app .t-assistant-backdrop {
  position: fixed;
  inset: 0;
  z-index: 68;
  background: rgba(0, 0, 0, .38);
}
body.tech-app .t-assistant-backdrop[hidden],
body.tech-app .t-assistant-dock[hidden] {
  display: none;
}
body.tech-app .t-assistant-dock {
  position: fixed;
  left: 50%;
  bottom: 0;
  z-index: 69;
  display: grid;
  grid-template-rows: auto auto minmax(112px, 1fr) auto auto;
  width: 100%;
  max-width: 640px;
  height: min(82dvh, 720px);
  max-height: calc(100dvh - env(safe-area-inset-top, 0px));
  transform: translateX(-50%);
  overflow: hidden;
  border-radius: var(--md-shape-xl) var(--md-shape-xl) 0 0;
  background: var(--md-surface-c-low);
  color: var(--md-on-surface);
  box-shadow: var(--md-elev-3);
}
body.tech-app .t-assistant-dock-head {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 20px 12px 10px 16px;
  border-bottom: 1px solid var(--md-outline-variant);
}
body.tech-app .t-assistant-dock-head > div:first-child {
  flex: 1 1 auto;
  min-width: 0;
}
body.tech-app .t-assistant-dock-head h2 {
  margin: 0;
  font-size: var(--md-title-lg);
  line-height: var(--md-title-lg-lh);
}
body.tech-app .t-assistant-context {
  overflow: hidden;
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.tech-app .t-assistant-head-actions,
body.tech-app .t-assistant-attach-actions {
  display: flex;
  flex: 0 0 auto;
  gap: 4px;
}
body.tech-app .t-assistant-icon-btn,
body.tech-app .t-assistant-attachment-remove {
  display: inline-grid;
  place-items: center;
  width: 48px;
  min-width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: var(--md-shape-full);
  background: transparent;
  color: var(--md-primary);
  font: inherit;
  font-size: var(--md-title-lg);
  cursor: pointer;
}
body.tech-app .t-assistant-icon-btn:active,
body.tech-app .t-assistant-attachment-remove:active {
  background: color-mix(in srgb, var(--md-primary) 10%, transparent);
}
body.tech-app .t-assistant-status {
  min-height: 24px;
  padding: 4px 16px;
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
}
body.tech-app .t-assistant-status:empty { min-height: 0; padding-block: 0; }
body.tech-app .t-assistant-status.is-error {
  background: var(--md-error-container);
  color: var(--md-on-error-container);
}
body.tech-app .t-assistant-messages {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px 12px 16px;
  scroll-padding-bottom: 16px;
}
body.tech-app .t-assistant-welcome {
  padding: 14px;
  border-radius: var(--md-shape-md);
  background: var(--md-surface-c);
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-md);
  line-height: var(--md-body-md-lh);
}
body.tech-app .t-assistant-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
body.tech-app .t-assistant-msg {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-bottom: 10px;
}
body.tech-app .t-assistant-msg.user { align-items: flex-end; }
body.tech-app .t-assistant-bubble {
  max-width: 88%;
  padding: 10px 12px;
  border-radius: var(--md-shape-lg);
  background: var(--md-surface-c-high);
  color: var(--md-on-surface);
  font-size: var(--md-body-md);
  line-height: var(--md-body-md-lh);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
body.tech-app .t-assistant-msg.user .t-assistant-bubble {
  background: var(--md-primary-container);
  color: var(--md-on-primary-container);
}
body.tech-app .t-assistant-bubble.md-body { white-space: normal; }
body.tech-app .t-assistant-prompt-attachments {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  max-width: 88%;
  margin-top: 6px;
}
body.tech-app .t-assistant-prompt-attachment {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  min-width: 0;
  max-width: 240px;
  padding: 5px;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-sm);
  background: var(--md-surface-c-high);
  color: var(--md-on-surface);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
body.tech-app .t-assistant-prompt-attachment:focus-visible {
  outline: 3px solid var(--md-primary);
  outline-offset: 2px;
}
body.tech-app .t-assistant-prompt-preview {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  overflow: hidden;
  border-radius: var(--md-shape-xs);
  background: var(--md-surface-c-highest);
  color: var(--md-on-surface-variant);
  font-size: var(--md-label-sm);
  font-weight: 700;
}
body.tech-app .t-assistant-prompt-preview img,
body.tech-app .t-assistant-prompt-preview video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
body.tech-app .t-assistant-prompt-copy {
  display: grid;
  min-width: 0;
  gap: 2px;
}
body.tech-app .t-assistant-prompt-copy strong,
body.tech-app .t-assistant-prompt-copy span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.tech-app .t-assistant-prompt-copy strong { font-size: var(--md-label-md); }
body.tech-app .t-assistant-prompt-copy span {
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
}
body.tech-app .t-assistant-trace {
  max-width: 92%;
  margin-top: 4px;
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
  overflow-wrap: anywhere;
}
body.tech-app .t-assistant-tray {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 8px;
  max-height: 176px;
  overflow-y: auto;
  padding: 8px 12px;
  border-top: 1px solid var(--md-outline-variant);
  background: var(--md-surface-c);
}
body.tech-app .t-assistant-tray[hidden] { display: none; }
body.tech-app .t-assistant-attachment {
  position: relative;
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) 40px;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 56px;
  padding: 6px;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-sm);
  background: var(--md-surface-c-high);
}
body.tech-app .t-assistant-attachment.is-busy { opacity: .72; }
body.tech-app .t-assistant-attachment.is-error {
  border-color: var(--md-error);
}
body.tech-app .t-assistant-attachment-preview {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  overflow: hidden;
  border-radius: var(--md-shape-xs);
  background: var(--md-surface-c-highest);
  color: var(--md-on-surface-variant);
  font-size: var(--md-label-sm);
  font-weight: 700;
}
body.tech-app .t-assistant-attachment-preview img,
body.tech-app .t-assistant-attachment-preview video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
body.tech-app .t-assistant-attachment-name,
body.tech-app .t-assistant-attachment-state {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.tech-app .t-assistant-attachment-name {
  font-size: var(--md-label-md);
  font-weight: 600;
}
body.tech-app .t-assistant-attachment-state {
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
}
body.tech-app .t-assistant-attachment-state.is-error {
  color: var(--md-error);
}
body.tech-app .t-assistant-attachment-remove {
  width: 40px;
  min-width: 40px;
  height: 40px;
  font-size: var(--md-title-md);
}
body.tech-app .t-assistant-compose {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: end;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--md-outline-variant);
  background: var(--md-surface-c);
}
body.tech-app #t-assistant-input {
  width: 100%;
  min-height: 48px;
  max-height: 128px;
  resize: none;
  padding: 12px 14px;
  border: 1px solid var(--md-outline);
  border-radius: var(--md-shape-lg);
  background: var(--md-surface);
  color: var(--md-on-surface);
  font: inherit;
  font-size: 16px;
  line-height: 22px;
}
body.tech-app #t-assistant-input:focus {
  outline: 2px solid var(--md-primary);
  outline-offset: 1px;
}
body.tech-app .t-assistant-send {
  min-width: 68px;
  padding-inline: 16px;
}
body.tech-app .t-assistant-media-gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  width: min(100%, 520px);
  margin-top: 8px;
}
body.tech-app .t-assistant-media-card {
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-md);
  background: var(--md-surface-c);
}
body.tech-app .t-assistant-media-card img,
body.tech-app .t-assistant-media-card video {
  display: block;
  width: 100%;
  max-height: 220px;
  object-fit: cover;
  background: var(--md-inverse-surface);
}
body.tech-app .t-assistant-media-meta {
  display: grid;
  gap: 2px;
  padding: 8px;
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
  overflow-wrap: anywhere;
}
body.tech-app .t-assistant-media-open {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  color: var(--md-primary);
  font-weight: 600;
}
body.tech-app .t-assistant-approval {
  width: min(100%, 520px);
  margin-top: 8px;
  padding: 12px;
  border: 1px solid var(--md-tertiary);
  border-radius: var(--md-shape-md);
  background: var(--md-tertiary-container);
  color: var(--md-on-tertiary-container);
}
body.tech-app .t-assistant-approval-status {
  margin-bottom: 8px;
  font-size: var(--md-label-md);
  font-weight: 700;
}
body.tech-app .t-assistant-approval-preview {
  width: 100%;
  min-height: 96px;
  resize: vertical;
  padding: 10px;
  border: 1px solid currentColor;
  border-radius: var(--md-shape-xs);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 16px;
}
body.tech-app .t-assistant-approval-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
body.tech-app .t-assistant-approval-actions .t-btn {
  flex: 1 1 132px;
  min-width: 0;
  padding-inline: 12px;
}
body.tech-app .t-assistant-approval.is-done {
  border-color: var(--md-outline-variant);
  background: var(--md-surface-c);
  color: var(--md-on-surface-variant);
}
/* REQ-ACTION-005: a second view of the same action is a reference, not a
   second decision — it never carries an enabled button. */
body.tech-app .t-assistant-approval.is-duplicate {
  border-style: dashed;
  background: var(--md-surface-c);
  color: var(--md-on-surface-variant);
}
body.tech-app .t-assistant-approval-duplicate {
  margin-top: 6px;
  font-size: var(--md-body-sm);
  font-weight: 600;
}
/* REQ-ACTION-008 / REQ-COMMS-004: diagnostics live under Details, never in
   the headline the human is meant to act on. */
body.tech-app .t-assistant-approval-detail,
body.tech-app .t-assistant-trace {
  margin-top: 8px;
  font-size: var(--md-body-sm);
  color: var(--md-on-surface-variant);
}
body.tech-app .t-assistant-approval-detail > summary,
body.tech-app .t-assistant-trace > summary {
  display: flex;
  align-items: center;
  min-height: 48px;
  font-weight: 600;
  cursor: pointer;
}
body.tech-app .t-assistant-approval-detail-body {
  overflow-wrap: anywhere;
}
body.tech-app .t-assistant-trace-list {
  margin: 0;
  padding-left: 20px;
}
/* REQ-PHONE-002: the canonical job/visit identity line, on every job and
   visit surface, in the same place and the same weight each time. */
body.tech-app .t-canonical-id {
  font-size: var(--md-label-lg);
  line-height: var(--md-label-lg-lh);
  font-weight: 700;
  letter-spacing: .3px;
  color: var(--md-on-surface);
  overflow-wrap: anywhere;
}
body.tech-app .t-timeline-item .t-canonical-id {
  font-size: var(--md-body-sm);
  font-weight: 600;
  color: var(--md-on-surface-variant);
}

/* Gemini-inspired field assistant shell. The MTG brass context mark, field
   approvals, attachment behavior, and company permissions remain product-owned. */
body.tech-app .t-assistant-bar {
  gap: 10px;
  width: min(680px, calc(100% - 24px));
  min-height: 56px;
  padding: 6px 10px;
  border-color: var(--md-outline-variant);
  border-radius: 28px;
  background: color-mix(in srgb, var(--md-surface-c-high) 94%, transparent);
  box-shadow: var(--md-elev-2);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}
body.tech-app .t-assistant-bar-plus {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: var(--md-shape-full);
  background: var(--md-surface-c-highest);
  color: var(--md-primary);
}
body.tech-app .t-assistant-bar-plus svg,
body.tech-app .t-assistant-icon-btn svg,
body.tech-app .t-assistant-send svg {
  width: 20px;
  height: 20px;
}
body.tech-app .t-assistant-bar-label {
  color: var(--md-on-surface);
  font-weight: 600;
}
body.tech-app .t-assistant-bar-context {
  flex: 0 1 auto;
  max-width: 180px;
  overflow: hidden;
  padding: 6px 10px;
  border-radius: var(--md-shape-full);
  background: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
  font-size: var(--md-body-sm);
  font-weight: 650;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.tech-app .t-assistant-backdrop {
  background: color-mix(in srgb, black 42%, transparent);
  backdrop-filter: blur(2px);
}
body.tech-app .t-assistant-dock {
  bottom: 10px;
  grid-template-rows: auto auto minmax(112px, 1fr) auto auto;
  width: min(760px, calc(100% - 24px));
  max-width: none;
  height: min(86dvh, 800px);
  max-height: calc(100dvh - 20px - env(safe-area-inset-top, 0px));
  overflow: hidden;
  border: 1px solid var(--md-outline-variant);
  border-radius: 28px;
  background: var(--md-surface-c-low);
  box-shadow: var(--md-elev-3);
}
body.tech-app .t-assistant-dock-head {
  min-height: 64px;
  padding: 10px 10px 10px 16px;
  border-bottom: 0;
}
body.tech-app .t-assistant-dock-head > .t-assistant-identity {
  display: flex;
  align-items: center;
  gap: 10px;
}
body.tech-app .t-assistant-mark,
body.tech-app .t-assistant-welcome-mark {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  border-radius: 14px;
  background: conic-gradient(from 215deg, var(--md-primary), var(--md-tertiary), var(--md-secondary), var(--md-primary));
  color: var(--md-on-primary);
  box-shadow: 0 7px 22px color-mix(in srgb, var(--md-primary) 30%, transparent);
}
body.tech-app .t-assistant-mark {
  width: 40px;
  height: 40px;
}
body.tech-app .t-assistant-mark svg { width: 23px; height: 23px; }
body.tech-app .t-assistant-identity-copy {
  display: grid;
  min-width: 0;
  line-height: 1.15;
}
body.tech-app .t-assistant-dock-head h2 {
  font-size: var(--md-title-md);
  font-weight: 700;
}
body.tech-app .t-assistant-context { margin-top: 3px; }
body.tech-app .t-assistant-head-actions { gap: 0; }
body.tech-app .t-assistant-head-actions .t-assistant-icon-btn {
  width: 44px;
  min-width: 44px;
  height: 44px;
  color: var(--md-on-surface-variant);
}
body.tech-app .t-assistant-messages {
  padding: 14px 22px 8px;
  scroll-padding-bottom: 18px;
}
body.tech-app .t-assistant-welcome {
  display: grid;
  justify-items: center;
  gap: 8px;
  width: min(620px, 100%);
  margin: auto;
  padding: clamp(26px, 7vh, 64px) 0 18px;
  border-radius: 0;
  background: transparent;
  color: var(--md-on-surface-variant);
  text-align: center;
}
body.tech-app .t-assistant-welcome-mark {
  width: 54px;
  height: 54px;
  margin-bottom: 4px;
  border-radius: 20px;
}
body.tech-app .t-assistant-welcome-mark svg { width: 31px; height: 31px; }
body.tech-app .t-assistant-welcome-kicker {
  color: var(--md-on-surface-variant);
  font-size: var(--md-label-md);
  font-weight: 750;
  letter-spacing: .09em;
  text-transform: uppercase;
}
body.tech-app .t-assistant-welcome-title {
  font-size: clamp(25px, 6vw, 36px);
  line-height: 1.12;
  font-weight: 620;
  letter-spacing: -.025em;
  background: linear-gradient(100deg, var(--md-primary), var(--md-tertiary), var(--md-on-surface));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
body.tech-app .t-assistant-welcome-copy {
  max-width: 540px;
  font-size: var(--md-body-md);
  line-height: 1.55;
}
body.tech-app .t-assistant-suggestions {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  width: 100%;
  margin-top: 16px;
}
body.tech-app .t-assistant-chip {
  display: grid;
  align-content: space-between;
  gap: 5px;
  min-height: 100px;
  padding: 14px;
  border: 0;
  border-radius: 18px;
  background: var(--md-surface-c);
  color: var(--md-on-surface);
  text-align: left;
}
body.tech-app .t-assistant-chip strong { font-size: var(--md-body-md); }
body.tech-app .t-assistant-chip span {
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-sm);
  line-height: 1.35;
}
body.tech-app .t-assistant-msg {
  width: min(620px, 100%);
  margin: 0 auto 16px;
}
body.tech-app .t-assistant-msg.assistant .t-assistant-bubble {
  width: 100%;
  max-width: none;
  padding: 4px 0;
  border-radius: 0;
  background: transparent;
  line-height: 1.62;
}
body.tech-app .t-assistant-msg.user .t-assistant-bubble {
  max-width: 86%;
  padding: 11px 15px;
  border-radius: 22px 22px 6px 22px;
}
body.tech-app .t-assistant-trace {
  width: min(620px, 92%);
  max-width: none;
}
body.tech-app .t-assistant-tray {
  width: min(680px, calc(100% - 24px));
  margin: 0 auto;
  padding: 8px 4px 0;
  border-top: 0;
  background: transparent;
}
body.tech-app .t-assistant-compose {
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: end;
  gap: 4px;
  width: min(680px, calc(100% - 24px));
  margin: 8px auto 12px;
  padding: 6px 8px;
  border: 1px solid var(--md-outline-variant);
  border-radius: 28px;
  background: var(--md-surface-c-high);
  box-shadow: var(--md-elev-2);
}
body.tech-app .t-assistant-attach-actions { gap: 0; }
body.tech-app .t-assistant-compose .t-assistant-icon-btn {
  width: 44px;
  min-width: 44px;
  height: 48px;
  color: var(--md-on-surface-variant);
}
body.tech-app #t-assistant-input {
  min-height: 48px;
  padding: 12px 8px;
  border: 0;
  border-radius: 20px;
  background: transparent;
  line-height: 24px;
}
body.tech-app #t-assistant-input:focus {
  outline: none;
  border-color: transparent;
}
body.tech-app .t-assistant-send {
  display: grid;
  place-items: center;
  width: 48px;
  min-width: 48px;
  height: 48px;
  min-height: 48px;
  padding: 0;
  border-radius: var(--md-shape-full);
}
body.tech-app .t-assistant-send-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
@media (max-width: 720px) {
  body.tech-app .t-assistant-bar { width: calc(100% - 20px); }
  body.tech-app .t-assistant-bar-context { display: none; }
  body.tech-app .t-assistant-dock {
    bottom: 0;
    width: 100%;
    height: min(88dvh, 820px);
    max-height: calc(100dvh - env(safe-area-inset-top, 0px));
    border-width: 1px 0 0;
    border-radius: 26px 26px 0 0;
  }
  body.tech-app .t-assistant-messages { padding: 8px 16px 4px; }
  body.tech-app .t-assistant-welcome { padding: 24px 0 12px; }
  body.tech-app .t-assistant-suggestions { grid-template-columns: 1fr; }
  body.tech-app .t-assistant-chip { min-height: 70px; }
  body.tech-app .t-assistant-tray,
  body.tech-app .t-assistant-compose { width: calc(100% - 16px); }
  body.tech-app .t-assistant-compose {
    margin-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  }
}
@media (max-width: 380px) {
  body.tech-app .t-assistant-compose .t-assistant-icon-btn {
    width: 40px;
    min-width: 40px;
  }
  body.tech-app .t-assistant-media-gallery {
    grid-template-columns: 1fr;
  }
}
@media (prefers-reduced-motion: reduce) {
  body.tech-app .t-assistant-dock,
  body.tech-app .t-assistant-bar,
  body.tech-app .t-assistant-mark,
  body.tech-app .t-assistant-welcome-mark {
    animation: none;
    transition: none;
  }
}
