/* ============================ NARRATOR OPENING (detective VO) ============================ */
/* The first-person case intro (US-01, US-02): five narration beats over atmosphere, the five suspect
   portraits rising one by one, then a hand-off into the eavesdrop. Full-bleed, one viewport, noir,
   the same visual language as the eavesdrop cutscene. All motion gates on html[data-reduce="1"] (the
   Settings reduced-motion signal, NOT the bare media query) so a reduce-by-default OS can force it on. */

#narrator-view { max-width: none; margin: 0; padding: 0; }
.nr-stage { position: relative; overflow: hidden; background: #0a0805; }

/* Cold-open video backdrop: the detective at the empty frame, playing UNDER the first two narration
   beats, then fading to the atmosphere wash. Sits above the gradient backdrop (z-1) so it covers it
   while shown; the vignette (also z-1, later in the DOM) darkens its edges for caption legibility. */
.nr-video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000;
  display: block; z-index: 1; opacity: 0; transition: opacity .8s ease;
}
.nr-video.show { opacity: 1; }

/* Per-beat backdrop art (beats 3-5): a warm-noir still that cross-fades in as each beat opens (the
   detective's case file, the empty gilded frame in the gallery, the door). Layered above the gradient
   wash and below the vignette, so the wash is the fallback if an image ever fails to load. */
.nr-still {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background-size: cover; background-position: center;
  opacity: 0; transition: opacity .8s ease;
}
.nr-still.show { opacity: 1; }

/* Atmosphere backdrop: a slow warm-noir gradient wash (fallback when no beat art is shown; beats 1-2
   run over the video, later beats over the stills above). A gentle drift reads as a held camera. */
