:root {
  --void: #050407;
  --night: #0d0a10;
  --char: #17141b;
  --stone: #2c2832;
  --stone-lit: #4a4552;
  --steel: #6d6878;
  --bone: #d8cdb4;
  --bone-dim: rgba(216, 205, 180, 0.62);
  --banner: #1f6b43;
  --banner-deep: #0c2a1b;
  --spirit: #3ddc84;
  --spirit-hot: #c8ffd9;
  --snow: #e4ebee;
  --snow-shade: #a9b6c0;
  --ink: #000;
  --blackletter: "UnifrakturCook", "Old English Text MT", "Times New Roman", serif;
  --caps: "Cinzel", "Trajan Pro", Georgia, serif;
  --ui: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--void);
  color: var(--bone);
  font-family: var(--ui);
  overflow-x: hidden;
}

/* ---------- Nav ---------- */

.site-header {
  position: fixed;
  top: 14px;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  justify-content: center;
  padding: 0 16px;
  pointer-events: none;
}

.nav {
  display: flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 5px;
  border: 1px solid rgba(216, 205, 180, 0.22);
  border-radius: 4px;
  background: rgba(8, 7, 10, 0.86);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 0 0 1px #000, 0 14px 40px -12px rgba(0, 0, 0, 0.9);
  pointer-events: auto;
}

.nav-brand {
  display: grid;
  flex: none;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--bone-dim);
  color: var(--bone);
  background: var(--banner-deep);
  font-family: var(--blackletter);
  font-size: 1.15rem;
  text-decoration: none;
  clip-path: polygon(0 0, 100% 0, 100% 62%, 50% 100%, 0 62%);
  transition: background 200ms ease;
}

.nav-brand:hover {
  background: var(--banner);
}

.nav-links {
  position: relative;
  display: flex;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.nav-links a {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  color: var(--bone-dim);
  font-family: var(--caps);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  transition: color 200ms ease;
}

.nav-links a:focus-visible {
  outline: 1px solid var(--bone);
  outline-offset: -3px;
}

.nav-indicator {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0;
  border-bottom: 2px solid var(--spirit);
  background: linear-gradient(180deg, rgba(31, 107, 67, 0.15), rgba(31, 107, 67, 0.55));
  opacity: 0;
  transition:
    transform 280ms cubic-bezier(0.2, 0.8, 0.2, 1),
    width 280ms cubic-bezier(0.2, 0.8, 0.2, 1),
    opacity 160ms ease;
}

.nav.ready .nav-indicator {
  opacity: 1;
}

.nav.ready .nav-links a.lit,
.nav:not(.ready) .nav-links a[aria-current="page"] {
  color: var(--bone);
}

.nav:not(.ready) .nav-links a[aria-current="page"] {
  background: rgba(31, 107, 67, 0.55);
}

.live-dot {
  position: relative;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--spirit);
  box-shadow: 0 0 8px var(--spirit);
}

.live-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--spirit);
  animation: ping 1.8s cubic-bezier(0, 0, 0.2, 1) infinite;
}

@keyframes ping {
  75%,
  100% {
    transform: scale(2.6);
    opacity: 0;
  }
}

/* ---------- The approach (parallax) ---------- */

/* index.js writes --p and the derived values below as you scroll through this track. */
.approach {
  position: relative;
  height: 560vh;
}

.stage {
  --p: 0;
  --castle: 0.62;
  --bridge: -1;
  --gate: 0;
  --title: 1;
  --out: 1;
  --out-blur: 0px;
  --hall: 0;
  --hall-scale: 0.55;
  --hall-blur: 16px;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: var(--void);
}

