/* ============================================================================
   WS OPS — operations console
   Design system v3 (2026-08-16): editorial. Vox-style.

   The rules this file follows:
   - NO neon. No glows, no shadow-halos, no saturated colour on black, no
     gradient card tints, no pulsing. Colour is flat and printed.
   - Type carries the hierarchy, not boxes. Kicker → headline → deck, the way
     a news card works. The well number is the headline.
   - Hairlines and whitespace separate things. A heavy border is a last resort.
   - Two real themes. Light is the primary editorial surface; dark is a true
     dark theme (not an inverted one), and both are first-class.
   - Everything tappable is >= 40px. Nothing overflows a 375px screen.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens -- */
:root, html[data-theme="light"] {
  --bg: #ffffff;
  --bg-elev: #ffffff;
  --page: #f4f6f8;          /* the page behind the cards */
  --surface: #ffffff;
  --surface-2: #f2f4f7;
  --line: #d9dde2;
  --line-soft: #e8ebef;
  --line-strong: #b6bec7;

  --text: #0f1419;
  --text-2: #46505c;
  --dim: #667280;
  --faint: #8b95a1;

  /* semantic — chosen for contrast on white, print-flat */
  --red: #c0392f;
  --amber: #96601a;
  --green: #16764a;
  --purple: #6a3ec0;
  --blue: #0f6bb0;
  --red-bg: #fdeceb;
  --amber-bg: #fdf3e3;
  --green-bg: #e8f5ee;
  --purple-bg: #f1ebfc;
  --blue-bg: #e8f2fa;

  /* solid fills used for pills — always paired with --on-fill text */
  --red-fill: #c0392f;
  --amber-fill: #f0a52c;
  --green-fill: #16764a;
  --purple-fill: #6a3ec0;
  --blue-fill: #0f6bb0;
  --on-red: #ffffff;
  --on-amber: #2c1d00;
  --on-green: #ffffff;
  --on-purple: #ffffff;
  --on-blue: #ffffff;

  --brand: #96601a;
  --brand-fill: #f0a52c;
  --on-brand: #2c1d00;

  --card-shadow: 0 1px 2px rgba(15, 20, 25, .06);
}

html[data-theme="dark"] {
  --bg: #0f1216;
  --bg-elev: #14181d;
  --page: #0f1216;
  --surface: #171c22;
  --surface-2: #1f252c;
  --line: #2b323b;
  --line-soft: #222831;
  --line-strong: #3b434e;

  --text: #e9ecf0;
  --text-2: #a9b2bd;
  --dim: #8a94a0;
  --faint: #68727e;

  --red: #f08279;
  --amber: #dda54c;
  --green: #56c78c;
  --purple: #ad86ea;
  --blue: #69b3ec;
  --red-bg: #2a1917;
  --amber-bg: #2a2117;
  --green-bg: #16261e;
  --purple-bg: #221b2f;
  --blue-bg: #16232f;

  --red-fill: #c8433a;
  --amber-fill: #d9992f;
  --green-fill: #2f8f60;
  --purple-fill: #7a51c9;
  --blue-fill: #2b7cbd;
  --on-red: #ffffff;
  --on-amber: #1e1503;
  --on-green: #ffffff;
  --on-purple: #ffffff;
  --on-blue: #ffffff;

  --brand: #dda54c;
  --brand-fill: #d9992f;
  --on-brand: #1e1503;

  --card-shadow: none;
}

