/* habitkept.com (T90, redesigned 2026-10-18 from docs/design/boards/). The app's own look (SPEC-app-shell.md,
   "The look"): warm paper, blue-black ink, ledger green, the crooked KEPT stamp, Bricolage Grotesque (served from
   fonts/, SIL Open Font License in fonts/OFL.txt) for titles and numbers, the system font for the rest. The film
   stage is the ink desk in both modes; everything after it follows the device's light or dark setting. Every text
   color keeps WCAG AA contrast in both. Nothing waits invisible for a scroll: motion is transform only, and none of
   it runs under Reduce Motion. */

@font-face { font-family: "Bricolage Grotesque"; src: url("fonts/BricolageGrotesque_700Bold.ttf") format("truetype"); font-weight: 700; font-display: swap; }
@font-face { font-family: "Bricolage Grotesque"; src: url("fonts/BricolageGrotesque_800ExtraBold.ttf") format("truetype"); font-weight: 800; font-display: swap; }

:root {
  --paper: #F6F4EF; --tile: #FFFFFF; --ink: #1C2143; --pencil: #5F5E66; --line: #E7E3DA;
  --stamp: #1D6B4C; --wash: #E3EFE8; --on-stamp: #FFFFFF; --seal: #C0392B;
  --ink-tile: #1C2143; --on-ink: #F6F4EF; --on-ink-muted: #C9CBD8;
  --shadow: 0 1px 2px rgba(28, 33, 67, 0.06), 0 8px 24px rgba(28, 33, 67, 0.06);
  /* The film stage and the closing band: the ink desk, the same in both modes. */
  --desk: #1C2143; --desk-text: #F6F4EF; --desk-muted: #C9CBD8; --desk-green: #5CC995;
  --display: "Bricolage Grotesque", -apple-system, sans-serif;
  --grain: url("assets/grain.jpg");
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0B0C0B; --tile: #171917; --ink: #EDEBE6; --pencil: #A3A19A; --line: #262826;
    --stamp: #5CC995; --wash: #14261C; --on-stamp: #0B0C0B; --seal: #FF7B6E;
    --ink-tile: #232622; --on-ink: #EDEBE6; --on-ink-muted: #B5B3AC;
    --shadow: none;
    --grain: none;
  }
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--paper) var(--grain) 0 0 / 512px; color: var(--ink);
  font: 17px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--stamp); }
:focus-visible { outline: 3px solid var(--stamp); outline-offset: 3px; border-radius: 8px; }
h1, h2, h3 { font-family: var(--display); font-weight: 800; margin: 0; }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 16px; top: 16px; background: var(--tile); color: var(--ink); padding: 8px 12px; z-index: 20; }
.fine { margin: 12px 0 0; font-size: 14px; color: var(--pencil); }
.aside { margin: 24px 0 0; max-width: 46em; color: var(--pencil); }

/* ---- The film: a sticky stage, with the chapters scrolling over it ---- */
.film { position: relative; background: var(--desk); color: var(--desk-text); }
.film a { color: var(--desk-green); }
.film :focus-visible { outline-color: var(--desk-green); }
.film-stage { position: sticky; top: 0; height: 100dvh; overflow: hidden; }
.film-poster img, .film-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.film-video { visibility: hidden; }
.film-stage.playing .film-video { visibility: visible; }
/* Keeps every line of copy at AA over the paper tape, whatever frame is showing. */
/* Light on purpose, so the film reads as on the board; the film keeps its left side clear for the copy. */
.film-shade {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(28, 33, 67, 0.6) 0, rgba(28, 33, 67, 0) 140px),
    linear-gradient(90deg, rgba(28, 33, 67, 0.7) 0%, rgba(28, 33, 67, 0.45) 34%, rgba(28, 33, 67, 0) 58%);
}
/* The gift fills the frame in the last chapter, so the shade deepens there to keep its copy at AA. */
.film-shade::after {
  content: ""; position: absolute; inset: 0; opacity: 0; transition: opacity 400ms ease;
  background: linear-gradient(90deg, rgba(28, 33, 67, 0.9) 0%, rgba(28, 33, 67, 0.75) 34%, rgba(28, 33, 67, 0) 60%);
}
.film[data-read="4"] .film-shade::after, .film[data-read="5"] .film-shade::after { opacity: 1; }
@media (max-width: 860px) {
  .film-shade::after { background: linear-gradient(0deg, rgba(28, 33, 67, 0.95) 0%, rgba(28, 33, 67, 0.85) 50%, rgba(28, 33, 67, 0) 75%); }
}
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

