:root {
  color-scheme: dark;

  /* Surfaces. Warm-neutral rather than blue-grey — the gold has to sit on
     them without turning green, and pure #000 makes OLED phones smear on
     scroll. */
  --bg: #0d0d0c;
  --bg-elev: #121211;
  --surface-1: #171716;
  --surface-2: #1f1f1d;
  --surface-3: #292927;
  --surface-4: #333331;

  --line: rgba(255,255,255,.07);
  --line-strong: rgba(255,255,255,.14);
  /* The 1px of light along the top of a raised surface. Does more for
     perceived quality than any shadow. */
  --edge-light: rgba(255,255,255,.06);

  --text-primary: #f7f6f3;
  --text-secondary: #bdbcb2;
  --text-muted: #85847b;
  --text-faint: #5c5b54;

  --series-1: #4a8ff0;
  --series-2: #e0663a;
  --series-3: #1fae7d;
  --good: #1fae7d;
  --warn: #d59300;
  --bad: #e2544a;

  --gold: #d4af37;
  --gold-lit: #f6e39a;
  --gold-deep: #9c7a24;
  --gold-soft: rgba(212,175,55,.30);
  --gold-wash: rgba(212,175,55,.08);

  /* Type scale, 1.2 ratio off a 15px base. */
  --t-xs: .74rem;
  --t-sm: .83rem;
  --t-base: .94rem;
  --t-md: 1.05rem;
  --t-lg: 1.28rem;
  --t-xl: 1.6rem;
  --t-2xl: 2.1rem;
  --t-3xl: 2.9rem;

  /* Spacing, 4px base. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s7: 32px; --s8: 44px;

  --radius-xs: 8px;
  --radius-sm: 11px;
  --radius: 15px;
  --radius-lg: 22px;

  --sidebar-w: 248px;
  --tabbar-h: 62px;

  --shadow-card: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px -14px rgba(0,0,0,.7);
  --shadow-lift: 0 2px 6px rgba(0,0,0,.34), 0 18px 40px -18px rgba(0,0,0,.8);
  --shadow-pop:  0 4px 12px rgba(0,0,0,.4), 0 32px 64px -24px rgba(0,0,0,.85);

  /* One easing for everything, so the whole app moves like one object. */
  --ease: cubic-bezier(.32,.72,0,1);
  --fast: .14s;
  --med: .24s;

  font-family: ui-sans-serif, -apple-system, "SF Pro Text", "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
  font-feature-settings: "cv05" 1, "ss01" 1;

  /* Primary action + accent ink. Brand-driven: brand.js overrides these
     per licensee, and the gold values here are the origin brand's. */
  --primary: #3a7fe0;
  --primary-lit: #5c9bf3;
  --primary-hover: #2f74d6;
  --primary-lit-hover: #6ba6f5;
  --on-primary: #fff;
  --on-accent: #241c07;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text-primary);
  -webkit-font-smoothing: antialiased;
  font-size: 15px;
  line-height: 1.5;
}
a { color: inherit; text-decoration: none; }
h1, h2, h3 { margin: 0; font-weight: 640; letter-spacing: -.01em; }
h1 { font-size: 1.75rem; font-weight: 700; }
h2 { font-size: 1.05rem; }
h3 { font-size: .95rem; }
p { margin: 0; }

/* ---------- buttons & fields ---------- */
.btn {
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--text-primary);
  border-radius: 999px;
  padding: 9px 16px;
  font: inherit;
  font-weight: 560;
  font-size: .9rem;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, opacity .15s ease;
}
.btn:hover { background: var(--surface-3); }
.btn-primary { background: var(--primary); border-color: transparent; color: var(--on-primary); }
.btn-primary:hover { background: var(--primary-hover); }
.btn-block { width: 100%; padding: 12px 16px; }
.btn-sm { padding: 6px 12px; font-size: .82rem; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.linkbtn {
  background: none; border: 0; color: var(--text-muted);
  font: inherit; font-size: .85rem; cursor: pointer; padding: 6px 0; text-decoration: underline;
  text-underline-offset: 3px;
}
.linkbtn:hover { color: var(--text-secondary); }
.linkbtn.is-danger { color: var(--warn); }
.linkbtn.is-danger:hover { color: var(--warn); opacity: .8; }
.icon-btn {
  background: none; border: 0; color: var(--text-secondary);
  font-size: 1.15rem; cursor: pointer; padding: 6px 8px; border-radius: 8px;
}
.field { display: block; margin-bottom: 14px; }
.field > span { display: block; font-size: .82rem; color: var(--text-secondary); margin-bottom: 6px; }
.field input, .field select, .field textarea {
  width: 100%; padding: 11px 13px; font: inherit; font-size: .95rem;
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid var(--series-1); outline-offset: 1px; border-color: transparent;
}

/* ---------- auth ---------- */
.auth {
  min-height: 100dvh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 18px; padding: 24px 16px;
}
.auth-card {
  width: 100%; max-width: 400px; background: var(--surface-1);
  border: 1px solid var(--line); border-radius: 18px; padding: 28px 24px 22px;
}
.auth-logo { display: block; margin: 0 auto; max-width: 180px; height: auto; border-radius: 14px; }
.auth-sub, .vault-sub { color: var(--text-secondary); font-size: .9rem; margin: 10px 0 20px; text-align: center; }
.auth-note { font-size: .85rem; color: var(--text-secondary); margin-top: 12px; min-height: 1.2em; }
.auth-note.is-error { color: #e66767; }
.auth-note.is-ok { color: var(--good); }
.auth-foot { color: var(--text-muted); font-size: .82rem; }
.btn.btn-google {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: #fff; color: #1f1f1f; border-color: #fff; margin-bottom: 14px;
}
.btn.btn-google:hover { background: #f1f1f1; }
.auth-divider { display: flex; align-items: center; gap: 12px; margin: 4px 0 18px; color: var(--text-faint); font-size: .8rem; }
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.tabs { display: flex; gap: 4px; background: var(--surface-2); padding: 4px; border-radius: 999px; margin-bottom: 20px; }
.tab {
  flex: 1; border: 0; background: none; color: var(--text-secondary);
  font: inherit; font-size: .88rem; font-weight: 560; padding: 8px; border-radius: 999px; cursor: pointer;
}
.tab.is-active { background: var(--surface-3); color: var(--text-primary); }

/* ---------- shell ---------- */
.app { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100dvh; }
.sidebar {
  background: var(--surface-1); border-right: 1px solid var(--line);
  padding: 20px 14px; display: flex; flex-direction: column; gap: 22px;
  position: sticky; top: 0; height: 100dvh;
}
.brand { position: relative; display: flex; align-items: center; gap: 10px; padding: 0 6px; font-weight: 640; letter-spacing: -.01em; }
.brand-menu-toggle { width: 32px; height: 32px; flex-shrink: 0; }
.brand-menu-toggle[aria-expanded="true"] { background: var(--surface-2); color: var(--text-primary); }
/* Same panel language as .notif-panel -- a dropdown off a top-left
   control instead of a top-right one, so it anchors from the left
   edge rather than the right. */
.brand-menu {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 20;
  width: min(240px, 85vw);
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface-1) 60%);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0,0,0,.35);
  padding: var(--s2);
  display: flex; flex-direction: column; gap: 2px;
}
.brand-menu-item {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--radius-xs);
  font-size: var(--t-sm); font-weight: 560; color: var(--text-primary);
  text-decoration: none; transition: background var(--fast) var(--ease);
}
.brand-menu-item:hover { background: var(--surface-3); }
.brand-menu-icon { width: 20px; height: 20px; flex-shrink: 0; border-radius: 5px; object-fit: contain; }
.brand-menu-icon-empty { display: inline-block; }
.brand-mark { color: var(--series-1); display: grid; place-items: center; }
/* `display:grid` above outranks the UA stylesheet's [hidden]{display:none},
   so a brand with no logo file -- BE WELLthy and BoboHQ are typographic
   wordmarks, they have none -- would have shown a broken-image box next
   to its name. applyBrand() sets .hidden on those; this is what makes it
   mean anything. */
.brand-mark[hidden] { display: none; }
.brand-text { font-size: .95rem; }
.brand-lg { font-size: 1.1rem; }
.brand-lg .brand-text { font-size: 1.1rem; }
.sidebar-toggle { margin-left: auto; flex: none; }

/* Collapsed to a slim icon rail: just the logo and the toggle, stacked,
   so the main view gets its width back without losing the brand mark or
   the one way back out. Scoped to the width where the sidebar is a real
   grid column at all -- below 860px it's already off-canvas, and the
   mobile override further down restores everything regardless of this
   class, same as any other state that shouldn't survive a resize. */
@media (min-width: 861px) {
  .app { transition: grid-template-columns .18s ease; }
  .app.sidebar-collapsed { grid-template-columns: 64px 1fr; }
  .app.sidebar-collapsed .sidebar { padding: 20px 10px; }
  .app.sidebar-collapsed .brand { flex-direction: column; justify-content: center; gap: 10px; padding: 0; }
  .app.sidebar-collapsed .brand-text,
  .app.sidebar-collapsed .nav,
  .app.sidebar-collapsed .nav-crest,
  .app.sidebar-collapsed .side-foot { display: none; }
  .app.sidebar-collapsed .sidebar-toggle { margin-left: 0; }
  .app.sidebar-collapsed .sidebar-toggle svg { transform: rotate(180deg); }
}

.nav { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; }
.nav-group { display: flex; flex-direction: column; gap: 2px; margin: 6px 0; padding: 6px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.nav-group-label {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 10px 8px; font-size: .74rem; font-weight: 640;
  text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted);
}
.nav-item {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--radius-sm);
  color: var(--text-secondary); font-size: .98rem; font-weight: 520;
  transition: background .15s ease, color .15s ease;
}
.nav-item:hover { background: var(--surface-2); color: var(--text-primary); }
.nav-item.is-active { background: var(--surface-3); color: var(--text-primary); }
.nav-item.is-active::before {
  content: ''; position: absolute; left: -14px; top: 8px; bottom: 8px; width: 3px;
  border-radius: 0 2px 2px 0; background: linear-gradient(180deg, var(--gold-lit), var(--gold) 60%, var(--gold-deep));
}
.nav-ico { width: 20px; text-align: center; opacity: .9; font-size: .9rem; display: flex; align-items: center; justify-content: center; }

.side-foot { display: flex; flex-direction: column; align-items: stretch; gap: 10px; padding: 0 6px; }
.side-foot .linkbtn { text-align: center; }
.mode-toggle { display: flex; gap: 2px; background: var(--surface-2); padding: 3px; border-radius: 999px; }
.mode-toggle-btn {
  flex: 1; border: 0; background: none; color: var(--text-secondary);
  font: inherit; font-size: .78rem; font-weight: 640; padding: 7px 4px;
  border-radius: 999px; cursor: pointer; transition: background .15s ease, color .15s ease;
}
.mode-toggle-btn.is-active {
  background: linear-gradient(180deg, var(--gold-lit), var(--gold) 55%, var(--gold-deep));
  color: #231b06;
}
.demo-toggle {
  border: 1px solid var(--line); background: none; color: var(--text-secondary);
  font: inherit; font-size: .78rem; font-weight: 640; padding: 7px 10px;
  border-radius: 999px; cursor: pointer;
}
.demo-toggle.is-active { border-color: var(--gold); color: var(--gold-lit); }

.main { min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 26px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: rgba(15,15,14,.86); backdrop-filter: blur(8px); z-index: 5;
}
.crumb { font-size: .9rem; color: var(--text-secondary); flex: 1; }
.who { font-size: .85rem; color: var(--text-muted); }
.view { padding: 26px; max-width: 1180px; width: 100%; }

/* ---------- layout pieces ---------- */
.page-head { margin-bottom: 22px; }
.page-head p { color: var(--text-secondary); font-size: .93rem; margin-top: 6px; }
.grid { display: grid; gap: 14px; }
.kpis { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); margin-bottom: 20px; }
.cols-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.cols-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.section { margin: 28px 0; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.section-head h2 { position: relative; padding-left: 13px; }
.section-head h2::before {
  content: ''; position: absolute; left: 0; top: 3px; bottom: 3px; width: 3px;
  border-radius: 2px; background: linear-gradient(180deg, var(--gold-lit), var(--gold) 60%, var(--gold-deep));
}
.section-head .hint { font-size: .82rem; color: var(--text-muted); }

.card {
  background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow-card);
}
.card-hd { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.card p.sub { color: var(--text-secondary); font-size: .88rem; }

/* NeuroTracker brain training -- their own app fills whatever frame it's
   given, and the docs don't specify a size, so this picks a height big
   enough to actually train in rather than a cramped preview. */
.ntx-frame-card { padding: 0; overflow: hidden; }
.ntx-frame { width: 100%; height: min(78vh, 760px); border: 0; display: block; }

/* KPI tile */
.kpi { background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow-card); }
.kpi .label { font-size: .78rem; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted); }
.kpi .value { font-size: 1.85rem; font-weight: 680; letter-spacing: -.02em; margin-top: 6px; font-variant-numeric: tabular-nums; }
.kpi .foot { font-size: .82rem; color: var(--text-secondary); margin-top: 2px; }

/* momentum strip: denser, larger hero stats above the standing KPIs */
.momentum { margin-bottom: 20px; }
.kpi-hero {
  border-color: var(--line-strong);
  background: linear-gradient(180deg, rgba(212,175,55,.07), var(--surface-1) 55%);
}
.kpi-hero .value { font-size: 2.15rem; }
.kpi-hero .of14 { font-size: 1rem; color: var(--text-muted); font-weight: 500; margin-left: 1px; }

/* top values */
.values-row { margin-top: 0; }
.value-card { display: flex; align-items: center; gap: 14px; border-color: var(--gold-soft); box-shadow: var(--shadow-card); }
.value-rank {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: linear-gradient(135deg, var(--gold-lit) 0%, var(--gold) 45%, var(--gold-deep) 100%);
  box-shadow: 0 2px 8px -2px rgba(212,175,55,.55);
  color: var(--on-accent); font-weight: 700; font-size: 1rem;
  display: flex; align-items: center; justify-content: center;
}
.value-label { font-weight: 600; font-size: 1rem; line-height: 1.3; }

/* freshness / staleness chips */
.freshness { margin-left: auto; font-size: .74rem; color: var(--text-muted); white-space: nowrap; }
.legend-row { flex-wrap: wrap; row-gap: 2px; }
.legend-row .stale { margin-left: 6px; font-size: .76rem; color: var(--text-muted); }

/* activity feed */
.activity-row { align-items: center; }
.activity-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; }

/* progress bar */
.bar { height: 8px; background: var(--surface-3); border-radius: 999px; overflow: hidden; }
.bar > i { display: block; height: 100%; border-radius: 999px; background: var(--series-1); transition: width .4s ease; }
.bar-row { display: flex; align-items: center; gap: 12px; }
.bar-row .bar { flex: 1; }
.bar-row .num { font-size: .85rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 64px; text-align: right; }

