/* LoveBlossom book.css: Grandma's front door (the guest welcome, the account welcome's age box,
   not13, an old link's error variants), the invite and keep cards on the bond page, the keep
   choice and "What Grandma sees" sheet other screens include, and the memory book with its
   print styles. Built on app.css tokens and components; adds only its own classes: .welcome
   (.welcome-join, .welcome-size, .welcome-preview), .step, .env, .hello, .keepchoice, .sees-,
   .consent, .retired, .not13, .invite, .keep-card, .book, .cover, .contents, .chapter, .page,
   .polaroid, .margin-note, .reply-compose, .wishes, .fading, .learned.
   Rules: no color-mix() (iOS 15), every theme difference is a token, every movement sits
   in the motion block at the end (prefers-reduced-motion: no-preference, html:not(.calm)),
   people's words go in through Jinja autoescape or textContent. */

/* ------------------------------------------------------------------ tokens */
:root {
  --env-paper: var(--card);
  --env-flap: var(--sunken);
  --env-line: var(--hairline);
  --polaroid: #FFFFFF;
  --polaroid-edge: rgba(59, 31, 51, .10);
  --tape: rgba(232, 218, 190, .82);
  --note-bg: #FBF0D9;
  --note-line: #EAD6AE;
  --ribbon: var(--rose);
  --on-ribbon: var(--on-rose);
  --cloth-shade: rgba(0, 0, 0, .22);
  --cloth-light: rgba(255, 255, 255, .10);
  --cloth-weave: rgba(255, 255, 255, .035);
  --page-edge: #EFE4D6;
  --leader: var(--hairline);
  --kp-shine: rgba(255, 255, 255, .7);
  --paper-0: rgba(251, 245, 238, 0);
}
@media (prefers-color-scheme: dark) {
  :root {
    --polaroid: #EFE7DA;
    --polaroid-edge: rgba(0, 0, 0, .35);
    --tape: rgba(214, 196, 160, .55);
    --note-bg: #3A2E1F;
    --note-line: #5A4630;
    --cloth-shade: rgba(0, 0, 0, .38);
    --cloth-light: rgba(255, 255, 255, .07);
    --page-edge: #3A2B36;
    --kp-shine: rgba(255, 236, 196, .28);
    --paper-0: rgba(27, 18, 25, 0);
  }
}

/* =================================================================== WELCOME
   One step at a time with JS (.welcome.is-stepped); all three in order without. */
.welcome-page .wrap { padding-top: 1rem; }
.welcome { container-type: inline-size; container-name: welcome; display: flex; flex-direction: column; gap: 1rem; }
.welcome__form { display: flex; flex-direction: column; gap: 3rem; }
.welcome.is-stepped .welcome__form { gap: 0; }
.step { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: .875rem; }
.step__top { display: flex; align-items: center; justify-content: center; }
.step__back { align-self: center; min-height: var(--tap-lg); min-width: 8rem; padding-left: .875rem; padding-right: 1.25rem; }
.step__back .mark { width: 1.25em; height: 1.25em; }
.step__title { font-size: 1.6rem; line-height: 1.15; }
.step__title:focus, .welcome__title:focus { outline: none; }
.step__title:focus-visible, .welcome__title:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; border-radius: 4px; }
.step__next, .step__act { margin-top: .25rem; }
.step__act > .step__next { margin-top: 0; }
.welcome:not(.is-stepped) .step__act { display: none; }
/* With JS, steps 1 and 2 keep their main action on screen. When the step is taller than the
   screen (big text, a long note, a small phone), it rests on the bottom edge over a soft paper
   fade, and settles back into place as you scroll to it. Taps on the fade go through. Step 3's
   Turn on / Not now are never pinned: the consent facts always come before the choice. */
.welcome.is-stepped .step__act {
  position: -webkit-sticky; position: sticky; bottom: 0; z-index: 2;
  margin: -1rem calc(-1 * var(--gutter)) -.75rem; padding: 1.25rem var(--gutter) max(.75rem, env(safe-area-inset-bottom));
  pointer-events: none;
}
.welcome.is-stepped .step__act > * { pointer-events: auto; }
.welcome.is-stepped .step__act::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, var(--paper-0), var(--paper) 1.25rem);
}

/* The owner's preview: a tag above Grandma's screen, and the text-size toggle under it (ux-2). */
.welcome-preview-bar { display: flex; flex-direction: column; align-items: center; gap: .5rem; margin-bottom: -.25rem; }
.welcome-preview {
  display: flex; align-items: center; align-self: center; gap: .375rem;
  padding: .25rem .875rem; border-radius: var(--r-pill);
  background: var(--honey-soft); color: var(--ink); font-weight: 700; font-size: .9375rem; line-height: 1.3;
  border: 1.5px dashed var(--honey);
}
.welcome-preview .mark { color: var(--honey-text); }
.welcome-size {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); gap: .25rem;
  width: 100%; max-width: 24rem; padding: .25rem; border-radius: var(--r-tile); background: var(--sunken);
}
.welcome-size__opt {
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: var(--tap); padding: .25rem .625rem; border-radius: 12px;
  color: var(--ink); font-weight: 700; font-size: .9375rem; line-height: 1.2; text-decoration: none;
}
.welcome-size__opt[aria-current] { background: var(--card); color: var(--rose-text); box-shadow: var(--e1), inset 0 0 0 2px var(--rose); }

/* A signed-in visitor: one card, add the flower to your garden (ux-12). */
.welcome-join { display: flex; flex-direction: column; align-items: stretch; gap: .75rem; margin-top: .5rem; }
.welcome-join__art {
  display: inline-flex; align-items: center; justify-content: center; align-self: flex-start;
  width: 3.5rem; height: 3.5rem; border-radius: 50%; background: var(--kind-soft); color: var(--kind-text);
  --mark-accent: var(--kind); --mark-accent-o: .35;
}
.welcome-join__art .mark { width: 2rem; height: 2rem; }
.welcome-join__title { font-size: 1.6rem; line-height: 1.15; text-wrap: balance; }
.welcome-join__email { font-weight: 700; }
.welcome-join__go { margin-top: .25rem; }
.welcome-join__out { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 0 .25rem; color: var(--muted); font-weight: 700; }
.welcome-join__signout { min-height: var(--tap); }

.welcome__title { font-size: 1.875rem; line-height: 1.12; text-wrap: balance; }
.welcome__lead { color: var(--ink); }
.welcome__strip {
  list-style: none; margin: 0; padding: .25rem 0 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem;
  text-align: center;
}
.welcome__strip li { position: relative; display: flex; flex-direction: column; align-items: center; gap: .3rem; font-weight: 700; font-size: .875rem; line-height: 1.25; color: var(--ink); }
.welcome__strip .mark { width: 2.25rem; height: 2.25rem; color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .3; }
.welcome__strip li + li::before {
  content: ""; position: absolute; top: 1.05rem; right: calc(50% + 1.6rem); width: calc(100% - 3.2rem + .5rem); border-top: 2px dotted var(--hairline);
}
.welcome__private { display: flex; align-items: flex-start; gap: .5rem; font-weight: 700; }
.welcome__private .mark { width: 1.5rem; height: 1.5rem; color: var(--rose); --mark-accent: var(--rose); --mark-accent-o: .9; }
/* "What Craig sees": a link-like button that opens the sees sheet (ux-18) */
.welcome__sees {
  -webkit-appearance: none; appearance: none; display: inline; padding: .375rem 0; margin: -.375rem 0; border: 0; background: none;
  color: var(--rose-text); font: inherit; font-weight: 700; text-decoration: underline; text-decoration-thickness: 2px;
  text-underline-offset: 3px; cursor: pointer; text-align: left;
}
.welcome__aa, .welcome__signin { color: var(--muted); text-align: center; }
.welcome__aa-key {
  display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
  min-width: 2rem; height: 1.6rem; padding: 0 .3rem; margin: 0 .1rem;
  border-radius: 7px; background: var(--card); box-shadow: 0 0 0 1px var(--hairline), 0 1px 0 1px var(--hairline);
  color: var(--ink);
}
.welcome__aa-key .mark { width: 1.1rem; height: 1.1rem; }
.welcome__signin a { font-weight: 700; }

/* Step 2, "Two quick things": the keep choice, its two plain lines, then "How old are you?"
   (ux-3, ux-4). Its Next isn't pinned, so nothing ever covers the cards. */
.step__keep { display: flex; flex-direction: column; gap: .625rem; }
.step__keep-notes { display: flex; flex-direction: column; gap: .25rem; font-size: .9375rem; line-height: 1.4; color: var(--muted); }
.step__keep-notes p:first-child { font-weight: 700; }
.step__age { display: flex; flex-direction: column; gap: .375rem; padding-top: .5rem; border-top: 1px dashed var(--hairline); }
.step__age-label { font-family: var(--font-story); font-weight: 600; font-size: 1.25rem; line-height: 1.2; color: var(--ink); padding-top: .375rem; }
.welcome .step__age-input { width: 7rem; max-width: 100%; font-size: max(16px, 1.375rem); font-weight: 700; text-align: center; font-variant-numeric: lining-nums tabular-nums; letter-spacing: .04em; }
.step__age-note { font-size: .9375rem; font-weight: 500; color: var(--muted); }
.step__age .hint-error { margin-top: .125rem; }
.welcome.is-stepped .step--two .step__act { position: static; margin: .25rem 0 0; padding: 0; pointer-events: auto; }
.welcome.is-stepped .step--two .step__act::before { display: none; }

/* ------------------------------------------- the keep choice (_keep_choice.html, ux-3)
   Two or three equal radio cards: Let them fade, Keep my stories, Keep everything. Each card
   is a title and a plain note. The marks step aside when the cards are narrow (large text,
   the Sent card, the keep card), by a container query on the cards themselves. */
.keepchoice { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: .5rem; }
.keepchoice__legend { padding: 0; margin-bottom: .5rem; font-weight: 700; font-size: .9375rem; color: var(--muted); }
.keepchoice__line {
  display: flex; align-items: flex-start; gap: .5rem;
  padding: .625rem .875rem; border-radius: 14px; background: var(--honey-soft); color: var(--ink);
  font-family: var(--font-story); font-weight: 600; font-size: 1.0625rem; line-height: 1.35;
}
.keepchoice__line .mark { flex: none; margin-top: .05em; color: var(--honey-text); --mark-accent: var(--honey); --mark-accent-o: .6; }
.keepchoice__cards { display: flex; flex-direction: column; gap: .625rem; container: keepchoice / inline-size; }
/* The visible card is .keepchoice__face, the radio's next sibling, so the checked state
   needs no :has() (iOS 15.0-15.3 lacks it). */
