/* picard — afterword
   Scene = square stage (the plate's own coordinate space) that covers the
   viewport; overlays inside it are positioned in % of the plate. */

:root {
  --ink: #0a0c09;
  --tan: #c9b28f;
  --tan-dim: #9d8b6c;
  --amber: #d99a4e;
  --silver: #ccd2cd;
  --flick: 1;            /* TV flicker, driven per-frame from JS */
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
           "Times New Roman", serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100%;
  background: var(--ink);
  overflow: hidden;
}

body {
  font-family: var(--serif);
  color: var(--tan);
  -webkit-font-smoothing: antialiased;
}

/* ---------- scene ---------- */

#scene {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* Default (no-JS) cover behavior; main.js refines position so the TV stays
   centered when the viewport crops the square plate. */
#stage {
  position: absolute;
  width: 100vmax;
  height: 100vmax;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

#plate {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

/* ---------- lighting ---------- */

.wash, .vignette, .glow-ember, #tvGlow, #fireGlow {
  position: absolute;
  pointer-events: none;
}

/* The plate already carries the baked lighting; these layers only modulate
   it, so they stay small and quiet. */

/* warm room wash breathing off the TV — the slow lighting change */
.wash-warm {
  inset: -5%;
  background: radial-gradient(40% 34% at 47.1% 48%,
              rgba(255, 158, 64, 0.13),
              rgba(158, 84, 24, 0.04) 45%,
              rgba(0, 0, 0, 0) 72%);
  mix-blend-mode: screen;
  animation: warmBreath 47s ease-in-out infinite alternate;
}

/* cool moonlit haze drifting through the upper right */
.wash-cool {
  inset: -5%;
  background: radial-gradient(55% 40% at 74% 12%,
              rgba(148, 168, 152, 0.10),
              rgba(90, 110, 96, 0.03) 50%,
              rgba(0, 0, 0, 0) 76%);
  mix-blend-mode: screen;
  animation: coolBreath 67s ease-in-out infinite alternate;
  animation-delay: -33s;
}

/* slow ember bloom around the set */
.glow-ember {
  left: 47.1%;
  top: 46.9%;
  width: 46%;
  height: 38%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side,
              rgba(255, 172, 84, 0.20),
              rgba(214, 118, 40, 0.07) 45%,
              rgba(0, 0, 0, 0) 72%);
  mix-blend-mode: screen;
  animation: emberBreath 17s ease-in-out infinite alternate;
}

/* firelight from the set starting to burn — red-orange, licking upward into
   the smoke; intensity is driven per-frame from JS (--fire), with surges */
#fireGlow {
  left: 48.5%;
  top: 37.5%;
  width: 27%;
  height: 32%;
  transform: translate(-50%, -50%);
  background: radial-gradient(50% 55% at 45% 55%,
              rgba(255, 118, 44, 0.17),
              rgba(202, 74, 22, 0.06) 52%,
              rgba(0, 0, 0, 0) 76%);
  mix-blend-mode: screen;
  opacity: var(--fire, 0.5);
}

/* cold breath around the ghost child — she is lit by something other than
   the TV, so her light moves on its own slow rhythm */
.wash-ghost {
  left: 76%;
  top: 59.3%;
  width: 30%;
  height: 52%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side,
              rgba(150, 172, 158, 0.12),
              rgba(120, 140, 128, 0.04) 55%,
              rgba(0, 0, 0, 0) 75%);
  mix-blend-mode: screen;
  animation: ghostBreath 29s ease-in-out infinite alternate;
  animation-delay: -11s;
}

/* tight screen halo, flicker-synced from JS */
#tvGlow {
  left: 47.1%;
  top: 46.9%;
  width: 28%;
  height: 23%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side,
              rgba(255, 205, 140, 0.38),
              rgba(255, 150, 60, 0.14) 50%,
              rgba(0, 0, 0, 0) 75%);
  mix-blend-mode: screen;
  opacity: calc(0.8 * var(--flick));
}

