/*
 * site/styles.css — the whole visual layer, and the whole token layer.
 *
 * WHAT
 *   Mobile-first CSS with every colour, space, radius and type size declared once as a
 *   custom property in :root. Nothing below :root holds a raw value that a designer would
 *   want to change.
 *
 * WHY IT IS BUILT THIS WAY
 *   Daniel art-directs the visual pass himself, after this works. That pass should be a
 *   rewrite of :root and nothing else — so the rules below are deliberately plain, use no
 *   framework, no build step, and no clever selector that would have to be understood
 *   before a colour could be changed. If a restyle needs a find-and-replace, this file
 *   failed at its job.
 *
 * THE PALETTE HAS NO ALARM STATE, ON PURPOSE (spec §4.15.4)
 *   There is no --danger, no --overdue, no .is-late. Not "unused" — absent. A red token
 *   sitting in this file is a red badge waiting for the first session where somebody
 *   thinks a missed hard date should stand out. It should not. A date that has passed says
 *   so in words, in the same type as every other line. The strongest emphasis available
 *   anywhere here is --ink-strong on --surface-raised, and that is spent on caveats — the
 *   thing that makes a date less certain than it looks — rather than on lateness.
 *   For the same reason there is no progress bar, meter, or counter rule in this file.
 *
 * PROVENANCE  Family dashboard v1, 2026-08-10.
 */

:root {
  /* type */
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --size-xs: 0.78rem;
  --size-sm: 0.88rem;
  --size-md: 1rem;
  --size-lg: 1.2rem;
  --size-xl: 1.5rem;
  --leading: 1.55;
  --weight-normal: 400;
  --weight-strong: 600;

  /* ink — warm near-blacks (overnight revamp 2026-08-17, from the Replit study §1:
     warm-tinted neutrals hue 30-45 instead of cold gray; every pair below is
     mechanically AA-checked by TestPaletteContrast, both themes) */
  --ink: #23221b;
  --ink-strong: #12110b;
  --ink-quiet: #6a675f;
  --ink-invert: #ffffff;

  /* ground — warm paper */
  --surface: #f9f7f2;
  --surface-raised: #ffffff;
  --surface-sunken: #efece4;
  --line: #e5e2d8;
  --line-strong: #cdc9bb;

  /* accent — one, and it is calm (eucalyptus: on-mascot, and it makes the whole
     app feel like one designed object) */
  --accent: #2a794a;
  --accent-ink: #ffffff;
  --accent-quiet: #e7f1e9;

  /* geometry — radius softened in the same pass (10/6 → 16/10, the Replit
     friendliness without going toy) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2.25rem;
  --radius: 16px;
  --radius-sm: 10px;
  --measure: 38rem;
  --border: 1px solid var(--line);
}

/* THE THEME CONTRACT (overnight revamp): default is system-following; a manual
   choice stamps data-theme="light"|"dark" on <html> (site/app.js, localStorage).
   The dark token set therefore appears TWICE below, verbatim — once under the
   media query guarded so an explicit light choice beats a dark OS, once under the
   explicit dark stamp. TestThemeContract pins the two blocks token-for-token, so
   they cannot drift apart. Edit BOTH or the test fails. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #e9e6db;
    --ink-strong: #f4f2e7;
    --ink-quiet: #a09d92;
    --ink-invert: #131211;
    --surface: #131211;
    --surface-raised: #1e1c1a;
    --surface-sunken: #0d0c0b;
    --line: #2b2a26;
    --line-strong: #403e37;
    --accent: #4baf73;
    --accent-ink: #12241a;
    --accent-quiet: #1d2f24;
  }
}

:root[data-theme="dark"] {
  --ink: #e9e6db;
  --ink-strong: #f4f2e7;
  --ink-quiet: #a09d92;
  --ink-invert: #131211;
  --surface: #131211;
  --surface-raised: #1e1c1a;
  --surface-sunken: #0d0c0b;
  --line: #2b2a26;
  --line-strong: #403e37;
  --accent: #4baf73;
  --accent-ink: #12241a;
  --accent-quiet: #1d2f24;
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--size-md);
  line-height: var(--leading);
  color: var(--ink);
  background: var(--surface);
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-4) var(--space-4) var(--space-6);
}

h1 {
  font-size: var(--size-xl);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: 0 0 var(--space-3);
}

h2 {
  font-size: var(--size-md);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: 0 0 var(--space-2);
}

p { margin: 0 0 var(--space-3); }

a { color: var(--accent); }

.quiet {
  color: var(--ink-quiet);
  font-size: var(--size-sm);
}

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: var(--space-3);
  top: var(--space-3);
  background: var(--surface-raised);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
}

/* chrome ------------------------------------------------------------------------------ */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-raised);
  border-bottom: var(--border);
}

.wordmark {
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  letter-spacing: 0.01em;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

button {
  font: inherit;
  font-size: var(--size-sm);
  color: var(--ink);
  background: var(--surface-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  min-height: 2.5rem;
}

button:disabled {
  opacity: 0.5;
  cursor: default;
}

button.primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: var(--weight-strong);
}

button.linkish {
  background: none;
  border: none;
  color: var(--accent);
  padding: 0;
  min-height: 0;
  text-decoration: underline;
}

.uid {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--size-sm);
  word-break: break-all;
  background: var(--surface-sunken);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
}

/* controls ---------------------------------------------------------------------------- */

