﻿/* ============================================================
   Albert Jackson  |  Heritage Toronto tribute
   Heritage-postal design system
   ============================================================ */

:root {
  /* Palette drawn from the Canada Post stamp: navy uniform,
     crimson collar, brass trim, parchment ground */
  --navy:        #16233F;
  --navy-deep:   #0D1526;
  --navy-soft:   #223354;
  --crimson:     #A02B22;
  --crimson-deep:#7C201A;
  --brass:       #C39A50;
  --brass-light: #E2C88C;
  --brick:       #8C4A38;

  --parchment:   #F6EEDD;
  --parchment-2: #EFE4CD;
  --cream:       #FCF8EF;
  --ink:         #241C12;
  --ink-soft:    #574B39;
  --ink-faint:   #857863;

  --line:        #DED0B2;

  --maxw: 1200px;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --radius: 14px;
  --radius-lg: 22px;

  --font-serif: "Newsreader", Georgia, "Times New Roman", serif;
  --font-sans:  "Public Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

  --shadow-sm: 0 2px 10px rgba(20, 15, 6, 0.08);
  --shadow-md: 0 14px 40px rgba(20, 15, 6, 0.16);
  --shadow-lg: 0 30px 70px rgba(13, 21, 38, 0.30);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--parchment);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: 18px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: inherit; }

h1, h2, h3, h4 { line-height: 1.08; margin: 0; font-weight: 600; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

.skip-link {
  position: fixed; left: 1rem; top: -100px; z-index: 200;
  background: var(--navy); color: #fff; padding: 0.65rem 1rem;
  border-radius: 8px; font-family: var(--font-sans); font-size: 0.9rem;
  text-decoration: none; transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 1rem; }

/* ---------- Scroll progress ---------- */
.progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px;
  background: transparent; z-index: 120;
}
.progress span {
  display: block; height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--crimson), var(--brass));
  transition: width 0.1s linear;
}

/* ============================================================
   HEADER
   ============================================================ */
/* The hero is a night sky, so the header rides over it in cream and
   only takes a parchment ground once you scroll past it. */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.5rem);
  padding: 1.1rem var(--gutter);
  background: transparent;
  box-shadow: none;
  transition: background 0.4s var(--ease), box-shadow 0.4s var(--ease),
              padding 0.4s var(--ease), backdrop-filter 0.4s var(--ease);
}
/* Unscrolled, the header floats over the planet, whose landmasses are
   nearly parchment. Without this scrim the nav drops under 3:1. */
.site-header::before {
  content: ""; position: absolute; inset: -1px 0 auto 0; height: 190%;
  z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 8, 16, 0.92) 0%, rgba(4, 8, 16, 0.55) 45%, transparent 100%);
  transition: opacity 0.4s var(--ease);
}
.site-header.scrolled::before { opacity: 0; }
.atlas-body .site-header::before { opacity: 0; }
.site-header.scrolled {
  background: rgba(246, 238, 221, 0.95);
  backdrop-filter: saturate(1.3) blur(14px);
  -webkit-backdrop-filter: saturate(1.3) blur(14px);
  box-shadow: 0 1px 0 rgba(195, 154, 80, 0.42), var(--shadow-sm);
  padding-top: 0.62rem; padding-bottom: 0.62rem;
}

/* Pages without a dark hero (the atlas) start in the solid state. */
.atlas-body .site-header { background: rgba(246, 238, 221, 0.95); }

.brand { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; color: var(--cream); }
.site-header.scrolled .brand { color: var(--navy); }
/* A cast bronze tile rather than a flat one: the gradient plus the two
   inset hairlines read as a lit edge and a shadowed one, which is what
   stops it looking like a default app icon. */
.brand-mark {
  display: grid; place-items: center; width: 40px; height: 40px; flex-shrink: 0;
  border-radius: 11px; color: var(--navy-deep);
  background: linear-gradient(155deg, #F2E0B4 0%, var(--brass-light) 45%, var(--brass) 100%);
  box-shadow:
    0 6px 18px rgba(0,0,0,0.34),
    inset 0 1px 0 rgba(255,255,255,0.6),
    inset 0 -1px 0 rgba(120,88,30,0.45);
  transition: background 0.4s var(--ease), color 0.4s var(--ease);
}
.site-header.scrolled .brand-mark {
  background: var(--navy); color: var(--brass-light);
  box-shadow: 0 4px 12px rgba(13,21,38,0.28), inset 0 1px 0 rgba(255,255,255,0.09);
}
.brand-text { display: flex; flex-direction: column; line-height: 1; font-family: var(--font-sans); }
.brand-text strong { font-size: 0.98rem; font-weight: 700; letter-spacing: 0.01em; white-space: nowrap; }
.brand-text strong i { font-style: normal; opacity: 0.55; margin: 0 0.15em; }
.brand-text em {
  font-style: normal; font-size: 0.66rem; margin-top: 4px;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(252, 248, 239, 0.6);
}
.site-header.scrolled .brand-text em { color: var(--ink-faint); }

.site-nav {
  display: flex; gap: clamp(1rem, 2.2vw, 2rem); margin-left: auto;
  font-family: var(--font-sans); font-size: 0.82rem; font-weight: 600;
  letter-spacing: 0.04em;
}
.site-nav a {
  text-decoration: none; color: rgba(252, 248, 239, 0.92);
  position: relative; padding: 6px 0; white-space: nowrap;
  transition: color 0.2s var(--ease);
}
.site-header.scrolled .site-nav a { color: var(--ink-soft); }
.site-nav a::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0;
  background: var(--brass-light); transition: width 0.25s var(--ease);
}
.site-header.scrolled .site-nav a::after { background: var(--crimson); }
.site-nav a:hover { color: var(--cream); }
.site-header.scrolled .site-nav a:hover { color: var(--navy); }
.site-nav a:hover::after { width: 100%; }

.nav-cta {
  display: inline-flex; align-items: center; gap: 0.45rem; flex-shrink: 0;
  font-family: var(--font-sans); font-size: 0.85rem; font-weight: 600;
  text-decoration: none; color: #fff; background: var(--crimson);
  padding: 0.62rem 1.1rem; border-radius: 999px; box-shadow: var(--shadow-sm);
  transition: transform 0.2s var(--ease), background 0.2s var(--ease);
}
.nav-cta:hover { background: var(--crimson-deep); transform: translateY(-1px); }

/* ---- Mobile menu ---- */
/* Mirror of the CTA that nav.js appends into the panel. Only ever
   shown inside the open mobile menu, never in the desktop nav row. */
.nav-cta-mobile { display: none; }

