/* =====================================================================
   FLEET ARMOR — UI 2. Loaded AFTER app.css, so it wins on the cascade.

   Kept deliberately as its own file rather than a rewrite of app.css:
   app.css is 1,849 lines of hard-won behaviour (phone card tables, the
   route dial, forced-colors, safe-area padding) and most of its comments
   record a real incident. Deleting it to restyle would put all of that
   at risk at once. Remove the one <link> in base.html and the dashboard
   is exactly as it was.

   The brief: more user friendly, more intuitive, more futuristic.
   The read on the old design: everything glowed equally, so nothing was
   important. Six same-weight pills per row, green meaning seven
   different things, 77px rows, uppercase everywhere. Futuristic here
   means PRECISION -- hairlines, tabular numerals, real depth, one vivid
   accent spent carefully -- not more glow.
   ===================================================================== */

/* ---------------------------------------------------------- 1. TOKENS */
:root {
  /* Neutrals are near-neutral with a cool cast. The old ramp was tinted
     green, which left the green accent nothing to stand out against. */
  --bg:         #05080c;
  --bg-2:       #080d13;
  --panel:      #0c131a;
  --panel-2:    #111a22;
  --panel-3:    #16212b;
  --line:       #1d2a35;
  --line-soft:  #15202a;

  --text:       #e8f1f0;
  --text-2:     #b9cac7;
  --muted:      #93a8a6;        /* 4.8:1 on --bg, was #5f7d6e at 2.9:1 */

  --accent:     #00ff95;
  --accent-2:   #35ffb0;
  --accent-dim: #0cc47a;
  --accent-ink: #00160d;        /* text ON accent */
  --accent-a12: rgba(0,255,149,.12);
  --accent-a20: rgba(0,255,149,.20);
  --accent-a35: rgba(0,255,149,.35);

  --cyan:       #52dcff;
  --ok:         #2ee6a8;
  --warn:       #ffb84d;
  --bad:        #ff5f79;

  --radius:     12px;
  --radius-sm:  8px;
  --radius-pill: 999px;

  /* Depth, not haze. A hairline + a real shadow reads as a surface; a
     blanket glow reads as fog. */
  --elev-1: 0 1px 0 rgba(255,255,255,.03), 0 1px 2px rgba(0,0,0,.5);
  --elev-2: 0 1px 0 rgba(255,255,255,.04), 0 6px 20px rgba(0,0,0,.55);
  --glow:      0 0 16px rgba(0,255,149,.18);
  --glow-soft: 0 0 0 1px rgba(0,255,149,.07), 0 8px 26px rgba(0,0,0,.5);

  --mono: ui-monospace, "Cascadia Mono", "JetBrains Mono", "SF Mono", Consolas, monospace;

  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
  --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
}

:root[data-theme="light"] {
  --bg:         #eef2f5;
  --bg-2:       #f6f8fa;
  --panel:      #ffffff;
  --panel-2:    #f4f7f9;
  --panel-3:    #eaeff3;
  --line:       #c9d6dd;
  --line-soft:  #dde6eb;

  --text:       #0c1719;
  --text-2:     #33474b;
  --muted:      #56686c;        /* 5.9:1 on --panel */

  --accent:     #067a4c;        /* 4.6:1 on white -- the neon fails badly here */
  --accent-2:   #08915a;
  --accent-dim: #05633e;
  --accent-ink: #ffffff;
  --accent-a12: rgba(6,122,76,.10);
  --accent-a20: rgba(6,122,76,.18);
  --accent-a35: rgba(6,122,76,.32);

  --cyan:       #0b6f96;
  --ok:         #067a4c;
  --warn:       #8a5a00;
  --bad:        #b3213c;

  --elev-1: 0 1px 2px rgba(16,32,40,.08);
  --elev-2: 0 8px 24px rgba(16,32,40,.10);
  --glow: none;
  --glow-soft: 0 0 0 1px rgba(6,122,76,.10), 0 6px 18px rgba(16,32,40,.08);
}

