:root {
  --bg: #0b0a09;
  --bg-card: #161311;
  --ink: #ece6dc;
  --ink-dim: #a99f8f;
  --accent: #d1a35c;
  --accent-dim: #8a6d3c;
  --border: #2a2521;
  --radius: 6px;
  --serif: Georgia, "Times New Roman", Times, serif;
  --mono: "Courier New", Courier, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding-top: 1.1rem;
  background: var(--bg);
  background-image:
    radial-gradient(ellipse at top, rgba(209,163,92,0.06), transparent 60%),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.015) 0px, transparent 1px, transparent 2px),
    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='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
  color: var(--ink);
  font-family: var(--serif);
  line-height: 1.5;
}

.site-header {
  position: relative;
  text-align: center;
  padding: 1.3rem 1.5rem 1.1rem;
  border-bottom: 1px solid var(--border);
  background-image: radial-gradient(ellipse at 50% -30%, rgba(209,163,92,0.14), transparent 65%);
}

.brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
}

.brand-link {
  color: inherit;
  text-decoration: none;
  display: contents;
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  border: 1px solid var(--accent-dim);
  border-radius: 50%;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.85rem;
  letter-spacing: 0.05em;
}

.site-header h1 {
  font-size: 1.9rem;
  letter-spacing: 0.06em;
  margin: 0;
  font-weight: 400;
  text-transform: uppercase;
}

.tagline {
  margin: 0.45rem auto 0;
  font-style: italic;
  color: var(--ink-dim);
  max-width: 32rem;
}

.welcome {
  margin: 0.5rem auto 0;
  color: var(--ink);
  max-width: 34rem;
  font-size: 0.95rem;
}

.home-link {
  margin: 0.75rem auto 0;
}

.home-link a {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  padding: 0.35rem 0.9rem;
}

.home-link a:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.pd-note {
  margin: 0.6rem auto 0;
  max-width: 34rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--accent-dim);
  text-transform: uppercase;
}

.pd-note a {
  color: var(--accent);
}

.about-body {
  max-width: 42rem;
  margin: 2.5rem auto 6rem;
  padding: 0 1.5rem;
  font-size: 0.98rem;
}

.about-body h2 {
  margin-top: 2.5rem;
  font-size: 1.2rem;
  font-weight: 600;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.5rem;
}

.about-entry {
  padding: 1rem 0;
  border-bottom: 1px dotted var(--border);
}

.about-entry h3 {
  font-size: 1rem;
  margin: 0 0 0.4rem;
  font-weight: 600;
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
}

.about-entry p {
  margin: 0.3rem 0;
  font-size: 0.88rem;
  color: var(--ink-dim);
}

.about-caveat {
  font-style: italic;
}

.about-back {
  margin-top: 2.5rem;
}

.about-back a {
  color: var(--accent);
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  max-width: 1200px;
  margin: 1.75rem auto 0;
  padding: 0 1.5rem;
}

.filter-btn {
  border: 1px solid var(--accent-dim);
  background: transparent;
  color: var(--ink-dim);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.35rem 0.9rem;
  border-radius: 999px;
  cursor: pointer;
}

.filter-btn:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.filter-btn.is-active {
  background: var(--accent-dim);
  border-color: var(--accent-dim);
  color: var(--bg);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.75rem;
  max-width: 1200px;
  margin: 2.5rem auto;
  padding: 0 1.5rem;
}

.card.is-filtered-out {
  display: none;
}

.card-title-link {
  color: inherit;
  text-decoration: none;
}

.card-title-link:hover {
  color: var(--accent);
}

.grid--single {
  grid-template-columns: minmax(0, 560px);
  justify-content: center;
}

.film-page-back {
  max-width: 560px;
  margin: 1.5rem auto 3rem;
  padding: 0 1.5rem;
  text-align: center;
}

.film-page-back a {
  color: var(--accent);
}

.card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 0.2s ease, border-color 0.2s ease;
}

.card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-dim);
}

.clip-frame {
  position: relative;
}

