/* smore — marketing site.

   The s'more, on paper: toned paper lit from above, cocoa ink,
   hairlines, graham for the one thing to do, money in green and clay.
   Every color here is a variable because the page runs through an
   evening — golden hour at the top, dusk, sunset, and night by the fire
   at the end — and line.js melts one into the next as the line
   unfolds, so the paper turns over exactly when it does.
   Headlines take Rubik, standing in for the app's display face:
   oversized, heavy, soft-cornered, tightly tracked. Everything else
   is Inter, but for the odd note in hand, in Gaegu, the way the teaser
   writes smore.money. All three are self-hosted and none is Apple's
   system face, which the site can't use. */

/* Rubik and Inter, each one variable file for the Latin set the page
   uses, under the SIL Open Font License 1.1 — see fonts/*-OFL.txt. */
@font-face {
  font-family: "Rubik";
  src: url("/fonts/Rubik-Variable-latin.woff2") format("woff2");
  font-weight: 500 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Inter";
  src: url("/fonts/Inter-Variable-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Gaegu, bold, for the notes in hand — the Latin set, under the SIL
   Open Font License 1.1 (fonts/Gaegu-OFL.txt). */
@font-face {
  font-family: "Gaegu";
  src: url("/fonts/Gaegu-Bold-latin.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Inter's right arrow, which the Latin file leaves out: its own file,
   fetched only by a page that has one (the privacy policy). */
@font-face {
  font-family: "Inter";
  src: url("/fonts/Inter-arrow.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+2192;
}

:root {
  /* The s'more, from the teaser: graham, cocoa, mallow, char. The page
     opens at golden hour and runs to night by the fire (line.js paints
     each section's colors as the page scrolls); these are the top's. */
  --graham: #dea45b;
  --cocoa: #481f19;
  --mallow: #f4f4ec;
  --char: #070506;
  --paper: #f3e7d3;
  --paper-top: #fcf5e8;
  --paper-bottom: #e6d0ae;
  --surface: #faf1e3;
  --hairline: #e3d2b8;
  --accent: var(--graham);
  --positive: #5c6b2b;
  --negative: #9a4f30;
  /* The ink is cocoa, in every theme but night, where it's the mallow. */
  --ink: #481f19;
  --ink-2: #5e362d;
  --ink-3: #7a5446;
  /* What's drawn in ink — a phone's frame, a coin's rim — and what a
     lifted thing casts and catches. Tokens, so dark mode can move them. */
  --frame: #2b1511;
  --coin-ink: #481f19;
  --shade: #2b1511;
  --gleam: rgba(255, 255, 255, 0.6);
  --grain: 0.12;
  color-scheme: light;

  /* No system-ui or -apple-system in either list: on Apple devices
     those are SF. */
  --display: "Rubik", "Helvetica Neue", Arial, sans-serif;
  --text: "Inter", "Helvetica Neue", Arial, sans-serif;
  --hand: "Gaegu", "Chalkboard SE", "Comic Sans MS", cursive;
  /* The page's column: never wider than --page, centered, and never
     closer to the window's edge than the side margin — wide enough on a
     phone for the line to run down its middle, roomier on a desktop. */
  --page: 1120px;
  --margin: max(clamp(28px, 7vw, 120px), calc((100vw - var(--page)) / 2));

  /* Four sizes, and no fifth. */
  --size-display: clamp(40px, 5vw, 60px);
  --size-large: clamp(22px, 2.2vw, 30px);
  --size-body: 18px;
  --size-small: 14px;
}

/* Dark: golden hour's dark tones, until the scroll says otherwise
   (line.js paints each section's). Ink turns to the mallow; what's drawn in ink stays drawn. Follows the
   system, unless the page is stamped with a choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #1c1610;
    --paper-top: #100c08;
    --paper-bottom: #33271a;
    --surface: #28201a;
    --hairline: #3a2f24;
    --accent: #c99550;
    --positive: #9db266;
    --negative: #d08f6e;
    --ink: #f4f4ec;
    --ink-2: #d9d6cb;
    --ink-3: #a39e92;
    --frame: #3b3430;
    --coin-ink: #896f69;
    --shade: #000;
    --gleam: rgba(255, 255, 255, 0.05);
    --grain: 0.09;
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --paper: #1c1610;
  --paper-top: #100c08;
  --paper-bottom: #33271a;
  --surface: #28201a;
  --hairline: #3a2f24;
  --accent: #c99550;
  --positive: #9db266;
  --negative: #d08f6e;
  --ink: #f4f4ec;
  --ink-2: #d9d6cb;
  --ink-3: #a39e92;
  --frame: #3b3430;
  --coin-ink: #896f69;
  --shade: #000;
  --gleam: rgba(255, 255, 255, 0.05);
  --grain: 0.09;
  color-scheme: dark;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

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

/* Nothing ever widens the page — iOS Safari zooms out to show whatever
   pokes past the edge, and ignores body's overflow for it; clip, unlike
   hidden, makes no scroll box, so the review still holds (sticky). The
   ground behind the page is the top of the paper, which is what Safari
   shows round its bars. */
html { -webkit-text-size-adjust: 100%; overflow-x: clip; background: var(--paper-top); }

body {
  background: var(--paper);
  font-family: var(--text);
  font-weight: 400;
  color: var(--ink);
  min-height: 100vh;
  overflow-x: clip;
}

/* The paper, lit from above the way the app's home poster is: brightest
   at the top of the window, settling deeper toward the bottom. Pinned,
   so the light stays where it is while the page runs past. */
body::before {
  content: "";
  position: fixed;
  /* Past the window's top and bottom by a toolbar's height, in the end
     colors: Safari draws the page under its see-through bars, and the
     wash has to carry on under them rather than stop short. */
  inset: -160px 0;
  z-index: -2;
  background: linear-gradient(var(--paper-top) 160px, var(--paper-bottom) calc(100% - 160px));
}

/* The tooth of the paper: a tile of fractal noise over the wash, faint
   enough to be felt rather than seen. It sits under the shape and
   under the words, so nothing has to read through it. */
body::after {
  content: "";
  position: fixed;
  inset: -160px 0;
  z-index: -1;
  pointer-events: none;
  opacity: var(--grain);
  background-image: url("/img/grain.svg");
  background-size: 160px 160px;
}

/* ---- The line --------------------------------------------------------- */

/* One canvas, a few windows tall, sitting in the page and scrolling
   with it — line.js moves it on when the window nears its edge — so
   the line stays exactly with the words through a fling on a phone.
   It is drawn under the words and never takes a click. */
.line {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
  pointer-events: none;
  will-change: transform;
}

/* Across the review, three grey dots just ahead of the line's end
   (line.js), for the line to fill; the bulb on the end is the line's
   own, drawn by its shader. */
.line-guide {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
  width: 100%;
  overflow: visible;
  pointer-events: none;
}
.guide-dot { fill: color-mix(in srgb, var(--ink) 32%, transparent); }
.colophon { position: relative; z-index: 1; }

/* Main holds no layer of its own: each section holds one over the
   line, all but the first — see #hero. */
main { position: relative; }

/* The marshmallow (#coin-face): lit from the left and turning away on
   the right, a faint sheen along its top, a soft shadow under it, toasted along its crown in whatever the section says (--coin), and a line that's cocoa
   on light paper and a lighter brown on dark. Here rather than
   on the symbol, so the page carries no inline style for the policy in
   _headers to refuse. */
/* The mallow takes a little of the paper, so it doesn't glare on dark
   paper; on light paper that's next to nothing. */
:root {
  --mallow-face: color-mix(in srgb, var(--mallow) 90%, var(--paper));
}
.mallow-lit { stop-color: color-mix(in srgb, var(--mallow-face) 72%, #fff); }
.mallow-mid { stop-color: var(--mallow-face); }
.mallow-turn { stop-color: color-mix(in srgb, var(--mallow-face) 82%, var(--graham)); }
.mallow-shade { stop-color: var(--cocoa); }
.mallow-glint-line { stroke: #fff; opacity: 0.8; }
.mallow-ground { fill: var(--cocoa); opacity: 0.22; }
.coin-face { fill: var(--coin); }
.coin-ink { stroke: var(--coin-ink); }

/* ---- The bar ---------------------------------------------------------- */

/* The name, three stops on the page, and the one thing to do. It holds
   to the top of the window over the line, and takes a ground — the
   paper, frosted, and a hairline — only once the page has moved under
   it (page.js marks it). */
.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 32px;
  padding: 16px var(--margin);
}

/* The ground sits on a layer of its own and fades in whole — frost,
   paper and hairline together — so nothing snaps when it arrives. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--paper-top) 78%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  border-bottom: 1px solid var(--hairline);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.nav.moved::before { opacity: 1; }

/* The name is the smore mark, drawn in pen (img/smore-wordmark.svg, from
   the brand studio). It's a mask filled with the ink, so it turns cream
   in dark mode with the words; the name itself is there for screen
   readers. Its pen line is fine, so it's set a little larger than a
   name in type would be, to hold its own beside the headlines. */
.name {
  display: inline-block;
  height: 38px;
  aspect-ratio: 287.42 / 93.62;
  background: var(--ink);
  -webkit-mask: url("/img/smore-wordmark.svg") center / contain no-repeat;
  mask: url("/img/smore-wordmark.svg") center / contain no-repeat;
  flex: none;
}

.nav-links { display: flex; gap: 28px; margin-left: auto; }

.nav-links a,
.colophon-links a {
  font-size: var(--size-small);
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
}

.nav-links a:hover,
.colophon-links a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 4px; }

/* The one thing to do, in the bar: the app's primary button, with the
   s'more in outline at its left, drawn in pen like the rest of the
   brand (img/smore-outline.svg, a mask in the button's ink). */
.nav-action {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 11px 20px 11px 16px;
  border-radius: 13px;
  background: var(--accent);
  color: var(--cocoa);
  font-size: 16px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  box-shadow: 0 4px 14px -6px color-mix(in srgb, var(--accent) 60%, transparent);
  transition: transform 0.15s;
}

/* Small, and pressed down a little — a fifth shorter than the drawing —
   so it sits low and tight beside the words. */
.nav-action-icon {
  flex: none;
  width: 23px;
  aspect-ratio: 144 / 85;
  background: currentColor;
  -webkit-mask: url("/img/smore-outline.svg") center / 100% 100% no-repeat;
  mask: url("/img/smore-outline.svg") center / 100% 100% no-repeat;
}

/* The hero's copy of it, for phones. There the button sits under the
   hero's words, and the bar's own waits until that one has gone up
   under the bar — page.js marks the bar `waits` when there's a hero
   button to wait for, and `action-due` once it's gone. */
.hero-action { display: none; }
@media (max-width: 900px) {
  .hero-action { display: inline-flex; margin-top: 24px; }
  .nav.waits .nav-action { transition: opacity 0.35s ease, transform 0.15s; }
  .nav.waits:not(.action-due) .nav-action { opacity: 0; pointer-events: none; visibility: hidden; }
}

.nav-action:hover { transform: translateY(-1px); }
.nav-action:active { transform: scale(0.97); }

/* ---- The beta note ---------------------------------------------------- */

/* What "Get smore" opens (beta.js): a card on the dimmed page, the
   app's surface and ink, one accent button. The dialog itself is only
   the frame, so a click on it and not the card is a click outside. */
.beta {
  margin: auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  max-width: calc(100vw - 32px);
}
.beta::backdrop {
  background: color-mix(in srgb, var(--char) 38%, transparent);
  backdrop-filter: blur(4px);
}
.beta-card {
  position: relative;
  width: min(420px, calc(100vw - 32px));
  padding: 36px 30px 24px;
  border-radius: 26px;
  background: var(--surface);
  box-shadow: 18px 18px 0 color-mix(in srgb, var(--shade) 10%, transparent);
}
.beta h2 {
  font-size: var(--size-large);
  line-height: 1.1;
  padding-right: 32px;
}
.beta-card > p:not(.beta-note) {
  margin-top: 0.7em;
  font-size: var(--size-body);
  line-height: 1.5;
  color: var(--ink-2);
}
.beta-form {
  display: grid;
  gap: 10px;
  margin-top: 22px;
}
.beta-form input {
  width: 100%;
  padding: 14px 16px;
  border: 1.5px solid var(--hairline);
  border-radius: 14px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 16px; /* no zoom on focus in iOS Safari */
}
.beta-form input::placeholder { color: var(--ink-3); }
.beta-form input:focus { outline: none; border-color: var(--ink); }
.beta-form input[aria-invalid="true"] { border-color: var(--negative); }
.beta-form button {
  padding: 14px 18px;
  border: 0;
  border-radius: 14px;
  background: var(--accent);
  color: var(--cocoa);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 6px 18px -8px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: transform 0.15s;
}
.beta-form button:hover { transform: translateY(-1px); }
.beta-form button:active { transform: scale(0.98); }
.beta-form button:disabled { opacity: 0.6; cursor: default; transform: none; }
.beta-form[hidden], .beta-status:empty { display: none; }
.beta-status { font-size: var(--size-small); color: var(--ink-2); }
.beta-thanks {
  margin-top: 22px;
  padding: 14px 16px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--positive) 14%, transparent);
  color: var(--ink);
  font-weight: 600;
}
.beta-note {
  margin-top: 14px;
  font-size: var(--size-small);
  line-height: 1.5;
  color: var(--ink-3);
  text-align: center;
}
.beta-note a { color: inherit; text-underline-offset: 3px; }
.beta-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink-2);
  cursor: pointer;
}
.beta-close svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }
.beta-form button:focus-visible, .beta-close:focus-visible, .beta-note a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
  .beta[open] .beta-card { animation: beta-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.15); }
}
@keyframes beta-in {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to { opacity: 1; transform: none; }
}

