/* ===========================================================
   Jusa — ON THE DAY
   The public design system. Source of truth for every
   server-rendered page.

   Ground is a cool paper so the logo green sits native.
   Ink is the logo navy so the mark reads as part of the type.
   Green does exactly one job: "this is set / this went out /
   this is live". The accent is clay — warm, human, and near
   complementary to the logo green so the pair reads deliberate.

   The logo itself (static/brand/**) is frozen and untouched.

   Ordering:
     1. tokens          5. shared objects
     2. base            6. public components
     3. type            7. legacy shims (DEPRECATED — sweep)
     4. layout          8. a11y / motion / small-phone hygiene
   =========================================================== */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT,WONK@0,9..144,300..700,0..60,0..1;1,9..144,400..600,0..60,0..1&family=IBM+Plex+Mono:ital,wght@0,400;0,500;0,600;1,400&family=Instrument+Sans:ital,wght@0,400..700;1,400..700&display=swap');

/* ============================================================
   1. TOKENS
   ============================================================ */
:root {
  /* night-band variants of the semantic pair, and the muted that survives
     on --ground-2. Were inline literals until the theme sweep. */
  --warning-bright: #E0B25A;
  --danger-bright:  #E2708A;
  --muted-on-2:     #5A6560;
  /* ---- GROUND & SURFACE ------------------------------------ */
  --ground:        #F2F3F0;  /* page ground, marketing + SPA. NOT cream. */
  --ground-2:      #E8EAE5;  /* banded sections, inset wells, table zebra */
  --ground-3:      #DCDFD8;  /* press states, run-bar track, disabled fills */
  --surface:       #FFFFFF;  /* cards, panels, the widget, modals */
  --surface-2:     #FAFBF9;  /* a nested surface inside a card */
  --elevated:      #FFFFFF;  /* dropdowns, popovers — same paint, real shadow */

  /* ---- INK ------------------------------------------------- */
  --ink:           #171C1A;  /* headlines, primary text        15.5:1 on ground */
  --ink-2:         #2A323B;  /* THE LOGO NAVY. secondary heads, dark surfaces  11.7:1 */
  --ink-soft:      #47514E;  /* long-form body, table cells     7.4:1 */
  --muted:         #66716C;  /* meta, captions, placeholders    4.6:1 */
  --subtle:        #97A09B;  /* disabled text, chart gridlines — decorative only */

  /* ---- RULES ----------------------------------------------- */
  --line:          #E0E2DC;  /* the default hairline. Does 90% of the structural work. */
  --line-strong:   #C6CAC1;  /* input borders, table head rules, band separators */

  /* ---- ACCENT — clay --------------------------------------- */
  --accent:        #B4431F;  /* buttons, links, emphasis  5.0:1 on ground, 5.9:1 on white */
  --accent-hover:  #8F3317;  /* hover / press            7.1:1 on ground */
  --accent-soft:   rgba(180, 67, 31, 0.09);   /* active nav, selected row, chip bg */
  --accent-line:   rgba(180, 67, 31, 0.28);   /* accent hairline, focus underline */
  --accent-bright: #F0805A;  /* accent on dark bands     6.6:1 on --night */
  --accent-bright-hover: #F79274;  /* its hover/press on the night bands */
  --on-accent:     #FFFFFF;  /* label on an accent fill  5.6:1 */

  /* ---- LIVE — the logo green. Fills only. Type is --live-ink. */
  --live:          #2A323B;  /* SET / SENT / LIVE. fills only: dots, run bars, ticks */
  --live-ink:      #2A323B;  /* SET type on light       11.7:1 on ground */
  --live-bright:   #E8EAE5;  /* SET on dark bands       12.1:1 on --night */
  --live-soft:     rgba(55, 172, 52, 0.11);

  /* ---- SEMANTIC -------------------------------------------- */
  --success:       #2A323B;
  --success-soft:  rgba(55, 172, 52, 0.11);
  --warning:       #8A5F0F;  /* wallet low, band climbing, cap near   5.1:1 */
  --warning-fill:  #B27A15;  /* the amber used as a fill, never as type */
  --warning-soft:  rgba(178, 122, 21, 0.13);
  --danger:        #97213B;  /* oxblood — hue 345, never confusable with the clay */
  --danger-soft:   rgba(151, 33, 59, 0.10);
  --info:          #2A323B;  /* neutral notices reuse the logo navy. No new blue. */
  --info-soft:     rgba(42, 50, 59, 0.07);

  /* ---- INVERTED / NIGHT ------------------------------------ */
  --night:         #161B20;  /* the dark band ground — navy-black, logo-native */
  --night-2:       #2A323B;  /* THE LOGO NAVY as the raised surface inside a band */
  --night-3:       #3A434C;  /* hairline / border on dark */
  --night-text:    #F2F3F0;
  --night-muted:   #9AA3A8;
  --night-line:    rgba(242, 243, 240, 0.13);

  /* ---- RATE WATCH ramp (verdict scale, good -> bad) --------- */
  --rate-good:     #2A323B;
  --rate-hold:     #8A5F0F;
  --rate-bad:      #97213B;
  --rate-series:   #B4431F;
  --rate-ghost:    rgba(42, 50, 59, 0.14);
  --rate-band:     rgba(180, 67, 31, 0.10);

  /* ---- AVATAR TINTS (6). Glyph/initials are always --ink. --- */
  --av-clay:  #EBD3C8;
  --av-sage:  #DCDAD2;
  --av-ochre: #EDDDB9;
  --av-dusk:  #CDD4DB;
  --av-rose:  #EBCCD4;
  --av-moss:  #CFD6DB;

  /* ---- CHART CATEGORICAL (6, in order) --------------------- */
  --cat-1: #B4431F;  --cat-2: #2A323B;  --cat-3: #12655C;
  --cat-4: #8A5F0F;  --cat-5: #12857F;  --cat-6: #6E4F8E;

  /* ---- TYPE FAMILIES --------------------------------------- */
  --f-display: "Fraunces", Georgia, "Times New Roman", serif;
  --f-body:    "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
               system-ui, sans-serif;
  --f-num:     "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* ---- RADIUS — exactly three. There is no fourth. ---------- */
  --r-card:  14px;
  --r-ctl:   9px;
  --r-round: 999px;

  /* ---- SHADOW — exactly two. ------------------------------- */
  --shadow-lift:  0 1px 2px -1px rgba(23, 28, 26, .10),
                  0 10px 24px -14px rgba(23, 28, 26, .20);
  --shadow-modal: 0 28px 60px -22px rgba(23, 28, 26, .38);

  /* ---- SPACE — 4px base. Nothing off-scale. ---------------- */
  --s-1: 4px;   --s-2: 8px;   --s-3: 12px;  --s-4: 16px;
  --s-5: 24px;  --s-6: 32px;  --s-7: 48px;  --s-8: 64px;
  --s-9: 96px;  --s-10: 128px;

  /* ---- LAYOUT ---------------------------------------------- */
  --gutter:        clamp(1.25rem, 4vw, 2.5rem);
  --container:     1280px;
  --container-app: 1440px;
  --measure-lede:  56ch;
  --measure-body:  68ch;
  --section-pad:   clamp(4.5rem, 9vw, 8rem);
  --band-pad:      clamp(5.5rem, 11vw, 9.5rem);

  /* ---- DENSITY — one system, two amplitudes. --------------- */
  --d:    1;      /* every type size below is multiplied by --d */
  --rh:   64px;   /* person-row height */
  --pad:  24px;   /* panel padding */
  --av:   56px;   /* avatar size on this surface */

  /* ---- MOTION ---------------------------------------------- */
  --ease:      cubic-bezier(.2, .7, .3, 1);
  --t-state:   160ms;
  --t-enter:   240ms;
  --t-runbar:  420ms;

  /* ---- TYPE SCALE — sizes only; weight/lh/tracking live on
         the classes below so the shorthand stays legal. ------- */
  --t-display-xl: calc(clamp(3rem, 8.5vw, 6rem) * var(--d));
  --t-display-1:  calc(clamp(2.5rem, 5.5vw, 4rem) * var(--d));
  --t-display-2:  calc(clamp(1.875rem, 3.4vw, 2.75rem) * var(--d));
  --t-display-3:  calc(1.5rem * var(--d));
  --t-name:       calc(1.0625rem * var(--d));
  --t-quote:      calc(clamp(1.25rem, 2.2vw, 1.75rem) * var(--d));
  --t-lede:       calc(clamp(1.0625rem, 1.5vw, 1.3125rem) * var(--d));
  --t-body:       calc(1.0625rem * var(--d));
  --t-sm:         calc(0.9375rem * var(--d));
  --t-xs:         calc(0.8125rem * var(--d));
  --t-ui:         calc(0.875rem * var(--d));
  /* The one size that is NOT multiplied by --d. §3.3 scales it; anti-pattern 17
     pins it ("no ALL CAPS except --t-label at 11px with +.14em tracking"). The
     anti-pattern wins: at the SPA's --d of .875 the scaled value is 9.6px
     tracked caps, below any legibility floor, and this is the most-repeated
     type in the product. 11px everywhere, both densities. */
  --t-label:      0.6875rem;
  --t-num-xl:     calc(clamp(2.75rem, 6vw, 4.25rem) * var(--d));
  --t-num-lg:     calc(1.75rem * var(--d));
  --t-num:        calc(1.0625rem * var(--d));
  --t-num-sm:     calc(0.875rem * var(--d));

  /* ============================================================
     BACKWARDS-COMPATIBILITY ALIASES
     DEPRECATED — sweep. They exist so the ~10 000 lines of
     existing markup do not break mid-migration. Do not write
     new code against them.
     ============================================================ */
  --paper:        var(--ground);          /* DEPRECATED — sweep */
  --paper-warm:   var(--ground-2);        /* DEPRECATED — sweep */
  --paper-deep:   var(--ground-3);        /* DEPRECATED — sweep */
  --bg:           var(--ground);          /* DEPRECATED — sweep */
  --fg:           var(--ink);             /* DEPRECATED — sweep */
  --rule:         var(--line);            /* DEPRECATED — sweep */
  --rule-strong:  var(--line-strong);     /* DEPRECATED — sweep */
  --rule-dark:    var(--night-3);         /* DEPRECATED — sweep */
  --accent-50:    var(--accent-soft);     /* DEPRECATED — sweep */
  --stamp:        var(--accent);          /* DEPRECATED — sweep */
  --stamp-deep:   var(--accent-hover);    /* DEPRECATED — sweep */
  --stamp-soft:   var(--accent-soft);     /* DEPRECATED — sweep */
  --stamp-glow:   var(--accent-bright);   /* DEPRECATED — sweep */
  --brass:        var(--accent);          /* DEPRECATED — sweep */
  --brass-soft:   var(--accent-soft);     /* DEPRECATED — sweep */
  --brass-glow:   var(--accent-bright);   /* DEPRECATED — sweep */
  --f-mono:       var(--f-num);           /* DEPRECATED — sweep */
  --ok:           var(--success);         /* DEPRECATED — sweep */
  --ok-soft:      var(--success-soft);    /* DEPRECATED — sweep */
  --warn:         var(--warning);         /* DEPRECATED — sweep */
  --warn-soft:    var(--warning-soft);    /* DEPRECATED — sweep */
  --text:         var(--ink);             /* DEPRECATED — sweep */
  --panel:        var(--surface);         /* DEPRECATED — sweep */
  --panel-2:      var(--ground-2);        /* DEPRECATED — sweep */
  --accent-dim:   var(--accent-bright);   /* DEPRECATED — sweep */
  /* --shadow-sm/md/lg are deleted, not aliased, so nobody can reach
     for them. Use --shadow-lift, or a 1px solid var(--line) border,
     which is nearly always what was wanted. */
}

