/* ============== TOKENS ============== */
:root {
  /* Linen / pre-dawn surface */
  --bg: #f4efe5;
  --bg-deeper: #ece5d6;
  --surface: #faf6ec;
  --surface-2: #ffffff;
  --ink: #2c2a26;
  --ink-2: #5b574e;
  --ink-3: #8d877b;
  --hairline: #d9d2c1;
  --hairline-soft: #e6dfce;

  /* Disc "page" — the parchment surface of the inner circle */
  --disc-page: #fbf8f0;
  --disc-glow: rgba(255, 255, 255, 0.55);

  /* Five categories — pigment hues, slightly desaturated for paper feel */
  --cat-self: #2f7c83;       /* tide deep teal */
  --cat-outdoors: #4f7a3c;   /* moss / forest green */
  --cat-people: #b85546;     /* rosehip warm red */
  --cat-play: #c89441;       /* brass amber gold */
  --cat-work: #6b7a86;       /* slate cool grey-blue (desat) */

  /* Gilded */
  --gilt: #c9a04d;
  --gilt-soft: #e8c878;

  /* Type — Fraunces italic for voice, system sans for UI. The brand sits in
     the serif italic; the sans is invisible workhorse for buttons, labels,
     section markers. SOFT axis softens Fraunces away from glossy-editorial. */
  --serif: 'Fraunces', 'Iowan Old Style', 'Palatino', Georgia, serif;
  --sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  /* Motion */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

[data-theme='dark'] {
  --bg: #1a1916;
  --bg-deeper: #131210;
  --surface: #25231f;
  --surface-2: #2c2a25;
  --ink: #ece5d2;
  --ink-2: #b8b1a0;
  --ink-3: #807a6e;
  --hairline: #3a352d;
  --hairline-soft: #2e2a23;

  /* Dark mode: lift the disc "page" well above bg, warm it slightly so
     it reads as parchment under a low lamp — not a dark hole. */
  --disc-page: #4a4438;
  --disc-glow: rgba(255, 238, 200, 0.16);

  /* Dark mode: hues lifted a touch so they hold against deep parchment */
  --cat-self: #5da9b0;
  --cat-outdoors: #82a86d;
  --cat-people: #d57b6c;
  --cat-play: #e2b56c;
  --cat-work: #95a3ad;

  --gilt: #e0bf75;
  --gilt-soft: #f4d99a;
}

/* ============== BASE ============== */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* === Fraunces variable axes ===
   Tune the italic so it reads warm-noticed, not editorial-glossy:
   • opsz   9..144  — should MATCH rendered size
   • SOFT   0..100  — 100 = soft terminals, less editorial-axe
   We set per-element via --fr-opsz / --fr-soft. Fallbacks ignore safely. */
.brand,
.hero__title, .hero__title em,
.hero__obs,
.section-head h2, .section-head h2 em,
.state-card__name,
.state-card__body,
.strip-item__sub,
.story-panel__title, .story-panel__title em,
.story-panel__body,
.story-cta__title,
.footer .brand__name, .footer .footer__tag,
.disc__num {
  font-variation-settings: 'opsz' var(--fr-opsz, 24), 'SOFT' var(--fr-soft, 100);
}

/* Per-element opsz + weight tuning — lighter than 400 so the italic reads
   noticed, not editorial-bold. !important on weight to defeat earlier
   font-weight: 400 declarations on the same elements. */
.hero__title,
.hero__title em        { --fr-opsz: 84; font-weight: 340 !important; }
.hero__obs             { --fr-opsz: 22; font-weight: 380 !important; }
.section-head h2,
.section-head h2 em    { --fr-opsz: 52; font-weight: 340 !important; }
.state-card__name      { --fr-opsz: 22; font-weight: 380 !important; }
.state-card__body      { --fr-opsz: 14; --fr-soft: 80; font-weight: 400; }
.strip-item__sub       { --fr-opsz: 14; --fr-soft: 80; font-weight: 400; }
.disc__num             { --fr-opsz: 96; font-weight: 340 !important; }
.story-panel__title,
.story-panel__title em { --fr-opsz: 52; font-weight: 340 !important; }
.story-panel__body     { --fr-opsz: 18; font-weight: 400; }
.story-cta__title      { --fr-opsz: 32; font-weight: 380 !important; }
.brand                 { --fr-opsz: 22; font-weight: 400; }
.footer .brand__name   { --fr-opsz: 20; font-weight: 400; }
.footer .footer__tag   { --fr-opsz: 16; font-weight: 380; }

body {
  background:
    radial-gradient(1200px 800px at 80% -10%, rgba(255, 240, 210, 0.55), transparent 60%),
    radial-gradient(900px 600px at 5% 100%, rgba(255, 235, 205, 0.35), transparent 65%),
    var(--bg);
  min-height: 100vh;
}
[data-theme='dark'] body {
  background:
    radial-gradient(1200px 800px at 80% -10%, rgba(120, 95, 60, 0.20), transparent 60%),
    radial-gradient(900px 600px at 5% 100%, rgba(80, 70, 50, 0.18), transparent 65%),
    var(--bg);
}

a { color: inherit; }
button { font-family: inherit; cursor: pointer; }

/* ============== TOPBAR ============== */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px clamp(20px, 4vw, 56px);
  border-bottom: 1px solid var(--hairline-soft);
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
}

.brand { display: flex; align-items: center; gap: 10px; font-family: var(--serif); font-size: 22px; }
.brand__mark { width: 22px; height: 22px; color: var(--ink); }
.brand__tag {
  margin-left: 14px;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 3px 10px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
}

.theme-toggle {
  width: 38px;
  height: 38px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--ink-2);
  display: grid;
  place-items: center;
  transition: all 0.2s var(--ease);
}
.theme-toggle:hover { color: var(--ink); border-color: var(--ink-3); }

/* ============== PAGE ============== */
.page {
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(40px, 6vw, 80px) clamp(20px, 4vw, 56px) 80px;
}

.eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 18px;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
}
.eyebrow .dot { width: 6px; height: 6px; border-radius: 999px; background: var(--cat-self); display: inline-block; }

.kicker {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 12px;
}

.section-head {
  margin: 0 0 28px;
  text-align: left;
  max-width: 60ch;
}
.section-head h2 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(34px, 5vw, 52px);
  margin: 0 0 12px;
  letter-spacing: -0.01em;
}
.section-head .lede {
  color: var(--ink-2);
  font-size: 16px;
  margin: 0;
}

