/* ==========================================================================
   Lantern Meadow — landing page
   Dark field, warm light. See docs/landing-page-brief.md.
   ========================================================================== */

/* ---------- Fonts (self-hosted, Fontshare) ---------- */

@font-face {
  font-family: "Gambetta";
  src: url("fonts/Gambetta-Light.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Gambetta";
  src: url("fonts/Gambetta-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Gambetta";
  src: url("fonts/Gambetta-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "General Sans";
  src: url("fonts/GeneralSans-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "General Sans";
  src: url("fonts/GeneralSans-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ---------- Design tokens ---------- */

:root {
  /* 0 at the top of the page, 1 at the bottom — set by scroll.js */
  --night: 0;

  /* color */
  --dusk: #0f1c27;       /* Deep Dusk — darkest point, deep in the scroll */
  --sunset-field: #2b3242; /* the hero's base: dusk just after sunset */
  --horizon-warm: #4a3b3a; /* low warm band — a sun just gone down */
  --dusk-deeper: #0a141d; /* further toward night, foot of the page */
  --dusk-lifted: #142633; /* the sky just after sunset, top of page */
  --field: #16282f;      /* lifted surfaces, the lower ground */
  --lantern: #f3b65a;    /* warm amber glow — this is light, use sparingly */
  --ember: #ffcf8e;      /* the hot pale center of a flame */
  --farlight: #b98a55;   /* distant lanterns, low opacity, depth */
  --paper: #f1e9da;      /* text on dark, never pure white */
  --grey: #93a6ae;       /* secondary text, dates, quiet labels */
  --amber-deep: #d98e45; /* decorative amber for light backgrounds */
  --amber-ink: #7d461c;  /* amber that reads as text on dawn (AA) */
  --ink: #2b2015;        /* text at dawn */
  --ink-70: rgba(43, 32, 21, 0.74);
  --ink-45: rgba(43, 32, 21, 0.5);

  /* text that survives the coming of morning: paper/grey/amber by night,
     ink tones as --dawn rises — never lost mid-transition */
  --text-strong: color-mix(in oklab, var(--paper) calc((1 - var(--dawn, 0)) * 100%), var(--ink));
  --text-soft: color-mix(in oklab, var(--grey) calc((1 - var(--dawn, 0)) * 100%), var(--ink-70));
  --label-color: color-mix(in oklab, var(--lantern) calc((1 - var(--dawn, 0)) * 100%), var(--amber-ink));

  /* type */
  --serif: "Gambetta", Georgia, serif;
  --sans: "General Sans", system-ui, sans-serif;
  --size-hero: clamp(2.9rem, 6.5vw, 6.5rem);
  --size-display: clamp(2.4rem, 5.6vw, 4.4rem);
  --size-beat: clamp(2.1rem, 4.4vw, 3.4rem);
  --size-body: clamp(1.15rem, 1.2vw + 0.95rem, 1.4rem);
  --size-label: 0.85rem;

  /* rhythm */
  --breath: clamp(7rem, 18vh, 13rem); /* vertical space between passages */
  --edge: clamp(1.6rem, 5vw, 4rem);   /* horizontal page margin */
}

/* ---------- Base ---------- */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  position: relative;
  /* the sky itself deepens as you scroll: twilight at the top of the page,
     night at the bottom. Static gradient first as the fallback. */
  background:
    linear-gradient(to bottom, var(--dusk-lifted) 0%, var(--dusk) 34%, var(--dusk) 70%, var(--dusk-deeper) 100%)
    var(--dusk);
  background: color-mix(
    in oklab,
    var(--dusk-lifted) calc((1 - var(--night)) * 100%),
    #10202e
  );
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--size-body);
  font-weight: 400;
  line-height: 1.65;
  min-height: 100vh;
  overflow-x: hidden;
}

::selection { background: var(--farlight); color: var(--dusk); }

/* ---------- Film grain ---------- */

.grain {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  opacity: 0.055;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
}

/* ---------- The pinned sky & the floor ---------- */

/* Sunset, not midnight: the sky settling toward a warm horizon. Fixed to
   the viewport and faded toward night by scroll — one persistent world. */
#bg-sunset {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    #252d3d 0%,
    var(--sunset-field) 38%,
    #3b3540 68%,
    var(--horizon-warm) 85%,
    #2a2833 94%,
    var(--dusk-lifted) 100%
  );
}

/* Morning, waiting beneath the night — crossfaded in by scroll progress. */
#bg-dawn {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(to bottom, #c9997a 0%, #e5c6a4 38%, #f2e7d6 72%, #f8f1e3 100%);
}

/* A warm glow gathering low on the horizon as the visitor reads. */
#bg-horizon {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    ellipse 130% 55% at 50% 108%,
    rgba(243, 182, 90, 0.4) 0%,
    rgba(196, 120, 70, 0.14) 45%,
    transparent 72%
  );
}