:root {
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI", Roboto, system-ui, sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --r: 10px;          /* cards */
  --r-sm: 6px;        /* inner blocks, buttons */
  --r-pill: 999px;
  --tap: 44px;
  /* legacy aliases still referenced by a few rules */
  --accent: var(--brand);
  --bad: var(--red);
  --ok: var(--green);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  background: var(--page);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  transition: background-color .2s ease, color .2s ease;
}
button, input, textarea { font-family: inherit; -webkit-tap-highlight-color: transparent; }
button { touch-action: manipulation; }
.hidden { display: none !important; }
::-webkit-scrollbar { width: 0; height: 0; }
.wdur, .wsince, .wname, .tl-time, .wstep-at, .sum-n { font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* --------------------------------------------------------------- wordmark -- */
.wordmark {
  font-family: var(--sans);
  font-weight: 800;
  letter-spacing: -.01em;
  font-size: 20px;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 9px;
}
.wordmark .mark {
  width: 4px; height: 17px;
  background: var(--brand-fill);
  border-radius: 1px;
  display: inline-block;
  flex: none;
}
.wordmark.sm { font-size: 15px; }
.wordmark.sm .mark { height: 15px; width: 3.5px; }

/* ------------------------------------------------------------------ login -- */
.login {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
  z-index: 50;
  padding: 24px;
}
.login-card { width: 100%; max-width: 330px; }
.login-sub {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
  margin: 12px 0 34px 13px;
}
.login input {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 16px;
  padding: 15px 14px;
  outline: none;
  border-radius: var(--r-sm);
}
.login input:focus { border-color: var(--text); }
.login button {
  width: 100%;
  min-height: var(--tap);
  margin-top: 10px;
  background: var(--text);
  color: var(--bg);
  border: none;
  font-weight: 700;
  letter-spacing: .1em;
  font-size: 13px;
  padding: 14px;
  cursor: pointer;
  border-radius: var(--r-sm);
  transition: opacity .12s ease;
}
.login button:active { opacity: .8; }
.login-err { font-size: 13px; color: var(--red); margin-top: 12px; min-height: 18px; }

/* ------------------------------------------------------------------ shell -- */
.shell { height: 100%; height: 100dvh; display: flex; flex-direction: column; }
.topbar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 16px;
  padding-top: calc(11px + env(safe-area-inset-top));
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  z-index: 20;
}
.status { display: flex; gap: 10px; align-items: center; }
.st {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--dim);
  display: flex;
  align-items: center;
  gap: 5px;
}
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--line-strong); display: inline-block; }
.dot.ok { background: var(--green-fill); }
.dot.bad { background: var(--red-fill); }
.dot.warn { background: var(--amber-fill); }
.menu-btn {
  position: relative;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: 15px;
  line-height: 1;
  min-width: 36px; min-height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 9px;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.menu-btn:active { background: var(--surface-2); }
.menu-btn.open { color: var(--bg); background: var(--text); border-color: var(--text); }
/* the hamburger carries no alert dot (Moe 2026-08-16) — the ALERT counter
   and the alerts section already say it, on the board where you are looking */
.theme-btn { padding: 0 8px; min-width: 34px; }
.theme-btn svg { display: block; }

/* ----------------------------------------------------------------- drawer -- */
.drawer {
  flex: none;
  max-height: 48dvh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  border-bottom: 1px solid var(--line);
  background: var(--bg-elev);
  padding: 6px 16px 16px;
  z-index: 15;
}
.drawer-section { border-bottom: 1px solid var(--line-soft); padding: 0; margin: 0; }
.drawer-section:last-of-type { border-bottom: none; }
.drawer-title {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text);
  background: none;
  border: none;
  padding: 14px 0 12px;
  min-height: var(--tap);
  width: 100%;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.drawer-title .chev { margin-left: auto; transition: transform .2s ease; color: var(--faint); font-size: 10px; }
.drawer-section.collapsed .chev { transform: rotate(-90deg); }
.drawer-section.collapsed .drawer-list { display: none; }
.drawer-count { color: var(--dim); font-weight: 700; }
.drawer-count:empty { display: none; }
.drawer-list { display: flex; flex-direction: column; gap: 1px; padding-bottom: 10px; }
.drawer-item {
  border: none;
  border-left: 3px solid var(--line-strong);
  border-radius: 0;
  padding: 9px 0 9px 11px;
  background: none;
}
.drawer-item.alert { border-left-color: var(--amber-fill); }
.drawer-well {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.drawer-since { color: var(--dim); font-family: var(--mono); font-size: 11px; font-weight: 400; }
.drawer-restart { color: var(--green); font-size: 12px; margin-top: 3px; }
.drawer-nf {
  font-size: 9.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  margin-left: 6px; padding: 2px 7px; border-radius: var(--r-pill);
  color: var(--on-blue); background: var(--blue-fill); white-space: nowrap;
}
.drawer-nf.sd { color: var(--on-purple); background: var(--purple-fill); }
.drawer-nf.sent { color: var(--on-green); background: var(--green-fill); }
.drawer-nf.pre { color: var(--bg); background: var(--dim); }
/* PENDING MY SHIFT rows wear the event's own colour, tag and clock keyed off the
   same k-<kind> class so the two can never disagree (same rule as ALMS). The
   clock takes the tag's FILL as its text: the tag's own colour is white on that
   fill, and a row of white clocks would say nothing. */
.drawer-nf.k-trip { color: var(--on-red); background: var(--red-fill); }
.drawer-nf.k-msd { color: var(--on-purple, var(--purple)); background: var(--purple-fill); }
.drawer-nf.k-startup { color: var(--on-blue); background: var(--blue-fill); }
.drawer-nf.k-shutdown { color: var(--on-purple); background: var(--purple-fill); }
.drawer-nf.k-sched { color: var(--on-amber, #1a1206); background: var(--amber-fill); }
.drawer-nf.k-sent { color: var(--on-green); background: var(--green-fill); }
.drawer-since.k-trip { color: var(--red); }
.drawer-since.k-msd, .drawer-since.k-shutdown { color: var(--purple); }
.drawer-since.k-startup { color: var(--blue); }
.drawer-reason { font-size: 13.5px; color: var(--text-2); margin-top: 4px; line-height: 1.45; }
/* "no update found" is a finding, not an absence — dimmed and italic so it reads
   as the system saying it looked, never as an empty field */
.drawer-reason.none { color: var(--faint); font-style: italic; }
/* a cleared pending stays listed, visibly settled rather than outstanding */
.drawer-item.pdone { border-left-color: var(--green-fill); }
.drawer-item.pdone .drawer-well { color: var(--text-2); }
.drawer-empty { font-size: 13px; color: var(--faint); padding-bottom: 10px; }
/* carried over from an earlier shift — present, but never read as tonight's
   handover (Moe 2026-08-24) */
.drawer-divider {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--faint); padding: 12px 0 8px; margin-top: 6px;
  border-top: 1px solid var(--line);
}
.drawer-item.pold { border-left-color: var(--line); }
.drawer-item.pold .drawer-well { color: var(--text-2); }

/* ---- ALMS entry log (Moe 2026-08-16) --------------------------------------
   One tap target per well. The box is a square that fills solid green when the
   event has been entered into ALMS; it empties itself when the well moves
   again, so an empty box always means "this needs entering". */
.drawer-count.done { color: var(--green); }
.alms-row {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 2px; background: none; border: 0; border-bottom: 1px solid var(--line);
  font: inherit; color: var(--text); text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.alms-row:last-child { border-bottom: 0; }
.alms-row:active { opacity: .6; }
.alms-box {
  flex: 0 0 auto; width: 19px; height: 19px; border-radius: 4px;
  border: 2px solid var(--line-strong); background: none;
  position: relative; transition: background .12s, border-color .12s;
}
.alms-row.on .alms-box { background: var(--green); border-color: var(--green); }
.alms-row.on .alms-box::after {
  content: ""; position: absolute; left: 5px; top: 1.5px;
  width: 4px; height: 9px; border: solid var(--bg);
  border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.alms-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.alms-line { display: flex; align-items: center; gap: 7px; }
/* Fixed column so every tag starts at the same x. Well names are all BG-XXXX
   but proportional digits make them a hair different in width, which was enough
   to leave the tags visibly ragged down the list (Moe 2026-08-17). */
.alms-well {
  font-weight: 800; letter-spacing: .3px; font-size: 14px;
  flex: 0 0 auto; min-width: 74px; font-variant-numeric: tabular-nums;
}
.alms-row.on .alms-well { color: var(--dim); }
/* short cause under the well — never the whole message */
.alms-reason {
  font-size: 11.5px; color: var(--dim); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.alms-row.on .alms-reason { color: var(--faint); }
/* All tags the same size (Moe 2026-08-17): TRIP / START / M/SD are different
   lengths, so left to themselves they render as three different-width chips
   down one column. Fixed box, text centred — the row now reads as a table. */
.alms-kind {
  font-size: 10px; font-weight: 800; letter-spacing: .6px;
  padding: 3px 6px; border-radius: 4px; color: var(--dim); background: var(--line);
  flex: 0 0 auto; min-width: 52px; text-align: center; box-sizing: border-box;
}
.alms-kind.k-trip { color: var(--on-red); background: var(--red-fill); }
.alms-kind.k-start { color: var(--on-green); background: var(--green-fill); }
.alms-kind.k-msd { color: var(--on-purple, var(--purple)); background: var(--purple-fill); }
/* a commissioning is entered into the GC BEFORE its start-up can be — blue, so
   it reads as its own kind of entry rather than a second green start */
.alms-kind.k-commission { color: var(--on-blue); background: var(--blue-fill); }
/* ticked, then the well moved again — the box cleared and it needs re-entering */
.alms-again {
  font-size: 10px; font-weight: 800; letter-spacing: .6px;
  padding: 2px 6px; border-radius: 4px; color: var(--on-amber); background: var(--amber-fill);
}
/* The clock wears its event's colour, same key as the tag (Moe 2026-08-17):
   red trip, green start, purple M/SD. It takes the tag's FILL colour as text —
   the tag's own text is white on that fill, so copying `color` literally would
   have made every clock white and said nothing. */
.alms-at { margin-left: auto; align-self: flex-start; padding-top: 2px; font-size: 12px; color: var(--dim); font-variant-numeric: tabular-nums; font-weight: 700; }
.alms-at.k-trip { color: var(--red); }
.alms-at.k-start { color: var(--green); }
.alms-at.k-msd { color: var(--purple); }
.alms-at.k-commission { color: var(--blue-fill); }
.drawer-title.foract { color: var(--red); }

.drawer-sub { margin-left: 2px; border-left: 1px solid var(--line-soft); padding-left: 12px; }
.drawer-subtitle {
  font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dim);
  background: none; border: none;
  padding: 11px 0 9px;
  min-height: 40px;
  width: 100%; text-align: left;
  display: flex; align-items: center; gap: 7px;
  cursor: pointer;
}
.drawer-subtitle .chev { margin-left: auto; transition: transform .2s ease; }
.drawer-sub.collapsed .chev { transform: rotate(-90deg); }
.drawer-sub.collapsed .drawer-sublist { display: none; }
.drawer-sublist { display: flex; flex-direction: column; gap: 1px; margin-bottom: 8px; }

/* appearance control at the top of the drawer */
.drawer-pref {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 0 14px;
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: 2px;
}
.drawer-pref-label {
  font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text);
}
.segbar { display: flex; margin-left: auto; }
.segopt {
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--dim);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 0 13px;
  min-height: 32px;
  margin-right: -1px;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.segopt:first-child { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.segopt:last-child { border-radius: 0 var(--r-sm) var(--r-sm) 0; margin-right: 0; }
.segopt.on { color: var(--bg); background: var(--text); border-color: var(--text); position: relative; z-index: 1; }

.clearbtn {
  margin-top: 14px;
  width: 100%;
  min-height: var(--tap);
  background: none;
  border: 1px solid var(--line);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: 12px 0;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.clearbtn:active { background: var(--surface-2); }

/* -------------------------------------------------------- tab bar + views -- */
.view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.askview .feed { flex: 1; }
.tabbar {
  flex: none;
  display: flex;
  align-items: stretch;
  border-top: 1px solid var(--line);
  background: var(--bg);
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 20;
}
.tab {
  flex: 1;
  position: relative;
  background: none;
  border: none;
  color: var(--dim);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  min-height: 50px;
  padding: 14px 0 12px;
  cursor: pointer;
  transition: color .15s ease;
}
.tab.on { color: var(--text); }
.tab.on::before {
  content: "";
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 3px;
  background: var(--brand-fill);
}
.tab.pushtab { flex: none; width: 52px; font-size: 15px; }
.tab.pushtab.on::before { display: none; }
.tab.pushtab.on { color: var(--brand); }
.shift-ico { display: inline-flex; align-items: center; color: var(--dim); }
.shift-ico.sun.live { color: var(--amber); }
.shift-ico.moon.live { color: var(--blue); }

/* -------------------------------------------------------------- dashboard -- */
.dashview { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-y: contain; background: var(--page); }
.dash { padding: 0 14px 30px; max-width: 780px; margin: 0 auto; width: 100%; }
.dash-loading { font-size: 13px; color: var(--faint); padding: 30px 2px; }
.dash-empty { font-size: 13px; color: var(--faint); padding: 4px 0 12px; }

/* --- board summary: the one-glance row. A stat block, newspaper-style:
       big numeral, small label, hairline between. Tap jumps to the section. --- */
.dash-summary {
  display: grid;
  /* 7 tiles since DIESEL joined (Moe 2026-08-16): 6 columns left one orphan on
     a second row. 4 columns splits 4 + 3, which reads as a deliberate block. */
  grid-template-columns: repeat(4, 1fr);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  margin: 14px 0 4px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
}
.sum {
  appearance: none;
  background: none;
  border: none;
  border-right: 1px solid var(--line-soft);
  padding: 11px 2px 10px;
  min-height: var(--tap);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  cursor: pointer;
  transition: background .15s ease;
}
.sum:last-child { border-right: none; }
/* 4-up grid: kill the right rule at the end of each row, and the row rule on
   the last row, so the block reads as a table rather than stacked buttons */
.sum:nth-child(4n) { border-right: none; }
/* row rule only when a second row actually exists (7 tiles on mornings, 6 at
   night when the DIESEL tile is dropped) */
.dash-summary:has(.sum:nth-child(5)) .sum:nth-child(-n+4) { border-bottom: 1px solid var(--line-soft); }
.sum:active { background: var(--surface-2); }
.sum-n {
  font-size: 22px;
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.02em;
  color: var(--line-strong);
}
.sum-l {
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--faint);
  white-space: nowrap;
}
/* counter pairs (Moe 2026-08-16): "open / done" on one line — the open count in
   the tile's own colour, a plain slash, the closed count in green. Baseline
   aligned so the two numbers read as one figure, not as two stacked stats. */
.sum-v {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 1px;
}
.sum-sep {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-2);
  margin: 0 1px;
}
.sum-done {
  font-size: 17px;
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.02em;
  color: var(--green);
  font-variant-numeric: tabular-nums;
}
/* a tile only takes colour when it has something in it */
.sum.live .sum-l { color: var(--text-2); }
.sum.live.s-down  .sum-n { color: var(--red); }
.sum.live.s-alert .sum-n { color: var(--amber); }
.sum.live.s-act   .sum-n { color: var(--red); }
.sum.live.s-req   .sum-n { color: var(--blue); }
.sum.live.s-msd   .sum-n { color: var(--purple); }
.sum.live.s-ok    .sum-n { color: var(--green); }
/* NEW WELL (Moe 2026-09-01) — a commissioning tile, only rendered on the shifts
   that have one. Green because that is the commissioned card's own dot colour,
   and a counter must never disagree with the card it scrolls to. Declared HERE
   with the other tile colours, not at the end of the file: the grey-zero rule
   below has the same specificity and has to stay last (see its comment). */
.sum.live.s-comm  .sum-n { color: var(--green); }
/* The zero rule lives at the very END of this file — see "grey zero" there.
   It has to beat every per-tile colour rule, and they are the same specificity,
   so document order is the only thing deciding it. */

/* --- sort: quiet segmented control --- */
.dash-sort {
  flex: none;
  display: flex; align-items: center; gap: 0;
  padding: 10px 14px 0;
  max-width: 780px; margin: 0 auto; width: 100%;
  font-size: 9px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint);
  -webkit-user-select: none; user-select: none;
}
.dash-sort > .sortopt:first-of-type { margin-left: auto; border-radius: var(--r-sm) 0 0 var(--r-sm); }
.dash-sort > .sortopt:last-of-type { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.sortopt {
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--dim);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 0 12px;
  min-height: 30px;
  /* one width for all three, sized on CONTRACTOR (the longest label) so the
     segmented control reads as one column instead of three ragged chips */
  flex: 0 0 auto; min-width: 98px; text-align: center;
  margin: 0 -1px 0 0;
  border-radius: 0;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.sortopt.on { color: var(--bg); background: var(--text); border-color: var(--text); z-index: 1; }

/* --- section: a Vox category header. Bold label, thick rule, count right. --- */
.wgroup {
  border: none;
  background: none;
  padding: 0;
  margin-top: 26px;
}
.wgroup-title {
  position: sticky;
  top: 0;
  z-index: 5;
  font-size: 13px; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--text);
  padding: 12px 0 7px;
  margin: 0 0 10px;
  border-bottom: 3px solid var(--text);
  background: var(--page);
  display: flex; align-items: baseline; gap: 8px;
}
.wgroup-title .n {
  margin-left: auto;
  font-size: 12px;
  font-weight: 800;
  color: var(--dim);
}
.wgroup-title .n:empty { display: none; }
/* the rule colour is the section's meaning */
.wgroup-title.waiting { border-bottom-color: var(--amber-fill); }
.wgroup-title.foract { color: var(--red); border-bottom-color: var(--red-fill); }
.wgroup-title.foract .n { color: var(--red); }
.wgroup-title.pre { color: var(--dim); border-bottom-color: var(--line-strong); }
.wgroup.pre { opacity: .82; }

.dash-sec {
  font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text);
  margin: 22px 0 10px;
  padding-bottom: 6px;
  border-bottom: 3px solid var(--text);
  display: flex; align-items: baseline; gap: 8px;
}
.dash-sec:first-child { margin-top: 8px; }
.dash-sec .n { margin-left: auto; color: var(--dim); }
.dash-sec.waiting { border-bottom-color: var(--amber-fill); }
.dash-sec.foract { color: var(--red); border-bottom-color: var(--red-fill); }
.dash-sec.foract .n { color: var(--red); }

/* ---------------------------------------------------------------- article -- */
/* A well card reads like a news card: kicker, headline, deck, then tools.
   The 3px left bar is the only decoration, and it is flat. */
.wcard {
  position: relative;
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--surface);
  padding: 13px 15px 13px 14px;
  margin-bottom: 10px;
  box-shadow: var(--card-shadow);
}
.wcard.alert    { border-left-color: var(--amber-fill); }
.wcard.restored { border-left-color: var(--green-fill); }
.wcard.waiting  { border-left-color: var(--amber-fill); }
.wcard.foract   { border-left-color: var(--red-fill); }
.wcard.msd      { border-left-color: var(--purple-fill); }
.wcard.req.su   { border-left-color: var(--green-fill); }
.wcard.req.sd   { border-left-color: var(--purple-fill); }
.wcard.critical { border-color: var(--red-fill); border-left-color: var(--red-fill); }
.wcard.pre { opacity: .78; }
.wcard.pre.critical { opacity: 1; }

/* kicker — GC · CONTRACTOR, the category line */
.wkick {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 5px;
}
.wcard.alert    .wkick { color: var(--amber); }
.wcard.foract   .wkick { color: var(--red); }
.wcard.critical .wkick { color: var(--red); }
.wcard.msd      .wkick { color: var(--purple); }
.wcard.restored .wkick { color: var(--green); }
.wcard.req.su   .wkick { color: var(--green); }
.wcard.req.sd   .wkick { color: var(--purple); }

.wcard-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 9px;
}
/* the dot is redundant next to a coloured bar + kicker — keep it tiny */
.wdot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--line-strong); }
.wdot.orange { background: var(--amber-fill); }
.wdot.red { background: var(--red-fill); }
.wdot.green { background: var(--green-fill); }
.wdot.msd { background: var(--purple-fill); }
.wdot.req { background: var(--blue-fill); }
.wdot.alert { background: var(--amber-fill); }

