/* Airmeez Command Center
 *
 * The visual system is airmeez.com's, not a lookalike. Tokens are copied from
 * the site's own `site/src/styles/global.css`, which derives them from the logo
 * — see the site repo's `docs/02-brand.md`. Do not invent a colour here; if one
 * is missing, it is missing from the brand.
 *
 * Fonts are self-hosted, deliberately. The brand doc forbids a Google Fonts CDN
 * link: a third-party request is not acceptable on a product sold on security
 * posture, and the same reasoning applies to an internal operations console.
 */

/* --- self-hosted type, the same files airmeez.com ships ------------------- */

@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('/static/fonts/inter-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
                 U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,
                 U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url('/static/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 500;
  src: url('/static/fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
}

:root {
  /* --- brand, verbatim from airmeez.com --- */
  --brand-cyan:  #2eb8d9;
  --brand-teal:  #16ccb5;
  --brand-green: #0cdda1;
  --brand-gradient: linear-gradient(100deg, #2eb8d9 0%, #16ccb5 50%, #0cdda1 100%);
  --accent: #0a6270;

  --ink:        #1a1718;
  --ink-soft:   #4a4547;
  --ink-faint:  #909494;
  --paper:      #ffffff;
  --paper-alt:  #f7f8f8;
  --sunken:     #eef1f1;
  --rule:       #e2e6e6;
  --rule-strong:#909494;

  /* --- night band, for the dark theme ---
     The site's own hero/footer palette. Every pair below is one the site's
     contrast script already verified: #eef2f2 / #a3aeae / #16ccb5 on
     #0f1213 and #171b1c. */
  --night:       #0f1213;
  --night-alt:   #171b1c;
  --night-text:  #eef2f2;
  --night-soft:  #a3aeae;
  --night-rule:  #252b2c;
  --night-accent:#16ccb5;

  /* --- derived, for data --- */
  --pos: #0f7a5a;
  --neg: #b3261e;
  --warn:#8a5a00;
  --shadow:   0 1px 2px rgba(26,23,24,.05), 0 10px 28px -16px rgba(26,23,24,.18);
  --shadow-sm:0 1px 2px rgba(26,23,24,.06);

  --font-sans: "Inter Variable", "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --r-md: .375rem;
  --r-lg: .5rem;
  --r-xl: .75rem;
  --r-2xl: 1rem;
}

/* Dark theme: the surfaces become the site's night band, so the two themes are
   the same palette used two ways rather than two palettes to keep in step. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink:        #eef2f2;   /* night-text */
    --ink-soft:   #a3aeae;   /* night-soft */
    --ink-faint:  #6f7a7a;
    --paper:      #171b1c;   /* night-alt  */
    --paper-alt:  #0f1213;   /* night      */
    --sunken:     #1e2425;
    --rule:       #252b2c;   /* night-rule */
    --rule-strong:#3a4243;
    --accent:     #16ccb5;   /* night-accent */
    --pos: #4fc79b;
    --neg: #f0857a;
    --warn:#d9a441;
    --shadow:   0 1px 2px rgba(0,0,0,.4), 0 10px 28px -16px rgba(0,0,0,.7);
    --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  }
}
:root[data-theme="dark"] {
  --ink:#eef2f2; --ink-soft:#a3aeae; --ink-faint:#6f7a7a;
  --paper:#171b1c; --paper-alt:#0f1213; --sunken:#1e2425;
  --rule:#252b2c; --rule-strong:#3a4243; --accent:#16ccb5;
  --pos:#4fc79b; --neg:#f0857a; --warn:#d9a441;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 10px 28px -16px rgba(0,0,0,.7);
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper-alt);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.mono, .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.num { font-family: inherit; }

/* ------------------------------------------------------------ environment */

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--paper);
  padding: 10px 16px; border-radius: 0 0 var(--r-md) 0; font-weight: 600; font-size: 13px;
}
.skip:focus { left: 0; text-decoration: none; }

/* Inverts with the theme — ink on paper, paper on ink — so it stays a legible
   band in both rather than depending on a fixed light text colour. */
/* One band, and only when something is wrong: the "sandbox environment" strip
   that used to sit above every page was cut on 2026-09-23 (Darryl) — the
   sign-in, the data and the URL all say which environment this is, and a bar
   that is on every page in every environment but production is a bar nobody
   reads. The degraded-access band below is the one that still earns its row. */
.envbar {
  background: var(--ink); color: var(--paper);
  font-size: 12px; font-weight: 500; letter-spacing: .01em;
  text-align: center; padding: 6px 12px;
}
.envbar.warn { background: var(--neg); }
.envbar::first-letter { text-transform: uppercase; }

/* ------------------------------------------------------------------ chrome */
/* Structure follows the site's own Header.astro: sticky, hairline rule,
   translucent paper with a backdrop blur, 72rem measure, pill nav links. */

.brand { display: flex; align-items: center; gap: 12px; flex: none; text-decoration: none; }
.brand:hover { text-decoration: none; }

/* The wordmark is the logo — never retyped as text, never recoloured. Its own
   gradient on the `a` is the brand mark; nothing else here competes with it. */
.wordmark { height: 26px; width: auto; display: block; }
.wordmark-lg { height: 38px; width: auto; margin: 0 auto; display: block; }

/* Ink wordmark on light surfaces, light wordmark on dark ones. */
.on-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .on-light { display: none; }
  :root:not([data-theme="light"]) .on-dark  { display: block; }
}
:root[data-theme="dark"] .on-light { display: none; }
:root[data-theme="dark"] .on-dark  { display: block; }

/* "Command Center" is set beside the logo, divided by a hairline — it names
   this application without pretending to be part of the wordmark. */
.brand .unit {
  font-size: 14px; font-weight: 500; color: var(--ink-soft);
  padding-left: 12px; border-left: 1px solid var(--rule);
  white-space: nowrap;
}