.controls {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin: 0 0 var(--space-5);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.chip {
  display: inline-block;
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: var(--space-1) var(--space-3);
}

.chip-toggle {
  min-height: 2.25rem;
  cursor: pointer;
}

.chip-toggle[aria-pressed="true"] {
  background: var(--accent-quiet);
  border-color: var(--accent);
  color: var(--ink-strong);
  font-weight: var(--weight-strong);
}

/* sections ---------------------------------------------------------------------------- */

.group { margin: 0 0 var(--space-5); }

.group > details > summary {
  font-size: var(--size-lg);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  cursor: pointer;
  padding: var(--space-2) 0;
}

.items {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.later {
  border-top: var(--border);
  padding-top: var(--space-3);
}

/* item card --------------------------------------------------------------------------- */

.item {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-4);
}

.item.is-done {
  background: var(--surface-sunken);
}

.item-head { margin-bottom: var(--space-2); }

.check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  cursor: pointer;
}

.check input {
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.2rem;
  flex: none;
  accent-color: var(--accent);
}

.item-title {
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
}

.chips-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.condition {
  font-size: var(--size-sm);
  color: var(--ink-strong);
  background: var(--accent-quiet);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
}

.due { margin-bottom: var(--space-2); }

.lead-why { margin-bottom: var(--space-3); }

/* Caveats get the only raised treatment in the file. They are the honesty layer — the
   thing that stops a date looking firmer than it is — and nothing else competes with them. */
.caveats {
  border-left: 3px solid var(--line-strong);
  background: var(--surface-sunken);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: var(--space-3);
  margin: 0 0 var(--space-3);
}

.caveats p {
  font-size: var(--size-sm);
  color: var(--ink-strong);
  margin: 0 0 var(--space-2);
}

.caveats p:last-child { margin-bottom: 0; }

.what-to-do { margin-bottom: var(--space-3); }

.whence {
  font-size: var(--size-sm);
  color: var(--ink-quiet);
  margin-bottom: var(--space-3);
}

.whence summary {
  cursor: pointer;
  color: var(--accent);
}

.whence-body { padding-top: var(--space-2); }

.whence-body q { display: block; }

.whence-body cite {
  font-style: normal;
  font-size: var(--size-xs);
  word-break: break-all;
}

.links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--size-sm);
}

.calendar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  border-top: var(--border);
  padding-top: var(--space-3);
}

.calendar-row .cal-note {
  flex-basis: 100%;
  color: var(--ink-quiet);
  font-size: var(--size-xs);
}

.email-row {
  border-top: var(--border);
  padding-top: var(--space-3);
  margin-bottom: var(--space-3);
}

.done-line { margin: var(--space-3) 0 0; }

.item-answered {
  background: var(--surface-sunken);
  border-style: dashed;
}

.item-answered .item-title { margin-bottom: var(--space-2); }

/* email preview ------------------------------------------------------------------------
   The screen where a family reads a message before they send it themselves (§4.14). Two
   things earn emphasis here and nothing else does: the blank that has to be filled before
   anything can be sent, and the two send controls. The blank uses the accent — the same
   calm green the condition line uses — because it is a NEXT STEP, not a mistake. There is
   still no alarm token in this file and there is still nothing to reach for. */

.email-blanks {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--accent-quiet);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin-bottom: var(--space-2);
}

.email-blank {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--size-sm);
  color: var(--ink-strong);
  font-weight: var(--weight-strong);
}

.email-blank input {
  font: inherit;
  font-weight: var(--weight-normal);
  color: var(--ink);
  background: var(--surface-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  min-height: 2.5rem;
}

.email-head {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-3);
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
  font-size: var(--size-sm);
}

.email-head dt {
  color: var(--ink-quiet);
}

.email-head dd {
  margin: 0;
  color: var(--ink-strong);
  word-break: break-word;
}

.email-body-label {
  display: block;
  font-size: var(--size-sm);
  color: var(--ink-quiet);
  margin-bottom: var(--space-2);
}

/* A textarea, because "review before you send" has to be something you can act on. */
.email-body {
  width: 100%;
  font: inherit;
  font-size: var(--size-sm);
  line-height: var(--leading);
  color: var(--ink);
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3);
  resize: vertical;
}

.email-actions,
.email-sent-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-3) 0;
}

.email-sent-row {
  border-top: var(--border);
  padding-top: var(--space-4);
  margin-top: var(--space-5);
}

/* An anchor, not a button: mailto: from a real link is the path mobile mail apps handle
   most reliably. It has to LOOK like the primary control it is. */
.btn {
  display: inline-block;
  font-size: var(--size-sm);
  text-decoration: none;
  text-align: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  min-height: 2.5rem;
  line-height: 2;
  cursor: pointer;
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: var(--weight-strong);
}

/* Withheld, not broken. Matches button:disabled exactly, because the two mean the same
   thing to a person and should not look like two different states. */
.btn.is-off {
  opacity: 0.5;
  cursor: default;
}

/* footer ------------------------------------------------------------------------------ */

.fineprint {
  border-top: var(--border);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

/* wider screens ------------------------------------------------------------------------ */

@media (min-width: 40rem) {
  main { padding: var(--space-5) var(--space-5) var(--space-6); }
  h1 { font-size: 1.75rem; }
}

/* explore — the public tab (addendum v1.1) -------------------------------------------- */
/* Same tokens, same calm. The feed is finite and vertical on a phone; on wider screens
   the cards flow into columns as an enhancement (mobile-first ruling, 8/10). No badge,
   meter or counter appears here for the same §4.15.4 reasons as the dashboard. */

/* The bottom tab bar (Daniel, 8/16): fixed to the bottom edge, phone-app grammar —
   four equal-width targets, icon over a short label. safe-area padding keeps the bar
   clear of the iPhone home indicator (viewport-fit=cover in the meta makes the env()
   real); main's bottom padding below keeps the last card tappable above the bar. */
.tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: flex;
  /* Solid fallback first; translucent + blur where supported (Replit study §2 —
     the iOS frosted-bar feel). color-mix keeps the tint on the theme token. */
  background: var(--surface-raised);
  background: color-mix(in srgb, var(--surface-raised) 82%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-top: var(--border);
  padding: var(--space-1) var(--space-2)
    calc(var(--space-1) + env(safe-area-inset-bottom, 0px));
}

.tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.125rem;
  border: none;
  background: none;
  font: inherit;
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  padding: var(--space-1) var(--space-1);
  border-radius: var(--radius-sm);
  cursor: pointer;
  min-height: 3rem;
}

