@layer reset, base, components, pages;

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  html { scroll-behavior: smooth; }
  body, h1, h2, h3, p { margin: 0; }
  button, input { font: inherit; }
  img, svg { display: block; max-width: 100%; }
}

@layer base {
  :root {
    color-scheme: dark;
    --ink: #f8f0e7;
    --ink-muted: #bcb1c5;
    --night: #17131f;
    --night-deep: #0e0b14;
    --panel: #211a2b;
    --panel-soft: #2b2236;
    --line: rgba(248, 240, 231, .14);
    --coral: #ff806a;
    --coral-bright: #ff9b86;
    --gold: #f2d89c;
    --violet: #9b86ff;
    --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
    --sans: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  }

  body {
    min-width: 320px;
    background:
      radial-gradient(circle at 12% 5%, rgba(155, 134, 255, .12), transparent 28rem),
      radial-gradient(circle at 88% 34%, rgba(255, 128, 106, .08), transparent 32rem),
      var(--night);
    color: var(--ink);
    font-family: var(--sans);
    font-size: 1rem;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
  }

  a { color: inherit; }
  h1, h2, h3 { font-family: var(--serif); font-weight: 500; line-height: 1.02; }
  h1 { font-size: clamp(3rem, 8vw, 6.8rem); letter-spacing: -.055em; }
  h2 { font-size: clamp(2.2rem, 5vw, 4rem); letter-spacing: -.04em; }
  h3 { font-size: 1.55rem; letter-spacing: -.02em; }

  ::selection { background: var(--coral); color: var(--night-deep); }
  :focus-visible { outline: 3px solid var(--gold); outline-offset: 4px; }
}

@layer components {
  .skip-link {
    position: fixed;
    top: .75rem;
    left: .75rem;
    z-index: 20;
    padding: .65rem .9rem;
    background: var(--ink);
    color: var(--night);
    transform: translateY(-160%);
    transition: transform .2s ease;
  }
  .skip-link:focus { transform: translateY(0); }

  .site-header {
    width: min(100% - 2rem, 88rem);
    min-height: 5.5rem;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2rem;
    border-bottom: 1px solid var(--line);
  }

  .brand {
    display: inline-flex;
    align-items: center;
    gap: .7rem;
    font-family: var(--serif);
    font-size: 1.18rem;
    font-weight: 600;
    letter-spacing: -.02em;
    text-decoration: none;
  }
  .brand svg { width: 2rem; height: 2rem; fill: none; stroke: var(--coral); stroke-width: 1.5; }

  nav { display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.5rem); }
  nav a, .footer-links a {
    color: var(--ink-muted);
    font-size: .84rem;
    font-weight: 650;
    letter-spacing: .08em;
    text-decoration: none;
    text-transform: uppercase;
  }
  nav a:hover, nav a[aria-current="page"], .footer-links a:hover { color: var(--ink); }

  .eyebrow {
    color: var(--coral-bright);
    font-size: .76rem;
    font-weight: 750;
    letter-spacing: .18em;
    text-transform: uppercase;
  }

  .button {
    min-height: 3.5rem;
    padding: .9rem 1.35rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: .88rem;
    font-weight: 750;
    letter-spacing: .04em;
    text-decoration: none;
    cursor: pointer;
    transition: transform .2s ease, background .2s ease, box-shadow .2s ease;
  }
  .button:hover { transform: translateY(-2px); }
  .button-primary {
    background: var(--coral);
    color: #211018;
    box-shadow: 0 .7rem 2.5rem rgba(255, 128, 106, .18);
  }
  .button-primary:hover { background: var(--coral-bright); box-shadow: 0 1rem 3rem rgba(255, 128, 106, .27); }

  footer {
    width: min(100% - 2rem, 88rem);
    margin: 0 auto;
    padding: 3rem 0;
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 2rem;
    border-top: 1px solid var(--line);
    color: var(--ink-muted);
    font-size: .9rem;
  }
  footer > div:first-child p { max-width: 28rem; margin-top: .8rem; }
  .footer-brand { color: var(--ink); }
  .footer-links { display: flex; flex-wrap: wrap; align-items: start; gap: 1.4rem; }
  .copyright { grid-column: 1 / -1; padding-top: 1.5rem; border-top: 1px solid var(--line); }
}

