/* ---------------------------------------------------------------------------
 * Birth Blooms — site styles. Built on tokens.css; every value comes from the
 * scale (P-19). Structure first, surface second (P-07).
 *
 * The voice is a museum herbarium: cotton-rag paper, mounted specimens, accession
 * marks, gold rules, and deep ink-green bands. The page is allowed to be romantic
 * about what it is instead of apologising for what it isn't.
 * ------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--t-0);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; }

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 300;
  line-height: var(--lh-tight);
  letter-spacing: -0.021em;
  font-variation-settings: "opsz" 110, "SOFT" 28, "WONK" 1;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: var(--t-5); }
h2 { font-size: var(--t-4); }
h3 { font-size: var(--t-2); letter-spacing: -0.012em; font-variation-settings: "opsz" 40, "SOFT" 22, "WONK" 0; }
/* The italic is the romance. It is a real optical italic, not a slant. */
em, .say em, h1 em, h2 em { font-style: italic; font-variation-settings: "opsz" 96, "SOFT" 40, "WONK" 1; }
p  { margin: 0 0 var(--s-4); max-width: var(--measure); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

.wrap { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--s-5); }
.section { padding-block: var(--s-9); }
.section--tight { padding-block: var(--s-8); }
.rule { height: 1px; background: var(--border); border: 0; margin: 0; }
.center { text-align: center; }
.center p { margin-inline: auto; }

/* Accession marks: the letterspaced caps that carry the archive voice. Used for
   eyebrows, plate numbers, cabinet headers and the utility bar. */
.accession {
  font-size: var(--t--2); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.22em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.eyebrow {
  display: inline-flex; align-items: center; gap: var(--s-3);
  font-size: var(--t--2); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.24em;
  color: var(--gold);
  margin: 0 0 var(--s-5);
}
.eyebrow::before {
  content: ""; width: 26px; height: 1px; background: currentColor; flex: none; opacity: .7;
}
.eyebrow--center { justify-content: center; }
.eyebrow--center::after {
  content: ""; width: 26px; height: 1px; background: currentColor; flex: none; opacity: .7;
}

.lede { font-size: var(--t-1); line-height: 1.5; color: var(--ink-soft); }
.fine { font-size: var(--t--1); color: var(--ink-faint); line-height: 1.5; }

/* ------------------------------------------------------------ action pyramid */
/* One primary, solid, in the oxblood. The accent appears nowhere else (P-38, P-20). */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-3);
  min-height: 52px; padding: var(--s-3) var(--s-6);
  font-family: var(--body); font-size: var(--t--1); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.11em;
  border: 1px solid transparent; border-radius: var(--r-sm);
  text-decoration: none; cursor: pointer; text-align: center;
  transition: background-color .2s var(--ease), color .2s var(--ease),
              border-color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
.btn--primary { background: var(--accent); color: var(--on-accent); box-shadow: var(--lift-1); }
.btn--primary:hover { background: var(--accent-deep); box-shadow: var(--lift-2); transform: translateY(-1px); }
.btn--secondary { background: transparent; color: var(--ink); border-color: var(--border-firm); }
.btn--secondary:hover { border-color: var(--ink); background: color-mix(in srgb, var(--paper-deep) 70%, transparent); }
.btn--ghost { background: transparent; color: var(--on-forest); border-color: color-mix(in srgb, var(--on-forest) 34%, transparent); }
.btn--ghost:hover { border-color: var(--on-forest); background: color-mix(in srgb, var(--on-forest) 10%, transparent); }
.btn--light { background: var(--paper); color: var(--ink); }
.btn--light:hover { background: #fff; transform: translateY(-1px); box-shadow: var(--lift-2); }
.btn--wide { width: 100%; }
.btn:focus-visible, a:focus-visible, input:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } .btn:hover { transform: none; } }
/* Visible-but-not-yet-live: the $8 button shows at rest, before a month is
   picked, so it needs a state that reads as "not yet" rather than "broken". */
.btn[aria-disabled="true"] { opacity: .5; box-shadow: none; }
.btn[aria-disabled="true"]:hover { transform: none; box-shadow: none; }
/* .btn is a flex row, so any inline <span> inside it (the month name) became its
   own flex item: the row gap opened a hole either side of the word and the rest
   of the sentence wrapped one fragment per line. The label is now a single flex
   item, so it wraps as ordinary text, balanced across two lines on a phone. */