/* ------------------------------------------------------ 2. FOUNDATION */
body {
  background:
    radial-gradient(1200px 600px at 50% -200px, rgba(0,255,149,.05), transparent 70%),
    var(--bg);
  color: var(--text);
  font: 14px/1.5 "Inter", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  letter-spacing: .1px;
}
:root[data-theme="light"] body {
  background:
    radial-gradient(1200px 600px at 50% -240px, rgba(6,122,76,.06), transparent 70%),
    var(--bg);
}

/* The old scan grid covered the WHOLE viewport and was a fixed, masked,
   compositor-promoted layer. Confined to the masthead area it still reads
   as a console without sitting on top of every number on the page. */
body::before {
  background-image:
    linear-gradient(rgba(0,255,149,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,255,149,.05) 1px, transparent 1px);
  background-size: 40px 40px;
  mask-image: linear-gradient(180deg, #000 0, transparent 260px);
  -webkit-mask-image: linear-gradient(180deg, #000 0, transparent 260px);
  opacity: .8;
}
:root[data-theme="light"] body::before { opacity: .5; }

/* Numbers line up in columns. Non-negotiable on a board of battery
   percentages and elapsed times. */
table, .mono, .stat .n, .batt, input, select { font-variant-numeric: tabular-nums; }

::selection { background: var(--accent-a35); color: var(--text); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.muted { color: var(--muted); }

/* ---------------------------------------------------------- 3. TOPBAR */
.topbar {
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border-bottom: 1px solid var(--line);
  box-shadow: var(--elev-1);
  gap: var(--sp-3);
}
:root[data-theme="light"] .topbar {
  background: linear-gradient(180deg, #ffffff, #f4f7f9);
  border-bottom: 1px solid var(--line);
}

.brand { letter-spacing: .4px; font-weight: 800; }

/* Sentence case. Uppercase nav is slower to read and it spent the loudest
   signal on the thing you look at least. */
.topbar nav a, .navmore > summary {
  text-transform: none;
  letter-spacing: .1px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-2);
  border-radius: var(--radius-sm);
  padding: 7px 11px;
  transition: background .14s, color .14s;
}
.topbar nav a:hover, .navmore > summary:hover {
  background: var(--panel-3);
  color: var(--text);
}
/* The selected tab: a solid accent underline instead of a glowing ring.
   Reads instantly and does not compete with status colour in the table. */
.topbar nav a.on, .navmore > summary.on {
  color: var(--text);
  background: var(--accent-a12);
  box-shadow: inset 0 -2px 0 var(--accent);
}

.who { gap: var(--sp-2); }
.who .user { color: var(--muted); font-size: 12.5px; }
.logout {
  text-transform: none;
  letter-spacing: .1px;
  font-size: 12.5px;
  color: var(--text-2);
  white-space: nowrap;          /* "SIGN OUT" was wrapping and clipping */
}
.logout:hover { color: var(--text); }

/* ------------------------------------------------------ 4. STAT TILES */
.stats { gap: var(--sp-3); margin-bottom: var(--sp-5); }
.stat {
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--elev-1);
  padding: 13px 18px 12px;
  min-width: 124px;
  transition: border-color .16s, transform .16s, box-shadow .16s;
}
.stat:hover { transform: translateY(-1px); box-shadow: var(--elev-2); }
/* The accent stripe moves to the TOP edge and only appears on a tile that
   is actually reporting something. A row of identical green bars next to
   seven zeroes was pure decoration. */
.stat::after {
  left: 0; right: 0; top: 0; bottom: auto;
  width: auto; height: 2px;
  opacity: 0; box-shadow: none;
  transition: opacity .16s;
}
.stat.ok::after, .stat.warn::after, .stat.bad::after, .stat.sel::after { opacity: 1; }
.stat.sel {
  border-color: var(--accent-a35);
  background: linear-gradient(180deg, var(--accent-a12), var(--panel));
}
.stat .n {
  font-size: 30px; font-weight: 700; letter-spacing: -.5px;
  color: var(--text); text-shadow: none;
}
.stat.ok .n   { color: var(--accent); text-shadow: 0 0 18px rgba(0,255,149,.25); }
.stat.warn .n { color: var(--warn); }
.stat.bad .n  { color: var(--bad); }
.stat .l {
  text-transform: none; letter-spacing: .2px;
  font-size: 12.5px; color: var(--muted); font-weight: 500; margin-top: 2px;
}

/* ---------------------------------------------------------- 5. PANELS */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--elev-1);
}