/* Fixed behind everything: the meadow continues through the whole page. */
.ambient {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

/* content scrolls over the pinned sky */
main,
.site-head,
.site-foot {
  position: relative;
  z-index: 1;
}

/* ---------- Shared pieces ---------- */

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--edge);
  z-index: 60;
  padding: 0.6em 1em;
  background: var(--field);
  color: var(--paper);
  font-family: var(--sans);
  font-size: 0.9rem;
  text-decoration: none;
}
.skip-link:focus-visible { top: 0.75rem; }

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

.wordmark {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  color: var(--paper);
}

/* section kickers: amber, generous, unmissable */
.label {
  font-family: var(--sans);
  font-weight: 500;
  font-size: clamp(0.95rem, 1.4vw, 1.15rem);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--label-color);
  margin-bottom: 2rem;
}

.display {
  font-family: var(--serif);
  font-weight: 300;
  font-size: var(--size-display);
  line-height: 1.22;
  letter-spacing: 0.002em;
  color: var(--text-strong);
  text-wrap: balance;
  max-width: 21ch;
}

.prose {
  margin-top: 1.6rem;
  max-width: 56ch;
  font-size: calc(var(--size-body) * 1.06);
  line-height: 1.75;
  color: var(--text-soft);
}

/* the written memories read like a letter */
.memory {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.25em;
  line-height: 1.5;
  color: var(--paper);
  max-width: 30ch;
  margin-top: 2rem;
}

/* ---------- Actions ---------- */

