/* Squeeeks — design tokens and shared components.
   Every page imports this file unchanged. Contrast figures are WCAG ratios,
   measured against --cream unless stated. */

@font-face { font-family: "Fredoka"; font-weight: 600; font-display: swap; src: url("media/fonts/web/Fredoka-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "Fredoka"; font-weight: 700; font-display: swap; src: url("media/fonts/web/Fredoka-Bold.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-weight: 400; font-display: swap; src: url("media/fonts/web/Nunito-Regular.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-weight: 600; font-display: swap; src: url("media/fonts/web/Nunito-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-weight: 700; font-display: swap; src: url("media/fonts/web/Nunito-Bold.woff2") format("woff2"); }
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 600; font-display: swap; src: url("media/fonts/web/PlusJakartaSans-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 700; font-display: swap; src: url("media/fonts/web/PlusJakartaSans-Bold.woff2") format("woff2"); }
/* Receipt only: a 4.7 KB subset (ASCII plus · – — ’ “ ” … ×). A glyph outside it falls back to the system mono. */
@font-face { font-family: "JetBrains Mono"; font-weight: 400; font-display: swap; src: url("media/fonts/web/JetBrainsMono-Regular.woff2") format("woff2"); unicode-range: U+0020-007E, U+00B7, U+00D7, U+2013-2014, U+2019, U+201C-201D, U+2026; }

:root {
  /* Surfaces — AppColors */
  --cream: #F9F6F0;        /* page */
  --oat: #F2E7CE;          /* cards */
  --oat-line: #E3D4B0;     /* card borders, hairlines on oat */
  --butter: #FCE7B0;       /* sampled from the app icon's rays */
  --coral: #E3937C;        /* sampled from the app icon's rays; never text */
  --sage: #A8CABA;
  --lawn: #86B571;         /* sampled from app--home--home--furnished.jpg */

  /* Ink — no black anywhere */
  --brown: #6E5230;        /* 6.68 on cream · 5.87 on oat */
  --brown-soft: #7C6243;   /* brown at 90%: 5.28 on cream · 4.64 on oat (80% fails at 4.17) */
  --brown-deep: #4A3520;   /* the only ink that passes on --lawn (4.87) */
  --contour: #6B4A2F;      /* sticker outlines */

  /* Accent — app teal is decoration only (2.89 on cream fails as text) */
  --teal: #1FA397;
  --teal-ink: #0B6B62;     /* button fill: cream on it is 5.91 */
  /* Keyboard focus ring (2026-10-19). App teal is 2.89 on cream and 2.54 on oat, under the 3:1 that
     WCAG 1.4.11 asks of a focus indicator, so the ring is the deeper teal: 5.91 on cream, 5.19 on
     oat, 5.22 on butter. It is still the one teal; nothing new is saturated. Use this, never a colour. */
  --focus-ring: 3px solid var(--teal-ink);

  /* Type */
  --font-display: "Fredoka", ui-rounded, system-ui, sans-serif;
  --font-body: "Nunito", ui-rounded, system-ui, sans-serif;
  --font-label: "Plus Jakarta Sans", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --track-label: 0.08em;

  /* Shape */
  --radius-sticker: 22px;
  --radius-card: 18px;
  --radius-pill: 999px;
  --outline: 2px solid var(--contour);
  --shadow-sticker: 0 2px 0 var(--oat-line), 0 14px 30px -12px rgba(110, 82, 48, 0.35);

  /* Layout */
  --gutter: 16px;
  --header-h: 56px;
  --maxw: 1200px;

  /* Motion — content settles with a little weight */
  --ease-settle: cubic-bezier(0.22, 1.2, 0.36, 1);
  --settle-dur: 700ms;
  --settle-step: 90ms;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--cream);
  color: var(--brown);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Small uppercase label — uppercase through CSS so screen readers read words */
.label {
  font-family: var(--font-label);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  line-height: 1.3;
}

/* The die-cut sticker frame: rounded, 2px warm-brown outline, soft oat shadow. No bezels. */
.sticker {
  position: relative;
  border: var(--outline);
  border-radius: var(--radius-sticker);
  box-shadow: var(--shadow-sticker);
  overflow: hidden;
  background: var(--lawn);
}
.sticker > img { width: 100%; }

/* Quoted prop labels: hairline leader from a real prop to a small quoted tag */
.props { position: absolute; inset: 0; pointer-events: none; }
.props svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.props line { stroke: var(--contour); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
.props circle { fill: var(--cream); stroke: var(--contour); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.prop-tag {
  position: absolute;
  transform: translate(-50%, -50%);
  background: var(--cream);
  color: var(--brown);
  border: 1.5px solid var(--contour);
  border-radius: 6px;
  padding: 3px 7px 2px;
  white-space: nowrap;
  font-size: 11px;
}
.prop-tag::before { content: "\201C"; }
.prop-tag::after { content: "\201D"; }

/* The one button — app teal deepened until cream passes */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 18px;
  border-radius: var(--radius-pill);
  background: var(--teal-ink); color: var(--cream);
  font-family: var(--font-display); font-weight: 600; font-size: 16px;
  text-decoration: none;
  box-shadow: 0 2px 0 var(--brown-deep);
}
.btn:focus-visible, a:focus-visible { outline: var(--focus-ring); outline-offset: 3px; }

/* Apple's badge, used as supplied */
.store-badge { display: inline-block; line-height: 0; }
.store-badge img { height: 48px; width: auto; }

/* Speech bubble */
.bubble {
  position: relative;
  background: var(--cream);
  border: var(--outline);
  border-radius: 16px;
  padding: 6px 12px;
  font-family: var(--font-body); font-weight: 600; font-size: 15px;
  color: var(--brown);
}

/* Settle-in: everything with [data-settle] drops into place, staggered by --i */
@keyframes settle {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
[data-settle] {
  animation: settle var(--settle-dur) var(--ease-settle) both;
  animation-delay: calc(var(--i, 0) * var(--settle-step));
}
@media (prefers-reduced-motion: reduce) {
  [data-settle] { animation: none; }
}
/* The "Check your inbox" card that signup.js swaps in settles the same way. */
@media (prefers-reduced-motion: no-preference) {
  .done { animation: settle var(--settle-dur) var(--ease-settle) both; }
}

/* ---------- Type scale ---------- */
:root {
  --h1-mobile: 38px;
  --h1-desktop: 56px;
  --h2-mobile: 30px;
  --h2-desktop: 44px;
  --body-lg: 17px;
  --body-lg-desktop: 19px;
  --small: 14px;
}

/* ---------- Storybook paper: the page is an oat desk, content sits on rounded cream sheets ---------- */
.desk { background: var(--oat); min-height: 100vh; }
.paper {
  background: var(--cream);
  border: var(--outline);
  border-radius: 28px;
  margin: 0 8px 12px;
}
@media (min-width: 900px) {
  .paper { max-width: 1400px; margin: 4px auto 24px; }
}

/* ---------- Site header (sticky, sits on the desk) ---------- */
.site-head {
  position: sticky; top: 0; z-index: 5;
  height: var(--header-h);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 0 var(--gutter);
  background: var(--oat);
}
.wordmark { display: inline-flex; align-items: center; gap: 8px; text-decoration: none; font-family: var(--font-display); font-weight: 700; font-size: 22px; color: var(--brown); }
.wordmark img { width: 28px; height: 28px; border-radius: 8px; border: 1.5px solid var(--contour); }
/* The duck-foam header icon (/media/art/duck-foam-160.webp, class "badge") is a round badge with its
   own ring: no square contour around it. A square icon (the quiz's icon-96.png) keeps the contour. */
.wordmark .badge { border: 0; border-radius: 50%; }
.head-right { display: flex; align-items: center; gap: 28px; }
.nav { display: none; gap: 24px; }
.nav a { text-decoration: none; color: var(--brown); }
.nav a:hover { text-decoration: underline; text-underline-offset: 4px; }
/* Header tap targets are 44px, and the button stays on one line even on a 320px phone. These were
   the homepage's own rules, copied into /press/, /studio/ and the 404; they live here now (2026-10-19). */
.site-head .wordmark { min-height: 44px; }
.btn-head { min-height: 44px; font-size: 15px; padding: 0 16px; white-space: nowrap; }
@media (max-width: 359px) {
  .site-head { gap: 8px; }
  .site-head .wordmark { gap: 6px; font-size: 20px; }
  .btn-head { padding: 0 12px; font-size: 14px; }
}
@media (min-width: 900px) {
  :root { --gutter: 40px; --header-h: 64px; }
  .nav { display: flex; }
  .nav a { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; }
}

/* ---------- The duck speaks ---------- */
.speaker { display: flex; align-items: center; gap: 10px; }
.speaker img { width: 52px; height: auto; flex: none; }
.speaker .bubble { margin: 0; border-radius: 999px; padding: 6px 14px; }
.speaker .bubble::before {
  content: ""; position: absolute; left: -7px; top: 50%; width: 12px; height: 12px;
  background: var(--cream); border-left: var(--outline); border-bottom: var(--outline);
  transform: translateY(-50%) rotate(45deg);
}
@media (min-width: 900px) {
  .speaker img { width: 64px; }
  .speaker .bubble { font-size: 17px; }
}

/* ---------- A sticker standing on a soft lawn hill ---------- */
.on-hill { position: relative; }
.on-hill::before { content: ""; position: absolute; left: 3%; right: 3%; bottom: -12px; height: 42%; background: var(--lawn); border-radius: 50%; opacity: 0.4; }
.on-hill .sticker { transform: rotate(-1.2deg); }
@media (min-width: 900px) { .on-hill::before { bottom: -28px; } }
.prop-tag { border-radius: 999px; padding: 3px 9px 2px; }
@media (min-width: 900px) { .prop-tag { font-size: 12px; padding: 4px 10px 3px; } }

/* ---------- Fine print ---------- */
.terms { font-size: var(--small); line-height: 1.4; color: var(--brown-soft); }
.terms span { white-space: nowrap; }
.proof { font-size: var(--small); font-weight: 700; color: var(--brown); }
.proof .star { color: var(--teal-ink); }

/* ---------- QR (desktop only) ---------- */
.qr { display: none; }
@media (min-width: 900px) {
  .qr { display: flex; align-items: center; gap: 12px; }
  .qr img { width: 112px; height: 112px; padding: 8px; background: var(--cream); border: 1.5px solid var(--oat-line); border-radius: 12px; }
  .qr span { font-size: var(--small); max-width: 6.5em; line-height: 1.3; color: var(--brown-soft); }
  .store-badge img { height: 56px; }
}

/* ==========================================================================
   Shared page components (full site, 2026-10-19). Markup for each one is in the
   build's COMPONENTS.md. Mobile first; desktop from 900px, as above.
   ========================================================================== */

/* Space between two stacked sheets, mirrored from .paper's margins. The tape seam
   and the stacked-paper hand-off read it. A page that spaces its sheets with a
   flex/grid gap instead of margins sets its own value. */
:root { --sheet-gap: 12px; }
@media (min-width: 900px) { :root { --sheet-gap: 24px; } }

/* ---------- Early-access form (every page with a signup) ----------
   signup.js wires each form.join[data-signup]: .ts holds Turnstile, .status speaks,
   and on success the form is swapped for div.done (which settles in, see above).
   Moved here unchanged from the v1 homepage. */
.join { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 440px; text-align: left; }
.join .row { display: flex; flex-wrap: wrap; gap: 8px; }
.join input {
  flex: 1 1 200px; min-width: 0; min-height: 48px; padding: 0 18px;
  font: inherit; font-size: 17px; color: var(--brown); background: var(--cream);
  border: var(--outline); border-radius: var(--radius-pill);
}
.join input::placeholder { color: var(--brown-soft); }
.join input:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.join .btn { min-height: 48px; font-size: 17px; border: 0; cursor: pointer; flex: 1 0 auto; }
.join .btn[disabled] { opacity: .6; cursor: progress; }
.join .status { margin: 0; font-size: var(--small); font-weight: 700; }
.join .status:empty, .join .ts:empty { display: none; }
.join .status.err { color: var(--brown-deep); }
.join .status.err::before { content: "\26A0\FE0E\20"; }
.done { background: var(--oat); border: var(--outline); border-radius: var(--radius-card); padding: 14px 18px; text-align: left; max-width: 440px; }
.done h2 { font-family: var(--font-display); font-weight: 700; font-size: 22px; margin: 0 0 4px; }
.done p { margin: 0; }
/* The quiz sizes its own column (560px); its form and card stay full width there. */
.quiz .join, .quiz .done { max-width: none; }

/* ---------- Site footer (every page; landers and the 404 use a shorter one) ----------
   Sits on the desk: the doormat sign-off, plain words about your email, the links,
   the © line and the two joke footnotes. Text is brown-soft, which still passes at
   the homepage's warmest (butter) scroll stop. Links are 44px tall and at least 44px wide to tap
   (the width rule was the homepage's own until 2026-10-19; /press/, /studio/ and the 404 lacked it). */
.site-foot {
  padding: 8px 16px 40px;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  text-align: center;
}
.doormat {
  margin: 0; padding: 10px 22px;
  font-family: var(--font-display); font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--brown); background: var(--butter);
  border: 2px dashed var(--contour); border-radius: 10px;
}
.site-foot .privacy-note { margin: 0; max-width: 60ch; font-size: var(--small); color: var(--brown-soft); }
.site-foot .legal { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 14px; margin: 0; font-size: 13px; color: var(--brown-soft); }
.site-foot .legal a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; }
.site-foot .legal.tiny { font-size: 12px; }
.site-foot .foot-fine { margin: 0; font-size: 13px; color: var(--brown-soft); }
.site-foot .footnotes { margin: 0; padding: 0; list-style: none; font-size: 12px; line-height: 1.45; color: var(--brown-soft); }

/* ---------- Spec line: the purist small print under a section's body ----------
   Typed in plain case, uppercased here so screen readers read words. Each group
   sits in a <span> so a line breaks at the dots, never inside a group. */
.spec {
  margin: 0;
  font-family: var(--font-label); font-weight: 600; font-size: 12px; line-height: 1.5;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--brown-soft);
}
.spec span { white-space: nowrap; }

/* ---------- Masking tape: a crooked butter strip, hand-lettered (homepage only, two strips) ----------
   Static. The torn short ends are a clip-path on the fill, and the faint shadow is a
   drop-shadow on the strip, so it follows the torn shape. --tilt turns it: -1.5deg
   by default; the second strip tilts the other way. Plain butter, never stripes.
   .tape-seam (optional) lays a strip across the gap between two sheets. */
.tape {
  --tilt: -1.5deg;
  position: relative;
  display: block; width: fit-content; max-width: min(100%, 560px);
  margin: 0 auto; padding: 8px 20px 7px;
  color: var(--brown);
  font-family: var(--font-display); font-weight: 600; font-size: clamp(13px, 3.6vw, 15px); line-height: 1.3;
  letter-spacing: .07em; text-transform: uppercase; text-align: center; text-wrap: balance;
  transform: rotate(var(--tilt));
  filter: drop-shadow(0 2px 2px rgba(110, 82, 48, 0.22));
}
.tape::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, transparent 70%, rgba(110, 82, 48, 0.07)), var(--butter);
  clip-path: polygon(
    0 3%, 6px 15%, 1px 29%, 7px 42%, 2px 56%, 6px 69%, 0 83%, 5px 100%,
    calc(100% - 4px) 100%, 100% 87%, calc(100% - 6px) 73%, calc(100% - 1px) 60%,
    calc(100% - 7px) 46%, calc(100% - 2px) 32%, calc(100% - 6px) 17%, 100% 0);
}
.tape-seam {
  position: relative; z-index: 2; top: calc(var(--sheet-gap) / -2);
  height: 0; padding: 0 var(--gutter);
  display: flex; align-items: center; justify-content: center;
}
@media (min-width: 900px) { .tape { font-size: 17px; padding: 10px 32px 9px; } }