/* ---------------------------------------------------------- 6. TABLES */
/* Density: the old row was ~77px, so a 60-phone fleet took six screens.
   This lands near 46px without crowding the tap target. */
th, td { padding: 8px 10px; border-bottom: 1px solid var(--line-soft); }
th {
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .7px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
  padding-top: 9px; padding-bottom: 9px;
}
td { font-size: 13.5px; color: var(--text-2); vertical-align: middle; }
td b, td strong { color: var(--text); font-weight: 650; }

tbody tr { transition: background .12s, box-shadow .12s; }
tbody tr:hover {
  background: var(--accent-a12);
  box-shadow: inset 2px 0 0 var(--accent);
}
tbody tr:nth-child(even) { background: rgba(255,255,255,.012); }
tbody tr:nth-child(even):hover { background: var(--accent-a12); }
:root[data-theme="light"] tbody tr:nth-child(even) { background: rgba(12,23,25,.022); }

.dot { width: 7px; height: 7px; }
.dot.on { box-shadow: 0 0 0 3px rgba(0,255,149,.14), 0 0 10px var(--accent); }
.dot.off { background: #3d4d57; }

/* ----------------------------------------------------------- 7. PILLS */
/* One component, three weights, so a glance can rank them:
     .pill.ok / .warn / .bad  -> SOFT  : a state worth noticing
     .pill.ghost              -> GHOST : metadata, recedes
     .pill.model / .telnum    -> cyan  : facts about the handset
   Smaller, tighter and no longer shouting in mono uppercase. */
.pill {
  padding: 2.5px 9px;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .3px;
  text-transform: uppercase;
  font-family: var(--mono);
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--panel-3);
  color: var(--text-2);
  vertical-align: middle;
}
.pill.ok {
  color: var(--ok);
  border-color: rgba(46,230,168,.35);
  background: rgba(46,230,168,.10);
}
.pill.warn {
  color: var(--warn);
  border-color: rgba(255,184,77,.35);
  background: rgba(255,184,77,.10);
}
.pill.bad {
  color: var(--bad);
  border-color: rgba(255,95,121,.38);
  background: rgba(255,95,121,.12);
}
/* Metadata: present, readable, but it stops competing with status. */
.pill.ghost {
  color: var(--muted);
  border-color: var(--line-soft);
  background: transparent;
  font-weight: 550;
}
.pill.model {
  color: var(--cyan);
  border-color: rgba(82,220,255,.28);
  background: rgba(82,220,255,.07);
  box-shadow: none;
  letter-spacing: .5px;
}
.telnum {
  color: var(--cyan);
  border-bottom: 1px dotted rgba(82,220,255,.4);
}
.telnum:hover { text-shadow: none; border-bottom-style: solid; }

.batt { font-weight: 650; }
.batt.low { color: var(--bad); }
.batt.mid { color: var(--warn); }

/* --------------------------------------------------- 8. BUTTONS/INPUT */
button, .btn {
  text-transform: none;
  letter-spacing: .1px;
  font-size: 13px;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--panel-3);
  color: var(--text);
  padding: 8px 14px;
  transition: background .14s, border-color .14s, transform .06s;
}
button:hover, .btn:hover { background: var(--panel-2); border-color: var(--accent-a35); }
button:active, .btn:active { transform: translateY(1px); }

/* Exactly one primary action per bar, and it is unmistakable. */
button.primary, .btn.primary, button[type="submit"] {
  background: linear-gradient(180deg, var(--accent-2), var(--accent-dim));
  border-color: transparent;
  color: var(--accent-ink);
  font-weight: 700;
  box-shadow: 0 2px 14px rgba(0,255,149,.22);
}
button.primary:hover, .btn.primary:hover, button[type="submit"]:hover {
  filter: brightness(1.06);
  border-color: transparent;
}