.vignette {
  inset: 0;
  background: radial-gradient(92% 92% at 50% 46%,
              rgba(0, 0, 0, 0) 58%,
              rgba(2, 3, 2, 0.40) 84%,
              rgba(1, 2, 1, 0.62) 100%);
  animation: vignetteBreath 37s ease-in-out infinite alternate;
}

@keyframes warmBreath     { from { opacity: 0.45; } to { opacity: 1; } }
@keyframes coolBreath     { from { opacity: 0.3; } to { opacity: 1; } }
@keyframes emberBreath    { from { opacity: 0.45; transform: translate(-50%,-50%) scale(1); }
                            to   { opacity: 0.9; transform: translate(-50%,-50%) scale(1.07); } }
@keyframes vignetteBreath { from { opacity: 0.8; } to { opacity: 1; } }
@keyframes ghostBreath    { from { opacity: 0.35; } to { opacity: 0.95; } }

/* ---------- TV static ---------- */

/* static fills the measured glass bbox; the occluder image above it trims it
   to the true glass shape (bezel, rounded corners, foreground) */
#tv {
  position: absolute;
  left: 35.17%;
  top: 38.28%;
  width: 23.60%;
  height: 17.22%;
  -webkit-mask-image: radial-gradient(120% 120% at 50% 50%,
                      #000 62%, rgba(0,0,0,0.6) 82%, rgba(0,0,0,0) 100%);
  mask-image: radial-gradient(120% 120% at 50% 50%,
              #000 62%, rgba(0,0,0,0.6) 82%, rgba(0,0,0,0) 100%);
  opacity: 0.95;
}

#tvOccluder {
  position: absolute;
  left: 32.46%;
  top: 35.57%;
  width: 29.03%;
  height: 22.65%;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

#smoke {
  position: absolute;
  left: 18%;
  top: 0;
  width: 72%;
  height: 64%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 2.5s ease 0.6s;
}

body.loaded #smoke { opacity: 1; }

/* ---------- grain ---------- */

.grain {
  position: fixed;
  inset: -100%;
  width: 300%;
  height: 300%;
  pointer-events: none;
  opacity: 0.055;
  mix-blend-mode: overlay;
  animation: grainShift 0.9s steps(8) infinite;
  /* background-image set from JS (generated noise tile) */
}

@keyframes grainShift {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-3%, 2%); }
  50%  { transform: translate(2%, -3%); }
  75%  { transform: translate(-2%, -2%); }
  100% { transform: translate(3%, 3%); }
}

/* ---------- UI ---------- */

.ui {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  pointer-events: none;
  padding: clamp(20px, 6vh, 64px) 24px clamp(16px, 4.5vh, 44px);
}

.masthead {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 2.2vh, 22px);
}

.logo {
  width: clamp(230px, 44vw, 560px);
  height: auto;
  filter: drop-shadow(0 3px 22px rgba(0, 0, 0, 0.6));
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

.subtitle,
.tagline {
  font-size: clamp(0.64rem, 2vw, 1.02rem);
  letter-spacing: 0.55em;
  margin-left: 0.55em;    /* optically recenter the tracked text */
  text-transform: lowercase;
  color: var(--tan-dim);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.8);
}

.tagline {
  font-size: clamp(0.72rem, 1.3vw, 0.94rem);
  letter-spacing: 0.5em;
  margin-left: 0.5em;
}

/* the full title reads over the brightest smoke — silver, like the ghost,
   with a deeper shadow so the smoke can't wash it out */
.subtitle {
  color: var(--silver);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.9), 0 0 24px rgba(0, 0, 0, 0.65);
}

/* ---------- colophon links ---------- */

.colophon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2.4vh, 20px);
}

#links {
  display: flex;
  gap: clamp(18px, 3vw, 30px);
  pointer-events: auto;   /* .ui swallows clicks; re-enable for the links */
}