.who { display: flex; align-items: center; gap: 14px; font-size: 13px; color: var(--ink-soft); flex: none; }
.who .email { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The site's primary control: solid ink, white label, no border. */
.btn-ink {
  background: var(--ink); color: var(--paper);
  padding: 7px 14px; border-radius: var(--r-lg);
  font-size: 13px; font-weight: 600; white-space: nowrap;
  transition: opacity .12s;
}
.btn-ink:hover { opacity: .85; text-decoration: none; color: var(--paper); }

.role {
  font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 99px; border: 1px solid var(--rule);
  color: var(--ink-soft); background: var(--sunken);
}
.role-admin    { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.role-approver { color: var(--pos); border-color: color-mix(in srgb, var(--pos) 35%, transparent); }

/* -------------------------------------------------------------------- rail */
/* The shell's whole chrome: the brand at the top, every menu in the middle,
   who is signed in at the foot. Each module is a group with its icon; its
   sections hang off a guide line, and the current page marks that line with
   the brand gradient. Modules hand their menus to the shell (view.menu);
   none draws navigation of its own. */

:root { --rail-w: 16.5rem; }

.frame { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); min-height: 100vh; }
.page { min-width: 0; }

.rail {
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column;
  background: var(--paper); border-right: 1px solid var(--rule);
}
.rail svg {
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.rail-top { padding: 22px 22px 10px; }
.rail-brand { display: inline-block; }
.rail-brand:hover { text-decoration: none; }
.rail-brand .wordmark { height: 22px; }
.rail-unit { margin-top: 7px; font-size: 12px; font-weight: 600; letter-spacing: .01em; color: var(--ink-faint); }

.rail-nav { flex: 1; min-height: 0; overflow-y: auto; padding: 8px 12px 20px; scrollbar-width: thin; }
.rail-caption {
  margin: 20px 10px 6px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint);
}
.rail summary { list-style: none; cursor: pointer; }
.rail summary::-webkit-details-marker { display: none; }

.rail-link {
  display: flex; align-items: center; gap: 11px;
  height: 36px; padding: 0 10px; border-radius: var(--r-lg);
  font-size: 14px; font-weight: 500; color: var(--ink-soft);
  user-select: none; transition: background-color .12s, color .12s;
}
.rail-link:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
.rail-link > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-link .ico { width: 18px; height: 18px; flex: none; }
.rail-link.on, .rail-group.on > .rail-head { color: var(--ink); font-weight: 600; }
.rail-link.on { background: color-mix(in srgb, var(--accent) 9%, var(--paper)); }
.rail-link.on .ico, .rail-group.on > .rail-head .ico { color: var(--accent); }
.rail-nav > * + .rail-group, .rail-nav > * + a.rail-link { margin-top: 2px; }

/* Its own name: the users page draws a different caret called .chev. */
.rail-chev { width: 15px; height: 15px; flex: none; color: var(--ink-faint); transition: transform .15s ease; }
.rail details[open] > summary .rail-chev { transform: rotate(90deg); }

.rail-sub { list-style: none; margin: 2px 0 8px 19px; padding: 0 0 0 12px; border-left: 1px solid var(--rule); }
.rail-pages .rail-sub { margin: 1px 0 4px 10px; max-height: 20rem; overflow-y: auto; scrollbar-width: thin; }
.rail-sub > li { position: relative; }
.rail-sub > li + li { margin-top: 1px; }
.rail-item {
  display: block; padding: 6px 10px; border-radius: var(--r-md);
  font-size: 13.5px; line-height: 1.35; color: var(--ink-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background-color .12s, color .12s;
}
.rail-item:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
.rail-item.on { color: var(--ink); font-weight: 600; background: var(--sunken); }
.rail-item.trail { color: var(--ink); }
/* The current page marks the guide line beside it. */
.rail-sub > li:has(> .rail-item.on)::before,
.rail-sub > li:has(> details > summary > .rail-item.on)::before {
  content: ""; position: absolute; left: -13px; top: 5px; width: 2px; height: 21px;
  border-radius: 2px; background: var(--brand-gradient);
}
/* A page list that scrolls clips at its padding edge, so there the mark sits
   just inside the guide line instead of on it. */
.rail-pages .rail-sub > li:has(> .rail-item.on)::before { left: -12px; }
.rail-pages > summary { display: flex; align-items: center; gap: 2px; }
.rail-pages > summary > .rail-item { flex: 1; min-width: 0; }
.rail-toggle { display: grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: var(--r-md); }
.rail-toggle:hover { background: var(--sunken); }
.rail-toggle .rail-chev { width: 14px; height: 14px; }

.rail-foot {
  display: flex; align-items: center; gap: 10px;
  margin: 0 12px; padding: 14px 6px 16px; border-top: 1px solid var(--rule);
}
.rail-foot .avatar { width: 32px; height: 32px; font-size: 11.5px; flex: none; }
.rail-me { display: flex; flex-direction: column; flex: 1; min-width: 0; line-height: 1.3; }
.rail-me b, .rail-me span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-me b { font-size: 13px; font-weight: 600; }
.rail-me span { font-size: 11.5px; color: var(--ink-faint); }
.rail-out {
  display: grid; place-items: center; flex: none; width: 32px; height: 32px;
  border-radius: var(--r-md); color: var(--ink-soft);
}
.rail-out:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
.rail-out .ico { width: 18px; height: 18px; }

.mobile-bar { display: none; }
.rail-menu {
  display: grid; place-items: center; width: 36px; height: 36px; margin-left: -6px;
  border: 0; border-radius: var(--r-md); background: transparent; color: var(--ink); cursor: pointer;
}
.rail-menu svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }

/* Where a non-production page's time went: this process's Server-Timing marks,
   then what the browser spent. A diagnostic, so quiet and out of the way. */
.timing {
  position: fixed; right: 12px; bottom: 12px; z-index: 30;
  padding: 5px 11px; border-radius: 99px;
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-soft);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  border: 1px solid var(--rule); box-shadow: var(--shadow-sm);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}

/* ------------------------------------------------------------------- layout */

main { max-width: 72rem; margin: 0 auto; padding: 36px 24px 96px; }
main.wide { max-width: 96rem; }
.frame main { margin: 0; }
/* A wide page is a page whose content is a grid, and a grid has no reading
   width to protect. On a monitor wider than the old 96rem cap it spreads as far
   as the glass allows. */
@media (min-width: 1536px) {
  body.wide main.wide { max-width: none; }
}