.nav a:focus-visible,
.colophon a:focus-visible,
summary:focus-visible,
.promises a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px; }

/* The stops the bar jumps to land clear of it. */
html { scroll-padding-top: 72px; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

/* ---- A section: one stop, one rested shape -------------------------- */

.stage {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  padding: clamp(80px, 12vh, 128px) var(--margin);
}

#hero { min-height: 88vh; }

/* The line starts in the hero's phone — once round the ring in the
   screenshot and out through its side — so the hero lets it over the
   phone. Only the words keep a layer over it. */
#hero { z-index: auto; }
#hero .words { position: relative; z-index: 1; }

/* Room for the ring beside the words, and for the line to bounce in
   above it and leave it below. The words give the ring a little more
   of the column where the column is short, so the ring can be big
   enough to hold the goal at a heading's size. */
#circle { min-height: max(600px, 76vh); }
/* Room for the pile of share cards, and for the text conversation the
   line hangs beside them (line.js). */
#next { min-height: max(680px, 80vh); }
#circle .words { max-width: min(600px, 54%); }

/* A breath between the ring and the three cards, room for the line to
   come down to them at the pace of the scroll, and room under the cards
   for the line to run back along. */
#three { margin-top: clamp(48px, 12vh, 140px); padding-bottom: clamp(120px, 20vh, 220px); }

main { position: relative; }

#trust, #faq { min-height: 0; }

.words { width: 100%; max-width: 600px; }
.words.right { margin-left: auto; }
.words.wide { max-width: none; margin: 0; }

h1, h2, .amount, blockquote, .action {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.03;
}

h1, h2 { font-size: var(--size-display); }

/* A section's heading is two lines, broken by hand, and the words under
   it keep to its width — a little wider under a short heading, so a
   line of them still reads. The heading sets the width; the words take
   none of their own (width 0) and stretch to it. */
hgroup { width: fit-content; max-width: 100%; }
hgroup .lede { width: 0; min-width: max(100%, 19em); text-wrap: pretty; }

/* The hero's line is the page's poster: far bigger than any heading
   after it, set tight, and given the room left of the phone. */
#hero h1 {
  font-size: clamp(54px, 7.6vw, 108px);
  letter-spacing: -0.045em;
  line-height: 0.94;
}