/* ============================================================
   2. BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 96px; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video, canvas { max-width: 100%; height: auto; }

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

a { color: inherit; text-decoration: none; transition: color var(--t-state) var(--ease); }
a.link, .prose a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--accent-line);
}
a.link:hover, .prose a:hover { color: var(--accent-hover); text-decoration-color: currentColor; }

button { font: inherit; cursor: pointer; }

p { margin: 0 0 1em; max-width: var(--measure-body); }
p:last-child { margin-bottom: 0; }

hr, hr.rule {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--s-5) 0;
}

code, pre, kbd, samp {
  font-family: var(--f-num);
  font-variant-numeric: tabular-nums;
}
code {
  font-size: 0.86em;
  background: var(--ground-2);
  padding: 0.1rem 0.32rem;
  border-radius: 5px;
}
pre { overflow-x: auto; }

/* One global focus treatment. No :focus { outline: none } anywhere. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
.invert :focus-visible,
.band :focus-visible { outline-color: var(--accent-bright); }

/* Skip link — visible on focus, on every public page. */
.skip-link {
  position: absolute; left: var(--s-4); top: -100px; z-index: 100;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  padding: 10px 16px;
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 500;
}
.skip-link:focus-visible { top: var(--s-4); }

/* ============================================================
   3. TYPE
   ============================================================ */

/* Display — Fraunces. WONK 1 only above 1.5rem, weight never above 600,
   never below 1rem, never in a paragraph. */
.h-display, .section-title, .hero-title, .band-title, .quote,
h1.h-display, h2.section-title, h1.hero-title {
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 144, 'SOFT' 40, 'WONK' 1;
  font-weight: 600;
  color: var(--ink);
  margin: 0;
  max-width: none;              /* headlines run to the gutter. No max-width. */
  text-wrap: balance;
}

.hero-title  { font-size: var(--t-display-xl); line-height: .92; letter-spacing: -.032em; }
.band-title  { font-size: var(--t-display-1);  line-height: .98; letter-spacing: -.028em; }
.section-title, h2.section-title {
  font-size: var(--t-display-2); line-height: 1.06; letter-spacing: -.022em;
}
.band .section-title, .invert .section-title {
  font-size: var(--t-display-1); line-height: .98; letter-spacing: -.028em;
}
.h-display   { font-size: var(--t-display-2); line-height: 1.06; letter-spacing: -.022em; }
.card-title, h3.card-title, .h3 {
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 600;
  font-size: var(--t-display-3);
  line-height: 1.15; letter-spacing: -.016em;
  color: var(--ink); margin: 0;
}

/* Names, and anything under 1.5rem in the display face. */
.person-name, .t-name {
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 500;
  font-size: var(--t-name);
  line-height: 1.2; letter-spacing: -.008em;
  color: var(--ink);
}

/* The only italic display in the system. */
.quote {
  font-size: var(--t-quote); line-height: 1.35; letter-spacing: -.01em;
  font-weight: 400; font-style: italic;
  font-variation-settings: 'opsz' 96, 'SOFT' 40, 'WONK' 1;
  max-width: var(--measure-lede);
}

/* Emphasis inside a headline is a colour shift, never an italic. */
.h-display em, .section-title em, .hero-title em, .band-title em,
.card-title em, h1 em, h2 em, h3 em {
  font-style: normal;
  font-weight: inherit;
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
  text-decoration-color: var(--accent-line);
}
/* The two words the whole page is about. A highlighter stroke sits behind
   the lower half of the word — ink stays ink, so the headline still reads as
   one sentence, but the eye lands on Airtime and ZESA first. Distinct from
   <em>, which is the clay underline reserved for the promise ("choose"). */
