/* ─────────────────────────────────────────────────────────────────────────
   Verboom newsletter — site styles
   Everything resolves to the design system tokens in ds/tokens/. Colour and
   size literals appear only where a token genuinely does not exist.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  /* On a Forest ground the system's frosted glass inverts: paper at a very low
     alpha instead of paper at 0.8. */
  --glass-on-forest: rgba(255, 253, 240, 0.07);
  --glass-on-forest-strong: rgba(255, 253, 240, 0.11);
  /* One step above the system's `--border-on-forest-strong` (0.3), which
     composites to 2.25:1 over the glass card — under the 3:1 floor a control
     boundary has to meet. At 0.45 it clears it. Only for edges that a reader
     needs in order to find a control; decorative rules stay on the token. */
  --border-on-forest-loud: rgba(255, 253, 240, 0.45);
}

body { min-width: 320px; }

.shell {
  width: min(var(--container-max), calc(100% - 128px));
  margin: 0 auto;
}
@media (max-width: 900px) { .shell { width: calc(100% - 48px); } }
@media (max-width: 480px) { .shell { width: calc(100% - 32px); } }

.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;
}

:where(a, button, input, summary):focus-visible {
  outline: 2px solid var(--color-secondary);
  outline-offset: 3px;
}
/* Terracotta is the interaction colour, but on the Forest ground it is only
   2.43:1 — under the 3:1 floor a focus indicator has to clear. Inside the
   opening the ring switches to paper (8.9:1); everywhere else it stays Terra. */
.hero :where(a, button, input, summary):focus-visible {
  outline-color: var(--on-forest);
}

/* ── Type helpers ───────────────────────────────────────────────────────── */
.display {
  margin: 0;
  font-family: var(--font-serif);
  font-size: clamp(var(--type-display-hero-mobile-size), 9vw, var(--type-display-hero-size));
  font-weight: var(--type-display-hero-weight);
  line-height: var(--type-display-hero-line);
  letter-spacing: var(--type-display-hero-track);
  text-wrap: balance;
}
.headline {
  margin: 0;
  font-family: var(--font-serif);
  font-size: clamp(var(--type-headline-lg-mobile-size), 4vw, var(--type-headline-lg-size));
  font-weight: 400;
  line-height: var(--type-headline-lg-line);
  text-wrap: balance;
}
.title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--type-headline-sm-size);
  font-weight: 400;
  line-height: var(--type-headline-sm-line);
}
.lede {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--type-serif-body-size);
  line-height: var(--type-serif-body-line);
  color: var(--text-variant);
  max-width: 44ch;
  text-wrap: balance;
}
.seclabel {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-label-size);
  font-weight: var(--type-label-weight);
  line-height: var(--type-label-line);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--text-primary);
}
.seclabel i {
  flex: 0 0 auto;
  width: 32px; height: 1px;
  background: currentColor;
  opacity: 0.5;
}

/* ── Controls ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: var(--type-label-size);
  font-weight: var(--type-label-weight);
  line-height: var(--type-label-line);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  padding: 12px 24px;
  border: var(--border-structural);
  border-radius: var(--radius);
  background: var(--color-secondary);
  /* The border keeps the system's 2px structure but takes the fill's colour:
     an ink ring around a terracotta button reads as two competing edges. */
  border-color: var(--color-secondary);
  color: var(--color-on-secondary);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-base), color var(--dur-base), border-color var(--dur-base);
}
.btn:hover { background: var(--terra-deep); border-color: var(--terra-deep); }
.btn--sm { padding: 8px 16px; }
.btn[disabled] { opacity: 0.4; cursor: not-allowed; }

/* The strongest control in the system — once per screen. */
.btn-split {
  display: inline-flex;
  align-items: stretch;
  border: var(--border-structural);
  border-radius: var(--radius);
  background: var(--paper);
  text-decoration: none;
  overflow: hidden;
  cursor: pointer;
  padding: 0;
  font: inherit;
}
.btn-split__label {
  display: flex;
  align-items: center;
  height: 48px;
  padding: 0 24px;
  font-family: var(--font-sans);
  font-size: var(--type-label-size);
  font-weight: var(--type-label-weight);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--text-primary);
  white-space: nowrap;
}
.btn-split__glyph {
  width: 48px;
  display: grid;
  place-items: center;
  border-left: var(--border-structural);
  background: var(--color-secondary);
  color: var(--color-on-secondary);
  transition: background var(--dur-base);
}
.btn-split:hover .btn-split__glyph { background: var(--terra-deep); }
.btn-split[disabled] { opacity: 0.4; cursor: not-allowed; }
.btn-split svg { width: 20px; height: 20px; }

