/* admin/css/10-base.css: Tokens, base, words, panel surface, buttons, chips, status, fields, figures.
   The admin stylesheet is these files in numeric order, linked from admin.html; a later file overrides an earlier one, so keep the order. */
/* ============================================================================
   Two Guys USA admin (rewritten 2026-09-13): the ledger.

   A quiet operations console. One surface, one hairline, and hierarchy that
   comes from type size and spacing rather than from color. Color is spent at
   three points only: the primary button and the section you are in (blaze),
   a figure that is money in (moss), and a figure or a date that is a problem
   (rose). Status is a small dot beside a plain word, never a fill.

   The file is ONE layer, in reading order: tokens, base, the shell, then every
   component once. Add to the section a rule belongs in; do not append a
   "pass" at the end that overrides an earlier value. The previous stylesheet
   grew to five such layers and the owner's read of it was "messy, everything
   looks the same, too colorful".
   ============================================================================ */

/* ---------- tokens ---------- */
/* One theme for every role (the customer's went dark on 2026-09-30; its
   bigger scale is the `.easy` block at the end). */
:root{
  --g0:#0B1510;--g1:#0E1A13;--card:#132018;--card-2:#182920;
  --line:rgba(255,255,255,.08);--line-2:rgba(255,255,255,.14);--hairline:var(--line);--hl-soft:rgba(255,255,255,.06);
  --ink:#EEF2EC;--slate:#9DAC9D;--mist:#8A9E8B;
  --blaze:#E8560F;--blaze-hot:#FF6A24;--blaze-btn:#C94406;--blaze-ink:#2B0A00;--wheat:#E3A130;--moss:#3E7A4E;--moss-hot:#6FCB88;
  /* the palette, five meanings; the contrast test reads these names */
  --t-blaze:#FF6A24;--t-wheat:#E3A130;--t-kraft:#C7B88F;--t-moss:#6FCB88;--t-rose:#E88A7C;--t-slate:#9DAC9D;
  --t-sky:var(--t-wheat);--t-teal:var(--t-kraft);--t-mint:var(--t-moss);--t-violet:var(--t-kraft);
  /* status: one warm ladder that fills as the job banks */
  --st-new:#FF6A24;--st-contacted:#E3A130;--st-quoted:#C7B88F;--st-won:#A6DCAE;--st-scheduled:#8AD39B;--st-done:#6FCB88;--st-approved:#4FC07A;--st-lost:#E88A7C;
  --rgb-new:255,106,36;--rgb-contacted:227,161,48;--rgb-quoted:199,184,143;--rgb-won:166,220,174;--rgb-scheduled:138,211,155;--rgb-done:111,203,136;--rgb-approved:79,192,122;--rgb-lost:232,138,124;
  --tone:var(--t-slate);--tone-rgb:157,172,157;--tone-ink:#0B1510;
  --r:10px;--r-sm:8px;--r-pill:100px;
  --ease:cubic-bezier(.2,.8,.3,1);
  --shadow-float:0 12px 40px rgba(0,0,0,.45);
  --rail:248px;--topbar:64px;--tabbar:64px;--viewbar:56px;--measure:1400px;
  --display:'Archivo',sans-serif;--text:'Figtree',sans-serif;
}
[data-tone=blaze]{--tone:var(--t-blaze);--tone-rgb:255,106,36;--tone-ink:#2B0A00}
[data-tone=wheat],[data-tone=sky]{--tone:var(--t-wheat);--tone-rgb:227,161,48;--tone-ink:#2A1700}
[data-tone=kraft],[data-tone=teal],[data-tone=violet]{--tone:var(--t-kraft);--tone-rgb:199,184,143;--tone-ink:#2A2010}
[data-tone=moss],[data-tone=mint]{--tone:var(--t-moss);--tone-rgb:111,203,136;--tone-ink:#06240F}
[data-tone=rose]{--tone:var(--t-rose);--tone-rgb:232,138,124;--tone-ink:#2B0A05}
[data-tone=slate]{--tone:var(--t-slate);--tone-rgb:157,172,157;--tone-ink:#0B1510}

/* ---------- base ---------- */
*{margin:0;padding:0;box-sizing:border-box}
html{background:var(--g0);color-scheme:dark;-webkit-text-size-adjust:100%;overscroll-behavior:none;scroll-behavior:smooth}
body{font-family:var(--text);font-size:15.5px;line-height:1.5;color:var(--ink);background:transparent;min-height:100svh;-webkit-font-smoothing:antialiased;overflow-x:clip}
/* the site's dark section (.rev, .cta), turned down for work: the blaze glow
   top right, the moss glow bottom left, on the same forest ground (2026-10-12,
   "give it a real Two Guys look") */
html::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(900px 560px at 100% -12%,rgba(232,86,15,.085),transparent 62%),
    radial-gradient(820px 520px at -6% 112%,rgba(46,92,62,.30),transparent 62%),
    linear-gradient(180deg,var(--g0),var(--g1) 30%,var(--g1) 70%,var(--g0))}
h1,h2,h3{font-family:var(--display);letter-spacing:-.02em;font-weight:700;line-height:1.2}
/* selection, caret and focus carry the site's blaze rather than the browser's blue */
::selection{background:rgba(255,106,36,.32);color:#fff}
input,textarea{caret-color:var(--blaze-hot)}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0}
a{color:var(--blaze-hot)}
img{max-width:100%;display:block}
[hidden]{display:none!important}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.ic{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;flex:none}
.mono,.mono-num{font-variant-numeric:tabular-nums}
.mono-num{font-size:13px;color:var(--slate)}
.num{font-family:var(--display);font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
:where(a,button,select,input,textarea,[tabindex]):focus-visible{outline:2px solid var(--blaze-hot);outline-offset:2px;border-radius:6px}
.skip-to{position:absolute;left:-9999px;top:0;z-index:100;background:var(--blaze-btn);color:#fff;padding:12px 18px;border-radius:0 0 10px 0;font-weight:700;text-decoration:none}
.skip-to:focus{left:0}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}

/* ---------- words ---------- */
/* A section label is a plain line of text. No mono, no caps, no rule before it. */
.kicker{display:flex;align-items:center;gap:10px;font-size:14px;font-weight:600;color:var(--slate);line-height:1.4}
.kicker .tail{margin-left:auto;font-weight:500;color:var(--mist);font-variant-numeric:tabular-nums}
.kicker .tail.late{color:var(--t-rose)}
.sub{color:var(--slate);font-size:14.5px;line-height:1.55}
.muted{color:var(--mist)}
.hint{font-size:13px;color:var(--mist)}
.group-help,.lp-help,.fold-help{font-size:14px;color:var(--slate);line-height:1.55}
.count,.count-note{font-size:13.5px;color:var(--mist);font-variant-numeric:tabular-nums;font-weight:500}
.fold-h{font-family:var(--display);font-size:15px;font-weight:700;color:var(--ink);margin:0}
/* a second subject inside one fold body: the hairline says a new thing starts */
.fold-body>.set-rule{border-top:1px solid var(--line);padding-top:18px}
/* a second heading after a form grid needs the room a new section gets, not the 0px it had under the last select */
.form-grid+.set-rule{margin-top:24px}
/* the QuickBooks item map, one kind of job a row with its product under it at the panel's full width:
   in half columns "Residential Concrete Driveway Replacement" was cut to "Residential Concrete Drivew" */
.form-grid.qb-map{grid-template-columns:minmax(0,1fr);gap:14px}
.set-rule+.sub{margin:4px 0 14px}

/* ---------- panel: one surface ---------- */
/* DEPTH, not decoration. One light source above (the top hairline is brighter
   than the other three) and a shadow that only just exists, so a panel sits ON
   the ground rather than being drawn on it. No gradient, no glow, no color:
   the ledger's rules still hold. */
.panel{position:relative;background:var(--card);border:1px solid var(--line);border-top-color:rgba(255,255,255,.13);
  border-radius:var(--r);padding:22px 24px;min-width:0;
  box-shadow:0 1px 1px rgba(0,0,0,.25),0 14px 28px -22px rgba(0,0,0,.9)}
.panel.tight{padding:16px}
/* THE RHYTHM INSIDE A BLOCK (2026-09-14). Stacked lines get at least four
   tenths of the larger type size between their INK, measured with a Range and
   not the element box, which hides half a line of leading either side. A 16.5px
   name with its meta line three pixels under it reads as one crowded object
   however well the panel around it is inset, and that is what the owner keeps
   seeing. Every number below was measured, not guessed (`space.mjs`). */
.panel-head{display:flex;flex-direction:column;gap:9px;margin-bottom:18px}
.panel-head h2{font-size:19px}
.panel-head .row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.panel-head .count{font-size:13px}
/* A COUNT BELONGS BESIDE THE THING IT COUNTS. The row is space-between so a
   button (Add a person) sits at the right, but that threw a bare "1" to the
   far edge as well: on the contractor's Jobs screen "New offer" and its count
   ended up eleven hundred pixels apart, which reads as a stray character
   rather than as a number. The auto margin puts the count next to the title
   and still pushes any button after it to the right. A `.count-note` ("22 of
   22") is a phrase, not a digit, and stays where it is. */
.panel-head .row .count,.group-head .count{margin-right:auto}
.panel-head .sub{margin-top:2px}
.panel.is-link{cursor:pointer;transition:border-color .15s,transform .15s var(--ease),box-shadow .15s}
@media(hover:hover){.panel.is-link:hover{border-color:var(--line-2);transform:translateY(-1px);box-shadow:0 2px 2px rgba(0,0,0,.25),0 18px 34px -22px rgba(0,0,0,.95)}}
.panel.is-lapsing{border-color:rgba(232,138,124,.4)}
.grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
/* A PAIR OF LISTS IS NOT A PAIR OF CHARTS. A grid stretches both cells to the
   taller one, which is right for two charts (they have a fixed height anyway)
   and wrong for two lists: ten services beside four towns gave the towns a
   bordered box with 287px of nothing under the last row, which reads as
   something that failed to load. The list pairs size to their own content;
   the chart pairs on Reports keep the matched height. */
.stats .grid-2,#rpPeople{align-items:start}
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.two{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.stack{display:flex;flex-direction:column;gap:12px}
.empty{padding:36px 20px;text-align:center;color:var(--slate);display:flex;flex-direction:column;align-items:center;gap:8px}
.empty h3{font-size:16px;color:var(--ink)}
.empty p{max-width:44ch;line-height:1.55;font-size:14px}
/* the illustration only: a button in an empty state keeps its own icon, its
   color and its size (the orange "See what we do" drew a gray-green smudge) */
.empty>.ic{width:24px;height:24px;color:var(--mist);margin-bottom:4px}
.empty .btn{margin-top:8px}

/* ---------- buttons ---------- */
/* pills, the site's button shape (--r-btn:100px there); a menu's full width
   buttons stay squared (.more-list .btn) so a list reads as a list */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;font-weight:600;font-size:14px;border-radius:var(--r-pill);padding:10px 16px;
  border:1px solid transparent;text-decoration:none;white-space:nowrap;line-height:1.2;
  transition:background .15s,border-color .15s,color .15s,transform .09s var(--ease)}
/* it answers the press: a pixel down, and back */
.btn:active,.icon-btn:active,.chip:active{transform:translateY(1px)}
.btn-blaze{box-shadow:0 1px 1px rgba(0,0,0,.3),0 8px 18px -10px rgba(0,0,0,.75)}
.btn .ic{width:15px;height:15px}
.btn-blaze{background:var(--blaze-btn);color:#fff}
/* #D84B08 was 4.25:1 with white at 14px, under AA, and the resting
   --blaze-btn beside it is 4.87. A hover that lights up cannot go past
   #D14706 (4.55) without taking the label under the floor. Found by running
   axe over the guide's own buttons, which is the first time anything had
   been measured in its HOVERED state. */
@media(hover:hover){.btn-blaze:hover{background:#D14706}}
.btn-line{background:transparent;border-color:var(--line-2);color:var(--ink)}
@media(hover:hover){.btn-line:hover{border-color:rgba(255,255,255,.3);background:rgba(255,255,255,.04)}}
.btn-ghost{color:var(--slate)}
@media(hover:hover){.btn-ghost:hover{color:var(--ink);background:rgba(255,255,255,.05)}}
.btn-danger{border-color:rgba(232,138,124,.4);color:var(--t-rose)}
@media(hover:hover){.btn-danger:hover{background:rgba(232,138,124,.1)}}
.btn-sm{padding:7px 11px;font-size:13px}
/* "more" (2026-10-09): one square button that holds a row's secondary actions */
.btn-icon{padding:10px;min-width:40px}
.btn-icon .ic{width:18px;height:18px}
.more-menu{margin:auto;inset:0;min-width:min(280px,calc(100vw - 32px));max-width:min(360px,calc(100vw - 32px));height:fit-content;
  padding:14px;border:1px solid var(--line-2);border-radius:var(--r);background:var(--card);color:var(--ink);box-shadow:var(--shadow-float)}
.more-menu::backdrop{background:rgba(5,10,7,.55)}
.more-title{display:block;font-family:var(--display);font-size:16px;font-weight:700;margin:2px 4px 12px;overflow-wrap:anywhere}
.more-list{display:flex;flex-direction:column;gap:8px}
.more-list .btn{width:100%;justify-content:flex-start;padding:12px 14px;font-size:14.5px;border-radius:var(--r-sm)}
.more-list label,.more-list .row-pick{display:block;width:100%}
.btn-wide{width:100%}
.big-btn{min-height:52px;font-size:15px}
.btn[disabled],.btn.is-busy{opacity:.5;pointer-events:none}
.icon-btn{display:inline-grid;place-items:center;width:36px;height:36px;border-radius:50%;color:var(--slate);border:1px solid transparent;transition:background .15s,color .15s}
@media(hover:hover){.icon-btn:hover{background:rgba(255,255,255,.06);color:var(--ink)}}
.link-btn{font:inherit;color:var(--blaze-hot);background:none;border:0;padding:0;cursor:pointer;text-decoration:underline;text-underline-offset:3px;text-decoration-color:rgba(255,106,36,.4)}
@media(hover:hover){.link-btn:hover{text-decoration-color:currentColor}}
.quick{display:flex;gap:8px;flex-wrap:wrap}
.upload{position:relative;display:inline-flex}
.upload input{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer}
/* a button that stands in a form row beside an input is the input's height, not a 30px chip floating by a 46px box */
.field:has(>.lbl-spacer) .btn,.field>.upload.btn{min-height:46px;padding-inline:16px;font-size:14px}
.upload.is-busy .btn{opacity:.5;pointer-events:none}

/* ---------- chips (filters, ranges, tabs) ---------- */
.chips{display:flex;gap:6px;flex-wrap:wrap}
.chip{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;font-weight:600;padding:8px 13px;border-radius:var(--r-pill);border:1px solid var(--line);
  background:transparent;color:var(--slate);transition:background .15s,color .15s,border-color .15s;text-decoration:none}
@media(hover:hover){.chip:hover{color:var(--ink);border-color:var(--line-2)}}
.chip.on{background:var(--ink);border-color:var(--ink);color:var(--g0)}
.chip-count{display:inline-block;padding:0 6px;border-radius:var(--r-pill);background:rgba(255,255,255,.1);font-size:12px;line-height:1.6;font-variant-numeric:tabular-nums}
.chip.on .chip-count{background:rgba(0,0,0,.12)}
.chip.chip-st::before,.chip.chip-hot::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--sc,var(--mist));flex:none}
.chip.on.chip-st::before,.chip.on.chip-hot::before{background:var(--sc,var(--mist))}
.chip.chip-hot{--sc:var(--st-new)}
.chip[data-f=new]{--sc:var(--st-new)} .chip[data-f=contacted]{--sc:var(--st-contacted)} .chip[data-f=quoted]{--sc:var(--st-quoted)} .chip[data-f=won]{--sc:var(--st-won)}
.chip[data-f=scheduled]{--sc:var(--st-scheduled)} .chip[data-f=done]{--sc:var(--st-done)} .chip[data-f=approved]{--sc:var(--st-approved)} .chip[data-f=lost]{--sc:var(--st-lost)}
.chip-static{display:inline-flex;align-items:center;padding:3px 9px;border-radius:var(--r-pill);border:1px solid var(--line);font-size:12px;font-weight:600;color:var(--mist);white-space:nowrap}
.range{display:flex;gap:6px;flex-wrap:wrap}
.toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.toolbar .sort{display:flex;align-items:center;gap:8px}
.toolbar .sort .kicker{font-size:13px}
.toolbar .sort .select{width:auto;min-width:150px;padding:8px 32px 8px 12px;font-size:13.5px;min-height:38px}
/* the roster's search box; a style attribute on it used to hold it at 40px on a touch screen */
.toolbar .sort .input{width:180px;padding:8px 12px;font-size:14px;min-height:40px}
.toolbar .sub{font-size:13.5px}

/* ---------- status: a dot and a word ---------- */
.status-chip{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;font-weight:600;color:var(--ink);white-space:nowrap}
.status-chip::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--sc,var(--mist));flex:none}
.status-chip.new{--sc:var(--st-new)} .status-chip.contacted{--sc:var(--st-contacted)} .status-chip.quoted{--sc:var(--st-quoted)} .status-chip.won{--sc:var(--st-won)}
.status-chip.scheduled{--sc:var(--st-scheduled)} .status-chip.done{--sc:var(--st-done)} .status-chip.approved{--sc:var(--st-approved)} .status-chip.lost{--sc:var(--st-lost);color:var(--slate)}
/* Scheduled with no date is a problem, said where the status is drawn */
.status-chip.undated,.status-sel.undated{color:var(--t-rose)}
/* the row select: the same dot and word, with a chevron */
.status-sel{appearance:none;-webkit-appearance:none;font-size:13.5px;font-weight:600;color:var(--ink);border-radius:var(--r-sm);padding:7px 26px 7px 22px;border:1px solid var(--line);cursor:pointer;
  background-color:transparent;
  background-image:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="9" height="6" viewBox="0 0 9 6"><path d="M1 1l3.5 3.5L8 1" stroke="%239DAC9D" stroke-width="1.6" fill="none" stroke-linecap="round"/></svg>'),radial-gradient(circle,var(--sc,var(--mist)) 3.5px,transparent 4px);
  background-repeat:no-repeat,no-repeat;background-position:right 9px center,left 8px center;background-size:9px 6px,9px 9px}
.status-sel.new{--sc:var(--st-new)} .status-sel.contacted{--sc:var(--st-contacted)} .status-sel.quoted{--sc:var(--st-quoted)} .status-sel.won{--sc:var(--st-won)}
.status-sel.scheduled{--sc:var(--st-scheduled)} .status-sel.done{--sc:var(--st-done)} .status-sel.approved{--sc:var(--st-approved)} .status-sel.lost{--sc:var(--st-lost)}
.status-sel option{color:var(--ink);background:var(--card-2)}
@media(hover:hover){.status-sel:hover{border-color:var(--line-2)}}
/* the segmented control in the panel */
.seg{display:flex;flex-wrap:wrap;gap:6px}
.seg-btn{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;font-weight:600;padding:9px 13px 9px 11px;border-radius:var(--r-sm);border:1px solid var(--line);color:var(--slate);background:transparent;transition:background .15s,color .15s,border-color .15s}
.seg-btn::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--sc,var(--mist));flex:none}
.seg-btn[data-status=new]{--sc:var(--st-new)} .seg-btn[data-status=contacted]{--sc:var(--st-contacted)} .seg-btn[data-status=quoted]{--sc:var(--st-quoted)} .seg-btn[data-status=won]{--sc:var(--st-won)}
.seg-btn[data-status=scheduled]{--sc:var(--st-scheduled)} .seg-btn[data-status=done]{--sc:var(--st-done)} .seg-btn[data-status=approved]{--sc:var(--st-approved)} .seg-btn[data-status=lost]{--sc:var(--st-lost)}
@media(hover:hover){.seg-btn:hover{color:var(--ink);border-color:var(--line-2)}}
.seg-btn.on{background:var(--ink);border-color:var(--ink);color:var(--g0)}
.seg-btn.on.undated{background:transparent;border-color:rgba(232,138,124,.55);color:var(--t-rose)}
.seg-btn[disabled]{opacity:.4;pointer-events:none}
/* small flags on a name */
.band,.spam-flag,.repeat,.task-kind{display:inline-flex;align-items:center;gap:4px;vertical-align:1px;font-size:11.5px;font-weight:700;letter-spacing:.02em;padding:2px 7px;border-radius:4px;border:1px solid var(--line);color:var(--slate);white-space:nowrap}
.band-hot{color:var(--blaze-hot);border-color:rgba(255,106,36,.4)}
.band-warm{color:var(--wheat);border-color:rgba(227,161,48,.4)}
.spam-flag{color:var(--t-rose);border-color:rgba(232,138,124,.4);cursor:help}
.repeat .ic{width:11px;height:11px}
.role-chip,.cstatus{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;color:var(--slate);white-space:nowrap}
.cstatus::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--sc,var(--mist))}
.cstatus.active{--sc:var(--t-moss);color:var(--ink)} .cstatus.approved{--sc:var(--wheat)} .cstatus.pending{--sc:var(--blaze-hot)} .cstatus.inactive{--sc:var(--mist)} .cstatus.rejected{--sc:var(--t-rose)}
.ins{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--slate)}
.ins .ic{width:14px;height:14px}
.ins.ok{color:var(--t-moss)} .ins.uploaded,.ins.expiring,.ins.none{color:var(--wheat)} .ins.expired{color:var(--t-rose)}
.due{font-size:13.5px;color:var(--slate);font-weight:500}
.due.warn{color:var(--wheat)} .due.late{color:var(--t-rose)} .due.good{color:var(--t-moss)}
.pay,.kv .pay,.jobcard .meta .pay,.offer-pay b{font-family:var(--display);font-weight:700;color:var(--t-moss)}
.offer-pay{margin-top:10px;font-size:14px;color:var(--slate)}
.paid-tag{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;font-weight:600;color:var(--t-moss)}
.paid-tag .ic{width:13px;height:13px}

