/* ═══════════════════════════════════════════════════════════════════════
   kalya Circles — /circles
   Static, self-hosted, zero external requests.

   1. Fonts
   2. Tokens (from the kalya design system)
   3. Base
   4. Layout helpers
   5. Hero + fold
   6. Session card
   7. World table
   8. FAQ
   9. Close (footer)
   10. Short-viewport tuning
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. Fonts ─────────────────────────────────────────────────────────
   Outfit (OFL), self-hosted. 300, 400 and 500 only; never 600 or above.
   Each weight is a font file the reader downloads. */
@font-face {
  font-family: "Outfit";
  src: url("assets/fonts/Outfit-Light.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Outfit";
  src: url("assets/fonts/Outfit-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Outfit";
  src: url("assets/fonts/Outfit-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ── 2. Tokens ────────────────────────────────────────────────────── */
:root {
  /* Type family */
  --font-core: "Outfit", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: var(--font-core);
  --font-display: var(--font-core);

  /* Read off the reference layout, which uses three sizes rather than one:
     a wide break before the mini cards and before the buttons, a tight one
     tying the time zone to the cards it converts, and a middle one under the
     buttons. Desktop values are 50, 21 and 31. */
  --break-wide: clamp(30px, 18.46px + 2.963vw, 50px);
  --break-tight: clamp(14px, 11.11px + .741vw, 21px);
  --break-mid: clamp(20px, 16.15px + .988vw, 31px);

  /* Set so the single-line title lockups render at exactly 80px: they are
     1.373x this, and the plain wordmark frames the same letters tighter.
     The vw term only bites on narrow phones, where 80px would put the
     widest lockup past the gutters. */
  --hero-mark-h: min(58.3px, calc(15.5vw - 5px));

  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;

  /* Warm foundation */
  --cream-page: #EDE7DF;   /* the page ground */
  --cream-surface: #F8F5F1;
  --white: #FFFFFF;

  /* Ink */
  --ink-900: #2E2822;
  --ink-800: #3A342D;
  --ink-950: #201C17;
  --ink-600: #4A4239;
  --ink-400: #857C71;
  --ink-line: #D6CFC4;
  --ink-line-strong: #C2BAAD;

  /* Noon and midnight are icon colours. No text carries either: the words
     are ink and the colour goes on the sun and the moon. Ratios below are
     ground, card, white. */
  --noon-500: #A47A07;      /* sun icon only; 3.19, 3.60, 3.91 */
  --midnight-500: #336486;  /* moon icon only; 5.17, 5.84, 6.35 */

  /* Olive — the single accent, split by job. The 500 goes on shapes only;
     the 700 is the one green that carries text. Ratios are ground, card,
     white. Do not lighten either. */
  --olive-500: #738544;   /* shapes only; 3.31, 3.74, 4.06 */
  --olive-700: #5F6E39;   /* the only green text; 4.53, 5.12, 5.56 */
  --olive-200: #E0E2CB;   /* selected fill */
  --olive-100: #ECECDD;   /* quietest wash */

  /* Semantic */
  --bg-page: var(--cream-page);
  --text-primary: var(--ink-900);
  --text-secondary: var(--ink-600);
  --text-tertiary: var(--ink-400);
  --text-self: var(--olive-500);
  --text-others: var(--olive-700);
  --text-link: var(--olive-700);
  --text-link-hover: var(--olive-500);
  --border-hairline: var(--ink-line);
  --border-self: var(--olive-500);
  --focus-ring: var(--olive-500);
  --state-selected-bg: var(--olive-200);
  --state-hover-bg: var(--olive-100);
  --presence-self: var(--olive-500);
  --presence-others: var(--olive-500);
  --action-primary: var(--ink-900);
  --action-primary-hover: var(--ink-800);
  --action-primary-active: var(--ink-950);

  /* Radius */
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  /* Six-armed asterisk, used as the list marker on /refuse. Inline so the
     page still makes no request it did not ship with. */
  --asterisk: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M12 2.5v19'/%3E%3Cpath d='m3.77 7.25 16.46 9.5'/%3E%3Cpath d='m20.23 7.25-16.46 9.5'/%3E%3C/svg%3E");

  /* Motion */
  --duration-instant: 120ms;
  --duration-fast: 180ms;
  --duration-base: 240ms;
  --ease-calm: cubic-bezier(.22, .61, .36, 1);
  --ease-in-out: cubic-bezier(.42, 0, .32, 1);

  /* Surfaces */
  --hairline: 1px solid var(--border-hairline);
  --hairline-soft: 1px solid rgba(46, 40, 34, .10);
  --focus-ring-style: 2px solid var(--focus-ring);
  --focus-ring-offset: 3px;

  /* Rhythm — mobile first */
  --gutter: 16px;
  --gutter-text: 22px;
  --section-gap: 56px;

  /* The content column. Everything that lines up — hero copy, session
     card, FAQ — is measured from this, so widening it moves them
     together. */
  --column: 1000px;
}

@media (min-width: 640px) {
  :root {
    --gutter: 24px;
    --gutter-text: 24px;
    --section-gap: 72px;
  }
}

@media (min-width: 900px) {
  :root {
    --gutter: 32px;
    --gutter-text: 32px;
    --section-gap: 104px;
  }
}

@media (min-width: 1200px) {
  :root { --column: 1180px; }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-instant: 1ms;
    --duration-fast: 1ms;
    --duration-base: 1ms;
  }
}

/* ── 3. Base ──────────────────────────────────────────────────────── */
*,
*::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(--bg-page);
  color: var(--text-primary);
  font: var(--weight-regular) 16px/1.65 var(--font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  text-wrap: pretty;
}

h1, h2, h3 {
  margin: 0;
  font-weight: var(--weight-medium);
  letter-spacing: -.012em;
}

p { margin: 0; }

img, svg { display: block; max-width: 100%; }

a {
  color: var(--text-link);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--duration-fast) var(--ease-calm);
}
a:hover { color: var(--text-link-hover); }

button, input, select { font: inherit; color: inherit; }

::selection { background: var(--olive-200); color: var(--ink-900); }

:focus-visible {
  outline: var(--focus-ring-style);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-xs);
}

/* Visually hidden, still announced */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  z-index: 30;
  background: var(--ink-900);
  color: var(--white);
  padding: 10px 18px;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  text-decoration: none;
  font-size: 14px;
  font-weight: var(--weight-medium);
}
.skip:focus-visible {
  transform: translate(-50%, 0);
  color: var(--white);
}