.btn-ghost {
  background: transparent;
  border: none;
  border-bottom: 2px solid var(--border-ink);
  border-radius: 0;
  padding: 0 0 6px;
  font-family: var(--font-sans);
  font-size: var(--type-label-size);
  font-weight: var(--type-label-weight);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--text-primary);
  cursor: pointer;
  text-decoration: none;
  transition: color var(--dur-fast), border-color var(--dur-fast);
}
.btn-ghost:hover { color: var(--color-secondary); border-bottom-color: var(--color-secondary); }

/* ── Masthead: paper, over the Forest opening ───────────────────────────── */
.masthead {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--surface-page);
  border-bottom: var(--border-structural);
}
.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-stack-sm);
  height: var(--nav-height);
}
.wordmark {
  font-family: var(--font-serif);
  font-size: var(--type-headline-sm-size);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--text-primary);
  text-decoration: none;
}
.wordmark i { font-style: normal; color: var(--color-secondary); }

.masthead__links { display: flex; align-items: center; gap: var(--space-gutter); }
.masthead__links a,
.masthead__links summary {
  position: relative;
  padding-bottom: 4px;
  font-size: var(--type-body-size);
  color: var(--text-variant);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--dur-base);
}
/* The underline wipes in from the left on a transform, not on width: the same
   movement without asking the browser to re-lay-out the nav on every frame. */
.masthead__links a::after {
  content: "";
  position: absolute; left: 0; bottom: -2px;
  width: 100%; height: 2px;
  background: var(--color-secondary);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 250ms var(--ease-editorial);
}
.masthead__links a:hover { color: var(--color-secondary); }
.masthead__links a:hover::after { transform: scaleX(1); }

/* The "Take a look inside" disclosure */
.inside { position: relative; }
.inside > summary { list-style: none; display: inline-flex; align-items: center; gap: 8px; }
.inside > summary::-webkit-details-marker { display: none; }
.inside > summary svg { width: 14px; height: 14px; transition: transform 180ms var(--ease-editorial); }
.inside[open] > summary { color: var(--color-secondary); }
.inside[open] > summary svg { transform: rotate(180deg); }
.inside__panel {
  position: absolute;
  top: calc(100% + 18px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  width: 440px;
  padding: 8px;
  background: var(--surface-page);
  border: var(--border-structural);
  border-radius: var(--radius-lg);
}
.inside__panel a {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--radius);
  color: var(--text-primary);
  transition: background var(--dur-base);
}
.inside__panel a::after { content: none; }
.inside__panel a:hover { background: var(--surface-container); color: var(--color-secondary); }
.inside__panel strong { display: block; font-family: var(--font-serif); font-size: var(--type-headline-xs-size); font-weight: 400; }
.inside__panel span { display: block; font-size: var(--type-body-sm-size); color: var(--text-variant); }
.inside__panel hr { margin: 8px 16px; border: none; border-top: 1px solid var(--border-divider); }
.inside__panel svg { width: 18px; height: 18px; }

@media (max-width: 1000px) { .masthead__links { display: none; } }

/* ── Hero: the page's one Forest ground ─────────────────────────────────── */
/* The opening holds the screen. A hero that ends well above the fold reads as a
   header, not as a first viewport. */
.hero {
  position: relative;
  display: grid;
  align-content: center;
  min-height: calc(100svh - var(--nav-height));
  background-color: var(--surface-forest);
  background-image: var(--texture-dots);
  background-size: var(--texture-dots-size);
  color: var(--on-forest);
  padding: 96px 0 132px;
  overflow: hidden;
}
.hero__inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-stack-sm);
}
/* Two lines, so the statement claims width instead of sitting in the middle of
   an empty measure. */
