/* TRIMATRON surface system, ported from Field Ops (grip-app) so the two apps
   feel like one hand built them. Corey, 2026-09-14: "I want the surfaces to be
   familiar." Two kinds of rule live here, and the source comment on each block
   says which:
   VERBATIM: tokens (fieldmap.html :root), carbon background (data/carbon-bg.css),
   map header (.top), status board + machined plates (fieldmap.html deck), zone
   tiles (data/zone-grid.css), tab bar + drawer (data/nav.css), panel shell
   (.wpanel), stat wells (briefing.html .env-tile), sheet + toast (fieldmap.html).
   Change those in Field Ops first, then here.
   TRIMATRON additions: rules Field Ops has no equivalent for (copper/heat plate
   fills, the tall tote plate, .deck-note, .wp-foot, .sheet-foot, .scr-h, the
   machine-tile count badge tints). Marked "(TRIMATRON)" inline. */
:root {
  --ink:#0b0c0f; --ink-2:#0f1014; --surface:#16171b; --surface-2:#151921;
  --line:#2a2c31; --line-hi:#353841;
  --bone:#efeae0; --bone-2:#b5bcc8; --muted:#8f8a82; --muted-2:#5c6472; --faint:#4a515b;
  --blue:#b8521e; --blue-hi:#c75c24; --copper:#b8521e;
  --green:#66e58e; --amber:#ffcc66; --heat:#ff5c4a; --water:#60a5fa;
  --mono:'JetBrains Mono', ui-monospace, monospace;
  --sans:'Inter', system-ui, -apple-system, sans-serif;
  --disp:'Inter Tight', system-ui, sans-serif;
}
html, body { background: var(--ink); margin: 0; min-height: 100%; }
body { color: var(--bone); font-family: var(--sans); -webkit-font-smoothing: antialiased; }