.clip-frame video {
  width: 100%;
  aspect-ratio: 16 / 9;
  display: block;
  background: #000;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}

.sound-badge {
  position: absolute;
  bottom: 0.3rem;
  right: 0.6rem;
  z-index: 2;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: 1px solid var(--accent-dim);
  background: rgba(11, 10, 9, 0.75);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sound-badge:hover {
  border-color: var(--accent);
}

.clip-caption {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1;
  overflow: hidden;
  background: rgba(5, 4, 3, 0.78);
  border-top: 1px solid var(--accent-dim);
  padding: 0.3rem 0;
  pointer-events: none;
}

.clip-caption-track {
  display: flex;
  width: max-content;
  white-space: nowrap;
  animation: clip-caption-scroll linear infinite;
  animation-play-state: paused;
}

.card:hover .clip-caption-track {
  animation-play-state: running;
}

/* While narration is playing, script.js drives the caption's position
   directly (via transform) to track actual playback progress, instead
   of the free-running decorative scroll -- this beats the hover rule
   above so a synced caption doesn't get fought over on a hovered card.
   Fully removing the animation (not just pausing it) matters here: a
   paused CSS animation still holds its last frozen transform value,
   which outranks a plain inline style in the cascade and would
   silently block the JS-driven transform from ever showing. */
.clip-caption-track.is-narrating {
  animation: none !important;
}

.clip-caption-track span {
  padding-right: 4rem;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.78rem;
  color: var(--ink);
}

@keyframes clip-caption-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .clip-caption-track {
    animation: none;
  }
}

/* One fixed class per whole-second duration (14-28s), computed at build
   time by scripts/build_static.py. Avoids setting animation-duration via
   an inline style attribute, which the CSP's style-src would otherwise
   have to allow with 'unsafe-inline'. */
.duration-14 { animation-duration: 14s; }
.duration-15 { animation-duration: 15s; }
.duration-16 { animation-duration: 16s; }
.duration-17 { animation-duration: 17s; }
.duration-18 { animation-duration: 18s; }
.duration-19 { animation-duration: 19s; }
.duration-20 { animation-duration: 20s; }
.duration-21 { animation-duration: 21s; }
.duration-22 { animation-duration: 22s; }
.duration-23 { animation-duration: 23s; }
.duration-24 { animation-duration: 24s; }
.duration-25 { animation-duration: 25s; }
.duration-26 { animation-duration: 26s; }
.duration-27 { animation-duration: 27s; }
.duration-28 { animation-duration: 28s; }

.narration-audio {
  display: none;
}

.card-body {
  padding: 1.1rem 1.25rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  cursor: pointer;
}

.card-title-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}

.card-title-row h2 {
  font-size: 1.15rem;
  margin: 0;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.card-year {
  font-family: var(--mono);
  color: var(--accent);
  font-size: 0.85rem;
  white-space: nowrap;
}

.card-meta {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-dim);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.scene-label {
  font-size: 0.8rem;
  font-style: italic;
  color: var(--accent);
}

.listen-row {
  display: flex;
  justify-content: flex-end;
}

.commentary {
  font-size: 0.92rem;
  color: var(--ink);
  margin: 0;
}

.narrate-btn {
  border: 1px solid var(--accent-dim);
  background: transparent;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  cursor: pointer;
}

.narrate-btn:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.narrate-btn.narrating {
  background: var(--accent-dim);
  color: var(--bg);
}

.card-footer-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  margin-top: 0.3rem;
  flex-wrap: wrap;
}

.pd-badge {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.02em;
  color: var(--accent-dim);
  text-decoration: none;
  border-bottom: 1px dotted var(--accent-dim);
  white-space: nowrap;
}

.pd-badge:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.watch-link {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px dotted var(--accent);
  white-space: nowrap;
}

.watch-link:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

/* Ad slots: reserved space with no ad network wired in yet (that needs an
   approved account; see README). Filled for now with a slow-scrolling
   filmstrip built from the site's own poster stills -- an actual
   "collection," not a stock photo -- so it's never a bare, broken-looking
   box. Each tile is sized to the image's own aspect ratio (16:9, same as
   the film clips) rather than stretched to the slot's outer box, so the
   whole picture shows instead of a sliver of it. */
.poster-strip {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0.5rem 1.5rem;
}

.poster-strip--top {
  margin-top: 1.5rem;
}

.poster-strip--infeed {
  grid-column: 1 / -1;
  padding: 0;
}