.nav-toggle {
  display: none; margin-left: auto; cursor: pointer;
  width: 44px; height: 44px; padding: 0; border-radius: 11px;
  background: rgba(252, 248, 239, 0.1); color: var(--cream);
  border: 1px solid rgba(252, 248, 239, 0.2);
  place-items: center; transition: background 0.2s var(--ease);
}
.site-header.scrolled .nav-toggle {
  background: rgba(22, 35, 63, 0.07); color: var(--navy);
  border-color: rgba(22, 35, 63, 0.12);
}
.nav-toggle:hover { background: rgba(252, 248, 239, 0.2); }
.site-header.scrolled .nav-toggle:hover { background: rgba(22, 35, 63, 0.14); }
.nav-toggle-bars { display: block; width: 19px; height: 13px; position: relative; }
.nav-toggle-bars span {
  position: absolute; left: 0; height: 2px; width: 100%; border-radius: 2px;
  background: currentColor; transition: transform 0.28s var(--ease), opacity 0.2s var(--ease);
}
.nav-toggle-bars span:nth-child(1) { top: 0; }
.nav-toggle-bars span:nth-child(2) { top: 5.5px; }
.nav-toggle-bars span:nth-child(3) { top: 11px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* ============================================================
   HERO
   ============================================================ */
/* ============================================================
   STAGE HERO
   The collaboration, not the subject. A night sky, a turning
   planet, and the people who came off it. Albert is the worked
   example and lives below the fold.
   ============================================================ */
.stage {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center;
  padding: clamp(7rem, 16vh, 11rem) var(--gutter) clamp(6rem, 12vh, 8rem);
  overflow: hidden;
  background:
    radial-gradient(1100px 780px at 72% 46%, rgba(34, 51, 84, 0.85), transparent 68%),
    radial-gradient(900px 620px at 12% 8%, rgba(195, 154, 80, 0.13), transparent 62%),
    linear-gradient(178deg, #070C17 0%, var(--navy-deep) 46%, #0A1424 100%);
  color: var(--cream);
}

.stage-stars { position: absolute; inset: 0; z-index: 0; display: block; }

/* The planet: large, offset right, half of it beyond the edge */
.stage-planet {
  position: absolute; z-index: 1;
  top: 50%; left: 68%;
  width: min(1180px, 96vw); aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.stage-planet canvas { display: block; }
.stage-planet-fallback {
  position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(circle at 36% 30%, rgba(195,154,80,0.26), transparent 48%),
    radial-gradient(circle at 64% 68%, rgba(160,43,34,0.20), transparent 54%),
    linear-gradient(150deg, #1d3054 0%, #101c31 60%, #070E1A 100%);
  box-shadow: inset -40px -30px 120px rgba(0,0,0,0.66), 0 0 160px rgba(195,154,80,0.12);
  transition: opacity 0.9s var(--ease);
}
.stage-planet.live .stage-planet-fallback { opacity: 0; }

/* Portrait medallions of figures from the atlas */
.stage-faces { position: absolute; inset: 0; z-index: 2; pointer-events: none; }

/* Each face is a link to the person it shows. The wrapper carries the
   position and the drift; the circle is the inner .stage-face-photo, so
   the badge and the name can sit outside the clipped disc. */
.stage-face {
  position: absolute; left: var(--fx); top: var(--fy);
  width: var(--fs); height: var(--fs);
  margin: calc(var(--fs) / -2) 0 0 calc(var(--fs) / -2);
  pointer-events: auto; text-decoration: none;
  opacity: 0;
  animation: faceIn 1.1s var(--ease) var(--fdelay) forwards,
             faceBob var(--fdur) ease-in-out var(--fdelay) infinite alternate;
}
.stage-face-photo {
  position: absolute; inset: 0;
  border-radius: 50%; overflow: hidden;
  background: var(--navy-soft);
  box-shadow: 0 0 0 1.5px rgba(226, 200, 140, 0.7), 0 14px 40px rgba(0,0,0,0.5);
  transition: box-shadow 0.28s var(--ease), transform 0.28s var(--ease);
}
.stage-face img { width: 100%; height: 100%; object-fit: cover; filter: sepia(0.3) contrast(1.03); }
.stage-face-initials {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-family: var(--font-sans); font-weight: 700; font-size: 0.8rem;
  color: var(--brass-light); background: var(--navy);
}

/* A portrait and a portrait you can talk to have to be told apart without
   hovering, so the speech mark is always on. */
.stage-face-badge {
  position: absolute; right: -2px; bottom: -2px;
  display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--brass-light); color: var(--navy-deep);
  border: 2px solid var(--navy-deep);
  box-shadow: 0 3px 10px rgba(0,0,0,0.45);
  transition: transform 0.28s var(--ease), background 0.28s var(--ease);
}

/* Its own dark pill, because the veil that keeps the headline readable
   passes over these and would otherwise wash the name out. */
.stage-face-label {
  position: absolute; top: calc(100% + 11px); left: 50%;
  transform: translate(-50%, 4px);
  padding: 0.28rem 0.66rem; border-radius: 999px;
  font-family: var(--font-sans); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.02em; white-space: nowrap;
  color: var(--cream); background: rgba(9, 15, 28, 0.94);
  border: 1px solid rgba(226, 200, 140, 0.42);
  opacity: 0; pointer-events: none;
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease);
}

.stage-face:hover .stage-face-photo,
.stage-face:focus-visible .stage-face-photo {
  box-shadow: 0 0 0 2.5px var(--brass-light), 0 18px 46px rgba(0,0,0,0.6);
  transform: scale(1.06);
}
.stage-face:hover .stage-face-badge,
.stage-face:focus-visible .stage-face-badge { transform: scale(1.14); }
.stage-face:hover .stage-face-label,
.stage-face:focus-visible .stage-face-label {
  opacity: 1; transform: translate(-50%, 0);
}
.stage-face:focus-visible { outline: none; }
@keyframes faceIn { to { opacity: 1; } }
@keyframes faceBob {
  from { transform: translate3d(0, 7px, 0)  rotate(-1.6deg); }
  to   { transform: translate3d(0, -9px, 0) rotate(1.6deg);  }
}

/* Keeps the copy readable over whatever is behind it */
.stage-veil {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(97deg,
    #070C17 0%, rgba(7,12,23,0.94) 24%, rgba(7,12,23,0.68) 45%,
    rgba(7,12,23,0.16) 68%, transparent 88%);
}

.stage-inner { position: relative; z-index: 4; max-width: 40rem; }

.stage-kicker {
  display: inline-flex; align-items: center; gap: 0.7rem; margin: 0 0 1.6rem;
  padding: 0.45rem 1rem; border-radius: 999px;
  background: rgba(195, 154, 80, 0.1);
  border: 1px solid rgba(195, 154, 80, 0.42);
  font-family: var(--font-sans); font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.15em; text-transform: uppercase; color: var(--brass-light);
}
.stage-kicker i { font-style: normal; opacity: 0.6; }

.stage-title {
  font-size: clamp(2.9rem, 6.4vw, 5.6rem);
  font-weight: 600; letter-spacing: -0.028em; line-height: 1.02;
  color: var(--cream); margin: 0 0 1.5rem;
  text-shadow: 0 2px 30px rgba(0,0,0,0.4);
}
.stage-lede {
  font-size: clamp(1.05rem, 1.35vw, 1.24rem); line-height: 1.62;
  color: rgba(252, 248, 239, 0.8); max-width: 46ch; margin: 0 0 2.2rem;
}

.stage-actions { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-bottom: 2.8rem; }
.btn-outline {
  background: transparent; color: var(--cream);
  box-shadow: inset 0 0 0 1.5px rgba(252, 248, 239, 0.42);
}
.btn-outline:hover {
  background: rgba(252, 248, 239, 0.1); transform: translateY(-2px);
  box-shadow: inset 0 0 0 1.5px var(--brass-light);
}
.btn-outline:hover svg { transform: translateX(4px); }

.stage-facts { display: flex; gap: clamp(1.4rem, 3.4vw, 3rem); margin: 0; flex-wrap: wrap; }
.stage-facts div { display: flex; flex-direction: column; }
.stage-facts dt {
  font-family: var(--font-serif); font-size: 2rem; font-weight: 600;
  color: var(--brass-light); line-height: 1;
}
.stage-facts dd {
  margin: 0.35rem 0 0; font-family: var(--font-sans); font-size: 0.79rem;
  color: rgba(252, 248, 239, 0.66); max-width: 16ch; line-height: 1.4;
}

@media (max-width: 900px) {
  .stage { text-align: center; justify-content: center; }
  .stage-inner { margin-inline: auto; }
  .stage-kicker, .stage-actions, .stage-facts { justify-content: center; }
  .stage-lede { margin-inline: auto; }
  .stage-planet { left: 50%; top: 38%; width: min(760px, 130vw); }
  .stage-veil {
    background: linear-gradient(184deg,
      rgba(7,12,23,0.72) 0%, rgba(7,12,23,0.5) 28%,
      rgba(7,12,23,0.86) 62%, #070C17 100%);
  }
  .stage-face { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .stage-face { animation: faceIn 0.01s forwards; }
}

/* ============================================================
   SPLIT HERO  (retained: still used for section layout helpers)
   ============================================================ */
.split {
  position: relative;
  min-height: 100svh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  overflow: hidden;
}

.split-pane {
  position: relative;
  display: flex; align-items: center;
  padding: clamp(6rem, 11vh, 8.5rem) clamp(1.6rem, 4vw, 4rem) clamp(4.5rem, 9vh, 6rem);
  overflow: hidden;
  min-width: 0;
}

.split-heritage {
  background:
    radial-gradient(900px 600px at 30% 15%, rgba(195,154,80,0.18), transparent 62%),
    linear-gradient(160deg, var(--parchment) 0%, var(--parchment-2) 100%);
}

.split-world {
  background:
    radial-gradient(700px 520px at 70% 42%, rgba(34,51,84,0.75), transparent 70%),
    linear-gradient(200deg, var(--navy) 0%, var(--navy-deep) 100%);
  color: var(--cream);
}

/* Brass hairline between the two halves */
.split-world::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px;
  background: linear-gradient(180deg, transparent, rgba(195,154,80,0.55) 22%, rgba(195,154,80,0.55) 78%, transparent);
  z-index: 4;
}

.hero-grain {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}

.split-inner {
  position: relative; z-index: 3;
  width: 100%; max-width: 34rem; margin-left: auto;
}
.split-world .split-inner { margin-left: 0; margin-right: auto; }

/* ---- The cropped half globe ----
   Deliberately oversized and pushed right so roughly half the
   sphere sits beyond the viewport edge. */
.split-globe {
  position: absolute; z-index: 1;
  top: 50%; left: 34%;
  width: 150%; aspect-ratio: 1 / 1;
  transform: translateY(-50%);
  pointer-events: none;
}
.split-globe canvas { display: block; }

/* Shown until (or instead of) the 3D globe: a lit sphere in the
   same palette, so the pane never looks broken or empty. */
.split-globe-fallback {
  position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, rgba(195,154,80,0.30), transparent 46%),
    radial-gradient(circle at 62% 66%, rgba(160,43,34,0.24), transparent 52%),
    linear-gradient(150deg, #1d3054 0%, #101c31 62%, #0a1220 100%);
  box-shadow: inset -28px -22px 90px rgba(0,0,0,0.6), 0 0 120px rgba(195,154,80,0.14);
  opacity: 1; transition: opacity 0.7s var(--ease);
}
.split-globe.live .split-globe-fallback { opacity: 0; }

/* Keeps the copy legible over whatever the globe is doing behind it */
.split-scrim {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(100deg,
    var(--navy-deep) 0%,
    rgba(13,21,38,0.92) 26%,
    rgba(13,21,38,0.55) 48%,
    rgba(13,21,38,0.08) 72%,
    transparent 100%);
}

/* Dark-pane type. Scoped to the pane rather than a modifier class so
   these always outrank the base .hero-* rules regardless of source
   order. A plain .hero-title--light loses to .hero-title on equal
   specificity, which rendered the title navy-on-navy. */
.split-world .hero-title { color: var(--cream); }
.split-world .hero-lede  { color: rgba(252, 248, 239, 0.82); }
.split-world .eyebrow    { color: var(--brass-light); }
.split-world .eyebrow-line { background: var(--brass-light); }
.split-world .hero-facts dt { color: var(--brass-light); }
.split-world .hero-facts dd { color: rgba(252, 248, 239, 0.7); }

/* Faint postmark watermark, the one heritage flourish the left pane keeps.
   Sits in the empty upper-right of the pane, clear of the copy column
   and well clear of the facts row. */
.split-heritage .postmark {
  position: absolute; z-index: 1;
  top: clamp(6rem, 14vh, 10rem); right: clamp(1rem, 3vw, 3.25rem);
  bottom: auto; left: auto;
  color: var(--crimson); opacity: 0.15;
  transform: rotate(-11deg) scale(1.85);
  transform-origin: top right;
  pointer-events: none;
}
@media (max-width: 1180px) { .split-heritage .postmark { display: none; } }

.eyebrow, .section-eyebrow {
  display: flex; align-items: center; gap: 0.8rem;
  font-family: var(--font-sans); font-size: 0.82rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--crimson);
  margin: 0 0 1.4rem;
}
.eyebrow-line { display: inline-block; width: 46px; height: 2px; background: var(--brass); }

.hero-title {
  /* Sized for a half-width pane, not a full-bleed hero */
  font-size: clamp(2.7rem, 5.2vw, 4.8rem);
  font-weight: 600; letter-spacing: -0.02em; color: var(--navy);
  margin-bottom: 1.2rem;
}
.hero-lede {
  font-size: clamp(1.02rem, 1.25vw, 1.18rem); color: var(--ink-soft);
  max-width: 36ch; margin: 0 0 1.9rem;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-bottom: 2.2rem; }

.btn {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-family: var(--font-sans); font-weight: 600; font-size: 1rem;
  text-decoration: none; padding: 0.9rem 1.5rem; border-radius: 999px;
  cursor: pointer; border: none; transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), background 0.2s var(--ease);
}
.btn svg { transition: transform 0.25s var(--ease); }
.btn-primary { background: var(--navy); color: var(--cream); box-shadow: var(--shadow-md); }
.btn-primary:hover { background: var(--navy-deep); transform: translateY(-2px); }
.btn-primary:hover svg { transform: translateX(4px); }
.btn-ghost { background: transparent; color: var(--navy); box-shadow: inset 0 0 0 1.5px var(--navy); }
.btn-ghost:hover { background: var(--navy); color: var(--cream); transform: translateY(-2px); }
/* For the dark half of the split hero */
.btn-brass { background: var(--brass-light); color: var(--navy-deep); box-shadow: var(--shadow-md); }
.btn-brass:hover { background: #F0DCAA; transform: translateY(-2px); }
.btn-brass:hover svg { transform: rotate(28deg); }

.hero-facts { display: flex; gap: clamp(1.2rem, 3vw, 2.6rem); margin: 0; flex-wrap: wrap; }
.hero-facts div { display: flex; flex-direction: column; }
.hero-facts dt { font-family: var(--font-serif); font-size: 1.75rem; font-weight: 600; color: var(--crimson); }
.hero-facts dd { margin: 0; font-family: var(--font-sans); font-size: 0.82rem; color: var(--ink-faint); letter-spacing: 0.03em; max-width: 15ch; }

.stamp-card {
  position: relative; margin: 0; max-width: 380px;
  background: var(--cream); padding: 14px 14px 10px; border-radius: 6px;
  box-shadow: var(--shadow-lg);
  transform: rotate(-2.5deg);
  transition: transform 0.5s var(--ease);
}
.stamp-card::before {
  content: ""; position: absolute; inset: 6px; border-radius: 4px;
  box-shadow: inset 0 0 0 2px rgba(0,0,0,0.06);
  pointer-events: none;
}
.stamp-card img { border-radius: 3px; }
.stamp-card figcaption {
  font-family: var(--font-sans); font-size: 0.76rem; color: var(--ink-faint);
  text-align: center; padding: 0.7rem 0.4rem 0.2rem; line-height: 1.4;
}
.postmark {
  position: absolute; top: -26px; right: 2px; color: var(--crimson);
  opacity: 0.72; transform: rotate(12deg);
  mix-blend-mode: multiply;
}
.postmark .pm-top, .postmark .pm-bot { font-family: var(--font-sans); font-size: 11px; font-weight: 700; letter-spacing: 0.12em; fill: currentColor; }
.postmark .pm-mid { font-family: var(--font-serif); font-size: 20px; font-weight: 700; fill: currentColor; }

/* Sits in the middle of the heritage pane, not on the divider,
   so it never straddles the light/dark boundary. */
.scroll-hint {
  position: absolute; z-index: 5;
  left: 25%; bottom: 1.6rem; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 0.4rem;
  font-family: var(--font-sans); font-size: 0.72rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-soft); text-decoration: none;
}
.scroll-hint:hover { color: var(--crimson); }
/* On the dark stage the hint needs to be light, not ink */
.stage .scroll-hint { left: 50%; color: rgba(252, 248, 239, 0.72); }
.stage .scroll-hint:hover { color: var(--brass-light); }
.scroll-hint svg { animation: bob 1.8s var(--ease) infinite; }
@keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(6px); } }