@layer pages {
  .hero {
    width: min(100% - 2rem, 88rem);
    min-height: min(49rem, calc(100vh - 5.5rem));
    margin: 0 auto;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(22rem, .95fr);
    align-items: center;
    gap: 2rem;
    overflow: hidden;
  }
  .hero-copy { position: relative; z-index: 2; padding: 5rem 0; }
  .hero h1 { max-width: 55rem; margin: 1rem 0 1.5rem; }
  .hero h1 em { color: var(--coral); font-weight: 400; }
  .hero-lead { max-width: 39rem; color: var(--ink-muted); font-size: clamp(1.08rem, 2vw, 1.3rem); }
  .hero .button { margin-top: 2.3rem; }
  .privacy-note { margin-top: 1rem; color: var(--ink-muted); font-size: .83rem; }
  .privacy-note span { color: var(--gold); }

  /* Sized against its own grid column, not the viewport. `47vw` is unrelated to
     the track the art actually sits in, so at 834px and 1280px it grew past it
     and `.hero`'s overflow clipped the constellation by ~13px. Firefox reported
     it; the other two engines hid it behind the same clip. */
  .orbit-art { width: min(100%, 38rem); justify-self: center; }
  .orbit-art svg { overflow: visible; }
  .orbit { fill: none; stroke: rgba(248, 240, 231, .17); stroke-width: 1.2; }
  .orbit-one { stroke-dasharray: 4 8; }
  .orbit-two { stroke-dasharray: 1 6; }
  .planet { filter: drop-shadow(0 0 2.5rem rgba(255, 128, 106, .12)); }
  .constellation { fill: none; stroke: rgba(242, 216, 156, .42); stroke-width: 1; }
  .stars { fill: var(--gold); }
  .orbit-art text { fill: var(--ink); font-family: var(--serif); font-size: 2rem; opacity: .8; }

  .tool-section {
    position: relative;
    isolation: isolate;
    padding: clamp(5rem, 10vw, 9rem) max(1rem, calc((100vw - 88rem) / 2));
    background:
      linear-gradient(rgba(255,255,255,.025) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255,255,255,.025) 1px, transparent 1px),
      var(--night-deep);
    background-size: 4rem 4rem;
    border-block: 1px solid var(--line);
    overflow: hidden;
  }
  /* A slow drift of light behind the tool, in the palette the site already
     uses. Deliberately CSS gradients rather than a canvas or WebGL shader:
     this is the section the whole product converts on, and a canvas there costs
     battery on a phone, adds a paint layer that behaves differently in every
     engine, and would be the fourth thing this week to look fine here and break
     on someone's real device. Layered radial gradients composite on the GPU,
     render identically everywhere and cost nothing measurable. */
  .tool-section::before {
    content: "";
    position: absolute;
    inset: -30%;
    z-index: -1;
    background:
      radial-gradient(38rem 26rem at 22% 28%, rgba(255, 128, 106, .17), transparent 62%),
      radial-gradient(34rem 30rem at 78% 24%, rgba(155, 134, 255, .16), transparent 62%),
      radial-gradient(30rem 24rem at 62% 82%, rgba(242, 216, 156, .11), transparent 60%),
      radial-gradient(26rem 22rem at 12% 78%, rgba(155, 134, 255, .10), transparent 60%);
    filter: blur(28px);
    animation: drift 42s ease-in-out infinite alternate;
    will-change: transform;
    pointer-events: none;
  }
  @keyframes drift {
    from { transform: translate3d(-3%, -2%, 0) scale(1.02); }
    to   { transform: translate3d(3%, 2%, 0) scale(1.12); }
  }
  @media (prefers-reduced-motion: reduce) {
    .tool-section::before { animation: none; }
  }
  .pair-form {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1.4rem;
  }
  /* The form's header row. `margin-bottom` here plus the grid `gap` above is the 3.5rem that
     used to sit under a standalone section heading, so the desktop rhythm is unchanged. */
  .form-heading { grid-column: 1 / -1; max-width: 49rem; margin-bottom: 2.1rem; }
  .form-heading h2 { margin: .75rem 0 1rem; }
  .form-heading > p:last-child { max-width: 39rem; color: var(--ink-muted); font-size: 1.08rem; }
  .person-card {
    min-width: 0;
    margin: 0;
    padding: clamp(1.4rem, 4vw, 2.4rem);
    border: 1px solid var(--line);
    border-radius: 1.5rem;
    background: rgba(33, 26, 43, .88);
    box-shadow: 0 1.5rem 5rem rgba(0, 0, 0, .2);
  }
  /* Direct child only. The birth date is now its own nested <fieldset>, and a
     descendant selector styled that one as a card title too -- in the card's
     serif at 1.55rem. */
  .person-card > legend {
    padding: 0 .6rem;
    font-family: var(--serif);
    font-size: 1.55rem;
  }
  .person-card > legend span {
    width: 2rem;
    height: 2rem;
    margin-right: .5rem;
    display: inline-grid;
    place-items: center;
    border: 1px solid var(--coral);
    border-radius: 50%;
    color: var(--coral-bright);
    font-family: var(--sans);
    font-size: .75rem;
  }
  .person-card label { display: block; margin: 1rem 0 .45rem; color: var(--ink-muted); font-size: .8rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
  .person-card input {
    width: 100%;
    min-height: 3.6rem;
    padding: .8rem 1rem;
    border: 1px solid rgba(248, 240, 231, .25);
    border-radius: .8rem;
    /* `background-color`, not the `background` shorthand: the shorthand resets
       background-image, and this rule sits in a later cascade layer than the
       one that draws the calendar mark on date inputs -- so it silently erased
       it. */
    background-color: var(--night);
    color: var(--ink);
  }
  .person-card input:focus { border-color: var(--coral); outline: 2px solid transparent; }
  /* Invisible, not gone. Chromium still draws its own picker button; hiding the
     glyph leaves our mark as the only one visible while the native button stays
     exactly where it is and keeps working as the click target. */
  .person-card input::-webkit-calendar-picker-indicator { opacity: 0; }
  .field-hint { margin-top: .65rem; color: var(--ink-muted); font-size: .82rem; }
  .plus { color: var(--gold); font-family: var(--serif); font-size: 2rem; }
  .form-action { grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; margin-top: 1.2rem; }
  .form-error { min-height: 1.5rem; margin-top: .65rem; color: var(--coral-bright); font-size: .9rem; }

  .result {
    margin-top: 5rem;
    border: 1px solid var(--line);
    border-radius: 1.75rem;
    background: linear-gradient(145deg, rgba(43, 34, 54, .98), rgba(23, 19, 31, .98));
    overflow: hidden;
    box-shadow: 0 2rem 8rem rgba(0, 0, 0, .28);
  }
  .result-intro { padding: clamp(1.5rem, 5vw, 3.5rem); }
  /* Wraps because two long sign names plus the mark between them do not fit a
     phone: "Capricorn × Gemini" overran its own container by 65px at 390px wide.
     The name size is already clamped to its floor at that width, so wrapping is
     what actually has to give. */
  .sign-pair { margin: 1.4rem 0 2.5rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1.2rem; }
  .sign-pair > div { display: flex; align-items: center; gap: .7rem; }
  /* Text presentation, not emoji. Left to themselves, iOS and Android both
     resolve the zodiac glyphs to their colour-emoji forms and paint purple
     tiles in the middle of a serif headline -- which is what the operator saw
     on Android. `font-variant-emoji` covers current browsers; a U+FE0E selector
     appended at render time covers the ones that ignore it. */
  .sign-symbol { color: var(--gold); font-family: var(--serif); font-size: 2rem; font-variant-emoji: text; }
  .sign-pair strong { font-family: var(--serif); font-size: clamp(1.8rem, 5vw, 3.4rem); font-weight: 500; }
  .pair-mark { color: var(--coral); font-family: var(--serif); font-size: 2rem; }
  .score-wrap { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 2rem; }
  .score-ring {
    --score-angle: 0deg;
    width: 8.5rem;
    aspect-ratio: 1;
    display: grid;
    place-content: center;
    border-radius: 50%;
    background: radial-gradient(circle at center, var(--panel) 57%, transparent 59%), conic-gradient(var(--coral) var(--score-angle), rgba(255,255,255,.1) 0);
    font-family: var(--serif);
    font-size: 2.4rem;
  }
  .score-ring.score-band-0 { --score-angle: 36deg; }
  .score-ring.score-band-1 { --score-angle: 108deg; }
  .score-ring.score-band-2 { --score-angle: 180deg; }
  .score-ring.score-band-3 { --score-angle: 252deg; }
  .score-ring.score-band-4 { --score-angle: 324deg; }
  .score-ring small { color: var(--ink-muted); font-family: var(--sans); font-size: .68rem; text-align: center; }
  .result-label { margin-bottom: .35rem; color: var(--gold); font-family: var(--serif); font-size: 1.75rem; }
  #result-summary { max-width: 39rem; color: var(--ink-muted); }
  .result-faces { max-width: 39rem; margin-top: .5rem; color: var(--gold); font-family: var(--serif); font-style: italic; font-size: .98rem; }
  .result-weight { max-width: 39rem; margin-top: .6rem; color: var(--ink-muted); font-size: .88rem; }
  .result-omen {
    max-width: 46rem;
    margin-top: 2.2rem;
    padding-top: 1.8rem;
    border-top: 1px solid var(--line);
    color: var(--gold);
    font-family: var(--serif);
    font-size: clamp(1.15rem, 2.4vw, 1.5rem);
    font-style: italic;
    line-height: 1.5;
  }
  /* Six tracks so the five cards break 3 + 2 instead of leaving a hole in the
     second row. The border rules below are written for exactly five cards:
     3 and 5 end a row, 4 and 5 sit on the last one. Adding or removing a card
     means revisiting them. */
  .result-grid { display: grid; grid-template-columns: repeat(6, 1fr); border-top: 1px solid var(--line); }
  .result-grid article { grid-column: span 2; min-height: 15rem; padding: 2rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
  .result-grid article:nth-child(4), .result-grid article:nth-child(5) { grid-column: span 3; border-bottom: 0; }
  .result-grid article:nth-child(3), .result-grid article:nth-child(5) { border-right: 0; }
  .result-grid h3 { margin: 1.1rem 0 .8rem; }
  .result-grid p { color: var(--ink-muted); font-size: .94rem; }
  .card-number { color: var(--coral); font-size: .72rem; font-weight: 750; letter-spacing: .12em; }
  .result-actions { padding: 1.2rem 2rem; display: flex; justify-content: space-between; gap: 1rem; border-top: 1px solid var(--line); color: var(--ink-muted); font-size: .82rem; }
  /* 44px tall because this is the button that starts a second reading, and it
     sat at roughly 26px on every phone in the matrix. Padding alone would have
     moved the underline away from the text, so the height comes from the box
     and the text stays centred in it. */
  .text-button {
    min-height: 44px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    border: 0;
    background: none;
    color: var(--ink);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: .25em;
  }

  .principles { width: min(100% - 2rem, 88rem); margin: 0 auto; padding: clamp(5rem, 10vw, 9rem) 0; }
  .principle-grid { margin-top: 2rem; display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1px solid var(--line); }
  .principle-grid article { padding: 2rem 2rem 2rem 0; }
  .principle-grid article + article { padding-left: 2rem; border-left: 1px solid var(--line); }
  .principle-grid span { color: var(--coral); font-size: .72rem; font-weight: 750; letter-spacing: .12em; }
  .principle-grid h2 { margin: 1rem 0; font-size: 2rem; }
  .principle-grid p { color: var(--ink-muted); }

  .article-shell { width: min(100% - 2rem, 58rem); margin: 0 auto; padding: clamp(5rem, 10vw, 9rem) 0; }
  .article-shell h1 { margin: 1rem 0 1.5rem; font-size: clamp(3rem, 8vw, 5.7rem); }
  .article-lead { max-width: 45rem; color: var(--ink-muted); font-size: 1.2rem; }
  .prose { margin: 4rem 0; padding-top: 1rem; border-top: 1px solid var(--line); }
  .prose h2 { margin: 3rem 0 1rem; font-size: 2.1rem; }
  .prose p { margin-bottom: 1.2rem; color: var(--ink-muted); }
  .prose a { color: var(--ink); text-underline-offset: .2em; }
  .prose aside { margin-top: 2.5rem; padding: 1.5rem; border-left: 3px solid var(--coral); background: var(--panel); color: var(--ink-muted); }
  .prose aside strong { color: var(--ink); }
  .updated { font-size: .88rem; }

  .not-found { width: min(100% - 2rem, 46rem); min-height: 100vh; margin: 0 auto; display: grid; place-content: center; text-align: center; }
  .not-found h1 { margin: 1rem 0; font-size: clamp(3rem, 8vw, 5rem); }
  .not-found p:not(.eyebrow) { color: var(--ink-muted); }
  .not-found .button { margin: 2rem auto 0; }

  /* Below this width the hero stacks, so every ornament in it is pure vertical distance between
     the promise and the tool. The rhythm tightens step by step from here down; nothing is
     removed -- the eyebrow, the headline, the lead, the "Read the connection" call to action, the
     privacy line and the constellation are all still on the page, just no longer spending a
     screen and a half of scroll before the first date field. */
  @media (max-width: 52rem) {
    .hero { min-height: auto; grid-template-columns: 1fr; gap: 1rem; }
    .hero-copy { padding: 3rem 0 0; }
    .hero h1 { margin: .6rem 0 1rem; }
    .hero .button { margin-top: 1.7rem; }
    .orbit-art { width: min(70vw, 26rem); margin-bottom: 2rem; }
    .tool-section { padding-block-start: 3.5rem; }
    .form-heading { margin-bottom: .5rem; }
    .pair-form { grid-template-columns: 1fr; }
    .plus { justify-self: center; }
    .result-grid, .principle-grid { grid-template-columns: 1fr; }
    /* Stacked, the 3 + 2 spans and their row-end border rules stop meaning
       anything, and `span 2` against a single track would invent columns. Undo
       both at the same specificity that set them. */
    .result-grid article,
    .result-grid article:nth-child(3),
    .result-grid article:nth-child(4),
    .result-grid article:nth-child(5) { grid-column: auto; min-height: auto; border-right: 0; border-bottom: 1px solid var(--line); }
    .result-grid article:last-child { border-bottom: 0; }
    .principle-grid article, .principle-grid article + article { padding: 1.7rem 0; border-left: 0; border-bottom: 1px solid var(--line); }
  }

  @media (max-width: 38rem) {
    .site-header { min-height: 4.5rem; }
    .site-header nav a:first-child { display: none; }
    .hero-copy { padding-top: 2.25rem; }
    /* 3rem headline wrapped to three lines at 390px and pushed the whole page down with it.
       2.5rem lets the authored line break do its job, so the headline is the two lines it was
       written as. */
    .hero h1 { font-size: 2.5rem; }
    .orbit-art { width: min(56vw, 15rem); margin-bottom: 1.25rem; }
    .form-heading h2 { font-size: 1.95rem; margin: .5rem 0 .6rem; }
    .form-heading > p:last-child { font-size: .98rem; }
    /* Stacked rather than wrapped, so the mark sits between the two names the
       way the form's "+" sits between the two cards. Left to wrap, it trailed
       off the end of the first name with nothing after it. */
    .sign-pair { flex-direction: column; align-items: stretch; margin-bottom: 1.9rem; gap: .5rem; }
    .sign-pair strong { font-size: 1.7rem; }
    .sign-symbol { font-size: 1.5rem; }
    .pair-mark { font-size: 1.5rem; text-align: center; }
    .score-wrap { grid-template-columns: 1fr; }
    .score-ring { width: 7.5rem; }
    .result-actions, footer { grid-template-columns: 1fr; flex-direction: column; }
    footer { display: grid; }
    .copyright { grid-column: 1; }
  }

  @media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { transition-duration: .01ms !important; }
  }
}

