/*
  STARR KL — public site.

  Tokens copied from src/theme.ts and legal/styles.css so the app, the legal
  pages and this site are one object rather than three things that resemble
  each other. If a colour moves in theme.ts, move it here too.

  The design brief the app already answers: black room, gold only where
  something is earned, Bodoni for anything that speaks, platform sans for
  anything that informs. Nothing here is grey — the app's own comment explains
  why, and it applies harder on a phone held at arm's length in a dark room.
*/

@import url('https://fonts.googleapis.com/css2?family=Bodoni+Moda:opsz,ital,wght@6..96,0,400;6..96,0,500;6..96,1,400&display=swap');

* { box-sizing: border-box; }

:root {
  --void: #000000;
  --ink: #0B0B0C;
  --char: #141416;
  --ash: #232326;
  --line: rgba(255, 255, 255, 0.14);
  --line2: rgba(255, 255, 255, 0.26);
  --bone: #EDEDF0;
  --white: #FFFFFF;
  --gold: #C4A468;
  --gold-light: #F4E7C4;
  --gold-deep: #6E5A2E;

  --serif: 'Bodoni Moda', 'Didot', Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, sans-serif;

  --gutter: clamp(20px, 5vw, 64px);
  --rhythm: clamp(88px, 13vh, 168px);
}

html { background: var(--void); scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--void);
  color: var(--bone);
  font-family: var(--sans);
  line-height: 1.6;
  font-size: 16.5px;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Film grain. Luxury print has tooth; a flat black screen reads as cheap.
   Kept very low and fixed so it never reads as noise on scroll. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 var(--gutter); }
.measure { max-width: 620px; }

/* ── typography ───────────────────────────────────────────────────────── */

.label {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 3.4px;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 22px;
  font-weight: 500;
}
.label--bone { color: var(--bone); }

h1, h2, h3 { font-family: var(--serif); font-weight: 400; color: var(--white); }

h1 {
  font-size: clamp(46px, 9.5vw, 132px);
  line-height: .95;
  letter-spacing: -0.02em;
  margin: 0;
}

h2 {
  font-size: clamp(32px, 5.2vw, 66px);
  line-height: 1.02;
  letter-spacing: -0.015em;
  margin: 0 0 28px;
}

h3 {
  font-size: clamp(20px, 2.2vw, 26px);
  line-height: 1.2;
  margin: 0 0 12px;
}

em { font-style: italic; }

p { margin: 0 0 20px; }
.lede { font-size: clamp(17px, 1.5vw, 20px); line-height: 1.55; color: var(--bone); }
/*
  Nothing in the club is grey. src/theme.ts collapsed smoke, mist and bone to a
  single #EDEDF0 for exactly this reason: dimmed text is legible on a monitor
  and invisible on a phone at arm's length in a dark room, which is the only
  place any of this is ever read. Hierarchy here comes from size, spacing and
  case — never from fading the ink.
*/
.muted { color: var(--bone); font-size: 14.5px; line-height: 1.6; }

a { color: inherit; }

/* ── rules ────────────────────────────────────────────────────────────── */
.rule { height: 1px; background: var(--line); border: 0; margin: 0; }

/* ── nav ──────────────────────────────────────────────────────────────── */
.topbar {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  transition: background .4s ease, border-color .4s ease, backdrop-filter .4s ease;
  border-bottom: 1px solid transparent;
}
.topbar.is-stuck {
  background: rgba(0, 0, 0, .74);
  backdrop-filter: saturate(160%) blur(18px);
  border-bottom-color: var(--line);
}
.topbar .wrap {
  display: flex; align-items: center; justify-content: space-between;
  padding-top: 22px; padding-bottom: 22px;
}
.topnav { display: flex; gap: clamp(18px, 3vw, 40px); align-items: center; }
.topnav a {
  text-decoration: none;
  font-size: 10.5px; letter-spacing: 2.6px; text-transform: uppercase;
  color: var(--bone);
  transition: color .25s ease;
}
.topnav a:hover { color: var(--gold-light); }