#links a { display: inline-block; line-height: 0; }

#links a:focus-visible {
  outline: 2px solid var(--tan-dim);
  outline-offset: 4px;
}

#links .link {
  width: clamp(24px, 3.2vw, 32px);
  height: auto;
  opacity: 0.7;
  filter: drop-shadow(0 1px 8px rgba(0, 0, 0, 0.8));
  transition: opacity 0.4s ease;
  -webkit-user-drag: none;
}

#links a:hover .link,
#links a:focus-visible .link { opacity: 1; }

/* entrance */
#plate, .logo, .subtitle, .tagline, #links {
  opacity: 0;
  transition: opacity 1.6s ease;
}
.logo     { transition-delay: 0.45s; transform: translateY(6px);
            transition-property: opacity, transform; }
.subtitle { transition-delay: 0.95s; }
.tagline  { transition-delay: 1.35s; }
#links    { transition-delay: 1.6s; }

/* text settles at full opacity: --tan-dim over the near-black plate clears
   WCAG AA (~5.5:1); dimming it below ~0.9 does not */
body.loaded #plate,
body.loaded .subtitle,
body.loaded .tagline,
body.loaded #links { opacity: 1; }
body.loaded .logo  { opacity: 1; transform: translateY(0); }

/* ---------- sound toggle ---------- */

.sound-toggle {
  position: fixed;
  left: clamp(14px, 2.5vw, 28px);
  bottom: clamp(14px, 4vh, 36px);
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid rgba(201, 178, 143, 0.35);
  background: rgba(10, 12, 9, 0.5);
  color: var(--tan-dim);
  display: grid;
  place-items: center;
  cursor: pointer;
  pointer-events: auto;
  opacity: 0;
  transition: opacity 1.2s ease 1.8s, color 0.25s ease;
}

body.loaded .sound-toggle { opacity: 0.8; }

/* while silent, the button breathes amber like the set — come closer, listen */
.sound-toggle.off {
  animation: beckon 2.6s ease-in-out infinite;
}

@keyframes beckon {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(217, 154, 78, 0), 0 0 8px rgba(217, 154, 78, 0.2);
    border-color: rgba(201, 178, 143, 0.35);
  }
  50% {
    box-shadow: 0 0 0 4px rgba(217, 154, 78, 0.12), 0 0 20px rgba(217, 154, 78, 0.5);
    border-color: rgba(217, 154, 78, 0.75);
  }
}

.sound-toggle:hover,
.sound-toggle:focus-visible {
  opacity: 1;
  color: var(--tan);
  transition-delay: 0s;
}

.sound-toggle:focus-visible {
  outline: 2px solid var(--tan-dim);
  outline-offset: 3px;
}

.sound-toggle svg { width: 20px; height: 20px; display: block; }
.sound-toggle .icon-play { display: none; }
.sound-toggle.off .icon-play { display: block; }
.sound-toggle.off .icon-stop { display: none; }

/* short landscape screens: dock the lockup in the corners, clear of the TV */
@media (max-height: 480px) {
  .ui { align-items: flex-start; padding: 18px 22px; }
  .masthead { align-items: flex-start; gap: 8px; }
  .logo { width: clamp(130px, 26vh, 220px); }
  .subtitle { font-size: 0.62rem; letter-spacing: 0.42em; margin-left: 0; }
  .colophon { align-self: flex-end; align-items: flex-end; gap: 10px; }
  .tagline { font-size: 0.6rem; letter-spacing: 0.4em; margin-left: 0; }
  #links { gap: 14px; }
  #links .link { width: 22px; }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .wash-warm, .wash-cool, .wash-ghost, .glow-ember, .vignette, .grain {
    animation: none;
  }
  #smoke { transition: none; }
  #plate, .logo, .subtitle, .tagline, #links, .sound-toggle { transition: none; }
  /* no pulse, but keep a steady glow so the control still draws the eye */
  .sound-toggle.off {
    animation: none;
    box-shadow: 0 0 16px rgba(217, 154, 78, 0.35);
    border-color: rgba(217, 154, 78, 0.6);
  }
  .letter, .modal, #letterBackdrop { transition: none; }
  body.loaded .hotspot::before { animation: none; }
}