.poster-strip-frame {
  overflow: hidden;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
}

.poster-strip--top .poster-strip-frame {
  height: 100px;
}

.poster-strip--infeed .poster-strip-frame {
  height: 100px;
}

.poster-strip-track {
  display: flex;
  width: max-content;
  height: 100%;
  animation: poster-strip-scroll 180s linear infinite;
}

.poster-strip-track a {
  flex: none;
  height: 100%;
  aspect-ratio: 16 / 9;
  display: block;
}

.poster-strip-track img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(35%) sepia(10%) brightness(0.75);
  transition: filter 0.15s ease;
}

.poster-strip-track a:hover img,
.poster-strip-track a:focus-visible img {
  filter: none;
}

@keyframes poster-strip-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* Motion-safe fallback: a scrolling filmstrip with the animation switched
   off would just freeze on its first couple of tiles forever, which reads
   as broken ("why is it always the same two pictures?"), not as a
   deliberate accessibility choice. Wrapping into a static mosaic instead
   shows a full, varied grid with no motion at all. */
@media (prefers-reduced-motion: reduce) {
  .poster-strip-track {
    animation: none;
    flex-wrap: wrap;
    width: 100%;
    height: auto;
  }

  .poster-strip--top .poster-strip-frame,
  .poster-strip--infeed .poster-strip-frame {
    height: auto;
    max-height: 280px;
    overflow: hidden;
  }

  .poster-strip-track a {
    height: 90px;
  }
}

.site-footer {
  text-align: center;
  padding: 2rem 1.5rem 6rem;
  color: var(--ink-dim);
  font-size: 0.82rem;
}

.site-footer code {
  font-family: var(--mono);
  color: var(--accent);
}

/* Reaction cam */
.reaction-cam {
  position: fixed;
  left: 50%;
  bottom: 0.5rem;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  z-index: 50;
  transition: transform 0.2s ease;
  pointer-events: none; /* decorative -- never block a click meant for a card beneath it */
}

.reaction-cam-frame {
  position: relative;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #141210, #050505 70%);
  border: 3px solid var(--accent-dim);
  box-shadow:
    0 0 0 4px var(--bg),
    0 0 0 5px var(--accent-dim),
    0 4px 16px rgba(0,0,0,0.65);
  overflow: hidden;
}

.reaction-figure {
  width: 100%;
  height: 100%;
  animation: rc-bob 3.2s ease-in-out infinite;
}

