/* ──────────────────────────────────────────────────────────────────────────
   Khustup Temple of Knowledge — under-construction page.

   Tokens below are copied verbatim from the Classical design system
   (classical.css, kept in this repo as the reference source of truth). Only
   the tokens and the two component classes this page actually uses (.btn,
   .input) are reproduced here, so the page ships one small stylesheet instead
   of the full 11 KB system + a render-blocking Google Fonts @import.

   If a token changes in classical.css, change it here too.
   ────────────────────────────────────────────────────────────────────────── */

/* — self-hosted fonts (Cormorant Garamond + Lora, latin & latin-ext).
     Both are variable fonts, so one file per family covers 400–600. — */
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(../fonts/cormorant-garamond-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(../fonts/cormorant-garamond-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(../fonts/lora-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(../fonts/lora-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Classical tokens */
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201f1d;
  --color-accent: #b68235;
  --color-accent-400: #e1ad66;

  --font-heading: "Cormorant Garamond", system-ui, sans-serif;
  --font-body: "Lora", system-ui, sans-serif;

  --space-1: 4.6px;
  --space-2: 9.2px;
  --space-3: 13.8px;
  --space-4: 18.4px;
  --space-6: 27.6px;
  --space-8: 36.8px;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;

  /* Page-local: this screen sits on a dark ground, so text roles invert. */
  --ground: #201f1d;
  --on-ground-strong: #f8f4f4;
  --on-ground: #f3f2f2;
  --on-ground-muted: rgba(243, 242, 242, .82);
}

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

html, body {
  margin: 0;
  height: 100%;
  background: var(--ground);
  color: var(--on-ground);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

/* One focus treatment for the whole page — never the browser default. */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── stage ─────────────────────────────────────────────────────────────── */

/* The layout is fluid rather than stepped: the design specifies clamp() on
   every size that changes with the viewport, so one rule covers phone through
   desktop and there is no breakpoint where the page visibly jumps. The media
   query further down only handles the things that genuinely switch mode. */

.stage {
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: var(--ground);
}

.stage__photo,
.stage__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.stage__photo img {
  object-fit: cover;
  /* Design specifies 72% X. The summit sits in the top 8–25% of the frame, so
     the Y value decides whether it survives the crop on viewports wider than
     3:2. See the media query below for the narrow-screen value. */
  object-position: 72% 26%;
  filter: sepia(0.22) saturate(0.78) contrast(1.05) brightness(0.62);
}

.stage__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(32,31,29,.55), rgba(32,31,29,.2) 40%, rgba(32,31,29,.85));
}

.stage__content {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: clamp(48px, 10vh, 120px);
  padding: clamp(28px, 4vw, 44px) clamp(24px, 5vw, 64px) clamp(40px, 5vw, 60px);
  color: var(--on-ground);
}

.masthead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}

.wordmark {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(18px, 4.6vw, 22px);
  line-height: 1.2;
  letter-spacing: .02em;
  color: var(--on-ground);
}

/* ── sound toggle ──────────────────────────────────────────────────────── */

/* Hidden until the script confirms the browser can actually play the track.
   A button that silently does nothing is worse than no button at all. */
.sound {
  flex: none;
  display: none;
  align-items: center;
  justify-content: center;
  width: clamp(44px, 11vw, 46px);
  height: clamp(44px, 11vw, 46px);
  padding: 0;
  border-radius: 999px;
  background: rgba(248, 244, 244, .08);
  border: 1px solid rgba(225, 173, 102, .55);
  color: var(--color-accent-400);
  cursor: pointer;
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.sound[data-ready] { display: inline-flex; }
.sound:hover  { background: rgba(225, 173, 102, .18); }
.sound:active { background: rgba(225, 173, 102, .26); }
.sound svg { display: block; }

/* One icon shows at a time, driven by aria-pressed so the state has a single
   source of truth that assistive tech reads too. */
.sound .icon-on  { display: none; }
.sound .icon-off { display: block; }
.sound[aria-pressed="true"] .icon-on  { display: block; }
.sound[aria-pressed="true"] .icon-off { display: none; }

/* ── hero ──────────────────────────────────────────────────────────────── */

.hero {
  max-width: 680px;
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2.4vw, 22px);
}

.kicker {
  font-size: clamp(10px, 2.6vw, 11px);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--color-accent-400);
  font-feature-settings: 'tnum';
}

.hero__title {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(44px, 10.5vw, 86px);
  line-height: 1.04;
  letter-spacing: -.02em;
  margin: 0;
  color: var(--on-ground-strong);
  text-wrap: balance;
}

/* Closing the gate moves focus here (tabindex="-1") so keyboard users and
   screen readers land inside the page rather than back at the top of the
   document. The heading is not interactive, though, so painting a focus ring
   on it is only noise — a box would appear around the headline for anyone who
   dismissed the gate with a mouse. Focus still moves; it just isn't drawn.
   This is the usual treatment for a programmatic focus target. */
.hero__title:focus,
.hero__title:focus-visible { outline: none; }

.rule {
  width: clamp(56px, 14vw, 88px);
  height: 1px;
  background: rgba(225, 173, 102, .85);
}

.hero__body {
  font-size: clamp(15px, 3.9vw, 17px);
  line-height: 1.65;
  max-width: 520px;
  margin: 0;
  color: var(--on-ground-muted);
  text-wrap: pretty;
}

/* ── signup ────────────────────────────────────────────────────────────── */

.signup { margin-top: 8px; }