/* the headline */
.wname {
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--text);
  white-space: nowrap;
}
.wsince { font-family: var(--mono); font-size: 11.5px; color: var(--faint); }
/* the deck already spells the clock out ("Tripped @15:17" / the event chain),
   so the bare timestamp in the head is noise — drop it where it duplicates.
   Falls back harmlessly to showing it on engines without :has(). */
.wcard:has(.wstatus) .wsince,
.wcard:has(.wchain) .wsince { display: none; }
/* elapsed time — the second read. Flat, no glow, escalates by colour. */
.wdur {
  font-family: var(--mono);
  font-size: 13px; font-weight: 700;
  color: var(--text-2);
  margin-left: auto;
  background: var(--surface-2);
  border-radius: var(--r-pill);
  padding: 3px 10px;
}
.wcard.restored .wdur { color: var(--green); background: var(--green-bg); }
.wdur.dur-warn { color: var(--red); background: var(--red-bg); }
.wdur.dur-crit { color: var(--on-red); background: var(--red-fill); }
.wcrit {
  color: var(--red);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .07em;
}
.wremind {
  color: var(--red);
  font-size: 11px;
  font-weight: 700;
  margin-left: auto;
  text-align: right;
}

/* status pills — flat fills, no glow */
.wtag {
  font-size: 9.5px;
  letter-spacing: .06em;
  font-weight: 800;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  line-height: 1.4;
}
.wtag.norep { color: var(--on-red); background: var(--red-fill); }
.wtag.rep { color: var(--on-green); background: var(--green-fill); }
.wtag.fup { color: var(--on-amber); background: var(--amber-fill); }
/* alarm on an already-M/SD well (BG-1822) — amber: attention, not a new trip */
.wtag.msdalarm { color: var(--on-amber); background: var(--amber-fill); }
.wtag.claim { color: var(--on-amber); background: var(--amber-fill); }
/* master/slave power link - informational, not a state: kept visually quiet
   so it never competes with TRIP or the alarm tags (Moe 2026-09-04). */