/* ── 4. Layout helpers ────────────────────────────────────────────── */
.wrap {
  width: min(100% - var(--gutter) * 2, var(--column));
  margin-inline: auto;
}

/* ── 5. Hero + fold ───────────────────────────────────────────────────
   Copy sits left, in the same column as the card below it. Two ambient
   forms sit behind it, both cropped by the edges of the frame — `.hero`
   clips them.

   A hangs above the copy and sets where the copy begins: --hero-pad-top
   is derived from it, never set by hand, so the copy can neither collide
   with it nor drift away. B is the wider form on the right, and appears
   only where there is room for it. (The art is 376x375, so its height is
   its width for this purpose — a quarter of a percent out.) */
.fold {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  padding-bottom: 8px;
}

.hero {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  text-align: left;
  padding-block: var(--hero-pad-top) clamp(36px, 5.5vh, 84px);
  /* Tall enough to hold whichever blob reaches lowest. Without this the
     hero ends mid-blob and the clipping below slices a straight edge
     across a soft shape. Derived, so resizing a blob adjusts the hero
     with it. */
  min-height: max(
    calc(var(--blob-a-top) + var(--blob-a-size) * var(--blob-ratio)),
    calc(var(--blob-b-top, 0px) + var(--blob-b-size, 0px) * var(--blob-ratio))
  );
  /* Both blobs run past the left and right edges on purpose, so this has
     to contain them or the page gains a horizontal scrollbar. `hidden`
     rather than `clip`: supported everywhere, and the scroll container
     it creates is harmless because the only sticky element on the page —
     the FAQ heading — sits outside .hero entirely. */
  overflow: hidden;
}

:root {
  /* The Lottie composition is 273 x 239.42, so its height is .877 of
     its width. Everything derived from a blob's height uses this. */
  --blob-ratio: .877;

  --blob-a-size: 120vw;
  --blob-a-left: -10vw;
  --blob-a-top: -60vw;
  --blob-gap: 5vw;
  --hero-pad-top: calc(var(--blob-a-top) + var(--blob-a-size) * var(--blob-ratio) + var(--blob-gap));
}

@media (min-width: 900px) {
  :root {
    /* Where the content column starts. Blob A is placed from here, not
       from the viewport edge — measured in vw it drifted against the
       copy as the window changed, which read as off-centre. In vw
       because a fixed background is positioned against the viewport. */
    --column-start: max(var(--gutter), (100vw - var(--column)) / 2);

    --blob-a-size: clamp(260px, 26vw, 400px);
    --blob-gap: clamp(60px, 6.8vw, 110px);
    --blob-a-inset: clamp(24px, 5vw, 110px);   /* right of the column edge */
    --blob-a-left: calc(var(--column-start) + var(--blob-a-inset));
    --blob-a-top: calc(var(--blob-a-size) * -.25);

    --blob-b-size: clamp(400px, 46vw, 780px);
    --blob-b-left: auto;
    --blob-b-right: calc(var(--blob-b-size) * -.1);
    --blob-b-top: calc(var(--blob-b-size) * -.16);
  }
}

/* The blobs are animations now, so they are elements rather than
   background layers. They sit on their own layer beneath the copy, and
   that layer is masked so they dissolve toward the hero's lower edge —
   without it, that edge cuts a hard line across the artwork wherever the
   card below is not there to justify it.

   Being elements, they scroll with the hero; a background could be
   `fixed` against the viewport, an animation cannot without clipping
   itself out of the section. */
.hero__blobs {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* No z-index and no mask. Either one would make this a stacking context and
     isolate the blobs' blend from the page ground. The bottom fade the mask
     used to draw is gone with it; z-index moved to .blob. */
}

/* Height is stated outright rather than left to aspect-ratio. The player
   inlines `height: 100%` on the <svg> it injects, and a percentage height
   cannot resolve against a parent whose height is `auto` — which is what
   aspect-ratio leaves it as, however it computes the used value. */
.blob {
  position: absolute;
  pointer-events: none;
}

/* If the animation cannot be drawn — opened straight from disk, where
   fetch is blocked, or the player failing for any other reason — the
   still art stands in. Decoration should degrade, not disappear. */
/* One dial for the animation's tone, in case it needs lifting off the ground.
   1 is the asset untouched. Do not reach for saturate() here: it drains the
   warmth that makes the shape read as light rather than grey. */
:root {
  --blob-lift: 1;      /* 1 is the asset untouched */
  --blob-opacity: .65; /* eased back toward the page, still a form */
}

.blob {
  opacity: var(--blob-opacity);
  filter: brightness(var(--blob-lift));
  mix-blend-mode: luminosity;
  /* Layering lives here rather than on the container, so no ancestor between
     this element and body creates a stacking context and isolates the blend. */
  z-index: 0;
}

.blob.is-still {
  filter: none;
  background: url("assets/img/ambient-blob.webp") center / contain no-repeat;
}
.blob svg {
  display: block;
  width: 100%;
  height: 100%;
  /* The artwork is drawn smaller inside its frame than the version before it
     (672 x 38% in a 255.6 frame, against 672 x 41.7% in a 273 frame), and it
     is centred where the old one sat 1.4% down and right. Both corrections
     live here so the geometry tokens keep meaning what they say. */
  transform: translate(1.4%, 1.46%) scale(1.0274);
}

