/*
  XR Camp site styles.
  The page is readable on its own: the 3D scene behind it is an enhancement.
  Text always sits on a solid-enough panel to keep WCAG AA contrast over any
  part of the scene. No web fonts: system fonts load instantly everywhere,
  including mainland China.
*/

:root {
  --night: #0d0820;
  --panel: rgb(20 12 44 / 0.88);
  --panel-edge: rgb(201 167 255 / 0.25);
  --text: #f5f2ff;
  --muted: #cfc6e8;
  --lilac: #c9a7ff;
  --pink: #ff8fc3;
  --gold: #ffd166;
  --teal: #5fd4c4;
  --ink: #1a0f2e;
  --paper: #fdfcf8;
  --paper-text: #1b1b1f;
  --paper-muted: #4a4a55;
  --deep-purple: #5b2a86;
  --radius: 1rem;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
}

* { box-sizing: border-box; }

/* Buttons set display, which would otherwise override the hidden attribute. */
[hidden] { display: none !important; }

html { background: var(--night); }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--text);
  /* Shown whenever the 3D scene is off or unavailable. */
  background:
    radial-gradient(60rem 40rem at 80% 10%, rgb(91 42 134 / 0.55), transparent 70%),
    radial-gradient(50rem 40rem at 10% 90%, rgb(31 138 138 / 0.35), transparent 70%),
    var(--night);
  background-attachment: fixed;
}

/* The scene fills the window, behind everything. */
#scene-layer {
  position: fixed;
  inset: 0;
  z-index: 0;
  /* Fully visible by 45% of the fold, so the images can fly in clear night. */
  opacity: clamp(0, calc(var(--fold, 0) * 2.2), 1);
}

/* Daylight in front of the night: the 2D half of the site. The threshold
   sets --fold from 0 to 1 as you scroll through it. */
#day {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--paper);
  opacity: clamp(0, calc(1 - var(--fold, 0) * 2.2), 1);
}
#scene-layer a-scene { width: 100%; height: 100%; }

.site-header, main, .site-footer { position: relative; z-index: 1; }

a { color: var(--lilac); text-underline-offset: 0.2em; }
a:hover { color: var(--pink); }

:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; border-radius: 0.25rem; }

.skip-link { position: absolute; left: -999rem; z-index: 10; }
.skip-link:focus { left: 1rem; top: 1rem; padding: 0.5rem 1rem; background: var(--gold); color: var(--ink); }

/* Header */

/* Above main (z-index 1), so the header and its language menu are never
   covered by the content scrolling beneath them. Below the skip link. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  padding: 0.75rem clamp(1rem, 4vw, 2.5rem);
  background: rgb(13 8 32 / 0.8);
  backdrop-filter: blur(8px);
}

.site-nav ul { display: flex; gap: 0.25rem 1.25rem; margin: 0; padding: 0; list-style: none; }
.site-nav a { display: inline-block; padding: 0.5rem 0; color: var(--text); text-decoration: none; font-weight: 600; font-size: 0.95rem; }
.site-nav a:hover { color: var(--gold); }
@media (max-width: 60rem) {
  /* On phones and tablets the header wraps to several rows, which is too tall
     to keep on screen: it scrolls away with the page instead. */
  /* Relative, not static: z-index only works on positioned elements, and
     the language menu must still open above the page. */
  .site-header { position: relative; }
  /* On small screens the menu wraps to a second row, so every item is
     visible without scrolling sideways. */
  .site-nav { order: 3; width: 100%; }
  .site-nav ul { flex-wrap: wrap; }
}

.brand { font-weight: 800; font-size: 1.25rem; color: var(--text); text-decoration: none; letter-spacing: 0.02em; }

.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }

.controls button, .languages summary {
  font: inherit;
  font-size: 0.9rem;
  min-height: 2.75rem;
  padding: 0.4rem 0.9rem;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--panel-edge);
  border-radius: 999px;
  cursor: pointer;
}