.hero-title mark {
  background: linear-gradient(to top, var(--accent-soft) 0 46%, transparent 46%);
  /* "Airtime" and "ZESA" are the two words the whole page is about, so they
     are named in the accent rather than merely underlined in it. */
  color: var(--accent);
  padding: 0 .04em;
  margin: 0 -.04em;
  border-radius: .08em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.hero-title mark::selection { background: var(--accent-soft); }

.invert .h-display em, .invert .section-title em, .invert .band-title em,
.invert h1 em, .invert h2 em, .invert h3 em,
.band .section-title em, .band .band-title em, .band h1 em, .band h2 em {
  color: var(--accent-bright);
  text-decoration-color: rgba(240, 128, 90, .34);
}

/* Body */
.lede, .section-lede, .hero-sub {
  font-family: var(--f-body);
  font-size: var(--t-lede); line-height: 1.52; letter-spacing: -.005em;
  font-weight: 400;
  color: var(--ink-soft);
  max-width: var(--measure-lede);
  margin: 0;
}
.t-body { font-size: var(--t-body); line-height: 1.6; max-width: var(--measure-body); }
.t-sm   { font-size: var(--t-sm);   line-height: 1.5; }
.t-xs, .fineprint {
  font-size: var(--t-xs); line-height: 1.45; color: var(--muted);
  max-width: var(--measure-body);
}
.t-ui { font-size: var(--t-ui); line-height: 1.2; font-weight: 500; }

/* The system's signature: 11px mono, uppercase, +.14em. */
.t-label, .eyebrow, .field-label, .person-rel, .person-when,
.figure-label, .table th, .tag {
  font-family: var(--f-num);
  font-size: var(--t-label);
  line-height: 1;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Every numeral that is money, a date, a time-until or units. */
.num, .figure, .figure-val, .person-amt, .amt,
.table td.num, .table th.num,
[class*="-amt"], [class*="-val"] {
  font-family: var(--f-num);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1, 'zero' 1;   /* slashed zero */
  letter-spacing: -.005em;
}
.num-xl { font-size: var(--t-num-xl); line-height: 1; font-weight: 500; letter-spacing: -.02em; }
.num-lg { font-size: var(--t-num-lg); line-height: 1; font-weight: 500; letter-spacing: -.015em; }
.num-sm { font-size: var(--t-num-sm); line-height: 1.2; font-weight: 500; letter-spacing: 0; }

/* Deltas always carry a polarity word in the markup; the colour only reinforces it. */
.delta { font-family: var(--f-num); font-size: var(--t-num-sm); font-weight: 500;
         font-variant-numeric: tabular-nums; color: var(--muted); }
.delta.up, .delta.good, .delta.ok { color: var(--success); }
.delta.down, .delta.bad          { color: var(--danger); }
.delta.warn, .delta.hold         { color: var(--warning); }
.invert .delta.up, .invert .delta.good, .invert .delta.ok { color: var(--live-bright); }
.invert .delta.down, .invert .delta.bad { color: var(--danger-bright); }
.invert .delta.warn, .invert .delta.hold { color: var(--warning-bright); }

.muted { color: var(--muted); }
.mono  { font-family: var(--f-num); font-variant-numeric: tabular-nums; }

/* ============================================================
   4. LAYOUT
   ============================================================ */
.wrap {
  width: 100%; max-width: var(--container);
  margin: 0 auto; padding: 0 var(--gutter);
}
.wrap-narrow { max-width: 860px; }

section.section, .section { padding: var(--section-pad) 0; position: relative; }
.section.on-ground-2 { background: var(--ground-2); }
/* --muted is tuned for --ground (4.6:1). On the ground-2 field it falls to
   4.2:1 — below AA, and this is the field the 11px .eyebrow sits on. The
   surfaces painted in ground-2 darken it one notch rather than every rule
   that uses it needing an exception. */
.section.on-ground-2, footer.site { --muted: var(--muted-on-2); }
.section.on-surface  { background: var(--surface); }

/* The two night bands plus the closer. Nothing else is dark. */
.band, .invert {
  background: var(--night);
  color: var(--night-text);
}
.band { padding: var(--band-pad) 0; position: relative; }
.band h1, .band h2, .band h3,
.invert h1, .invert h2, .invert h3,
.band .section-title, .band .band-title, .band .card-title,
.invert .section-title, .invert .card-title, .invert .person-name { color: var(--night-text); }
.band p, .invert p { color: var(--night-muted); }
.band .lede, .band .section-lede, .invert .lede, .invert .section-lede { color: var(--night-muted); }
.band .t-xs, .invert .t-xs, .band .fineprint, .invert .fineprint { color: var(--night-muted); }
.band a.link, .invert a.link { color: var(--accent-bright); text-decoration-color: rgba(240,128,90,.34); }
.band hr, .invert hr, .band hr.rule, .invert hr.rule { border-top-color: var(--night-line); }
.band code, .invert code { background: rgba(242,243,240,.08); color: var(--night-text); }

/* Asymmetric splits only. Never 6/6 on the marketing site. */
.split-7-5, .split-8-4, .split-5-7, .split-4-8 {
  display: grid; gap: clamp(var(--s-6), 5vw, var(--s-8)); align-items: start;
}
.split-7-5 { grid-template-columns: 7fr 5fr; }
.split-5-7 { grid-template-columns: 5fr 7fr; }
.split-8-4 { grid-template-columns: 8fr 4fr; }
.split-4-8 { grid-template-columns: 4fr 8fr; }
@media (max-width: 900px) {
  .split-7-5, .split-8-4, .split-5-7, .split-4-8 { grid-template-columns: 1fr; }
}

.grid { display: grid; gap: clamp(var(--s-4), 2.4vw, var(--s-5)); }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 980px) { .grid.cols-3, .grid.cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .grid.cols-2, .grid.cols-3, .grid.cols-4 { grid-template-columns: 1fr; } }

.section-head {
  display: flex; flex-direction: column; gap: var(--s-4);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
  /* no max-width — display type runs to the gutter */
}
.stack   { display: flex; flex-direction: column; gap: var(--s-4); }
.stack-2 { display: flex; flex-direction: column; gap: var(--s-2); }
.row     { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.actions { display: flex; align-items: center; gap: var(--s-2); }

/* ============================================================
   5. SHARED OBJECTS
   === SHARED OBJECTS v1 — keep byte-equivalent with
       frontend/src/styles/objects.css ===
   Five nouns: .eyebrow, .person, .runbar, .tag, .figure.
   If a design need is not one of these, it is a composition
   of them.
   ============================================================ */

/* --- 1. .eyebrow — the section label. No numbering, ever. --- */
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-num);
  font-size: var(--t-label); line-height: 1; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}
.eyebrow::before {
  content: ""; flex: none;
  width: 3px; height: 14px; border-radius: 1px;
  background: var(--accent);
}
.eyebrow.is-accent { color: var(--accent); }
.band .eyebrow, .invert .eyebrow { color: var(--night-muted); }
.band .eyebrow::before, .invert .eyebrow::before { background: var(--accent-bright); }
.band .eyebrow.is-accent, .invert .eyebrow.is-accent { color: var(--accent-bright); }

/* --- 2. .person — the person row. The most-repeated object. -- */
.person {
  display: grid;
  grid-template-columns: var(--av) 1fr auto;
  align-items: center;
  gap: var(--s-4);
  min-height: var(--rh);
  padding: 0 var(--pad);
  transition: background var(--t-state) var(--ease);
}
.person + .person { border-top: 1px solid var(--line); }
.band .person + .person, .invert .person + .person { border-top-color: var(--night-line); }
.person.is-link, a.person, .person[role="button"] { cursor: pointer; }
.person.is-link:hover, a.person:hover { background: var(--surface-2); }
.person.is-link:hover .person-av, a.person:hover .person-av { transform: scale(1.02); }
.band .person.is-link:hover, .invert .person.is-link:hover { background: rgba(242,243,240,.05); }

.person-av {
  width: var(--av); height: var(--av); border-radius: var(--r-round);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--av-dusk); color: var(--ink);
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 500;
  font-size: calc(var(--av) * .38);
  line-height: 1; overflow: hidden; flex: none;
  transition: transform var(--t-state) var(--ease);
}
.person-av img { width: 100%; height: 100%; object-fit: cover; }
.person-av.av-clay  { background: var(--av-clay); }
.person-av.av-sage  { background: var(--av-sage); }
.person-av.av-ochre { background: var(--av-ochre); }
.person-av.av-dusk  { background: var(--av-dusk); }
.person-av.av-rose  { background: var(--av-rose); }
.person-av.av-moss  { background: var(--av-moss); }
.person-av.is-lg { width: 96px; height: 96px; font-size: 36px; }
.person-av.is-xl { width: 140px; height: 140px; font-size: 52px; }

