/* =========================================================================
   RFactor — landing page styles
   Tokens mirror the RFactor Design System (paper / ink modes).
   ========================================================================= */

:root {
  /* Paper (cream) — used as the page surface */
  --bg:        #ece4d2;
  --bg-2:      #e3dac4;
  --bg-3:      #d8cfb9;
  --ink:       #2a1d24;
  --ink-2:     #3d2c33;
  --ink-3:     #5e4e55;
  --ink-4:     #8a7d83;
  --ink-5:     #b3a9ad;

  --rule:        rgba(42, 29, 36, 0.16);
  --rule-strong: rgba(42, 29, 36, 0.36);
  --hairline:    rgba(42, 29, 36, 0.08);

  /* Ink (wine) — used inside the form panel */
  --wine:       #2a1d24;
  --wine-2:     #33242b;
  --wine-3:     #3d2c33;
  --cream:      #ece4d2;
  --cream-2:    #d8cfb9;
  --cream-3:    #b8ad96;
  --cream-4:    #8a8071;

  --rule-w:        rgba(236, 228, 210, 0.16);
  --rule-w-strong: rgba(236, 228, 210, 0.36);
  --hairline-w:    rgba(236, 228, 210, 0.10);

  /* Accents */
  --accent:        oklch(0.78 0.12 75);     /* brass on wine */
  --accent-paper:  oklch(0.58 0.12 75);     /* deeper brass on cream */
  --accent-paper-2: oklch(0.42 0.10 75);    /* deepest brass for hover */
  --negative:      oklch(0.58 0.18 25);     /* error pomegranate, paper-readable */

  /* Type */
  --display: 'EB Garamond', 'Times New Roman', serif;
  --body:    'Manrope', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono:    'DM Mono', ui-monospace, monospace;

  /* Visible viewport offsets (set by main.js via visualViewport API).
     --vv-top:    top chrome height (URL bar / status bar) — non-zero in
                  Top Address Bar mode, ~0 with floating bottom URL pill.
     --vv-bottom: bottom chrome reported by visualViewport (zero when iOS
                  treats chrome as overlay). For positioning we generally
                  combine this with (100lvh - 100svh) to capture chrome
                  that visualViewport reports as zero — see .cta/.film__skip. */
  --vv-top:    0px;
  --vv-bottom: env(safe-area-inset-bottom, 0px);

  /* Space scale */
  --s1:  4px;
  --s2:  8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
  --s9: 96px;

  /* Easings */
  --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
  --ease-out-expo:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
html {
  /* Dark by default so iOS Safari's status-bar overlay and URL-bar surround
     (which paint pixels from the page itself in viewport-fit=cover mode)
     blend with the cinematic intro video. Flipped to cream by main.js
     once the hero is revealed. */
  background: #0a0a0a;
  transition: background-color 320ms linear;
}
body {
  font-family: var(--body);
  color: var(--ink);
  background: #0a0a0a;
  transition: background-color 320ms linear;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden;             /* page is a fixed stage; nothing scrolls */
}
html.is-revealed,
body.is-revealed { background: var(--bg); }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input { font: inherit; color: inherit; }
::selection { background: var(--accent-paper); color: var(--bg); }

/* ---------- stage ---------- */
.stage {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;            /* fallback */
  height: 100lvh;           /* iOS Safari: fill the LARGEST viewport so the
                               video extends edge-to-edge behind the status
                               bar and the floating URL pill. UI elements
                               below use env(safe-area-inset-*) to stay
                               clear of the chrome. */
  overflow: hidden;
  background-color: #0a0a0a;
  transition: background-color 320ms linear;
}
.stage[data-state="reveal"],
.stage[data-state="ready"],
.stage[data-state="panel"] {
  background-color: var(--bg);
}

/* =========================================================================
   HERO  (cream paper, sits beneath the film and is revealed by the fade)
   ========================================================================= */
.hero {
  /* Cream paper layer — full bleed via position:absolute inset:0. */
  position: absolute;
  inset: 0;
  background: var(--bg);
}
.hero__center {
  /* The wordmark is fixed-positioned and centered on the actual VISIBLE
     viewport across both iOS Safari URL-bar layouts.
     Anchor: layout-viewport top + (top chrome) + (visible_height / 2).
       — top chrome  = --vv-top (from visualViewport, non-zero when Top
                       Address Bar is active; 0 when bottom floating pill).
       — visible_h/2 = 50svh (smallest possible viewport with all chrome
                       shown — what the spec calls the "shrunk" viewport).
     Bottom Address Bar (floating pill): --vv-top=0, 50svh = visible_h/2,
       so wordmark sits at vertical center of the area above the pill.
     Top Address Bar (solid bars): --vv-top=URL_bar_h, 50svh = visible_h/2,
       so wordmark sits at the center of the band between the two bars. */
  position: fixed;
  top: calc(var(--vv-top, 0px) + 50svh);
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: left;
}
@supports not (top: 50svh) {
  .hero__center {
    /* Fall back to layout-viewport center for browsers without small-vp units. */
    top: 50%;
  }
}


/* ---------- wordmark ---------- */
.wordmark {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(72px, 12vw, 168px);
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: var(--ink);
  text-align: center;
  /* symmetric h-padding so italic ascenders don't clip on either side */
  padding: 0 0.04em;
}
.wordmark__line {
  position: relative;
  display: inline-block;
  white-space: nowrap;
  /* Symmetric padding keeps the visible glyphs optically centered while
     still leaving room for the caret to sit just past the final glyph. */
  padding: 0 0.6ch;
}
.glyph {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.04em);
  transition: opacity 90ms linear;
  font-style: normal;
  /* keep typographic rhythm even while invisible */
  visibility: visible;
}
.glyph--italic {
  font-style: italic;
  font-weight: 500;
  /* small optical correction so italic 'f' kerns into the upright 'a' nicely */
  margin-right: -0.02em;
  margin-left: -0.01em;
}
.glyph.is-on { opacity: 1; }

