/* Intro: "go into the computer". A fixed overlay on top of the page (the page loads underneath).
   Video push-in -> canvas dive through the code -> glitch flash -> typed line -> fade out.
   Animations: transform/opacity/filter only. */
html.intro-on, html.intro-on body { overflow: hidden; }
.intro { position: fixed; inset: 0; z-index: 9999; overflow: hidden; background: #010603; contain: strict;
  transition: opacity .5s cubic-bezier(.2, .8, .2, 1); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.intro.out { opacity: 0; pointer-events: none; }
.intro video, .intro canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.intro video { object-fit: cover; object-position: 50% 45%; opacity: 0; transform: scale(1.02); transform-origin: 50% 42%;
  transition: opacity .45s linear; }
.intro.v-on video { opacity: 1; }
/* last part of the clip is his POV: push the camera at the monitor before the dive */
.intro.push video { transform: scale(1.85); transform-origin: 50% 30%; transition: opacity .45s linear, transform 1s cubic-bezier(.55, 0, .9, .45); }
.intro canvas { opacity: 0; transition: opacity .35s linear; }
.intro.c-on canvas { opacity: 1; }
/* soft vignette + scanlines on top of everything (no text, no HUD) */
.intro::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 90% at 50% 50%, transparent 55%, rgba(0, 0, 0, .75)),
    repeating-linear-gradient(0deg, rgba(0, 0, 0, .18) 0 1px, transparent 1px 3px); }

/* glitch flash when we break through the screen */
.intro.flash::before { content: ''; position: absolute; inset: 0; z-index: 3; pointer-events: none; background: #7dffb0;
  mix-blend-mode: screen; opacity: 0; animation: intro-flash .26s steps(4); }
@keyframes intro-flash { 0% { opacity: .55; transform: translateX(-6px); } 35% { opacity: .25; transform: translateX(8px); }
  60% { opacity: .45; transform: none; } 100% { opacity: 0; } }
.intro.shake canvas { animation: intro-shake .3s steps(3); }
@keyframes intro-shake { 0% { transform: translate(5px, -3px); } 50% { transform: translate(-7px, 2px); } 100% { transform: none; } }

/* typed lines */
.intro-type { position: absolute; z-index: 4; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(560px, calc(100% - 40px));
  margin: 0; font: 700 clamp(17px, 2.6vw, 26px)/1.55 'JB', ui-monospace, 'SF Mono', Menlo, monospace; color: #00ff41; letter-spacing: .01em;
  text-shadow: 0 0 6px rgba(0, 255, 65, .9), 0 0 26px rgba(0, 255, 65, .45); white-space: pre-wrap; pointer-events: none; }
.intro-type p { margin: 0; min-height: 1.55em; }
.intro-type p:empty { visibility: hidden; }
.intro-type i { display: inline-block; width: .6em; height: 1.05em; margin-left: 2px; vertical-align: -.16em; background: #00ff41;
  box-shadow: 0 0 10px rgba(0, 255, 65, .8); animation: intro-caret .9s steps(2, jump-none) infinite; }
@keyframes intro-caret { 50% { opacity: 0; } }
.intro-type.dim { opacity: 0; transition: opacity .3s; }

.intro-ctl { position: absolute; z-index: 5; top: max(14px, env(safe-area-inset-top)); right: max(14px, env(safe-area-inset-right));
  display: flex; gap: 8px; opacity: 0; animation: intro-in .4s .5s forwards; }
.intro-skip, .intro-snd { min-height: 36px; padding: 0 14px; border: 1px solid rgba(0, 255, 65, .32); border-radius: 6px; background: rgba(1, 6, 3, .55);
  color: #63a978; font: 400 13px/1 'JB', ui-monospace, 'SF Mono', Menlo, monospace; letter-spacing: .04em; cursor: pointer; }
.intro-snd { color: #00ff41; border-color: rgba(0, 255, 65, .55); box-shadow: 0 0 14px rgba(0, 255, 65, .25); }
.intro-snd[hidden] { display: none; }
.intro-skip:hover, .intro-skip:focus-visible, .intro-snd:hover { color: #00ff41; border-color: #00ff41; outline: none; }
@keyframes intro-in { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .intro, .intro video, .intro canvas { transition-duration: .3s; }
  .intro.flash::before, .intro.shake canvas { animation: none; }
}