.tab-icon {
  font-size: 1.3rem;
  line-height: 1;
}

.tab-label {
  line-height: 1.2;
}

.tab[aria-current="page"] {
  color: var(--ink-strong);
  font-weight: var(--weight-strong);
  background: var(--surface-sunken);
}

main {
  padding-bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px));
}

.card-list {
  display: grid;
  gap: var(--space-4);
  margin: var(--space-4) 0;
}

.card {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-4);
  cursor: pointer;
}

.card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.day-thumb {
  width: 100%;
  max-width: 100%;
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-3);
  display: block;
}

.day-headline {
  font-size: var(--size-lg);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: 0 0 var(--space-2);
}

.day-what {
  margin: var(--space-2) 0;
}

.program-age {
  font-size: var(--size-sm);
  margin: var(--space-2) 0;
}

.card-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin: var(--space-3) 0 0;
}

.fav-toggle {
  font-size: var(--size-sm);
}

.fav-toggle[aria-pressed="true"] {
  background: var(--accent-quiet);
  border-color: var(--accent);
}

.programs-heading {
  margin-top: var(--space-6);
}

.radius-block {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-3) 0;
}

.radius-block label {
  display: block;
  font-weight: var(--weight-strong);
  margin-bottom: var(--space-2);
}

.radius-block input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}

.radius-value {
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

.detail-label {
  font-size: var(--size-sm);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: var(--space-4) 0 var(--space-1);
}

.detail-section {
  font-size: var(--size-lg);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: var(--border);
}

/* the wage ladder: local rung, then national, then where it pays most */
.wage-rung {
  margin: 0 0 var(--space-2);
}

.wage-rung strong {
  color: var(--ink-strong);
}

.watch-link {
  display: block;
  margin: var(--space-3) 0;
}

.sources-line {
  margin-top: var(--space-4);
}

@media (min-width: 40rem) {
  .card-list {
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  }
}

/* layered browse (addendum §11 ruling 6) --------------------------------------------- */

.chip-group-label {
  font-size: var(--size-xs);
  font-weight: var(--weight-strong);
  color: var(--ink-quiet);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: var(--space-4) 0 var(--space-1);
}

.shelf {
  margin: var(--space-5) 0;
}

.shelf-head {
  font-size: var(--size-md);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: 0 0 var(--space-2);
  padding-bottom: var(--space-1);
  border-bottom: var(--border);
}

/* the expanded field's careers sit visibly inside it */
.chips-secondary {
  margin-left: var(--space-4);
  padding-left: var(--space-3);
  border-left: 2px solid var(--line);
}

/* the digestible layer: blurbs, ledes, card-face pay */
.shelf-blurb { margin: 0 0 var(--space-3); }

.detail-lede {
  font-size: var(--size-lg);
  color: var(--ink-strong);
  margin-bottom: var(--space-3);
}

.card-pay {
  font-size: var(--size-sm);
  color: var(--ink-quiet);
  margin: var(--space-1) 0 var(--space-2);
}

/* the browse tree ---------------------------------------------------------------------- */

.tree-bar {
  display: flex;
  justify-content: flex-end;
}

.tree-collapse {
  border: none;
  background: none;
  font: inherit;
  color: var(--ink-quiet);
  padding: var(--space-1) var(--space-2);
  cursor: pointer;
}

.tree-row {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: var(--size-md);
  color: var(--ink-strong);
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-2) 0 0;
  cursor: pointer;
}

.tree-row[aria-expanded="true"] {
  border-color: var(--accent);
  font-weight: var(--weight-strong);
}

.tree-depth-1 { margin-left: var(--space-4); width: calc(100% - var(--space-4)); }
.tree-depth-2 { margin-left: var(--space-6); width: calc(100% - var(--space-6)); font-size: var(--size-sm); }
.tree-depth-3 {
  margin-left: calc(var(--space-6) + var(--space-3));
  width: calc(100% - var(--space-6) - var(--space-3));
  font-size: var(--size-sm);
}

/* the selected role's dossier panel: the description IS the destination; the videos
   ride underneath it */
.role-panel {
  border: var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  padding: var(--space-4);
  margin: var(--space-3) 0;
}

.tree-blurb {
  margin: var(--space-2) 0 var(--space-1);
  padding-left: var(--space-4);
}

/* video-first day carousels ----------------------------------------------------------- */

.card-row {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: var(--space-2);
  -webkit-overflow-scrolling: touch;
}

.card-row .card {
  flex: 0 0 16rem;
  min-width: 16rem;
  scroll-snap-align: start;
}

.day-thumb-wrap {
  position: relative;
  margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) var(--space-3);
}

.day-thumb-wrap .day-thumb {
  border-radius: var(--radius) var(--radius) 0 0;
  margin: 0;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  width: 100%;
}

.thumb-tag {
  position: absolute;
  bottom: var(--space-2);
  left: var(--space-2);
  font-size: var(--size-xs);
  background: var(--surface-raised);
  color: var(--ink-quiet);
  border: var(--border);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-2);
}

