/* ============================================================
   dream1996 — stylesheet
   ------------------------------------------------------------
   1.  Tokens
   2.  Reset & base
   3.  Typography helpers
   4.  Background layers   (the only thing that blurs)
   5.  Liquid Glass system
   6.  Buttons
   7.  Navigation
   8.  Descent rail
   9.  Hero
   10. Sections
   11. Products
   12. Steps
   13. Values
   14. FAQ
   15. Finale
   16. Footer
   17. Sub pages
   18. Motion & reveal
   19. Responsive
   19b. Utility controls (audio + day/night)
   20. Reduced motion / print
   ============================================================ */


/* ---- 1. Tokens --------------------------------------------- */
:root {
  /* Palette — deliberately monochrome. The colour in this design
     comes from the photograph behind the interface, never from
     the interface itself.
       Cloudlight  #FFFFFF   primary text, highlights
       Vapour      #EFEDF8   cool white, secondary text base
       Deep dusk   #0A0912   scrim + shadow base            */
  --cloudlight: #ffffff;
  --vapour: #efedf8;
  --dusk: 10, 9, 18;

  --text-1: rgba(255, 255, 255, 0.97);
  --text-2: rgba(239, 237, 248, 0.78);
  --text-3: rgba(239, 237, 248, 0.63);
  --text-4: rgba(239, 237, 248, 0.48);

  --edge: rgba(255, 255, 255, 0.14);
  --edge-2: rgba(255, 255, 255, 0.22);
  --edge-3: rgba(255, 255, 255, 0.32);

  --surface: rgba(255, 255, 255, 0.055);
  --surface-2: rgba(255, 255, 255, 0.085);

  /* ---- Brand marks -------------------------------------------
     THE ONE PLACE THAT CONTROLS THE COLOUR OF ALL PRODUCT LOGOS.
     Every service logo is drawn as a CSS mask filled with this
     token, so the brands' own colours never appear and changing
     this line restyles all nine at once. White with a trace of
     lavender, to sit with the Dreamcore sky rather than on it. */
  --brand-icon-color: rgba(235, 230, 255, 0.85);
  --brand-icon-color-hover: rgba(246, 243, 255, 0.98);

  /* Type */
  --font-sans: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Rhythm — 4/8px based */
  --gutter: clamp(20px, 5vw, 48px);
  --section-space: clamp(96px, 15vh, 190px);
  --radius: 20px;
  --radius-sm: 14px;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur: 260ms;

  /* Background layer — written by src/background.js on scroll */
  --bg-blur: 0.5px;
  --bg-scale: 1;
  --bg-scrim: 0.2;

  /* Day/night crossfade length */
  --theme-fade: 800ms;
}


/* ---- 2. Reset & base --------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 120px;
}

body {
  margin: 0;
  min-height: 100%;
  background-color: #0a0912;
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.65;
  color: var(--text-2);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.85);
  outline-offset: 3px;
  border-radius: 6px;
}

.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 200;
  padding: 12px 20px;
  border-radius: 999px;
  background: rgba(12, 10, 22, 0.92);
  color: var(--text-1);
  border: 1px solid var(--edge-2);
  transform: translateY(-160%);
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus-visible { transform: translateY(0); }

.container {
  width: 100%;
  max-width: 1160px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: 820px; }


/* ---- 3. Typography helpers --------------------------------- */
.mono {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--text-4);
}

.wordmark {
  font-weight: 400;
  letter-spacing: -0.025em;
  color: var(--text-1);
}

.eyebrow { color: var(--text-4); }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* ---- 4. Background layers ----------------------------------
   A single fixed layer for the entire site. It is inset well
   beyond the viewport so that, once blurred, its soft edges
   never creep into frame.
   ------------------------------------------------------------ */
.bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

/* Two layers, day and night. Everything geometric is declared once
   here and therefore applies identically to both — same inset, same
   crop, same object-position, same transform, same blur. The only
   thing that ever differs between them is opacity.

   Both are hidden by default; the active one is switched on below.
   `visibility` is delayed by the length of the fade so the outgoing
   layer stays painted for the whole crossfade and then stops costing
   anything once it is invisible. */
