/* Toranj Flying Dragon: the website's styles.
   Every page is one night sky, like the ride's. The story and the legal pages are written on the game's scroll
   paper, and the chapters sit in the chapter panel's lotus frame. Colours are taken from the game's art: the
   painting's violet night, the paper, the title's orange and rose (Assets/Title/toranj.svg). */

:root {
  color-scheme: dark;

  --night-0: #07051a;
  --night-1: #0d0a26;
  --night-2: #17123f;
  --violet: #3a3191;
  --violet-soft: #4e46b0;
  --lavender: #b9a8ff;
  --text: #eeeaff;
  --text-dim: #b9b2dc;
  --orange: #ff8a2a;
  --orange-light: #ffb069;
  --rose: #e1517d;
  --gold: #e3a85c;
  --teal: #6fd1c4;

  /* On the scroll paper. */
  --paper: #faebd1;
  --ink: #2b2244;
  --ink-soft: #5c5079;
  --ink-heading: #3b2a6b;
  --ink-link: #6a35c4;

  --serif: ui-serif, "New York", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --persian: "Noto Nastaliq Urdu", "Geeza Pro", "Noto Naskh Arabic", "Segoe UI", serif;

  --gutter: clamp(16px, 4vw, 40px);
  --radius: 22px;
  --ease-out: cubic-bezier(.2, .8, .2, 1);
}

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

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

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

body {
  margin: 0;
  min-height: 100vh;
  overflow-x: hidden;
  background: var(--night-0);
  color: var(--text);
  font: 400 1.0625rem/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
}

img, svg, canvas, video { display: block; max-width: 100%; }

a { color: var(--lavender); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--text); }

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

[lang="fa"] { font-family: var(--persian); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip {
  position: absolute;
  left: 16px; top: -60px;
  z-index: 20;
  padding: 10px 16px;
  border-radius: 10px;
  background: var(--gold);
  color: var(--night-0);
  font-weight: 600;
  text-decoration: none;
}
.skip:focus { top: 12px; }

/* The night behind every page: a fixed glow and the stars (drawn by site.js). */
.sky {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 70% at 50% 115%, rgba(78, 70, 176, .5), transparent 62%),
    radial-gradient(70% 45% at 8% -8%, rgba(58, 49, 145, .4), transparent 65%),
    linear-gradient(var(--night-0), var(--night-1) 55%, var(--night-2));
}
.sky canvas { width: 100%; height: 100%; }

/* ---------- Header and footer ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px var(--gutter);
  background: linear-gradient(rgba(7, 5, 26, .82), rgba(7, 5, 26, .55));
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid rgba(185, 168, 255, .08);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  text-decoration: none;
  font: 600 1.05rem/1 var(--serif);
  letter-spacing: .02em;
}
.brand img { width: 24px; height: 28px; }

.site-nav { display: flex; align-items: center; gap: clamp(12px, 3vw, 28px); }
.site-nav a { color: var(--text-dim); font-size: .95rem; text-decoration: none; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--text); }

.music {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  padding: 0;
  border: 1px solid rgba(185, 168, 255, .25);
  border-radius: 50%;
  background: rgba(255, 255, 255, .05);
  color: var(--text-dim);
  cursor: pointer;
}
.music:hover { color: var(--text); border-color: var(--lavender); }
.music svg { width: 18px; height: 18px; fill: currentColor; }
.music[aria-pressed="true"] {
  color: var(--orange-light);
  border-color: rgba(255, 176, 105, .6);
  box-shadow: 0 0 16px rgba(255, 138, 42, .35);
}

@media (max-width: 420px) {
  .brand span { display: none; }
}

.site-footer {
  padding: 48px var(--gutter) 56px;
  border-top: 1px solid rgba(185, 168, 255, .1);
  color: var(--text-dim);
  font-size: .92rem;
  text-align: center;
}
.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 24px;
  margin-bottom: 16px;
}
.site-footer nav a { color: var(--text); text-decoration: none; }
.site-footer nav a:hover { color: var(--orange-light); }
.site-footer p { margin: 6px 0; }

/* ---------- Sections ---------- */

.section { position: relative; padding: clamp(72px, 12vw, 150px) var(--gutter); }
.wrap { max-width: 1120px; margin-inline: auto; }
.narrow { max-width: 720px; margin-inline: auto; }
.center { text-align: center; }