.person-main { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.person-name { display: block; overflow-wrap: anywhere; }
.person-rel {
  display: block; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.person-side {
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  text-align: right;
}
.person-amt {
  font-size: var(--t-num); line-height: 1.2; font-weight: 500;
  letter-spacing: -.005em; color: var(--ink);
}
.person-when { color: var(--muted); white-space: nowrap; }
.band .person-name, .invert .person-name, .band .person-amt, .invert .person-amt { color: var(--night-text); }
.band .person-rel, .invert .person-rel, .band .person-when, .invert .person-when { color: var(--night-muted); }

/* Required compact variant — tables, calendar chips, the mobile agenda. */
.person.is-compact {
  --av: 20px;
  grid-template-columns: 20px 1fr auto;
  gap: var(--s-2);
  min-height: 32px; padding: 0;
}
.person.is-compact .person-main { flex-direction: row; align-items: baseline; gap: var(--s-2); }
.person.is-compact .person-side { flex-direction: row; align-items: baseline; gap: var(--s-2); }
.person.is-compact .person-name { font-size: var(--t-sm); }
.person.is-compact .person-av { font-size: 10px; }

/* --- 3. .runbar — time until the next scheduled send. -------
   Renders nothing else. Never an inferred balance. Where there
   is no next send the bar is not rendered at all. */
.runbar {
  position: relative; display: block;
  height: 4px; border-radius: var(--r-round);
  background: var(--ground-3);
  overflow: hidden;
  margin: 0 var(--pad) var(--s-3);
}
.runbar > i, .runbar-fill {
  display: block; height: 100%;
  border-radius: var(--r-round);
  background: var(--live);
  width: var(--runbar-fill, 0%);
  transition: width var(--t-runbar) var(--ease);
}
.runbar::after {            /* the 1px notch at "today" */
  content: ""; position: absolute; top: 0; bottom: 0;
  left: var(--runbar-today, 0%);
  width: 1px; background: var(--ground);
}
.band .runbar, .invert .runbar { background: rgba(242,243,240,.16); }
.band .runbar > i, .invert .runbar > i,
.band .runbar-fill, .invert .runbar-fill { background: var(--live-bright); }
.band .runbar::after, .invert .runbar::after { background: var(--night); }
.runbar-label { display: block; padding: 0 var(--pad) var(--s-3);
                font-family: var(--f-num); font-size: var(--t-label);
                letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }

/* --- 4. .tag — the state pill. Read-only. ------------------- */
.tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-round);
  border: 0;
  /* --ink-soft, not --muted: 11px tracked caps on the ground-2 fill is
     4.2:1 in --muted, below AA. --ink-soft is 6.8:1 on the same fill. */
  background: var(--ground-2); color: var(--ink-soft);
  white-space: nowrap;
  /* no rotation, no border, no rubber-stamp tilt */
}
.tag.is-set,  .tag.ok      { background: var(--success-soft); color: var(--success); }
.tag.is-due,  .tag.info    { background: var(--info-soft);    color: var(--ink-2); }
.tag.is-live              { background: var(--live-soft);    color: var(--live-ink); }
.tag.is-warn, .tag.warn    { background: var(--warning-soft); color: var(--warning); }
.tag.is-bad,  .tag.bad,
.tag.fail                  { background: var(--danger-soft);  color: var(--danger); }
.tag.is-off,  .tag.dim,
.tag.pending               { background: var(--ground-2);     color: var(--ink-soft); }
.tag.is-live::before {
  content: ""; width: 6px; height: 6px; border-radius: var(--r-round);
  background: var(--live); flex: none;
  animation: live-pulse 2.4s var(--ease) infinite;
}
@keyframes live-pulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
.band .tag.is-off, .invert .tag.is-off,
.band .tag, .invert .tag { background: rgba(242,243,240,.09); color: var(--night-muted); }
.band .tag.is-set, .invert .tag.is-set { background: rgba(85,206,80,.14); color: var(--live-bright); }
.band .tag.is-live, .invert .tag.is-live { background: rgba(85,206,80,.14); color: var(--live-bright); }
.band .tag.is-warn, .invert .tag.is-warn { background: color-mix(in srgb, var(--warning-bright) 15%, transparent); color: var(--warning-bright); }
.band .tag.is-bad, .invert .tag.is-bad { background: color-mix(in srgb, var(--danger-bright) 15%, transparent); color: var(--danger-bright); }
.band .tag.is-due, .invert .tag.is-due { background: rgba(242,243,240,.09); color: var(--night-text); }

/* --- 5. .figure — the readout. Never carries a shadow. ------ */
.figure { display: flex; flex-direction: column; gap: var(--s-2); }
.figure-label { color: var(--muted); }
.figure-val {
  font-size: var(--t-num-lg); line-height: 1; font-weight: 500;
  letter-spacing: -.015em; color: var(--ink);
}
.figure.is-hero .figure-val { font-size: var(--t-num-xl); letter-spacing: -.02em; }
.figure-delta { font-family: var(--f-num); font-size: var(--t-num-sm); font-weight: 500;
                font-variant-numeric: tabular-nums; color: var(--muted); }
.figure-spark { display: block; height: 32px; width: 100%; }
.figure-spark path, .figure-spark polyline { fill: none; stroke: var(--rate-series); stroke-width: 1.5; }
.figure-grid {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.figure-grid > .figure { padding: var(--s-4) var(--s-5); border-left: 1px solid var(--line); }
.figure-grid > .figure:first-child { border-left: 0; padding-left: 0; }
.band .figure-val, .invert .figure-val { color: var(--night-text); }
.band .figure-label, .invert .figure-label { color: var(--night-muted); }
.band .figure-grid > .figure, .invert .figure-grid > .figure { border-left-color: var(--night-line); }

/* ============================================================
   6. PUBLIC COMPONENTS
   ============================================================ */

/* ---- Buttons. There is no green button anywhere in the
        system: green means state, not action. --------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; min-height: 44px; padding: 0 18px;
  border-radius: var(--r-ctl);
  border: 1px solid transparent;
  font-family: var(--f-body); font-weight: 500;
  font-size: var(--t-ui); line-height: 1.2; letter-spacing: 0;
  color: var(--ink); background: transparent;
  cursor: pointer; white-space: nowrap;
  transition: background var(--t-state) var(--ease),
              border-color var(--t-state) var(--ease),
              color var(--t-state) var(--ease);
}
.btn.primary { background: var(--accent); color: var(--on-accent); }
.btn.primary:hover { background: var(--accent-hover); }
.btn.secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn.secondary:hover { border-color: var(--ink-2); }
.btn.ghost { background: transparent; color: var(--accent); }
.btn.ghost:hover { background: var(--accent-soft); }
.btn.sm { height: 34px; min-height: 34px; padding: 0 12px; font-size: var(--t-xs); position: relative; }
.btn.sm::before {           /* padded to a 44px hit area */
  content: ""; position: absolute; left: 0; right: 0;
  top: 50%; transform: translateY(-50%); height: 44px;
}
.btn.lg { height: 52px; min-height: 52px; padding: 0 24px; font-size: var(--t-sm); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.btn .arrow { display: inline-block; transition: transform var(--t-state) var(--ease); }
.btn:hover .arrow { transform: translateX(2px); }
.band .btn.primary, .invert .btn.primary { background: var(--accent-bright); color: var(--night); }
.band .btn.primary:hover, .invert .btn.primary:hover { background: var(--accent-bright-hover); }
.band .btn.secondary, .invert .btn.secondary {
  background: transparent; color: var(--night-text); border-color: var(--night-3);
}
.band .btn.secondary:hover, .invert .btn.secondary:hover { border-color: var(--night-text); }
.band .btn.ghost, .invert .btn.ghost { color: var(--accent-bright); }
.band .btn.ghost:hover, .invert .btn.ghost:hover { background: rgba(240,128,90,.12); }

/* A text link that behaves like an action. */
.btn-link, .feat-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 500;
  color: var(--accent); min-height: 44px;
}
.btn-link:hover, .feat-link:hover { color: var(--accent-hover); }
.btn-link .arrow, .feat-link .arrow { transition: transform var(--t-state) var(--ease); }
.btn-link:hover .arrow, .feat-link:hover .arrow { transform: translateX(2px); }
.band .btn-link, .invert .btn-link, .band .feat-link, .invert .feat-link { color: var(--accent-bright); }

/* ---- Cards. No shadow at rest. Borders before shadows. ----- */
.card, .feat, .panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: var(--pad);
  position: relative;
  display: flex; flex-direction: column; gap: var(--s-3);
  transition: border-color var(--t-state) var(--ease),
              box-shadow var(--t-state) var(--ease);
}
.card.is-lift:hover { box-shadow: var(--shadow-lift); border-color: var(--line-strong); }
.card.no-hover:hover, .feat.no-hover:hover { border-color: var(--line); box-shadow: none; }
.card.is-flush { padding: 0; overflow: hidden; }
.card.is-well { background: var(--surface-2); }
.band .card, .invert .card, .band .feat, .invert .feat, .band .panel, .invert .panel {
  background: var(--night-2); border-color: var(--night-3); color: var(--night-text);
}
.band .card.is-lift:hover, .invert .card.is-lift:hover { border-color: var(--night-muted); box-shadow: none; }