.bg__media {
  position: absolute;
  /* Kept deliberately tight. Every pixel of inset pushes this layer's
     aspect ratio toward square, which makes `cover` crop more off the
     left and right — and that is where the staircase and the sign are.
     48px is enough: the push-in scale grows in step with the blur, so
     the margin hiding the soft edges is always ahead of what the blur
     needs (102px available against 54px required at maximum). */
  inset: -48px;
  width: calc(100% + 96px);
  height: calc(100% + 96px);
  max-width: none; /* must beat the img reset, or the layer is clipped */
  object-fit: cover;
  object-position: var(--bg-pos, 58% 50%);
  filter: blur(var(--bg-blur));
  transform: scale(var(--bg-scale));
  transform-origin: 58% 45%;
  will-change: filter, transform;

}

/* The crossfade.

   Only the night layer animates. It sits on top and fades its
   opacity in and out over a day layer that stays fully opaque
   underneath for the whole transition. That keeps coverage at
   100% the entire time.

   Fading the two in opposite directions would look like the
   obvious approach, but it dips: at the halfway point the
   compositor gives 0.5*night + 0.5*0.5*day, leaving a quarter of
   the page showing through as a dark sag in the middle of the
   fade. Holding one layer opaque avoids that completely.

   `visibility` is what stops the hidden layer costing anything.
   It flips only once the fade has finished (delayed by the fade
   length) and comes back instantly (0s) when the layer is needed
   again, so a fully occluded background is never being blurred
   for nothing. */
.bg__media--day {
  opacity: 1;
  visibility: visible;
  transition: visibility 0s linear 0s;
}

:root[data-theme='night'] .bg__media--day {
  visibility: hidden;
  transition: visibility 0s linear var(--theme-fade);
}

.bg__media--night {
  opacity: 0;
  visibility: hidden;
  transition:
    opacity var(--theme-fade) var(--ease),
    visibility 0s linear var(--theme-fade);
}

:root[data-theme='night'] .bg__media--night {
  opacity: 1;
  visibility: visible;
  transition:
    opacity var(--theme-fade) var(--ease),
    visibility 0s linear 0s;
}

/* Even, subtle darkening so white type stays legible. */
.bg__scrim {
  position: absolute;
  inset: 0;
  background: rgb(var(--dusk));
  opacity: var(--bg-scrim);
}

/* Directional shading only where the hero copy sits, so the
   staircase and the sign on the right stay untouched. */
.bg__vignette {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg, rgba(var(--dusk), 0.58) 0%, rgba(var(--dusk), 0.24) 34%, rgba(var(--dusk), 0) 60%),
    linear-gradient(to top, rgba(var(--dusk), 0.5) 0%, rgba(var(--dusk), 0) 28%);
}


/* ---- 5. Liquid Glass system --------------------------------
   Translucent, backdrop-blurred, with a bright top edge and a
   soft interior falloff. Restrained on purpose: thin borders,
   low-contrast fills, no reflections.
   ------------------------------------------------------------ */
.glass {
  position: relative;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.09) 0%, rgba(255, 255, 255, 0.035) 42%, rgba(255, 255, 255, 0.05) 100%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(255, 255, 255, 0.04),
    0 22px 50px -28px rgba(var(--dusk), 0.85);
}

/* Specular highlight along the top edge — brightest at centre. */
.glass::before {
  content: '';
  position: absolute;
  inset-inline: 12%;
  top: -1px;
  height: 1px;
  border-radius: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  opacity: 0.65;
  transition: opacity var(--dur) var(--ease);
  pointer-events: none;
}