/* the pill: warm gradient, breathing glow */
.cta {
  display: inline-block;
  font-family: var(--sans);
  font-weight: 500;
  font-size: 1.08rem;
  letter-spacing: 0.01em;
  color: #241505;
  background: linear-gradient(to bottom, #f6be77, var(--lantern));
  text-decoration: none;
  padding: 0.95rem 2.4rem;
  border-radius: 999px;
  box-shadow: 0 0 28px rgba(243, 182, 90, 0.32), 0 2px 14px rgba(0, 0, 0, 0.3);
  transition: box-shadow 0.4s ease, transform 0.3s ease;
}
.cta:hover,
.cta:focus-visible {
  box-shadow: 0 0 46px rgba(255, 207, 142, 0.5), 0 2px 14px rgba(0, 0, 0, 0.3);
  transform: translateY(-1px);
}
@media (prefers-reduced-motion: no-preference) {
  .cta { animation: breathe 4.6s ease-in-out infinite; }
  @keyframes breathe {
    0%, 100% { box-shadow: 0 0 24px rgba(243, 182, 90, 0.28), 0 2px 14px rgba(0, 0, 0, 0.3); }
    50% { box-shadow: 0 0 42px rgba(243, 182, 90, 0.46), 0 2px 14px rgba(0, 0, 0, 0.3); }
  }
}

.quiet-link {
  font-family: var(--sans);
  font-size: 0.95rem;
  color: var(--text-soft);
  text-decoration: underline;
  text-decoration-color: color-mix(in oklab, currentColor 45%, transparent);
  text-underline-offset: 0.25em;
  transition: color 0.4s ease, text-decoration-color 0.4s ease;
}
.quiet-link:hover {
  color: var(--text-strong);
  text-decoration-color: color-mix(in oklab, currentColor 70%, transparent);
}

/* ---------- Header ---------- */

.site-head {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  padding: clamp(1.2rem, 3vw, 2.2rem) var(--edge);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  color: var(--paper);
}
/* sign in: a quiet pill, but unmistakably there */
.site-head .signin {
  margin-left: auto;
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 500;
  color: var(--paper);
  text-decoration: none;
  padding: 0.5em 1.4em;
  border: 1px solid rgba(241, 233, 218, 0.35);
  border-radius: 999px;
  background: rgba(15, 28, 39, 0.25);
  transition: border-color 0.3s ease, background-color 0.3s ease, box-shadow 0.4s ease;
}
.site-head .signin:hover,
.site-head .signin:focus-visible {
  border-color: rgba(243, 182, 90, 0.65);
  background: rgba(243, 182, 90, 0.12);
  box-shadow: 0 0 18px rgba(243, 182, 90, 0.18);
}

/* ---------- The lantern mark (temporary) ---------- */

.logo { display: block; height: auto; }
.logo--head { width: 22px; }
.logo--hero {
  width: clamp(44px, 6vw, 60px);
  margin: 0 auto 2.4rem;
}
.logo--foot {
  width: clamp(84px, 10vw, 116px);
  margin: 0 auto 1.6rem;
  color: var(--ink);
}

/* ---------- Hero ---------- */

/* The hero owns no background — the sunset lives in the fixed sky layer,
   so scrolling past the meadow never crosses a seam. The inscription sits
   at the still center of the screen. */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.meadow {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* the meadow dissolves at its lower edge — never a hard cut against
     the persistent sky as it scrolls away */
  -webkit-mask-image: linear-gradient(to bottom, black 86%, transparent 100%);
  mask-image: linear-gradient(to bottom, black 86%, transparent 100%);
}

/* A breath of settling darkness behind the inscription so the type stays
   quiet against the warmer sky. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(64% 56% at 50% 52%, rgba(15, 28, 39, 0.3), transparent 72%);
}

/* a still, centered inscription — the anti-grid asymmetry begins below */
.hero-inner {
  position: relative;
  z-index: 10;
  padding: 0 var(--edge);
  width: 100%;
  text-align: center;
}

.hero-line {
  font-family: var(--serif);
  font-weight: 300;
  font-size: var(--size-hero);
  line-height: 1.06;
  letter-spacing: -0.005em;
  color: var(--paper);
  white-space: nowrap;
}
@media (max-width: 700px) {
  .hero-line {
    white-space: normal;
    font-size: clamp(2.8rem, 12vw, 4rem);
    text-wrap: balance;
  }
}

.hero-sub {
  margin-top: 2rem;
  font-size: calc(var(--size-body) * 1.14);
  color: var(--grey);
  max-width: 44ch;
  margin-inline: auto;
}

/* stacked: the button first, the quiet link beneath it */
.hero-actions {
  margin-top: 2.6rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.4rem;
}

/* ---------- Passages (the scroll) ---------- */

.passage {
  position: relative;
  padding: calc(var(--breath) / 2) var(--edge);
  margin-inline: auto;
  max-width: 72rem;
}

/* a breath of settling dark behind each passage, for quiet legibility —
   it fades away as dawn rises, so its edge can never show against morning */
.passage::before {
  content: "";
  position: absolute;
  inset: -1rem 0;
  z-index: -1;
  background: radial-gradient(ellipse 65% 90% at 50% 50%, rgba(10, 16, 24, 0.2), transparent 75%);
  opacity: calc(1 - var(--dawn, 0));
  pointer-events: none;
}

/* ----- The idea: an editorial column ----- */
.passage--idea  { padding-top: var(--breath); }
.passage--idea .display,
.passage--idea .label { margin-left: clamp(0rem, 6vw, 5rem); }
.passage--idea .prose { margin-left: clamp(0rem, 6vw, 5rem); }

/* a quiet invitation to touch the meadow */
.hint {
  position: relative;
  margin-top: clamp(2.4rem, 6vh, 4.5rem);
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1rem, 1.6vw, 1.3rem);
  color: var(--label-color);
  opacity: 0;
  animation: hint-rise 0.6s ease forwards;
  transition: opacity 1.2s ease;
  pointer-events: none;
  z-index: 10;
}
/* retiring the hint must be a slow exhale, not a cut — the rise animation's
   forward fill pins the opacity, so only another animation can ease it out */