/* Everything outside the walls. It blurs and fades as the camera passes through the gate. */
.outside {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: linear-gradient(180deg, #020306 0%, #04090b 34%, #081614 58%, #10252a 80%, #1b3036 100%);
  opacity: var(--out);
  filter: blur(var(--out-blur));
}

/* The Great Hall starts as a far, blurred room inside the gate and comes forward into focus. */
.hall {
  position: absolute;
  inset: 0;
  opacity: var(--hall);
  filter: blur(var(--hall-blur));
  transform: scale(var(--hall-scale));
  transform-origin: 50% 64%;
}

.hall.live {
  filter: none;
  transform: none;
}

.hall-anchor {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 100vh;
  pointer-events: none;
}

.layer {
  position: absolute;
  will-change: transform;
}

.sky {
  inset: 0;
  transform: translateY(calc(var(--p) * -5vh));
}

.stars {
  position: absolute;
  inset: 0 0 45%;
}

.star {
  position: absolute;
  width: 2px;
  height: 2px;
  background: var(--bone);
  opacity: 0.4;
  animation: twinkle var(--t, 3s) ease-in-out var(--d, 0s) infinite alternate;
}

@keyframes twinkle {
  from {
    opacity: 0.1;
  }
  to {
    opacity: 0.6;
  }
}

.aurora {
  position: absolute;
  inset: 0 -20% 40%;
  mix-blend-mode: screen;
  filter: blur(18px);
}

.aurora span {
  position: absolute;
  left: 0;
  right: 0;
  height: 34%;
  border-radius: 50%;
  background: linear-gradient(90deg, transparent, rgba(61, 220, 132, 0.5) 22%, rgba(80, 255, 200, 0.3) 45%, rgba(61, 220, 132, 0.55) 70%, transparent);
  transform-origin: 50% 50%;
  animation: aurora 16s ease-in-out infinite alternate;
}

.aurora span:nth-child(1) {
  top: 8%;
  transform: rotate(-7deg) skewX(-20deg);
}

.aurora span:nth-child(2) {
  top: 24%;
  height: 22%;
  opacity: 0.6;
  background: linear-gradient(90deg, transparent, rgba(40, 200, 170, 0.45) 30%, rgba(130, 255, 170, 0.35) 60%, transparent);
  animation-duration: 22s;
  animation-direction: alternate-reverse;
}

.aurora span:nth-child(3) {
  top: 38%;
  height: 16%;
  opacity: 0.35;
  animation-duration: 28s;
}

@keyframes aurora {
  0% {
    transform: translateX(-6%) rotate(-7deg) skewX(-20deg) scaleY(0.8);
  }
  50% {
    transform: translateX(3%) rotate(-3deg) skewX(10deg) scaleY(1.2);
  }
  100% {
    transform: translateX(8%) rotate(-9deg) skewX(-8deg) scaleY(0.9);
  }
}

.star.green {
  width: 3px;
  height: 3px;
  background: var(--spirit);
  box-shadow: 0 0 6px var(--spirit);
}

.moon {
  position: absolute;
  top: 9%;
  right: 14%;
  width: clamp(80px, 10vw, 130px);
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 38%, rgba(60, 80, 70, 0.35) 0 9%, transparent 10%),
    radial-gradient(circle at 60% 64%, rgba(60, 80, 70, 0.3) 0 14%, transparent 15%),
    radial-gradient(circle at 72% 30%, rgba(60, 80, 70, 0.25) 0 6%, transparent 7%),
    radial-gradient(circle at 40% 40%, #f2f7ee, #c3d2c4 60%, #8a9d8e);
  box-shadow: 0 0 60px 14px rgba(160, 255, 200, 0.22), 0 0 180px 50px rgba(61, 220, 132, 0.12);
  transform: translateY(calc(var(--p) * 12vh));
}

.crows {
  position: absolute;
  top: 24%;
  left: 0;
  width: clamp(90px, 12vw, 160px);
  animation: fly 26s linear 2s infinite;
}

.crow {
  fill: #000;
  transform-box: fill-box;
  transform-origin: center;
  animation: flap 0.5s ease-in-out infinite alternate;
}

.crow.k2 {
  animation-delay: -0.2s;
}

.crow.k3 {
  animation-delay: -0.35s;
}

@keyframes fly {
  from {
    transform: translate(-20vw, 6vh);
  }
  to {
    transform: translate(120vw, -8vh);
  }
}

@keyframes flap {
  to {
    transform: scaleY(0.35);
  }
}

.mountains {
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 62%;
  transform-origin: bottom;
  transform: translateY(calc(var(--p) * 12vh)) scale(calc(1 + var(--p) * 0.15));
}

.mountains .far {
  fill: #141a20;
  stroke: #000;
  stroke-width: 2;
  stroke-linejoin: miter;
}

.mountains .far-hatch {
  fill: url(#hatch);
  opacity: 0.5;
}

.mountains .peak-snow {
  fill: var(--snow-shade);
  stroke: #000;
  stroke-width: 1.5;
}

.mountains .sea {
  stroke: rgba(228, 235, 238, 0.35);
  stroke-width: 2;
}

.mountains .sea.back {
  fill: #2a3a42;
}

.mountains .sea.front {
  fill: #3b4c55;
  animation: sea 30s ease-in-out infinite alternate;
}

@keyframes sea {
  to {
    transform: translateX(-24px);
  }
}

/* The castle grows around its gate, then the camera dives through it. */
.castle-wrap {
  left: 50%;
  bottom: -2%;
  width: max(min(94vw, 860px), 62vh);
  transform-origin: 50% 69.6%;
  transform: translateX(-50%) scale(var(--castle));
}

.castle {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 800 / 690;
  overflow: visible;
}

.castle .stone,
.castle .spire,
.castle .crag,
.castle .gate-frame {
  stroke: #000;
  stroke-width: 2.5;
  stroke-linejoin: miter;
}

.castle .stone {
  fill: #2c313a;
}

.castle .spire {
  fill: #1a1e25;
}

.castle .crag {
  fill: #1b2026;
}

.castle .snow,
.foreground .snow {
  fill: var(--snow);
  stroke: #000;
  stroke-width: 2;
  stroke-linejoin: miter;
}

.castle .hatch {
  fill: url(#hatch);
  opacity: 0.7;
  pointer-events: none;
}

.castle .crack,
.castle .blocks {
  fill: none;
  stroke: #000;
  stroke-width: 2;
}

.castle .blocks {
  stroke-width: 1.5;
  opacity: 0.7;
}

.castle .merlons {
  fill: #2c313a;
  stroke: #000;
  stroke-width: 2.5;
}

.castle .gate-frame {
  fill: #3a404a;
}

.castle .gate-dark {
  fill: #050304;
}

.castle .slit {
  fill: var(--spirit-hot);
  stroke: #000;
  stroke-width: 1.5;
  filter: drop-shadow(0 0 5px var(--spirit)) drop-shadow(0 0 12px rgba(61, 220, 132, 0.6));
  animation: smoulder 3.2s ease-in-out infinite;
}

.castle .slit.dim {
  fill: #0e1a16;
  filter: none;
  animation: none;
}

@keyframes smoulder {
  0%,
  100% {
    opacity: 1;
  }
  40% {
    opacity: 0.7;
  }
  55% {
    opacity: 0.92;
  }
}

.castle .pennant line {
  stroke: #000;
  stroke-width: 2.5;
}

.castle .pennant path {
  fill: var(--banner);
  stroke: #000;
  stroke-width: 1.5;
  transform-box: fill-box;
  transform-origin: left center;
  animation: whip 0.9s ease-in-out infinite alternate;
}

.castle .p-left path {
  animation-delay: -0.3s;
}

.castle .p-right path {
  animation-delay: -0.6s;
}

@keyframes whip {
  from {
    transform: scaleX(1) skewY(-3deg);
  }
  to {
    transform: scaleX(0.84) skewY(8deg);
  }
}

.castle .banner-hang path:first-child {
  fill: var(--banner-deep);
  stroke: #000;
  stroke-width: 2;
}

.castle .banner-hang .sword {
  fill: none;
  stroke: var(--bone);
  stroke-width: 2.5;
}

.castle .portcullis {
  transform: translateY(calc(var(--gate) * -116px));
}

.castle .portcullis .bars {
  fill: none;
  stroke: #1d2128;
  stroke-width: 5;
}

.castle .portcullis .spikes {
  fill: #1d2128;
  stroke: #000;
  stroke-width: 1;
}

.castle .chasm {
  fill: #000;
}

/* scaleY -1 folds the bridge up over the gate; 1 drops it across the chasm. */
.castle .bridge {
  transform-origin: 400px 440px;
  transform: scaleY(var(--bridge));
}

.castle .bridge rect:first-child {
  fill: #3a2616;
  stroke: #000;
  stroke-width: 2.5;
}

.castle .bridge path {
  stroke: #000;
  stroke-width: 2;
}

.foreground {
  bottom: -2%;
  width: min(46vw, 440px);
  height: 78%;
}

.foreground.left {
  left: -4%;
  transform-origin: bottom left;
  transform: translate(calc(var(--p) * -45vw), calc(var(--p) * 24vh)) scale(calc(1 + var(--p) * 0.9));
}

.foreground.right {
  right: -4%;
  transform-origin: bottom right;
  transform: translate(calc(var(--p) * 45vw), calc(var(--p) * 24vh)) scale(calc(1 + var(--p) * 0.9));
}

.foreground .rock {
  fill: #0b090c;
  stroke: #000;
  stroke-width: 3;
  stroke-linejoin: miter;
}

.foreground .pine path:first-child,
.foreground .pine rect {
  fill: #05080a;
  stroke: #000;
  stroke-width: 2;
}

.foreground .pine-snow {
  fill: var(--snow);
  stroke: var(--snow);
  stroke-width: 5;
  stroke-linecap: round;
}

.mist {
  position: absolute;
  inset: auto 0 0;
  height: 34%;
  pointer-events: none;
  opacity: calc(0.8 - var(--p) * 0.5);
}

.mist span {
  position: absolute;
  inset: 0 -50%;
  background: radial-gradient(ellipse at 30% 70%, rgba(200, 215, 225, 0.22), transparent 55%),
    radial-gradient(ellipse at 75% 80%, rgba(170, 190, 200, 0.2), transparent 50%);
  filter: blur(14px);
  animation: mist 38s linear infinite alternate;
}

.mist span + span {
  animation-duration: 52s;
  animation-direction: alternate-reverse;
  opacity: 0.7;
}

@keyframes mist {
  to {
    transform: translateX(18%);
  }
}

.snowfall,
.wisps {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.flake {
  position: absolute;
  top: -10px;
  width: var(--s, 3px);
  height: var(--s, 3px);
  border-radius: 50%;
  background: var(--snow);
  opacity: 0.85;
  animation: fall var(--t, 10s) linear var(--d, 0s) infinite;
}

@keyframes fall {
  to {
    transform: translate(var(--dx, 40px), 110vh);
  }
}

.wisp {
  position: absolute;
  bottom: -10px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--spirit-hot);
  box-shadow: 0 0 8px 3px rgba(61, 220, 132, 0.8);
  animation: rise var(--t, 8s) ease-in var(--d, 0s) infinite;
}

@keyframes rise {
  0% {
    transform: translate(0, 0);
    opacity: 0;
  }
  15% {
    opacity: 1;
  }
  100% {
    transform: translate(var(--dx, 40px), -70vh);
    opacity: 0;
  }
}

.title {
  position: absolute;
  top: 15%;
  left: 50%;
  width: min(620px, calc(100vw - 32px));
  display: grid;
  justify-items: center;
  opacity: var(--title);
  transform: translate(-50%, calc((1 - var(--title)) * -8vh));
  pointer-events: none;
  text-align: center;
}

.kicker {
  margin: 0;
  color: var(--bone-dim);
  font-family: var(--caps);
  font-size: clamp(0.7rem, 1.8vw, 0.9rem);
  font-weight: 700;
  letter-spacing: 0.5em;
  text-transform: uppercase;
}

.title h1 {
  margin: 4px 0 0;
  color: var(--bone);
  font-family: var(--blackletter);
  font-size: clamp(2.8rem, 10vw, 5.6rem);
  font-weight: 700;
  line-height: 1;
  text-shadow: 0 3px 0 #000, 0 0 28px rgba(61, 220, 132, 0.65), 0 0 2px #000;
}

.divider {
  width: clamp(180px, 40vw, 300px);
  margin-top: 6px;
}

.divider .blade {
  fill: #9a95a6;
  stroke: #000;
  stroke-width: 1;
}

.divider .guard,
.divider .grip {
  stroke: var(--bone);
  stroke-width: 3;
}

.divider .grip {
  stroke: var(--banner);
  stroke-width: 4;
}

.divider .pommel {
  fill: var(--banner);
  stroke: var(--bone);
  stroke-width: 1.5;
}

.scroll-hint {
  display: grid;
  justify-items: center;
  gap: 8px;
  margin: clamp(26px, 6vw, 44px) 0 0;
  color: var(--bone-dim);
  font-family: var(--caps);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
}

.chevron {
  width: 12px;
  height: 12px;
  border-right: 2px solid var(--bone-dim);
  border-bottom: 2px solid var(--bone-dim);
  transform: rotate(45deg);
  animation: bounce 1.6s ease-in-out infinite;
}

@keyframes bounce {
  50% {
    transform: translateY(8px) rotate(45deg);
  }
}

/* ---------- The Great Hall ---------- */

/* The wall and floor run 150% past every edge of the screen (this box is 4x the hall), so the room
   never shows a border while it is small and blurred during the dive. */
.hall::before {
  content: "";
  position: absolute;
  inset: -150%;
  background-color: #121015;
  background-image:
    radial-gradient(ellipse 22% 14% at 50% 48.75%, rgba(61, 220, 132, 0.12), transparent),
    linear-gradient(180deg, rgba(0, 0, 0, 0.75) 37.5%, transparent 45%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='56'%3E%3Cg fill='%231b1820' stroke='%23000' stroke-width='3'%3E%3Cpath d='M1.5 1.5 H94.5 V26.5 H1.5 Z'/%3E%3Cpath d='M-46.5 29.5 H46.5 V54.5 H-46.5 Z'/%3E%3Cpath d='M49.5 29.5 H142.5 V54.5 H49.5 Z'/%3E%3C/g%3E%3Cpath d='M20 10 l8 4 M70 18 l-6 3 M30 40 l7 -3' stroke='%23000' stroke-width='1.5'/%3E%3C/svg%3E");
}

.hall-scene {
  --floor: 27%;
  position: relative;
  height: 100%;
  transform-origin: 50% 60%;
  transition: transform 750ms cubic-bezier(0.55, 0, 0.8, 0.4);
}

.hall-scene.entering {
  transform: scale(3.4);
}

.hall.instant h2,
.hall.instant .arch,
.hall.instant .signpost,
.hall.instant .flame {
  transition: none;
}

/* Coming back out of a door: start inside it, in the dark, and pull back out. */
.hall-scene.arriving {
  transform: scale(3.4);
  transition: none;
}

.hall-scene:not(.entering) {
  transition-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1);
}

.hall h2 {
  position: relative;
  z-index: 2;
  margin: 0;
  padding-top: clamp(96px, 16vh, 140px);
  color: var(--bone);
  font-family: var(--blackletter);
  font-size: clamp(2.2rem, 6vw, 3.8rem);
  font-weight: 700;
  text-align: center;
  text-shadow: 0 3px 0 #000, 0 0 30px rgba(61, 220, 132, 0.45);
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 700ms ease, transform 700ms ease;
}

.hall.lit h2 {
  opacity: 1;
  transform: none;
}

.hall-banners {
  position: absolute;
  inset: -150vh 0 auto;
  display: flex;
  justify-content: space-around;
  padding: 0 6%;
  pointer-events: none;
}

.hang {
  width: clamp(34px, 5vw, 58px);
  height: calc(150vh + clamp(110px, 22vh, 190px));
  background:
    linear-gradient(90deg, transparent 46%, rgba(216, 205, 180, 0.55) 46% 54%, transparent 54%),
    var(--banner-deep);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 21px), 84% calc(100% - 39px), 70% calc(100% - 7px), 52% calc(100% - 32px), 34% 100%, 18% calc(100% - 35px), 0 calc(100% - 14px));
  transform-origin: 50% 150vh;
  filter: drop-shadow(0 0 0 #000);
  animation: sway 6s ease-in-out infinite alternate;
}

.hang.black {
  background-color: #08090b;
  animation-delay: -3s;
}

@keyframes sway {
  from {
    transform: rotate(-1deg);
  }
  to {
    transform: rotate(1deg);
  }
}

.arches {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--floor) - 2px);
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(8px, 3vw, 36px);
  padding: 0 16px;
}