.nr-backdrop {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(64% 48% at 50% 20%, rgba(205,163,73,0.14), transparent 66%),
    radial-gradient(120% 90% at 50% 8%, rgba(40,32,18,0.55), transparent 60%),
    linear-gradient(#0c0a07, #060503);
  transform: scale(1.04); will-change: transform;
}
.nr-stage.play .nr-backdrop { animation: nr-drift 22s ease-out forwards; }
@keyframes nr-drift { from { transform: scale(1.04); } to { transform: scale(1.12); } }

.nr-vignette { position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: radial-gradient(120% 100% at 50% 40%, #00000000 40%, #000000dc 100%); }

/* Content: suspects (center) + caption + actions (lower third), over a scrim so text stays legible. */
.nr-content { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column;
  justify-content: flex-end; align-items: center; gap: clamp(16px,3vh,26px);
  padding: clamp(80px,14vh,140px) clamp(18px,5.5vw,28px) clamp(26px,5vh,44px);
  background: linear-gradient(to top, #000000d4 0%, #0000008c 30%, #00000000 62%); }

/* --- The five suspects: one compact row (portrait + name), rising one at a time. A single row that
   always fits the viewport width, so nothing scrolls off. The active suspect (whose line is reading)
   lifts and lights up. --- */
.nr-suspects { display: flex; flex-wrap: nowrap; justify-content: center; align-items: flex-start;
  gap: clamp(6px,2vw,16px); margin-bottom: clamp(10px,2vh,18px); margin-top: auto; width: 100%; }
.nr-suspect { margin: 0; display: flex; flex-direction: column; align-items: center; text-align: center;
  flex: 0 1 auto; min-width: 0;
  opacity: 0; transform: translateY(14px); transition: opacity .6s ease, transform .6s ease; }
.nr-suspect.show { opacity: 1; transform: none; }
.nr-portrait { width: clamp(52px,14vw,88px); height: clamp(52px,14vw,88px); border-radius: 50%;
  object-fit: cover; border: 2px solid rgba(205,163,73,0.34);
  box-shadow: 0 6px 22px #000a, 0 0 0 4px #0a08057a; background: #17130c;
  transition: border-color .35s ease, box-shadow .35s ease, transform .35s ease; }
.nr-name { margin-top: 7px; font-family: var(--font-display, "Playfair Display", serif);
  font-weight: 700; font-size: clamp(11px,3vw,15px); line-height: 1.15; color: var(--ink-soft, #cdbfa6);
  text-shadow: 0 1px 6px #000; transition: color .35s ease; max-width: clamp(60px,16vw,120px); }
/* Active suspect: the one whose line is being read. Lifts, gilds, brightens its name. */
.nr-suspect.active .nr-portrait { border-color: rgba(230,184,78,0.95);
  box-shadow: 0 8px 26px #000c, 0 0 0 4px #0a0805, 0 0 22px rgba(230,184,78,0.35); transform: translateY(-4px) scale(1.05); }
.nr-suspect.active .nr-name { color: var(--ink, #f2e9d8); }

/* Per-suspect characterization line, shown as each portrait lights up. */
.nr-subline { margin: 0 0 clamp(8px,1.6vh,14px); max-width: 560px; min-height: 2.6em; text-align: center;
  font-family: var(--font-read, "Newsreader", serif); font-style: italic;
  font-size: clamp(15px,4vw,18px); line-height: 1.45; color: var(--ink-soft, #cdbfa6);
  text-shadow: 0 1px 8px #000; }

/* --- Narration caption (the spoken beat) --- */
.nr-caption { margin: 0; max-width: 640px; text-align: center;
  font-family: var(--font-read, "Newsreader", serif); font-size: clamp(18px,5vw,24px); line-height: 1.5;
  color: var(--ink, #f2e9d8); text-shadow: 0 2px 18px #000, 0 0 8px #000, 0 1px 2px #000; min-height: 1.5em; }
.nr-ch { transition: opacity .12s linear; }
.nr-ch--pending { opacity: 0; }

/* --- Actions (Continue / Listen at the door) --- */
.nr-actions { display: flex; gap: 12px; min-height: 44px; justify-content: center; }
/* Keep the 44px reserved even while empty, so the Continue button fading in never shoves the
   caption up (2026-07-11). The button eases in instead of popping. */
html:not([data-reduce="1"]) .nr-actions button { animation: nr-btn-in 0.28s ease; }
@keyframes nr-btn-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }

/* Big featured-suspect portrait for the intro (beat 3): fills the empty top real-estate, one face at
   a time as the detective reads each blurb. Driven from narrator.js stepSuspectLines. (2026-07-11) */
.nr-bigportrait { position: absolute; left: 50%; top: clamp(4%, 6vh, 10%); transform: translateX(-50%);
  width: clamp(190px, 58%, 288px); aspect-ratio: 4 / 5; z-index: 1; opacity: 0; pointer-events: none;
  transition: opacity 0.5s ease; }
.nr-bigportrait.show { opacity: 1; }
html[data-reduce="1"] .nr-bigportrait { transition: none; }
.nr-bp-glow { position: absolute; inset: -20% -24%; border-radius: 50%;
  background: radial-gradient(58% 54% at 50% 30%, rgba(240, 199, 94, 0.3), transparent 70%); }
.nr-bp-img { position: absolute; inset: 0; background-size: cover; background-position: 50% 16%;
  border-radius: 6px; box-shadow: 0 22px 54px rgba(0, 0, 0, 0.72); filter: grayscale(0.4) contrast(1.1);
  -webkit-mask-image: radial-gradient(125% 100% at 50% 34%, #000 52%, transparent 100%);
          mask-image: radial-gradient(125% 100% at 50% 34%, #000 52%, transparent 100%); }
html:not([data-reduce="1"]) .nr-bp-img.swap { animation: nr-bp-settle 0.7s cubic-bezier(0.2, 0.7, 0.3, 1); }
@keyframes nr-bp-settle {
  0% { opacity: 0.2; transform: scale(1.08); filter: grayscale(0.7) contrast(1.2) brightness(1.35); }
  100% { opacity: 1; transform: scale(1); filter: grayscale(0.4) contrast(1.1); }
}

/* --- Reduced motion: no drift, no rise; captions and portraits are instant. --- */
html[data-reduce="1"] .nr-stage.play .nr-backdrop { animation: none; transform: none; }
html[data-reduce="1"] .nr-video { transition: none; }
html[data-reduce="1"] .nr-still { transition: none; }
html[data-reduce="1"] .nr-suspect { transition: none; transform: none; }
html[data-reduce="1"] .nr-suspect.active .nr-portrait { transform: none; transition: none; }
html[data-reduce="1"] .nr-ch { transition: none; }
