/* ═══════════════════════════════════════════════════════════════════
   Aria Snow — Christening invitation
   Layout and styling only. All event copy lives in index.html.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Fonts ──────────────────────────────────────────────────────────
   Self-hosted OFL subsets (see fonts/*-OFL.txt). Fallback metrics are
   measured, not guessed: Cormorant's x-height is 80.2% of Georgia's,
   so size-adjust holds the line length steady across the font swap. */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("fonts/cormorant-garamond-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("fonts/cormorant-garamond-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Parisienne";
  src: url("fonts/parisienne-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Cormorant Fallback";
  src: local("Georgia"), local("Times New Roman"), local("serif");
  size-adjust: 80.2%;
  ascent-override: 115.2%;
  descent-override: 35.8%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Parisienne Fallback";
  src: local("Snell Roundhand"), local("Georgia"), local("serif");
  size-adjust: 73.3%;
  ascent-override: 124.9%;
  descent-override: 60.9%;
  line-gap-override: 0%;
}

/* ── Tokens ─────────────────────────────────────────────────────── */

:root {
  /* Ground and ink */
  --cream:      #faf6ef;
  --card:       #fdfaf4;
  --ink:        #2b1d11;
  --ink-body:   #3a2a19;
  --ink-quiet:  #4b3927;

  /* Gold: --gold-ink is the text-safe tone (6.3:1 on card).
     --gold is decorative only (rules, cross, frame). */
  --gold-ink:   #67500f;
  --gold-deep:  #5a4611;
  --gold:       #b08d3f;
  --gold-soft:  #ddc9a0;

  /* Pastels — the attire palette */
  --blush:      #f2c9ce;
  /* Deep rose for text. The blush above is far too pale
     to read as type; this is its readable sibling (6.1:1 on the card). */
  --rose:       #9c4159;
  --rose-deep:  #7e2a40;

  /* Button fill lives behind these two, so the whole set can be switched
     between gold and rose by editing just here.
       gold: var(--gold-ink) / var(--gold-deep)
       rose: var(--rose)     / var(--rose-deep)   */
  --btn-bg:       var(--gold-ink);
  --btn-bg-hover: var(--gold-deep);
  --butter:     #f7e9c3;
  --sage:       #cfd8b4;
  --nude:       #e3c8b0;

  /* Type */
  --serif:  "Cormorant Garamond", "Cormorant Fallback", Georgia, serif;
  --script: "Parisienne", "Parisienne Fallback", "Snell Roundhand", cursive;

  /* Metrics */
  --nav-h:   3rem;
  --measure: 34rem;
  --frame:   clamp(0.75rem, 3vw, 1.5rem);

  /* Derived tints. Written out rather than computed with relative-colour
     syntax, which older phone browsers do not support. Each notes its source. */
  --veil:          rgba(250, 246, 239, 0.97);  /* --cream  @ 97% */
  --hairline:      rgba(176, 141, 63, 0.45);   /* --gold   @ 45% */
  --hairline-soft: rgba(176, 141, 63, 0.35);   /* --gold   @ 35% */
  --chip-ring:     rgba(54, 37, 23, 0.20);     /* --ink    @ 20% */
  --white:         #ffffff;
  --on-gold:       #fffdf8;

  /* Motion. One curve for everything: a confident arrival that decelerates
     hard and never overshoots. Bounce would be wrong for an invitation.

     Tempo lives here — every entrance reads from these, so the whole page
     can be slowed or quickened from one place. Hover feedback is
     deliberately NOT in this set: it must stay quick or it feels like lag. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  --dur-reveal:   950ms;   /* a content group arriving          */
  --dur-hero:    1250ms;   /* each step of the hero cascade     */
  --dur-settle:  1600ms;   /* the name coming into focus        */
  --dur-frame:   1500ms;   /* the card frame composing itself   */
  --step-group:    90ms;   /* per group, down a card            */
  --step-stagger:  70ms;   /* per item, in a genuine list       */
  --step-hero:    115ms;   /* per element, in the hero cascade  */

  /* Escape hatch: point this at a floral border image to replace the
     plain paper — see design.md Decision 4. Nothing else changes. */
  --floral-border: none;
}

/* ── Reset ──────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink-body);
  font-family: var(--serif);
  font-size: clamp(1.0625rem, 1rem + 0.5vw, 1.25rem);
  line-height: 1.65;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, p, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; }

/* Browser surfaces we did not draw still belong to the design. */
::selection {
  background: var(--blush);
  color: var(--ink);
}
body { caret-color: var(--gold-ink); }

@supports (scrollbar-color: auto) {
  html { scrollbar-color: var(--gold-soft) transparent; scrollbar-width: thin; }
}
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--gold-soft);
  border: 3px solid var(--cream);
  border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover { background: var(--gold); }