.btn__label { text-wrap: balance; }
.btn__icon { display: inline-flex; width: 14px; height: 14px; flex: none; overflow: hidden; }
.btn__icon svg { width: 100%; height: 100%; transition: transform .4s var(--ease-out); }
.btn:hover .btn__icon svg { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { .btn__icon svg { transition: none; } }

/* -------------------------------------------------------------- utility bar */
.utility {
  background: var(--forest-deep); color: var(--on-forest);
  font-size: var(--t--2); letter-spacing: 0.16em; text-transform: uppercase; font-weight: 600;
}
.utility .wrap {
  display: flex; align-items: center; justify-content: center; gap: var(--s-3) var(--s-5);
  min-height: 34px; flex-wrap: wrap; text-align: center;
}
.utility span { display: inline-flex; align-items: center; gap: var(--s-3); opacity: .82; }
.utility span + span::before { content: "·"; opacity: .5; }
/* One claim on small screens. Two wrapped onto a second line and orphaned the
   separator dot at the start of it. */
/* On a phone the one claim shown is "digital files, nothing ships": nothing else on the
   first phone screen says the product is a file rather than a framed print. */
.utility .utility__phone { display: none; }
.utility .utility__phone::before { content: none; }
@media (max-width: 700px) {
  .utility span { display: none; }
  .utility .utility__phone { display: inline-flex; opacity: .9; }
}

/* ------------------------------------------------------------------- header */
.site-head {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter: saturate(1.2) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background-color .3s var(--ease);
}
.site-head[data-scrolled] { border-bottom-color: var(--border); background: color-mix(in srgb, var(--paper) 96%, transparent); }
.site-head .wrap { display: flex; align-items: center; justify-content: space-between; gap: var(--s-5); min-height: 74px; }
.wordmark { display: inline-flex; align-items: center; gap: var(--s-3); text-decoration: none; min-height: 44px; }
.wordmark svg { width: 26px; height: 26px; color: var(--accent); flex: none; }
.wordmark b {
  display: block;
  font-family: var(--display); font-weight: 400; font-size: var(--t-1);
  letter-spacing: -0.004em; font-variation-settings: "opsz" 34, "SOFT" 30, "WONK" 1; line-height: 1.05;
}
.wordmark small {
  display: block; font-size: 0.5625rem; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; margin-top: 3px;
}
.site-nav { display: none; gap: var(--s-5); }
.site-nav a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t--2); font-weight: 600; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink-soft); text-decoration: none; white-space: nowrap;
  border-bottom: 1px solid transparent; transition: color .2s var(--ease), border-color .2s var(--ease);
}
.site-nav a:hover { color: var(--ink); border-bottom-color: var(--accent); }
@media (min-width: 1000px) { .site-nav { display: flex; } }
.site-head .btn { min-height: 44px; padding-inline: var(--s-5); white-space: nowrap; }
@media (max-width: 560px) {
  .site-head .wrap { min-height: 64px; gap: var(--s-3); }
  .site-head .btn { padding-inline: var(--s-3); font-size: 0.6875rem; letter-spacing: 0.06em; }
  .site-head .btn .btn__icon { display: none; }
  .cta-price { display: none; }
  .wordmark b { font-size: var(--t-0); }
  .wordmark small { display: none; }
}

/* --------------------------------------------------------------------- hero */
.hero { padding-block: var(--s-9) var(--s-8); }
.hero__grid { display: grid; gap: var(--s-8); align-items: start; }
@media (min-width: 940px) {
  .hero__grid { grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr); gap: var(--s-9); align-items: center; }
}
/* Below the two-column breakpoint the grid stacks, and the copy column is tall
   enough (headline + second headline + lede + two buttons + note) that the
   mounted specimen landed a whole screen below the fold: measured 449px past it
   on a 375x667 phone, 220px on a 390x844, and half-cut on iPad portrait. The
   product was invisible on the first screen of every phone. `display: contents`
   dissolves the copy wrapper on narrow viewports only, so the headline and the
   specimen become siblings in the same grid and the print sits directly under
   the headline where it is the first thing seen. Desktop is untouched: the
   wrapper is a normal grid item again at 940px, so the two-column hero is
   exactly as it was. Row gap goes to zero here because each block already
   carries its own margin-top; without that they would be double-spaced. */
@media (max-width: 939px) {
  .hero { padding-block: var(--s-7) var(--s-8); }
  .hero__grid { row-gap: 0; }
  .hero__text { display: contents; }
  .hero #hero-headline { order: 1; }
  .hero .specimen { order: 2; margin-top: var(--s-7); }
  .hero .lede { order: 3; }
  .hero__actions { order: 4; }
  .hero__note { order: 5; }
}
.hero h1 { max-width: 12ch; }
.hero h1 .say { display: block; }
/* Sized independently of the h1: as `em` it tracked the clamped display size and
   fell BELOW the lede beneath it on mobile, inverting the hierarchy. */
.hero h1 .say--2 {
  font-size: clamp(1.3125rem, 3.4vw, 1.75rem); color: var(--ink-soft);
  margin-top: .7em; letter-spacing: -0.004em; max-width: 30ch; line-height: 1.35;
  font-variation-settings: "opsz" 40, "SOFT" 22, "WONK" 0;
}
.hero .lede { margin-top: var(--s-6); max-width: 46ch; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-7); }
.hero__note { margin-top: var(--s-5); display: flex; align-items: flex-start; gap: var(--s-3); }
.hero__note svg { width: 15px; height: 15px; flex: none; margin-top: 4px; color: var(--gold); }

/* ------------------------------------------------------ the month landing */
/* Rendered by functions/index.js only when the visit names a month (a month pin's
   utm_content, or ?month=). The ad promised one flower, so the first phone screen
   keeps that promise: the month named, its watercolour, the $8 buy for it and the
   free wallpaper, with no scroll and no pick (P-30 message match, P-45 two safe
   steps side by side). Measured target: all of it inside 375x812. On a wide
   screen it takes the ordinary two-column hero shape, the print on the right. */
.hero--month { padding-block: var(--s-5) var(--s-7); }
.hm {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "head head" "art mean" "buy buy" "free free";
  column-gap: var(--s-4); align-items: start;
}
.hm__head { grid-area: head; }
.hm__kicker { margin: 0 0 var(--s-3); color: var(--gold); }
.hero--month h1 {
  max-width: 17ch;
  font-size: clamp(2.125rem, 5.2vw, 3.875rem);
  line-height: 1.04;
}
.hero--month .specimen.hm__art { grid-area: art; margin: var(--s-5) 0 0; padding: var(--s-2); box-shadow: var(--lift-2); }
.hm__art::after { inset: var(--s-1); }
.hm__art .specimen__well { padding: 0; }
/* The tiles carry a wide white margin around the flower. At phone size that
   margin is most of the picture, so the frame crops it and the flower fills the
   mount. The desktop mount below shows the whole sheet, as the June hero does. */