/* ---- Split hero, stacked ---- */
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; min-height: 0; }
  .split-pane { min-height: 88svh; padding-block: clamp(5rem, 14vh, 7rem) clamp(3rem, 8vh, 4.5rem); }
  .split-world::before {
    left: 0; right: 0; top: 0; bottom: auto; width: auto; height: 1px;
    background: linear-gradient(90deg, transparent, rgba(195,154,80,0.55) 20%, rgba(195,154,80,0.55) 80%, transparent);
  }
  .split-inner, .split-world .split-inner {
    margin-inline: auto; max-width: 40rem; text-align: center;
  }
  .split-inner .eyebrow,
  .split-inner .hero-actions,
  .split-inner .hero-facts { justify-content: center; }
  .split-inner .hero-lede { margin-inline: auto; }
  /* Centre the sphere behind the copy rather than cropping it at an edge
     that no longer exists once the panes stack. */
  .split-globe { left: 50%; top: 46%; width: 118%; transform: translate(-50%, -50%); }
  .split-scrim {
    background: linear-gradient(180deg,
      rgba(13,21,38,0.86) 0%, rgba(13,21,38,0.62) 40%,
      rgba(13,21,38,0.80) 78%, var(--navy-deep) 100%);
  }
  .scroll-hint { left: 50%; }
}

@media (max-width: 420px) {
  .hero-title { font-size: 2.5rem; }
  .hero-facts { gap: 1.1rem; }
  .hero-facts dt { font-size: 1.45rem; }
}

/* ============================================================
   THESIS
   ============================================================ */
.thesis {
  max-width: 900px; margin: 0 auto; padding: clamp(4.5rem, 9vw, 8rem) var(--gutter);
  text-align: center;
}
.thesis-eyebrow {
  font-family: var(--font-sans); font-size: 0.86rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--crimson);
  margin: 0 0 1.5rem;
}
.thesis-text { font-size: clamp(1.4rem, 3vw, 2.05rem); line-height: 1.42; color: var(--navy); font-weight: 400; margin: 0; }
.thesis-text::first-letter { }

/* ============================================================
   SECTION HEADERS (shared)
   ============================================================ */
.section-eyebrow { justify-content: flex-start; }
.section-title {
  font-size: clamp(2.2rem, 5vw, 3.6rem); color: var(--navy);
  letter-spacing: -0.015em; margin-bottom: 1rem; max-width: 18ch;
}
.section-sub { font-size: 1.12rem; color: var(--ink-soft); max-width: 52ch; margin: 0; }
.section-eyebrow--light { color: var(--brass-light); }
.section-title--light { color: var(--cream); }
.section-sub--light { color: rgba(252, 248, 239, 0.72); }

/* ============================================================
   STORY / TIMELINE
   ============================================================ */
.story { max-width: var(--maxw); margin: 0 auto; padding: clamp(2rem, 5vw, 4rem) var(--gutter) clamp(4rem, 8vw, 7rem); }
.story-head { max-width: 640px; margin: 0 auto clamp(3rem, 6vw, 5rem); text-align: center; }
.story-head .section-eyebrow, .speak-head .section-eyebrow { justify-content: center; }
.story-head .section-title, .speak-head .section-title { margin-left: auto; margin-right: auto; }
.story-head .section-sub, .speak-head .section-sub { margin-left: auto; margin-right: auto; }

.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.timeline::before {
  content: ""; position: absolute; left: 50%; top: 8px; bottom: 8px; width: 2px;
  background: linear-gradient(var(--brass), var(--line));
  transform: translateX(-50%);
}

.chapter {
  position: relative; display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 4rem); align-items: center;
  margin-bottom: clamp(3rem, 6vw, 5.5rem);
}
.chapter::before {
  content: attr(data-year);
  position: absolute; left: 50%; top: -2.4rem; transform: translateX(-50%);
  font-family: var(--font-sans); font-size: 0.76rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--crimson);
  background: var(--parchment); padding: 0.3rem 0.9rem; border-radius: 999px;
  border: 1px solid var(--line); white-space: nowrap; z-index: 2;
}
.chapter::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 15px; height: 15px;
  background: var(--crimson); border: 3px solid var(--parchment);
  border-radius: 50%; transform: translate(-50%, -50%); z-index: 1;
  box-shadow: 0 0 0 4px rgba(160,43,34,0.15);
}

.chapter-media {
  position: relative; border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: var(--shadow-md); aspect-ratio: 4 / 3; background: var(--parchment-2);
}
.chapter-media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.7s var(--ease); }
.chapter:hover .chapter-media img { transform: scale(1.04); }
.media-tag {
  position: absolute; left: 14px; bottom: 14px;
  font-family: var(--font-sans); font-size: 0.74rem; font-weight: 600;
  letter-spacing: 0.06em; color: var(--cream); background: rgba(13,21,38,0.72);
  backdrop-filter: blur(4px); padding: 0.35rem 0.8rem; border-radius: 999px;
}

.chapter-num {
  font-family: var(--font-sans); font-size: 0.78rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass);
  margin: 0 0 0.7rem;
}
.chapter-body h3 { font-size: clamp(1.5rem, 3vw, 2.1rem); color: var(--navy); margin-bottom: 0.9rem; }
.chapter-body p { color: var(--ink-soft); margin: 0; }

/* Alternate sides */
.chapter:nth-child(even) .chapter-media { order: 2; }
.chapter:nth-child(even) .chapter-body { order: 1; text-align: right; }
.chapter:nth-child(even) .chapter-num { }

/* Wide (text-only) chapters center a single column card */
.chapter-body--wide {
  grid-column: 1 / -1; max-width: 620px; margin: 0 auto; text-align: center;
  background: var(--cream); padding: clamp(2rem, 4vw, 3rem); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); border: 1px solid var(--line);
}
.chapter:has(.chapter-body--wide) { grid-template-columns: 1fr; }
.chapter:has(.chapter-body--wide) .chapter-num { color: var(--crimson); }

/* Even-numbered chapters right-align their text, because the image sits on
   the left and the column should read towards it. A wide chapter has no
   image and is centred, but `.chapter:nth-child(even) .chapter-body` beats
   `.chapter-body--wide` on specificity, so a wide chapter in an even slot
   came out right-aligned beside its centred neighbours. Chapter VI is the
   first even one, which is why this only appeared when it lost its photo. */
.chapter:nth-child(even) .chapter-body--wide { text-align: center; }

/* A two-column chapter puts the node dot in the gutter between the image
   and the text, which is where the spine runs. A wide chapter has no
   gutter: its card sits on the spine, so the same dot lands in the middle
   of the paragraph. The year pill directly above the card is already the
   marker on the spine here, so the dot is redundant as well as in the way.
   It comes back below 720px, where the spine moves into the left margin
   and the dot is clear of the text again. */
.chapter:has(.chapter-body--wide)::after { display: none; }

.chapter-link {
  display: inline-flex; align-items: center; gap: 0.45rem; margin-top: 1.3rem;
  font-family: var(--font-sans); font-weight: 600; font-size: 0.95rem;
  color: var(--crimson); text-decoration: none;
}
.chapter-link svg { transition: transform 0.25s var(--ease); }
.chapter-link:hover svg { transform: translateX(4px); }

/* ============================================================
   SPEAK WITH ALBERT
   ============================================================ */
.speak {
  position: relative;
  background:
    radial-gradient(900px 500px at 15% 10%, rgba(195,154,80,0.14), transparent 55%),
    linear-gradient(165deg, var(--navy) 0%, var(--navy-deep) 100%);
  padding: clamp(4.5rem, 8vw, 7.5rem) var(--gutter);
  color: var(--cream);
}
.speak-head { max-width: 640px; margin: 0 auto clamp(2.5rem, 5vw, 3.5rem); text-align: center; }

/* ---- Speak layout: portrait beside the conversation ---- */
.speak-body {
  max-width: 1010px; margin: 0 auto;
  display: grid; grid-template-columns: 210px 1fr; gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}

/* ---- Albert's animated portrait ----
   Every layer is the same archival photograph. The blink is that
   photo's own brow-skin drawn briefly over the eye; the speech
   motion is that photo's own jaw, masked and nudged. Nothing is
   redrawn, recoloured, or generated. */
.albert-stage { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 0.7rem; }

/* A mounted archival print, shown whole. The frame matches the
   photograph's own 400x680 aspect exactly, so every overlay
   percentage below maps 1:1 onto the image. Cropping it was what
   put the blink above his eyes. */
.albert-frame {
  position: relative; width: 100%; aspect-ratio: 400 / 680;
  border-radius: 10px;
  overflow: hidden; isolation: isolate;
  background: #EFEAE0;
  box-shadow: 0 0 0 1px rgba(195,154,80,0.5), var(--shadow-lg);
}
.albert-frame img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center center;
  filter: sepia(0.18) contrast(1.04);
}

/* Outer span = the fixed window (carries the mask).
   Inner <i>  = the same photograph, free to move inside it. */
.albert-jaw,
.albert-lid { position: absolute; inset: 0; pointer-events: none; }
.albert-jaw > i,
.albert-lid > i {
  position: absolute; inset: 0; display: block;
  background-image: url("assets/portrait-1882.jpg");
  background-size: 100% 100%;   /* frame aspect matches the photo exactly */
  filter: sepia(0.18) contrast(1.04);
}

/* Calibration markers, only with ?debug=face in the URL. */
.face-marker {
  position: absolute; z-index: 9; width: 10px; height: 10px;
  margin: -5px 0 0 -5px; border-radius: 50%;
  background: #29F; box-shadow: 0 0 0 1.5px #fff;
  pointer-events: none;
}
.face-marker::after {
  content: attr(data-label); position: absolute; left: 12px; top: -4px;
  font: 700 9px/1 var(--font-sans); color: #29F;
  background: #fff; padding: 2px 4px; border-radius: 3px; white-space: nowrap;
}
.albert-frame img {
  transition: transform 0.5s var(--ease);
  will-change: transform;
}