/* ============== HERO ============== */
.hero {
  text-align: center;
  margin: 0 auto clamp(56px, 8vw, 96px);
  max-width: 740px;
}
.hero .eyebrow { margin-bottom: 20px; }
.hero__title {
  font-family: var(--serif);
  font-size: clamp(44px, 7.5vw, 88px);
  line-height: 1.02;
  margin: 0 0 16px;
  font-weight: 400;
  letter-spacing: -0.02em;
}
.hero__obs {
  color: var(--ink-2);
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 2.4vw, 24px);
  margin: 0 0 36px;
  min-height: 1.6em;
  transition: opacity 0.4s var(--ease);
}

.stage {
  display: grid;
  place-items: center;
  margin: 0 0 28px;
}

/* ============== DISC (the painterly v2) ============== */
.disc-wrap {
  width: clamp(280px, 50vw, 460px);
  aspect-ratio: 1 / 1;
  position: relative;
  display: block;
}
.disc-wrap--small { width: 100%; max-width: 140px; }
.disc-wrap--med { width: 100%; max-width: 200px; }
.disc-wrap--story { width: clamp(220px, 50vw, 300px); }

/* The .disc element receives custom properties --disc-inner-r, --disc-band-outer-r, --disc-thickness */
.disc-wrap.disc {
  /* nothing extra; layers absolute-position inside */
}

/* Each layer fills the wrapper */
.disc__breath,
.disc__band,
.disc__lume,
.disc__flow,
.disc__gilt,
.disc__paper,
.disc__empty-hint,
.disc__sectors,
.disc__bloom {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* === BREATH halo (radial pulse from centre, very subtle) ===
   Lives BEHIND the band. We size it to roughly 1.4× the band so it spills
   gently outside, then blur and pulse it. */
.disc__breath {
  --outer: var(--disc-band-outer-r, 42%);
  inset: calc(50% - var(--outer) - 8%);
  width: calc(2 * (var(--outer) + 8%));
  height: calc(2 * (var(--outer) + 8%));
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 50%,
    color-mix(in srgb, var(--cat-people) 22%, transparent) 0%,
    color-mix(in srgb, var(--cat-play) 16%, transparent) 30%,
    color-mix(in srgb, var(--cat-self) 10%, transparent) 55%,
    transparent 85%
  );
  filter: blur(22px);
  opacity: 0.45;
  transform-origin: 50% 50%;
  animation: discBreath 7.5s ease-in-out infinite;
  z-index: 0;
}
@keyframes discBreath {
  0%, 100% { transform: scale(0.94); opacity: 0.35; }
  50%      { transform: scale(1.06); opacity: 0.55; }
}
[data-theme='dark'] .disc__breath {
  opacity: 0.6;
  filter: blur(28px);
}

/* === BAND (the painted ring) ===
   conic-gradient set via inline style on the element.
   The band element is sized to match the outer band radius so we can use
   simple radial percentages (0% center, 100% rim).
   The painted ring + feathered edges are then a clean radial mask. */
.disc__band {
  /* The outer band radius as a percentage of the disc box. */
  --outer: var(--disc-band-outer-r, 42%);
  /* Inner page radius as a percentage of the disc box. */
  --inner: var(--disc-inner-r, 28%);
  /* Inner radius as % of the band's own (smaller) box. */
  --inner-pct: calc(var(--inner) / var(--outer) * 100%);

  /* The conic density mask is set inline by JS via --density-mask.
     Default to a uniform white so static demos still render. */
  --density-mask: conic-gradient(rgba(255,255,255,0.95), rgba(255,255,255,0.95));

  /* Position the band element at the band's outer radius, centred. */
  inset: calc(50% - var(--outer));
  width: calc(2 * var(--outer));
  height: calc(2 * var(--outer));
  border-radius: 50%;

  /* Two-layer mask: the radial mask shapes the ring (donut), the conic
     mask varies opacity by angle (brush pressure). They INTERSECT — you see
     the band only where BOTH masks allow it. */
  -webkit-mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent calc(var(--inner-pct) - 1%),
      rgba(0, 0, 0, 0.85) calc(var(--inner-pct) + 0.5%),
      #000 calc(var(--inner-pct) + 4%),
      #000 92%,
      rgba(0, 0, 0, 0.5) 97%,
      transparent 100%
    ),
    var(--density-mask);
  -webkit-mask-composite: source-in;
          mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent calc(var(--inner-pct) - 1%),
      rgba(0, 0, 0, 0.85) calc(var(--inner-pct) + 0.5%),
      #000 calc(var(--inner-pct) + 4%),
      #000 92%,
      rgba(0, 0, 0, 0.5) 97%,
      transparent 100%
    ),
    var(--density-mask);
          mask-composite: intersect;
  filter: saturate(1.0) contrast(1.02);
  z-index: 1;
}

/* === LUME (depth / brightness) ===
   v3.2: a separate brightness layer driven by a depth conic that scales with
   raw log count (independent of mask alpha). Sits over the band and only
   contributes where a category was lived in *multiple times*. Uses the same
   ring shape as the band so it never bleeds outside the painted area.
   Blend mode 'overlay' lifts mid-tones without blowing out hue, so a heavy
   category sings while empty/light ones stay untouched. */
.disc__lume {
  --outer: var(--disc-band-outer-r, 42%);
  --inner: var(--disc-inner-r, 28%);
  --inner-pct: calc(var(--inner) / var(--outer) * 100%);
  --density-mask: conic-gradient(rgba(255,255,255,0), rgba(255,255,255,0));

  inset: calc(50% - var(--outer));
  width: calc(2 * var(--outer));
  height: calc(2 * var(--outer));
  border-radius: 50%;

  background: rgba(255, 252, 245, 1);

  /* Same intersect: ring shape × lume-density conic. */
  -webkit-mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent calc(var(--inner-pct) - 1%),
      rgba(0, 0, 0, 0.85) calc(var(--inner-pct) + 0.5%),
      #000 calc(var(--inner-pct) + 4%),
      #000 92%,
      rgba(0, 0, 0, 0.5) 97%,
      transparent 100%
    ),
    var(--density-mask);
  -webkit-mask-composite: source-in;
          mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent calc(var(--inner-pct) - 1%),
      rgba(0, 0, 0, 0.85) calc(var(--inner-pct) + 0.5%),
      #000 calc(var(--inner-pct) + 4%),
      #000 92%,
      rgba(0, 0, 0, 0.5) 97%,
      transparent 100%
    ),
    var(--density-mask);
          mask-composite: intersect;

  mix-blend-mode: overlay;
  filter: blur(1.5px);
  opacity: 0.7;
  z-index: 2;
}
[data-theme='dark'] .disc__lume {
  /* In dark mode 'overlay' tends to read as colour-shift, screen reads as
     a clean lift. Drop opacity a touch so it doesn't wash out hue. */
  mix-blend-mode: screen;
  opacity: 0.45;
}