.page-head { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; margin-bottom: 26px; }
.page-head .grow { flex: 1; min-width: 260px; }
.eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 6px;
}
h1 { font-size: 27px; font-weight: 600; letter-spacing: -.02em; margin: 0; line-height: 1.15; }
h2 { font-size: 12px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-faint); margin: 0 0 12px; }
h3 { font-size: 16px; font-weight: 600; letter-spacing: -.01em; margin: 0; }
.lede { color: var(--ink-soft); margin: 6px 0 0; max-width: 72ch; font-size: 14.5px; }

section + section { margin-top: 40px; }

/* -------------------------------------------------------------------- cards */

.card {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r-xl); box-shadow: var(--shadow-sm);
}
.card.pad { padding: 20px; }

.grid { display: grid; gap: 14px; }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* module tiles on the home page */
.tile {
  display: flex; flex-direction: column; gap: 12px;
  padding: 20px; min-height: 168px;
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r-xl); box-shadow: var(--shadow-sm);
  color: inherit; position: relative; overflow: hidden;
  transition: box-shadow .16s ease, transform .16s ease, border-color .16s ease;
}
a.tile:hover { text-decoration: none; box-shadow: var(--shadow); transform: translateY(-1px); border-color: var(--rule-strong); }
.tile::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--brand-gradient); opacity: 0;
  transition: opacity .16s ease;
}
a.tile:hover::before { opacity: 1; }
.tile.off { opacity: .62; }
.tile .t-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tile .t-title { font-size: 16px; font-weight: 600; letter-spacing: -.01em; }
.tile .t-sum { font-size: 13.5px; color: var(--ink-soft); flex: 1; text-wrap: pretty; }
.tile .t-stats { display: flex; gap: 18px; flex-wrap: wrap; border-top: 1px solid var(--rule); padding-top: 11px; }
.tile .t-stat { display: flex; flex-direction: column; gap: 1px; }
.tile .t-stat b { font-size: 17px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.tile .t-stat span { font-size: 11px; color: var(--ink-faint); letter-spacing: .04em; text-transform: uppercase; font-weight: 600; }

/* status dot */
.dot { width: 7px; height: 7px; border-radius: 99px; flex: none; display: inline-block; }
.dot.up   { background: var(--brand-green); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-green) 22%, transparent); }
.dot.down { background: var(--neg);         box-shadow: 0 0 0 3px color-mix(in srgb, var(--neg) 22%, transparent); }
.dot.idle { background: var(--rule-strong); }
.status { display: inline-flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--ink-faint); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }

/* ------------------------------------------------------------------- stats */

.stat {
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-lg);
  padding: 15px 16px; display: flex; flex-direction: column; gap: 3px;
}
.stat .k { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); }
.stat .v { font-size: 25px; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat .s { font-size: 12.5px; color: var(--ink-soft); }
.stat .v.neg { color: var(--neg); }
.ageing { margin: 0 0 24px; }
.ageing .grid { margin-bottom: 14px; }

/* ------------------------------------------------------------------ tables */

.table-wrap { overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--r-xl); background: var(--paper); }
table { border-collapse: collapse; width: 100%; font-size: 13.5px; }
thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--paper); text-align: left;
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); padding: 11px 12px; white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
tbody td { padding: 10px 12px; border-bottom: 1px solid var(--rule); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--paper-alt); }
td.r, th.r { text-align: right; font-variant-numeric: tabular-nums; }
td.money { font-variant-numeric: tabular-nums; white-space: nowrap; }
.sku { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-soft); }
.sub { font-size: 12px; color: var(--ink-faint); }
.group-row td {
  background: var(--sunken); font-size: 10.5px; font-weight: 700;
  letter-spacing: .11em; text-transform: uppercase; color: var(--ink-soft);
  padding: 7px 12px;
}

.margin-good { color: var(--pos); font-weight: 600; }
.margin-thin { color: var(--warn); font-weight: 600; }
.margin-bad  { color: var(--neg);  font-weight: 600; }

/* ------------------------------------------------------------------- chips */

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600; padding: 2.5px 8px;
  border-radius: 99px; border: 1px solid var(--rule);
  background: var(--sunken); color: var(--ink-soft); white-space: nowrap;
}
.chip.pending  { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.chip.approved { color: var(--pos);  border-color: color-mix(in srgb, var(--pos) 35%, transparent); }
.chip.rejected,
.chip.withdrawn{ color: var(--neg);  border-color: color-mix(in srgb, var(--neg) 35%, transparent); }

/* ------------------------------------------------------------------ forms */

.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
[hidden] { display: none !important; }

input[type=text], input[type=search], input[type=email], input[type=number], select, textarea {
  font: inherit; font-size: 13.5px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r-md); padding: 7px 10px;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--brand-teal) 55%, transparent);
  outline-offset: 1px; border-color: transparent;
}
textarea { width: 100%; min-height: 84px; resize: vertical; }
label.field { display: flex; flex-direction: column; gap: 5px; font-size: 12px; font-weight: 600; color: var(--ink-soft); }