/* caret: a thin solid block, vertically centered on the lowercase x-height
   of the wordmark — measured empirically against EB Garamond rendering. */
.caret {
  position: absolute;
  top: 0.36em;
  left: 0;
  width: 2px;
  height: 0.55em;
  background: var(--ink);
  opacity: 0;
  transition: left 110ms var(--ease-out-quart), opacity 200ms linear;
  pointer-events: none;
  will-change: left;
}
.caret.is-blink { animation: blink 1s steps(2, jump-none) infinite; opacity: 1; }
.caret.is-resting { opacity: 0.28; animation: blink 1.6s steps(2, jump-none) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ---------- rule beneath wordmark ---------- */
.rule {
  position: relative;
  height: 1px;
  margin: clamp(20px, 2vw, 32px) auto 0;
  /* width is set by JS once the wordmark width is known; falls back to type-width-ish */
  width: var(--rule-w-px, 60%);
  max-width: calc(100% + 8vw);
  background: transparent;
  overflow: hidden;
}
.rule__fill {
  position: absolute;
  inset: 0;
  background: var(--rule-strong);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 600ms var(--ease-out-quart);
}
.rule.is-on .rule__fill { transform: scaleX(1); }

/* ---------- tagline ---------- */
.tagline {
  margin: var(--s4) 0 0;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.32em;
  color: var(--ink-3);
  text-transform: uppercase;
  text-align: center;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 320ms linear, transform 320ms var(--ease-out-quart);
}
.tagline.is-on { opacity: 1; transform: none; }

/* ---------- CTA ("Get in touch") — no-fill variant ---------- */
.cta {
  position: absolute;
  left: 50%;
  /* Keep the CTA above iOS chrome (URL pill OR button bar) with comfortable
     cushion. The (100lvh - 100svh - --vv-top) term gives bottom chrome
     height in any layout — it works even when visualViewport reports
     floating chrome as zero, because svh accounts for the spec-shrunk
     viewport. --vv-bottom is also kept as a third source of truth. */
  bottom: max(
    clamp(40px, 6vh, 72px),
    calc(100lvh - 100svh - var(--vv-top, 0px) + 56px),
    calc(var(--vv-bottom, 0px) + 56px)
  );
  transform: translateX(-50%) translateY(8px);
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px 14px 28px;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  opacity: 0;
  transition:
    opacity 2200ms linear,
    transform 600ms var(--ease-out-quart),
    background-color 200ms linear,
    border-color 200ms linear,
    color 200ms linear;
}
.cta.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.cta__label { line-height: 1; white-space: nowrap; }
.cta__return {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0;
  opacity: 0.55;
  transform: translateY(-1px);
}
.cta:hover {
  background: var(--ink);
  color: var(--bg);
}
.cta:hover .cta__return { opacity: 1; }
.cta:focus-visible {
  outline: 2px solid var(--accent-paper);
  outline-offset: 3px;
}
.cta:active { transform: translateX(-50%) scale(0.985); }

/* hide CTA before its time — JS strips this */
.stage[data-state="boot"] .cta,
.stage[data-state="film"] .cta,
.stage[data-state="reveal"] .cta {
  pointer-events: none;
}
.stage[data-state="ready"] .cta { pointer-events: auto; }

/* =========================================================================
   FILM  (cinematic intro video; fades to expose hero below)
   ========================================================================= */
.film {
  position: absolute;
  inset: 0;
  /* Dark default so iOS Safari has no cream surface to sample for chrome
     tinting before the video paints over it. As .film fades out, .hero
     (cream) underneath is what's revealed — the visible transition still
     reads as video → cream hero. */
  background: #0a0a0a;
  z-index: 10;
  opacity: 1;
  transition: opacity 1000ms var(--ease-out-quart);
  pointer-events: auto;
}
.film.is-fading { opacity: 0; }
.film.is-gone   { display: none; }

.film__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  background: #0a0a0a;
}
.film__skip {
  position: absolute;
  /* Keep SKIP below the iOS status bar / dynamic island. */
  top: max(clamp(20px, 3vh, 32px), env(safe-area-inset-top, 0px) + 12px);
  right: max(clamp(20px, 3vw, 32px), env(safe-area-inset-right, 0px) + 12px);
  padding: 8px 12px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.32em;
  color: rgba(236, 228, 210, 0.72);
  background: transparent;
  border: 1px solid rgba(236, 228, 210, 0.24);
  border-radius: 2px;
  text-transform: uppercase;
  opacity: 0;
  transition: opacity 400ms linear, color 200ms linear, border-color 200ms linear;
  cursor: pointer;
}
.film__skip.is-on { opacity: 1; }
.film__skip:hover {
  color: var(--cream);
  border-color: var(--cream);
}
.film__skip:focus-visible {
  outline: 1px solid var(--cream);
  outline-offset: 3px;
}