.wtag.master { color: var(--muted, #9aa0a6); background: rgba(255,255,255,.06); }
/* tripped this shift but already back — green chip inside TRIPPED THIS SHIFT */
.wtag.back { color: var(--on-green); background: var(--green-fill); }
.wtag.nf { color: var(--on-blue); background: var(--blue-fill); }
/* a well online for the first time — blue like the ALMS commission entry it needs */
.wtag.comm { color: var(--on-blue); background: var(--blue-fill); }
/* wrong GC / wrong contractor reported on a well ALMS has already settled
   (Moe 2026-08-28). Amber, not red: nothing is broken on the well, but the
   information circulating about it is, and that is his to go and correct. */
.wtag.mism { color: var(--on-amber); background: var(--amber-fill); }
.wtag.pre { color: var(--bg); background: var(--dim); }
.wtag.prekind { color: var(--dim); background: none; border: 1px solid var(--line); }
/* --- FOR YOUR ACTION lifecycle (Moe 2026-08-16) --- */
.wtag.done { color: var(--on-green); background: var(--green-fill); }
.wtag.open { color: var(--dim); background: none; border: 1px solid var(--line-strong); }
/* a completed action stays readable but visibly settled — it is no longer work */
.wcard.foract.st-completed { opacity: .62; }
.wcard.foract.st-completed .wreq { border-left-color: var(--green-fill); background: var(--green-bg); }
.wact-done { border-color: var(--green-fill); color: var(--green); font-weight: 800; }

/* legacy meta lines (still used by the request source line) */
.wgc, .wcontr {
  display: inline-block;
  color: var(--dim);
  font-size: 12.5px;
  margin: 5px 8px 0 0;
}

/* deck */
.wstatus { color: var(--text); font-size: 14px; font-weight: 600; margin: 7px 0 0; }
/* the clock carries the state colour (Moe 2026-08-16) — "Tripped @18:00" with
   @18:00 in the card's own colour. Mono + tabular so it can't jitter, and it
   inherits the row colour inside .wev where the whole line is already stated. */
.wtime { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; color: inherit; }
.wtime.t-orange, .wtime.t-alert { color: var(--amber); }
.wtime.t-red { color: var(--red); }
.wtime.t-green { color: var(--green); }
.wtime.t-msd { color: var(--purple); }
.wtime.t-req { color: var(--blue); }
.wreason { font-size: 14.5px; color: var(--text-2); margin-top: 6px; line-height: 1.5; }
/* "Reason not reported" — a stated gap, not a cause. Italic and quiet so it can
   never be mistaken for a diagnosis; the context under it is quieter still. */
.norsn { font-style: italic; color: var(--dim); font-weight: 500; }
.wev-reason.norsn { font-weight: 400; }
.wreason.wctx { font-size: 13.5px; color: var(--dim); margin-top: 3px; }
.wmsd-from { font-size: 13px; color: var(--purple); margin-top: 6px; line-height: 1.45; }
/* the ALMS reminder on a commissioning card — an instruction, not an event, so
   it reads in the ordinary text colour with the two times carrying the colour */
.wmsd-from.wcomm { color: var(--text); font-weight: 600; }
/* the new well's tank on a commissioning card (Moe 2026-08-31) — a fact about
   the well, not an instruction, so it sits quieter than the ALMS line above it
   with only the numbers carrying weight */
.wmsd-from.wdsl { color: var(--text); font-weight: 400; }
.wmsd-from.wdsl b { font-weight: 700; }
.wmsd-from.wdsl .dsub { color: var(--muted); font-size: 12px; }
/* a plain SCADA alarm note — the machine echoing a state change already on the
   card. An ordinary comment, so it reads in the ordinary comment colour; only a
   FALSE alarm (.wfa) keeps the purple of a withdrawn event. (Moe 2026-08-20) */
.wmsd-from.wnote { color: var(--muted); }

/* episode chain — a small timeline, hairline rail, no glow */
.wchain { margin: 9px 0 2px; padding-left: 14px; border-left: 1px solid var(--line); }
.wev { position: relative; font-size: 13.5px; line-height: 1.65; color: var(--dim); }
/* The dot marks the EVENT, so it sits on the event's own line — the first one.
   It used to be top:50% of the whole row, which is fine on a one-liner but on a
   trip row whose reason wraps to four lines the dot slid three lines down and
   read as belonging to nothing (Moe 2026-08-16). 0.825em = half of the 1.65
   line-height, i.e. the centre of the first line box. */
.wev::before {
  content: ""; position: absolute; left: -18px; top: 0.825em;
  transform: translateY(-50%);
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--bg); border: 1.5px solid var(--line-strong);
}
/* and the dot carries the event's colour, same rule as the clock: a trip dot is
   red, a start dot green — outlined while it is history, filled when it is the
   current state of the well. */
.wev.ev-trip::before { border-color: var(--red); }
.wev.ev-start::before { border-color: var(--green); }
.wev.ev-alert::before { border-color: var(--amber); }
.wev.ev-msd::before { border-color: var(--purple); }
.wev.cur { color: var(--text); font-weight: 700; }
.wev.ev-trip { color: var(--red); }
.wev.ev-start { color: var(--green); }
.wev.ev-alert { color: var(--amber); }
.wev.ev-msd { color: var(--purple); }
.wev-reason { color: var(--dim); font-size: 12.5px; font-weight: 400; }
.wev.cur.ev-trip::before { background: var(--red-fill); border-color: var(--red-fill); }
.wev.cur.ev-start::before { background: var(--green-fill); border-color: var(--green-fill); }
.wev.cur.ev-alert::before { background: var(--amber-fill); border-color: var(--amber-fill); }
.wev.cur.ev-msd::before { background: var(--purple-fill); border-color: var(--purple-fill); }

/* the ask — a pull-quote. This is the thing you act on. */
.wreq {
  background: var(--surface-2);
  border: none;
  border-left: 3px solid var(--amber-fill);
  color: var(--text);
  font-size: 14.5px;
  font-weight: 500;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 9px 12px;
  margin-top: 10px;
  line-height: 1.45;
}
/* the ball is in OUR court */
.wreq.req-onus {
  border-left-color: var(--red-fill);
  background: var(--red-bg);
  color: var(--text);
}
.wnote {
  background: var(--surface-2); color: var(--text-2);
  border: none; border-left: 3px solid var(--line-strong);
  font-size: 13.5px;
  border-radius: 0 var(--r-sm) var(--r-sm) 0; padding: 9px 12px; margin-top: 10px;
}

/* progress steps */
.wsteps { margin-top: 11px; border-top: 1px solid var(--line-soft); padding-top: 9px; }
.wsteps-hint { float: right; font-weight: 700; letter-spacing: .06em; color: var(--faint); text-transform: none; }
.wstep.tap { cursor: pointer; margin: 0 -6px; padding: 2px 6px; border-radius: var(--r-sm); }
.wstep.tap:active { background: var(--surface-2); }
.wstep.tap .wstep-ico { color: var(--line-strong); }
.wstep.busy { opacity: .5; }
.wsteps-head {
  font-size: 9.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 6px;
}
.wstep {
  display: flex; align-items: baseline; gap: 9px;
  font-size: 13.5px; line-height: 1.6; color: var(--dim);
}
.wstep-ico { font-size: 11px; color: var(--line-strong); width: 11px; flex: none; }
.wstep-what { flex: 1; }
.wstep-at { font-family: var(--mono); font-size: 11px; color: var(--faint); white-space: nowrap; }
.wstep.done .wstep-ico { color: var(--green); }
.wstep.done .wstep-what { color: var(--text); }
.wstep.done .wstep-at { color: var(--green); }

/* tools */
.wacts { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.wact {
  background: none;
  border: 1px solid var(--line);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 0 14px;
  min-height: 38px;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.wact:active { background: var(--text); color: var(--bg); border-color: var(--text); }
.wact.copied { border-color: var(--green-fill); color: var(--on-green); background: var(--green-fill); }
.wact-copy { border-color: var(--line-strong); color: var(--text); }
.wact-gen { border-color: var(--red-fill); color: var(--red); }

/* SENT tray */
.wsent { margin-top: 4px; }
.wsent > summary {
  cursor: pointer;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--green);
  padding: 11px 2px;
  min-height: 40px;
  display: flex; align-items: center; gap: 8px;
  user-select: none;
  list-style: none;
}
.wsent > summary::-webkit-details-marker { display: none; }
.wsent > summary::before { content: "▸"; transition: transform .2s ease; display: inline-block; }
.wsent[open] > summary::before { transform: rotate(90deg); }
.wsent > summary .n { color: var(--dim); }

.dash-meta {
  font-size: 11.5px; color: var(--faint);
  margin-top: 22px; padding-top: 12px;
  border-top: 1px solid var(--line-soft);
  line-height: 1.6;
}
#cleared-reset { text-decoration: underline; color: var(--text-2) !important; }

/* --------------------------------------------------------------- timeline -- */
.timeview { overflow: hidden; background: var(--page); }
.time-controls {
  flex: none;
  padding: 11px 14px 10px;
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.time-controls .chips { margin-top: 0; gap: 6px; }
.tl-range, .tl-kind {
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  padding: 8px 13px; min-height: 36px; border-radius: var(--r-pill);
}
.tl-range.on, .tl-kind.on { color: var(--bg); background: var(--text); border-color: var(--text); }
.tl-filter {
  flex: 1; min-width: 130px;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 16px; /* 16px stops iOS zooming the page on focus */
  padding: 9px 12px;
  min-height: 38px;
  border-radius: var(--r-sm);
  outline: none;
}
.tl-filter::placeholder { font-size: 13px; color: var(--faint); }
.tl-filter:focus { border-color: var(--text); }
.timeline { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 4px 14px 30px; }
.tl-day {
  position: sticky; top: 0; z-index: 4;
  font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text); margin: 18px 0 8px; padding: 10px 0 6px;
  border-bottom: 2px solid var(--text);
  background: var(--page);
}
.tl-item {
  display: flex; gap: 12px;
  padding: 9px 0;
  border-left: 2px solid var(--line);
  padding-left: 13px;
  margin-left: 3px;
}
.tl-item.t-trip { border-left-color: var(--red-fill); }
.tl-item.t-start { border-left-color: var(--green-fill); }
.tl-item.t-false_alarm { border-left-color: var(--line-strong); }
.tl-item.t-msd, .tl-item.t-planned_msd, .tl-item.t-msd_request { border-left-color: var(--purple-fill); }
.tl-item.t-email { border-left-color: var(--amber-fill); }
.tl-time { font-family: var(--mono); font-size: 11.5px; color: var(--faint); flex: none; width: 40px; padding-top: 2px; }
.tl-body { min-width: 0; }
.tl-head { font-size: 14px; font-weight: 700; }
.tl-head .tl-type { color: var(--dim); font-size: 9.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; margin-left: 8px; }
.tl-item.t-trip .tl-type { color: var(--red); }
.tl-item.t-start .tl-type { color: var(--green); }
.tl-sum { font-size: 13.5px; color: var(--text-2); margin-top: 3px; line-height: 1.45; word-break: break-word; }
.tl-status { color: var(--text); font-size: 13.5px; font-weight: 600; margin-top: 3px; }
.tl-wellmeta { color: var(--dim); font-size: 12.5px; }

.tlw {
  position: relative;
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--surface);
  padding: 12px 14px; margin: 10px 0;
  box-shadow: var(--card-shadow);
}
.tlw.foract { border-left-color: var(--red-fill); }
.tlw.critical { border-color: var(--red-fill); border-left-color: var(--red-fill); }
.tlw .tlw-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.tlw .wname { font-size: 18px; }
.tlw .wdur { margin-left: auto; font-size: 12.5px; }
.tlw-ev { font-size: 13.5px; margin: 5px 0 0 16px; color: var(--text-2); }
.tlw-ev.h-trip { color: var(--red); }
.tlw-ev.h-start { color: var(--green); }
.tlw-ev.tlw-msd { color: var(--purple); }
.tlw-ev.tlw-alert { color: var(--amber); }
.tlw-ev.tlw-req { color: var(--red); font-weight: 700; }
.tlw-ev.tlw-rem { color: var(--red); font-weight: 700; text-transform: uppercase; }

/* ------------------------------------------------------------------- rigs -- */
.rigview { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 10px 14px 30px; background: var(--page); }
.rig-top { margin: 4px 0 10px; }
.rcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--r);
  padding: 13px 15px;
  margin-bottom: 10px;
  box-shadow: var(--card-shadow);
}
.rcard.mine { border-left-color: var(--brand-fill); }
.rhead { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.rhead .wname { font-size: 18px; }
.rjob {
  font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  padding: 3px 8px; border-radius: var(--r-pill); border: 1px solid var(--line);
  color: var(--dim);
}
.rjob.j-INSTALLATION { color: var(--blue); border-color: var(--blue); }
.rjob.j-POOH, .rjob.j-DISMANTLE, .rjob.j-CUTCABLE { color: var(--amber); border-color: var(--amber); }
.rjob.j-RIGRELEASE { color: var(--faint); }
.rlabel {
  font-size: 10px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  color: var(--bg); background: var(--dim); border-radius: var(--r-pill); padding: 3px 8px;
}
.rcard.mine .rlabel { color: var(--on-brand); background: var(--brand-fill); }
.rwhy { color: var(--text); font-size: 14.5px; margin-top: 6px; font-weight: 700; }
.rwhen { color: var(--text-2); font-size: 14px; margin-top: 4px; }
.rmeta { color: var(--dim); font-size: 13px; margin-top: 4px; }
.rcomment { color: var(--faint); font-size: 13px; margin-top: 6px; line-height: 1.45; }
.rtels { display: flex; gap: 8px; margin-top: 11px; flex-wrap: wrap; }
.rtel {
  font-family: var(--mono); font-size: 13px; font-weight: 700; text-decoration: none;
  color: var(--green); border: 1px solid var(--line);
  padding: 0 14px; min-height: 38px; display: inline-flex; align-items: center;
  border-radius: var(--r-sm);
}
.rtel:active { background: var(--surface-2); }
.rtel.dead { color: var(--faint); }
.rig-others .chev { transition: transform .2s ease; display: inline-block; }
.rig-others.closed .chev { transform: rotate(-90deg); }

/* -------------------------------------------------------------------- ask -- */
.feed {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 22px 16px 12px;
  scroll-behavior: smooth;
  background: var(--bg);
}
.feed > * { max-width: 780px; margin-left: auto; margin-right: auto; }
.empty { text-align: left; padding-top: 9vh; }
.empty-title { font-size: 24px; font-weight: 800; letter-spacing: -.02em; line-height: 1.2; }
.empty-sub { color: var(--dim); margin-top: 9px; font-size: 15px; line-height: 1.5; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 24px; }
.chip {
  background: none;
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 13.5px;
  padding: 10px 15px;
  min-height: 40px;
  cursor: pointer;
  border-radius: var(--r-pill);
  transition: background .15s ease;
}
.chip:active { background: var(--surface-2); }

.msg { margin-bottom: 20px; }
.msg.user { display: flex; justify-content: flex-end; }
.msg.user .body {
  border: none;
  background: var(--surface-2);
  padding: 11px 15px;
  border-radius: 16px 16px 4px 16px;
  max-width: 86%;
  white-space: pre-wrap;
}
.msg.bot .body { border-left: 3px solid var(--brand-fill); padding: 2px 0 2px 15px; }
.msg .meta { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--faint); margin-bottom: 6px; }
.msg.user .metawrap { text-align: right; max-width: 86%; }
.toolline { font-family: var(--mono); font-size: 12px; color: var(--dim); margin: 0 0 8px 18px; }
.toolline::before { content: "▸ "; color: var(--line-strong); }
.thinking { font-size: 13px; color: var(--dim); margin-left: 18px; display: inline-block; }
.thinking::after {
  content: ""; display: inline-block; width: 7px; height: 13px;
  background: var(--text); margin-left: 4px; vertical-align: text-bottom;
  animation: blink 1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
.errline { font-size: 13px; color: var(--red); margin: 6px 0 6px 18px; }

/* rendered markdown */
.body h1, .body h2, .body h3 { font-size: 16px; font-weight: 800; margin: 15px 0 6px; color: var(--text); }
.body p { margin: 8px 0; }
.body ul, .body ol { margin: 8px 0 8px 20px; }
.body li { margin: 4px 0; }
.body code {
  font-family: var(--mono); font-size: 13px;
  background: var(--surface-2); border: none;
  padding: 2px 5px; border-radius: 4px;
}
.body pre {
  background: var(--surface-2); border: 1px solid var(--line-soft);
  padding: 12px 14px; overflow-x: auto; border-radius: var(--r-sm); margin: 10px 0;
}
.body pre code { background: none; padding: 0; font-size: 12.5px; }
.body table { border-collapse: collapse; margin: 12px 0; font-size: 13.5px; width: 100%; display: block; overflow-x: auto; }
.body th, .body td { border: 1px solid var(--line); padding: 8px 11px; text-align: left; white-space: nowrap; }
.body th { font-size: 10.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--dim); background: var(--surface-2); }
.body strong { color: var(--text); font-weight: 700; }
.wellid {
  font-family: var(--mono); font-size: .92em; font-weight: 700;
  color: var(--text); background: var(--surface-2);
  border: none; padding: 1px 5px; border-radius: 4px; white-space: nowrap;
}
tr.row-ok td { background: var(--green-bg); }
tr.row-ok td:nth-child(2) { color: var(--green); }
tr.row-bad td { background: var(--red-bg); }
tr.row-bad td:nth-child(2) { color: var(--red); }
tr.row-warn td { background: var(--amber-bg); }
tr.row-warn td:nth-child(2) { color: var(--amber); }
td.note-req, tr.row-warn td.note-req {
  background: var(--surface-2); color: var(--text);
  border-left: 3px solid var(--amber-fill);
  font-weight: 500;
}
td.note-req .wellid { color: var(--amber); }