.blob--a {
  width: var(--blob-a-size);
  height: calc(var(--blob-a-size) * var(--blob-ratio));
  left: var(--blob-a-left);
  top: var(--blob-a-top);
}

/* The second form only appears where there is room for it. */
.blob--b { display: none; }

@media (min-width: 900px) {
  .blob--b {
    display: block;
    width: var(--blob-b-size);
    height: calc(var(--blob-b-size) * var(--blob-ratio));
    right: var(--blob-b-right);
    top: var(--blob-b-top);
  }
}

/* Same box as .wrap, so the copy's left edge lines up with the left edge
   of the card below it. The two must stay in step. */
.hero__copy {
  position: relative;
  z-index: 1;
  width: min(100% - var(--gutter) * 2, var(--column));
  margin-inline: auto;
}

.hero__mark {
  width: auto;
  height: var(--hero-mark-h);
}

/* The combined lockups are all drawn on one grid: kalya is 43.5 units in
   every file and every ink block starts at x 4.0, y 33.3. The plain logo
   frames the same letters tighter, filling .737 of its box against .537 of
   theirs, so at one CSS height they would draw kalya 27 percent smaller and
   30 percent lower. These numbers cancel that, and because the artworks
   share an origin, one correction serves them all. */
.hero__mark[src$="kalya-circles-wordmark.svg"],
.hero__mark[src$="kalya-privacy-wordmark.svg"],
.hero__mark[src$="help.svg"],
.hero__mark[src$="kalya-refuses-wordmark.svg"] {
  height: calc(var(--hero-mark-h) * 1.373);
  margin-top: calc(var(--hero-mark-h) * -0.303);
  margin-left: calc(var(--hero-mark-h) * -0.068);
}

/* The title is the artwork; the heading is only carrying it. */
.page__title--art {
  margin: 0;
  line-height: 0;
}

/* The wordmark leads; the title is a quiet line beneath it. */
.hero__title {
  margin-top: clamp(14px, 11.11px + .741vw, 20px);
  /* Larger than the statement below it, as the reference sets it. */
  font-size: clamp(20px, 17.77px + .571vw, 26px);
  font-weight: var(--weight-regular);
  line-height: 1.35;
  letter-spacing: -.005em;
  color: var(--text-primary);
}

/* The statement — the largest thing here after the wordmark. */
.hero__lede {
  margin-top: clamp(36px, 22.52px + 3.457vw, 64px);
  font-size: clamp(19px, 17.14px + .476vw, 24px);
  font-weight: var(--weight-medium);
  line-height: 1.25;
  letter-spacing: -.012em;
}

.hero__body {
  margin-top: clamp(10px, 8.07px + .494vw, 14px);
  max-width: 44em;
  font-size: clamp(16px, 15.04px + .247vw, 18px);
  line-height: 1.6;
  color: var(--text-secondary);
}

/* ── The home page ────────────────────────────────────────────────────
   One screen for the mark and the line, then two offers stacked under it:
   Circles, which exists, and the app, which does not yet. The hero holds a
   full screen so the cue at its foot has somewhere to point. */
.hero--home {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  /* Less than the Circles page takes. There the padding keeps the copy
     clear of the blob above it; here the copy is centred in the screen,
     so a full clearance would push it low and read as bottom-weighted.
     Enough is kept that the mark still sits under the blob, not in it. */
  padding-top: calc(var(--hero-pad-top) * .5);
  /* The cue sits well clear of the bottom edge. Pinned to it, it read as
     chrome and went unnoticed. */
  padding-bottom: clamp(48px, 36.46px + 2.963vw, 80px);
}

/* The copy takes the space the cue does not, and centres itself in it, so
   the mark sits optically in the screen rather than under the blobs. */
.home__hero-copy {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Dominant: this is the only thing the page says at first. It is the h1,
   so the alt text on the image carries the name. */
.home__mark {
  margin: 0;
  line-height: 0;
}
.home__mark img {
  width: auto;
  height: clamp(80px, 46.6px + 8.571vw, 170px);
}

.home__line {
  margin-top: clamp(20px, 15.19px + 1.235vw, 30px);
  max-width: 20em;
  font-size: clamp(20px, 16.15px + .988vw, 28px);
  font-weight: var(--weight-regular);
  line-height: 1.3;
  letter-spacing: -.008em;
  color: var(--text-primary);
}

/* Sits at the foot of the first screen. A link, not a script — it works
   with JavaScript off and gives the keyboard a real target. */
.home__cue {
  position: relative;
  z-index: 1;
  align-self: center;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 0;
  text-decoration: none;
  color: var(--text-secondary);
  font-size: clamp(14px, 13.04px + .247vw, 16px);
}
.home__cue:hover { color: var(--text-primary); }
.home__cue-icon { width: 26px; height: 26px; }

@media (prefers-reduced-motion: no-preference) {
  .home__cue-icon { animation: cue-drift 2.6s var(--ease-calm) infinite; }
}
@keyframes cue-drift {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(4px); }
}

/* The two offers. The primary one carries a surface so it reads first;
   the secondary sits on the page ground. */
.offer {
  width: min(100% - var(--gutter) * 2, var(--column));
  margin-inline: auto;
  padding-block: clamp(40px, 28.46px + 2.963vw, 72px);
}
.offer + .offer { border-top: var(--hairline); }

.offer__inner { max-width: 34em; }

.offer__label {
  font-size: clamp(13px, 12.52px + .123vw, 14px);
  font-weight: var(--weight-medium);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.offer__lede {
  margin-top: clamp(12px, 10.07px + .494vw, 16px);
  font-size: clamp(22px, 18.15px + .988vw, 30px);
  font-weight: var(--weight-medium);
  line-height: 1.25;
  letter-spacing: -.012em;
  text-wrap: balance;
}

.offer__cta { margin-top: clamp(22px, 18.15px + .988vw, 30px); }

/* ── Waiting list ─────────────────────────────────────────────────
   No backend and no third party, so the form hands the address to the
   reader's own mail client. The markup is the shape a real endpoint
   would want, so wiring one in later is a change of handler, not of
   layout. */
.waitlist { margin-top: clamp(22px, 18.15px + .988vw, 30px); }

.waitlist__label {
  display: block;
  margin-bottom: 10px;
  font-size: clamp(14px, 13.52px + .123vw, 15px);
  color: var(--text-secondary);
}

.waitlist__row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 30em;
}