/* ---------- figure hotspots ---------- */

/* invisible buttons glued to the figures in plate coordinates; a soft glow
   answers hover/focus so the scene stays clean until you reach into it */
.hotspot {
  position: absolute;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  pointer-events: auto;
}

.hotspot-man   { left: 10%; top: 30%; width: 32%; height: 52%; }
.hotspot-child { left: 67%; top: 38%; width: 19%; height: 40%; }
.hotspot-tv    { left: 33.5%; top: 36%; width: 27%; height: 21%; }

.hotspot::before {
  content: "";
  position: absolute;
  inset: -8%;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.7s ease;
  pointer-events: none;
  mix-blend-mode: screen;
}

/* the man sits in near-black shadow; screen needs a much hotter glow to read */
.hotspot-man::before {
  background: radial-gradient(50% 50% at 50% 50%,
              rgba(255, 172, 84, 0.42),
              rgba(255, 172, 84, 0.22) 40%,
              rgba(255, 172, 84, 0) 78%);
}

.hotspot-child::before {
  background: radial-gradient(50% 50% at 50% 50%,
              rgba(150, 172, 158, 0.18), rgba(150, 172, 158, 0) 70%);
}

/* the set already burns bright; its answer glow stays faint and hot */
.hotspot-tv::before {
  background: radial-gradient(50% 50% at 50% 50%,
              rgba(255, 216, 160, 0.13), rgba(255, 216, 160, 0) 70%);
}

.hotspot:hover::before,
.hotspot:focus-visible::before { opacity: 1; }

.hotspot:focus-visible {
  outline: 1px solid rgba(201, 178, 143, 0.4);
  outline-offset: -1px;
  border-radius: 12px;
}

/* discovery hint: the glows breathe twice after the scene settles */
body.loaded .hotspot::before {
  animation: hotspotHint 2.6s ease-in-out 3.6s 2;
}

@keyframes hotspotHint {
  0%, 100% { opacity: 0; }
  50%      { opacity: 0.85; }
}

/* ---------- letters (slide-out panels) ---------- */

#letterBackdrop {
  position: fixed;
  inset: 0;
  z-index: 65;
  background: rgba(2, 3, 2, 0.45);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s ease, visibility 0s linear 0.5s;
}

#letterBackdrop.open {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.letter {
  position: fixed;
  top: 0;
  height: 100%;
  width: min(460px, 92vw);
  z-index: 70;
  padding: clamp(56px, 10vh, 96px) clamp(28px, 5vw, 52px)
           clamp(32px, 6vh, 64px);
  overflow-y: auto;
  background: linear-gradient(rgba(10, 13, 10, 0.72), rgba(7, 9, 7, 0.80));
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(201, 178, 143, 0.28);
  visibility: hidden;
  transition: transform 0.6s cubic-bezier(0.22, 0.8, 0.3, 1),
              visibility 0s linear 0.6s;
}

.letter-left {
  left: 0;
  transform: translateX(-103%);
  box-shadow: 30px 0 60px rgba(0, 0, 0, 0.45);
}

.letter-right {
  right: 0;
  transform: translateX(103%);
  box-shadow: -30px 0 60px rgba(0, 0, 0, 0.45);
}

.letter.open {
  visibility: visible;
  transform: translateX(0);
  transition-delay: 0s;
}

.letter-title {
  font-size: clamp(0.82rem, 1.6vw, 1rem);
  font-weight: normal;
  letter-spacing: 0.42em;
  text-transform: lowercase;
  color: var(--tan);
  margin-bottom: clamp(20px, 4vh, 36px);
}