:focus-visible {
  outline: 2px solid var(--gold-ink);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Quickjump nav ──────────────────────────────────────────────────
   position: sticky, not fixed — it stays in flow so the hero begins
   beneath it and the full-height maths stay honest (design Decision 11). */

.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--veil);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--hairline);
}

.nav--hidden { transform: translateY(-100%); }

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(0.85rem, 4vw, 2rem);
  /* Any overflow scrolls inside the bar — never widens the document. */
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 0 1rem;
}
.nav__list::-webkit-scrollbar { display: none; }

.nav__link {
  display: block;
  position: relative;
  white-space: nowrap;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  padding: 0.35rem 0;
}

.nav__link--rsvp {
  color: var(--gold-ink);
  font-weight: 600;
}

/* ── Card shell ─────────────────────────────────────────────────── */

.card {
  position: relative;
  min-height: 100vh;          /* fallback first */
  min-height: 100svh;         /* small-viewport unit: no mobile URL-bar jump */
  display: grid;
  place-items: center;
  padding: clamp(2.5rem, 8vw, 4.5rem) clamp(1.25rem, 5vw, 3rem);
  background: var(--card);
  /* Anchor targets clear the returning nav bar. */
  scroll-margin-top: calc(var(--nav-h) + 0.75rem);
}

/* The hero sits below the nav, so it gets the remaining height —
   otherwise its centred content is pushed below the fold on load. */
.card:first-of-type {
  min-height: calc(100vh - var(--nav-h));
  min-height: calc(100svh - var(--nav-h));
}

/* Short viewports (landscape phones): let content set the height. */
@media (max-height: 600px) {
  .card, .card:first-of-type { min-height: auto; }
}

/* Optional floral artwork overlay — off by default. */
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--floral-border);
  background-size: cover;
  background-position: center;
  pointer-events: none;
}

/* Hairline inset frame, as on the reference cards. */
.card::after {
  content: "";
  position: absolute;
  inset: var(--frame);
  border: 1px solid var(--hairline-soft);
  pointer-events: none;
}

.card__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  text-align: center;
}

/* ── Shared type ────────────────────────────────────────────────── */

.script {
  font-family: var(--script);
  font-weight: 400;
  color: var(--rose);
  line-height: 1.25;
}
.script--lg { font-size: clamp(2.25rem, 9vw, 3.5rem); }
.script--md { font-size: clamp(1.75rem, 6vw, 2.5rem); }
.script--sm { font-size: clamp(1.5rem, 5vw, 1.875rem); }

.section-title {
  font-size: clamp(1.75rem, 6.5vw, 2.75rem);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--ink);
  margin-bottom: 1.5rem;
}

.eyebrow {
  font-style: italic;
  color: var(--ink-quiet);
  font-size: 1.0625rem;
}

.prose {
  max-width: 30rem;
  margin-inline: auto;
  margin-bottom: 1.25rem;
  text-wrap: pretty;
}
.prose strong { font-weight: 600; color: var(--rose); }
.prose--quiet {
  font-style: italic;
  color: var(--ink-quiet);
  font-size: 0.9375em;
}

.rule {
  width: min(9rem, 45%);
  height: 1px;
  margin: clamp(1.5rem, 4vw, 2.25rem) auto;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}

.cross {
  width: clamp(1.35rem, 4vw, 1.75rem);
  height: auto;
  fill: var(--gold);
  margin-bottom: 1.5rem;
}
.cross--sm { width: 1.125rem; margin-bottom: 1.25rem; }

/* ── Hero ───────────────────────────────────────────────────────── */
/* The hero used to carry four competing treatments — script, bold caps,
   tracked caps and italic — all within one card. It now runs on two:
   roman for the facts, italic for the connective phrases. Capitals are
   reserved for exactly two lines (the occasion and the date) so they
   still signal importance instead of becoming the default. */