/* ------------------------------------------------------------------ input -- */
.inputbar {
  flex: none;
  border-top: 1px solid var(--line);
  padding: 10px 14px;
  padding-bottom: calc(10px + env(safe-area-inset-bottom));
  background: var(--bg);
}
.inputwrap { max-width: 780px; margin: 0 auto; display: flex; gap: 9px; align-items: flex-end; }

/* --- attachment tray: staged files above the box, so the caption you type
       afterwards is still the focus --- */
.attach-tray {
  max-width: 780px; margin: 0 auto 9px;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.att {
  position: relative;
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: var(--r-sm);
  padding: 7px 30px 7px 10px;
  max-width: 210px;
}
.att.img { padding: 0; border: none; background: none; }
.att.img img {
  width: 62px; height: 62px; object-fit: cover;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  display: block;
}
.att-ico { color: var(--dim); font-size: 13px; flex: none; }
.att-name {
  font-size: 12.5px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.att-x {
  position: absolute; top: -6px; right: -6px;
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid var(--bg);
  background: var(--text); color: var(--bg);
  font-size: 13px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
}
.att:not(.img) .att-x { top: 50%; right: 5px; transform: translateY(-50%); border: none; width: 20px; height: 20px; }

.attach-btn {
  flex: none;
  width: var(--tap); height: var(--tap);
  background: none;
  border: 1px solid var(--line);
  color: var(--text-2);
  font-size: 22px;
  font-weight: 400;
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
  transition: background .15s ease;
}
.attach-btn:active { background: var(--surface-2); }

/* attachments inside a sent message */
.msg-atts { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 7px; }
.msg-atts img {
  width: 116px; max-height: 150px; object-fit: cover;
  border-radius: var(--r-sm); display: block;
}
.msg-file {
  font-size: 12.5px; color: var(--text-2);
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 5px 9px;
}
.msg.user .body.att-only { padding: 6px; }
.msg.user .body.att-only .msg-atts { margin-bottom: 0; }
#input {
  flex: 1 1 0;
  min-width: 0;          /* without this the textarea refuses to shrink and the
                            send button gets pushed off a narrow phone */
  overflow-y: auto;      /* never silently swallow a line */
  background: var(--surface-2);
  border: 1px solid transparent;
  color: var(--text);
  font-size: 16px;
  line-height: 1.4;
  padding: 12px 15px;
  border-radius: 20px;
  resize: none;
  outline: none;
  max-height: 132px;
}
#input:focus { border-color: var(--line-strong); }
#input::placeholder { color: var(--faint); font-size: 15px; }
#send {
  flex: none;
  width: var(--tap); height: var(--tap);
  background: var(--text);
  color: var(--bg);
  border: none;
  font-size: 19px;
  font-weight: 700;
  cursor: pointer;
  border-radius: 50%;
  transition: opacity .12s ease;
}
#send:active { opacity: .75; }
#send:disabled { background: var(--surface-2); color: var(--faint); cursor: default; }