.btn {
  font: inherit; font-size: 13.5px; font-weight: 600;
  padding: 7px 14px; border-radius: var(--r-md);
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink);
  cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 7px;
}
.btn:hover { background: var(--sunken); text-decoration: none; }
.btn.primary { border-color: transparent; background: var(--accent); color: #fff; }
.btn.primary:hover { filter: brightness(1.08); background: var(--accent); }
.btn.danger { color: var(--neg); border-color: color-mix(in srgb, var(--neg) 35%, transparent); }
.btn.brand { border-color: transparent; background: var(--brand-gradient); color: #06282c; }

/* ------------------------------------------------------------------ notices */

.flash {
  background: color-mix(in srgb, var(--brand-teal) 12%, var(--paper));
  border: 1px solid color-mix(in srgb, var(--brand-teal) 40%, transparent);
  border-radius: var(--r-lg); padding: 11px 14px; margin-bottom: 20px; font-size: 13.5px;
}
/* A warning flash, for a dashboard that has quietly stopped moving. */
.flash.bad {
  background: color-mix(in srgb, var(--neg) 10%, var(--paper));
  border-color: color-mix(in srgb, var(--neg) 35%, var(--rule));
  color: var(--neg);
}
.notice {
  border: 1px dashed var(--rule-strong); border-radius: var(--r-lg);
  padding: 18px; color: var(--ink-soft); font-size: 13.5px; background: var(--paper);
}
.notice b { color: var(--ink); }
.notice.bad { border-style: solid; border-color: color-mix(in srgb, var(--neg) 40%, transparent); }
.empty { padding: 34px 18px; text-align: center; color: var(--ink-faint); font-size: 13.5px; }

/* ------------------------------------------------------------------- charts */

.bars { display: flex; flex-direction: column; gap: 7px; }
.bar-row { display: grid; grid-template-columns: minmax(120px, 1.4fr) 1fr auto; gap: 12px; align-items: center; font-size: 13px; }
/* Both are spans, so they must be blockified — width and height do nothing on
   an inline box, and the fill silently disappears. */
.bar-track { display: block; background: var(--sunken); border-radius: 99px; height: 8px; overflow: hidden; }
.bar-fill  { display: block; height: 100%; min-width: 2px; border-radius: 99px; background: var(--brand-gradient); }
.bar-fill.voice { background: var(--brand-cyan); }
.bar-fill.text  { background: var(--brand-green); }
.bar-fill.fee   { background: var(--accent); }
.bar-val { font-variant-numeric: tabular-nums; color: var(--ink-soft); font-size: 12.5px; }

/* ----------------------------------------------------------------- heatmap */

table.heat { border-collapse: separate; border-spacing: 0; font-size: 12px; }
table.heat th, table.heat td { padding: 0; border: 0; }
table.heat th.cell-h { font-size: 9.5px; letter-spacing: .02em; text-align: center; padding: 0 0 6px; }
.sticky-name {
  position: sticky; left: 0; z-index: 2; background: var(--paper);
  text-align: left; padding-right: 14px !important;
  min-width: 190px; max-width: 190px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-size: 12.5px;
}
thead .sticky-name { z-index: 3; }
.heat-cell { padding: 0 !important; }
.heat-cell span {
  display: block; width: 22px; height: 22px; margin: 1px;
  border-radius: 3px;
}
table.heat tbody tr:hover { background: transparent; }
table.heat td.money { padding-left: 14px !important; white-space: nowrap; }

/* ------------------------------------------------------------------- login */

.signin { min-height: 72vh; display: grid; place-items: center; padding: 40px 20px; }
.signin .box { width: 100%; max-width: 380px; text-align: center; display: flex; flex-direction: column; gap: 16px; }

@media (max-width: 720px) {
  main { padding: 22px 14px 72px; }
  /* On a phone the rail is a drawer behind the menu button. */
  .frame { grid-template-columns: minmax(0, 1fr); }
  .mobile-bar {
    position: sticky; top: 0; z-index: 40;
    display: flex; align-items: center; gap: 10px; height: 54px; padding: 0 14px;
    background: color-mix(in srgb, var(--paper) 95%, transparent);
    backdrop-filter: saturate(1.4) blur(10px); -webkit-backdrop-filter: saturate(1.4) blur(10px);
    border-bottom: 1px solid var(--rule);
  }
  .mobile-bar .wordmark { height: 20px; }
  .rail {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 60;
    width: min(86vw, 18rem); transform: translateX(-102%);
    transition: transform .2s ease; box-shadow: var(--shadow);
  }
  body.rail-open .rail { transform: none; }
  body.rail-open::after {
    content: ""; position: fixed; inset: 0; z-index: 50;
    background: rgba(15, 18, 19, .38);
  }
}

/* ------------------------------------------------------------------ people
   Administration → Users. One row per person; a row opens in place to edit
   that person's groups and account, so no bare form control sits in a grid. */

.btn.sm { font-size: 12.5px; padding: 5px 11px; }

.people-stats { margin-bottom: 22px; }
.people-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-bottom: 14px; }
.people-bar input[type=search] { flex: 1 1 16rem; max-width: 26rem; }
.people-add { display: flex; gap: 8px; margin-left: auto; flex: 0 1 26rem; }
.people-add input { flex: 1; min-width: 0; }

.seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--sunken); border-radius: var(--r-lg); }
.seg button {
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
  background: transparent; border: 0; padding: 5px 10px; border-radius: var(--r-md); cursor: pointer;
}
.seg button:hover { color: var(--ink); }
.seg button.on { background: var(--paper); color: var(--ink); box-shadow: var(--shadow-sm); }

.people {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r-xl); box-shadow: var(--shadow-sm); overflow: hidden;
}
.people-head, .person > summary {
  display: grid; align-items: center; gap: 14px;
  grid-template-columns: 34px minmax(12rem, 1.1fr) minmax(0, 2fr) 7.5rem 12px;
  padding: 11px 18px;
}
.people-head {
  padding-block: 9px; border-bottom: 1px solid var(--rule);
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint);
}
.person + .person { border-top: 1px solid var(--rule); }
.person > summary { list-style: none; cursor: pointer; transition: background-color .12s; }
.person > summary::-webkit-details-marker { display: none; }
.person > summary:hover, .person[open] > summary { background: var(--paper-alt); }
.person.off .avatar, .person.off .who-cell { opacity: .5; }