/* money tab */
.money-body {
  padding: var(--space-3) var(--space-4);
}
.money-body p { margin-bottom: var(--space-3); }

/* The retirement ledger (§11 ruling 7m). Phone-first: the two paths stack; on a wide
   screen they sit side by side so the claim-vs-balance contrast reads at a glance. */
#ledger-block { margin-top: var(--space-6); }
#ledger-heading { margin-bottom: var(--space-2); }
#ledger-lesson {
  font-weight: var(--weight-strong);
  margin-bottom: var(--space-3);
}
.ledger-sliders {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-3) 0;
}
.ledger-slider { margin-bottom: var(--space-3); }
.ledger-slider:last-child { margin-bottom: 0; }
.ledger-slider label {
  display: block;
  font-weight: var(--weight-strong);
  margin-bottom: var(--space-1);
}
.ledger-slider input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}
.ledger-slider-value { color: var(--ink-quiet); font-weight: normal; }
.ledger-body { padding: var(--space-3) var(--space-4); }
.ledger-body p { margin-bottom: var(--space-3); }
.ledger-after { margin: var(--space-3) 0 var(--space-2); }
.ledger-sides {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
@media (min-width: 700px) {
  .ledger-sides { grid-template-columns: 1fr 1fr; }
}
.ledger-side {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
}
.ledger-side h3 { margin-bottom: var(--space-2); }
.ledger-side p { margin-bottom: var(--space-2); }
.ledger-headline {
  font-size: var(--size-lg);
  font-weight: var(--weight-strong);
}
.ledger-sourced { margin-bottom: var(--space-2); }
.ledger-cite { font-size: var(--size-sm); }

/* The take-home ledger (§11 rulings 7y + 7z) — lives inside the gross-vs-net money
   card. Waterfall rows are full-width tappable lines with a right-aligned amount and
   a small per-line year-seam chip; act headings pace Daniel's three-beat arc. */
/* Money-tab sections (§11 ruling 7bb): five narrative groups, each led by a
   one-line why — the hook that earns the tap. */
.money-section-head { margin: var(--space-5) 0 var(--space-1); }

/* Selector rows (§11 ruling 7ff — Daniel: no pill buttons; cohesive with the
   full row). Options render as full-width rows in the ledger grammar: label
   left, figure right, the selected row marked by the accent edge. */
.takehome-options { margin: var(--space-2) 0 var(--space-3); }
.takehome-option {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  border-top: 1px solid var(--line);
  border-left: 3px solid transparent;
  padding: var(--space-2);
  cursor: pointer;
}
.takehome-options .takehome-option:last-child { border-bottom: 1px solid var(--line); }
.takehome-option[aria-pressed="true"] {
  border-left-color: var(--accent);
  background: var(--accent-quiet);
  color: var(--ink-strong);
  font-weight: var(--weight-strong);
}

.takehome { margin-top: var(--space-3); }
.takehome-act { margin: var(--space-4) 0 var(--space-1); }
.takehome-line { border-top: 1px solid var(--line); padding: var(--space-2) 0; }
.takehome-line-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.takehome-amount {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}
/* Headline amounts (net, what's-left) are long two-part strings: they take their
   own full-width line under the label instead of squeezing beside it — the
   phone-pass fix for the label wrapping one word per line while the amount ran
   off-screen. */
.takehome-headline .takehome-amount {
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  flex-basis: 100%;
  margin-left: 0;
  white-space: normal;
}
.takehome-ladder { margin: var(--space-2) 0; }
.takehome-ladder-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--size-sm);
  padding: 2px 0;
}
.takehome-ladder-row .takehome-amount { font-variant-numeric: tabular-nums; }
.takehome-seam { margin-left: var(--space-2); }
.takehome-line-detail { padding: var(--space-2) 0 var(--space-1); }
.takehome-workers-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1) 0;
}

.thumb-play {
  position: absolute;
  right: var(--space-2);
  bottom: var(--space-2);
  background: var(--surface-raised);
  color: var(--ink-strong);
  border: var(--border);
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--size-sm);
}

/* the myths section (§11 ruling 7vv, placed by §11b 7ccc) — one block per myth. The
   belief is set apart with the accent rule and a raised ground so a reader can see at a
   glance which line is the rumour and which line is the evidence; nothing here is red,
   struck through or otherwise made to look foolish, because the rail is never mock the
   person who believed it. */
.myth {
  margin: var(--space-4) 0;
  padding-left: var(--space-3);
  border-left: 3px solid var(--accent-quiet);
}

.myth-belief {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
}

/* the Myth:/Truth:/Fact: tags (§11b ruling 7kkk). Same label grammar the browse tree's
   group labels use — small, upper-case, letter-spaced — so the tag reads as a tag and not
   as the first two words of the sentence. That is the whole ruling: a reader who skims
   headlines must see MYTH before they see the rumour. Deliberately NOT red and not a
   warning colour on the belief; 7s says never mock the person who believed it. */
.myth-label {
  display: inline-block;
  margin-right: var(--space-1);
  font-size: var(--size-xs);
  font-weight: var(--weight-strong);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  vertical-align: baseline;
}

.myth-belief .myth-label,
.myth-why .myth-label {
  color: var(--ink-quiet);
}

.myth-truth .myth-label,
.fact .myth-label {
  color: var(--accent);
}

/* a Fact: quick bit (§11b ruling 7kkk ②). Same section, same tag, and deliberately
   plainer than a myth: there is no belief to set apart on raised ground, so the block is
   one statement and its links. It keeps the myth's accent rule so the section still reads
   as one thing. */