.eyebrow {
  margin: 0 0 14px;
  color: var(--gold);
  font: 600 .78rem/1.2 var(--sans);
  letter-spacing: .18em;
  text-transform: uppercase;
}

h2, .h2 { margin: 0 0 18px; font: 600 clamp(1.8rem, 4.2vw, 2.9rem)/1.12 var(--serif); }
h1, h2, h3 { text-wrap: balance; }
h3 { margin: 0 0 8px; font: 600 1.2rem/1.3 var(--serif); }
p { margin: 0 0 1em; }
.lead { max-width: 60ch; color: var(--text-dim); font-size: clamp(1.08rem, 2vw, 1.22rem); }
.center .lead { margin-inline: auto; }

.button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 22px;
  border: 1px solid rgba(227, 168, 92, .5);
  border-radius: 999px;
  background: rgba(255, 255, 255, .06);
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
}
.button:hover { color: var(--text); border-color: var(--gold); background: rgba(227, 168, 92, .12); }

/* "Coming soon": a plain badge. Apple's own App Store badge goes here once the app is live. */
.soon {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  border: 1px solid rgba(227, 168, 92, .45);
  border-radius: 999px;
  background: rgba(255, 255, 255, .06);
  font-weight: 600;
}
.soon::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--orange);
  box-shadow: 0 0 12px var(--orange);
}

/* Sections rise into view (site.js adds .is-visible); without JavaScript they are simply there. */
.js .reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .9s var(--ease-out), transform .9s var(--ease-out);
}
.js .reveal.is-visible { opacity: 1; transform: none; }

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

.hero {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: 72px var(--gutter) clamp(150px, 22vw, 230px);
  overflow: hidden;
  text-align: center;
}

/* The name, written by a pen in the pomegranate's skin as on the game's launch window (home.js). The design
   team's lettering, in its own colours, shows instead without JavaScript. */
.title {
  position: relative;
  width: min(52vw, 300px);
  aspect-ratio: 958 / 1118;
  margin: 0 auto;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
}
.title img, .title canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.title img {
  filter: drop-shadow(0 0 28px rgba(255, 109, 0, .28));
  /* Shows by itself if the pen never starts (no JavaScript): home.js takes over well before. */
  animation: fade-in .8s ease 1.2s both;
}
/* The glow is the skin's pink rim. */
.title canvas { opacity: 0; filter: drop-shadow(0 0 28px rgba(230, 164, 228, .3)); }
.title.is-writing img, .title.is-written img { animation: none; opacity: 0; }
.title.is-writing canvas, .title.is-written canvas { opacity: 1; }
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.hero h1 {
  margin: 30px 0 12px;
  font: 600 clamp(2rem, 5.4vw, 3.6rem)/1.08 var(--serif);
  letter-spacing: .01em;
}
.tagline {
  max-width: 40ch;
  margin: 0 auto 30px;
  color: var(--text-dim);
  font-size: clamp(1.05rem, 2.2vw, 1.25rem);
}

.moon {
  position: absolute;
  top: clamp(90px, 14vh, 150px);
  right: clamp(24px, 12vw, 180px);
  z-index: -1;
  width: clamp(44px, 6vw, 70px);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: inset clamp(9px, 1.3vw, 15px) clamp(-11px, -1vw, -6px) 0 0 #f6d38c;
  filter: drop-shadow(0 0 22px rgba(246, 211, 140, .45));
  transform: rotate(-12deg);
}
@media (max-width: 640px) {
  .moon { top: 74px; right: 18px; width: 34px; }
}

/* The ride's 3D clouds, drifting along the bottom of the hero over the page's own sky. Their band repeats with no
   seam (tools/make_clouds.mjs): moving it one image-width (`--band`, its width over its height) loops. The near
   clouds fade out at their bottoms, as in the game; the band fades too, into the next section. */