/* the fuse: the one signature device, a wait bar under a lead nobody has answered */
.wait{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;white-space:nowrap}
.wait::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.wait.ok{color:var(--t-moss)} .wait.warn{color:var(--wheat)} .wait.late{color:var(--blaze-hot)}
.wait.late::before{animation:pulse 1.8s ease-in-out infinite}
@keyframes pulse{50%{box-shadow:0 0 0 5px rgba(255,106,36,.14)}}
.fuse{position:relative;height:2px;border-radius:1px;background:rgba(255,255,255,.08);overflow:hidden;margin-top:10px}
.fuse>i{position:absolute;inset:0 auto 0 0;width:var(--w,4%);background:var(--t-moss);transition:width .9s var(--ease)}
.fuse.warn>i{background:var(--wheat)} .fuse.late>i{background:var(--blaze-hot)}

/* the stage pill: dots lit as far as the job has come */
.stage{display:inline-flex;align-items:center;gap:9px;font-size:13px;font-weight:500;color:var(--slate);white-space:nowrap;max-width:100%}
/* how far the job has come, as a short segmented bar: six loose dots asked
   to be counted and had no legend; a bar that fills reads as progress on
   sight, and each segment still names its step on hover (2026-10-12) */
.stage .dots{display:inline-flex;gap:3px;flex:none;align-items:center}
.stage .dots i{width:11px;height:5px;border-radius:3px;border:0;background:rgba(255,255,255,.14);display:block}
.stage .dots i.on{background:var(--t-moss)}
.stage .dots i.next{background:transparent;box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.5)}
.stage.warn .stage-label{color:var(--wheat)} .stage.late .stage-label{color:var(--t-rose)} .stage.ok .stage-label{color:var(--ink)} .stage.done .stage-label{color:var(--t-moss)} .stage.lost .stage-label{color:var(--t-rose)}
.stage.done .dots i.on{background:var(--st-approved)}
.stage-label{overflow:hidden;text-overflow:ellipsis}
.stage.big{font-size:13.5px;gap:10px;white-space:normal}
.stage.big .stage-label{overflow:visible}   /* the panel head has the room: "Waiting on Brian Duquai..." was cut at 320 */
.stage.big .dots{gap:5px}
.stage.big .dots i{width:16px;height:6px}