.hero__occasion { margin: 0.5rem 0 0.25rem; }

.hero__baptism {
  display: block;
  font-size: clamp(1.5rem, 6vw, 2.125rem);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.2;
}

.hero__relation {
  font-style: italic;
  color: var(--ink-quiet);
  margin-top: 0.85rem;
}

/* Aria herself, between "our daughter" and her name. Cropped to a circle
   by CSS so the source stays a plain square; the gold hairline ring
   matches the card frame, and the white gap keeps it off the photo. */
.hero__photo {
  display: block;
  width: clamp(11.25rem, 51vw, 15rem);
  aspect-ratio: 1;
  height: auto;
  object-fit: cover;
  border-radius: 50%;
  margin: 1.1rem auto 0.9rem;
  padding: 3px;
  background: var(--card);
  border: 1px solid var(--gold-soft);
}

/* The one moment that should dominate the card. */
.hero__name {
  font-size: clamp(2.75rem, 13vw, 4.5rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
  line-height: 1.05;
  margin-top: 0.25rem;
}

.hero__date {
  font-weight: 600;
  font-size: clamp(1.0625rem, 3.6vw, 1.25rem);
  letter-spacing: 0.16em;
  color: var(--ink);
  text-transform: uppercase;
}
.hero__time {
  font-style: italic;
  color: var(--ink-quiet);
  margin-bottom: 1.75rem;
}

.hero__venue { margin-bottom: 1.15rem; }

/* Sentence case, not capitals: these were competing with the date for
   the same emphasis and neither was winning. */
.hero__venue-name {
  display: block;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
  font-size: clamp(1.0625rem, 3.4vw, 1.1875rem);
  line-height: 1.3;
}
.hero__venue-address,
.hero__reception-lead {
  display: block;
  font-style: italic;
  color: var(--ink-quiet);
  font-size: 0.9375rem;
}
.hero__reception-lead { margin-bottom: 0.2rem; }
/* ── Attire swatches ────────────────────────────────────────────── */

.swatches {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1rem, 5vw, 2.5rem) clamp(1.25rem, 5vw, 2.5rem);
  margin: 1.75rem 0 0.5rem;
}
.swatch {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.swatch__chip {
  width: clamp(2.5rem, 9vw, 3.25rem);
  aspect-ratio: 1;
  border-radius: 50%;
  display: block;
  box-shadow: inset 0 0 0 1px var(--chip-ring);
}
.swatch__chip--pink  { background: var(--blush); }
.swatch__chip--nude  { background: var(--nude); }
.swatch__chip--white { background: var(--white); }

.swatch__label {
  font-size: 0.8125rem;
  white-space: nowrap;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}

/* ── Gift QR codes ──────────────────────────────────────────────── */

/* Two by two on every width: four in a row would shrink the codes below
   what a phone camera reads comfortably from another screen. */
.qrs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 11rem));
  justify-content: center;
  gap: clamp(1.25rem, 5vw, 2rem) clamp(1rem, 5vw, 2rem);
  margin: 1.75rem 0 2rem;
}
.qr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.qr__label {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}
/* White tile, not the cream card: scanners want the quiet zone to read
   as true white, and the hairline sets each code apart as its own slip. */
.qr__code {
  display: block;
  width: 100%;
  height: auto;
  background: var(--white);
  padding: 0.35rem;
  border: 1px solid var(--hairline-soft);
  border-radius: 2px;
}

/* ── Health protocols ───────────────────────────────────────────── */

.protocols {
  display: grid;
  gap: 0.85rem;
  max-width: 26rem;
  margin: 1.5rem auto 0;
  text-align: left;
}
.protocol {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: baseline;
  font-weight: 600;
  color: var(--ink);
  font-size: 1.0625rem;
}
.protocol__icon {
  color: var(--rose);
  font-size: 0.5rem;
  line-height: 2.4;
}

/* ── Venues ─────────────────────────────────────────────────────── */

.venues {
  display: grid;
  gap: clamp(1.5rem, 5vw, 2.5rem);
  margin-top: 1.5rem;
}
@media (min-width: 40rem) {
  .venues { grid-template-columns: 1fr 1fr; }
}