/* Shared background copy for the overlay layers */
.albert-jaw, .albert-lid {
  background-image: url("assets/portrait-1882.jpg");
  background-size: cover; background-position: center 22%;
  pointer-events: none;
}

/* Jaw: the mouth region, softly masked, nudged down while speaking.
   Coordinates are fractions of the photograph itself (see FACE below
   in script.js, which is the single source of truth for them). */
.albert-jaw {
  -webkit-mask-image: radial-gradient(ellipse 11% 4.6% at 49% 50.2%, #000 42%, transparent 78%);
          mask-image: radial-gradient(ellipse 11% 4.6% at 49% 50.2%, #000 42%, transparent 78%);
  opacity: 0;
}
.albert-jaw > i { transform-origin: 49% 42%; }
.albert-stage.speaking .albert-jaw { opacity: 1; }
.albert-stage.speaking .albert-jaw > i {
  animation: albertSpeak 300ms ease-in-out infinite alternate;
}
/* The chin drops inside a fixed mouth window: the jaw moves, not the frame. */
@keyframes albertSpeak {
  from { transform: translateY(0)    scaleY(1);     }
  to   { transform: translateY(0.9%) scaleY(1.05);  }
}

/* Lids: brow skin from just above each eye, flashed over it */
.albert-lid { opacity: 0; transition: opacity 70ms linear; }
/* Shifting the photo DOWN inside a fixed eye-shaped window brings the
   brow skin from just above the eye across it. That is the blink. */
.albert-lid > i { transform: translateY(2.9%); }
.albert-lid--l {
  -webkit-mask-image: radial-gradient(ellipse 6% 2% at 44.2% 36.3%, #000 50%, transparent 82%);
          mask-image: radial-gradient(ellipse 6% 2% at 44.2% 36.3%, #000 50%, transparent 82%);
}
.albert-lid--r {
  -webkit-mask-image: radial-gradient(ellipse 6% 2% at 58.5% 36%, #000 50%, transparent 82%);
          mask-image: radial-gradient(ellipse 6% 2% at 58.5% 36%, #000 50%, transparent 82%);
}
.albert-stage.blink .albert-lid { opacity: 1; }

/* Warm glow while he is talking */
.albert-halo {
  position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 0 0 rgba(195,154,80,0);
  transition: box-shadow 0.4s var(--ease);
}
.albert-stage.speaking .albert-halo {
  box-shadow: inset 0 0 46px 6px rgba(195,154,80,0.28);
}

/* ---- Press-him hotspots ----
   Invisible until hovered or focused, so the portrait reads as a
   photograph first and an interface second. */
.albert-spot {
  position: absolute; z-index: 6;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  transform: translate(-50%, -50%);
  padding: 0; cursor: pointer;
  background: transparent;
  border: 1.5px solid transparent; border-radius: 14px;
  /* The label is for screen readers and the tooltip, not for display */
  font-size: 0; color: transparent;
  transition: background 0.22s var(--ease), border-color 0.22s var(--ease),
              box-shadow 0.22s var(--ease);
}
.albert-spot:hover,
.albert-spot:focus-visible {
  background: rgba(195, 154, 80, 0.16);
  border-color: rgba(226, 200, 140, 0.85);
  box-shadow: 0 0 22px rgba(195, 154, 80, 0.35);
  outline: none;
}
/* Tooltip drawn from data-hint */
.albert-spot::after {
  content: attr(data-hint);
  position: absolute; left: 50%; bottom: calc(100% + 8px);
  transform: translateX(-50%);
  padding: 0.3rem 0.55rem; border-radius: 7px;
  background: rgba(13, 21, 38, 0.94); color: var(--cream);
  border: 1px solid rgba(195, 154, 80, 0.45);
  font: 600 0.68rem/1.2 var(--font-sans); letter-spacing: 0.02em;
  white-space: nowrap; opacity: 0; pointer-events: none;
  transition: opacity 0.2s var(--ease);
}
.albert-spot:hover::after,
.albert-spot:focus-visible::after { opacity: 1; }

/* A single slow pulse on the coat, so visitors know he can be pressed */
.albert-stage .albert-spot[data-topic="uniform"]:nth-of-type(3)::before {
  content: ""; position: absolute; inset: 0; border-radius: 14px;
  border: 1.5px solid rgba(226, 200, 140, 0.5);
  animation: spotHint 3.4s var(--ease) infinite;
  pointer-events: none;
}
@keyframes spotHint {
  0%, 72%, 100% { opacity: 0; transform: scale(0.96); }
  84%           { opacity: 1; transform: scale(1);    }
}
.albert-stage:hover .albert-spot::before { animation: none; opacity: 0; }

.albert-prompt-hint {
  margin: 0; font-family: var(--font-sans); font-size: 0.68rem;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: rgba(252, 248, 239, 0.6); text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .albert-stage .albert-spot::before { animation: none; }
}

.albert-stage figcaption {
  font-family: var(--font-sans); font-size: 0.72rem; letter-spacing: 0.06em;
  color: rgba(252,248,239,0.62); text-align: center;
}

.albert-motion {
  display: inline-flex; align-items: center; gap: 0.42rem; cursor: pointer;
  font-family: var(--font-sans); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.04em;
  padding: 0.4rem 0.7rem; min-height: 32px; border-radius: 999px;
  color: rgba(252,248,239,0.72); background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.14);
  transition: all 0.2s var(--ease);
}
.albert-motion:hover { background: rgba(255,255,255,0.14); color: #fff; }
.albert-motion-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--ink-faint);
}
.albert-motion[aria-pressed="true"] { color: var(--brass-light); border-color: rgba(195,154,80,0.45); }
.albert-motion[aria-pressed="true"] .albert-motion-dot {
  background: #6FCF97; box-shadow: 0 0 0 3px rgba(111,207,151,0.22);
}

@media (max-width: 860px) {
  .speak-body { grid-template-columns: 1fr; justify-items: center; }
  .albert-stage { width: 170px; }
}

@media (prefers-reduced-motion: reduce) {
  .albert-stage.speaking .albert-jaw { animation: none; opacity: 0; }
  .albert-frame img { transition: none; }
}

.chat {
  max-width: 760px; margin: 0 auto; width: 100%; min-width: 0;
  background: var(--cream); color: var(--ink);
  border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  max-height: 640px;
}
.chat-topbar {
  display: flex; align-items: center; gap: 0.85rem;
  padding: 0.9rem 1.2rem; background: var(--navy); color: var(--cream);
  border-bottom: 3px solid var(--brass);
}
.chat-avatar { width: 46px; height: 46px; border-radius: 50%; overflow: hidden; flex-shrink: 0; box-shadow: 0 0 0 2px var(--brass); background: var(--navy-soft); }
.chat-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; filter: sepia(0.15); }
.chat-who { display: flex; flex-direction: column; line-height: 1.2; font-family: var(--font-sans); }
.chat-who strong { font-size: 1.02rem; }
.chat-who span { font-size: 0.78rem; color: rgba(252,248,239,0.7); display: flex; align-items: center; gap: 0.4rem; margin-top: 2px; }
.chat-who .dot { width: 7px; height: 7px; border-radius: 50%; background: #6FCF97; box-shadow: 0 0 0 3px rgba(111,207,151,0.25); }
/* Live / offline badge for the Claude-backed conversation */
.chat-mode {
  margin-left: auto; font-family: var(--font-sans); font-size: 0.66rem;
  font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  padding: 0.3rem 0.6rem; border-radius: 999px; cursor: default;
  border: 1px solid transparent; white-space: nowrap;
}
.chat-mode--live    { color: #BFF0D2; background: rgba(111,207,151,0.16); border-color: rgba(111,207,151,0.45); }
.chat-mode--offline { color: rgba(252,248,239,0.62); background: rgba(255,255,255,0.07); border-color: rgba(255,255,255,0.14); }
.chat-mode--checking{ color: var(--brass-light); background: rgba(195,154,80,0.16); border-color: rgba(195,154,80,0.4); }

/* Voice toggle: Albert reads his answers aloud */
.chat-voice {
  margin-left: 0.5rem; display: inline-flex; align-items: center; gap: 0.4rem;
  font-family: var(--font-sans); font-size: 0.78rem; font-weight: 600;
  color: rgba(252,248,239,0.8); background: rgba(255,255,255,0.08);
  border: 1px solid transparent; padding: 0.45rem 0.75rem; border-radius: 999px;
  cursor: pointer; transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.chat-voice:hover { background: rgba(255,255,255,0.16); color: #fff; }
.chat-voice .wave-1, .chat-voice .wave-2 { opacity: 0.35; transition: opacity 0.2s var(--ease); }
.chat-voice.on {
  background: rgba(195,154,80,0.2); color: var(--brass-light);
  border-color: rgba(195,154,80,0.5);
}
.chat-voice.on .wave-1 { opacity: 1; animation: waveOn 1.4s ease-in-out infinite; }
.chat-voice.on .wave-2 { opacity: 1; animation: waveOn 1.4s ease-in-out 0.25s infinite; }
@keyframes waveOn { 0%,100% { opacity: 0.35; } 50% { opacity: 1; } }

/* Microphone: the visitor asks out loud. Scoped to .chat-input so it
   outranks the filled crimson `.chat-input button` send styling; the
   mic is the secondary action and should not read as a second Send. */
.chat-input .chat-mic {
  display: grid; place-items: center; width: 48px; height: 48px; flex-shrink: 0;
  background: transparent; color: var(--navy);
  border: 1.5px solid var(--line); border-radius: 50%; cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.chat-input .chat-mic:hover {
  border-color: var(--navy); background: var(--parchment); transform: none;
}
.chat-input .chat-mic.on {
  background: var(--crimson); border-color: var(--crimson); color: #fff;
  animation: micPulse 1.3s ease-in-out infinite;
}
@keyframes micPulse {
  0%,100% { box-shadow: 0 0 0 0 rgba(160,43,34,0.45); }
  60%     { box-shadow: 0 0 0 12px rgba(160,43,34,0); }
}

.chat-reset {
  margin-left: 0.5rem; display: inline-flex; align-items: center; gap: 0.4rem;
  font-family: var(--font-sans); font-size: 0.78rem; font-weight: 600;
  color: rgba(252,248,239,0.8); background: rgba(255,255,255,0.08);
  border: none; padding: 0.45rem 0.75rem; border-radius: 999px; cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.chat-reset:hover { background: rgba(255,255,255,0.16); color: #fff; }

.chat-log {
  flex: 1; overflow-y: auto; padding: 1.4rem 1.2rem;
  display: flex; flex-direction: column; gap: 1rem;
  background:
    linear-gradient(var(--cream), var(--cream)) padding-box,
    repeating-linear-gradient(0deg, transparent, transparent 31px, rgba(160,43,34,0.04) 31px, rgba(160,43,34,0.04) 32px);
  scroll-behavior: smooth;
}
.msg { display: flex; gap: 0.7rem; max-width: 85%; animation: msgIn 0.4s var(--ease) both; }
@keyframes msgIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.msg-avatar { width: 34px; height: 34px; border-radius: 50%; overflow: hidden; flex-shrink: 0; box-shadow: 0 0 0 1.5px var(--brass); }
.msg-avatar--mark {
  display: grid; place-items: center; overflow: visible;
  background: var(--navy); color: var(--brass-light);
  font-family: var(--font-sans); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.04em;
}
.msg-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; filter: sepia(0.15); }
.msg-bubble { padding: 0.8rem 1.05rem; border-radius: 16px; font-size: 1.02rem; line-height: 1.55; }
.msg-bubble p { margin: 0; }
.msg-bubble p + p { margin-top: 0.7em; }

.msg.albert .msg-bubble { background: var(--parchment); color: var(--ink); border-top-left-radius: 4px; box-shadow: var(--shadow-sm); }
.msg.albert .msg-bubble em { color: var(--ink-faint); font-style: italic; }
.msg.user { margin-left: auto; flex-direction: row-reverse; }
.msg.user .msg-bubble { background: var(--navy); color: var(--cream); border-top-right-radius: 4px; }
.msg.user .msg-avatar { background: var(--crimson); box-shadow: 0 0 0 1.5px var(--crimson-deep); display: grid; place-items: center; color: #fff; }

/* typing indicator */
.typing { display: inline-flex; gap: 4px; align-items: center; padding: 2px 0; }
.typing span { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-faint); opacity: 0.5; animation: typing 1.2s infinite; }
.typing span:nth-child(2) { animation-delay: 0.2s; }
.typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing { 0%,60%,100% { transform: translateY(0); opacity: 0.4; } 30% { transform: translateY(-5px); opacity: 1; } }

.chat-suggests {
  display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.9rem 1.2rem 0.2rem;
  border-top: 1px solid var(--line);
}
.suggest {
  font-family: var(--font-sans); font-size: 0.85rem; font-weight: 500;
  color: var(--navy); background: transparent; border: 1.5px solid var(--line);
  padding: 0.5rem 0.9rem; border-radius: 999px; cursor: pointer;
  transition: all 0.2s var(--ease);
}
.suggest:hover { border-color: var(--crimson); color: var(--crimson); background: rgba(160,43,34,0.05); transform: translateY(-1px); }

.chat-input { display: flex; gap: 0.6rem; padding: 0.9rem 1.2rem 1.2rem; }
.chat-input input {
  flex: 1; font-family: var(--font-serif); font-size: 1.02rem;
  padding: 0.8rem 1.1rem; border: 1.5px solid var(--line); border-radius: 999px;
  background: #fff; color: var(--ink); transition: border-color 0.2s var(--ease);
}
.chat-input input:focus { outline: none; border-color: var(--crimson); box-shadow: 0 0 0 3px rgba(160,43,34,0.12); }
.chat-input button {
  display: grid; place-items: center; width: 48px; height: 48px; flex-shrink: 0;
  background: var(--crimson); color: #fff; border: none; border-radius: 50%;
  cursor: pointer; transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
.chat-input button:hover { background: var(--crimson-deep); transform: scale(1.06); }
.chat-input.busy input { opacity: 0.6; }
.chat-input.busy button { background: var(--ink-faint); cursor: progress; transform: none; }
.chat-input button:disabled:hover { background: var(--ink-faint); transform: none; }

/* ---- The record: facts and credits, replacing the old gallery ---- */
.record-grid {
  max-width: var(--maxw); margin: 0 auto;
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4.5rem);
}
.record-col h3 {
  font-size: 1.02rem; font-family: var(--font-sans); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--crimson);
  margin: 0 0 1rem;
}
.record-col h3 + ul { margin-bottom: 2.2rem; }

.record-list { margin: 0; }
.record-list > div {
  display: grid; grid-template-columns: 8.5rem 1fr; gap: 1rem;
  padding: 0.7rem 0; border-top: 1px solid var(--line);
}
.record-list > div:last-child { border-bottom: 1px solid var(--line); }
.record-list dt {
  font-family: var(--font-sans); font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint);
  padding-top: 0.2rem;
}
.record-list dd { margin: 0; font-size: 1rem; line-height: 1.5; }

.credit-list { list-style: none; margin: 0; padding: 0; }
.credit-list li {
  padding: 0.6rem 0; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 2px;
}
.credit-list strong { font-weight: 600; font-size: 0.99rem; }
.credit-list span {
  font-family: var(--font-sans); font-size: 0.79rem; color: var(--ink-faint);
}
.record-note {
  margin: 1.2rem 0 0; font-family: var(--font-sans);
  font-size: 0.76rem; line-height: 1.55; color: var(--ink-faint);
}

/* Story images are the lightbox entry point now */
.chapter-media[data-full] { cursor: zoom-in; }
.chapter-media[data-full]:focus-visible {
  outline: 2px solid var(--crimson); outline-offset: 3px;
}

@media (max-width: 860px) {
  .record-grid { grid-template-columns: 1fr; }
  .record-list > div { grid-template-columns: 1fr; gap: 0.15rem; }
}

/* ============================================================
   DRIFTING MAIL  -  ambient background motion
   Letters rising slowly through the dark sections. Composited
   on the GPU (transform/opacity only) and clipped by the host.
   ============================================================ */
.drift {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden; pointer-events: none;
}
.drift-item {
  position: absolute; top: 50%; left: var(--x);
  width: var(--size); height: auto;
  color: var(--brass);
  opacity: 0;
  will-change: transform, opacity;
  animation: driftUp var(--dur) linear var(--delay) infinite;
}
.drift-item svg { display: block; width: 100%; height: auto; }

@keyframes driftUp {
  0%   { transform: translate3d(0, 62vh, 0) rotate(0deg); opacity: 0; }
  14%  { opacity: var(--fade); }
  86%  { opacity: var(--fade); }
  100% { transform: translate3d(var(--drift), -62vh, 0) rotate(var(--spin)); opacity: 0; }
}

/* The hero's paper grain, breathing very slowly */
.hero-grain { animation: grainShift 26s ease-in-out infinite alternate; }
@keyframes grainShift {
  from { transform: translate3d(0, 0, 0)      scale(1);    opacity: 0.5;  }
  to   { transform: translate3d(-14px, 9px, 0) scale(1.05); opacity: 0.34; }
}

@media (prefers-reduced-motion: reduce) {
  .drift { display: none; }
  .hero-grain { animation: none; }
}

/* ============================================================
   ABOUT THIS PROJECT  (the Saylavy panel)
   ============================================================ */
.about-demo {
  position: relative; overflow: hidden;
  background:
    radial-gradient(800px 480px at 82% 15%, rgba(195,154,80,0.15), transparent 60%),
    linear-gradient(170deg, var(--navy-deep) 0%, var(--navy) 100%);
  color: var(--cream);
  padding: clamp(4rem, 8vw, 6.5rem) var(--gutter);
  border-top: 1px solid rgba(195,154,80,0.28);
}
.about-inner { position: relative; z-index: 1; max-width: var(--maxw); margin: 0 auto; }
.about-lede {
  max-width: 60ch; margin: 0 0 2.6rem;
  font-size: clamp(1.05rem, 1.4vw, 1.22rem); color: rgba(252,248,239,0.82);
}
.about-lede strong { color: var(--brass-light); font-weight: 600; }

.about-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(1.2rem, 2.5vw, 2rem);
}
.about-card {
  padding: 1.4rem 1.5rem; border-radius: var(--radius);
  background: rgba(255,255,255,0.055);
  border: 1px solid rgba(195,154,80,0.24);
}
.about-card h3 {
  margin: 0 0 0.6rem; font-size: 1.08rem; font-weight: 600; color: var(--brass-light);
}
.about-card p { margin: 0; font-size: 0.97rem; line-height: 1.6; color: rgba(252,248,239,0.78); }
.about-card a { color: var(--brass-light); text-underline-offset: 3px; }

.about-note {
  max-width: 62ch; margin: 2.4rem 0 0;
  font-family: var(--font-sans); font-size: 0.88rem; line-height: 1.65;
  color: rgba(252,248,239,0.66);
}

.speak-note {
  max-width: 760px; margin: 1.4rem auto 0; text-align: center;
  font-family: var(--font-sans); font-size: 0.82rem; color: rgba(252,248,239,0.55);
}

/* ============================================================
   LEGACY
   ============================================================ */
.legacy { max-width: var(--maxw); margin: 0 auto; padding: clamp(4.5rem, 8vw, 7.5rem) var(--gutter); }
.legacy .story-head { text-align: center; }

.legacy-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1.5rem;
  margin-bottom: clamp(3rem, 6vw, 4.5rem);
}
.legacy-card {
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 2rem 1.8rem; box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.legacy-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); }
.legacy-icon {
  display: grid; place-items: center; width: 54px; height: 54px; border-radius: 14px;
  background: var(--navy); color: var(--brass-light); margin-bottom: 1.2rem;
}
.legacy-year { font-family: var(--font-sans); font-weight: 700; font-size: 0.82rem; letter-spacing: 0.14em; color: var(--crimson); margin: 0 0 0.5rem; }
.legacy-card h3 { font-size: 1.4rem; color: var(--navy); margin-bottom: 0.7rem; }
.legacy-card p { font-size: 1rem; color: var(--ink-soft); margin: 0; }

.plaque-quote {
  position: relative; max-width: 820px; margin: 0 auto;
  background: linear-gradient(160deg, var(--navy) 0%, var(--navy-deep) 100%);
  color: var(--cream); padding: clamp(2.5rem, 5vw, 3.8rem);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  border: 1px solid rgba(195,154,80,0.3);
}
.plaque-crest {
  display: grid; place-items: center; width: 56px; height: 56px; margin: 0 auto 1.5rem;
  border-radius: 50%; color: var(--brass-light); border: 1.5px solid rgba(195,154,80,0.5);
}
.plaque-quote blockquote { margin: 0; font-size: clamp(1.05rem, 2vw, 1.2rem); line-height: 1.6; }
.plaque-quote blockquote p { margin: 0 0 1.1rem; color: rgba(252,248,239,0.9); }
.plaque-quote blockquote p:first-child { font-size: 1.15em; color: var(--cream); }
.plaque-quote figcaption {
  margin-top: 1.5rem; padding-top: 1.3rem; border-top: 1px solid rgba(195,154,80,0.28);
  font-family: var(--font-sans); font-size: 0.84rem; color: var(--brass-light); text-align: center;
}

/* ============================================================
   GALLERY
   ============================================================ */
.gallery { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter) clamp(4.5rem, 8vw, 7.5rem); }
.gallery .story-head { text-align: center; }
.gallery-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; }
.gallery-item {
  margin: 0; position: relative; border-radius: var(--radius); overflow: hidden;
  cursor: pointer; box-shadow: var(--shadow-sm); background: var(--parchment-2);
  aspect-ratio: 3 / 4;
}
.gallery-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.gallery-item:hover img { transform: scale(1.06); }
.gallery-item figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 1.4rem 1rem 0.9rem; color: #fff;
  font-family: var(--font-sans); font-size: 0.9rem; font-weight: 600;
  background: linear-gradient(transparent, rgba(13,21,38,0.85));
  display: flex; flex-direction: column;
  transform: translateY(0); transition: opacity 0.3s var(--ease);
}
.gallery-item figcaption span { font-weight: 400; font-size: 0.74rem; opacity: 0.78; margin-top: 2px; }

/* Lightbox */
.lightbox {
  position: fixed; inset: 0; z-index: 300; display: none;
  place-items: center; padding: 4vw;
  background: rgba(13,21,38,0.94); backdrop-filter: blur(6px);
}
.lightbox.open { display: grid; animation: fade 0.3s var(--ease); }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.lightbox figure { margin: 0; max-width: 92vw; max-height: 88vh; display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.lightbox img { max-width: 100%; max-height: 78vh; border-radius: 8px; box-shadow: var(--shadow-lg); object-fit: contain; }
.lightbox figcaption { font-family: var(--font-sans); font-size: 0.92rem; color: var(--brass-light); text-align: center; max-width: 60ch; }
.lightbox-close {
  position: absolute; top: 1.4rem; right: 1.6rem; width: 46px; height: 46px;
  display: grid; place-items: center; border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,0.1); color: #fff; border: none;
  transition: background 0.2s var(--ease);
}
.lightbox-close:hover { background: rgba(255,255,255,0.22); }

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer { background: var(--navy-deep); color: rgba(252,248,239,0.8); padding: clamp(3.5rem, 6vw, 5rem) var(--gutter) 2rem; }
.footer-inner {
  max-width: var(--maxw); margin: 0 auto;
  display: grid; grid-template-columns: 1.6fr 1fr 1.4fr; gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: 2.5rem; border-bottom: 1px solid rgba(255,255,255,0.1);
}
.footer-name { font-family: var(--font-serif); font-size: 1.7rem; font-weight: 600; color: var(--cream); margin: 0 0 0.3rem; }
.footer-dates { font-family: var(--font-sans); font-size: 0.86rem; color: var(--brass-light); margin: 0 0 1.1rem; letter-spacing: 0.02em; }
.footer-tribute { font-size: 0.98rem; line-height: 1.6; margin: 0; color: rgba(252,248,239,0.65); max-width: 42ch; }
.footer-col h4 { font-family: var(--font-sans); font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass); margin: 0 0 1rem; }
.footer-col a { display: block; text-decoration: none; color: rgba(252,248,239,0.8); font-family: var(--font-sans); font-size: 0.95rem; padding: 0.28rem 0; transition: color 0.2s var(--ease); }
.footer-col a:hover { color: var(--cream); }
.footer-col p { font-size: 0.9rem; line-height: 1.55; margin: 0 0 0.8rem; color: rgba(252,248,239,0.6); }
.footer-credit { margin-top: 1rem !important; font-size: 0.8rem !important; color: rgba(252,248,239,0.6) !important; }
.footer-base {
  max-width: var(--maxw); margin: 0 auto; padding-top: 1.6rem;
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  font-family: var(--font-sans); font-size: 0.82rem; color: rgba(252,248,239,0.5);
}
.footer-mark { color: var(--brass-light); }