.keepchoice__card { position: relative; display: block; cursor: pointer; }
.keepchoice__card > input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; z-index: 1; }
.keepchoice__face {
  display: flex; align-items: center; gap: .75rem;
  min-height: 4rem; padding: .75rem 1rem .75rem .75rem;
  border-radius: var(--r-tile); background: var(--sunken); border: 2px solid transparent;
  line-height: 1.25;
}
.keepchoice__mark { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 2.25rem; height: 2.25rem; border-radius: 50%; background: var(--card); color: var(--muted); }
.keepchoice__mark .mark { width: 1.375rem; height: 1.375rem; }
.keepchoice__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .125rem; overflow-wrap: break-word; }
.keepchoice__title { display: block; font-weight: 700; font-size: 1.0625rem; }
.keepchoice__note { display: block; font-weight: 500; font-size: .9375rem; line-height: 1.35; color: var(--muted); }
/* first in the markup (so it can float, below), last on the card */
.keepchoice__radio { order: 3; flex: none; width: 1.5rem; height: 1.5rem; border-radius: 50%; border: 2px solid var(--muted); background: var(--card); }
.keepchoice__card > input:checked + .keepchoice__face { background: var(--rose-soft); border-color: var(--rose); color: var(--rose-text); }
.keepchoice__card > input:checked + .keepchoice__face .keepchoice__note { color: var(--ink); }
.keepchoice__card > input:checked + .keepchoice__face .keepchoice__mark { background: var(--rose); color: var(--on-rose); --mark-accent: var(--on-rose); --mark-accent-o: .35; }
.keepchoice__card > input:checked + .keepchoice__face .keepchoice__radio { border-color: var(--rose); background: radial-gradient(circle, var(--on-rose) 0 28%, var(--rose) 31%); }
.keepchoice__card > input:focus-visible + .keepchoice__face { outline: 3px solid var(--ink); outline-offset: 2px; }
.keepchoice.needs-attention, [data-keep-choice].needs-attention { outline-offset: 6px; }
/* compact (the flower page's keep card): no marks, a little less height */
.keepchoice--compact .keepchoice__face { min-height: 3.5rem; padding: .625rem .875rem; }
.keepchoice--compact .keepchoice__cards { gap: .5rem; }
/* narrow cards: the marks step aside so the words keep their width */
@container keepchoice (max-width: 18rem) {
  .keepchoice__mark { display: none; }
  .keepchoice__face { padding-left: .875rem; gap: .625rem; }
}
/* very narrow (a large-text phone): the radio floats beside the title's first line only (no
   taller than that line), so every other line of the title and the note gets the card's whole
   width and a long word like "everything" stays whole */
@container keepchoice (max-width: 13rem) {
  .keepchoice__face { display: block; padding-right: .875rem; }
  .keepchoice__face::after { content: ""; display: table; clear: both; }
  .keepchoice__radio { float: right; width: 1.25rem; height: 1.25rem; margin: .04rem 0 0 .5rem; }
  .keepchoice__text { display: block; }
  .keepchoice__note { margin-top: .125rem; }
}
html.nocq-18 .keepchoice__mark { display: none; }
html.nocq-18 .keepchoice__face { padding-left: .875rem; gap: .625rem; }
html.nocq-14-5 .keepchoice__face { display: block; padding-right: .875rem; }
html.nocq-14-5 .keepchoice__face::after { content: ""; display: table; clear: both; }
html.nocq-14-5 .keepchoice__radio { float: right; width: 1.25rem; height: 1.25rem; margin: .04rem 0 0 .5rem; }
html.nocq-14-5 .keepchoice__text { display: block; }
html.nocq-14-5 .keepchoice__note { margin-top: .125rem; }

/* ------------------------------------------- "What Grandma sees" (_sees_sheet.html, ux-18) */
.sees-sec { display: flex; flex-direction: column; gap: .5rem; }
.sees-sec + .sees-sec { padding-top: .875rem; border-top: 1px dashed var(--hairline); }
.sees-sec__title { font-family: var(--font-ui); font-weight: 700; font-size: 1.0625rem; line-height: 1.3; color: var(--ink); }
.sees-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .5rem; }
.sees-list > li { position: relative; padding-left: 1.875rem; line-height: 1.4; overflow-wrap: break-word; }
/* sees: a rose petal, as on the promise lists */
.sees-list > li::before {
  content: ""; position: absolute; left: .3rem; top: .38em; width: .8rem; height: .8rem;
  background: var(--rose); border-radius: 50% 0 50% 50%; transform: rotate(-45deg);
}
/* never sees: a hollow ring with a line through it */
.sees-list--never > li::before {
  left: .25rem; top: .3em; width: .95rem; height: .95rem; border-radius: 50%; transform: none;
  background: linear-gradient(135deg, transparent calc(50% - 1px), var(--muted) calc(50% - 1px), var(--muted) calc(50% + 1px), transparent calc(50% + 1px));
  box-shadow: inset 0 0 0 2px var(--muted);
}
.sees-guest { display: flex; flex-direction: column; gap: .625rem; padding: .875rem 1rem; border-radius: 14px; background: var(--honey-soft); color: var(--ink); }
.sees-guest__line { display: flex; align-items: flex-start; gap: .5rem; line-height: 1.4; }
.sees-guest__line .mark { flex: none; margin-top: .1em; color: var(--honey-text); --mark-accent: var(--honey); --mark-accent-o: .6; }
.sees-guest a { font-weight: 700; color: var(--rose-text); text-decoration: underline; }

.step__choice { display: grid; gap: .625rem; grid-template-columns: 1fr 1fr; margin-top: .25rem; }
.step__choice .btn { width: 100%; padding-left: .75rem; padding-right: .75rem; }