.venue__role {
  font-style: italic;
  color: var(--ink-quiet);
  font-size: 0.9375rem;
}
.venue__name {
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
  font-size: 1.0625rem;
  margin-top: 0.15rem;
}
.venue__address {
  font-style: italic;
  color: var(--ink-quiet);
  font-size: 0.9375rem;
  margin-bottom: 0.6rem;
}
.venue__map {
  display: inline-block;
  margin-top: 0.15rem;
  padding: 0.6rem 1.35rem;
  background: var(--btn-bg);
  color: var(--on-gold);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--btn-bg);
  border-radius: 2px;
}

/* ── Godparents ─────────────────────────────────────────────────── */

.godparents {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 5vw, 3rem);
  margin-top: 1rem;
}
.godparents__group {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.godparents__group h3 { margin-bottom: 0.5rem; }

/* Names read left-aligned inside a centred block, so the numerals form a
   clean column the way they do on the printed reference cards. */
.names {
  counter-reset: n;
  text-align: left;
}
.names li {
  counter-increment: n;
  font-size: clamp(0.9375rem, 3.4vw, 1.0625rem);
  line-height: 1.6;
  color: var(--ink-body);
  padding-left: 1.6em;
  text-indent: -1.6em;
}
.names li::before {
  content: counter(n) ".";
  display: inline-block;
  width: 1.35em;
  margin-right: 0.25em;
  text-align: right;
  color: var(--rose);
  font-size: 0.8em;
}

.placeholder-note {
  margin-top: 1.75rem;
  font-style: italic;
  font-size: 0.875rem;
  color: var(--ink-quiet);
}

/* ── Godparents page ──────────────────────────────────────────────── */

/* A smaller setting of the name, since here it is context rather than
   the headline — the word "Godparents" leads this page. */
.hero__name--sm { font-size: clamp(1.75rem, 7vw, 2.5rem); }

/* The single most important line on the page: when to arrive. */
.callout {
  margin: 1.25rem auto 1rem;
  padding: 0.9rem 1.5rem;
  max-width: 24rem;
  border: 1px solid var(--hairline);
  border-radius: 2px;
  background: var(--veil);
  font-size: 1.0625rem;
  color: var(--ink-body);
}
.callout strong {
  display: block;
  margin-top: 0.15rem;
  font-size: clamp(1.375rem, 5vw, 1.75rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
}

/* The columns are uneven (10 names vs 9), so this line lands right under
   the longer one and needs room of its own to read as a separate thought. */
.gp-thanks { margin-top: clamp(2rem, 6vw, 3rem); }

.backlink {
  margin-top: 2.25rem;
  font-style: italic;
  font-size: 0.9375rem;
}
.backlink a {
  color: var(--ink-quiet);
  text-underline-offset: 3px;
  text-decoration-color: var(--gold-soft);
}
.backlink a:hover { color: var(--rose); }

/* ── The ask (godparent invite) ───────────────────────────────────── */

.ask__question {
  font-size: clamp(2rem, 8.5vw, 3.25rem);
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1.15;
  color: var(--ink);
  margin: 0.5rem 0 0.25rem;
  text-wrap: balance;
}

.choice {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.85rem 1rem;
  margin-top: 0.5rem;
}

/* ── Closing ────────────────────────────────────────────────────── */

.card__inner--center { display: grid; justify-items: center; }

.closing__line { margin-bottom: 1.25rem; }

.closing__signoff { margin-bottom: 2rem; }
.closing__love {
  display: block;
  font-style: italic;
  color: var(--ink-quiet);
}
.closing__name {
  display: block;
  font-weight: 600;
  font-size: clamp(1.5rem, 5.5vw, 2rem);
  letter-spacing: 0.02em;   /* matches .hero__name */
  color: var(--ink);
}

/* ── Peeking photos ─────────────────────────────────────────────── */

/* Any card can carry the two cut-outs of Aria by adding .card--photos
   and the two <img class="card__photo ..."> as direct children.

   The photos reach the card's own edges, so the card drops its side
   and bottom padding and hands the side padding to the text instead. */
.card--photos {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "crawl" "content" "peek";
  place-items: initial;
  align-content: space-between;
  row-gap: 0.5rem;
  padding: clamp(1.5rem, 5vw, 2.5rem) 0 0;
}
.card--photos > .card__inner {
  grid-area: content;
  padding-inline: clamp(1.25rem, 5vw, 3rem);
}

/* Above the hairline frame, so she sits in front of it, not behind. */
.card__photo {
  position: relative;
  z-index: 2;
  display: block;
  height: auto;
  align-self: end;
}
/* Narrow screens: the text needs the full width, so each photo takes a
   row of its own and grows with the screen — upper left, lower right. */
.card__photo--crawl { grid-area: crawl; justify-self: start;  width: min(64vw, 24rem); --i: 0; }
.card__photo--peek  { grid-area: peek;  justify-self: end;    width: min(60vw, 22rem); --i: 4; }

/* Wide screens: there is now a clear gutter either side of the text
   column (--measure), so the first two photos move out of the rows and
   into those gutters — upper left and lower right, centred on the 20%
   and 80% lines — sized to fill the gutter exactly, which is what keeps
   them off the RSVP content. */
@media (min-width: 60rem) {
  .card--photos {
    /* vw rather than %, because this also feeds `top` below, where a
       percentage would mean the card's height instead of its width. */
    --gutter: calc((100vw - var(--measure)) / 2 - 1.5rem);
    grid-template-areas: "content";
    align-content: center;
    padding-block: clamp(2.5rem, 8vw, 4.5rem);
  }
  .card--photos > .card__inner { align-self: center; }
  .card__photo--crawl,
  .card__photo--peek {
    --w: min(var(--gutter), 28rem);
    position: absolute;
    grid-area: auto;
    width: var(--w);
  }
  /* Centred on the 20% and 80% lines of the card. --h is each photo's
     height as a multiple of its width (900/816 and 900/711), which lets
     the max()/min() keep a tall photo inside the card on a short screen
     instead of letting the centring push it off the edge. */
  .card__photo--crawl {
    --h: 1.103;
    left: 0;
    top: max(1rem, calc(20% - var(--w) * var(--h) / 2));
    --i: 4;
  }
  .card__photo--peek {
    --h: 1.266;
    right: 0;
    top: min(calc(80% - var(--w) * var(--h) / 2), calc(100% - var(--w) * var(--h) - 1rem));
    --i: 5;
  }
}

.btn {
  display: inline-block;
  padding: 0.95rem 2.75rem;
  background: var(--btn-bg);
  color: var(--on-gold);
  font-size: 0.875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--btn-bg);
  border-radius: 2px;
  box-shadow: 0 1px 2px rgba(54, 37, 23, 0.12), 0 6px 16px rgba(54, 37, 23, 0.10);
}
/* Hover fill uses --gold-ink, not --gold: cream on --gold measures 3.07:1,
   which fails AA for the button's small-caps label. --gold-ink gives 4.87:1. */
.btn:hover {
  background: var(--gold-ink);
  border-color: var(--gold-ink);
  color: var(--on-gold);
}

/* The RSVP is the one action the whole invitation leads to, so it is
   larger than the other buttons (about 218 x 65px), and its label is
   larger again — the padding is trimmed to make room for the bigger
   label without the button itself growing. The nav's RSVP is a
   .nav__link, not a .btn, so it is unaffected. */
.btn[data-rsvp] {
  font-size: 1.3rem;
  padding: 0.9rem 2.45rem;
}

/* ── Unconfigured links ─────────────────────────────────────────────
   Applied by main.js while an href is still a #TODO- placeholder, so a
   dead link looks unfinished rather than broken. */

[aria-disabled="true"] {
  opacity: 0.42;
  cursor: not-allowed;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.btn[aria-disabled="true"]:hover {
  background: transparent;
  color: var(--ink);
}

/* ═══════════════════════════════════════════════════════════════════
   Motion

   One idea, stated once and then whispered: things arrive slightly out
   of focus and settle. The hero says it loudly — the name resolves from
   a blur with its tracking easing in — and everywhere else it is a short
   rise and fade.

   Content is fully visible by default. The starting states below are
   scoped to `.js`, so a script failure leaves an un-animated page rather
   than a blank one.
   ═══════════════════════════════════════════════════════════════════ */

/* Smooth anchor scrolling runs unconditionally, by request. It is a
   short in-page traversal, not a decorative effect. */
html { scroll-behavior: smooth; }

.js [data-reveal] {
  opacity: 0;
  --dur: var(--dur-reveal);
  --delay: calc(var(--i, 0) * var(--step-group) + var(--j, 0) * var(--step-stagger));
  transform: translateY(var(--rise, 18px));
  transition:
    opacity        var(--dur) var(--ease) var(--delay, 0ms),
    transform      var(--dur) var(--ease) var(--delay, 0ms),
    filter         var(--dur) var(--ease) var(--delay, 0ms),
    letter-spacing var(--dur) var(--ease) var(--delay, 0ms);
}

.js .is-revealed [data-reveal] {
  opacity: 1;
  transform: none;
}

/* Items inside a genuine list carry --j; everything else leaves it unset
   and simply follows its group's place in the cascade. */

/* ── The authored moment: the name settling into focus ────────────── */

.js #hero [data-reveal] {
  --dur: var(--dur-hero);
  --step-group: var(--step-hero);
}

.js [data-settle] {
  --dur: var(--dur-settle);
  --rise: 10px;
  filter: blur(9px);
  letter-spacing: 0.3em;
}
.js .is-revealed [data-settle] {
  filter: blur(0);
  letter-spacing: 0.06em;   /* matches .hero__name resting tracking */
}

/* The frame eases in from just outside its resting inset, so the card
   composes itself around the name rather than being there first. */
.js #hero.card::after {
  opacity: 0;
  transform: scale(1.012);
  transition: opacity var(--dur-frame) var(--ease) 150ms, transform var(--dur-frame) var(--ease) 150ms;
}
.js #hero.is-revealed.card::after {
  opacity: 1;
  transform: none;
}

