

.wu-stage { margin-top: 0; max-width: 1080px; }


.wu-screen {
  position: relative; aspect-ratio: 16 / 9; min-height: 420px;
  border-radius: 10px 10px 0 0; overflow: hidden;
  background:
    radial-gradient(760px 320px at 50% 12%, rgba(0,212,255,.09), transparent 70%),
    repeating-linear-gradient(to bottom, rgba(255,255,255,.022) 0 1px, transparent 1px 3px),
    #05070d;
  border: 1px solid var(--border); border-bottom: 0;
  display: grid; place-items: center;
}


/* Every scene stacks in the same cell and the controller shows one.

   The scene wrapper does not fade. All of the dissolving happens one level
   down, at the shot, which is the only layer that should be crossfading:
   two nested fades multiply, and the product dips in the middle, which is
   the visible flicker at every scene change. The wrapper only holds itself
   in the render tree long enough for its last shot to dissolve out under
   the incoming scene's first shot. */
.wu-scene {
  grid-area: 1 / 1; width: 100%; height: 100%; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 26px 4%;
  contain: layout paint;
  opacity: 1; visibility: hidden;
  transition: visibility 0s .78s;
}

.wu-scene.on { visibility: visible; transition: visibility 0s 0s; }


/* ── skip ──
   Ghost pill in the corner of the screen. Present the whole time the film
   is running or paused, absent on the poster and after the end, because at
   those moments there is nothing to skip. */
.wu-skip {
  /* bottom corner, not top: the site nav is fixed over the top of the
     screen when the film is at the top of the page, and a skip button
     under the nav cannot be clicked */
  position: absolute; bottom: 20px; right: 16px; z-index: 7;
  background: rgba(5,7,13,.55); border: 1px solid rgba(255,255,255,.3);
  color: #fff; font-family: 'Syne', sans-serif; font-weight: 600;
  font-size: .76rem; letter-spacing: .07em; text-transform: uppercase;
  padding: 8px 15px; border-radius: 999px; cursor: pointer;
  backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden;
  transition: opacity .25s, visibility .25s, border-color .18s;
}

.wu-stage.playing .wu-skip, .wu-stage.paused .wu-skip {
  opacity: 1; visibility: visible; }

.wu-stage.ended .wu-skip { opacity: 0; visibility: hidden; }

.wu-skip:hover { border-color: var(--cyan); }


/* ── the sound invitation ──
   Only exists during the muted first play of a session. One pulse ring so
   it reads as the thing to press, killed under reduced motion. */
.wu-sound {
  position: absolute; left: 50%; bottom: 20px; transform: translateX(-50%);
  z-index: 7; display: inline-flex; align-items: center; gap: 8px;
  background: rgba(0,212,255,.16); border: 1px solid var(--cyan);
  color: #fff; font-family: 'Syne', sans-serif; font-weight: 600;
  font-size: .84rem; padding: 11px 20px; border-radius: 999px;
  cursor: pointer; backdrop-filter: blur(2px);
  animation: wuSoundPulse 2.4s ease-out infinite;
}

.wu-sound[hidden] { display: none; }


/* ── the minimized strip ──
   Stands in for the whole stage after the film has been seen once this
   session. Slim on purpose: the page is the point now, the film is an
   offer. */
.wu-mini {
  display: flex; align-items: center; gap: 15px;
  width: 100%; max-width: 660px; margin: 0 auto;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 18px 10px 10px;
  cursor: pointer; color: var(--white); text-align: left;
  font-family: inherit;
  transition: border-color .18s, background .18s;
}

.wu-mini:hover { border-color: var(--cyan); background: rgba(0,212,255,.05); }

.wu-mini[hidden], .wu-stage[hidden] { display: none; }

.wu-mini-shot {
  width: 88px; aspect-ratio: 16 / 9; flex: none; border-radius: 6px;
  border: 1px solid var(--border);
  background:
    radial-gradient(60px 26px at 50% 18%, rgba(0,212,255,.22), transparent 70%),
    #05070d;
  display: grid; place-items: center;
}

.wu-mini-tri {
  width: 0; height: 0; margin-left: 3px;
  border-left: 13px solid var(--cyan);
  border-top: 8px solid transparent; border-bottom: 8px solid transparent;
}

.wu-mini-l { min-width: 0; }

.wu-mini-l b { display: block; font-family: 'Syne', sans-serif;
  font-size: .94rem; line-height: 1.25; }

.wu-mini-l small { color: var(--muted); font-size: .73rem; }

.wu-mini-go {
  margin-left: auto; flex: none;
  font-family: 'IBM Plex Mono', monospace; font-size: .7rem;
  letter-spacing: .13em; text-transform: uppercase; color: var(--cyan);
  border: 1px solid rgba(0,212,255,.45); border-radius: 999px;
  padding: 7px 16px;
}
@media (max-width: 560px) {
  .wu-mini-go { display: none; }
  .wu-skip { bottom: 14px; right: 10px; padding: 7px 12px; }
  /* the character name tag rides the bottom left of the frame on a phone,
     so the sound pill moves up a row instead of sitting on it */
  .wu-sound { bottom: 80px; }
}


/* ── the play button ── */
.wu-play {
  position: absolute; inset: 0; z-index: 6; width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  background: rgba(5,7,13,.72); backdrop-filter: blur(3px);
  border: 0; cursor: pointer; color: #fff; font-family: inherit;
  transition: opacity .4s ease, visibility .4s;
}

.wu-play[hidden], .wu-stage.playing .wu-play { opacity: 0; visibility: hidden;
  pointer-events: none; backdrop-filter: none; }

.wu-play-tri {
  width: 78px; height: 78px; border-radius: 50%;
  background: var(--cyan); position: relative;
  transition: transform .25s cubic-bezier(.2,1.4,.4,1);
}

.wu-play-tri::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid rgba(0,212,255,.5); animation: wuPulse 2.6s ease-out infinite;
}

.wu-play-tri::after {
  content: ''; position: absolute; left: 56%; top: 50%; transform: translate(-50%,-50%);
  border-style: solid; border-width: 15px 0 15px 25px;
  border-color: transparent transparent transparent #04121a;
}

.wu-play:hover .wu-play-tri { transform: scale(1.09); }

.wu-play-l {
  font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1.06rem;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
}

.wu-play-l small {
  font-family: 'IBM Plex Mono', ui-monospace, monospace; font-weight: 400;
  font-size: .66rem; letter-spacing: .2em; text-transform: uppercase;
  color: rgba(255,255,255,.55);
}


.wu-brand {
  position: absolute; right: 16px; bottom: 14px; z-index: 5;
  font-family: 'Syne', sans-serif; font-weight: 700; font-size: .74rem;
  letter-spacing: .04em; color: rgba(255,255,255,.32);
  opacity: 0; transition: opacity .4s ease;
}

.wu-stage.playing .wu-brand, .wu-stage.paused .wu-brand { opacity: 1; }

.wu-chapter {
  position: absolute; left: 18px; top: 16px; z-index: 5;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .62rem; letter-spacing: .2em; text-transform: uppercase;
  color: rgba(255,255,255,.55); padding: 5px 11px; border-radius: 4px;
  background: rgba(0,0,0,.45); border: 1px solid rgba(255,255,255,.12);
  opacity: 0; transition: opacity .35s ease;
}

.wu-stage.playing .wu-chapter, .wu-stage.paused .wu-chapter { opacity: 1; }


/* ── scene 1: inbox ── */
.wu-mail, .wu-msg, .wu-wire {
  width: min(640px, 100%); text-align: left; border-radius: 8px; overflow: hidden;
  border: 1px solid rgba(255,255,255,.14); background: #0b1017;
  box-shadow: 0 12px 30px rgba(0,0,0,.55);
}