/* ---------------------------------------------------- the hello (voice or note) */
.hello { display: flex; flex-direction: column; gap: .75rem; }
.hello__play {
  -webkit-appearance: none; appearance: none;
  display: flex; align-items: center; gap: .875rem; width: 100%;
  min-height: var(--tap-xl); padding: .25rem 1rem .25rem .25rem;
  border: 0; border-radius: var(--r-pill); background: var(--sunken); color: var(--ink);
  font: inherit; font-weight: 700; font-size: 1.1875rem; line-height: 1.25; text-align: left;
  cursor: pointer; touch-action: manipulation;
}
.hello__btn {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 3.5rem; height: 3.5rem; border-radius: 50%;
  background: var(--rose); color: var(--on-rose); box-shadow: var(--lip), 0 6px 16px -6px var(--rose-glow);
  --mark-accent: currentColor; --mark-accent-o: 1;
}
.hello__btn .mark { width: 1.5rem; height: 1.5rem; }
.hello__len { font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hello__play[aria-busy="true"] .hello__btn { opacity: .7; }
.hello__player { padding: .25rem 0; }
.hello__note { margin: 0; display: flex; flex-direction: column; gap: .375rem; }
.hello__bubble {
  position: relative; margin: 0; padding: .75rem 1rem .8rem;
  border-radius: 20px 20px 20px 6px; background: var(--card);
  box-shadow: 0 0 0 1px var(--hairline), var(--e1);
}
.hello__bubble::after {
  content: ""; position: absolute; left: 1.1rem; bottom: -.55rem; width: 1.1rem; height: .6rem;
  background: var(--card); clip-path: polygon(0 0, 100% 0, 0 100%);
  filter: drop-shadow(0 1px 0 var(--hairline));
}
.hello__bubble .story { font-size: 1.125rem; line-height: 1.4; }
.hello__from { padding-left: 2.5rem; font-weight: 700; font-size: .9375rem; line-height: 1.2; color: var(--muted); }
/* A written hello says more than the pictures do, so they make room for it. */
.welcome[data-hello="note"] .welcome__strip, .welcome[data-hello="both"] .welcome__strip { display: none; }
.welcome[data-hello="both"] .env { font-size: .76rem; }

/* ------------------------------------------------- the envelope and its seed packet
   Sized in em off .env's font-size, so one number scales the whole drawing. Layers, back
   to front: the open flap (lined), the back, the packet (clipped at the bottom edge), the
   front pocket, the closed flap with its seal, the address. The markup state is open. */
.env { --w: 13.25em; --h: 7.8em; --f: 2.7em; font-size: .84rem; display: flex; flex-direction: column; align-items: center; gap: .55em; margin: .25rem 0 .125rem; }
.env__stage { position: relative; width: var(--w); height: calc(var(--h) + var(--f)); max-width: 100%; }
.env__body, .env__front, .env__pocket, .env__flap, .env__flap-open { position: absolute; left: 0; right: 0; }
.env__body { bottom: 0; height: var(--h); border-radius: .55em; background: var(--env-paper); box-shadow: 0 0 0 1px var(--env-line), var(--e2); }
.env__flap-open {
  bottom: var(--h); height: var(--f); transform-origin: 50% 100%;
  background:
    radial-gradient(circle, var(--kind) 0 .085em, transparent .1em) .35em .2em / .7em .7em,
    var(--env-flap);
  clip-path: polygon(0 100%, 47% 7%, 50% 0, 53% 7%, 100% 100%);
}
.env__pocket { bottom: 0; height: calc(var(--h) + var(--f)); overflow: hidden; border-radius: 0 0 .55em .55em; }
.env__packet {
  /* 8.25em tall; the window's foot (5.65em down) meets the pocket's V (56% of --h) */
  position: absolute; left: 50%; width: 6.2em; height: 8.25em; margin-left: -3.1em;
  bottom: calc(var(--h) * .44 - 2.6em);
  background: var(--kind-soft);
  border-radius: 0 0 .4em .4em;
  box-shadow: inset 0 0 0 1px var(--env-line);
  -webkit-mask: linear-gradient(#000, #000) 0 .45em / 100% 100% no-repeat, conic-gradient(from 135deg at 50% 0, #000 90deg, transparent 0) 0 0 / .62em .46em repeat-x;
  mask: linear-gradient(#000, #000) 0 .45em / 100% 100% no-repeat, conic-gradient(from 135deg at 50% 0, #000 90deg, transparent 0) 0 0 / .62em .46em repeat-x;
}
.env__packet::before { content: ""; position: absolute; left: 0; right: 0; top: .95em; border-top: 1px dashed var(--env-line); }
.env__window {
  position: absolute; left: 50%; top: 1.35em; width: 4.3em; height: 4.3em; margin-left: -2.15em;
  border-radius: 50%; overflow: hidden; background: var(--card);
  box-shadow: 0 0 0 1px var(--env-line), inset 0 2px 6px rgba(59, 31, 51, .08);
}
/* max-width: none, or .flower's max-width: 100% squeezes it to the window and pushes it left */
.env__window .flower { position: absolute; left: 50%; top: -.9em; width: 6.6em; max-width: none; margin-left: -3.3em; }
.env__front {
  bottom: 0; height: var(--h); border-radius: 0 0 .55em .55em;
  filter: drop-shadow(0 -1px 0 var(--env-line));
}
.env__front::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background:
    linear-gradient(to top left, transparent calc(50% - .7px), var(--env-line) 50%, transparent calc(50% + .7px)) left bottom / 50.5% 44% no-repeat,
    linear-gradient(to top right, transparent calc(50% - .7px), var(--env-line) 50%, transparent calc(50% + .7px)) right bottom / 50.5% 44% no-repeat,
    var(--env-paper);
  clip-path: polygon(0 24%, 50% 56%, 100% 24%, 100% 100%, 0 100%);
}
.env__flap { top: var(--f); height: calc(var(--h) * .56); transform-origin: 50% 0; filter: drop-shadow(0 1.5px 0 var(--env-line)) drop-shadow(0 4px 6px rgba(59, 31, 51, .10)); visibility: hidden; }
.env__flap-in { display: block; width: 100%; height: 100%; border-radius: .5em .5em 0 0; background: var(--env-flap); clip-path: polygon(0 0, 100% 0, 53% 96%, 50% 100%, 47% 96%); }
.env__seal { position: absolute; z-index: 1; left: 50%; top: calc(var(--f) + var(--h) * .56 - 1.45em); width: 2.6em; height: 2.6em; margin-left: -1.3em; visibility: hidden; }
.env__address {
  position: absolute; left: 50%; bottom: .45em; transform: translateX(-50%);
  width: max-content; max-width: calc(100% - 1.25em);
  display: flex; flex-wrap: wrap; justify-content: center; column-gap: .3em;
  padding: .15em .6em .2em; border-radius: .35em; background: var(--env-paper);
  font-family: var(--font-story); font-weight: 500; font-size: .9em; line-height: 1.2; color: var(--ink); text-align: center;
}
.env__address b { font-weight: 650; }
.env__address > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }   /* two lines at most: a long name ends in … */
/* The address is part of the drawing (the whole .env is aria-hidden, and the names are the h1
   right under it), so it scales with the envelope; the caption is words to read, so it never
   goes under the .875rem floor however small the drawing gets. */
.env__caption { font-family: var(--font-story); font-weight: 600; font-size: max(.875rem, 1.0625em); line-height: 1.25; color: var(--kind-text); text-align: center; text-wrap: balance; }

/* closed (the device's first visit, before welcome.js opens it) */
.env.is-closed .env__flap, .env.is-closed .env__seal { visibility: visible; }
.env.is-closed .env__flap-open { transform: scaleY(0); }
.env.is-closed .env__packet { transform: translateY(6.3em); visibility: hidden; }
.env.is-closed .env__caption { opacity: 0; }

/* A short screen (a phone with Safari's bars showing): the picture strip says what the lead
   already says, so it makes room, and the envelope draws a little smaller. The main action
   stays on screen either way (see .step__act). */
@media (max-height: 760px) {
  .welcome-page .wrap { padding-top: .625rem; }
  .step { gap: .75rem; }
  .welcome__strip { display: none; }
  .env { font-size: .74rem; }
  .welcome:not([data-hello=""]) .env { font-size: .7rem; }
}
@media (max-height: 700px) {
  .welcome:not([data-hello=""]) .step__top--first { display: none; }
}

/* Larger text: the drawing shrinks and then steps aside, so every step still fits on one
   screen with its main button. The words keep their size (lead 1.1875rem, rows 4rem).
   Container widths: 21rem at normal text, about 16.4rem at Large, 13.3rem at Extra large. */
@container welcome (max-width: 18rem) {
  .env { font-size: .74rem; }
  .welcome__title { font-size: 1.65rem; }
  /* With a hello to hear or read, the hello is the picture: the envelope steps aside so the
     three steps and "Only Craig sees your answers" stay above the pinned Let's start. */
  .welcome:not([data-hello=""]) .env { display: none; }
}
@container welcome (max-width: 14.5rem) {
  .step { gap: .625rem; }
  .welcome__form { margin-top: -.375rem; }
  .step__top--first, .env, .welcome__strip { display: none; }
  .welcome__title { font-size: 1.35rem; line-height: 1.15; }
  .step__title { font-size: 1.35rem; }
  .step__next, .step__choice .btn { min-height: var(--tap-lg); font-size: 1.125rem; }
  .welcome__private .mark { display: none; }
  .hello { gap: .5rem; }
  .hello__bubble .story { font-size: 1.0625rem; }
  .hello__bubble::after { display: none; }
  .hello__bubble { border-radius: 18px; }
  .hello__from { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .welcome[data-hello="both"] .step { gap: .5rem; }
  .welcome[data-hello="both"] .welcome__title { font-size: 1.25rem; }
}
/* The same two steps without container queries (iOS 15): html.nocq-* from base.html's head
   script, measured from the same column. Keep these in step with the container rules above.
   (The Large step's smaller envelope is left out: the short-screen rule above already draws
   it smaller where it matters, and the type floor keeps .env sizes to the listed rules.) */
html.nocq-18 .welcome .welcome__title { font-size: 1.65rem; }
html.nocq-18 .welcome:not([data-hello=""]) .env { display: none; }
html.nocq-14-5 .welcome .step { gap: .625rem; }
html.nocq-14-5 .welcome .welcome__form { margin-top: -.375rem; }
html.nocq-14-5 .welcome .step__top--first, html.nocq-14-5 .welcome .env, html.nocq-14-5 .welcome .welcome__strip { display: none; }
html.nocq-14-5 .welcome .welcome__title { font-size: 1.35rem; line-height: 1.15; }
html.nocq-14-5 .welcome .step__title { font-size: 1.35rem; }
html.nocq-14-5 .welcome .step__next, html.nocq-14-5 .welcome .step__choice .btn { min-height: var(--tap-lg); font-size: 1.125rem; }
html.nocq-14-5 .welcome .welcome__private .mark { display: none; }
html.nocq-14-5 .welcome .hello { gap: .5rem; }
html.nocq-14-5 .welcome .hello__bubble .story { font-size: 1.0625rem; }
html.nocq-14-5 .welcome .hello__bubble::after { display: none; }
html.nocq-14-5 .welcome .hello__bubble { border-radius: 18px; }
html.nocq-14-5 .welcome .hello__from { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
html.nocq-14-5 .welcome[data-hello="both"] .step { gap: .5rem; }
html.nocq-14-5 .welcome[data-hello="both"] .welcome__title { font-size: 1.25rem; }

/* ------------------------------------------------- smart follow-ups (_ai_consent) */
.consent { display: flex; flex-direction: column; gap: .75rem; }
.consent__title { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; font-size: 1.25rem; }
.consent__title > .mark { color: var(--peri-text); --mark-accent: var(--peri); --mark-accent-o: .5; }
.consent__demo { display: flex; flex-direction: column; align-items: flex-start; gap: .375rem; padding: .125rem 0; }
.consent__answer {
  align-self: flex-end; max-width: 80%;
  padding: .5rem .875rem; border-radius: 16px 16px 4px 16px;
  background: var(--card); box-shadow: 0 0 0 1px var(--hairline);
  font-family: var(--font-story); font-weight: 500; font-size: 1.0625rem; line-height: 1.3;
}
.consent__ask {
  display: inline-flex; align-items: center; gap: .4rem; max-width: 88%;
  padding: .5rem .875rem; border-radius: 16px 16px 16px 4px;
  background: var(--peri-soft); color: var(--ink);
  font-family: var(--font-story); font-weight: 600; font-size: 1.0625rem; line-height: 1.3;
}
.consent__ask .mark { flex: none; color: var(--peri-text); --mark-accent: var(--peri); --mark-accent-o: .6; }
.consent__lead { font-size: 1.0625rem; line-height: 1.45; }
.consent__facts { margin: 0; display: flex; flex-direction: column; gap: .5rem; padding: .75rem 1rem; border-radius: 14px; background: var(--sunken); }
.consent__fact { line-height: 1.45; }
.consent__fact dt { display: inline; font-weight: 700; }
.consent__fact dd { display: inline; margin: 0; }
@container welcome (max-width: 14.5rem) {
  .consent { gap: .5rem; }
  .consent__demo { display: none; }
  .consent__lead { font-size: .9375rem; }
  .consent__facts { padding: .5rem .75rem; gap: .375rem; font-size: .9375rem; }
}
html.nocq-14-5 .welcome .consent { gap: .5rem; }
html.nocq-14-5 .welcome .consent__demo { display: none; }
html.nocq-14-5 .welcome .consent__lead { font-size: .9375rem; }
html.nocq-14-5 .welcome .consent__facts { padding: .5rem .75rem; gap: .375rem; font-size: .9375rem; }

/* ---------------------------------------- an old guest link says what happened (ux-13)
   error.html's variants: joined, replaced, closed, left, expired (app.css .error-page). */
.retired__art {
  display: inline-flex; align-items: center; justify-content: center;
  width: 5rem; height: 5rem; border-radius: 50%; background: var(--sunken); color: var(--muted);
  --mark-accent: var(--muted); --mark-accent-o: .35;
}
.retired__art .mark { width: 2.75rem; height: 2.75rem; }
.retired--joined .retired__art { background: var(--leaf-soft); color: var(--leaf-text); --mark-accent: var(--leaf); }
.retired--replaced .retired__art, .retired--expired .retired__art { background: var(--rose-soft); color: var(--rose-text); --mark-accent: var(--rose); }
.retired h1 { text-wrap: balance; }
.retired .lead { text-wrap: pretty; }
.retired__kept { display: flex; align-items: center; justify-content: center; gap: .5rem; font-weight: 700; color: var(--honey-text); }
.retired__kept .mark { flex: none; color: var(--gold-b); --mark-accent: var(--gold-a); --mark-accent-o: 1; }
.retired__go { align-self: stretch; max-width: 22rem; width: 100%; margin-left: auto; margin-right: auto; }
.retired__home { min-height: var(--tap); }
.not13__out { margin-top: .25rem; }
.age-field .age-field__input { width: 7rem; max-width: 100%; text-align: center; font-weight: 700; font-variant-numeric: lining-nums tabular-nums; letter-spacing: .04em; }

/* -------------------------------------------------------------------- not13 */
.not13 { padding-top: 1.5rem; gap: .875rem; }
.not13__art { position: relative; display: block; width: 6rem; height: 5.5rem; }
.not13__dice { position: absolute; left: .25rem; top: 1rem; width: 4rem; height: 4rem; color: var(--peri-text); --mark-accent: var(--peri); --mark-accent-o: .35; transform: rotate(-10deg); }
.not13__bloom { position: absolute; right: 0; top: 0; width: 2.75rem; height: 2.75rem; color: var(--rose); --mark-accent: var(--honey); --mark-accent-o: 1; }
.not13 .btn { margin-top: .5rem; }
/* At a 35px root, 2rem pushes "LoveBlossom" past the screen in this centred column (a long
   word can't shrink its box); the cap leaves 2rem alone up to a 28px root. not13.html and the
   account welcome's under-13 card both use it. */
.not13 h1 { font-size: min(2rem, 14vw); }

/* ============================================================== INVITE CARD */
.invite { display: flex; flex-direction: column; gap: .875rem; container-type: inline-size; container-name: invite; }
.invite__notice { display: flex; align-items: center; gap: .5rem; font-weight: 700; background: var(--leaf-soft); color: var(--leaf-text); }
.invite__notice .mark { flex: none; }
.invite__head { display: grid; grid-template-columns: auto 1fr; column-gap: .75rem; row-gap: .25rem; align-items: center; }
.invite__art { grid-row: span 2; display: inline-flex; align-items: center; justify-content: center; width: 3.25rem; height: 3.25rem; border-radius: 50%; background: var(--kind-soft); color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .35; }
.invite__art .mark { width: 1.75rem; height: 1.75rem; }
.invite__art--quiet { background: var(--sunken); color: var(--muted); }
.invite__title { font-size: 1.35rem; line-height: 1.2; }
.invite__lead { grid-column: 2; color: var(--ink); }
.invite--expired .invite__head { grid-template-columns: auto 1fr; }
.invite--expired .invite__art { grid-row: auto; }
.invite__share { display: flex; flex-wrap: wrap; gap: .625rem; }
.invite__share .btn { flex: 1 1 6.5rem; }
.invite__share .btn--primary { flex: 2 1 10rem; }
/* "Share the link now" (ux-11) takes its own row rather than squeezing onto two lines */
.invite__share .invite__share-btn { flex: 1 1 15rem; }
.invite__part { display: flex; flex-direction: column; gap: .625rem; margin: 0; padding: 1rem 0 0; min-width: 0; border: 0; border-top: 1px dashed var(--hairline); }
.invite__part-title { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; padding: 0; font-family: var(--font-story); font-weight: 600; font-size: 1.125rem; line-height: 1.25; color: var(--ink); }
.invite__part-title > .mark { color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .3; }
.invite__summary { min-height: var(--tap); cursor: pointer; list-style: none; }
.invite__summary::-webkit-details-marker { display: none; }
.invite__summary::after { content: ""; width: .55rem; height: .55rem; margin-left: auto; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg) translateY(-.15rem); }
/* A title with no chip keeps its mark beside the words at any text size (the words wrap in
   their own box), instead of leaving the mark alone on a line. */
.invite__purpose .invite__part-title, .invite__summary { flex-wrap: nowrap; }
.invite__purpose .invite__part-title { align-items: flex-start; }
.invite__purpose .invite__part-title > .mark { margin-top: .1em; }
.invite__purpose .invite__part-title > .mark, .invite__summary > .mark, .invite__summary::after { flex: none; }
.invite__purpose .invite__part-title > span, .invite__summary > span { min-width: 0; }
.invite__presets[open] .invite__summary::after { transform: rotate(-135deg) translateY(-.1rem); }
/* WebKit counts a closed <details>' hidden content as a flex item, so no gap here */
.invite__presets { gap: 0; }
.invite__presets > :not(summary) { margin-top: .625rem; }
.invite__fieldset { display: flex; flex-direction: column; gap: .5rem; margin: 0; padding: 0; border: 0; min-width: 0; }
.invite__hint { color: var(--muted); }
.invite__row { display: flex; flex-wrap: wrap; gap: .5rem; }
.invite__row > .btn { flex: 1 1 auto; }
/* the saved note, as the speech bubble the guest will see */
.invite__note { position: relative; margin-bottom: .5rem; padding: .75rem 1rem .8rem; border-radius: 20px 20px 20px 6px; background: var(--paper); box-shadow: 0 0 0 1px var(--hairline); font-size: 1.125rem; line-height: 1.4; }
.invite__note::after { content: ""; position: absolute; left: 1.1rem; bottom: -.55rem; width: 1.1rem; height: .6rem; background: var(--paper); clip-path: polygon(0 0, 100% 0, 0 100%); filter: drop-shadow(0 1px 0 var(--hairline)); }
.invite__saved, .invite__choose, .invite__rec, .invite__write { display: flex; flex-direction: column; gap: .625rem; }
.invite__rec-note { padding: .625rem .875rem; border-radius: 12px; background: var(--peri-soft); color: var(--ink); font-weight: 700; }
.invite__rec-live { display: flex; align-items: center; gap: 1rem; }
.invite__ring { position: relative; flex: none; width: 3.5rem; height: 3.5rem; border-radius: 50%; background: var(--sunken); box-shadow: inset 0 0 0 3px var(--hairline); }
.invite__ring::after { content: ""; position: absolute; inset: 1.05rem; border-radius: 50%; background: var(--muted); }
.invite__ring.is-on { background: var(--rose-soft); box-shadow: inset 0 0 0 3px var(--rose); }
.invite__ring.is-on::after { background: var(--rose); }
.invite__timer { font-family: var(--font-story); font-weight: 700; font-size: 1.75rem; font-variant-numeric: tabular-nums lining-nums; }
.invite__timer-of { font-family: var(--font-ui); font-weight: 700; font-size: .9375rem; color: var(--muted); }
.invite__rec-state { font-weight: 700; min-height: 1.5em; }
.invite__rec-state:empty { display: none; }
.invite__help { display: flex; flex-direction: column; gap: .5rem; padding: .75rem 1rem; border-radius: 14px; background: var(--honey-soft); }
.invite__listen:empty { display: none; }
.invite__fine { font-size: .875rem; color: var(--muted); }
.invite__presets .check-row { min-height: 3.25rem; }
.invite__links { list-style: none; margin: 0; padding: .75rem 0 0; display: flex; flex-direction: column; gap: .125rem; border-top: 1px dashed var(--hairline); }
.invite__links a { display: flex; align-items: center; gap: .625rem; min-height: var(--tap); font-weight: 700; text-decoration: none; }
.invite__links a span { text-decoration: underline; text-underline-offset: .15em; }
.invite__links .mark { color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .3; }
/* "This link is just for Dad." (ux-19): the fine print that says a link is a key */
.invite__key { display: flex; align-items: flex-start; gap: .4rem; line-height: 1.4; }
.invite__key .mark { flex: none; width: 1.125rem; height: 1.125rem; margin-top: .1em; color: var(--muted); --mark-accent: var(--muted); --mark-accent-o: .5; }
/* "Why are you inviting Dad?" (f-3): two chips, one pressed */
.invite__chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.invite__chip { min-height: var(--tap); padding: .375rem 1rem; font-size: 1rem; text-align: left; }
/* the saved hello's kept or fade line, and "Keep this hello" beside its save */
.invite__kept { display: flex; align-items: center; gap: .4rem; }
.invite__kept .mark { flex: none; width: 1.125rem; height: 1.125rem; color: var(--muted); --mark-accent: var(--gold-b); --mark-accent-o: .8; }
.invite__keep-row .check-row { min-height: 3.25rem; }
.invite__newlink { display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
/* playing: one quiet row, its one button "Send Dad a new link" (ux-19). No URL. */
.invite--playing { gap: .5rem; }
.invite__quiet { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .125rem .75rem; min-height: var(--tap-lg); padding: .375rem .375rem .375rem 1rem; border-radius: var(--r-card); background: var(--sunken); }
.invite__quiet-text { flex: 1 1 11rem; display: flex; align-items: center; gap: .5rem; min-width: 0; font-weight: 700; overflow-wrap: break-word; }
.invite__quiet-text .mark { flex: none; color: var(--leaf-text); --mark-accent: var(--leaf); --mark-accent-o: .4; }
.invite__quiet .invite__newlink { flex: 0 1 auto; margin-left: auto; }
.invite__newlink-btn { min-height: var(--tap); text-align: left; }
/* right after a new link: "New link ready. Send it to Dad." with Share and Copy, this once */
.invite--fresh .invite__art { background: var(--leaf-soft); color: var(--leaf-text); --mark-accent: var(--leaf); }
.invite--fresh .invite__title { grid-row: span 2; }

/* Large text (after the base rules, which it overrides): the little envelope steps aside so the title keeps its width */
@container invite (max-width: 15rem) {
  .invite__head { grid-template-columns: 1fr; }
  .invite__art { display: none; }
  .invite__lead { grid-column: 1; }
}
/* The same without container queries (iOS 15): html.nocq-15 from base.html's head script. */
html.nocq-15 .invite__head { grid-template-columns: 1fr; }
html.nocq-15 .invite__art { display: none; }
html.nocq-15 .invite__lead { grid-column: 1; }

/* ================================================================ KEEP CARD */
.keep-card { display: flex; flex-direction: column; gap: .75rem; }
.keep-card__title { display: flex; align-items: center; gap: .5rem; font-size: 1.25rem; }
.keep-card__title > .mark { color: var(--gold-b); --mark-accent: var(--gold-a); --mark-accent-o: 1; }
.keep-card__petals {
  position: relative; overflow: hidden;
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: .25rem .3rem;
  padding: .5rem .25rem .375rem;
}
/* Each petal is this flower's own (fp-rose, fp-ray or fp-fmn) in its palette, laid down at
   a slight angle like petals pressed in a row. A gold rim (the edge <use>, behind the
   petal, so only its outer half shows) appears when kept; paler petals fade sooner. */
.kpetal { --fresh: 1; flex: none; display: inline-flex; opacity: .8; opacity: calc(.34 + .66 * var(--fresh)); transform: rotate(var(--tilt, 0deg)); }
/* Narrower than the drawing and tipped further, so a row reads as scattered petals rather
   than a row of ovals. */
.kpetal:nth-child(4n+1) { --tilt: -24deg; }
.kpetal:nth-child(4n+2) { --tilt: 16deg; }
.kpetal:nth-child(4n+3) { --tilt: -9deg; }
.kpetal:nth-child(4n) { --tilt: 25deg; }
.kpetal svg { display: block; width: auto; height: 1.5rem; overflow: visible; transform: scaleX(.78); }
.kp-fp-rose { --kp-len: 119; --kp-edge: 6; --kp-ink: 1.6; }
.kpetal__fill { --fl-ink: var(--fl-ps); --fl-inko: .55; --fl-inkw: var(--kp-ink); }
.kpetal__edge { --fl-pf: none; --fl-ps: transparent; --fl-ink: var(--gold-b); --fl-inko: 1; --fl-inkw: var(--kp-edge); opacity: 0; }
.kpetal.is-kept { opacity: 1; }
.kpetal.is-kept .kpetal__edge { opacity: 1; }
.keep-card__petals::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(100deg, rgba(255, 255, 255, 0) 30%, var(--kp-shine) 50%, rgba(255, 255, 255, 0) 70%);
}
.keep-card__more { font-weight: 700; font-size: .875rem; color: var(--muted); padding-left: .25rem; }
.keep-card__next { font-weight: 700; font-size: .9375rem; color: var(--muted); }
.keep-card__next a { margin-left: .25rem; }
.keep-card__empty { color: var(--muted); }
.keep-card__copy { color: var(--ink); }
.keep-card__both { display: flex; align-items: flex-start; gap: .5rem; font-size: .9375rem; font-weight: 700; line-height: 1.4; color: var(--leaf-text); }
.keep-card__both .mark { flex: none; margin-top: .1em; color: var(--leaf-text); --mark-accent: var(--leaf); --mark-accent-o: .35; }

/* ====================================================================== BOOK */
.book { display: flex; flex-direction: column; gap: 1.5rem; }
/* Where a #link lands (Open the book, the contents, Show me, Next-up's book#wishes, #fading and
   #p-<id>): just under the sticky header. html's scroll-padding-top does most of it (base.html's
   head script sets it in px, since WebKit read its rem at 16px at any text size); this adds a
   little air. */
.chapter, .learned, .page, .page__more, .book-card, .contents { scroll-margin-top: .25rem; }

/* ------------------------------------------------------------------- cover
   Cloth in the kind colour: a woven texture, a spine and hinge on the left, a debossed
   double rule, a recessed paper plate holding the pressed flower, cream titles, and the
   page block showing at the fore-edge. */
.cover { display: flex; flex-direction: column; gap: 1.125rem; padding: .25rem .5rem 0 0; }
.cover__cloth {
  --cloth: var(--cloth-familial);
  position: relative;
  padding: .9rem .9rem .9rem 1.55rem;
  border-radius: 3px 9px 9px 3px;
  color: var(--cloth-title);
  background:
    linear-gradient(90deg, rgba(0, 0, 0, .30) 0, rgba(0, 0, 0, .10) .5rem, rgba(255, 255, 255, .10) .62rem, rgba(0, 0, 0, .14) .72rem, transparent 1.1rem),
    repeating-linear-gradient(0deg, var(--cloth-weave) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, var(--cloth-weave) 0 1px, transparent 1px 3px),
    radial-gradient(130% 90% at 30% 15%, var(--cloth-light), transparent 62%),
    var(--cloth);
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, .18),
    3px 3px 0 0 var(--page-edge), 4px 4px 0 0 var(--hairline),
    6px 6px 0 0 var(--page-edge), 7px 7px 0 0 var(--hairline),
    0 22px 34px -14px rgba(59, 31, 51, .5);
}
.cover--romantic .cover__cloth { --cloth: var(--cloth-romantic); }
.cover--platonic .cover__cloth { --cloth: var(--cloth-platonic); }
.cover--familial .cover__cloth { --cloth: var(--cloth-familial); }
.cover__frame {
  display: flex; flex-direction: column; align-items: center; gap: .55rem;
  padding: 1.5rem 1rem 1.375rem;
  border-radius: 5px;
  text-align: center;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, .28), inset 1px 1px 0 1px rgba(255, 255, 255, .07),
    inset 0 0 0 5px transparent, inset 0 0 0 6px rgba(0, 0, 0, .2), inset 1px 1px 0 6px rgba(255, 255, 255, .06);
}
.cover__plate {
  display: flex; align-items: center; justify-content: center;
  width: 10rem; max-width: 100%; aspect-ratio: 1 / 1.1; margin-bottom: .5rem; overflow: hidden;
  border-radius: 6px;
  background-color: #F6EDE0; background-image: var(--grain); background-size: 128px 128px;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, .35), inset 0 0 0 1px rgba(0, 0, 0, .25), 0 1px 0 rgba(255, 255, 255, .10);
}
.cover__plate .flower--pressed { width: 8.25rem; margin-top: .25rem; }
/* before the first petal: a blossom debossed into the plate, waiting for its flower */
.cover__plate-mark { display: inline-flex; color: rgba(59, 31, 51, .22); --mark-accent: rgba(59, 31, 51, .22); --mark-accent-o: .5; filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .55)); }
.cover__plate-mark .mark { width: 4rem; height: 4rem; }
.cover__title { color: var(--cloth-title); font-size: 2rem; font-size: min(2rem, 11vw); line-height: 1.12; overflow-wrap: break-word; text-wrap: balance; text-shadow: 0 1px 0 rgba(0, 0, 0, .35), 0 -1px 0 rgba(255, 255, 255, .06); }
.cover__sub { font-family: var(--font-story); font-weight: 500; font-size: 1.0625rem; font-size: min(1.0625rem, 6.5vw); line-height: 1.35; text-wrap: balance; }   /* under the title at any size (the 17px default is unchanged) */
.cover__rule { display: flex; align-items: center; gap: .6rem; width: 70%; color: var(--cloth-title); opacity: .75; --mark-accent: var(--cloth-title); --mark-accent-o: .35; }
.cover__rule::before, .cover__rule::after { content: ""; flex: 1 1 auto; border-top: 1px solid currentColor; opacity: .6; }
.cover__rule .mark { width: 1.125rem; height: 1.125rem; }
.cover__count { font-weight: 700; font-size: .9375rem; letter-spacing: .06em; text-transform: uppercase; }
.cover__actions { display: flex; flex-direction: column; align-items: center; gap: .25rem; }
.cover__actions .btn--primary { align-self: stretch; }
.cover__print { font-size: 1rem; }
@media (prefers-color-scheme: dark) {
  .cover__plate { background-color: #E7DCCB; }
  .cover__cloth { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06), 3px 3px 0 0 var(--page-edge), 4px 4px 0 0 #2A1D27, 6px 6px 0 0 var(--page-edge), 7px 7px 0 0 #2A1D27, 0 22px 34px -14px rgba(0, 0, 0, .7); }
}

.book__news { display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .5rem; padding: .75rem 1rem; border-radius: 14px; background: var(--rose-soft); color: var(--rose-text); font-weight: 700; }
.book__news .mark { color: var(--rose-text); }
.book__news a { color: var(--rose-text); }

/* ------------------------------------------------- wishes and the fading checklist */
.book-card { display: flex; flex-direction: column; gap: .875rem; }
.book-card__title { display: flex; align-items: flex-start; gap: .5rem; font-size: 1.25rem; line-height: 1.25; }
.book-card__title .mark { flex: none; margin-top: .1em; width: 1.5rem; height: 1.5rem; }
.wishes { border-color: var(--honey); box-shadow: inset 0 5px 0 var(--honey-soft), var(--e1); }
.wishes .book-card__title .mark { color: var(--rose); --mark-accent: var(--rose); --mark-accent-o: .5; }
.wishes__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .75rem; }
.wishes__item { display: flex; flex-direction: column; gap: .375rem; padding: .875rem 1rem 1rem; border-radius: var(--r-paper); background: var(--paper); box-shadow: 0 0 0 1px var(--hairline); }
.wishes__q { font-weight: 700; font-size: .9375rem; color: var(--muted); }
.wishes__a { font-family: var(--font-story); font-weight: 450; font-size: 1.1875rem; line-height: 1.4; overflow-wrap: break-word; }   /* never clamped: the author chooses on all of it */
.wishes__lead { margin-top: -.375rem; color: var(--ink); }
.wishes__about, .fading__about { font-size: .9375rem; line-height: 1.35; color: var(--muted); }
.wishes__when { display: flex; align-items: center; gap: .375rem; font-weight: 700; font-size: .875rem; color: var(--muted); }
.wishes__when .mark { flex: none; width: 1.125rem; height: 1.125rem; }
/* Keep it and Let it fade weigh the same (ux-24): two equal buttons, side by side while
   they fit, stacked at large text */