.top {
  position: absolute; z-index: 3; top: 0; left: 0; right: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: max(20px, env(safe-area-inset-top)) clamp(16px, 5vw, 64px) 0;
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--desk-text) !important; text-decoration: none; font: 800 24px var(--display); }
.brand img { border-radius: 9px; }
/* Nav: a text link whose hairline slides in from the left. */
.nav-join {
  position: relative; padding: 10px 0; color: var(--desk-text) !important; text-decoration: none;
  font-weight: 500; letter-spacing: 0.08em;
}
/* A full hairline, as on the board; a green one slides over it on hover. */
.nav-join::before, .nav-join::after { content: ""; position: absolute; left: 0; right: 0; bottom: 3px; height: 2px; }
.nav-join::before { background: rgba(246, 244, 239, 0.85); }
.nav-join::after { background: var(--desk-green); transform: scaleX(0); transform-origin: left; transition: transform 240ms ease; }
.nav-join:hover::after, .nav-join:focus-visible::after { transform: scaleX(1); }

/* The chapter stamps: one box per chapter, stamped as it's read. */
.rail {
  position: absolute; z-index: 3; right: clamp(16px, 4vw, 48px); top: 50%; transform: translateY(-50%);
  display: grid; gap: 10px; margin: 0; padding: 0; list-style: none;
}
.rail li {
  position: relative; width: 30px; height: 30px; border-radius: 6px;
  border: 2px solid rgba(246, 244, 239, 0.45);
}
/* The real rubber stamps (assets/stamp-k.png, stamp-x.png, from docs/brand/stamps/): ink masks, so each use
   colors them, green for a kept day and red for a missed one (decision 93). They come already set down at -8°. */
.stamp-k, .stamp-x, .rail li::after { -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat; }
.stamp-k, .rail li::after { -webkit-mask-image: url("assets/stamp-k.png"); mask-image: url("assets/stamp-k.png"); }
.stamp-x { -webkit-mask-image: url("assets/stamp-x.png"); mask-image: url("assets/stamp-x.png"); }
/* A read chapter gets the K stamp. */
.rail li::after { content: ""; position: absolute; inset: -6px; background: var(--desk-green); visibility: hidden; }
.rail li.kept::after { visibility: visible; animation: stamp 220ms cubic-bezier(0.2, 0.9, 0.3, 1.3); }
@keyframes stamp { from { transform: translateY(-10px) scale(1.5); } to { transform: none; } }

.film-story { position: relative; z-index: 2; margin-top: -100dvh; }
.chapter { display: flex; align-items: center; min-height: 100dvh; padding: 96px clamp(16px, 6vw, 96px); }
.copy { max-width: min(34rem, 44vw); text-shadow: 0 2px 22px rgba(11, 13, 30, 0.6); }
.chapter-hero { align-items: flex-start; padding-top: clamp(120px, 20dvh, 200px); }
.chapter-hero .copy { max-width: min(70rem, 74vw); }
.chapter h1 { font-size: clamp(44px, 5.4vw, 86px); line-height: 1.02; letter-spacing: -0.02em; }
@media (min-width: 1000px) { .chapter h1 .line { white-space: nowrap; } }
.chapter h2 { font-size: clamp(36px, 4.6vw, 60px); line-height: 1.04; letter-spacing: -0.015em; }
.chapter p { margin: 18px 0 0; color: var(--desk-muted); font-size: 19px; }
.eyebrow { margin: 0 0 18px !important; color: var(--desk-text) !important; font-weight: 500; font-size: 17px !important; letter-spacing: 0.08em; }
.chapter .lede { margin-top: 26px; color: var(--desk-text); font-size: clamp(18px, 1.5vw, 22px); }
/* The last chapter runs long so the gift is wrapped at an easy scroll; its copy holds on screen meanwhile. */
.chapter-end { min-height: 250dvh; align-items: flex-start; }
.chapter-end .copy { position: sticky; top: 30dvh; }
.end-stamp { display: block; width: 128px; height: 128px; margin-top: 28px; background: var(--desk-green); }
.film[data-read="5"] .end-stamp { animation: stamp 260ms cubic-bezier(0.2, 0.9, 0.3, 1.3); }