/* === BLOOM (outer bristle) ===
   Same hue conic, sized slightly larger than the band, masked by a soft
   outer-edge radial × the bloom-density conic. Where a category was heavy
   it spills outward into the linen like a brush bleeding off the page. */
.disc__bloom {
  --outer: var(--disc-band-outer-r, 42%);
  --bloom-extend: 8%;            /* how far past the band the bloom reaches */
  --density-mask: conic-gradient(rgba(255,255,255,0), rgba(255,255,255,0));

  inset: calc(50% - var(--outer) - var(--bloom-extend));
  width: calc(2 * (var(--outer) + var(--bloom-extend)));
  height: calc(2 * (var(--outer) + var(--bloom-extend)));
  border-radius: 50%;

  /* Outer-edge radial fade: only show pigment in a ring just past the band’s
     outer edge, fading rapidly into linen. The conic-density mask then
     selects WHICH angles bloom. */
  -webkit-mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent 78%,
      rgba(0,0,0,0.55) 86%,
      rgba(0,0,0,0.35) 92%,
      transparent 100%
    ),
    var(--density-mask);
  -webkit-mask-composite: source-in;
          mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent 78%,
      rgba(0,0,0,0.55) 86%,
      rgba(0,0,0,0.35) 92%,
      transparent 100%
    ),
    var(--density-mask);
          mask-composite: intersect;
  filter: blur(3px) saturate(1.05);
  opacity: 0.85;
  z-index: 0;
  pointer-events: none;
}
[data-theme='dark'] .disc__bloom {
  opacity: 0.55;
  filter: blur(3.5px) saturate(1.1);
}

/* Empty state hint: a faint hairline ring just outside the page */
.disc__empty-hint {
  border-radius: 50%;
  --inner: var(--disc-inner-r, 28%);
  border: 1px dashed var(--hairline);
  inset: calc(50% - var(--inner) - 2%);
  width: calc(2 * var(--inner) + 4%);
  height: calc(2 * var(--inner) + 4%);
  opacity: 0.5;
  pointer-events: none;
}

/* === SEGMENTED UNDERLAY (variant: sectors) =========================== */
/* A separate ring beneath the band, painted as 5 fixed-position sectors. */
/* Each sector is one category at its home angle, opacity proportional to */
/* count. The band sits ON TOP at full opacity, so this layer only bleeds */
/* through at the band's outer edge — a faint compositional reading.     */
.disc__sectors {
  /* Sized slightly LARGER than the band so a thin ring of sector tint   */
  /* shows just outside the band's outer edge, like a coloured halo.      */
  --outer: calc(var(--disc-band-outer-r, 42%) + 4.5%);
  --inner: var(--disc-inner-r, 28%);
  --inner-pct: calc(var(--inner) / var(--outer) * 100%);

  inset: calc(50% - var(--outer));
  width: calc(2 * var(--outer));
  height: calc(2 * var(--outer));
  border-radius: 50%;

  /* Conic background is set inline (5 sector hard-edged gradient). */

  /* Donut mask only — no per-angle density mask here. The conic itself */
  /* carries per-sector alpha. Soft inner cut to avoid a hard hairline.  */
  -webkit-mask: radial-gradient(
    circle at 50% 50%,
    transparent 0,
    transparent calc(var(--inner-pct) - 1%),
    rgba(0,0,0,0.6) calc(var(--inner-pct) + 1%),
    #000 calc(var(--inner-pct) + 4%),
    #000 86%,
    rgba(0,0,0,0.55) 94%,
    transparent 100%
  );
          mask: radial-gradient(
    circle at 50% 50%,
    transparent 0,
    transparent calc(var(--inner-pct) - 1%),
    rgba(0,0,0,0.6) calc(var(--inner-pct) + 1%),
    #000 calc(var(--inner-pct) + 4%),
    #000 86%,
    rgba(0,0,0,0.55) 94%,
    transparent 100%
  );
  /* v3.9: wider blur so sector boundaries dissolve into watercolour     */
  /* edges rather than reading as a pie chart. Lower base opacity carries */
  /* the rest of the ~20% softening; the alpha curve in app.js does the   */
  /* real work.                                                            */
  filter: blur(5px) saturate(0.9);
  opacity: 0.78;
  pointer-events: none;
  z-index: 0; /* below band (z=1) so band paints over the inner area */
}
[data-theme='dark'] .disc__sectors {
  filter: blur(5px) saturate(1.05) brightness(1.1);
  opacity: 0.92;
}

/* === FLOW WAVE (additive lighter highlight, rotating) ===
   Sized like the band so we can use the same simple 0–100% radial coords. */