.wishes__choice { display: grid; gap: .5rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.75rem), 1fr)); margin-top: .375rem; }
.wishes__choice .btn { width: 100%; padding-left: .625rem; padding-right: .625rem; }
.wishes__btn { background: var(--card); box-shadow: 0 0 0 1.5px var(--hairline); }
.wishes__btn .mark { color: var(--muted); }
.wishes__btn[data-wish-keep] .mark { color: var(--gold-b); --mark-accent: var(--gold-a); --mark-accent-o: 1; }
.wishes__done { font-weight: 700; color: var(--honey-text); }

/* The fading checklist (ux-7): each row a check row; a voice answer's small player and a
   photo's 64px picture ride with it. At large text the box sits above the words. */
.fading .book-card__title .mark { color: var(--muted); }
.fading__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .5rem; container: fading / inline-size; }
.fading__item { display: flex; flex-direction: column; border-radius: var(--r-tile); background: var(--sunken); }
.fading__check { align-items: flex-start; padding-top: .75rem; padding-bottom: .75rem; background: transparent; }
.fading__check .check-row__box { margin-top: .1rem; }
.fading__check > input { top: 1.6rem; }
.fading__text { display: flex; flex-direction: column; gap: .125rem; font-weight: 400; overflow-wrap: break-word; }
.fading__flag { display: flex; align-items: flex-start; gap: .375rem; margin-bottom: .125rem; font-weight: 700; font-size: .9375rem; line-height: 1.3; color: var(--leaf-text); }
.fading__flag .mark { flex: none; width: 1.125rem; height: 1.125rem; margin-top: .05em; --mark-accent: var(--leaf); --mark-accent-o: .5; }
.fading__flag--wish { color: var(--rose-text); }
.fading__flag--wish .mark { color: var(--rose); --mark-accent: var(--rose); --mark-accent-o: 1; }
.fading__q { font-weight: 700; font-size: .9375rem; color: var(--muted); }
.fading__a { font-family: var(--font-story); font-weight: 500; font-size: 1.0625rem; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.fading__when { font-size: .875rem; font-weight: 700; color: var(--muted); }
.fading__thumb { flex: none; width: 4rem; height: 4rem; max-width: 64px; max-height: 64px; margin-top: .125rem; border-radius: 8px; object-fit: cover; background: var(--card); box-shadow: 0 0 0 1px var(--hairline); }
.fading__voice { padding: 0 .875rem .75rem calc(.875rem + 1.75rem + .875rem); }
.fading__item.is-kept { background: var(--honey-soft); }
.fading__item.is-kept .fading__when { color: var(--honey-text); }
@container fading (max-width: 16.5rem) {
  .fading__check { flex-direction: column; align-items: stretch; gap: .5rem; }
  .fading__check > input { top: .75rem; left: .875rem; transform: none; }
  .fading__check .check-row__box { margin-top: 0; }
  .fading__voice { padding-left: .875rem; }
  .fading__a { display: block; -webkit-line-clamp: unset; overflow: visible; }
}
html.nocq-15 .fading__check { flex-direction: column; align-items: stretch; gap: .5rem; }
html.nocq-15 .fading__check > input { top: .75rem; left: .875rem; transform: none; }
html.nocq-15 .fading__voice { padding-left: .875rem; }
html.nocq-15 .fading__a { display: block; -webkit-line-clamp: unset; overflow: visible; }

/* ----------------------------------------------------------------- contents */
.contents { padding: 1.5rem 1.25rem 1.125rem; border-radius: var(--r-paper); background-color: var(--card); background-image: var(--grain); background-size: 128px 128px; box-shadow: var(--e1); outline: 1px solid var(--hairline); outline-offset: -11px; }
.contents__title { text-align: center; font-size: 1.5rem; letter-spacing: .01em; margin-bottom: .75rem; }
.contents__list { list-style: none; margin: 0; padding: 0; }
.contents__link { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; min-height: var(--tap); padding: .375rem .25rem; color: var(--ink); text-decoration: none; border-radius: 8px; }
a.contents__link:active { background: var(--sunken); }
.contents__mark { flex: none; width: 1.625rem; height: 1.625rem; color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .3; }
.contents__name { font-family: var(--font-story); font-weight: 500; font-size: 1.125rem; line-height: 1.25; }
.contents__lead { flex: 1 1 1.5rem; min-width: .75rem; align-self: flex-end; margin-bottom: .55em; border-bottom: 2px dotted var(--leader); }
.contents__count { flex: none; margin-left: auto; font-family: var(--font-story); font-weight: 650; font-size: 1.125rem; font-variant-numeric: lining-nums tabular-nums; }
.contents__item--empty .contents__link { color: var(--muted); }
.contents__item--empty .contents__mark { color: var(--muted); opacity: .6; }
.contents__item--learned { margin-top: .375rem; padding-top: .375rem; border-top: 1px dashed var(--hairline); }
.contents__list { container: contents / inline-size; }
@container contents (min-width: 17rem) {
  .contents__link { flex-wrap: nowrap; align-items: flex-end; }
  .contents__name { flex: 0 1 auto; min-width: 0; }
  .contents__lead { flex: 1 1 .75rem; margin-bottom: .45em; }
  .contents__mark { align-self: center; }
}

/* ----------------------------------------------------------------- chapters */
.chapter, .learned { display: flex; flex-direction: column; gap: 1.25rem; }
.chapter__opener { display: flex; flex-direction: column; align-items: center; gap: .25rem; padding: 1.25rem 0 .25rem; text-align: center; }
.chapter__ornament { width: 3rem; height: 3rem; color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .3; }
.chapter__title { font-size: 1.6rem; line-height: 1.15; }
.chapter__count { font-weight: 700; font-size: .875rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.chapter__opener::after { content: ""; width: 5rem; margin-top: .5rem; border-top: 2px dotted var(--hairline); }
.chapter__pages { display: flex; flex-direction: column; gap: 1.5rem; }

/* ---------------------------------------------------------------------- page */
.page { display: flex; flex-direction: column; gap: .75rem; padding: 1.625rem 1.375rem 1.125rem; container: lb-page / inline-size; }
.page__meta { font-family: var(--font-ui); font-weight: 700; font-size: .875rem; line-height: 1.3; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); padding-right: 2rem; }
/* the running head: the chapter in its colour, then the date; no separator, so a date that
   wraps starts its own line cleanly */
.page__head { display: flex; flex-wrap: wrap; column-gap: .75rem; }
.page--dedication .page__head { justify-content: center; }
.page__chapter { color: var(--kind-text); }
.page__date { white-space: nowrap; }
/* the question, with Read it to me beside it when that's on (the kernel shows [data-speak]) */
.page__qrow { display: flex; align-items: flex-start; gap: .5rem; }
.page__qrow > .page__q { flex: 1 1 auto; min-width: 0; }
.page__speak { margin-top: -.25rem; }
.page--sealed .page__qrow { justify-content: center; }
.page--sealed .page__qrow > .page__q { flex: 0 1 auto; }
.page__q { font-family: var(--font-story); font-weight: 600; font-size: 1.125rem; line-height: 1.3; color: var(--ink); }
/* Large text (ux-16): Read it to me is its own full-width row under the question, with its
   words (the kernel's .speak-btn--row look), so it never squeezes them. */
@container lb-page (max-width: 17rem) {
  .page__qrow { flex-direction: column; align-items: stretch; gap: .625rem; }
  .page--sealed .page__qrow > .page__q { flex: 1 1 auto; }
  html.can-speak.speak-on .page .page__speak {
    display: flex; width: 100%; height: auto; min-height: var(--tap); margin-top: 0; gap: .5rem;
    padding: .375rem min(1.25rem, 21px); border-radius: 1.75rem;
    font-family: var(--font-ui); font-weight: 700; font-size: 1.0625rem; line-height: 1.25; text-align: center;
  }
  .page .page__speak .speak-btn__label { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; clip-path: none; white-space: normal; }
}
/* The same without container queries (iOS 15): html.nocq-18 from base.html's head script. */
html.nocq-18 .page__qrow { flex-direction: column; align-items: stretch; gap: .625rem; }
html.nocq-18 .page--sealed .page__qrow > .page__q { flex: 1 1 auto; }
html.nocq-18.can-speak.speak-on .page .page__speak {
  display: flex; width: 100%; height: auto; min-height: var(--tap); margin-top: 0; gap: .5rem;
  padding: .375rem min(1.25rem, 21px); border-radius: 1.75rem;
  font-family: var(--font-ui); font-weight: 700; font-size: 1.0625rem; line-height: 1.25; text-align: center;
}
html.nocq-18 .page .page__speak .speak-btn__label { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; clip-path: none; white-space: normal; }
/* the largest text: a short answer's big type steps down and the margin note gives its
   words the page's width, so they stay whole */
@container lb-page (max-width: 11rem) {
  .page__words.story--lg { font-size: 1.1875rem; }
  /* (.page raises these above the margin note's own rules, which come later in this file) */
  .page .margin-note { margin-left: 0; padding-left: .625rem; padding-right: .625rem; }
  .page .margin-note__words { font-size: 1rem; }
  .page .margin-note__reply-open { align-self: stretch; justify-content: center; text-align: center; padding-left: .375rem; padding-right: .375rem; font-size: 1rem; }
  .page .margin-note__reply-open .mark { display: none; }
}
html.nocq-14-5 .page__words.story--lg { font-size: 1.1875rem; }
html.nocq-14-5 .page .margin-note { margin-left: 0; padding-left: .625rem; padding-right: .625rem; }
html.nocq-14-5 .page .margin-note__words { font-size: 1rem; }
html.nocq-14-5 .page .margin-note__reply-open { align-self: stretch; justify-content: center; text-align: center; padding-left: .375rem; padding-right: .375rem; font-size: 1rem; }
html.nocq-14-5 .page .margin-note__reply-open .mark { display: none; }
/* "About: What was your first job?" on a follow-up or ask that stands on its own (ux-6) */
.page__about { font-family: var(--font-ui); font-size: .9375rem; line-height: 1.4; color: var(--muted); overflow-wrap: break-word; }
.page__about-label { font-weight: 700; color: var(--kind-text); }
.page__words { margin-top: .125rem; }
.page__sig { margin-top: 0; }
.page__waiting { font-family: var(--font-ui); font-weight: 500; font-size: .9375rem; color: var(--muted); }
.page__wish-line { display: flex; align-items: center; gap: .5rem; padding: .5rem .75rem; border-radius: 12px; background: var(--honey-soft); color: var(--honey-text); font-family: var(--font-ui); font-weight: 700; font-size: .9375rem; }
.page__wish-line .mark { flex: none; --mark-accent: var(--rose); --mark-accent-o: .5; color: var(--rose-text); }

/* the 1-10 answer */
.page__scale { display: flex; flex-direction: column; gap: .5rem; font-family: var(--font-ui); }
.page__scale-num { display: flex; align-items: baseline; gap: .5rem; }
.page__scale-num .num { font-size: 2.75rem; line-height: 1; color: var(--ink); }
.page__scale-of { font-weight: 700; font-size: 1rem; color: var(--muted); }
.page__scale-dots { display: grid; grid-template-columns: repeat(10, 1fr); gap: .3rem; max-width: 18rem; }
.page__dot { height: .5rem; border-radius: 999px; background: var(--hairline); }
.page__dot.is-on { background: var(--kind); }
.page__scale-ends { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .125rem 1rem; max-width: 18rem; font-weight: 700; font-size: .875rem; color: var(--muted); }
.page__scale-ends > :last-child { margin-left: auto; text-align: right; }

/* a photo as a taped Polaroid; gold-foil corners once the page is kept */
.polaroid { position: relative; align-self: center; width: min(100%, 17rem); margin: .75rem 0 .5rem; transform: rotate(-1.5deg); }
.chapter__pages > .page:nth-child(even) .polaroid { transform: rotate(1.25deg); }
.polaroid__frame { display: block; padding: 10px 10px 2.25rem; background: var(--polaroid); box-shadow: 0 0 0 1px var(--polaroid-edge), 0 10px 18px -10px rgba(59, 31, 51, .45); }
.polaroid img { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; background: var(--sunken); }
.polaroid::before, .polaroid::after { content: ""; position: absolute; z-index: 1; top: -.55rem; width: 4.25rem; height: 1.25rem; background: var(--tape); box-shadow: 0 1px 1px rgba(59, 31, 51, .06); }
.polaroid::before { left: -.75rem; transform: rotate(-32deg); }
.polaroid::after { right: -.75rem; transform: rotate(32deg); }
.polaroid__corner { display: none; position: absolute; z-index: 2; width: 1.6rem; height: 1.6rem; background: linear-gradient(135deg, var(--gold-a), var(--gold-b) 55%, var(--gold-c)); box-shadow: 0 1px 2px rgba(59, 31, 51, .3); }
.polaroid__corner--tl { left: -2px; top: -2px; clip-path: polygon(0 0, 100% 0, 0 100%); }
.polaroid__corner--br { right: -2px; bottom: -2px; clip-path: polygon(100% 0, 100% 100%, 0 100%); }
.page--kept .polaroid__corner { display: block; }
.page--kept .polaroid::before, .page--kept .polaroid::after { display: none; }

.page__voice { display: flex; flex-direction: column; gap: .25rem; padding: .25rem 0; font-family: var(--font-ui); }
.page__voice-print { display: none; }
.page .undo-bar, .book .undo-bar { font-family: var(--font-ui); }

/* the guess, written in the margin */
.margin-note {
  position: relative; display: flex; flex-wrap: wrap; gap: .5rem .75rem; align-items: flex-start;
  margin: .25rem 0 0 .75rem; padding: .75rem .875rem .8rem;
  border-radius: 4px 12px 12px 4px; background: var(--note-bg);
  box-shadow: inset 3px 0 0 var(--note-line), 0 1px 2px rgba(59, 31, 51, .08);
  font-family: var(--font-ui); font-size: .9375rem; line-height: 1.4;
  transform: rotate(-.6deg);
}
.margin-note__mark { flex: none; width: 2.5rem; height: 2.5rem; color: var(--stamp-c, var(--muted)); transform: rotate(-6deg); }
.margin-note--nailed { --stamp-c: var(--leaf-text); }
.margin-note--close { --stamp-c: var(--honey-text); }
.margin-note--missed { --stamp-c: var(--peri-text); }
.margin-note--heard { --stamp-c: var(--rose-text); }
/* beside the stamp when there's room; under it at large text, so words never break */
.margin-note__body { flex: 1 1 10.5rem; display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.margin-note__line { font-weight: 700; color: var(--ink); }
.margin-note__verdict { font-family: var(--font-story); font-weight: 700; font-size: 1rem; color: var(--stamp-c, var(--muted)); }
.margin-note__label { font-weight: 700; font-size: .875rem; color: var(--muted); }
.margin-note__stamp { display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .5rem; }
.margin-note__stamp .reply-badge__stamp { width: 2.25rem; height: 2.25rem; }
.margin-note__stamp .reply-badge__stamp .mark { width: 1.375rem; height: 1.375rem; }
.margin-note__note { display: flex; flex-direction: column; gap: .125rem; min-width: 0; }
.margin-note__words { font-family: var(--font-story); font-weight: 450; font-size: 1.0625rem; line-height: 1.4; color: var(--ink); white-space: pre-wrap; overflow-wrap: break-word; }
/* A note's or reply's ⋯ (ux-8): hide or report, never a bare Report under loving words. It
   ends the note, on the right, so it never narrows the words at large text. */
.margin-note__more { align-self: flex-end; margin: -.375rem -.625rem -.5rem 0; color: var(--muted); }
/* The author's one reply (f-13), across the whole note, under a hairline */
.margin-note__reply { flex: 1 1 100%; display: flex; flex-direction: column; gap: .25rem; min-width: 0; padding-top: .625rem; border-top: 1px dashed var(--note-line); }
.margin-note__reply-stamp { display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .5rem; }
.margin-note__reply-stamp .reply-badge__stamp { width: 2.25rem; height: 2.25rem; }
.margin-note__reply-stamp .reply-badge__stamp .mark { width: 1.375rem; height: 1.375rem; }
.margin-note__reply--new { border-top: 0; padding-top: .125rem; }
.margin-note__reply-open { align-self: flex-start; justify-content: flex-start; max-width: 100%; min-height: var(--tap); background: var(--card); box-shadow: 0 0 0 1px var(--note-line); text-align: left; }
.margin-note__reply-open > span { min-width: 0; }
.margin-note__reply-open .mark { color: var(--kind-text); }
.reply-compose { display: flex; flex-direction: column; gap: .5rem; padding-top: .25rem; }
.reply-compose__title { font-family: var(--font-story); font-weight: 600; font-size: 1.0625rem; line-height: 1.25; color: var(--ink); }
.reply-compose__stamps { grid-template-columns: repeat(auto-fit, minmax(min(100%, 6.25rem), 1fr)); }
.reply-compose .reply { min-height: 3.5rem; padding: .375rem; font-size: .9375rem; }
.reply-compose .reply .mark { width: 1.5rem; height: 1.5rem; }
.reply-compose__field input { background: var(--card); box-shadow: 0 0 0 1px var(--note-line); }
.reply-compose__count { font-size: .875rem; font-weight: 500; color: var(--muted); }
.reply-compose__row { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; }

/* your own guess that was never judged: the three judge buttons, under the note (book.js).
   Three across while they fit, else one per row; never two and one. */
.margin-note__judge { flex: 1 1 100%; display: flex; flex-direction: column; gap: .375rem; padding-top: .25rem; }
.margin-note__judge-q { font-family: var(--font-story); font-weight: 600; font-size: 1.0625rem; line-height: 1.25; color: var(--ink); }
.margin-note__judge-row { display: grid; gap: .375rem; grid-template-columns: repeat(auto-fit, minmax(max((100% - .75rem) / 3, min(100%, (14rem - 100%) * 999)), 1fr)); }
.margin-note__judge .judge { min-height: 4.25rem; padding: .375rem .25rem; }
.margin-note__judge .judge__mark { width: 2.25rem; height: 2.25rem; }
.margin-note[aria-busy="true"] .judge { opacity: .7; }

/* follow-ups and answers to asks continue on the same page */
.page__more { position: relative; display: flex; flex-direction: column; gap: .5rem; padding-top: 1rem; margin-top: .25rem; border-top: 2px dotted var(--hairline); }
.page__more-who { font-family: var(--font-ui); font-weight: 700; font-size: .875rem; letter-spacing: .04em; color: var(--kind-text); }
.page__q--more { font-size: 1rem; color: var(--muted); }
.page__more .page__words { font-size: 1.125rem; }
.page__more .story--lg { font-size: 1.25rem; }
.page__more--sealed { flex-direction: row; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; font-family: var(--font-ui); }
.page__mini-seal { flex: none; width: 2.25rem; height: 2.25rem; }
.page__mini-seal .seal { width: 100%; height: 100%; }
.page__more-sealed-text { flex: 1 1 10rem; min-width: 0; font-size: .9375rem; line-height: 1.35; }
.page__more-sealed-text .page__more-who { display: block; }
.page__more-q { color: var(--muted); }
.page__open { flex: none; }

/* the foot: kept or fading, and what you can do */
.page__foot { display: flex; flex-direction: column; align-items: stretch; gap: .5rem; margin-top: .375rem; padding-top: .75rem; border-top: 1px dashed var(--hairline); font-family: var(--font-ui); }
.page__status { display: flex; align-items: center; gap: .4rem; font-weight: 700; font-size: .9375rem; color: var(--muted); min-width: 0; }
.page__status .mark { flex: none; width: 1.375rem; height: 1.375rem; }
.page__status--kept { color: var(--honey-text); }
.page__status--kept .mark { color: var(--gold-b); --mark-accent: var(--gold-a); --mark-accent-o: 1; }
.page__actions { display: flex; align-items: center; flex-wrap: wrap; gap: .375rem .5rem; }
.page__actions:empty { display: none; }
.page__menu { margin-left: auto; }
.page__keep, .page__wish { min-height: var(--tap); font-size: 1rem; padding-left: .875rem; padding-right: 1rem; }
.page__keep .mark { color: var(--gold-b); --mark-accent: var(--gold-a); --mark-accent-o: 1; }
.page__wish .mark { color: var(--rose); --mark-accent: var(--rose); --mark-accent-o: .25; }
.page__unkeep { min-height: var(--tap); font-size: .9375rem; padding: 0 .5rem; }
.page__menu { color: var(--muted); }
/* a page I wished for: "Craig hasn't kept this yet", beside its fade date (ux-24) */
.page__status--fade { flex-wrap: wrap; }
.page__wished-line { flex-basis: 100%; padding-left: calc(1.375rem + .4rem); color: var(--rose-text); }
.page:not(.page--kept) .page__status--kept,
.page--kept .page__status--fade,
.page--kept .page__keep,
.page:not(.page--bypage) .page__unkeep,
.page--kept .page__wish,
.page--wished .page__wish,
.page:not(.page--wished) .page__wished-line { display: none; }
.page__status--fade:has(> span[data-fade-label]:empty) { display: none; }

/* kept: a pressed flower lands in the corner */
.page__pressed { position: absolute; right: 1.1rem; top: .9rem; display: none; width: 2.5rem; height: 2.5rem; color: var(--gold-b); --mark-accent: var(--gold-a); --mark-accent-o: 1; transform: rotate(12deg); pointer-events: none; }
.page__pressed .mark { width: 100%; height: 100%; }
.page--kept > .page__pressed { display: block; }

/* the New ribbon, a bookmark hanging from the top edge */
.page__ribbon {
  position: absolute; left: 1.25rem; top: -.375rem; z-index: 1;
  padding: .375rem .5rem .875rem; min-width: 2.75rem;
  background: var(--ribbon); color: var(--on-ribbon);
  font-family: var(--font-ui); font-weight: 700; font-size: .875rem; line-height: 1; text-align: center; letter-spacing: .02em;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% calc(100% - .45rem), 0 100%);
  box-shadow: 0 2px 3px rgba(59, 31, 51, .2);
}
.page--new .page__meta { padding-left: 3rem; }

/* the front pages: a dedication, and the inviter's hello */
.book__front { display: flex; flex-direction: column; gap: 1.5rem; }
.page--dedication { align-items: center; text-align: center; padding-top: 2rem; padding-bottom: 1.25rem; }
.page--dedication .page__meta, .page--hello .page__meta { padding-right: 0; }
.page--dedication .page__q { font-size: 1rem; color: var(--muted); font-weight: 500; }
.page--dedication .page__words { font-size: 1.5rem; line-height: 1.4; text-wrap: balance; }
.page--dedication .page__sig { align-self: center; text-align: center; }
.page--dedication .page__foot, .page--dedication .margin-note { align-self: stretch; text-align: left; }
.page--hello .page__q { font-size: 1.375rem; }

/* someone else's page you haven't opened yet: an envelope, sealed */
.page--sealed {
  position: relative; display: flex; flex-direction: column; gap: .5rem;
  padding: 0 1.25rem 1.25rem; overflow: hidden;
  border-radius: 10px; background: var(--env-paper);
  box-shadow: 0 0 0 1px var(--env-line), var(--e1);
}
.page__env { position: relative; height: 4.5rem; margin: 0 -1.25rem .5rem; }
.page__env-flap { position: absolute; inset: 0; background: var(--env-flap); clip-path: polygon(0 0, 100% 0, 52% 96%, 50% 100%, 48% 96%); filter: drop-shadow(0 1px 0 var(--env-line)); }
.page__env-seal { position: absolute; left: 50%; bottom: -1.1rem; width: 2.6rem; height: 2.6rem; margin-left: -1.3rem; }
.page--sealed .page__meta { padding: .75rem 0 0; text-align: center; }
.page--sealed .page__q { text-align: center; text-wrap: balance; }
.page__sealed-line { font-family: var(--font-ui); font-weight: 700; color: var(--kind-text); text-align: center; margin-bottom: .25rem; }

.book__empty { padding: 1.75rem 1.25rem; align-items: center; }
.book__empty-mark { width: 3rem; height: 3rem; color: var(--kind-text); --mark-accent: var(--kind); --mark-accent-o: .3; }

/* ---------------------------------------------------- things I didn't know */
.learned__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .75rem; container: learned / inline-size; }
.learned__epigraph { font-family: var(--font-story); font-weight: 450; font-size: 1.0625rem; line-height: 1.35; color: var(--muted); }
.learned__item {
  position: relative; display: flex; flex-direction: column; gap: .3rem;
  padding: 1rem 3.75rem .5rem 1.125rem; border-radius: 4px;
  background: var(--card); box-shadow: 0 0 0 1px var(--hairline), var(--e1);
  border-left: 3px solid var(--rose-soft);
}
.learned__mark { position: absolute; right: .75rem; top: .75rem; width: 2.5rem; height: 2.5rem; transform: rotate(-8deg); color: var(--peri-text); }
.learned__item--close .learned__mark { color: var(--honey-text); }
.learned__item--close { border-left-color: var(--honey-soft); }
.learned__q { font-weight: 700; font-size: .9375rem; color: var(--muted); }
.learned__a { font-family: var(--font-story); font-weight: 500; font-size: 1.1875rem; line-height: 1.4; }
.learned__foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0 1rem; }
.learned__guess { font-size: .9375rem; color: var(--muted); }
.learned__link { display: inline-flex; align-items: center; min-height: var(--tap); font-weight: 700; }
/* the largest text: the stamp joins the words instead of holding a column beside them */
@container learned (max-width: 13rem) {
  .learned__item { padding-right: 1.125rem; }
  .learned__mark { position: static; width: 2rem; height: 2rem; }
}
html.nocq-14-5 .learned__item { padding-right: 1.125rem; }
html.nocq-14-5 .learned__mark { position: static; width: 2rem; height: 2rem; }