.fact {
  margin: var(--space-4) 0;
  padding-left: var(--space-3);
  border-left: 3px solid var(--accent-quiet);
}

.fact-body {
  margin-bottom: var(--space-2);
}

.myth-belief strong,
.myth-truth strong {
  color: var(--ink-strong);
}

.myth-why {
  margin-bottom: var(--space-2);
}

.myth-truth {
  margin-bottom: var(--space-2);
}

.myth-cites {
  font-size: var(--size-sm);
  margin-bottom: 0;
}

/* the Reads tab (§11b ruling 7bbb). An article card is the same card the feed uses; the
   body below is long-form prose, so it gets a reading measure and a little more air
   between blocks than a dossier field does. */
.article-card .day-headline {
  margin-bottom: var(--space-2);
}

.article-quote {
  margin: var(--space-3) 0;
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--accent-quiet);
  background: var(--surface-raised);
}

.article-list {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-5);
}

.article-list li {
  margin-bottom: var(--space-2);
}

.article-bridge {
  margin-bottom: var(--space-3);
}

.article-cite {
  font-size: var(--size-sm);
  margin-bottom: var(--space-2);
}

.article-cite-detail {
  font-size: var(--size-sm);
  margin: 0 0 var(--space-2) var(--space-3);
}

/* the tracker chart (§11b ruling 7yy ④) — the first data graphic on this site ---------
 *
 * THE FORM IS THE RULING: two horizontal bars on ONE people-per-year axis, the openings
 * bar segmented into the field growing / people leaving the workforce / people moving to
 * other work, a small completions trend line beneath, and the ratio range as the caption.
 * Never two scales. The bars are one comparison, not two series, so there is no legend
 * box — the bar labels name them, and the segmented bar carries a small inline label row
 * instead.
 *
 * THE SIX COLOURS ARE THE ONLY COLOURS IN THIS FILE THAT ARE NOT INK, GROUND OR ACCENT,
 * and they exist for exactly one job: telling the three parts of an openings number
 * apart. They were derived from --accent's own hue (the pipeline pair is that hue,
 * stepped up in chroma until it clears the identity floor) and validated with the data-viz
 * method's runnable checks — lightness band, chroma floor, protan/deutan separation,
 * normal-vision separation and contrast against the card surface — in BOTH modes:
 *   categorical, light on #ffffff and dark on #1e2226 ....... ALL CHECKS PASS
 *   the pipeline pair as an ordinal ramp, both modes ........ ALL CHECKS PASS
 * The dark column is the same four hues re-stepped for the dark surface, chosen for that
 * mode's band — not an automatic flip. Changing any one of these six means re-running the
 * validator, and a guard test pins them against the registry that draws with them.
 *
 * TEXT NEVER WEARS THE SERIES COLOUR. Every value, label and percentage on a chart is set
 * in --ink / --ink-quiet, exactly like the prose beside it; the coloured mark carries the
 * identity. There is still no alarm token in this file — none of these six means good or
 * bad, and none is reused for a status anywhere.
 */

:root {
  --chart-pipeline: #008a6f;
  --chart-pipeline-far: #66c6ab;
  --chart-growth: #2a78d6;
  --chart-exit: #eb6834;
  --chart-transfer: #4a3aa7;
  --chart-plain: var(--line-strong);
}

@media (prefers-color-scheme: dark) {
  :root {
    --chart-pipeline: #009f81;
    --chart-pipeline-far: #186351;
    --chart-growth: #3987e5;
    --chart-exit: #d95926;
    --chart-transfer: #9085e9;
  }
}

.tracker-chart {
  margin: var(--space-3) 0 var(--space-4);
}

.tk-row { margin-bottom: var(--space-3); }

.tk-bar-label {
  font-size: var(--size-sm);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: 0 0 var(--space-1);
}

/* The track is the row; the PLOT inside it is the shared axis. Both bars are measured
   against the same plot width, which is what makes them one comparison and not two charts
   stacked — and the direct label sits outside the plot so a long figure can never steal
   axis from the bar it labels. */
.tk-track {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.tk-plot {
  flex: 1 1 auto;
  min-width: 0;
}

.tk-value { flex: none; }

.tk-bar {
  display: flex;
  height: 0.85rem;
  min-width: 2px;
  border-radius: 0 4px 4px 0;
  overflow: hidden;
  background: transparent;
}

.tk-seg {
  display: block;
  height: 100%;
  /* The global button rule sets a 2.5rem min-height for thumbs; a chart segment is a
     MARK, not a control, and it has to stay thin. The tap target lives on the key row
     below instead, which is text-sized and full-width — bigger than the mark, which is
     the rule. */
  min-height: 0;
  min-width: 2px;
  box-sizing: border-box;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* The 2px surface gap between stacked fills, drawn as a border in the card's own ground
   so two touching segments never read as one. */
.tk-seg + .tk-seg { border-left: 2px solid var(--surface-raised); }

.tk-pipe { background: var(--chart-pipeline); }
.tk-pipe-far { background: var(--chart-pipeline-far); }
.tk-growth { background: var(--chart-growth); }
.tk-exit { background: var(--chart-exit); }
.tk-transfer { background: var(--chart-transfer); }
.tk-plain { background: var(--chart-plain); }

.tk-value {
  font-size: var(--size-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-strong);
  white-space: nowrap;
}

/* Not a legend box — the names of the three parts of the bar directly above, in ink, each
   with its own small mark. */
.tk-keys {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  margin: var(--space-1) 0 0;
}

/* Each key is the tap target for its segment: text-sized, comfortably bigger than the
   0.85rem mark it names, and it still reads as a label rather than a button. */
.tk-key {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font: inherit;
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1) 0;
  min-height: 1.9rem;
  text-align: left;
  cursor: pointer;
}

.tk-key:hover { color: var(--ink-strong); }

.tk-swatch {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 2px;
  flex: none;
}

.tk-readout {
  font-size: var(--size-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-strong);
  min-height: 1.4em;
  margin: var(--space-1) 0 0;
}

.tk-trend { margin-top: var(--space-2); }

.tk-trend svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.tk-trend-ends {
  display: flex;
  justify-content: space-between;
  font-size: var(--size-xs);
  font-variant-numeric: tabular-nums;
  color: var(--ink-quiet);
  margin: 0;
}

.tk-trend-word {
  font-size: var(--size-sm);
  color: var(--ink);
  margin: var(--space-1) 0 0;
}

.tk-caption {
  font-size: var(--size-sm);
  color: var(--ink-strong);
  margin: var(--space-2) 0 var(--space-1);
}

/* The sentence that carries the same two numbers, so the data survives without the
   graphic — for a printout, a screen reader, or a browser that draws none of this. */
.tk-fallback { margin-bottom: var(--space-2); }

.tk-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--size-sm);
  font-variant-numeric: tabular-nums;
}