/* ---------- fields ---------- */
.field{display:flex;flex-direction:column;gap:7px;min-width:0}
.field>span,.field>label{font-size:13.5px;font-weight:600;color:var(--slate)}
.input,.select,.textarea{width:100%;background:rgba(255,255,255,.03);border:1px solid var(--line-2);border-radius:var(--r-sm);padding:10px 12px;font-size:16px;color:var(--ink);transition:border-color .15s,background .15s}
.input::placeholder,.textarea::placeholder{color:var(--mist)}
.input:focus,.select:focus,.textarea:focus{outline:none;border-color:var(--blaze-hot);background:rgba(255,255,255,.05)}
.textarea{min-height:88px;resize:vertical;line-height:1.5}
.select{appearance:none;-webkit-appearance:none;padding-right:34px;cursor:pointer;
  background-image:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="11" height="7" viewBox="0 0 11 7"><path d="M1 1l4.5 4.5L10 1" stroke="%239DAC9D" stroke-width="1.7" fill="none" stroke-linecap="round"/></svg>');
  background-repeat:no-repeat;background-position:right 12px center}
.select option{background:var(--card-2);color:var(--ink)}
/* A select that holds several: a <details> dressed as one, its ticks below it.
   In flow, not floating, so it can never open off the edge of a phone panel. */