/* ── Micro-interactions ───────────────────────────────────────────── */

/* Nav underline sweeps from the centre — same hairline material as the
   card frame, so the interaction belongs to the world. */
.nav__link {
  position: relative;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--gold);
  transform: scaleX(0);
  transition: transform 260ms var(--ease);
}
.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="true"]::after {
  transform: scaleX(1);
}
.nav__link[aria-current="true"] { color: var(--gold-ink); }
.nav__link[aria-disabled="true"]::after { display: none; }

/* Filled buttons: they read as pressable at rest, so hover only needs to
   confirm the pointer is on target — a darker fill and a 1px lift. */
.btn,
.venue__map {
  transition: background-color 200ms var(--ease),
              border-color 200ms var(--ease),
              transform 200ms var(--ease),
              box-shadow 200ms var(--ease);
}

.btn:hover,
.btn:focus-visible,
.venue__map:hover,
.venue__map:focus-visible {
  background: var(--btn-bg-hover);
  border-color: var(--btn-bg-hover);
  transform: translateY(-1px);
}
.btn:hover,
.btn:focus-visible {
  box-shadow: 0 2px 4px rgba(54, 37, 23, 0.16), 0 10px 22px rgba(54, 37, 23, 0.13);
}

.btn:active,
.venue__map:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(54, 37, 23, 0.14);
}