#hero .words { max-width: 720px; }

/* The s'more and the name over the headline, small beside it, the name
   under the s'more the way the teaser ends. The name is the bar's mark
   at a larger size, so it can unravel and write itself into the bar
   (nameflight.js). */
.lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: fit-content;
  margin: 0 0 clamp(18px, 2.6vh, 28px);
}
.lockup-icon {
  display: block;
  width: clamp(92px, 8.4vw, 120px);
  height: auto;
}
.lockup-name { display: block; height: clamp(46px, 4.2vw, 58px); margin-top: 6px; }

/* While the name unravels into the bar, the bar's own waits for it. The
   thread is drawn on a canvas over everything, fixed to the window. */
.name-flies .nav .name { opacity: 0; }
.name-flies.name-landed .nav .name { opacity: 1; }
/* Scrolled quickly, the thread is skipped and the name fades in. */
/* Only a start: it ends on whatever the rules above say, so the bar's
   name can still hide again at the top of the page. */
.name-fade-in { animation: name-fade-in 0.45s ease; }
@keyframes name-fade-in { from { opacity: 0; } }
.name-thread {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 11;
  pointer-events: none;
  visibility: hidden;
}
#hero .lede { max-width: 30em; font-size: clamp(19px, 1.55vw, 23px); line-height: 1.5; }

/* The headline's full stop, as a marshmallow — the size of a heavy full
   stop and a little more, sitting on the baseline. */
.last-word { white-space: nowrap; }
.coin-stop {
  display: inline-block;
  width: 0.28em;
  height: 0.28em;
  margin-left: 0.04em;
  vertical-align: baseline;
}
.coin-stop svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* The marshmallow rolls off the headline and falls out of the window
   (page.js) — there's more below. Where it was, a dashed outline of it;
   at the foot of the page, it's the footer line's full stop. */
.coin-stop { position: relative; }

/* The headline's marshmallow, and the footer's, toasted in graham. */
.coin-stop, .coin-slot-coin { --coin: var(--graham); }
.coin-stop.gone svg { visibility: hidden; }
.coin-stop.gone::after {
  content: "";
  position: absolute;
  inset: 15% 14%;
  border-radius: 26%;
  border: 0.018em dashed var(--ink-3);
  opacity: 0.7;
}

.coin-flying {
  position: fixed;
  z-index: 20;
  margin: 0;
  pointer-events: none;
}

.coin-slot { display: inline-block; }
.coin-slot-coin {
  display: none;
  width: 0.95em;
  height: 0.95em;
  margin-left: 0.14em;
  vertical-align: -0.1em;
  overflow: visible;
}
.coin-slot.landed .coin-slot-coin { display: inline-block; }
.coin-slot.landed .coin-slot-stop {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
.coin-slot.landing .coin-slot-coin { animation: land 0.75s cubic-bezier(0.3, 1.5, 0.5, 1) both; }

@keyframes land {
  from { transform: translateY(-3em) rotate(-160deg); }
  to { transform: none; }
}

.lede {
  font-size: var(--size-body);
  line-height: 1.55;
  color: var(--ink-2);
  margin-top: 1.1em;
}

.quiet {
  font-size: var(--size-small);
  line-height: 1.6;
  color: var(--ink-3);
  margin-top: 1.6em;
  max-width: 46ch;
}

/* Words that stay on one line, like "check-in" — Rubik has no
   non-breaking hyphen. */
.whole { white-space: nowrap; }

/* Read aloud, never drawn. */
.offscreen {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- The welcome's three beats, as they sit on the first screen ----- */

.beats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
  margin-top: 104px;
}

/* The app's sample card — surface, a hairline, soft corners — with the
   step's title and its question, and under them one motif from the app
   that stands for the step: the dial, coins leaving a row, the ring.
   Kept abstract; the sections below show each step for real. The cards
   are solid, so the line passes behind them and shows in the gaps. */
/* One card, used for the three steps and the four promises: the app's
   surface, a hairline, soft corners, and a lift so slight it reads as
   paper on paper. What's on it is set the same way on both: a heading
   in the display face, always one line, then a sentence that says a
   little more, then the motif. */
.beat,
.promises li {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  padding: 28px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 22px;
  box-shadow: 0 1px 0 var(--gleam) inset, 0 10px 30px -18px color-mix(in srgb, var(--shade) 18%, transparent);
}

/* The heading: one line, always — it sizes down with its card rather
   than wrap (each grid sets how far, by its longest heading). */
.beat-title,
.promises h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: min(24px, var(--fit));
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--ink);
  white-space: nowrap;
}

.beat { --fit: 8cqi; }
.promises li { --fit: 4.4cqi; }