.hm__art .specimen__well img { width: 100%; max-width: 300px; aspect-ratio: 1 / 1.08; object-fit: cover; }
.hm__art .specimen__plate { display: none; }
.hm__meaning { grid-area: mean; margin-top: var(--s-5); }
.hm__means {
  font-family: var(--display); font-size: var(--t-1); line-height: 1.3; color: var(--ink);
  font-variation-settings: "opsz" 40, "SOFT" 22, "WONK" 0; margin-bottom: var(--s-3);
}
.hm__what { font-size: var(--t--1); line-height: 1.5; color: var(--ink-soft); margin: 0; }
.hm__buy { grid-area: buy; margin-top: var(--s-5); }
.hm__buy .risk { margin-top: var(--s-2); max-width: none; }
.hm__free, .hm__done { grid-area: free; margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--border); }
.hm__row, .inline-field { display: flex; gap: var(--s-2); }
.hm__row input, .inline-field input {
  flex: 1 1 auto; min-width: 0; min-height: 52px; padding: var(--s-3) var(--s-4);
  font-family: var(--body); font-size: var(--t-0); color: var(--ink);
  background: var(--paper-deep); border: 1px solid var(--border-firm); border-radius: var(--r-sm);
}
.hm__row input:focus, .inline-field input:focus { background: var(--paper); border-color: var(--ink-faint); }
.hm__row input::placeholder, .inline-field input::placeholder { color: var(--ink-faint); }
.hm__row .btn, .inline-field .btn { flex: none; padding-inline: var(--s-5); }
.hm__done-line { color: var(--ink-soft); margin-bottom: var(--s-4); }
@media (min-width: 940px) {
  .hero--month { padding-block: var(--s-8); }
  .hm {
    grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
    /* The print is taller than the copy. The two 1fr spacer rows take the
       difference, so the copy sits as one centred stack beside it instead of
       being pulled apart row by row. */
    grid-template-rows: 1fr auto auto auto auto 1fr;
    grid-template-areas: ". art" "head art" "mean art" "buy art" "free art" ". art";
    column-gap: var(--s-9);
  }
  .hero--month .specimen.hm__art { margin: 0; padding: var(--s-5); box-shadow: var(--lift-3); align-self: center; }
  .hm__art::after { inset: var(--s-3); }
  .hm__art .specimen__well { padding: var(--s-6) var(--s-5); }
  .hm__art .specimen__well img { aspect-ratio: 880 / 1120; object-fit: contain; }
  .hm__art .specimen__plate { display: flex; }
  .hm__meaning { margin-top: var(--s-6); max-width: 46ch; }
  .hm__buy, .hm__free, .hm__done { max-width: 30rem; }
  .hm__buy { margin-top: var(--s-6); }
}

/* ---------------------------------------------------------- chart landing */
/* A chart pin already answers "what is my birth flower", so this first screen
   sells the chart itself: the sheet exactly as it prints, the $19 buy, and the
   twelve months as one row of names for anyone who came for their own month.
   Same grid idea as the month hero. Measured target: headline, the sheet, the
   buy button and its refund line inside 375x812.

   Always the light palette, dark mode or not. The chart pins are cream; a phone
   in dark mode used to tap a cream chart and land on a near-black page, which
   read as somewhere else (Iris, 2026-09-28). A month opened from this screen
   carries the same attribute, so the tap does not land somewhere darker. */
@media (prefers-color-scheme: dark) {
  html[data-bb-light] {
    color-scheme: light;
    --paper: #F5F1EB; --paper-deep: #EEE9E0; --paper-sink: #E6DFD3; --paper-edge: #D7CEC1;
    --ink: #1C1F1D; --ink-soft: #4A4F4B; --ink-faint: #626763; --stem: #5A605C;
    --forest: #1E211F; --forest-deep: #1A1C1B;
    --accent: #762E3C; --accent-deep: #5E2430; --accent-tint: #F0E4E5;
    --gold: #7E5F28; --gold-soft: #C3A065;
    --border: #DFD7CA; --border-firm: #C9BEAD;
    --on-accent: #FBF8F3; --on-accent-soft: #E3D4D2;
    --on-forest: #EDE8DF; --on-forest-soft: #C0BCB5; --on-forest-faint: #A9A59E;
    --lift-1: 0 1px 1px hsl(30 24% 24% / .07), 0 2px 4px hsl(30 24% 20% / .06);
    --lift-2: 0 1px 1px hsl(30 24% 24% / .10), 0 10px 26px hsl(30 24% 20% / .11);
    --lift-3: 0 2px 3px hsl(30 24% 24% / .13), 0 26px 56px hsl(30 24% 20% / .17);
  }
}
.hero--chart { padding-block: var(--s-5) var(--s-7); }
.hc {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "head" "art" "buy" "months" "what";
  column-gap: var(--s-4); align-items: start;
}
.hc__head { grid-area: head; }
.hero--chart h1 {
  max-width: 16ch;
  font-size: clamp(2rem, 5vw, 3.5rem);
  line-height: 1.04;
}
.hc__free { margin: var(--s-3) 0 0; font-size: var(--t-0); color: var(--ink-soft); }
/* The product has to be readable, not a thumbnail: one column on phones, the
   sheet centred at up to 15rem (Iris, G2). */