/* ==================================================================== MOTION
   Everything that moves, inside no-preference and scoped to html:not(.calm). Calm and
   reduced motion keep the same words and states with no movement. */
@media (prefers-reduced-motion: no-preference) {
  /* The guest envelope (first visit, 1.6 s): the seal parts (0-300), the flap folds back
     through 180 degrees with perspective (200-700), the seed packet rises (700-1300) and
     the caption arrives (1300-1600). welcome.js adds .is-opening; a tap jumps to the end. */
  html:not(.calm) .env.is-opening .env__seal { visibility: visible; }
  html:not(.calm) .env.is-opening .seal__whole { opacity: 0; }
  html:not(.calm) .env.is-opening .seal__half { opacity: 1; }
  html:not(.calm) .env.is-opening .seal__half--l { animation: env-half-l 300ms var(--ease-move) both; }
  html:not(.calm) .env.is-opening .seal__half--r { animation: env-half-r 300ms var(--ease-move) both; }
  html:not(.calm) .env.is-opening .env__flap { visibility: visible; animation: env-flap-shut 250ms var(--ease-in) 200ms both; }
  html:not(.calm) .env.is-opening .env__flap-open { animation: env-flap-open 250ms var(--ease-out) 450ms both; }
  html:not(.calm) .env.is-opening .env__packet { animation: env-packet 600ms var(--ease-out) 700ms both; }
  html:not(.calm) .env.is-opening .env__caption { animation: env-caption 300ms var(--ease-out) 1300ms both; }
}
@keyframes env-half-l { from { transform: none; opacity: 1; } to { transform: translate(-.35em, .6em) rotate(-12deg); opacity: 0; } }
@keyframes env-half-r { from { transform: none; opacity: 1; } to { transform: translate(.35em, .6em) rotate(12deg); opacity: 0; } }
@keyframes env-flap-shut { from { transform: perspective(800px) rotateX(0deg); } to { transform: perspective(800px) rotateX(90deg); } }
@keyframes env-flap-open { from { transform: perspective(800px) rotateX(-90deg); } to { transform: perspective(800px) rotateX(0deg); } }
@keyframes env-packet { from { transform: translateY(6.3em); } to { transform: none; } }
@keyframes env-caption { from { opacity: 0; transform: translateY(.4em); } to { opacity: 1; transform: none; } }