.letter-body p {
  color: #b4a284;
  font-size: clamp(0.92rem, 1.15vw, 1.03rem);
  line-height: 1.75;
  margin-bottom: 1.2em;
}

.letter-body .lede {
  color: var(--tan);
  font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  letter-spacing: 0.04em;
}

.letter-body em { color: #c3b191; font-style: italic; }

/* ---------- band modal (centered) ---------- */

.modal {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 70;
  width: 70vw;
  max-height: min(82vh, 760px);
  overflow-y: auto;
  padding: clamp(40px, 7vh, 64px) clamp(28px, 5vw, 56px);
  background: linear-gradient(rgba(10, 13, 10, 0.72), rgba(7, 9, 7, 0.80));
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(201, 178, 143, 0.28);
  border-radius: 3px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  visibility: hidden;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.96);
  transition: opacity 0.45s ease,
              transform 0.45s cubic-bezier(0.22, 0.8, 0.3, 1),
              visibility 0s linear 0.45s;
}

.modal.open {
  visibility: visible;
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  transition-delay: 0s;
}

/* keep the wide modal readable: two book-page columns, lede spanning both */
@media (min-width: 1000px) {
  .modal .letter-body {
    column-count: 2;
    column-gap: clamp(40px, 4vw, 72px);
  }
  .modal .lede { column-span: all; }
  .modal .members { break-inside: avoid; }
}

@media (max-width: 720px) {
  .modal { width: 92vw; }
}

.members {
  list-style: none;
  margin: 0 0 1.4em;
  padding: 0.2em 0 0.2em 1.2em;
  border-left: 1px solid rgba(201, 178, 143, 0.22);
  color: #b4a284;
  line-height: 1.9;
  font-size: clamp(0.9rem, 1.1vw, 1rem);
}

.members .inst {
  margin-left: 0.6em;
  font-size: 0.8em;
  letter-spacing: 0.18em;
  text-transform: lowercase;
  color: #857659;
}

.signoff {
  margin-top: 1.8em;
  font-size: clamp(0.72rem, 1.1vw, 0.84rem);
  letter-spacing: 0.4em;
  text-transform: lowercase;
  color: var(--tan-dim);
}

.letter-close {
  position: absolute;
  top: 14px;
  right: 16px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--tan-dim);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  transition: color 0.25s ease;
}

.letter-close:hover,
.letter-close:focus-visible { color: var(--tan); }

.letter-close:focus-visible {
  outline: 2px solid var(--tan-dim);
  outline-offset: 2px;
}

/* ---------- scrollbars ---------- */

/* Chrome 121+ and Firefox take the standard properties; Safari falls back to
   the -webkit pseudo-elements below (browsers with the standard properties
   ignore the pseudo-elements, so the two sets never fight) */
.letter,
.modal {
  scrollbar-width: thin;
  scrollbar-color: rgba(157, 139, 108, 0.35) transparent;
}

.letter::-webkit-scrollbar,
.modal::-webkit-scrollbar {
  width: 10px;
}

.letter::-webkit-scrollbar-track,
.modal::-webkit-scrollbar-track {
  background: transparent;
}

.letter::-webkit-scrollbar-thumb,
.modal::-webkit-scrollbar-thumb {
  background: rgba(157, 139, 108, 0.3);
  border: 2px solid transparent;
  border-radius: 6px;
  background-clip: padding-box;
}

.letter::-webkit-scrollbar-thumb:hover,
.modal::-webkit-scrollbar-thumb:hover {
  background: rgba(201, 178, 143, 0.5);
  border: 2px solid transparent;
  border-radius: 6px;
  background-clip: padding-box;
}

/* ---------- debug (?debug=1) ---------- */

.debug-box {
  position: absolute;
  border: 1px solid rgba(0, 255, 128, 0.9);
  pointer-events: none;
  z-index: 50;
}