.avatar {
  width: 34px; height: 34px; border-radius: 99px; display: grid; place-items: center;
  font-size: 12px; font-weight: 700; letter-spacing: .03em;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--paper));
}
.avatar.super { color: #06282c; background: var(--brand-gradient); }
.who-cell { display: flex; flex-direction: column; min-width: 0; line-height: 1.35; }
.who-cell b, .who-cell .sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-cell b { font-size: 14px; font-weight: 600; }
.you {
  margin-left: 6px; padding: 0 6px; vertical-align: 1px;
  font-size: 10.5px; font-weight: 600; color: var(--ink-faint);
  border: 1px solid var(--rule); border-radius: 99px;
}
.groups-cell { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.chip.super { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.chip.warn  { color: var(--warn);   border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.seen { font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; }
.chev {
  width: 7px; height: 7px; transform: rotate(-45deg); transition: transform .12s;
  border-right: 1.5px solid var(--ink-faint); border-bottom: 1.5px solid var(--ink-faint);
}
.person[open] .chev { transform: rotate(45deg); }

.person-body {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(15rem, 1fr); gap: 32px;
  padding: 18px 18px 22px 66px;
  background: var(--paper-alt); border-top: 1px solid var(--rule);
}
.person-body h3 {
  margin: 0 0 10px; font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-faint);
}
.person-body p.sub { margin: 0 0 10px; max-width: 60ch; }
.picks { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.pick { position: relative; }
.pick input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.pick span {
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 12px;
  font-size: 13px; font-weight: 500; color: var(--ink-soft);
  background: var(--paper); border: 1px solid var(--rule); border-radius: 99px;
  transition: background-color .12s, border-color .12s, color .12s;
}
.pick span::before {
  content: ""; width: 7px; height: 7px; border-radius: 99px;
  border: 1.5px solid var(--rule-strong);
}
.pick:hover span { border-color: var(--rule-strong); color: var(--ink); }
.pick input:checked + span {
  color: var(--ink); border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 10%, var(--paper));
}
.pick input:checked + span::before { background: var(--accent); border-color: var(--accent); }
.pick input:focus-visible + span {
  outline: 2px solid color-mix(in srgb, var(--brand-teal) 55%, transparent); outline-offset: 1px;
}
.pick input:disabled + span { opacity: .6; }
.facts { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 0 0 16px; font-size: 13px; }
.facts dt { color: var(--ink-faint); }
.facts dd { margin: 0; font-variant-numeric: tabular-nums; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; }
.actions form { margin: 0; }

@media (max-width: 900px) {
  .people-head { display: none; }
  .person > summary { grid-template-columns: 34px minmax(0, 1fr) 12px; row-gap: 6px; }
  .person > summary .chev { grid-column: 3; grid-row: 1; }
  .person > summary .groups-cell, .person > summary .seen { grid-column: 2; }
  .person-body { grid-template-columns: minmax(0, 1fr); gap: 20px; padding-left: 18px; }
  .people-add { margin-left: 0; flex-basis: 100%; }
}

/* An agent's role for a person, from their groups here. */
.chip.agent { color: var(--ink); background: color-mix(in srgb, var(--accent) 8%, var(--paper)); border-color: color-mix(in srgb, var(--accent) 30%, transparent); }
.person-account h3 + .facts + .reapply, .person-account .reapply { margin: -6px 0 18px; }
.person-account .facts + h3 { margin-top: 4px; }
.drift { color: var(--warn); font-weight: 600; }

/* -------------------------------------------------------------------- keys
   Administration → API keys: one block per agent that issues keys. */

.keys-agent + .keys-agent { margin-top: 40px; }
.keys-agent .table-bar { margin-bottom: 12px; }
.keys-agent .table-bar h2 { margin: 0; }
.keys-agent tr.off td { opacity: .5; }
.key-access { display: flex; flex-wrap: wrap; gap: 5px; }
.key-form { margin-top: 16px; scroll-margin-top: 20px; }
.key-form h3 { margin: 0 0 14px; }
.key-fields { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 14px; }
.key-fields .field { flex: 1 1 14rem; max-width: 22rem; }
.key-fields input, .key-fields select { width: 100%; }
.field-label { margin: 0 0 8px; font-size: 12px; font-weight: 600; color: var(--ink-soft); }
.key-once {
  margin: 0 0 24px; padding: 16px 18px; border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--brand-teal) 12%, var(--paper));
  border: 1px solid color-mix(in srgb, var(--brand-teal) 40%, transparent);
}
.key-once p { margin: 4px 0 12px; color: var(--ink-soft); font-size: 13.5px; }
.key-secret { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.key-secret code {
  flex: 1 1 20rem; min-width: 0; padding: 8px 12px; overflow-wrap: anywhere;
  font-family: var(--font-mono); font-size: 13px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-md);
}

/* ---------------------------------------------------------------- Expenses
   The vendor matrix, its filters and its charts. Kept at the end of the sheet
   so the module can grow without disturbing the shell above it. */

.filters {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px;
  padding: 14px 16px; margin: 0 0 20px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.filters label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: .74rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-faint);
}
.filters select, .filters input {
  font: inherit; font-size: .9rem; color: var(--ink);
  background: var(--paper-alt); border: 1px solid var(--rule);
  border-radius: var(--r-md); padding: 6px 8px; min-width: 9rem;
}

/* The matrix can be wider than the screen; the month column stays put so a
   figure never loses the row it belongs to. */
.table-bar { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
.table-bar h2 { margin: 0; }
.table-bar .grow { flex: 1; }
details.runs { margin: 0 0 16px; }
details.runs summary { cursor: pointer; font-size: .84rem; color: var(--ink-soft); margin-bottom: 8px; }

/* Horizontally only. The table is not its own scrollport: a grid this tall
   inside a fixed-height box means two scrollbars fighting over one gesture,
   so the page does the up and down. */
.table-wrap.matrix { overflow-x: auto; overflow-y: hidden; max-height: none; }
.table-wrap.matrix table { border-collapse: separate; border-spacing: 0; }
.table-wrap.matrix thead th {
  z-index: 2;
  background: var(--paper); border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap; font-size: .78rem;
}
.table-wrap.matrix tfoot th {
  z-index: 2;
  background: var(--paper); border-top: 1px solid var(--rule-strong);
}
/* The year, small, in front of Prod / SB / Total -- so a year block says
   which year it is without depending on the band above it. */
.yr-y { color: var(--ink-faint); font-weight: 500; }
.yr-t .yr-y { color: var(--ink-soft); }
.table-wrap.matrix .stick {
  position: sticky; left: 0; z-index: 3; background: var(--paper);
  border-right: 1px solid var(--rule);
}
.table-wrap.matrix thead .stick, .table-wrap.matrix tfoot .stick { z-index: 4; }
.table-wrap.matrix td, .table-wrap.matrix th { padding: 6px 10px; }
.table-wrap.matrix tbody tr:nth-child(even) td { background: var(--paper-alt); }
.table-wrap.matrix tbody tr:nth-child(even) td.stick { background: var(--paper-alt); }
.blank { color: var(--ink-faint); }
.path { font-family: var(--font-mono); font-size: .72rem; color: var(--ink-soft); word-break: break-all; }

.charts { margin: 0 0 24px; }
.charts-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.charts-head h2 { margin: 0; }
.charts-head .grow { flex: 1; }
.chart-toggles {
  display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 14px;
  padding: 12px 16px; background: var(--sunken); border-radius: var(--r-lg);
}
.toggle { display: flex; align-items: center; gap: 6px; font-size: .84rem; cursor: pointer; }
.toggle input { accent-color: var(--accent); }
.chart-grid {
  /* Three across at the old shell width, and one more column for every extra
     chart's width the monitor gives us -- the small charts float rather than
     stretching, while the two full-width ones keep the whole row. Dense flow
     backfills any hole those full-width charts leave behind. */
  display: grid; gap: 16px; grid-auto-flow: dense;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 440px), 1fr));
}
.chart-card {
  margin: 0; padding: 14px 16px 10px;
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
}
.chart-card.wide { grid-column: 1 / -1; }
.chart-card figcaption {
  font-size: .74rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint); margin-bottom: 8px;
}
.chart-svg { width: 100%; height: auto; display: block; }
.chart-svg .grid { stroke: var(--rule); stroke-width: 1; }
.chart-svg .tick {
  /* User units, so this is only honest while the viewBox matches the rendered
     width -- see NARROW/WIDE in charts.js. */
  fill: var(--ink-soft); font-size: 12px; font-family: var(--font-mono);
}
.chart-svg .tick.lg { font-size: 13px; fill: var(--ink); font-family: var(--font-sans); }
.chart-svg .tick.r { text-anchor: end; }
.chart-svg .tick.mid { text-anchor: middle; }
.chart-svg .line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-svg .line.thin { stroke-width: 1.5; opacity: .85; }
.chart-svg .area { opacity: .12; }
.chart-svg .marker { stroke: var(--paper); stroke-width: 2; }
/* The unfinished tail of the month axis. Hatched rather than hidden:
   the figures are real, they are just not a whole month yet. */