.disc__flow {
  --outer: var(--disc-band-outer-r, 42%);
  --inner: var(--disc-inner-r, 28%);
  --inner-pct: calc(var(--inner) / var(--outer) * 100%);
  --density-mask: conic-gradient(rgba(255,255,255,1), rgba(255,255,255,1));

  inset: calc(50% - var(--outer));
  width: calc(2 * var(--outer));
  height: calc(2 * var(--outer));
  border-radius: 50%;

  background: conic-gradient(
    from 0deg,
    rgba(255, 255, 255, 0) 0deg,
    rgba(255, 255, 255, 0) 300deg,
    rgba(255, 255, 255, 0.45) 340deg,
    rgba(255, 255, 255, 0.85) 360deg,
    rgba(255, 255, 255, 0.45) 20deg,
    rgba(255, 255, 255, 0) 60deg,
    rgba(255, 255, 255, 0) 360deg
  );

  /* Same two-mask intersect approach: ring-shape × density.
     The flow only brightens where the band actually has pigment. */
  -webkit-mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent calc(var(--inner-pct) + 0%),
      #000 calc(var(--inner-pct) + 4%),
      #000 90%,
      transparent 100%
    ),
    var(--density-mask);
  -webkit-mask-composite: source-in;
          mask:
    radial-gradient(
      circle at 50% 50%,
      transparent 0,
      transparent calc(var(--inner-pct) + 0%),
      #000 calc(var(--inner-pct) + 4%),
      #000 90%,
      transparent 100%
    ),
    var(--density-mask);
          mask-composite: intersect;

  mix-blend-mode: soft-light;
  filter: blur(2.5px);
  opacity: 0.9;
  animation: discFlow 11s linear infinite;
  z-index: 2;
}
[data-theme='dark'] .disc__flow {
  mix-blend-mode: screen;
  opacity: 0.5;
}
@keyframes discFlow {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* Strip discs flow a touch slower so the page doesn't get busy */
.disc-wrap--small .disc__flow { animation-duration: 14s; }
.disc-wrap--med .disc__flow   { animation-duration: 12s; }
.disc-wrap--story .disc__flow { animation-duration: 12s; }

/* === GILT outer thread (full weeks — the “data-full=1” badge) === */
.disc__gilt {
  --outer: var(--disc-band-outer-r, 42%);
  /* Progressive crown — multiplied by --gilt-intensity (0..1) set inline by JS.
     0 → invisible, 0.35 → faint hint, 0.65 → clear thread, 1 → full glow. */
  --gilt-intensity: 1;
  /* Crown the ring: a fine bright thread riding the band's outer edge,
     plus a soft bloom that drifts into the linen. */
  inset: calc(50% - var(--outer) - 4%);
  width: calc(2 * (var(--outer) + 4%));
  height: calc(2 * (var(--outer) + 4%));
  border-radius: 50%;

  /* Crown the band: a fine bright thread riding the band's outer edge,
     plus a soft bloom that drifts into the linen.
     With bounding box = (outer + 4%) * 2, the band's outer edge is at
     ~outer / (outer + 4%) ≈ 92% of the bounding radius. */
  -webkit-mask:
    radial-gradient(circle at 50% 50%,
      transparent 0,
      transparent 89%,
      #000 91%,
      #000 93%,
      rgba(0,0,0,0.5) 95%,
      transparent 100%);
          mask:
    radial-gradient(circle at 50% 50%,
      transparent 0,
      transparent 89%,
      #000 91%,
      #000 93%,
      rgba(0,0,0,0.5) 95%,
      transparent 100%);

  background:
    conic-gradient(from 0deg,
      var(--gilt) 0%,
      var(--gilt-soft) 25%,
      var(--gilt) 50%,
      var(--gilt-soft) 75%,
      var(--gilt) 100%);
  filter: drop-shadow(0 0 6px rgba(232, 200, 120, 0.5));
  animation: giltGlow 4.2s ease-in-out infinite;
  z-index: 3;
}
@keyframes giltGlow {
  0%, 100% { opacity: calc(0.85 * var(--gilt-intensity, 1)); filter: drop-shadow(0 0 4px rgba(232, 200, 120, 0.35)); }
  50%      { opacity: calc(1    * var(--gilt-intensity, 1)); filter: drop-shadow(0 0 9px rgba(232, 200, 120, 0.6)); }
}

/* === PAPER (SVG: inner page + ticks + text) === */
.disc__paper {
  z-index: 4;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.disc__page {
  fill: var(--disc-page);
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.04));
}
.disc__page-glow {
  fill: url(#noGlow);
  /* fall back to subtle inner highlight via radial gradient defined in CSS via mask */
  fill: var(--disc-glow);
  mix-blend-mode: screen;
  filter: blur(2px);
  opacity: 0.6;
}
[data-theme='dark'] .disc__page-glow {
  mix-blend-mode: screen;
  opacity: 0.7;
}
.disc__page-edge {
  fill: none;
  stroke: var(--hairline);
  stroke-width: 0.45;
  opacity: 0.7;
}
.disc__tick {
  stroke: var(--ink-3);
  stroke-width: 0.4;
  stroke-linecap: round;
}
.disc__num {
  font-family: var(--serif);
  font-style: italic;
  fill: var(--ink);
  font-weight: 400;
}
.disc__lbl {
  font-family: var(--sans);
  font-style: normal;
  fill: var(--ink-3);
  letter-spacing: 0.18em;
}

/* === KEPT DOT (just outside the band, between gilt and paper) === */
/* A small paper-coloured dot marking a kept moment at its day-angle. */
/* Reads as a bookmark, not an award — quiet, warm, slightly aglow.   */
.disc__kept-dot {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--disc-page);
  border: 0.5px solid color-mix(in srgb, var(--gilt) 70%, transparent);
  transform: translate(-50%, -50%);
  filter:
    drop-shadow(0 0 2px color-mix(in srgb, var(--gilt-soft) 70%, transparent))
    drop-shadow(0 0 5px color-mix(in srgb, var(--gilt) 35%, transparent));
  pointer-events: none;
  z-index: 4; /* above gilt (3), below paper SVG (also 4 but appended later) */
  opacity: 0.95;
}
[data-theme='dark'] .disc__kept-dot {
  background: color-mix(in srgb, var(--gilt-soft) 50%, var(--disc-page));
  border-color: color-mix(in srgb, var(--gilt-soft) 80%, transparent);
  filter:
    drop-shadow(0 0 3px color-mix(in srgb, var(--gilt-soft) 80%, transparent))
    drop-shadow(0 0 7px color-mix(in srgb, var(--gilt) 50%, transparent));
}

/* === SPARK on log === */
.disc__spark {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: rgba(255, 250, 235, 0.95);
  transform: translate(-50%, -50%) scale(0.2);
  filter:
    drop-shadow(0 0 3px rgba(255, 250, 235, 0.95))
    drop-shadow(0 0 8px rgba(255, 230, 180, 0.6));
  pointer-events: none;
  animation: discSpark 1s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
  z-index: 5;
}
@keyframes discSpark {
  0%   { transform: translate(-50%, -50%) scale(0.2); opacity: 0; }
  20%  { transform: translate(-50%, -50%) scale(1.6); opacity: 1; }
  60%  { transform: translate(-50%, -50%) scale(1.1); opacity: 0.85; }
  100% { transform: translate(-50%, -50%) scale(2.6); opacity: 0; }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .disc__breath,
  .disc__flow,
  .disc__gilt,
  .disc__spark { animation: none !important; }
  .disc__breath { transform: scale(1); opacity: 0.5; }
}

/* ============== CONTROLS ============== */
.controls {
  max-width: 520px;
  margin: 0 auto;
}
.controls__label {
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  text-transform: lowercase;
  margin: 0 0 12px;
  text-align: center;
}
.chip-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-bottom: 16px;
}
.chip {
  --c: var(--cat-self);
  font-size: 14px;
  padding: 10px 16px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  background: var(--surface);
  color: var(--ink);
  transition: all 0.2s var(--ease);
  position: relative;
}
.chip[data-cat='self']     { --c: var(--cat-self); }
.chip[data-cat='outdoors'] { --c: var(--cat-outdoors); }
.chip[data-cat='people']   { --c: var(--cat-people); }
.chip[data-cat='play']     { --c: var(--cat-play); }
.chip[data-cat='work']     { --c: var(--cat-work); }

.chip::before {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--c);
  margin-right: 8px;
  vertical-align: middle;
  transform: translateY(-1px);
}
.chip:hover {
  border-color: var(--c);
  color: var(--c);
  transform: translateY(-1px);
}
.chip:active { transform: translateY(0); }