.waitlist__input {
  flex: 1 1 auto;
  min-width: 0;
  height: 60px;
  padding: 0 18px;
  background: var(--white);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: 15px;
  color: var(--text-primary);
}
.waitlist__input::placeholder { color: var(--text-tertiary); }
.waitlist__input:focus-visible {
  outline: 2px solid var(--action-primary);
  outline-offset: 2px;
  border-color: transparent;
}

.waitlist__button { flex: 0 0 auto; }

.waitlist__note {
  margin-top: 10px;
  font-size: clamp(13px, 12.52px + .123vw, 14px);
  color: var(--text-secondary);
}

/* Empty until the form has something to say, so it holds no space. */
.waitlist__status:not(:empty) {
  margin-top: 10px;
  font-size: clamp(13px, 12.52px + .123vw, 14px);
  color: var(--text-others);
}

@media (min-width: 640px) {
  .waitlist__row { flex-direction: row; }
  .waitlist__button { min-width: 120px; }
}

/* Sits directly under the body line and before the card, in ink. */
.hero__belong {
  margin-top: clamp(10px, 8.07px + .494vw, 14px);
  font-size: clamp(16px, 15.04px + .247vw, 18px);
  font-weight: var(--weight-medium);
  line-height: 1.6;
  color: var(--text-primary);
}

/* Text pages: the same blobs in the same places, with the page title
   standing where the wordmark stands on the Circles page. No fold, so the
   header is only as tall as the blobs need. */
/* Only as tall as the title needs. The Circles hero stretches to hold the
   whole of the lower blob; here that left 230-280px of empty ground under
   the title. The mask on .hero__blobs fades whatever this cuts off, so the
   shorter header costs a soft edge rather than a hard one. */
.hero--page {
  padding-bottom: clamp(28px, 18.4px + 2.469vw, 48px);
}

/* The page name sits beside the mark, the way "Circles" does in the combined
   artwork. Every number here is read off that file: Circles' cap height is
   .478 of kalya's full ink, they share a baseline, and the gap between them
   is .759 of that ink. kalya's ink is .737 of the mark's box, and its 'y'
   drops .210 of the box below the baseline — which is what the negative
   margin cancels, since an image's baseline is its bottom edge. */
.hero__lockup {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  column-gap: calc(var(--hero-mark-h) * .56);
}
.hero__lockup .hero__mark { margin-bottom: calc(var(--hero-mark-h) * -.21); }
.hero__lockup .page__title {
  margin: 0;
  /* .478 x .737 of the box is the cap height; Outfit's caps are about .70
     of its em, so the em is that over .70. */
  font-size: calc(var(--hero-mark-h) * .503);
}

.page__title {
  font-size: clamp(32px, 24.30px + 1.975vw, 48px);
  font-weight: var(--weight-medium);
  line-height: 1.15;
  letter-spacing: -.018em;
  text-wrap: balance;
}

/* ── 5b. Prose ────────────────────────────────────────────────────────
   One reading column, in the same box as everything else on the site so
   the left edge holds from the header down. */
.prose {
  width: min(100% - var(--gutter) * 2, var(--column));
  margin-inline: auto;
  padding-block: clamp(32px, 22.4px + 2.469vw, 52px) clamp(28px, 22.22px + 1.481vw, 40px);
}

.prose__inner {
  max-width: 34em;
  margin-inline: auto;
  font-size: clamp(16px, 15.04px + .247vw, 18px);
  line-height: 1.65;
  color: var(--text-secondary);
}

.prose__inner > * + * { margin-top: clamp(18px, 15.11px + .741vw, 24px); }

.prose__inner b {
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

.prose__lede {
  font-size: clamp(18px, 16.07px + .494vw, 22px);
  color: var(--text-primary);
}

.prose__close {
  color: var(--text-primary);
  font-weight: var(--weight-medium);
}

.prose__more a { font-weight: var(--weight-medium); }

/* The refusals: one hairline-separated line each, lead in ink. */
.marklist {
  /* One size for the marker, on every page that uses this list. */
  --mark-size: clamp(15px, 14.04px + .247vw, 17px);
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 16.15px + .988vw, 28px);
}

/* Clear of the paragraph above: at the generic paragraph gap the first
   hairline read as an underline of the sentence before it. */
.prose__inner > .marklist { margin-top: clamp(34px, 24.4px + 2.469vw, 54px); }

/* No rules between the items. The asterisk marks each one instead, and the
   block sits centred against it rather than hanging from its first line. */
.marklist__item {
  display: flex;
  gap: clamp(14px, 11.11px + .741vw, 20px);
}

.marklist__item::before {
  content: "";
  flex: 0 0 auto;
  align-self: flex-start;
  width: var(--mark-size);
  height: var(--mark-size);
  /* Sits on the first line rather than the middle of the block. The offset is
     half the difference between that line's box and the mark: the text is
     1.65 line-height, so the box is 1.65em and the mark is --mark-size. */
  margin-top: calc((1.65em - var(--mark-size)) / 2);
  background-color: var(--olive-700);
  /* Masked rather than drawn, so the mark takes a token colour instead of
     carrying one of its own. */
  -webkit-mask: var(--asterisk) no-repeat center / contain;
  mask: var(--asterisk) no-repeat center / contain;
}

/* The lead-in and the sentence after it are one run of text, not two lines.
   Wrapping them in a single element makes that explicit: flex would
   otherwise leave them to an anonymous box it does not name. */
.marklist__text { min-width: 0; }