/* area tile */
.area-tile { display: block; background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px; }
.area-tile:hover { border-color: var(--line-strong); }
.area-top { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.area-top h3, .area-top h1 { font-size: 1.2rem; }
.area-tag { font-size: .92rem; color: var(--text-secondary); margin-bottom: 14px; }

/* the Money Muscle Memory brain-and-dumbbell mark, standing in for the flat
   colored dots that used to mark each life area — sized per call site via
   the width/height attributes areaIcon() sets in app.js. */
.area-icon { border-radius: 7px; flex: none; object-fit: contain; background: #000; }
.rating { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.rating input[type=range] { flex: 1; accent-color: var(--series-1); }
.rating .score { font-variant-numeric: tabular-nums; font-weight: 640; font-size: 1rem; min-width: 42px; text-align: right; }
.rating .score .of { color: var(--text-muted); font-weight: 400; font-size: .8rem; }

/* module rows */
.mod {
  display: flex; align-items: flex-start; gap: 13px; padding: 14px 4px;
  border-bottom: 1px solid var(--line);
}
.mod:last-child { border-bottom: 0; }
.mod-check {
  flex: none; width: 22px; height: 22px; border-radius: 7px; margin-top: 2px;
  border: 1.5px solid var(--line-strong); background: var(--surface-2);
  display: grid; place-items: center; cursor: pointer; color: transparent; font-size: .8rem;
}
.mod-check.is-done { background: var(--good); border-color: var(--good); color: #05150f; }
.mod-check.is-locked { cursor: not-allowed; opacity: .55; }

/* Marketing Hub board -- drag-and-drop column states */
.marketing-col .mod { flex-direction: column; border: 1px solid var(--line); border-radius: 10px; margin-bottom: 8px; padding: 10px; }
.marketing-col .mod.is-dragging { opacity: .4; }
.marketing-col[data-status-col].is-drop-target > .card { outline: 2px dashed var(--gold, var(--good)); outline-offset: -2px; border-radius: 10px; }
.mod-body { flex: 1; min-width: 0; }
.mod-title { font-weight: 570; font-size: .95rem; }
.mod-title a:hover { text-decoration: underline; }
.mod-sum { color: var(--text-secondary); font-size: .87rem; margin-top: 3px; }
.mod-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 7px; font-size: .78rem; color: var(--text-muted); }
.pill {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 640;
  padding: 3px 8px; border-radius: 999px; background: var(--surface-3); color: var(--text-secondary);
}
.pill.free { background: rgba(57,135,229,.16); color: #7db2ef; }
.pill.locked { background: rgba(201,133,0,.16); color: #e0a93c; }
.pill.soon { background: var(--surface-3); color: var(--text-muted); }
.pill.draft { background: rgba(124,92,255,.18); color: #a894ff; }

/* Unpublished content is readable by admins only (RLS: is_published OR
   mmm_is_admin), so this note is self-selecting -- a member can never be
   on a page that renders it. */
.draft-note {
  margin: 12px 0 0; padding: 9px 13px; border-radius: var(--radius-sm);
  background: rgba(124,92,255,.12); border: 1px solid rgba(124,92,255,.3);
  color: #a894ff; font-size: var(--t-sm); font-weight: 560;
}

/* tools */
.tool { display: flex; flex-direction: column; gap: 10px; }
.tool .row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* Health tools grid: the tile's image stands in for the title text that
   used to sit above the description. */
.tool-icon { display: flex; align-items: center; justify-content: center; height: 84px; color: var(--gold); overflow: hidden; border-radius: var(--radius-xs); }
.tool-icon-svg { height: 100%; width: auto; max-width: 100%; }
.tool-icon-photo { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-xs); }
.tool-icon-brain { height: 84px; }
.tool-icon-brain svg { height: 100%; width: auto; border-radius: var(--radius-xs); }
.tool-label {
  margin-top: auto; padding-top: 6px; font-size: var(--t-xs); font-weight: 640;
  text-transform: uppercase; letter-spacing: .06em; color: var(--gold);
}

/* Lesson section carousel -- one mini-section at a time, paged with
   left/right, each with its own placeholder photo/video slot. */
.section-media-empty {
  display: flex; align-items: center; justify-content: center;
  min-height: 160px; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
  color: var(--text-muted); font-size: var(--t-sm); text-align: center; padding: var(--s4);
}
.section-carousel-body { margin-top: var(--s3); }
.section-carousel-pos { font-size: var(--t-xs); color: var(--text-muted); letter-spacing: .04em; text-transform: uppercase; }
.section-carousel-body h3 { margin: 4px 0 8px; }
.section-carousel-nav {
  display: flex; align-items: center; justify-content: center; gap: var(--s3);
  margin-top: var(--s4);
}
.section-carousel-dots { display: flex; gap: 7px; }
.section-carousel-dot {
  width: 8px; height: 8px; border-radius: 999px; background: var(--surface-3);
  border: 1px solid var(--line); padding: 0; transition: background var(--fast) var(--ease);
}
.section-carousel-dot.is-active { background: var(--gold); border-color: var(--gold); }
.section-carousel-admin { text-align: center; margin-top: var(--s3); }

/* The Brain module's own mini anatomy diagram, docked beside its lesson
   carousel -- 20% of the row on wide screens, stacked above the lesson
   content on narrow ones where there's no room for a side column. */
.section-carousel.has-brain-mini { display: flex; align-items: flex-start; gap: var(--s4); }
.section-carousel-brain-mini { flex: 0 0 20%; max-width: 180px; text-align: center; }
.section-carousel-brain-mini .brain-svg { width: 100%; height: auto; display: block; }
.brain-mini-label {
  margin-top: 6px; font-size: var(--t-xs); color: var(--text-muted);
  letter-spacing: .04em; text-transform: uppercase;
}
.section-carousel-main { flex: 1 1 0; min-width: 0; }
@media (max-width: 640px) {
  .section-carousel.has-brain-mini { flex-direction: column; align-items: center; }
  .section-carousel-brain-mini { flex: 0 0 auto; max-width: 140px; }
  .section-carousel-main { width: 100%; }
}

.section-admin-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--s2); }
.section-admin-row {
  display: flex; align-items: center; gap: var(--s3); padding: 8px 0;
  border-bottom: 1px solid var(--line); font-size: var(--t-sm);
}
.section-admin-row:last-child { border-bottom: none; }
.section-admin-num { color: var(--text-muted); font-size: var(--t-xs); flex: none; width: 16px; }
.section-admin-label { flex: 1; font-weight: 560; }
.section-admin-media { color: var(--text-muted); font-size: var(--t-xs); }

/* upgrade banner */
.upsell {
  border: 1px solid rgba(201,133,0,.35); background: rgba(201,133,0,.08);
  border-radius: var(--radius); padding: 18px; display: flex; gap: 16px;
  align-items: center; justify-content: space-between; flex-wrap: wrap;
  box-shadow: var(--shadow-card);
}
.upsell p { color: var(--text-secondary); font-size: .9rem; margin-top: 4px; max-width: 60ch; }

.empty { color: var(--text-muted); font-size: .9rem; padding: 20px 0; }
.skeleton { color: var(--text-muted); padding: 40px 0; text-align: center; }

/* the WELLth Wheel */
.wheel-question { margin-bottom: 14px; }
.wheel-question h3 { font-size: 1rem; margin: 0 0 6px; }
.wheel-track { height: 3px; background: var(--surface-3); border-radius: 999px; overflow: hidden; margin-bottom: 10px; }
.wheel-track i { display: block; height: 100%; width: 0; background: var(--gold); border-radius: 999px; transition: width .22s ease; }
.wheel-qmeta {
  display: flex; justify-content: space-between; font-size: .72rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 18px;
}
.wheel-qmeta b { color: var(--gold); font-weight: 700; }
.wheel-qtext { font-size: 1.12rem; line-height: 1.35; margin: 0 0 18px; }
.wheel-opt {
  display: block; width: 100%; text-align: left; padding: 13px 15px; margin-bottom: 9px;
  background: var(--surface-2); color: var(--text-primary); border: 1px solid var(--line);
  border-radius: 12px; font: inherit; font-size: .95rem; line-height: 1.4; cursor: pointer;
  transition: border-color .14s ease, background .14s ease;
}
.wheel-opt:hover { border-color: var(--gold); }
.wheel-opt.is-on { border-color: var(--gold); background: rgba(212, 175, 106, .10); }
.wheel-back {
  background: none; border: none; color: var(--text-muted); font: inherit;
  font-size: .85rem; cursor: pointer; padding: 8px 0 0;
}
.wheel-back:hover { color: var(--gold); }
.wheel-result-card { display: flex; justify-content: center; padding: 24px; }
.wheel-svg { width: 100%; max-width: 420px; height: auto; }
.wheel-score-label { font-size: .78rem; color: var(--text-muted); margin-bottom: 6px; }
.wheel-score-num { font-size: 1.4rem; font-weight: 700; }
.wheel-score-num span { font-size: .85rem; font-weight: 500; color: var(--text-muted); }

/* membership tiers */
.tier-card { display: flex; flex-direction: column; }
.tier-card.is-current { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold-soft); }
.tier-card h3 { font-size: 1.1rem; margin: 0; }
.tier-price { font-size: 1.7rem; font-weight: 700; margin: 8px 0 4px; }
.tier-features { list-style: none; margin: 16px 0; padding: 0; display: flex; flex-direction: column; gap: 9px; flex: 1; }
.tier-features li { font-size: .88rem; color: var(--text-secondary); padding-left: 22px; position: relative; }
.tier-features li::before { content: '✓'; position: absolute; left: 0; color: var(--good); font-weight: 700; }

/* triangle */
.triangle-wrap { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.triangle-legend { display: flex; flex-direction: column; gap: 10px; flex: 1; min-width: 190px; }
.legend-row { display: flex; align-items: center; gap: 9px; font-size: .87rem; color: var(--text-secondary); }
.legend-row .num { margin-left: auto; color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 600; }

.scrim { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 8; }
/* !important because .icon-btn further down sets display:inline-grid at
   equal specificity and wins on source order, which forced the ☰ onto
   desktop where the sidebar is already open and it appears to do
   nothing. It is not a dead button -- below 860px it is the only way to
   reach the nav at all, so the fix is to hide it properly, never to
   remove it. */
.only-mobile { display: none !important; }
/* Inverse of .only-mobile -- the collapse toggle is a desktop concept
   (reclaiming width on a wide screen); below 860px the sidebar is
   already off-canvas by default, controlled by the hamburger instead. */
.only-desktop { display: inline-flex; }

/* lesson / class content */
.lesson-hero {
  display: block; width: 100%; max-height: 340px; object-fit: cover;
  border-radius: var(--radius-sm); margin-bottom: 14px; background: var(--surface-2);
}
.video-embed {
  position: relative; width: 100%; padding-top: 56.25%;
  background: #000; border-radius: var(--radius-sm); overflow: hidden;
}
.video-embed iframe, .video-embed video {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
}
.lesson-content { margin-top: 16px; color: var(--text-secondary); font-size: 1.08rem; line-height: 1.75; }
.lesson-content p { margin-bottom: 16px; }
.lesson-content p:last-child { margin-bottom: 0; }
.lesson-overview { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.lesson-overview-label { font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--text-muted); margin-bottom: 4px; }

/* In-lesson index: every module in the current area, so a member can see
   where they are and jump to any other lesson without leaving the page. */
.lesson-index { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.lesson-index-item {
  display: flex; align-items: center; gap: 7px; padding: 7px 12px 7px 8px;
  background: var(--surface-1); border: 1px solid var(--line); border-radius: 999px;
  color: var(--text-secondary); font-size: .82rem; font-weight: 550; text-decoration: none;
  max-width: 220px; transition: all .15s ease;
}
.lesson-index-item:hover { border-color: rgba(212,175,106,.5); color: var(--text-primary); }
.lesson-index-item.is-current { background: var(--gold-wash); border-color: var(--gold); color: var(--text-primary); }
.lesson-index-item.is-locked { opacity: .5; cursor: not-allowed; }
.lesson-index-num {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 20px; height: 20px; border-radius: 999px; background: var(--surface-3);
  font-size: .72rem; font-weight: 700;
}
.lesson-index-item.is-current .lesson-index-num { background: var(--gold); color: var(--on-accent); }
.lesson-index-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 620px) {
  .lesson-index-item { max-width: none; }
  .lesson-index-title { max-width: 46vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* Glossary — collapsible key-terms reference per area, shown on the area
   page and every module page in it. */
.glossary {
  margin: 20px 0; background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 18px;
}
.glossary summary {
  cursor: pointer; font-weight: 600; color: var(--text-primary); list-style: none;
  display: flex; align-items: center; gap: 8px;
}
.glossary summary::-webkit-details-marker { display: none; }
.glossary summary::before { content: '▸'; color: var(--text-muted); transition: transform .15s ease; }
.glossary[open] summary::before { transform: rotate(90deg); }
.glossary-list { margin-top: 14px; display: grid; gap: 12px; }
.glossary-list dt { font-weight: 700; color: var(--text-primary); font-size: .94rem; }
.glossary-list dd { margin: 3px 0 0; color: var(--text-secondary); font-size: .88rem; line-height: 1.55; }

/* comments & reactions */
.comment-input {
  width: 100%; padding: 11px 13px; font: inherit; font-size: .92rem;
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  resize: vertical; margin-bottom: 8px;
}
.comment-input:focus { outline: 2px solid var(--series-1); outline-offset: 1px; border-color: transparent; }

/* ask your assistant */
.assistant-results { display: flex; flex-direction: column; gap: 2px; }
.assistant-result {
  display: flex; align-items: center; gap: 10px; padding: 10px 8px;
  border-radius: var(--radius-sm); color: var(--text-primary);
}
.assistant-result:hover { background: var(--surface-2); }
.assistant-result-kind {
  flex: none; font-size: .68rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
  padding: 3px 8px; border-radius: 999px; background: var(--surface-3); color: var(--text-secondary);
}
.assistant-result-title { font-weight: 560; font-size: .92rem; }
.assistant-result-sub { margin-left: auto; font-size: .8rem; color: var(--text-muted); flex: none; }
.assistant-answer {
  padding: 12px; border-radius: var(--radius-sm); background: var(--surface-2);
  border: 1px solid var(--gold-soft); margin-bottom: 10px;
}
.assistant-answer p { font-size: .92rem; line-height: 1.55; color: var(--text-primary); }
.assistant-answer-tier {
  display: inline-block; margin-top: 8px; font-size: .72rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--text-muted);
}
#assistant-form { display: flex; gap: 8px; align-items: flex-start; flex-wrap: wrap; }
#assistant-form .comment-input { margin-bottom: 0; flex: 1; min-width: 200px; }
#assistant-form .btn { flex: none; }
#assistant-form .vx-mic { width: 40px; height: 40px; --vx-fg: var(--gold-lit); }
.comment-list { margin-top: 18px; display: flex; flex-direction: column; gap: 14px; }
.comment { padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.comment:last-child { border-bottom: 0; padding-bottom: 0; }
.comment.is-reply {
  margin: 10px 0 0 28px; padding: 0 0 0 14px; border-bottom: 0; border-left: 2px solid var(--line);
}
.comment-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.comment-author { font-weight: 600; font-size: .88rem; }
.comment-time { font-size: .78rem; color: var(--text-muted); }
.comment-delete { margin-left: auto; font-size: .76rem; padding: 0; }
.comment-body { margin-top: 4px; font-size: .9rem; color: var(--text-secondary); line-height: 1.5; white-space: pre-wrap; }
.reaction-bar { display: flex; gap: 4px; margin-top: 8px; flex-wrap: wrap; }
.reaction {
  background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: 999px;
  padding: 3px 9px; font-size: .85rem; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
}
.reaction:hover { background: var(--surface-3); }
.reaction.is-mine { background: var(--gold-soft); border-color: var(--gold); }
.reaction-count { font-size: .74rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.reaction-more { font-weight: 700; color: var(--text-secondary); }
.emoji-picker {
  display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; padding: 10px;
  background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  max-height: 160px; overflow-y: auto; width: 100%;
}
.emoji-picker-item {
  background: none; border: 0; font-size: 1.1rem; line-height: 1; padding: 4px;
  cursor: pointer; border-radius: 6px;
}
.emoji-picker-item:hover { background: var(--surface-3); }
.comment-reply-toggle { margin-top: 6px; font-size: .8rem; }
.reply-form { margin-top: 10px; }

/* calendar */
.cal-toggle { display: flex; gap: 4px; background: var(--surface-2); padding: 3px; border-radius: 999px; }
.cal-toggle .linkbtn {
  padding: 5px 12px; border-radius: 999px; text-decoration: none; color: var(--text-secondary);
}
.cal-toggle .linkbtn.is-active { background: var(--surface-3); color: var(--text-primary); }
.cal-card.is-grid { display: flex; flex-direction: column; min-height: 0; }
.cal-nav {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; flex: none;
}
.cal-nav-label { display: flex; align-items: center; gap: 10px; }
.cal-nav-label strong { font-size: .95rem; }
.cal-nav .linkbtn { text-decoration: none; font-size: 1rem; padding: 4px 10px; }
.cal-today {
  font-size: .76rem; padding: 3px 9px; border: 1px solid var(--line-strong); border-radius: 999px;
}
.cal-day-list { max-height: min(58vh, 520px); overflow-y: auto; }
.cal-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; flex: 1; min-height: 0;
}
.cal-grid.is-month { height: min(62vh, 620px); }
.cal-grid.is-week { grid-template-rows: auto 1fr; height: min(46vh, 420px); }
.cal-dow {
  text-align: center; font-size: .76rem; color: var(--text-muted); padding-bottom: 6px;
  text-transform: uppercase; letter-spacing: .02em;
}
.cal-cell {
  min-height: 0; border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 6px; background: var(--surface-2); display: flex; flex-direction: column; gap: 3px; overflow: hidden;
}
.cal-cell.is-empty { border-color: transparent; background: none; }
.cal-cell.is-today { border-color: var(--series-1); }
.cal-daynum { font-size: .78rem; color: var(--text-muted); font-variant-numeric: tabular-nums; flex: none; }
.cal-cell.is-today .cal-daynum { color: var(--series-1); font-weight: 600; }
.cal-event {
  font-size: .74rem; color: var(--text-primary); background: var(--surface-3);
  border-radius: 5px; padding: 2px 5px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; flex: none;
}
.cal-more { font-size: .72rem; color: var(--text-muted); padding: 0 5px; flex: none; }

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; z-index: 9; width: 264px; left: 0; top: 0;
    transform: translateX(-100%); transition: transform .22s ease;
  }
  .app.nav-open .sidebar { transform: none; }
  /* Matches the !important above, which it has to override. */
  .only-mobile { display: inline-flex !important; }
  .only-desktop { display: none !important; }
  /* A collapsed state saved on a wide screen must not also shrink the
     off-canvas mobile sidebar down to a 64px sliver -- the grid column
     rule above already overrides it, but the sidebar's own width is set
     directly, so it needs the same override here. */
  .app.sidebar-collapsed .sidebar { width: 264px; padding: 20px 14px; align-items: stretch; }
  .app.sidebar-collapsed .brand { flex-direction: row; justify-content: flex-start; }
  .app.sidebar-collapsed .brand-text,
  .app.sidebar-collapsed .nav,
  .app.sidebar-collapsed .nav-crest,
  .app.sidebar-collapsed .side-foot { display: revert; }
  .view { padding: 18px 16px 40px; }
  .topbar { padding: 12px 16px; }
  .cal-toggle { flex-wrap: wrap; }
  .cal-grid.is-month { height: min(56vh, 460px); }
  .cal-grid.is-week { height: min(40vh, 320px); }
  .cal-event { font-size: 0; padding: 0; height: 6px; border-radius: 3px; }
  .cal-more { font-size: .68rem; }
}

/* install-as-app banner */
.install-banner {
  position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 20;
  max-width: 460px; margin: 0 auto;
  display: flex; align-items: center; gap: 12px;
  background: var(--surface-1); border: 1px solid var(--gold-soft);
  border-radius: var(--radius); padding: 12px 14px;
  box-shadow: var(--shadow-lift);
}
.install-banner img { border-radius: 8px; flex: none; }
.install-banner-body { flex: 1; min-width: 0; }
.install-banner-title { font-weight: 640; font-size: .92rem; }
.install-banner-text { font-size: .8rem; color: var(--text-secondary); margin-top: 2px; }
.install-banner .btn { flex: none; }
.install-banner .icon-btn { flex: none; font-size: .9rem; padding: 4px 6px; }

@media (max-width: 520px) {
  .install-banner { flex-wrap: wrap; }
  .install-banner-body { order: 1; flex-basis: 100%; }
}

/* ---------------------------------------------------------------
   Plate tracker
---------------------------------------------------------------- */
.pill.warn { background: rgba(201,133,0,.16); color: #e0a93c; }

.plate-day { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.plate-day strong { font-size: 1.05rem; }

.plate-hero { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.plate-hero-side { flex: 1; min-width: 190px; }
.plate-ring { flex: none; }
.plate-ring-score { font-size: 34px; font-weight: 700; font-variant-numeric: tabular-nums; }
.plate-ring-label { font-size: 10px; fill: var(--text-muted); text-transform: uppercase; letter-spacing: .09em; }
.plate-target-note { margin-top: 10px; font-size: .8rem; color: var(--text-muted); }

.plate-legend { display: grid; gap: 7px; }
.plate-leg { display: flex; align-items: center; gap: 8px; font-size: .88rem; }
.plate-dot { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.plate-leg-label { flex: 1; color: var(--text-secondary); }
.plate-leg-num { font-variant-numeric: tabular-nums; font-weight: 620; }
.plate-leg-gap { font-size: .78rem; color: var(--text-muted); min-width: 56px; text-align: right; }

.plate-coach {
  margin: 12px 0; padding: 11px 13px; font-size: .9rem; line-height: 1.5;
  background: linear-gradient(180deg, rgba(212,175,55,.08), transparent);
  border-left: 2px solid var(--gold); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.week-strip { display: flex; gap: 6px; margin-bottom: 12px; }
.week-day {
  flex: 1; background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  padding: 8px 0; display: grid; gap: 5px; justify-items: center; cursor: pointer; font: inherit;
}
.week-day:hover { border-color: var(--line); }
.week-day.is-active { border-color: var(--line-strong); background: var(--surface-2); }
.week-dot { width: 13px; height: 13px; border-radius: 50%; background: var(--surface-3); }
.week-letter { font-size: .7rem; color: var(--text-muted); text-transform: uppercase; }

.macro-row { display: flex; gap: 8px; margin: 12px 0 6px; flex-wrap: wrap; }
.macro { flex: 1; min-width: 62px; background: var(--surface-2); border-radius: var(--radius-sm); padding: 9px 4px; text-align: center; }
.macro-num { display: block; font-weight: 640; font-variant-numeric: tabular-nums; }
.macro-label { display: block; font-size: .7rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; margin-top: 2px; }

.log-card { margin-top: 18px; }
.log-actions { margin-top: 14px; }
.log-photo-row { display: flex; gap: 10px; }
.log-photo-row .btn { flex: 1; }
.log-photo, .log-photo-camera { display: block; text-align: center; cursor: pointer; }
.log-or { text-align: center; font-size: .8rem; color: var(--text-muted); margin: 12px 0; }

/* in-page camera capture */
.camera-overlay {
  position: fixed; inset: 0; z-index: 50; background: rgba(0,0,0,.82);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.camera-frame {
  width: 100%; max-width: 480px; background: var(--surface-1);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-lift);
}
.camera-frame video { display: block; width: 100%; max-height: 70vh; background: #000; object-fit: cover; }
.camera-controls { display: flex; gap: 10px; padding: 14px; }
.camera-controls .btn { flex: 1; }
.log-text { display: flex; gap: 8px; }
.log-text input {
  flex: 1; padding: 11px 13px; font: inherit; font-size: .92rem;
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
}
.log-text .btn { flex: none; }

.draft-card { margin-top: 18px; border-color: var(--gold-soft); }
.draft-body { display: flex; gap: 18px; flex-wrap: wrap; }
.draft-photo { width: 200px; border-radius: var(--radius-sm); object-fit: cover; align-self: flex-start; }
.draft-fields { flex: 1; min-width: 260px; }
.draft-total { margin: 4px 0 14px; font-variant-numeric: tabular-nums; }
.draft-total.is-off { color: var(--warn); }
.draft-actions { display: flex; align-items: center; gap: 14px; margin-top: 6px; }

.slot-row { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.slot { text-transform: capitalize; }
.slot.is-active { border-color: var(--series-1); color: #fff; background: rgba(57,135,229,.18); }

.slider-row { display: grid; grid-template-columns: 1fr 140px 46px; align-items: center; gap: 12px; margin-bottom: 12px; }
.slider-label { display: flex; align-items: center; gap: 8px; font-size: .9rem; }
.slider-label i { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.slider-label em { font-style: normal; font-size: .75rem; color: var(--text-muted); }
.slider-row output { font-variant-numeric: tabular-nums; text-align: right; font-size: .88rem; }
.slider-row input[type=range] { accent-color: var(--series-1); width: 100%; }

.meal { display: flex; gap: 14px; align-items: flex-start; background: var(--surface-1);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; margin-bottom: 10px; }
.meal-photo { width: 72px; height: 72px; border-radius: var(--radius-sm); object-fit: cover; flex: none; }
.meal-photo-blank { background: var(--surface-3); }
.meal-body { flex: 1; min-width: 0; }
.meal-head { display: flex; align-items: baseline; gap: 9px; margin-bottom: 8px; }
.meal-slot { font-size: .74rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }
.meal-bar { display: flex; height: 8px; border-radius: 999px; overflow: hidden; background: var(--surface-3); }
.meal-bar i { display: block; height: 100%; }
.meal-coach { font-size: .84rem; color: var(--text-secondary); margin-top: 8px; }
.meal-side { flex: none; text-align: right; }
.meal-score { font-size: 1.5rem; font-weight: 680; font-variant-numeric: tabular-nums; display: block; }

.roster-row { text-decoration: none; color: inherit; }
.roster-row:hover { border-color: var(--line-strong); }

@media (max-width: 620px) {
  .plate-hero { justify-content: center; }
  .slider-row { grid-template-columns: 1fr 96px 40px; gap: 8px; }
  .draft-photo { width: 100%; }
  .log-photo-row { flex-direction: column; }
}

/* ===============================================================
   DESIGN SYSTEM v2

   Everything below refines what the classes above already render, so
   the whole app moves at once rather than one page at a time. New
   components (tab bar, sheets, set rows, timers) come after.
   =============================================================== */

/* ---------- base ---------- */
body {
  font-size: 15px;
  /* Two barely-there washes so large dark areas aren't dead flat. */
  background:
    radial-gradient(1200px 600px at 78% -8%, rgba(74,143,240,.05), transparent 60%),
    radial-gradient(900px 500px at 12% 104%, rgba(212,175,55,.045), transparent 62%),
    var(--bg);
  background-attachment: fixed;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}
::selection { background: rgba(212,175,55,.26); }
h1 { font-size: var(--t-xl); letter-spacing: -.022em; }
h2 { font-size: var(--t-md); letter-spacing: -.012em; }
h3 { font-size: var(--t-base); letter-spacing: -.008em; }

/* One focus ring for the whole app, and only for keyboards. */
:focus-visible { outline: 2px solid var(--series-1); outline-offset: 2px; border-radius: 6px; }
:focus:not(:focus-visible) { outline: none; }

* { scrollbar-width: thin; scrollbar-color: var(--surface-3) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 999px; }
*::-webkit-scrollbar-thumb:hover { background: var(--surface-4); }
*::-webkit-scrollbar-track { background: transparent; }

.num { font-variant-numeric: tabular-nums; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 38px; padding: 9px 17px;
  border: 1px solid var(--line-strong);
  background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
  box-shadow: inset 0 1px 0 var(--edge-light);
  font-weight: 570; letter-spacing: -.005em;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease), opacity var(--fast);
}
.btn:hover { background: linear-gradient(180deg, var(--surface-4), var(--surface-3)); border-color: rgba(255,255,255,.2); }
.btn:active { transform: scale(.975); }
.btn-primary {
  background: linear-gradient(180deg, var(--primary-lit), var(--primary));
  border-color: transparent; color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 4px 14px -6px rgba(74,143,240,.7);
}
.btn-primary:hover { background: linear-gradient(180deg, var(--primary-lit-hover), var(--primary-hover)); border-color: transparent; }
.btn-gold {
  background: linear-gradient(180deg, var(--gold-lit), var(--gold) 55%, var(--gold-deep));
  border-color: transparent; color: var(--on-accent); font-weight: 680;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 4px 16px -6px rgba(212,175,55,.6);
}
.btn-ghost { background: transparent; border-color: var(--line); box-shadow: none; }
.btn-ghost:hover { background: var(--surface-2); }
.btn-danger { color: var(--bad); border-color: rgba(226,84,74,.35); background: rgba(226,84,74,.08); box-shadow: none; }
.btn-block { width: 100%; min-height: 46px; padding: 12px 18px; font-size: var(--t-base); }
.btn-sm { min-height: 32px; padding: 6px 13px; font-size: var(--t-sm); }
.btn-lg { min-height: 52px; padding: 14px 24px; font-size: var(--t-md); border-radius: 999px; }
.icon-btn {
  min-width: 40px; min-height: 40px; display: inline-grid; place-items: center;
  border-radius: 11px; transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.icon-btn:hover { background: var(--surface-2); color: var(--text-primary); }
.icon-btn:active { transform: scale(.94); }
.linkbtn { transition: color var(--fast) var(--ease); }

/* ---------- fields ---------- */
.field > span, .field-label {
  display: block; font-size: var(--t-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-muted); margin-bottom: 7px;
}
.field input, .field select, .field textarea {
  min-height: 46px; padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--surface-2); border-color: var(--line);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.25);
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.field input::placeholder, .field textarea::placeholder { color: var(--text-faint); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--series-1); background: var(--surface-3);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.25), 0 0 0 3px rgba(74,143,240,.18);
}
.field textarea { min-height: 72px; resize: vertical; }

/* A password field with a trailing show/hide toggle. .field-pw wraps
   just the input (not the whole .field label), so .field input's own
   width/padding/border rules above still apply unchanged everywhere
   else that uses .field -- this only adds room on the right for the
   button and positions it over that room. */
.field-pw { position: relative; }
.field-pw input { padding-right: 44px; }
.field-pw-toggle {
  position: absolute; top: 50%; right: 5px; transform: translateY(-50%);
  min-width: 34px; min-height: 34px; display: inline-grid; place-items: center;
  background: none; border: 0; border-radius: 8px; color: var(--text-muted);
  cursor: pointer; transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.field-pw-toggle:hover { background: var(--surface-3); color: var(--text-primary); }
.field-pw-toggle:active { transform: translateY(-50%) scale(.94); }

/* ---------- cards ---------- */
.card {
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface-1) 52%);
  border-color: var(--line);
  border-radius: var(--radius);
  padding: var(--s5);
  box-shadow: inset 0 1px 0 var(--edge-light), var(--shadow-card);
}
.card-hd h3 { font-size: var(--t-base); }
.card p.sub, .sub { color: var(--text-secondary); font-size: var(--t-sm); line-height: 1.55; }
.card-tight { padding: var(--s4); }
.card-flush { padding: 0; overflow: hidden; }

/* ---------- stat tiles ---------- */
.kpi {
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1) 58%);
  border-radius: var(--radius); padding: var(--s4) var(--s5);
  box-shadow: inset 0 1px 0 var(--edge-light), var(--shadow-card);
  transition: transform var(--med) var(--ease), border-color var(--med) var(--ease);
}
.kpi:hover { transform: translateY(-1px); border-color: var(--line-strong); }
.kpi .label { font-size: var(--t-xs); letter-spacing: .09em; font-weight: 640; }
.kpi .value { font-size: var(--t-2xl); font-weight: 700; letter-spacing: -.035em; line-height: 1.05; }
.kpi .value small { font-size: var(--t-md); font-weight: 560; color: var(--text-muted); letter-spacing: 0; }
.kpi .foot { font-size: var(--t-sm); }
.kpi-hero { background: linear-gradient(180deg, var(--gold-wash), var(--surface-1) 58%); border-color: var(--gold-soft); }
.kpi-hero .value { font-size: var(--t-3xl); }

/* ---------- shell ---------- */
.topbar {
  padding: 13px var(--s6);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line);
}
.crumb { font-weight: 560; color: var(--text-primary); font-size: var(--t-base); letter-spacing: -.01em; }
.who { font-size: var(--t-sm); }
.sidebar { background: linear-gradient(180deg, var(--bg-elev), var(--bg)); padding: var(--s5) var(--s3); }
.nav-item { padding: 10px 11px; font-size: var(--t-base); font-weight: 530; border-radius: var(--radius-xs); }
.nav-item.is-active { background: linear-gradient(90deg, var(--gold-wash), var(--surface-2)); }
.view { padding: var(--s6); }

/* ---------- section headers ---------- */
.section-head h2 { font-size: var(--t-md); }
.section { margin: var(--s7) 0; }

/* ---------- pills ---------- */
.pill { font-size: var(--t-xs); padding: 4px 9px; letter-spacing: .05em; }
.pill.good { background: rgba(31,174,125,.16); color: #4fd3a5; }
.pill.warn { background: rgba(213,147,0,.16); color: #e6b23f; }
.pill.gold { background: rgba(212,175,55,.16); color: var(--gold-lit); }

/* ===============================================================
   Bottom tab bar — mobile only

   Five destinations, thumb height, with the log action raised into the
   middle. This is the single thing that stops a web app reading as a
   website on a phone.
   =============================================================== */
.tabbar { display: none; }
.tab-ico { display: block; width: 23px; height: 23px; }

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .view { padding: var(--s4) var(--s4) calc(var(--tabbar-h) + 34px + env(safe-area-inset-bottom)); }
  .topbar { padding: 11px var(--s4); }

  .tabbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    display: grid; grid-template-columns: repeat(5, 1fr);
    align-items: center;
    height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    background: color-mix(in srgb, var(--bg-elev) 88%, transparent);
    backdrop-filter: saturate(180%) blur(22px);
    -webkit-backdrop-filter: saturate(180%) blur(22px);
    border-top: 1px solid var(--line);
  }
  .tab-item {
    display: grid; justify-items: center; gap: 3px;
    padding: 7px 0; color: var(--text-muted);
    font-size: 10px; font-weight: 620; letter-spacing: .03em; text-transform: uppercase;
    transition: color var(--fast) var(--ease);
    -webkit-tap-highlight-color: transparent;
  }
  .tab-item:active { transform: scale(.94); }
  .tab-item.is-active { color: var(--gold); }
  .tab-item.is-active .tab-ico { filter: drop-shadow(0 0 10px rgba(212,175,55,.45)); }

  .tab-fab {
    justify-self: center;
    width: 54px; height: 54px; margin-top: -22px;
    border: 0; border-radius: 50%; cursor: pointer;
    background: linear-gradient(180deg, var(--gold-lit), var(--gold) 52%, var(--gold-deep));
    color: var(--on-accent);
    display: grid; place-items: center;
    box-shadow: 0 6px 20px -6px rgba(212,175,55,.75), inset 0 1px 0 rgba(255,255,255,.45);
    transition: transform var(--fast) var(--ease);
  }
  .tab-fab:active { transform: scale(.9); }
  .tab-fab svg { width: 26px; height: 26px; }
}

/* ===============================================================
   Sheet — the bottom sheet on mobile, a centred dialog on desktop.
   Used by quick-log, the exercise picker and any confirm step.
   =============================================================== */
.sheet-scrim {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(0,0,0,.6); backdrop-filter: blur(3px);
  animation: fade var(--med) var(--ease);
}
.sheet {
  position: fixed; z-index: 41; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 32px)); max-height: 86vh; overflow-y: auto;
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1) 40%);
  border: 1px solid var(--line-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: var(--s5);
  animation: pop var(--med) var(--ease);
}
.sheet-grab { display: none; }
.sheet-hd { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: var(--s4); }
.sheet-hd h3 { font-size: var(--t-md); }
.sheet-actions { display: grid; gap: var(--s2); }
.sheet-action {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; text-align: left; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 14px 15px; color: inherit; font: inherit;
  transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.sheet-action:hover { background: var(--surface-3); }
.sheet-action:active { transform: scale(.985); }
.sheet-action-ico {
  flex: none; width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center;
  background: var(--surface-3); color: var(--gold);
}
.sheet-action-body { flex: 1; min-width: 0; }
.sheet-action-title { font-weight: 600; font-size: var(--t-base); }
.sheet-action-sub { font-size: var(--t-sm); color: var(--text-muted); margin-top: 1px; }

@keyframes fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes pop { from { opacity: 0; transform: translate(-50%, calc(-50% + 12px)) scale(.97) } to { opacity: 1 } }
@keyframes slide-up { from { transform: translateY(100%) } to { transform: translateY(0) } }

@media (max-width: 620px) {
  .sheet {
    left: 0; right: 0; top: auto; bottom: 0; width: 100%;
    transform: none; max-height: 88vh;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-bottom: 0;
    padding: var(--s3) var(--s4) calc(var(--s5) + env(safe-area-inset-bottom));
    animation: slide-up var(--med) var(--ease);
  }
  .sheet-grab {
    display: block; width: 38px; height: 4px; border-radius: 999px;
    background: var(--surface-4); margin: 6px auto var(--s4);
  }
}

/* ---------- segmented control ---------- */
.seg {
  display: inline-flex; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px; gap: 2px; width: 100%;
}
.seg button {
  flex: 1; border: 0; background: none; color: var(--text-secondary);
  font: inherit; font-size: var(--t-sm); font-weight: 580;
  padding: 8px 12px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.seg button.is-active {
  background: linear-gradient(180deg, var(--surface-4), var(--surface-3));
  color: var(--text-primary); box-shadow: inset 0 1px 0 var(--edge-light);
}

/* ---------- chips ---------- */
.chip-row { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: var(--s4); }
.slot.is-active {
  border-color: var(--gold-soft); color: var(--gold-lit);
  background: linear-gradient(180deg, rgba(212,175,55,.2), rgba(212,175,55,.08));
}

/* ---------- search ---------- */
.search { position: relative; margin-bottom: var(--s3); }
.search input {
  width: 100%; min-height: 46px; padding: 12px 14px 12px 42px; font: inherit; font-size: var(--t-base);
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--line); border-radius: 999px;
}
.search input:focus { outline: none; border-color: var(--series-1); box-shadow: 0 0 0 3px rgba(74,143,240,.18); }
.search svg { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); width: 17px; height: 17px; color: var(--text-muted); }

/* ---------- list rows ---------- */
.row-list { display: grid; gap: 1px; background: var(--line); border-radius: var(--radius); overflow: hidden; }
.row-item {
  display: flex; align-items: center; gap: var(--s3);
  background: var(--surface-1); padding: 13px 15px; cursor: pointer;
  color: inherit; font: inherit; text-align: left; border: 0; width: 100%;
  transition: background var(--fast) var(--ease);
}
.row-item:hover { background: var(--surface-2); }
/* The edit target inside a row that also carries its own quick-delete
   icon (finance.js's Manage accounts list) -- same flex/gap as
   .row-item itself, just scoped one level in so the trash button can
   sit beside it without being nested inside another button. */
.row-item-main {
  display: flex; align-items: center; gap: var(--s3); flex: 1; min-width: 0;
  background: none; border: 0; color: inherit; font: inherit; text-align: left;
  cursor: pointer; padding: 0;
}
.row-item-body { flex: 1; min-width: 0; }
.row-item-title { font-weight: 560; font-size: var(--t-base); }
.row-item-sub { font-size: var(--t-sm); color: var(--text-muted); margin-top: 1px; }

/* ---------- skeleton ---------- */
.skeleton, .sk {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: shimmer 1.4s infinite linear;
  border-radius: var(--radius-sm); color: transparent;
}
@keyframes shimmer { from { background-position: 200% 0 } to { background-position: -200% 0 } }

/* ---------- toast ---------- */
.toast {
  position: fixed; z-index: 60; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-h) + 22px + env(safe-area-inset-bottom));
  background: var(--surface-4); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 11px 20px; font-size: var(--t-sm); font-weight: 560;
  box-shadow: var(--shadow-pop); animation: pop var(--med) var(--ease);
  display: flex; align-items: center; gap: 9px; max-width: calc(100vw - 32px);
}
.toast.is-pr { background: linear-gradient(180deg, var(--gold-lit), var(--gold)); color: var(--on-accent); border-color: transparent; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ===============================================================
   Training — the set logger

   The grid is the screen someone stares at between sets, one-handed,
   out of breath. Numbers are big, targets are 44px, and last session's
   numbers sit in the row so the decision is made without navigating.
   =============================================================== */
.ex-block { margin-bottom: var(--s4); }
.ex-head {
  display: flex; align-items: center; gap: var(--s3);
  padding: 12px 14px; border-radius: var(--radius) var(--radius) 0 0;
  background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
  border: 1px solid var(--line); border-bottom: 0;
}
.ex-name { flex: 1; min-width: 0; font-weight: 620; font-size: var(--t-base); }
.ex-sub { font-size: var(--t-xs); color: var(--text-muted); margin-top: 1px; font-weight: 500; text-transform: none; letter-spacing: 0; }

.set-grid {
  border: 1px solid var(--line); border-radius: 0 0 var(--radius) var(--radius);
  background: var(--surface-1); overflow: hidden;
}
.set-row {
  display: grid;
  grid-template-columns: 38px 1fr 78px 68px 46px;
  align-items: center; gap: var(--s2);
  padding: 7px 12px; border-top: 1px solid var(--line);
  transition: background var(--fast) var(--ease);
}
.set-row:first-child { border-top: 0; }
.set-row.is-head {
  font-size: 10px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--text-faint); font-weight: 680; padding: 8px 12px;
}
.set-row.is-done { background: rgba(31,174,125,.07); }
.set-row.is-warmup .set-no { color: var(--warn); }
.set-no { font-weight: 680; font-variant-numeric: tabular-nums; color: var(--text-muted); text-align: center; }
.set-prev {
  font-size: var(--t-sm); color: var(--text-faint); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.set-row input {
  width: 100%; min-height: 40px; text-align: center;
  font: inherit; font-size: var(--t-md); font-weight: 620; font-variant-numeric: tabular-nums;
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--line); border-radius: var(--radius-xs);
  -moz-appearance: textfield;
}
.set-row input::-webkit-outer-spin-button,
.set-row input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.set-row input:focus { outline: none; border-color: var(--series-1); background: var(--surface-3); }
.set-row input::placeholder { color: var(--text-faint); font-weight: 500; }
.set-check {
  width: 40px; height: 40px; border-radius: 11px; cursor: pointer;
  border: 1.5px solid var(--line-strong); background: var(--surface-2);
  display: grid; place-items: center; color: var(--text-faint);
  transition: background var(--fast) var(--ease), transform var(--fast) var(--ease), color var(--fast) var(--ease);
}
.set-check:active { transform: scale(.9); }
.set-check.is-done { background: var(--good); border-color: var(--good); color: #04160f; }
.set-check svg { width: 18px; height: 18px; }
.set-add {
  width: 100%; border: 0; border-top: 1px solid var(--line); background: var(--surface-2);
  color: var(--text-secondary); font: inherit; font-size: var(--t-sm); font-weight: 580;
  padding: 11px; cursor: pointer; transition: background var(--fast) var(--ease);
}
.set-add:hover { background: var(--surface-3); color: var(--text-primary); }

/* rest timer, docked above the tab bar while it runs */
.rest-timer {
  position: fixed; z-index: 35; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-h) + 14px + env(safe-area-inset-bottom));
  width: min(420px, calc(100vw - 28px));
  background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-pop); padding: 11px 15px;
  display: flex; align-items: center; gap: var(--s3);
  animation: pop var(--med) var(--ease);
}
.rest-time { font-size: var(--t-lg); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.02em; min-width: 62px; }
.rest-bar { flex: 1; height: 5px; background: var(--surface-4); border-radius: 999px; overflow: hidden; }
.rest-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--gold), var(--gold-lit)); border-radius: 999px; transition: width 1s linear; }
.rest-timer.is-done .rest-bar i { background: var(--good); }

