/* Our Episode — speech bubbles (the SpeechBubble spec, "07 · Speech bubbles"). Tokens only.
   Rendered inside the TV screen, under the scanlines, so they read as part of the broadcast. Sizes are the spec's at a
   760px TV (screen 490px wide; talk text = 5.3% of the screen width) and scale with --ep-bubble-scale, which the TV
   sets from its screen width (1 at the reference size).

   <div class="ep-bubble" data-variant="talk|shout|whisper|thought" data-tail="left|center|right|none">
     <span class="ep-bubble-text">…</span>
   </div>
   <div class="ep-bubble" data-variant="caption">Meanwhile, upstairs…</div>                                        */

.ep-bubble {
  --s: var(--ep-bubble-scale, 1);
  --b-line: calc(2.5px * var(--s));
  --b-ink: var(--ep-ink);
  --b-edge: var(--ep-den);
  --b-pop: calc(3px * var(--s));
  --tail-x: 50%;
  position: relative; box-sizing: border-box; width: max-content; max-width: 12em;
  padding: calc(12px * var(--s)) calc(18px * var(--s)) calc(13px * var(--s));
  border-radius: calc(16px * var(--s)); border: var(--b-line) solid var(--b-edge);
  background: var(--ep-cream); color: var(--b-ink); box-shadow: var(--b-pop) var(--b-pop) 0 var(--b-edge);
  font: 400 calc(26px * var(--s))/1.12 var(--ep-font-display); text-align: center; text-wrap: balance;
}
.ep-bubble[data-tail="left"] { --tail-x: 22%; }
.ep-bubble[data-tail="right"] { --tail-x: 78%; }
/* the tail: a 16px square at 45°, 10px showing, pointing down at the speaker from directly above */
.ep-bubble::after {
  content: ""; position: absolute; left: var(--tail-x); bottom: calc(-10px * var(--s)); width: calc(16px * var(--s)); height: calc(16px * var(--s));
  margin-left: calc(-8px * var(--s)); background: var(--ep-cream); border-right: var(--b-line) solid var(--b-edge);
  border-bottom: var(--b-line) solid var(--b-edge); transform: rotate(45deg);
}
.ep-bubble[data-tail="none"]::after, .ep-bubble[data-variant="thought"]::after, .ep-bubble[data-variant="caption"]::after { display: none; }
/* Our addition to the spec: when there's no room above the speaker (our people stand tall in the frame), the bubble
   sits beside the head and its tail points sideways at it: "to-right" (bubble on the left) / "to-left". */
.ep-bubble[data-tail="to-right"]::after, .ep-bubble[data-tail="to-left"]::after { bottom: auto; top: 58%; margin: calc(-8px * var(--s)) 0 0; }
.ep-bubble[data-tail="to-right"]::after { left: auto; right: calc(-10px * var(--s)); transform: rotate(-45deg); }
.ep-bubble[data-tail="to-left"]::after { left: calc(-10px * var(--s)); transform: rotate(135deg); }
.ep-bubble[data-tail="to-right"] { --tail-x: 100%; }
.ep-bubble[data-tail="to-left"] { --tail-x: 0%; }

.ep-bubble[data-variant="shout"] {
  --b-line: calc(3px * var(--s)); --b-edge: var(--ep-tomato); --b-pop: calc(4px * var(--s));
  padding: calc(12px * var(--s)) calc(20px * var(--s)) calc(13px * var(--s)); border-radius: calc(10px * var(--s));
  font-size: calc(30px * var(--s)); rotate: -2deg;
}
.ep-bubble[data-variant="whisper"] {
  --b-line: calc(2px * var(--s)); --b-ink: var(--ep-ink-2);
  padding: calc(10px * var(--s)) calc(16px * var(--s)) calc(11px * var(--s));
  border-style: dashed; box-shadow: none; font-size: calc(21px * var(--s));
}
.ep-bubble[data-variant="whisper"]::after { border-right-style: dashed; border-bottom-style: dashed; }
.ep-bubble[data-variant="thought"] {
  padding: calc(14px * var(--s)) calc(22px * var(--s)) calc(15px * var(--s)); border-radius: var(--ep-radius-full); font-size: calc(24px * var(--s));
}
/* the thought's two-dot tail, under the side the speaker is on */
.ep-bubble-dots { position: absolute; top: 100%; left: var(--tail-x); display: flex; flex-direction: column; align-items: flex-start;
  gap: calc(3px * var(--s)); margin-top: calc(4px * var(--s)); pointer-events: none; }
.ep-bubble-dots::before, .ep-bubble-dots::after { content: ""; box-sizing: border-box; border-radius: 50%; background: var(--ep-cream);
  border: var(--b-line) solid var(--ep-den); }
.ep-bubble-dots::before { width: calc(12px * var(--s)); height: calc(12px * var(--s)); margin-left: calc(-6px * var(--s)); }
.ep-bubble-dots::after { width: calc(7px * var(--s)); height: calc(7px * var(--s)); margin-left: calc(2px * var(--s)); border-width: calc(2px * var(--s)); }
.ep-bubble[data-tail="none"] .ep-bubble-dots { display: none; }

/* the narrator: no speaker, no tail */
.ep-bubble[data-variant="caption"] {
  max-width: none; padding: calc(7px * var(--s)) calc(12px * var(--s)) calc(8px * var(--s)); border: 0; border-radius: var(--ep-radius-xs);
  background: var(--ep-mustard); color: var(--ep-ink); box-shadow: var(--b-pop) var(--b-pop) 0 var(--ep-ink);
  font: var(--ep-text-label); font-size: calc(15px * var(--s)); letter-spacing: .12em; text-transform: uppercase; white-space: nowrap;
}

/* the TV shows a bubble's whole line at once (no empty box); .off is any not-yet-shown part, which keeps its space */
.ep-bubble .off { visibility: hidden; }

/* enter: scale .85 -> 1 from the tail, 160ms; exit: fade, 120ms */
@keyframes ep-bubble-in { from { scale: .85; opacity: 0; } }
@keyframes ep-bubble-out { to { opacity: 0; } }
.ep-bubble.is-in { transform-origin: var(--tail-x) 100%; animation: ep-bubble-in var(--ep-dur-ui) var(--ep-ease) both; }
.ep-bubble.is-out { animation: ep-bubble-out 120ms linear both; }
@media (prefers-reduced-motion: reduce) { .ep-bubble.is-in, .ep-bubble.is-out { animation: none; } }