.chart-svg .partial-band { fill: var(--ink); opacity: .055; }
.table-wrap.matrix th.part, .table-wrap.matrix td.part { background: var(--sunken); }
.table-wrap.matrix thead th.part a::after { content: ' *'; color: var(--warn); }
.legend { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 8px; font-size: .74rem; color: var(--ink-soft); }
.legend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; }
.legend span { cursor: default; white-space: nowrap; }
.chart-table { width: 100%; font-size: .84rem; }
.chart-table td { padding: 3px 4px; border-bottom: 1px solid var(--rule); }
.swatch { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 6px; }

/* Pointing at a chart.
   Two dozen services is more than any palette can name on its own, so every
   mark and every legend entry answers to the pointer: hovering one lights that
   series wherever it appears and fades the rest, and a tooltip says which it
   is and what it cost. */
.chart-card [data-s] { transition: opacity .12s ease; }
.chart-card.focusing [data-s]:not(.hot) { opacity: .12; }
.chart-card.focusing .legend span:not(.hot) { opacity: .3; }
/* A one-and-a-half pixel line needs more than full opacity to stand out
   from two dozen faded ones. */
.chart-card.focusing .chart-svg .line.hot { stroke-width: 3; opacity: 1; }
.chart-card.focusing .legend span.hot { color: var(--ink); font-weight: 600; }
.chart-card.focusing .chart-table tr.hot td { background: var(--sunken); }
/* Invisible, but the only thing big enough to aim at. */
.chart-svg .hit { fill: transparent; }
.chart-svg .hit-line { fill: none; stroke: transparent; stroke-width: 11; }
.chart-tip {
  position: fixed; z-index: 60; pointer-events: none;
  opacity: 0; transition: opacity .1s ease;
  max-width: 280px; padding: 7px 10px;
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-md); box-shadow: var(--shadow);
  font-size: .78rem; line-height: 1.45;
}
.chart-tip.on { opacity: .97; }
.chart-tip b { display: block; font-weight: 600; }
.chart-tip b i {
  display: inline-block; width: 9px; height: 9px;
  border-radius: 2px; margin-right: 6px;
}
.chart-tip span { display: block; opacity: .75; font-variant-numeric: tabular-nums; }

.split { display: grid; gap: 24px; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); }
.split section h2 { margin-top: 0; }
.notes { margin-top: 28px; padding: 16px; background: var(--sunken); border-radius: var(--r-lg); }
.notes h2 { margin-top: 0; font-size: .95rem; }
.notes ul { margin: 0; padding-left: 1.1rem; color: var(--ink-soft); font-size: .88rem; }
.upto {
  display: block; font-weight: 400; font-size: .66rem;
  color: var(--ink-faint); font-family: var(--font-mono);
}

/* Transposed matrix: services down the left, months across the top. A cell is
   a figure, a gap, or outside that service's span — the three states are the
   point of the view, so they are distinguished by shape as well as colour. */
.table-wrap.matrix td.gap {
  background: color-mix(in srgb, var(--neg) 12%, transparent);
  color: var(--neg); font-weight: 600;
}
.table-wrap.matrix td.out::after { content: "·"; color: var(--rule); }
/* Not a gap: the service did not exist yet, or no longer did. Solid rather
   than dotted, because there is nothing here to look for. */
.table-wrap.matrix td.na {
  background: repeating-linear-gradient(
    -45deg, var(--sunken), var(--sunken) 3px,
    color-mix(in srgb, var(--rule) 45%, transparent) 3px,
    color-mix(in srgb, var(--rule) 45%, transparent) 4px);
}
.table-wrap.matrix .tot { border-left: 1px solid var(--rule); font-weight: 600; }
.table-wrap.matrix thead th.r { font-family: var(--font-mono); font-size: .72rem; }
.table-wrap.matrix .stick { min-width: 15rem; }

.pill {
  display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px;
  font-size: .66rem; letter-spacing: .03em; font-weight: 600; vertical-align: middle;
}
.pill.bad { background: color-mix(in srgb, var(--neg) 14%, transparent); color: var(--neg); }
.pill.quiet { background: var(--sunken); color: var(--ink-faint); font-weight: 500; }
/* A cancelled service. Deliberately quieter than .bad: the trailing blanks are
   the correct answer, not a gap to chase. */
.pill.done {
  background: transparent; color: var(--ink-faint); font-weight: 500;
  border: 1px solid var(--rule);
}