/* Disabled was nearly invisible, so a greyed-out bulk bar looked broken
   rather than waiting for a selection. */
button:disabled, .btn:disabled, button[disabled] {
  opacity: 1;
  color: var(--muted);
  background: transparent;
  border-color: var(--line-soft);
  border-style: dashed;
  cursor: not-allowed;
}

input[type="text"], input[type="search"], input[type="password"],
input[type="email"], select, textarea {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 12px;
  font-size: 13.5px;
  transition: border-color .14s, box-shadow .14s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-a20);
  outline: none;
}
::placeholder { color: var(--muted); opacity: 1; }

/* Segmented control (battery lens) reads as one object, not six buttons. */
.seg {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 2px;
  gap: 0;
}
.seg button, .seg a {
  border: 0; background: transparent; border-radius: var(--radius-pill);
  padding: 5px 12px; font-size: 12px; font-weight: 650;
  text-transform: none; letter-spacing: .2px; color: var(--muted);
}
.seg button:hover, .seg a:hover { background: transparent; color: var(--text); }
.seg .on, .seg button.on, .seg a.on {
  background: var(--accent); color: var(--accent-ink); box-shadow: none;
}
.seg-lbl {
  text-transform: uppercase; letter-spacing: .7px;
  font-size: 10.5px; color: var(--muted);
}

/* -------------------------------------------------- 9. STICKY HEADERS */
.sticky-head th { position: sticky; top: 58px; z-index: 5; }

/* ------------------------------------------------------- 10. FEEDBACK */
.toast {
  background: var(--panel-2);
  border: 1px solid var(--accent-a35);
  border-radius: var(--radius);
  box-shadow: var(--elev-2);
  color: var(--text);
  font-size: 13.5px;
}
.modal-card, .modal > div {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--elev-2);
}

/* ------------------------------------------------------ 11. HUD FRAME */
/* One deliberate sci-fi motif, used once per panel: corner brackets. It
   costs two pseudo-elements, never moves, and gives the console its
   character back now that the all-over glow is gone. */
.panel { position: relative; }
.panel::before, .panel::after {
  content: "";
  position: absolute;
  width: 14px; height: 14px;
  border: 1px solid var(--accent-a35);
  pointer-events: none;
  opacity: .55;
}
.panel::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0;
                 border-top-left-radius: var(--radius); }
.panel::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0;
                 border-bottom-right-radius: var(--radius); }

/* ------------------------------------------------- 12. PHONE (<760px) */
@media (max-width: 760px) {
  /* app.css turns every table into stacked cards here. Give the cards a
     real surface so they read as objects rather than loose text. */
  tbody tr {
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--elev-1);
    margin-bottom: var(--sp-3);
    padding: var(--sp-2);
  }
  tbody tr:hover { box-shadow: var(--elev-1); }
  td { border-bottom: 1px solid var(--line-soft); font-size: 14px; }
  td:last-child { border-bottom: 0; }
  .topbar nav a, .navmore > summary { font-size: 14px; padding: 9px 12px; }
  button, .btn { padding: 10px 14px; font-size: 14px; }  /* 44px tap target */
}

/* ------------------------------------------- 13. MOTION / ACCESSIBILITY */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
@media (forced-colors: active) {
  .pill, .stat, .panel, button, .btn { border: 1px solid CanvasText; }
  .panel::before, .panel::after { display: none; }
}

/* ------------------------------------------------------- 14. DENSITY */
/* Row height is set by the ROUTE cell, which stacks holder / driver /
   next-stop. Tightening its leading and type size buys ~10px a row --
   worth about two extra phones per screen -- without touching markup or
   dropping a line a dispatcher reads. */
.rcell .rmeta { gap: 0; }
.rm-who, .rm-next { font-size: 12px; line-height: 1.32; }
.rm-who .mono { font-size: 11px; }
.rm-k {
  text-transform: uppercase; letter-spacing: .6px;
  font-size: 10px; color: var(--muted);
}