/* ── wordmark ─────────────────────────────────────────────────────────────
   ST + a stroked five-point star + RR over a ruled KL. The star path is
   copied verbatim from src/components/art.tsx:23 so the two marks are the
   same shape, not merely similar. */
.mark { display: inline-flex; flex-direction: column; align-items: center; gap: 6px; }
.mark-row { display: flex; align-items: center; }
.mark-row span {
  font-family: var(--serif); font-weight: 400;
  letter-spacing: .06em; color: var(--white); line-height: 1;
}
.mark-row svg { margin: 0 -.04em; }
.kl-row { display: flex; align-items: center; gap: 10px; width: 100%; }
.kl-rule { height: 1px; background: var(--line2); flex: 1; }
.kl-text { font-size: 9.5px; letter-spacing: 5px; color: var(--bone); }

/* ── hero ─────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
}
/* The sky is drawn on canvas — see starfield() in index.html. It sits behind
   everything and is purely decorative, so it is aria-hidden and never focusable. */
.hero-sky {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}

/* The hero copy must not swallow pointer events meant for the sky, or the
   constellations under the headline would never light. Anything actually
   clickable inside re-enables them. */
.hero-inner { pointer-events: none; }
.hero-inner a,
.hero-inner button { pointer-events: auto; }

/*
  A single faint warm bloom low in the frame, so the field has a horizon rather
  than reading as evenly scattered dots.

  Order matters and it was wrong. In `background: A, B` the first layer paints
  on top, so listing the gold radial first put it above the black ramp that was
  supposed to fade it out — the bloom then ran straight into the hero's bottom
  edge and stopped dead against the next section, leaving a visible seam across
  the page.

  Now the ramp is on top and the bloom sits higher in the frame, so the light
  has already fallen off before the edge arrives and the hero ends on true #000
  — the same black the next section starts on, which is what makes the join
  disappear.
*/
.hero-glow {
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      #000 0%,
      transparent 20%,
      transparent 64%,
      rgba(0, 0, 0, .55) 84%,
      rgba(0, 0, 0, .92) 95%,
      #000 100%),
    radial-gradient(78% 44% at 50% 82%, rgba(196, 164, 104, .20) 0%, transparent 64%);
}
.hero-inner { position: relative; z-index: 2; padding-bottom: clamp(56px, 9vh, 112px); }

/* ── entrance ─────────────────────────────────────────────────────────────
   The hero animates itself on load rather than on scroll, staggered so the
   mark settles before the headline arrives. Each line of the headline is its
   own element so they can climb in sequence. */
.rise { opacity: 0; transform: translate3d(0, 26px, 0); animation: rise 1.15s cubic-bezier(.16,.84,.44,1) forwards; }
.rise--1 { animation-delay: .15s; }
.rise--2 { animation-delay: .38s; }
.rise--3 { animation-delay: .52s; }
.rise--4 { animation-delay: .78s; }
.rise--5 { animation-delay: .96s; }
@keyframes rise { to { opacity: 1; transform: none; } }

h1 .line { display: block; overflow: hidden; }

/* The rules either side of KL draw themselves outward. */
.hero .kl-rule { transform: scaleX(0); transform-origin: center; animation: ruleOut 1.4s cubic-bezier(.16,.84,.44,1) .62s forwards; }
@keyframes ruleOut { to { transform: scaleX(1); } }
.hero .mark { align-items: flex-start; margin-bottom: clamp(28px, 5vh, 56px); }
.hero .kl-row { justify-content: flex-start; }
.hero h1 { max-width: 12ch; }
.hero .lede { max-width: 46ch; margin-top: 28px; }