/* ---- 6. Buttons -------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 24px;
  border: 1px solid var(--edge-2);
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 400;
  letter-spacing: 0.005em;
  color: var(--text-1);
  background: rgba(255, 255, 255, 0.06);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  backdrop-filter: blur(18px) saturate(150%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 10px 26px -16px rgba(var(--dusk), 0.9);
  transition:
    background var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    transform var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

.btn--primary {
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.3);
}

.btn--ghost {
  background: rgba(255, 255, 255, 0.02);
  border-color: rgba(255, 255, 255, 0.15);
  color: var(--text-2);
}

.btn--sm { min-height: 44px; padding: 0 18px; font-size: 0.9rem; }
.btn--lg { min-height: 56px; padding: 0 34px; font-size: 1.02rem; }

@media (hover: hover) {
  .btn:hover {
    background: rgba(255, 255, 255, 0.17);
    border-color: var(--edge-3);
    transform: translateY(-1px) scale(1.015);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.3),
      0 16px 34px -18px rgba(var(--dusk), 0.95);
  }
  .btn--ghost:hover { background: rgba(255, 255, 255, 0.09); color: var(--text-1); }
}
.btn:active { transform: translateY(0) scale(0.995); }


/* ---- 7. Navigation ----------------------------------------- */
.nav-wrap {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  padding: clamp(12px, 2vw, 20px) var(--gutter);
  padding-top: max(clamp(12px, 2vw, 20px), env(safe-area-inset-top));
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.nav {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
  width: 100%;
  max-width: 1160px;
  padding: 9px 9px 9px 22px;
  border-radius: 999px;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

/* Slightly denser once the page has moved, for legibility. */
.nav.is-scrolled {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.11) 0%, rgba(255, 255, 255, 0.06) 100%),
    rgba(var(--dusk), 0.42);
  border-color: var(--edge-2);
}

.nav__brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 1.02rem;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.4vw, 30px);
  margin-left: auto;
}

.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.92rem;
  color: var(--text-3);
  transition: color var(--dur) var(--ease);
}
@media (hover: hover) {
  .nav__link:hover { color: var(--text-1); }
}

.nav__cta { flex: none; }


/* ---- 8. Descent rail --------------------------------------
   Marks how far into the page you have gone. It exists because
   the page really does descend: the background blurs as you go.
   ------------------------------------------------------------ */
.rail {
  position: fixed;
  left: 26px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 90;
  display: none;
}

.rail__line {
  position: absolute;
  left: 3px;
  top: 4px;
  bottom: 4px;
  width: 1px;
  background: rgba(255, 255, 255, 0.13);
}

.rail__progress {
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--rail-progress, 0%);
  background: rgba(255, 255, 255, 0.55);
  transition: height 120ms linear;
}

.rail__list { display: flex; flex-direction: column; gap: 22px; }

.rail__item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 22px;
}

.rail__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.rail__label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--text-4);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  white-space: nowrap;
}

.rail__item.is-active .rail__dot { background: rgba(255, 255, 255, 0.95); transform: scale(1.15); }

@media (hover: hover) {
  .rail__item:hover .rail__dot { background: rgba(255, 255, 255, 0.8); }
}

/* Labels stay in the DOM for screen readers but only surface
   where there is room for them beside the content column. */
.rail__item:focus-visible .rail__label { opacity: 0.9; transform: none; }

@media (hover: hover) and (min-width: 1500px) {
  .rail:hover .rail__label { opacity: 0.72; transform: none; }
}


/* ---- 9. Hero ----------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: clamp(140px, 22vh, 220px) clamp(90px, 14vh, 150px);
}

/* Held to the left so the staircase in the photograph breathes. */
.hero__inner {
  max-width: 620px;
  text-shadow: 0 1px 30px rgba(var(--dusk), 0.45);
}

.hero__domain { margin-bottom: clamp(20px, 4vh, 34px); color: var(--text-3); }

.hero__title {
  font-size: clamp(3.4rem, 9.5vw, 7rem);
  font-weight: 300;
  line-height: 0.96;
  letter-spacing: -0.045em;
}

.hero__tagline {
  margin-top: clamp(16px, 2.6vh, 24px);
  font-size: clamp(1.1rem, 2.2vw, 1.5rem);
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--text-1);
}

.hero__intro {
  margin-top: clamp(18px, 2.8vh, 26px);
  max-width: 44ch;
  font-size: clamp(0.98rem, 1.3vw, 1.075rem);
  color: var(--text-2);
}