/* ============================================================
   REVEAL ANIMATIONS
   ============================================================ */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
.reveal.in { opacity: 1; transform: none; }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 960px) {
  /* The nav collapses into a panel rather than vanishing. Hiding it
     outright left phone visitors with no way to reach any section. */
  .nav-toggle { display: inline-grid; }
  .site-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 0; padding: 0.4rem var(--gutter) 1rem;
    background: rgba(246, 238, 221, 0.98);
    backdrop-filter: saturate(1.3) blur(12px);
    -webkit-backdrop-filter: saturate(1.3) blur(12px);
    box-shadow: 0 14px 30px rgba(20, 15, 6, 0.16);
    border-bottom: 1px solid var(--line);
    font-size: 1.05rem;
    visibility: hidden; opacity: 0; transform: translateY(-10px);
    transition: opacity 0.24s var(--ease), transform 0.24s var(--ease), visibility 0.24s;
  }
  .site-nav a {
    padding: 0.85rem 0; border-bottom: 1px solid rgba(222, 208, 178, 0.55);
    color: var(--navy);
  }
  .site-nav a:last-of-type { border-bottom: none; }
  .site-nav a::after { display: none; }

  .nav-cta { display: none; }
  .site-nav .nav-cta-mobile {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
    margin-top: 0.9rem; padding: 0.8rem 1.05rem; border-radius: 999px;
    background: var(--crimson); color: #fff; font-family: var(--font-sans);
    font-weight: 600; font-size: 0.95rem; text-decoration: none; border-bottom: none;
  }

  .site-header.nav-open .site-nav {
    visibility: visible; opacity: 1; transform: none;
  }
  /* Hero copy stays left-aligned here: the split is still two columns
     until 860px, and centring it mid-column reads as a mistake. */
  .legacy-grid { grid-template-columns: 1fr; }
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  .footer-inner { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  body { font-size: 17px; }
  .timeline::before { left: 22px; }
  .chapter { grid-template-columns: 1fr; gap: 1.2rem; padding-left: 3rem; }
  .chapter::before { left: 22px; transform: none; }
  .chapter::after { left: 22px; top: 8px; transform: translate(-50%, 0); }
  .chapter:nth-child(even) .chapter-media { order: 0; }
  .chapter:nth-child(even) .chapter-body { order: 0; text-align: left; }
  .chapter-body--wide { text-align: left; margin: 0; max-width: none; }
  .chapter:has(.chapter-body--wide) { padding-left: 3rem; }
  /* The spine is in the left margin at this width, so the dot is clear of
     the card and earns its place back. */
  .chapter:has(.chapter-body--wide)::after { display: block; }
  .chat { max-height: 78svh; }
  .msg { max-width: 92%; }
  .nav-cta { display: none; }
}