/* ---------- PROOF OF WORK receipt (homepage S3) ----------
   Thermal paper: oat, zigzag top and bottom (a CSS mask), JetBrains Mono. The rows
   are typed at exactly 30 columns, and the type scales with the receipt's own width
   (container units), so no row wraps or overflows, even on a 320px phone. */
.receipt {
  --tooth: 12px;
  width: min(300px, 100%);
  margin: 0;
  container-type: inline-size;
  filter: drop-shadow(0 0 0.6px var(--contour)) drop-shadow(0 10px 12px rgba(110, 82, 48, 0.22));
}
.receipt pre {
  margin: 0; padding: calc(var(--tooth) + 12px) 14px;
  overflow: hidden; white-space: pre;
  background: var(--oat); color: var(--brown);
  font-family: var(--font-mono); font-size: 12.5px; line-height: 1.65;
  font-size: clamp(10px, (100cqi - 28px) / 18.6, 15px);
  -webkit-mask:
    conic-gradient(from -45deg at bottom, transparent, var(--brown) 1deg 89deg, transparent 90deg) bottom / var(--tooth) 51% repeat-x,
    conic-gradient(from 135deg at top, transparent, var(--brown) 1deg 89deg, transparent 90deg) top / var(--tooth) 51% repeat-x;
  mask:
    conic-gradient(from -45deg at bottom, transparent, var(--brown) 1deg 89deg, transparent 90deg) bottom / var(--tooth) 51% repeat-x,
    conic-gradient(from 135deg at top, transparent, var(--brown) 1deg 89deg, transparent 90deg) top / var(--tooth) 51% repeat-x;
}