/* Outfit ships 400 and 500 only, so a <b> here was being synthesised into a
   fake 700. This is the real medium, carrying the emphasis in ink against
   the secondary tone of the sentence that follows it. */
.marklist__item b {
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

.close__home {
  display: inline-block;
  border: 0;
  text-decoration: none;
}

/* ── 6. Session card ──────────────────────────────────────────────── */
.session {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* A solid fill rather than white at 45 percent: the translucent version
     took its final colour from whatever ground it sat on, so it moved every
     time the page colour did, and the contrast figures moved with it. */
  background: var(--cream-surface);
  border-radius: var(--radius-lg);
  /* Same reasoning as the mini cards: the floor carries the phone, where
     the card is the whole screen. Desktop values are unchanged. */
  padding: clamp(46px, 42.29px + .952vw, 56px) clamp(20px, 6.52px + 3.457vw, 48px)
           clamp(60px, 53.49px + 1.669vw, 78px);
}

.session__eyebrow {
  font-size: clamp(14px, 13.63px + .095vw, 15px);
  font-weight: var(--weight-medium);
  line-height: 1.3;
}

.session__big {
  margin-top: clamp(8px, 7.04px + .247vw, 10px);
  font-size: clamp(29px, 23.7px + 1.358vw, 40px);
  font-weight: var(--weight-medium);
  line-height: 1.15;
  letter-spacing: -.014em;
  text-wrap: balance;
}

.session__meta {
  margin-top: clamp(8px, 7.04px + .247vw, 10px);
  font-size: clamp(16px, 15.04px + .247vw, 18px);
  line-height: 1.4;
  color: var(--text-others);
}
.session__meta b {
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}

/* Every "[Time] Circle" on the page carries its icon and its own colour,
   wherever it appears and whichever Circle is next. Noon spends two steps of
   one colour because a goldenrod light enough to read as daytime cannot also
   clear 4.5:1 as text: the 500 goes on the icon, which needs only 3:1, and
   the 700 on the words. Midnight is dark enough to serve both from one. */
.circle[data-circle="noon"] .circle__icon { color: var(--noon-500); }
.circle[data-circle="midnight"] .circle__icon { color: var(--midnight-500); }

/* The Circle named on the meta line carries the same sun or moon as the
   mini card it points at. Only the matching one is shown, and it takes the
   accent because an icon is not text. */
.session__meta-icon {
  display: inline-flex;
  vertical-align: -.16em;
  margin-right: .4em;
}
.meta-icon { width: 1.05em; height: 1.05em; }
.session .meta-icon { display: none; }
.session[data-circle="noon"] .meta-icon--noon {
  display: block;
  color: var(--noon-500);
}
.session[data-circle="midnight"] .meta-icon--midnight {
  display: block;
  color: var(--midnight-500);
}
/* Nothing named while a Circle is running. */
/* While a Circle is running the meta line reads "left in this Circle" and
   names nothing, so its icon goes; the eyebrow carries it instead. */
.session.is-live .session__meta-icon { display: none; }
.session:not(.is-live) .session__eyebrow-icon { display: none; }

.session__eyebrow-icon {
  display: inline-flex;
  vertical-align: -.16em;
  margin-right: .4em;
}
.session__eyebrow-icon .meta-icon { width: 1.05em; height: 1.05em; }

/* The open Circle names itself, so it takes its colour — the text step. */
.session.is-live[data-circle="noon"] .session__eyebrow { color: var(--text-primary); }
.session.is-live[data-circle="midnight"] .session__eyebrow { color: var(--text-primary); }

/* Name, separator, countdown — one line, with only the countdown set in
   medium so the eye lands on the number. */
.session__meta-dot {
  margin: 0 .45em;
}

/* Nothing to separate while a Circle is running: the meta line reads
   "left in this Circle" on its own. */
.session__meta-name:empty + .session__meta-dot {
  display: none;
}

.session__live {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(22px, 21.04px + .247vw, 24px);
  margin-top: clamp(10px, 9.04px + .247vw, 12px);
  font-size: clamp(13px, 12.52px + .123vw, 14px);
  line-height: 1.4;
  color: var(--text-secondary);
}

/* Nothing writes to this slot today, so reserving it only added height to the
   open state and made that card taller than the others. It costs nothing if
   something fills it later. */
.session__live:empty { display: none; }

/* Live state — the headline becomes the time left in the open Circle, at the
   same size the clock time uses in every other state. Only the figures change
   behaviour: tabular ones keep a per-second countdown from jittering. */
.session.is-live .session__big {
  font-variant-numeric: tabular-nums;
}
.session.is-live .session__meta { color: var(--text-secondary); }

/* The two Circles */
/* The pair sits at 769px in the reference, centred rather than filling the
   card: 368px each with 33px between them. Left at width:100% they stretched
   to 535px each, which is what made them read as short and squat. */
.circles {
  display: grid;
  gap: clamp(14px, 8.23px + 1.72vw, 33px);
  width: 100%;
  max-width: 769px;
  margin-inline: auto;
  margin-top: var(--break-wide);
}

@media (min-width: 640px) {
  .circles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(16px, -14.81px + 2.5vw, 32px);
    max-width: 672px;
  }
}

.circle {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(9px, 6.27px + .698vw, 18px);
  background: var(--white);
  border: var(--hairline);
  border-radius: 16px;
  /* The floor matters more than the ceiling here: the cards stack on a
     phone, so the vertical padding is what keeps them from reading as a
     tight band. Desktop values are unchanged. */
  padding: clamp(30px, 29.28px + .185vw, 32px) 20px clamp(36px, 33.83px + .557vw, 42px);
}

.circle__name {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-secondary);
  font-size: clamp(13px, 12.52px + .123vw, 14px);
  font-weight: var(--weight-medium);
  line-height: 1.2;
}

.circle__icon {
  width: clamp(16px, 15.52px + .123vw, 17px);
  height: clamp(16px, 15.52px + .123vw, 17px);
  flex: 0 0 auto;
}