@media (max-width: 480px) {
  .gallery-grid { grid-template-columns: 1fr; }
  .hero-facts { gap: 1.2rem; }
  .btn { width: 100%; justify-content: center; }
}

/* ============================================================
   MOTION PREFERENCES
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
  .reveal { opacity: 1; transform: none; }
  .scroll-hint svg { animation: none; }
}

/* ============================================================
   INTERACTION LAYER
   ------------------------------------------------------------
   Every control on the site answers a press the same way: it
   compresses, it takes a ripple from where the pointer landed,
   and the filled ones catch a sweep of light on hover.

   This block sits at the END of the stylesheet on purpose. The
   :active rules tie on specificity with the :hover rules above
   them, and a tie is decided by source order. Move this up and
   nothing presses.
   ============================================================ */

/* ---------- The surface a ripple needs ---------- */

.btn,
.nav-cta,
.nav-toggle,
.suggest,
.chat-input button[type="submit"],
.chat-mic,
.atlas-ctrl,
.atlas-chip,
.atlas-mode,
.atlas-ask,
.atlas-voices-hint,
.atlas-item,
.atlas-card-close,
.voice-chip,
.voice-send,
.voice-sound,
.voice-close,
.lightbox-close {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  -webkit-tap-highlight-color: transparent;
}

.ripple {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  /* currentColor means the ripple is always the button's own text
     colour: white on crimson, navy on brass, brass on navy. One rule,
     right everywhere, nothing to keep in sync. */
  background: currentColor;
  /* On the dark panels currentColor is itself a translucent cream, so the
     ink lands at roughly two thirds of this. 0.34 is the value at which it
     reads on navy without looking like a stamp on brass. */
  opacity: 0.34;
  transform: scale(0);
  animation: ripple-out 620ms cubic-bezier(0.16, 0.84, 0.44, 1) forwards;
}
@keyframes ripple-out {
  to { transform: scale(1); opacity: 0; }
}

/* Keep the label above the ink.
   :not(.ripple) is load-bearing. Without it this rule also matches the ink
   span, and `.btn > *` outspecifies `.ripple`, so the ink loses its
   position:absolute, rejoins the flow and inflates the button to the size
   of the circle. */
.btn > *:not(.ripple),
.nav-cta > *:not(.ripple),
.atlas-ask > *:not(.ripple),
.atlas-voices-hint > *:not(.ripple),
.atlas-item > *:not(.ripple),
.atlas-chip > *:not(.ripple),
.suggest > *:not(.ripple) { position: relative; z-index: 1; }

/* ---------- The press ---------- */
/* Scale rather than translate, so the control reads as being pushed
   into the page instead of sliding down it. Fast on the way in, eased
   on the way out: that asymmetry is most of what makes it feel physical. */

.btn:active,
.nav-cta:active,
.atlas-ask:active,
.atlas-voices-hint:active,
.chat-input button[type="submit"]:active,
.voice-send:active,
.suggest:active,
.atlas-mode:active,
.atlas-chip:active,
.voice-chip:active,
.atlas-ctrl:active,
.chat-mic:active,
.nav-toggle:active,
.voice-sound:active,
.voice-close:active,
.atlas-card-close:active,
.lightbox-close:active {
  transform: scale(0.955);
  transition-duration: 80ms;
}

/* The big ones have further to fall, so they compress less. A 4 per cent
   squeeze on a full-width button looks like a glitch; on a 32px circle it
   is barely there. */
.btn:active,
.atlas-ask:active,
.atlas-voices-hint:active {
  transform: scale(0.978);
}

.atlas-item:active { transform: scale(0.99); transition-duration: 80ms; }

/* ---------- The sweep ---------- */
/* Filled buttons only. A band of light crosses the face on hover, once,
   and does not loop: it should read as the surface catching the light,
   not as something demanding attention. */

.btn-primary::after,
.btn-brass::after,
.nav-cta::after,
.atlas-ask::after,
.chat-input button[type="submit"]::after,
.voice-send::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 32%,
    rgba(255, 255, 255, 0.30) 48%,
    rgba(255, 255, 255, 0.30) 52%,
    transparent 68%
  );
  transform: translateX(-130%);
  transition: transform 0.75s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.btn-primary:hover::after,
.btn-brass:hover::after,
.nav-cta:hover::after,
.atlas-ask:hover::after,
.chat-input button[type="submit"]:hover::after,
.voice-send:hover::after {
  transform: translateX(130%);
}
/* Brass is already bright; a white sweep on it just looks washed out. */
.btn-brass::after {
  background: linear-gradient(
    100deg,
    transparent 32%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 68%
  );
}

/* ---------- Hover depth ---------- */
/* The existing rules lift these by 1 to 2px. Adding the shadow bloom is
   what turns the lift into something the eye reads as height. */

.btn-primary:hover { box-shadow: 0 16px 34px rgba(13, 21, 38, 0.32); }
.btn-brass:hover   { box-shadow: 0 16px 34px rgba(195, 154, 80, 0.34); }
.nav-cta:hover     { box-shadow: 0 10px 22px rgba(160, 43, 34, 0.34); }
.atlas-ask:hover   { box-shadow: 0 12px 26px rgba(160, 43, 34, 0.42); }
.chat-input button[type="submit"]:hover,
.voice-send:hover  { box-shadow: 0 8px 18px rgba(160, 43, 34, 0.4); }

/* ---------- Focus ---------- */
/* One ring, brass, offset far enough to clear the rounded corners. Every
   control gets the same one so that tabbing through the site does not
   feel like tabbing through three different sites. */