/* ---------------------------------------------------------------------------
   Ad slots.

   The height table below is the SAME table as packages/ad-slot/src/states.js
   `reservedBlockSizePx` (base / >=768 / >=1280), and test/site.test.js compares all
   eighteen values against that function rather than trusting this comment. Shape adapted
   from design/design-v1/adslot.css onto this site's own tokens.

   `block-size` is fixed, never min-height, never auto: `contain: size` makes the box's
   layout size causally independent of its child, so an oversized or expanding creative
   cannot grow it, and `overflow: clip` keeps it from reaching documentElement.scrollWidth.
   Every state is the same height, so no transition between them shifts the page.
   --------------------------------------------------------------------------- */
@layer components {
  :root {
    --adslot-h-A: 0px; --adslot-h-B: 280px; --adslot-h-C: 280px;
    --adslot-h-D: 280px; --adslot-h-E: 0px; --adslot-h-F: 66px;
  }
  @media (min-width: 768px) {
    :root { --adslot-h-A: 106px; --adslot-h-D: 106px; --adslot-h-F: 116px; }
  }
  @media (min-width: 1280px) {
    :root { --adslot-h-E: 280px; }
  }

  .sf-adslot {
    display: grid;
    place-items: center;
    inline-size: 100%;
    block-size: var(--sf-adslot-h);
    overflow: clip;
    overflow-clip-margin: 0px;
    contain: layout size paint;
    margin-block: 4rem 0;
    padding: 0 1rem;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 1.1rem;
    color: var(--ink-muted);
    text-align: center;
  }
  .sf-adslot-note {
    font-size: .78rem;
    font-weight: 650;
    letter-spacing: .14em;
    text-transform: uppercase;
  }
  /* Once a creative is in the box the house line steps aside; the box does not move. */
  .sf-adslot[data-sf-adslot-state="filled"] .sf-adslot-note { display: none; }

  /* An unconfigured slot renders NOTHING -- no box, no border, no house line, no
     reserved height.

     AdSense mints ad-unit ids only after it approves a site, so `data-ad-unit` is
     empty for as long as review takes -- days to weeks. Holding 280px of bordered
     emptiness captioned ADVERTISEMENT for every visitor across that window is a
     hole in the page that looks broken, and it is what the AdSense reviewer sees
     too. The zero-CLS argument does not apply here: layout shift is what happens
     when a creative lands during a page view, and no creative can land in a slot
     with no unit id. Reserving space for an ad that cannot arrive buys nothing and
     costs the page.

     The reserved height comes back with the unit id, in the same deploy -- which is
     a new page load, not a shift. */
  .sf-adslot[data-ad-unit=""] { display: none; }
  .sf-adslot .adsbygoogle { inline-size: 100%; block-size: 100%; }
}