.card-head, .feat-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}
.band .card-head, .invert .card-head,
.band .feat-head, .invert .feat-head { border-bottom-color: var(--night-line); }
.card-foot, .feat-detail {
  margin-top: auto; padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap;
  font-family: var(--f-num); font-size: var(--t-label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.card-foot b, .feat-detail b { color: var(--ink); font-weight: 600; }
.band .card-foot, .invert .card-foot,
.band .feat-detail, .invert .feat-detail { border-top-color: var(--night-line); color: var(--night-muted); }
.band .card-foot b, .invert .feat-detail b { color: var(--night-text); }

.card p, .feat p { color: var(--ink-soft); font-size: var(--t-sm); line-height: 1.5; }
.band .card p, .invert .card p, .band .feat p, .invert .feat p { color: var(--night-muted); }

/* ---- Signal strip — 32px, one line, never dismissible. ----- */
.signal-strip {
  background: var(--night); color: var(--night-text);
  height: 32px; display: flex; align-items: center; overflow: hidden;
}
.signal-strip .wrap { display: flex; align-items: center; justify-content: center; gap: 10px; }
.signal-strip, .signal-strip a {
  font-family: var(--f-num); font-size: var(--t-label);
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  line-height: 1; white-space: nowrap;
}
.signal-strip a { color: var(--accent-bright); }
.signal-strip .dot {
  width: 6px; height: 6px; border-radius: var(--r-round);
  background: var(--live-bright); flex: none;
  animation: live-pulse 2.4s var(--ease) infinite;
}
.signal-strip .marquee {
  display: inline-flex; gap: 10px; align-items: center;
  animation: signal-scroll 40s linear infinite;
}
@keyframes signal-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---- Sticky header ---------------------------------------- */
header.site {
  position: sticky; top: 0; z-index: 20;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(140%) blur(8px);
  -webkit-backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--line);
}
.nav-bar, .nav-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5); min-height: 64px;
}
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); }
.brand img, .brand .jusa-mark { width: 34px; height: 34px; }

/* --- Jusa mark (inline SVG from templates/_jusa_mark.html) ----------------
   The tick is SMIL inside the SVG (an <animateTransform> on the hand), so no
   CSS transform may touch .hand: a CSS transform outranks the animated
   attribute and would freeze it. Recolour with --jusa-ink / --jusa-accent. */
.jusa-mark { display: block; flex-shrink: 0; }
.brand .word {
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 500; font-size: 15px; line-height: 1; letter-spacing: -.008em;
  /* The wordmark carries the accent. This is identity, not a call to action:
     it is the same clay, but it never competes with a button because it never
     looks like one. See the 70/20/10 note at the top of this file. */
  color: var(--accent);
}
.brand .word em { font-style: normal; font-weight: 500; color: var(--accent); }
.band .brand .word, .invert .brand .word { color: var(--accent-bright); }
.nav-links { display: inline-flex; align-items: center; gap: clamp(12px, 2.2vw, 28px); }
.nav-links a {
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 500;
  color: var(--ink-soft);
  display: inline-flex; align-items: center; min-height: 44px;
}
.nav-links a:hover { color: var(--accent); }
.nav-links a[aria-current="page"] { color: var(--ink); }
.nav-links a.nav-cta {
  height: 34px; min-height: 34px; padding: 0 14px;
  border-radius: var(--r-ctl);
  background: var(--accent); color: var(--on-accent);
  transition: background var(--t-state) var(--ease);
}
.nav-links a.nav-cta:hover { background: var(--accent-hover); color: var(--on-accent); }
@media (max-width: 640px) { .nav-links a.hide-on-mobile { display: none; } }

/* ---- Footer ----------------------------------------------- */
footer.site {
  background: var(--ground-2);
  border-top: 1px solid var(--line-strong);
  padding: var(--s-8) 0 var(--s-6);
}
footer.site .row {
  display: flex; flex-wrap: wrap; gap: var(--s-5);
  justify-content: space-between; align-items: baseline;
  color: var(--ink-soft); font-size: var(--t-sm);
}
footer.site a { color: var(--ink-soft); margin-right: var(--s-4); }
footer.site a:hover { color: var(--accent); }
footer.site .legal {
  font-family: var(--f-num); font-size: var(--t-label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}

footer.site .foot-app {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2) var(--s-4);
  margin: var(--s-5) 0 var(--s-3); font-size: var(--t-sm);
}
footer.site .foot-app .eyebrow { margin: 0; }
footer.site .foot-app a { color: var(--ink); margin-right: 0; text-decoration: underline;
  text-decoration-color: var(--accent-line); text-underline-offset: 3px; }

/* ---- Store badges: the official artwork, unmodified. ---------
   Google's PNG carries its own clear space (41px of 250 on every side),
   Apple's SVG carries none; Google's is shown in a box the size of the
   badge itself (the clear space trimmed, the artwork untouched) so both
   badges show at the same visible height, which is what both sets of
   guidelines ask for. Apple's minimum on screen is 40px; this is 48. */
.store-badges { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-4); }
.store-badge { display: inline-flex; line-height: 0; border-radius: 8px; }
.store-badge.is-apple img { height: 48px; width: auto; }
.store-badge.is-play { width: 162px; height: 48px; overflow: hidden; }
.store-badge.is-play img { flex: none; height: 72px; width: 186px; max-width: none; margin: -12px; }
.store-trademarks { font-size: 11px; line-height: 1.5; color: var(--muted); margin-top: var(--s-4); max-width: 60ch; }

/* ---- Tables. Below 700px they restructure, never scroll. --- */
.table { width: 100%; border-collapse: collapse; }
.table th, .table td {
  padding: 10px 12px; text-align: left;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm); color: var(--ink-soft);
}
.table th { color: var(--muted); border-bottom: 1px solid var(--line-strong); }
.table td.num, .table th.num { text-align: right; }
.table tr:last-child td { border-bottom: 0; }
.table.is-zebra tbody tr:nth-child(even) { background: var(--surface-2); }
.table-scroll { overflow-x: auto; }

/* ---- Forms ------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--s-4); }
.field-label { display: block; color: var(--muted); }
.input, input.text, select.text, textarea.text {
  width: 100%; height: 44px; padding: 0 12px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  font-family: var(--f-body); font-size: var(--t-body); font-weight: 400; line-height: 1.2;
  transition: border-color var(--t-state) var(--ease);
}
textarea.text, textarea.input { height: auto; padding: 10px 12px; line-height: 1.5; }
.input:focus, input.text:focus, select.text:focus, textarea.text:focus {
  outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent);
}
.input::placeholder, input.text::placeholder { color: var(--muted); }
.input.is-num, input.text.is-num {
  font-family: var(--f-num); font-variant-numeric: tabular-nums;
}
.field-hint  { font-size: var(--t-xs); line-height: 1.45; color: var(--muted); }
.field-error { font-size: var(--t-xs); line-height: 1.45; color: var(--danger); }
.input-wrap { position: relative; }

/* ---- Pills — a choice, not a state. ----------------------- */
.pill {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 14px;
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  background: var(--surface); color: var(--ink);
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 500;
  cursor: pointer;
  transition: border-color var(--t-state) var(--ease),
              background var(--t-state) var(--ease), color var(--t-state) var(--ease);
}
.pill:hover { border-color: var(--accent); }
.pill[data-active="1"], .pill.is-on, .pill[aria-pressed="true"] {
  /* --accent-hover, not --accent: the 9% accent wash over --ground is only
     4.4:1 against --accent, and 4.1:1 over --ground-2. --accent-hover clears
     AA on every ground this pill can sit on. */
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent-hover);
}

/* ---- Tabs — a 2px accent underline. Not pill-shaped. ------- */
.tabs { display: flex; gap: var(--s-5); border-bottom: 1px solid var(--line); }
.tab, .tab-btn {
  appearance: none; background: none; border: 0;
  padding: 0 0 10px; min-height: 44px;
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 500;
  color: var(--muted); cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab:hover, .tab-btn:hover { color: var(--ink); }
.tab.is-on, .tab[aria-selected="true"], .tab-btn[data-active="1"], .tab-btn.active {
  color: var(--ink); border-bottom-color: var(--accent);
}

/* ---- Segmented control. Used once: Now | Later. ----------- */
.seg {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 4px; padding: 4px;
  background: var(--ground-2); border-radius: var(--r-ctl);
}
.seg-btn {
  appearance: none; border: 0; background: transparent;
  min-height: 40px; padding: 0 14px;
  border-radius: 6px;
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 500;
  color: var(--muted); cursor: pointer;
  transition: background var(--t-state) var(--ease), color var(--t-state) var(--ease);
}
.seg-btn:hover { color: var(--ink); }
.seg-btn[data-active="1"], .seg-btn.is-on, .seg-btn[aria-pressed="true"] {
  background: var(--surface); color: var(--ink); box-shadow: var(--shadow-lift);
}

/* ---- Empty states ----------------------------------------- */
.empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-4);
  text-align: center;
  background: var(--surface-2);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-card);
  padding: var(--s-7);
}
.empty h3, .empty .card-title { font-size: var(--t-display-3); }
.empty p { font-size: var(--t-sm); color: var(--muted); max-width: 44ch; }