.btn:focus-visible,
.nav-cta:focus-visible,
.nav-toggle:focus-visible,
.suggest:focus-visible,
.chat-input button[type="submit"]:focus-visible,
.chat-mic:focus-visible,
.atlas-ctrl:focus-visible,
.atlas-chip:focus-visible,
.atlas-mode:focus-visible,
.atlas-ask:focus-visible,
.atlas-voices-hint:focus-visible,
.atlas-item:focus-visible,
.atlas-card-close:focus-visible,
.voice-chip:focus-visible,
.voice-send:focus-visible,
.voice-sound:focus-visible,
.voice-close:focus-visible,
.lightbox-close:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  /* The ripple is clipped by overflow:hidden; the focus ring must not be. */
  overflow: visible;
}

/* On the dark panels brass alone is not bright enough against navy. */
.voice-chip:focus-visible,
.voice-send:focus-visible,
.voice-sound:focus-visible,
.voice-close:focus-visible,
.atlas-chip:focus-visible,
.atlas-mode:focus-visible,
.atlas-item:focus-visible,
.atlas-voices-hint:focus-visible {
  outline-color: var(--brass-light);
}

/* ---------- Disabled ---------- */

.chat-input button[type="submit"]:disabled,
.voice-send:disabled,
.btn:disabled {
  transform: none;
  box-shadow: none;
}
.chat-input button[type="submit"]:disabled::after,
.voice-send:disabled::after { display: none; }

/* ---------- Reduced motion ---------- */
/* interactions.js does not run at all, so there is no ripple to suppress.
   What is left is the sweep and the compression, both removed here. The
   colour changes and the focus ring stay: those carry meaning. */

@media (prefers-reduced-motion: reduce) {
  .btn-primary::after,
  .btn-brass::after,
  .nav-cta::after,
  .atlas-ask::after,
  .chat-input button[type="submit"]::after,
  .voice-send::after { display: none; }

  .btn:active,
  .nav-cta:active,
  .atlas-ask:active,
  .atlas-voices-hint:active,
  .chat-input button[type="submit"]:active,
  .voice-send:active,
  .suggest:active,
  .atlas-mode:active,
  .atlas-chip:active,
  .voice-chip:active,
  .atlas-ctrl:active,
  .chat-mic:active,
  .nav-toggle:active,
  .voice-sound:active,
  .voice-close:active,
  .atlas-item:active { transform: none; }
}

/* ============================================================
   PRELOADER
   ------------------------------------------------------------
   A postmark that draws itself while the page arrives: the two
   things this site is about, a letter and an archive.

   Three rules govern it, in order of importance:

   1. It must never trap anyone. A loading screen that outlives
      its page is worse than no loading screen, so it fails
      open three separate ways: the script dismisses it, a CSS
      animation dismisses it at 6s whether or not the script
      ever ran, and <noscript> removes it entirely.
   2. It must not invent delay. There is a 420ms floor purely
      so a fast load does not flash, and nothing above that.
   3. It lives in styles.css rather than an inline block
      because the stylesheet is render-blocking: it is already
      parsed at first paint, so the preloader is on screen in
      the same frame the page first draws.
   ============================================================ */

.preloader {
  position: fixed; inset: 0; z-index: 9999;
  display: grid; place-items: center;
  background: var(--navy-deep);
  opacity: 1;
  transition: opacity 0.55s var(--ease), visibility 0.55s var(--ease);

  /* Failsafe. If the script never runs, never loads, or throws before
     it can dismiss this, the page still becomes usable on its own. */
  animation: preloader-failsafe 1ms linear 6s forwards;
}
@keyframes preloader-failsafe {
  to { opacity: 0; visibility: hidden; pointer-events: none; }
}

.preloader.is-done {
  opacity: 0; visibility: hidden; pointer-events: none;
}

/* Same ledger rule as the video and the rest of the site. */
.preloader::before {
  content: ""; position: absolute; inset: 0;
  background-image: repeating-linear-gradient(
    to bottom, rgba(195, 154, 80, 0.05) 0 1px, transparent 1px 84px
  );
}
.preloader::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(70% 60% at 50% 45%, transparent 38%, rgba(4, 8, 16, 0.6) 100%);
}

.preloader-inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center;
  padding: 2rem;
}

/* ---------- The postmark ---------- */

.preloader-mark {
  position: relative;
  display: grid; place-items: center;
  width: 108px; height: 108px;
  margin-bottom: 1.9rem;
}
.preloader-ring {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  transform: rotate(-90deg);
}
.preloader-ring circle {
  fill: none; stroke-width: 2.5; stroke-linecap: round;
}
.preloader-ring-track { stroke: rgba(195, 154, 80, 0.20); }
.preloader-ring-arc {
  stroke: var(--brass-light);
  /* r=46 -> circumference ~289. A quarter is drawn and chases its
     own tail, which reads as a postmark being stamped rather than
     as a spinner. */
  stroke-dasharray: 72 217;
  transform-origin: 50% 50%;
  animation: preloader-arc 1.5s cubic-bezier(0.6, 0.05, 0.35, 0.95) infinite;
}
@keyframes preloader-arc {
  to { transform: rotate(360deg); }
}

.preloader-glyph {
  width: 40px; height: 40px;
  color: var(--brass-light);
  animation: preloader-breathe 2.8s ease-in-out infinite;
}
@keyframes preloader-breathe {
  0%, 100% { opacity: 0.82; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.04); }
}

/* ---------- Wordmark ---------- */

.preloader-brand {
  margin: 0 0 1.5rem;
  font-family: var(--font-serif); font-size: 1.42rem; font-weight: 600;
  letter-spacing: 0.005em; color: var(--cream); text-align: center;
}
.preloader-brand i { font-style: normal; color: var(--brass); margin: 0 0.16em; }

/* ---------- The hairline ---------- */

.preloader-bar {
  position: relative; overflow: hidden;
  width: 208px; height: 2px;
  background: rgba(195, 154, 80, 0.18);
}
.preloader-bar-fill {
  position: absolute; inset: 0;
  transform-origin: left center; transform: scaleX(0);
  background: linear-gradient(90deg, var(--brass), var(--brass-light));
  /* Eases towards nearly-full and waits there. The script takes it the
     rest of the way, so the bar never claims to be finished before the
     page is. */
  animation: preloader-fill 2.6s cubic-bezier(0.16, 0.84, 0.44, 1) forwards;
}
@keyframes preloader-fill {
  to { transform: scaleX(0.92); }
}
.preloader.is-done .preloader-bar-fill {
  transform: scaleX(1);
  transition: transform 0.3s var(--ease);
  animation: none;
}

.preloader-note {
  margin: 1.15rem 0 0;
  font-family: var(--font-sans); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.26em; text-transform: uppercase;
  color: rgba(226, 200, 140, 0.62);
}

@media (max-width: 480px) {
  .preloader-mark { width: 88px; height: 88px; margin-bottom: 1.5rem; }
  .preloader-glyph { width: 33px; height: 33px; }
  .preloader-brand { font-size: 1.18rem; }
  .preloader-bar { width: 168px; }
}

/* Reduced motion keeps the screen and drops the movement. The arc holds
   still, the mark stops breathing, and the bar simply sits full: the
   information is "the page is loading", and that survives without any
   of the animation. */
@media (prefers-reduced-motion: reduce) {
  .preloader-ring-arc { animation: none; stroke-dasharray: 217 72; }
  .preloader-glyph { animation: none; opacity: 1; }
  .preloader-bar-fill { animation: none; transform: scaleX(1); }
  .preloader { transition-duration: 0.01ms; }
}

/* ============================================================
   ON THE STREET
   ------------------------------------------------------------
   The physical half of the proposal: a code beside the plaque,
   or in it. The mock-ups are drawn in CSS rather than
   photographed, deliberately. A composited photo of a plaque
   that does not exist, standing in a real Toronto planting
   bed, is the kind of thing that gets forwarded without its
   caption and read as real. A diagram cannot be mistaken for
   evidence.

   The QR codes are the exception: those are real, generated
   from the same deep links people.js reads, and they scan.
   ============================================================ */

.street {
  position: relative;
  padding: clamp(4.5rem, 9vw, 7.5rem) 0;
  background: var(--parchment);
  border-top: 1px solid var(--line);
}
.street-inner {
  max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter);
}

/* Wide enough that "The bronze does not change." holds one line; below
   that it breaks after "not" and reads as a stutter. */
.street-head { max-width: 900px; margin-bottom: clamp(3rem, 6vw, 4.5rem); }
.street-lede {
  margin: 1.4rem 0 0;
  font-size: clamp(1.05rem, 1.9vw, 1.24rem); line-height: 1.7;
  color: var(--ink-soft);
}
.street-lede strong { color: var(--ink); font-weight: 600; }

/* ---------- The two placements ---------- */

.street-options {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(1.5rem, 3.5vw, 2.75rem);
  margin-bottom: clamp(3rem, 6vw, 4.5rem);
}
.street-option {
  display: flex; flex-direction: column;
  border-radius: var(--radius-lg); overflow: hidden;
  background: var(--cream);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}