/* An unconfigured link must not look pressable. */
.btn[aria-disabled="true"],
.venue__map[aria-disabled="true"] {
  background: transparent;
  color: var(--ink-quiet);
  border-color: var(--gold-soft);
  box-shadow: none;
  transform: none;
}

/* Nav bar. */
.nav { transition: transform 320ms var(--ease); }

/* ── Reduced motion ───────────────────────────────────────────────────
   Not "no motion" — fewer and gentler. Opacity still carries the arrival
   and every hover still confirms itself; what goes is the spatial travel,
   the blur, and the tracking shift, which are what actually provoke
   vestibular discomfort. Smooth scrolling stays on by explicit request. */

@media (prefers-reduced-motion: reduce) {
  /* Keep the tempo close to the standard path — a noticeably faster page
     under this setting reads as a different, snappier design rather than a
     calmer one. What changes is the movement, not the pace. */
  :root {
    --dur-reveal:   800ms;
    --dur-hero:    1000ms;
    --dur-settle:  1100ms;
    --dur-frame:   1000ms;
    --step-group:    75ms;
    --step-stagger:  55ms;
    --step-hero:     90ms;
  }

  .js [data-reveal] {
    --rise: 0px;
    transform: none;
  }

  .js [data-settle] {
    filter: none;
    letter-spacing: 0.06em;
  }
  .js #hero.card::after {
    transform: none;
    transition: opacity var(--dur-frame) var(--ease) 150ms;
  }

  .nav { transition: transform 220ms var(--ease); }
  .nav__link::after { transition: transform 200ms var(--ease); }
  .btn, .venue__map { transition-duration: 140ms; }
}