.hero--chart .specimen.hc__art {
  grid-area: art; margin: var(--s-5) 0 0; padding: var(--s-2); box-shadow: var(--lift-2);
  width: min(100%, 15rem); justify-self: center;
}
.hc__art::after { inset: var(--s-1); }
.hc__art .specimen__well { padding: 0; }
.hc__art .specimen__well img { width: 100%; max-width: none; height: auto; aspect-ratio: 960 / 1200; }
.hc__what {
  grid-area: what; margin: var(--s-5) 0 0; align-self: center;
  font-size: 1rem; line-height: 1.5; color: var(--ink-soft);
}
.hc__buy { grid-area: buy; margin-top: var(--s-5); }
.hc__buy .risk { margin-top: var(--s-2); max-width: none; font-size: 1rem; }
.hc__months { grid-area: months; margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--border); }
.hc__note { margin: 0 0 var(--s-3); font-size: 1rem; color: var(--ink-soft); }
.hc__row {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s-2);
  list-style: none; margin: 0; padding: 0;
}
.hc__month {
  display: flex; align-items: center; justify-content: center; min-height: 44px;
  font-size: .8125rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); text-decoration: none;
  background: var(--paper); border: 1px solid var(--border-firm); border-radius: var(--r-sm);
  transition: border-color .15s ease, background .15s ease;
}
.hc__month:hover, .hc__month:focus-visible { border-color: var(--gold); background: var(--paper-deep); }
/* One accent, one action: the header's month button steps back to an outline
   here, so the $19 is the only filled wine button on the screen. */
html[data-bb-chart] .site-head .btn--primary {
  background: transparent; color: var(--accent); border: 1px solid var(--accent); box-shadow: none;
}
@media (min-width: 700px) {
  .hc__row { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}
@media (min-width: 940px) {
  .hero--chart { padding-block: var(--s-8); }
  .hc {
    grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
    grid-template-rows: 1fr auto auto auto auto 1fr;
    column-gap: var(--s-9);
  }
  .hero--chart .specimen.hc__art { margin: 0; padding: var(--s-5); box-shadow: var(--lift-3); align-self: center; max-width: 26rem; justify-self: end; width: 100%; }
  .hc { grid-template-areas: ". art" "head art" "buy art" "months art" "what art" ". art"; }
  .hc__art::after { inset: var(--s-3); }
  .hc__what { margin-top: var(--s-5); max-width: 40ch; }
  .hc__buy, .hc__months { max-width: 32rem; }
  .hc__buy { margin-top: var(--s-6); }
  .hc__row { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) { .hc__month { transition: none; } }

/* ------------------------------------------------------- the specimen mount */
/* A print is not a JPEG on a page. It is a sheet, mounted, catalogued, and lit
   from above. The mount is what makes the file feel like an object (P-13). */
.specimen {
  position: relative;
  background: var(--paper);
  border: 1px solid var(--border-firm);
  box-shadow: var(--lift-3);
  padding: var(--s-5);
}
.specimen::after {
  /* the gold hairline inside the mount — an archival frame line */
  content: ""; position: absolute; inset: var(--s-3);
  border: 1px solid color-mix(in srgb, var(--gold) 34%, transparent);
  pointer-events: none;
}
.specimen__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
  padding-bottom: var(--s-3); margin-bottom: var(--s-5);
  border-bottom: 1px solid var(--border);
}
.specimen__well {
  background: var(--paper-sink);
  padding: var(--s-6) var(--s-5);
  display: flex; align-items: center; justify-content: center;
}
.specimen__well img { width: 100%; max-width: 300px; }
.specimen__plate {
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s-4);
  margin-top: var(--s-5); padding-top: var(--s-4);
  border-top: 1px solid var(--border);
}
.specimen__plate h3 { font-size: var(--t-2); margin: 0; }
.specimen__plate p { margin: 4px 0 0; font-size: var(--t--1); color: var(--ink-faint); font-style: italic; }
.seal {
  position: absolute; right: calc(var(--s-5) * -1); bottom: var(--s-7);
  width: 74px; height: 74px; border-radius: 50%;
  display: grid; place-items: center; text-align: center;
  background: var(--accent); color: var(--on-accent);
  font-size: 0.5rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  line-height: 1.35; box-shadow: var(--lift-2);
}
@media (max-width: 560px) {
  .specimen { padding: var(--s-4); }
  .seal {
    width: 58px; height: 58px; font-size: 0.4375rem;
    right: -14px; bottom: -18px;
  }
}

/* ---------------------------------------------------------------- wall label */
/* One line stating what the object is, the way a museum label does. Replaces a
   four-card grid with decorative 01–04 numbering: four parallel facts are not a
   sequence, and cards were the lazy container for them. */
.wall-label { border-block: 1px solid var(--border); background: var(--paper-deep); }
.wall-label p {
  margin: 0; max-width: none; text-align: center;
  padding-block: var(--s-5);
  font-size: var(--t--1); color: var(--ink-soft);
  letter-spacing: 0.02em;
}
.wall-label b {
  font-family: var(--display); font-weight: 400; font-size: var(--t-1);
  color: var(--ink); font-variant-numeric: tabular-nums;
  font-variation-settings: "opsz" 30, "WONK" 1;
}
.wall-label span { color: var(--gold); padding-inline: var(--s-2); }
@media (max-width: 700px) { .wall-label p { line-height: 2; padding-inline: var(--s-2); } }