.hero .display { max-width: 7ch; }
.hero .lede { color: var(--on-forest-muted); max-width: 42ch; }

/* The weather: the marks a reader already knows, held at arm's length. */
.weather { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.weather span {
  position: absolute;
  display: grid;
  place-items: center;
  width: 84px; height: 84px;
  padding: 16px;
  background: var(--glass-on-forest);
  border: 1px solid var(--border-on-forest);
  border-radius: var(--radius-lg);
}
.weather img {
  width: 100%; height: 100%;
  object-fit: contain;
  filter: grayscale(1) brightness(0) invert(1);
  opacity: 0.34;
}
/* Neighbouring marks must never travel in step. */
.f3 { animation: verboom-float 3s ease-in-out infinite; }
.f4 { animation: verboom-float 4s ease-in-out infinite; }
.f5 { animation: verboom-float 5s ease-in-out infinite; }
.f6 { animation: verboom-float 6s ease-in-out infinite; }

.w1  { left: 3%;  top: 8%; }
.w2  { left: 12%; top: 34%; }
.w3  { left: 5%;  top: 62%; }
.w4  { left: 19%; top: 80%; }
/* w5 and w10 sit inside the display type's band, so they only appear once the
   viewport is wide enough for the statement to clear them. */
.w5  { left: 27%; top: 12%; }
.w6  { right: 4%;  top: 10%; }
.w7  { right: 13%; top: 38%; }
.w8  { right: 6%;  top: 66%; }
.w9  { right: 20%; top: 82%; }
.w10 { right: 28%; top: 14%; }

/* ── Signup: email first, on glass, inside the hero ─────────────────────── */
.signupcard {
  width: min(30rem, 100%);
  margin-top: 8px;
  padding: var(--space-stack-sm);
  text-align: left;
  background: var(--glass-on-forest-strong);
  -webkit-backdrop-filter: blur(10px) saturate(0.4);
  backdrop-filter: blur(10px) saturate(0.4);
  border: 1px solid var(--border-on-forest);
  border-radius: var(--radius-lg);
}
.signup { display: flex; flex-direction: column; gap: var(--space-stack-sm); align-items: stretch; }
/* `.signup` sets display, which beats the user-agent [hidden] rule — without
   this the success state leaves a blank, reset form stacked above it. */
.signup[hidden] { display: none; }

/* On the Forest ground the split button loses its paper body: the label sits
   on the ground itself and only the glyph carries terracotta. */
.signupcard .btn-split {
  align-self: center;
  background: transparent;
  border-color: var(--on-forest);
}
.signupcard .btn-split__label { color: var(--on-forest); }
.signupcard .btn-split__glyph { border-left-color: var(--on-forest); }

.field { display: flex; flex-direction: column; gap: 8px; }
.field__label {
  font-family: var(--font-sans);
  font-size: var(--type-label-size);
  font-weight: var(--type-label-weight);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--on-forest);
}
.field__input {
  width: 100%;
  background: transparent;
  border: none;
  /* Raised from 0.3 alpha: at 0.3 the field's only edge sat at 2.25:1 against
     the card, under the 3:1 floor for a control boundary. */
  border-bottom: 2px solid var(--border-on-forest-loud);
  border-radius: 0;
  padding: 12px 0;
  font-family: var(--font-sans);
  font-size: var(--type-body-size);
  line-height: var(--type-body-line);
  letter-spacing: var(--type-body-track);
  color: var(--on-forest);
  transition: border-color var(--dur-base);
}
.field__input::placeholder { color: var(--on-forest-muted); }
/* A hue shift at identical lightness is not a focus indicator: terracotta and
   the resting border differ by 1.08:1. The ring carries the state; the
   terracotta underline stays as the secondary, brand-coloured cue. */
.field__input:focus-visible {
  outline: 2px solid var(--on-forest);
  outline-offset: 3px;
}
.field__input:focus { border-bottom-color: var(--color-secondary); }

.signup__honeypot { position: absolute; left: -9999px; }

.signup__details { display: flex; flex-direction: column; gap: 14px; }
.signup__details[hidden] { display: none; }

