/* "Hacked" font by David Libeau (CC-BY) — https://hackedfont.com */
@font-face{
  font-family:'Hacked';
  src:url('https://hackedfont.com/HACKED.ttf') format('truetype');
  font-display:swap;
}

:root{
  --ink:#0B0F14;
  --text:#E6EDF3;
  --cyan:#00E5FF;
  --magenta:#FF2A6D;
}
*{margin:0;padding:0;box-sizing:border-box}
body{
  background:var(--ink);
  color:var(--text);
  min-height:100vh;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
}
/* boot log — startup lines typed in the corner before the mark reveals */
#boot{
  position:fixed;top:28px;left:28px;
  font-family:'Press Start 2P',monospace;
  font-size:clamp(.5rem,1.3vw,.7rem);
  letter-spacing:.06em;
  line-height:2.4;
  color:#8B98A5;
  text-shadow:0 0 6px rgba(230,237,243,.18);
}
#stage.preboot{visibility:hidden}

#stage{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:0px;
  transition:transform 1.2s cubic-bezier(.5,0,.15,1);
  will-change:transform;
}

.tagline{
  align-self:flex-start;   /* type from the wordmark's left edge, not the middle */
  /* zero-width box: the text overflows to the right without widening the stage,
     so the centered stage never re-centers (shifts left) as typing progresses */
  width:0;
  white-space:nowrap;
  font-family:'Press Start 2P',monospace;
  font-size:clamp(.55rem,1.6vw,.85rem);
  letter-spacing:.08em;
  color:#8B98A5;
  image-rendering:pixelated;
  /* slight permanent bloom on the typed text */
  text-shadow:0 0 6px rgba(230,237,243,.18);
}
/* freshest character glows hot, then cools to the base bloom */
.tagline .fresh,
#boot .fresh{
  animation:charglow .9s ease-out both;
}
@keyframes charglow{
  0%{color:var(--cyan);text-shadow:0 0 22px rgba(0,229,255,1), 0 0 10px rgba(0,229,255,.95), 0 0 4px rgba(0,229,255,1)}
  100%{color:#8B98A5;text-shadow:0 0 6px rgba(230,237,243,.18)}
}
.cursor{
  display:inline-block;width:.9em;height:1em;
  background:var(--cyan);vertical-align:text-bottom;
  margin-left:.4em;animation:blink 1s steps(1) infinite;
  /* cursor bloom */
  box-shadow:0 0 18px rgba(0,229,255,.75), 0 0 8px rgba(0,229,255,.7), 0 0 3px rgba(0,229,255,.9);
}
@keyframes blink{50%{opacity:0}}

/* 404 page — tagline, typed glow and cursor run hot magenta instead of cyan */
.err404 .tagline{
  color:var(--magenta);
  text-shadow:0 0 6px rgba(255,42,109,.35);
}
.err404 .tagline .fresh{animation-name:charglow-red}
@keyframes charglow-red{
  0%{color:#fff;text-shadow:0 0 22px rgba(255,42,109,1), 0 0 10px rgba(255,42,109,.95), 0 0 4px rgba(255,42,109,1)}
  100%{color:var(--magenta);text-shadow:0 0 6px rgba(255,42,109,.35)}
}
.err404 .cursor{
  background:var(--magenta);
  box-shadow:0 0 18px rgba(255,42,109,.75), 0 0 8px rgba(255,42,109,.7), 0 0 3px rgba(255,42,109,.9);
}

.mark-box{
  position:relative;display:inline-block;
  filter:url(#wavy);
  animation:flicker 1.8s linear infinite;
}
/* phosphor flicker — opacity-only so it works on iOS Safari (which ignores
   SVG url() filters on HTML elements); brightness surges are handled in JS */
@keyframes flicker{
  0%,100%{opacity:1}
  7%{opacity:.88}
  12%{opacity:1}
  23%{opacity:.93}
  31%{opacity:1}
  39%{opacity:.78}
  43%{opacity:1}
  55%{opacity:.9}
  62%{opacity:1}
  71%{opacity:.82}
  76%{opacity:1}
  87%{opacity:.92}
  93%{opacity:1}
}

.glitch{
  font-family:'Hacked',sans-serif;
  font-weight:400;
  font-size:clamp(3.2rem,12vw,9rem);
  letter-spacing:.04em;
  line-height:1;
  position:relative;
  display:inline-block;
  user-select:none;
  /* permanent chromatic aberration — RGB fringe visible even at rest */
  text-shadow:2px 0 0 rgba(255,42,109,.55), -2px 0 0 rgba(0,229,255,.55);
}
.glitch::before,
.glitch::after{
  content:attr(data-text);
  position:absolute;inset:0;
  opacity:0;
  text-shadow:none;
}
.glitch::before{color:var(--cyan);z-index:-1}
.glitch::after{color:var(--magenta);z-index:-2}

/* burst state — toggled by JS at random intervals */
.glitch.burst{text-shadow:5px 0 0 rgba(255,42,109,.8), -5px 0 0 rgba(0,229,255,.8)}
.glitch.burst::before{opacity:1;animation:slice-a .55s steps(8,end) both, shift-a .55s steps(8,end) both}
.glitch.burst::after {opacity:1;animation:slice-b .55s steps(8,end) both, shift-b .55s steps(8,end) both}
.glitch.burst{animation:jitter .55s steps(8,end) both}
@keyframes shift-a{0%{transform:translateX(-5px)}14%{transform:translateX(3px)}28%{transform:translateX(-2px)}42%{transform:translateX(4px)}58%{transform:translateX(-3px)}72%{transform:translateX(2px)}86%{transform:translateX(-1px)}100%{transform:translateX(0)}}
@keyframes shift-b{0%{transform:translateX(5px)}14%{transform:translateX(-3px)}28%{transform:translateX(2px)}42%{transform:translateX(-4px)}58%{transform:translateX(3px)}72%{transform:translateX(-2px)}86%{transform:translateX(1px)}100%{transform:translateX(0)}}
@keyframes jitter{0%{transform:skewX(-1.5deg) translateX(-2px)}15%{transform:skewX(1deg) translateX(1px)}32%{transform:translateX(2px)}48%{transform:skewX(-1deg) translateX(-1px)}64%{transform:skewX(.5deg) translateX(1px)}80%{transform:translateX(-1px)}100%{transform:none}}
@keyframes slice-a{
  0%{clip-path:polygon(0 12%,100% 12%,100% 28%,0 28%)}
  14%{clip-path:polygon(0 55%,100% 55%,100% 64%,0 64%)}
  28%{clip-path:polygon(0 2%,100% 2%,100% 10%,0 10%)}
  42%{clip-path:polygon(0 78%,100% 78%,100% 92%,0 92%)}
  58%{clip-path:polygon(0 33%,100% 33%,100% 50%,0 50%)}
  72%{clip-path:polygon(0 65%,100% 65%,100% 72%,0 72%)}
  86%{clip-path:polygon(0 15%,100% 15%,100% 24%,0 24%)}
  100%{clip-path:polygon(0 40%,100% 40%,100% 46%,0 46%)}
}
@keyframes slice-b{
  0%{clip-path:polygon(0 66%,100% 66%,100% 80%,0 80%)}
  14%{clip-path:polygon(0 8%,100% 8%,100% 20%,0 20%)}
  28%{clip-path:polygon(0 88%,100% 88%,100% 97%,0 97%)}
  42%{clip-path:polygon(0 30%,100% 30%,100% 42%,0 42%)}
  58%{clip-path:polygon(0 5%,100% 5%,100% 14%,0 14%)}
  72%{clip-path:polygon(0 45%,100% 45%,100% 58%,0 58%)}
  86%{clip-path:polygon(0 70%,100% 70%,100% 85%,0 85%)}
  100%{clip-path:polygon(0 50%,100% 50%,100% 58%,0 58%)}
}
/* micro-blip — a quick single-band flash between full bursts */
.glitch.blip{text-shadow:4px 0 0 rgba(255,42,109,.7), -4px 0 0 rgba(0,229,255,.7)}
.glitch.blip::before{opacity:1;clip-path:polygon(0 30%,100% 30%,100% 42%,0 42%);transform:translateX(4px)}
.glitch.blip::after{opacity:1;clip-path:polygon(0 60%,100% 60%,100% 74%,0 74%);transform:translateX(-4px)}

/* CRT vertical-hold roll — a barely-perceptible slip, returns exactly to rest */
.glitch.roll{animation:vroll .6s cubic-bezier(.45,0,.55,1) both}
@keyframes vroll{
  0%,100%{transform:translateY(0)}
  35%{transform:translateY(1.5px)}
  65%{transform:translateY(-2px)}
}
/* idle flutter — horizontal-only micro drift, identical start/end state */
.glitch.flutter{animation:flutter 3.2s ease-in-out infinite}
@keyframes flutter{
  0%,100%{transform:translateX(0)}
  25%{transform:translateX(.5px)}
  50%{transform:translateX(-.4px)}
  75%{transform:translateX(.3px)}
}

@media (prefers-reduced-motion:reduce){
  .glitch.burst,.glitch.burst::before,.glitch.burst::after,
  .glitch.flutter,.glitch.roll{animation:none}
  .mark-box{animation:none;filter:none}
  .cursor{animation:none}
  .glitch.burst::before{opacity:.5;transform:translate(-3px,2px);clip-path:polygon(0 10%,100% 10%,100% 45%,0 45%)}
  .glitch.burst::after{opacity:.5;transform:translate(3px,-2px);clip-path:polygon(0 55%,100% 55%,100% 90%,0 90%)}
}