/* The sentence under it. */
.question,
.promises p {
  margin-top: 8px;
  font-family: var(--text);
  font-weight: 400;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ink-2);
}

.beat-art {
  position: relative;
  flex: 1;
  min-height: 184px;
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* Set your goal: the dial, larger, turning. */
.beat-art .ruler { flex: none; width: 100%; max-width: 260px; height: 64px; }

/* Review with intention: a row of marshmallows, a few of which leave it
   for the bank below. */
.mini-visits { display: flex; justify-content: center; gap: 8px; }

.mini-coin {
  position: relative;
  flex: none;
  width: var(--d, 26px);
  height: var(--d, 26px);
  --coin: color-mix(in srgb, var(--graham) 45%, var(--mallow));
}

.mini-coin svg { display: block; width: 100%; height: 100%; }

/* What a skipped visit leaves behind: the ring of where it was. */
.mini-coin.left svg { visibility: hidden; }
.mini-coin.left::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 28%;
  border: 1.5px dashed var(--ink-3);
  opacity: 0.6;
}

.mini-bank { width: 132px; height: 64px; margin-top: 28px; border-bottom: 1.5px solid var(--hairline); }

/* A marshmallow in the bank: toasted clay while short of the goal,
   golden once there. */
.banked {
  position: absolute;
  left: 0;
  top: 0;
  --coin: var(--negative);
  pointer-events: none;
}

.banked svg { display: block; width: 100%; height: 100%; }

.review-art.reached .banked {
  --coin: var(--graham);
}

/* Track your spending: the ring, closing clockwise from the top. */
.mini-ring { display: block; width: 150px; height: 150px; transform: rotate(-90deg); overflow: visible; }
.ring-track { fill: none; stroke: color-mix(in srgb, var(--hairline) 80%, var(--surface)); stroke-width: 12; }

.ring-arc {
  fill: none;
  stroke: var(--positive);
  stroke-width: 12;
  stroke-linecap: round;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 0;
  filter: drop-shadow(1.5px 2.5px 0 color-mix(in srgb, var(--shade) 14%, transparent));
}

.amount { font-size: var(--size-body); letter-spacing: -0.4px; font-variant-numeric: tabular-nums; }

/* The goal dial, still: a row of ticks fading toward the edges, the
   needle on the center — what shows until dial.js draws it turning. */
.ruler {
  position: relative;
  flex: 1;
  min-width: 90px;
  height: 30px;
  background-image:
    repeating-linear-gradient(90deg, var(--ink-2) 0 2px, transparent 2px 25px),
    repeating-linear-gradient(90deg, var(--ink-2) 0 1px, transparent 1px 5px);
  background-size: 100% 17px, 100% 9px;
  background-position: center 8px, center 12px;
  background-repeat: repeat-x;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
}

.ruler::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 4px;
  bottom: 4px;
  width: 3px;
  margin-left: -1.5px;
  background: var(--ink);
}

/* ---- The three flows ------------------------------------------------ */

.flows { position: relative; }

.rows.ledger li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-variant-numeric: tabular-nums;
}

.sum { font-weight: 700; }

.dial {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: clamp(24px, 4vh, 36px);
}

.amount.big { font-size: var(--size-large); letter-spacing: -0.03em; }

.ruler.tall { height: 44px; max-width: 320px; }

/* Once dial.js draws the ruler, the still picture of it gives way. */
.ruler.drawn { background: none; -webkit-mask-image: none; mask-image: none; }
.ruler.drawn::after { display: none; }
.ruler.drawn canvas { position: absolute; inset: 0; display: block; }

/* ---- The review's example: the app's skip screen, on a sheet ------ */

/* "Hit your goal", the screen the review opens on, set on a sheet of
   the app's surface: last month in a line; the places you went, with a
   coin for every visit; the bank the skipped visits fall into; and
   where that leaves you against the goal. plan.js runs it. */
.sheet {
  position: relative;
  padding: 24px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 28px;
  box-shadow: 14px 14px 0 color-mix(in srgb, var(--shade) 6%, transparent);
  font-variant-numeric: tabular-nums;
}

.sheet-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--size-large);
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.sheet-month {
  margin-top: 8px;
  font-size: var(--size-small);
  line-height: 1.5;
  color: var(--ink-3);
}

.sheet-month strong { font-weight: 600; color: var(--ink-2); }

/* A place, as the app lists it: the name, and the stepper — plus, the
   spend you'd keep, minus; how often and what it counts as; and then
   the visits themselves — one coin each, sized by what a visit costs. */
.habits { margin-top: 16px; border-top: 1px solid var(--hairline); }

.habit {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 12px;
  align-items: center;
  padding: 12px 0 14px;
  border-bottom: 1px solid var(--hairline);
}

.habit-name {
  font-size: var(--size-body); font-weight: 600; line-height: 1.3;
  /* One line, always: a long name trails off rather than wrapping into
     the line under it. */
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.habit-meta { grid-column: 1 / -1; margin-top: 2px; font-size: var(--size-small); color: var(--ink-3); }

/* The app's stepper: two quiet squares either side of the spend. */
.stepper { display: flex; align-items: center; gap: 8px; }
.stepper .sum { min-width: 4.3em; text-align: right; font-size: var(--size-body); line-height: 1.3; }

.step {
  appearance: none;
  -webkit-appearance: none;
  width: 30px;
  height: 30px;
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 9px;
  background: color-mix(in srgb, var(--hairline) 65%, transparent);
  display: grid;
  place-items: center;
  font: inherit;
  font-size: var(--size-body);
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
  transition: transform 0.12s, opacity 0.2s, background 0.2s;
}

.step:hover:not(:disabled) { background: var(--hairline); }
.step:active:not(:disabled) { transform: scale(0.9); }
.step:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.step:disabled { opacity: 0.35; cursor: default; }

/* A number that changes flips to the new one, digit by digit, the way
   the app's numbers do: only the digits that changed move. */
.flip { display: inline-block; white-space: pre; }
.habit.gone .habit-name { text-decoration: line-through; text-decoration-thickness: 1px; color: var(--ink-2); }

.visits {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
}

/* A visit: a marshmallow still in the bag, barely toasted. Tap it to skip
   the visit and it drops into the bank; what's left in the row is the
   dashed outline of it, which brings it back. */
.visit {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: none;
  width: calc(var(--d, 26px) * var(--k, 1));
  height: calc(var(--d, 26px) * var(--k, 1));
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 28%;
  background: none;
  cursor: pointer;
  --coin: color-mix(in srgb, var(--graham) 45%, var(--mallow));
  transition: transform 0.2s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.visit svg { display: block; width: 100%; height: 100%; transition: opacity 0.2s, transform 0.2s; }
.visit::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 28%;
  border: 1.5px dashed var(--ink-3);
  opacity: 0;
  transition: opacity 0.25s;
}

.visit:hover:not([aria-pressed="true"]) { transform: translateY(-3px); }
.visit:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.visit[aria-pressed="true"] svg { opacity: 0; transform: scale(0.6); }
.visit[aria-pressed="true"]::after { opacity: 0.6; }

/* The bank: the pit the skipped visits fall into, and what's in it.
   The coins are drawn in .coins over the whole sheet, so they fall from
   the row they left; plan.js runs the physics. */
.bank {
  position: relative;
  height: 56px;
  border-bottom: 1.5px solid var(--hairline);
}

/* Until a coin lands, the empty bank says what to do. */
.bank-hint {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--size-small);
  color: var(--ink-3);
  transition: opacity 0.3s;
}

