/* ═══════════════════════════════════════════════════════════════════════════
   TZA Hub — iPad field design system
   ---------------------------------------------------------------------------
   Target: iPad 10.9" in Safari, used on roofs and building sites — touch and
   Apple Pencil, often in direct sun, often through a glove. Everything here is
   sized for that: body type 15–17px, primary buttons 64px, list rows 72px+.

   The --tza-* custom properties below are the whole contract. Field mode
   (Standard / Sunlight / Gloved hands) and rail style are per-device settings
   that do nothing but re-point these values; no component has a hardcoded
   border weight, control height or shadow of its own. Settings › Display &
   touch writes data-field-mode / data-rail onto <html>, and includes/header.php
   replays the stored choice before first paint.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  color-scheme:light;

  /* ── Brand ─────────────────────────────────────────────────────────────── */
  --tza-indigo:#26387D;      /* primary — buttons, active states, structure   */
  --tza-indigo-hover:#1F2E69;
  --tza-accent:#B92D92;      /* magenta — accent ONLY, never a bulk surface   */
  --tza-accent-hover:#9C2079;

  /* ── Text ──────────────────────────────────────────────────────────────── */
  --tza-ink:#0E1230;         /* headings                                      */
  --tza-body:#3B4256;
  --tza-muted:#525A72;
  --tza-faint:#6F7791;
  --tza-ghost:#9AA1B7;

  /* ── Lines & surfaces ──────────────────────────────────────────────────── */
  --tza-line:#DDE0EA;        /* standard border                               */
  --tza-inline:#C3C8D7;      /* input border                                  */
  --tza-hair:#ECEEF4;        /* row separator inside a card                   */
  --tza-surface:#F6F7FA;     /* page background                               */
  --tza-tint:#F1F3FA;        /* indigo wash — summary strips, module chips    */
  --tza-tint-line:#BFC7E6;
  --tza-accent-tint:#FDF2F9; /* magenta wash — the urgent tool card           */

  /* ── Status ────────────────────────────────────────────────────────────── */
  --tza-green:#1F7A52;--tza-green-bg:#EFF8F3;
  --tza-amber:#8F5500;--tza-amber-bg:#FDF6EA;--tza-amber-line:#B26A00;
  --tza-red:#A61B1B;--tza-red-bg:#FBECEC;

  /* ── Type ──────────────────────────────────────────────────────────────── */
  --tza-head:Poppins,'IBM Plex Sans',system-ui,-apple-system,sans-serif;
  --tza-sans:'IBM Plex Sans',system-ui,-apple-system,BlinkMacSystemFont,sans-serif;
  --tza-mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  /* ── Field-mode variables ──────────────────────────────────────────────────
     Standard. data-field-mode on <html> overrides these three ways; nothing
     else in this file redefines them. */
  --tza-bw:1px;                              /* card border                   */
  --tza-shadow:0 1px 2px rgba(14,18,48,.06); /* card shadow                   */
  --tza-inbw:2px;                            /* input border                  */
  --tza-sigbw:2px;                           /* signature pad / outline btn   */
  --tza-btn:64px;                            /* primary button height         */
  --tza-btn-sm:60px;
  --tza-btn-xs:56px;                         /* inline row action             */
  --tza-row:72px;                            /* list-row min-height           */
  --tza-row-lg:88px;                         /* card-row min-height           */
  --tza-thumb:56px;                          /* uploaded-photo tile           */
  --tza-safe-top:env(safe-area-inset-top);   /* status bar over the page — 0 with the solid bar */
  --tza-rail:88px;                           /* nav rail width                */
  --tza-railitem:76px;
  --tza-raillabel:block;
  --tza-sig:320px;                           /* signature pad height          */
  --tza-sig-sm:280px;

  font-family:var(--tza-sans);

  /* ── Legacy neutral ramp ───────────────────────────────────────────────────
     Views still reach for var(--gray-500) and friends inline. Kept, but
     re-pointed at the palette above so nothing renders in the old cool greys. */
  --gray-50:#FAFBFD;--gray-100:#F3F4F8;--gray-200:#DDE0EA;--gray-300:#C3C8D7;
  --gray-400:#9AA1B7;--gray-500:#6F7791;--gray-600:#525A72;--gray-700:#3B4256;
  --gray-800:#1B2140;--gray-900:#0E1230;
  --brand-text:#0E1230;
  --primary:#26387D;--primary-light:#F1F3FA;--primary-dark:#1F2E69;
  --accent:#B92D92;
  --navy:#26387D;--navy-light:#F1F3FA;--navy-dark:#1F2E69;
  --green:#1F7A52;--green-light:#EFF8F3;--green-dark:#155F40;
  --blue:#26387D;--orange:#8F5500;--red:#A61B1B;--yellow:#8F5500;
}

/* Sunlight: heavier edges, no shadows — a 1px hairline and a soft shadow both
   disappear under glare, so the card has to be drawn, not suggested. */
html[data-field-mode="sunlight"]{
  --tza-bw:2px;--tza-shadow:none;--tza-inbw:3px;--tza-sigbw:3px;
  --tza-row:76px;--tza-row-lg:92px;--tza-thumb:60px;--tza-sig:340px;--tza-sig-sm:300px;
  --tza-line:#C3C8D7;--tza-hair:#DDE0EA;
}
/* Gloved hands: same weights as standard, everything you press gets bigger. */
html[data-field-mode="gloves"]{
  --tza-bw:2px;
  --tza-btn:80px;--tza-btn-sm:74px;--tza-btn-xs:68px;
  --tza-row:92px;--tza-row-lg:104px;--tza-thumb:72px;--tza-sig:400px;--tza-sig-sm:340px;
  --tza-railitem:88px;
}
/* Rail style — per device, same permitted item list either way. */
html[data-rail="icons"]{--tza-rail:76px;--tza-raillabel:none;}
html[data-rail="wide"]{--tza-rail:208px;}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;background:var(--tza-surface)}
body{
  background:var(--tza-surface);min-height:100vh;color:var(--tza-body);
  font-family:var(--tza-sans);font-size:16px;line-height:1.5;
  -webkit-tap-highlight-color:transparent;-webkit-font-smoothing:antialiased;
}
button{cursor:pointer;border:none;outline:none;font-family:inherit;touch-action:manipulation;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
input,select,textarea{font-family:inherit;outline:none;-webkit-user-select:text;user-select:text}
a{color:var(--tza-indigo)}
:focus-visible{outline:3px solid var(--tza-accent);outline-offset:2px}

/* Every number, reference, date and currency figure is mono with tabular
   figures, so a column of them lines up and a changing digit doesn't reflow. */
.mono,.kes{font-family:var(--tza-mono);font-variant-numeric:tabular-nums}

/* ── Type scale ─────────────────────────────────────────────────────────── */
.eyebrow{font-family:var(--tza-head);font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;font-weight:600;color:var(--tza-faint)}
.eyebrow-accent{color:var(--tza-accent)}
.eyebrow-indigo{color:var(--tza-indigo)}
.display{font-family:var(--tza-head);font-size:32px;line-height:1.15;letter-spacing:-.015em;font-weight:600;color:var(--tza-ink)}
.h2,.card-title,.page-title{font-family:var(--tza-head);font-size:23px;font-weight:600;letter-spacing:-.01em;color:var(--tza-ink);line-height:1.25}
.h3{font-family:var(--tza-head);font-size:19px;font-weight:600;color:var(--tza-ink)}
.h4{font-family:var(--tza-head);font-size:17px;font-weight:600;color:var(--tza-ink)}
.sub,.page-subtitle,.card-sub{font-size:14px;color:var(--tza-faint);margin-top:4px}
.prose{font-size:15px;line-height:1.6;color:var(--tza-body);text-wrap:pretty}

/* ── App frame ──────────────────────────────────────────────────────────── */
#app{min-height:100vh}
#main{
  margin-left:var(--tza-rail);min-height:100vh;display:flex;flex-direction:column;
  transition:margin-left .18s ease;
}
#content{flex:1;padding:24px;padding-bottom:calc(24px + env(safe-area-inset-bottom))}

/* iPadOS 26 draws the Home Screen app under the status bar and blurs that
   strip, whatever the status-bar-style meta says. There is no switch for it.
   WebKit leaves the blur out when a fixed or sticky box with an opaque
   background covers the top edge: more than about 10px tall and at least 90%
   of the width. The topbar does not qualify — it starts after the rail, so it
   is under 90% wide — which is why padding it never cured the blur. This
   strip does: a real element (not a pseudo-element), full width, opaque, at
   least 16px in the Home Screen app, and the rail and topbar sit below it
   through --tza-safe-top. Zero height in Safari, where the browser chrome is
   above the page. Below modals and the camera, which cover the screen. */