/* ---------------------------------------------------------------------------
   Touch targets. Every navigation link was 22-32px tall -- comfortably under the
   44px minimum this project already committed to in docs/36-mobile-ios-pwa.md.
   It had been that way since the site was written; nothing could see it, because
   the committed checks measured HTTP and Lighthouse scores, not whether a thumb
   can hit a link. site-responsive-check.mjs found it on 2026-07-31.

   The fix is padding, not font size: the hit area grows to 44px while the type
   and the layout stay exactly as designed. Negative inline margin keeps the
   visual gaps unchanged so nothing moves.
   --------------------------------------------------------------------------- */
@layer components {
  .site-header nav a,
  .site-header .brand,
  footer a,
  footer .brand {
    /* The links were 22-32px tall against a 44px minimum. They were never too
       NARROW -- 53 to 147px wide -- so only the block axis needs growing, and
       inline-flex with a min block size does it without touching the inline box
       at all. The first version of this rule also added inline padding with a
       negative margin to cancel it; that made every link paint past its
       container's trailing edge, which is a spill on every page and a wrapped
       footer row. Growing one axis is enough; do not reintroduce the other. */
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
  }
}


/* ---------------------------------------------------------------------------
   The birth date is three <select>s, not <input type="date">.

   The native control was tried and abandoned: it takes a fixed 379px intrinsic
   width on iOS and ignores `width: 100%`, paints nothing at all when empty on
   iOS, is enforced silently by Safari so the submit button reads as dead, and
   collapses its own segments to "dd------yyyy" in Chrome once the box narrows
   or the locale runs wider than en-GB. Firefox draws a picker button over
   anything placed at the inline end. Fixing one broke another.

   Selects behave the same in every browser on every platform, so what is left
   here is only layout.
   --------------------------------------------------------------------------- */