.scroll-cue {
  display: flex; align-items: center; gap: 12px;
  margin-top: clamp(32px, 6vh, 64px);
  font-size: 10px; letter-spacing: 3px; text-transform: uppercase;
  color: var(--bone);
}
.scroll-cue i {
  display: block; width: 54px; height: 1px;
  background: linear-gradient(90deg, var(--gold) 0%, var(--line2) 100%);
  transform-origin: left;
  animation: cue 2.6s ease-in-out infinite;
}
@keyframes cue {
  0%, 100% { transform: scaleX(.35); opacity: .5; }
  50%      { transform: scaleX(1);   opacity: 1; }
}

/* ── sections ─────────────────────────────────────────────────────────── */
section { padding: var(--rhythm) 0; }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 6vw, 96px);
  align-items: center;
}
.split--reverse > :first-child { order: 2; }

/* ── phones ───────────────────────────────────────────────────────────── */
.phone {
  position: relative;
  width: 100%;
  max-width: 300px;
  aspect-ratio: 1290 / 2796;
  border-radius: 44px;
  padding: 9px;
  background: linear-gradient(160deg, #2a2a2e 0%, #0d0d0f 42%, #35353a 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,.16) inset,
    0 50px 90px -30px rgba(0,0,0,.95),
    0 0 0 1px rgba(0,0,0,.6);
}
.phone img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: top;
  border-radius: 36px;
  display: block;
}
.phone-pair {
  display: flex; gap: clamp(14px, 2.4vw, 28px); align-items: flex-start;
  justify-content: center;
}
.phone-pair .phone:nth-child(2) { margin-top: clamp(28px, 6vw, 72px); }

/* ── index list ───────────────────────────────────────────────────────── */
.index { border-top: 1px solid var(--line); margin-top: 56px; }
.index-row {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) minmax(0, 1.35fr);
  gap: clamp(16px, 3vw, 40px);
  padding: 30px 0;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.index-row .n {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--gold);
  letter-spacing: .08em;
}
.index-row h3 { margin: 0; }
.index-row p { margin: 0; color: var(--bone); font-size: 15.5px; }

/* ── quiet panel (no side accent; matches legal/styles.css:110) ───────── */
.panel {
  background: var(--ink);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: clamp(24px, 3vw, 36px);
}
.panel p:last-child { margin-bottom: 0; }

/* ── full-bleed plate ─────────────────────────────────────────────────── */
.plate {
  position: relative;
  min-height: 78vh;
  display: grid; align-items: center;
  overflow: hidden;
  /* No borders. A hairline across the full width announces the join between
     one section and the next, which is exactly what we are trying not to do. */
}
/*
  No photograph here on purpose. The only artwork in the repo is 1100x660,
  which is soft the moment it is stretched full-bleed on a retina display —
  and upscaling it would invent detail the file does not contain. Until the
  club supplies artwork at 2560px or wider, this plate is light rather than
  image: its own slow starfield behind a warm bloom.
*/
/*
  Same rule as the hero: the black ramp is listed first so it paints over the
  warm light, and the plate therefore begins and ends on true #000. Any glow
  that survives to the edge draws a line across the page.
*/
.plate-art {
  position: absolute; inset: 0;
  background:
    linear-gradient(to bottom,
      #000 0%,
      rgba(0, 0, 0, .55) 12%,
      transparent 34%,
      transparent 66%,
      rgba(0, 0, 0, .55) 88%,
      #000 100%),
    radial-gradient(66% 90% at 18% 50%, rgba(196,164,104,.16) 0%, transparent 62%),
    radial-gradient(78% 100% at 92% 30%, rgba(237,237,240,.06) 0%, transparent 64%);
}
.plate .wrap { position: relative; z-index: 2; }

/* ── buttons ──────────────────────────────────────────────────────────── */
.btn-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 16px 32px;
  border: 1px solid var(--line2);
  border-radius: 100px;
  color: var(--white);
  text-decoration: none;
  font-size: 11px; letter-spacing: 2.6px; text-transform: uppercase;
  transition: border-color .3s ease, color .3s ease, background-color .3s ease;
}
.btn:hover { border-color: var(--gold); color: var(--gold-light); }
.btn--solid { background: var(--white); color: var(--void); border-color: var(--white); }
.btn--solid:hover { background: var(--gold-light); border-color: var(--gold-light); color: var(--void); }
.btn--quiet {
  opacity: .48; border-style: dashed; cursor: default;
}
.btn--quiet:hover { border-color: var(--line2); color: var(--white); }