/* The mock: a plaque on a post, drawn rather than photographed. */
.street-mock {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  padding: 2.6rem 1.5rem 0;
  min-height: 300px;
  background:
    radial-gradient(120% 80% at 50% 0%, #26374F 0%, #16233F 55%, #0D1526 100%);
}
.mock-plaque {
  position: relative;
  width: min(300px, 100%); padding: 1.15rem 1.1rem 1.25rem;
  display: flex; flex-direction: column; align-items: center; gap: 0.45rem;
  border-radius: 10px;
  background: linear-gradient(158deg, #6E6552 0%, #4A4638 46%, #2F2E26 100%);
  box-shadow:
    0 14px 30px rgba(0,0,0,0.45),
    inset 0 1px 0 rgba(226,200,140,0.42),
    inset 0 0 0 2px rgba(226,200,140,0.22);
}
.mock-crest {
  width: 22px; height: 22px; border-radius: 50%;
  background: rgba(226,200,140,0.5);
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
  margin-bottom: 0.15rem;
}
.mock-title {
  width: 62%; height: 9px; border-radius: 2px;
  background: rgba(240,224,180,0.82);
  margin-bottom: 0.35rem;
}
.mock-line {
  width: 88%; height: 4px; border-radius: 2px;
  background: rgba(226,200,140,0.34);
}
.mock-line.short { width: 62%; }

.mock-post {
  width: 13px; height: 66px;
  background: linear-gradient(90deg, #2A2A24, #4A4A3E 40%, #23231E);
  border-radius: 0 0 2px 2px;
}

/* Option one: the separate plate, hanging on the post. */
.mock-plate {
  position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%);
  padding: 7px; border-radius: 5px;
  background: linear-gradient(155deg, #F4EEDF, #D9CFB6);
  box-shadow: 0 5px 14px rgba(0,0,0,0.45), inset 0 0 0 1px rgba(0,0,0,0.18);
}
.mock-plate img { display: block; width: 52px; height: 52px; }

/* Option two: the code cast into the plaque's own corner. */
.mock-inset {
  position: absolute; top: 12px; right: 12px;
  padding: 4px; border-radius: 3px;
  background: rgba(232, 220, 190, 0.9);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.28);
}
.mock-inset img { display: block; width: 38px; height: 38px; }
.mock-plaque--inset { padding-right: 3.6rem; }

.street-option-body { padding: clamp(1.5rem, 2.6vw, 2rem); }
.street-tag {
  margin: 0 0 0.5rem;
  font-family: var(--font-sans); font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass);
}
.street-option-body h3 {
  margin: 0 0 0.7rem; font-size: clamp(1.2rem, 2.2vw, 1.45rem); color: var(--navy);
}
.street-option-body p { margin: 0 0 1rem; color: var(--ink-soft); line-height: 1.65; }

.street-facts { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.street-facts li {
  position: relative; padding-left: 1.15rem;
  font-family: var(--font-sans); font-size: 0.86rem; color: var(--ink-soft);
}
.street-facts li::before {
  content: ""; position: absolute; left: 0; top: 0.52em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--brass);
}
.street-facts strong { color: var(--ink); font-weight: 600; }

/* ---------- The working code ---------- */

.street-demo {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding: clamp(1.75rem, 3.5vw, 2.6rem);
  margin-bottom: clamp(3rem, 6vw, 4.5rem);
  border-radius: var(--radius-lg);
  background: var(--navy-deep); color: var(--cream);
  box-shadow: var(--shadow-md);
}
.street-demo-code {
  padding: 14px; border-radius: 12px; background: var(--cream);
  box-shadow: 0 10px 26px rgba(0,0,0,0.4);
}
.street-demo-code img { display: block; width: 132px; height: 132px; }
.street-demo-body h3 {
  margin: 0 0 0.7rem; color: var(--cream);
  font-size: clamp(1.2rem, 2.3vw, 1.5rem);
}
.street-demo-body p {
  margin: 0 0 0.7rem; line-height: 1.7;
  color: rgba(246,238,221,0.82);
}
.street-demo-note {
  font-family: var(--font-sans); font-size: 0.82rem;
  color: rgba(226,200,140,0.72) !important;
}

/* ---------- Who does what ---------- */

.street-deal {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(1.5rem, 3.5vw, 2.75rem);
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.street-deal-col {
  padding: clamp(1.5rem, 2.6vw, 2rem);
  border-radius: var(--radius-lg);
  background: var(--cream); border: 1px solid var(--line);
}
.street-deal-col h3 {
  display: flex; align-items: center; gap: 0.65rem;
  margin: 0 0 1.1rem; font-size: 1.16rem; color: var(--navy);
}
.street-deal-mark {
  display: grid; place-items: center; flex-shrink: 0;
  width: 32px; height: 32px; border-radius: 9px;
  font-family: var(--font-sans); font-size: 0.76rem; font-weight: 700;
  letter-spacing: 0.02em;
  background: var(--crimson); color: #fff;
}
.street-deal-mark--ht { background: var(--navy); color: var(--brass-light); }
.street-deal-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.62rem; }
.street-deal-col li {
  position: relative; padding-left: 1.3rem;
  line-height: 1.6; color: var(--ink-soft);
}
.street-deal-col li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 8px; height: 2px; background: var(--brass);
}

.street-close {
  max-width: 640px; margin: 0;
  font-family: var(--font-serif); font-size: clamp(1.1rem, 2.1vw, 1.35rem);
  font-style: italic; line-height: 1.6; color: var(--navy);
}

@media (max-width: 900px) {
  .street-options, .street-deal { grid-template-columns: 1fr; }
  .street-demo { grid-template-columns: 1fr; justify-items: start; }
}
@media (max-width: 480px) {
  .street-demo-code img { width: 110px; height: 110px; }
  .mock-plaque { width: 100%; }
}

/* ============================================================
   CO-BRAND LOCKUP
   ------------------------------------------------------------
   Heritage Toronto's logo sits beside their name wherever the
   two brands appear together. The asset is theirs and is not in
   this repository, so every use is written to work without it:
   the logo is hidden until it actually loads, the typed wordmark
   stands in until then, and a failed request removes the image
   rather than leaving a broken graphic in the header.

   Drop the file at assets/heritage-toronto.png and it appears in
   all three places at once.
   ============================================================ */

.brand-lockup {
  display: inline-flex; align-items: center; gap: 0.4rem;
}
.brand-ht {
  display: none;             /* until onload confirms it resolved */
  height: 32px; width: auto;
  /* The logo is dark type on white. On the navy header that needs a light
     plate under it rather than being left to disappear. */
  padding: 3px 5px; border-radius: 4px;
  background: var(--cream);
}
.brand-lockup.has-ht .brand-ht { display: block; }
.brand-lockup.has-ht .brand-ht-text { display: none; }

/* The scrolled header is parchment, so the plate is unnecessary there. */
.site-header.scrolled .brand-ht { background: transparent; padding: 3px 0; }

/* ---------- In the collaboration section ---------- */

.street-deal-logo {
  display: none;
  height: 34px; width: auto; margin-right: 0.15rem;
}
.street-deal-col h3.has-ht .street-deal-logo { display: block; }
.street-deal-col h3.has-ht .street-deal-mark--ht { display: none; }

/* ---------- The affiliation notice ---------- */

.footer-affiliation {
  max-width: 62ch;
  margin: 1.5rem auto 0;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(226, 200, 140, 0.16);
  font-family: var(--font-sans); font-size: 0.76rem; line-height: 1.65;
  color: rgba(252, 248, 239, 0.5);
  text-align: center;
}
.footer-affiliation a { color: rgba(226, 200, 140, 0.8); }

@media (max-width: 720px) {
  .brand-ht { height: 26px; }
  .footer-affiliation { text-align: left; }
}

/* ============================================================
   CHAT TOPBAR ON A PHONE
   ------------------------------------------------------------
   Avatar, name, role, live/offline badge, voice toggle and
   "Start over" is more than fits one row at 375px. It did not
   scroll the page, because the chat clips it, but the reset
   button sat at x=370 in a 375px viewport: present, and
   unreachable. It wraps now, and the buttons keep their icons
   while the labels go.
   ============================================================ */

@media (max-width: 620px) {
  .chat-topbar { flex-wrap: wrap; gap: 0.6rem 0.5rem; padding: 0.8rem 1rem; }
  .chat-avatar { width: 38px; height: 38px; }
  .chat-who { flex: 1 1 auto; min-width: 0; }
  .chat-who strong { font-size: 0.95rem; }
  .chat-who span { font-size: 0.72rem; }

  /* The badge keeps its place at the end of the first row; the two
     buttons drop to a second row and share it. */
  .chat-mode { margin-left: auto; }
  .chat-voice, .chat-reset { margin-left: 0; flex: 0 0 auto; }
  .chat-voice { order: 3; }
  .chat-reset { order: 4; margin-left: auto; }
}

/* Below 380px even the wrapped row is tight, so the buttons keep the
   glyph and drop the word. Both still carry an accessible name. */
@media (max-width: 380px) {
  .chat-voice span, .chat-reset { font-size: 0.72rem; }
  .chat-reset { padding: 0.45rem 0.6rem; }
  .chat-voice { padding: 0.45rem 0.6rem; }
}

/* ============================================================
   HEADER ON A VERY NARROW PHONE
   ------------------------------------------------------------
   At 320px the brand lockup took 267px of a 305px line and flex
   crushed the menu button down to 2px. The button was still in
   the DOM, still focusable, and impossible to hit: on a 320px
   phone there was no way to open the navigation at all.

   The button never shrinks now, and the brand gives way instead.
   ============================================================ */

.nav-toggle { flex-shrink: 0; }

@media (max-width: 420px) {
  .brand { min-width: 0; }
  .brand-text { min-width: 0; }
  .brand-lockup { min-width: 0; }
  /* Truncate rather than wrap: two ragged lines in a 60px-tall header
     looks broken, one clipped line reads as intentional. */
  .brand-text strong,
  .brand-text em {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    display: block;
  }
  .brand-lockup { display: flex; }
}

/* Footer links sit at 15px tall, which is a small target on a phone. The
   two inline "Saylavy" links inside sentences are exempt under WCAG 2.2
   and are left alone; the column links are list navigation and get the
   padding. */
@media (max-width: 720px) {
  .footer-col a { display: inline-block; padding: 0.32rem 0; }
}

/* ============================================================
   THE PROPOSAL FILM
   ------------------------------------------------------------
   Navy, after the parchment of the collaboration section, so the
   page darkens into the film the way a room does.
   ============================================================ */

.film {
  position: relative;
  padding: clamp(4rem, 8vw, 6.5rem) 0 clamp(4.5rem, 9vw, 7rem);
  background:
    radial-gradient(120% 90% at 50% 0%, #1B2C4C 0%, var(--navy) 45%, var(--navy-deep) 100%);
  color: var(--cream);
}
.film-inner {
  max-width: 1040px; margin: 0 auto; padding: 0 var(--gutter);
}
.film-head { max-width: 720px; margin-bottom: clamp(2rem, 4vw, 3rem); }
.film-lede {
  margin: 1.2rem 0 0;
  font-size: clamp(1.02rem, 1.8vw, 1.18rem); line-height: 1.7;
  color: rgba(246, 238, 221, 0.76);
}

.film-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid rgba(226, 200, 140, 0.28);
  box-shadow: 0 40px 90px rgba(3, 7, 14, 0.6);
  background: var(--navy-deep);
}

/* The facade: a still, a scrim, a button, a caption. */
.film-play {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%;
  padding: 0; border: 0; cursor: pointer;
  background: none; color: inherit;
}
.film-play img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 0.6s var(--ease), filter 0.4s var(--ease);
}
.film-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(7,12,23,0.10) 0%, rgba(7,12,23,0.06) 55%, rgba(7,12,23,0.22) 100%);
  transition: background 0.4s var(--ease);
}
.film-btn {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  display: grid; place-items: center;
  width: 78px; height: 78px; border-radius: 50%;
  background: var(--crimson); color: #fff;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.5);
  transition: transform 0.28s var(--ease), background 0.28s var(--ease);
  /* Nudge the triangle so it reads as centred in the circle. */
  padding-left: 5px;
}

.film-play:hover img,
.film-play:focus-visible img { transform: scale(1.03); }
.film-play:hover .film-btn,
.film-play:focus-visible .film-btn {
  transform: translate(-50%, -50%) scale(1.08);
  background: var(--crimson-deep);
}
.film-play:hover .film-scrim {
  background: linear-gradient(180deg, rgba(7,12,23,0.04) 0%, transparent 55%, rgba(7,12,23,0.16) 100%);
}
.film-play:focus-visible { outline: 2px solid var(--brass-light); outline-offset: -4px; }

/* The real player, once it has been asked for. */
.film-embed { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.film-note {
  margin: 1.3rem 0 0;
  font-family: var(--font-sans); font-size: 0.84rem; line-height: 1.6;
  color: rgba(246, 238, 221, 0.6);
}
.film-note a { color: var(--brass-light); }

@media (max-width: 600px) {
  .film-btn { width: 62px; height: 62px; }
}
@media (prefers-reduced-motion: reduce) {
  .film-play:hover img, .film-play:focus-visible img { transform: none; }
  .film-play:hover .film-btn, .film-play:focus-visible .film-btn { transform: translate(-50%, -50%); }
}