@layer components {
  fieldset { min-inline-size: 0; }

  .date-parts {
    min-inline-size: 0;
    margin: 0;
    padding: 0;
    display: grid;
    /* Day and month need room for "September"; the year is a fixed four
       digits. `minmax(0, ...)` because a grid track refuses to shrink below its
       content otherwise, which is how the old field escaped its card. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr) minmax(0, 1fr);
    gap: .5rem;
    border: 0;
  }
  .date-parts > legend {
    padding: 0;
    margin-block-end: .45rem;
    color: var(--ink-muted);
    font-family: var(--sans);
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
  }
  .date-part { min-inline-size: 0; display: block; }
  /* The per-part labels are for assistive tech; the option text already says
     "Day", "Month", "Year" on screen, and repeating it wastes a phone's height. */
  .date-part > label {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .date-parts select {
    inline-size: 100%;
    max-inline-size: 100%;
    min-inline-size: 0;
    /* 44px minimum, and comfortably above it: this is the control the whole
       product depends on being easy to hit. */
    min-block-size: 3.4rem;
    padding: .8rem 2.1rem .8rem .85rem;
    -webkit-appearance: none;
    appearance: none;
    border: 1px solid rgba(248, 240, 231, .25);
    border-radius: .8rem;
    background-color: var(--night);
    background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23bcb1c5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>');
    background-repeat: no-repeat;
    background-position: right .7rem center;
    background-size: 1rem;
    color: var(--ink);
    font-family: var(--sans);
    font-size: 1rem;
    text-overflow: ellipsis;
  }
  .date-parts select:focus-visible { border-color: var(--coral); }

  /* Three across does not survive a phone. Measured at 390px with the widest
     real values: "September" truncated to "Septem..." and 1987 to "19...",
     which makes the year unreadable -- and the year is the part a visitor most
     needs to confirm. Day and month share the first row, the year takes the
     second on its own, where it has room to spell itself out. */
  @media (max-width: 30rem) {
    .date-parts { grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); }
    .date-part:last-child { grid-column: 1 / -1; }
  }
  /* The dropdown list itself is drawn by the OS, which uses the system palette;
     naming both keeps the open list readable on a dark page. */
  .date-parts option { background: var(--panel); color: var(--ink); }
}