.multi{min-width:0}
.multi>summary{list-style:none;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-height:46px;line-height:24px}
.multi>summary::-webkit-details-marker{display:none}
.multi[open]>summary{border-color:var(--line-2);border-bottom-left-radius:0;border-bottom-right-radius:0}
.multi-list{border:1px solid var(--line-2);border-top:0;border-radius:0 0 var(--r-sm) var(--r-sm);padding:6px 4px 10px;background:rgba(255,255,255,.02)}
.multi-opt{display:flex;align-items:center;gap:12px;min-height:44px;padding:0 10px;border-radius:var(--r-sm);cursor:pointer;font-size:15px;font-weight:500;color:var(--ink)}
.multi-opt input{width:18px;height:18px;accent-color:var(--blaze-hot);flex:none;margin:0}
.multi-opt:has(input:focus-visible){outline:2px solid var(--blaze-hot);outline-offset:-2px}
@media(hover:hover){.multi-opt:hover{background:rgba(255,255,255,.04)}}
.multi-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:8px 10px 0}
.multi-foot .field-note{margin-top:0}
.input[type=date],.input[type=time],.input[type=datetime-local]{-webkit-appearance:none;appearance:none;display:block;width:100%;min-width:0;text-align:left;min-height:46px;line-height:1.3}
.input[type=date]::-webkit-date-and-time-value,.input[type=time]::-webkit-date-and-time-value,.input[type=datetime-local]::-webkit-date-and-time-value{text-align:left;min-height:1.3em;margin:0}
.input[type=date]::-webkit-calendar-picker-indicator,.input[type=datetime-local]::-webkit-calendar-picker-indicator{opacity:.7}
/* AN EMPTY DATE FIELD SAYS SO (2026-09-27). `appearance:none` fits the field
   to the ledger, and on a real iPhone it left an empty one a plain box: no
   placeholder, no calendar, nothing to say a tap opens a picker (Chromium
   kept its mm/dd/yyyy; desktop Safari painted TODAY's date in, which reads as
   set). While it is empty and not being edited it reads "Pick a date" beside
   a calendar. The engine's own text and button are still there, unseen, so a
   click on the calendar still opens Chromium's picker, and focus hands the
   field back to the engine. `is-empty` is kept in step by installDateHints()
   in ui.js. A filled field is exactly as it was. One pseudo-element a rule:
   an engine that does not know one drops the whole rule it is in. */