/* session header while a workout is open */
.live-bar {
  display: flex; align-items: center; gap: var(--s3);
  background: linear-gradient(180deg, var(--gold-wash), transparent);
  border: 1px solid var(--gold-soft); border-radius: var(--radius);
  padding: 13px 16px; margin-bottom: var(--s4);
}
.live-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--good); animation: pulse 2s infinite; }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }
.live-elapsed { font-variant-numeric: tabular-nums; font-weight: 640; font-size: var(--t-md); }

/* PR badge */
.pr-badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--t-xs); font-weight: 680; letter-spacing: .04em;
  color: var(--on-accent); background: linear-gradient(180deg, var(--gold-lit), var(--gold));
  padding: 3px 9px; border-radius: 999px;
}

/* volume trend */
.trend { display: flex; align-items: flex-end; gap: 6px; height: 108px; margin-top: var(--s2); }
.trend-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 7px; height: 100%; }
.trend-bar {
  width: 100%; min-height: 4px; border-radius: 6px 6px 3px 3px;
  background: linear-gradient(180deg, var(--series-1), rgba(74,143,240,.28));
  transition: height var(--med) var(--ease);
}
.trend-col:last-child .trend-bar { background: linear-gradient(180deg, var(--gold-lit), var(--gold-soft)); }
.trend-label { font-size: 10px; color: var(--text-faint); font-weight: 600; }

/* plan cards */
.plan-days { display: grid; gap: var(--s2); margin-top: var(--s3); }
.plan-day { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 13px 15px; }
.plan-day-head { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; margin-bottom: 7px; }
.plan-day-head strong { min-width: 34px; }
.plan-list { margin: 0; padding-left: 17px; display: grid; gap: 4px; }
.plan-list li { font-size: var(--t-sm); color: var(--text-secondary); }
.plan-list em { font-style: normal; color: var(--text-faint); font-size: var(--t-xs); display: block; }

.kind-chip { flex: none; width: 4px; align-self: stretch; border-radius: 999px; min-height: 44px; }
.kind-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: var(--s4); }

/* ---------- plate v2 ---------- */
.plate-hero { gap: var(--s6); padding: var(--s6); }
.plate-ring-score { font-size: 38px; font-weight: 740; letter-spacing: -.03em; }
.plate-coach { font-size: var(--t-base); }
.meal { transition: border-color var(--fast) var(--ease); }
.meal:hover { border-color: var(--line-strong); }
.meal-score small { font-size: var(--t-sm); font-weight: 560; color: var(--text-muted); }

@media (max-width: 620px) {
  .set-row { grid-template-columns: 30px 1fr 70px 60px 42px; gap: 5px; padding: 6px 9px; }
  .set-row input { min-height: 38px; font-size: var(--t-base); }
  .set-check { width: 38px; height: 38px; }
  .plate-hero { padding: var(--s4); gap: var(--s4); }
}

/* ---------- mobile density fixes ---------- */
@media (max-width: 860px) {
  /* Two stat tiles across on a phone. At 170px minimum they fall to one
     per row at 375px wide, which wastes half the screen on whitespace. */
  .kpis { grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 10px; }
  .kpi { padding: 13px 14px; }
  .kpi .value { font-size: var(--t-xl); }
  .kpi-hero .value { font-size: var(--t-2xl); }
  .grid { gap: 12px; }
  .card { padding: var(--s4); }
  h1 { font-size: var(--t-lg); }

  /* The More tab is a <button>, so it arrives with the UA's own
     background and border. Match it to the anchors beside it. */
  button.tab-item { background: none; border: 0; font-family: inherit; cursor: pointer; }
}

