:root {
  --bg: #000;
  --g: #41ff7e;        /* phosphor */
  --g-hi: #c6ffd8;     /* hot phosphor */
  --g-mid: #27c45c;
  --g-dim: #17803b;
  --g-deep: #0a3318;
  --glow: 0 0 2px rgba(65, 255, 126, .55), 0 0 10px rgba(65, 255, 126, .2);
  --font: ui-monospace, "SF Mono", Menlo, Monaco, "Cascadia Mono", "Roboto Mono", Consolas, "Liberation Mono", "Courier New", monospace;
  /* ~42 columns on a phone, never larger than 15px */
  --fs: clamp(11px, calc((100vw - 32px) / 25.5), 15px);
}

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
}
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  color: var(--g);
  font: 400 var(--fs)/1.45 var(--font);
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}

/* ---------- screen ---------- */

.crt {
  position: fixed;
  inset: 0;
  max-width: 820px;
  margin: 0 auto;
  height: 100vh;
  height: 100dvh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  padding:
    calc(env(safe-area-inset-top) + 12px)
    calc(env(safe-area-inset-right) + 16px)
    calc(env(safe-area-inset-bottom) + 10px)
    calc(env(safe-area-inset-left) + 16px);
  text-shadow: var(--glow);
  animation: power .6s cubic-bezier(.2, .7, .2, 1) both;
}

.head { flex: none; margin-bottom: .9em; }
.box {
  border: 1px solid var(--g-mid);
  padding: .5em .75em .45em;
  box-shadow: 0 0 10px rgba(65, 255, 126, .18), inset 0 0 14px rgba(65, 255, 126, .07);
}
.t1 { color: var(--g-hi); font-weight: 700; letter-spacing: .06em; }
.t2 { color: var(--g-mid); font-size: .9em; letter-spacing: .14em; }
.meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: .35em;
  font-size: .82em;
  color: var(--g-dim);
}
.live { animation: pulse 2.4s ease-in-out infinite; }

#sound {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  color: inherit;
  text-shadow: inherit;
  letter-spacing: .04em;
  background: none;
  border: 0;
  border-radius: 0;
  padding: .8em 0 .8em 1.2em;
  margin: -.8em 0;
  cursor: pointer;
}
#sound.on { color: var(--g); }
#sound:focus-visible { outline: 1px dashed var(--g-mid); outline-offset: -.5em; }

.log {
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: none;
  padding-bottom: 1.4em;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 1.1em);
  mask-image: linear-gradient(to bottom, transparent 0, #000 1.1em);
}
.log::-webkit-scrollbar { display: none; }

/* ---------- lines ---------- */