.lens { margin: 0; padding: 0; border: none; }
.lens legend {
  padding: 0 0 10px;
  font-family: var(--font-sans);
  font-size: var(--type-label-size);
  font-weight: var(--type-label-weight);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--on-forest);
}
/* One connected segmented control, still a real radio group underneath. */
.lens__options {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--border-on-forest-loud);
  border-radius: var(--radius);
  overflow: hidden;
}
.lens__option { position: relative; display: block; }
.lens__option input {
  position: absolute;
  opacity: 0;
  inset: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.lens__option span {
  display: grid;
  place-items: center;
  min-height: 52px;
  padding: 10px 8px;
  border-left: 1px solid var(--border-on-forest-strong);
  font-size: var(--type-body-xs-size);
  line-height: 1.25;
  text-align: center;
  color: var(--on-forest-muted);
  transition: background var(--dur-base), color var(--dur-base);
}
.lens__option:first-child span { border-left: none; }
.lens__option input:hover + span { background: var(--glass-on-forest); color: var(--on-forest); }
/* The selected option flips ground rather than taking an accent fill — the
   same move EditorialCard makes on hover. Terra fails twice here: paper on
   Terra is 3.67:1 (under AA at 14px) and Terra against the card is 2.43:1
   (under the 3:1 indicator floor). Terra Deep fixes the text but lands at
   1.03:1 against the card, so the selection loses its edge instead.
   Paper clears both: 8.9:1 as an indicator, and ink on paper for the label.
   The weight change is the non-colour cue, so the state survives forced
   colours and a monochrome screen. */
.lens__option input:checked + span {
  background: var(--paper);
  color: var(--text-primary);
  font-weight: 600;
}
/* Terracotta drawn inside a terracotta fill was a 1:1 indicator — invisible on
   exactly the option a keyboard user is standing on, because arrow keys check
   as they move. Now that the checked ground is paper, the ring switches with
   it: paper on the card, ink on the checked option. Both clear 3:1. */
.lens__option input:focus-visible + span {
  outline: 2px solid var(--on-forest);
  outline-offset: -3px;
}
.lens__option input:checked:focus-visible + span { outline-color: var(--color-primary); }

.signup__note,
.signup__consent {
  margin: 0;
  font-size: var(--type-body-xs-size);
  line-height: 1.45;
  color: var(--on-forest-faint);
}
.signup__consent a { color: var(--on-forest-muted); border-bottom: 1px solid var(--border-on-forest-strong); }
.signup__consent a:hover { color: var(--color-secondary); border-bottom-color: var(--color-secondary); }

.signup__status { margin: 0; font-size: var(--type-body-sm-size); color: var(--terra-pale); min-height: 0; }
.signup__status:empty { display: none; }

.signup__success { display: flex; flex-direction: column; gap: 12px; }
.signup__success[hidden] { display: none; }
.signup__success h2 {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--type-headline-sm-size);
  font-weight: 400;
  line-height: 1.2;
  outline: none;
}
.signup__success p { margin: 0; font-size: var(--type-body-sm-size); color: var(--on-forest-muted); }
.signup__success strong { color: var(--on-forest); font-weight: 600; }
/* The card sits on Forest, so the base stylesheet's Forest link colour and the
   ghost button's ink treatment both disappear into it. */
.signup__success a:not(.btn-ghost) {
  color: var(--on-forest);
  border-bottom: 1px solid var(--border-on-forest-loud);
}
.signup__success a:not(.btn-ghost):hover { color: var(--color-secondary); border-bottom-color: var(--color-secondary); }
.signup__success .btn-ghost { color: var(--on-forest); border-bottom-color: var(--on-forest); }
.signup__success .btn-ghost:hover { color: var(--color-secondary); border-bottom-color: var(--color-secondary); }

.hero__secondary {
  margin-top: 4px;
  color: var(--on-forest);
  border-bottom-color: var(--on-forest);
}
.hero__secondary:hover { color: var(--color-secondary); border-bottom-color: var(--color-secondary); }

/* ── The sheet below: everything after the Forest ground is Paper ───────── */
.sheet {
  position: relative;
  z-index: 2;
  background: var(--surface-page);
  border-radius: var(--radius-editorial) var(--radius-editorial) 0 0;
  margin-top: -60px;
  padding-top: var(--space-stack-md);
}