.input[type=date],.input[type=datetime-local]{position:relative}
.input:is([type=date],[type=datetime-local]).is-empty:not(:focus)::-webkit-datetime-edit{opacity:0}
.input:is([type=date],[type=datetime-local]).is-empty:not(:focus)::-webkit-calendar-picker-indicator{opacity:0}
.input:is([type=date],[type=datetime-local]).is-empty:not(:focus)::before{content:"Pick a date";position:absolute;inset:0;padding:inherit;padding-right:44px;
  display:flex;align-items:center;color:var(--mist);white-space:nowrap;overflow:hidden;pointer-events:none}
.input[type=datetime-local].is-empty:not(:focus)::before{content:"Pick a day and time"}
.input:is([type=date],[type=datetime-local]).is-empty:not(:focus)::after{content:"";position:absolute;right:13px;top:50%;width:18px;height:18px;margin-top:-9px;background:var(--slate);pointer-events:none;
  -webkit-mask:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>') center/contain no-repeat;
  mask:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>') center/contain no-repeat}
.input.is-invalid,.select.is-invalid{border-color:var(--t-rose)}
.field-err{font-size:12.5px;color:var(--t-rose);font-weight:600}
.field-note{display:block;margin-top:6px;font-size:12.5px;line-height:1.45;color:var(--mist)}
.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.form-grid .span-2{grid-column:1/-1}
.form-actions{display:flex;justify-content:flex-end;align-items:center;gap:10px;margin-top:18px;flex-wrap:wrap}
.form-note{font-size:13px;color:var(--slate);margin-top:10px}
.form-note.warn{color:var(--wheat)}
.val-in{width:104px;padding:7px 10px;font-size:13.5px;min-height:36px;font-variant-numeric:tabular-nums}
.toggle{display:inline-flex;align-items:center;gap:10px;cursor:pointer;font-weight:500;font-size:14px}
.toggle input{width:1px;height:1px;opacity:0;position:absolute}
.toggle .knob{width:38px;height:22px;border-radius:11px;background:rgba(255,255,255,.1);border:1px solid var(--line-2);position:relative;transition:background .2s;flex:none}
.toggle .knob::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--slate);transition:transform .2s,background .2s}
.toggle input:checked+.knob{background:rgba(111,203,136,.3);border-color:rgba(111,203,136,.5)}
.toggle input:checked+.knob::after{transform:translateX(16px);background:var(--t-moss)}
.toggle input:focus-visible+.knob{outline:2px solid var(--blaze-hot);outline-offset:2px}
.note-box{display:flex;gap:8px;align-items:flex-end}
.note-box .textarea{min-height:48px}
.caption-box{display:flex;gap:8px;align-items:flex-start}
.caption-box .textarea{min-height:72px}
/* the next step can be a sentence ("Install weed barrier, correct grade by garage..."): two lines, not one cut off */
.textarea.next-text{min-height:0;resize:vertical;field-sizing:content;max-height:9lh}
/* an address or an email: one line like the inputs beside it (46px), a second
   when the words need it, instead of running out of sight (ui.js oneLine) */
.input.one-line{display:block;resize:none;overflow:hidden;field-sizing:content}
.temp-pass{font-family:var(--display);font-size:22px;letter-spacing:.04em;font-weight:600;color:var(--ink);border:1px dashed var(--line-2);border-radius:var(--r-sm);padding:14px 16px;text-align:center;margin:12px 0}