/* ------------------------------------------------------------ the marquee */
.marquee { overflow: hidden; padding-block: var(--s-8); background: var(--paper-deep); border-block: 1px solid var(--border); }
.marquee__mask {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee__track { display: flex; width: max-content; animation: bb-marquee var(--marquee-duration) linear infinite; }
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__set { display: flex; gap: var(--s-6); flex: none; padding-right: var(--s-6); }
.marquee__set img {
  width: 244px; height: auto; flex: none;
  background: var(--paper); padding: var(--s-3);
  border: 1px solid var(--border-firm); box-shadow: var(--lift-1);
}
@media (max-width: 700px) { .marquee__set img { width: 172px; } }
@keyframes bb-marquee { to { transform: translateX(-33.3333%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  .marquee__mask { -webkit-mask-image: none; mask-image: none; }
  .marquee { overflow-x: auto; }
}

/* --------------------------------------------------------- the cabinet grid */
/* #twelve-list is filled by quiz.js with .bloom-row items. It is styled here as
   a specimen cabinet: twelve drawers, each with its mark, month and meaning. */
.cabinet { border: 1px solid var(--border-firm); background: var(--paper); box-shadow: var(--lift-2); }
.cabinet__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  background: var(--forest); color: var(--on-forest);
}
.cabinet__head .accession { color: var(--on-forest-faint); }
.bloom-list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 640px) { .bloom-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 960px) { .bloom-list { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.bloom-row {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--s-2);
  padding: var(--s-5) var(--s-3);
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
  transition: background-color .3s var(--ease), transform .3s var(--ease);
}
.bloom-row:hover { background: var(--paper-deep); }
.bloom-mark {
  width: 52px; height: 52px; background-color: var(--ink-faint);
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  opacity: .8; transition: opacity .3s var(--ease), transform .45s var(--ease-out), background-color .3s var(--ease);
}
.bloom-row:hover .bloom-mark { opacity: 1; background-color: var(--accent); transform: scale(1.09) translateY(-2px); }
.bloom-month {
  font-family: var(--display); font-weight: 400; font-size: var(--t-1);
  font-variation-settings: "opsz" 30, "SOFT" 24, "WONK" 1;
}
.bloom-what { font-size: var(--t--2); color: var(--ink-faint); line-height: 1.45; }
.bloom-what strong { display: block; color: var(--ink); font-weight: 600; font-size: var(--t--1); letter-spacing: 0.02em; }
.bloom-what em { display: block; font-style: italic; opacity: .8; margin-top: 2px; }

/* ------------------------------------------------------- the specimen panel */
/* Houses the quiz. Left: the catalogue copy. Right: the picker and the form. */
.panel { border: 1px solid var(--border-firm); background: var(--paper); box-shadow: var(--lift-2); overflow: hidden; }
/* One explicit shrinkable column: an implicit auto column grew to its widest child and overflowed the panel on phones. */
.panel__grid { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .panel__grid { grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr); } }
.panel__aside {
  padding: var(--s-8) var(--s-6);
  background: var(--paper-deep);
  border-bottom: 1px solid var(--border);
}
@media (min-width: 900px) { .panel__aside { border-bottom: 0; border-right: 1px solid var(--border); } }
.panel__aside h2 { font-size: var(--t-3); margin-bottom: var(--s-4); }
.panel__body { padding: var(--s-8) var(--s-6); }
@media (max-width: 560px) { .panel__aside, .panel__body { padding: var(--s-6) var(--s-5); } }
.panel__art { margin-top: var(--s-6); background: var(--paper-sink); padding: var(--s-5); text-align: center; }
.panel__art img { width: 100%; max-width: 220px; margin-inline: auto; }
.panel__art-cap { margin: var(--s-4) 0 0; }
/* Was --ink-faint on the sink ground: 4.36:1, under AA. Measured by npm run audit. */
.panel__art-cap .accession { color: var(--ink-soft); }
.panel__art-cap strong {
  display: block; font-family: var(--display); font-weight: 400; font-size: var(--t-1);
  padding-bottom: var(--s-3); margin-bottom: var(--s-3);
  border-bottom: 1px solid color-mix(in srgb, var(--gold) 40%, transparent);
}

/* --------------------------------------------------------------------- quiz */
.quiz { margin: 0; }
.quiz h2 { font-size: var(--t-2); margin-bottom: var(--s-2); }
.quiz__sub { margin-top: 0; color: var(--ink-faint); font-size: var(--t--1); }
.months {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2);
  margin-top: var(--s-5); list-style: none; padding: 0;
}
@media (min-width: 560px) { .months { grid-template-columns: repeat(6, 1fr); } }
.month-btn {
  width: 100%; min-height: 52px; padding: var(--s-2) var(--s-1);
  font-family: var(--body); font-size: var(--t--2); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-soft);
  background: var(--paper); border: 1px solid var(--border-firm); border-radius: var(--r-sm);
  cursor: pointer; transition: border-color .18s var(--ease), background-color .18s var(--ease),
                               color .18s var(--ease), transform .18s var(--ease);
}
.month-btn:hover { border-color: var(--ink-faint); color: var(--ink); transform: translateY(-1px); }
.month-btn[aria-pressed="true"] {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
  box-shadow: var(--lift-1); transform: none;
}
@media (prefers-reduced-motion: reduce) { .month-btn { transition: none; } .month-btn:hover { transform: none; } }