/* ── Example issue preview ──────────────────────────────────────────────── */
/* The big block unfolds downward as it enters: anchored at its top edge so the
   growth reads as the sheet opening, not as a card zooming at the viewer.
   `--issue-scale` and `--issue-radius` are what the scroll drives. */
.issue {
  --issue-scale: 1;
  --issue-radius: var(--radius-editorial);
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: var(--space-gutter);
  align-items: stretch;
  border: var(--border-structural);
  border-radius: var(--issue-radius);
  overflow: hidden;
  background: var(--surface-page);
  transform: scale(var(--issue-scale));
  transform-origin: 50% 0%;
}
.issue__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-stack-sm);
  padding: var(--space-stack-md) 0 var(--space-stack-md) var(--space-stack-md);
}
.issue__intro .headline { max-width: 16ch; }
.issue__actions { margin-top: auto; padding-top: var(--space-stack-sm); }

.issue__preview {
  background-color: var(--surface-container-low);
  background-image: var(--texture-hairline);
  border-left: var(--border-structural);
  padding: var(--space-stack-md);
}
.issue__paper {
  background: var(--paper);
  border: var(--border-structural);
  border-radius: var(--radius-lg);
  padding: var(--space-stack-sm);
}
.issue__masthead {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 12px;
  margin-bottom: var(--space-stack-sm);
  border-bottom: var(--border-structural);
  font-family: var(--font-sans);
  font-size: var(--type-mono-sm-size);
  font-weight: var(--type-label-weight);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--text-muted);
}
.issue__list { list-style: none; margin: 0; padding: 0; }
.issue__list li { padding: 16px 0; border-top: 1px solid var(--border-divider); }
.issue__list li:first-child { border-top: none; padding-top: 0; }
.issue__list h3 {
  margin: 0 0 4px;
  font-family: var(--font-serif);
  font-size: var(--type-headline-xs-size);
  font-weight: 400;
  line-height: var(--type-headline-xs-line);
}
.issue__list p { margin: 0; font-size: var(--type-body-sm-size); line-height: var(--type-body-sm-line); color: var(--text-variant); }

/* ── What the newsletter carries ────────────────────────────────────────── */
.carries { margin-top: var(--space-stack-lg); }
.carries__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-gutter);
  margin-top: var(--space-stack-md);
}
/* Each card arrives on its own, blur to sharp, in its natural reading order. */
.carry {
  display: flex;
  flex-direction: column;
  gap: 16px;
  opacity: var(--carry-o, 1);
  filter: blur(var(--carry-blur, 0px));
  transform: translateY(var(--carry-y, 0px));
}
.carry__frame {
  border: var(--border-structural);
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--surface-container-low);
}
.carry__frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  filter: grayscale(1);
  transition: filter var(--dur-grayscale), transform var(--dur-slow) var(--ease-editorial);
}
.carry:hover .carry__frame img { filter: grayscale(0); transform: scale(1.03); }
.carry p { margin: 0; font-size: var(--type-body-sm-size); line-height: var(--type-body-sm-line); color: var(--text-variant); }

/* ── Lenses ─────────────────────────────────────────────────────────────── */
.lenses { margin-top: var(--space-stack-lg); }
.lenses__list { list-style: none; margin: var(--space-stack-md) 0 0; padding: 0; }
.lenses__list li { border-top: var(--border-structural); }
.lenses__list li:last-child { border-bottom: var(--border-structural); }
.lenses__list a {
  display: grid;
  grid-template-columns: minmax(14rem, 20rem) 1fr auto;
  align-items: baseline;
  gap: var(--space-gutter);
  padding: var(--space-stack-sm) 0;
  color: var(--text-primary);
  text-decoration: none;
  transition: color var(--dur-base);
}
.lenses__list a:hover { color: var(--color-secondary); }
.lenses__list p { margin: 0; font-size: var(--type-body-size); color: var(--text-variant); }
.lenses__list a:hover p { color: var(--color-secondary); }
.lenses__list svg { width: 20px; height: 20px; align-self: center; }