.arch {
  display: grid;
  justify-items: center;
  gap: 8px;
  color: var(--bone);
  text-decoration: none;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 500ms ease, transform 500ms ease;
  transition-delay: calc(var(--i, 0) * 120ms + 200ms);
  -webkit-tap-highlight-color: transparent;
}

.hall.lit .arch {
  opacity: 1;
  transform: none;
}

.arch:focus-visible {
  outline: none;
}

.arch-banner {
  padding: 6px 14px;
  border: 1px solid rgba(216, 205, 180, 0.35);
  color: var(--bone);
  background: #0b090c;
  box-shadow: 0 0 0 1px #000;
  font-family: var(--caps);
  font-size: clamp(0.66rem, 1.9vw, 0.86rem);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background 200ms ease, border-color 200ms ease, transform 200ms ease;
}

.doorway {
  position: relative;
  display: grid;
  place-items: center;
  width: clamp(88px, 17vw, 180px);
  aspect-ratio: 120 / 170;
}

.frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.frame .outer {
  fill: #35303b;
  stroke: #000;
  stroke-width: 3;
}

.frame .voussoirs {
  fill: none;
  stroke: #000;
  stroke-width: 2;
}

.frame .inner {
  fill: #040304;
  stroke: #000;
  stroke-width: 2;
}