/* ---- FAQ — <details>, hairline-separated, no boxes. ------- */
.faq details, details.faq-item {
  border-bottom: 1px solid var(--line);
  padding: var(--s-4) 0;
}
.faq summary, details.faq-item > summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
  cursor: pointer; list-style: none;
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 600; font-size: var(--t-display-3);
  line-height: 1.15; letter-spacing: -.016em; color: var(--ink);
  min-height: 44px;
}
.faq summary::-webkit-details-marker, details.faq-item > summary::-webkit-details-marker { display: none; }
.faq summary::after, details.faq-item > summary::after {
  content: "+"; flex: none;
  font-family: var(--f-num); font-size: var(--t-num); font-weight: 500;
  color: var(--accent);
}
.faq details[open] > summary::after, details.faq-item[open] > summary::after { content: "\2212"; }
.faq details > *:not(summary), details.faq-item > *:not(summary) {
  margin-top: var(--s-3);
  font-size: var(--t-body); line-height: 1.6; color: var(--ink-soft);
  max-width: var(--measure-body);
}

/* ---- Charts. Hand-rolled SVG only. ------------------------ */
.chart-wrap { overflow-x: auto; }
.chart-grid line { stroke: var(--subtle); stroke-dasharray: 2 4; stroke-width: 1; }
.chart-series { fill: none; stroke: var(--rate-series); stroke-width: 2; }
.chart-band { fill: var(--rate-band); stroke: none; }
.chart-ghost { fill: none; stroke: var(--rate-ghost); stroke-width: 1; stroke-dasharray: 3 3; }
.chart-axis {
  font-family: var(--f-num); font-size: var(--t-label);
  letter-spacing: .14em; text-transform: uppercase; fill: var(--muted);
}
.bar { height: 8px; border-radius: var(--r-round); background: var(--ground-3); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--live); border-radius: var(--r-round); }
.bar.warn > i { background: var(--warning-fill); }
.bar.danger > i { background: var(--danger); }

/* ---- Hero. The argument on the left, the live widget on the
        right. 7/5, never 6/6. -------------------------------- */
.hero { padding: clamp(2.5rem, 6vw, 5rem) 0 var(--section-pad); }
.hero-copy { display: flex; flex-direction: column; gap: var(--s-5); align-items: flex-start; }
.hero-copy .ctas, .ctas { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }

/* The proof strip — four label cells split by hairline verticals.
   Replaces the old .hero-meta and its ✕ separators. */
.proof-strip {
  display: flex; flex-wrap: wrap; align-items: center;
  margin: 0; padding: 0; list-style: none;
}
.proof-strip > * {
  font-family: var(--f-num); font-size: var(--t-label); line-height: 1.6;
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
  padding: 0 var(--s-4); border-left: 1px solid var(--line);
}
.proof-strip > *:first-child { padding-left: 0; border-left: 0; }
.band .proof-strip > *, .invert .proof-strip > * {
  color: var(--night-muted); border-left-color: var(--night-line);
}

/* ---- Timeline strip — the scheduling spearhead rendered as a
        picture: dated .person rows, each with a .runbar. ------ */
.timeline { display: flex; flex-direction: column; gap: var(--s-2); }
.timeline > .card { padding: var(--s-3) 0 0; gap: var(--s-2); }
.timeline-end {
  border-top: 1px dashed var(--line);
  padding-top: var(--s-3);
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
  font-family: var(--f-num); font-size: var(--t-label);
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
}
.timeline-end .num, .timeline-end b { color: var(--ink); font-weight: 600; }
.band .timeline-end, .invert .timeline-end {
  border-top-color: var(--night-line); color: var(--night-muted);
}
.band .timeline-end .num, .invert .timeline-end .num,
.band .timeline-end b, .invert .timeline-end b { color: var(--night-text); }

/* ---- Disclosure — the quiet "Also for teams and researchers"
        block. A <details>, never a dismissible banner. -------- */
details.disclosure {
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: var(--s-4) 0;
}
details.disclosure > summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
  cursor: pointer; list-style: none; min-height: 44px;
  font-family: var(--f-body); font-size: var(--t-ui); font-weight: 600; color: var(--ink);
}
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary::after {
  content: "+"; flex: none;
  font-family: var(--f-num); font-size: var(--t-num); font-weight: 500; color: var(--accent);
}
details.disclosure[open] > summary::after { content: "\2212"; }
details.disclosure > summary .sub { color: var(--muted); font-weight: 400; }
.disclosure-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-4); flex-wrap: wrap;
  border-top: 1px solid var(--line); padding: var(--s-4) 0 0; margin-top: var(--s-4);
}
.disclosure-row p { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; }

/* ---- Rate Watch: the nudge. Never blocks the purchase, never
        a modal. One sentence, one line of small print. -------- */
.nudge {
  display: flex; flex-direction: column; gap: var(--s-2);
  background: var(--surface-2);
  border-left: 3px solid var(--line-strong);
  border-radius: 0 var(--r-ctl) var(--r-ctl) 0;
  padding: var(--s-3) var(--s-4);
}
.nudge p { margin: 0; font-size: var(--t-sm); line-height: 1.5; color: var(--ink-soft); max-width: none; }
.nudge b, .nudge strong { color: var(--ink); font-weight: 600; }
.nudge small, .nudge .fineprint {
  display: block; font-size: var(--t-xs); line-height: 1.45; color: var(--muted);
}
.nudge .btn { align-self: flex-start; }
.nudge.is-good     { border-left-color: var(--live); }
.nudge.is-info     { border-left-color: var(--info); }
.nudge.is-warn     { border-left-color: var(--warning-fill); }
.nudge.is-learning { border-left-color: var(--muted); }
.band .nudge, .invert .nudge { background: rgba(242,243,240,.05); }
.band .nudge p, .invert .nudge p { color: var(--night-muted); }
.band .nudge b, .invert .nudge b { color: var(--night-text); }

/* ---- Rate Watch: the staircase. The signature asset. Six
        published bands, ascending; heights are indicative and
        the caption says so. The <title>/<desc> in the SVG carry
        the same explanation in words. ------------------------- */
.staircase { display: block; width: 100%; height: auto; }
.staircase .step { fill: var(--accent); }
.staircase .step-1 { opacity: .35; }
.staircase .step-2 { opacity: .48; }
.staircase .step-3 { opacity: .61; }
.staircase .step-4 { opacity: .74; }
.staircase .step-5 { opacity: .87; }
.staircase .step-6 { opacity: 1; }
.staircase .step-label, .staircase .caption {
  font-family: var(--f-num); font-size: 11px;
  font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  fill: var(--muted);
}
.staircase .reset-arc {
  fill: none; stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 4;
}
.staircase .here-marker { fill: var(--live); }
.staircase .here-label { fill: var(--live-ink); }
.band .staircase .step, .invert .staircase .step { fill: var(--accent-bright); }
.band .staircase .step-label, .invert .staircase .step-label,
.band .staircase .caption, .invert .staircase .caption { fill: var(--night-muted); }
.band .staircase .reset-arc, .invert .staircase .reset-arc { stroke: rgba(242,243,240,.30); }
.band .staircase .here-marker, .invert .staircase .here-marker { fill: var(--live-bright); }
.band .staircase .here-label, .invert .staircase .here-label { fill: var(--live-bright); }
.staircase-note { font-size: var(--t-xs); line-height: 1.45; color: var(--muted); }
.band .staircase-note, .invert .staircase-note { color: var(--night-muted); }

/* ---- Rate Watch: band position. Six segments — done, current,
        still to come. A state, never an error. ---------------- */
.stepbar { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 3px; }
.stepbar > i {
  display: block; height: 10px; border-radius: 2px;
  background: var(--ground-3);
}
.stepbar > i.is-done { background: var(--accent); }
.stepbar > i.is-now  { background: var(--live); }
.stepbar-scale {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 3px;
  margin-top: 6px;
  font-family: var(--f-num); font-size: var(--t-label);
  font-weight: 600; letter-spacing: .14em; color: var(--muted);
}
.band .stepbar > i, .invert .stepbar > i { background: rgba(242,243,240,.16); }
.band .stepbar > i.is-done, .invert .stepbar > i.is-done { background: var(--accent-bright); }
.band .stepbar > i.is-now, .invert .stepbar > i.is-now { background: var(--live-bright); }
.band .stepbar-scale, .invert .stepbar-scale { color: var(--night-muted); }

/* ============================================================
   7. LEGACY SHIMS — DEPRECATED, sweep on contact.
   The postal metaphor is retired: these selectors survive only
   so pages mid-migration keep their layout. Each renders as a
   plain object with no metaphor left in it. Do not use them in
   new markup — use .eyebrow, .tag, .card, .figure.
   ============================================================ */
