/* ---- header ---- */
.header {
  position: fixed; inset: 0 0 auto 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 28px; color: var(--ivory);
  transition: color .4s ease;
}
.header.on-light { color: #14101d; }
.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; }
.header .brand { opacity: var(--brand, 1); }
.header.brand-hidden .brand, .is-playing .header .brand { visibility: hidden; pointer-events: none; }
.is-playing .header .brand { opacity: 0; }
.brand-seat { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: rgba(9, 11, 18, .55); }
.brand-mark { width: 40px; height: auto; }
.brand-word { font-size: 1rem; }
.header-left { display: flex; align-items: center; gap: .9rem; }
.is-playing .header .header-left { opacity: 0; pointer-events: none; }
.header-right { display: flex; align-items: center; gap: .8rem; transition: opacity .3s; }
.is-playing .header-right { opacity: 0; pointer-events: none; }


/* ---- sound toggle: top left, a ring with three bars that breathe while sound is on ---- */
/* The ring and its bars are drawn in currentColor, so .header.on-light carries them onto a lit frame
 * with everything else: literal colours here meant the adaptive header never reached them and both
 * washed out over the canopy. The mixes are also the resting contrast - 62% of ivory on the dark header
 * clears WCAG 1.4.11's 3:1 for a control boundary, where the old .45 of silver measured 2.92. */
.sound { position: relative; width: 40px; height: 40px; border-radius: 50%; border: 1px solid color-mix(in srgb, currentColor 62%, transparent); background: transparent; cursor: pointer; display: grid; place-items: center; transition: border-color .2s, box-shadow .2s; }
.sound:hover, .sound:focus-visible { border-color: currentColor; box-shadow: 0 0 0 4px rgba(143, 163, 255, .12); outline: none; }
.sound[aria-pressed="true"] { border-color: currentColor; }
.sound-bars { display: flex; gap: 3px; align-items: center; height: 14px; }
.sound-bars i { display: block; width: 2px; height: 14px; background: currentColor; transform: scaleY(.15); transform-origin: center; transition: transform .3s; }
.sound[aria-pressed="true"] .sound-bars i { animation: sound-breathe 2.4s ease-in-out infinite; }
.sound[aria-pressed="true"] .sound-bars i:nth-child(2) { animation-delay: .4s; }
.sound[aria-pressed="true"] .sound-bars i:nth-child(3) { animation-delay: .8s; }
@keyframes sound-breathe { 0%, 100% { transform: scaleY(.35); } 50% { transform: scaleY(1); } }
.sound-word { position: absolute; top: calc(100% + 6px); left: 50%; transform: translateX(-50%); font: 500 .58rem/1 var(--font-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--mist); opacity: 0; transition: opacity .2s; pointer-events: none; }
.sound:hover .sound-word, .sound:focus-visible .sound-word { opacity: 1; }
.reduced .sound[aria-pressed="true"] .sound-bars i { animation: none; transform: scaleY(.7); }

/* ---- the ghost rail (spec section 6) ----
   A column of tick marks down the left edge: where you are in the film, and how to get anywhere else in it.
   Low-contrast on purpose - it should read as furniture until you look at it, and the name only appears
   beside the tick you are pointing at. It is `hidden` until the first scroll rather than transparent, so
   nobody can tab into a rail that is not on the screen. */
.ghost-nav {
  position: fixed; left: 0; top: 50%; transform: translateY(-50%); z-index: 30;
  display: flex; flex-direction: column; gap: 10px; padding: 14px 10px 14px 14px;
  animation: ghost-in .8s ease both;
}
.ghost-nav[hidden] { display: none; }
@keyframes ghost-in { from { opacity: 0; transform: translate(-8px, -50%); } to { opacity: 1; transform: translate(0, -50%); } }
.reduced .ghost-nav { animation: none; }
@media (prefers-reduced-motion: reduce) { .ghost-nav { animation: none; } }