/* === SIT-WITH MODE ====================================================
   Activated when a moment is marked kept. The hero holds for ~2.5s.
   Chips, toggle, and hint dim. Title and obs line cross-fade. The disc
   gets a soft category-tinted halo that fades in and out. No layout
   shift, no movement — just a quieter room.
   ===================================================================== */
.hero {
  position: relative; /* anchor for the sit-with veil */
}
.hero__title,
.hero__obs {
  /* let copy swap fade rather than snap */
  transition: opacity 0.6s var(--ease);
}
/* Dim everything that isn't the disc + words */
.hero[data-sit-with] .controls {
  opacity: 0.32;
  filter: saturate(0.7);
  transition: opacity 0.7s var(--ease), filter 0.7s var(--ease);
  pointer-events: none; /* prevent accidental taps during the hold */
}
.hero[data-sit-with] .eyebrow {
  opacity: 0.45;
  transition: opacity 0.7s var(--ease);
}
/* Default state of those elements (so the un-dim is also smooth) */
.hero .controls,
.hero .eyebrow {
  transition: opacity 0.7s var(--ease), filter 0.7s var(--ease);
}
/* Slow the disc breath — it should feel like a held breath, not a heartbeat */
.hero[data-sit-with] .disc__breath {
  animation-duration: 9s !important;
}

/* Soft tinted veil behind the disc — large, blurred, breathing.
   Sits behind everything in .stage. Colour comes from the kept category. */
.hero::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(820px, 92vw);
  height: min(820px, 92vw);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    circle at 50% 50%,
    color-mix(in srgb, var(--sit-color, var(--cat-self)) 28%, transparent) 0%,
    color-mix(in srgb, var(--sit-color, var(--cat-self)) 14%, transparent) 35%,
    transparent 70%
  );
  filter: blur(40px);
  z-index: 0;
  transition: opacity 0.9s var(--ease);
}
.hero[data-sit-with]::before {
  opacity: 0.85;
  animation: sitVeilBreathe 4.2s ease-in-out infinite;
}
.hero[data-sit-with='self']     { --sit-color: var(--cat-self); }
.hero[data-sit-with='outdoors'] { --sit-color: var(--cat-outdoors); }
.hero[data-sit-with='people']   { --sit-color: var(--cat-people); }
.hero[data-sit-with='play']     { --sit-color: var(--cat-play); }
.hero[data-sit-with='work']     { --sit-color: var(--cat-work); }

[data-theme='dark'] .hero[data-sit-with]::before {
  opacity: 0.55; /* darker rooms need less light to feel different */
}

@keyframes sitVeilBreathe {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.04); }
}

/* Make sure the disc + copy sit above the veil */
.hero .eyebrow,
.hero__title,
.hero__obs,
.hero .stage,
.hero .controls {
  position: relative;
  z-index: 1;
}

/* Reduced-motion: keep the colour wash but skip the pulse */
@media (prefers-reduced-motion: reduce) {
  .hero[data-sit-with]::before { animation: none; }
  .hero[data-sit-with] .disc__breath { animation-duration: 12s !important; }
}

/* === AFTERGLOW =========================================================
   After sit-with dismisses, the just-kept sector keeps a soft localised
   halo for ~30s. Implemented as a ::after on the disc-wrap with a conic
   gradient: bright at the category's home angle, transparent elsewhere.
   The strength fades via --afterglow-strength (set by JS, 1 → 0).
   The room remembers what just happened.
   ====================================================================== */
[data-disc-stage][data-afterglow] {
  --ag: var(--cat-self); /* default; overridden below per category */
  /* HOME_ANGLE: people=0, play=72, outdoors=144, self=216, work=288 (degrees) */
  --ag-angle: 216deg;
  --afterglow-strength: 0;
}
[data-disc-stage][data-afterglow='people']   { --ag: var(--cat-people);   --ag-angle: 0deg;   }
[data-disc-stage][data-afterglow='play']     { --ag: var(--cat-play);     --ag-angle: 72deg;  }
[data-disc-stage][data-afterglow='outdoors'] { --ag: var(--cat-outdoors); --ag-angle: 144deg; }
[data-disc-stage][data-afterglow='self']     { --ag: var(--cat-self);     --ag-angle: 216deg; }
[data-disc-stage][data-afterglow='work']     { --ag: var(--cat-work);     --ag-angle: 288deg; }

[data-disc-stage][data-afterglow]::after {
  content: '';
  position: absolute;
  inset: -10%;
  border-radius: 50%;
  pointer-events: none;
  /* Conic gradient anchored before the home angle so the bright lobe sits
     centred on it. Window is ~70deg wide — wide enough to read without
     being a slice of pie. */
  /* Two stacked conic gradients: a softer outer halo + a denser core lobe */
  background:
    conic-gradient(
      from calc(var(--ag-angle) - 35deg) at 50% 50%,
      color-mix(in srgb, var(--ag) 100%, transparent) 0deg,
      color-mix(in srgb, var(--ag) 75%, transparent) 30deg,
      color-mix(in srgb, var(--ag) 25%, transparent) 60deg,
      transparent 70deg 360deg
    );
  /* Mask to a ring sitting just outside the band. The band outer is
     ~42% of the wrapper (which is now inset:-10%, so the new wrapper
     percentages shift). The band, expressed in this larger box, lives at
     ~42*100/120 ≈ 35%. We paint 36–52% (just outside, generously thick). */
  -webkit-mask: radial-gradient(circle at 50% 50%,
    transparent 0 36%,
    #000 40% 50%,
    transparent 56%);
          mask: radial-gradient(circle at 50% 50%,
    transparent 0 36%,
    #000 40% 50%,
    transparent 56%);
  filter: blur(12px) saturate(1.6);
  opacity: var(--afterglow-strength, 0);
  animation: afterglowBreathe 5s ease-in-out infinite;
  z-index: 5; /* above paper, below story content */
  /* Multiply on light gives the glow body against cream; otherwise the
     mid-tone band hues just blend into the paper. */
  mix-blend-mode: multiply;
}
[data-theme='dark'] [data-disc-stage][data-afterglow]::after {
  filter: blur(14px) saturate(1.2) brightness(1.2);
  /* Screen on dark gives an additive glow against the near-black surface. */
  mix-blend-mode: screen;
}
@keyframes afterglowBreathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.02); }
}
@media (prefers-reduced-motion: reduce) {
  [data-disc-stage][data-afterglow]::after { animation: none; }
}