/* ---------------------------------------------------------- small phones -- */
@media (max-width: 400px) {
  .status { gap: 8px; }
  .st { font-size: 9px; }
  .wordmark.sm { font-size: 14px; }
  .dash { padding-left: 12px; padding-right: 12px; }
  .sum-n { font-size: 20px; }
  .sum-l { font-size: 8px; letter-spacing: .05em; }
  .wname { font-size: 19px; }
  .feed { padding: 18px 14px 8px; }
}

/* ======================================================================
   DIESEL board (Moe 2026-08-16)
   Its own section, three categories kept visually distinct because they
   need three different reactions: forward a REQUEST, order for a LOW
   tank, investigate a DROP. Same editorial language as the well cards —
   kicker, headline, deck — so it reads as one board, not a bolt-on.
   ====================================================================== */
.wgroup-title.diesel { border-bottom-color: var(--blue-fill); }

/* --- reminder bar: a deadline, so it sits above the cards, not among them --- */
.drem {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 12px 14px;
  margin: 0 0 14px;
  background: var(--amber-bg);
  border-left: 3px solid var(--amber-fill);
  border-radius: 0 6px 6px 0;
}
.drem-t {
  flex: 1 1 180px;
  font-size: 13.5px; font-weight: 700; color: var(--amber);
  line-height: 1.35;
}
.drem-b {
  min-height: 40px;
  padding: 0 16px;
  border: none; border-radius: 6px;
  background: var(--amber-fill); color: var(--on-amber);
  font: inherit; font-size: 13px; font-weight: 800;
  letter-spacing: .02em;
  cursor: pointer;
}
.drem-b.copied { background: var(--green-fill); color: var(--on-green); }
.drem-x {
  min-height: 40px;
  padding: 0 10px;
  background: none; border: none;
  color: var(--dim); font: inherit; font-size: 12.5px;
  text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}
.drem.sent {
  background: var(--green-bg);
  border-left-color: var(--green-fill);
}
.drem.sent .drem-t { color: var(--green); font-weight: 600; }

/* --- category sub-header inside the section --- */
.dsub {
  display: flex; align-items: baseline; gap: 8px;
  margin: 16px 0 8px;
  font-size: 11.5px; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--dim);
}
.dsub .n { margin-left: auto; font-weight: 800; }

/* --- the card --- */
.dcard {
  border-left: 3px solid var(--line-strong);
  padding: 12px 14px;
}
.dcard.d-req  { border-left-color: var(--blue-fill); }
.dcard.d-low  { border-left-color: var(--amber-fill); }
.dcard.d-drop { border-left-color: var(--red-fill); }

.dkicker {
  font-size: 11px; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--dim);
  margin-bottom: 4px;
}
.d-req  .dkicker { color: var(--blue); }
.d-low  .dkicker { color: var(--amber); }
.d-drop .dkicker { color: var(--red); }

.dhead {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px;
}
.dwell {
  font-size: 20px; font-weight: 800; letter-spacing: -.01em;
  color: var(--text);
}
/* the one number that matters, per kind: litres asked / % left / % missing */
.dbig {
  font-variant-numeric: tabular-nums;
  font-size: 15px; font-weight: 800;
  color: var(--text-2);
}
.d-drop .dbig { color: var(--red); }
.dtag {
  margin-left: auto;
  font-size: 10.5px; font-weight: 800; letter-spacing: .06em;
  padding: 3px 8px; border-radius: 4px;
  white-space: nowrap;
}
.dtag.d-req  { background: var(--blue-bg);  color: var(--blue); }
.dtag.d-low  { background: var(--amber-bg); color: var(--amber); }
.dtag.d-drop { background: var(--red-fill); color: var(--on-red); }

/* --- the fuel line: was -> now, and what it cost, in litres --- */
/* Its own row rather than more text in the deck: these are the figures Moe
   reacts to, they are numeric, and tabular-nums keeps them in a column down a
   stack of cards. Wraps as a unit on a phone instead of splitting an arrow off
   its number. */
.dvol {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: 6px; margin-top: 7px;
  font-variant-numeric: tabular-nums;
  font-size: 13.5px; font-weight: 700;
  color: var(--text-2);
}
.dv-was { color: var(--faint); }
.dv-ar  { color: var(--faint); font-weight: 600; }
.dv-now { color: var(--text); font-weight: 800; }
.dv-gone {
  padding: 1.5px 7px; border-radius: 999px;
  background: var(--amber-bg); color: var(--amber);
  font-weight: 800; white-space: nowrap;
}
/* the drop itself is only ever amber now — red is decided by the unaccounted
   litres beside it, not by how much the well burned */
.dv-gone.hot { background: var(--amber-bg); color: var(--amber); }
/* Inside its own normal burn: still a drop worth watching, but nothing is
   unaccounted for, so it drops out of red. */
.dcard.d-quiet { border-left-color: var(--amber); }
.dcard.d-quiet .dkicker,
.dcard.d-quiet .dbig { color: var(--amber); }
.dcard.d-quiet .dtag.d-drop { background: var(--amber-bg); color: var(--amber); }
/* DAILY USE: what the well is entitled to burn, in litres and percent, sitting
   next to the drop it gets subtracted from. Quiet by default — it is context,
   not an alarm. */
.dv-day {
  padding: 1.5px 7px; border-radius: 999px;
  border: 1px solid var(--line, rgba(128,138,157,.35));
  color: var(--text-2); font-weight: 700; font-size: 12.5px; white-space: nowrap;
}
/* No daily-consumption line in the report (Moe 2026-08-19). This is NOT a
   detail — with nothing to subtract, the whole drop is being counted as
   unaccounted for, which is what puts the well in the email. It has to be
   visible enough that Moe never mails a GC without knowing it. */
/* The well is down (Moe 2026-08-19). Loud, because it reframes every figure on
   the card: a well that is off should burn nothing, so the whole drop is
   unaccounted for. */
.dv-msd {
  padding: 1.5px 7px; border-radius: 999px;
  background: var(--text-2); color: var(--surface, #fff);
  font-weight: 800; font-size: 11.5px; letter-spacing: .04em;
  white-space: nowrap; text-transform: uppercase;
}
/* a down well that still reports a daily burn contradicts itself — flag it
   rather than quietly subtracting a figure that should not exist */
.dv-day.odd { border-color: var(--amber); color: var(--amber); }
.dv-day.none {
  border-style: dashed; border-color: var(--amber);
  background: var(--amber-bg); color: var(--amber); font-weight: 800;
}
/* the second row of the fuel block: down-state + daily-use chips, kept off the
   numbers line so the litres never wrap around a badge (Moe 2026-08-31) */
.dvol.dvol-tags { margin-top: 6px; }
.dcard.d-hot { border-left-color: var(--red); }
.dcard.d-hot .dbig { color: var(--red); }
/* stays inline right after the figures — it is the denominator, not a stat */
.dv-cap { color: var(--faint); font-weight: 600; white-space: nowrap; }

/* --- emailed to the GC: green, and it outranks the red --- */
/* The card stays on the board because the diesel is still unexplained, but the
   colour has to say "off my list" at a glance, so it overrides d-hot. */
.dcard.d-sent { border-left-color: var(--green-fill); background: var(--green-bg); }
.dcard.d-sent .dkicker { color: var(--green); }
.dcard.d-sent .dbig { color: var(--green); }
.dcard.d-sent .dv-gone,
.dcard.d-sent .dv-gone.hot { background: var(--green-fill); color: var(--on-green); }
.dtag.d-sent-tag { background: var(--green-fill); color: var(--on-green); }

/* draft button on the ABNORMAL DROP subheader */
.dsub-b {
  margin-left: auto;
  font: inherit; font-size: 11px; font-weight: 800; letter-spacing: .04em;
  padding: 5px 11px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--red-fill); background: var(--red-fill); color: var(--on-red);
}
.dsub-b.done { border-color: var(--green-fill); background: transparent; color: var(--green); }
.dsub .n + .dsub-b { margin-left: 10px; }

/* --- the draft sheet --- */
.dsheet-wrap { position: fixed; inset: 0; z-index: 90; display: flex; align-items: flex-end; justify-content: center; }
.dsheet-bg { position: absolute; inset: 0; background: rgba(8,12,18,.55); }
.dsheet {
  position: relative; width: 100%; max-width: 720px; max-height: 92vh;
  display: flex; flex-direction: column;
  background: var(--page); border-radius: 14px 14px 0 0;
  border: 1px solid var(--line); border-bottom: 0;
  box-shadow: 0 -8px 40px rgba(0,0,0,.35);
}
.dsheet-top {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface); border-radius: 14px 14px 0 0;
}
.dsheet-t { font-size: 12px; font-weight: 800; letter-spacing: .07em; color: var(--text); }
.dsheet-t .n { margin-left: 8px; color: var(--dim); font-weight: 700; letter-spacing: 0; }
.dsheet-x {
  margin-left: auto; border: 0; background: transparent; cursor: pointer;
  font-size: 24px; line-height: 1; color: var(--dim); padding: 0 4px;
}
/* minmax(0,1fr), not 1fr: a grid item defaults to min-width:auto, so the 640px
   email table inside the preview was forcing every card wider than the phone
   and pushing the addresses off screen. */