.bank.filled .bank-hint { opacity: 0; }

.bank-sum {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  font-size: var(--size-small);
  color: var(--ink-3);
}

.bank-sum strong { font-weight: 700; color: var(--ink); }

/* Where that leaves you: the distance to the goal, large, wearing
   loss or gain, and a bar that fills as the bank does and turns green
   when it gets there. */
.standing { margin-top: 16px; }

.distance-line { font-size: var(--size-body); line-height: 1.35; color: var(--ink-2); }
.distance-line strong { font-weight: 700; color: var(--ink); }

.distance-line .distance {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--size-large);
  letter-spacing: -0.03em;
  margin-right: 2px;
}

.distance-line .distance.loss { color: var(--negative); }
.distance-line .distance.gain { color: var(--positive); }

.meter {
  margin-top: 12px;
  height: 10px;
  border-radius: 5px;
  background: color-mix(in srgb, var(--hairline) 70%, var(--surface));
  overflow: hidden;
}

.meter span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--negative);
  transition: width 0.35s cubic-bezier(0.2, 0.7, 0.2, 1), background 0.4s;
}

.sheet.reached .meter span { background: var(--positive); }
.sheet.reached .meter { animation: reached 0.6s cubic-bezier(0.3, 1.4, 0.5, 1); }

@keyframes reached {
  40% { transform: scaleY(1.8); }
}

/* The coins that have dropped: clay while you're short, green once
   you're there — the app's bank. */
.coins {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}

.coin {
  position: absolute;
  left: 0;
  top: 0;
  --coin: var(--negative);
  will-change: transform;
}

.sheet.reached .coin {
  --coin: var(--graham);
}

.coin svg { display: block; width: 100%; height: 100%; }

.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* "Test it out!": a note in the sheet's top corner, drawn the way the
   s'more is — a marshmallow on a stick in pen, the words in hand, and
   an arrow down to the habits. In the ink, with the mallow toasted in
   graham. */
.sticker {
  position: absolute;
  top: -104px;
  right: -92px;
  z-index: 3;
  width: 220px;
  aspect-ratio: 230 / 170;
  pointer-events: none;
}

.sticker-art { display: block; width: 100%; height: 100%; overflow: visible; }
.sticker-stick { fill: none; stroke: var(--ink); stroke-width: 4; stroke-linecap: round; }
.sticker-mallow { fill: var(--mallow); }
.sticker-toast { fill: var(--graham); }
.sticker-ink { fill: none; stroke: var(--ink); stroke-width: 3.5; stroke-linejoin: round; }
.sticker-arrow { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }

.sticker-words {
  position: absolute;
  left: -4%;
  top: 8%;
  transform: rotate(-7deg);
  font-family: var(--hand);
  font-weight: 700;
  font-size: 30px;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink);
}

/* The receipt: the plan read back as one plain sentence. */
.receipt {
  margin-top: 16px;
  font-size: var(--size-large);
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--ink-2);
}

.receipt strong { font-weight: 700; color: var(--ink); }

/* ---- Hairline rows: the lessons, and what comes next ---------------- */

.rows { list-style: none; margin-top: clamp(24px, 4vh, 36px); }
.quiet + .rows { margin-top: 14px; }
.quiet + .quiet { margin-top: 0.6em; }
.quiet a { color: var(--ink-2); text-decoration: underline; text-decoration-color: var(--ink-3); text-underline-offset: 3px; }

.rows li {
  font-size: var(--size-body);
  line-height: 1.5;
  padding: 11px 0;
  border-bottom: 1px solid var(--hairline);
}

.rows li:first-child { border-top: 1px solid var(--hairline); }

.rows.spaced li { padding: 18px 0; color: var(--ink-2); }
.rows.spaced strong { display: block; font-weight: 700; color: var(--ink); }

/* The saying, on its own: a clear, centered header between the review
   and the check-in, in Ember's orange deepened toward the ink so it
   reads as large text on the paper (and lightens toward the cream in
   dark mode). */
.saying { justify-content: center; }

blockquote {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--size-display);
  line-height: 1.05;
  letter-spacing: -0.03em;
  max-width: 20ch;
  margin: 0 auto;
  text-align: center;
  text-wrap: balance;
  color: color-mix(in srgb, var(--accent) 60%, var(--ink));
}

/* ---- The app's primary button ---------------------------------------- */

.action {
  display: inline-block;
  margin-top: clamp(28px, 4vh, 40px);
  padding: 16px 40px;
  border-radius: 14px;
  background: var(--accent);
  color: var(--cocoa);
  font-size: var(--size-body);
  font-weight: 600;
  letter-spacing: 0;
  text-decoration: none;
}

.action {
  box-shadow: 0 6px 22px -6px color-mix(in srgb, var(--accent) 45%, transparent);
}

.action { transition: transform 0.15s; }
.action:hover { transform: translateY(-1px); }
.action:active { transform: scale(0.97); }
.action:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

.action + .quiet { margin-top: 0.9em; }

/* A section with a phone: the words on one side, the phone on the
   other, and the shape resting behind the phone. */
.with-phone { justify-content: space-between; gap: clamp(32px, 5vw, 96px); }
.with-phone .words { max-width: 600px; }
.with-phone .phone { flex-shrink: 0; margin-top: 0; }
.phone-first .phone { order: -1; }

/* The goal, in the middle of the ring, the way the app's ring says it:
   what it is, and under it the amount — both at a heading's size, as
   far as the ring can hold them (line.js sizes them down to fit).
   Placed by the route. */
.in-ring {
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: var(--display);
  font-size: var(--size-display);
  line-height: 1.03;
  letter-spacing: -0.03em;
  white-space: nowrap;
  pointer-events: none;
}

.in-ring span {
  font-weight: 700;
  color: var(--ink-2);
}

.in-ring strong {
  font-weight: 800;
  color: var(--ink);
}

.in-ring { opacity: 0; transition: opacity 0.25s; }
.no-line .in-ring, .no-line .ring-room { display: none; }

/* Room for the ring on a narrow window; nothing on a wide one. */
.ring-room { display: none; }

/* With the line, the Get Started button is the foot of the flame the
   line ends in: room above it for the flame's point, and below it for
   its round foot. On a narrow window it sits in the middle, so the
   flame fits. */
.has-line #close .action { margin-top: 240px; }
.has-line #close .action + .quiet { margin-top: 116px; }