/* === Keep chips: ghost variant of .chip with a sparkle icon. =========== */
/* Active (kept) state pulls in gilt colour so it reads as "earned".       */
/* Disabled state (no log of that cat yet) ghosts back into the page so it */
/* reads as available-but-empty rather than denied.                        */
.controls__hint {
  margin: 6px auto 10px;
  max-width: 460px;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-3);
  --fr-opsz: 13;
  --fr-soft: 100;
  font-weight: 380;
}
.controls__hint em {
  font-style: italic;
  color: var(--ink-2);
}
.chip-row--keep {
  margin-bottom: 18px;
  gap: 6px;
}
.chip--keep {
  --c: var(--ink-3);
  font-size: 13px;
  padding: 7px 12px;
  background: transparent;
  border-color: color-mix(in srgb, var(--hairline) 70%, transparent);
  color: var(--ink-3);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.chip--keep::before { display: none; }
.chip__star {
  display: inline-block;
  font-size: 12px;
  color: var(--ink-3);
  transform: translateY(-0.5px);
  transition: color 0.2s var(--ease), transform 0.2s var(--ease);
}
.chip--keep:hover:not(:disabled) {
  color: var(--ink);
  border-color: var(--gilt);
}
.chip--keep:hover:not(:disabled) .chip__star { color: var(--gilt); }
.chip--keep[data-active='1'] {
  color: var(--ink);
  border-color: var(--gilt);
  background: color-mix(in srgb, var(--gilt) 8%, transparent);
}
.chip--keep[data-active='1'] .chip__star {
  color: var(--gilt);
  transform: translateY(-0.5px) scale(1.1);
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--gilt) 60%, transparent));
}
.chip--keep:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ============== FOOTER ============== */
.footer {
  margin-top: 60px;
  padding-top: 30px;
  border-top: 1px solid var(--hairline-soft);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 14px;
  color: var(--ink-3);
  font-size: 13px;
}
.footer .brand__name { font-family: var(--serif); font-size: 20px; color: var(--ink); }
.footer .footer__tag { font-family: var(--serif); font-style: italic; font-size: 16px; color: var(--ink-2); }
/* ============== v4.0 — empty disc state ============== */
/* When the week has zero logs, the disc renders as a hairline ring with    */
/* 7 quiet daypoint ticks and the italic word "begin" in the centre.        */
/* Empty IS a real state, not a bug. Permission, not pressure.              */
.disc__num--empty {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 380;
  --fr-opsz: 28;
  --fr-soft: 100;
  /* Note: SVG font-size is set in user-units on the element (7.5) so the
     word scales with the disc viewBox. Do NOT set CSS font-size here —
     it would override the SVG attribute and blow up to CSS pixels. */
  fill: var(--ink-3);
  letter-spacing: 0.01em;
  opacity: 0.75;
}
.disc__tick {
  stroke: var(--hairline);
  stroke-width: 1.2;
  stroke-linecap: round;
}

/* ============== v4.0 — first-tap whisper ============== */
/* Single line of poetry. Shown ~2.6s after the first-ever chip tap on a    */
/* fresh install, then fades. Never reappears (margin.whisper.seen).        */
.whisper {
  font-family: var(--serif);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-3);
  text-align: center;
  margin: 18px auto 0;
  max-width: 32ch;
  line-height: 1.5;
  opacity: 0;
  transition: opacity 0.6s var(--ease);
  pointer-events: none;
}
.whisper[data-show='1'] { opacity: 1; }
.whisper[hidden] { display: none; }

/* ============== v4.0 — legend panel (collapsible) ============== */
/* Hidden behind the "?" in the topbar. Quiet inline panel just under the   */
/* topbar. Surfaces the five colours so people can learn over time without  */
/* a forced tour.                                                            */
.legend-toggle {
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--ink-2);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: all 0.2s var(--ease);
}
.legend-toggle:hover {
  color: var(--ink);
  border-color: var(--hairline);
  background: var(--surface);
}
.legend-toggle[aria-expanded='true'] {
  color: var(--ink);
  border-color: var(--hairline);
  background: var(--surface);
}
.legend-panel {
  max-width: 720px;
  margin: 0 auto;
  padding: 18px clamp(20px, 4vw, 36px) 4px;
  animation: legendIn 0.28s var(--ease);
}
.legend-panel[hidden] { display: none; }
@keyframes legendIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
.legend {
  list-style: none;
  padding: 0;
  margin: 0 0 12px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.legend li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: color-mix(in srgb, var(--surface) 70%, transparent);
  border: 1px solid var(--hairline-soft);
  border-radius: 12px;
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.4;
}
.legend li strong {
  color: var(--ink);
  margin-right: 4px;
  font-weight: 500;
}
.legend .swatch {
  width: 14px;
  height: 14px;
  border-radius: 999px;
  background: var(--c);
  flex: 0 0 auto;
  border: 1px solid color-mix(in srgb, var(--c) 60%, var(--ink) 30%);
}
.legend__aside {
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-3);
  margin: 8px 0 0;
  max-width: 60ch;
  line-height: 1.55;
}
.legend__aside em { font-style: italic; color: var(--ink-2); }

/* ============== v4.0 — previously link (corner) ============== */
/* Tiny corner link to last week's recap. Only renders when there IS a      */
/* previous week with at least one log. Hidden otherwise.                   */
.previously {
  margin-top: clamp(40px, 6vw, 60px);
  text-align: center;
}
.previously[hidden] { display: none; }
.previously__link {
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-3);
  background: transparent;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--hairline) 70%, transparent);
  padding: 2px 0;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.previously__link:hover {
  color: var(--ink-2);
  border-color: var(--ink-3);
}

/* ============== v4.0 — recap as sunday home screen ============== */
/* Not an overlay. Sunday IS the recap. The .recap section uses the same    */
/* .hero base styles for layout/typography continuity.                       */
.recap[hidden] { display: none; }
.home[hidden] { display: none; }

.recap__title {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  --fr-opsz: 56;
  --fr-soft: 60;
  font-size: clamp(34px, 5.4vw, 52px);
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 6px 0 8px;
  color: var(--ink);
}
.recap__title em { font-style: italic; }
.recap__count {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16px;
  color: var(--ink-2);
  margin: 0 0 clamp(20px, 3vw, 32px);
}
.stage--recap .disc-wrap {
  max-width: 360px;
  margin: 0 auto;
}