/* min-height:0 is load-bearing: a flex item defaults to min-height:auto, so the
   body refused to shrink below its content, overflowed the 92vh sheet, and the
   finger scrolled the dashboard behind instead. overscroll-behavior stops the
   page moving when the list hits its end. */
.dsheet-body {
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  min-height: 0; flex: 1 1 auto; overscroll-behavior: contain;
  padding: 12px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px;
}
/* Belt to the JS lock's braces: nothing behind the sheet takes a touch. */
body.sheet-open { overflow: hidden; touch-action: none; }
body.sheet-open .dsheet-wrap, body.sheet-open .dsheet-body { touch-action: auto; }

.dmail { min-width: 0; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 13px 14px; }
.dmail.sent { border-color: var(--green-fill); }
.dmail-h { display: flex; align-items: center; gap: 9px; font-size: 17px; font-weight: 800; color: var(--text); }
.dmail-w { font-size: 12px; font-weight: 700; color: var(--dim); }
.dmail-sent {
  margin-left: auto; font-size: 10.5px; font-weight: 800; letter-spacing: .06em;
  padding: 3px 8px; border-radius: 4px; background: var(--green-fill); color: var(--on-green);
}
/* What was deliberately left out of this draft: wells of the same GC emailed
   earlier in the shift. Named, so a missing well never reads as a bug. */
.dmail-skip {
  margin-top: 8px; padding: 6px 9px; border-radius: 6px;
  background: var(--green-soft, var(--surface-2)); color: var(--dim);
  font-size: 11.5px; font-weight: 600; line-height: 1.4; word-break: break-word;
}
.dmail-none { padding: 22px 14px; text-align: center; color: var(--dim); font-size: 13.5px; }
.dmail-f {
  display: flex; gap: 8px; margin-top: 7px;
  font-size: 12.5px; color: var(--text-2); word-break: break-word;
}
.dmail-f span {
  flex: 0 0 54px; color: var(--faint); font-weight: 700;
  text-transform: uppercase; font-size: 10.5px; letter-spacing: .05em; padding-top: 2px;
}
/* The preview is the real email markup, so it must not inherit dash styling —
   what Moe sees here is exactly the bytes that go on the clipboard. */