.almanac {                                   /* DEPRECATED — use .eyebrow */
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-num); font-size: var(--t-label); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.almanac .num { color: var(--accent); font-weight: 600; }
.almanac .dash { width: 3px; height: 14px; border-radius: 1px; background: var(--accent); display: inline-block; }
.band .almanac, .invert .almanac { color: var(--night-muted); }
.band .almanac .num, .invert .almanac .num { color: var(--accent-bright); }
.band .almanac .dash, .invert .almanac .dash { background: var(--accent-bright); }

.stamped {                                   /* DEPRECATED — use .tag */
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border: 0; border-radius: var(--r-round);
  font-family: var(--f-num); font-size: var(--t-label); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; line-height: 1; white-space: nowrap;
  background: var(--info-soft); color: var(--ink-2);
  transform: none;                            /* the tilt is gone */
}
.stamped.ok   { background: var(--success-soft); color: var(--success); }
.stamped.dark { background: var(--ground-2); color: var(--ink-2); }
.band .stamped, .invert .stamped { background: rgba(242,243,240,.09); color: var(--night-text); }

.postmark, .moon-mark {                      /* DEPRECATED — use the real mark */
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--r-round);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  flex-shrink: 0; transform: none;            /* no tilt, no dashed ring */
}
.postmark svg, .moon-mark svg { width: 20px; height: 20px; color: var(--ink-2); }
.band .postmark, .invert .postmark, .band .moon-mark, .invert .moon-mark {
  background: transparent; border-color: var(--night-3);
}
.band .postmark svg, .invert .postmark svg,
.band .moon-mark svg, .invert .moon-mark svg { color: var(--night-text); }

.perf-edge {                                 /* DEPRECATED — use hr */
  height: 1px; border: 0; border-top: 1px solid var(--line); background: none;
}
.perf-edge::before { content: none; }

.route {                                     /* DEPRECATED — use .person */
  display: grid; grid-template-columns: auto 1fr auto 1fr;
  gap: var(--s-4); align-items: center;
  padding: var(--s-3) 0; border-top: 1px solid var(--line);
}
.route .lbl {
  font-family: var(--f-num); font-size: var(--t-label); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.route .name {
  font-family: var(--f-display); font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 500; font-size: var(--t-name); letter-spacing: -.008em;
}
.route .arrow { color: var(--accent); font-style: normal; }

.feat-num, .step-num {                       /* DEPRECATED — no numbering, anywhere */
  display: block;
  font-family: var(--f-num); font-size: var(--t-label); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); margin-bottom: var(--s-2);
}
.feat-icon {
  width: 40px; height: 40px; flex-shrink: 0;
  border: 1px solid var(--line); border-radius: var(--r-round);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2);
}
.feat-icon svg { width: 20px; height: 20px; color: var(--ink-2); }
h3.feat-title, .feat-title, h3.step-title, .step-title {
  font-family: var(--f-display);
  font-variation-settings: 'opsz' 24, 'SOFT' 20, 'WONK' 0;
  font-weight: 600; font-size: var(--t-display-3);
  line-height: 1.15; letter-spacing: -.016em;
  margin: 0; color: var(--ink);
}
.band .feat-title, .invert .feat-title, .band .step-title, .invert .step-title { color: var(--night-text); }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(var(--s-5), 3vw, var(--s-7)); }
@media (max-width: 880px) { .steps { grid-template-columns: 1fr; gap: var(--s-6); } }
.step p { color: var(--ink-soft); font-size: var(--t-sm); margin: 0; max-width: 42ch; }

.italic-brass, .italic-stamp {               /* DEPRECATED — the italic tic is retired */
  font-style: normal; font-weight: inherit; color: var(--accent);
}
.band .italic-stamp, .invert .italic-stamp,
.band .italic-brass, .invert .italic-brass { color: var(--accent-bright); }

.tg, .tg-display {                           /* DEPRECATED — use .mono / .t-label */
  font-family: var(--f-num); letter-spacing: 0; font-variant-numeric: tabular-nums;
}
.btn.brass, .btn.stamp {                     /* DEPRECATED — use .btn.primary */
  background: var(--accent); color: var(--on-accent);
}
.btn.brass:hover, .btn.stamp:hover { background: var(--accent-hover); }
.card.stamp-card, .feat.stamp-card {         /* DEPRECATED — the scalloped edge is gone */
  background: var(--surface);
  border: 1px solid var(--line);
}

/* ============================================================
   8. ACCESSIBILITY · MOTION · SMALL-PHONE HYGIENE
   ============================================================ */

/* Rows enter once — 6px up and a fade, staggered 40ms. Never loops.
   Countdowns never animate; the run bar fills once on first view. */
@keyframes row-enter { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: no-preference) {
  .enter { animation: row-enter var(--t-enter) var(--ease) both; }
  .enter:nth-child(2) { animation-delay:  40ms; }
  .enter:nth-child(3) { animation-delay:  80ms; }
  .enter:nth-child(4) { animation-delay: 120ms; }
  .enter:nth-child(5) { animation-delay: 160ms; }
  .enter:nth-child(6) { animation-delay: 200ms; }
  .enter:nth-child(7) { animation-delay: 240ms; }
  .enter:nth-child(8) { animation-delay: 280ms; }
}

/* Every interactive element clears 44×44 on every surface. */
a[role="button"], button, .btn, .pill, .seg-btn, .tab, .tab-btn,
.nav-links a, .btn-link { touch-action: manipulation; }

/* Small-phone polish (≤560px): tap-target floor, long-title wrapping,
   CTA stacking, and tables restructuring instead of scrolling. */
@media (max-width: 560px) {
  h1, h2, h3, .section-title, .hero-title, .band-title, .card-title {
    overflow-wrap: anywhere; word-break: break-word;
  }
  .ctas, .cta-row, .btn-row {
    width: 100%; display: flex; flex-direction: column; gap: 10px;
  }
  .ctas > .btn, .cta-row > .btn, .btn-row > .btn { width: 100%; justify-content: center; }
  .band, .closer, .signal-strip {
    padding-left: max(1rem, env(safe-area-inset-left));
    padding-right: max(1rem, env(safe-area-inset-right));
  }
  .person { --av: 44px; padding: 0 var(--s-4); gap: var(--s-3); }
  .runbar, .runbar-label { margin-left: var(--s-4); margin-right: var(--s-4); padding-left: 0; padding-right: 0; }
  .figure-grid > .figure { border-left: 0; border-top: 1px solid var(--line); padding-left: 0; }
  .figure-grid > .figure:first-child { border-top: 0; }
  .proof-strip > * { padding: 2px 0; border-left: 0; width: 100%; }
  .staircase .step-label { font-size: 9px; letter-spacing: .08em; }
  .stepbar-scale { font-size: 9px; letter-spacing: .06em; }
}

/* Tables restructure below 700px. Charts and code scroll; data tables do not. */
@media (max-width: 700px) {
  .table.is-stackable thead { position: absolute; width: 1px; height: 1px;
                              overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .table.is-stackable tr { display: block; border-bottom: 1px solid var(--line); padding: var(--s-3) 0; }
  .table.is-stackable td { display: flex; justify-content: space-between; gap: var(--s-4);
                           border: 0; padding: 3px 0; }
  .table.is-stackable td::before {
    content: attr(data-label);
    font-family: var(--f-num); font-size: var(--t-label); font-weight: 600;
    letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
  }
}

/* Motion. Everything expressive lives inside no-preference. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .runbar > i, .runbar-fill { transition: none; }        /* renders at its final fill */
  .tag.is-live::before, .signal-strip .dot { animation: none; opacity: 1; }
  .signal-strip .marquee { animation: none; transform: none; }
  .btn:hover .arrow, .btn-link:hover .arrow, .feat-link:hover .arrow { transform: none; }
  .person.is-link:hover .person-av, a.person:hover .person-av { transform: none; }
  .enter { animation: none !important; opacity: 1; transform: none; }
}

/* Print — the paper ground is already paper. */
@media print {
  .signal-strip, header.site, footer.site { display: none; }
  .band, .invert { background: var(--surface); color: var(--ink); }
}

/* ============================================================
   9. THE CURRENT LINE — background circuit
   ------------------------------------------------------------
   Water to turbine to grid to the cities, drawn once across the
   page and animated very quietly. Markup: templates/_currentline.html.

   Rules it must never break:
     - it is decoration, so aria-hidden and pointer-events: none
     - it never sits above content (z-index 0; content is z-index 1)
     - it never causes layout or a scrollbar
     - every animation stops under prefers-reduced-motion
   ============================================================ */
.currentline {
  position: fixed;
  inset: auto 0 0 0;
  height: min(62vh, 620px);
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  opacity: .075;
  contain: strict;
}
.currentline svg { width: 100%; height: 100%; display: block; }