.ln {
  min-height: 1.45em;
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.ln.sp { min-height: 0; height: .85em; }
.pfx { color: var(--g-dim); }
.dim { color: var(--g-dim); text-shadow: 0 0 6px rgba(23, 128, 59, .35); }
.noise { font-size: .92em; }
.hi, .voice, .ok { color: var(--g-hi); }
.hi { font-weight: 600; }
.ps1 { color: var(--g-mid); }

.inv, .bad {
  background: var(--g);
  color: #000;
  text-shadow: none;
  box-shadow: 0 0 10px rgba(65, 255, 126, .5);
  padding: 0 .2em;
  font-weight: 600;
}

.big {
  font-size: 2.1em;
  line-height: 1.3;
  letter-spacing: .18em;
  font-weight: 700;
  color: var(--g-hi);
  text-shadow: 0 0 4px rgba(65, 255, 126, .9), 0 0 18px rgba(65, 255, 126, .55), 0 0 42px rgba(65, 255, 126, .25);
}
.big .pfx { font-size: .5em; letter-spacing: 0; vertical-align: middle; }
.pulse { animation: pulse 1.6s ease-in-out infinite; }
.emoji { font-size: 1.6em; line-height: 1.3; text-shadow: none; }

/* loading bars: segmented phosphor fill, light sweep while loading */
.barln {
  display: flex;
  align-items: center;
  gap: .6em;
  min-height: 1.7em;
}
.bar {
  position: relative;
  flex: 1;
  max-width: 30em;
  height: .95em;
  padding: 2px;
  border: 1px solid var(--g-mid);
  background: repeating-linear-gradient(90deg, rgba(65, 255, 126, .07) 0 .45em, transparent .45em .6em) content-box;
  box-shadow: 0 0 8px rgba(65, 255, 126, .2), inset 0 0 6px rgba(65, 255, 126, .08);
}
.bar-fill {
  position: relative;
  display: block;
  width: 0;
  height: 100%;
  overflow: hidden;
  background: repeating-linear-gradient(90deg, var(--g) 0 .45em, transparent .45em .6em);
  filter: drop-shadow(0 0 3px rgba(65, 255, 126, .75));
}
.loading .bar-fill::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 40%;
  background: linear-gradient(90deg, rgba(220, 255, 230, 0), rgba(220, 255, 230, .6), rgba(220, 255, 230, 0));
  animation: sheen 1.1s linear infinite;
}
.wait .bar-fill::after { animation-play-state: paused; opacity: .35; }
.bar-pct {
  min-width: 4ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--g-hi);
}
.done .bar { border-color: var(--g); }
.done .bar-fill { animation: barflash .7s ease-out 1; }
.hang .bar-pct { animation: blink 1.06s steps(1, end) infinite; }
.fail .bar { border-color: var(--g-dim); }
.fail .bar-fill {
  background: repeating-linear-gradient(90deg, var(--g-dim) 0 .45em, transparent .45em .6em);
  filter: none;
  animation: barfail .45s steps(2, end) 3;
}
.fail .bar-pct { background: var(--g); color: #000; text-shadow: none; padding: 0 .2em; font-weight: 600; }

/* cursor: solid while output streams or the system hangs, blinking when idle */
.cur {
  display: inline-block;
  width: .62em;
  height: 1.12em;
  margin-left: 1px;
  vertical-align: -.2em;
  background: var(--g);
  box-shadow: 0 0 6px rgba(65, 255, 126, .8);
  animation: blink 1.06s steps(1, end) infinite;
}
.typing .cur, .frozen .cur { animation: none; opacity: 1; }

/* ---------- CRT layers ---------- */

.fx {
  position: fixed;
  inset: 0;
  pointer-events: none;
}
.scan {
  background: repeating-linear-gradient(180deg, rgba(0, 0, 0, 0) 0 2px, rgba(0, 0, 0, .28) 2px 3px);
  opacity: .55;
}
.vignette {
  background:
    radial-gradient(120% 90% at 50% 45%, rgba(30, 120, 60, .07) 0%, rgba(0, 0, 0, 0) 60%),
    radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, .6) 100%);
}
.roll {
  bottom: auto;
  height: 22vh;
  background: linear-gradient(180deg, rgba(65, 255, 126, 0), rgba(65, 255, 126, .035), rgba(65, 255, 126, 0));
  will-change: transform;
  animation: roll 9s linear infinite;
}
.flick {
  background: #000;
  opacity: 0;
  will-change: opacity;
  animation: flick 5.3s steps(1, end) infinite;
}
.crt.frozen ~ .fx { animation-play-state: paused; }
body.gate { cursor: pointer; }

/* glitch: a short tear + shake, then back to normal */
.crt.glitch .log { animation: glitch .26s steps(3, end) 1; }
.crt.jitter .log { animation: jitter .14s steps(2, end) 1; }
.crt.glitch::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: var(--tear, 40%);
  height: 2px;
  background: rgba(65, 255, 126, .45);
  box-shadow: 0 0 12px rgba(65, 255, 126, .6);
}

@keyframes blink { 50% { opacity: 0; } }
@keyframes sheen { to { transform: translateX(350%); } }
@keyframes barflash {
  0% { opacity: .3; }
  20% { opacity: 1; }
  35% { opacity: .55; }
  100% { opacity: 1; }
}
@keyframes barfail { 50% { opacity: .25; } }
@keyframes pulse { 50% { opacity: .5; } }
@keyframes roll {
  from { transform: translateY(-30vh); }
  to { transform: translateY(130vh); }
}
@keyframes flick {
  0% { opacity: 0; }
  11% { opacity: .05; }
  12% { opacity: 0; }
  46% { opacity: .03; }
  47% { opacity: 0; }
  71% { opacity: .07; }
  72% { opacity: .02; }
  73% { opacity: 0; }
}
@keyframes glitch {
  0% { transform: translate(-3px, 1px) skewX(5deg); filter: brightness(1.7); }
  33% { transform: translate(3px, -1px) skewX(-3deg); filter: brightness(.8); }
  66% { transform: translate(-1px, 0); filter: brightness(1.3); }
  100% { transform: none; filter: none; }
}
@keyframes jitter {
  0% { transform: translateX(1.5px); }
  50% { transform: translateX(-1px); }
  100% { transform: none; }
}
@keyframes power {
  0% { opacity: 0; transform: scale(.6, .004); filter: brightness(4); }
  12% { opacity: 1; }
  45% { transform: scale(1, .006); filter: brightness(3); }
  100% { transform: none; filter: none; }
}

@media (prefers-reduced-motion: reduce) {
  .crt, .roll, .flick, .live, .pulse, .loading .bar-fill::after { animation: none; }
  .crt.glitch .log, .crt.jitter .log { animation: none; }
  .crt.glitch::after { display: none; }
}