.quiz__step2[hidden], .quiz__done[hidden] { display: none; }
.quiz__step2 { margin-top: var(--s-6); border-top: 1px solid var(--border); padding-top: var(--s-6); }
#reveal {
  font-family: var(--display); font-size: var(--t-1); color: var(--ink);
  font-variation-settings: "opsz" 34, "SOFT" 24, "WONK" 1;
  padding-top: var(--s-4); border-top: 1px solid var(--gold);
}
.field { margin-bottom: var(--s-4); }
.field label {
  display: block; font-size: var(--t--2); font-weight: 700; margin-bottom: var(--s-2);
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-soft);
}
.field .hint { font-weight: 500; color: var(--ink-faint); letter-spacing: 0.06em; text-transform: none; }
.field input {
  width: 100%; min-height: 52px; padding: var(--s-3) var(--s-4);
  font-family: var(--body); font-size: var(--t-0); color: var(--ink);
  background: var(--paper-deep); border: 1px solid var(--border-firm); border-radius: var(--r-sm);
  transition: border-color .18s var(--ease), background-color .18s var(--ease);
}
.field input:focus { background: var(--paper); border-color: var(--ink-faint); }
.field input::placeholder { color: var(--ink-faint); }
.field-row { display: grid; gap: var(--s-4); }
@media (min-width: 620px) { .field-row { grid-template-columns: 1fr 1fr; } }
.risk { margin-top: var(--s-4); font-size: var(--t--1); color: var(--ink-faint); }
/* After a pick: that month's art and what the pack holds, directly above its $8
   button, then the trust line, then one open email field for the free wallpaper.
   All of it sits where the thumb already is after tapping a month. */
.pick[hidden] { display: none; }
.pick {
  display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: var(--s-4); align-items: center;
  margin-bottom: var(--s-4); padding: var(--s-3); background: var(--paper-sink);
  border: 1px solid var(--border);
}
.pick__art { width: 96px; aspect-ratio: 1 / 1.08; object-fit: cover; background: var(--paper); }
.pick__title { font-family: var(--display); font-size: var(--t-1); line-height: 1.2; color: var(--ink); margin: 0 0 var(--s-2); }
.pick__strip { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-2); list-style: none; margin: 0; padding: 0; }
.pick__strip li {
  font-size: var(--t--2); font-weight: 600; letter-spacing: 0.06em; color: var(--ink-soft);
  padding: 2px var(--s-2); border: 1px solid var(--border-firm); border-radius: var(--r-sm);
}
.pick__count { margin: var(--s-2) 0 0; font-size: var(--t--1); color: var(--ink-soft); }
@media (max-width: 420px) {
  .pick { grid-template-columns: 76px minmax(0, 1fr); gap: var(--s-3); }
  .pick__art { width: 76px; }
}
.quiz__step2 > .risk { margin-top: var(--s-2); }
.quiz__email { margin-top: var(--s-6); padding-top: var(--s-5); border-top: 1px solid var(--border); }
.quiz__email label, .hm__free label {
  display: block; font-size: var(--t--2); font-weight: 700; margin-bottom: var(--s-2);
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-soft);
}
.quiz__email .risk { margin-top: var(--s-2); }
#reveal.is-prompt { color: var(--accent); }
/* The launch-price note. Deliberately quiet: the deadline is real and the server
   enforces it, so it does not need to shout. Shouting is what fake urgency looks like. */
.launch { margin-top: var(--s-3); font-size: var(--t--1); color: var(--ink-soft); font-weight: 600; }
.quiz__done h3 { margin-bottom: var(--s-3); }
.quiz__done ul { margin: var(--s-5) 0 0; padding-left: 1.1em; color: var(--ink-soft); font-size: var(--t--1); }
.quiz__done li { margin-bottom: var(--s-2); }
.err { color: var(--accent); font-size: var(--t--1); margin-top: var(--s-3); font-weight: 600; }

/* ----------------------------------------------------------------- features */
.feature { display: grid; gap: var(--s-7); align-items: center; padding-block: var(--s-9); }
.feature + .feature { border-top: 1px solid var(--border); }
@media (min-width: 880px) {
  .feature { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-10); }
  .feature--flip .feature__media { order: -1; }
}
.feature h3 { margin-bottom: var(--s-5); }
.feature__media { background: var(--paper-deep); padding: var(--s-7); border: 1px solid var(--border); }
.feature__media img { box-shadow: var(--lift-2); margin-inline: auto; }
.feature__media--plain { background: transparent; border: 0; padding: 0; }
.feature__media--plain img { box-shadow: none; }

/* --------------------------------------------------------------- deep bands */
/* The two near-neutral deep grounds. They read as ink-green only because of the
   cream around them, which is why they stay under the audit's chroma threshold. */