/* ---------- Catalogue cards (homepage S4) ----------
   A deadpan shop catalogue: art on an oat plinth, the item's quoted name, then field
   rows (label, dotted leader, value). Phone: a horizontal snap row with the next card
   peeking. Desktop: three across. The scroller takes tabindex="0", role="region" and
   an aria-label so a keyboard can scroll it (focus shows --focus-ring). --bleed lets it run to the sheet edge. */
.cat-row {
  --bleed: 0px;
  display: grid; grid-auto-flow: column; grid-auto-columns: 78%; gap: 12px;
  margin: 0 calc(-1 * var(--bleed)); padding: 2px var(--bleed) 10px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-padding-inline: var(--bleed);
  scrollbar-width: none;
}
.cat-row::-webkit-scrollbar { display: none; }
.cat-row:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-card); }
.cat-card {
  scroll-snap-align: start; min-width: 0;
  display: flex; flex-direction: column; gap: 10px;
  margin: 0; padding: 12px 14px 16px;
  background: var(--cream); color: var(--brown);
  border: var(--outline); border-radius: var(--radius-card);
  box-shadow: 0 2px 0 var(--oat-line);
}
.cat-art { position: relative; margin: 0; aspect-ratio: 4 / 3; background: var(--oat); border-radius: 12px; }
.cat-art img { position: absolute; top: 14px; left: 14px; width: calc(100% - 28px); height: calc(100% - 28px); object-fit: contain; }
.cat-name { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1.15; letter-spacing: .04em; text-transform: uppercase; }
.cat-name::before { content: "\201C"; }
.cat-name::after { content: "\201D"; }
.cat-fields { margin: 0; display: flex; flex-direction: column; gap: 7px; }
/* A value too long for the row drops to its own line, right-aligned, and the leader runs the full width. */
.cat-field { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; }
.cat-field dt {
  flex: 1 0 auto; display: flex; align-items: baseline; gap: 6px;
  font-family: var(--font-label); font-weight: 600; font-size: 12px; line-height: 1.3;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--brown-soft);
}
.cat-field dt::after {
  content: ""; flex: 1 1 auto; min-width: 14px; height: 4px;
  background: radial-gradient(circle, var(--brown-soft) 0.9px, transparent 1.3px) left bottom / 6px 4px repeat-x;
}
.cat-field dd {
  flex: 0 1 auto; min-width: 0; margin: 0 0 0 auto; text-align: right;
  font-family: var(--font-label); font-weight: 700; font-size: 13px; line-height: 1.3;
  letter-spacing: .04em; text-transform: uppercase; color: var(--brown);
}
/* A sentence-long value (the shop note) stacks under its label, in plain case. */
.cat-field.note { flex-direction: column; align-items: stretch; gap: 2px; }
.cat-field.note dt::after { content: none; }
.cat-field.note dd { margin: 0; text-align: left; font-family: var(--font-body); font-weight: 400; font-size: 15px; line-height: 1.4; letter-spacing: 0; text-transform: none; }
@media (min-width: 900px) {
  .cat-row {
    grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px;
    margin: 0; padding: 0; overflow: visible; scroll-snap-type: none;
  }
}