.hint.spent { animation: hint-fade 1.8s ease forwards; }
@keyframes hint-rise {
  to { opacity: 0.85; }
}
@keyframes hint-fade {
  from { opacity: 0.85; }
  to { opacity: 0; }
}

/* ----- How it works: each step is its own moment ----- */
.step-row {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: center;
  min-height: 62vh;
  padding-block: calc(var(--breath) / 2);
}
.step-row--flip .step-visual { order: 2; }
.step-visual svg {
  display: block;
  width: 100%;
  max-width: 560px;
  height: auto;
  margin-inline: auto;
}
.step-text .prose { margin-top: 1.2rem; }

.display--beat { font-size: var(--size-beat); }

/* The step vignettes breathe: lanterns drift, embers twinkle, flames
   flicker, and the little screen lifts toward you on hover. All of it
   sits out for anyone who prefers stillness. */
@media (prefers-reduced-motion: no-preference) {
  .step-svg .drift  { animation: step-drift 7s ease-in-out infinite; }
  .step-svg .drift2 { animation: step-drift 9.5s ease-in-out -3.2s infinite; }
  .step-svg .drift3 { animation: step-drift 11s ease-in-out -6.4s infinite; }
  .step-svg .twk    { animation: step-twinkle 5s ease-in-out infinite; }
  .step-svg .twk2   { animation: step-twinkle 6.8s ease-in-out -2.6s infinite; }
  .step-svg .flame  { animation: step-flame 3.4s ease-in-out infinite; }
  .step-visual .ui-card { transition: transform 0.8s cubic-bezier(0.22, 0.8, 0.3, 1); }
  .step-visual:hover .ui-card { transform: translateY(-5px); }
}
@keyframes step-drift {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
@keyframes step-twinkle {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
@keyframes step-flame {
  0%, 100% { opacity: 1; }
  42% { opacity: 0.75; }
  58% { opacity: 0.92; }
}

@media (max-width: 760px) {
  .step-row {
    grid-template-columns: 1fr;
    min-height: 0;
    gap: 1.8rem;
    padding-block: calc(var(--breath) / 2.6);
  }
  .step-row--flip .step-visual { order: 0; }
  .step-visual svg { max-width: 380px; }
}

/* ----- The meadow fills: one large centered breath ----- */
.passage--fills {
  text-align: center;
  padding-block: var(--breath);
}
.passage--fills .display {
  font-size: calc(var(--size-display) * 1.2);
  max-width: 18ch;
  margin-inline: auto;
}
.passage--fills .prose {
  margin-inline: auto;
  font-size: calc(var(--size-body) * 1.2);
  font-family: var(--serif);
  font-weight: 300;
}

/* ----- The invitation: morning ----- */
.passage--close {
  position: relative;
  padding-top: var(--breath);
  padding-bottom: calc(var(--breath) * 0.8);
  text-align: center;
}
.passage--close .display { margin-inline: auto; }
.passage--close .prose--close { margin-inline: auto; }
.close-action { margin-top: 3rem; }

/* At dawn every text color has already interpolated to ink via the
   --dawn mixes above; the zone only needs a focus ring that reads on
   morning light. */
.dawn-zone :focus-visible { outline-color: var(--ink); }

/* ---------- The scroll: reveals & kinetic type ---------- */

/* Everything arrives slowly and settles — soft fades and rises, weighted
   easing, staggered by --d within each passage. Nothing snappy. */
.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity 1.6s ease var(--d, 0s),
    transform 2s cubic-bezier(0.16, 0.55, 0.22, 1) var(--d, 0s);
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Display lines settle word by word, warming from farlight into paper. */
.display .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.35em);
  /* mixes toward --label-color, not a fixed gold — that way the dim
     pre-reveal state still reads correctly once dawn lightens the page */
  color: color-mix(in oklab, var(--text-strong) 72%, var(--label-color));
  transition:
    opacity 1s ease,
    transform 1.3s cubic-bezier(0.16, 0.55, 0.22, 1),
    color 1.1s ease;
  transition-delay: calc(var(--d, 0s) + var(--i, 0) * 0.07s);
}
.display.is-visible .w {
  opacity: 1;
  transform: translateY(0);
  color: var(--text-strong);
}