/* The set number and the header labels are buttons/spans sitting in the
   same grid as the inputs, so they need the UA chrome removed and their
   own columns centred over what they label. */
.set-no {
  background: none; border: 0; font: inherit; cursor: pointer;
  padding: 0; line-height: 1; border-radius: 8px;
  transition: color var(--fast) var(--ease);
}
.set-no:hover { color: var(--text-secondary); }
.set-row.is-head span:nth-child(3),
.set-row.is-head span:nth-child(4) { text-align: center; }
.set-row.is-head span:nth-child(1) { text-align: center; }

/* Sheet action rows are built from spans (a <button> can't contain block
   elements in valid HTML), so they need their own display. */
.sheet-action-body, .sheet-action-title, .sheet-action-sub { display: block; }

/* ---------------------------------------------------------------
   Finance dashboard — net worth hero + bucket breakdown.
---------------------------------------------------------------- */
.finance-hero {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; padding-bottom: 18px; margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.finance-networth { font-size: 2.1rem; font-weight: 650; letter-spacing: -.01em; }
.finance-delta { font-size: .85rem; color: var(--text-muted); margin-top: 4px; }
.finance-delta.is-up { color: var(--good); }
.finance-delta.is-down { color: var(--bad); }
.finance-spark { display: block; }
.finance-buckets {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px;
}
.finance-bucket {
  background: var(--surface-2); border-radius: var(--radius); padding: 14px;
}
.finance-bucket-label { font-size: .78rem; color: var(--text-muted); margin-bottom: 6px; }
.finance-bucket-value { font-size: 1.15rem; font-weight: 600; }
.finance-bucket-value.is-debt { color: var(--bad); }
.finance-bucket-count { font-size: .76rem; color: var(--text-faint); margin-top: 2px; }
.finance-note { font-size: .78rem; color: var(--text-faint); margin-top: 16px; }
.tax-donut-wrap { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.tax-donut { flex-shrink: 0; }
.tax-legend { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 10px; }
.tax-legend-row { display: flex; align-items: flex-start; gap: 10px; }
.tax-swatch { width: 12px; height: 12px; border-radius: 3px; margin-top: 3px; flex-shrink: 0; }
.tax-legend-label { flex: 1; font-size: .88rem; font-weight: 560; }
.tax-legend-amt { font-size: .92rem; font-weight: 600; white-space: nowrap; }
.finance-form-actions { display: flex; gap: 10px; margin-top: 6px; }
.finance-add-btn { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 14px; }
.field-hint { font-size: .78rem; color: var(--text-faint); margin: -8px 0 14px; }

@media (max-width: 620px) {
  .finance-buckets { grid-template-columns: repeat(2, 1fr); }
  .finance-hero { flex-direction: column; align-items: flex-start; }
}

/* ---------------------------------------------------------------
   The Interactive Brain
---------------------------------------------------------------- */
/* Diagram column widened from 1.3fr to 2fr (2026-10-26, Pete's call: "make
   the brain image bigger"). The panel still has room for the four fields
   because they are stacked paragraphs, not a grid. */
.brain-layout { display: grid; gap: var(--s5); grid-template-columns: 2fr 1fr; align-items: start; }
@media (max-width: 1100px) { .brain-layout { grid-template-columns: 1.5fr 1fr; } }
@media (max-width: 860px)  { .brain-layout { grid-template-columns: 1fr; } }
.brain-diagram-wrap {
  background: #05070c; border: 1px solid var(--gold-soft); border-radius: var(--radius);
  padding: var(--s3);
}
/* "Show all structures" -- names the secondary anatomy without promoting it
   to a seventh teaching region. Off by default; see brain.js. */
.brain-toggle-row { display: flex; justify-content: center; margin-top: var(--s3); }
.brain-toggle {
  border-radius: 999px; padding: 6px 16px; font-size: .72rem; font-weight: 600;
  letter-spacing: .02em; cursor: pointer; transition: background .15s ease, border-color .15s ease, color .15s ease;
  background: transparent; border: 1px solid var(--gold-soft); color: var(--gold);
}
.brain-toggle:hover { border-color: var(--gold); background: rgba(190,158,68,.1); }
.brain-toggle.is-active { background: var(--gold); border-color: var(--gold); color: #090909; }

/* "Which system has the wheel" -- the state identifiers. Cards rather than
   plain buttons because each carries a one-line description, not just a
   name; the dot ties each state to the colour its structures light up in. */
.brain-state-grid {
  display: grid; gap: var(--s3); margin-bottom: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.brain-state-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  text-align: left; cursor: pointer; padding: 14px; border-radius: var(--radius);
  background: var(--surface-1); border: 1px solid var(--line); color: inherit;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.brain-state-btn:hover { border-color: var(--gold); transform: translateY(-1px); box-shadow: var(--shadow-card); }
.brain-state-btn.is-active { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold-soft); }
.brain-state-name { font-weight: 600; font-size: .95rem; }
.brain-state-line { font-size: .82rem; line-height: 1.45; opacity: .72; }
.brain-state-card { margin-top: var(--s3); }
.brain-state-card h3 { margin: 0; font-size: 1.15rem; }
.brain-tells { margin: 8px 0 0; padding-left: 18px; }
.brain-tells li { font-size: .9rem; line-height: 1.6; opacity: .82; margin-bottom: 5px; }

/* The streetlight. Appears under the six region tiles when a state is
   picked and lights the level of the brain that state runs on. Lamps are
   stacked like a real signal head, dark until lit -- an unlit lamp has to
   stay visible, because "the other one is off" is half the information. */
.brain-streetlight {
  margin-top: var(--s4); padding: 14px 16px; border-radius: var(--radius);
  background: #0b0e16; border: 1px solid var(--line);
}
.brain-lamp-stack { display: flex; flex-direction: column; gap: 9px; }
.brain-lamp-row { display: flex; align-items: center; gap: 11px; }
.brain-lamp {
  width: 15px; height: 15px; border-radius: 999px; flex-shrink: 0;
  background: #1b2030; border: 1px solid rgba(255,255,255,.1);
  transition: background .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.brain-lamp-label {
  font-size: .82rem; font-weight: 600; letter-spacing: .01em;
  color: var(--text-faint); transition: color .25s ease;
}
.brain-lamp-row.is-on .brain-lamp-higher {
  background: #8fd49a; border-color: #b6e6bd;
  box-shadow: 0 0 10px 1px rgba(143,212,154,.55), inset 0 0 4px rgba(255,255,255,.45);
}
.brain-lamp-row.is-on .brain-lamp-lower {
  background: #e0758f; border-color: #f2a5b6;
  box-shadow: 0 0 10px 1px rgba(224,117,143,.55), inset 0 0 4px rgba(255,255,255,.45);
}
.brain-lamp-row.is-on .brain-lamp-label { color: var(--text-primary); }
.brain-lamp-note {
  margin: 12px 0 0; font-size: .82rem; line-height: 1.55; color: var(--text-muted);
}
@media (prefers-reduced-motion: reduce) {
  .brain-lamp, .brain-lamp-label { transition: none; }
}
.brain-svg { width: 100%; height: auto; display: block; }
.brain-hotspot { cursor: pointer; }
.brain-hotspot path, .brain-hotspot ellipse { transition: all .2s ease; }
.brain-caption { margin-top: var(--s3); font-size: .8rem; line-height: 1.5; color: rgba(255,255,255,.7); text-align: center; }
.brain-panel-col { display: flex; flex-direction: column; gap: var(--s4); }
.brain-panel { border-top-width: 3px; border-top-style: solid; }
.brain-panel-hd { display: flex; align-items: center; gap: 10px; }
.brain-panel-hd h2 { font-size: 1.2rem; margin: 0; }
.brain-dot { display: inline-block; width: 10px; height: 10px; border-radius: 999px; flex-shrink: 0; }
.brain-field { margin-top: var(--s4); }
.brain-field:first-of-type { margin-top: var(--s3); }
.brain-field-label { font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--text-muted); margin-bottom: 4px; }
.brain-field p { color: var(--text-secondary); line-height: 1.6; }
.brain-practice { border-left: 3px solid; padding-left: var(--s4); }
.brain-practice p { color: var(--text-primary); }

/* The region panel's fields, collapsed by default -- six dense
   paragraphs stacked open made the panel outgrow the diagram next to
   it and pushed the rest of the page below the fold. <details> opens
   and closes itself; this just makes it look like part of the panel
   rather than a browser default. */
.brain-acc-stack { margin-top: var(--s3); display: flex; flex-direction: column; gap: 8px; }
.brain-acc {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-1); overflow: hidden;
}
.brain-acc-summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 11px 14px; cursor: pointer; list-style: none;
  font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
  -webkit-tap-highlight-color: transparent;
}
.brain-acc-summary::-webkit-details-marker { display: none; }
.brain-acc-summary::marker { content: ''; }
.brain-acc-chevron {
  flex-shrink: 0; font-size: 1.1rem; line-height: 1; color: var(--text-muted);
  transition: transform .18s ease;
}
.brain-acc[open] > .brain-acc-summary .brain-acc-chevron { transform: rotate(90deg); }
.brain-acc-body { padding: 0 14px 14px; }
.brain-acc-body p { color: var(--text-secondary); line-height: 1.6; margin: 0; }
.brain-acc-practice { border-left: 3px solid; }
.brain-acc-practice .brain-acc-body p { color: var(--text-primary); }

.brain-btn-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.brain-region-btn {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--radius-sm);
  color: var(--text-secondary); font-size: .88rem; font-weight: 560; text-align: left; cursor: pointer;
  transition: all .15s ease;
}
.brain-region-btn:hover { border-color: rgba(212,175,106,.5); color: var(--text-primary); }
.brain-region-btn.is-active { background: var(--gold-wash); border-color: var(--gold); color: var(--text-primary); }

@media (max-width: 780px) {
  .brain-layout { grid-template-columns: 1fr; }
  .brain-btn-grid { grid-template-columns: 1fr 1fr; }
}
   Service Desk

   A different register from the rest of MMM on purpose. This is a
   professional's workspace — someone pushes forty cases a day through
   it — so it runs denser, quieter and more numeric than the member
   surfaces. Same tokens, tighter rhythm. The client-facing portal will
   go the other way: calm and spacious, because the person on that side
   is typing their Social Security number.
---------------------------------------------------------------- */

.sd .section-head { margin-top: var(--s6); }
.sd-muted { color: var(--text-muted); font-size: var(--t-sm); }
.sd-mono {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  letter-spacing: .02em;
}

/* Guidance that prevents a rejection. Quiet enough to skip once you know
   it, present enough to catch someone the first time. */
.sd-note {
  font-size: var(--t-sm); color: var(--text-muted);
  border-left: 2px solid var(--line-strong);
  padding: 2px 0 2px var(--s3); margin: var(--s3) 0;
  max-width: 62ch;
}
.sd-warn { font-size: var(--t-xs); color: var(--warn); margin-top: 3px; }

/* Book header numbers */
/* A board row is a row-item holding two real buttons side by side --
   open the case, or open its "..." menu -- rather than one button
   with a nested one, which is invalid markup and unpredictable to
   click. The open button resets every bit of .btn/.row-item chrome
   it would otherwise inherit from being a <button>, so it reads as
   plain row content and not a second, oddly-bordered control. */
.sd-case-row { padding: 0 15px 0 0; }
.sd-case-row-open {
  flex: 1; min-width: 0; display: flex; align-items: center;
  background: none; border: 0; padding: 13px 0 13px 15px; margin: 0;
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.sd-case-row-menu { flex-shrink: 0; color: var(--text-muted); }
.sd-case-row-menu:hover { color: var(--text-primary); }

.sd-stats { display: flex; gap: var(--s6); flex-wrap: wrap; margin-bottom: var(--s4); }
.sd-stat { display: flex; flex-direction: column; gap: 1px; }
.sd-stat-n {
  font-size: var(--t-xl); font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.sd-stat-l { font-size: var(--t-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }

.sd-searchbar {
  display: flex; align-items: center; gap: var(--s2);
  background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 0 var(--s3);
  color: var(--text-muted); margin-bottom: var(--s3);
}
.sd-searchbar input {
  flex: 1; background: none; border: 0; outline: none; color: var(--text-primary);
  font: inherit; padding: 11px 0;
}
.sd-searchbar input::placeholder { color: var(--text-faint); }

.sd-book .row-item[hidden] { display: none; }

/* A row that displays rather than navigates. Without this it looks
   clickable and isn't, which reads as a broken button. */
.row-item.is-static { cursor: default; }
.row-item.is-static:hover { background: var(--surface-1); }

.sd-back {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--t-sm); color: var(--text-muted);
  text-decoration: none; margin-bottom: var(--s3);
}
.sd-back:hover { color: var(--text-primary); }

.sd-client-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--s5); flex-wrap: wrap;
}
.sd-client-head h2 { margin: 0 0 var(--s1); }
.sd-client-meta {
  display: flex; flex-direction: column; gap: 3px; align-items: flex-end;
  font-size: var(--t-sm); text-align: right;
}

.sd-grid-2, .sd-grid-3 { display: grid; gap: var(--s3); }
.sd-grid-2 { grid-template-columns: 1fr 1fr; }
.sd-grid-3 { grid-template-columns: 2fr 1fr 1fr; }
@media (max-width: 560px) {
  .sd-grid-2, .sd-grid-3 { grid-template-columns: 1fr; }
}

.sd-empty-state { max-width: 62ch; }
.sd-empty-state h2 { margin-top: 0; }

/* ---------------------------------------------------------------
   Contract number confirmation

   The one screen in this module that is deliberately slow. A wrong
   contract number is not a typo — it is a request filed against another
   person's policy — so the number is pulled apart and read back before
   anything is saved. Characters that actually get confused when a number
   is dictated or read off a statement are tinted; the rest stay plain so
   the tint means something.
---------------------------------------------------------------- */

.sd-confirm { padding-bottom: var(--s2); }
.sd-charrow {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: var(--s4) 0 var(--s3);
}
.sd-char {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: var(--t-lg); line-height: 1;
  min-width: 34px; padding: 12px 6px;
  text-align: center; border-radius: var(--radius-xs);
  background: var(--surface-2); border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.sd-char.is-risky {
  background: var(--gold-wash);
  border-color: var(--gold-soft);
  color: var(--gold-lit);
}
.sd-confirm-legend { max-width: 54ch; }
.sd-confirm-meta {
  display: flex; gap: var(--s5); flex-wrap: wrap;
  font-size: var(--t-sm); margin: var(--s4) 0;
  padding-top: var(--s3); border-top: 1px solid var(--line);
}

/* Service Desk — cases and the checklist -------------------------

   The checklist is the product, so it gets the clearest hierarchy in
   the module: a tick column your eye can run straight down, the
   requirement in plain language, and the answer underneath in the
   quieter colour. Outstanding items are the only ones with an action,
   which is what makes the list scannable at speed.
----------------------------------------------------------------- */

.sd-checklist {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  overflow: hidden; background: var(--surface-1);
}
.sd-check {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: 12px 15px; border-bottom: 1px solid var(--line);
}
.sd-check:last-child { border-bottom: 0; }
.sd-check-mark {
  flex: none; width: 19px; height: 19px; margin-top: 1px;
  border-radius: 50%; border: 1.5px solid var(--line-strong);
  display: grid; place-items: center; color: var(--bg);
}
.sd-check.is-met .sd-check-mark {
  background: var(--good); border-color: var(--good);
}
.sd-check-body { flex: 1; min-width: 0; }
.sd-check-label { font-size: var(--t-base); line-height: 1.35; }
.sd-check.is-met .sd-check-label { color: var(--text-secondary); }
.sd-check-value {
  font-size: var(--t-sm); color: var(--text-secondary); margin-top: 2px;
  word-break: break-word;
}
.sd-yesno { display: flex; gap: 8px; flex: none; }
.sd-check .linkbtn { flex: none; align-self: center; }

/* The honesty banner. It sits above the checklist because the moment to
   learn that a rule is unverified is before you rely on it. */
.sd-banner { border-left: 3px solid var(--line-strong); }
.sd-banner.is-warn { border-left-color: var(--warn); }
.sd-banner strong { display: block; margin-bottom: 4px; }
.sd-banner p { margin: 0; font-size: var(--t-sm); color: var(--text-muted); max-width: 66ch; }

.pill.is-blocked { color: var(--warn); }
.pill.is-clear   { color: var(--good); }

/* A checkbox that reads as a statement the person is signing, not a
   toggle they are flicking. Used for "I have checked this against the
   carrier's current form", which is a claim, not a setting. */
.sd-checkfield {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: 12px 14px; margin: var(--s4) 0;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); cursor: pointer;
  font-size: var(--t-sm); line-height: 1.4;
}
.sd-checkfield input { margin-top: 2px; flex: none; accent-color: var(--gold); }

/* A file input dressed as the same link-button every other row action
   uses, so "Attach" does not announce itself as a different species of
   control halfway down a checklist. */
.sd-upload { cursor: pointer; }

/* One tool, one door. The tab strip inside the Financial Professional
   Assistant, so the book, the queue and the rule library read as three
   views of one job rather than three products sharing a sidebar. */
.sd-tabs {
  display: flex; gap: var(--s1); align-items: center;
  border-bottom: 1px solid var(--line); margin-bottom: var(--s5);
}
.sd-tab {
  padding: 10px 14px; font-size: var(--t-sm); font-weight: 520;
  color: var(--text-muted); text-decoration: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  display: inline-flex; align-items: center; gap: 7px;
  transition: color var(--fast) var(--ease);
}
.sd-tab:hover { color: var(--text-primary); }
.sd-tab.is-active { color: var(--text-primary); border-bottom-color: var(--gold); }
.sd-tab-count {
  font-size: var(--t-xs); font-variant-numeric: tabular-nums;
  background: var(--surface-3); color: var(--text-secondary);
  border-radius: 999px; padding: 1px 7px;
}
.sd-shell > .section:first-of-type { margin-top: 0; }

/* WELLth Vault: the client-facing shell (#vault in index.html) -- a
   third top-level surface alongside #auth/#app, not a mode of either. */
.vault { max-width: 640px; margin: 0 auto; min-height: 100vh; }
.vault-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line);
}
.vault-body { padding: var(--s4); }

/* WELLth Vault: documents row actions + the message thread. */
.sd-vault-actions { display: flex; gap: 10px; flex: none; }
.sd-messages {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 320px; overflow-y: auto; padding: var(--s2) 0;
}
.sd-message {
  max-width: 80%; padding: 8px 12px; border-radius: 12px;
  background: var(--surface-2); align-self: flex-start;
}
.sd-message.is-advisor { align-self: flex-end; background: var(--surface-3); }
.sd-message-body { font-size: var(--t-sm); white-space: pre-wrap; word-break: break-word; }
.sd-message-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 3px; }
.sd-message-form { display: flex; gap: 8px; margin-top: var(--s2); }
.sd-message-form input { flex: 1; }

/* WELLth Vault: client-facing task list (Phase 1b) -- one card per open
   case, reusing the advisor side's own .sd-checklist/.sd-check rows so a
   client sees the exact same checkmarks their advisor does. */
.sd-task-card { margin-bottom: var(--s3); }
.sd-task-card .sd-checklist { margin-top: var(--s2); }

/* Advisor previewing one client's portal. Deliberately loud: the one
   failure mode of a read-only preview is forgetting you are in one. */
.sd-preview-banner {
  font-size: var(--t-sm); line-height: 1.5;
  background: var(--surface-1);
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--gold, var(--line-strong));
  border-radius: var(--radius-sm);
  padding: var(--s3); margin-bottom: var(--s4);
  max-width: 72ch;
}
.sd-preview-banner strong { display: block; color: var(--text-primary); }
.vip-row-actions { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }

/* The Ripple Book: the leather binder on screen. Facts in a two-column
   definition list so a policy reads like a statement line rather than a
   paragraph; the values block is boxed and carries its own date, because
   an undated balance is the one thing this screen must never imply. */