/* The mark itself is the button's ::before: a short rule that lengthens and lights when it is the one you
   are at, or the one you are pointing at. The button is bigger than the rule so it is comfortable to hit. */
.ghost-mark {
  position: relative; display: block; width: 46px; height: 14px; padding: 0;
  background: none; border: 0; cursor: pointer; -webkit-appearance: none; appearance: none;
}
.ghost-mark::before {
  content: ''; position: absolute; left: 0; top: 50%; width: 14px; height: 1px; margin-top: -.5px;
  background: rgba(200, 184, 219, .3);
  transition: width .28s cubic-bezier(.22, 1, .36, 1), background-color .28s ease;
}
.ghost-mark:hover::before, .ghost-mark:focus-visible::before { width: 30px; background: rgba(200, 184, 219, .7); }
.ghost-mark[aria-current]::before { width: 26px; background: var(--mark-peri); }
.ghost-mark:focus-visible { outline: 1px solid rgba(143, 163, 255, .7); outline-offset: 3px; border-radius: 2px; }
/* A diamond on the far end of the mark you are at - the same diamond as the tittle on the i in the wordmark,
   which is where the rail gets its gothic from. Only the current mark wears one, so the eye has one thing to
   find rather than twelve. */
.ghost-mark::after {
  content: ''; position: absolute; left: 24px; top: 50%; width: 5px; height: 5px;
  margin: -2.5px 0 0 -2.5px; background: var(--mark-peri); transform: rotate(45deg) scale(0);
  transition: transform .28s cubic-bezier(.22, 1, .36, 1);
}
.ghost-mark[aria-current]::after { transform: rotate(45deg) scale(1); }
.reduced .ghost-mark::before, .reduced .ghost-mark::after, .reduced .ghost-name { transition: none; }

/* The name rides just past the end of the longest tick, and only for the mark under the pointer. */
.ghost-name {
  position: absolute; left: 36px; top: 50%; transform: translateY(-50%);
  white-space: nowrap; opacity: 0; pointer-events: none;
  font: 500 .62rem/1 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  color: rgba(232, 226, 240, .85); text-shadow: 0 1px 6px rgba(5, 5, 7, .9);
  transition: opacity .2s ease;
}
.ghost-mark:hover .ghost-name, .ghost-mark:focus-visible .ghost-name { opacity: 1; }

/* No rail on a phone: it would sit in the thumb's path down the left edge of the screen, and the film is
   scrubbed by scrolling there rather than jumped around. */
.phone .ghost-nav { display: none; }
@media (max-width: 760px) { .ghost-nav { display: none; } }

/* ---- the ground the film fades into ---- */
:root { --ground: #0a0a1a; }

/* ---- the finale's two actions (the beat itself is film.css) ---- */
.finale-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.6rem; }

/* The closing band: the dark the fade lands on, one line set like the hero's inscription, one exit. */
.closing { position: relative; background: #0a0a1a; padding: 18vh 6vw 14vh; text-align: center; }
.closing-line { margin: 0 0 2rem; font: 400 clamp(.72rem, .9vw, .84rem)/1.6 var(--font-caps); letter-spacing: .34em; text-indent: .34em; text-transform: uppercase; color: rgba(200, 184, 219, .62); }

/* ---- footer: the same ground, the tree's ember as a faint gold radial at the very bottom edge ---- */
.footer {
  position: relative; isolation: isolate; padding: 3rem 7vw 4rem; color: var(--mist);
  background: radial-gradient(52vw 16vh at 50% 100%, rgba(211, 165, 74, .11), transparent 70%) var(--ground);
  border-top: 1px solid rgba(249, 244, 245, .06);
}
.footer::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: .04;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='280'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E") 0 0 / 280px 280px repeat;
}
.footer-inner { position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem 3rem; }
.footer .brand-mark { width: 28px; }
.footer .brand-word { font-size: .9rem; }
.footer-links { display: flex; flex-wrap: wrap; gap: 1rem 2rem; }
.footer-links a { font: 500 .72rem/1 var(--font-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--mist); text-decoration: none; padding-bottom: .3rem; border-bottom: 1px solid rgba(211, 165, 74, .45); transition: color .2s, border-color .2s; }
.footer-links a:hover, .footer-links a:focus-visible { color: var(--ivory); border-bottom-color: var(--gold); outline: none; }
.footer-copy { margin: 0; margin-left: auto; font-size: .85rem; }