/* On/off state is shown by a mark as well as colour. */
.controls button[aria-pressed="true"] { background: var(--lilac); color: var(--ink); border-color: var(--lilac); }
.controls button[aria-pressed="true"]::before { content: "✓ "; }

.languages { position: relative; }
.languages summary { list-style: none; }
.languages summary::-webkit-details-marker { display: none; }
.languages ul {
  position: absolute;
  right: 0;
  z-index: 1;
  margin: 0.5rem 0 0;
  padding: 0.5rem;
  list-style: none;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 0.75rem;
  min-width: 10rem;
}
.languages li a { display: block; padding: 0.5rem 0.75rem; color: var(--text); }
.languages a[aria-current="page"] { font-weight: 700; color: var(--gold); }

/* Content */

main { padding: 0 clamp(1rem, 4vw, 2.5rem); }

section { padding: 12vh 0; }

.panel {
  max-width: 36rem;
  padding: clamp(1.25rem, 3vw, 2rem);
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  backdrop-filter: blur(6px);
}


.eyebrow { margin: 0; color: var(--gold); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.02em; }

h1 { font-size: clamp(2.25rem, 6vw, 4rem); line-height: 1.08; margin: 0.5rem 0 1rem; letter-spacing: -0.02em; }
h2 { font-size: clamp(1.6rem, 3.5vw, 2.4rem); line-height: 1.15; margin: 0 0 1rem; }
h3 { font-size: 1.3rem; margin: 0 0 0.5rem; }

.lead { font-size: 1.2rem; color: var(--text); }
.note { color: var(--muted); font-size: 0.95rem; margin-bottom: 0; }

.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.button {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.6rem 1.25rem;
  font: inherit;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  background: transparent;
  border: 2px solid var(--lilac);
  border-radius: 999px;
  cursor: pointer;
}
.button:hover { color: var(--ink); background: var(--lilac); }
.button.primary { color: var(--ink); background: var(--pink); border-color: var(--pink); }
.button.primary:hover { background: var(--gold); border-color: var(--gold); }
.button.xr { border-color: var(--teal); }
.button.xr:hover { background: var(--teal); }

pre {
  overflow-x: auto;
  padding: 1rem;
  background: rgb(0 0 0 / 0.35);
  border-radius: 0.5rem;
  font-size: 0.95rem;
}
code { color: var(--gold); }
figure { margin: 1.5rem 0 0; }
figcaption { color: var(--muted); font-size: 0.95rem; margin-top: 0.5rem; }

/* The eight phases. On wide screens they alternate sides, so the world each
   one describes is visible beside it. */
.phases { list-style: none; margin: 0; padding: 0; }
.phase { margin: 0 0 40vh; }
.phase-number { margin: 0; color: var(--gold); font-weight: 700; }
.facts { margin: 0.75rem 0; padding-left: 1.25rem; color: var(--muted); }

@media (min-width: 60rem) {
  .phase:nth-child(even) { margin-left: auto; }
  section[data-station="end"] .panel { margin-left: auto; }
}

.how { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.25rem; }
.how p { margin: 0; color: var(--muted); }

.why { display: grid; gap: 1.25rem; max-width: 44rem; align-items: start; }
.why img { border-radius: var(--radius); width: 8rem; height: auto; }
.why .name { font-weight: 800; font-size: 1.2rem; margin: 0; }
.why .place { color: var(--muted); margin: 0 0 1rem; }
.why blockquote { margin: 0; font-style: italic; }
@media (min-width: 40rem) {
  .why { grid-template-columns: 8rem 1fr; }
}

.site-footer {
  max-width: none;
  margin-top: 10vh;
  border-radius: 0;
  border-width: 1px 0 0;
  padding: 2rem clamp(1rem, 4vw, 2.5rem);
  color: var(--muted);
}
.site-footer summary { cursor: pointer; color: var(--text); font-weight: 700; }