.signup__row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/* .btn / .input, retuned for the dark ground. Base rules match classical.css. */
.input {
  font: inherit;
  font-family: var(--font-body);
  /* 16px is deliberate: anything smaller makes iOS Safari zoom the page in
     when the field takes focus, and it never zooms back out. */
  font-size: 16px;
  caret-color: var(--color-accent-400);
  border-radius: var(--radius-md);
  flex: 1 1 260px;
  min-width: 0;
  max-width: 340px;
  padding: 13px 14px;
  background: rgba(248, 244, 244, .1);
  border: 1px solid rgba(243, 242, 242, .4);
  color: var(--on-ground-strong);
}
.input::placeholder { color: rgba(243, 242, 242, .5); }
.input:hover { border-color: rgba(243, 242, 242, .7); }
.input[aria-invalid="true"] { border-color: var(--color-accent-400); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  text-decoration: none;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 14px;
  line-height: 1.2;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  /* 48px clears the minimum comfortable touch target. */
  flex: 1 1 200px;
  min-height: 48px;
  padding: 13px 22px;
  white-space: nowrap;
}
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn-primary { color: var(--color-accent-400); border-color: var(--color-accent-400); }
.btn-primary:not(:disabled):hover  { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.btn-primary:not(:disabled):active { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }

/* Quiet reassurance under the field — the promise that replaces the sentence
   cut from the body copy. */
.signup__note {
  display: block;
  margin-top: 11px;
  font-size: 11.5px;
  line-height: 1.5;
  color: rgba(243, 242, 242, .5);
}

/* Inline error — accent hairline + 12px message under the field. */
.signup__error {
  display: none;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid rgba(225, 173, 102, .5);
  max-width: 380px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--on-ground-muted);
}
.signup__error:not(:empty) { display: block; }

/* ── confirmation ──────────────────────────────────────────────────────── */

.confirm {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  margin-top: 8px;
  padding: 14px 18px;
  border: 1px solid rgba(225, 173, 102, .5);
  border-radius: var(--radius-md);
  background: rgba(225, 173, 102, .1);
  max-width: 520px;
}
.confirm__lede {
  font-family: var(--font-heading);
  font-size: 19px;
  color: var(--color-accent-400);
}
.confirm__text {
  font-size: 14px;
  color: rgba(243, 242, 242, .85);
  word-break: break-word;
}
.confirm:focus { outline: none; }

[hidden] { display: none !important; }

/* ── narrow screens ────────────────────────────────────────────────────── */

/* Only mode switches live here — every size is already fluid above. */
@media (max-width: 620px) {
  /* Portrait crops horizontally, so X is what frames the summit: 64% lands
     the visible slice across the peak. */
  .stage__photo img {
    object-position: 64% 40%;
    filter: sepia(0.22) saturate(0.78) contrast(1.05) brightness(0.6);
  }
  .stage__scrim {
    background: linear-gradient(180deg, rgba(32,31,29,.6), rgba(32,31,29,.18) 34%, rgba(32,31,29,.9));
  }

  .wordmark { max-width: 200px; line-height: 1.15; }

  /* Field over button, both full width — side by side is too cramped here.

     The flex shorthands must be reset. `.input` and `.btn` carry
     `flex: 1 1 260px` / `1 1 200px` for the desktop row, where the basis is a
     WIDTH. Turning the container into a column re-reads that basis as a
     HEIGHT, so the field became a 260px-tall box and grew from there. Height
     here has to come from content and padding, so: flex: none. */
  .signup__row { flex-direction: column; align-items: stretch; gap: 11px; }
  .input,
  .btn { flex: none; width: 100%; }
  .input { max-width: none; padding: 14px; }
  .btn { padding: 14px; min-height: 50px; font-size: 15px; }

  /* The confirmation reads better stacked once the line has to wrap anyway. */
  .confirm { flex-direction: column; align-items: flex-start; gap: 7px; padding: 18px; }
  .confirm__lede { font-size: 24px; }
  .confirm__text { font-size: 14.5px; line-height: 1.6; }
}

@media (prefers-reduced-motion: no-preference) {
  .btn, .input, .sound { transition: background-color 180ms ease, border-color 180ms ease, opacity 180ms ease; }
}

/* ── entry gate ────────────────────────────────────────────────────────── */

/* Sits over the page until the visitor clicks through. Its only job is to
   convert "the site opened" into a real user gesture, which is the one thing
   browsers require before they will let sound play. */
.gate {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(24px, 6vw, 48px);
  text-align: center;
  /* Deeper than the page scrim so the photo reads as a backdrop, not content. */
  background: rgba(32, 31, 29, .82);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.gate__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(18px, 3vw, 26px);
  max-width: 420px;
}

.gate__wordmark {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(28px, 7.5vw, 40px);
  line-height: 1.12;
  letter-spacing: .01em;
  color: var(--on-ground-strong);
}

/* The gate's button hugs its label — the form's flex sizing must not apply. */
.gate__enter {
  flex: none;
  width: auto;
  min-width: 160px;
  padding: 14px 30px;
  font-size: 15px;
}

.gate__note {
  font-size: 12px;
  line-height: 1.6;
  color: rgba(243, 242, 242, .55);
}

/* A quiet way past the gate for anyone who does not want sound. Underlined
   rather than button-shaped so it never competes with Enter. */
.gate__skip {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: rgba(243, 242, 242, .8);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.gate__skip:hover { color: var(--color-accent-400); }

/* Dismissal. The element is removed from the DOM on transitionend, so a
   reduced-motion visitor who gets no transition is handled by a timeout in
   the script rather than being left with an invisible overlay on top. */
.gate[data-leaving] {
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .gate { transition: opacity 520ms ease; }
}