.legend-row {
  display: flex; flex-wrap: wrap; gap: 18px; margin: 10px 2px 0;
  font-size: .78rem; color: var(--ink-soft);
}
.legend-row .key { display: inline-flex; align-items: center; gap: 7px; }
.sw { width: 13px; height: 13px; border-radius: 3px; border: 1px solid var(--rule); }
.sw.filed { background: var(--paper); }
.sw.gapc { background: color-mix(in srgb, var(--neg) 14%, transparent); border-color: var(--neg); }
.sw.nac {
  background: repeating-linear-gradient(
    -45deg, var(--sunken), var(--sunken) 3px,
    color-mix(in srgb, var(--rule) 45%, transparent) 3px,
    color-mix(in srgb, var(--rule) 45%, transparent) 4px);
}
/* Nothing filed and nothing declared — the swatch says "unknown", not "grey
   like the one above it", or the two states stop being distinguishable. */
.sw.outc { background: var(--paper); border-style: dashed; }

.filters label.check {
  flex-direction: row; align-items: center; gap: 7px;
  font-size: .82rem; color: var(--ink-soft); align-self: end; padding-bottom: 8px;
}
.filters label.check input { width: auto; margin: 0; }

/* The block of three totals closing each calendar year: production, sandbox,
   total. Tinted and ruled hard on its left edge so a year reads as a band
   across the grid rather than three more columns of numbers. */
.table-wrap.matrix th.yr, .table-wrap.matrix td.yr {
  background: var(--sunken); color: var(--ink);
}
.table-wrap.matrix th.yr-1, .table-wrap.matrix td.yr-1 { border-left: 2px solid var(--rule-strong); }
.table-wrap.matrix th.yr-t, .table-wrap.matrix td.yr-t {
  font-weight: 700; border-right: 2px solid var(--rule-strong);
}
.table-wrap.matrix th.yr-p, .table-wrap.matrix td.yr-p,
.table-wrap.matrix th.yr-s, .table-wrap.matrix td.yr-s {
  color: var(--ink-soft); font-weight: 500;
}
.table-wrap.matrix thead th.yr {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-faint);
}
.table-wrap.matrix thead th.yr-t { color: var(--ink); }

/* Sorting affordance on the matrix headings. The arrow is drawn in a pseudo
   element so adding it cannot change the row height. */
.table-wrap.matrix th.sortable { cursor: pointer; user-select: none; position: relative; }
.table-wrap.matrix th.sortable:hover { color: var(--ink); }
.table-wrap.matrix th.sort-asc::after,
.table-wrap.matrix th.sort-desc::after {
  content: '▲'; font-size: .5rem; margin-left: 3px; color: var(--accent);
}
.table-wrap.matrix th.sort-desc::after { content: '▼'; }

/* One line per row, always. The pills used to wrap under a long service name
   and make that row twice the height of its neighbours, which broke the
   left-to-right read the grid exists for. */
.table-wrap.matrix td.stick, .table-wrap.matrix th.stick {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 22rem;
}
.table-wrap.matrix tbody tr { height: 2.05rem; }
.table-wrap.matrix tbody td { white-space: nowrap; }
.table-wrap.matrix .pill {
  max-width: 8.5rem; overflow: hidden; text-overflow: ellipsis;
  vertical-align: baseline;
}

/* ------------------------------------------------------------ demo estate */
/* One toolbar over a list of brands. The page's own prose was cut on
   2026-09-23 — Darryl: the reader came for an address, not for an essay — and
   the first cut of the filters put twelve brands and nine types across two
   rows of chips, which was taller than the first demo it was filtering. Who
   and what are menus now; state is three buttons, because that is the axis
   people actually toggle and its counts belong where the eye already is. */

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

.estate-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 20px;
}
.estate-find { flex: 0 1 22rem; min-width: 12rem; }
.estate-find input { width: 100%; }
.estate-pick { margin-left: auto; flex: none; }
.estate-pick select { min-width: 16rem; font-weight: 600; }

/* Who and what: a row each, one click per chip. The head (label, All, None)
   is its own non-shrinking box so it never moves; the chips wrap beside it. */
.trow { flex: 1 1 100%; display: flex; align-items: flex-start; gap: 10px; }
.trow-head { flex: none; display: flex; align-items: center; gap: 2px; min-width: 9.5rem; height: 30px; }
.tlabel {
  margin-right: 4px; font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-faint);
}
.tchips { flex: 1; display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.tchip {
  height: 30px; padding: 0 12px; border-radius: 99px; cursor: pointer;
  border: 1px solid var(--rule); background: var(--paper);
  font: inherit; font-size: 12.5px; color: var(--ink-faint); white-space: nowrap;
}
.tchip:hover { background: var(--sunken); color: var(--ink); }
.tchip.on {
  color: var(--ink); font-weight: 600; border-color: color-mix(in srgb, var(--accent) 45%, var(--rule));
  background: color-mix(in srgb, var(--accent) 8%, var(--paper));
}

.flink {
  padding: 4px 8px; border: 0; border-radius: var(--r-md); background: none;
  font: inherit; font-size: 12px; color: var(--ink-faint); cursor: pointer;
}
.flink:hover { background: var(--sunken); color: var(--ink); }

.seg { display: inline-flex; border: 1px solid var(--rule); border-radius: var(--r-lg); overflow: hidden; }
.segb {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  border: 0; background: var(--paper); cursor: pointer;
  font: inherit; font-size: 12.5px; color: var(--ink-faint); white-space: nowrap;
}
.segb + .segb { border-left: 1px solid var(--rule); }
.segb:hover { background: var(--sunken); }
.segb.on { color: var(--ink); font-weight: 600; background: color-mix(in srgb, var(--accent) 8%, var(--paper)); }
/* Off is off: a dot that still glowed on a switched-off button read as on. */
.segb:not(.on) .dot { background: var(--rule-strong); box-shadow: none; }
.segb b { font-weight: 600; font-variant-numeric: tabular-nums; }
.fcount { font-size: 12px; color: var(--ink-faint); white-space: nowrap; }

.textdlg {
  width: min(860px, 92vw); padding: 14px; color: var(--ink);
  border: 1px solid var(--rule); border-radius: var(--r-xl);
  background: var(--paper); box-shadow: var(--shadow);
}
.textdlg::backdrop { background: rgba(0,0,0,.45); }
.dlghead { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; font-size: 14px; }
.dlgbtns { display: inline-flex; gap: 6px; }
#dlgtext {
  display: block; width: 100%; height: min(480px, 60vh); resize: vertical; padding: 10px;
  border: 1px solid var(--rule); border-radius: var(--r-lg); background: var(--sunken); color: var(--ink);
  font-family: var(--font-mono); font-size: 12.5px; line-height: 1.5; white-space: pre;
}