/* ---------- Tactility ---------- */

/* A little light the visitor carries through the meadow. */
/* the header keeps its footing when morning comes */
body.dawnlit .site-head .wordmark { color: var(--ink); transition: color 0.8s ease; }
body.dawnlit .cursor-warmth { opacity: 0 !important; }
.site-head .wordmark { transition: color 0.8s ease; }

.cursor-warmth {
  position: fixed;
  left: 0;
  top: 0;
  width: 360px;
  height: 360px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(243, 182, 90, 0.07),
    rgba(243, 182, 90, 0.028) 45%,
    transparent 68%
  );
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 35;
  opacity: 0;
  transition: opacity 1.2s ease;
  will-change: transform;
}

/* On touch, a tap outside the meadow sends a soft ripple of light. */
.tap-ripple {
  position: fixed;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 207, 142, 0.5);
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 35;
  transform: translate(-50%, -50%) scale(1);
  opacity: 0.6;
  animation: tap-ripple 1.4s ease-out forwards;
}
@keyframes tap-ripple {
  to {
    transform: translate(-50%, -50%) scale(11);
    opacity: 0;
  }
}

/* Real dusk: near sunset on the device clock, the sky opens rosier —
   the page quietly meets the visitor at their own dusk. */
.real-dusk #bg-sunset {
  background: linear-gradient(
    to bottom,
    #2a2f45 0%,
    #363448 36%,
    #4a3a44 66%,
    #5c4139 85%,
    #2e2a34 94%,
    var(--dusk-lifted) 100%
  );
}

/* ---------- Footer ---------- */

.site-foot {
  /* the footer rests in the grass — extra room so text sits in the haze,
     above the dense blades */
  padding: calc(var(--breath) / 2) var(--edge) clamp(8rem, 22vh, 15rem);
  text-align: center;
}
.wordmark--foot { font-size: 1rem; color: var(--text-soft); }
.foot-line {
  margin-top: 0.7rem;
  font-size: 0.92rem;
  color: var(--text-soft);
}
.foot-links {
  margin-top: 1.6rem;
  display: flex;
  justify-content: center;
  gap: 1.8rem;
}
.foot-links .quiet-link { font-size: 0.85rem; }
.foot-copy {
  margin-top: 1.6rem;
  font-size: 0.8rem;
  color: var(--text-soft);
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
  /* reveals become simple fades — nothing rises, nothing staggers */
  .reveal {
    transform: none;
    transition: opacity 0.8s ease !important;
    transition-delay: 0s;
  }
  .hint {
    animation: none;
    opacity: 0.85;
  }
}

/* ---------- Narrow screens ---------- */

@media (max-width: 640px) {
  .logo--hero { margin-bottom: 1.8rem; }
}