/* =========================================================================
   PANEL  (form, wipes in from the left over the cream paper)
   ========================================================================= */
.panel {
  position: fixed;
  inset: 0;
  background: var(--wine);
  color: var(--cream);
  z-index: 20;
  transform: translateX(-101%);
  transition: transform 700ms var(--ease-out-expo);
  display: grid;
  grid-template-rows: auto 1fr;
  pointer-events: none;
  visibility: hidden;
}
.panel.is-open {
  transform: translateX(0);
  pointer-events: auto;
  visibility: visible;
}

/* a thin vertical hairline at ~60% to honor the asymmetric grid */
.panel__rule {
  position: absolute;
  top: 14vh;
  bottom: 14vh;
  left: 60%;
  width: 1px;
  background: var(--rule-w);
}

/* ---------- chrome (top bar inside the panel) ---------- */
.panel__chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: clamp(20px, 3vh, 32px) clamp(24px, 5vw, 64px);
  border-bottom: 1px solid var(--rule-w);
}
.panel__brand {
  display: inline-flex;
  align-items: baseline;
  gap: 18px;
}
.panel__mark {
  font-family: var(--display);
  font-size: 28px;
  font-weight: 400;
  letter-spacing: -0.04em;
  color: var(--cream);
  line-height: 1;
}
.panel__mark em { font-style: italic; font-weight: 500; }