/* ── figures ──────────────────────────────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 18px; overflow: hidden; margin-top: 48px; }
.stat { background: var(--void); padding: 30px 26px; }
.stat b { display: block; font-family: var(--serif); font-size: 30px; color: var(--white); font-weight: 400; margin-bottom: 6px; }
.stat span { font-size: 11px; letter-spacing: 2.2px; text-transform: uppercase; color: var(--bone); }

/* ── footer ───────────────────────────────────────────────────────────── */
footer { padding: var(--rhythm) 0 72px; border-top: 1px solid var(--line); }
.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  margin-bottom: 64px;
}
.foot-col h4 {
  font-family: var(--sans); font-size: 10.5px; letter-spacing: 2.8px;
  text-transform: uppercase; color: var(--bone);
  margin: 0 0 18px; font-weight: 500;
}
.foot-col a { display: block; text-decoration: none; font-size: 15px; margin-bottom: 11px; color: var(--bone); transition: color .25s ease; }
.foot-col a:hover { color: var(--gold-light); }
.sig {
  font-family: var(--serif);
  font-size: clamp(13px, 1.6vw, 16px);
  letter-spacing: .5em;
  text-transform: uppercase;
  color: var(--bone);
  text-align: center;
  margin: 0 0 28px;
}
.colophon { display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; }

/* ── reveal ───────────────────────────────────────────────────────────── */
.reveal { opacity: 0; transform: translate3d(0, 22px, 0); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity 1s cubic-bezier(.22,.61,.36,1), transform 1s cubic-bezier(.22,.61,.36,1);
}

/* Index rows arrive one after another rather than as a block. The delay is set
   from JS per row so it works however many rows a section has. */
.index-row { opacity: 0; transform: translate3d(0, 18px, 0); }
.index-row.is-in {
  opacity: 1; transform: none;
  transition: opacity .85s cubic-bezier(.22,.61,.36,1), transform .85s cubic-bezier(.22,.61,.36,1);
}
.index-row .n { transition: color .4s ease; }
.index-row:hover .n { color: var(--gold-light); }

/* Phones breathe, slightly out of phase with each other, so a pair never looks
   like one rigid object. */
.phone { animation: float 9s ease-in-out infinite; }
.phone-pair .phone:nth-child(2) { animation-duration: 11s; animation-delay: -3.5s; }
@keyframes float {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -12px, 0); }
}

/* Parallax on the plate art, driven from JS with a scroll-linked custom
   property so the image drifts against the copy. */
.plate-art { transform: translate3d(0, var(--shift, 0px), 0) scale(1.14); will-change: transform; }

/* ── responsive ───────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; gap: 44px; }
  .split--reverse > :first-child { order: 0; }
  .index-row { grid-template-columns: 34px 1fr; }
  .index-row p { grid-column: 2; margin-top: 8px; }
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .phone { max-width: 240px; }
}

@media (max-width: 560px) {
  .topnav { gap: 15px; }
  .topnav a { font-size: 9.5px; letter-spacing: 1.6px; }
  .foot-grid { grid-template-columns: 1fr; }
  .phone-pair .phone:nth-child(2) { display: none; }
  .phone { max-width: 268px; }
}

/* Everything that moves is switched off together, not partially. A page that
   still drifts for someone who asked it not to is worse than a static one. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal,
  .index-row { opacity: 1; transform: none; transition: none; }
  .rise { opacity: 1; transform: none; animation: none; }
  .hero .kl-rule { transform: none; animation: none; }
  .scroll-cue i { animation: none; transform: none; }
  .phone { animation: none; }
  .plate-art { transform: scale(1.14); }
}