.hero__actions {
  margin-top: clamp(32px, 5vh, 48px);
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.hero__scroll {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(28px, 5vh, 48px);
  display: none;
  align-items: center;
  min-height: 44px;
  gap: 12px;
  color: var(--text-4);
  transition: color var(--dur) var(--ease);
}
.hero__scroll-line {
  display: block;
  width: 46px;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  animation: railPulse 3.6s var(--ease) infinite;
}
@media (hover: hover) { .hero__scroll:hover { color: var(--text-2); } }

@keyframes railPulse {
  0%, 100% { transform: scaleX(0.55); opacity: 0.5; }
  50%      { transform: scaleX(1);    opacity: 1; }
}


/* ---- 10. Sections ------------------------------------------ */
.section { padding-block: var(--section-space); }

.section__head { max-width: 640px; margin-bottom: clamp(44px, 7vh, 72px); }

.section__title {
  margin-top: 18px;
  font-size: clamp(1.9rem, 4vw, 3rem);
  font-weight: 300;
  line-height: 1.12;
  letter-spacing: -0.032em;
  color: var(--text-1);
}

.section__intro {
  margin-top: 16px;
  max-width: 52ch;
  font-size: 1.02rem;
  color: var(--text-3);
}


/* ---- 11. Products ------------------------------------------ */
.products {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: clamp(16px, 1.8vw, 22px);
}

.product {
  display: flex;
  flex-direction: column;
  /* Padding moved onto the button inside, so the whole card is one
     target rather than a card with a small hotspot in it. */
  padding: 0;
  transition:
    transform var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    background var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

@media (hover: hover) {
  .product:hover {
    transform: translateY(-3px) scale(1.012);
    border-color: var(--edge-2);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.22),
      inset 0 -1px 0 rgba(255, 255, 255, 0.05),
      0 30px 60px -30px rgba(var(--dusk), 0.95);
  }
  .product:hover::before { opacity: 1; }
}

/* The card is a single button: same look, one clear target. */
.product__open {
  display: flex;
  flex: 1;
  flex-direction: column;
  width: 100%;
  padding: clamp(22px, 2.4vw, 28px);
  border: 0;
  border-radius: inherit;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.product__open:focus-visible { outline-offset: -3px; }

.product__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 22px;
}

.product__note {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--text-4);
}

.product__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--edge);
  background: rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--text-2);
  overflow: hidden;
}
/* The brand mark, painted as a mask so its colour comes entirely
   from --brand-icon-color. `contain` keeps every mark's own aspect
   ratio, so nothing is ever stretched or squashed, and --logo-scale
   (from src/products.js) evens out their perceived size. */
.product__logo {
  display: block;
  width: calc(22px * var(--logo-scale, 1));
  height: calc(22px * var(--logo-scale, 1));
  background-color: var(--brand-icon-color);
  /* mask-image itself is set per service in src/render.js. */
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  transition:
    background-color var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

@media (hover: hover) {
  .product:hover .product__logo {
    background-color: var(--brand-icon-color-hover);
    transform: scale(1.03);
  }
}

.product__name {
  font-size: 1.12rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--text-1);
}

.product__desc {
  margin-top: 8px;
  font-size: 0.93rem;
  line-height: 1.6;
  color: var(--text-3);
}

/* Price reads through size and space, never colour. */
.product__prices {
  margin-top: auto;
  padding-top: 26px;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
}

.product__from {
  font-size: 0.72rem;
  color: var(--text-4);
}

.product__now {
  font-size: clamp(2rem, 3.2vw, 2.45rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

.product__period {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-4);
}

.product__cta {
  margin-top: 24px;
  width: 100%;
}


/* ---- 12. Steps --------------------------------------------- */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  gap: clamp(16px, 1.8vw, 22px);
}

.step {
  padding: clamp(26px, 2.6vw, 34px);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .step:hover { transform: translateY(-2px); border-color: var(--edge-2); }
  .step:hover::before { opacity: 1; }
}

.step__num { color: var(--text-4); }

.step__title {
  margin-top: 20px;
  font-size: 1.1rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--text-1);
}

.step__body { margin-top: 10px; font-size: 0.93rem; color: var(--text-3); }


/* ---- 13. Values -------------------------------------------- */
.values {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(28px, 3vw, 40px);
}