.panel__eyebrow {
  display: inline-flex;
  align-items: baseline;
  gap: 14px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--cream-3);
}
.panel__eyebrow-step {
  color: var(--accent);
}

.panel__close {
  width: 32px;
  height: 32px;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--rule-w-strong);
  border-radius: 2px;
  color: var(--cream);
  transition: background-color 160ms linear, color 160ms linear, border-color 160ms linear;
}
.panel__close:hover {
  background: var(--cream);
  color: var(--wine);
  border-color: var(--cream);
}
.panel__close:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 3px;
}

/* ---------- body / form column ---------- */
.panel__body {
  position: relative;
  display: grid;
  place-content: center start;
  padding: clamp(32px, 6vh, 72px) clamp(24px, 5vw, 64px);
}

.panel__intro {
  width: min(460px, 100%);
  margin: 0 0 clamp(28px, 4vh, 44px);
  font-family: var(--display);
  font-size: clamp(26px, 2.6vw, 32px);
  font-weight: 400;
  line-height: 1.28;
  color: var(--cream);
  letter-spacing: -0.005em;
}
.panel__intro em {
  font-style: italic;
  font-weight: 500;
}

.form {
  width: min(460px, 100%);
  display: grid;
  gap: clamp(24px, 3.4vh, 36px);
}
.form__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
}

.field {
  position: relative;
  display: grid;
  gap: 6px;
}
.field__label {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--cream-3);
  transition: color 200ms linear;
}
.field__input {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule-w-strong);
  border-radius: 0;
  padding: 8px 0 10px;
  font-family: var(--display);
  font-size: 22px;
  line-height: 1.2;
  color: var(--cream);
  caret-color: var(--accent);
  transition: border-color 200ms linear, border-bottom-width 0s;
  outline: none;
  width: 100%;
}
.field__input::placeholder { color: var(--cream-4); }
.field__input:hover { border-bottom-color: var(--cream-3); }
.field__input:focus-visible,
.field:focus-within .field__input {
  border-bottom-color: var(--accent);
  /* simulate 1.5px without layout shift */
  box-shadow: 0 1px 0 0 var(--accent);
}
.field:focus-within .field__label { color: var(--cream); }

.field--filled .field__input { border-bottom-color: var(--cream-2); }
.field--filled .field__label  { color: var(--cream-2); }

.field--error .field__input { border-bottom-color: var(--negative); box-shadow: 0 1px 0 0 var(--negative); }
.field--error .field__label { color: var(--negative); }

.field__error {
  font-family: var(--mono);
  font-style: italic;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--negative);
  min-height: 0;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 200ms linear, transform 200ms var(--ease-out-quart);
}
.field--error .field__error { opacity: 1; transform: translateY(0); }

/* ---------- send button ---------- */
.form__foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}
.send {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px 14px 28px;
  background: var(--cream);
  color: var(--wine);
  border: 1px solid var(--cream);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  transition:
    background-color 200ms linear,
    color 200ms linear,
    border-color 200ms linear,
    opacity 200ms linear,
    transform 80ms var(--ease-out-quart);
}
.send__return { font-size: 12px; opacity: 0.5; }
.send:hover { background: var(--accent); color: var(--wine); border-color: var(--accent); }
.send:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.send:active { transform: scale(0.985); }
.send:disabled { opacity: 0.32; cursor: not-allowed; }
.send:disabled:hover { background: var(--cream); border-color: var(--cream); color: var(--wine); }

/* ---------- thanks state ---------- */
.thanks {
  width: min(540px, 100%);
  display: grid;
  gap: 18px;
  align-content: center;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 360ms linear, transform 360ms var(--ease-out-quart);
}
.thanks.is-on { opacity: 1; transform: none; }
.thanks__line {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(28px, 3.4vw, 36px);
  font-weight: 400;
  line-height: 1.2;
  color: var(--cream);
}
.thanks__line em { font-style: italic; }
.thanks__caption {
  margin: 0;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--cream-3);
}
.thanks__back {
  margin-top: 12px;
  justify-self: start;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cream-3);
  padding: 6px 0;
  border-bottom: 1px solid transparent;
  transition: color 160ms linear, border-color 160ms linear;
  opacity: 0;
  pointer-events: none;
}
.thanks__back.is-on { opacity: 1; pointer-events: auto; }
.thanks__back:hover { color: var(--cream); border-color: var(--rule-w-strong); }
.thanks__back:focus-visible { outline: 1px solid var(--accent); outline-offset: 3px; }