/* Calm and reduced motion: things that leave or arrive simply fade (150 ms). */
.is-leaving { opacity: 0; transition: opacity 150ms linear; }
@media (prefers-reduced-motion: no-preference) {
  /* Keep a page: it presses (scale .97, the shadow deepens), the pressed flower lands in
     the corner (180-420, pop) and all settles by 600. */
  html:not(.calm) .page.is-pressing { animation: page-press 600ms var(--ease-out); }
  html:not(.calm) .page.is-pressing > .page__pressed { animation: page-pressed 420ms var(--ease-pop) both; }
  html:not(.calm) .page.is-pressing .polaroid__corner { animation: lb-fade-in 240ms var(--ease-out) 300ms both; }
  html:not(.calm) .is-leaving { transition: opacity 240ms var(--ease-in), transform 240ms var(--ease-in); transform: translateY(-6px); }
  /* New ribbons drop in as their page arrives */
  html:not(.calm) .page__ribbon.is-waiting { transform: translateY(-110%); }
  html:not(.calm) .page__ribbon.is-in { transform: none; transition: transform 420ms var(--ease-pop) 120ms; }
  /* Keep everything turned on: a shimmer sweeps the petals, which deepen 25 ms apart and
     take their gold edge. Turned off, the gold simply fades. */
  html:not(.calm) .kpetal { transition: opacity 240ms var(--ease-out) calc(var(--i, 0) * 15ms); }
  html:not(.calm) .kpetal__edge { stroke-dasharray: var(--kp-len); stroke-dashoffset: var(--kp-len); transition: opacity 200ms var(--ease-out), stroke-dashoffset 0s linear 200ms; }
  html:not(.calm) .kpetal.is-kept .kpetal__edge { stroke-dashoffset: 0; transition: opacity 0s, stroke-dashoffset 300ms var(--ease-out); }
  html:not(.calm) .keep-card.is-shimmer .kpetal { transition-delay: calc(120ms + var(--i, 0) * 25ms); }
  html:not(.calm) .keep-card.is-shimmer .kpetal.is-kept .kpetal__edge { transition-delay: 0s, calc(160ms + var(--i, 0) * 25ms); }
  html:not(.calm) .keep-card.is-shimmer .keep-card__petals::after { animation: kp-sweep 700ms var(--ease-move) 120ms both; }
  html:not(.calm) .keep-card__copy { transition: opacity 200ms var(--ease-out); }
  html:not(.calm) .invite__ring { transition: transform 80ms linear, background-color 200ms var(--ease-out); }
  html:not(.calm) .invite__ring.is-on { animation: none; }
}
@keyframes page-press {
  0% { transform: none; }
  30% { transform: scale(.97); box-shadow: 0 2px 4px rgba(59, 31, 51, .10), 0 24px 40px -18px rgba(110, 45, 75, .45); }
  100% { transform: none; }
}
@keyframes page-pressed {
  0%, 40% { transform: rotate(12deg) scale(.6); opacity: 0; }
  100% { transform: rotate(12deg) scale(1); opacity: 1; }
}
@keyframes kp-sweep { 0% { transform: translateX(-100%); opacity: 0; } 25% { opacity: 1; } 100% { transform: translateX(100%); opacity: 0; } }