.wu-bar { display: flex; align-items: center; gap: 7px; padding: 10px 14px;
  background: #131b26; border-bottom: 1px solid rgba(255,255,255,.09); }

.wu-dot { width: 9px; height: 9px; border-radius: 50%; }

.wu-dot.r { background: #ff5f57; }
 .wu-dot.y { background: #febc2e; }
 .wu-dot.g { background: #28c840; }

.wu-bar-t { margin-left: 10px; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .64rem; letter-spacing: .14em; color: rgba(255,255,255,.5); }

.wu-row { display: grid; grid-template-columns: 158px 1fr auto; gap: 12px; align-items: center;
  padding: 13px 16px; border-bottom: 1px solid rgba(255,255,255,.05); font-size: .85rem; }

.wu-row.old { color: rgba(255,255,255,.32); }

.wu-row.new { color: #fff; background: rgba(0,212,255,.07);
  box-shadow: inset 3px 0 0 var(--cyan); }

.wu-scene.on .wu-row.new { animation: wuArrive .7s cubic-bezier(.2,.9,.3,1) .5s both; }

.wu-from { font-weight: 700; }

.wu-sub, .wu-from { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.wu-time { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .68rem;
  color: rgba(255,255,255,.38); }


/* ── scene 2: the message ── */
.wu-msg { padding-bottom: 18px; }

.wu-msg-head { display: flex; align-items: center; gap: 13px; flex-wrap: wrap;
  padding: 15px 18px; background: #131b26; border-bottom: 1px solid rgba(255,255,255,.09); }

.wu-avatar { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  background: #2f6fae; color: #fff; font-weight: 700; font-size: .86rem; flex-shrink: 0; }

.wu-who { display: flex; flex-direction: column; }

.wu-who strong { color: #fff; font-size: .95rem; }

.wu-who span { color: rgba(255,255,255,.48); font-size: .74rem; }

.wu-addr { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; }

.wu-addr-l { font-size: .66rem; color: rgba(255,255,255,.4); }

.wu-addr-v { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .74rem;
  color: rgba(255,255,255,.72); }

.wu-fake { position: relative; color: #ff8fa3; }

.wu-fake::after { content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 2px;
  background: #ff4d6d; transform: scaleX(0); transform-origin: left; }

.wu-scene.on .wu-fake::after { animation: wuUnderline .5s cubic-bezier(.4,0,.2,1) 1.9s forwards; }

.wu-body { margin: 17px 20px 0; color: rgba(255,255,255,.82); font-size: .93rem; line-height: 1.7; }

.wu-body strong { color: #fff; }

.wu-sig { margin: 13px 20px 0; font-size: .76rem; color: rgba(255,255,255,.36); font-style: italic; }

.wu-flagline { display: block; margin: 15px 20px 0; padding: 10px 14px; border-radius: 5px;
  background: rgba(255,77,109,.16); border: 1px solid rgba(255,77,109,.55);
  font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .72rem;
  color: #ffb3c1; line-height: 1.5; opacity: 0; }

.wu-scene.on .wu-flagline { animation: wuFade .5s ease 2.4s forwards; }


/* ── scene 3: the wire ── */
.wu-wire { padding: 18px 20px 22px; position: relative; }

.wu-wire-h { display: flex; justify-content: space-between; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .66rem; letter-spacing: .18em; text-transform: uppercase; color: rgba(255,255,255,.55);
  padding-bottom: 12px; border-bottom: 1px solid rgba(255,255,255,.09); }

.wu-wire-h span { color: var(--cyan); }

.wu-wl { display: flex; justify-content: space-between; gap: 16px; align-items: baseline;
  padding: 11px 0; border-bottom: 1px solid rgba(255,255,255,.05); font-size: .84rem; }

.wu-wl span { color: rgba(255,255,255,.45); }

.wu-wl b { color: #fff; font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .82rem; }

.wu-wl.amt b { font-family: 'Bebas Neue', sans-serif; font-size: 1.9rem; color: #ff8fa3; }

.wu-send { display: block; margin-top: 15px; padding: 13px; border-radius: 5px; text-align: center;
  background: #1f8fe0; color: #fff; font-family: 'Syne', sans-serif; font-weight: 700; font-size: .9rem; }

.wu-scene.on .wu-send { animation: wuArm 1.2s ease-in-out 1.4s infinite; }

.wu-cursor { position: absolute; right: 44px; bottom: 26px; width: 15px; height: 22px; background: #fff;
  clip-path: polygon(0 0, 0 78%, 26% 60%, 44% 100%, 62% 88%, 46% 52%, 78% 50%);
  filter: drop-shadow(0 2px 5px rgba(0,0,0,.7)); opacity: 0; }

.wu-scene.on .wu-cursor { animation: wuCursor 1.8s cubic-bezier(.3,.8,.4,1) 1.0s infinite; }


/* ── scene 4: the Guardian ── */
.wu-hero { position: relative; width: clamp(200px, 26vw, 300px); }

.wu-blocked { position: absolute; top: -6px; right: -18px; z-index: 3;
  font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .64rem; letter-spacing: .14em;
  padding: 5px 10px; border-radius: 5px; color: #38f8a7;
  background: rgba(56,248,167,.12); border: 1px solid rgba(56,248,167,.5); }


/* ── scene 5: the signals ── */
.wu-signals { list-style: none; margin: 0; padding: 0; width: min(620px, 100%);
  display: grid; gap: 8px; text-align: left; }

.wu-signals li { display: grid; grid-template-columns: 26px 1fr; gap: 5px 12px; align-items: baseline;
  padding: 10px 15px; border-radius: 5px; background: rgba(255,77,109,.07);
  border: 1px solid rgba(255,77,109,.26); opacity: 0; }

.wu-scene.on .wu-signals li {
  animation: wuSig .5s cubic-bezier(.2,.9,.3,1) forwards;
  animation-delay: calc(.5s + var(--i) * .55s);
}

.wu-sflag { grid-row: 1 / 3; align-self: center; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; background: rgba(255,77,109,.18);
  border: 1px solid rgba(255,77,109,.5); color: #ff8fa3;
  font-family: 'Bebas Neue', sans-serif; font-size: .9rem; }

.wu-sh { color: #fff; font-weight: 700; font-size: .87rem; }

.wu-sd { color: rgba(255,255,255,.55); font-size: .76rem;
  font-family: 'IBM Plex Mono', ui-monospace, monospace; }


/* ── scene 6: the money ── */
.wu-saved { text-align: center; }

.wu-amt { display: block; font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(3rem, 9vw, 5.6rem); line-height: 1; color: #38f8a7;
  text-shadow: 0 0 44px rgba(56,248,167,.4); }

.wu-scene.on .wu-amt { animation: wuPop .8s cubic-bezier(.2,1.3,.35,1) .3s both; }

.wu-amt-l { display: block; margin-top: 9px; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .68rem; letter-spacing: .24em; text-transform: uppercase; color: rgba(56,248,167,.85); }


/* ── scene 7: the close ── */
.wu-close { text-align: center; }

.wu-close-k { display: block; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .66rem; letter-spacing: .3em; text-transform: uppercase; color: var(--cyan); margin-bottom: 16px; }

.wu-close strong { display: block; font-family: 'Bebas Neue', sans-serif; font-weight: 400;
  font-size: clamp(1.9rem, 5.4vw, 3.8rem); line-height: .98; color: #fff; letter-spacing: .02em; }

.wu-close strong em { font-style: normal; color: #38f8a7; }

.wu-close-s { display: block; margin-top: 18px; color: rgba(255,255,255,.6); font-size: .9rem; }


/* ── the end card ──────────────────────────────────────────────────
   A finished film that keeps its full sixteen by nine frame is a large
   dead rectangle in the middle of the page. When the story ends the stage
   collapses to a band, the last frame goes, and what is left is the one
   thing a viewer wants next: watch it again, or find out what it costs. */
.wu-end {
  position: absolute; inset: 0; z-index: 7;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; text-align: center; padding: 26px 6%;
  background:
    radial-gradient(600px 240px at 50% 40%, rgba(0,212,255,.10), transparent 70%),
    rgba(5,7,13,.94);
  opacity: 0; visibility: hidden;
  transition: opacity .45s ease, visibility 0s .45s;
}

.wu-stage.ended .wu-end { opacity: 1; visibility: visible; transition: opacity .45s ease .1s, visibility 0s; }

.wu-end[hidden] { display: flex; }

.wu-end-k { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .64rem;
  letter-spacing: .3em; text-transform: uppercase; color: var(--cyan); }

.wu-end-h { font-family: 'Syne', sans-serif; font-weight: 800;
  font-size: clamp(1.1rem, 2.6vw, 1.7rem); color: #fff; max-width: 22ch; line-height: 1.25; }

.wu-end-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 4px; }

.wu-end-btn {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 11px 20px; border-radius: 999px; font-family: 'Syne', sans-serif;
  font-weight: 700; font-size: .86rem; text-decoration: none;
  border: 1px solid rgba(255,255,255,.22); background: rgba(255,255,255,.06);
  color: #fff; transition: background .2s ease, border-color .2s ease, transform .2s ease;
}

.wu-end-btn:hover { transform: translateY(-2px); border-color: var(--cyan);
  background: rgba(0,212,255,.14); }

.wu-end-btn.again { background: var(--cyan); color: #04121a; border-color: var(--cyan); }

.wu-end-btn.again:hover { background: #7fe9ff; }

.wu-end-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }


/* the frame gives its height back once there is nothing left to watch */
.wu-screen { transition: min-height .5s cubic-bezier(.3,.8,.3,1), aspect-ratio .5s; }

.wu-stage.ended .wu-screen { aspect-ratio: auto; min-height: 250px; }

.wu-stage.ended .wu-scene, .wu-stage.ended .wu-chapter { visibility: hidden; }
@media (max-width: 760px) {
  .wu-stage.ended .wu-screen { min-height: 290px; }
}


/* ── controls ── */
.wu-controls {
  display: flex; align-items: center; gap: 14px; padding: 14px 18px;
  background: #0a0f16; border: 1px solid var(--border); border-radius: 0 0 10px 10px;
}

.wu-btn {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center; color: #fff;
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.14);
  transition: background .2s ease, border-color .2s ease;
}

.wu-btn:hover { background: rgba(0,212,255,.16); border-color: var(--cyan); }

.wu-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }

.wu-ico-pause { width: 12px; height: 13px; border-left: 4px solid currentColor;
  border-right: 4px solid currentColor; }

.wu-btn.is-paused .wu-ico-pause { width: 0; height: 0; border: 0;
  border-style: solid; border-width: 7px 0 7px 12px;
  border-color: transparent transparent transparent currentColor; margin-left: 3px; }

.wu-ico-sound { width: 14px; height: 14px; border-radius: 2px;
  background: currentColor;
  clip-path: polygon(0 32%, 32% 32%, 62% 0, 62% 100%, 32% 68%, 0 68%); }

.wu-btn.muted .wu-ico-sound { opacity: .38; }

.wu-ico-replay { font-size: 1.2rem; line-height: 1; }


.wu-track { position: relative; flex: 1; height: 5px; border-radius: 3px;
  background: rgba(255,255,255,.10); cursor: pointer; }

.wu-track:focus-visible { outline: 2px solid var(--cyan); outline-offset: 6px; }

.wu-track i { display: block; height: 100%; width: 0; border-radius: 3px;
  background: linear-gradient(90deg, var(--cyan), var(--green)); }

.wu-dotnav { position: absolute; top: 50%; width: 20px; height: 20px; margin: -10px 0 0 -10px;
  border: 0; background: none; cursor: pointer; display: grid; place-items: center; padding: 0; }

.wu-dotnav span { width: 8px; height: 8px; border-radius: 50%;
  background: rgba(255,255,255,.3); border: 1px solid rgba(255,255,255,.35);
  transition: background .2s ease, transform .2s ease; display: block; }

.wu-dotnav:hover span { background: var(--cyan); transform: scale(1.35); }

.wu-dotnav.done span { background: var(--cyan); border-color: var(--cyan); }

.wu-dotnav.now span { background: #fff; border-color: #fff; transform: scale(1.5); }

.wu-dotnav:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; border-radius: 50%; }


.wu-time-l { flex-shrink: 0; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .72rem; color: rgba(255,255,255,.55); min-width: 88px; text-align: right; }


/* ── captions ── */
.wu-caps { position: relative; margin-top: 22px; min-height: 116px; }

.wu-cap { position: absolute; inset: 0; margin: 0; opacity: 0; visibility: hidden;
  color: rgba(255,255,255,.82); font-size: clamp(1rem, 1.9vw, 1.16rem); line-height: 1.72;
  max-width: 84ch;
  /* same handoff as the scenes: the old line clears before the new arrives,
     otherwise two paragraphs sit on top of each other mid transition */
  transform: translateY(6px);
  transition: opacity .16s ease-in, transform .16s ease-in, visibility 0s .16s; }

.wu-cap.on { opacity: 1; visibility: visible; transform: none;
  transition: opacity .34s cubic-bezier(.2,.9,.3,1) .16s,
              transform .42s cubic-bezier(.2,.9,.3,1) .16s, visibility 0s; }


/* ── the transcript, which is also the version machines read ── */
.wu-transcript { margin-top: 22px; border-top: 1px solid var(--border); padding-top: 16px; }

.wu-transcript summary { cursor: pointer; list-style: none; display: inline-flex;
  align-items: center; gap: 10px; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; color: var(--cyan); }

.wu-transcript summary::-webkit-details-marker { display: none; }

.wu-transcript summary::before { content: '+'; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; border: 1px solid rgba(0,212,255,.45);
  font-size: .9rem; line-height: 1; }

.wu-transcript[open] summary::before { content: '2'; }

.wu-transcript summary:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }

.wu-tr-body { margin-top: 18px; display: grid; gap: 14px; max-width: 82ch; }

.wu-tr-row { display: grid; grid-template-columns: 52px 1fr; gap: 4px 16px; }

.wu-tr-t { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .74rem;
  color: var(--cyan); padding-top: 2px; }

.wu-tr-s { font-family: 'Syne', sans-serif; font-weight: 700; font-size: .84rem; color: #fff; }

.wu-tr-row p { grid-column: 2; margin: 0; color: rgba(255,255,255,.72);
  font-size: .95rem; line-height: 1.65; }


.wu-after { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; margin-top: 44px; }
@media (max-width: 760px) {
  .wu-screen { aspect-ratio: auto; min-height: 560px; }
  .wu-row { grid-template-columns: 1fr auto; font-size: .78rem; }
  .wu-row .wu-sub { display: none; }
  .wu-addr { margin-left: 0; align-items: flex-start; width: 100%; }
  .wu-controls { flex-wrap: wrap; gap: 10px; }
  .wu-track { order: 3; flex-basis: 100%; }
  .wu-time-l { min-width: 0; font-size: .68rem; }
  .wu-caps { min-height: 170px; }
}
@media (prefers-reduced-motion: reduce) {
  .wu-scene { transition: visibility 0s; transform: none; }
  .wu-scene.on .ct-shot.on * { animation: none !important; opacity: 1 !important; }
  .wu-scene.on > *:not(.ct-shot) { animation: none !important; opacity: 1 !important; }
  .wu-fake::after { transform: scaleX(1); }
  .wu-play-tri::before { animation: none; }
  .wu-sound { animation: none; }
}



/* ═══════════════════════════════════════════════════════════════
   THE CARTOON
   Flat vector characters on a staged set, moved by camera pushes
   and per-limb poses rather than crossfades.
   ═══════════════════════════════════════════════════════════════ */

/* ── the character ── */
.ct-person { width: 100%; height: auto; display: block; overflow: visible; }

.ct-skin { fill: #f3c9a4; }

.ct-head { stroke: #d9a97f; stroke-width: 2; }

.ct-torso { stroke: #14375c; stroke-width: 2.5; }

.ct-collar { fill: #f3c9a4; }

.ct-chair { fill: #24313f; stroke: #16202b; stroke-width: 2.5; }

.ct-arm path { stroke: #3f7fbe; stroke-width: 19; fill: none; }

.ct-ceo .ct-arm path { stroke: #2b3744; stroke-width: 18; }

.ct-ceo .ct-brows path { stroke: #33241a; }

.ct-hand { fill: #f3c9a4; stroke: #d9a97f; stroke-width: 1.5; }

.ct-eye { fill: #23303c; }

.ct-brows path { stroke: #4a3222; stroke-width: 4.2; fill: none; stroke-linecap: round; }

.ct-mouth { stroke: #a4553f; stroke-width: 3.4; fill: none; stroke-linecap: round; opacity: 0; }

.ct-blush { fill: #f0a58c; opacity: .45; }

.ct-sweat { fill: #7fd8ff; opacity: 0; }


/* the pose is set by a class on the figure, one mouth at a time */
.ct-person[data-mood="neutral"] .ct-m-neutral,
.ct-person[data-mood="worry"]   .ct-m-worry,
.ct-person[data-mood="smile"]   .ct-m-smile { opacity: 1; }

.ct-person[data-mood="worry"] .ct-brows path:first-child { transform: translate(2px, 2px) rotate(5deg); }

.ct-person[data-mood="worry"] .ct-brows path:last-child  { transform: translate(-2px, 2px) rotate(-5deg); }

.ct-person[data-mood="worry"] .ct-sweat { opacity: 1; animation: ctSweat 1.8s ease-in-out infinite; }

.ct-person[data-mood="smile"] .ct-eyes ellipse { ry: 4; }

.ct-brows path { transform-box: fill-box; transform-origin: right center;
  transition: transform .45s cubic-bezier(.3,.8,.3,1); }

.ct-brows path:last-child { transform-origin: left center; }

/* she blinks */
.ct-eyes { animation: ctBlink 5.2s steps(1) infinite; transform-box: fill-box; transform-origin: center; }


/* ── the set ── */
.ct-desk { width: 100%; height: auto; display: block; overflow: visible; }

.ct-desktop { fill: #6f4a33; }

.ct-desk-body { fill: #4a3122; }

.ct-desk-edge { stroke: #8a5f43; stroke-width: 2; }

.ct-mug rect { fill: #e8eef4; }

.ct-mug path { stroke: #e8eef4; }

.ct-steam path { stroke: rgba(255,255,255,.4); stroke-width: 3; fill: none; stroke-linecap: round;
  animation: ctSteam 3s ease-in-out infinite; }

.ct-steam path:last-child { animation-delay: .8s; }

.ct-pot { fill: #c1663f; }

.ct-leaf { fill: #3f8f5c; transform-box: fill-box; transform-origin: bottom center;
  animation: ctLeaf 6s ease-in-out infinite; }

.ct-leaf:nth-of-type(2) { animation-delay: 1.2s; }

.ct-leaf:nth-of-type(3) { animation-delay: 2.4s; }

.ol-title {
  display: flex; align-items: center; gap: 12px; padding: 8px 12px;
  background: #2c3b8f; color: #fff; font-size: 12px;
}

.ol-logo { width: 16px; height: 14px; border-radius: 2px; background: #fff; position: relative; flex-shrink: 0; }

.ol-logo::after { content: ''; position: absolute; left: 2px; top: 2px; width: 7px; height: 10px;
  border-radius: 2px; background: #2c3b8f; }

.ol-title-t { font-weight: 600; }

.ol-search { flex: 1; max-width: 300px; background: rgba(255,255,255,.16); border-radius: 3px;
  padding: 3px 10px; font-size: 11px; color: rgba(255,255,255,.75); }

.ol-win { margin-left: auto; display: flex; gap: 12px; align-items: center; }

.ol-win i { width: 9px; height: 1px; background: rgba(255,255,255,.85); display: block; }

.ol-win i:nth-child(2) { height: 8px; border: 1px solid rgba(255,255,255,.85); background: none; }

.ol-win i.x { height: 9px; background: none; position: relative; }

.ol-win i.x::before, .ol-win i.x::after { content: ''; position: absolute; inset: 0;
  border-top: 1px solid rgba(255,255,255,.85); top: 4px; }

.ol-win i.x::before { transform: rotate(45deg); }
 .ol-win i.x::after { transform: rotate(-45deg); }


.ol-ribbon { display: flex; align-items: center; gap: 14px; padding: 7px 14px;
  background: #f3f2f1; border-bottom: 1px solid #e1dfdd; font-size: 11.5px; color: #444; }

.ol-tab { padding-bottom: 3px; }

.ol-tab.on { color: #2c3b8f; font-weight: 600; box-shadow: 0 2px 0 #2c3b8f; }

.ol-rsep { width: 1px; height: 14px; background: #d8d6d4; }

.ol-cmd { color: #333; }

.ol-cmd.new { background: #2c3b8f; color: #fff; border-radius: 3px; padding: 4px 11px; font-weight: 600; }


.ol-body { display: grid; grid-template-columns: 116px 196px 1fr; min-height: 254px; }

.ol-rail { min-width: 0; background: #f3f2f1; border-right: 1px solid #e1dfdd; padding: 10px 0; font-size: 12px; }

.ol-rail-h { padding: 3px 14px 8px; color: #605e5c; font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; }

.ol-folder { display: flex; align-items: center; gap: 9px; padding: 6px 14px; color: #201f1e; }

.ol-folder.sel { background: #e1dfdd; font-weight: 600; box-shadow: inset 3px 0 0 #2c3b8f; }

.ol-fi { width: 11px; height: 9px; border: 1.5px solid #4a5b9e; border-radius: 1px; flex-shrink: 0; }

.ol-badge { margin-left: auto; background: #2c3b8f; color: #fff; border-radius: 9px;
  font-size: 9.5px; padding: 1px 6px; }


.ol-list { border-right: 1px solid #e1dfdd; background: #fff; min-width: 0; }

.ol-list-h { padding: 9px 13px; font-size: 12px; font-weight: 600; color: #2c3b8f;
  border-bottom: 1px solid #edebe9; box-shadow: inset 0 -2px 0 #2c3b8f; }

.ol-list-h span { color: #605e5c; font-weight: 400; margin-left: 16px; box-shadow: none; }

.ol-mail { display: flex; gap: 9px; align-items: flex-start; padding: 9px 12px;
  border-bottom: 1px solid #f1efed; font-size: 11.5px; }

.ol-mail.sel { background: #eff6fc; box-shadow: inset 3px 0 0 #2c3b8f; }

.ol-av { width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0; color: #fff;
  display: grid; place-items: center; font-size: 10px; font-weight: 700; }

.ol-av.big { width: 36px; height: 36px; font-size: 13px; }

.ol-mid { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.ol-who { color: #201f1e; }

.ol-subj { color: #605e5c; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 118px; }

.ol-mail.unread .ol-who { font-weight: 700; }

.ol-mail.unread .ol-subj { color: #201f1e; font-weight: 600; }

.ol-when { margin-left: auto; color: #605e5c; font-size: 10.5px; white-space: nowrap; }


.ol-read { background: #fff; padding: 13px 16px; min-width: 0; overflow: hidden; }

.ol-read-h { display: flex; gap: 12px; align-items: flex-start; }

.ol-rh-mid { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

.ol-rh-subj { font-size: 14px; font-weight: 600; }

.ol-rh-from { font-size: 11.5px; color: #605e5c; }

.ol-addr { font-weight: 400; color: #605e5c; }

.ol-addr em { font-style: normal; position: relative; }

.ol-rh-time { margin-left: auto; font-size: 11px; color: #605e5c; white-space: nowrap; }

.ol-actions { display: flex; gap: 16px; margin: 11px 0 0; font-size: 11.5px; color: #2c3b8f; }

.ol-banner { margin: 11px 0 0; padding: 7px 11px; border-radius: 3px; font-size: 11px;
  background: #fff4ce; border-left: 4px solid #d29200; color: #3b3a39; opacity: 0; }

.ol-read-b { margin-top: 12px; font-size: 12.5px; line-height: 1.6; color: #201f1e; }

.ol-read-b p { margin: 0 0 9px; }

.ol-sig { color: #8a8886; font-style: italic; }


/* the lookalike domain gets caught in the act */
.ol.flag .ol-addr em { color: #a4262c; font-weight: 700; }

.ol.flag .ol-addr em::after {
  content: ''; position: absolute; left: -2px; right: -2px; bottom: -3px; height: 2px;
  background: #a4262c; transform: scaleX(0); transform-origin: left;
}

.ct-shot.on .ol.flag .ol-addr em::after {
  animation: ctUnderline .42s cubic-bezier(.4,0,.2,1)
             calc(var(--shot, 1.7s) * .1) forwards;
}

.ct-shot.on .ol.flag .ol-banner {
  animation: ctFade .4s ease calc(var(--shot, 1.7s) * .28) forwards; }


/* the quarantine card slams over the window */
.ol-quarantine {
  position: absolute; inset: 0; z-index: 4; display: flex; flex-direction: column;
  align-items: flex-end; justify-content: center; gap: 9px; text-align: right;
  padding-right: 7%; padding-left: 52%;
  background: rgba(5,12,20,.955);
  opacity: 0; visibility: hidden; transform: scale(1.06);
  transition: opacity .32s ease, transform .32s cubic-bezier(.2,1.3,.4,1), visibility .32s;
}

.ct-shot.on .ol.quarantined .ol-quarantine { opacity: 1; visibility: visible; transform: scale(1); }

.ol-q-mark { width: 62px; height: 62px; border-radius: 50%; border: 3px solid #38f8a7; position: relative; }

.ol-q-mark::after { content: ''; position: absolute; left: 17px; top: 28px; width: 26px; height: 13px;
  border-left: 4px solid #38f8a7; border-bottom: 4px solid #38f8a7; transform: rotate(-45deg); }

.ol-q-t { font-family: 'Syne', sans-serif; font-weight: 800; font-size: 1.16rem; color: #fff; }

.ol-q-s { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .68rem;
  letter-spacing: .14em; text-transform: uppercase; color: #38f8a7; }


/* ── the lookalike domain, magnified ── */
.ct-mag { width: min(560px, 94%); border-radius: 10px; overflow: hidden; text-align: left;
  background: #070d15; border: 1px solid rgba(255,77,109,.34);
  box-shadow: 0 12px 30px rgba(0,0,0,.55); padding: 16px 18px 18px; }

.ct-mag-k { display: block; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .6rem; letter-spacing: .24em; text-transform: uppercase;
  color: rgba(255,255,255,.5); margin-bottom: 12px; }

.ct-mag-row { display: flex; align-items: baseline; gap: 12px; padding: 6px 0; }

.ct-mag-l { font-size: .68rem; color: rgba(255,255,255,.42); min-width: 84px; }

.ct-mag-v { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .92rem;
  letter-spacing: .02em; }

.ct-mag-v.good { color: rgba(255,255,255,.78); }

.ct-mag-v.good b { color: #7fe9ff; font-weight: 400; }

.ct-mag-v.bad { color: #ffb3c1; }

.ct-mag-v.bad b.hit { color: #ff4d6d; font-weight: 700; position: relative; }

.ct-shot.on .ct-mag-v.bad b.hit::after {
  content: ''; position: absolute; left: -2px; right: -2px; bottom: -4px; height: 2px;
  background: #ff4d6d; transform: scaleX(0); transform-origin: left;
  animation: ctUnderline .4s cubic-bezier(.4,0,.2,1) calc(var(--shot, 1.7s) * .18) forwards; }

.ct-mag-zoom { display: flex; align-items: center; justify-content: center; gap: 16px;
  margin: 14px 0 10px; padding: 12px 0; border-top: 1px solid rgba(255,255,255,.08);
  border-bottom: 1px solid rgba(255,255,255,.08); opacity: 0; }

.ct-shot.on .ct-mag-zoom {
  animation: ctFade .45s ease calc(var(--shot, 1.7s) * .3) forwards; }

.ct-mag-big { font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: clamp(2rem, 5vw, 3.1rem); line-height: 1; letter-spacing: -.04em; }

.ct-mag-big.good { color: #7fe9ff; }

.ct-mag-big.bad { color: #ff4d6d; }

/* the r and the n pushed together is the entire trick, so close the gap */
.ct-mag-big.bad i { font-style: normal; margin-left: -.14em; }

.ct-mag-vs { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .62rem;
  letter-spacing: .18em; text-transform: uppercase; color: rgba(255,255,255,.45); }

.ct-mag-note { display: block; font-size: .74rem; line-height: 1.55;
  color: rgba(255,255,255,.6); opacity: 0; }

.ct-shot.on .ct-mag-note {
  animation: ctFade .45s ease calc(var(--shot, 1.7s) * .48) forwards; }
@media (max-width: 600px) {
  .ct-mag-row { flex-direction: column; gap: 2px; }
  .ct-mag-l { min-width: 0; }
  .ct-mag-v { font-size: .8rem; }
  .ct-mag-zoom { gap: 10px; }
}

.ct-shot.on .bk-send::after { animation: ctArm 1.15s ease-out .45s infinite; }

.ct-shot.on .bk-cursor { animation: ctCursor 1.7s cubic-bezier(.3,.8,.4,1) .35s infinite; }


/* ── staging: how each scene composes the set ── */
.ct-stage { position: relative; width: 100%; height: 100%; display: grid; place-items: center; }


/* wide shot: the screen she is looking at, and her beside it */
/* The staged composition is laid out at its natural size and then fitted to
   the frame. Two things were wrong before: it was a block inside a wider
   camera wrapper, so it sat left of centre rather than in the middle of the
   picture, and at its natural height it already stood 16px taller than the
   frame, which meant any camera push past 1.0 shaved the edge off the set.
   The margin centres it and the fit scale leaves room for a nine percent
   push in both axes. */
.ct-wide {
  position: relative; width: min(870px, 95%); margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 1fr) 190px; align-items: end;
  gap: 20px; padding-bottom: 54px;
  /* zoom, not transform: scale. Both fit the set to the frame, but a
     transform adds a second scaled layer over a subtree full of SVG that
     the compositor has to resample, and measured against a static floor in
     the same browser that cost 1.6 percent of frames against 0.6. zoom
     resolves at layout, so the frame it produces is free. */
  zoom: .87;
}

.ct-wide .ct-screen { grid-column: 1; grid-row: 1; min-width: 0; z-index: 2; }

.ct-wide .ct-screen > * { max-width: 100%; }

.ct-wide .ct-figure { grid-column: 2; grid-row: 1; width: 100%; z-index: 1;
  align-self: end; transform: translateY(10px); }

.ct-wide .ct-deskwrap {
  position: absolute; left: -3%; right: -3%; bottom: 0; z-index: 3; height: 56px; overflow: hidden;
}

.ct-wide .ct-deskwrap .ct-desk { height: 100%; width: 100%; }


/* the camera push. it now rides the shot rather than the scene, so every
   beat gets its own move instead of one push every five seconds. */
/* The move is sized to the beat. A shot that holds for four seconds with a
   one second push is a still frame for three of them, which is the other
   half of why the film felt like it was skipping: the picture stopped
   moving long before the sentence finished. --shot is set per shot by the
   controller from the real scene timings. */
.ct-cam { transition: transform calc(var(--shot, 1.7s) * .62)
                      cubic-bezier(.22,.72,.26,1) 0s;
  transform: var(--cam-from, scale(.965)); backface-visibility: hidden; }

/* percentage widths inside a shrink to fit flex item resolve against the
   intrinsic width, so the wrapper came out wider than the thing inside it
   and every framed window sat about a hundred pixels left of centre */
.ct-cam > * { margin-inline: auto; }

.ct-shot.on .ct-cam { transform: var(--cam, none); transition-delay: .28s; }


/* the Guardian flying in to intercept */
.ct-guard { position: absolute; z-index: 6; width: 25%; left: 27%; top: 50%; }

.ct-shot.on .ct-guard {
  animation: ctSwoop .8s cubic-bezier(.15,1.12,.3,1) calc(var(--shot, 1.7s) * .06) both; }

.ct-shock { position: absolute; left: 50%; top: 50%; width: 46%; aspect-ratio: 1; z-index: 5;
  transform: translate(-50%,-50%); border-radius: 50%; opacity: 0;
  border: 3px solid rgba(0,212,255,.9); }

.ct-shot.on .ct-shock {
  animation: ctShock .85s cubic-bezier(.2,.8,.3,1) calc(var(--shot, 1.7s) * .3) 2; }


/* the branded console for the signals beat */
.ct-console { width: min(660px, 96%); border-radius: 8px; overflow: hidden; text-align: left;
  background: #070d15; border: 1px solid rgba(0,212,255,.3);
  box-shadow: 0 12px 30px rgba(0,0,0,.55); }

.ct-con-h { display: flex; align-items: center; gap: 10px; padding: 10px 15px;
  background: rgba(0,212,255,.08); border-bottom: 1px solid rgba(0,212,255,.24); }

.ct-con-dot { width: 9px; height: 9px; border-radius: 50%; background: #38f8a7;
  box-shadow: 0 0 10px #38f8a7; animation: ctLive 1.6s ease-in-out infinite; }

.ct-con-t { font-family: 'Syne', sans-serif; font-weight: 700; font-size: .86rem; color: #fff; }

.ct-con-s { margin-left: auto; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .62rem; letter-spacing: .16em; text-transform: uppercase; color: var(--cyan); }

.ct-con-b { padding: 12px 15px 15px; display: grid; gap: 7px; }

.ct-sig { display: grid; grid-template-columns: 22px 1fr auto; gap: 3px 11px; align-items: center;
  padding: 9px 12px; border-radius: 4px; background: rgba(255,77,109,.07);
  border: 1px solid rgba(255,77,109,.24); opacity: 0; }

.ct-shot.on .ct-sig { animation: ctSig .42s cubic-bezier(.2,.9,.3,1) both;
  animation-delay: calc(var(--shot, 1.7s) * .1 + var(--i) * var(--shot, 1.7s) * .2); }

.ct-sig-i { grid-column: 1; grid-row: 1 / 3; width: 20px; height: 20px; border-radius: 50%; display: grid;
  place-items: center; background: rgba(255,77,109,.18); border: 1px solid rgba(255,77,109,.5);
  color: #ff8fa3; font-family: 'Bebas Neue', sans-serif; font-size: .84rem; }

.ct-sig-h { grid-column: 2; grid-row: 1; color: #fff; font-weight: 700; font-size: .84rem; }

.ct-sig-d { grid-column: 2; grid-row: 2; color: rgba(255,255,255,.5); font-size: .72rem;
  font-family: 'IBM Plex Mono', ui-monospace, monospace; }

.ct-sig-v { grid-column: 3; grid-row: 1 / 3; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .62rem; color: #ff8fa3; }

.ct-verdict { margin-top: 4px; padding: 10px 12px; border-radius: 4px; text-align: center;
  background: rgba(56,248,167,.10); border: 1px solid rgba(56,248,167,.42);
  font-family: 'Syne', sans-serif; font-weight: 700; font-size: .86rem; color: #38f8a7; opacity: 0; }

.ct-shot.on .ct-verdict { animation: ctFade .4s ease 1.2s forwards; }


/* ── shots inside a scene ─────────────────────────────────────────────
   A dissolve, not a cut. The outgoing shot falls across exactly the same
   window the incoming one rises through, so the frame is never empty and
   the eye reads one continuous picture instead of a slide show. Underneath
   it a slow drift keeps the camera alive for the whole 1.7 seconds a shot
   is up, which is what stops a run of stills feeling choppy.

   opacity and scale are the only properties in flight. Both are handled by
   the compositor, so the main thread does no layout or paint per frame. */
.ct-shot { position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; padding: 26px 4%;
  contain: layout paint;
  backface-visibility: hidden;
  opacity: 0; visibility: hidden;
  /* A constant power dissolve. Two layers fading linearly are both at half
     opacity in the middle, and half over half composites to 75 percent of
     full brightness, so the picture visibly dips at every cut. These two
     curves trace sqrt(x) and 1 minus sqrt(1 minus x), which holds the
     composite at 91 percent or better right through the handover.

     Opacity is the only thing moving during the handover. The camera waits
     until the dissolve is finished before it starts, so no subtree is being
     transformed and blended at the same time. */
  transition: opacity .26s cubic-bezier(.4,.2,1,.55), visibility 0s .26s; }

.ct-shot.on { opacity: 1; visibility: visible;
  transition: opacity .26s cubic-bezier(0,.45,.6,.8), visibility 0s; }


/* A HELD BEAT. Where two consecutive shots frame the same thing and differ
   only in a highlight, a pose or a cursor, dissolving between them is both
   invisible and the most expensive thing on the timeline: two near identical
   full frames rasterised and blended for a quarter of a second to produce a
   picture that did not change. A held beat swaps instantly instead, and the
   incoming camera starts exactly where the outgoing one stopped, so the move
   runs unbroken across all three beats of the scene. Seven of the seventeen
   cuts are held, and the frame is identical on both sides of every one. */
.ct-shot.hold.on { transition: opacity 0s, visibility 0s; }

.ct-shot.cutout:not(.on) { transition: opacity 0s, visibility 0s; }


/* A CHAPTER TURN. A cut between two beats of the same scene and a cut
   between two scenes are different edits and should not look the same. The
   beat cuts are quick because the narration is continuous across them. The
   chapter turns land on a new sentence, so they get twice the dissolve and
   a slow settle out of the outgoing frame. The constant power curves are
   unchanged, so the picture still never dips. */
.ct-shot.chapter-in.on {
  transition: opacity .52s cubic-bezier(0,.45,.6,.8), visibility 0s; }

.ct-shot.chapter-out {
  transition: opacity .52s cubic-bezier(.4,.2,1,.55), visibility 0s .52s;
  scale: 1.012; }

.ct-shot.chapter-out.hold, .ct-shot.chapter-out.cutout {
  transition: opacity .52s cubic-bezier(.4,.2,1,.55), visibility 0s .52s; }

.ct-shot.hold.on .ct-cam { transition-delay: 0s; }


/* No will-change here on purpose. Chromium already promotes an element for
   the duration of a running opacity transition, and pinning six full frame
   layers open costs more than it saves: measured against a static floor in
   the same browser it took dropped frames from 2.5 percent to 4.1 percent.
   The hint is a promise about the future, and the future here is 260ms. */

/* anything out of frame stops burning frames. the ambient loops (blinking,
   steam, the live dot, the caret) are declared on the element itself, so
   without this they keep ticking in all six scenes at once. */
.wu-scene:not(.on), .wu-scene:not(.on) *,
.wu-scene:not(.on) *::before, .wu-scene:not(.on) *::after,
.ct-shot:not(.on), .ct-shot:not(.on) *,
.ct-shot:not(.on) *::before, .ct-shot:not(.on) *::after {
  /* important, because several of these loops are declared further down at a
     higher specificity than the selector that has to stop them. paired
     against the shipped build in the same browser this took dropped frames
     from 5.1 percent to 4.4, twice running, and changes nothing anybody can
     see: the elements it freezes are the ones that are not on screen. */
  animation-play-state: paused !important; }

/* a parked scene is skipped by the renderer entirely: no layout, no paint,
   no style resolution for roughly five hundred nodes of SVG */
.wu-scene.parked { content-visibility: hidden; }


/* the mouse pointer, moved per shot */
.ct-cursor {
  position: absolute; z-index: 9; width: 20px; height: 28px;
  left: var(--cx, 50%); top: var(--cy, 50%);
  /* position is owned by --cx and --cy alone. transitioning left and top
     while a keyframe animation moves the transform meant two systems were
     driving the same pixel, which is what made it jump. */
}

.ct-cursor svg { display: block; width: 100%; height: 100%; }

.ct-shot.on .ct-cursor.travel {
  animation: ctTravel calc(var(--shot, 1.7s) * .42) cubic-bezier(.3,.8,.35,1) both; }

.ct-shot.on .ct-cursor.click {
  animation: ctClick .34s ease calc(var(--shot, 1.7s) * .2) 2; }

.ct-click-ring {
  position: absolute; z-index: 8; width: 34px; height: 34px; margin: -17px 0 0 -17px;
  left: var(--cx, 50%); top: var(--cy, 50%); border-radius: 50%;
  border: 2px solid #7fe9ff; opacity: 0; }

.ct-shot.on .ct-click-ring {
  animation: ctRing .5s ease-out calc(var(--shot, 1.7s) * .19) 2; }


/* the row she is about to click lights up */
.ol-mail.hot { transition: background .4s ease; }

.ct-shot.on .ol-mail.hot { background: #cfe4f7; box-shadow: inset 3px 0 0 #2c3b8f; }

.ct-shot.on .ol-mail.hot .ol-who { color: #10306a; }


/* the ping when the mail lands */
.ct-ping { position: absolute; z-index: 7; padding: 9px 15px; border-radius: 7px;
  background: #2c3b8f; color: #fff; font-family: 'Segoe UI', system-ui, sans-serif;
  font-size: 12px; box-shadow: 0 8px 18px rgba(0,0,0,.55);
  right: 4%; top: 8%; opacity: 0; }

.ct-ping b { display: block; font-size: 11px; opacity: .8; font-weight: 400; }

.ct-shot.on .ct-ping {
  animation: ctPing calc(var(--shot, 1.7s) * .82) cubic-bezier(.2,.9,.3,1)
             calc(var(--shot, 1.7s) * .08) both; }


/* typing into the bank field */
.ct-typed { position: relative; }

.ct-shot.on .ct-typed::after {
  content: ''; position: absolute; right: -6px; top: 10%; bottom: 10%; width: 2px;
  background: #12212f; animation: ctCaret .55s steps(1) infinite;
}


/* ── the blocked panel ── */
.ct-blockwrap { width: min(660px, 100%); border-radius: 10px; overflow: hidden;
  background: #070d15; border: 1px solid rgba(56,248,167,.34);
  box-shadow: 0 12px 30px rgba(0,0,0,.55); text-align: left; }

.ct-blockhead { display: flex; align-items: center; gap: 16px; padding: 16px 18px;
  background: rgba(56,248,167,.08); border-bottom: 1px solid rgba(56,248,167,.26); }

.ct-guard-still { width: 74px; flex-shrink: 0; }

.ct-guard-still .cgk-attacks, .ct-guard-still .cgk-barrier { display: none; }

.ct-blocked-t { display: block; font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(1.9rem, 5vw, 3rem); line-height: 1; letter-spacing: .1em; color: #38f8a7; }

.ct-shot.on .ct-blocked-t {
  animation: ctPunch .4s cubic-bezier(.3,1.1,.4,1) calc(var(--shot, 1.7s) * .07) both; }

.ct-blocked-t { transform-origin: left center; }

.ct-blockhead > div:last-child { min-width: 0; }

.ct-blocked-s { display: block; margin-top: 5px;
  font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .66rem;
  letter-spacing: .14em; text-transform: uppercase; color: rgba(255,255,255,.6); }


/* who we are watching, named on screen */
/* Anchored to the bottom left gutter, which is the one region of the frame
   nothing else occupies: the scene chip owns the top left, the brand owns
   the bottom right, and the composition is centred. Centring this at the
   top put it straight through the Outlook title bar. */
.ct-tag-name { position: absolute; left: 20px; bottom: 74px; transform: translateX(-50%);
  transform: none; z-index: 5; padding: 5px 13px; border-radius: 999px;
  background: rgba(5,10,18,.88); border: 1px solid rgba(0,212,255,.45);
  box-shadow: 0 4px 14px rgba(0,0,0,.5);
  font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .64rem;
  letter-spacing: .16em; text-transform: uppercase; color: #7fe9ff; opacity: 0; }

.ct-shot.on .ct-tag-name {
  animation: ctFade .4s ease calc(var(--shot, 1.7s) * .2) forwards; }


/* ── the celebration: the two people and the mascot, and a BLOCKED stamp ── */
.ct-celebrate { position: relative; width: min(760px, 100%); text-align: center;
  padding-top: 96px; }

.ct-cast { display: flex; align-items: flex-end; justify-content: center; gap: clamp(6px, 3vw, 40px); }

.ct-cast > * { width: clamp(96px, 15vw, 168px); }

.ct-cast .ct-mascot { width: clamp(120px, 19vw, 210px); align-self: center; }

.ct-shot.on .ct-cast > * { animation: ctCheer .5s cubic-bezier(.2,1.3,.35,1) both; }

.ct-shot.on .ct-cast > *:nth-child(2) { animation-delay: calc(var(--shot, 1.7s) * .07); }

.ct-shot.on .ct-cast > *:nth-child(3) { animation-delay: calc(var(--shot, 1.7s) * .14); }

.ct-stamp {
  position: absolute; left: 50%; top: 0; z-index: 6;
  padding: 7px 20px 9px; border: 3px solid #ff2d55; border-radius: 6px;
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(1.1rem, 2.6vw, 1.7rem);
  line-height: 1.05; white-space: nowrap;
  letter-spacing: .12em; color: #ff2d55; background: rgba(255,45,85,.12);
  transform: translate(-50%, 0) rotate(-9deg) scale(2.6); opacity: 0;
}

.ct-shot.on .ct-stamp {
  animation: ctStamp .42s cubic-bezier(.3,1.1,.4,1) calc(var(--shot, 1.7s) * .28) both; }

.ct-stamp small { display: block; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .4em; letter-spacing: .16em; color: #ff8fa3; margin-top: 4px; }

.ct-names { display: flex; justify-content: center; gap: clamp(10px, 5vw, 62px); margin-top: 10px; }

.ct-name { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: .64rem;
  letter-spacing: .16em; text-transform: uppercase; color: rgba(255,255,255,.5); }

.ct-name.hi { color: #38f8a7; }


/* ── the closing brand card ── */
.ct-close { text-align: center; }

.ct-close .ct-mark { width: clamp(90px, 13vw, 128px); margin: 0 auto 20px; }

.ct-close-k { display: block; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .64rem; letter-spacing: .32em; text-transform: uppercase; color: var(--cyan); margin-bottom: 14px; }

.ct-close strong { display: block; font-family: 'Bebas Neue', sans-serif; font-weight: 400;
  font-size: clamp(1.8rem, 5vw, 3.6rem); line-height: .98; color: #fff; letter-spacing: .02em; }

.ct-close strong em { font-style: normal; color: #38f8a7; }

.ct-close-s { display: block; margin-top: 16px; color: rgba(255,255,255,.62); font-size: .88rem; }


/* the saved figure */
.ct-saved { text-align: center; }

.ct-saved .ct-amt { display: block; font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(2.8rem, 8.5vw, 5.4rem); line-height: 1; color: #38f8a7;
  text-shadow: 0 0 48px rgba(56,248,167,.42); }

.ct-shot.on .ct-saved .ct-amt {
  animation: ctPop .7s cubic-bezier(.2,1.3,.35,1) calc(var(--shot, 1.7s) * .1) both; }

.ct-saved .ct-amt-l { display: block; margin-top: 8px; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .66rem; letter-spacing: .24em; text-transform: uppercase; color: rgba(56,248,167,.85); }

.ct-relief { width: clamp(110px, 15vw, 160px); margin: 0 auto 4px; }


/* what did NOT happen, which is the part a business owner actually buys */
.ct-outcomes { display: flex; flex-wrap: wrap; justify-content: center; gap: 9px; margin-top: 20px; }

.ct-out {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 15px; border-radius: 999px; font-size: .82rem;
  background: rgba(56,248,167,.08); border: 1px solid rgba(56,248,167,.34);
  color: rgba(255,255,255,.86); opacity: 0;
}

.ct-out b { color: #38f8a7; font-weight: 400; }

.ct-shot.on .ct-out { animation: ctSig .42s cubic-bezier(.2,.9,.3,1) both;
  animation-delay: calc(var(--shot, 1.7s) * .22 + var(--i) * var(--shot, 1.7s) * .16); }
@media (max-width: 600px) { .ct-out { font-size: .74rem; padding: 7px 12px; } }
@media (max-width: 860px) {
  .ol-body { grid-template-columns: 1fr; min-height: 0; }
  .ol-rail, .ol-list { display: none; }
  .ol-ribbon .ol-cmd:nth-child(n+6) { display: none; }
  .ct-wide { grid-template-columns: minmax(0, 1fr); }
  .ct-wide .ct-figure { display: none; }
  .ct-wide .ct-screen { width: 100%; transform: none; }
  .ct-wide .ct-deskwrap { display: none; }

  /* On a phone the set already fills the frame, so a camera push has
     nowhere to go but off the edge. It is switched off, and each
     composition is fitted to the taller portrait frame instead. */
  .ct-cam { transform: none !important; transition: none; }
  .ct-shot { padding: 14px 3%; }
  .ct-wide { zoom: .78; }
  .ct-cam > div:not(.ct-wide) { zoom: .86; }
  .ct-blockwrap, .ct-celebrate, .ct-close, .ct-saved { zoom: .94; }
  .ct-tag-name { top: auto; bottom: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .ct-person *, .ct-desk *, .ol *, .bk *, .ct-guard, .ct-shock,
  .ct-sig, .ct-verdict, .ct-saved .ct-amt { animation: none !important; }
  .ct-cam { transition: none; transform: none !important; }
  .ct-shot, .ct-shot.on { animation: none !important;
    transition: opacity .2s linear, visibility 0s !important; }
  .ct-sig, .ct-verdict, .ol-banner { opacity: 1; }
  .ol.flag .ol-addr em::after { transform: scaleX(1); }
}
@keyframes wuSoundPulse {
  0%   { box-shadow: 0 0 0 0 rgba(0,212,255,.45); }
  70%  { box-shadow: 0 0 0 14px rgba(0,212,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(0,212,255,0); }
}
@keyframes wuPulse {
  0%   { opacity: .85; transform: scale(1); }
  60%  { opacity: 0;   transform: scale(1.68); }
  100% { opacity: 0;   transform: scale(1.68); }
}
@keyframes wuArrive {
  0%   { opacity: 0; transform: translateY(-13px); background: rgba(0,212,255,.34); }
  100% { opacity: 1; transform: none; background: rgba(0,212,255,.07); }
}
@keyframes wuUnderline { to { transform: scaleX(1); } }
@keyframes wuFade { to { opacity: 1; } }
@keyframes wuArm {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,77,109,.5); }
  55%      { box-shadow: 0 0 0 13px rgba(255,77,109,0); }
}
@keyframes wuCursor {
  0%   { opacity: 0; transform: translate(30px, 32px); }
  22%  { opacity: 1; }
  62%  { opacity: 1; transform: translate(0,0); }
  72%  { transform: translate(0, 3px); }
  100% { opacity: 1; transform: translate(0,0); }
}
@keyframes wuSig { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: none; } }
@keyframes wuPop { from { opacity: 0; transform: scale(.72); } to { opacity: 1; transform: none; } }
@keyframes ctSweat {
  0%, 100% { transform: translateY(0); opacity: .9; }
  50%      { transform: translateY(5px); opacity: .5; }
}
@keyframes ctBlink { 0%, 96%, 100% { transform: scaleY(1); } 97%, 99% { transform: scaleY(.1); } }
@keyframes ctSteam { 0% { opacity: 0; transform: translateY(6px); } 40% { opacity: .8; } 100% { opacity: 0; transform: translateY(-12px); } }
@keyframes ctLeaf { 0%, 100% { transform: rotate(0deg); } 50% { transform: rotate(3deg); } }
@keyframes ctUnderline { from { transform: scaleX(0); transform-origin: left; } to { transform: scaleX(1); } }
@keyframes ctFade { to { opacity: 1; } }
@keyframes ctArm {
  0%   { opacity: .85; transform: scale(1); }
  100% { opacity: 0;   transform: scale(1.13); }
}
@keyframes ctCursor {
  0%   { opacity: 0; transform: translate(34px, 36px); }
  20%  { opacity: 1; }
  58%  { opacity: 1; transform: translate(0,0); }
  68%  { transform: translate(0, 4px); }
  100% { opacity: 1; transform: translate(0,0); }
}
@keyframes ctSwoop {
  0%   { opacity: 0; transform: translate(-260%, -150%) scale(.45) rotate(-18deg); }
  70%  { opacity: 1; }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
}
@keyframes ctShock {
  0%   { opacity: .95; transform: translate(-50%,-50%) scale(.4); }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(1.7); }
}
@keyframes ctLive { 0%,100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes ctSig { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
@keyframes ctTravel {
  from { transform: translate(var(--fx, -90px), var(--fy, 60px)); }
  to   { transform: none; }
}
@keyframes ctClick { 0%,100% { transform: scale(1); } 45% { transform: scale(.82); } }
@keyframes ctRing {
  0%   { opacity: .9; transform: scale(.3); }
  100% { opacity: 0; transform: scale(1.5); }
}
@keyframes ctPing {
  0%   { opacity: 0; transform: translateX(40px); }
  16%  { opacity: 1; transform: none; }
  78%  { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(20px); }
}
@keyframes ctCaret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes ctPunch {
  0%   { opacity: 0; transform: scale(2.2); }
  70%  { opacity: 1; transform: scale(.94); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes ctCheer {
  from { opacity: 0; transform: translateY(26px) scale(.9); }
  to   { opacity: 1; transform: none; }
}
@keyframes ctStamp {
  0%   { opacity: 0; transform: translate(-50%,0) rotate(-9deg) scale(1.9); }
  70%  { opacity: 1; transform: translate(-50%,0) rotate(-9deg) scale(.94); }
  100% { opacity: 1; transform: translate(-50%,0) rotate(-9deg) scale(1); }
}
@keyframes ctPop { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }
/* The film opens in a dialog over the page, never inline (Travis 2026-10-06). The film's own markup and
   CSS are the ones the old site shipped; only the shell around it is new-site chrome. */
.film-open{position:fixed;inset:0;z-index:300;display:none;align-items:center;justify-content:center;
  padding:clamp(12px, 2vw, 40px);background:rgba(4,8,18,.86);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.film-open[open],.film-open.is-on{display:flex}
.film-box{position:relative;width:min(1180px, 100%);max-height:calc(100svh - 2 * clamp(12px, 2vw, 40px));overflow:auto;
  background:var(--bg);border:1px solid rgba(var(--glow-blue),.32);border-radius:10px;
  box-shadow:0 0 0 1px rgba(0,0,0,.6), 0 30px 90px rgba(0,0,0,.6), 0 0 60px rgba(var(--glow-blue),.18)}
/* the controls sit on the top edge: replay to the left of centre, close at the right (Travis's placement) */
.film-bar{position:sticky;top:0;z-index:2;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:12px;
  padding:10px clamp(10px, 1.4vw, 18px);background:linear-gradient(180deg, rgba(6,11,24,.96), rgba(6,11,24,.72) 70%, transparent)}
.film-replay{grid-column:2;justify-self:end;margin-right:clamp(40px, 9vw, 190px)}
.film-x{grid-column:3;justify-self:end;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
  border-radius:4px;background:rgba(12,20,38,.6);border:1px solid rgba(255,255,255,.18);color:var(--ink-2);cursor:pointer}
.film-x:hover{border-color:rgba(var(--glow-ice),.8);color:#fff}
.film-body{padding:0 clamp(10px, 1.4vw, 18px) clamp(14px, 1.6vw, 24px)}
.film-body .section-inner{padding:0;max-width:none}
@media (max-width:600px){ .film-replay{margin-right:0;justify-self:center} }
@media (prefers-reduced-motion:reduce){ .film-open{backdrop-filter:none} }

/* the slot beside the wordmark, top left: one click opens the film from anywhere on the site
   (Travis 2026-10-07). On a page that is not the homepage it is a link home with #film, which opens there. */
.film-cue{display:inline-flex;align-items:center;gap:8px;margin-left:clamp(10px, 1.4vw, 22px);padding:6px 12px 6px 8px;
  border-radius:999px;background:rgba(12,24,48,.7);border:1px solid rgba(var(--glow-blue),.35);
  color:var(--ink-2);text-decoration:none;font-family:var(--mono);font-size:var(--t-mono-s);letter-spacing:.08em;
  text-transform:uppercase;white-space:nowrap;transition:border-color .3s, color .3s, box-shadow .3s}
.film-cue:hover{color:#fff;border-color:rgba(var(--glow-ice),.8);
  box-shadow:0 0 0 1px rgba(var(--glow-blue),.45), 0 0 18px rgba(var(--glow-blue),.35)}
.film-cue svg{width:16px;height:16px;flex:none}
@media (max-width:900px){ .film-cue span{display:none} .film-cue{padding:6px;margin-left:8px} }

/* The bubble over the shield: the film's own invitation, shown once. Travis 2026-10-07, "you only click it
   once on first entry, refreshes and then it moves up top real small" - after that first visit the header
   cue is the permanent, small version. It sits over the hero art and never touches the artwork itself. */
.film-bubble{position:absolute;left:50%;top:34%;transform:translate(-50%,-50%) scale(.96);z-index:3;
  display:none;align-items:center;gap:9px;padding:9px 15px 11px;max-width:min(290px, 64vw);
  background:rgba(8,14,28,.92);border:1px solid rgba(var(--glow-gold),.45);border-radius:14px;
  color:var(--ink-2);text-align:left;text-decoration:none;cursor:pointer;
  box-shadow:0 0 0 1px rgba(0,0,0,.5), 0 14px 40px rgba(0,0,0,.5), 0 0 34px rgba(255,170,60,.22);
  animation:filmBubbleIn .5s cubic-bezier(.2,.8,.2,1) .9s both, filmBubbleFloat 5s ease-in-out 1.4s infinite}
.film-bubble.is-on{display:inline-flex}
.film-bubble::after{content:"";position:absolute;left:28px;top:100%;width:14px;height:12px;
  background:rgba(8,14,28,.92);clip-path:polygon(0 0, 100% 0, 18% 100%);
  border-right:1px solid rgba(var(--glow-gold),.45);border-bottom:1px solid rgba(var(--glow-gold),.45)}
.film-bubble:hover{border-color:rgba(var(--glow-gold),.85);color:#fff;
  box-shadow:0 0 0 1px rgba(0,0,0,.5), 0 14px 40px rgba(0,0,0,.5), 0 0 46px rgba(255,170,60,.38)}
.fb-face{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;font-size:15px;
  background:rgba(255,190,90,.16);border:1px solid rgba(var(--glow-gold),.4)}
.fb-copy{display:flex;flex-direction:column;gap:2px;min-width:0}
.fb-name{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold)}
.fb-line{font-size:13px;line-height:1.3;color:var(--ink-2)}
@keyframes filmBubbleIn{from{opacity:0;transform:translate(-50%,-38%) scale(.88)}
  to{opacity:1;transform:translate(-50%,-50%) scale(.96)}}
@keyframes filmBubbleFloat{50%{transform:translate(-50%,-54%) scale(.96)}}
@media (max-width:700px){ .film-bubble{top:30%;max-width:min(240px, 72vw);padding:8px 12px 10px} }
@media (prefers-reduced-motion:reduce){ .film-bubble{animation:none} }

/* the hero button is the quiet way back to the film, so it waits until the film has been played once
   (Travis 2026-10-07: the homepage must not offer it in three places at the same time) */
.film-later{display:none}
.film-later.is-on{display:inline-flex}