.clouds {
  --cloud-height: clamp(110px, 19vw, 230px);
  --band: calc(2400 / 345);
  position: absolute;
  left: 0; right: 0;
  bottom: 0;
  z-index: -1;
  height: var(--cloud-height);
  background: url("/assets/img/clouds.webp") repeat-x 0 50% / auto 100%;
  -webkit-mask-image: linear-gradient(#000 75%, transparent);
  mask-image: linear-gradient(#000 75%, transparent);
  animation: drift 110s linear infinite;
}
/* Behind them, a little higher and slower, farther away: the colourful clouds once painted on the ride's sky, a band
   of its panorama with its own night around them, faded at its edges. */
.clouds--colour {
  --band: calc(2048 / 330);
  bottom: calc(var(--cloud-height) * .2);
  background-image: url("/assets/img/clouds-colour.webp");
  -webkit-mask-image: linear-gradient(transparent, #000 35%, #000 75%, transparent);
  mask-image: linear-gradient(transparent, #000 35%, #000 75%, transparent);
  animation-duration: 170s;
}
@keyframes drift {
  to { background-position-x: calc(var(--cloud-height) * var(--band) * -1); }
}

.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--text-dim);
  font-size: .78rem;
  letter-spacing: .16em;
  text-decoration: none;
  text-transform: uppercase;
  text-shadow: 0 1px 8px var(--night-0);
  transform: translateX(-50%);
}
.scroll-cue::after {
  content: "";
  width: 1px; height: 34px;
  background: linear-gradient(var(--lavender), transparent);
  animation: cue 2.4s ease-in-out infinite;
  transform-origin: top;
}
@keyframes cue {
  0%, 100% { transform: scaleY(.4); opacity: .4; }
  50% { transform: scaleY(1); opacity: 1; }
}

/* ---------- The scroll paper ---------- */

/* The game's scroll paper with its lotus border, as a border image: the borders keep their shape and the sides'
   lotuses repeat however long the text is. The slices are the paper's own pixels (assets/img/paper.webp,
   1024×1536): its top band, with the cartouche for a title, is 200 px tall, the sides 96, the bottom 100. */
.paper {
  --scale: .34;
  position: relative;
  border-style: solid;
  border-width: calc(200px * var(--scale)) calc(96px * var(--scale)) calc(100px * var(--scale));
  border-image-source: url("/assets/img/paper.webp");
  border-image-slice: 200 96 100 96;
  border-image-repeat: stretch round;
  padding: 10px clamp(6px, 2vw, 26px) 14px;
  /* The paper's own middle would repeat with seams on long pages: a parchment of the same colour instead. */
  background: radial-gradient(120% 90% at 50% 35%, #fcf3e2, var(--paper) 55%, #f3e0bf) padding-box;
  color: var(--ink);
  filter: drop-shadow(0 30px 60px rgba(0, 0, 0, .45));
}
@media (min-width: 640px) {
  .paper { --scale: .5; }
}

/* A title in the cartouche at the top of the paper: the cartouche's middle is 103 px above the band's lower edge. */
.cartouche {
  position: absolute;
  left: 50%;
  top: calc(-103px * var(--scale));
  margin: 0;
  color: var(--ink-heading);
  font: 400 calc(46px * var(--scale))/1 var(--persian);
  white-space: nowrap;
  transform: translate(-50%, -50%);
}

/* ---------- The tale ---------- */

.tale {
  display: grid;
  gap: clamp(36px, 6vw, 72px);
  align-items: center;
}
@media (min-width: 920px) {
  .tale { grid-template-columns: minmax(0, 520px) minmax(0, 1fr); }
}

.tale__text { font: 400 1.04rem/1.7 var(--serif); }
.tale__text p { margin-bottom: .85em; }
.tale__text .proverb {
  margin: 1.1em 0 0;
  color: #b0254f;
  font-size: 1.12rem;
  font-style: italic;
  text-align: center;
}

/* The scroll unrolls downwards when it comes into view (the negative insets leave room for its shadow). */
.js .unroll {
  clip-path: inset(-80px -80px 100% -80px);
  transition: clip-path 1.8s var(--ease-out);
}
.js .unroll.is-visible { clip-path: inset(-80px); }

.painting {
  margin: 0;
  justify-self: center;
  width: min(100%, 460px);
}
.painting img {
  width: 100%;
  height: auto;
  border-radius: 26px;
  box-shadow: 0 0 0 1px rgba(227, 168, 92, .35), 0 40px 90px rgba(0, 0, 0, .55), 0 0 120px rgba(78, 70, 176, .45);
  transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: transform .4s var(--ease-out);
}
.painting figcaption, .caption {
  margin-top: 16px;
  color: var(--text-dim);
  font-size: .92rem;
  text-align: center;
}

/* ---------- Chapter banners (the chapter panel's frame) ---------- */

/* The frame's corners are 96 px of its 2× image; its middle is see-through, so a dark glass shows behind it. */
.chapter {
  max-width: 640px;
  margin: 0 auto clamp(40px, 7vw, 72px);
  padding: 10px 18px;
  border-style: solid;
  border-width: 34px;
  border-image: url("/assets/img/frame.webp") 96 fill / 34px stretch;
  border-radius: 30px;
  background: rgba(23, 18, 63, .72);
  text-align: center;
}
.chapter__number {
  margin: 0 0 4px;
  color: var(--orange-light);
  font: 600 clamp(1.5rem, 3.6vw, 2.1rem)/1.15 var(--serif);
}
.chapter__line { margin: 0; color: var(--text); font: italic 400 clamp(1rem, 2.2vw, 1.15rem)/1.4 var(--serif); }
.chapter__line [lang="fa"] { font-style: normal; }

/* ---------- Chapter I: the island and the orbit ---------- */

.split {
  display: grid;
  gap: clamp(36px, 6vw, 72px);
  align-items: center;
}
@media (min-width: 920px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--flip > :first-child { order: 2; }
}

.steps { margin: 22px 0 0; padding: 0; list-style: none; }
.steps li {
  position: relative;
  margin: 0 0 12px;
  padding-left: 30px;
  color: var(--text-dim);
}
.steps li::before {
  content: "";
  position: absolute;
  left: 4px; top: .55em;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff, var(--dot) 55%);
  box-shadow: 0 0 10px var(--dot);
}
/* The fruit's colours: apple, pomegranate, banana and orange, pineapple. */
.steps li:nth-child(1) { --dot: #ff5b4f; }
.steps li:nth-child(2) { --dot: #d9366f; }
.steps li:nth-child(3) { --dot: #ffb347; }
.steps li:nth-child(4) { --dot: #f5c542; }
.steps strong { color: var(--text); font-weight: 600; }

.split figure { margin: 0; }

/* The island in a round window, the ingredients circling it (home.js moves them; they sit still without it). */
.orbit {
  position: relative;
  width: min(84vw, 440px);
  aspect-ratio: 1;
  margin-inline: auto;
}
.orbit__island {
  position: absolute;
  inset: 13%;
  z-index: 1;
  overflow: hidden;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(227, 168, 92, .45), 0 0 90px rgba(111, 209, 196, .22), 0 30px 70px rgba(0, 0, 0, .5);
}
.orbit__island img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transform: scale(1.18);
}
.orbit__gem {
  position: absolute;
  left: 50%; top: 50%;
  z-index: 2;
  width: 26px; height: 26px;
  margin: -13px 0 0 -13px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff 0 12%, var(--gem) 45%, transparent 72%);
  box-shadow: 0 0 18px var(--gem), 0 0 42px var(--gem);
}
.gem--rose { --gem: #ff5c8a; }
.gem--gold { --gem: #ffc24b; }
.gem--teal { --gem: #5fe0d0; }
/* The orbit's path, a faint ring around the island. */
.orbit::before {
  content: "";
  position: absolute;
  left: 5%; right: 5%;
  top: 39%; bottom: 23%;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 50%;
}

/* ---------- The knot (scrolled through: the dragon untangles) ---------- */

.knot { position: relative; height: 300vh; }
.knot__stage {
  position: sticky;
  top: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 18px;
  height: 100vh;
  height: 100svh;
  padding: 72px var(--gutter) 28px;
  overflow: hidden;
}
@media (min-width: 920px) {
  .knot__stage {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    max-width: 1200px;
    margin-inline: auto;
  }
}
.knot__drawing { width: min(80vw, 54svh, 560px); aspect-ratio: 1; }
.knot__drawing svg { width: 100%; height: 100%; overflow: visible; }

.knot__captions { position: relative; width: min(100%, 460px); min-height: 220px; }
.knot__caption {
  position: absolute;
  inset: 0 0 auto;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .6s ease, transform .6s var(--ease-out);
}
.knot__caption.is-active { opacity: 1; transform: none; }
.knot__caption p { color: var(--text-dim); }

.progress {
  display: flex;
  gap: 6px;
  margin-top: 6px;
}
.progress span {
  width: 26px; height: 3px;
  border-radius: 2px;
  background: rgba(185, 168, 255, .2);
  transition: background .4s;
}
.progress span.is-on { background: var(--orange-light); }

/* ---------- Chapter II: the ride and the medallion ---------- */

.ride { position: relative; height: 280vh; }
.ride__stage {
  position: sticky;
  top: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 22px;
  height: 100vh;
  height: 100svh;
  padding: 72px var(--gutter) 24px;
  overflow: hidden;
  text-align: center;
}
.ride__stage .clouds { --cloud-height: clamp(80px, 12vw, 160px); opacity: .75; animation-duration: 90s; }
.medallion { width: min(78vw, 440px); width: min(78vw, 44svh, 440px); aspect-ratio: 1; }
.medallion svg { width: 100%; height: 100%; overflow: visible; }
/* Drawn in a disc of radius 100 (home.js), turning slowly like a constellation. */
.medallion__turn { transform-box: view-box; transform-origin: center; animation: turn 240s linear infinite; }
@keyframes turn { to { transform: rotate(360deg); } }
.medallion .strand { fill: none; stroke: rgba(227, 168, 92, .6); stroke-width: 1.1; stroke-linecap: round; }
.medallion .ray { fill: none; stroke: rgba(227, 168, 92, .38); stroke-width: .8; }
.medallion .orb, .medallion .dot { fill: rgba(246, 211, 140, .75); }
.medallion .tile { fill: rgba(185, 168, 255, .06); }
.medallion .petal { fill: rgba(185, 168, 255, .1); transition: fill .6s ease; }
.medallion .petal.is-lit { fill: var(--fruit); filter: url(#petal-glow); }
.medallion .star { fill: rgba(185, 168, 255, .12); transition: fill 1s ease; }
.medallion.is-complete .star { fill: #fff1cf; filter: url(#petal-glow); }

.ride__text { max-width: 600px; }
.ride__text p { color: var(--text-dim); text-shadow: 0 1px 12px var(--night-0); }
.fed { color: var(--orange-light); font: 600 .9rem/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; }

/* ---------- How you play ---------- */

.cards {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  margin-top: 36px;
}
.card {
  padding: 26px 24px;
  border: 1px solid rgba(185, 168, 255, .14);
  border-radius: var(--radius);
  background: linear-gradient(160deg, rgba(78, 70, 176, .3), rgba(13, 10, 38, .72));
  /* Frosted glass: the dragon flying behind shows as a soft glow, the words stay sharp. */
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  backdrop-filter: blur(14px) saturate(130%);
}
.card__number { margin: 0 0 14px; color: var(--gold); font: 400 1.9rem/1.2 var(--persian); }
.card p { margin: 0; color: var(--text-dim); }
.note { margin-top: 24px; color: var(--text-dim); font-size: .95rem; }

/* ---------- The island in 3D (Chapter I) ---------- */

/* Where WebGL works (home.js sets .has-island), the game's island takes the round painting's place: unframed,
   floating in the night like the game's. Its canvas covers the whole section, behind the words; the empty box only
   says where the island stands (and where the dragon circles). */
.island3d__view { display: none; }
.island3d__canvas { display: none; }
.has-island .island3d .orbit { display: none; }
.has-island .island3d__view {
  display: block;
  width: min(100%, 520px);
  margin-inline: auto;
  aspect-ratio: 1;
  pointer-events: none;
}
/* The island is drawn a little taller than its box: the caption clears its roots. */
.has-island .island3d figcaption { margin-top: clamp(36px, 7vw, 60px); }
.has-island .island3d__canvas {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  cursor: grab;
  /* Sideways drags turn it; vertical swipes still scroll the page on phones. */
  touch-action: pan-y;
  opacity: 0;
  transition: opacity 1.2s ease;
}
.has-island .island3d__canvas.is-shown { opacity: 1; }
.has-island .island3d__canvas.is-pointing { cursor: pointer; }
.has-island .island3d__canvas:active { cursor: grabbing; }
.has-island .island3d__canvas:focus-visible { outline: 2px solid var(--gold); outline-offset: -6px; }
/* Beside the words, the rocks that swing out over them fade away there. */
@media (min-width: 920px) {
  .has-island .island3d__canvas {
    -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, .15) 30%, #000 52%);
    mask-image: linear-gradient(to right, rgba(0, 0, 0, .15) 30%, #000 52%);
  }
}
/* The words over the canvas; everywhere else a press reaches the island. */
.has-island .island3d .wrap { position: relative; z-index: 1; pointer-events: none; }
.has-island .island3d .chapter,
.has-island .island3d .split > :first-child,
.has-island .island3d figcaption { pointer-events: auto; }
/* What just happened on the island; two lines kept free so the page doesn't jump as it changes. */
.island3d__status {
  min-height: 3.2em;
  margin-top: 18px;
  color: var(--gold);
  font: italic 400 1.05rem/1.55 var(--serif);
}
/* Shown only once the island could start. */
.island-yes { display: none; }
.has-island .island-yes { display: block; }
.has-island span.island-yes { display: inline; }
.island3d__try { color: var(--gold); }

/* Until the visitor picks a fruit, a label floats over the one glowing on the tree (island.js moves it there), its
   tail pointing down at the fruit's stem. */
.island3d__hint { display: none; }
.has-island .island3d__hint {
  display: flex;
  align-items: center;
  gap: 8px;
  position: absolute;
  top: 0; left: 0;
  margin: 0;
  padding: 7px 14px;
  border: 1px solid rgba(227, 168, 92, .55);
  border-radius: 999px;
  background: rgba(13, 10, 38, .72);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--text);
  font-size: .92rem;
  font-weight: 600;
  white-space: nowrap;
  transform: translate(-50%, calc(-100% - 22px));
  opacity: 0;
  transition: opacity .5s ease;
  pointer-events: none;
}
.has-island .island3d__hint.is-shown { opacity: 1; }
/* A gold dot that pulses, like the one on the "Coming soon" badge. */
.island3d__hint::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 10px var(--gold);
  animation: hint-pulse 1.6s ease-in-out infinite;
}
/* Its tail: under its middle, or as far towards the fruit as the label had to move to stay on the screen. */
.island3d__hint::after {
  content: "";
  position: absolute;
  top: 100%; left: calc(50% + var(--tail, 0px));
  width: 1px; height: 18px;
  background: linear-gradient(rgba(227, 168, 92, .8), transparent);
}
@keyframes hint-pulse {
  50% { transform: scale(1.6); opacity: .55; }
}

/* ---------- Team and the last call ---------- */

.team {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  margin-top: 36px;
}
.member {
  padding: 24px 16px;
  border: 1px solid rgba(185, 168, 255, .12);
  border-radius: 20px;
  background: rgba(255, 255, 255, .04);
  text-align: center;
}
.member__badge {
  display: grid;
  place-items: center;
  width: 62px; height: 62px;
  margin: 0 auto 12px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, var(--orange-light), var(--rose) 75%);
  color: #2b1630;
  font: 600 1.15rem/1 var(--serif);
}
.member h3 { font-size: 1.05rem; }
.member p { margin: 0; color: var(--text-dim); font-size: .92rem; }

.last-call .soon { margin: 10px 0 22px; }

/* ---------- The ride's scenery around the page: lanterns, clouds, mountains, lace (tools/make_*.mjs) ---------- */

/* Each section holding scenery keeps it behind its words and over the page's sky, inside its own edges. */
.night-scene, #play, #team, .last-call { isolation: isolate; overflow: hidden; }

/* Pictures drawn by CSS below the hero load as their section nears the screen (home.js adds .is-near). */
.lazy-bg:not(.is-near) { background-image: none !important; }

/* A Persian lantern of the ride's sky, floating: it bobs and sways, its gold glowing around it. */
.lantern {
  position: absolute;
  z-index: -1;
  width: var(--lantern, clamp(40px, 5vw, 72px));
  height: auto;
  filter: drop-shadow(0 0 22px rgba(246, 211, 140, .45));
  animation: bob 7s ease-in-out infinite;
  pointer-events: none;
}
@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(-2.5deg); }
  50% { transform: translateY(-16px) rotate(2.5deg); }
}

/* One of the ride's lilac clouds on its own, drifting to and fro. */
.drift-cloud {
  position: absolute;
  z-index: -1;
  height: auto;
  opacity: .9;
  animation: sway 26s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes sway {
  to { transform: translateX(var(--sway, 70px)); }
}

.lantern--hero-left { --lantern: clamp(40px, 5.4vw, 80px); top: 30%; left: clamp(14px, 11vw, 190px); }
.lantern--hero-right {
  --lantern: clamp(30px, 4vw, 58px);
  top: 50%;
  right: clamp(14px, 14vw, 230px);
  animation-duration: 8.5s;
  animation-delay: -3s;
}

/* Clear of the knot, which the dragon (or its drawing) ties in the middle of the stage. */
.knot__cloud--low { width: clamp(150px, 20vw, 300px); left: 3%; bottom: 4%; --sway: 60px; }
.knot__cloud--high {
  width: clamp(110px, 13vw, 200px);
  right: 5%;
  bottom: 18%;
  opacity: .75;
  --sway: -50px;
  animation-duration: 32s;
}

/* Chapter II's world: the lace of the ride's sky hanging from the top, the ride's clouds below, drifting past as
   the dragon flies, and lanterns between. */
.night-scene { padding-bottom: calc(clamp(110px, 19vw, 230px) + clamp(40px, 6vw, 80px)); }
.lace-border {
  position: absolute;
  z-index: -1;
  top: 0; left: 0; right: 0;
  height: clamp(100px, 15vw, 180px);
  background: url("/assets/img/lace-border.webp") repeat-x 50% 0 / auto 100%;
  opacity: .9;
}
.mountains {
  --cloud-height: var(--peaks);
  --band: calc(2000 / 333);
  position: absolute;
  z-index: -1;
  left: 0; right: 0; bottom: 0;
  height: var(--peaks);
  background: url("/assets/img/mountains.webp") repeat-x 0 100% / auto 100%;
  animation: drift 240s linear infinite;
}
.night-scene__lantern--a { --lantern: clamp(36px, 4.6vw, 70px); top: 36%; left: clamp(12px, 9vw, 170px); }
.night-scene__lantern--b {
  --lantern: clamp(28px, 3.4vw, 52px);
  top: 24%;
  right: clamp(14px, 12vw, 220px);
  animation-delay: -2s;
}
.night-scene__lantern--c {
  --lantern: clamp(24px, 2.8vw, 44px);
  top: 54%;
  right: clamp(24px, 6vw, 110px);
  animation-duration: 9s;
  animation-delay: -4.5s;
}

/* The lace's arch stands over the medallion as it does over the shamseh in the game: its springing (the picture's
   bottom edge) on the medallion's heart, its sides fading into the sky. */
.medallion { position: relative; isolation: isolate; }
.medallion__arch {
  position: absolute;
  z-index: -1;
  left: 50%;
  bottom: 50%;
  width: 230%;
  max-width: none;
  height: auto;
  transform: translateX(-50%);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
  pointer-events: none;
}

/* A row of the lace's big stars, between the ride and how to play. */
.lace-stars {
  position: absolute;
  z-index: -1;
  top: clamp(8px, 2.4vw, 36px);
  left: 0; right: 0;
  height: clamp(36px, 5vw, 66px);
  background: url("/assets/img/lace-stars.webp") repeat-x 50% 0 / auto 100%;
  opacity: .9;
}
.play__lantern--left { --lantern: clamp(30px, 3.8vw, 56px); bottom: 3%; left: clamp(12px, 8vw, 150px); }
.play__lantern--right {
  --lantern: clamp(36px, 4.6vw, 68px);
  bottom: 9%;
  right: clamp(12px, 10vw, 190px);
  animation-delay: -3.5s;
}

/* The whole lace cap, seen from below, turning slowly behind the team. */
.lace-cap {
  position: absolute;
  z-index: -1;
  top: 50%; left: 50%;
  width: min(118vw, 760px);
  max-width: none;
  height: auto;
  translate: -50% -50%;
  opacity: .38;
  animation: turn 480s linear infinite;
  pointer-events: none;
}
@keyframes turn {
  to { rotate: 360deg; }
}

/* The last words over the mountains far below, drifting past, lanterns rising either side. */
.last-call {
  --peaks: clamp(140px, 22vw, 300px);
  padding-bottom: calc(clamp(72px, 12vw, 150px) + var(--peaks) * .6);
}
.last-call__lantern--left { --lantern: clamp(32px, 4.2vw, 62px); top: 16%; left: clamp(12px, 12vw, 220px); }
.last-call__lantern--right {
  --lantern: clamp(38px, 5vw, 76px);
  top: 32%;
  right: clamp(12px, 11vw, 200px);
  animation-delay: -2.5s;
}

/* On a phone the words take the width: one lantern a section, clear of them, and one cloud by the knot. */
@media (max-width: 599px) {
  .lantern--hero-right, .night-scene__lantern--b, .night-scene__lantern--c, .play__lantern--left,
  .last-call__lantern--left, .knot__cloud--high { display: none; }
  .last-call__lantern--right { top: 4%; }
}

/* ---------- Legal pages ---------- */

.doc-page { padding: clamp(44px, 8vw, 90px) var(--gutter) clamp(60px, 10vw, 110px); }
.doc-head { max-width: 760px; margin: 0 auto clamp(28px, 5vw, 44px); text-align: center; }
.doc-head h1 { margin: 0 0 10px; font: 600 clamp(2.1rem, 5.6vw, 3.2rem)/1.08 var(--serif); }
.doc-head p { margin: 0; color: var(--text-dim); }

.doc { max-width: 780px; margin-inline: auto; font-size: 1.02rem; }
.doc h2 { margin: 1.7em 0 .45em; color: var(--ink-heading); font: 600 1.32rem/1.25 var(--serif); }
.doc h2:first-of-type { margin-top: .6em; }
.doc h3 { margin: 1.2em 0 .3em; color: var(--ink-heading); font-size: 1.08rem; }
.doc p, .doc li { color: var(--ink); }
.doc ul { padding-left: 1.2em; }
.doc li { margin-bottom: .4em; }
.doc a { color: var(--ink-link); }
.doc a:hover { color: var(--ink); }
.doc .meta { color: var(--ink-soft); font-size: .92rem; text-align: center; }

.summary {
  margin: 14px 0 6px;
  padding: 16px 18px;
  border: 1px solid rgba(106, 53, 196, .25);
  border-radius: 14px;
  background: rgba(106, 53, 196, .07);
}
.summary p:last-child { margin-bottom: 0; }

.table-wrap { overflow-x: auto; margin: 10px 0 18px; }
.doc table { width: 100%; min-width: 520px; border-collapse: collapse; font-size: .94rem; }
.doc th, .doc td {
  padding: 10px 8px;
  border-bottom: 1px solid rgba(43, 34, 68, .16);
  color: var(--ink);
  text-align: left;
  vertical-align: top;
}
.doc th { color: var(--ink-heading); font-weight: 600; }

.faq details {
  margin: 0 0 10px;
  padding: 12px 16px;
  border: 1px solid rgba(43, 34, 68, .14);
  border-radius: 12px;
  background: rgba(255, 255, 255, .35);
}
.faq summary { color: var(--ink-heading); font-weight: 600; cursor: pointer; }
.faq details p { margin: .7em 0 .2em; }

/* What must be filled in before the site is published: grep for data-todo (see README). */
mark.todo {
  padding: 0 4px;
  border: 1px dashed #d6336c;
  border-radius: 6px;
  background: #ffe1ee;
  color: #8a1450;
}

/* ---------- The game's dragon and scroll in 3D (home.js adds .has-3d where WebGL works) ---------- */

/* The dragon flies over the stars and behind the page. */
.sky .dragon { position: absolute; inset: 0; }

.tale3d { display: none; }
.has-3d .tale3d { display: block; position: relative; height: 420vh; }
.tale3d__stage {
  position: sticky;
  top: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  justify-items: center;
  gap: 10px;
  height: 100vh;
  height: 100svh;
  padding: 64px var(--gutter) 28px;
}
@media (min-width: 920px) {
  .tale3d__stage {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-template-rows: none;
    align-items: center;
    max-width: 1200px;
    margin-inline: auto;
  }
}
.tale3d__scroll { width: 100%; height: 100%; min-height: 0; align-self: stretch; }
.tale3d__words { width: min(100%, 460px); min-height: 8em; }
.tale3d__line {
  margin: 0;
  color: var(--text);
  font: italic 400 clamp(1.15rem, 2.4vw, 1.6rem)/1.45 var(--serif);
  text-shadow: 0 1px 14px var(--night-0);
  text-wrap: balance;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .35s ease, transform .35s ease;
}
.tale3d__line.is-shown { opacity: 1; transform: none; }

/* With the 3D scroll the written story stays, for screen readers only. */
.has-3d .tale {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
/* The 3D dragon ties the knot itself: the drawing leaves it the room. */
.has-3d .knot__drawing svg { visibility: hidden; }

/* ---------- 404 ---------- */

.lost { display: grid; place-items: center; min-height: 70vh; padding: 80px var(--gutter); text-align: center; }
.lost h1 { margin: 0 0 12px; font: 600 clamp(2rem, 6vw, 3.4rem)/1.1 var(--serif); }

/* ---------- Reduce Motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .js .unroll { clip-path: none; }
  .title img { animation: none; }
  .painting img { transform: none; }
  /* No scrubbing through tall sections: each shows its finished picture. */
  .knot, .ride { height: auto; }
  .knot__stage, .ride__stage { position: relative; height: auto; min-height: 0; padding-block: 56px; }
  .ride__stage { padding-bottom: 190px; }
  .knot__captions { min-height: 0; }
  .knot__caption { position: static; opacity: 1; transform: none; margin-bottom: 18px; }
}