/* ---------- Secondary button: a cream pill with a contour (quiz invite, press) ----------
   For the second action next to or instead of the teal .btn. Never saturated. */
.btn-outline {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 18px;
  border: var(--outline); border-radius: var(--radius-pill);
  background: var(--cream); color: var(--brown);
  font-family: var(--font-display); font-weight: 600; font-size: 16px; line-height: 1.2;
  text-decoration: none; cursor: pointer;
  box-shadow: 0 2px 0 var(--oat-line);
}
.btn-outline:hover { background: var(--oat); }
.btn-outline:focus-visible { outline: var(--focus-ring); outline-offset: 3px; }
.btn-outline.small { padding: 0 14px; font-size: 15px; }

/* ---------- Oat cards (homepage S6 promises; lander promise cards) ----------
   Stacked on phone; one row on desktop, as many columns as there are cards.
   The card title can be an h2 or an h3 (whichever keeps the outline unbroken). */
.cards-3 { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; margin: 0; padding: 0; list-style: none; }
.cards-3 > * {
  margin: 0; padding: 16px 18px 18px;
  display: flex; flex-direction: column; gap: 6px;
  background: var(--oat); color: var(--brown);
  border: var(--outline); border-radius: var(--radius-card);
  box-shadow: 0 2px 0 var(--oat-line);
}
.cards-3 :is(h2, h3) { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1.2; text-wrap: balance; }
.cards-3 p { margin: 0; }
@media (min-width: 900px) {
  .cards-3 { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 20px; }
  .cards-3 > * { padding: 20px 22px 22px; }
  .cards-3 :is(h2, h3) { font-size: 22px; }
}