.recap-stack {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 560px;
  margin: clamp(28px, 4vw, 44px) auto 0;
}
.recap-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px clamp(16px, 3vw, 22px) 18px;
  background: color-mix(in srgb, var(--surface) 60%, transparent);
  border: 1px solid var(--hairline-soft);
  border-radius: 14px;
  text-align: left;
}
.recap-row__eyebrow {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0;
}
.recap-row__line {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 380;
  --fr-opsz: 18;
  --fr-soft: 100;
  font-size: clamp(16px, 2vw, 19px);
  line-height: 1.45;
  color: var(--ink);
  margin: 2px 0 0;
}
.recap-row__line em { font-style: italic; color: var(--ink); }
.recap-row--despite .recap-row__line { color: var(--ink); }
.recap-row--kept {
  background: color-mix(in srgb, var(--gilt) 6%, var(--surface) 94%);
  border-color: color-mix(in srgb, var(--gilt) 30%, var(--hairline) 70%);
}
.recap-row--kept .recap-row__eyebrow { color: var(--gilt); }
.recap-row--ritual {
  background: transparent;
  border-color: var(--hairline-soft);
  text-align: center;
  align-items: center;
}
.recap-row__keeps {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0 0;
}
.recap-row__keeps .chip {
  pointer-events: none;
  cursor: default;
}

.recap__close {
  display: block;
  margin: clamp(28px, 4vw, 40px) auto 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  transition: all 0.2s var(--ease);
}
.recap__close[hidden] { display: none; }
.recap__close:hover { color: var(--ink); border-color: var(--ink-3); }

/* ============== v4.1 — the noticing field ============== */
/* The inline note field. Lives under the chip-row, fades in on first-tap-
   per-category-per-week, fades out at 6s if untouched. Italic serif,
   hairline border, no label. The field commits on blur, dismisses on esc.
   Caret colour and underline pick up the tapped chip's category colour. */
.note-field {
  margin: 14px auto 0;
  max-width: 320px;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  animation: noteFieldIn 0.32s var(--ease);
}
.note-field[data-leaving='1'] { animation: noteFieldOut 0.4s var(--ease) forwards; }
@keyframes noteFieldIn {
  from { opacity: 0; transform: translateY(-3px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes noteFieldOut {
  from { opacity: 1; }
  to { opacity: 0; }
}
.note-field__caret {
  font-family: var(--serif);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-3);
  text-align: center;
  letter-spacing: 0.04em;
  margin: 0;
}
.note-field__caret strong {
  color: var(--c, var(--ink-2));
  font-weight: 500;
  font-style: normal;
  letter-spacing: 0.01em;
}
.note-field__input {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--hairline) 70%, transparent);
  padding: 6px 4px 8px;
  font-family: var(--serif);
  font-style: italic;
  font-size: 15px;
  color: var(--ink);
  text-align: center;
  outline: none;
  transition: border-color 0.2s var(--ease);
  caret-color: var(--c, var(--ink-2));
}
.note-field__input::placeholder {
  color: color-mix(in srgb, var(--ink-3) 70%, transparent);
  font-style: italic;
}
.note-field__input:focus {
  border-bottom-color: color-mix(in srgb, var(--c, var(--ink-2)) 60%, transparent);
}
.note-field__hint {
  font-family: var(--serif);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-3);
  text-align: center;
  letter-spacing: 0.02em;
  margin: 0;
}

/* ============== v4.1 — chip marginalia (noted dot) ============== */
/* When a chip's category has at least one note this week, paint a tiny
   coloured dot in the corner. The note text never appears on the home —
   only this private mark. Keeps friday-evening home-screen minimal even
   with notes accumulated. */
.chip[data-noted='1'] {
  position: relative;
}
.chip[data-noted='1']::after {
  content: '';
  position: absolute;
  top: 6px;
  right: 8px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--c, var(--ink-2));
  opacity: 0.7;
}
.chip[data-noted='1'][data-cat='self']     { --c: var(--cat-self); }
.chip[data-noted='1'][data-cat='outdoors'] { --c: var(--cat-outdoors); }
.chip[data-noted='1'][data-cat='people']   { --c: var(--cat-people); }
.chip[data-noted='1'][data-cat='play']     { --c: var(--cat-play); }
.chip[data-noted='1'][data-cat='work']     { --c: var(--cat-work); }

/* ============== v4.1 — keep prompt (recap-only) ============== */
/* Opens when a recap keep-chip is starred. Gilt-bordered, slightly more
   visible than the first-tap field because the act of keeping is itself
   deliberate. Skip-button closes without saving. */
.keep-prompt {
  margin: 14px auto 0;
  max-width: 360px;
  padding: 14px 16px;
  background: color-mix(in srgb, var(--gilt) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--gilt) 30%, var(--hairline) 70%);
  border-radius: 12px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: keepPromptIn 0.36s var(--ease);
}
.keep-prompt[data-leaving='1'] { animation: noteFieldOut 0.4s var(--ease) forwards; }
@keyframes keepPromptIn {
  from { opacity: 0; transform: translateY(-2px); }
  to { opacity: 1; transform: translateY(0); }
}
.keep-prompt__star {
  font-size: 16px;
  color: var(--gilt);
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--gilt) 60%, transparent));
  line-height: 1;
}
.keep-prompt__line {
  font-family: var(--serif);
  font-style: italic;
  font-size: 14px;
  color: var(--ink);
  margin: 0;
}
.keep-prompt__line strong {
  color: var(--c, var(--gilt));
  font-style: normal;
  font-weight: 500;
}
.keep-prompt__input {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--gilt) 50%, transparent);
  padding: 4px 4px 6px;
  font-family: var(--serif);
  font-style: italic;
  font-size: 15px;
  color: var(--ink);
  text-align: center;
  outline: none;
  caret-color: var(--gilt);
}
.keep-prompt__input::placeholder {
  color: color-mix(in srgb, var(--ink-3) 70%, transparent);
  font-style: italic;
}
.keep-prompt__skip {
  font-family: var(--serif);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-3);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 2px 8px;
  align-self: center;
  transition: color 0.2s var(--ease);
}
.keep-prompt__skip:hover { color: var(--ink-2); }

/* ============== v4.1 — noted recap row ============== */
/* Surfaces every noted moment in the sunday recap. Kept ones lead with a
   gilt star; unkept-but-noted follow. Each entry: italic line, then a
   uppercase-ish meta line with category and day. Left-edge bar in the
   category colour is the only place note text picks up colour. */