/* ---- Waitlist form ---- */
.join { margin-top: 36px; max-width: 36rem; }
.join-row { position: relative; display: flex; flex-wrap: wrap; gap: 12px; }
.join input[type="email"] {
  flex: 1 1 220px; min-height: 60px; padding: 0 18px; border: 1px solid rgba(246, 244, 239, 0.3); border-radius: 6px;
  background: rgba(11, 13, 30, 0.45); color: var(--desk-text); font: inherit;
}
.join input[type="email"]::placeholder { color: var(--desk-muted); }
/* The submit button is a postage stamp, as on the board: perforated edges, a dashed rim, a typed label.
   Pressing it imprints. The mask punches the perforation holes. */
.stamp-button {
  --hole: 3px;
  min-height: 60px; padding: 0 30px; border: 0; cursor: pointer;
  background: #1D6B4C; color: #F6F4EF; font: 600 18px ui-monospace, "SF Mono", Menlo, Consolas, monospace; letter-spacing: 0.04em;
  outline: 2px dashed rgba(246, 244, 239, 0.75); outline-offset: -9px;
  -webkit-mask: radial-gradient(var(--hole), #0000 98%, #000) round calc(-1.5 * var(--hole)) calc(-1.5 * var(--hole)) / calc(3 * var(--hole)) calc(3 * var(--hole)),
                linear-gradient(#000 0 0) no-repeat 50% / calc(100% - 3 * var(--hole)) calc(100% - 3 * var(--hole));
          mask: radial-gradient(var(--hole), #0000 98%, #000) round calc(-1.5 * var(--hole)) calc(-1.5 * var(--hole)) / calc(3 * var(--hole)) calc(3 * var(--hole)),
                linear-gradient(#000 0 0) no-repeat 50% / calc(100% - 3 * var(--hole)) calc(100% - 3 * var(--hole));
  transition: transform 120ms ease, background-color 120ms ease;
}
.stamp-button:hover { background: #22795A; }
.stamp-button:focus-visible { outline: 3px solid #F6F4EF; outline-offset: -9px; }
.stamp-button:active { transform: translateY(2px) rotate(-1.5deg) scale(0.98); background: #17573E; }
.stamp-button:disabled { cursor: progress; opacity: 0.8; }
@media (max-width: 420px) { .stamp-button { flex: 1 1 100%; } }
.join-stamp { position: absolute; right: -16px; top: -42px; width: 60px; height: 60px; background: var(--desk-green); visibility: hidden; }
.join:has(.status.ok) .join-stamp { visibility: visible; animation: stamp 220ms cubic-bezier(0.2, 0.9, 0.3, 1.3); }
.join .fine { color: var(--desk-muted); }
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.status { min-height: 1.55em; margin: 8px 0 0 !important; font-weight: 600; font-size: 16px !important; color: var(--desk-text) !important; }
.status.ok { color: var(--desk-green) !important; }
.status.error { color: #FF9C91 !important; }

/* ---- After the film: one container, each section its own layout ---- */
.calc, .habits, .faq { max-width: 1080px; margin: 0 auto; padding: 96px 16px 0; }
.calc h2, .faq h2 { font-size: clamp(44px, 8vw, 96px); line-height: 0.98; letter-spacing: -0.03em; }

/* Stake calculator: an instrument. A dial on a paper-tape track, and the receipt beside it. */
.calc-grid { display: grid; gap: 32px; align-items: center; margin-top: 28px; }
@media (min-width: 860px) { .calc-grid { grid-template-columns: 1.4fr 1fr; } }
.dial label { display: block; font-weight: 600; color: var(--pencil); }
.amount { display: block; margin: 4px 0 14px; font: 800 clamp(72px, 12vw, 132px)/1 var(--display); letter-spacing: -0.03em; }
.dial input[type="range"] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 44px; margin: 0; border-radius: 6px; cursor: pointer;
  background:
    repeating-linear-gradient(90deg, transparent 0 22px, color-mix(in srgb, var(--stamp) 60%, transparent) 22px 30px) center / 100% 8px no-repeat,
    var(--line);
}
.dial input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 34px; height: 34px; border-radius: 50%; background: var(--stamp);
  border: 4px solid var(--tile); box-shadow: 0 2px 8px rgba(28, 33, 67, 0.25);
}
.dial input[type="range"]::-moz-range-thumb {
  width: 26px; height: 26px; border-radius: 50%; background: var(--stamp);
  border: 4px solid var(--tile); box-shadow: 0 2px 8px rgba(28, 33, 67, 0.25);
}
.receipt-wrap { filter: drop-shadow(0 8px 18px rgba(28, 33, 67, 0.12)); transform: rotate(-2deg); }
/* Printed on a torn strip of real receipt paper (assets/receipt.png): ink on paper in both modes. */
.receipt {
  margin: 0; padding: 36px 52px; color: #1C2143;
  background: url("assets/receipt.png") center / 100% 100% no-repeat;
  font: 16px/1.4 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
.receipt div { display: flex; justify-content: space-between; gap: 16px; padding: 12px 0; border-bottom: 1px dashed rgba(28, 33, 67, 0.3); }
.receipt .sum { border-bottom: 0; font-weight: 700; font-size: 18px; }
.receipt dd { margin: 0; white-space: nowrap; }
.outcomes { display: grid; gap: 14px; margin-top: 40px; }
@media (min-width: 720px) { .outcomes { grid-template-columns: 1.3fr 1fr; } }
.outcome { position: relative; padding: 28px; border-radius: 24px; }
.outcome h3 { font-size: clamp(30px, 4vw, 44px); line-height: 1.05; }
.outcome p { margin: 12px 0 0; max-width: 30em; }
.finish { background: var(--tile); border: 1px solid var(--line); box-shadow: var(--shadow); padding-right: 120px; }
.finish p { color: var(--pencil); }
.finish strong { color: var(--stamp); }
.miss { background: var(--ink-tile); color: var(--on-ink); }
.miss p { color: var(--on-ink-muted); }
.miss strong { color: var(--on-ink); }
.miss { padding-right: 120px; }
.mini-stamp { position: absolute; right: 26px; top: 50%; width: 76px; height: 76px; background: var(--stamp); transform: translateY(-50%); }
.miss .mini-stamp { background: #FF7B6E; }
@media (max-width: 480px) { .finish, .miss { padding-right: 28px; } .mini-stamp { position: static; display: block; margin-top: 16px; transform: none; } }

/* The stamped paper tape from the film (a generated photo, assets/tape.png). */
.tape { display: block; width: min(100% - 32px, 1200px); height: auto; margin: 0 auto; transform: rotate(-0.6deg); }
.tape-short { width: min(100%, 720px); transform: rotate(0.8deg); }

/* The sixteen habits: a ledger index, group names in the margin. */
.habits h2 { margin-top: 32px; text-align: center; font-size: clamp(36px, 6vw, 64px); line-height: 1.04; letter-spacing: -0.02em; }
.ledger { margin-top: 40px; padding: 8px clamp(16px, 4vw, 40px); background: var(--tile); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow); }
.group { display: grid; gap: 4px 32px; padding: 20px 0; border-bottom: 1px solid var(--line); }
.group:last-child { border-bottom: 0; }
@media (min-width: 760px) { .group { grid-template-columns: 9rem 1fr; } }
.group h3 { font-size: 30px; padding-top: 6px; }
.group ul { margin: 0; padding: 0; list-style: none; }
.group li { display: grid; grid-template-columns: 28px minmax(10rem, 15rem) 1fr; gap: 6px 16px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--line); }
.group li:last-child { border-bottom: 0; }
.group b { font-weight: 600; }
.group span { color: var(--pencil); font-size: 15px; }
@media (max-width: 620px) { .group li { grid-template-columns: 28px 1fr; } .group span { grid-column: 2; } }
.glyph { width: 28px; height: 28px; background: currentColor; -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat; }

/* Questions: ruled rows; the plus turns into a cross when open. */
.faq { max-width: 860px; padding-bottom: 96px; }
.faq h2 { margin-bottom: 24px; }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 22px 0; cursor: pointer; list-style: none;
  font: 700 clamp(20px, 2.4vw, 26px)/1.25 var(--display);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; flex: 0 0 auto; font: 400 32px/1 -apple-system, sans-serif; transition: transform 200ms ease; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details p { margin: -6px 0 22px; max-width: 42em; color: var(--pencil); }

/* Closing band: the ink desk again. The headline is the link; its arrow runs along a ledger rule. */
.close, .foot { background: var(--desk); color: var(--desk-text); }
.close { position: relative; padding: 104px clamp(16px, 6vw, 96px) 72px; }
.close h2 { max-width: 1080px; margin: 0 auto; font-size: clamp(44px, 7.4vw, 104px); line-height: 1; letter-spacing: -0.03em; }
.close-link { display: block; color: var(--desk-text) !important; text-decoration: none; }
.close-rule { position: relative; display: block; height: 2px; margin-top: 36px; background: rgba(246, 244, 239, 0.4); }
.close-rule::after {
  content: ""; position: absolute; left: 0; top: -7px; width: 16px; height: 16px; border-top: 2px solid var(--desk-green); border-right: 2px solid var(--desk-green);
  transform: translateX(0) rotate(45deg); transition: transform 600ms cubic-bezier(0.3, 0.7, 0.2, 1);
}
.close-link:hover .close-rule::after, .close-link:focus-visible .close-rule::after { transform: translateX(min(80vw, 1060px)) rotate(45deg); }
.close-hint { position: absolute; left: 0; top: 14px; font: 600 16px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; letter-spacing: 0.02em; color: var(--desk-green); }
/* Kept's mark, stamped on the closing band. */
.tag { position: absolute; right: clamp(16px, 8vw, 120px); top: 60px; width: 104px; height: 104px; background: var(--desk-green); }
@media (max-width: 720px) { .tag { width: 64px; height: 64px; top: 28px; } }

.foot { padding: 32px clamp(16px, 6vw, 96px) max(40px, env(safe-area-inset-bottom)); border-top: 1px solid rgba(246, 244, 239, 0.18); color: var(--desk-muted); font-size: 14px; }
.foot nav { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-bottom: 12px; font-size: 15px; }
.foot a { color: var(--desk-text); }
.foot p { margin: 4px 0; }

/* ---- Phones: copy sits low over a shade from the bottom; the chapter stamps move to the top ---- */
@media (max-width: 860px) {
  .film-shade {
    background:
      linear-gradient(180deg, rgba(28, 33, 67, 0.9) 0, rgba(28, 33, 67, 0) 150px),
      linear-gradient(0deg, rgba(28, 33, 67, 0.95) 0%, rgba(28, 33, 67, 0.9) 42%, rgba(28, 33, 67, 0) 72%);
  }
  .chapter { align-items: flex-end; padding: 120px 16px max(48px, env(safe-area-inset-bottom)); }
  .copy { max-width: 36rem; }
  .chapter p { font-size: 17px; }
  .chapter h1 { font-size: clamp(34px, 10vw, 48px); }
  .chapter-end .copy { top: 52dvh; }
  .rail { top: calc(max(20px, env(safe-area-inset-top)) + 56px); right: 16px; transform: none; grid-auto-flow: column; gap: 8px; }
  .rail li { width: 24px; height: 24px; }
  .rail li::after { inset: -5px; }
  .nav-join { font-size: 15px; }
  .calc, .habits, .faq { padding-top: 72px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