.sd-policy-card { margin-bottom: var(--s3); }
.sd-policy-meta {
  display: flex; align-items: center; gap: var(--s3);
  flex-wrap: wrap; margin-top: calc(-1 * var(--s1));
}
.sd-policy-tag {
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 1px var(--s2);
}
.sd-policy-facts {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s2) var(--s4); margin: var(--s3) 0 0;
}
.sd-policy-facts > div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.sd-policy-facts dt {
  font-size: var(--t-xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em;
}
.sd-policy-facts dd {
  margin: 0; font-size: var(--t-sm); color: var(--text-primary);
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.sd-policy-values {
  margin-top: var(--s3); padding: var(--s3);
  background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.sd-policy-values-head {
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted);
}
.sd-policy-values .sd-policy-facts { margin-top: var(--s2); }
.sd-policy-values .sd-note { margin-bottom: 0; }
.sd-policy-actions {
  display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3);
}
.sd-policy-actions .btn { display: inline-flex; align-items: center; gap: 2px; }

@media (max-width: 480px) {
  .sd-policy-facts { grid-template-columns: 1fr; }
  .sd-policy-actions .btn { flex: 1 1 auto; justify-content: center; }
}

/* Vault header: groups the bell and sign-out so they sit together at the
   right edge instead of both fighting flexbox alone. */
.vault-head .head-actions { display: flex; align-items: center; gap: var(--s3); }

/* Notification bell + dropdown. Shared by the member/FPA topbar
   (#notif-root) and the WELLth Vault header (#notif-root-vault) -- same
   markup, same styling, different mount point. */
.notif-wrap { position: relative; }
.bell-btn {
  position: relative; display: inline-grid; place-items: center;
  width: 36px; height: 36px; border-radius: 10px; color: var(--text-secondary);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.bell-btn:hover { background: var(--surface-2); color: var(--text-primary); }
.bell-badge {
  position: absolute; top: 2px; right: 2px; min-width: 15px; height: 15px;
  padding: 0 3px; border-radius: 999px; background: var(--gold);
  color: #171716; font-size: 10px; font-weight: 700; line-height: 15px; text-align: center;
}
.notif-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 20;
  width: min(340px, 90vw); max-height: 420px; overflow-y: auto;
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface-1) 60%);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0,0,0,.35);
}
.notif-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line);
  font-size: var(--t-sm); font-weight: 600;
}
.notif-panel-list { padding: var(--s2); }
.notif-row {
  display: block; padding: 10px 12px; border-radius: var(--radius-xs);
  transition: background var(--fast) var(--ease);
}
.notif-row:hover { background: var(--surface-3); }
.notif-row.is-unread { background: var(--gold-wash); }
.notif-title { font-size: var(--t-sm); font-weight: 600; color: var(--text-primary); }
.notif-body { font-size: var(--t-xs); color: var(--text-secondary); margin-top: 2px; }
.notif-meta { font-size: var(--t-xs); color: var(--text-muted); margin-top: 3px; }
.notif-panel-list .empty { padding: var(--s3) var(--s2); }

/* Standalone product: a wordmark where the member logo sits, until this
   product has a mark of its own. Deliberately restrained — a borrowed
   consumer logo on a professional tool's login screen undoes the whole
   separation. */
.auth-wordmark {
  font-size: var(--t-xl); font-weight: 600; letter-spacing: -.01em;
  line-height: 1.15; text-align: center; margin: var(--s4) auto var(--s2);
  max-width: 11ch; color: var(--text-primary);
}
.is-standalone .brand { padding-left: 2px; }

.sd-billing { max-width: 62ch; }
.sd-billing-state { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.sd-billing p { font-size: var(--t-sm); color: var(--text-secondary); margin: 0 0 var(--s4); }

.sd-create-agency { max-width: 34ch; margin-top: var(--s4); }
.sd-create-agency .btn { margin-top: var(--s2); }

.sd-head-actions { display: inline-flex; gap: var(--s4); align-items: center; }
#sd-import textarea { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--t-xs); }

/* The one action a case offers, when it offers one. Set apart from the
   checklist so "send" never sits next to something outstanding. */
.sd-actions {
  margin-top: var(--s5); padding-top: var(--s4);
  border-top: 1px solid var(--line);
}
.sd-actions .sd-note { border-left: 0; padding-left: 0; margin-top: 0; }

/* ---------------------------------------------------------------
   Carrier picker

   A text box that is deliberately not the value. The hidden input is
   only ever written by choosing from the menu, so a half-typed or
   nearly-right name cannot become a carrier — which is the whole reason
   this replaced a <select>. The "yours" pill carries the ranking: an
   agent's own carriers sort first and say so.
---------------------------------------------------------------- */
.sd-picker { position: relative; }
.sd-picker .field { margin-bottom: 0; }

.sd-picker-menu {
  position: absolute; z-index: 40; left: 0; right: 0; top: 100%;
  margin-top: 4px; max-height: 280px; overflow-y: auto;
  background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-pop);
  padding: 4px;
}
.sd-picker-menu[hidden] { display: none; }

.sd-picker-opt {
  display: flex; align-items: center; gap: var(--s2); width: 100%;
  background: none; border: 0; cursor: pointer; text-align: left;
  color: var(--text-primary); font: inherit;
  padding: 9px var(--s3); border-radius: var(--radius-xs);
}
.sd-picker-opt:hover, .sd-picker-opt:focus-visible {
  background: var(--surface-3); outline: none;
}
.sd-picker-opt-name { flex: 1; }
.sd-picker-opt-line {
  font-size: var(--t-xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em;
}
.sd-picker-none {
  font-size: var(--t-sm); color: var(--text-muted);
  padding: var(--s3); margin: 0; max-width: 46ch;
}
.sd-picker-hint {
  font-size: var(--t-xs); color: var(--text-muted); margin: 5px 0 0;
}

.pill-soft {
  font-size: var(--t-xs); background: var(--surface-3);
  color: var(--text-secondary); border-radius: 999px; padding: 1px 7px;
}

/* ---------------------------------------------------------------
   My carriers — the agency's shelf
---------------------------------------------------------------- */
.sd-subhead {
  font-size: var(--t-xs); color: var(--text-muted); font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em;
  margin: var(--s5) 0 var(--s2);
}
.sd-carrier-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: var(--s2);
}
.sd-carrier-row {
  display: flex; align-items: flex-start; gap: var(--s3); cursor: pointer;
  background: var(--surface-1); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: var(--s3);
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.sd-carrier-row:hover { border-color: var(--line-strong); }
.sd-carrier-row.is-on { border-color: var(--gold); background: var(--surface-2); }
.sd-carrier-row input { margin-top: 2px; accent-color: var(--gold); flex: none; }
.sd-carrier-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sd-carrier-name { font-size: var(--t-sm); font-weight: 500; }
.sd-carrier-sub { font-size: var(--t-xs); color: var(--text-muted); }

/* An open question. It sits above the thing it is about and does not
   look like a notice you can dismiss, because nothing proceeds until
   somebody answers it. */
.sd-ask { border-left: 3px solid var(--gold); }
.sd-ask h3 { margin: 0 0 var(--s2); font-size: var(--t-md); }
.sd-ask p { margin: 0 0 var(--s2); max-width: 66ch; }
.sd-ask-opts { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3); }
.sd-tab-ask { background: var(--gold); color: var(--bg); }

/* ---------------------------------------------------------------
   Getting set up

   Shown until all three steps are done, then gone. A permanent banner
   telling someone to finish what they finished is how a tool starts
   getting ignored.
---------------------------------------------------------------- */
.sd-setup { margin-bottom: var(--s5); border-left: 3px solid var(--gold); }
.sd-setup h2 { margin: 0 0 var(--s2); font-size: var(--t-lg); }
.sd-setup > .sd-muted { margin: 0 0 var(--s4); max-width: 62ch; }

.sd-step {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) 0; border-top: 1px solid var(--line);
}
.sd-step:first-of-type { border-top: 0; }
.sd-step-n {
  flex: none; width: 24px; height: 24px; border-radius: 999px;
  display: grid; place-items: center;
  font-size: var(--t-xs); font-weight: 600;
  background: var(--surface-3); color: var(--text-secondary);
}
.sd-step.is-done .sd-step-n { background: var(--gold); color: var(--bg); }
.sd-step-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sd-step-title { font-size: var(--t-base); line-height: 1.35; }
.sd-step.is-done .sd-step-title { color: var(--text-secondary); }
.sd-step-detail { font-size: var(--t-sm); color: var(--text-muted); max-width: 58ch; }
.sd-step-action { flex: none; align-self: center; }

@media (max-width: 560px) {
  .sd-step { flex-wrap: wrap; }
  .sd-step-action { width: 100%; padding-left: calc(24px + var(--s3)); }
}

/* ---------------------------------------------------------------
   Licensee build affordances (brand.js)
---------------------------------------------------------------- */

/* A licensee instance takes no sign-ups off the street, so the auth
   tablist holds one control. Kill the strip that only made sense as a
   two-way switch rather than leaving a lone tab looking broken. */
.tabs.is-single { display: none; }

/* Says out loud that a branded build is a concept, wherever it gets
   forwarded. Fixed, unmissable, and never over an interactive control. */
/* ---- Disclosure footer ----
   A registered representative's disclosures are compulsory and they are
   also the last thing anyone reads, which is exactly why they usually
   look like sediment at the bottom of the page. These get treated as
   design instead: a row of chips that matches the rest of the app, with
   the long text one tap away at #/disclosures rather than dumped here.

   Tokens only — a brand that switches this on inherits its own accent,
   so nothing in here is Kate-specific. */
.site-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 1180px;
  margin: var(--s6) auto 0;
  padding: 18px 26px calc(18px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--surface-3);
}

/* Signed out there is no sidebar to align to, so it centres under the
   card instead of tracking the view's left edge. */
#auth .site-foot {
  justify-content: center;
  max-width: 560px;
  border-top: 0;
  margin-top: var(--s5);
}
#auth .foot-note { text-align: center; }

/* The demo flag is fixed to the bottom centre. Without this the last row
   of chips sits underneath it. */
body.is-demo .site-foot { padding-bottom: calc(46px + env(safe-area-inset-bottom)); }

.foot-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--gold-wash);
  color: var(--gold-lit);
  font-size: var(--t-xs);
  font-weight: 560;
  letter-spacing: .02em;
  text-decoration: none;
  white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.foot-chip:hover {
  background: var(--gold-soft);
  border-color: var(--gold-soft);
  color: var(--text-primary);
}
/* The one that opens the full page reads as the primary of the row. */
.foot-chip.is-lead { background: var(--gold); color: var(--on-accent); }
.foot-chip.is-lead:hover { background: var(--gold-lit); color: var(--on-accent); }

.foot-note {
  flex-basis: 100%;
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: var(--t-xs);
  line-height: 1.55;
}