/* ---------- Glossary: a small dictionary page (homepage S7, "SQUEEEKS, DEFINED") ----------
   Fredoka headword, italic part of speech (Nunito has no italic file, so the browser
   slants it), Nunito definition. Two columns with a center rule on desktop. */
.dict { display: block; margin: 0; }
.dict > div { break-inside: avoid; padding: 0 0 16px; }
.dict dt { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1.25; color: var(--brown); }
.dict .pos { margin-left: 4px; font-family: var(--font-body); font-weight: 400; font-style: italic; font-size: 16px; color: var(--brown-soft); }
.dict dd { margin: 2px 0 0; font-family: var(--font-body); color: var(--brown); }
@media (min-width: 900px) {
  .dict { columns: 2; column-gap: 56px; column-rule: 1.5px solid var(--oat-line); }
}
/* Footnote marker (* or **) pointing at the footer; the tap area grows, the text doesn't move. */
.fn-ref { position: relative; padding: 0 1px; font-weight: 700; color: var(--brown); text-decoration: none; }
.fn-ref::after { content: ""; position: absolute; inset: -12px -14px; }

/* ---------- Caption under a figure or a row of screens ---------- */
.caption { margin: 0; font-size: var(--small); line-height: 1.4; color: var(--brown-soft); text-wrap: pretty; }
figure > .caption { margin-top: 10px; }