/* ── Closing action: Paper, because the hero already spent the Forest ───── */
.close {
  margin-top: var(--space-stack-lg);
  border: var(--border-structural);
  border-radius: var(--radius-editorial);
  background-color: var(--surface-container-low);
  background-image: var(--texture-hairline);
  padding: var(--space-stack-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-stack-sm);
}
.close .headline { max-width: 18ch; }

/* ── Footer ─────────────────────────────────────────────────────────────── */
.pagefoot {
  border-top: var(--border-structural);
  margin-top: var(--space-stack-lg);
  padding: var(--space-stack-md) 0;
}
.pagefoot__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-stack-sm);
}
.pagefoot__links { display: flex; flex-wrap: wrap; gap: var(--space-stack-sm); font-size: var(--type-body-sm-size); }
.pagefoot__links a,
.pagefoot__links button {
  color: var(--text-muted);
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
}
.pagefoot__links a:hover,
.pagefoot__links button:hover { color: var(--color-secondary); }

/* The scroll choreography only runs once GSAP has claimed these elements, so a
   failed script or reduced motion leaves the page fully visible. */
.has-scroll-motion .issue { --issue-scale: 0.62; --issue-radius: 24px; }
.has-scroll-motion .carry { --carry-o: 0; --carry-blur: 12px; --carry-y: 18px; }

/* ── The one authored entrance ──────────────────────────────────────────── */
.rise { animation: verboom-reveal var(--dur-reveal) var(--ease-editorial) both; }
.rise--1 { animation-delay: 60ms; }
.rise--2 { animation-delay: 160ms; }
.rise--3 { animation-delay: 260ms; }

.reveal { opacity: 0; transform: translateY(30px); }
.reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-reveal) var(--ease-editorial), transform var(--dur-reveal) var(--ease-editorial);
}

@media (prefers-reduced-motion: reduce) {
  .rise { animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ── Responsive ─────────────────────────────────────────────────────────── */
/* Compound selectors so these beat `.weather span`, which also sets display. */
@media (max-width: 1420px) {
  .weather .w5, .weather .w10 { display: none; }
}
@media (max-width: 1100px) {
  .weather .w4, .weather .w9 { display: none; }
}
/* w2 and w7 sit at the height of the proposition line; below this width they
   crowd it, so the field drops to the four corner marks. */
@media (max-width: 1000px) {
  .weather .w2, .weather .w7 { display: none; }
}

@media (max-width: 1000px) {
  .issue { grid-template-columns: 1fr; }
  .issue__intro { padding: var(--space-stack-md) var(--space-stack-sm) 0; }
  .issue__preview { border-left: none; border-top: var(--border-structural); padding: var(--space-stack-sm); }
  .carries__grid { grid-template-columns: 1fr; }
  .lenses__list a { grid-template-columns: 1fr auto; }
  .lenses__list p { grid-column: 1 / -1; }
}

@media (max-width: 760px) {
  /* On a narrow screen the marks stop drifting across the type and take two
     clear strips instead: one above the statement, one below the card. The
     padding is what guarantees they never collide with the copy. */
  .hero { padding: 128px 0 132px; }
  .weather span { width: 58px; height: 58px; padding: 12px; }
  .weather .w2, .weather .w7 { display: none; }
  .w1 { left: 4%;  top: 28px; bottom: auto; }
  .w6 { right: 4%; top: 28px; bottom: auto; }
  .w3 { left: 4%;  top: auto; bottom: 28px; }
  .w8 { right: 4%; top: auto; bottom: 28px; }
  .sheet { margin-top: -40px; }
  .carries, .lenses, .close, .pagefoot { margin-top: 72px; }
  .close { padding: var(--space-stack-sm); }
  /* Two columns, not three stacked rows: the disclosure injects ~330px between
     the field and the button on a screen the keyboard has already halved.
     Two rows of two costs half the height and keeps every target over 44px. */
  .lens__options { grid-template-columns: 1fr 1fr; }
  .lens__option span { min-height: 52px; border-left: 1px solid var(--border-on-forest-loud); }
  .lens__option:nth-child(odd) span { border-left: none; }
  .lens__option:nth-child(n + 3) span { border-top: 1px solid var(--border-on-forest-loud); }
  .lens__option:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