/* Several pills stack in one cell; a little less vertical padding on each
   keeps a two-pill cell from setting the row height on its own. */
td .pill { padding-top: 2px; padding-bottom: 2px; }

/* The checkbox column does not need 10px of side padding on both edges. */
td:first-child, th:first-child { padding-left: 12px; padding-right: 4px; }

/* "map ↗ never" was two unrelated values jammed together with nothing
   between them. Space them so the eye separates link from timestamp. */
td a + span, td a + .muted { margin-left: 6px; }

/* =====================================================================
   15. CONSOLE CHARACTER
   Stripping the all-over glow fixed the hierarchy but left the board
   looking like any other admin panel. The character comes back here as
   GEOMETRY rather than haze: notched corners, tick marks, a live sweep
   on the masthead. None of it sits on top of a number, none of it
   animates in the table, and all of it stops under prefers-reduced-motion.
   ===================================================================== */

/* Notched tile corner -- the strongest sci-fi signal available for one
   property, and unlike a glow it costs nothing in legibility. */
.stat {
  border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 14px 100%, 0 calc(100% - 14px));
}
/* The clip eats a plain border, so the edge is redrawn as an inset ring. */
.stat { border-color: transparent; box-shadow: inset 0 0 0 1px var(--line), var(--elev-1); }
.stat:hover { box-shadow: inset 0 0 0 1px var(--accent-a35), var(--elev-2); }
.stat.sel  { box-shadow: inset 0 0 0 1px var(--accent-a35), var(--glow); }

/* A live sweep along the masthead's bottom edge: the one moving thing on
   the page, and it reads as "the console is up". */
.topbar { position: relative; }
.topbar::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg,
    transparent 0%, var(--accent-a35) 12%, var(--accent) 50%,
    var(--accent-a35) 88%, transparent 100%);
  background-size: 220% 100%;
  animation: fa-sweep 7s linear infinite;
  opacity: .75; pointer-events: none;
}
@keyframes fa-sweep {
  from { background-position: 120% 0; }
  to   { background-position: -120% 0; }
}

/* Column heads get a tick, the way a scale is marked on an instrument. */
thead th { position: relative; }
thead th::after {
  content: ""; position: absolute; left: 10px; bottom: -1px;
  width: 10px; height: 2px; background: var(--accent);
  opacity: .5;
}
thead th:first-child::after { display: none; }

/* Monospace the small structural type. Proportional digits in a label row
   above a column of mono numbers is the detail that reads as "web page"
   instead of "instrument". */
.stat .l, .seg-lbl, thead th { font-family: var(--mono); }
.stat .l { font-size: 11.5px; letter-spacing: .4px; text-transform: uppercase; }

/* The online dot gets a containment ring -- a target lock, not a bulb. */
.dot.on {
  box-shadow: 0 0 0 1px var(--accent-a35), 0 0 0 4px rgba(0,255,149,.08),
              0 0 10px var(--accent);
}

@media (prefers-reduced-motion: reduce) {
  .topbar::after { animation: none; background-position: 50% 0; }
}
@media (forced-colors: active) {
  .stat { clip-path: none; border: 1px solid CanvasText; }
  .topbar::after, thead th::after { display: none; }
}

/* ------------------------------------------------- 16. PRIMARY ACTION */
/* The markup never uses a .primary class, so "one obvious main action"
   had to be wired to the real ids. Without this every control on the
   bulk bar carried identical weight and nothing said where to click.
   Kept to ids that ARE the page's main verb -- not every button. */
#bulk-send, #fix-go, .btn.primary, button.primary {
  background: linear-gradient(180deg, var(--accent-2), var(--accent-dim));
  border-color: transparent;
  color: var(--accent-ink);
  font-weight: 700;
  box-shadow: 0 2px 14px rgba(0,255,149,.20);
}
#bulk-send:hover, #fix-go:hover { filter: brightness(1.07); border-color: transparent; }

/* Disabled has to beat the gradient, or a greyed-out primary still looks
   clickable -- the single worst thing a bulk bar can do. */