.dmail-prev {
  margin-top: 11px; padding: 12px; overflow-x: auto;
  background: #ffffff; border: 1px solid var(--line-soft); border-radius: 8px;
}
.dmail-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.dmail-b {
  font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
  padding: 9px 14px; border-radius: 8px;
  border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--text);
}
.dmail-b.ok { border-color: var(--green-fill); background: var(--green-fill); color: var(--on-green); }
.dmail-b.sub { color: var(--dim); }
.dmail-b.copied { border-color: var(--green-fill); color: var(--green); }
/* Waiting on the PC watcher: dimmed, spinning, and NOT claiming success yet. */
.dmail-b.wait { display: inline-flex; align-items: center; gap: 8px; background: var(--surface-2); color: var(--text-2); border-color: var(--line-strong); }
.dmail-b.done { border-color: var(--green-fill); background: var(--green-fill); color: var(--on-green); }
.dmail-b.done::before { content: "✓"; margin-right: 7px; font-weight: 900; }
.dmail-b.err { border-color: var(--red, #b3261e); color: var(--red, #b3261e); background: var(--surface-2); }
.dmail-b[disabled] { cursor: default; }
.dmail-b.wait .spin {
  width: 13px; height: 13px; flex: 0 0 13px; border-radius: 50%;
  border: 2px solid var(--line-strong); border-top-color: var(--text-2);
  animation: dspin .7s linear infinite;
}
@keyframes dspin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .dmail-b.wait .spin { animation-duration: 2.4s; } }

.ddeck {
  margin-top: 5px;
  font-size: 14px; line-height: 1.45; color: var(--text-2);
}
.dmeta {
  margin-top: 6px;
  font-size: 12px; color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* summary tile */
.sum.s-diesel.live .sum-n { color: var(--blue); }

/* ---- PENDING PRE-SHIFT (Moe 2026-08-16) ----
   The pending list Moe feeds into chat: what is outstanding, plus the LATEST
   thing email/WhatsApp says about it. Slate rail — deliberately not one of the
   trip colours, because a pending item is carried-over work, not an event. */
.wcard.pendingpre { border-left-color: var(--dim); }
.wcard.pendingpre .wkick { color: var(--dim); }
.wdot.pending { background: var(--dim); }
.wtime.t-pending { color: var(--dim); }
.sum.live.s-pending .sum-n { color: var(--text); }
/* LATEST line: the label is a small caps chip so the found status is visibly a
   FINDING from the groups, not something we decided. */
.wpend-st { font-size: 14px; color: var(--text-2); margin-top: 7px; line-height: 1.5; }
.wpend-lbl {
  font-size: 10.5px; font-weight: 800; letter-spacing: .07em;
  color: var(--blue); margin-right: 6px; vertical-align: 1px;
}
.wpend-src {
  font-family: var(--mono); font-size: 11.5px; color: var(--faint);
  margin-top: 3px; font-variant-numeric: tabular-nums;
}



/* --- foldable card detail (Moe 2026-08-17) ---------------------------------
   Cards open FOLDED: head row, event chain and the REQ box stay, the reading
   material (cause, steps, buttons) folds away. Collapsed, the cause survives as
   one clamped line — a board of identical headers is clean and useless. */
.wcard-head { cursor: pointer; }
.wfold {
  margin-left: auto;
  flex: none;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0;
  background: transparent;
  color: var(--muted);
  font: inherit; font-size: 17px; line-height: 1;
  border-radius: 6px;
  transform: rotate(90deg);          /* › points down when the card is open */
  transition: transform .15s ease, color .15s ease;
  cursor: pointer;
}
.wcard.folded .wfold { transform: rotate(0deg); }
.wcard-head:active .wfold { color: var(--text); }
/* the one-line peek, shown only while folded */
.wpeek {
  margin-top: 7px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wpeek.norsn { font-style: italic; opacity: .8; }
.wcard:not(.folded) .wpeek { display: none; }
.wcard.folded .wdet { display: none; }
/* the chain keeps its LINES while folded — when a well tripped and came back is
   the point of the card — but not the trip reason hanging off the trip row,
   which wraps to four lines and is the wall of text the fold exists to remove.
   The one-line peek carries the cause instead. */
.wcard.folded .wev-reason { display: none; }
/* a folded card is a tighter object than an open one */
.wcard.folded { padding-bottom: 11px; }

/* ---- COLLAPSE THE WHOLE CARD (Moe 2026-08-21) -----------------------------
   Folding hides the reading material; collapsing takes the card down to its one
   head line so dealt-with work stops using up the board. Everything but the head
   row goes — including the GC · CONTRACTOR kicker, which is a second line. */
.wcoll {
  flex: none;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0;
  background: transparent;
  color: var(--muted);
  font: inherit; font-size: 17px; line-height: 1;
  border-radius: 6px;
  cursor: pointer;
}
.wcoll:active { color: var(--text); }
/* the fold chevron sits at the end of the head row; the collapse button follows
   it, so the auto-margin that used to push the chevron right moves here */
.wcard-head .wfold { margin-left: auto; }
.wcard.collapsed > *:not(.wcard-head):not(.dhead) { display: none; }
/* a diesel card collapses to its own head row (Moe 2026-08-23) */
.wcard.dcard.collapsed .dkicker { display: none; }
.dhead .wcoll { margin-left: auto; }
.dtag.new { color: var(--on-blue); background: var(--blue-fill); }
.wcard.collapsed .wkick { display: none; }
.wcard.collapsed { padding-top: 9px; padding-bottom: 9px; }
/* a collapsed card has no details to reveal — only the + that brings it back */
.wcard.collapsed .wfold { display: none; }

/* Something landed on this card since he last looked. It has already opened
   itself; the chip says WHY it is open, and goes the moment he touches it. */
.wtag.new { color: var(--on-blue); background: var(--blue-fill); }
.wcard.justnew { box-shadow: inset 3px 0 0 0 var(--blue-fill); }

/* ---- COLLAPSE A WHOLE SECTION (Moe 2026-08-21) ----------------------------
   The control sits on the section header, opposite the title and centred on the
   rule — the title reads from the left, this reads from the right. The count
   keeps its place between them. */
.wsecfold {
  align-self: center;              /* the row is baseline-aligned; this is not text */
  flex: none;
  width: 24px; height: 24px;
  margin-left: 6px;
  display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0;
  background: transparent;
  color: var(--dim);
  font: inherit; font-size: 18px; font-weight: 700; line-height: 1;
  border-radius: 6px;
  cursor: pointer;
}
.wsecfold:active { color: var(--text); }
/* the count no longer owns the right edge — it sits beside the control */
.wgroup-title .n { margin-left: auto; }
.wgroup.seccollapsed > *:not(.wgroup-title) { display: none; }
.wgroup.seccollapsed .wgroup-title { margin-bottom: 0; }

/* --- grey zero: MUST STAY LAST IN THIS FILE ---------------------------------
   A zero keeps the neutral colour on a live tile: "0/2" means nothing is left
   on you, and a coloured 0 would read as an alarm. Every per-tile rule
   (.sum.live.s-down .sum-n, .sum.live.s-pending .sum-n, .sum.s-diesel.live
   .sum-n …) has the SAME specificity as this one, so whichever comes last wins.
   PENDING and DIESEL are declared far below the others, which is exactly how
   PENDING's 0 ended up rendering near-black while every other 0 was grey
   (Moe 2026-08-17). Anything added after this line breaks it again. */
.sum.live .sum-n.zero { color: var(--line-strong); }

/* ------------------------------------------------------- voice — مهندس -- */
/* Design-system rules apply: flat, hairlines, no glow, no pulsing. State is
   carried by a word and a hairline bar, not by animation. */

.voice-btn {
  flex: none;
  width: var(--tap); height: var(--tap);
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  cursor: pointer;
  display: grid; place-items: center;
  padding: 0;
}
.voice-btn:active { background: var(--surface-2); }
/* header placement: lives beside the wordmark, reachable from every tab.
   Slightly smaller than --tap so the topbar keeps its height; margin-right
   auto pins it to the wordmark while the status cluster stays right. */
.topbar-voice {
  width: 36px; height: 36px;
  margin-left: 2px;
  margin-right: auto;
}
.topbar-voice svg { width: 22px; height: 22px; }
.voice-btn svg { width: 26px; height: 26px; display: block; }

/* the engineer figure */
.voice-btn .hat, .voice-figure .hat { fill: var(--amber); }
.voice-btn .hat-rib, .voice-figure .hat-rib {
  fill: none; stroke: var(--bg); stroke-width: 2; stroke-linecap: round;
}
.voice-btn .head, .voice-figure .head { fill: var(--text-2); }
.voice-btn .body, .voice-figure .body { fill: var(--text); }

/* ---- panel ---- */
.voice-panel {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(15, 20, 25, .55);
  display: grid; place-items: center;
  padding: 20px;
}
.voice-panel.hidden { display: none; }

.voice-card {
  position: relative;
  width: 100%; max-width: 340px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 26px 20px 20px;
  text-align: center;
}

.voice-close {
  position: absolute; top: 8px; right: 8px;
  width: 34px; height: 34px;
  background: none; border: none; cursor: pointer;
  color: var(--dim); font-size: 15px; line-height: 1;
}

.voice-figure { width: 76px; height: 76px; margin: 0 auto 10px; }
.voice-figure svg { width: 100%; height: 100%; display: block; }

.voice-name {
  font-size: 21px; font-weight: 700; color: var(--text);
  letter-spacing: .01em;
}

.voice-state {
  margin-top: 4px; padding-bottom: 10px;
  font-family: var(--mono);
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--dim);
  border-bottom: 2px solid var(--line-soft);
}
.voice-panel.listening .voice-state { color: var(--green); border-bottom-color: var(--green); }
.voice-panel.thinking  .voice-state { color: var(--amber); border-bottom-color: var(--amber); }
.voice-panel.speaking  .voice-state { color: var(--blue);  border-bottom-color: var(--blue); }
.voice-panel.err       .voice-state { color: var(--red);   border-bottom-color: var(--red); text-transform: none; letter-spacing: 0; }

.voice-log {
  margin-top: 12px;
  max-height: 190px; overflow-y: auto;
  text-align: left;
  display: flex; flex-direction: column; gap: 7px;
}
.voice-line { font-size: 13px; line-height: 1.42; }
.voice-line.you { color: var(--text-2); }
.voice-line.you::before { content: "you  "; font-family: var(--mono); font-size: 10px; color: var(--faint); }
.voice-line.bot { color: var(--text); font-weight: 500; }
.voice-line.err { color: var(--red); font-size: 12px; }
/* a hint is not a failure — it must not read as red alarm text */
.voice-line.note { color: var(--dim); font-size: 12px; font-style: italic; }

.voice-toggle {
  margin-top: 16px; width: 100%; min-height: var(--tap);
  background: var(--text); color: var(--bg);
  border: none; border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  letter-spacing: .1em; cursor: pointer;
}
.voice-toggle:active { opacity: .75; }

/* icon variants */
.ico-line { fill: none; stroke: var(--amber); stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; }
.ico-mark rect { fill: none; stroke: var(--amber); stroke-width: 3; }
.ico-mark text { fill: var(--text); font-family: var(--sans); font-size: 30px; font-weight: 700; }
.ico-solid .hat { fill: var(--amber); }
.ico-solid .hat-rib { fill: none; stroke: var(--bg); stroke-width: 2; stroke-linecap: round; }
.ico-solid .head { fill: var(--text-2); }
.ico-solid .body { fill: var(--text); }

/* prefs */
.voice-prefs { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.voice-prefrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.voice-preflabel {
  font-family: var(--mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--faint);
}
#voice-icons { display: flex; gap: 6px; }
.voice-opt {
  width: 38px; height: 38px; padding: 5px;
  background: none; border: 1px solid var(--line); border-radius: var(--r-sm);
  cursor: pointer; display: grid; place-items: center;
}
.voice-opt svg { width: 100%; height: 100%; display: block; }
.voice-opt.on { border-color: var(--text); background: var(--surface-2); }
.voice-pick {
  flex: 1; max-width: 150px; min-height: 34px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 12px; padding: 0 8px;
}
.voice-prefnote { font-size: 10px; color: var(--faint); text-align: right; }
.voice-prefval { font-family: var(--mono); font-size: 11px; color: var(--text-2); }
/* Settings stay shut. The panel is a thing he talks to, not a control surface. */
.voice-prefs-toggle {
  display: block; margin: 10px auto 0; padding: 4px 2px;
  background: none; border: 0; cursor: pointer;
  font-family: var(--mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--faint);
}
.voice-prefs-toggle:hover { color: var(--text-2); }

/* ------------------------------------------------- ALMS upload (drawer) -- */
.almsup { margin-top: 14px; }
.almsup.busy {
  color: var(--text);
  border-color: var(--text-2);
  background:
    linear-gradient(90deg, transparent, var(--surface-2), transparent) 0 0 / 40% 100% no-repeat;
  animation: almsup-sweep 1.1s linear infinite;
}
@keyframes almsup-sweep {
  from { background-position-x: -40%; }
  to   { background-position-x: 140%; }
}
.almsup.done { color: var(--green); border-color: var(--green); background: var(--green-bg); }
.almsup.bad  { color: var(--red);   border-color: var(--red);   background: var(--red-bg); }

.alms-modal {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  padding: 24px;
}
.alms-modal.hidden { display: none; }
.alms-modal-card {
  width: min(320px, 100%);
  background: var(--surface, var(--bg));
  border: 1px solid var(--line);
  border-radius: var(--r-md, 12px);
  padding: 18px 18px 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .35);
}
.alms-modal-head {
  font-size: 11px; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--green); margin-bottom: 10px;
}
.alms-modal-head.bad { color: var(--red); }
.alms-modal-big {
  font-size: 40px; font-weight: 800; line-height: 1; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.alms-modal-sub {
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-2); margin: 4px 0 12px;
}
.alms-modal-row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 5px 0; border-top: 1px solid var(--line);
  font-size: 12px; color: var(--text-2);
}
.alms-modal-row b { color: var(--text); font-variant-numeric: tabular-nums; }
.alms-modal-err { font-size: 13px; color: var(--red); word-break: break-word; }
.alms-modal-close {
  margin-top: 14px; width: 100%; min-height: var(--tap);
  background: var(--text); color: var(--bg); border: 0;
  font-size: 11px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; border-radius: var(--r-sm); cursor: pointer;
}
.alms-modal-close:active { opacity: .85; }

/* rig sheet failed to ingest / report predates this shift (Moe 2026-09-01) */
.rig-stale {
  background: var(--amber-bg);
  color: var(--amber);
  border-left: 3px solid var(--amber-fill);
  border-radius: 4px;
  padding: 8px 10px;
  margin: 6px 0 10px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.45;
}

/* DeepSeek out of funds - between counters and cards (Moe 2026-09-01) */
.ds-nofunds {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--red-bg, #2a0f12); border: 1px solid var(--red, #ff4d4f);
  border-left: 4px solid var(--red, #ff4d4f);
  border-radius: 5px; padding: 9px 12px; margin: 8px 0 12px;
}
.ds-tag {
  background: var(--red, #ff4d4f); color: #fff; font-weight: 700;
  font-size: 11px; letter-spacing: .5px; padding: 3px 8px; border-radius: 3px;
  white-space: nowrap;
}
.ds-msg { font-size: 12.5px; color: var(--red, #ff4d4f); flex: 1 1 200px; }
.ds-fix {
  background: var(--red, #ff4d4f); color: #fff; border: 0; cursor: pointer;
  font-weight: 700; font-size: 12.5px; padding: 6px 16px; border-radius: 4px;
  white-space: nowrap;
}
.ds-fix:disabled { opacity: .65; cursor: default; }
.ds-fix:active { transform: translateY(1px); }

/* KEPT SHUT DOWN - still a trip, held down, timer frozen (Moe 2026-09-02) */
.wtag.kept {
  background: var(--amber-bg); color: var(--amber);
  border: 1px solid var(--amber-fill);
}