.value { padding-top: 22px; border-top: 1px solid var(--edge); }

.value__title {
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--text-1);
}

.value__body { margin-top: 8px; font-size: 0.92rem; color: var(--text-3); }


/* ---- 14. FAQ ----------------------------------------------- */
.faq { padding: 6px clamp(18px, 2.4vw, 30px); }

.faq__item { border-top: 1px solid var(--edge); }
.faq__item:first-of-type { border-top: 0; }

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 24px 0;
  min-height: 44px;
  font-size: 1.01rem;
  font-weight: 400;
  color: var(--text-1);
  cursor: pointer;
  list-style: none;
  transition: color var(--dur) var(--ease);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:focus-visible { outline-offset: -2px; }

/* Plus that becomes a minus. */
.faq__mark {
  position: relative;
  flex: none;
  width: 13px;
  height: 13px;
  opacity: 0.6;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.faq__mark::before,
.faq__mark::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
}
.faq__mark::before { width: 13px; height: 1px; }
.faq__mark::after  { width: 1px; height: 13px; transition: opacity var(--dur) var(--ease); }

.faq__item[open] .faq__mark { transform: rotate(180deg); opacity: 0.9; }
.faq__item[open] .faq__mark::after { opacity: 0; }

@media (hover: hover) {
  .faq__q:hover .faq__mark { opacity: 1; }
}

.faq__a { overflow: hidden; }
.faq__a p {
  padding-bottom: 26px;
  max-width: 62ch;
  font-size: 0.95rem;
  color: var(--text-3);
}


/* ---- 15. Finale -------------------------------------------- */
.finale {
  padding-block: clamp(140px, 26vh, 280px);
  text-align: center;
}

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

.finale__wordmark {
  font-size: clamp(2.6rem, 7vw, 5rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.045em;
}

.finale__tagline {
  margin-top: 20px;
  font-size: clamp(1rem, 1.8vw, 1.2rem);
  font-weight: 300;
  color: var(--text-2);
}

.finale__line { margin-top: 40px; color: var(--text-4); }

.finale .btn { margin-top: 44px; }


/* ---- 16. Footer -------------------------------------------- */
.footer {
  padding-block: clamp(40px, 6vh, 60px);
  /* Extra room at the very bottom so the fixed audio control never
     sits on top of the footer row. */
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 84px);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px 32px;
}

.footer__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 24px;
}

.footer__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.88rem;
  color: var(--text-3);
  transition: color var(--dur) var(--ease);
}
@media (hover: hover) { .footer__link:hover { color: var(--text-1); } }

.footer__domain, .footer__copy { color: var(--text-4); }


/* ---- 17. Sub pages ----------------------------------------- */
.page {
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: clamp(140px, 20vh, 200px) clamp(80px, 12vh, 140px);
}

.page__inner { max-width: 660px; }

.page__title {
  margin-top: 18px;
  font-size: clamp(2.1rem, 5vw, 3.2rem);
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.035em;
  color: var(--text-1);
}

.page__body { margin-top: 28px; }
.page__body p { margin-top: 16px; max-width: 60ch; color: var(--text-2); }
.page__body h2 {
  margin-top: 40px;
  font-size: 1.1rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--text-1);
}

/* Lists in long-form copy. A hairline dash rather than a bullet, to
   stay in keeping with the rest of the page. */
.page__body ul {
  margin-top: 16px;
  max-width: 60ch;
}
.page__body li {
  position: relative;
  margin-top: 9px;
  padding-left: 20px;
  color: var(--text-2);
}
.page__body li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.78em;
  width: 7px;
  height: 1px;
  background: var(--text-4);
}

/* Inline links in body copy: underlined so they read as links
   without needing a colour of their own. */
.page__link {
  color: var(--text-1);
  text-decoration: underline;
  text-decoration-color: var(--edge-2);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .page__link:hover { text-decoration-color: var(--text-2); }
}
.page__back { margin-top: 48px; }