.band { background: var(--forest); color: var(--on-forest); padding-block: var(--s-10); }
.band h2, .band h3 { color: var(--on-forest); }
.band .eyebrow { color: var(--gold-soft); }
.band .lede, .band p { color: var(--on-forest-soft); }
.band .accession { color: var(--on-forest-faint); }
.band .rule { background: #3A3E3B; }
.band em { color: var(--gold-soft); }

/* The showcase: the drawing at full scale, on the deep ground it was made for. */
.showcase { background: var(--forest); color: var(--on-forest); padding-block: var(--s-10); }
.showcase__inner { display: flex; flex-direction: column; align-items: center; text-align: center; }
.showcase__art { width: min(560px, 78vw); height: auto; }
.showcase__frame {
  padding: var(--s-6);
  border: 1px solid color-mix(in srgb, var(--gold-soft) 42%, transparent);
  background: color-mix(in srgb, #000 16%, transparent);
}
.showcase__copy { max-width: 56ch; margin-top: var(--s-7); }
.showcase__copy h3 { margin-bottom: var(--s-4); color: var(--on-forest); }
.showcase__copy p { margin-inline: auto; color: var(--on-forest-soft); }
.showcase .eyebrow { color: var(--gold-soft); }

/* -------------------------------------------------------- scroll-open frame */
/* The mount opens from 64% to full width as it enters view. The wrapper carries
   the FINAL aspect ratio so the mount's height never changes while the width
   animates: without it the image height tracks the width, and every frame of the
   animation reflows the whole page below. Width is still a layout property, but
   it is now contained to one fixed-size box rather than the document. */
.expand {
  display: flex; justify-content: center;
  aspect-ratio: 1600 / 1244;
  contain: layout;
}
.expand__frame {
  position: relative; width: 64%; height: 100%; overflow: hidden;
  background: var(--paper);
  /* 18.4px, not 24px, on the block axis. The mount's aspect ratio is the plate's,
     but padding does not scale with it: equal padding all round leaves the inner
     box wider than the plate, which is what made `cover` slice the bottom row's
     captions off. 25 / (1600/1244) - 1 = 18.44 is the block padding that keeps
     the inner box on the plate's exact ratio, given the 1px border and 24px
     inline padding. Change any of those three and redo the arithmetic. */
  padding: 18.4px var(--s-5);
  border: 1px solid var(--border-firm); box-shadow: var(--lift-3);
  transition: width .95s var(--ease-out);
}
.expand__frame[data-expanded] { width: 100%; }
/* Cover, so the plate fills the mount and crops at the sides while the frame
   opens. Once settled the padded box is on the plate's exact ratio (see the
   padding note above), so cover crops nothing at all. `bottom` is the safety
   net: it pins the plate's bottom edge, so if that arithmetic is ever broken
   again the crop eats the 31px of white margin at the TOP instead of slicing
   through the SEPTEMBER..DECEMBER captions, which sit 31px above the bottom. */
.expand__frame img { width: 100%; height: 100%; object-fit: cover; object-position: center bottom; }
.tag {
  position: absolute; left: var(--s-7); bottom: var(--s-7);
  display: inline-flex; align-items: center;
  padding: 7px 14px; border-radius: var(--r-sm);
  background: var(--forest); color: var(--on-forest);
  font-size: var(--t--2); font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  opacity: 0; transform: translateY(10px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out);
}
.expand__frame[data-expanded] .tag { opacity: 1; transform: none; }
/* Top-left, not bottom-left: at the bottom the pill sat exactly on top of the
   SEPTEMBER caption and hid it, which reads as another missing label. The
   plate's top-left corner is whitespace in the January cell. */
.expand__frame .tag { top: var(--s-7); bottom: auto; }
/* On a phone the plate is small enough that the pill covers two of the twelve
   flowers wherever it sits, and the heading directly above already says "the
   complete year". Drop it rather than let it cover the product. */
@media (max-width: 700px) { .expand__frame .tag { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .expand__frame { width: 100%; transition: none; }
  .tag { opacity: 1; transform: none; transition: none; }
}
.tag--static { opacity: 1; transform: none; }
.shot { position: relative; margin: 0; }
.shot .tag--static { position: absolute; left: var(--s-4); bottom: var(--s-4); }

/* ------------------------------------------------------------------ the buy */
.buy { background: var(--paper-deep); border-block: 1px solid var(--border); }
.buy__card {
  background: var(--paper); border: 1px solid var(--border-firm);
  padding: var(--s-9) var(--s-8); box-shadow: var(--lift-3);
  position: relative;
}
.buy__card::after {
  content: ""; position: absolute; inset: var(--s-4);
  border: 1px solid color-mix(in srgb, var(--gold) 26%, transparent); pointer-events: none;
}
@media (max-width: 700px) { .buy__card { padding: var(--s-7) var(--s-5); } }
.buy__grid { display: grid; gap: var(--s-8); position: relative; z-index: 1; }
@media (min-width: 880px) { .buy__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-10); align-items: center; } }
.price {
  display: inline-block; font-family: var(--display); font-weight: 300;
  font-size: var(--t-5); line-height: .92; margin-top: var(--s-3);
  font-variation-settings: "opsz" 140, "SOFT" 30, "WONK" 1;
  font-variant-numeric: tabular-nums; color: var(--accent);
}
.manifest { list-style: none; margin: 0; padding: 0; }
.manifest li {
  display: grid; grid-template-columns: 2.6em 1fr; gap: var(--s-4);
  padding-block: var(--s-4); border-top: 1px solid var(--border); font-size: var(--t--1);
}
.manifest li:first-child { border-top: 0; }
.manifest li b {
  font-family: var(--display); font-weight: 400; font-size: var(--t-1);
  color: var(--gold); font-variant-numeric: tabular-nums;
}
.manifest li span { color: var(--ink-soft); }

/* -------------------------------------------------------------- paper chips */
.chips { display: flex; flex-wrap: wrap; gap: var(--s-3); list-style: none; margin: var(--s-6) 0 0; padding: 0; }
.chip {
  display: inline-flex; flex-direction: column; gap: 2px;
  padding: var(--s-3) var(--s-5); min-width: 96px;
  border: 1px solid var(--border-firm); background: var(--paper);
  font-size: var(--t--2); color: var(--ink-faint);
  text-transform: uppercase; letter-spacing: 0.12em; font-weight: 600;
}
.chip b {
  font-family: var(--display); font-size: var(--t-1); color: var(--ink);
  letter-spacing: 0; text-transform: none; font-weight: 400; font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- the note card */
.card-note {
  background: var(--paper-deep); border: 1px solid var(--border-firm);
  padding: var(--s-6); box-shadow: var(--lift-1);
}
.card-note h3 { font-size: var(--t-1); margin-bottom: var(--s-4); }
.card-note dl { margin: 0; display: grid; gap: var(--s-3); }
.card-note dt {
  font-size: var(--t--2); font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-faint);
}
.card-note dd { margin: 2px 0 0; font-size: var(--t--1); color: var(--ink-soft); }
.card-note dd + dt { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--border); }