.circle__time {
  font-size: clamp(28px, 26.07px + .494vw, 32px);
  font-weight: var(--weight-medium);
  line-height: 1.15;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}

.circle__ref {
  font-size: clamp(13px, 12.04px + .247vw, 15px);
  line-height: 1.3;
  color: var(--text-tertiary);
}


/* Each Circle carries its own colour: goldenrod for noon, purple for
   midnight. The card already knows which it is. */
.circle[data-circle="noon"] .circle__name { color: var(--text-secondary); }

.circle[data-circle="midnight"] .circle__name { color: var(--text-secondary); }

/* The subheader names one of the two, so it takes that colour too. It
   falls back to the page accent while a Circle is running, when the
   line reads "left in this Circle" and names nothing. */
.session[data-circle="noon"] .session__meta { color: var(--text-primary); }
.session[data-circle="midnight"] .session__meta { color: var(--text-primary); }

/* Time zone */
.tz {
  display: flex;
  /* Reversed rather than reordered: the label stays first in the source, so
     aria-labelledby and reading order are unaffected, and only the paint
     order changes. It goes back to a row from 640 up. */
  flex-direction: column-reverse;
  align-items: center;
  gap: 10px;
  margin-top: var(--break-tight);
}

@media (min-width: 640px) {
  .tz { flex-direction: row; gap: 12px; }
  .tz__control { padding: 8px 12px; }
}

.tz__label {
  font-size: clamp(12px, 11.52px + .123vw, 13px);
  color: var(--text-tertiary);
}

.tz__control {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  border: var(--hairline);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  background: var(--white);
  color: var(--text-secondary);
  font-size: clamp(12px, 11.52px + .123vw, 13px);
  line-height: 1.2;
  transition: border-color var(--duration-fast) var(--ease-calm);
}
.tz__control:hover { border-color: var(--ink-line-strong); }
.tz__control:focus-within {
  outline: var(--focus-ring-style);
  outline-offset: var(--focus-ring-offset);
}

/* The real control sits on top, invisible: native keyboard and native
   mobile pickers, our own chrome. */
.tz__select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  border: 0;
  background: transparent;
}

.tz__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tz__chev {
  width: clamp(13px, 12.52px + .123vw, 14px);
  height: clamp(13px, 12.52px + .123vw, 14px);
  flex: 0 0 auto;
  color: var(--text-tertiary);
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  cursor: pointer;
  /* Buttons are buttons whether they are <button> or <a>. Without this the
     global link underline lands on any anchor wearing this class. */
  text-decoration: none;
  font-weight: var(--weight-medium);
  transition: background-color var(--duration-fast) var(--ease-calm),
              border-color var(--duration-fast) var(--ease-calm),
              color var(--duration-fast) var(--ease-calm);
}

.btn--primary,
.btn--secondary {
  /* One width for every button on the site. Capped at the container so a
     288px button cannot push a narrow phone into a sideways scroll. */
  width: min(288px, 100%);
}

.btn--primary {
  height: 60px;
  padding: 0 34px;
  background: var(--action-primary);
  color: var(--white);
  border-radius: var(--radius-pill);
  font-size: 15px;
}
/* The same box as the primary, drawn rather than filled. Border and text
   both take the primary's own colour so the two read as one pair. */
.btn--secondary {
  height: 60px;
  padding: 0 34px;
  background: transparent;
  color: var(--action-primary);
  border: 2px solid var(--action-primary);
  border-radius: var(--radius-pill);
  font-size: 15px;
}
.btn--secondary:hover {
  color: var(--action-primary-hover);
  border-color: var(--action-primary-hover);
}
.btn--secondary:active {
  color: var(--action-primary-active);
  border-color: var(--action-primary-active);
}

.btn--primary:hover { background: var(--action-primary-hover); }
.btn--primary:active { background: var(--action-primary-active); }

/* The two actions share a row and wrap to a stack when there is no room.
   The gap above them is the same clamp .circles uses above the mini cards,
   so the two breaks in the card are equal. */
.session__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(12px, 5.08px + 1.778vw, 28px);
  width: 100%;
  margin-top: var(--break-wide);
}
.session__actions .session__cta { margin-top: 0; }

/* Only on offer while Join is showing; the rest of the time the primary
   button is already the calendar. */
.session:not(.is-joinable) .session__cta--alt { display: none; }

.session__cta {
  margin-top: clamp(24px, 22.07px + .494vw, 28px);
}

/* Sits close under the primary: the two are one pair, not two decisions.
   Declared after .session__cta so it wins at equal specificity. */
.session__cta--alt { margin-top: clamp(10px, 9.04px + .247vw, 12px); }



.session__note {
  margin-top: var(--break-mid);
  text-align: center;
  font-size: clamp(16px, 15.04px + .247vw, 18px);
  font-weight: var(--weight-light);
  line-height: 1.35;
  color: var(--text-secondary);
}

/* The second of the two lines under the button sits close to the first.
   Declared after .session__note so it wins at equal specificity. */
.session__note--tight { margin-top: 0; }

/* ── 7. World table ───────────────────────────────────────────────── */
.world {
  box-sizing: content-box;
  max-width: 540px;
  margin: calc(var(--section-gap) * .5 + 52px) auto 0;
  padding-inline: 34px;
}

@media (min-width: 640px) {
  .world { padding-inline: 24px; }
}