/* The share card, beside its words. */
#next { justify-content: space-between; gap: clamp(32px, 5vw, 96px); }
.card { width: min(300px, 70vw); flex-shrink: 0; }
.card img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 28px;
  box-shadow: 0 2px 14px color-mix(in srgb, var(--shade) 18%, transparent);
}

/* The pile: the app's card on top, the same card personalized six ways
   squared up close behind it, the way a stack of photos sits in a hand
   — each one further back stepped a little up and right, turned a
   little further, a little smaller and in a little shade, so the top
   three show their edges past it and the rest wait out of sight
   behind. Each card's place in the pile is its data-slot, 0 on top:
   the pile turns over on its own while it's in view, and a swipe, a
   tap or an arrow key turns it too — the top card slides out, tucks
   under, and the rest each step up one place (page.js). */
.deck {
  position: relative;
  width: min(280px, 64vw);
  aspect-ratio: 1;
  /* Room for the pile's edges past the top card. */
  margin-right: max(0px, calc(56px - var(--margin)));
  perspective: 1400px;
  touch-action: pan-y;
  cursor: grab;
  -webkit-user-select: none;
  user-select: none;
}
.deck:active { cursor: grabbing; }
.deck:focus-visible { outline: 2px solid var(--ink); outline-offset: 10px; border-radius: 30px; }
.deck .deck-card {
  position: absolute;
  inset: 0;
  --x: 0%; --y: 0%; --r: -2deg; --ry: 0deg; --s: 1; --lit: 1;
  transform: translate(var(--x), var(--y)) rotate(var(--r)) rotateY(var(--ry)) scale(var(--s));
  filter: brightness(var(--lit));
  box-shadow: 0 10px 28px color-mix(in srgb, var(--shade) 22%, transparent);
  -webkit-user-drag: none;
  pointer-events: none;
}
.deck [data-slot="0"] { z-index: 7; }
.deck [data-slot="1"] { z-index: 6; --x: 5%; --y: -2.5%; --r: 1deg; --ry: -6deg; --s: 0.97; --lit: 0.95; }
.deck [data-slot="2"] { z-index: 5; --x: 9.5%; --y: -4.5%; --r: 3.5deg; --ry: -10deg; --s: 0.94; --lit: 0.9; }
.deck [data-slot="3"],
.deck [data-slot="4"],
.deck [data-slot="5"],
.deck [data-slot="6"] { z-index: 4; --x: 13.5%; --y: -6%; --r: 6deg; --ry: -14deg; --s: 0.91; --lit: 0.85; }
.deck [data-slot="4"] { z-index: 3; }
.deck [data-slot="5"] { z-index: 2; }
.deck [data-slot="6"] { z-index: 1; }
@media (prefers-reduced-motion: no-preference) {
  /* A card stepping up a place: as the top one slides away, the next
     comes forward and squares up to face you, the ones behind it just
     after. */
  .deck .deck-card {
    transition: transform 0.55s cubic-bezier(0.22, 0.8, 0.28, 1), filter 0.55s ease;
    transition-delay: calc(0.06s + var(--step, 0) * 0.04s);
  }
  .deck [data-slot="1"] { --step: 1; }
  .deck [data-slot="2"] { --step: 2; }
  /* The top card to the back, in one motion: out to the side, swinging
     away from you as it goes, under the pile at the far end of the arc,
     and in to the back place. It starts from wherever the hand left it
     (--fx, --fy, --fr). */
  .deck .deck-card.to-back { animation: to-back 0.7s cubic-bezier(0.45, 0, 0.2, 1) both; }
  /* The deal: squared up under the top card until it's in view, then
     fanned out, the nearest first. */
  .deck.waiting .deck-card { transform: rotate(-2deg); }
  .deck.dealing .deck-card { transition-duration: 0.7s; transition-delay: calc(var(--step, 0) * 0.08s); }
  /* The card in the hand follows it, with no lag. */
  .deck .deck-card.held { transition: none; }
}
@keyframes to-back {
  0% {
    transform: translate(var(--fx, 0px), var(--fy, 0px)) rotate(var(--fr, -2deg));
    filter: brightness(1);
    z-index: 8;
  }
  42% {
    transform: translate(var(--out, -60%), 2%) rotate(calc(var(--way, -1) * 7deg)) rotateY(calc(var(--way, -1) * -28deg)) scale(0.95);
    filter: brightness(0.92);
    z-index: 8;
  }
  43% { z-index: 0; }
  100% {
    transform: translate(var(--x), var(--y)) rotate(var(--r)) rotateY(var(--ry)) scale(var(--s));
    filter: brightness(var(--lit));
    z-index: 0;
  }
}

/* The review: the words on the left, the skip screen played out on
   the right, the shape below the words. */
/* The review holds still while you scroll through it. On a wide window
   the words take the left column and the sheet the right, and both stay
   where they are for --track of scroll — plan.js sets it, and --stick,
   where they hold — while the scroll plays the sheet. The result sits
   under the words, clear of the part that holds, so it rises into place
   as the hold ends and the line, drawn on the page, can circle it. */
.with-example {
  display: grid;
  grid-template-columns: minmax(0, 600px) min(100%, 560px);
  justify-content: space-between;
  column-gap: clamp(32px, 5vw, 96px);
  align-items: start;
}

.story { display: flex; flex-direction: column; }
.with-example .words { max-width: 600px; }
.lead::after, .example::after { content: ""; display: block; height: var(--track, 0px); }
.lead .words, .example .sheet { position: sticky; top: var(--stick, 0px); }

.example { width: 100%; }

/* Room round the result for the line to loop round it, and the height
   of the result the play ends on held from the start (plan.js measures
   it), so the loop is drawn round the place the result lands. The
   result comes in out of a blur, and goes back into one quicker when a
   hand changes it. */
.with-example .receipt {
  margin-top: 88px;
  min-height: 2.6em;
  opacity: 0;
  filter: blur(12px);
  transform: translateY(10px);
  transition: opacity 0.35s, filter 0.35s, transform 0.35s;
}

.with-example .receipt.shown {
  opacity: 1;
  filter: blur(0);
  transform: none;
  transition: opacity 0.9s, filter 0.9s, transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .with-example .receipt, .with-example .receipt.shown, .visit, .visit svg, .visit::after, .meter span, .bank-hint, .step { transition: none; }
  .sheet.reached .meter { animation: none; }
}

/* ---- What smore can and can't do ------------------------------------ */

/* Four promises, two by two: a small mark drawn the way the app draws
   its icons, a line that says it, and a sentence that backs it. Rules,
   not cards — they're read, not handled. */
.promises {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
  margin-top: clamp(32px, 5vh, 52px);
}

/* The mark sits in a small tile of the paper, where the steps' cards
   have their motif. */
.promise-mark {
  width: 48px;
  height: 48px;
  padding: 11px;
  margin-bottom: 22px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--paper) 70%, var(--surface));
  border: 1px solid var(--hairline);
  fill: none;
  stroke: var(--positive);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.promises p { max-width: 46ch; }