/* Content rides above it. Sections that paint their own background (the
   night bands) hide it completely, which is what makes it come and go. */
body > header.site, body > main, body > footer, body > .signal-strip { position: relative; z-index: 1; }

.currentline path, .currentline circle, .currentline rect {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.currentline .cl-thin path, .currentline path.cl-thin,
.currentline .cl-thin circle { stroke-width: 1; }
.currentline .cl-ground { stroke-width: 1.2; }
.currentline .cl-water path { stroke-width: 1; opacity: .55; }

/* Reservoir drift — the surface moves, barely. */
.currentline .cl-drift   { animation: cl-drift 19s ease-in-out infinite; }
.currentline .cl-drift-2 { animation-duration: 26s; animation-direction: reverse; }
@keyframes cl-drift { 0%,100% { transform: translateX(0); } 50% { transform: translateX(14px); } }

/* Spillway — water falling down the face. */
.currentline .cl-spill path {
  stroke-dasharray: 5 13;
  animation: cl-fall 2.6s linear infinite;
  opacity: .5;
}
.currentline .cl-spill path:nth-child(2) { animation-duration: 3.3s; }
.currentline .cl-spill path:nth-child(3) { animation-duration: 2.1s; }
@keyframes cl-fall { to { stroke-dashoffset: -36; } }

/* The turbine turns. Slowly — this is 50Hz seen from very far away. */
.currentline .cl-turbine {
  transform-box: fill-box;
  transform-origin: center;
  animation: cl-spin 11s linear infinite;
}
@keyframes cl-spin { to { transform: rotate(360deg); } }

/* Windows come on and go off, each on its own clock. */
.currentline .cl-lit rect {
  fill: var(--ink);
  stroke: none;
  opacity: 0;
  animation: cl-lit 9s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
@keyframes cl-lit {
  0%, 44%  { opacity: 0; }
  52%, 84% { opacity: .5; }
  100%     { opacity: 0; }
}

/* The current. A short dash travelling the whole route, in the accent so it
   reads as energy rather than as another line. */
.currentline .cl-pulse path {
  stroke: var(--accent);
  stroke-width: 2.4;
  stroke-dasharray: 26 1600;
  animation: cl-run 21s linear infinite;
  animation-delay: var(--d, 0s);
}
@keyframes cl-run { from { stroke-dashoffset: 1626; } to { stroke-dashoffset: 0; } }

/* Phones: the scene is mostly off-canvas and the paint is not worth it. */
@media (max-width: 720px) {
  .currentline { height: 40vh; opacity: .055; }
  .currentline .cl-water, .currentline .cl-lit { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .currentline .cl-drift,
  .currentline .cl-spill path,
  .currentline .cl-turbine,
  .currentline .cl-lit rect,
  .currentline .cl-pulse path { animation: none; }
  .currentline .cl-lit rect { opacity: .38; }
  .currentline .cl-pulse path { stroke-dasharray: none; opacity: .22; }
}

/* ============================================================
   10. AMBIENT — one quiet, live backdrop per page
   ------------------------------------------------------------
   The sibling of §9's current line, generalised: each page gets
   a scene about that page (templates/_ambient.html), so the site
   reads as one place with different rooms. Same rules as §9 and
   as the app's lib/common/ambient/ — fixed, aria-hidden, no
   pointer events, no layout cost, and every animation stops
   under prefers-reduced-motion while the drawing stays.
   ============================================================ */
.ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  opacity: .07;
  contain: strict;
}
.ambient svg { width: 100%; height: 100%; display: block; }

.ambient path, .ambient circle, .ambient rect {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.ambient .am-hot { fill: var(--accent); stroke: none; }
.ambient .am-dot { fill: var(--ink); stroke: none; }

/* --- orbits: MyFamilyTime ---------------------------------- */
.ambient .am-orbit { transform-origin: 600px 300px; }
.ambient .am-orbit-1 { animation: am-spin 54s linear infinite; }
.ambient .am-orbit-2 { animation: am-spin 84s linear infinite reverse; }
.ambient .am-orbit-3 { animation: am-spin 128s linear infinite; }
@keyframes am-spin { to { transform: rotate(360deg); } }

/* --- bands: Rate Watch. The climb runs the staircase, one band
       at a time, then the month resets and it starts again. ---- */
.ambient .am-climb rect { fill: var(--accent); stroke: none; opacity: 0; }
.ambient .am-climb rect:nth-child(1) { animation: am-step 36s linear infinite 0s; }
.ambient .am-climb rect:nth-child(2) { animation: am-step 36s linear infinite 3s; }
.ambient .am-climb rect:nth-child(3) { animation: am-step 36s linear infinite 6s; }
.ambient .am-climb rect:nth-child(4) { animation: am-step 36s linear infinite 9s; }
.ambient .am-climb rect:nth-child(5) { animation: am-step 36s linear infinite 12s; }
.ambient .am-climb rect:nth-child(6) { animation: am-step 36s linear infinite 15s; }
@keyframes am-step {
  0%, 2%   { opacity: 0; }
  8%, 50%  { opacity: 1; }
  62%, 100%{ opacity: 0; }
}

/* --- signal: for developers -------------------------------- */
.ambient .am-arc path { stroke: var(--ink); opacity: 0; }
.ambient .am-arc path:nth-child(1) { animation: am-out 9s ease-out infinite 0s; }
.ambient .am-arc path:nth-child(2) { animation: am-out 9s ease-out infinite 1.1s; }
.ambient .am-arc path:nth-child(3) { animation: am-out 9s ease-out infinite 2.2s; }
@keyframes am-out { 0% { opacity: 0; } 12% { opacity: 1; } 100% { opacity: 0; } }
.ambient .am-wire { stroke-dasharray: 24 1400; animation: am-run 14s linear infinite; stroke: var(--accent); }
@keyframes am-run { from { stroke-dashoffset: 1424; } to { stroke-dashoffset: 0; } }

/* --- tide: long-form pages --------------------------------- */
.ambient .am-tide { animation: am-drift 34s ease-in-out infinite; }
.ambient .am-tide-2 { animation-duration: 46s; animation-direction: reverse; }
.ambient .am-tide-3 { animation-duration: 58s; }
@keyframes am-drift { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-300px); } }

/* --- settle: error pages ----------------------------------- */
.ambient .am-settle circle { opacity: 0; transform-origin: 600px 300px; }
.ambient .am-settle circle:nth-child(1) { animation: am-ripple 13s ease-out infinite 0s; }
.ambient .am-settle circle:nth-child(2) { animation: am-ripple 13s ease-out infinite 4.3s; }
.ambient .am-settle circle:nth-child(3) { animation: am-ripple 13s ease-out infinite 8.6s; }
@keyframes am-ripple {
  0%   { opacity: 0; transform: scale(.2); }
  10%  { opacity: 1; }
  100% { opacity: 0; transform: scale(4.2); }
}

@media (max-width: 720px) { .ambient { opacity: .05; } }

@media (prefers-reduced-motion: reduce) {
  .ambient * { animation: none !important; }
  /* Anything that only exists mid-animation is shown at rest instead of
     never being seen at all. */
  .ambient .am-climb rect,
  .ambient .am-arc path,
  .ambient .am-settle circle { opacity: .5; }
}

/* ---- ZESA status tile ------------------------------------------------ */
.zesa-tile {
  margin: var(--s-2) 0 0; padding: 9px 12px;
  border: 1px solid var(--line); border-radius: 9px; background: var(--surface);
}
.zesa-tile-row { display: flex; align-items: center; gap: 8px; }
.zesa-dot { width: 7px; height: 7px; border-radius: 999px; flex: none; background: var(--live); }
.zesa-tile-name, .zesa-tile-state {
  font-family: var(--f-num); font-size: 11px; font-weight: 500; letter-spacing: .14em;
}
.zesa-tile-name { color: var(--ink); }
.zesa-tile-state { color: var(--muted); }
.zesa-tile-times {
  margin-left: auto; font-family: var(--f-num); font-variant-numeric: tabular-nums;
  font-size: 12px; color: var(--muted); white-space: nowrap;
}
.zesa-tile .zesa-tile-note { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--warning); max-width: none; }
.zesa-tile.is-down { background: var(--warning-soft); border-color: color-mix(in srgb, var(--warning-fill) 45%, transparent); }
.zesa-tile.is-down .zesa-dot { background: var(--warning-fill); }
.zesa-tile.is-down .zesa-tile-state, .zesa-tile.is-down .zesa-tile-times { color: var(--warning); }