.rc-shoulders { fill: url(#rc-shoulders-grad); }
.rc-head { fill: url(#rc-head-grad); }
.rc-ear { fill: url(#rc-head-grad); }
.rc-hair { fill: #b8b3a8; }
.rc-nose { fill: none; stroke: #a88f68; stroke-width: 1.5; stroke-linecap: round; }
.rc-hat-crown { fill: #1c1a17; }
.rc-hat-brim { fill: #100f0d; }
.rc-beard, .rc-mustache { fill: #b6b0a3; }
.rc-glasses-frame {
  fill: rgba(120, 90, 40, 0.18);
  stroke: #241c14;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rc-brows, .rc-eyes { display: none; }
.rc-brows path { fill: none; stroke: #4a3c2c; stroke-width: 2.8; stroke-linecap: round; }
.rc-eyes circle { fill: #1a1a1a; }
[data-mood="neutral"] .rc-eyes-neutral circle { animation: rc-blink 4.6s ease-in-out infinite; transform-origin: center; }
.rc-eyes path { fill: none; stroke: #1a1a1a; stroke-width: 2; stroke-linecap: round; }
.rc-pupil { fill: #cbb89a !important; }

.rc-mouth { fill: none; stroke: #6b5a44; stroke-width: 2; stroke-linecap: round; display: none; }
.rc-mouth-laughing, .rc-mouth-thrilled { fill: #4a3c2c; stroke: #4a3c2c; }
.rc-mouth-sleepy { fill: #4a3c2c; stroke: #4a3c2c; }

.rc-heart { fill: #c9505f; }

[data-mood="neutral"] .rc-brows-neutral,
[data-mood="neutral"] .rc-eyes-neutral,
[data-mood="neutral"] .rc-mouth-neutral,
[data-mood="scared"] .rc-brows-scared,
[data-mood="scared"] .rc-eyes-scared,
[data-mood="scared"] .rc-mouth-scared,
[data-mood="laughing"] .rc-brows-laughing,
[data-mood="laughing"] .rc-eyes-laughing,
[data-mood="laughing"] .rc-mouth-laughing,
[data-mood="amazed"] .rc-brows-amazed,
[data-mood="amazed"] .rc-eyes-amazed,
[data-mood="amazed"] .rc-mouth-amazed,
[data-mood="tense"] .rc-brows-tense,
[data-mood="tense"] .rc-eyes-tense,
[data-mood="tense"] .rc-mouth-tense,
[data-mood="thrilled"] .rc-brows-thrilled,
[data-mood="thrilled"] .rc-eyes-thrilled,
[data-mood="thrilled"] .rc-mouth-thrilled,
[data-mood="swoon"] .rc-brows-swoon,
[data-mood="swoon"] .rc-eyes-swoon,
[data-mood="swoon"] .rc-mouth-swoon,
[data-mood="sleepy"] .rc-brows-sleepy,
[data-mood="sleepy"] .rc-eyes-sleepy,
[data-mood="sleepy"] .rc-mouth-sleepy,
[data-mood="wink"] .rc-brows-wink,
[data-mood="wink"] .rc-eyes-wink,
[data-mood="wink"] .rc-mouth-wink,
[data-mood="dizzy"] .rc-brows-dizzy,
[data-mood="dizzy"] .rc-eyes-dizzy,
[data-mood="dizzy"] .rc-mouth-dizzy,
[data-mood="suspicious"] .rc-brows-suspicious,
[data-mood="suspicious"] .rc-eyes-suspicious,
[data-mood="suspicious"] .rc-mouth-suspicious {
  display: block;
}

[data-mood="scared"] .reaction-figure { animation: rc-shake 0.4s ease-in-out infinite; }
[data-mood="laughing"] .reaction-figure { animation: rc-bounce 0.5s ease-in-out infinite; }
[data-mood="tense"] .reaction-figure { animation: rc-tense-pulse 1.6s ease-in-out infinite; }
[data-mood="thrilled"] .reaction-figure { animation: rc-thrilled-jiggle 0.45s ease-in-out infinite; }
[data-mood="swoon"] .reaction-figure { animation: rc-swoon-sway 2.4s ease-in-out infinite; }
[data-mood="sleepy"] .reaction-figure { animation: rc-sleepy-nod 3.6s ease-in-out infinite; }
[data-mood="wink"] .reaction-figure { animation: rc-wink-tilt 2s ease-in-out infinite; }
[data-mood="dizzy"] .reaction-figure { animation: rc-dizzy-wobble 2.2s ease-in-out infinite; }
[data-mood="suspicious"] .reaction-figure { animation: rc-suspicious-tilt 3s ease-in-out infinite; }
[data-mood="suspicious"] .rc-pupil-suspicious {
  transform-box: fill-box;
  transform-origin: center;
  animation: rc-side-eye 2.4s ease-in-out infinite;
}

.reaction-popcorn {
  position: absolute;
  left: -22px;
  bottom: 4px;
  width: 34px;
  height: 34px;
  z-index: 3;
  overflow: visible; /* kernels fly outside the 40x40 viewBox mid-animation -- an SVG clips to its own viewBox by default */
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.5));
}

/* The bucket itself gets launched too, not just the kernels -- he's
   so startled he throws the whole thing. This transform composes
   with each kernel's own animation below, so the kernels scatter
   away from a bucket that's also being tossed around. */
[data-mood="scared"] .reaction-popcorn { animation: rc-bucket-toss 1.1s ease-out infinite; }
@keyframes rc-bucket-toss {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  20% { transform: translate(9px, -24px) rotate(-18deg); }
  45% { transform: translate(15px, -12px) rotate(22deg); }
  70% { transform: translate(11px, 3px) rotate(-10deg); }
  88% { transform: translate(4px, -3px) rotate(5deg); }
}

.rc-popcorn-bucket { fill: #8a6d3c; }
.rc-popcorn-bucket-rim { fill: #d1a35c; }
.rc-popcorn-kernel {
  fill: #ece6dc;
  stroke: #0b0a09;
  stroke-width: 0.5;
  transform-box: fill-box;
  transform-origin: center;
}

/* Popcorn goes flying for a horror pick -- each kernel gets its own
   erratic flight path (not just a shared path offset in time) so the
   whole bucket reads as a chaotic little explosion instead of five
   kernels doing the same hop in sequence. */
[data-mood="scared"] .rc-popcorn-kernel:nth-of-type(1) { animation: rc-pop-1 1.05s ease-out infinite; }
[data-mood="scared"] .rc-popcorn-kernel:nth-of-type(2) { animation: rc-pop-2 0.95s ease-out infinite 0.12s; }
[data-mood="scared"] .rc-popcorn-kernel:nth-of-type(3) { animation: rc-pop-3 1.15s ease-out infinite 0.24s; }
[data-mood="scared"] .rc-popcorn-kernel:nth-of-type(4) { animation: rc-pop-4 0.9s ease-out infinite 0.36s; }
[data-mood="scared"] .rc-popcorn-kernel:nth-of-type(5) { animation: rc-pop-5 1.1s ease-out infinite 0.48s; }

@keyframes rc-pop-1 {
  0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
  15% { transform: translate(14px, -30px) scale(1.4) rotate(-40deg); }
  35% { transform: translate(38px, -58px) scale(1.15) rotate(-90deg); }
  55% { transform: translate(52px, -40px) scale(1) rotate(-130deg); }
  75%, 92% { transform: translate(50px, -32px) scale(0.9) rotate(-140deg); }
}
@keyframes rc-pop-2 {
  0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
  18% { transform: translate(18px, -34px) scale(1.5) rotate(35deg); }
  40% { transform: translate(45px, -62px) scale(1.2) rotate(80deg); }
  60% { transform: translate(62px, -30px) scale(1.05) rotate(110deg); }
  78%, 94% { transform: translate(60px, -18px) scale(0.9) rotate(120deg); }
}
@keyframes rc-pop-3 {
  0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
  12% { transform: translate(10px, -26px) scale(1.3) rotate(-25deg); }
  32% { transform: translate(30px, -64px) scale(1.2) rotate(-70deg); }
  52% { transform: translate(40px, -50px) scale(1) rotate(-110deg); }
  72%, 90% { transform: translate(38px, -48px) scale(0.85) rotate(-105deg); }
}
@keyframes rc-pop-4 {
  0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
  20% { transform: translate(20px, -22px) scale(1.4) rotate(45deg); }
  42% { transform: translate(48px, -50px) scale(1.15) rotate(100deg); }
  62% { transform: translate(66px, -16px) scale(1) rotate(140deg); }
  80%, 95% { transform: translate(64px, -12px) scale(0.9) rotate(150deg); }
}
@keyframes rc-pop-5 {
  0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
  16% { transform: translate(12px, -28px) scale(1.35) rotate(-30deg); }
  36% { transform: translate(34px, -56px) scale(1.1) rotate(-75deg); }
  56% { transform: translate(46px, -44px) scale(1) rotate(-115deg); }
  76%, 91% { transform: translate(44px, -46px) scale(0.88) rotate(-110deg); }
}

/* The drink goes flying right along with the popcorn -- both hands
   throw everything up at once when he's startled. Mirrored off the
   opposite edge of the frame so the two props launch from either
   side and rain back down across him. */
.reaction-drink {
  position: absolute;
  right: -22px;
  bottom: 4px;
  width: 34px;
  height: 34px;
  z-index: 3;
  overflow: visible;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.5));
}

[data-mood="scared"] .reaction-drink { animation: rc-cup-toss 1.1s ease-out infinite 0.08s; }
@keyframes rc-cup-toss {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  20% { transform: translate(-9px, -26px) rotate(20deg); }
  45% { transform: translate(-16px, -10px) rotate(-24deg); }
  70% { transform: translate(-12px, 4px) rotate(12deg); }
  88% { transform: translate(-4px, -2px) rotate(-6deg); }
}

.rc-drink-cup { fill: #7a8a94; }
.rc-drink-cup-rim { fill: #a9b8c1; }
.rc-drink-droplet {
  fill: #bcd6e0;
  stroke: #3d5560;
  stroke-width: 0.3;
  transform-box: fill-box;
  transform-origin: center;
}

[data-mood="scared"] .rc-drink-droplet:nth-of-type(1) { animation: rc-drop-1 1s ease-out infinite; }
[data-mood="scared"] .rc-drink-droplet:nth-of-type(2) { animation: rc-drop-2 0.9s ease-out infinite 0.1s; }
[data-mood="scared"] .rc-drink-droplet:nth-of-type(3) { animation: rc-drop-3 1.1s ease-out infinite 0.2s; }
[data-mood="scared"] .rc-drink-droplet:nth-of-type(4) { animation: rc-drop-4 0.95s ease-out infinite 0.3s; }

@keyframes rc-drop-1 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0; }
  15% { transform: translate(-14px, -28px) scale(1.3); opacity: 1; }
  45% { transform: translate(-40px, -54px) scale(1.1); opacity: 1; }
  75%, 92% { transform: translate(-52px, -34px) scale(0.85); opacity: 0.9; }
}
@keyframes rc-drop-2 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0; }
  18% { transform: translate(-18px, -32px) scale(1.4); opacity: 1; }
  48% { transform: translate(-46px, -58px) scale(1.15); opacity: 1; }
  78%, 94% { transform: translate(-62px, -18px) scale(0.85); opacity: 0.9; }
}
@keyframes rc-drop-3 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0; }
  12% { transform: translate(-10px, -24px) scale(1.25); opacity: 1; }
  42% { transform: translate(-32px, -60px) scale(1.1); opacity: 1; }
  72%, 90% { transform: translate(-40px, -46px) scale(0.8); opacity: 0.85; }
}
@keyframes rc-drop-4 {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0; }
  20% { transform: translate(-20px, -20px) scale(1.35); opacity: 1; }
  50% { transform: translate(-50px, -46px) scale(1.1); opacity: 1; }
  80%, 95% { transform: translate(-64px, -10px) scale(0.85); opacity: 0.9; }
}

/* Every prop below lives inside the same SVG coordinate space as the
   face itself (not a separately positioned sibling element like the
   popcorn bucket), so there's no cross-element alignment to get
   wrong -- the lesson from the spit-take prop this replaced, which
   depended on a separate cup graphic lining up with the mouth. */
.rc-swoon-hearts, .rc-sleepy-zzz { display: none; }
[data-mood="swoon"] .rc-swoon-hearts { display: block; }
[data-mood="sleepy"] .rc-sleepy-zzz { display: block; }

.rc-float-heart {
  fill: #c9505f;
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
}
[data-mood="swoon"] .rc-float-heart-1 { animation: rc-heart-float 2.2s ease-out infinite; }
[data-mood="swoon"] .rc-float-heart-2 { animation: rc-heart-float 2.2s ease-out infinite 0.5s; }
[data-mood="swoon"] .rc-float-heart-3 { animation: rc-heart-float 2.2s ease-out infinite 1s; }

@keyframes rc-heart-float {
  0% { transform: translateY(0) scale(0.6); opacity: 0; }
  20% { transform: translateY(-3px) scale(1); opacity: 1; }
  100% { transform: translateY(-16px) scale(0.85); opacity: 0; }
}

@keyframes rc-swoon-sway {
  0%, 100% { transform: rotate(0deg) translateY(0); }
  25% { transform: rotate(-3deg) translateY(-1px); }
  50% { transform: rotate(0deg) translateY(-2px); }
  75% { transform: rotate(3deg) translateY(-1px); }
}

.rc-z {
  font-family: var(--serif);
  font-weight: bold;
  fill: #cbb89a;
  opacity: 0;
}
.rc-z-1 { font-size: 8px; }
.rc-z-2 { font-size: 6px; }
.rc-z-3 { font-size: 5px; }
[data-mood="sleepy"] .rc-z-1 { animation: rc-zzz-float 3s ease-in-out infinite; }
[data-mood="sleepy"] .rc-z-2 { animation: rc-zzz-float 3s ease-in-out infinite 1s; }
[data-mood="sleepy"] .rc-z-3 { animation: rc-zzz-float 3s ease-in-out infinite 2s; }

@keyframes rc-zzz-float {
  0% { transform: translate(0, 0); opacity: 0; }
  15% { opacity: 1; }
  85% { opacity: 0.7; }
  100% { transform: translate(6px, -10px); opacity: 0; }
}

@keyframes rc-sleepy-nod {
  0%, 15% { transform: rotate(0deg) translateY(0); }
  45%, 55% { transform: rotate(4deg) translateY(3px); }
  75%, 100% { transform: rotate(0deg) translateY(0); }
}

@keyframes rc-wink-tilt {
  0%, 100% { transform: rotate(0deg); }
  30%, 50% { transform: rotate(-6deg); }
  70% { transform: rotate(0deg); }
}

@keyframes rc-dizzy-wobble {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-5deg); }
  75% { transform: rotate(5deg); }
}

@keyframes rc-suspicious-tilt {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(-2deg); }
}

@keyframes rc-side-eye {
  0%, 20%, 100% { transform: translateX(0); }
  40%, 60% { transform: translateX(2.5px); }
}

.reaction-cam-scanline {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    rgba(0,0,0,0.25) 0px,
    rgba(0,0,0,0.25) 1px,
    transparent 1px,
    transparent 3px
  );
  pointer-events: none;
}

.reaction-cam-label {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

@keyframes rc-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-2px); }
}

@keyframes rc-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-1.5px); }
  75% { transform: translateX(1.5px); }
}

@keyframes rc-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}

@keyframes rc-tense-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.035); }
}