.estate-sec { padding: 18px 20px 20px; }
.estate-sec + .estate-sec { margin-top: 18px; }
.estate-sec .sec-head { margin-bottom: 14px; }
.estate-sec h2 { font-size: 17px; }
.estate-sec .sec-head .sub { margin: 4px 0 0; }
.estate-sec .grp + .grp { margin-top: 16px; }
.estate-sec h3 {
  margin: 0 0 7px; font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint);
}
.estate-sec .where a { word-break: break-all; }
.estate-sec .where .val { font-family: var(--font-mono); font-size: 12.5px; }
.state { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.dot.warn    { background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 22%, transparent); }
.dot.unknown { background: var(--rule-strong); }
.sec-empty { display: none; margin: 0; color: var(--ink-faint); font-size: 13px; }
.estate-sec.all-out .sec-empty { display: block; }
.estate-foot { margin: 20px 2px 0; font-size: 12px; color: var(--ink-faint); }

@media (max-width: 720px) {
  .estate-find { flex: 1 1 100%; }
  .estate-pick { margin-left: 0; flex: 1 1 100%; }
  .estate-pick select { width: 100%; }
  .seg { flex: 1 1 100%; }
  .trow { flex-direction: column; gap: 6px; }
  .trow-head { height: auto; }
  .segb { flex: 1; justify-content: center; }
}

/* --------------------------------------------------------- the narrow rail */
/* One preference, remembered per browser: the rail folds to its icons so a
   wide page gets the width back (Darryl, 2026-09-23). Folded is a real state,
   not a hidden rail — every module is still one click away, each icon keeps
   its title, and a click on any of them widens the rail rather than opening a
   menu with no room to read it. The phone rail is untouched: there the rail
   already slides in over the page and folding it would leave nothing. */

.rail-top { position: relative; }
.rail-mark { display: none; width: 26px; height: 26px; border-radius: var(--r-md); }
.rail-fold {
  position: absolute; top: 20px; right: 14px;
  display: grid; place-items: center; width: 28px; height: 28px;
  border: 0; border-radius: var(--r-md); background: none;
  color: var(--ink-faint); cursor: pointer; opacity: 0; transition: opacity .12s;
}
.rail:hover .rail-fold, .rail-fold:focus-visible { opacity: 1; }
.rail-fold:hover { background: var(--sunken); color: var(--ink); }
.rail-fold .ico { width: 17px; height: 17px; }

body.rail-folded { --rail-w: 4.25rem; }
body.rail-folded .rail-top { padding: 22px 0 10px; text-align: center; }
body.rail-folded .rail-brand .wordmark { display: none; }
body.rail-folded .rail-mark { display: inline-block; }
body.rail-folded .rail-unit { display: none; }
body.rail-folded .rail-fold { position: static; margin: 12px auto 0; opacity: 1; transform: rotate(180deg); }
body.rail-folded .rail-nav { padding: 8px 10px 20px; }
body.rail-folded .rail-caption { height: 1px; margin: 14px 10px; padding: 0; overflow: hidden; background: var(--rule); color: transparent; }
body.rail-folded .rail-link { justify-content: center; padding: 0; gap: 0; }
body.rail-folded .rail-link > span, body.rail-folded .rail-chev { display: none; }
body.rail-folded .rail-link .ico { width: 19px; height: 19px; }
body.rail-folded .rail-sub { display: none; }
body.rail-folded .rail-foot { flex-direction: column; gap: 8px; margin: 0 8px; padding: 12px 0 14px; }
body.rail-folded .rail-me { display: none; }

@media (max-width: 720px) {
  /* Here the rail is the drawer behind the menu button, and a drawer of icons
     helps nobody — the fold is undone rather than drawn. */
  body.rail-folded { --rail-w: 16.5rem; }
  body.rail-folded .rail-mark, .rail-fold { display: none; }
  body.rail-folded .rail-brand .wordmark, body.rail-folded .rail-unit,
  body.rail-folded .rail-link > span, body.rail-folded .rail-chev,
  body.rail-folded .rail-sub, body.rail-folded .rail-me { display: revert; }
  body.rail-folded .rail-caption { height: auto; background: none; color: var(--ink-faint); }
  body.rail-folded .rail-link { justify-content: flex-start; padding: 0 10px; gap: 11px; }
  body.rail-folded .rail-foot { flex-direction: row; }
}

/* ---------------------------------------------------------------- tabstrip
   One record, several faces of it — a partner's company details, its
   customers, and the three parts of its portal. Not navigation: the rail owns
   that (`view.rail()`), and a module draws none of its own. This is the one
   record staying put while the view of it changes, which is why it sits under
   the page head rather than in the rail, and why a tab the person may not open
   is absent rather than disabled — the router refuses it too. */
.tabstrip {
  display: flex; gap: 2px; flex-wrap: wrap;
  border-bottom: 1px solid var(--rule);
  margin: 0 0 22px;
}
.tabstrip a {
  padding: 9px 14px; font-size: 13.5px; font-weight: 500;
  color: var(--ink-soft); border-bottom: 2px solid transparent;
  margin-bottom: -1px; border-radius: var(--r-md) var(--r-md) 0 0;
}
.tabstrip a:hover { color: var(--ink); background: var(--sunken); text-decoration: none; }
.tabstrip a.on { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }

/* A form that edits the record the page is about, rather than filtering a list.
   `.filters` is a row of controls above a table; this is a labelled grid. */
.editrow { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.editrow label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--ink-faint); }
.editrow input, .editrow select { min-width: 12rem; }
/* A row's long description, folded behind a toggle (Demo Estate). */
details.more summary { cursor: pointer; font-size: .78rem; color: var(--ink-soft); list-style: none; }
details.more summary::-webkit-details-marker { display: none; }
details.more[open] summary { margin-bottom: 4px; }