.frame .glow {
  opacity: 0;
  transition: opacity 260ms ease;
}

.frame .planks {
  fill: #2a1a10;
  stroke: #000;
  stroke-width: 2;
}

.frame .bands {
  fill: none;
  stroke: #15131a;
  stroke-width: 7;
}

.frame .studs {
  fill: none;
  stroke: #5a5560;
  stroke-width: 4;
  stroke-linecap: round;
}

.sigil {
  position: relative;
  width: 42%;
  margin-top: 18%;
  color: var(--bone);
  transition: transform 260ms ease, color 260ms ease, filter 260ms ease;
}

.sigil svg {
  display: block;
  width: 100%;
  height: auto;
}

.plaque {
  min-height: 2.8em;
  max-width: clamp(88px, 17vw, 180px);
  color: var(--bone-dim);
  font-family: var(--caps);
  font-size: clamp(0.56rem, 1.4vw, 0.7rem);
  letter-spacing: 0.06em;
  text-align: center;
}

.arch:hover .glow,
.arch:focus-visible .glow,
.arch.selected .glow {
  opacity: 1;
}

.arch:hover .sigil,
.arch.selected .sigil {
  color: var(--spirit-hot);
  filter: drop-shadow(0 0 10px var(--spirit));
  transform: translateY(-3px);
}