.phone .header { padding: 12px 16px; }
.phone .brand-seat { width: 40px; height: 40px; }
.phone .brand-mark { width: 32px; }
.phone .brand-word { display: none; }
.phone .footer { padding-left: 6vw; padding-right: 6vw; }
.phone .footer-copy { margin-left: 0; }

/* ---- boot veil ---- */
.veil { position: fixed; inset: 0; z-index: 60; background: var(--ink); display: grid; place-content: center; justify-items: center; transition: opacity .6s ease; }
.veil.is-gone { opacity: 0; pointer-events: none; }
.veil[hidden] { display: none; }
.veil-word { font-size: 1.6rem; }
.veil-bar { display: block; width: 160px; height: 1px; margin-top: 14px; background: rgba(249, 244, 245, .15); }
.veil-bar i { display: block; height: 100%; width: 0; background: var(--gold); transition: width .2s linear; }

/* ---- plain view toggle (Plan 11, spec section 4.1) ----
 * The way out of the film, for anyone who just wants the information. It has to be findable without
 * being loud: dim until hovered, and it never takes the eye off the wordmark. The switch is drawn
 * rather than an <input> because it navigates to another page instead of flipping a state here.
 * Like the sound ring, all three pieces are drawn out of the header's own colour, so they follow it onto
 * a lit frame instead of staying a fixed lilac that vanishes there. PLAIN VIEW is text, so 1.4.3's 4.5:1
 * is its floor - 60% of ivory on the dark header clears it where the old .46 of lilac measured 3.00. */
.plain-toggle {
  display: flex; align-items: center; gap: .5rem; padding: .4rem .5rem;
  text-decoration: none; color: color-mix(in srgb, currentColor 60%, transparent);
  font: 500 .58rem/1 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  transition: color .3s ease;
}
.plain-toggle-track {
  position: relative; width: 26px; height: 14px; border-radius: 7px;
  border: 1px solid color-mix(in srgb, currentColor 42%, transparent); transition: border-color .3s ease;
}
.plain-toggle-knob {
  position: absolute; left: 2px; top: 50%; width: 8px; height: 8px; border-radius: 50%;
  transform: translateY(-50%); background: color-mix(in srgb, currentColor 62%, transparent);
  transition: transform .3s cubic-bezier(.16, .6, .2, 1), background-color .3s ease;
}
.plain-toggle:hover, .plain-toggle:focus-visible {
  color: var(--ivory); outline: none;
}
.plain-toggle:hover .plain-toggle-track, .plain-toggle:focus-visible .plain-toggle-track { border-color: rgba(140, 220, 222, .55); }
.plain-toggle:hover .plain-toggle-knob, .plain-toggle:focus-visible .plain-toggle-knob { transform: translateY(-50%) translateX(12px); background: rgba(140, 220, 222, .9); }
.reduced .plain-toggle-knob { transition: background-color .3s ease; }
.reduced .plain-toggle:hover .plain-toggle-knob { transform: translateY(-50%) translateX(12px); }
/* Someone whose system asks for less motion is offered plain view rather than sent there: the control
 * simply stops being quiet, so the choice is visible and still theirs. Spec section 4.1. */
@media (prefers-reduced-motion: reduce) { .plain-toggle { color: var(--mist); } .plain-toggle-track { border-color: rgba(140, 220, 222, .45); } }
/* On a phone the label goes and the switch stands alone. */
.phone .plain-toggle-label { display: none; }