.world__head {
  text-align: center;
  font-size: 20px;
  line-height: 1.4;
  letter-spacing: .04em;
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

.world__table {
  width: 100%;
  /* Air between the heading and the sun/moon row. */
  margin-top: clamp(36px, 30.22px + 1.481vw, 48px);
  border-collapse: collapse;
  font-size: clamp(16px, 15.04px + .247vw, 18px);
}

.world__table th,
.world__table td {
  padding: clamp(12px, 11.52px + .123vw, 13px) 0;
  border-top: var(--hairline-soft);
}

/* Weight is set per row, not per cell, so a marked row can move the whole row
   at once. th needs the explicit inherit: the browser's own stylesheet sets it
   to bold, and a UA rule on the element beats a value inherited from the row.
   Saying inherit is a direct rule that defers to the row rather than fighting
   it, which a fixed weight here would do. */
.world__table tr { font-weight: var(--weight-regular); }
.world__table th { font-weight: inherit; }

.world__table thead th {
  padding: 0 0 clamp(11px, 10.52px + .123vw, 12px);
  border-top: 0;
  font-size: clamp(11px, 10.52px + .123vw, 12px);
  font-weight: var(--weight-medium);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Column heads carry the same sun and moon as the two cards above, in the
   same colours, so the table reads as the same pair seen from elsewhere.
   Icon only — the word survives for screen readers in a .vh span, so the
   column still has a name. */
.world__col {
  display: inline-flex;
  align-items: center;
}

/* Sized in px, not em: the head's own font is 10-11px, so an em-based
   icon would be tied to type far smaller than the mark wants to be. */
.world__icon {
  flex: 0 0 auto;
  width: clamp(22px, 20.08px + .494vw, 26px);
  height: clamp(22px, 20.08px + .494vw, 26px);
}

.world__icon--noon { color: var(--noon-500); }
.world__icon--midnight { color: var(--midnight-500); }

.world__table thead th:not(:first-child) { text-align: center; }

/* Alignment only. Colour is set on the row, and a colour set here would
   outrank it: th:first-child scores higher than a two-class row selector,
   so the marked row's city name would stay ink while its times went green. */
.world__table th:first-child {
  text-align: left;
}

/* Times are centred, not right-aligned, so the sun and moon above them
   sit over their own data. Right-aligned numbers under a centred mark
   read as misaligned even when the mark is exactly centred in its
   column — the eye measures against the text, not the cell. */
.world__table td {
  width: clamp(108px, 100.3px + 1.975vw, 126px);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* The day indicator: quiet, and never part of the tabular alignment.
   Absolutely placed so it cannot pull the time off centre — only two of
   the rows carry one, and they would otherwise sit askew of the rest. */
.world__table td { position: relative; }
.world__cell {
  position: relative;
  display: inline-block;
}
.world__day {
  position: absolute;
  left: calc(100% + .4em);
  top: 50%;
  translate: 0 -50%;
  font-size: .78em;
  font-variant-numeric: normal;
  color: var(--text-primary);
}
.is-you .world__day,
.is-home .world__day { color: inherit; }

/* New York — the city the Circles are set by. An anchor, in full ink,
   so the other rows read as conversions of it. */
.world__table .is-home {
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

/* The reader's own row: the accent, at medium weight. No wash — the
   colour and weight carry it. olive-700 rather than the -500 the system
   nominates for markers, because on the page's cream this size of text
   needs 4.5:1 and -500 reaches only 3.31:1. 500 is the heaviest weight
   the system allows; it never goes to 600. */
.world__table .is-you {
  color: var(--olive-700);
  font-weight: var(--weight-medium);
}

.world__foot {
  margin-top: clamp(20px, 19.04px + .247vw, 22px);
  text-align: center;
  font-size: clamp(15px, 14.04px + .247vw, 17px);
  line-height: 1.6;
  color: var(--text-primary);
}

/* ── 8. FAQ ───────────────────────────────────────────────────────── */
.faq {
  margin-top: calc(var(--section-gap) * .7 + 40px);
}

.faq__grid {
  width: min(100% - var(--gutter-text) * 2, var(--column));
}

@media (min-width: 900px) {
  .faq__grid {
    display: grid;
    /* 320 rather than 400: the full phrase measures 400.3px at 34px, so a
       400px column held it on one line by a third of a pixel. 320 breaks it
       after 'asked', which needs 254px. */
    grid-template-columns: minmax(260px, 320px) 1fr;
    column-gap: clamp(40px, -66.67px + 8.889vw, 72px);
  }
}

.faq__head {
  font-size: clamp(27px, 24.35px + .671vw, 34px);
  font-weight: var(--weight-medium);
  line-height: 1.2;
  letter-spacing: -.012em;
  margin-bottom: 28px;
}

/* Sticky only where there is a column beside it to stick against. */
@media (min-width: 900px) {
  .faq__head {
    position: sticky;
    top: 48px;
    margin-top: 14px;
    margin-bottom: 0;
  }
}

.faq__item { border-top: var(--hairline); }
.faq__item--last { border-bottom: var(--hairline); }

.faq__q {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: normal;
}

.faq__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  padding: clamp(18px, 15.11px + .741vw, 22px) 2px;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
  font-size: clamp(18px, 16.14px + .476vw, 23px);
  font-weight: var(--weight-medium);
  line-height: 1.35;
  color: var(--text-primary);
}

@media (min-width: 900px) {
  .faq__btn { gap: 24px; font-weight: var(--weight-regular); }
}

.faq__sign {
  position: relative;
  flex: 0 0 auto;
  width: clamp(13px, 12.52px + .123vw, 14px);
  height: clamp(13px, 12.52px + .123vw, 14px);
}
/* Horizontal bar — always there */
.faq__sign::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  translate: 0 -50%;
  height: 2px;
  border-radius: 1px;
  background: var(--text-tertiary);
}
/* Vertical bar — makes the plus when the row is closed */
.faq__sign::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  translate: -50% 0;
  width: 2px;
  border-radius: 1px;
  background: var(--text-tertiary);
  transition: opacity var(--duration-fast) var(--ease-calm),
              rotate var(--duration-base) var(--ease-in-out);
}
.faq__item.is-open .faq__sign::after {
  opacity: 0;
  rotate: 90deg;
}

.faq__panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows var(--duration-base) var(--ease-in-out),
              visibility 0s linear var(--duration-base);
}
.faq__panel > .faq__answer { overflow: hidden; min-height: 0; }