/* ===================================================================== PRINT
   Save as PDF prints the book on A5: white paper, each chapter on a new page, nothing to
   tap, and no sealed pages. Voice notes print as their waveform with a caption. */
@media print {
  @page { size: 148mm 210mm; margin: 18mm 16mm 20mm; }
  /* White paper whatever the phone's theme: the signal colours go back to their light,
     print-safe values (app.css resets ink, muted and rose; the kind colours read these). */
  .book-page {
    --on-rose: #FFFFFF;
    --leaf: #6FB37A; --leaf-text: #276B45; --leaf-soft: #E3F3E9;
    --honey: #F2B33D; --honey-text: #8F5A0B; --honey-soft: #FCEFD2;
    --peri: #8FA2F2; --peri-text: #4152B0; --peri-soft: #E6EAFD;
    --polaroid: #FFFFFF; --polaroid-edge: rgba(59, 31, 51, .10); --page-edge: #EFE4D6;
  }
  .book-page .wrap { gap: 0; }
  .book { display: block; }
  .book p, .book li { orphans: 3; widows: 3; }
  .cover { break-after: page; padding: 0; min-height: 160mm; justify-content: center; }
  .cover__cloth { -webkit-print-color-adjust: exact; print-color-adjust: exact; box-shadow: none; }
  .cover__plate { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .cover__actions, .book__news, .wishes, .fading, .learned { display: none !important; }
  .contents__lead { border-bottom-color: #CDB9AC; }
  .page--sealed, .page__more--sealed, .page__foot, .page__menu, .page__ribbon, .page__waiting, .page__wish-line,
  .margin-note__more, .margin-note__judge, .margin-note__reply--new, .learned__link, .contents__item--learned { display: none !important; }
  .contents { break-after: page; box-shadow: none; outline: 0; padding: 0; background: none; }
  .contents__item--empty { display: none; }
  .book__front { break-after: page; }
  .chapter { display: block; break-before: page; }
  .chapter__opener { padding-top: 0; margin-bottom: 6mm; }
  .chapter__pages { display: block; }
  .page { display: block; break-inside: avoid; margin: 0 0 7mm; padding: 6mm 0 0; box-shadow: none; outline: 0; background: none; border-top: 1px solid #DCCBBE; }
  .page > * + * { margin-top: 3mm; }
  .page--kept > .page__pressed { position: absolute; }
  .polaroid { break-inside: avoid; transform: none; width: 60mm; margin: 3mm auto; }
  .polaroid::before, .polaroid::after { display: none; }
  .polaroid__frame { box-shadow: 0 0 0 1px #DCCBBE; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .polaroid__corner { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .page__voice .player__btn, .page__voice .player__time, .page__voice .player__bar-track { display: none; }
  .page__voice .player__bar { opacity: 1; background: #B9A6AE; }
  .page__voice .player__wave { -webkit-print-color-adjust: exact; print-color-adjust: exact; height: 7mm; }
  .page__voice-print { display: block; font-size: 9pt; color: #5E4656; }
  .margin-note { transform: none; box-shadow: none; border-left: 2px solid #DCCBBE; background: none; margin-left: 0; }
  .page__more { break-inside: avoid; }
}