.tk-table-wrap { overflow-x: auto; margin: var(--space-2) 0 var(--space-3); }

.tk-table th,
.tk-table td {
  text-align: right;
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.tk-table th:first-child,
.tk-table td:first-child { text-align: left; }

.tk-table thead th {
  color: var(--ink-quiet);
  font-weight: var(--weight-normal);
  font-size: var(--size-xs);
}

.tk-table tr.is-benchmark td {
  color: var(--ink-strong);
  font-weight: var(--weight-strong);
  border-top: 1px solid var(--line-strong);
}

.tk-pocket {
  margin: var(--space-3) 0;
  padding-left: var(--space-3);
  border-left: 3px solid var(--accent-quiet);
}

/* The target-schools lane (addendum v1.2 §§1-4). Almost everything here reuses the
   lane grammar the hustles and tracker lanes already established — rows, .money-body,
   .tk-bar-label — so the tab reads as one surface. Only three things are new, and each
   one earns its rule:

   .target-quote  A school's own sentence, set apart so it can never be mistaken for
                  ours. The rule down the left is the visual form of the attribution.
   .target-course One (course × school) record. Indented under its group so 25 of them
                  read as a list of the same kind of thing, not 25 sections.
   .target-edge   The two sides of a tradeoff, always rendered as a pair. They are
                  given the same weight on purpose: styling one as a warning would
                  make the pair a recommendation. */

.target-quote {
  margin: 0 0 var(--space-2);
  padding-left: var(--space-3);
  border-left: 3px solid var(--accent-quiet);
  color: var(--ink-strong);
}

.target-course {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-3);
  border-left: 1px solid var(--line);
}

.target-course-name {
  font-weight: var(--weight-strong);
  margin-bottom: var(--space-1);
}

.target-course p { margin-bottom: var(--space-1); }

.target-edge { margin-bottom: var(--space-2); }

/* ---------------------------------------------------------------------------------------
 * My journey (addendum v1.1 §11b ruling 7iii)
 * ---------------------------------------------------------------------------------------
 * TWO ALTITUDES, ONE TAB. The switcher is PICK-ONE, so ruling 7ff makes it full-width rows
 * — the `.tree-row` grammar every lane on Explore already uses, plus a help line on the
 * row's own face so the choice explains itself before it is made.
 *
 * THE THREE STATES ARE TOLD APART BY WEIGHT AND EDGE, NEVER BY ALARM. This file's banner
 * says there is no --danger token and no .is-late rule, and the four-year map is exactly
 * the surface that would tempt someone to add one: a senior year that is entirely
 * "planned" is a plan nobody has made yet, and §4.15.4 forbids styling that as a problem.
 * So: CONFIRMED carries the accent (it is the settled one), LEANING TOWARD carries a
 * dashed edge (a line that has not been drawn firmly yet — a picture of the state, not a
 * warning about it), PLANNED carries the ordinary line every other row on this site has.
 * No colour on this surface means "bad", because no state on this surface is bad.
 */

.altitudes {
  margin: 0 0 var(--space-4);
}

.altitude-row {
  display: block;
}

.altitude-row[aria-current="true"] {
  border-color: var(--accent);
  background: var(--accent-quiet);
}

.altitude-label {
  display: block;
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
}