/* ------------------------------------------------------------------------
   The 2D half: a flat, light, image-led page.
   Every rule here is scoped to .flat, so the 3D half is untouched.
   ------------------------------------------------------------------------ */

.flat {
  /* Spacing follows the width, not the height, so a phone held sideways
     is not cramped and a tall monitor is not mostly empty. */
  --gap: clamp(2rem, 5vw, 4.5rem);
  color: var(--paper-text);
  max-width: 72rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 9vw, 7rem) 0;
  scroll-margin-top: 5rem;
}
.flat a:not(.button) { color: var(--deep-purple); text-decoration-thickness: 0.08em; }
/* The night hover colour (pink) is too faint on paper. */
.flat a:not(.button):hover { color: var(--ink); text-decoration-thickness: 0.15em; }
/* The gold focus ring is too faint on paper (about 1.4:1); purple is 9:1. */
.flat :focus-visible { outline-color: var(--deep-purple); }
.flat p { color: var(--paper-muted); }
.flat h1, .flat h2, .flat h3 { color: var(--paper-text); text-wrap: balance; }
.flat p, .flat li { max-width: 65ch; }
.flat .eyebrow { color: var(--deep-purple); }
.flat .lead { color: var(--paper-text); font-size: clamp(1.1rem, 1.6vw, 1.25rem); }
.flat img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgb(27 27 31 / 0.06), 0 12px 32px -12px rgb(91 42 134 / 0.28);
}
.flat .button { color: var(--paper-text); border-color: var(--deep-purple); }
.flat .button:hover { color: #fff; background: var(--deep-purple); }
.flat .button.primary { color: var(--ink); background: var(--pink); border-color: var(--pink); }
/* Gold is too pale to show the hover on paper: go darker instead. */
.flat .button.primary:hover { color: #fff; background: var(--deep-purple); border-color: var(--deep-purple); }

/* Hero: tall enough to feel like a first screen, never a wall of space. */
.hero-2d {
  display: grid;
  gap: var(--gap);
  align-items: center;
  min-height: min(calc(100svh - 5rem), 44rem);
  padding-top: clamp(2rem, 6vw, 4rem);
  padding-bottom: clamp(1rem, 3vw, 2rem);
}
.hero-2d h1 { margin-top: 0.75rem; }

.split { display: grid; gap: var(--gap); align-items: center; }
.split h2, #program h2, #why h2 { position: relative; padding-top: 1rem; }
/* A short purple rule above each heading ties the sections together. */
.split h2::before, #program h2::before, #why h2::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 2.5rem;
  height: 0.25rem;
  border-radius: 1rem;
  background: linear-gradient(90deg, var(--deep-purple), var(--pink));
}
@media (min-width: 56rem) {
  .hero-2d { grid-template-columns: 1.1fr 1fr; }
  .split { grid-template-columns: 1fr 1fr; }
  .split.reverse > img { order: 2; }
}

.cards {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
}
/* One, two, or four across: never three and one left on its own. */
@media (min-width: 36rem) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 68rem) { .cards { grid-template-columns: repeat(4, 1fr); } }
.card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid #e6e1ee;
  border-radius: var(--radius);
  padding: 1rem 1rem 1.25rem;
}
.card img { aspect-ratio: 4 / 3; object-fit: cover; margin-bottom: 1rem; box-shadow: none; transition: opacity 0.2s; }
/* The XR diagram is square: show all of it rather than cropping it. */
.card img[data-lift="2"] { object-fit: contain; background: #fff; }
.card h3 { margin-bottom: 0.25rem; }
.card p { margin: 0; }
.card .credit { margin-top: auto; padding-top: 0.75rem; font-size: 0.85rem; }
@media (prefers-reduced-motion: no-preference) {
  .card { transition: transform 0.2s, box-shadow 0.2s; }
  .card:hover { transform: translateY(-3px); box-shadow: 0 12px 28px -14px rgb(91 42 134 / 0.35); }
}

.why-2d .why { max-width: none; gap: clamp(1.25rem, 4vw, 3rem); }
.why-2d .why img { width: min(12rem, 60%); }
.why-2d .name { color: var(--paper-text); font-size: 1.35rem; }
.why-2d .place { color: var(--paper-muted); }
.why-2d blockquote {
  /* Upright, not italic: Chinese has no true italic, and browsers slant it. */
  font-style: normal;
  padding-left: clamp(1rem, 2.5vw, 1.5rem);
  border-left: 0.25rem solid var(--lilac);
}
.why-2d blockquote p { color: var(--paper-text); font-size: 1.1rem; }
.why-2d blockquote p:first-child { font-size: clamp(1.2rem, 2vw, 1.4rem); font-weight: 600; line-height: 1.45; }
.why-2d blockquote p:last-child { color: var(--deep-purple); font-weight: 700; }
@media (min-width: 40rem) {
  .why-2d .why { grid-template-columns: 12rem 1fr; }
  .why-2d .why img { width: 12rem; }
}

/* Windows High Contrast and other forced-colour modes: keep edges visible. */
@media (forced-colors: active) {
  .card, .flat img { border: 1px solid CanvasText; }
  .split h2::before, #program h2::before, #why h2::before { background: CanvasText; }
}

/* ------------------------------------------------------------------------
   The threshold: a tall section with a panel that stays in view while the
   page folds from day into the 3D night.
   ------------------------------------------------------------------------ */

#threshold { height: 240vh; padding: 0; }
.threshold-inner {
  position: sticky;
  top: 22vh;
  display: flex;
  justify-content: center;
  /* Fades out over the last part of the fold, as the 3D sections arrive. */
  opacity: clamp(0, calc((1 - var(--fold, 0)) * 7), 1);
}
.threshold-inner .panel { text-align: center; max-width: 40rem; }
.threshold-inner .actions { justify-content: center; }

/* ------------------------------------------------------------------------
   The 3D half keeps the night styles above.
   ------------------------------------------------------------------------ */

.deep { scroll-margin-top: 5rem; }

/* ------------------------------------------------------------------------
   The lower half with the 3D scene off (or unavailable). scene.js sets
   data-scene="on" on <html> only while the scene runs; everywhere else the
   panels drop the tall gaps and side-to-side layout that frame the worlds,
   and sit in a compact, centred grid instead.
   ------------------------------------------------------------------------ */

:root:not([data-scene="on"]) .deep {
  max-width: 72rem;
  margin: 0 auto;
  padding: clamp(1.5rem, 4vw, 3rem) 0;
}
:root:not([data-scene="on"]) .deep .panel { max-width: none; margin-left: 0; }
:root:not([data-scene="on"]) .deep .panel p,
:root:not([data-scene="on"]) .deep .facts { max-width: 65ch; }

/* The eight phases as a grid of cards: one, two, or four across. */
:root:not([data-scene="on"]) .phases {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
  margin-top: clamp(1rem, 2vw, 1.5rem);
}
:root:not([data-scene="on"]) .phase {
  display: flex;
  flex-direction: column;
  margin: 0;
}
/* "Open this phase" lines up along the bottom of each row. */
:root:not([data-scene="on"]) .phase > p:last-child { margin: auto 0 0; padding-top: 0.5rem; }
@media (min-width: 40rem) {
  :root:not([data-scene="on"]) .phases { grid-template-columns: repeat(2, 1fr); }
  :root:not([data-scene="on"]) .how { grid-template-columns: repeat(2, 1fr); gap: 1.5rem 2rem; }
}
@media (min-width: 80rem) {
  :root:not([data-scene="on"]) .phases { grid-template-columns: repeat(4, 1fr); }
}

/* Still long enough for the day-to-night fade, but no empty screens. */
:root:not([data-scene="on"]) #threshold { height: 130vh; }
:root:not([data-scene="on"]) .threshold-inner { top: 30vh; }