.recap-row--noted {
  background: transparent;
  border-color: var(--hairline-soft);
  text-align: left;
  padding: 16px clamp(16px, 3vw, 22px) 18px;
}
.recap-row--noted .recap-row__eyebrow {
  text-align: center;
  color: var(--gilt);
  letter-spacing: 0.22em;
  margin-bottom: 10px;
}
.noted-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.noted-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 6px 6px;
  border-left: 2px solid var(--c, var(--ink-3));
  padding-left: 12px;
}
.noted-row[data-cat='self']     { --c: var(--cat-self); }
.noted-row[data-cat='outdoors'] { --c: var(--cat-outdoors); }
.noted-row[data-cat='people']   { --c: var(--cat-people); }
.noted-row[data-cat='play']     { --c: var(--cat-play); }
.noted-row[data-cat='work']     { --c: var(--cat-work); }
.noted-row__line {
  flex: 1;
  font-family: var(--serif);
  font-style: italic;
  font-size: 15px;
  line-height: 1.45;
  color: var(--ink);
  margin: 0;
}
.noted-row__meta {
  display: block;
  font-style: normal;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 4px;
}
.noted-row__meta--kept {
  color: var(--gilt);
}

/* ============== FOOTER (cleanup) ============== */
/* The "concept page · not the live app" p tag was removed in v4.0, so the */
/* margin-left:auto rule no longer applies. Footer now reads as a single   */
/* baseline-aligned line.                                                  */

/* ============== MOBILE ============== */
@media (max-width: 640px) {
  .topbar { padding: 14px 18px; }
  .brand__tag { display: none; }
  .page { padding: 24px 18px 60px; }
  .legend-panel { padding: 14px 18px 0; }
  .legend { grid-template-columns: 1fr; }
  .recap-stack { gap: 14px; }
  .footer { flex-direction: column; align-items: flex-start; gap: 6px; }
}

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

/* ============== v4.1.1 — once-off intro card ============== */
/* First-load only. Floating card centred over a softly dimmed disc.
   The disc keeps breathing behind the card so the user senses the
   surface they're about to use. Dismissed only by the begin button —
   no auto-fade, no tap-anywhere, no escape. The act of beginning
   should be small but deliberate. */
.intro-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  animation: introOverlayIn 0.5s var(--ease);
}
.intro-overlay[hidden] { display: none; }
.intro-overlay[data-leaving='1'] {
  animation: introOverlayOut 0.5s var(--ease) forwards;
}
@keyframes introOverlayIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes introOverlayOut { from { opacity: 1; } to { opacity: 0; } }

.intro-card {
  width: min(100%, 360px);
  padding: 28px 28px 22px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--ink) 4%, transparent),
    0 14px 36px -12px color-mix(in srgb, var(--ink) 18%, transparent);
  animation: introCardIn 0.6s var(--ease);
}
@keyframes introCardIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
.intro-card__title {
  font-family: var(--serif);
  font-size: 32px;
  line-height: 1.1;
  font-weight: 400;
  color: var(--ink);
  margin: 2px 0 4px;
  letter-spacing: -0.01em;
}
.intro-card__title em { font-style: italic; }
.intro-card__line {
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
}
.intro-card__line em { font-style: italic; }
.intro-card__line--quiet {
  font-style: italic;
  font-size: 13px;
  color: var(--ink-3);
  letter-spacing: 0.02em;
  margin-bottom: 6px;
}
.intro-card__begin {
  align-self: center;
  margin-top: 10px;
  padding: 9px 28px;
  background: transparent;
  color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--gilt) 60%, var(--hairline) 40%);
  border-radius: 999px;
  font-family: var(--serif);
  font-style: italic;
  font-size: 15px;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.intro-card__begin:hover {
  background: color-mix(in srgb, var(--gilt) 12%, transparent);
  border-color: var(--gilt);
}
.intro-card__begin:focus-visible {
  outline: 2px solid var(--gilt);
  outline-offset: 3px;
}

/* While the intro is mounted, soften the page behind it. The disc keeps
   breathing — we just dim chips/text to keep focus on the card. */
body[data-intro-active='1'] .home,
body[data-intro-active='1'] .recap {
  filter: saturate(0.85) brightness(0.96);
}

/* ============== footer link + topbar link (about page nav) ============== */
.footer__link {
  margin-left: 14px;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.footer__link:hover {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--gilt) 60%, transparent);
}
.topbar__link {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-decoration: none;
  margin-right: 4px;
  transition: color 0.2s var(--ease);
}
.topbar__link:hover { color: var(--ink); }

/* Brand becomes a link on /about — keep the inline-flex baseline */
a.brand {
  text-decoration: none;
  color: inherit;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
a.brand:hover { color: var(--ink); }

/* ============== /about page ============== */
.about-page {
  max-width: 640px;
  margin: 0 auto;
  padding-top: 32px;
}
.about {
  padding: 8px 4px 40px;
}
.about__eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
}
.about__eyebrow .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--gilt);
  opacity: 0.85;
}
.about__title {
  font-family: var(--serif);
  font-size: clamp(40px, 7vw, 64px);
  line-height: 1.0;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 8px;
  letter-spacing: -0.015em;
}
.about__title em { font-style: italic; }
.about__tag {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16px;
  color: var(--ink-2);
  margin: 0 0 28px;
}
.about__rule {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: 28px 0;
  width: 64px;
}
.about__lead {
  font-family: var(--serif);
  font-size: 22px;
  line-height: 1.4;
  font-style: italic;
  color: var(--ink);
  margin: 0 0 20px;
}
.about p {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 18px;
}
.about__h2 {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gilt);
  font-weight: 500;
  margin: 0 0 16px;
}
.about__legend {
  list-style: none;
  margin: 8px 0 22px;
  padding: 0;
  display: grid;
  gap: 10px;
}
/* Each legend li is a normal paragraph with the swatch positioned in a
   left gutter. This lets the inline text (strong, em-dash, description)
   wrap as a single paragraph instead of breaking word-by-word. */
.about__legend li {
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  position: relative;
  padding-left: 22px;
}
.about__legend .swatch {
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--c) 30%, transparent);
}
.about__legend strong {
  font-style: normal;
  font-weight: 500;
  color: var(--ink);
}
.about__quiet {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 14px 0 0;
}
.about__close {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--ink-2);
  text-align: center;
  margin: 18px 0 4px;
}
.about__cta {
  display: flex;
  justify-content: center;
  margin: 18px 0 0;
}
.about__begin {
  display: inline-block;
  padding: 10px 32px;
  border: 1px solid color-mix(in srgb, var(--gilt) 60%, var(--hairline) 40%);
  border-radius: 999px;
  font-family: var(--serif);
  font-style: italic;
  font-size: 15px;
  color: var(--ink);
  text-decoration: none;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.about__begin:hover {
  background: color-mix(in srgb, var(--gilt) 12%, transparent);
  border-color: var(--gilt);
}

@media (max-width: 640px) {
  .about__title { font-size: 44px; }
  .about__lead { font-size: 19px; }
  .about p { font-size: 16px; }
  .footer__link { margin-left: 0; }
  .topbar__link { display: none; }
}