/* form fades out before thanks fades in */
.form.is-out,
.panel__intro.is-out { opacity: 0; pointer-events: none; transition: opacity 220ms linear; }

/* =========================================================================
   RESPONSIVE
   ========================================================================= */
@media (max-width: 720px) {
  .hero__center { padding: 0 24px; }
  .wordmark { font-size: clamp(64px, 18vw, 120px); }
  .form__pair { grid-template-columns: 1fr; gap: clamp(20px, 3.2vh, 28px); }
  .form { width: 100%; gap: clamp(20px, 3vh, 28px); }
  .panel { display: grid; grid-template-rows: auto 1fr; }
  .panel__chrome { padding: 16px 20px; }
  /* On mobile, stretch the form across the full inner width by defining
     an explicit single-column track. (Default `place-content: center start`
     shrink-wraps the implicit track to content width.) */
  .panel__body {
    padding: 0 24px;
    grid-template-columns: minmax(0, 1fr);
    justify-items: stretch;
  }
  .panel__rule { display: none; }
  .panel__brand { gap: 12px; }
  .panel__mark { font-size: 22px; }
  .field__input { font-size: 19px; padding: 6px 0 8px; }
  .field__label { font-size: 10px; letter-spacing: 0.28em; }
  .send { padding: 12px 18px 12px 22px; font-size: 10px; }
  .thanks__line { font-size: clamp(24px, 7vw, 32px); }
  .film__skip {
    top: auto;
    /* Comfortable cushion above iOS chrome (URL pill or button bar) on
       mobile. See the desktop .cta rule for an explanation of the three
       max() terms — same reasoning applies here. */
    bottom: max(
      clamp(20px, 4vh, 32px),
      calc(100lvh - 100svh - var(--vv-top, 0px) + 56px),
      calc(var(--vv-bottom, 0px) + 56px)
    );
    right: max(clamp(16px, 5vw, 24px), env(safe-area-inset-right, 0px) + 16px);
    font-size: 10px;
  }
  .cta {
    padding: 13px 20px 13px 26px;
    bottom: max(
      clamp(28px, 5vh, 56px),
      calc(100lvh - 100svh - var(--vv-top, 0px) + 56px),
      calc(var(--vv-bottom, 0px) + 56px)
    );
    transform: translateX(-50%) translateY(8px);
  }
  .cta.is-on { transform: translateX(-50%) translateY(0); }
}

@media (max-width: 380px) {
  .wordmark { font-size: clamp(56px, 20vw, 88px); }
  .panel__chrome { padding: 14px 16px; }
  .panel__body { padding: 0 18px; }
  .field__input { font-size: 17px; }
  .form__foot { justify-content: stretch; }
  .send { width: 100%; justify-content: center; }
  .cta {
    letter-spacing: 0.2em;
    padding: 12px 16px 12px 22px;
    gap: 10px;
  }
}

/* very tall narrow screens — keep wordmark from sitting too low */
@media (max-aspect-ratio: 3/4) {
  .hero { grid-template-rows: 1fr auto; }
}

/* =========================================================================
   REDUCED MOTION
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 200ms !important;
  }
  .caret { display: none; }
  .glyph { opacity: 1 !important; transform: none !important; }
  .rule__fill { transform: scaleX(1) !important; }
  .tagline { opacity: 1 !important; transform: none !important; }
  .cta { opacity: 1 !important; transform: translateX(-50%) translateY(0) !important; }
  .film { display: none !important; }
  .panel { transition: opacity 200ms linear !important; transform: none !important; opacity: 0; }
  .panel.is-open { opacity: 1; }
}