/* ---- Questions --------------------------------------------------------- */

.words.faq { max-width: 760px; }

.questions { margin-top: clamp(28px, 4vh, 44px); border-bottom: 1px solid var(--hairline); }

.questions details { border-top: 1px solid var(--hairline); }

.questions summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  padding: 20px 0;
  font-size: var(--size-large);
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  cursor: pointer;
  list-style: none;
}

.questions summary::-webkit-details-marker { display: none; }

/* A plus that turns to a cross as the answer opens. */
.questions summary::after {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background:
    linear-gradient(var(--ink), var(--ink)) center / 100% 2.4px no-repeat,
    linear-gradient(var(--ink), var(--ink)) center / 2.4px 100% no-repeat;
  transition: transform 0.25s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.questions details[open] summary::after { transform: rotate(45deg); }

.questions details p {
  padding: 0 48px 24px 0;
  font-size: var(--size-body);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 62ch;
}

.questions details p + p { margin-top: -12px; }

.questions details p a,
.promises + .quiet a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--ink-3); text-underline-offset: 3px; }

/* ---- The phone ------------------------------------------------------- */

.phone {
  position: relative;
  width: min(300px, 74vw);
  margin-top: clamp(28px, 4vh, 40px);
  background: var(--surface);
  border: 9px solid var(--frame);
  border-radius: 52px;
  box-shadow: 20px 20px 0 color-mix(in srgb, var(--shade) 7%, transparent);
  overflow: hidden;
  /* A phone held in the hand: turned a little toward the words beside
     it, and tipping back as it passes up the window (page.js sets
     --tip, -1 below the middle to 1 above). The line lays its route by
     the phone's box, not its turn (line.js), so the turn moves nothing. */
  --turn: 0;
  --tip: 0;
  transform: perspective(1600px) rotateY(calc(var(--turn) * 1deg)) rotateX(calc(var(--tip) * -5deg));
  transform-origin: 50% 50%;
}

.phone picture { display: contents; }

.phone img,
.phone video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 43px;
}

/* A screen that moves: the recording sits over its last frame, which is
   the picture, and plays once as the phone comes into view. */
.phone video {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s;
}

/* Turned toward its words: a phone on the right faces left, a phone on
   the left faces right. The hero's holds still — the line starts on it. */
.with-phone .phone { --turn: -9; }
.phone-first .phone { --turn: 9; }
#hero .phone { --turn: 0; transform: none; }

/* The hero's hand of three, all to the right of the line's way out
   down the left: Lagoon peeking out behind the Budget screen, turned a
   little, and the lock screen held up in front of its lower corner,
   smaller, so its check-in reads whole. The front phone holds still
   where the line starts; the fan reaches past the column only into the margin beside it. */
.fan {
  position: relative;
  flex-shrink: 0;
  width: fit-content;
  /* The reach past the front phone is about 0.72 of its width: into
     the window's side margin where there's room, out of the words'
     room where there isn't. */
  margin-right: max(24px, calc(248px - var(--margin)));
}
.fan .phone { margin-top: 0; }
/* One column: the hand a little smaller, and the whole of it — the
   front phone and the reach of the two beside it — centered. */
@media (max-width: 900px) {
  .fan { --w: min(220px, 50vw); align-self: flex-start; margin: 8px 0 18%; margin-left: max(0px, calc(50% - 0.86 * var(--w))); }
  .fan .phone.fan-main { width: var(--w); }
}
#hero .fan-card {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  box-shadow: 14px 14px 0 color-mix(in srgb, var(--shade) 6%, transparent);
}
#hero .fan-theme { transform: translate(36%, -5%) rotate(9deg); }
#hero .fan-lock { transform: translate(84%, 20%) rotate(6deg) scale(0.78); }

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

/* ---- Foot ------------------------------------------------------------ */

/* The name again, the line it stands for, where to read more and who
   to ask, and the year. */
.colophon {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: 8px 32px;
  margin-top: clamp(40px, 8vh, 96px);
  padding: 28px var(--margin) clamp(32px, 6vh, 56px);
  border-top: 1px solid var(--hairline);
}

.colophon-line { font-size: var(--size-small); color: var(--ink-3); }

/* The address in hand, the way the teaser signs off, under the name. */
.colophon-hand {
  grid-column: 1;
  grid-row: 2;
  margin-top: -6px;
  font-family: var(--hand);
  font-weight: 700;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-2);
}
.colophon-links { display: flex; gap: 24px; }
.colophon-fine { grid-column: 1 / -1; font-size: 12px; color: var(--ink-3); }

/* Light or dark: a small switch at the foot, in the app's style — a
   track that takes the accent when on, and a knob that slides. */
.theme-switch {
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--size-small);
  font-weight: 500;
  color: var(--ink-2);
  cursor: pointer;
}

.theme-switch-track {
  position: relative;
  width: 38px;
  height: 22px;
  border-radius: 11px;
  background: color-mix(in srgb, var(--hairline) 55%, var(--ink-3));
  transition: background 0.2s;
}

.theme-switch-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 3px color-mix(in srgb, var(--shade) 30%, transparent);
  transition: transform 0.2s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.theme-switch[aria-checked="true"] .theme-switch-track { background: var(--accent); }
.theme-switch[aria-checked="true"] .theme-switch-thumb { transform: translateX(16px); background: var(--cocoa); }
.theme-switch:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 12px; }

/* ---- Prose pages (privacy) ------------------------------------------- */

.page { padding: clamp(40px, 8vh, 96px) var(--margin) clamp(40px, 8vh, 96px); }

.page h1 { max-width: 14ch; }

/* The privacy page opens on the promises, then the policy in full. */
.summary { margin-bottom: clamp(56px, 10vh, 112px); }
.policy-title { font-size: var(--size-display); max-width: 14ch; }

.dateline {
  margin-top: 1.2em;
  font-style: italic;
  font-size: var(--size-body);
  color: var(--ink-3);
}

.prose {
  max-width: 68ch;
  margin-top: clamp(32px, 6vh, 64px);
}

.prose h2 {
  font-size: var(--size-large);
  letter-spacing: -0.01em;
  margin: 2.4em 0 0.6em;
}

.prose h2:first-child { margin-top: 0; }

.prose p, .prose li { font-size: var(--size-body); line-height: 1.7; }

.prose p + p { margin-top: 0.8em; }

.prose ul { list-style: none; margin-top: 0.6em; }

.prose li { padding: 10px 0; border-bottom: 1px solid var(--hairline); }

.prose li:first-child { border-top: 1px solid var(--hairline); }

.prose strong { font-weight: 700; }

.prose .never { color: var(--negative); }

.prose a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--ink-3);
  text-underline-offset: 3px;
}

/* ---- Small screens --------------------------------------------------- */