.faq__item.is-open .faq__panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--duration-base) var(--ease-in-out),
              visibility 0s;
}

.faq__answer {
  max-width: 560px;
  font-size: clamp(16px, 15.04px + .247vw, 18px);
  font-weight: var(--weight-light);
  line-height: 1.62;
  color: var(--text-secondary);
}
.faq__answer > * {
  margin: 0;
  padding-inline: 2px;
}
.faq__answer > *:first-child { padding-top: 0; }
.faq__answer > * + * { margin-top: clamp(12px, 11.04px + .247vw, 14px); }
.faq__answer > *:last-child { padding-bottom: clamp(22px, 20.07px + .494vw, 26px); }

/* ── 9. Close ─────────────────────────────────────────────────────────
   No curve and no separate ground now: the close sits on the page cream
   with one large ambient form rising from the bottom, cropped by the
   edge of the page. The wordmark is kalya alone, not kalya Circles. */
.close {
  position: relative;
  overflow: hidden;
  background: var(--bg-page);
  color: var(--text-primary);
  text-align: center;
  /* Small: the footer's own top padding is generous and the blob's upper
     arc reaches its top edge, so a large margin here reads as dead space
     rather than separation. */
  margin-top: clamp(72px, 55.7px + 4.19vw, 97px);
  /* The text pages already end in .prose's own bottom padding, so the gap the
     Circles page needs reads as a hole on them. main.prose exists only on
     those pages, so this scopes without a class or a wrapper. */
  /* The blob is centred on the lockup, so the whole circle is visible only
     if the section reaches half a blob above that centre and half below.
     Both paddings are derived from the blob rather than chosen, and the
     blob is sized to the lockup it sits behind: at its old 1100px it would
     have needed a footer around 1200px tall to show in full. */
  --close-mark-h: clamp(40px, 30.37px + 2.469vw, 60px);
  --close-blob-size: min(520px, 78vw);
  --close-blob-h: calc(var(--close-blob-size) * var(--blob-ratio));
  padding-block: calc(var(--close-blob-h) / 2 + 16px)
                 max(88px, calc(var(--close-blob-h) / 2 - 160px));
  padding-inline: var(--gutter-text);
}

/* Centred on the content, not on the footer. Anchoring it to the footer's
   bottom edge meant the two chased each other: pushing the copy down grew
   the footer, which moved the blob down by the same amount. Centred on
   .close__inner it holds regardless of padding, and .close crops whatever
   runs past the top and bottom of the section. */
.close__blob {
  position: absolute;
  z-index: 0;
  width: var(--close-blob-size);
  height: var(--close-blob-h);
  /* Centred on the visible pair, not on the image box. The wordmark file
     carries 41 percent empty space above its letterforms and 5 percent
     below, so centring on the box put the type low in the circle. This
     lands between the top of the letterforms and the line underneath. */
  top: calc(var(--close-mark-h) * .7 + 14px);
  left: 50%;
  translate: -50% -50%;
}

.prose + .close { margin-top: clamp(32px, 24.6px + 1.9vw, 44px); }

.close__inner {
  position: relative;
  width: min(100%, 640px);
  margin-inline: auto;
}

/* Above the blob it is centred on. */
.close__inner > *:not(.close__blob) {
  position: relative;
  z-index: 1;
}

.close__mark {
  width: auto;
  height: var(--close-mark-h);
  margin-inline: auto;
}

.close__sub {
  margin-top: clamp(4px, 2.07px + .494vw, 10px);
  font-size: clamp(24px, 21.3px + .671vw, 31px);
  font-weight: var(--weight-medium);
  letter-spacing: -.01em;
  color: var(--text-primary);
}

.close__legal {
  display: flex;
  flex-direction: column;
  /* The two fine lines read as one pair, so the gap is tight and fixed. Air
     between them and the links row above comes from .close__links instead. */
  gap: 3px;
  margin-top: clamp(140px, 84px + 14vw, 260px);
  font-size: clamp(16px, 14.85px + .287vw, 19px);
  line-height: 1.5;
  color: var(--text-secondary);
}

/* One step below the link line above them. Only the size changes: the
   line-height and the flex gap that spaces the three lines both live on
   .close__legal, so the rhythm is unaffected. */
.close__fine {
  font-size: clamp(15px, 13.85px + .287vw, 18px);
}

.close__links {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(10px, 8.07px + .494vw, 14px);
  /* Separates the links from the two fine lines, which now sit tight. */
  margin-bottom: clamp(14px, 10px + 1vw, 22px);
}
.close__links a {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.close__links a:hover { color: var(--text-secondary); }
.close__links span { color: var(--text-tertiary); }

/* ── 10. Short-viewport tuning ────────────────────────────────────────
   The fold has to hold the hero, the card and the "camera off is fine"
   line at 390x844. On short screens the decorative air comes out first,
   then a little of the card's own padding. */
/* Genuinely short windows only. This used to start at 940px tall, which
   caught every laptop and shrank the lockup to 36px — it was there to keep
   the whole fold on screen, a requirement the hero redesign retired. The
   proportions matter more than the fold, so the squeeze now begins well
   below a normal laptop viewport. */
@media (max-height: 760px) and (min-width: 900px) {
  :root {
    --blob-a-size: 22vw;
    --blob-a-top: -10vw;
    --blob-b-size: 36vw;
    --blob-gap: 4vw;
  }
}

/* Short and narrow. The card's own padding and spacing are no longer squeezed
   here: those overrides existed to keep the whole fold on a 390x844 screen, a
   requirement the redesign retired, and they were quietly undoing the padding
   set on .session and .circle. */
@media (max-height: 940px) and (max-width: 899px) {
  .hero__title { margin-top: 14px; line-height: 1.1; }
}

/* Very short viewports (landscape phones): stop fighting for the fold. */
@media (max-height: 620px) {
  .fold { min-height: 0; }
  :root { --blob-a-size: 20vw; --blob-a-top: -6vw; --blob-gap: 2vw; }
}