.arch.selected .arch-banner,
.arch:focus-visible .arch-banner {
  border-color: var(--spirit);
  background: var(--banner-deep);
  transform: translateY(-3px);
}

.arch.sealed .sigil {
  color: #77717f;
  filter: none;
}

.arch.sealed.rattle .doorway {
  animation: rattle 380ms ease;
}

@keyframes rattle {
  20%,
  60% {
    transform: translateX(-4px);
  }
  40%,
  80% {
    transform: translateX(4px);
  }
}

/* The way to the throne hall: one more stop for the knight, on the floor at the right. */
.signpost {
  position: absolute;
  right: max(16px, 7%);
  bottom: calc(var(--floor) - 150px);
  z-index: 2;
  width: clamp(96px, 11vw, 150px);
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 500ms ease 560ms, transform 500ms ease 560ms;
  -webkit-tap-highlight-color: transparent;
}

.hall.lit .signpost {
  opacity: 1;
  transform: none;
}

.signpost:focus-visible {
  outline: none;
}

.signpost svg {
  display: block;
  width: 100%;
  overflow: visible;
}

.signpost .post {
  fill: #1e1309;
  stroke: #000;
  stroke-width: 3;
}

.signpost .board {
  fill: #2a1a10;
  stroke: #000;
  stroke-width: 3;
  stroke-linejoin: miter;
  transition: stroke 200ms ease, filter 200ms ease;
}