@media (max-width: 900px) {
  .stage { min-height: 92vh; padding-block: clamp(56px, 10vh, 96px); }
  .words, .words.right, .words.wide { max-width: none; margin-left: 0; }
  /* One column: the words take the column, however short the heading. */
  hgroup { width: auto; }
  hgroup .lede { width: auto; min-width: 0; }
  .beats { grid-template-columns: minmax(0, 1fr); gap: 16px; margin-top: 40px; }
  .beat-art { min-height: 150px; }
  .phone { width: min(250px, 70vw); margin-inline: auto; }
  .with-phone, .with-example, #next { display: flex; flex-direction: column; align-items: stretch; }
  /* One column: the words, then the sheet — which alone holds still —
     then the result. */
  .with-example { row-gap: 32px; }
  .story, .lead { display: contents; }
  .lead::after { display: none; }
  .lead .words { position: static; }
  .with-example .example { order: 1; }
  .with-example .receipt { order: 2; margin-top: 36px; }
  .with-phone .words, .with-example .words { max-width: none; }
  .phone-first .phone { order: 0; }
  .example { width: 100%; }
  .sheet { padding: 20px 16px; border-radius: 24px; box-shadow: 8px 8px 0 color-mix(in srgb, var(--shade) 6%, transparent); }
  /* Down inside the sheet's top corner, beside the title, so the
     header never cuts it off. */
  .sticker { width: 118px; top: -8px; right: -10px; }
  .sticker-words { font-size: 17px; }
  /* The loop round the result runs down the margins; a little room
     inside it, so the words don't crowd the line. */
  .with-example .receipt { padding-inline: 8px; }
  #circle { flex-direction: column; align-items: stretch; }
  #circle .words { max-width: none; margin: 0; }
  .ring-room { display: block; width: 100%; height: 84vw; max-height: 380px; margin-top: 16px; }
  .in-ring { display: flex; }
  .has-line #close .action { display: block; width: fit-content; margin-inline: auto; }
  .card { margin-inline: auto; }
  /* The heading sits in a little from the margin, so the line coming
     down it keeps clear of the bubble round the heading. */
  .has-line #next h2 { margin-left: 22px; }
  /* The line draws a chat bubble round the heading (line.js): room
     under it for the bubble's tail before the words go on. */
  .has-line #next h2 + .lede { margin-top: 96px; }
  /* One column: the pile in the middle, its edges past the top card
     balanced against it. */
  .deck { width: min(260px, 64vw); margin-right: 0; margin-left: max(0px, calc(50% - 0.56 * min(260px, 64vw))); margin-top: 12%; margin-bottom: 4%; }
  blockquote { max-width: 16ch; }
  .nav { gap: 16px; }
  .nav-links { display: none; }
  .nav-action { margin-left: auto; }
  .promises { grid-template-columns: minmax(0, 1fr); }
  .questions details p { padding-right: 0; }
  .colophon { grid-template-columns: minmax(0, 1fr); }
  .theme-switch { grid-column: 1; justify-self: start; }
  .with-phone .phone, .phone-first .phone { --turn: 0; }
}

/* A small phone: the stepper and the card's margins give a little, so
   a place's name stays on one line; on the smallest, the coins shrink
   so a row of eight still fits. */
@media (max-width: 400px) {
  .sheet { padding-inline: 14px; }
  .stepper { gap: 4px; }
  .stepper .sum { min-width: 0; }
  .step { width: 28px; height: 28px; border-radius: 8px; }
  .habit { column-gap: 8px; }
}

@media (max-width: 340px) {
  .sheet { --k: 0.84; }
  .visits { gap: 4px; }
  .habit-name { font-size: var(--size-small); }
}

/* ---- Load-in ---------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .nav { animation: fade 0.6s ease both; }
  #hero .words > * {
    animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }
  #hero .words > :nth-child(1) { animation-delay: 0.08s; }
  #hero .words > :nth-child(2) { animation-delay: 0.16s; }
  #hero .words > :nth-child(3) { animation-delay: 0.24s; }
}

@keyframes fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

/* ---- Embers ------------------------------------------------------------ */

/* Out-of-focus embers drifting up, the teaser's fire: fixed behind the
   line and the words, and only as strong as --embers, which line.js
   sets from how far into the night the page is — only by the fire at
   the end, in light mode and dark. Each one its own place, size, pace
   and start. */
.embers {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  opacity: var(--embers, 0);
  transition: opacity 0.6s linear;
}
.embers i {
  position: absolute;
  bottom: -60px;
  width: var(--s, 18px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(240 140 70 / 0.85), rgb(222 120 60 / 0.35) 45%, transparent 70%);
  filter: blur(var(--b, 3px));
  opacity: 0;
  animation: ember var(--d, 12s) linear var(--w, 0s) infinite;
}
.embers i:nth-child(1)  { left: 6%;  --s: 22px; --b: 5px; --d: 13s; --w: -2s; }
.embers i:nth-child(2)  { left: 14%; --s: 10px; --b: 2px; --d: 9s;  --w: -6s; }
.embers i:nth-child(3)  { left: 22%; --s: 34px; --b: 9px; --d: 16s; --w: -11s; }
.embers i:nth-child(4)  { left: 31%; --s: 14px; --b: 3px; --d: 11s; --w: -1s; }
.embers i:nth-child(5)  { left: 39%; --s: 8px;  --b: 1px; --d: 8s;  --w: -4s; }
.embers i:nth-child(6)  { left: 47%; --s: 26px; --b: 7px; --d: 14s; --w: -9s; }
.embers i:nth-child(7)  { left: 55%; --s: 12px; --b: 2px; --d: 10s; --w: -3s; }
.embers i:nth-child(8)  { left: 63%; --s: 40px; --b: 11px; --d: 18s; --w: -13s; }
.embers i:nth-child(9)  { left: 70%; --s: 9px;  --b: 1px; --d: 9s;  --w: -7s; }
.embers i:nth-child(10) { left: 77%; --s: 20px; --b: 5px; --d: 12s; --w: -5s; }
.embers i:nth-child(11) { left: 84%; --s: 13px; --b: 3px; --d: 10s; --w: -8s; }
.embers i:nth-child(12) { left: 90%; --s: 30px; --b: 8px; --d: 15s; --w: -10s; }
.embers i:nth-child(13) { left: 96%; --s: 11px; --b: 2px; --d: 9s;  --w: -2s; }
.embers i:nth-child(14) { left: 43%; --s: 16px; --b: 4px; --d: 13s; --w: -12s; }

/* Out of the night (line.js sets embers-on) they stop drifting. */
:root:not(.embers-on) .embers { visibility: hidden; }
:root:not(.embers-on) .embers i { animation-play-state: paused; }

@keyframes ember {
  0%   { transform: translate(0, 0); opacity: 0; }
  12%  { opacity: 0.9; }
  50%  { transform: translate(18px, -55vh); }
  85%  { opacity: 0.5; }
  100% { transform: translate(-10px, -110vh); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .embers i { animation: none; opacity: 0.6; }
  .embers i:nth-child(odd) { bottom: 18vh; }
  .embers i:nth-child(3n) { bottom: 42vh; }
}