#bulk-send:disabled, #fix-go:disabled, button.primary:disabled {
  background: transparent;
  color: var(--muted);
  border: 1px dashed var(--line-soft);
  box-shadow: none;
  filter: none;
}

/* Destructive keeps its own colour and never borrows the accent. */
#fix-go.danger, button.danger, .btn.danger {
  background: linear-gradient(180deg, #ff7188, var(--bad));
  color: #2a0209;
  border-color: transparent;
  box-shadow: 0 2px 14px rgba(255,95,121,.22);
}

/* =====================================================================
   17. QUIET THE WARNINGS
   The board was a wall of amber: SERVICING and NO PUSH on essentially
   every row, four of seven tiles striped. When everything warns, nothing
   does -- and the one phone that is actually dying gets lost in it.

   Nothing is hidden. Every warning still says exactly what it said; it
   just stops competing with the things that need hands on them today.
   WARN  -> amber text on a plain chip, no fill, no coloured border
   BAD   -> unchanged, still loud, because that is the point
   ===================================================================== */
.pill.warn {
  color: var(--warn);
  background: transparent;
  border-color: var(--line);
  font-weight: 550;
}
/* Anything chronic and fleet-wide is metadata, not an alarm. These two
   sit on nearly every row, so as warnings they were pure noise. */
.pill.warn[title*="push"], .pill.warn[title*="Push"] {
  color: var(--muted);
}

/* Tiles: only a real problem earns a coloured edge. A warn tile keeps its
   amber number so the count still reads at a glance. */
.stat.warn::after { opacity: .45; }
.stat.bad::after  { opacity: 1; }
.stat.warn { box-shadow: inset 0 0 0 1px var(--line), var(--elev-1); }
.stat.bad  { box-shadow: inset 0 0 0 1px rgba(255,95,121,.4), var(--elev-1); }

/* Keep the genuinely urgent unmistakable -- this is what the quiet buys. */
.pill.bad {
  color: var(--bad);
  background: rgba(255,95,121,.14);
  border-color: rgba(255,95,121,.5);
  font-weight: 700;
}
.batt.low { color: var(--bad); font-weight: 700; }

/* =====================================================================
   18. SCALE — bigger type, tighter frame
   Junior 2026-09-26, looking at the live board on a wide screen: "it's
   too big, and letter too small". Both halves are the same fault. I had
   traded type size for density, which reads fine on a laptop and badly
   on a 2000px monitor: the chrome and the row heights kept their scale
   while the words shrank. So the words go UP and the padding comes DOWN.
   ===================================================================== */
:root { font-size: 16px; }

body { font-size: 15px; line-height: 1.45; }

/* Table is where the reading actually happens. */
td { font-size: 14.5px; padding: 6px 10px; }
th { font-size: 12px; letter-spacing: .6px; padding: 8px 10px; }

/* The two-line device cell (name, then model chip + serial) is what makes
   a row ~90px. Tighten the leading between them, not the type. */
td .pill { font-size: 11.5px; padding: 2px 9px; }
tbody tr td:first-of-type, tbody tr td:nth-of-type(2) { line-height: 1.25; }

/* Nav and controls were sized for a small screen and look oversized wide. */
.topbar { padding-top: 6px; padding-bottom: 6px; }
.topbar nav a, .navmore > summary { font-size: 14px; padding: 6px 10px; }
.who .user, .logout { font-size: 13px; }
button, .btn { font-size: 13.5px; padding: 7px 13px; }
input[type="text"], input[type="search"], select { font-size: 14px; padding: 7px 11px; }
.seg button, .seg a { font-size: 12.5px; padding: 5px 11px; }

/* Tiles: same information, less furniture. */
.stats { gap: 10px; margin-bottom: 18px; }
.stat { padding: 10px 15px 9px; min-width: 112px; }
.stat .n { font-size: 26px; }
.stat .l { font-size: 11px; letter-spacing: .3px; }

/* On a genuinely wide monitor the columns drift so far apart that a row
   stops reading as one row. Hold the content to a sane measure and centre
   it, rather than stretching 10 columns across 2000px. */
main { max-width: 1680px; margin-left: auto; margin-right: auto; }