/* ---- 18. Motion & reveal ----------------------------------- */
/* Everything here is gated behind .js — added by an inline script
   in the head. Without JavaScript nothing is ever hidden, so the
   content stays readable and crawlable. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 900ms var(--ease), transform 900ms var(--ease);
}
.js .reveal.is-in { opacity: 1; transform: none; }

/* Orchestrated page-load for the hero only. */
.js .hero__domain,
.js .hero__title,
.js .hero__tagline,
.js .hero__intro,
.js .hero__actions {
  opacity: 0;
  transform: translateY(14px);
}
.is-ready .hero__domain,
.is-ready .hero__title,
.is-ready .hero__tagline,
.is-ready .hero__intro,
.is-ready .hero__actions {
  opacity: 1;
  transform: none;
  transition: opacity 1000ms var(--ease), transform 1000ms var(--ease);
}
.is-ready .hero__domain  { transition-delay: 80ms; }
.is-ready .hero__title   { transition-delay: 160ms; }
.is-ready .hero__tagline { transition-delay: 260ms; }
.is-ready .hero__intro   { transition-delay: 350ms; }
.is-ready .hero__actions { transition-delay: 440ms; }


/* ---- 19. Responsive ---------------------------------------- */
@media (min-width: 1280px) {
  .rail { display: block; }
  .hero__scroll { display: inline-flex; }
}

@media (max-width: 900px) {
  .products, .steps { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
}

/* Nav folds to two rows rather than hiding behind a menu. */
@media (max-width: 760px) {
  .nav {
    flex-wrap: wrap;
    justify-content: space-between;
    row-gap: 2px;
    padding: 8px 8px 8px 18px;
    border-radius: 26px;
  }
  .nav__links {
    order: 3;
    width: 100%;
    margin-left: 0;
    justify-content: space-between;
    gap: 8px;
    padding: 0 6px 2px;
  }
  .nav__link { font-size: 0.86rem; }
  .nav__brand { font-size: 0.98rem; }
  html { scroll-padding-top: 150px; }
}

@media (max-width: 620px) {
  .bg__media { object-position: var(--bg-pos-mobile, 46% 50%); }

  /* A phone crops the image to a narrow slice, so the composition
     can no longer be relied on to leave a quiet area for the type.
     An even, still-restrained wash carries readability instead. */
  .bg__vignette {
    background:
      linear-gradient(180deg,
        rgba(var(--dusk), 0.46) 0%,
        rgba(var(--dusk), 0.34) 38%,
        rgba(var(--dusk), 0.26) 64%,
        rgba(var(--dusk), 0.44) 100%);
  }
  .hero { padding-block: clamp(150px, 24vh, 200px) clamp(70px, 10vh, 110px); }
  .products, .steps, .values { grid-template-columns: 1fr; }
  .footer__inner { flex-direction: column; align-items: flex-start; gap: 4px; }
}


/* ---- 19b. Audio control ------------------------------------
   A quiet glass pill, fixed to the bottom-right. Deliberately
   not a player: one button, one slider, nothing else.
   ------------------------------------------------------------ */
/* The two persistent controls share one fixed row, so the spacing
   between them stays right without either hard-coding the other's
   width. They stay separate glass shapes rather than merging into
   one panel. */
.utility {
  position: fixed;
  z-index: 95;
  right: max(20px, env(safe-area-inset-right, 0px));
  bottom: max(20px, env(safe-area-inset-bottom, 0px));
  display: flex;
  align-items: center;
  gap: 10px;
}

.theme {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
  color: var(--text-1);
  cursor: pointer;
  transition:
    transform var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    background var(--dur) var(--ease);
}

@media (hover: hover) {
  .theme:hover {
    transform: translateY(-1px) scale(1.04);
    border-color: var(--edge-2);
    background: rgba(255, 255, 255, 0.11);
  }
  .theme:hover::before { opacity: 1; }
}
.theme:active { transform: translateY(0) scale(0.97); }

.theme__icon { width: 16px; height: 16px; }
.theme__icon--sun { display: none; }
:root[data-theme='night'] .theme__icon--moon { display: none; }
:root[data-theme='night'] .theme__icon--sun { display: block; }

.audio {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-right: 14px;
  border-radius: 999px;
  transition:
    transform var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    background var(--dur) var(--ease);
}

@media (hover: hover) {
  .audio:hover { transform: translateY(-1px) scale(1.02); border-color: var(--edge-2); }
  .audio:hover::before { opacity: 1; }
}
.audio:focus-within { border-color: var(--edge-2); }

.audio__toggle {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-1);
  cursor: pointer;
  transition: background var(--dur) var(--ease);
}
@media (hover: hover) {
  .audio__toggle:hover { background: rgba(255, 255, 255, 0.1); }
}