.demo-flag {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  z-index: 60;
  max-width: calc(100vw - 24px);
  padding: 5px 14px calc(5px + env(safe-area-inset-bottom));
  border: 1px solid var(--gold-soft);
  border-bottom: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: var(--t-xs);
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
/* Clear of the mobile tab bar, which owns the bottom edge on phones. */
body.is-demo .demo-flag { bottom: 0; }
@media (max-width: 860px) {
  .demo-flag { bottom: calc(var(--tabbar-h, 56px)); }
}

/* Set-new-password dialog, opened from a password-reset link. */
.set-password {
  border: 1px solid var(--line); border-radius: 16px; padding: 24px;
  background: var(--surface-2); color: inherit; width: min(380px, calc(100vw - 32px));
}
.set-password::backdrop { background: rgba(0,0,0,.6); }
.set-password h2 { margin: 0 0 16px; }

/* ---------------------------------------------------------------
   The family crest emblem in the sidebar.

   Sits above the nav in every mode. Deliberately quiet: it is the
   client's own mark, so it reads as belonging to them rather than
   competing with the brand lockup above it or the nav items below.
   The gold hairline is the only brand assertion, and it picks up
   whichever palette the current brand set.
---------------------------------------------------------------- */
.nav-crest {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  margin: 0 0 10px;
  border-radius: 12px;
  border: 1px solid var(--gold-soft);
  background: var(--gold-wash);
  color: var(--text-secondary);
  text-decoration: none;
  font-size: .82rem;
  line-height: 1.25;
  transition: border-color .15s ease, background .15s ease;
}
.nav-crest:hover { border-color: var(--gold); background: var(--gold-soft); }
.nav-crest img {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  border-radius: 8px;
  object-fit: contain;
  display: block;
}

/* ---------------------------------------------------------------
   The client financial dashboard: cash flow, spending, budgets,
   goals, accounts, activity.

   Built from the existing tokens only, so every brand gets it in its
   own palette without a line of per-brand CSS. Green and red are the
   one exception and are deliberate: money in and money out is the one
   place a client reads colour as meaning rather than decoration, and
   a gold-on-gold chart would say nothing.
---------------------------------------------------------------- */
.flow-hero {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  padding-bottom: 18px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--surface-3);
}
.flow-label { font-size: .74rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 4px; }
.flow-in  { font-size: 1.28rem; font-weight: 600; color: #4ea87a; }
.flow-out { font-size: 1.28rem; font-weight: 600; color: #c9656b; }

.flow-chart { display: flex; align-items: flex-end; gap: 10px; height: 148px; }
.flow-col { flex: 1; display: flex; flex-direction: column; align-items: center; height: 100%; }
.flow-bars { flex: 1; width: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 3px; }
.flow-bar { width: 42%; min-height: 2px; border-radius: 3px 3px 0 0; display: block; }
.flow-bar.is-in  { background: #4ea87a; }
.flow-bar.is-out { background: #c9656b; }
.flow-month { font-size: .72rem; color: var(--text-muted); padding-top: 8px; }

/* Spending, budgets and goals share one bar so they read as one family. */
.spend-row { display: grid; grid-template-columns: minmax(96px, 1.1fr) 2fr auto; align-items: center; gap: 12px; padding: 9px 0; }
.spend-name { font-size: .88rem; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spend-track { height: 8px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.spend-fill { display: block; height: 100%; border-radius: 4px; background: var(--gold); }
.spend-fill.is-over { background: #c9656b; }
.spend-fill.is-done { background: #4ea87a; }
.spend-amt { font-size: .84rem; color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.spend-amt.is-over { color: #c9656b; }

.goal-row { padding: 11px 0; }
/* The Y in SMARTY, on the goal itself. Quiet and italic: it is the
   client's own sentence, not a label we wrote. */
.goal-why {
  margin-top: 6px; padding-left: var(--s3);
  border-left: 2px solid var(--line-strong);
  font-size: var(--t-sm); font-style: italic; color: var(--text-muted);
  max-width: 62ch;
}
/* Budget and goal rows open their own sheet, so they need to look
   pressable rather than inert. */
.spend-row.is-editable, .goal-row.is-editable { cursor: pointer; }
.spend-row.is-editable:hover, .goal-row.is-editable:hover { opacity: .85; }
.spend-row.is-editable:focus-visible, .goal-row.is-editable:focus-visible {
  outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--radius-sm);
}
.goal-head { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 7px; }
.goal-name { font-size: .92rem; color: var(--text-primary); }
.goal-amt { font-size: .84rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.goal-foot { font-size: .76rem; color: var(--text-muted); padding-top: 6px; }

.acct-group + .acct-group { margin-top: 18px; }
.acct-group-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: .76rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-muted); padding-bottom: 8px;
  border-bottom: 1px solid var(--surface-3); margin-bottom: 4px;
}
.acct-group-head span { color: var(--text-primary); font-size: .92rem; letter-spacing: 0; text-transform: none; font-variant-numeric: tabular-nums; }
.acct-row { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; }
.acct-name { font-size: .9rem; color: var(--text-secondary); }
.acct-mask { color: var(--text-faint); font-size: .8rem; }
.acct-bal { font-size: .9rem; color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.acct-bal.is-debt { color: #c9656b; }

.tx-row { display: flex; justify-content: space-between; align-items: center; gap: 14px; padding: 10px 0; border-bottom: 1px solid var(--surface-2); }
.tx-row:last-child { border-bottom: 0; }
.tx-name { font-size: .9rem; color: var(--text-primary); }
.tx-meta { font-size: .76rem; color: var(--text-muted); padding-top: 2px; }
.tx-pending { font-size: .7rem; color: var(--text-faint); border: 1px solid var(--surface-4); border-radius: 4px; padding: 1px 5px; margin-left: 5px; }
.tx-amt { font-size: .9rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tx-amt.is-out { color: var(--text-primary); }
.tx-amt.is-in  { color: #4ea87a; }

@media (max-width: 620px) {
  .flow-hero { grid-template-columns: 1fr 1fr; }
  .spend-row { grid-template-columns: minmax(80px, 1fr) 1.4fr auto; gap: 9px; }
}

/* VIP roster: the evidence beside a name.
   A carrier tag means a placed policy; an inactive tag means the
   relationship ended; coaching means a different vertical entirely. All
   three are shown rather than filtered, because Pete decides who is a
   client and the CRM only has an opinion. */
.vip-marks { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.vip-badge {
  font-size: .7rem; letter-spacing: .02em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 4px; border: 1px solid;
  white-space: nowrap;
}
.vip-badge.is-carrier  { color: var(--gold);     border-color: var(--gold-soft);  background: var(--gold-wash); }
.vip-badge.is-inactive { color: #c9656b;         border-color: rgba(201,101,107,.35); background: rgba(201,101,107,.08); }
.vip-badge.is-coaching { color: var(--text-muted); border-color: var(--surface-4); }
.vip-badge.is-vip      { color: #4ea87a;         border-color: rgba(78,168,122,.4);  background: rgba(78,168,122,.1); }

/* ---------------------------------------------------------------
   The community board.

   `.chip` is new here rather than reused: .foot-chip above is a
   disclosure link with its own sizing and hover, and overloading it
   would tie a regulatory footer's appearance to a filter button's.
---------------------------------------------------------------- */
.board-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.chip {
  font-size: .8rem; padding: 5px 12px; border-radius: 999px;
  border: 1px solid var(--surface-4); background: transparent;
  color: var(--text-secondary); cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.chip:hover { border-color: var(--gold-soft); color: var(--text-primary); }
.chip.is-active { border-color: var(--gold); color: var(--on-accent); background: var(--gold); }
.chip.is-cat, .chip.is-pin { cursor: default; font-size: .7rem; padding: 2px 9px; text-transform: uppercase; letter-spacing: .03em; }
.chip.is-cat { color: var(--gold); border-color: var(--gold-soft); background: var(--gold-wash); }
.chip.is-pin { color: var(--text-muted); }

.board-post {
  padding: 14px 0; border-bottom: 1px solid var(--surface-2); cursor: pointer;
}
.board-post:last-child { border-bottom: 0; }
.board-post:hover .board-post-title { color: var(--gold); }
.board-post-head { display: flex; gap: 6px; margin-bottom: 8px; }
.board-post-title { font-size: 1rem; color: var(--text-primary); transition: color .15s ease; }
.board-post-meta { font-size: .76rem; color: var(--text-muted); padding-top: 5px; }

/* Members write in paragraphs and press return. Without this their line
   breaks are swallowed and every post arrives as one block. */
.board-body { white-space: pre-wrap; color: var(--text-secondary); line-height: 1.6; }

.board-reply { padding: 12px 0; border-bottom: 1px solid var(--surface-2); }
.board-reply:last-of-type { border-bottom: 0; }

/* VIP messages: one thread, two voices.
   Indented and tinted rather than chat-bubbled — this is a record of
   advice a client may reread months later, not a chat app. */
.vipmsg { padding: 12px 0 12px 12px; border-left: 2px solid var(--surface-4); margin-bottom: 4px; }
.vipmsg.is-them { border-left-color: var(--gold); }
.vipmsg.is-you  { border-left-color: var(--surface-4); }
.vipmsg-who { font-size: .74rem; color: var(--text-muted); margin-bottom: 5px; }

/* The sidebar mark sits in a fixed square box (width=28 height=28 on the
   <img>), which silently compresses any brand whose mark is not 1:1 —
   Plouton Life's 3:1 wordmark lockup rendered as a smudge until its mark
   became the water drop alone. This makes the failure visible as
   letterboxing instead of distortion, so the next wide mark looks small
   rather than wrong. */
.brand-mark { object-fit: contain; }


/* ---- Cash calendar -------------------------------------------------
   A month of dated money. Deliberately plain: the dots carry the
   meaning, so the grid stays readable at phone width where a client
   actually opens this. */
.cal-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
.cal-head strong { font-size:1rem; }
.cal-totals { display:flex; gap:14px; flex-wrap:wrap; font-size:.85rem; margin-bottom:14px; }
.cal-in   { color:#4ec98a; }
.cal-out  { color:#d98b8b; }
.cal-net  { font-weight:600; }
.cal-net.is-over { color:#d98b8b; }
.cal-dow {
  display:grid; grid-template-columns:repeat(7,1fr); gap:2px;
  font-size:.68rem; text-transform:uppercase; letter-spacing:.04em;
  opacity:.55; text-align:center; margin-bottom:4px;
}
.cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
.cal-cell {
  aspect-ratio:1; border-radius:7px; padding:4px;
  display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
  gap:3px; font-size:.78rem; background:rgba(255,255,255,.02);
}
.cal-cell.is-blank { background:none; }
.cal-cell.has-events { background:rgba(255,255,255,.06); }
.cal-cell.is-today { outline:1px solid var(--gold, #c9a227); }
.cal-num { line-height:1; }
.cal-dots { display:flex; gap:3px; }
.cal-dot { width:5px; height:5px; border-radius:50%; display:block; }
.cal-dot.is-in { background:#4ec98a; }
.cal-dot.is-out { background:#d98b8b; }
.cal-dot.is-windfall { background:var(--gold, #c9a227); }
.cal-list { margin-top:16px; }
@media (max-width: 420px) {
  .cal-cell { font-size:.7rem; padding:2px; }
}

/* ---- Ripple Book binder tabs ---------------------------------------
   The sections of the physical leather binder, in Pete's order. Scrolls
   sideways on a phone rather than wrapping into three ragged rows --
   six tabs will never fit across 375px, and a client opens this on a
   phone more often than not. */
.ripple-tabs {
  display: flex; gap: 6px; overflow-x: auto; margin: 0 0 18px;
  padding-bottom: 6px; scrollbar-width: none;
}
.ripple-tabs::-webkit-scrollbar { display: none; }
.ripple-tab {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line, rgba(255,255,255,.14));
  background: transparent; color: inherit;
  font: inherit; font-size: .85rem; white-space: nowrap;
  transition: background .15s, border-color .15s;
}
.ripple-tab:hover { background: rgba(255,255,255,.05); }
.ripple-tab.is-active {
  background: var(--gold, #c9a227);
  border-color: var(--gold, #c9a227);
  color: #141414; font-weight: 600;
}
.ripple-tab-n {
  font-size: .72rem; line-height: 1; padding: 2px 6px; border-radius: 999px;
  background: rgba(255,255,255,.12);
}
.ripple-tab.is-active .ripple-tab-n { background: rgba(0,0,0,.18); }

/* Running totals: the cumulative line through the cash calendar, and
   what the budget categories add up to. Both answer "where do I stand",
   which a per-row figure cannot. */
.cal-run-end { font-weight: 600; color: var(--text-secondary); }
.cal-run-end.is-over { color: #d98b8b; }
.cal-low { margin: 0 0 12px; font-size: .82rem; color: #d98b8b; line-height: 1.45; }
.cal-run { font-variant-numeric: tabular-nums; }
.cal-run.is-over { color: #d98b8b; }
.spend-foot {
  display: flex; gap: 16px; flex-wrap: wrap; justify-content: space-between;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--hairline, rgba(255,255,255,.1));
  font-size: .84rem; color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.spend-foot strong { color: var(--text-primary); }
.spend-foot .is-over, .spend-foot .is-over strong { color: #c9656b; }
.spend-foot .is-left strong { color: #4ec98a; }

/* The reservoir: a month of income and outflow as a tank with a stream
   in and a drain out. Sized by viewBox, so it scales to a phone with no
   media query of its own. */
.res-svg { display: block; width: 100%; height: auto; max-height: 320px; }
.res-label { fill: var(--text-secondary); font-size: 13px; letter-spacing: .02em; text-transform: uppercase; }
.res-fig { font-size: 22px; font-weight: 650; font-variant-numeric: tabular-nums; }
.res-in { fill: #4ec98a; }
.res-out { fill: #d98b8b; }
.res-sub { fill: var(--text-secondary); font-size: 12px; }
.res-kept { fill: var(--text-primary); font-size: 28px; font-weight: 700; font-variant-numeric: tabular-nums; }
.res-kept.is-dry { fill: #d98b8b; }
.res-toggle { display: inline-flex; gap: 2px; padding: 2px; border-radius: 999px;
  background: var(--surface-sunken, rgba(255,255,255,.06)); }
.res-tab { border: 0; cursor: pointer; padding: 5px 13px; border-radius: 999px;
  font-size: .8rem; color: var(--text-secondary); background: transparent; }
.res-tab.is-on { background: var(--surface-raised, rgba(255,255,255,.14)); color: var(--text-primary); }
.res-tab:focus-visible { outline: 2px solid var(--gold, #c9a86a); outline-offset: 2px; }
.res-group-head { margin: 14px 0 4px; font-size: .78rem; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-secondary); }
.res-group-head:first-child { margin-top: 0; }
.res-read { margin: 14px 0 0; font-size: .86rem; color: var(--text-secondary); line-height: 1.5; }
.res-read strong { color: var(--text-primary); }

/* The worked-example reservoir, for a client who has entered nothing.
   Visibly an example: a pill in the header, a dimmed and dashed frame,
   and copy that says whose numbers these are not. In a financial app a
   sample that reads as real data is worse than no sample, so the
   labelling is load-bearing, not decoration. */
.res-sample-pill { background: var(--surface-4, rgba(255,255,255,.12)); color: var(--text-secondary);
  border: 1px solid var(--hairline, rgba(255,255,255,.18)); }
.res-sample-frame { position: relative; opacity: .72; border: 1px dashed var(--hairline, rgba(255,255,255,.22));
  border-radius: 12px; padding: 6px; }
.res-sample-frame::after {
  content: 'Example'; position: absolute; top: 10px; right: 12px;
  font-size: .68rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-muted); pointer-events: none;
}
.res-sample .res-read strong { color: var(--text-primary); }

/* The "a new build is out" pill. Only ever shown when reloading would
   cost someone typed-in work -- otherwise the page just reloads. */
.build-stale {
  position: fixed; left: 50%; transform: translateX(-50%); top: 14px; z-index: 9999;
  border: 1px solid var(--gold, #c9a86a); border-radius: 999px; cursor: pointer;
  background: var(--gold, #c9a86a); color: #0b1b24; font-weight: 650;
  padding: 11px 22px; font-size: .92rem; box-shadow: 0 8px 30px rgba(0,0,0,.55);
  animation: build-stale-in .35s ease-out;
}
@keyframes build-stale-in { from { opacity: 0; transform: translate(-50%, -14px); }
                            to { opacity: 1; transform: translate(-50%, 0); } }
.build-stale:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* The family tree's worked example borrows the reservoir's sample
   treatment -- pill, dashed frame, copy that disclaims it -- because it
   is the same promise: this is what the page becomes, not your data. */
.fam-card-wrap.res-sample .res-sample-frame { padding: 10px 6px; }

/* Goals grouped by horizon. Every group is drawn even when empty, so a
   missing "Long term" never reads as "we do not do that here". */
.goal-group + .goal-group { margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--hairline, rgba(255,255,255,.1)); }
.goal-group-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.goal-group-name { font-size: .82rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-primary); }
.goal-group-when { font-size: .78rem; color: var(--text-muted); }
.goal-group-tot { margin-left: auto; font-size: .82rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.goal-group-empty { margin: 0; font-size: .84rem; }

/* Calendar: day view and the list beside it. Side by side on a wide
   screen, stacked on a phone -- the grid must never shrink below a
   tappable square. */
.cal-actions { display: inline-flex; gap: 14px; align-items: center; }
.linkbtn.is-on { color: var(--gold, #c9a86a); }
.cal-split { display: grid; grid-template-columns: 1fr; gap: 18px; }
.cal-split.has-side { grid-template-columns: minmax(280px, 1fr) minmax(240px, 0.85fr); }
@media (max-width: 760px) { .cal-split.has-side { grid-template-columns: 1fr; } }
.cal-cell { appearance: none; background: transparent; font: inherit; color: inherit; }
button.cal-cell { cursor: pointer; }
button.cal-cell:hover { background: var(--surface-3, rgba(255,255,255,.07)); }
.cal-cell.is-selected { outline: 2px solid var(--gold, #c9a86a); outline-offset: -2px; border-radius: 8px; }
.cal-cell:focus-visible { outline: 2px solid var(--gold, #c9a86a); outline-offset: 1px; }
.cal-tip { margin: 10px 0 0; }
.cal-side { border: 1px solid var(--hairline, rgba(255,255,255,.12)); border-radius: 12px; padding: 12px 14px; }
.cal-side-head { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; margin-bottom: 8px; }
.cal-side-tot { display: flex; gap: 12px; flex-wrap: wrap; font-size: .84rem; margin-bottom: 10px; }

/* Budgets: what is left, and whether anything is wired to the category. */
.budget-left { display: block; font-size: .76rem; color: var(--text-secondary); }
/* It is a button now, not a label: pressing it opens the calendar form
   pre-filled from the budget. A tooltip saying "not linked" did not
   exist on a phone and did not say what to do. */
.budget-unlinked { font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--gold, #c9a86a); margin-left: 6px; cursor: pointer;
  background: rgba(201,168,106,.12); border: 1px solid rgba(201,168,106,.4);
  border-radius: 999px; padding: 2px 8px; font-family: inherit; }
.budget-unlinked:hover { background: rgba(201,168,106,.22); }
.budget-unlinked:focus-visible { outline: 2px solid var(--gold, #c9a86a); outline-offset: 2px; }
.budget-undated { border-left: 2px solid rgba(201,168,106,.5); padding-left: 10px; }
.budget-undated strong { color: var(--text-primary); }
.budget-note { margin: 12px 0 0; line-height: 1.5; }

/* The overall cash reservoir: a level, not a flow. */
.res-overall-hero { text-align: center; margin-bottom: 4px; }
.res-overall-label { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); }
.res-overall-fig { font-size: 1.9rem; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--text-primary); }

/* The reservoir toggle sits on the image it controls. */
.res-bar { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }

/* Neutral observations, and the offer to ask a human about them. */
.res-notes { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hairline, rgba(255,255,255,.1)); }
.res-notes-head { font-size: .78rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-secondary); margin-bottom: 6px; }
.res-notes ul { margin: 0; padding-left: 18px; }
.res-notes li { font-size: .88rem; color: var(--text-secondary); line-height: 1.6; }
.res-notes strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.ask-block { margin-top: 16px; padding: 14px; border-radius: 12px;
  background: var(--gold-wash, rgba(201,168,106,.08));
  border: 1px solid var(--gold-soft, rgba(201,168,106,.28)); }
.ask-head { font-size: .92rem; color: var(--text-primary); margin-bottom: 4px; }
.ask-copy { margin: 0 0 10px; font-size: .84rem; color: var(--text-secondary); line-height: 1.55; }

/* The Plouton help bubble: a floating button in the client portal and
   the panel it opens. Fixed to the viewport so it is reachable from any
   scroll position, and it never covers the page's own actions on a
   phone -- the panel takes the full width there instead. */
.help-fab { position: fixed; right: 18px; bottom: 18px; z-index: 60;
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 11px 16px; border-radius: 999px; font: inherit; font-size: .88rem;
  color: var(--text-primary); background: var(--surface-3, rgba(28,28,30,.92));
  border: 1px solid var(--gold-soft, rgba(201,168,106,.4)); }
.help-fab:hover { border-color: var(--gold, #c9a86a); }
.help-fab:focus-visible { outline: 2px solid var(--gold, #c9a86a); outline-offset: 2px; }
.help-fab-mark { display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; font-size: .78rem;
  background: var(--gold-wash, rgba(201,168,106,.18)); color: var(--gold, #c9a86a); }
.help-panel { position: fixed; right: 18px; bottom: 74px; z-index: 61;
  width: min(380px, calc(100vw - 36px)); max-height: min(70vh, 620px); overflow-y: auto;
  padding: 16px; border-radius: 14px;
  background: var(--surface-2, #141416); border: 1px solid var(--hairline, rgba(255,255,255,.16)); }
.help-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; }
.help-map { display: grid; gap: 2px; margin-bottom: 14px; }
.help-row { display: block; padding: 9px 10px; border-radius: 9px; text-decoration: none; }
.help-row:hover { background: var(--surface-3, rgba(255,255,255,.06)); }
.help-row-title { display: block; font-size: .88rem; color: var(--text-primary); }
.help-row-line { display: block; font-size: .78rem; color: var(--text-secondary); line-height: 1.45; margin-top: 2px; }
.help-ask { border-top: 1px solid var(--hairline, rgba(255,255,255,.12)); padding-top: 12px; }
.help-starters { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.help-chip { display: inline-block; cursor: pointer; font: inherit; font-size: .76rem;
  padding: 6px 10px; border-radius: 999px; text-decoration: none;
  color: var(--text-secondary); background: transparent;
  border: 1px solid var(--hairline, rgba(255,255,255,.18)); }
.help-chip:hover { color: var(--text-primary); border-color: var(--gold-soft, rgba(201,168,106,.4)); }
.help-answer { margin-top: 12px; font-size: .88rem; line-height: 1.6; color: var(--text-primary); }
.help-answer p { margin: 0 0 8px; }
.help-related { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.help-handoff { margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  background: var(--gold-wash, rgba(201,168,106,.08));
  border: 1px solid var(--gold-soft, rgba(201,168,106,.28)); }
.help-handoff p { margin: 0 0 8px; font-size: .84rem; color: var(--text-secondary); }
.help-error { margin: 10px 0 0; font-size: .84rem; color: #d98b8b; }
.help-fine { margin: 10px 0 0 !important; font-size: .72rem; color: var(--text-muted); line-height: 1.45; }
@media (max-width: 620px) {
  .help-panel { right: 10px; left: 10px; width: auto; bottom: 68px; }
  .help-fab { right: 12px; bottom: 12px; }
}

/* Labels for the lines that cross the reservoir gauge. Larger and
   heavier than the surrounding scale text, because they sit on top of
   the water and have to win against it. */
.res-mark { font-size: 15px; font-weight: 650; letter-spacing: .01em; }


/* ---- The family tree ----------------------------------------------
   Generations as rows under a ripple banner. The ripple is the brand's
   own mark and the idea at the same time: rings spreading outward are
   generations. Generated on Artlist, 2026-10-23.
-------------------------------------------------------------------- */
.fam-section { margin-top: 8px; }

.fam-banner {
  position: relative; display: flex; flex-direction: column; align-items: center;
  gap: 2px; text-align: center;
  min-height: 196px; padding: 26px 22px 22px;
  border-radius: 14px 14px 0 0; overflow: hidden;
  background-image:
    radial-gradient(ellipse 60% 70% at 50% 46%, rgba(8,11,14,.22) 0%, rgba(8,11,14,.72) 70%, rgba(8,11,14,.9) 100%),
    url('/brands/plvip/family-ripple.jpg');
  background-size: cover; background-position: center 48%;
}

/* The drop sits at the centre the rings radiate from, so the photograph
   and the mark read as one image rather than a logo pasted on top. */
.fam-drop {
  width: 68px; height: 68px; display: block; margin-bottom: 2px;
  filter: drop-shadow(0 2px 14px rgba(201,168,106,.45));
}

.fam-banner-text h2 { margin: 0; font-size: 1.32rem; color: #f5f1e8; letter-spacing: .015em; }
.fam-banner-text p { margin: 3px 0 0; font-size: .84rem; color: rgba(245,241,232,.7); }
/* Pete, 2026-10-25: "put it closer to the left corner of the family
   tree" -- it lived top-right of the banner photo, a card's width away
   from the tree it adds to. Plain top-left of the card itself now, no
   absolute positioning needed since .card already pads 18px, and no
   mobile override needed either -- it was never anything else now. */
.fam-add { display: inline-flex; margin: 2px 0 12px; }

.fam-card-wrap { border-radius: 0 0 14px 14px; }

.fam-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 4px 0 8px; }
.fam-svg { display: block; min-width: 560px; width: 100%; height: auto; }

.fam-rail { stroke: var(--hairline, rgba(255,255,255,.07)); stroke-width: 1; }
/* Concierge setup: the advisor filling a client's tree in before they
   ever sign in. The mirror itself never changes shape -- only this strip
   above it -- so what gets set up is literally what they will see. */
.sd-mirror-rule-act { display: flex; align-items: center; gap: 12px; justify-content: space-between; }
.sd-setup-live { margin: 8px 0 12px; padding: 10px 14px; border-radius: 10px;
  background: rgba(201,168,106,.12); border: 1px solid rgba(201,168,106,.4);
  color: var(--text-secondary); font-size: .86rem; line-height: 1.5; }
.sd-setup-live strong { color: var(--text-primary); }
.fam-setup-note { margin: 0 0 14px; padding: 9px 12px; border-radius: 9px;
  background: rgba(201,168,106,.12); border: 1px solid rgba(201,168,106,.35); }

/* An empty seat on the example tree: the shape of a household with
   nobody in it. Dashed, because a solid card reads as a record. */
.fam-node.is-blank .fam-card { stroke-dasharray: 5 4; opacity: .85; }
.fam-node.is-blank .fam-mono-bg { fill: none; stroke: var(--hairline, rgba(255,255,255,.3));
  stroke-width: 1.5; stroke-dasharray: 4 3; }
.fam-node.is-blank .fam-rel { font-style: italic; opacity: .75; }

/* The marriage line: the couple joined, and one drop from the middle of
   it to the children. Heavier than a descent curve on purpose -- it is
   the join the whole tree hangs from. */
.fam-union { stroke: var(--gold, #c9a86a); stroke-width: 2; opacity: .55; stroke-linecap: round; }
/* The stem a couple's children hang from. Quieter than the marriage bar
   -- it is plumbing, not a relationship. */
.fam-stem { stroke: var(--gold, #c9a86a); stroke-width: 1.5; opacity: .38; stroke-linecap: round; }
/* The client's own marriage, heavier than the generations above it --
   it is the join the whole picture is built around. */
.fam-union.is-couple { stroke-width: 3.5; opacity: .85; }
.fam-gen { fill: var(--text-muted); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
.fam-edge { fill: none; stroke: var(--gold-soft, rgba(201,168,106,.38)); stroke-width: 1.5; }

.fam-card { fill: var(--surface-2, rgba(255,255,255,.045));
  stroke: var(--hairline, rgba(255,255,255,.14)); stroke-width: 1.5; }
.fam-mono-bg { fill: var(--surface-4, rgba(255,255,255,.1)); }
.fam-mono { fill: var(--text-secondary); font-size: 13px; font-weight: 650; letter-spacing: .04em; }
.fam-name { fill: var(--text-primary); font-size: 14.5px; font-weight: 600; }
.fam-rel  { fill: var(--text-secondary); font-size: 11.5px; letter-spacing: .015em; }

.fam-node[data-family-edit] { cursor: pointer; }
.fam-node[data-family-edit]:hover .fam-card,
.fam-node[data-family-edit]:focus-visible .fam-card { stroke: var(--gold, #c9a86a); }
.fam-node[data-family-edit]:focus-visible { outline: none; }

.fam-node.is-self .fam-card { fill: var(--gold-wash, rgba(201,168,106,.13));
  stroke: var(--gold-soft, rgba(201,168,106,.55)); stroke-width: 2; }
.fam-node.is-self .fam-mono-bg { fill: rgba(201,168,106,.26); }
.fam-node.is-self .fam-mono { fill: var(--gold, #c9a86a); }

/* The partner, picked out more quietly than the client, so the two of
   them read as the pair at the centre of the picture rather than as one
   highlighted person standing beside a stranger. */
.fam-node.is-partner .fam-card { fill: rgba(201,168,106,.06);
  stroke: rgba(201,168,106,.34); }
.fam-node.is-partner .fam-mono-bg { fill: rgba(201,168,106,.15); }

.fam-node.is-gone .fam-card { stroke-dasharray: 4 3; }
.fam-node.is-gone .fam-name, .fam-node.is-gone .fam-mono { opacity: .72; }
.fam-gone-mark { fill: var(--text-muted); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; }

.fam-doc-dot { fill: var(--gold-wash, rgba(201,168,106,.2)); stroke: var(--gold-soft, rgba(201,168,106,.45)); }
.fam-doc-n { fill: var(--gold, #c9a86a); font-size: 10.5px; font-weight: 650; }

.fam-tip { margin: 6px 0 0; line-height: 1.5; }

/* Their documents, listed inside the edit sheet. */
.fam-docs { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--hairline, rgba(255,255,255,.12)); }
.fam-docs-head { font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 8px; }
.fam-doc { display: flex; width: 100%; align-items: baseline; justify-content: space-between;
  gap: 12px; cursor: pointer; font: inherit; text-align: left;
  padding: 9px 11px; margin-bottom: 5px; border-radius: 9px;
  background: var(--surface-3, rgba(255,255,255,.05));
  border: 1px solid var(--hairline, rgba(255,255,255,.12)); }
.fam-doc:hover { border-color: var(--gold-soft, rgba(201,168,106,.42)); }
.fam-doc-label { color: var(--text-primary); font-size: .88rem; }
.fam-doc-cat { color: var(--text-muted); font-size: .74rem; white-space: nowrap; }

@media (max-width: 620px) {
  .fam-banner { min-height: 168px; padding: 20px 14px 18px; }
  .fam-banner-text h2 { font-size: 1.12rem; }
  .fam-drop { width: 56px; height: 56px; }
}

/* The reply box on a client's portal preview. Set apart from the
   read-only panels around it, because it is the one thing on that screen
   that does something. */
.sd-preview-compose { margin-bottom: 12px; border-color: var(--gold-soft, rgba(201,168,106,.3)); }

/* The book's proportion bars on the Everyone page. A track plus a fill,
   sized inline as a percentage -- no library, and it prints. */
.mm-bar { height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.mm-bar > span { display: block; height: 100%; background: var(--gold); border-radius: 3px; }
.mm-chart { width: 100%; height: auto; display: block; }

/* The Everyone page's filter bar. Groups stack on a phone and sit in a
   row on a desktop; each group's chips wrap within it rather than the
   whole bar becoming one long wrap, so a group stays readable as a
   group. */
.mstr-filters { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.mstr-fgroup { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.mstr-flabel {
  font-size: .76rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-faint); min-width: 72px;
}

/* ---------------------------------------------------------------
   Fulfilled AF workspace

   Pete, 2026-10-27: "make sure that Fulfilled AF workspace is branded
   for Fulfilled AF properly."

   The palette comes from brand.js's `faf` entry, which lifts
   fulfilledafbook.com's own tokens -- so everything here reads
   var(--gold) and var(--bg) rather than hard-coding #be9e44. Change the
   brand, this follows.

   The one thing NOT taken from the site is its webfont. fulfilledafbook.com
   sets Playfair Display, but this app loads no web fonts at all -- it is
   an installable PWA, and a blocking Google Fonts request on every screen
   to serve one workspace is the wrong trade. So the reader's face is
   Georgia, which ships on macOS, iOS, Windows and Android, needs no
   network, and is a genuine book serif. Playfair is named first in the
   stack purely so it is used by anyone who already has it locally.
   If the exact cover face matters more than the load cost later, the fix
   is one <link> in index.html, not a change here.

   A serif at all is the point: it is the whole difference between "an app
   showing text" and "a book". Scoped to this workspace so no other brand
   inherits it.
---------------------------------------------------------------- */

/* Chapter tabs. Narrower leading than a normal nav item because there
   are fourteen of them and they are read as a contents page. */
.faf-nav-item { font-size: .88rem; padding-top: 7px; padding-bottom: 7px; }
.faf-nav-item.is-done { color: var(--text-muted); }
.faf-nav-item.is-done .nav-ico { color: var(--gold); }
.nav-sep {
  height: 1px; margin: 10px 14px;
  background: linear-gradient(90deg, var(--gold-soft), transparent);
}

.faf-resume { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.faf-warn { border-left: 3px solid var(--gold); }

/* ---- chapter opener: the illustration and the epigraph ---- */
/* Side by side once there is room for both to breathe, stacked below that.
   The art column is capped rather than fluid so a 10MP press illustration and
   a 300px line drawing land at the same visual weight. */
/* The chapter's art and its epigraph.

   Pete, 2026-10-29: "enlarge and bring down the chapter image and the
   quote so during the reading it looks aligned."

   It used to open the page, above the tabs and the transport, which put
   the quietest thing on the screen in the loudest position and pushed
   every control down past it. It now sits directly above the book, with
   the controls gathered above IT -- so the eye runs tools, art, page,
   and the art shares an edge with the board it introduces.

   Bigger to match: the art was 300px against a book that is 880, which
   read as a thumbnail rather than a plate. */
.faf-opener {
  display: flex; gap: 32px; align-items: center; flex-wrap: wrap;
  margin: 26px 0 18px;
}
.faf-art { flex: 0 1 420px; margin: 0; min-width: 0; }
.faf-art img {
  display: block; width: 100%; height: auto; border-radius: 3px;
  /* The book's interior art is black and white on cream paper; on the dark
     portal a plain <img> floats as a bright rectangle. The frame gives it an
     edge to sit against instead. */
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.faf-epigraph {
  flex: 1 1 320px; min-width: 0; margin: 0;
  border-left: 2px solid var(--gold); padding: 2px 0 2px 20px;
}
.faf-epigraph p {
  margin: 0; font-style: italic; font-size: 1.22rem; line-height: 1.62;
  color: var(--text-primary); max-width: 46ch;
}
.faf-epigraph cite {
  display: block; margin-top: 10px; font-style: normal; font-size: .86rem;
  letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary);
}
.faf-epigraph cite::before { content: '— '; }

/* ---- mode switch ---- */
.faf-modes { display: flex; gap: 8px; margin: 0 0 18px; }
.faf-mode {
  flex: 0 0 auto; padding: 9px 20px; border-radius: 3px; cursor: pointer;
  background: var(--surface-2); color: var(--text-secondary);
  border: 1px solid transparent; font: inherit; font-size: .9rem;
  letter-spacing: .03em; transition: background .18s, color .18s, border-color .18s;
}
.faf-mode.is-on { background: var(--gold); color: var(--on-primary); font-weight: 600; }
.faf-mode:disabled { opacity: .38; cursor: not-allowed; }

/* ---- audiobook player ---- */
.faf-player-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.faf-play { flex: 0 0 auto; }
.faf-time { font-variant-numeric: tabular-nums; font-size: .82rem; color: var(--text-muted); min-width: 48px; }
.faf-scrub {
  flex: 1 1 180px; min-width: 120px; accent-color: var(--gold);
  height: 4px; cursor: pointer;
}
.faf-speed {
  background: var(--surface-2); color: var(--text-secondary);
  border: 1px solid var(--surface-4); border-radius: 3px; padding: 6px 8px; font: inherit; font-size: .82rem;
}

/* ---- the flip reader ----
   The turn is a 3D rotate on the leaf's own Y axis with the book as the
   perspective origin, which is what makes the page appear to lift off
   the spine rather than slide. transform-style: preserve-3d on the book
   and backface-visibility on the leaves are both load-bearing: without
   them the leaf flattens mid-turn and the whole thing reads as a fade.
   Honoured prefers-reduced-motion at the bottom -- a page-turn animation
   is exactly the kind of thing that makes some people ill. */
/* A FIXED height, not a minimum, and that is the whole fix.

   Pete, 2026-10-28: "there's some pages, like on the first chapter,
   where it's super long, and then you turn to the second page and it
   shortens the length vertically."

   min-height let every spread size itself to its own text, so the book
   grew and shrank as you turned pages -- the one thing a physical book
   never does. Pages hold different amounts of text; the page itself is
   always the same size. The height is tall enough that a full ~1,500
   character page fits without scrolling at desktop width, and anything
   longer scrolls inside the page rather than resizing the book. */
/* The book as an object: a gilt-edged board, a stack of pages behind the
   open spread, and a spine down the middle. Pete, 2026-10-28: "Add style
   to the book. visually show a book border, will look of pages." */
.faf-book {
  position: relative; display: flex; gap: 0;
  perspective: 2000px; perspective-origin: 50% 50%;
  background: var(--bg-elev);
  /* The board: a thin gilt rule, a dark bevel inside it, and the drop
     shadow of a real object sitting on the page. */
  border: 1px solid var(--gold-soft); border-radius: 5px;
  padding: 10px; overflow: hidden;
  height: clamp(540px, 76vh, 860px);
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, .55),
    0 26px 60px -24px rgba(0, 0, 0, .9),
    0 2px 0 rgba(190, 158, 68, .14);
}
/* The edges of the pages underneath the one being read -- the reason a
   closed book has a cream stripe down its side. Drawn as repeating hairline
   stripes just outside the text block, left and right. */
.faf-book::before,
.faf-book::after {
  content: ''; position: absolute; top: 14px; bottom: 14px; width: 7px;
  pointer-events: none; z-index: 1; border-radius: 2px;
  background: repeating-linear-gradient(to right,
    rgba(226, 216, 193, .50) 0 1px,
    rgba(120, 110, 92, .30) 1px 2px);
}
.faf-book::before { left: 3px; }
.faf-book::after  { right: 3px; }

/* Measuring happens before the first paint; hiding the leaves for that one
   frame is the difference between a book that appears and a book that
   appears to glitch. */
.faf-book.is-measuring .faf-leaf { visibility: hidden; }

/* The offscreen box the layout engine fills to find where a page ends. It
   must match .faf-page-body in every property that affects line breaking,
   which is why it IS a .faf-page-body with only its position changed. */
.faf-probe {
  position: fixed !important; left: -99999px !important; top: 0 !important;
  visibility: hidden !important; pointer-events: none !important;
  height: auto !important; max-height: none !important;
  overflow: visible !important; contain: layout style;
}
.faf-leaf {
  flex: 1 1 50%; min-width: 0; height: 100%; position: relative;
  transform-style: preserve-3d; backface-visibility: hidden;
  transform-origin: left center;
  transition: transform .34s cubic-bezier(.4, 0, .2, 1);
}
/* The left leaf is the verso: its spine is on the RIGHT, so it hinges
   there. Getting this backwards turns the book inside out. */
.faf-leaf-l { transform-origin: right center; }
.faf-book.is-turning-fwd .faf-leaf-r { transform: rotateY(-168deg); }
.faf-book.is-turning-back .faf-leaf-l { transform: rotateY(168deg); }
/* Held for exactly one frame at the end of a turn, while the new page text
   is written in and the rotation is reset. Without it the leaf animates
   back from 168deg -- the turn played in reverse, which is the flicker. */
.faf-book.is-settling .faf-leaf { transition: none; }

.faf-page {
  /* min-height: 0 is load-bearing inside a flex column -- without it a
     flex child refuses to shrink below its content, which is exactly how
     the page pushed the book taller in the first place. */
  height: 100%; min-height: 0; padding: 44px 40px 34px;
  /* Papyrus: a warm ground with fibre laid over it. Three cheap gradients
     rather than an image -- it scales to any page size, costs no request,
     and cannot go blurry. Pete asked for papyrus on 2026-10-28. */
  background-color: #efe6d2;
  background-image:
    repeating-linear-gradient(90deg, rgba(150, 128, 92, .055) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(0deg,  rgba(150, 128, 92, .045) 0 1px, transparent 1px 4px),
    radial-gradient(120% 90% at 30% 10%, rgba(255, 252, 243, .85), transparent 60%),
    radial-gradient(130% 100% at 80% 95%, rgba(176, 150, 104, .20), transparent 55%);
  color: #221c12;
  /* The dog-ear corner is absolutely positioned against the page. */
  position: relative;
  display: flex; flex-direction: column;
  /* Aged edges, so the sheet looks like paper rather than a rectangle. */
  box-shadow:
    inset 0 0 44px rgba(126, 100, 58, .26),
    inset 0 0 120px rgba(126, 100, 58, .10);
}
/* The gutter shadow, i.e. the only reason this looks like paper folded
   at a spine rather than two boxes side by side. */
.faf-leaf-l .faf-page { box-shadow: inset 0 0 44px rgba(126,100,58,.26), inset -26px 0 30px -24px rgba(60, 44, 20, .55); }
.faf-leaf-r .faf-page { box-shadow: inset 0 0 44px rgba(126,100,58,.26), inset 26px 0 30px -24px rgba(60, 44, 20, .55); }
.faf-page.is-blank { opacity: .30; }

.faf-page-body {
  /* overflow: hidden, not auto. The layout engine decides what fits, so
     there is nothing left to scroll -- and a scrollbar inside a page that
     also has a turn arrow was exactly what made the reader unsure which
     one moved them forward. Pete, 2026-10-28: "the only thing that we're
     showing the reader is what's on the page and that fits on one
     screen." */
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  font-family: 'Playfair Display', Georgia, 'Times New Roman', serif;
  font-size: 1.02rem; line-height: 1.7; color: #221c12;
  /* A measure, not a width: ~66 characters is where prose stops being
     tiring to read, and it is why this is a book and not a web page. */
  max-width: 34em;
}
.faf-page-body p { margin: 0 0 1.05em; }
/* No indent on the opening paragraph, indent on every one after -- the
   typographic convention every printed book follows. */
.faf-page-body p + p { text-indent: 1.4em; margin-top: -.35em; }
/* The tail of a paragraph that was split across a page break is not a new
   paragraph, so it takes no indent -- otherwise a sentence appears to
   start fresh halfway through itself. */
.faf-page-body p.is-cont { text-indent: 0; }
/* A section headline reaches the app as an ordinary paragraph -- the
   manuscript has no markup -- so without this it reads as body prose.
   Pete, 2026-10-28: "the headlines actually are bold and a bigger font."
   Sized in em so the whole scale follows the body down to a phone
   instead of needing its own number in every breakpoint. */
.faf-page-body .faf-h {
  font-size: 1.34em; line-height: 1.24; font-weight: 700;
  color: #1a1408;
  margin: .9em 0 .5em;
  /* Beats the p + p indent wherever a headline falls on the page. */
  text-indent: 0;
}
/* A headline that opens a page needs no space above it. */
.faf-page-body .faf-h:first-child { margin-top: 0; }
/* The paragraph under a headline starts flush, exactly as the opening
   paragraph of a chapter does -- indented, it reads as a continuation of
   the headline rather than the start of the section. */
.faf-page-body .faf-h + p { text-indent: 0; margin-top: 0; }
.faf-page-no {
  /* A fixed box, so a page number of "7" and one of "107" -- and the empty
     one in the measuring scaffold -- all leave the body exactly the same
     height to fill. Otherwise the layout measures against one box and
     renders into another, and the page count moves as the reader turns. */
  min-height: 1.1em;
  flex: 0 0 auto; padding-top: 14px; text-align: center;
  font-size: .74rem; letter-spacing: .14em; color: rgba(60, 46, 22, .5);
  font-variant-numeric: tabular-nums;
}

/* ---- what the reader can do, said out loud ---- */
/* The marking tools only appear on a selection, so without this line
   nobody discovers them. Quiet, one line, above the book. */
.faf-tools {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  margin: 0 0 10px; font-size: .82rem; color: var(--text-faint);
}
.faf-tool { display: inline-flex; align-items: center; gap: 7px; }
/* The gold swatch and the CSS triangle that used to live here are gone:
   they were abstractions of the tools rather than pictures of them, and
   neither told anybody what the tool did. A highlighter, a sticky note
   and a floppy-eared dog do. */
.faf-tool svg { flex: 0 0 auto; color: var(--gold); }
.faf-tool-link { margin-left: auto; color: var(--gold); }

@media (max-width: 820px) {
  /* On a phone the two hints wrap to two lines and the link to a third,
     which is more furniture than the page can spare above a book. */
  .faf-tools { gap: 10px 14px; font-size: .78rem; }
  .faf-tool-link { margin-left: 0; }
}

/* ---- the reader's own marks ---- */
/* Gold at low alpha rather than a flat fill: the page is dark, so a solid
   highlighter colour would bury the serif text it is meant to pick out. */
/* On cream paper a highlight has to read as ink laid over the page, not as
   a dark swatch -- so it is a warm amber wash with a drawn underline. */
.faf-hl {
  background: rgba(214, 170, 54, .34); color: inherit;
  border-radius: 2px; padding: .05em 0; cursor: pointer;
  box-shadow: 0 1px 0 rgba(150, 112, 20, .55);
}
.faf-hl:hover { background: rgba(214, 170, 54, .55); }
.faf-hl:focus-visible { outline: 2px solid #8a6a12; outline-offset: 2px; }
/* A highlight carrying a note earns a visible difference from one that is
   only a stripe of colour -- otherwise the reader has to click every mark
   to find the one they wrote on. */
.faf-hl.has-note { border-bottom: 2px solid #8a6a12; }
.faf-hl.has-note::after {
  content: '✎'; font-size: .72em; vertical-align: super;
  margin-left: .18em; color: #6d520c; opacity: .95;
}

/* The dog-ear is the page corner itself: a triangle that is flat when the
   page is unmarked and folded when it is. It sits inside the page's own
   padding so it never covers a word. */
.faf-ear {
  position: absolute; top: 0; right: 0; width: 34px; height: 34px;
  padding: 0; border: 0; background: transparent; cursor: pointer; z-index: 2;
  -webkit-appearance: none; appearance: none;
}
/* Unturned: a faint crease showing the corner can be folded. */
.faf-ear::after {
  content: ''; position: absolute; top: 0; right: 0;
  border-style: solid; border-width: 0 16px 16px 0;
  border-color: transparent rgba(126, 100, 58, .45) transparent transparent;
  opacity: .5; transition: opacity .18s, border-width .18s;
}
.faf-ear:hover::after { opacity: 1; }
.faf-ear:focus-visible { outline: 2px solid #8a6a12; outline-offset: -2px; }
/* Turned: the folded flap, shaded as the back of the sheet. */
.faf-page.is-eared .faf-ear::after {
  border-width: 0 28px 28px 0;
  border-color: transparent #c2ad83 transparent transparent;
  opacity: 1;
}
/* Turning the corner down: the flap swings past where it settles, which is
   what makes it read as a fold rather than a colour change. Pete,
   2026-10-28: "have that page fold a little bit more". */
.faf-page.is-folding .faf-ear::after,
.faf-page.is-folding .faf-ear::before { animation: faf-fold .42s cubic-bezier(.3, 1.4, .5, 1); }
@keyframes faf-fold {
  0%   { border-width: 0 16px 16px 0; }
  55%  { border-width: 0 42px 42px 0; }
  100% { border-width: 0 28px 28px 0; }
}
.faf-page.is-folding .faf-ear::before {
  animation-name: faf-fold-under;
}
@keyframes faf-fold-under {
  0%   { border-width: 16px 0 0 16px; }
  55%  { border-width: 42px 0 0 42px; }
  100% { border-width: 28px 0 0 28px; }
}
@media (prefers-reduced-motion: reduce) {
  .faf-page.is-folding .faf-ear::after,
  .faf-page.is-folding .faf-ear::before { animation: none; }
}

/* The hole the fold leaves behind, showing the page underneath. */
.faf-page.is-eared .faf-ear::before {
  content: ''; position: absolute; top: 0; right: 0;
  border-style: solid; border-width: 28px 0 0 28px;
  border-color: #d9cdb0 transparent transparent transparent;
  filter: brightness(.92);
}
.faf-leaf-r .faf-page .faf-ear { right: 0; }

/* The selection toolbar. Fixed, because it is positioned from a viewport
   rect, and above the book's own stacking context. */
/* Always in the DOM, shown by .is-on. Rebuilding this node on every
   selectionchange is what made it strobe while the reader dragged. Only
   opacity and a small lift animate; `left`/`top` are set without
   transition so the bar tracks the words exactly while the page scrolls
   rather than easing along behind them. */
.faf-markbar {
  position: fixed; z-index: 60; display: flex; gap: 2px;
  background: #121212; border: 1px solid var(--gold-soft);
  border-radius: 5px; padding: 3px; box-shadow: 0 8px 26px rgba(0, 0, 0, .6);
  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity .12s ease, transform .12s ease, visibility .12s;
  pointer-events: none;
}
.faf-markbar.is-on {
  opacity: 1; visibility: visible; transform: none; pointer-events: auto;
}
/* Scrolled away from the passage it belongs to: dimmed, still usable. */
.faf-markbar.is-off-text { opacity: .35; }
.faf-markbar.is-off-text:hover { opacity: 1; }
.faf-markbar-actions { display: flex; gap: 2px; }
.faf-markbar-actions button {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: transparent; color: var(--text-primary);
  font: inherit; font-size: .84rem; padding: 7px 12px;
  border-radius: 3px; cursor: pointer; white-space: nowrap;
}
.faf-markbar-actions button svg { opacity: .7; }
.faf-markbar-actions button:hover { background: var(--gold); color: var(--on-primary); }
.faf-markbar-actions button:hover svg { opacity: 1; }
/* A miniature of the real corner, so the button and the thing it does
   look like each other. */
.faf-ear-ico {
  width: 0; height: 0; flex: 0 0 auto;
  border-style: solid; border-width: 0 12px 12px 0;
  border-color: transparent var(--gold) transparent transparent;
}
.faf-markbar-actions button:hover .faf-ear-ico {
  border-right-color: var(--on-primary);
}

/* The note composer: the toolbar's other face. Swapped by a class so the
   node is never rebuilt, which is what used to make it flicker. */
.faf-markbar-note { display: none; width: min(340px, 90vw); }
.faf-markbar.is-noting .faf-markbar-actions { display: none; }
.faf-markbar.is-noting .faf-markbar-note { display: block; }
.faf-markbar-note textarea {
  width: 100%; resize: vertical; min-height: 68px;
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 3px;
  font: inherit; font-size: .9rem; padding: 8px 10px;
}
.faf-markbar-note textarea:focus { outline: 2px solid var(--gold); outline-offset: -1px; }
.faf-markbar-note-foot { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.faf-markbar-spacer { flex: 1 1 auto; }
/* Remove belongs to an existing mark, so it is absent while writing a new one. */
.faf-note-remove { display: none; }
.faf-markbar.is-editing .faf-note-remove { display: inline-flex; }

@media (prefers-reduced-motion: reduce) {
  .faf-markbar { transition: none; transform: none; }
}

/* ---- My notes ---- */
.faf-note-row { display: flex; align-items: flex-start; gap: 14px; }
.faf-note-row .mod-body { flex: 1 1 auto; min-width: 0; }
.faf-note-page {
  display: inline-block; margin-bottom: 6px; font-size: .78rem;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-secondary);
}
.faf-note-quote {
  margin: 0; padding-left: 14px; border-left: 2px solid var(--gold-soft);
  font-family: 'Playfair Display', Georgia, serif; font-style: italic;
  color: var(--text-primary); line-height: 1.6;
}
.faf-note-body { margin: 10px 0 0; color: var(--text-secondary); }

/* ---- Ask Pete ---- */
.faf-ask-strip .card { border-left: 3px solid var(--gold); }
.faf-thread { display: flex; align-items: center; gap: 14px; text-decoration: none; }
.faf-thread .mod-body { flex: 1 1 auto; min-width: 0; }

.faf-turn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 42px; height: 42px; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center;
  background: rgba(9, 9, 9, .72); color: var(--gold);
  border: 1px solid var(--gold-soft);
  transition: background .18s, opacity .18s;
}
.faf-turn:hover:not(:disabled) { background: var(--gold); color: var(--on-primary); }
.faf-turn:disabled { opacity: .22; cursor: default; }
.faf-turn-prev { left: 10px; }
.faf-turn-next { right: 10px; }

.faf-book-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; }
/* The phone layout: the arrows the spread hangs on the board's outer edges
   sit in this row instead, with the page count between them. Specificity
   is what keeps them full size -- the 820px block below shrinks a bare
   .faf-turn to 34px, and a two-class selector outranks it wherever it
   appears in the file. */
.faf-book-foot.has-turns { gap: 12px; margin-top: 12px; }
.faf-book-foot .faf-turn {
  position: static; transform: none; flex: 0 0 auto;
  width: 44px; height: 44px;
}
.faf-book-foot.has-turns .field-hint { text-align: center; }
.faf-chapter-nav { display: flex; justify-content: space-between; align-items: center; gap: 16px; }

@media (max-width: 820px) {
  /* One page instead of a spread, so the same character count needs
     roughly twice the height it does on a two-page desktop view. */
  /* One leaf instead of a spread. The height is driven by the viewport so
     the whole page is on screen with the app's chrome around it -- 100dvh
     rather than vh because mobile browsers shrink the viewport when the
     address bar retracts, and vh would leave the last line under it. */
  .faf-book { height: min(72dvh, 640px); padding: 7px; }
  .faf-book::before, .faf-book::after { width: 5px; top: 10px; bottom: 10px; }
  .faf-page { padding: 26px 20px 22px; }
  .faf-page-body { font-size: 1rem; line-height: 1.66; max-width: none; }
  /* The turn arrows sit over the text on a narrow page, so they shrink and
     move to the very edge, and the text keeps clear of them. */
  .faf-turn { width: 34px; height: 34px; }
  /* Tucked in tighter on a phone so a thumb reaching for the edge of the
     screen does not land on the button by accident while scrolling. */
  .faf-turn-prev { left: 4px; }
  .faf-turn-next { right: 4px; }
}

@media (prefers-reduced-motion: reduce) {
  .faf-leaf { transition: none; }
  .faf-book.is-turning-fwd .faf-leaf-r,
  .faf-book.is-turning-back .faf-leaf-l { transform: none; }
}

/* ---------------------------------------------------------------
   The reading nook

   Pete, 2026-10-27: "make it look like a book shelf design with the book
   on it. make it cozy and inviting inside."

   Cozy is light, not ornament. Three things do the work and nothing else
   is decoration: a warm lamp falling from the upper left, real contact
   shadows where objects meet the plank, and the book sitting a few
   degrees off square so it reads as something a person set down. One
   12 KB cover image; the shelf, the spines, the grain and the glow are
   all CSS, and all of them take their colour from the brand's --gold, so
   a rebrand repaints the room instead of stranding it.
---------------------------------------------------------------- */
.faf-nook {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: space-between;
  gap: 32px; flex-wrap: wrap;
  margin: 0 0 26px; padding: 34px 36px 0;
  border: 1px solid var(--gold-soft); border-radius: 6px;
  /* The lamp: a warm pool of light from the upper left over a deep,
     slightly brown-shifted dark. Two stops, because a single radial on
     flat black reads as a spotlight rather than a room. */
  background:
    radial-gradient(120% 90% at 12% 0%, rgba(190, 158, 68, .17) 0%, rgba(190, 158, 68, .05) 38%, transparent 68%),
    linear-gradient(170deg, #17130c 0%, var(--bg) 58%);
}
/* The vignette, which is what stops the panel looking like a rectangle
   of gradient and starts it looking like a corner of a room. */
.faf-nook::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 90px 10px rgba(0, 0, 0, .55);
}

.faf-nook-copy { position: relative; z-index: 1; flex: 1 1 290px; padding-bottom: 34px; }
.faf-nook-copy h1 {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(1.6rem, 3.4vw, 2.2rem); line-height: 1.12;
  margin: 0 0 10px; color: var(--text-primary);
}
.faf-nook-copy p { margin: 0 0 18px; color: var(--text-secondary); max-width: 44ch; }

/* ---- the shelf ----
   The plank runs off the right edge of the panel on purpose. Stopping it
   a few pixels short read as a clipping bug rather than a shelf; running
   it out of frame reads as a board fixed to a wall that continues past
   what you can see, which is what makes the corner feel like a room. The
   negative margin matches .faf-nook's own right padding. */
.faf-shelf {
  position: relative; z-index: 1; flex: 0 1 auto; align-self: flex-end;
  margin-right: -36px;
}
.faf-shelf-items {
  display: flex; align-items: flex-end; justify-content: center; gap: 10px;
  padding: 0 40px 0 30px;
}

/* The plank. The grain is a repeating gradient at a shallow angle rather
   than a texture file -- at this size it is indistinguishable and it
   costs nothing. The lighter top edge is the lit face of the board. */
.faf-plank {
  height: 16px; border-radius: 2px 0 0 2px;
  /* Wider than the books it carries. A plank that ends exactly where the
     last spine does is a pedestal, not a shelf. */
  margin-left: -14px;
  background:
    linear-gradient(180deg, #6b4f2a 0%, #4a371d 24%, #2e2212 100%),
    repeating-linear-gradient(97deg, rgba(0, 0, 0, .22) 0 2px, transparent 2px 11px);
  background-blend-mode: overlay, normal;
  box-shadow:
    0 1px 0 rgba(216, 198, 144, .22) inset,   /* the lit front edge */
    0 14px 26px -12px rgba(0, 0, 0, .9);      /* the board's own shadow */
}

/* The book. Tilted, lifted, and casting onto the plank. The ::after is
   the contact shadow -- without it the book floats and the whole scene
   collapses into a flat collage. */
.faf-book3d { position: relative; transform: rotate(-1.6deg); transform-origin: bottom center; }
.faf-book3d img {
  display: block; width: 132px; height: auto; border-radius: 2px 4px 4px 2px;
  box-shadow:
    0 18px 26px -14px rgba(0, 0, 0, .95),
    0 0 0 1px rgba(216, 198, 144, .16);
}
/* The spine: a sliver down the left edge, darker than the cover, which is
   what gives a flat jpg its thickness. */
.faf-book3d::before {
  content: ''; position: absolute; left: -5px; top: 2px; bottom: 0; width: 6px;
  border-radius: 2px 0 0 2px;
  background: linear-gradient(90deg, #0a0a0a, #241f17 60%, #0f0d0a);
  box-shadow: inset 1px 0 0 rgba(216, 198, 144, .12);
}
.faf-book3d::after {
  content: ''; position: absolute; left: -14px; right: -8px; bottom: -6px; height: 12px;
  background: radial-gradient(60% 100% at 50% 0%, rgba(0, 0, 0, .78), transparent 72%);
  filter: blur(2px);
}

/* The companion volumes, stood up either side. Slightly shorter than the
   book so the cover stays the subject. */
.faf-vol {
  width: 26px; height: 118px; border-radius: 2px 3px 3px 2px;
  display: grid; place-items: center;
  box-shadow: 0 14px 20px -12px rgba(0, 0, 0, .9), inset -2px 0 0 rgba(0, 0, 0, .35);
}
.faf-vol span {
  writing-mode: vertical-rl; transform: rotate(180deg);
  font-size: .6rem; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255, 253, 253, .72); white-space: nowrap;
}
.faf-vol-audio { background: linear-gradient(180deg, #3a2f14, #221b0d); transform: rotate(1.4deg); transform-origin: bottom center; }
.faf-vol-work  { background: linear-gradient(180deg, #4a371d, #2a1f10); height: 126px; }

/* Locked: the lamp is dimmed rather than the shelf removed. Someone who
   has not bought it should still see the room they are being invited
   into -- that is the pitch. */
.faf-nook.is-locked .faf-book3d img { filter: saturate(.72) brightness(.82); }
.faf-nook.is-locked::after { box-shadow: inset 0 0 90px 22px rgba(0, 0, 0, .72); }

@media (max-width: 720px) {
  .faf-nook { padding: 26px 22px 0; gap: 18px; }
  .faf-nook-copy { padding-bottom: 8px; }
  .faf-shelf { width: 100%; }
  .faf-book3d img { width: 112px; }
  .faf-vol { height: 100px; }
  .faf-vol-work { height: 106px; }
}

@media (prefers-reduced-motion: reduce) {
  .faf-book3d, .faf-vol-audio { transform: none; }
}

/* The thank-you page's "here is what you just unlocked" list. */
.faf-unlocked { margin: 0; padding-left: 20px; color: var(--text-secondary); }
.faf-unlocked li { margin: 4px 0; }
.faf-unlocked strong { color: var(--text-primary); }

/* The thank-you page as seen by somebody with no account yet: no sidebar,
   no chrome, just the room they just bought their way into. Webinar
   Center Stage 2's public registration page is the same shape -- a
   stranger with a link and nothing else -- so it shares the rule
   rather than duplicating it. */
.faf-public, .webinar-public { max-width: 880px; margin: 0 auto; padding: 28px 20px 60px; }


/* ---- Read along ----

   Pete, 2026-10-29: "as they read, they're highlighting the words that
   are being read so that it's also accessible."

   The word itself is painted with ::highlight(), which draws over a
   Range without touching the DOM -- the paragraphs underneath already
   carry the reader's own <mark> highlights, and rewriting them four
   times a second would destroy those and kill any live selection.

   Deliberately a different colour from a reader's own highlight: one is
   something they chose and keeps, the other is a cursor that moves on.
   The reader's gold stays the mark of record. */
::highlight(faf-readalong) {
  background: rgba(96, 148, 214, .32);
  color: inherit;
}

/* The tabs and the transport share a line above the book. They wrap to
   two lines on a narrow phone rather than squeezing, because five
   controls crushed to 30px each is five controls nobody can hit. */
.faf-topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px 18px; flex-wrap: wrap; margin: 0 0 18px;
}
.faf-topbar .faf-modes { margin: 0; }

.faf-transport { display: flex; align-items: center; gap: 6px; }
.faf-transport .faf-play { gap: 7px; padding-left: 15px; padding-right: 17px; }
/* The ten sits BESIDE the arrow, not inside it. Inside, the digits land
   on the arc at any size a thumb-sized button allows, and both become
   unreadable -- checked at 375px before this was changed. */
.faf-tp { display: inline-flex; align-items: center; gap: 2px; padding: 0 9px; }
.faf-tp-n {
  font: 600 10px/1 var(--font-ui, inherit); letter-spacing: -.02em;
  pointer-events: none; opacity: .85;
}
.faf-transport .faf-tp { touch-action: none; }

@media (max-width: 420px) {
  /* The word goes, the triangle stays: at this width the row is the
     only thing that has to fit, and five targets matter more than a
     label that repeats the icon. */
  .faf-play-word { display: none; }
  .faf-transport .faf-play { padding-left: 13px; padding-right: 13px; }
  .faf-topbar { gap: 10px 12px; }
}

.faf-readalong { display: grid; gap: 12px; }
.faf-rl-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0; }

/* The switch: a track the knob slides left to right along, which is the
   control Pete described rather than a checkbox. */
.faf-switch {
  display: inline-flex; align-items: center; gap: 10px;
  background: none; border: 0; padding: 6px 0; cursor: pointer;
  color: var(--text-secondary); font: inherit; font-size: .86rem;
}
.faf-switch-track {
  position: relative; flex: 0 0 auto; width: 40px; height: 22px;
  border-radius: 999px; background: var(--surface-3);
  border: 1px solid var(--line-strong); transition: background .18s, border-color .18s;
}
.faf-switch-knob {
  position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--text-muted);
  transition: transform .18s ease, background .18s;
}
.faf-switch.is-on .faf-switch-track { background: var(--gold); border-color: var(--gold); }
.faf-switch.is-on .faf-switch-knob { transform: translateX(18px); background: var(--on-primary); }
.faf-switch.is-on { color: var(--text-primary); }
.faf-switch:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 4px; }

@media (prefers-reduced-motion: reduce) {
  .faf-switch-knob { transition: none; }
}

/* ---- Fulfilled AF on a phone ---- */
@media (max-width: 560px) {
  .faf-book { height: min(70dvh, 560px); }
  .faf-page { padding: 22px 16px 20px; }
  .faf-page-body { font-size: .98rem; }
  /* Both hints on their own lines, and the swatch/ear still beside the
     words they describe. */
  /* Pete, 2026-10-29: "lets add a couple more formatting things to
     tighten."

     Three hints on three full-width lines, plus the follow switch and its
     explanation, put the first line of the book 1,243px down a 768px
     screen -- more than a screen and a half of chrome before any reading.
     The icons are what carry the meaning here (that is why they were
     drawn), so on a phone the sentence shrinks to its verb and the three
     sit on one line. The full wording is still there on any screen with
     room for it. */
  .faf-tools { gap: 8px 14px; font-size: .8rem; }
  .faf-tool { flex: 0 1 auto; gap: 5px; }
  .faf-tool-more { display: none; }
  .faf-tool-link { flex: 0 0 auto; }
  /* The switch explains itself; the sentence under it does not earn its
     line at this width. */
  .faf-rl-foot .field-hint { display: none; }
  /* A tall plate should not own the whole screen on its own. Contained
     rather than cropped: the chapter art is line drawing and a crop cuts
     a limb off. */
  .faf-art img { max-height: 36vh; width: auto; max-width: 100%; margin: 0 auto; }
  /* A selection toolbar near the bottom of a phone screen is under the
     thumb that made the selection, so it gets more room to be tapped. */
  .faf-markbar button { padding: 10px 14px; font-size: .88rem; }
  /* On one column the art stacks above the quote and both run the full
     width of the page they introduce, so the three blocks share an edge
     instead of stepping in and out. */
  .faf-opener { gap: 18px; margin: 20px 0 14px; }
  .faf-art { flex: 1 1 100%; max-width: none; margin: 0; }
  .faf-epigraph { flex: 1 1 100%; }
  .faf-epigraph p { font-size: 1.1rem; }
}

/* ---- Touch: nothing a thumb has to hit is under 44px ----

   Pete, 2026-10-29: "Fix the undersized mobile tap targets."

   Gated on (hover: none) rather than a width, because what decides this
   is whether the pointer is a finger, not how wide the window is. A
   narrow desktop window still has a mouse and does not need 44px
   furniture; a tablet in landscape is wider than most laptops and does.

   Every rule here raises a minimum height. None of them changes a width,
   a font size or a colour, so a phone gets the same layout it has now
   with more room to land on. 44px is Apple's floor and WCAG 2.5.5's. */
@media (hover: none) {
  .faf-ear { width: 46px; height: 46px; }

  .btn, .btn-sm { min-height: 44px; }
  .icon-btn { min-width: 44px; min-height: 44px; }
  .nav-item { min-height: 44px; }
  .faf-mode { min-height: 44px; }
  .faf-markbar-actions button { min-height: 44px; }

  /* .linkbtn appears both on its own beside a heading and inline inside a
     sentence, so it cannot be made a block without breaking the sentences.
     Vertical padding is what grows an inline element's hit box without
     moving the text around it. */
  .linkbtn { padding: 12px 0; }

  /* A flex item in the hints row above the book, so it can take a height
     directly. */
  .faf-tool-link { display: inline-flex; align-items: center; min-height: 44px; }

  /* The anchor only. The same class is a plain date label on a free-standing
     note, and padding a label out to 44px would push the note down for
     nothing. */
  a.faf-note-page { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ---- the scratch note on My notes ---- */
.faf-scratch textarea { width: 100%; }
.faf-scratch-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px;
}
.faf-scratch-foot select { flex: 1 1 240px; min-width: 0; }
@media (max-width: 560px) {
  .faf-scratch-foot { gap: 8px; }
  .faf-scratch-foot select, .faf-scratch-foot .btn { flex: 1 1 100%; }
}

/* The line set beside a chapter's illustration -- chapter 11's
   "What's your ripple?". In the book's own serif, because it is the
   book speaking and not the app. */
.faf-art figcaption {
  margin-top: 10px; text-align: center;
  font-family: 'Playfair Display', Georgia, 'Times New Roman', serif;
  font-style: italic; font-size: 1.04rem; letter-spacing: .01em;
  color: var(--gold);
}

/* ---- resume, offered rather than imposed ---- */
.faf-resume-bar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 0 0 14px;
}
.faf-resume-bar .btn { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; }
@media (max-width: 560px) {
  .faf-resume-bar .btn { flex: 1 1 100%; justify-content: center; }
  .faf-resume-bar .field-hint { flex: 1 1 100%; }
}

/* Legal links under the sign-in card. Quiet by design -- present and
   reachable for anyone who looks, without competing with the one thing
   that screen is asking somebody to do. */
.auth-legal {
  text-align: center;
  margin: 10px 0 0;
  font-size: .82rem;
  color: var(--text-muted);
}
.auth-legal a { color: var(--text-muted); text-decoration: none; }
.auth-legal a:hover { color: var(--gold); text-decoration: underline; }

/* ---------------------------------------------------------------
   The Tools launcher: a grid of apps.

   Pete, 2026-10-29: "That dashboard will have icons on it. Those
   icons will be apps inside of the app." The whole tile is the
   link, so the press target is the app itself rather than a small
   button inside a paragraph -- which matters on the Vibe board,
   where this is operated by hand from arm's length.

   auto-fit with a 200px floor rather than a fixed column count:
   three apps centre themselves, and the day there are seven the
   grid rewraps instead of needing a new class.
---------------------------------------------------------------- */
.app-grid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.app-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 20px;
  min-height: 170px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}
.app-tile:hover,
.app-tile:focus-visible {
  border-color: var(--gold);
  transform: translateY(-2px);
}
.app-tile:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .app-tile { transition: none; } }

/* ---------------------------------------------------------------
   Client messages: a worked queue.

   Pete: "a tab on the side that shows ... if it's been attended to,
   if it's waiting, if it needs attention ... available there for
   internal service." A rail of states with live counts, so a VA can
   see the size of each pile without opening it.
---------------------------------------------------------------- */
.vm-bar { display: flex; gap: 10px; align-items: flex-end; margin-bottom: 14px; flex-wrap: wrap; }
.vm-search { flex: 1; min-width: 220px; margin-bottom: 0; }

.vm-layout { display: grid; grid-template-columns: 220px 1fr; gap: 14px; align-items: start; }
@media (max-width: 820px) { .vm-layout { grid-template-columns: 1fr; } }

.vm-rail { display: flex; flex-direction: column; gap: 4px; }
@media (max-width: 820px) { .vm-rail { flex-direction: row; overflow-x: auto; } }

.vm-rail-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; min-height: 44px; padding: 0 13px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px;
  background: transparent; color: inherit; font: inherit; font-size: .9rem;
  white-space: nowrap;
}
.vm-rail-item:hover { border-color: var(--gold); }
.vm-rail-item.is-active { background: var(--gold); border-color: transparent; color: #111; font-weight: 600; }
.vm-rail-count {
  min-width: 22px; text-align: center; font-variant-numeric: tabular-nums;
  font-size: .78rem; opacity: .7;
}
.vm-rail-item.is-active .vm-rail-count { opacity: .85; }
/* Only the unanswered pile earns a colour, and only when it is not
   empty: a permanently red tab is wallpaper. */
.vm-rail-item.is-hot:not(.is-active) { border-color: #d98574; }
.vm-rail-item.is-hot:not(.is-active) .vm-rail-count { color: #d98574; opacity: 1; font-weight: 600; }

.vm-row-acts { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.vm-note { font-style: italic; opacity: .75; }

.app-tile-mark { display: block; line-height: 0; margin-bottom: 2px; }
.app-tile-name { font-size: 1.02rem; font-weight: 600; }
.app-tile-blurb { font-size: .85rem; opacity: .65; line-height: 1.45; }

/* How many tools sit behind a launcher tile. A group tile hides what it
   contains, so the count is the one thing that tells you whether this
   is a door worth opening. */
.app-tile-count {
  display: block;
  margin-top: 8px;
  font-size: .76rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: .8;
}