#tza-status-strip{
  position:fixed;top:0;left:0;right:0;height:var(--tza-safe-top);
  background:#fff;z-index:200;pointer-events:none;
}
@media (display-mode: standalone){
  /* The haze runs well below the status bar itself — down to about 50pt on
     the field iPads — so everything starts below that. */
  :root{--tza-safe-top:max(calc(env(safe-area-inset-top) + 26px), 50px)}
}
@media print{#tza-status-strip{display:none}}

/* ── Navigation rail — persistent, never collapses ──────────────────────── */
#rail{
  position:fixed;top:0;left:0;bottom:0;width:var(--tza-rail);z-index:120;
  background:var(--tza-indigo);display:flex;flex-direction:column;overflow:hidden;
  transition:width .18s ease;padding-top:var(--tza-safe-top);padding-bottom:env(safe-area-inset-bottom);
}
.rail-brand{
  height:76px;flex-shrink:0;background:none;
  border-bottom:1px solid rgba(255,255,255,.15);
  display:flex;align-items:center;justify-content:center;padding:0;
}
.rail-brand .rail-mark{width:34px;height:34px;display:block}
.rail-brand .rail-lockup{display:none}
.rail-items{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px 0;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.rail-item{
  width:100%;min-height:var(--tza-railitem);background:none;
  border-left:4px solid transparent;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  padding:8px 2px;text-decoration:none;font-family:var(--tza-sans);transition:background .12s;
}
.rail-item .ri-icon{font-size:26px;line-height:1}
.rail-item .ri-label{
  display:var(--tza-raillabel);font-size:10.5px;font-weight:600;letter-spacing:.02em;
  color:rgba(255,255,255,.72);text-align:center;line-height:1.2;
}
.rail-item:hover{background:rgba(255,255,255,.08)}
.rail-item.active{background:rgba(255,255,255,.16);border-left-color:var(--tza-accent)}
.rail-item.active .ri-label{color:#fff}
/* Wide labelled: the same buttons, laid on their side. */
html[data-rail="wide"] .rail-item{flex-direction:row;justify-content:flex-start;gap:14px;padding:8px 16px}
html[data-rail="wide"] .rail-item .ri-label{text-align:left;font-size:15px;font-weight:500}
html[data-rail="wide"] .rail-brand{justify-content:flex-start;padding:0 18px}
/* The rail is finally wide enough for the wordmark, so use the real lockup. */
html[data-rail="wide"] .rail-brand .rail-mark{display:none}
html[data-rail="wide"] .rail-brand .rail-lockup{display:block;width:100%;height:auto;max-height:40px}
.rail-more{
  min-height:76px;flex-shrink:0;background:none;border-top:1px solid rgba(255,255,255,.15);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  font-family:var(--tza-sans);
}
.rail-avatar{
  width:36px;height:36px;border-radius:999px;background:var(--tza-accent);color:#fff;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--tza-head);font-size:13px;font-weight:600;
}
.rail-more .ri-label{display:var(--tza-raillabel);font-size:10.5px;font-weight:600;color:rgba(255,255,255,.75)}
html[data-rail="wide"] .rail-more{flex-direction:row;gap:12px;justify-content:flex-start;padding:0 16px}

/* ── Module drawer — slides out from behind the rail ────────────────────── */
#drawer{
  position:fixed;top:0;bottom:0;left:var(--tza-rail);width:300px;max-width:calc(100vw - var(--tza-rail));
  background:var(--tza-indigo-hover);z-index:130;display:flex;flex-direction:column;overflow-y:auto;
  padding-top:var(--tza-safe-top);
  transform:translateX(-100%);visibility:hidden;transition:transform .18s ease,visibility .18s;
  box-shadow:24px 0 48px -12px rgba(14,18,48,.45);-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
}
#drawer.open{transform:translateX(0);visibility:visible}
/* The scrim starts where the drawer ends, so the rail stays tappable with the
   drawer open — you can jump straight to another tool without closing it. */
#drawer-scrim{position:fixed;inset:0;left:calc(var(--tza-rail) + 300px);background:rgba(14,18,48,.35);z-index:125;display:none}
#drawer-scrim.open{display:block}
.drawer-head{
  padding:20px 22px;border-bottom:1px solid rgba(255,255,255,.15);
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-shrink:0;
}
.drawer-name{font-family:var(--tza-head);font-size:15px;font-weight:600;color:#fff}
.drawer-role{font-size:12.5px;color:rgba(255,255,255,.6);text-transform:capitalize}
.drawer-close{width:44px;height:44px;border-radius:5px;background:rgba(255,255,255,.12);color:#fff;font-size:18px;flex-shrink:0}
.drawer-section{padding:18px 22px 6px;font-family:var(--tza-head);font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;font-weight:600;color:rgba(255,255,255,.5)}
.drawer-item{
  display:flex;align-items:center;gap:14px;width:100%;min-height:var(--tza-btn-sm);
  padding:0 22px;background:none;border-left:4px solid transparent;
  text-align:left;text-decoration:none;font-family:var(--tza-sans);
}
.drawer-item .di-icon{font-size:22px;width:28px;text-align:center;flex-shrink:0}
.drawer-item .di-label{font-size:16px;font-weight:500;color:rgba(255,255,255,.82)}
.drawer-item:hover{background:rgba(255,255,255,.08)}
.drawer-item.active{background:rgba(255,255,255,.16);border-left-color:var(--tza-accent)}
.drawer-item.active .di-label{color:#fff}
.drawer-foot{margin-top:auto;padding:18px 22px;flex-shrink:0}
.drawer-signout{
  display:flex;align-items:center;justify-content:center;width:100%;min-height:56px;
  border-radius:5px;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.25);
  color:#fff;font-size:15px;font-weight:600;text-decoration:none;
}

/* ── Topbar ─────────────────────────────────────────────────────────────── */
/* ── Role preview bar ────────────────────────────────────────────────────────
   The one place magenta is allowed to be a bulk surface: an admin who has
   taken their own rights away is the single most urgent thing on the screen,
   and it has to stay urgent on every page until they end it. Sticky above the
   topbar, and it prints on nothing. */
#viewas-bar{
  position:sticky;top:0;z-index:70;flex-shrink:0;
  background:var(--tza-accent);color:#fff;
  min-height:var(--tza-row);padding:calc(10px + var(--tza-safe-top)) 24px 10px;
  display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
}
.va-text{font-size:15px;font-weight:600;line-height:1.35;text-wrap:pretty}
.va-text strong{font-family:var(--tza-head)}
.va-exit{
  min-height:44px;padding:0 18px;border-radius:5px;flex-shrink:0;
  background:#fff;color:var(--tza-accent);border:none;
  font-family:var(--tza-sans);font-size:15px;font-weight:600;cursor:pointer;
}
/* Two sticky bars at top:0 would sit on top of each other, and the preview bar
   wraps to two lines on a narrow screen, so a fixed offset would be wrong as
   often as it was right. While the bar is there it is the one that sticks. */
#viewas-bar + #topbar{position:static;height:76px;padding-top:0}

/* The Home Screen app runs full screen (viewport-fit=cover, status bar
   black-translucent), so the iPad's status bar sits on top of the page. Every
   bar pinned to the top takes var(--tza-safe-top) as extra padding —
   zero in Safari, where the browser chrome already keeps it clear. */
#topbar{
  height:calc(76px + var(--tza-safe-top));flex-shrink:0;background:#fff;position:sticky;top:0;z-index:60;
  border-bottom:var(--tza-bw) solid var(--tza-line);
  padding:var(--tza-safe-top) 24px 0;display:flex;align-items:center;justify-content:space-between;gap:16px;
}
.tb-title{font-family:var(--tza-head);font-size:23px;font-weight:600;letter-spacing:-.01em;color:var(--tza-ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb-sub{font-size:12.5px;color:var(--tza-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb-status{
  display:flex;align-items:center;gap:8px;height:44px;padding:0 14px;border-radius:999px;
  background:var(--tza-green-bg);border:1px solid var(--tza-green);
  font-size:13px;font-weight:600;color:var(--tza-green);white-space:nowrap;
}
.tb-status .dot{width:10px;height:10px;border-radius:999px;background:var(--tza-green);display:block}
.tb-date{
  height:44px;padding:0 14px;display:flex;align-items:center;border-radius:5px;
  background:var(--tza-surface);border:var(--tza-bw) solid var(--tza-line);
  font-family:var(--tza-mono);font-size:13px;color:var(--tza-muted);white-space:nowrap;
}

/* ── Cards ──────────────────────────────────────────────────────────────── */
.card,.tza-card{
  background:#fff;border:var(--tza-bw) solid var(--tza-line);border-radius:12px;
  box-shadow:var(--tza-shadow);padding:24px;
}
.card-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:16px}
.card-inner{border:var(--tza-bw) solid var(--tza-line);border-radius:8px;padding:16px 18px}
/* Indigo wash — "Design so far", readings, payment terms. */
.panel-tint{background:var(--tza-tint);border:var(--tza-bw) solid var(--tza-tint-line);border-radius:12px;padding:20px 22px}
/* Magenta-ruled callout — the one thing on the screen that wants attention. */
.callout{
  background:#fff;border:var(--tza-bw) solid var(--tza-line);border-radius:8px;padding:20px;
  box-shadow:inset 3px 0 0 var(--tza-accent);
}
.callout-warn{background:var(--tza-amber-bg);border-color:var(--tza-amber-line)}
.callout-warn .callout-figure{font-family:var(--tza-mono);font-size:26px;font-weight:600;color:var(--tza-amber-line);font-variant-numeric:tabular-nums}

/* Divider strip of figures — job facts, readings, KPIs, fleet facts. */
.factstrip{display:flex;flex-wrap:wrap;gap:14px 0}
.factstrip>*{flex:1;min-width:140px;padding:0 22px;border-left:1px solid var(--tza-line)}
.fact-label{font-family:var(--tza-head);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;font-weight:600;color:var(--tza-faint)}
.fact-value{font-family:var(--tza-mono);font-size:17px;font-weight:600;color:var(--tza-ink);margin-top:8px;font-variant-numeric:tabular-nums}
.fact-value.lg{font-size:26px}

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn{
  height:var(--tza-btn);padding:0 28px;border-radius:5px;
  font-family:var(--tza-sans);font-size:17px;font-weight:600;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  transition:background .12s,border-color .12s;text-decoration:none;white-space:nowrap;
}
.btn-primary{background:var(--tza-indigo);color:#fff}
.btn-primary:hover{background:var(--tza-indigo-hover)}
.btn-secondary{background:#fff;color:var(--tza-indigo);border:var(--tza-sigbw) solid var(--tza-indigo)}
.btn-secondary:hover{background:var(--tza-tint)}
.btn-quiet{background:#fff;color:var(--tza-body);border:var(--tza-bw) solid var(--tza-inline)}
.btn-quiet:hover{background:var(--tza-surface)}
.btn-accent{background:var(--tza-accent);color:#fff}
.btn-accent:hover{background:var(--tza-accent-hover)}
.btn-danger{background:var(--tza-red);color:#fff}
.btn-danger:hover{background:#8A1616}
.btn-sm{height:var(--tza-btn-xs);padding:0 22px;font-size:16px}
.btn-block{width:100%}
.btn:disabled,.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn-icon{width:var(--tza-btn);padding:0;font-size:20px}
/* A single-glyph button — delete, dismiss — should be square, not a wide
   button with a small icon adrift in it. */
.btn-icon.btn-sm{width:var(--tza-btn-xs);font-size:18px}

/* ── Pills & chips ──────────────────────────────────────────────────────── */
/* gap, because a flex container drops the plain space between a text run and
   a child element: "Submitted <span>10 Oct</span>" rendered as "Submitted10 Oct". */
.chip,.badge,.pill{
  display:inline-flex;align-items:center;justify-content:center;gap:.35em;height:36px;padding:0 14px;
  border-radius:999px;font-size:13px;font-weight:600;background:var(--tza-tint);color:var(--tza-indigo);
  white-space:nowrap;
}
.chip-sm{height:30px;padding:0 12px;font-size:12.5px}
.chip-green,.badge-green{background:var(--tza-green-bg);color:var(--tza-green)}
.chip-amber,.badge-orange,.badge-yellow{background:var(--tza-amber-bg);color:var(--tza-amber)}
.chip-red,.badge-red{background:var(--tza-red-bg);color:var(--tza-red)}
.chip-indigo,.badge-blue{background:var(--tza-tint);color:var(--tza-indigo)}
.chip-grey,.badge-gray{background:var(--tza-surface);color:var(--tza-muted);border:1px solid var(--tza-line)}
.chip-fixed{width:120px}

/* Filter pills — projects, products, CRM. */
.filter-pill{
  height:52px;padding:0 20px;border-radius:999px;background:#fff;color:var(--tza-body);
  border:1px solid var(--tza-line);font-size:14px;font-weight:600;font-family:var(--tza-sans);
}
.filter-pill.active{background:var(--tza-indigo);color:#fff;border-color:var(--tza-indigo)}

/* ── Forms ──────────────────────────────────────────────────────────────── */
.form-group{margin-bottom:18px}
.form-label{display:block;font-size:13px;font-weight:600;color:var(--tza-body);margin-bottom:8px;letter-spacing:0;text-transform:none}
.form-input,.form-select,input[type=text],input[type=email],input[type=password],input[type=number],input[type=date],input[type=tel],input[type=search],select,textarea{
  width:100%;height:var(--tza-btn-sm);padding:0 16px;
  border:var(--tza-inbw) solid var(--tza-inline);border-radius:5px;
  font-family:var(--tza-sans);font-size:17px;color:var(--tza-ink);background:#fff;
}
/* Safari sizes a date input to its own wide intrinsic width and centres the
   value; in a two-column modal that pushed the dialog sideways into a scrollbar. */
/* With appearance:none Safari stops centring the value vertically, so the line
   box is set to the inner height (border-box, so less both borders). */
input[type=date]{-webkit-appearance:none;appearance:none;min-width:0;display:block;
  line-height:calc(var(--tza-btn-sm) - 2 * var(--tza-inbw))}
input[type=date]::-webkit-date-and-time-value{text-align:left;margin:0;line-height:inherit}
textarea,textarea.form-input{height:auto;min-height:132px;padding:14px 16px;line-height:1.5;resize:vertical}
.form-select,select{appearance:none;padding-right:40px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23525A72' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center;background-size:12px}
.form-input:focus,.form-select:focus,input:focus,select:focus,textarea:focus{border-color:var(--tza-indigo)}
.form-static{
  height:var(--tza-btn);padding:0 18px;display:flex;align-items:center;
  border:var(--tza-inbw) solid var(--tza-inline);border-radius:5px;font-size:17px;color:var(--tza-ink);background:#fff;
}
.field-error{font-size:13px;color:var(--tza-red);margin-top:6px}

/* ── Tappable option / checklist rows ───────────────────────────────────────
   The whole row is the target, not a 20px checkbox in the corner of it. */
.opt-row{
  display:flex;align-items:center;gap:18px;width:100%;min-height:var(--tza-row-lg);
  padding:18px 20px;border:2px solid var(--tza-line);background:#fff;border-radius:8px;
  text-align:left;font-family:var(--tza-sans);
}
.opt-row.selected{border-color:var(--tza-indigo);background:var(--tza-tint)}
.opt-radio{
  width:32px;height:32px;border-radius:999px;border:2px solid var(--tza-inline);background:#fff;
  display:flex;align-items:center;justify-content:center;color:#fff;font-size:17px;font-weight:700;flex-shrink:0;
}
.opt-row.selected .opt-radio{border-color:var(--tza-indigo);background:var(--tza-indigo)}
.opt-title{display:block;font-family:var(--tza-head);font-size:18px;font-weight:600;color:var(--tza-ink)}
.opt-desc{display:block;font-size:14px;color:var(--tza-muted);margin-top:3px;text-wrap:pretty}
.opt-price{font-family:var(--tza-mono);font-size:16px;font-weight:600;color:var(--tza-ink);font-variant-numeric:tabular-nums;flex-shrink:0}

.check-row{
  display:flex;align-items:center;gap:16px;width:100%;min-height:var(--tza-row);
  padding:14px 16px;background:#fff;border:none;border-bottom:1px solid var(--tza-hair);
  text-align:left;font-family:var(--tza-sans);
}
.check-row:last-child{border-bottom:none}
.check-box{
  width:36px;height:36px;border-radius:5px;border:2px solid var(--tza-inline);background:#fff;
  color:#fff;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:700;flex-shrink:0;
}
.check-row.checked{background:var(--tza-green-bg)}
.check-row.checked .check-box{border-color:var(--tza-green);background:var(--tza-green)}
.check-label{flex:1;font-size:17px;line-height:1.4;color:var(--tza-ink);text-wrap:pretty}
/* Legacy checklist markup, resized to match. */
.checklist-item{display:flex;align-items:center;gap:16px;padding:14px 2px;min-height:var(--tza-row);border-bottom:1px solid var(--tza-hair)}
.checklist-item:last-child{border-bottom:none}
.checklist-label{flex:1;font-size:17px;line-height:1.4;color:var(--tza-ink);cursor:pointer}
input[type=checkbox]{width:28px;height:28px;flex-shrink:0;accent-color:var(--tza-indigo);cursor:pointer;touch-action:manipulation}

/* ── Data rows presented as cards ───────────────────────────────────────── */
.rowcard{
  background:#fff;border:var(--tza-bw) solid var(--tza-line);border-radius:12px;
  box-shadow:var(--tza-shadow);padding:18px 20px;min-height:var(--tza-row-lg);width:100%;
  display:flex;align-items:center;gap:20px;flex-wrap:wrap;text-align:left;
  font-family:var(--tza-sans);text-decoration:none;
}
a.rowcard,button.rowcard{transition:border-color .12s}
a.rowcard:hover,button.rowcard:hover{border-color:var(--tza-indigo)}
.rowcard.warn{border-color:var(--tza-amber-line)}
.rowcard.bad{border-color:var(--tza-red)}
.rowcard.active{border-color:var(--tza-indigo);box-shadow:inset 0 0 0 1px var(--tza-indigo)}
.rowcard-ref{font-family:var(--tza-mono);font-size:15px;font-weight:600;color:var(--tza-indigo);display:block}
.rowcard-title{font-family:var(--tza-head);font-size:17px;font-weight:600;color:var(--tza-ink);display:block}
.rowcard-meta{font-size:14px;color:var(--tza-muted);margin-top:3px;display:block}
.rowcard-num{font-family:var(--tza-mono);font-size:19px;font-weight:600;color:var(--tza-ink);font-variant-numeric:tabular-nums;flex-shrink:0}
.stack{display:flex;flex-direction:column;gap:12px}
.stack-lg{display:flex;flex-direction:column;gap:20px}

/* ── Tables ─────────────────────────────────────────────────────────────── */
table{width:100%;border-collapse:collapse}
th{
  text-align:left;font-family:var(--tza-head);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;font-weight:600;color:var(--tza-faint);
  padding:0 12px 10px;border-bottom:2px solid var(--tza-ink);
}
td{padding:16px 12px;font-size:16px;color:var(--tza-ink);border-bottom:1px solid var(--tza-hair)}
td.num,th.num{text-align:right;font-family:var(--tza-mono);font-variant-numeric:tabular-nums}
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* ── Tabs — two large buttons, not small pills ──────────────────────────── */
.tabs{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:20px;border:none}
.tab{
  height:56px;padding:0 24px;border-radius:5px;background:#fff;color:var(--tza-body);
  border:1px solid var(--tza-line);font-size:16px;font-weight:600;font-family:var(--tza-sans);
  display:inline-flex;align-items:center;white-space:nowrap;
}
.tab.active{background:var(--tza-indigo);color:#fff;border-color:var(--tza-indigo)}
a.tab{text-decoration:none}
.tab:disabled{opacity:.55;cursor:default}

/* ── Step / wizard header ───────────────────────────────────────────────── */
.wizard-steps{display:flex;align-items:center;flex-wrap:wrap;margin:0}
.wizard-step{display:flex;align-items:center;gap:10px;padding:6px 0;flex-shrink:0}
/* Built by wizardStepsHtml(): each step is a button. Back is always open;
   forward only as far as the required answers before it allow, and a step
   out of reach is disabled rather than hidden, so the whole path stays in view. */
button.wizard-step{
  background:none;border:none;font:inherit;text-align:left;cursor:pointer;
  min-height:var(--tza-btn-xs);padding:0 4px;border-radius:8px;
}
button.wizard-step:disabled{cursor:default}
button.wizard-step:not(:disabled):not(.active):hover .wizard-step-label{color:var(--tza-indigo)}
button.wizard-step:focus-visible{outline:2px solid var(--tza-indigo);outline-offset:2px}
.wizard-step-num{
  width:44px;height:44px;border-radius:8px;display:flex;align-items:center;justify-content:center;
  font-family:var(--tza-head);font-weight:600;font-size:16px;flex-shrink:0;
  background:var(--tza-surface);color:var(--tza-faint);border:1px solid var(--tza-line);
}
.wizard-step-label{font-size:14px;color:var(--tza-faint);line-height:1.3}
.wizard-step.active .wizard-step-num{background:var(--tza-indigo);color:#fff;border-color:var(--tza-indigo)}
.wizard-step.active .wizard-step-label{color:var(--tza-ink);font-weight:600}
.wizard-step.done .wizard-step-num{background:var(--tza-green);color:#fff;border-color:var(--tza-green)}
.wizard-step.done .wizard-step-label{color:var(--tza-body);font-weight:500}
.wizard-divider{flex:1;min-width:8px;height:3px;margin:0 10px;background:var(--tza-line)}
.wizard-divider.done{background:var(--tza-green)}

/* ── Milestone tracker ──────────────────────────────────────────────────── */
.milestone-item{display:flex;gap:18px;align-items:stretch}
.milestone-connector{display:flex;flex-direction:column;align-items:center;flex-shrink:0}
.milestone-dot{
  width:44px;height:44px;border-radius:8px;display:flex;align-items:center;justify-content:center;
  font-family:var(--tza-head);font-size:17px;font-weight:600;flex-shrink:0;
  background:var(--tza-surface);color:var(--tza-faint);border:2px solid var(--tza-line);
}
.milestone-dot.done{background:var(--tza-green);color:#fff;border-color:var(--tza-green)}
.milestone-dot.active{background:var(--tza-indigo);color:#fff;border-color:var(--tza-indigo)}
.milestone-line{flex:1;width:3px;background:var(--tza-line);min-height:16px}
.milestone-line.done{background:var(--tza-green)}
.milestone-content{flex:1;min-width:0;padding-bottom:22px}
.milestone-title{font-family:var(--tza-head);font-size:18px;font-weight:600;color:var(--tza-ink);line-height:1.3}
.milestone-item.pending .milestone-title{color:var(--tza-faint)}
/* The project's stage list: title and status on the left, the module that
   stage is worked in on the right. The symbol is a button where the stage
   can be ticked by hand. */
.milestone-row{display:flex;align-items:flex-start;gap:14px;flex-wrap:wrap;padding-bottom:16px}
.milestone-open{flex-shrink:0;margin-left:auto}
button.milestone-tick{cursor:pointer;font:inherit;font-family:var(--tza-head);font-weight:600;font-size:17px;padding:0}
button.milestone-tick:not(.done):not(.active):hover{border-color:var(--tza-indigo);color:var(--tza-indigo)}
.milestone-meta{font-size:14px;color:var(--tza-faint);margin-top:4px}

/* ── Progress ───────────────────────────────────────────────────────────── */
.progress-bar-track{background:var(--tza-hair);border-radius:999px;height:12px;overflow:hidden}
.progress-bar-fill{height:100%;background:var(--tza-green);border-radius:999px;transition:width .3s}
.progress-bar-fill.accent{background:var(--tza-accent)}

/* ── Alerts ─────────────────────────────────────────────────────────────── */
.alert{
  padding:18px 20px;border-radius:8px;font-size:15px;line-height:1.5;margin-bottom:18px;
  display:flex;gap:16px;align-items:center;flex-wrap:wrap;border:var(--tza-bw) solid;
}
.alert-warning{background:var(--tza-amber-bg);border-color:var(--tza-amber-line);color:var(--tza-body);box-shadow:inset 3px 0 0 var(--tza-accent)}
.alert-error{background:var(--tza-red-bg);border-color:var(--tza-red);color:var(--tza-body);box-shadow:inset 3px 0 0 var(--tza-red)}
.alert-success{background:var(--tza-green-bg);border-color:var(--tza-green);color:var(--tza-body)}
.alert-info{background:var(--tza-tint);border-color:var(--tza-tint-line);color:var(--tza-body)}

/* ── Signature field (SIG-001, rebuilt) ─────────────────────────────────────
   The old pad was 150px behind a dashed grey border with no baseline and no
   signed state — customers could not tell it was a place to sign. Solid indigo
   border, a dashed line to sign above, and a status chip that flips on the
   first stroke. */
.sig-card{background:#fff;border:var(--tza-bw) solid var(--tza-line);border-radius:12px;box-shadow:var(--tza-shadow);padding:24px}
.sig-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:6px}
.sig-heading{font-family:var(--tza-head);font-size:23px;font-weight:600;letter-spacing:-.01em;color:var(--tza-ink)}
.sig-help{font-size:14px;color:var(--tza-muted);margin-top:6px;max-width:60ch}
.sig-status{
  height:44px;display:inline-flex;align-items:center;gap:8px;padding:0 16px;border-radius:999px;
  background:var(--tza-surface);border:var(--tza-bw) solid var(--tza-inline);
  font-size:13px;font-weight:600;color:var(--tza-muted);flex-shrink:0;
}
.sig-status.signed{background:var(--tza-green-bg);border-color:var(--tza-green);color:var(--tza-green)}
.sig-box{
  position:relative;margin-top:20px;border:var(--tza-sigbw) solid var(--tza-indigo);
  border-radius:8px;background:#fff;overflow:hidden;
}
.sig-box::before{
  content:'';position:absolute;left:0;right:0;bottom:74px;height:0;
  border-top:2px dashed var(--tza-inline);pointer-events:none;
}
.sig-box::after{
  content:'Sign above the line';position:absolute;right:20px;bottom:44px;
  font-family:var(--tza-head);font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;
  font-weight:600;color:var(--tza-ghost);pointer-events:none;
}
.sig-pad{width:100%;height:var(--tza-sig);display:block;touch-action:none;cursor:crosshair;position:relative;z-index:2;background:transparent}
/* Commissioning runs two pads on one screen, so they sit a size down. */
.sig-card.compact .sig-box::before{bottom:64px}
.sig-card.compact .sig-box::after{bottom:36px}
.sig-card.compact .sig-pad{height:var(--tza-sig-sm)}
.sig-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:18px}
.sig-meta{margin-left:auto;font-family:var(--tza-mono);font-size:13px;color:var(--tza-faint);line-height:1.5;text-align:right}

/* ── Dashboard ──────────────────────────────────────────────────────────── */
.dash{display:flex;gap:20px;flex-wrap:wrap;align-items:flex-start}
.dash-main{flex:1;min-width:420px;display:flex;flex-direction:column;gap:20px}
.dash-side{width:340px;flex-shrink:0;display:flex;flex-direction:column;gap:20px}
.jobband{background:var(--tza-indigo);border-radius:12px;padding:26px 28px 24px;color:#fff}
.jobband .eyebrow{color:rgba(255,255,255,.65)}
.jobband-name{font-family:var(--tza-head);font-size:32px;line-height:1.15;letter-spacing:-.015em;font-weight:600;color:#fff}
.jobband-line{font-size:16px;color:rgba(255,255,255,.78);margin-top:4px}
.jobband .factstrip{margin-top:26px;padding-top:22px;border-top:1px solid rgba(255,255,255,.22)}
.jobband .factstrip>*{border-left-color:rgba(255,255,255,.22);min-width:118px;padding:0 18px}
.jobband .fact-label{color:rgba(255,255,255,.6)}
.jobband .fact-value{color:#fff}
.jobband-btn-solid{height:var(--tza-btn-sm);padding:0 24px;border-radius:5px;background:#fff;color:var(--tza-indigo);font-size:16px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;gap:10px;text-decoration:none;font-family:var(--tza-sans)}
.jobband-btn-ghost{height:var(--tza-btn-sm);padding:0 24px;border-radius:5px;background:transparent;color:#fff;border:2px solid rgba(255,255,255,.45);font-size:16px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;gap:10px;text-decoration:none;font-family:var(--tza-sans)}
.jobband-resume{display:flex;align-items:center;gap:18px;margin-top:24px;flex-wrap:wrap}
.jobband-progress{height:10px;border-radius:999px;background:rgba(255,255,255,.2);overflow:hidden}
.jobband-progress>span{display:block;height:100%;background:var(--tza-accent);border-radius:999px}

.toolgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:16px}
.tool-card{
  min-height:170px;background:#fff;border:1px solid var(--tza-line);border-radius:12px;
  box-shadow:var(--tza-shadow);padding:22px;text-decoration:none;
  display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;gap:12px;
  font-family:var(--tza-sans);text-align:left;transition:border-color .12s;
}
.tool-card:hover{border-color:var(--tza-indigo)}
.tool-card .tc-icon{font-size:40px;line-height:1}
.tool-card .tc-label{display:block;font-family:var(--tza-head);font-size:19px;font-weight:600;color:var(--tza-ink);line-height:1.25}
.tool-card .tc-meta{display:block;font-size:13px;color:var(--tza-faint);margin-top:6px}
.tool-card.urgent{background:var(--tza-accent-tint);border-color:#EBC3DE}
.tool-card.urgent .tc-meta{color:var(--tza-accent-hover);font-weight:600}

/* ── Calendar ───────────────────────────────────────────────────────────── */
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}
.cal-dow{text-align:center;font-family:var(--tza-head);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;font-weight:600;color:var(--tza-faint);padding-bottom:8px;border-bottom:2px solid var(--tza-ink)}
.cal-cell{min-height:108px;border:1px solid var(--tza-line);border-radius:8px;padding:10px;background:#fff;display:flex;flex-direction:column;gap:6px}
.cal-cell.muted{background:var(--tza-surface);border-color:var(--tza-hair)}
.cal-cell.today{border-color:var(--tza-indigo);border-width:2px;background:var(--tza-tint)}
.cal-num{font-family:var(--tza-mono);font-size:15px;font-weight:500;color:var(--tza-faint);font-variant-numeric:tabular-nums}
.cal-cell.today .cal-num,.cal-cell:not(.muted) .cal-num{color:var(--tza-ink)}
.cal-cell.today .cal-num{font-weight:700;color:var(--tza-indigo)}
.cal-event{font-size:12.5px;font-weight:600;line-height:1.3;padding:6px 8px;border-radius:5px;background:var(--tza-tint);color:var(--tza-indigo);text-wrap:pretty;text-decoration:none;display:block}

/* ── Timeline (activity log, comms log) ─────────────────────────────────── */
.timeline-row{display:flex;gap:18px;padding:16px 0;border-bottom:1px solid var(--tza-hair)}
.timeline-row:last-child{border-bottom:none}
.timeline-ts{width:120px;flex-shrink:0;font-family:var(--tza-mono);font-size:13px;color:var(--tza-faint);line-height:1.5}
.timeline-main{flex:1;min-width:0}
.timeline-text{font-size:16px;color:var(--tza-ink);line-height:1.45;text-wrap:pretty}
.timeline-detail{font-size:13.5px;color:var(--tza-faint);margin-top:4px}

/* ── Pipeline bars ──────────────────────────────────────────────────────── */
.pipe-row{display:flex;align-items:center;gap:14px;min-height:56px}
.pipe-label{width:120px;flex-shrink:0;font-size:15px;color:var(--tza-body)}
.pipe-track{flex:1;height:10px;border-radius:999px;background:var(--tza-hair);overflow:hidden}
.pipe-track>span{display:block;height:100%;background:var(--tza-indigo);border-radius:999px}
.pipe-count{width:28px;text-align:right;font-family:var(--tza-mono);font-size:15px;font-weight:600;color:var(--tza-ink);font-variant-numeric:tabular-nums}

/* ── Login ──────────────────────────────────────────────────────────────── */
#login-page{min-height:100vh;background:#fff;display:flex;align-items:center;justify-content:center;padding:48px;position:relative}
.login-card{width:100%;max-width:420px;display:flex;flex-direction:column;align-items:stretch}
.login-logo{margin:0 auto 48px;display:block;width:250px;max-width:100%;height:auto}
.login-foot{text-align:center;font-size:12.5px;color:var(--tza-faint);margin-top:40px;font-family:var(--tza-mono)}

/* ── Modals ─────────────────────────────────────────────────────────────────
   Logistics' Receive and Issue dialogs had markup but no stylesheet at all —
   .modal-overlay / .modal were never defined, so "open the dialog" flipped
   display:none to display:flex and dumped the form inline at the foot of the
   page. */
.modal-overlay{position:fixed;inset:0;background:rgba(14,18,48,.45);z-index:300;display:none;align-items:center;justify-content:center;padding:calc(24px + var(--tza-safe-top)) 24px 24px;overflow-y:auto}
.modal-overlay.open{display:flex}
/* The close X every dialog carries top right, put there by initModalCloseButtons()
   in app.js. The dialog is what scrolls, so the X is sticky inside it and stays
   in the corner however far down the form goes. Its negative bottom margin
   takes it out of the flow; the first thing after it keeps clear of it. */
.modal-x{position:sticky;top:10px;z-index:2;width:44px;height:44px;margin:-14px -14px -30px auto;border-radius:6px;border:0;background:var(--tza-hair);
  color:var(--tza-ink);font-size:20px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.modal > .modal-x + *{padding-right:44px}
.modal-x:hover{background:var(--tza-line)}
.modal{background:#fff;border-radius:12px;border:var(--tza-bw) solid var(--tza-line);box-shadow:0 28px 56px -18px rgba(14,18,48,.4);padding:24px;width:100%;max-width:520px;max-height:90vh;overflow-y:auto}

/* ── Toast ──────────────────────────────────────────────────────────────── */
#toast-host{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:400;display:flex;flex-direction:column;gap:10px;align-items:center}

/* ── Misc kept from the old sheet, re-typeset ───────────────────────────── */
.page-header{margin-bottom:24px}
.grid-2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px}
/* A grid of form fields spaces them with its gap alone. With the field's own
   margin as well, a grid collapsed to one column (iPad portrait) put 36px
   between the two fields of a row and 18px between rows. */
.grid-2>.form-group,.grid-3>.form-group{margin-bottom:0}
.grid-2:has(>.form-group),.grid-3:has(>.form-group){margin-bottom:18px}
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
.autogrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:16px}
.flex-between{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}
.flex-gap{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.toolbar{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:18px}
.toolbar .form-input{flex:1;min-width:280px;height:var(--tza-btn-sm)}
.text-green{color:var(--tza-green)}.text-primary{color:var(--tza-indigo)}.text-navy{color:var(--tza-indigo)}
.text-accent{color:var(--tza-accent)}.text-red{color:var(--tza-red)}.text-gray{color:var(--tza-faint)}
.font-bold{font-weight:700}
.mt-2{margin-top:8px}.mt-4{margin-top:16px}
.hidden{display:none!important}
.loading{text-align:center;padding:48px;color:var(--tza-faint);font-size:16px}
.section-divider{border:none;border-top:1px solid var(--tza-line);margin:24px 0}
.stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:24px}
.stat-card{background:#fff;border-radius:12px;border:var(--tza-bw) solid var(--tza-line);box-shadow:var(--tza-shadow);padding:22px}
.stat-value{font-family:var(--tza-mono);font-size:26px;font-weight:600;color:var(--tza-ink);font-variant-numeric:tabular-nums}
.stat-label{font-size:13px;color:var(--tza-faint);margin-top:8px}
.stat-delta{font-size:13px;margin-top:6px;color:var(--tza-faint)}
.import-zone{border:2px dashed var(--tza-inline);border-radius:12px;padding:32px;text-align:center;background:var(--tza-surface)}
.import-zone:hover,.import-zone.drag-over{border-color:var(--tza-indigo);background:var(--tza-tint)}
.import-zone input[type=file]{display:none}
.stock-bar{height:8px;border-radius:999px;background:var(--tza-hair);overflow:hidden;margin-top:6px;width:100px}
.stock-bar-fill{height:100%;border-radius:999px;background:var(--tza-green)}
.stock-low .stock-bar-fill{background:var(--tza-amber-line)}
.stock-out .stock-bar-fill{background:var(--tza-red)}
.inv-alert{display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 14px;border-radius:999px;font-size:13px;font-weight:600}
.inv-alert.ok{background:var(--tza-green-bg);color:var(--tza-green)}
.inv-alert.low{background:var(--tza-amber-bg);color:var(--tza-amber)}
.inv-alert.out{background:var(--tza-red-bg);color:var(--tza-red)}
.mv-in{color:var(--tza-green);font-weight:600}
.mv-out{color:var(--tza-red);font-weight:600}
.tgl{position:relative;display:inline-block;width:56px;height:32px;flex-shrink:0}
.tgl input{opacity:0;width:0;height:0;position:absolute}
.tgl-track{position:absolute;cursor:pointer;inset:0;background:var(--tza-inline);border-radius:999px;transition:.2s;touch-action:manipulation}
.tgl-track:before{position:absolute;content:'';height:24px;width:24px;left:4px;bottom:4px;background:#fff;border-radius:50%;transition:.2s;box-shadow:0 1px 3px rgba(14,18,48,.25)}
input:checked+.tgl-track{background:var(--tza-green)}
input:checked+.tgl-track:before{transform:translateX(24px)}
.tgl input:disabled+.tgl-track{opacity:.4;cursor:not-allowed}

/* Kanban survives for anything that still drags; retuned for touch. */
.kanban{display:flex;gap:16px;overflow-x:auto;padding-bottom:12px;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch}
.kanban-col{flex-shrink:0;width:260px;background:var(--tza-surface);border:var(--tza-bw) solid var(--tza-line);border-radius:12px;padding:14px;scroll-snap-align:start}
.kanban-col-header{font-family:var(--tza-head);font-size:13px;font-weight:600;color:var(--tza-ink);margin-bottom:10px;display:flex;justify-content:space-between;align-items:center}
.kanban-card{background:#fff;border-radius:8px;border:1px solid var(--tza-line);padding:14px;margin-bottom:10px;min-height:72px;font-size:15px}
.kanban-card:hover{border-color:var(--tza-indigo)}
.kanban-card .proj-name{font-weight:600;color:var(--tza-ink);margin-bottom:4px}
.kanban-card .proj-meta{color:var(--tza-faint);font-size:13px}

/* ── Job Log ────────────────────────────────────────────────────────────────
   Laid out as a chat, because that is what it replaced and what everyone on
   the team already knows how to read: oldest at the top, newest at the bottom
   nearest the composer, your own messages on the right, a reply carrying a
   quote of what it answers rather than sitting indented under it.

   Used outdoors, on the screens Sunlight and Gloved hands exist for, so every
   control takes its height from the field-mode variables. A hardcoded 44px
   button in this module is a bug on a Marsabit rooftop.

   An instruction is drawn with the magenta rule the callout already uses — the
   one thing on the screen that wants attention. Nothing here invents a colour,
   and stage-style per-kind hues are not coming back. */

.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

.jl-panel{
  background:#fff;border:var(--tza-bw) solid var(--tza-line);border-radius:12px;
  box-shadow:var(--tza-shadow);overflow:hidden;display:flex;flex-direction:column;
}
/* The conversation scrolls in here, not the page, so the composer never leaves
   the screen. Capped rather than stretched: a thread is read from the bottom. */
.jl-scroll{
  height:min(58vh,620px);overflow-y:auto;-webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;background:var(--tza-surface);padding:18px 18px 8px;
}

.jl-loading,.jl-empty{
  padding:28px 20px;text-align:center;color:var(--tza-faint);font-size:15px;
  border:var(--tza-bw) dashed var(--tza-line);border-radius:12px;text-wrap:pretty;
  background:#fff;
}
.jl-older{display:flex;justify-content:center;margin-bottom:14px}

/* Day separator, and the "Unread" rule that works the same way. */
.jl-daysep{display:flex;justify-content:center;margin:16px 0 12px}
.jl-daysep span{
  background:#fff;border:var(--tza-bw) solid var(--tza-line);border-radius:999px;
  padding:5px 16px;font-size:12.5px;font-weight:600;color:var(--tza-muted);
}
.jl-newsep span{background:var(--tza-accent);border-color:var(--tza-accent);color:#fff}

/* ── Bubbles ───────────────────────────────────────────────────────────── */
.jl-row{display:flex;margin-bottom:8px}
.jl-row.jl-mine{justify-content:flex-end}
.jl-bubble{
  max-width:min(78%,620px);padding:10px 14px;border-radius:12px 12px 12px 4px;
  background:#fff;border:var(--tza-bw) solid var(--tza-line);box-shadow:var(--tza-shadow);
  min-width:120px;
}
/* Your own messages: the indigo wash already used for "mine" surfaces, and the
   tail on the other corner. No second brand colour, no green. */
.jl-mine .jl-bubble{background:var(--tza-tint);border-color:var(--tza-tint-line);border-radius:12px 12px 4px 12px}
.jl-row.jl-instruction .jl-bubble{background:var(--tza-accent-tint);border-color:var(--tza-tint-line);box-shadow:inset 3px 0 0 var(--tza-accent)}
.jl-row[data-jl-unread] .jl-bubble{border-left:4px solid var(--tza-indigo)}
.jl-row.jl-flash .jl-bubble{outline:3px solid var(--tza-accent);outline-offset:2px}
.jl-eyebrow{color:var(--tza-accent);margin-bottom:6px}
/* WhatsApp colours the sender's name and shows it once per run, not on every
   message. jlRender() decides the "once"; this is only how it looks. */
.jl-author{font-family:var(--tza-head);font-size:13.5px;font-weight:600;color:var(--tza-indigo);margin-bottom:4px}
.jl-body{font-size:16px;line-height:1.45;color:var(--tza-ink);text-wrap:pretty;overflow-wrap:anywhere}
.jl-removed{color:var(--tza-faint);font-style:italic;display:flex;gap:12px;align-items:baseline}

/* A reply quotes what it answers, inside its own bubble — tapping it jumps. */
.jl-quote{
  display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;
  background:rgba(38,56,125,.06);border:none;border-left:3px solid var(--tza-indigo);
  border-radius:5px;padding:8px 12px;margin-bottom:8px;font-family:var(--tza-sans);
}
/* Muted, not indigo. The sender's name directly above is indigo, and two
   indigo lines stacked read as one — you could not tell who wrote the message
   from who wrote the thing it answers. The left rule and the tint are what say
   "quote"; the colour does not have to as well. */
.jl-quote-author{font-size:12px;font-weight:600;color:var(--tza-muted);letter-spacing:.02em}
.jl-quote-body{font-size:13.5px;color:var(--tza-faint);overflow-wrap:anywhere;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* The line under the message: actions on the left, time on the right, the way
   a chat puts the clock in the corner of the bubble. */
.jl-foot{display:flex;align-items:center;gap:10px;margin-top:4px}
.jl-actions{display:flex;gap:2px;margin-right:auto}
.jl-action{
  background:none;border:none;padding:6px 8px;font-family:var(--tza-sans);
  font-size:12.5px;font-weight:600;color:var(--tza-faint);border-radius:5px;
}
.jl-action:hover{background:rgba(38,56,125,.08);color:var(--tza-indigo)}
.jl-clock{font-size:11.5px;color:var(--tza-faint);margin-left:auto;flex-shrink:0}
.jl-edited{font-size:11.5px;color:var(--tza-ghost)}
.jl-seen{margin-top:6px;font-size:12px;color:var(--tza-green)}
.jl-seen.jl-unseen{color:var(--tza-faint)}

/* Thumbnail grid. Tile size comes from --tza-thumb, so gloved hands get a
   bigger target here exactly as they do everywhere else. */
.jl-photos{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:8px}
.jl-thumb{
  /* Block-level whatever the element: an <a> tile is inline by default, and
     an inline box ignores width and height, so its photo drew at full size. */
  display:block;width:var(--tza-thumb);height:var(--tza-thumb);padding:0;border-radius:8px;overflow:hidden;
  border:var(--tza-bw) solid var(--tza-line);background:var(--tza-surface);flex-shrink:0;
}
.jl-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.jl-feed-row .jl-thumb{width:var(--tza-row);height:var(--tza-row)}
.jl-thumb:hover{border-color:var(--tza-indigo)}
.jl-edit-box{min-height:120px}
.jl-edit-actions{display:flex;gap:10px;margin-top:10px;flex-wrap:wrap}

/* A photo still uploading: the same tile, dimmed, with a spinner over it, so a
   burst of shots reads as a row of photos rather than a stack of status rows.
   A failed upload drops back to the tray row, which has room for the reason. */
.ph-pending{
  position:relative;display:inline-block;width:var(--tza-thumb);height:var(--tza-thumb);
  border-radius:8px;overflow:hidden;border:var(--tza-bw) solid var(--tza-line);flex-shrink:0;
}
.ph-pending img{width:100%;height:100%;object-fit:cover;display:block;opacity:.45}
.ph-pending::after{
  content:"";position:absolute;top:50%;left:50%;width:22px;height:22px;margin:-11px 0 0 -11px;
  border:3px solid var(--tza-indigo);border-right-color:transparent;border-radius:50%;
  animation:ph-spin .8s linear infinite;
}
@keyframes ph-spin{to{transform:rotate(360deg)}}

/* ── In-app camera (openMultiCamera in app.js) ─────────────────────────── */
/* Full screen and black, like the iPad's own camera: the viewfinder is the
   whole screen, the shutter sits where a thumb rests, and the shots taken so
   far run along the bottom. Above the lightbox and below toasts. */
#mc-overlay{position:fixed;inset:0;z-index:350;background:#000;display:flex;flex-direction:column;color:#fff}
#mc-overlay video{flex:1;min-height:0;width:100%;object-fit:contain;background:#000}
.mc-top{display:flex;align-items:center;gap:14px;padding:calc(14px + var(--tza-safe-top)) 18px 14px;font-family:var(--tza-sans)}
.mc-title{flex:1;min-width:0;font-size:17px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mc-bar{display:flex;align-items:center;gap:18px;padding:14px 18px calc(22px + env(safe-area-inset-bottom))}
.mc-strip{flex:1;min-width:0;display:flex;gap:8px;overflow-x:auto}
.mc-strip img{width:var(--tza-thumb);height:var(--tza-thumb);object-fit:cover;border-radius:6px;border:2px solid #fff;flex-shrink:0}
.mc-shutter{
  width:calc(var(--tza-btn) + 20px);height:calc(var(--tza-btn) + 20px);border-radius:50%;flex-shrink:0;background:#fff;
  border:6px solid rgba(255,255,255,.45);background-clip:padding-box;
}
.mc-shutter:active{transform:scale(.94)}
.mc-shutter:disabled{opacity:.4}
.mc-done{min-width:150px}
.mc-count{font-family:var(--tza-mono);font-variant-numeric:tabular-nums}
.mc-flash{position:absolute;inset:0;background:#fff;opacity:0;pointer-events:none;transition:opacity .25s}
.mc-flash.on{opacity:.7;transition:none}
.mc-message{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;padding:24px;text-align:center;font-size:17px}
/* The shot just taken, held for Retake / Draw / Use (single-photo fields and the iPad-camera fallback). */
#mc-overlay .mc-review{flex:1;min-height:0;width:100%;object-fit:contain;background:#000}
.mc-message .mc-review{flex:0 1 auto;max-height:60vh}
.mc-markup,.mc-retake{flex-shrink:0}

/* Photo mark-up (openPhotoMarkup in app.js): over the camera, under toasts. */
#pm-overlay{position:fixed;inset:0;z-index:360;background:#000;display:flex;flex-direction:column;color:#fff;font-family:var(--tza-sans)}
.pm-top{display:flex;align-items:center;flex-wrap:wrap;gap:12px;padding:calc(12px + var(--tza-safe-top)) 18px 10px}
.pm-tools{display:flex;gap:8px}
.pm-tools .btn.active{background:var(--tza-indigo);color:#fff}
.pm-colors{display:flex;gap:10px;flex:1}
.pm-color{width:var(--tza-btn-xs);height:var(--tza-btn-xs);border-radius:50%;border:3px solid rgba(255,255,255,.35);flex-shrink:0}
.pm-color.active{border-color:#fff;box-shadow:0 0 0 3px var(--tza-indigo)}
.pm-textbar{display:flex;gap:10px;padding:0 18px 10px}
.pm-textbar .form-input{flex:1;min-width:0}
.pm-hint{padding:0 18px 8px;font-size:15px;opacity:.8}
.pm-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;padding:0 12px}
.pm-stage canvas{max-width:100%;max-height:100%;width:auto;height:auto;touch-action:none;display:block}
.pm-bar{display:flex;justify-content:flex-end;gap:14px;padding:14px 18px calc(22px + env(safe-area-inset-bottom))}

/* ── Composer ──────────────────────────────────────────────────────────── */
.jl-composer{border-top:var(--tza-bw) solid var(--tza-line);padding:14px 18px;background:#fff}
.jl-kinds{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:12px}
/* A selected Instruction looks like the message it will send: the same
   magenta-ruled pink wash an instruction wears in the thread. Not a solid
   magenta fill — that is reserved for the single most urgent thing on a
   screen, and a mode toggle is not it. */
.jl-kinds .tab[data-jl-kind="instruction"].active{
  background:var(--tza-accent-tint);color:var(--tza-accent);
  border-color:var(--tza-accent);box-shadow:inset 3px 0 0 var(--tza-accent);
}
.jl-input{min-height:var(--tza-btn);max-height:220px;resize:vertical}
.jl-composer-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-top:12px}
.jl-camera{
  height:var(--tza-btn);padding:0 22px;border-radius:5px;display:inline-flex;align-items:center;gap:10px;
  background:#fff;color:var(--tza-indigo);border:var(--tza-sigbw) solid var(--tza-indigo);
  font-family:var(--tza-sans);font-size:16px;font-weight:600;cursor:pointer;white-space:nowrap;
}
.jl-camera:hover{background:var(--tza-tint)}
.jl-camera input{display:none}
/* Post sits at the end of the row, away from the two photo controls — the
   button that sends and the buttons that attach should not be adjacent when
   they are being pressed through a glove. */
#jl-post{margin-left:auto}
.jl-photo-tray{display:flex;flex-direction:column;gap:12px;margin-top:14px}
.jl-tray-item{
  display:flex;gap:14px;align-items:flex-start;padding:12px;border-radius:8px;
  border:var(--tza-bw) solid var(--tza-line);background:var(--tza-surface);
}
.jl-tray-item.jl-failed{border-color:var(--tza-red);background:var(--tza-red-bg)}
.jl-tray-item.jl-done{border-color:var(--tza-green)}
.jl-tray-item>img{width:var(--tza-row);height:var(--tza-row);object-fit:cover;border-radius:5px;flex-shrink:0}
.jl-tray-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px}
.jl-tray-status{font-size:13px;font-weight:600;color:var(--tza-muted);overflow-wrap:anywhere}
.jl-failed .jl-tray-status{color:var(--tza-red)}
.jl-done .jl-tray-status{color:var(--tza-green)}
.jl-keep{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--tza-body)}
.jl-tray-actions{display:flex;gap:8px;flex-shrink:0}
/* The reply banner mirrors the quote block inside a bubble, so the thing you
   are about to answer looks the same before and after you send it. */
#jl-replying{
  display:flex;align-items:center;gap:12px;margin-bottom:12px;
  padding:8px 14px;border-radius:5px;background:var(--tza-tint);
  border-left:3px solid var(--tza-indigo);font-size:14px;
}
.jl-replying-text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.jl-replying-to{font-size:12.5px;font-weight:600;color:var(--tza-indigo)}
.jl-replying-gist{font-size:13.5px;color:var(--tza-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── Lightbox ──────────────────────────────────────────────────────────── */
#jl-lightbox,#sv-lightbox,#dl-lightbox{position:fixed;inset:0;background:rgba(14,18,48,.88);z-index:320;display:none;align-items:center;justify-content:center;padding:calc(24px + var(--tza-safe-top)) 24px 24px}
#jl-lightbox.open,#sv-lightbox.open,#dl-lightbox.open{display:flex}
.jl-lightbox-inner{max-width:min(1100px,100%);max-height:100%;display:flex;flex-direction:column;gap:14px;align-items:center}
.jl-lightbox-inner img{max-width:100%;max-height:72vh;object-fit:contain;border-radius:8px;background:#fff}
.jl-lightbox-caption{color:#fff;font-size:15px;text-align:center;text-wrap:pretty}
.jl-lightbox-actions{display:flex;gap:12px;flex-wrap:wrap;justify-content:center}
.lightbox-x{position:absolute;top:calc(16px + var(--tza-safe-top));right:16px;margin:0;background:rgba(255,255,255,.16);color:#fff}
.lightbox-x:hover{background:rgba(255,255,255,.28)}

/* ── Cross-project feed ────────────────────────────────────────────────── */
.jl-feed-row{
  display:block;padding:18px 20px;border-radius:12px;text-decoration:none;
  background:#fff;border:var(--tza-bw) solid var(--tza-line);box-shadow:var(--tza-shadow);
  min-height:var(--tza-row-lg);
}
.jl-feed-row:hover{border-color:var(--tza-indigo)}
.jl-feed-row.jl-unread{border-left:4px solid var(--tza-indigo)}
.jl-feed-row.jl-instruction{box-shadow:inset 3px 0 0 var(--tza-accent)}
.jl-feed-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.jl-time{font-size:13px;color:var(--tza-faint);margin-left:auto}
.jl-feed-kind{font-family:var(--tza-head);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;font-weight:600;color:var(--tza-accent)}
.jl-feed-body{font-size:16px;color:var(--tza-ink);line-height:1.45;text-wrap:pretty}
.jl-feed-meta{margin-top:6px;font-size:13px;color:var(--tza-faint)}

/* The unread count on the rail and on the project tab. Small, indigo-on-white
   against the rail's indigo so it reads as a count rather than an alarm. */
.jl-badge{
  display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;
  padding:0 6px;border-radius:999px;background:var(--tza-accent);color:#fff;
  font-family:var(--tza-mono);font-size:11.5px;font-weight:600;font-variant-numeric:tabular-nums;
}
.rail-item{position:relative}
.rail-item .jl-badge{position:absolute;top:10px;right:calc(50% - 26px)}
.tab .jl-badge{margin-left:10px;background:#fff;color:var(--tza-indigo)}
.tab.active .jl-badge{background:var(--tza-accent);color:#fff}

/* ── Narrow iPad portrait / phone ───────────────────────────────────────── */
@media (max-width:900px){
  .dash-side{width:100%}
  .dash-main{min-width:0}
  .grid-2,.grid-3{grid-template-columns:1fr}
  #content{padding:18px}
  #topbar{padding-left:18px;padding-right:18px}
  .tb-status{display:none}
}
@media (max-width:700px){
  .factstrip>*{min-width:120px;padding:0 14px}
  .sig-meta{margin-left:0;text-align:left;width:100%}
}
@media print{
  #rail,#drawer,#drawer-scrim,#topbar,#viewas-bar,.no-print{display:none!important}
  #main{margin-left:0}
  .card,.tza-card{box-shadow:none;break-inside:avoid}
}

/* ── Site visit ────────────────────────────────────────────────────────── */
/* Remove control on a photo tile. Sits on the corner rather than under the
   tile, so a row of photos stays a row. */
.sv-photo-x{
  position:absolute;top:-8px;right:-8px;width:32px;height:32px;border-radius:50%;
  border:var(--tza-bw) solid var(--tza-line);background:#fff;color:var(--tza-red);
  font-size:14px;font-weight:700;display:flex;align-items:center;justify-content:center;
  box-shadow:var(--tza-shadow);
}
/* "Still to fill in" links, and the flash on whatever they land on. Anchors
   leave room for the sticky topbar when scrolled to. */
.sv-jump{
  background:none;border:none;padding:0;min-height:var(--tza-btn-xs);text-align:left;
  font:inherit;color:var(--tza-indigo);font-weight:600;text-decoration:underline;text-underline-offset:3px;
}
.sv-anchor{scroll-margin-top:calc(96px + var(--tza-safe-top))}
.sv-flash{animation:sv-flash 1.8s ease-out}
@keyframes sv-flash{0%,40%{box-shadow:0 0 0 4px var(--tza-accent)}100%{box-shadow:0 0 0 4px transparent}}
/* The Log section's thread is the Project Log panel; inside a card it should
   not draw a second frame around itself. */
.sv-log-mount .jl-panel{border-radius:8px}
/* A saved section's answers: label left, answer right, one row each. On a
   narrow screen the two stack rather than squeeze. */
.sv-answer{display:flex;flex-wrap:wrap;gap:4px 18px;padding:10px 0;border-bottom:1px solid var(--tza-hair)}
.sv-answer:last-child{border-bottom:none}
.sv-answer-label{flex:0 0 min(320px,100%);font-size:14px;color:var(--tza-muted)}
.sv-answer-value{flex:1;min-width:0;font-size:16px;color:var(--tza-ink);overflow-wrap:anywhere}
/* The section being filled in is the one thing on the page that is not done. */
.sv-open-section{border-color:var(--tza-indigo)}
/* A segmented choice: one row of buttons, exactly one active, wrapping to a
   second row rather than scrolling. Sized by the field-mode variables. */
.sv-seg{display:flex;flex-wrap:wrap;gap:10px}
.sv-seg-opt{
  min-height:var(--tza-btn-xs);padding:8px 22px;border-radius:5px;background:#fff;color:var(--tza-body);
  border:var(--tza-inbw) solid var(--tza-line);font-size:16px;font-weight:600;font-family:var(--tza-sans);
  display:inline-flex;align-items:center;text-align:left;
}
.sv-seg-opt.active{background:var(--tza-indigo);color:#fff;border-color:var(--tza-indigo)}
.sv-seg-opt:disabled{opacity:.55;cursor:default}
/* Fields sharing an `inline` value: side by side where they fit. */
.sv-inline{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:0 18px}

/* ── Data logging ──────────────────────────────────────────────────────── */
/* The wizard: the step list on the left, the open step on the right; one
   column on a narrow screen. */
.dl-layout{display:grid;grid-template-columns:minmax(220px,300px) 1fr;gap:20px;align-items:start}
/* Side by side, the list stays in view and scrolls on its own, so 8.x is
   reachable. Narrower — an iPad held upright — the open step comes first and
   the list follows, unpinned: pinned, it covered the step and took every tap. */
.dl-steps{display:flex;flex-direction:column;gap:4px;position:sticky;top:calc(12px + var(--tza-safe-top));
  max-height:calc(100vh - 24px - var(--tza-safe-top));overflow-y:auto;overscroll-behavior:contain}
@media (max-width:900px){
  .dl-layout{grid-template-columns:1fr}
  .dl-steps{position:static;max-height:none;overflow:visible;order:2}
  .dl-layout > .stack-lg{order:1}
}
.dl-phase{font-family:var(--tza-head);font-size:13px;font-weight:600;color:var(--tza-faint);text-transform:uppercase;letter-spacing:.04em;margin:12px 0 4px}
.dl-step{display:flex;align-items:center;gap:12px;min-height:var(--tza-btn-xs);padding:8px 12px;border-radius:5px;background:transparent;
  border:var(--tza-bw) solid transparent;font:inherit;font-size:15px;color:var(--tza-body);text-align:left;width:100%}
.dl-step.active{background:var(--tza-tint);border-color:var(--tza-tint-line);color:var(--tza-ink);font-weight:600}
.dl-step.locked{color:var(--tza-ghost)}
.dl-step-num{font-family:var(--tza-mono);font-variant-numeric:tabular-nums;font-size:13px;min-width:34px}
.dl-step-mark{margin-left:auto;font-size:15px}
.dl-gate{font-family:var(--tza-mono);font-size:11px;font-weight:600;color:var(--tza-indigo);border:var(--tza-bw) solid var(--tza-tint-line);border-radius:4px;padding:1px 5px}
/* One phase's reading: instant pass/fail. */
.dl-phases{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.dl-phasecard{border:var(--tza-inbw) solid var(--tza-line);border-radius:12px;padding:16px;background:#fff}
.dl-phasecard.pass{border-color:var(--tza-green);background:var(--tza-green-bg)}
.dl-phasecard.fail{border-color:var(--tza-red);background:var(--tza-red-bg)}
.dl-phasecard h4{font-family:var(--tza-head);font-size:17px;margin:0 0 10px;display:flex;justify-content:space-between;align-items:center}
.dl-big{font-family:var(--tza-mono);font-variant-numeric:tabular-nums;font-size:22px;min-height:var(--tza-btn);max-width:100%}
.dl-lesson{border-left:4px solid var(--tza-indigo);background:var(--tza-tint);padding:10px 14px;border-radius:0 6px 6px 0;font-size:14px;color:var(--tza-body);margin-bottom:12px}
.dl-trouble{border:var(--tza-inbw) solid var(--tza-amber-line);background:var(--tza-amber-bg);border-radius:8px;padding:12px 14px;margin-top:10px}
.dl-trouble.normal{border-color:var(--tza-line);background:var(--tza-surface)}
.dl-photos{display:flex;flex-wrap:wrap;gap:10px;margin-top:8px}
.dl-photos img{width:calc(var(--tza-thumb) * 1.6);height:calc(var(--tza-thumb) * 1.6);object-fit:cover;border-radius:6px;border:var(--tza-bw) solid var(--tza-line);cursor:pointer}
.dl-photos .retake{outline:3px solid var(--tza-red);outline-offset:1px}
.dl-photos .superseded{opacity:.45}
#dl-sync-bar{position:sticky;top:var(--tza-safe-top);z-index:40;margin-bottom:14px;padding:12px 16px;border-radius:8px;font-weight:600;
  background:var(--tza-amber-bg);border:var(--tza-inbw) solid var(--tza-amber-line);color:var(--tza-amber)}
#dl-sync-bar.bad{background:var(--tza-red-bg);border-color:var(--tza-red);color:var(--tza-red)}
#dl-sync-bar.hidden{display:none}
/* The device card, full screen at 3.3. */
#dl-card-overlay{position:fixed;inset:0;z-index:330;background:#fff;display:flex;flex-direction:column;padding:calc(16px + var(--tza-safe-top)) 18px 18px;gap:14px}
#dl-card-overlay img{flex:1;min-height:0;width:100%;object-fit:contain}
.dl-arrow{font-size:28px;font-family:var(--tza-head);font-weight:600;color:var(--tza-indigo)}
.dl-table{width:100%;border-collapse:collapse;font-size:14px}
.dl-table th{text-align:left;font-weight:600;color:var(--tza-muted);padding:8px 10px;border-bottom:var(--tza-bw) solid var(--tza-line)}
.dl-table td{padding:8px 10px;border-bottom:var(--tza-bw) solid var(--tza-hair);vertical-align:top}
/* "Now" sits inside the date-and-time field, at its left edge. */
.dl-now-wrap{position:relative}
.dl-now-wrap .form-input{padding-left:96px}
.dl-now{position:absolute;left:6px;top:50%;transform:translateY(-50%);height:calc(100% - 12px);min-width:80px;padding:0 14px;
  border:0;border-radius:4px;background:var(--tza-indigo);color:#fff;font:600 15px var(--tza-sans);cursor:pointer}
/* The wizard's stages, and the steps of the stage that is open, as two rows
   of tabs that scroll sideways rather than wrapping into a column. */
.dl-stagebar{padding:14px 16px}
.dl-stagebar .tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}
.dl-stagebar .tab{white-space:nowrap;flex-shrink:0}
/* The steps of the open stage: smaller, lighter pills under the stage tabs,
   plainly a level below them. */
.dl-substeps{display:flex;gap:8px;overflow-x:auto;-webkit-overflow-scrolling:touch;padding:10px 0 2px;border-top:var(--tza-bw) solid var(--tza-hair)}
.dl-subtab{flex-shrink:0;white-space:nowrap;min-height:44px;padding:6px 14px;border-radius:999px;font:500 14px var(--tza-sans);
  background:var(--tza-surface);color:var(--tza-body);border:var(--tza-bw) solid var(--tza-line);cursor:pointer}
.dl-subtab.active{background:#fff;color:var(--tza-indigo);border:var(--tza-inbw) solid var(--tza-indigo);font-weight:600}
.dl-subtab .mono{color:var(--tza-faint)}
/* Under every job tab: the calendar left, live data right. */
.dl-foot{margin-top:16px;padding-top:14px;border-top:var(--tza-bw) solid var(--tza-hair);gap:12px}
/* Folding sections on Details. */
.dl-fold > summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;min-height:var(--tza-btn-xs)}
.dl-fold > summary::-webkit-details-marker{display:none}
.dl-fold > summary::after{content:'▸';font-size:20px;color:var(--tza-faint);transition:transform .15s}
.dl-fold[open] > summary::after{transform:rotate(90deg)}