.audio__icon { width: 15px; height: 15px; fill: currentColor; }
.audio__icon--pause { display: none; }
.audio.is-playing .audio__icon--play { display: none; }
.audio.is-playing .audio__icon--pause { display: block; }

/* Space is reserved whether or not the glyph is showing, so
   nothing shifts when the volume reaches zero. */
.audio__muted {
  display: grid;
  place-items: center;
  width: 14px;
  color: var(--text-3);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.audio__muted svg { width: 13px; height: 13px; }
.audio.is-muted .audio__muted { opacity: 0.85; }

/* Range: the element stays 44px tall for a comfortable target,
   while the visible track is drawn as a hairline through it. */
.audio__range {
  -webkit-appearance: none;
  appearance: none;
  width: 76px;
  height: 44px;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}

.audio__range::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(
    to right,
    rgba(255, 255, 255, 0.85) var(--fill, 35%),
    rgba(255, 255, 255, 0.2) var(--fill, 35%)
  );
}
.audio__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 11px;
  height: 11px;
  margin-top: -4px; /* centre the thumb on the 3px track */
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(var(--dusk), 0.6);
  transition: transform var(--dur) var(--ease);
}

.audio__range::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.2);
}
.audio__range::-moz-range-progress {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.85);
}
.audio__range::-moz-range-thumb {
  width: 11px;
  height: 11px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(var(--dusk), 0.6);
}

@media (hover: hover) {
  .audio__range:hover::-webkit-slider-thumb { transform: scale(1.18); }
}
.audio__range:focus-visible { outline-offset: 2px; border-radius: 999px; }

@media (max-width: 620px) {
  .utility {
    right: max(14px, env(safe-area-inset-right, 0px));
    bottom: max(14px, env(safe-area-inset-bottom, 0px));
    gap: 8px;
  }
  .audio { padding-right: 12px; }
  .audio__range { width: 64px; }
}


/* ---- 19c. Plan modal ---------------------------------------
   The same glass, over a slightly deeper scrim. The Dreamcore
   background stays visible behind it.
   ------------------------------------------------------------ */
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(16px, 4vh, 48px) var(--gutter);
}
.modal[hidden] { display: none; }

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(var(--dusk), 0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity 240ms var(--ease);
}

.modal__panel {
  position: relative;
  width: 100%;
  max-width: 520px;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(26px, 3.4vw, 36px);
  border-radius: var(--radius);
  opacity: 0;
  transform: translateY(12px) scale(0.99);
  transition:
    opacity 240ms var(--ease),
    transform 240ms var(--ease);
}

.modal.is-open .modal__backdrop { opacity: 1; }
.modal.is-open .modal__panel { opacity: 1; transform: none; }

.modal__close {
  position: absolute;
  top: 12px;
  right: 12px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  transition:
    color var(--dur) var(--ease),
    background var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .modal__close:hover {
    color: var(--text-1);
    background: rgba(255, 255, 255, 0.09);
    border-color: var(--edge);
  }
}
.modal__close svg { width: 13px; height: 13px; }

.modal__title {
  margin-top: 16px;
  font-size: clamp(1.5rem, 3vw, 1.95rem);
  font-weight: 300;
  letter-spacing: -0.03em;
  color: var(--text-1);
}

.modal__note {
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--text-4);
}

.modal__plans {
  margin-top: clamp(22px, 3vh, 30px);
  display: grid;
  gap: 12px;
}

/* ---- A single plan ------------------------------------------ */
.plan {
  padding: 20px;
  border: 1px solid var(--edge);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.04);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
@media (hover: hover) {
  .plan:hover { border-color: var(--edge-2); background: rgba(255, 255, 255, 0.06); }
}