@keyframes rc-thrilled-jiggle {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  25% { transform: translate(-1.5px, -2px) rotate(-3deg); }
  50% { transform: translate(0, -3px) rotate(0deg); }
  75% { transform: translate(1.5px, -2px) rotate(3deg); }
}

@keyframes rc-blink {
  0%, 92%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(0.1); }
}

@media (prefers-reduced-motion: reduce) {
  .reaction-figure,
  [data-mood="scared"] .reaction-figure,
  [data-mood="laughing"] .reaction-figure,
  [data-mood="tense"] .reaction-figure,
  [data-mood="thrilled"] .reaction-figure,
  [data-mood="swoon"] .reaction-figure,
  [data-mood="sleepy"] .reaction-figure,
  [data-mood="wink"] .reaction-figure,
  [data-mood="dizzy"] .reaction-figure,
  [data-mood="suspicious"] .reaction-figure,
  [data-mood="suspicious"] .rc-pupil-suspicious,
  [data-mood="scared"] .reaction-popcorn,
  [data-mood="scared"] .reaction-drink,
  [data-mood="scared"] .rc-popcorn-kernel:nth-of-type(1),
  [data-mood="scared"] .rc-popcorn-kernel:nth-of-type(2),
  [data-mood="scared"] .rc-popcorn-kernel:nth-of-type(3),
  [data-mood="scared"] .rc-popcorn-kernel:nth-of-type(4),
  [data-mood="scared"] .rc-popcorn-kernel:nth-of-type(5),
  [data-mood="scared"] .rc-drink-droplet:nth-of-type(1),
  [data-mood="scared"] .rc-drink-droplet:nth-of-type(2),
  [data-mood="scared"] .rc-drink-droplet:nth-of-type(3),
  [data-mood="scared"] .rc-drink-droplet:nth-of-type(4),
  [data-mood="swoon"] .rc-float-heart-1,
  [data-mood="swoon"] .rc-float-heart-2,
  [data-mood="swoon"] .rc-float-heart-3,
  [data-mood="sleepy"] .rc-z-1,
  [data-mood="sleepy"] .rc-z-2,
  [data-mood="sleepy"] .rc-z-3 {
    animation: none;
  }
}

/* Shrink rather than hide on narrow screens -- this is the one place
   most phone visitors will ever see the mascot react, especially now
   that touch has its own first-tap preview (see script.js). Scaling
   the whole fixed-position group keeps every child's hand-tuned
   pixel offset (popcorn bucket, drink cup, label) proportional
   without having to recompute each one per breakpoint. */
@media (max-width: 480px) {
  .reaction-cam {
    transform: translateX(-50%) scale(0.72);
    transform-origin: bottom center;
  }
}

/* On-brand keyboard focus ring -- the browser default is a blue outline
   that clashes with this palette. Every interactive element here is a
   real <a>/<button>, so :focus-visible alone (no tabindex hacks) covers
   full keyboard operability. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