.altitude-help {
  display: block;
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

/* the legend — the states are taught before the grid spends them */
.journey-legend {
  margin: var(--space-3) 0 var(--space-5);
}

.journey-legend-item {
  font-size: var(--size-sm);
  color: var(--ink-quiet);
  margin: 0 0 var(--space-2);
}

.journey-grade {
  margin: 0 0 var(--space-5);
}

.journey-grade-head {
  margin-top: var(--space-4);
}

.journey-grade-name {
  display: block;
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
}

.journey-grade-theme {
  display: block;
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

.journey-course {
  display: block;
}

.journey-course-title {
  display: block;
  color: var(--ink-strong);
}

.journey-chips {
  display: block;
  margin: var(--space-1) 0 0;
}

/* CONFIRMED: the settled one, so it wears the single accent this palette has. */
.journey-state-confirmed { border-left: 3px solid var(--accent); }

/* LEANING TOWARD: a dashed edge is a picture of an unfinished choice. It is the SAME ink
   as every other row — nothing here is coloured to mean caution. */
.journey-state-intent { border-left: 3px dashed var(--line-strong); }

/* PLANNED: the ordinary edge. A future year looking ordinary is the correct outcome. */
.journey-state-planned { border-left: 3px solid var(--line); }

.journey-chip-confirmed { background: var(--accent-quiet); border-color: var(--accent); }
.journey-chip-intent { border-style: dashed; }

.journey-panel {
  border: var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  padding: var(--space-4);
  margin: 0 0 var(--space-2);
}

/* An approval line is a WAITING line. Same ink, same size, no icon, no colour: the family
   is not late for a meeting that has not been scheduled yet. */
.journey-approval {
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

.journey-lens {
  margin: var(--space-3) 0 0;
  padding-left: var(--space-3);
  border-left: 2px solid var(--line);
}

.journey-lens-school {
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
  margin: var(--space-3) 0 var(--space-1);
}

.journey-verify {
  margin: 0 0 var(--space-3) var(--space-4);
  padding: 0;
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

/* The empty state's call to action — the founder's own sentence, in the map's own voice.
   Sized up because it is the only thing on the screen, not because it is urgent. */
.journey-cta {
  font-size: var(--size-lg);
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
}

/* the vote row (ruling 7nnn ②) — under an armed video only ------------------------------ */
/* Two verdicts on one thing, side by side; the chosen one accent-lit. Calm by design:
   no counts shown, no red — a vote is feedback on the VIDEO, never a scoreboard. */

.vote-row {
  margin: var(--space-3) 0 var(--space-4);
}

.vote-question {
  font-size: var(--size-sm);
  font-weight: var(--weight-strong);
  color: var(--ink);
  margin: 0 0 var(--space-2);
}

.vote-buttons {
  display: flex;
  gap: var(--space-2);
}

.vote-button {
  flex: 1;
  padding: var(--space-2) var(--space-3);
}

.vote-button.vote-active {
  border-color: var(--accent);
  color: var(--ink-strong);
  font-weight: var(--weight-strong);
  box-shadow: inset 3px 0 0 var(--accent);
}

.vote-note {
  font-size: var(--size-xs);
  margin: var(--space-2) 0 0;
}

/* overnight revamp, phase 1 chrome (2026-08-17) --------------------------------------- */
/* Touch feedback: phones have no hover, so every tappable thing confirms the tap the
   moment the finger lands (the Replit v3 lesson). Buttons and tree rows only — form
   inputs and sliders keep their native behavior. */

button:not(:disabled):active,
.tree-row:active,
.day-card:active {
  transform: scale(0.985);
}

@media (prefers-reduced-motion: reduce) {
  button:not(:disabled):active,
  .tree-row:active,
  .day-card:active {
    transform: none;
  }
}

/* The active tab wears the accent (was: sunken pill) — the bar's one color moment. */
.tabbar .tab[aria-current="page"] {
  color: var(--accent);
  background: none;
}

/* Flat section-header grammar (Replit v3): a small uppercase label with a hairline
   rule running to the edge — the outer layer goes flat so the inner tiles read as
   the tappable things. */
.section-label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--size-xs);
  font-weight: var(--weight-strong);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-quiet);
  margin: var(--space-4) 0 var(--space-2);
}

.section-label::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* The "this navigates" marker (Replit v3's strongest cue): a chevron in a tinted
   accent circle. Markup adds <span class="go-chevron" aria-hidden="true">›</span>. */
.go-chevron {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  background: var(--accent-quiet);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--weight-strong);
  font-size: var(--size-md);
  line-height: 1;
}

/* Myth:/Truth: labels (7kkk) get the accent split from the Replit myths card:
   the myth tag in accent so a skimmer's eye catches the label before the claim,
   the truth tag in strong ink. Labels are registry-borne; this styles only. */
.myth-label { color: var(--accent); }
.myth-truth .myth-label { color: var(--ink-strong); }

/* Wage ladder: the top rung ("Where it pays most") carries a quiet accent tint —
   the one moment of color in the ladder, per the Replit card. */
.wage-rung:last-of-type {
  background: var(--accent-quiet);
  border-radius: var(--radius-sm);
}

/* The theme toggle (topbar): a quiet text control, three states, plain words. */
#theme-toggle {
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  text-decoration: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: var(--space-1) var(--space-3);
  min-height: 0;
  background: none;
}

/* overnight revamp, phase 2 — lens landings + explore navigation --------------------- */

/* Interest rows on the front door now NAVIGATE (single tap -> lens landing): flex so
   the chevron sits on the right edge of the same full-width row grammar. */
.tree-nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

/* The role tile (Replit v3 grammar): the innermost layer is the tappable thing, so it
   alone gets the raised-card treatment; the layer above it went flat (.section-label). */
.role-tile {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  text-align: left;
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-2);
}

.role-tile-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.role-tile-name {
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
}

.role-tile-pay {
  font-size: var(--size-sm);
  color: var(--ink-quiet);
}

/* The folded programs directory: the heading stays the section's h2; the marker says
   it opens. Everything inside is untouched machinery. */
.programs-fold > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.programs-fold > summary::-webkit-details-marker { display: none; }

.programs-fold > summary::after {
  content: "›";
  color: var(--accent);
  font-weight: var(--weight-strong);
  font-size: var(--size-lg);
  transition: transform 0.15s ease;
}

.programs-fold[open] > summary::after {
  transform: rotate(90deg);
}

.programs-fold > summary h2 { margin: 0; }

/* overnight revamp, phase 3 — bridges: one quiet line + one accent link ---------------- */
.bridge-line { margin: var(--space-3) 0 var(--space-1); }
.bridge-link {
  display: inline-block;
  margin: 0 0 var(--space-3);
  font-weight: var(--weight-strong);
}