.plan__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.plan__title {
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--text-1);
}

.plan__rate { color: var(--text-4); font-size: 0.7rem; }

.plan__pricing {
  margin-top: 16px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 18px;
  flex-wrap: wrap;
}

/* Regular price recedes; it is never coloured, only quieter. */
.plan__regular {
  font-size: 0.82rem;
  color: var(--text-4);
}
.plan__regular-label { font-size: 0.68rem; }
.plan__regular s { text-decoration-thickness: 1px; }

/* The dream1996 price carries the weight, through size alone. */
.plan__dream {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-left: auto;
}
.plan__dream-label { font-size: 0.68rem; color: var(--text-3); }
.plan__dream-price {
  font-size: clamp(1.7rem, 3vw, 2.05rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}
.plan__dream-period { font-size: 0.72rem; color: var(--text-4); }

.plan__cta { margin-top: 18px; width: 100%; }

@media (max-width: 620px) {
  /* Closer to a bottom sheet on a phone, same glass. */
  .modal { place-items: end center; padding: 0; }
  .modal__panel {
    max-width: none;
    max-height: 88svh;
    padding: 26px 20px calc(26px + env(safe-area-inset-bottom, 0px));
    border-radius: var(--radius) var(--radius) 0 0;
    transform: translateY(24px);
  }
  .plan__pricing { gap: 8px 12px; }
  .plan__dream { margin-left: 0; }
}


/* ---- 19c-b. Clock ------------------------------------------
   The visitor's local time, top right. Sized and coloured like
   the site's other quiet metadata so it reads as a detail that
   was always there rather than a widget that was added.

   It sits below the navbar because the nav pill spans the whole
   container width — there is no dependable gap beside it on
   narrower screens. Tabular figures keep the digits from
   shuffling when the minute turns.
   ------------------------------------------------------------ */
.clock {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + var(--clock-top, 100px));
  right: max(var(--gutter), env(safe-area-inset-right, 0px));
  z-index: 93;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: rgba(238, 234, 255, 0.5);
  text-shadow: 0 1px 16px rgba(var(--dusk), 0.7);
  pointer-events: none;
}

/* The navbar folds to two rows below this width, so the clock
   steps down to stay clear of it. */
@media (max-width: 760px) {
  :root { --clock-top: 132px; }
}


/* ---- 19d. Late night ---------------------------------------
   The one quiet line the site says to anyone here after midnight.
   Deliberately not a notification: no surface, no border, no
   shadow of its own, nothing to dismiss. It sits below the two
   utility controls in the stack so it can never cover them, and
   ignores the pointer entirely.
   ------------------------------------------------------------ */
.latenight {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 92px);
  transform: translateX(-50%);
  z-index: 94;
  margin: 0;
  max-width: min(88vw, 44ch);
  padding-inline: 8px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  line-height: 1.7;
  color: rgba(238, 234, 255, 0.58);
  text-shadow: 0 1px 18px rgba(var(--dusk), 0.7);
  pointer-events: none;

  /* Two opacities, multiplied by the browser. This outer element
     carries the scroll fade and follows the scroll exactly, with
     no transition of its own. */
  opacity: var(--ln-scroll, 1);
}

/* The inner span carries the fade cycle. Keeping them apart means
   scrolling can never interrupt a fade, and a fade never fights
   the scroll position. Duration is set per message in
   src/latenight.js so arriving and leaving can differ. */
.latenight__text {
  display: block;
  opacity: 0;
  transition: opacity 2000ms var(--ease);
}

.latenight.is-in .latenight__text { opacity: 1; }


/* ---- 20. Reduced motion ------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  :root {
    /* Background settles on one static value; nothing animates. */
    --bg-blur: 6px;
    --bg-scale: 1;
    --bg-scrim: 0.42;
  }
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  .hero__domain, .hero__title, .hero__tagline, .hero__intro, .hero__actions {
    opacity: 1;
    transform: none;
  }
  .bg__media { will-change: auto; }
}

@media print {
  .bg, .nav-wrap, .rail, .hero__scroll, .utility { display: none; }
  body { color: #000; background: #fff; }
}