/* carbon background layers */
.grip-bg { position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(1000px 700px at 85% -10%, rgba(184,82,30,0.07), transparent 55%),
              radial-gradient(130% 70% at 70% -5%, #1a1c22, #0f1014 45%, #0b0c0f); }
.grip-bg::after { content: ""; position: absolute; inset: -10%; opacity: 0.5; mix-blend-mode: overlay; pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.04 0'/></filter><rect width='220' height='220' filter='url(%23n)'/></svg>"); }
.grip-bg-rim { position: fixed; inset: 0; pointer-events: none; z-index: 0;
  box-shadow: inset 0 0 120px rgba(184,82,30,0.05), inset 0 0 40px rgba(184,82,30,0.035); }
#root { position: relative; z-index: 1; }

/* Grip watermark (data/carbon-bg.css Layer 3, VERBATIM; asset path is TRIMATRON's /brand/grip-mark.png).
   Fixed hex mark drifting behind the deck, screen-blended so the metallic shape lifts and its dark
   backdrop drops into the carbon. Cinematic pulse + slow drift; static under reduced motion; hidden
   in print; smaller and dimmer on phones. Corey 2026-09-14: "put the grip logo in the background
   like in the field ops app." Opt-in: <div class="grip-watermark" aria-hidden="true"></div> in body. */
.grip-watermark { position: fixed; top: 50%; left: 50%; width: min(680px, 78vw); aspect-ratio: 1 / 1; margin-top: -38vh; transform: translate(-50%, 0); z-index: 0; pointer-events: none;
  background: url("/brand/grip-mark.png") center / contain no-repeat; mix-blend-mode: screen; opacity: 0.07; filter: blur(0.3px) saturate(0.85);
  animation: gripWatermarkPulse 11s ease-in-out infinite, gripWatermarkDrift 38s ease-in-out infinite; }
@keyframes gripWatermarkPulse { 0%, 100% { opacity: 0.05; } 50% { opacity: 0.11; } }
@keyframes gripWatermarkDrift { 0%, 100% { transform: translate(-50%, 0) scale(1.00); } 50% { transform: translate(calc(-50% + 8px), 6px) scale(1.025); } }
@media (prefers-reduced-motion: reduce) { .grip-watermark { animation: none; opacity: 0.07; } }
/* Bloom: JS adds .blooming for ~1.4 s when a shift is handed off. Brand punctuation without a popup. */
.grip-watermark.blooming { animation: gripWatermarkBloom 1400ms cubic-bezier(0.22, 0.61, 0.36, 1) !important; }
@keyframes gripWatermarkBloom { 0% { opacity: 0.07; transform: translate(-50%, 0) scale(1.00); filter: blur(0.3px) saturate(0.85); } 35% { opacity: 0.26; transform: translate(-50%, -4px) scale(1.06); filter: blur(0px) saturate(1.2); } 100% { opacity: 0.07; transform: translate(-50%, 0) scale(1.00); filter: blur(0.3px) saturate(0.85); } }
@media (prefers-reduced-motion: reduce) { .grip-watermark.blooming { animation: none !important; } }
@media print { .grip-watermark { display: none !important; } }
@media (max-width: 540px) { .grip-watermark { width: min(540px, 92vw); margin-top: -34vh; opacity: 0.05; }
  @keyframes gripWatermarkPulse { 0%, 100% { opacity: 0.04; } 50% { opacity: 0.08; } } }


/* page frame */
.wrap { max-width: 720px; margin: 0 auto; padding: 12px 14px 40px; }

/* map header idiom */
.top { display: flex; align-items: center; gap: 10px; padding: 4px 2px 14px; }
.top .mark { display: block; width: 18px; height: 18px; flex: 0 0 auto; }
.top h1 { margin: 0; font: 800 15px/1.3 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--bone); }
.top .sub { margin: 2px 0 0; font: 600 10px/1 var(--mono); letter-spacing: 0.16em; color: var(--faint); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top > div { min-width: 0; flex: 1 1 auto; }
.top .crew { }
@media (max-width: 479px) { .top .crew { display: none; } }
.top .partner { margin-left: auto; height: 20px; width: auto; max-width: 122px; object-fit: contain; flex: 0 0 auto; }
.chip { font: 700 9px/1 var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--amber); border: 1px solid rgba(255,204,102,0.45); background: rgba(255,204,102,0.07); border-radius: 999px; padding: 5px 8px; }
.deck-stamp { display: flex; justify-content: space-between; align-items: baseline; padding: 0 2px 10px; font: 700 11px/1 var(--mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.deck-stamp .on { color: var(--bone); }
.ds-upd { font-size: 9px; color: var(--faint); letter-spacing: 0.1em; }
.ds-upd.stale { color: #fbbf24; }

/* status board */
.deck-board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; margin: 0 -14px 10px; background: #0f0f11; border-top: 1px solid #26262a; border-bottom: 1px solid #26262a; }
.db-cell { background: linear-gradient(180deg, #1d2026 0%, #15171c 55%, #121419 100%); border: 0; padding: 10px 7px 8px; text-align: left; cursor: pointer; min-width: 0; font-family: var(--mono); color: var(--bone);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), inset 0 -2px 5px -2px rgba(0,0,0,0.7); }
.db-cell.active { box-shadow: inset 0 0 0 1px var(--blue); }
.db-cell:active { transform: scale(0.97); }
.db-num { font: 400 22px/1.1 var(--mono); color: var(--bone); font-variant-numeric: tabular-nums; display: flex; align-items: center; gap: 6px; }
.db-num small { font: 500 11px/1 var(--mono); color: var(--muted); }
.db-cell.zero .db-num { color: var(--faint); }
.db-lab { font: 700 8.5px/1.4 var(--mono); letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.db-lamp { width: 5px; height: 5px; border-radius: 50%; background: #33353c; flex: 0 0 auto; }
.db-lamp.on { background: var(--blue); box-shadow: 0 0 6px rgba(184,82,30,0.7); }
.db-lock { display: inline-block; width: 12px; height: 12px; border-radius: 2px; background: #e22028; flex: 0 0 auto; }
.db-tri { display: inline-block; width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 11px solid #fbbf24; flex: 0 0 auto; }

/* action rail, machined plates (fieldmap.html deck; .copper/.heat-fill/.tall are TRIMATRON) */
.deck-rail { display: flex; gap: 8px; margin: 0 0 10px; }
.deck-plate { flex: 1; min-height: 48px; min-width: 0;
  background: linear-gradient(180deg, #262a31 0%, #191c22 55%, #14171d 100%);
  border: 1px solid rgba(255,255,255,0.08); border-radius: 8px; padding: 12px 6px;
  font: 700 11px/1.25 var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--bone-2); cursor: pointer; position: relative;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.09), inset 0 -2px 5px -2px rgba(0,0,0,0.7), 0 3px 7px -3px rgba(0,0,0,0.8); }
@media (max-width: 399px) { .deck-plate { font-size: 10px; letter-spacing: 0.12em; padding: 12px 4px; } }
.deck-plate:active { background: rgba(184,82,30,0.15); transform: scale(0.97); }
.deck-plate.primary { border-color: var(--blue); color: var(--blue); }
.deck-plate.copper { background: linear-gradient(180deg, #c75c24 0%, #b8521e 55%, #8c3d14 100%); border-color: rgba(255,255,255,0.12); color: #fff5ea;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.28), inset 0 -2px 5px -2px rgba(0,0,0,0.6), 0 3px 7px -3px rgba(0,0,0,0.8); }
.deck-plate.heat { border-color: var(--heat); color: var(--heat); }
.deck-plate.heat-fill { background: linear-gradient(180deg, #e04a38 0%, #cc3f2e 55%, #9a2d20 100%); border-color: rgba(255,255,255,0.12); color: #fff5f2;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.24), inset 0 -2px 5px -2px rgba(0,0,0,0.6), 0 3px 7px -3px rgba(0,0,0,0.8); }
/* (TRIMATRON) QC rec plate tones: amber for a moisture hold or a confounded effect, muted for an input read or a closed effect */
.deck-plate.amber { border-color: var(--amber); color: var(--amber); }
.deck-plate.muted { color: var(--muted); }
.deck-plate.tall { min-height: 84px; font-size: 12px; }
.deck-plate .big { display: block; font: 500 30px/1 var(--disp); letter-spacing: 0; text-transform: none; font-variant-numeric: tabular-nums; margin-bottom: 7px; }
.deck-plate .sub { display: block; font: 600 9px/1 var(--mono); letter-spacing: 0.16em; margin-top: 6px; color: inherit; opacity: 0.85; }
.dp-lamp { position: absolute; top: 6px; right: 7px; width: 5px; height: 5px; border-radius: 50%; background: transparent; }
.dp-lamp.on { background: #fbbf24; }
/* (TRIMATRON) tote plate wrapper + corner camera door: a photo is not a tap on
   the tote, so it is its own button, 36px, sitting on the plate's corner. */
.dp-wrap { position: relative; flex: 1; min-width: 0; display: flex; }
/* Three weigh plates in one rail (2026-09-15): the plate reads left-aligned
   like the status board cells above it, the numeral steps down and keeps a
   clear lane beside the 30px camera door (padding-right), so a five-glyph
   dry-in ticket (296.4) never runs under the camera at 375px: the centered
   24px numeral put its last digit under the door (review 2026-09-15). A
   six-glyph weight (1250.0) steps down again (.long, set by Line.jsx). */
.deck-rail.three .deck-plate.tall { padding: 12px 8px 10px 9px; font-size: 10px; letter-spacing: 0.12em; text-align: left; }
.deck-rail.three .deck-plate.tall .big { font-size: 22px; margin-bottom: 7px; padding-right: 34px; white-space: nowrap; }
.deck-rail.three .deck-plate.tall .big.long { font-size: 18px; }
.deck-rail.three .deck-plate.tall .sub { font-size: 8px; letter-spacing: 0.1em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.deck-rail.three .dp-cam { top: 4px; right: 4px; width: 30px; height: 30px; border-radius: 7px; }
.deck-rail.three .dp-cam svg { width: 14px; height: 14px; }
.dp-wrap > .deck-plate { width: 100%; }
.dp-cam { position: absolute; top: 6px; right: 6px; width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,0.16); background: rgba(0,0,0,0.38); color: var(--bone); cursor: pointer; padding: 0;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08); }
.dp-cam:active { transform: scale(0.94); background: rgba(0,0,0,0.55); }
/* (TRIMATRON) one line under the rail: down reason, active package, or the run hint */
.deck-note { font: 600 9.5px/1.4 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); text-align: right; margin: 0 2px 10px; }

/* panel shell + labels */
.wpanel { position: relative; border-radius: 14px; padding: 14px 14px 16px; margin: 14px 0;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 18px 36px -22px rgba(0,0,0,0.7); }
.wpanel::before { content: ""; position: absolute; top: 0; left: 14%; right: 14%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.14), transparent); pointer-events: none; }
.wp-label { font: 700 9px/1 var(--mono); letter-spacing: 0.22em; text-transform: uppercase; color: var(--muted); margin: 0 0 9px; display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.wp-asof { letter-spacing: 0.1em; color: var(--faint); text-transform: none; }
.hero-num { font: 500 54px/1 var(--disp); letter-spacing: -0.01em; color: var(--bone); font-variant-numeric: tabular-nums; }
.hero-num small { font: 400 15px/1 var(--mono); color: var(--faint); margin-left: 6px; letter-spacing: 0; }
.hero-sub { font: 500 12px/1.4 var(--mono); color: var(--muted); margin-top: 6px; }

/* recessed stat wells (briefing.html .env-tile, .env-tile-label, .env-tile-num, .env-tile-unit) */
.env-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 6px; }
.env-tile { padding: 8px 10px; border-radius: 7px; background: rgba(15,18,24,0.55); border: 1px solid var(--line); min-width: 0;
  box-shadow: inset 0 2px 4px -2px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.045); display: flex; flex-direction: column; gap: 3px; text-align: left; font-family: var(--sans); color: var(--bone); }
button.env-tile { cursor: pointer; }
button.env-tile:active { transform: scale(0.97); }
.env-tile span { display: block; font: 700 8.5px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.env-tile b { display: block; font: 700 18px/1.1 var(--disp); font-variant-numeric: tabular-nums; color: var(--bone); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.env-tile b small { font: 600 10px/1 var(--mono); color: var(--muted-2); letter-spacing: 0.04em; margin-left: 3px; }
.env-tile b.amber { color: var(--amber); } .env-tile b.heat { color: var(--heat); } .env-tile b.green { color: var(--green); }
/* (TRIMATRON) small facts under the wells: kief estimate, streak. SPEC-V7: keep small. */
.wp-foot { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px; font: 600 9px/1.5 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint); font-variant-numeric: tabular-nums; }
.wp-foot b { font-weight: 700; color: var(--muted); }
.site-fresh { font: 700 9px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--green); text-align: right; }
.site-fresh.warn { color: var(--amber); }
.site-fresh.heat { color: var(--heat); }

/* zone tiles, used here for machines */
.zg-block-label { font: 700 8.5px/1 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-2); margin: 0 0 6px; }
.zg-map { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 4px; }
.zg-cell { border-radius: 7px; border: 1px solid var(--line); min-height: 48px; min-width: 0; position: relative; padding: 13px 2px 4px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font: 700 10px/1 var(--mono); color: var(--muted); background: rgba(15,18,24,0.5); cursor: pointer; }
.zg-cell:active { transform: scale(0.95); transition: transform 120ms; }
.zg-cell .zg-id { font: 800 12px/1 var(--mono); }
.zg-cell small { font: 600 8.5px/1.2 var(--mono); letter-spacing: 0.04em; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); font-variant-numeric: tabular-nums; }
.zg-cell.zg-quiet { background: linear-gradient(180deg, #21242c 0%, #16181e 52%, #12141a 100%); border: 1px solid rgba(255,255,255,0.07);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), inset 0 -3px 6px -3px rgba(0,0,0,0.75), 0 3px 7px -3px rgba(0,0,0,0.85); }
.zg-cell.zg-quiet .zg-id { color: #dfe4ec; text-shadow: 0 1px 0 rgba(0,0,0,0.6); }
.zg-cell.zg-quiet small { color: #4a505c; }
.zg-cell.idle { border-style: dashed; color: var(--muted-2); background: rgba(15,18,24,0.5); box-shadow: none; }
.zg-cell.idle .zg-id { color: var(--muted-2); text-shadow: none; }
.zg-cell.mp-watering { border: 1.5px dashed rgba(96,165,250,0.9); background: linear-gradient(180deg, #38414f 0%, #29303c 55%, #232935 100%); animation: zgAnts 1.4s linear infinite;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), inset 0 0 20px rgba(95,135,205,0.22), 0 0 18px -5px rgba(95,135,205,0.6), 0 3px 7px -3px rgba(0,0,0,0.85); }
.zg-cell.mp-heat { border-color: rgba(251,191,36,0.55);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.09), inset 0 0 16px rgba(251,191,36,0.13), 0 0 0 1px rgba(251,191,36,0.4), 0 0 18px -4px rgba(251,191,36,0.6), 0 3px 7px -3px rgba(0,0,0,0.85); }
.zg-cell.mp-rei { border-color: rgba(255,92,74,0.7); border-style: solid; background: linear-gradient(180deg, #241417 0%, #1a0f11 60%, #150d0f 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), inset 0 0 16px rgba(255,92,74,0.14), 0 0 0 1px rgba(255,92,74,0.45), 0 0 18px -4px rgba(255,92,74,0.65), 0 3px 7px -3px rgba(0,0,0,0.85); }
.zg-cell.mp-dim { opacity: 0.22; animation: none; }
.mp-cnt { position: absolute; top: 3px; right: 4px; font: 700 8px/1 var(--mono); color: var(--muted); border: 1px solid var(--line-hi); border-radius: 7px; padding: 1px 4px; }
/* (TRIMATRON) count badge tints */
.mp-cnt.heat { color: var(--heat); border-color: rgba(255,92,74,0.6); }
.mp-cnt.amber { color: var(--amber); border-color: rgba(255,204,102,0.6); }
@keyframes zgAnts { 50% { border-color: rgba(96,165,250,0.35); } }

/* photo strip at the top of the surface (fieldmap.html .photo-strip / .ps-card / .ps-tag).
   Newest first, batches append as you scroll toward the end. Corey 2026-09-14:
   "the same infinite scroll for pics at the top of the main app surface." */
.photo-strip { display: flex; gap: 1px; overflow-x: auto; margin: 0 -14px 1px; background: #0f0f11; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.photo-strip::-webkit-scrollbar { display: none; }
.ps-card { position: relative; flex: 0 0 auto; width: 120px; height: 68px; padding: 0; border: 0; background: #17171a; cursor: pointer; }
.ps-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-tag { position: absolute; left: 6px; bottom: 5px; display: flex; flex-direction: column; gap: 1px; max-width: calc(100% - 12px); font: 700 9px/1.15 var(--mono); letter-spacing: 0.06em; color: #dfe3ea; text-shadow: 0 1px 3px rgba(0,0,0,0.9); text-align: left; }
.ps-tag .ps-l1, .ps-tag .ps-l2 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-tag .ps-l2 { font-weight: 600; font-size: 8.5px; opacity: 0.9; }
/* (TRIMATRON) score chip on a strip card, the fieldmap .pp-score idiom: bud % when analyzed, state word otherwise */
.ps-chip { position: absolute; top: 4px; left: 4px; padding: 2px 6px; border-radius: 6px; font: 700 10px/1 var(--mono); background: rgba(8,10,14,0.78); color: #d2d7e1; }
.ps-chip.good { color: var(--green); } .ps-chip.bad { color: var(--heat); } .ps-chip.wait { color: var(--muted); }
/* (TRIMATRON) estimate within 8 points under the target: amber, not red */
.ps-chip.amber { color: var(--amber); }

/* bottom tab bar + drawer */
.gtab-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; display: flex; align-items: stretch;
  background: linear-gradient(180deg, rgb(13,15,20), rgb(9,11,15)); border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px); box-shadow: 0 -12px 28px -18px rgba(0,0,0,0.8); }
.gtab { flex: 1 1 0; min-width: 0; min-height: 54px; display: flex; align-items: center; justify-content: center; gap: 5px;
  background: none; border: 0; cursor: pointer; text-decoration: none; font: 700 10px/1 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); position: relative; }
.gtab:active { transform: scale(0.95); transition: transform 120ms; }
.gtab.active { color: var(--copper); }
.gtab.active::after { content: ""; position: absolute; top: 0; left: 22%; right: 22%; height: 2px; background: var(--copper); border-radius: 0 0 2px 2px; }
.gtab-badge { font: 700 8.5px/1 var(--mono); color: #0b0c0f; background: var(--amber); border-radius: 8px; padding: 2px 5px; }
/* (TRIMATRON) critical count on the Machines tab; replaces the full-width red timer strip, 2026-09-14 */
.gtab-badge.heat { background: var(--heat); color: #fff5f2; }
.gnav-scrim { position: fixed; inset: 0; background: rgba(2,3,5,0.6); z-index: 90; opacity: 0; pointer-events: none; transition: opacity 0.22s; }
.gnav-scrim.on { opacity: 1; pointer-events: auto; }
.gnav-drawer { position: fixed; top: 0; left: 0; bottom: 0; width: 80%; max-width: 300px; background: var(--surface); border-right: 1px solid var(--line-hi); z-index: 91;
  padding: calc(env(safe-area-inset-top) + 18px) 0 calc(env(safe-area-inset-bottom) + 18px); display: flex; flex-direction: column; overflow-y: auto;
  transform: translateX(-104%); visibility: hidden; transition: transform 0.22s cubic-bezier(0.2,0.7,0.1,1), visibility 0s linear 0.22s; }
.gnav-drawer.on { transform: none; visibility: visible; transition: transform 0.22s cubic-bezier(0.2,0.7,0.1,1), visibility 0s; }
.gnav-h { font: 700 10px/1 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--faint); padding: 0 18px 14px; flex-shrink: 0; margin-top: 10px; }
.gnav-h:first-child { margin-top: 0; }
.gnav-link { display: block; width: 100%; text-align: left; background: none; border: none; border-top: 1px solid var(--line); color: var(--bone); font: 600 15px/1 var(--sans); padding: 16px 18px; text-decoration: none; flex-shrink: 0; cursor: pointer; }
.gnav-link.active { color: var(--blue-hi); font-weight: 700; }
.gnav-foot { margin-top: auto; padding: 16px 18px 0; border-top: 1px solid var(--line); font: 600 10px/1.6 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); }

/* bottom sheet + toast */
.scrim { position: fixed; inset: 0; background: rgba(2,3,5,0.7); z-index: 40; opacity: 0; transition: opacity 0.24s; }
.scrim.on { opacity: 1; }
.sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 41; max-width: 560px; margin: 0 auto; background: var(--surface); border: 1px solid var(--line-hi); border-bottom: none; border-radius: 16px 16px 0 0;
  transform: translate3d(0,102%,0); transition: transform 0.24s cubic-bezier(0.2,0.7,0.1,1); will-change: transform;
  max-height: 92vh; display: flex; flex-direction: column; padding-bottom: env(safe-area-inset-bottom); }
.sheet.on { transform: translate3d(0,0,0); }
.sheet-h { position: relative; display: flex; align-items: center; gap: 10px; padding: 16px 16px 10px; border-bottom: 1px solid var(--line); }
.sheet-h .grab { position: absolute; top: 7px; left: 50%; transform: translateX(-50%); width: 38px; height: 4px; border-radius: 2px; background: var(--line-hi); }
.sheet-h h2 { margin: 0; min-width: 0; font: 700 14px/1.1 var(--mono); letter-spacing: 0.10em; text-transform: uppercase; color: var(--bone); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-x { margin-left: auto; flex: 0 0 auto; background: none; border: 1px solid var(--line-hi); color: var(--muted); border-radius: 8px; width: 34px; height: 34px; font-size: 17px; line-height: 1; cursor: pointer; }
.sheet-body { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 14px 16px calc(18px + var(--kb-inset, 0px)); overscroll-behavior: contain; }
/* (TRIMATRON) pinned footer so the confirm row never scrolls below the fold on a phone.
   Review 2026-09-14: LINE DOWN's Confirm sat below the fold at 375x812. */
.sheet-foot { flex: 0 0 auto; display: flex; gap: 10px; padding: 10px 16px calc(14px + var(--kb-inset, 0px)); border-top: 1px solid var(--line); background: var(--surface); }
/* (TRIMATRON) screen title on the non-deck screens; the .top h1 is the page h1 */
.scr-h { margin: 0; font: 800 15px/1.3 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--bone); }
.scr-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin: 0 0 14px; }
.toast { position: fixed; left: 50%; bottom: calc(76px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); background: #0b0c0f; border: 1px solid var(--line-hi); color: var(--bone); padding: 11px 16px; border-radius: 10px; font: 600 12px/1.3 var(--mono); z-index: 60; max-width: 88vw; text-align: center; }

/* Reduced motion: slide-ins and the marching ring go still; functional status motion stays (tokens.js). */
@media (prefers-reduced-motion: reduce) { .zg-cell.mp-watering { animation: none; } .gnav-drawer, .gnav-scrim, .sheet, .scrim { transition: none; } }

/* Scan glyph (Corey 2026-09-15, "what icon can we use on the scan button"): a 1D
   barcode inside viewfinder corners, the METRC tag as the camera sees it. Barcode
   means tag, the camera glyph on the plates means photo; the two never share a look. */
.dp-scan { display: inline-flex; align-items: center; margin-right: 8px; vertical-align: -3px; }
.dp-scan svg { width: 17px; height: 17px; fill: currentColor; display: block; }

/* Five tabs (Value joined the floor, 2026-09-15). At 375 pt the Field Ops sizing
   (10px, .18em) put the Packages badge on top of Machines; tighter tracking and a
   slimmer badge keep every label whole on the smallest phone. */
.gtab-bar.five .gtab { font-size: 9.5px; letter-spacing: 0.1em; gap: 4px; padding: 0 2px; }
.gtab-bar.five .gtab-badge { font-size: 8px; padding: 2px 4px; }