/* overnight revamp, phase 4 — the deep end ------------------------------------------- */
.deep-end {
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0;
}

.deep-end > summary {
  cursor: pointer;
  font-weight: var(--weight-strong);
  color: var(--ink-strong);
}

/* overnight revamp, phase 5 — the way back up ---------------------------------------- */
.to-top {
  position: fixed;
  right: var(--space-4);
  bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px));
  z-index: 11;
  border-radius: 999px;
  background: var(--surface-raised);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  font-weight: var(--weight-strong);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  padding: var(--space-2) var(--space-4);
}

.bottom-back {
  display: block;
  margin: var(--space-5) 0 var(--space-3);
  font-weight: var(--weight-strong);
}

/* 8/17 layering + about ---------------------------------------------------------------- */
.about-row {
  margin: var(--space-6) 0 var(--space-2);
  text-align: center;
}

/* 7sss — the interest tiles: bigger, caption on the face --------------------------------- */
.lens-tile {
  padding: var(--space-4);
}

.lens-tile .role-tile-pay {
  line-height: 1.4;
}

/* 7uuu — the deferral ledger ---------------------------------------------------------- */
.deferral-ledger {
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-3) 0;
}

/* 7www ② — the comparison exhibit ----------------------------------------------------- */
.approach-cell {
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-2);
}

.approach-willabe {
  border-left: 3px solid var(--accent);
}

.approach-cell-head {
  font-size: var(--size-xs);
  font-weight: var(--weight-strong);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-quiet);
  margin: 0 0 var(--space-1);
}

.approach-cell p:last-child { margin: 0; }

/* The range filters (Daniel 8/17 night: "make the bars look like airbnb where it
   shows where the distribution is"). One histogram above a two-thumb track, bounds
   chips beneath. The bars are marks, not text: the selected range wears the accent,
   the rest the strong line tone; 2px surface gaps between bars per the house chart
   method. All colors ride the theme tokens, so both themes resolve as sets. */
.range-filter {
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-3) 0;
}
.range-filter .fr-label {
  display: block;
  font-weight: var(--weight-strong);
  margin-bottom: var(--space-2);
}
/* Geometry contract (2026-08-20, founder's alignment screenshot): the 24px thumb's
   center travels [14px, width−14px] of the card's padded box (2px track margin +
   12px thumb radius). The rail, the fill, and the histogram all share that exact
   span, so a thumb position, its fill edge, and the bar it points at agree. */
.fr-histo {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 44px;
  margin: 0 14px;
}
.fr-histo span {
  flex: 1 1 0;
  background: var(--line-strong);
  border-radius: 2px 2px 0 0;
  min-height: 2px;
}
/* Discrete axes: one chunky 20px bar CENTERED on each slider stop (margin =
   14 − 20/2), so the thumb at "2 years" sits under the 2-year bar. Rounded
   tops so lone bars read as deliberate marks, not broken slivers. */
.fr-histo.fr-histo-discrete {
  justify-content: space-between;
  gap: 0;
  margin: 0 4px;
}
.fr-histo.fr-histo-discrete span {
  flex: 0 0 20px;
  min-height: 0;
  border-radius: 4px 4px 0 0;
}
/* Scale ticks on a discrete rail — one dot per stop, sitting ON the rail so
   they read as the scale, never as data. */
.fr-rail .fr-tick {
  position: absolute;
  top: -1px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--line-strong);
  transform: translateX(-50%);
}
.fr-histo span.in { background: var(--accent); }
.fr-track { position: relative; height: 30px; margin: 0 2px; }
.fr-rail {
  position: absolute;
  top: 14px;
  left: 12px;
  right: 12px;
  height: 2px;
  background: var(--line);
  border-radius: 1px;
}
.fr-rail .fr-fill { position: absolute; top: 0; height: 2px; background: var(--accent); }
.fr-track input[type="range"] {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 30px;
  margin: 0;
  background: none;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}
.fr-track input[type="range"]::-webkit-slider-runnable-track { background: transparent; }
.fr-track input[type="range"]::-moz-range-track { background: transparent; }
.fr-track input[type="range"]::-webkit-slider-thumb {
  pointer-events: auto;
  -webkit-appearance: none;
  width: 24px;
  height: 24px;
  margin-top: 3px;
  border-radius: 50%;
  background: var(--surface-raised);
  border: 2px solid var(--ink);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  cursor: pointer;
}
.fr-track input[type="range"]::-moz-range-thumb {
  pointer-events: auto;
  /* Same 24px as WebKit — the alignment contract above assumes one thumb radius. */
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--surface-raised);
  border: 2px solid var(--ink);
  cursor: pointer;
}
.fr-track input[type="range"]:focus-visible::-webkit-slider-thumb {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.fr-track input[type="range"]:focus-visible::-moz-range-thumb {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.fr-bounds {
  display: flex;
  justify-content: space-between;
  margin-top: var(--space-1);
}
.fr-chip {
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  padding: 0.15rem 0.75rem;
  font-size: var(--size-sm);
  background: var(--surface-raised);
  font-variant-numeric: tabular-nums;
}
.fr-cap {
  display: block;
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  margin-bottom: 2px;
}
.fr-bounds > div:last-child { text-align: right; }
/* Rail-end labels (2026-08-19): the axis's real extent in words or actual
   numbers, sitting directly under the histogram, quiet tone. */
.fr-ends {
  display: flex;
  justify-content: space-between;
  font-size: var(--size-xs);
  color: var(--ink-quiet);
  margin-top: 2px;
}