.signpost .grain {
  fill: none;
  stroke: #000;
  stroke-width: 1.5;
  opacity: 0.55;
}

.signpost .crown {
  fill: #a08c55;
  stroke: #000;
  stroke-width: 2;
}

.signpost text {
  fill: var(--bone);
  font-family: var(--caps);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  transition: fill 200ms ease;
}

.signpost:hover .board,
.signpost.selected .board {
  stroke: var(--spirit);
  filter: drop-shadow(0 0 8px var(--spirit));
}

.signpost:hover text,
.signpost.selected text {
  fill: var(--spirit-hot);
}

.torch {
  position: relative;
  align-self: center;
  width: 10px;
  height: 44px;
  margin-bottom: 40px;
  border: 2px solid #000;
  background: linear-gradient(90deg, #2a2730, #121015);
  clip-path: polygon(0 0, 100% 0, 75% 100%, 25% 100%);
}

.torch-wrap {
  position: relative;
  align-self: center;
  margin-bottom: 40px;
}

.torch-wrap .torch {
  margin: 0;
}

.flame {
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 20px;
  height: 34px;
  margin-left: -10px;
  border-radius: 50% 50% 40% 40% / 70% 70% 30% 30%;
  background: radial-gradient(ellipse at 50% 78%, #f4fff7 0 14%, var(--spirit-hot) 36%, var(--spirit) 64%, #0f6b3a);
  box-shadow: 0 0 34px 14px rgba(61, 220, 132, 0.4), 0 0 90px 30px rgba(61, 220, 132, 0.15);
  transform-origin: bottom;
  transform: scale(0);
  transition: transform 400ms cubic-bezier(0.2, 0.9, 0.3, 1.5);
  transition-delay: calc(var(--i, 0) * 140ms);
}

.hall.lit .flame {
  transform: scale(1);
  animation: burn 0.7s ease-in-out calc(var(--i, 0) * 140ms + 400ms) infinite alternate;
}

@keyframes burn {
  from {
    transform: scale(1, 1) rotate(-3deg);
  }
  to {
    transform: scale(0.86, 1.16) rotate(4deg);
  }
}

/* Ink-drawn flagstones and carpet (built in index.js). The SVG reaches 150% past the sides and
   bottom of the screen, and 1000 viewBox units = one screen width across and one screen height down. */
.floor {
  position: absolute;
  left: -150%;
  top: calc(100% - var(--floor));
  width: 400%;
  height: calc(var(--floor) + 150%);
}

.floor .joints {
  fill: none;
  stroke: #000;
  stroke-width: 2.5;
}

.floor .brass {
  fill: none;
  stroke: url(#brassFade);
  stroke-width: 5;
}

.floor .sill {
  stroke: #000;
  stroke-width: 3;
}

.knight {
  position: absolute;
  bottom: calc(var(--floor) - 140px);
  left: 50%;
  z-index: 3;
  width: clamp(54px, 7vw, 76px);
  margin-left: calc(clamp(54px, 7vw, 76px) / -2);
  transition: left linear;
  filter: drop-shadow(0 8px 6px rgba(0, 0, 0, 0.8));
  transform-origin: 50% 100%;
}

/* Stepping out of a doorway: from the threshold, small and in shadow, down onto the floor. */
.knight.emerging {
  animation: emerge 1150ms cubic-bezier(0.3, 0.6, 0.4, 1) both;
}

@keyframes emerge {
  0%,
  28% {
    transform: translateY(var(--emerge-y, -120px)) scale(0.6);
    opacity: 0;
    filter: brightness(0.3);
  }
  50% {
    opacity: 1;
  }
  100% {
    transform: none;
    opacity: 1;
    filter: drop-shadow(0 8px 6px rgba(0, 0, 0, 0.8));
  }
}

.knight svg {
  display: block;
  width: 100%;
  overflow: visible;
}

.knight.face-left svg {
  transform: scaleX(-1);
}

.knight .steel {
  fill: #4a4652;
  stroke: #000;
  stroke-width: 2.5;
  stroke-linejoin: miter;
}

.knight .steel.dark {
  fill: #2c2932;
}

.knight .visor {
  fill: none;
  stroke: #000;
  stroke-width: 4;
}

.knight .plume {
  fill: var(--banner);
  stroke: #000;
  stroke-width: 2;
}

.knight .cape {
  fill: #06140e;
  stroke: #000;
  stroke-width: 2;
}

.knight .tabard {
  fill: var(--banner-deep);
  stroke: #000;
  stroke-width: 2;
}

.knight .blade {
  fill: #b9b4c4;
  stroke: #000;
  stroke-width: 1.5;
}

.knight .hilt {
  stroke: #000;
  stroke-width: 4;
}

.knight .leg {
  fill: #2c2932;
  stroke: #000;
  stroke-width: 2.5;
  transform-box: fill-box;
  transform-origin: top center;
}

.knight .body {
  transform-origin: 40px 110px;
}

.knight.walking .body {
  animation: bob 0.34s ease-in-out infinite alternate;
}

.knight.walking .leg.l {
  animation: step 0.34s ease-in-out infinite alternate;
}

.knight.walking .leg.r {
  animation: step 0.34s ease-in-out infinite alternate-reverse;
}

.knight.idle .body {
  animation: breathe 2.8s ease-in-out infinite;
}

@keyframes bob {
  to {
    transform: translateY(-3px) rotate(1.5deg);
  }
}

@keyframes step {
  from {
    transform: rotate(-18deg);
  }
  to {
    transform: rotate(18deg);
  }
}

@keyframes breathe {
  50% {
    transform: translateY(-1.5px);
  }
}

.hall-keys {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  z-index: 3;
  margin: 0;
  color: var(--bone-dim);
  font-family: var(--caps);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-align: center;
  text-transform: uppercase;
}

.hall-keys kbd {
  display: inline-block;
  min-width: 22px;
  margin: 0 2px;
  padding: 1px 6px;
  border: 1px solid var(--bone-dim);
  color: var(--bone);
  background: #0b090c;
  font-family: var(--ui);
  font-size: 0.72rem;
  letter-spacing: 0;
}

/* What's behind the door: a dark plate beside the knight, on the side with more room. */
.room-info {
  position: absolute;
  bottom: calc(var(--floor) - 150px);
  left: calc(var(--x, 50%) + 58px);
  z-index: 4;
  width: clamp(240px, calc(var(--room, 440px) - 80px), 440px);
  padding: 12px 16px 10px;
  border: 1px solid var(--banner);
  border-left: 3px solid var(--spirit);
  background: rgba(8, 7, 9, 0.92);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.7), 0 0 24px rgba(61, 220, 132, 0.12);
  color: var(--bone);
  opacity: 0;
  transform: translateY(8px);
  visibility: hidden;
  transition: opacity 260ms ease, transform 260ms ease, visibility 0s linear 260ms;
}

.room-info.on-left {
  left: auto;
  right: calc(100% - var(--x, 50%) + 58px);
  border-left: 1px solid var(--banner);
  border-right: 3px solid var(--spirit);
}

.room-info.shown {
  opacity: 1;
  transform: none;
  visibility: visible;
  transition: opacity 260ms ease, transform 260ms ease, visibility 0s;
}

.room-info h3 {
  margin: 0 0 6px;
  color: var(--spirit-hot);
  font-family: var(--caps);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.room-info p {
  margin: 0;
  font-family: var(--ui);
  font-size: 0.82rem;
  line-height: 1.42;
}

.room-info .links {
  margin-top: 9px;
  color: var(--bone-dim);
  font-size: 0.78rem;
}

.room-info a {
  color: var(--spirit);
  text-decoration: underline;
  text-decoration-color: rgba(61, 220, 132, 0.4);
  text-underline-offset: 3px;
}

.room-info a:hover,
.room-info a:focus-visible {
  color: var(--spirit-hot);
  text-decoration-color: currentColor;
}

.hall-fade {
  position: absolute;
  inset: 0;
  z-index: 10;
  background: var(--void);
  opacity: 0;
  pointer-events: none;
  transition: opacity 600ms ease 150ms;
}

.hall-scene.arriving .hall-fade,
.hall-scene.dark .hall-fade {
  opacity: 1;
  transition: none;
}

.hall-scene.entering .hall-fade,
.hall-scene.leaving .hall-fade {
  opacity: 1;
}

/* Portrait: the title takes the top of the sky, so the moon drops below it. */
@media (max-aspect-ratio: 3 / 4) {
  .moon {
    top: 36%;
    right: 8%;
  }
}

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

@media (max-width: 560px) {
  .nav-links a {
    padding: 8px 8px;
    font-size: 0.66rem;
    letter-spacing: 0.08em;
  }

  .torch-wrap {
    display: none;
  }

  .hall-keys {
    display: none;
  }

  /* Phones: no room beside the knight, so the panel takes the wall between the title and the doors. */
  .room-info,
  .room-info.on-left {
    top: clamp(190px, 25vh, 240px);
    bottom: auto;
    left: 16px;
    right: 16px;
    width: auto;
    border: 1px solid var(--banner);
    border-top: 3px solid var(--spirit);
  }
}

/* No scroll-driven zoom or ambient motion: the castle sits still with its gate open. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition-duration: 1ms !important;
  }
}