/* ---------- Sticker sheet: transparent stickers on an oat panel (homepage S5 ducks, /press/ stickers) ----------
   A wrapping grid; each sticker sits in a square box so mixed shapes line up. */
.sticker-sheet {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); gap: 12px;
  margin: 0; padding: 16px; list-style: none;
  background: var(--oat);
  border: 2px dashed var(--contour); border-radius: var(--radius-sticker);
}
.sticker-sheet > * { margin: 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.sticker-sheet img { width: 100%; max-width: 132px; aspect-ratio: 1; object-fit: contain; filter: drop-shadow(0 4px 5px rgba(110, 82, 48, 0.22)); }
.sticker-sheet a { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; font-size: var(--small); font-weight: 700; }
@media (min-width: 900px) {
  .sticker-sheet { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 16px 20px; padding: 22px 24px; }
}

/* ---------- Stacked-paper hand-off (homepage hero to S2) ----------
   Put .stack-under on the sheet AFTER the hero. It draws its own top edge tucked
   under the sheet before it, so a second contour edge peeks --peek (7px) out below
   that sheet, a little narrower, like the next page of a pad. Static: no animation.
   It paints at z-index -1, so no ancestor between it and body may set a background
   or a z-index, and the sheet itself must not set one either. */
.stack-under { --peek: 7px; position: relative; }
.stack-under::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  left: 10px; right: 10px; height: 64px;
  bottom: calc(100% + var(--sheet-gap) - var(--peek));
  background: var(--cream);
  border: var(--outline); border-radius: 0 0 24px 24px;
}