/* ---------------------------------------------------------------------- faq */
.faq__grid { display: grid; gap: var(--s-7); align-items: start; }
@media (min-width: 900px) { .faq__grid { grid-template-columns: minmax(0, .68fr) minmax(0, 1.32fr); gap: var(--s-10); } }
@supports (interpolate-size: allow-keywords) { :root { interpolate-size: allow-keywords; } }
.faq details {
  border-bottom: 1px solid var(--border);
  background: transparent; padding: 0;
  transition: border-color .3s var(--ease);
}
.faq details:first-of-type { border-top: 1px solid var(--border); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-5);
  padding: var(--s-5) 0; min-height: 44px;
  font-weight: 600; font-size: var(--t-0); cursor: pointer; list-style: none;
  transition: color .2s var(--ease);
}
.faq summary:hover { color: var(--accent); }
.faq summary::-webkit-details-marker, .faq summary::marker { display: none; content: ""; }
.faq summary::after { content: none; }
.faq .plus { position: relative; width: 14px; height: 14px; flex: none; color: var(--gold); }
.faq .plus::before, .faq .plus::after {
  content: ""; position: absolute; inset: 50% 0 auto 0;
  height: 1.5px; background: currentColor; border-radius: 2px;
  transition: transform .38s var(--ease-out), opacity .38s var(--ease-out);
}
.faq .plus::after { transform: rotate(90deg); }
.faq details[open] .plus::after { transform: rotate(0deg); opacity: 0; }
.faq details p { margin: 0; padding: 0 var(--s-8) var(--s-5) 0; color: var(--ink-soft); }
.faq details::details-content {
  block-size: 0; overflow: hidden;
  transition: block-size .4s var(--ease-out), content-visibility .4s allow-discrete;
}
.faq details[open]::details-content { block-size: auto; }
@media (prefers-reduced-motion: reduce) {
  .faq details::details-content { transition: none; }
  .faq .plus::before, .faq .plus::after { transition: none; }
}

/* ------------------------------------------------------------- closing band */
/* Fixed values, not the accent token. In dark mode the accent inverts to a light
   rose so buttons stay legible — correct for a 52px pill, wrong for a full-bleed
   band, which then reads as a different brand. The band stays oxblood in both. */
.closer { background: #762E3C; color: #FBF8F3; padding-block: var(--s-10); text-align: center; }
.closer h2 { color: #FBF8F3; max-width: 18ch; margin-inline: auto; }
.closer p { color: #E3D4D2; margin-inline: auto; margin-top: var(--s-5); max-width: 48ch; }
.closer .eyebrow { color: #E3D4D2; }
.closer .btn { margin-top: var(--s-7); }
.closer .btn--light { background: #FBF8F3; color: #762E3C; }
.closer .btn--light:hover { background: #FFFFFF; }

/* ------------------------------------------------------------------- footer */
.site-foot { background: var(--forest-deep); color: var(--on-forest); padding-block: var(--s-9) var(--s-7); }
.site-foot .wordmark svg { color: var(--gold-soft); }
.site-foot .wordmark b { color: var(--on-forest); }
.site-foot .wordmark small { color: var(--on-forest-faint); }
.foot-grid { display: grid; gap: var(--s-7); }
@media (min-width: 820px) { .foot-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--s-8); } }
.foot-col h3 {
  font-family: var(--body); font-size: var(--t--2); font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--on-forest-faint); margin-bottom: var(--s-4);
}
.foot-col nav { display: flex; flex-direction: column; }
.site-foot a {
  color: var(--on-forest-soft);
  text-decoration: none; font-size: var(--t--1);
}
.site-foot a:hover { color: var(--on-forest); text-decoration: underline; }
/* The legacy sub-page footers use `.site-foot nav a`; both must clear the floor. */
.foot-col nav a,
.site-foot nav a { display: inline-flex; align-items: center; min-height: 44px; }
.site-foot .fine { color: var(--on-forest-faint); }
.foot-base {
  display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center; justify-content: space-between;
  margin-top: var(--s-8); padding-top: var(--s-5);
  border-top: 1px solid #333734;
}

/* --------------------------------------------------------------- sticky CTA */
.sticky-cta {
  position: fixed; inset: auto 0 0 0; z-index: 30;
  padding: var(--s-3) var(--s-4) calc(var(--s-3) + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--paper) 95%, transparent);
  border-top: 1px solid var(--border-firm); backdrop-filter: blur(10px);
  display: none;
}
.sticky-cta[data-show] { display: block; }
.sticky-cta__trust[hidden] { display: none; }
.sticky-cta__trust { margin: var(--s-1) 0 0; text-align: center; font-size: var(--t--2); color: var(--ink-soft); max-width: none; }
@media (min-width: 880px) { .sticky-cta { display: none !important; } }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- the grain */
/* Felt, not seen. Cotton rag is not a flat rectangle (P-25 ext). */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: .05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: dark) { body::before { opacity: .06; } }
body > * { position: relative; z-index: 1; }

/* ---------------------------------------------------------------- the motion */
/* Scoped to .js — set by an inline script in <head>. Without JS the content is
   simply visible, rather than hidden forever by a transition that never runs. */
.js [data-reveal] {
  opacity: 0; transform: translateY(24px);
  transition: opacity .9s var(--ease-out) var(--d, 0ms), transform .9s var(--ease-out) var(--d, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
}

.section-head { max-width: 64ch; }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center p { margin-inline: auto; }
