/* ============================================================
   OA/1 — style.css
   One machine, one manual. Monochrome phosphor + paper.
   Every screen effect models a real cathode-ray phenomenon,
   tuned to the threshold of barely perceptible.
   ============================================================ */

/* ---------- font (self-hosted, no network calls) ---------- */
@font-face {
  font-family: "VT323";
  src: url("../fonts/VT323-Regular.woff2") format("woff2"),
       url("../fonts/VT323-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

/* ---------- tokens ---------- */
:root {
  /* the machine — amber tube (DEC VT220 / P3 lineage) */
  --bg:      #0B0B0A;
  --ink:     #DAD7CD;
  --dim:     #6E6B62;
  --accent:  #D08A3E;
  --err:     #B3564D;

  /* the room the machine sits in */
  --room:    #131211;
  --plastic: #1A1917;
  --plastic-edge: #26241f;

  /* the manual — paper */
  --paper:      #F2EFE9;
  --paper-ink:  #21201C;
  --paper-rule: #C9C4B8;
  --stamp:      #A83E32;

  --mono: "VT323", "Cascadia Mono", ui-monospace, Consolas, monospace;
  --fs: clamp(17px, 2.2vmin, 22px);
  --pad: clamp(14px, 2.6vmin, 30px);
}

[data-theme="green"] {
  --ink: #C2D4BC; --dim: #5E6E58; --accent: #93C48B; --err: #C48B8B;
}
[data-theme="white"] {
  --ink: #E8E6E1; --dim: #7A776F; --accent: #E8E6E1; --err: #B3564D;
}
/* REV 2026.03. decommissioned. do not reference. */
[data-theme="mint"] {
  --bg: #0A1220; --ink: #D7E7DE; --dim: #55705F; --accent: #3DFFA5; --err: #FF6B81;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  background: var(--room);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--fs);
  line-height: 1.3;
  overflow: hidden;
}

::selection { background: var(--ink); color: var(--bg); }

a { color: var(--accent); text-decoration: none; }
a:hover, a:focus-visible { background: var(--accent); color: var(--bg); outline: none; }

/* ============================================================
   THE MACHINE — bezel and tube
   ============================================================ */

#machine {
  position: fixed; inset: 0;
  display: flex; align-items: stretch; justify-content: center;
  padding: clamp(0px, 1.6vmin, 22px);
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(255,255,255,0.035), transparent 60%),
    var(--room);
}

#bezel {
  position: relative;
  flex: 1; max-width: 1600px;
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--plastic-edge), var(--plastic) 12%, #151412 90%);
  border-radius: clamp(6px, 1.4vmin, 18px);
  padding: clamp(8px, 1.8vmin, 26px);
  padding-bottom: 0;
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.55),
    0 2px 6px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5),
    inset 1px 0 0 rgba(255, 255, 255, 0.02),
    inset -1px 0 0 rgba(0, 0, 0, 0.3);
}

#screen {
  position: relative;
  flex: 1; min-height: 0;
  background: var(--bg);
  /* CRT glass corners: rounder vertically, like a real tube face */
  border-radius: clamp(10px, 2.4vmin, 30px) / clamp(14px, 3.6vmin, 44px);
  overflow: hidden;
  /* the tube sits deep in the case: seam ring + recess shadow outside,
     curved-glass edge darkening inside */
  box-shadow:
    0 0 0 clamp(2px, 0.5vmin, 6px) #060505,
    0 clamp(2px, 0.5vmin, 6px) clamp(8px, 1.8vmin, 20px) clamp(1px, 0.25vmin, 3px) rgba(0, 0, 0, 0.55),
    inset 0 0 0 1px rgba(0, 0, 0, 0.9),
    inset 0 0 clamp(18px, 4vmin, 48px) rgba(0, 0, 0, 0.75);
}

/* the seam catches light on its lower edge — makes the recess read as 3D */
#screen::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none; z-index: 45;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.045), inset 1px 0 0 rgba(255, 255, 255, 0.015);
}

#tube { position: absolute; inset: 0; }

#bezel-foot {
  display: flex; align-items: center; justify-content: space-between;
  height: clamp(26px, 4.4vmin, 44px);
  padding: 0 6px;
  user-select: none;
}
#badge {
  font-size: max(10px, calc(var(--fs) * 0.52));
  letter-spacing: 0.18em;
  color: #56534b;
}
#foot-right { display: flex; align-items: center; gap: 12px; }
#rev {
  font-size: max(10px, calc(var(--fs) * 0.52));
  letter-spacing: 0.14em;
  color: #45423c;
}
#led {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px 1px color-mix(in srgb, var(--accent) 55%, transparent);
  animation: led-breathe 4s ease-in-out infinite;
}
@keyframes led-breathe { 0%,100% { opacity: 0.9; } 50% { opacity: 0.55; } }

/* ---------- power state: the machine is on or it is not ---------- */
/* body.off = no power (cold open AND after exit). LED dies with it. */
body.off #led { animation: none; background: #3a3833; box-shadow: none; opacity: 0.6; }

/* dead tube: the glass stays — dark, physical, unlit. never an empty box. */
#screen.dead {
  background:
    linear-gradient(115deg, rgba(255, 255, 255, 0.02) 0%, rgba(255, 255, 255, 0.005) 30%, transparent 46%),
    #0D0D0C;
}
#screen.dead #tube,
#screen.dead #noise,
#screen.dead #band,
#screen.dead #dimmer { visibility: hidden; }

#power {
  width: clamp(20px, 3vmin, 28px); height: clamp(20px, 3vmin, 28px);
  padding: 0; border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.55);
  background: linear-gradient(180deg, #211f1c, #171512);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 1px 1px rgba(0, 0, 0, 0.4);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: box-shadow 0.45s ease;
}
#power:active { transform: translateY(1px); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6); }
#power:focus-visible { outline: 1px solid var(--dim); outline-offset: 2px; }
/* IEC power glyph, drawn: broken ring (::before) + stem (::after).
   Only the ring is clipped, so the stem survives in the gap. */
#power-sym {
  position: relative;
  width: 46%; height: 46%;
  transition: filter 0.45s ease;
}
#power-sym::before {
  content: "";
  position: absolute; inset: 0;
  border: 1.5px solid #5c584f; border-radius: 50%;
  clip-path: polygon(-25% 24%, 125% 24%, 125% 125%, -25% 125%);
  transition: border-color 0.45s ease;
}
#power-sym::after {
  content: "";
  position: absolute; left: 50%; top: -16%;
  transform: translateX(-50%);
  width: 1.5px; height: 58%;
  background: #5c584f;
  transition: background 0.45s ease;
}
/* powered: the symbol burns in the tube's accent, breathing with the LED */
body:not(.off) #power {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05),
              0 0 8px 1px color-mix(in srgb, var(--accent) 30%, transparent);
  animation: pwr-lit 4s ease-in-out infinite;
}
body:not(.off) #power-sym {
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 60%, transparent));
}
body:not(.off) #power-sym::before { border-color: var(--accent); }
body:not(.off) #power-sym::after { background: var(--accent); }
@keyframes pwr-lit { 0%, 100% { opacity: 1; } 50% { opacity: 0.72; } }
/* unpowered: the button is the only thing faintly alive */
body.off #power { animation: pwr-attract 3.4s ease-in-out infinite; }
body.off #power-sym::before { border-color: #8a857a; }
body.off #power-sym::after { background: #8a857a; }
@keyframes pwr-attract {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 1px 1px rgba(0,0,0,0.4); }
  50% { box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 0 8px 1px rgba(218,215,205,0.12); }
}

#scrap-tag {
  position: absolute; z-index: 80;
  top: clamp(-4px, -0.5vmin, -2px); right: clamp(24px, 7%, 120px);
  transform: rotate(-4deg);
  transform-origin: 50% 0;
  display: flex; flex-direction: column; gap: 2px;
  width: max-content; max-width: 46vw;
  padding: clamp(10px, 1.6vmin, 16px) clamp(12px, 2vmin, 20px) clamp(8px, 1.4vmin, 14px);
  border: 0;
  background: linear-gradient(175deg, #F2EFE9, #E7E2D7);
  color: #21201C;
  font-family: var(--mono);
  font-size: inherit;
  line-height: inherit;
  text-align: left;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.55), 0 2px 5px rgba(0, 0, 0, 0.35);
  user-select: none; cursor: zoom-in;
  appearance: none;
}
#scrap-tag:hover { transform: translateY(-1px) rotate(-4deg); }
#scrap-tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
/* the tape holding it to the case */
#scrap-tag::before {
  content: "";
  position: absolute; top: -9px; left: 50%;
  transform: translateX(-50%) rotate(1.5deg);
  width: 58%; height: 18px;
  background: rgba(214, 207, 191, 0.5);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
}
#scrap-tag .tag-maker {
  font-size: max(9px, calc(var(--fs) * 0.46));
  letter-spacing: 0.2em; color: #8d887c;
}
#scrap-tag .tag-stamp {
  align-self: flex-start;
  margin: 3px 0 2px;
  padding: 1px 7px;
  border: 2px solid #A83E32; color: #A83E32;
  font-size: max(12px, calc(var(--fs) * 0.62));
  letter-spacing: 0.14em;
  transform: rotate(-1.2deg);
}
#scrap-tag .tag-line {
  font-size: max(11px, calc(var(--fs) * 0.56));
  letter-spacing: 0.05em;
}
#scrap-tag .tag-sig {
  align-self: flex-end;
  font-size: max(10px, calc(var(--fs) * 0.5));
  color: #6d685d;
}
/* reading the warning is not consent */
#scrap-tag.no { animation: tag-refuse 0.4s ease-in-out; }
@keyframes tag-refuse {
  0%, 100% { transform: rotate(-4deg); }
  30% { transform: rotate(-6.5deg); }
  65% { transform: rotate(-2deg); }
}
/* pulled off when the machine is powered anyway */
#scrap-tag.pulled {
  transition: transform 0.7s cubic-bezier(0.5, 0, 0.9, 0.4), opacity 0.45s ease 0.3s;
  transform: translateY(46px) rotate(12deg);
  opacity: 0;
  pointer-events: none;
}

#tag-inspect {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(18px, 4vmin, 56px);
  background:
    radial-gradient(95% 120% at 50% 18%, rgba(242, 239, 233, 0.10), transparent 46%),
    rgba(8, 7, 6, 0.78);
}
#tag-inspect[hidden] { display: none; }
#tag-inspect::before {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(115deg, rgba(255, 255, 255, 0.055), transparent 32%),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.012) 0 1px, transparent 1px 4px);
  pointer-events: none;
}
#tag-inspect .tag-sheet {
  position: relative;
  width: min(92vw, 580px);
  max-height: min(86vh, 760px);
  overflow: auto;
  padding: clamp(30px, 6vmin, 58px) clamp(24px, 5vmin, 50px) clamp(26px, 5vmin, 44px);
  color: var(--paper-ink);
  background:
    linear-gradient(176deg, rgba(255,255,255,0.16), transparent 22%),
    repeating-linear-gradient(90deg, rgba(0,0,0,0.018) 0 1px, transparent 1px 5px),
    linear-gradient(var(--paper), #E8E2D7);
  box-shadow:
    0 1px 1px rgba(0,0,0,0.28),
    0 26px 70px rgba(0,0,0,0.66),
    0 52px 120px rgba(0,0,0,0.46);
  transform: rotate(-1.1deg);
  animation: tag-inspect-in 160ms ease-out;
}
#tag-inspect .tag-sheet::before {
  content: "";
  position: absolute; left: 0; right: 0; top: -7px; height: 7px;
  background: repeating-linear-gradient(90deg, var(--paper) 0 9px, transparent 9px 12px);
}
#tag-inspect .tag-sheet::after {
  content: "";
  position: absolute; left: 9%; right: 9%; bottom: 12px; height: 1px;
  background: rgba(33, 32, 28, 0.14);
}
#tag-close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(33, 32, 28, 0.55);
  background: transparent;
  color: var(--paper-ink);
  font: inherit;
  cursor: pointer;
}
#tag-close:hover,
#tag-close:focus-visible {
  background: var(--paper-ink);
  color: var(--paper);
  outline: none;
}
.tag-pin {
  position: absolute; top: -13px; left: 50%;
  width: min(260px, 54%); height: 32px;
  transform: translateX(-50%) rotate(1.4deg);
  background: rgba(214, 207, 191, 0.58);
  box-shadow: 0 2px 5px rgba(0,0,0,0.18);
}
.tag-sheet-maker {
  color: #7b766b;
  font-size: 0.78em;
  letter-spacing: 0.22em;
}
#tag-inspect h2 {
  margin: 0.5em 0 0.2em;
  font-size: clamp(1.8em, 8vw, 3.2em);
  line-height: 0.92;
  font-weight: 400;
  letter-spacing: 0.03em;
}
.tag-sheet-stamp {
  display: inline-block;
  margin: 0.65em 0 1.2em;
  padding: 0.1em 0.5em;
  border: 4px double var(--stamp);
  color: var(--stamp);
  font-size: clamp(1em, 4vw, 1.45em);
  letter-spacing: 0.12em;
  transform: rotate(-2.2deg);
}
#tag-inspect dl {
  display: grid;
  gap: 0;
  margin: 0.4em 0 1.4em;
  border-top: 1px solid var(--paper-rule);
}
#tag-inspect dl div {
  display: grid;
  grid-template-columns: minmax(5.5em, 32%) 1fr;
  gap: 1em;
  padding: 0.38em 0;
  border-bottom: 1px solid var(--paper-rule);
}
#tag-inspect dt {
  color: #6b675d;
  letter-spacing: 0.12em;
}
#tag-inspect dd { margin: 0; }
.tag-sheet-warning {
  display: inline-block;
  margin: 0.15em 0 0.6em;
  color: var(--stamp);
  font-size: clamp(1.5em, 6vw, 2.3em);
  line-height: 1;
  letter-spacing: 0.09em;
}
.tag-sheet-note {
  max-width: 28em;
  color: #5f5a50;
}
.tag-sheet-sig {
  margin-top: 1.5em;
  text-align: right;
  color: #6d685d;
  font-size: 1.25em;
}
@keyframes tag-inspect-in {
  from { opacity: 0; transform: translateY(12px) scale(0.94) rotate(-1.8deg); }
  to { opacity: 1; transform: translateY(0) scale(1) rotate(-1.1deg); }
}

@media (prefers-reduced-motion: reduce) {
  body.off #power, body:not(.off) #power { animation: none; }
  #scrap-tag.no { animation: none; }
  #tag-inspect .tag-sheet { animation: none; }
  #scrap-tag.pulled { transition: none; opacity: 0; }
}

/* ---------- display (phosphor surface) ---------- */
#display {
  position: absolute; inset: 0;
  overflow-y: auto; overflow-x: hidden;
  padding: var(--pad);
  padding-bottom: calc(var(--pad) + 0.5em);
  scrollbar-width: thin;
  scrollbar-color: #2c2a26 transparent;
  outline: none;
}

#term { white-space: pre-wrap; word-break: break-word; }

.line { min-height: 1.3em; }
pre.line { white-space: pre; overflow-x: auto; }

/* phosphor strike: a new line lands slightly hot, then settles */
[data-fx="full"] .line.hot { animation: strike 160ms ease-out; }
@keyframes strike {
  from { filter: brightness(2.1); }
  to   { filter: brightness(1); }
}

/* ink roles — monochrome discipline: ink, dim, one accent, error */
.d   { color: var(--dim); }
.a   { color: var(--accent); }
.e   { color: var(--err); }
.inv { background: var(--ink); color: var(--bg); }

/* ---------- the line editor ---------- */
#lineedit { white-space: pre-wrap; word-break: break-word; }
#le-prompt .u { color: var(--accent); }
#le-prompt .h { color: var(--ink); }
#le-prompt .p { color: var(--dim); }

#le-cursor {
  background: var(--accent);
  color: var(--bg);
  /* the ONE glow on this machine: cursor bloom */
  box-shadow: 0 0 7px color-mix(in srgb, var(--accent) 45%, transparent);
  animation: blink 1.06s steps(1) infinite;
}
[data-fx="off"] #le-cursor { box-shadow: none; }
body.unfocused #le-cursor { animation: none; background: transparent; color: var(--ink); outline: 1px solid var(--dim); }
@keyframes blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0.08; } }

/* cursor phosphor persistence ghosts (spawned by shell.js) */
.ghost {
  position: fixed; pointer-events: none; z-index: 5;
  background: var(--accent);
  animation: decay 240ms ease-out forwards;
}
@keyframes decay { from { opacity: 0.30; } to { opacity: 0; } }

/* hidden input — offscreen but focusable (drives mobile keyboards) */
#kbd {
  position: fixed; left: 0; bottom: 0;
  width: 4px; height: 4px;
  opacity: 0.01;
  border: 0; padding: 0;
  background: transparent; color: transparent;
  z-index: -1;
}

/* ---------- touch assist keys ---------- */
#keys {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; gap: 8px; padding: 8px 10px;
  overflow-x: auto;
  background: color-mix(in srgb, var(--room) 88%, black);
}
#keys button {
  font: inherit; font-size: calc(var(--fs) * 0.82);
  color: var(--dim);
  background: transparent;
  border: 1px solid #2e2c27;
  padding: 4px 12px;
  white-space: nowrap;
}
#keys button:active { color: var(--bg); background: var(--accent); }
body.has-keys #machine { bottom: 46px; }

/* ============================================================
   GLASS — scanlines, vignette, glare, refresh breathe
   ============================================================ */

#glass { position: absolute; inset: 0; pointer-events: none; z-index: 40; }

/* raster gaps + a faint vertical aperture grille */
#glass::before {
  content: "";
  position: absolute; inset: 0;
  background:
    repeating-linear-gradient(to bottom,
      rgba(0, 0, 0, 0.20) 0px, rgba(0, 0, 0, 0.20) 1px,
      transparent 1px, transparent 3px),
    repeating-linear-gradient(to right,
      rgba(0, 0, 0, 0.10) 0px, rgba(0, 0, 0, 0.10) 1px,
      transparent 1px, transparent 3px);
  opacity: 0.55;
}
@media (min-resolution: 2dppx) { #glass::before { opacity: 0.34; } }

/* curved glass: vignette + convex sheen (one broad top reflection,
   one faint counter-light at the bottom edge — that's what sells 3D) */
#glass::after {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(115% 90% at 50% 46%, transparent 62%, rgba(0,0,0,0.42) 100%),
    radial-gradient(90% 46% at 32% -6%, rgba(255,255,255,0.05), transparent 58%),
    radial-gradient(130% 60% at 50% 108%, rgba(255,255,255,0.02), transparent 55%);
}

/* animated layers live OUTSIDE the filtered tube so the shader chain
   is not re-evaluated every frame */

/* grain: tiny canvas, redrawn ~20fps by the shell; screen-blended */
#noise {
  position: absolute; inset: 0; z-index: 46;
  width: 100%; height: 100%;
  pointer-events: none;
  mix-blend-mode: screen;
  image-rendering: pixelated;
  opacity: 0;
}
[data-fx="full"] #noise { opacity: 0.05; }
#noise.burst { opacity: 0.5 !important; }

/* rolling 50 Hz band drifting down the tube */
#band {
  position: absolute; left: 0; right: 0; top: 0; z-index: 44;
  height: 22%;
  pointer-events: none;
  background: linear-gradient(to bottom,
    transparent, rgba(255, 255, 255, 0.035) 45%, rgba(0, 0, 0, 0.03) 75%, transparent);
  opacity: 0;
}
[data-fx="full"] #band { opacity: 1; animation: band 9s linear infinite; }
@keyframes band {
  from { transform: translateY(-160%); }
  to   { transform: translateY(560%); }
}

/* field breathe + rare dips, as a black veil over everything */
#dimmer {
  position: absolute; inset: 0; z-index: 47;
  background: #000;
  pointer-events: none;
  opacity: 0;
}
[data-fx="full"] #dimmer { animation: phosphor 13s steps(1) infinite; }
@keyframes phosphor {
  0%, 100% { opacity: 0; }
  20% { opacity: 0.012; }
  38% { opacity: 0.03; }
  50% { opacity: 0.015; }
  63%   { opacity: 0.055; }
  63.6% { opacity: 0.02; }
  64.1% { opacity: 0.005; }
  81.2% { opacity: 0.045; }
  82%   { opacity: 0.01; }
}

/* horizontal sync wobble — fired rarely by the shell, never on a loop */
#screen.jitter { animation: jitter 0.14s steps(3) 1; }
@keyframes jitter {
  0%   { transform: translateX(0); }
  33%  { transform: translateX(1.4px) skewX(0.2deg); filter: brightness(1.14); }
  66%  { transform: translateX(-0.9px); filter: brightness(0.92); }
  100% { transform: translateX(0); }
}

/* channel change: analog input-switch snap, fired on program/game/nano
   enter+exit together with a static burst on #noise */
#screen.channel { animation: channel 0.26s steps(5, end) 1; }
@keyframes channel {
  0%   { transform: scale(1, 1); filter: brightness(1); }
  22%  { transform: scale(1.015, 0.90) translateY(1.2%); filter: brightness(1.7) contrast(1.25); }
  48%  { transform: scale(0.99, 1.05); filter: brightness(0.62); }
  72%  { transform: scale(1.004, 0.984) translateY(-0.4%); filter: brightness(1.18); }
  100% { transform: scale(1, 1); filter: brightness(1); }
}

/* the shader chain: barrel displacement -> chromatic fringe -> phosphor
   bloom/halation. Built at runtime (shell.js) as an SVG filter graph —
   the only way to run a "fragment shader" over live, interactive DOM.
   Desktop + fx full only; flat DOM is always the fallback. */
#tube.curved { filter: url(#crt-shader); }

[data-fx="lite"] #glass::after { display: none; }
[data-fx="off"]  #glass { display: none; }

/* ---------- power transitions ---------- */
#screen.off .surface-hide { visibility: hidden; }

#screen.power-off { animation: power-off 0.5s cubic-bezier(0.7, 0, 0.9, 1) forwards; }
@keyframes power-off {
  0%   { transform: scaleY(1);     filter: brightness(1); }
  55%  { transform: scaleY(0.006); filter: brightness(7); }
  85%  { transform: scaleY(0.006) scaleX(0.12); filter: brightness(12); opacity: 1; }
  100% { transform: scaleY(0.006) scaleX(0.0015); filter: brightness(20); opacity: 0; }
}
#screen.power-on { animation: power-on 0.7s cubic-bezier(0.2, 0.8, 0.3, 1) forwards; }
@keyframes power-on {
  0%   { transform: scaleY(0.006) scaleX(0.0015); filter: brightness(16); opacity: 0.7; }
  38%  { transform: scaleY(0.006) scaleX(1); filter: brightness(9); opacity: 1; }
  70%  { transform: scaleY(1); filter: brightness(2.4) blur(1px); }
  100% { transform: scaleY(1); filter: brightness(1) blur(0); }
}

/* warm-up: first seconds after power-on the tube runs slightly hot */
#screen.warm #display { animation: warmup 2.4s ease-out 1; }
@keyframes warmup {
  0%   { filter: brightness(1.35) saturate(0.7); }
  100% { filter: brightness(1) saturate(1); }
}

/* degauss: coil thump when swapping the tube (theme) */
#screen.degauss { animation: degauss 0.42s ease-out 1; }
@keyframes degauss {
  0%   { transform: scale(1) skewX(0deg); filter: brightness(1); }
  18%  { transform: scale(1.012, 0.988) skewX(0.5deg); filter: brightness(1.6); }
  40%  { transform: scale(0.995, 1.006) skewX(-0.35deg); filter: brightness(0.92); }
  65%  { transform: scale(1.004, 0.997) skewX(0.15deg); filter: brightness(1.08); }
  100% { transform: scale(1) skewX(0deg); filter: brightness(1); }
}

/* ============================================================
   SCREENSAVER — low-power phosphor protection
   ============================================================ */
#saver {
  position: absolute; inset: 0; z-index: 30;
  background: var(--bg);
  cursor: none;
}
#saver-mark {
  position: absolute; left: 0; top: 0;
  color: var(--dim);
  white-space: pre;
  transition: transform 4s linear;
  will-change: transform;
}
#saver-mark .a { color: var(--accent); }

/* ============================================================
   PROGRAM TUI — projects run full screen
   ============================================================ */
#program {
  position: absolute; inset: 0; z-index: 20;
  display: flex; flex-direction: column;
  background: var(--bg);
  padding: var(--pad);
  padding-bottom: 0;
}
#program .prog-mark { white-space: pre; color: var(--accent); overflow-x: auto; flex-shrink: 0; }
#program .prog-maker { color: var(--dim); margin: 0.25em 0 0.8em; }

#program .prog-tabs { display: flex; gap: 1.4em; flex-shrink: 0; flex-wrap: wrap; }
#program .prog-tabs button {
  font: inherit; background: none; border: 0;
  color: var(--dim); cursor: pointer; padding: 0;
}
#program .prog-tabs button .k { color: var(--dim); }
#program .prog-tabs button[aria-selected="true"] { background: var(--ink); color: var(--bg); }
#program .prog-tabs button[aria-selected="true"] .k { color: var(--bg); }

#program .prog-body {
  flex: 1; min-height: 0; overflow-y: auto;
  margin-top: 0.8em;
  white-space: pre-wrap; word-break: break-word;
  scrollbar-width: thin; scrollbar-color: #2c2a26 transparent;
}
#program .prog-body pre { white-space: pre; overflow-x: auto; }
#program .prog-body .metric-k { color: var(--dim); }

#program .prog-status {
  flex-shrink: 0;
  display: flex; justify-content: space-between; gap: 1em;
  background: var(--ink); color: var(--bg);
  padding: 0 0.6em;
  margin: 0.6em calc(-1 * var(--pad)) 0;
  font-size: calc(var(--fs) * 0.92);
  white-space: nowrap; overflow: hidden;
}

/* loader box (drawn in the terminal flow) */
.loadbox { color: var(--dim); }
.loadbox .ok { color: var(--ink); }

/* nano pager */
#program.nano { padding: 0; }
#program.nano .nano-top {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 1.4em;
  padding: 0 var(--pad);
  background: var(--ink); color: var(--bg);
}
#program.nano .nano-top .inv { background: transparent; }
#program.nano .nano-top .nano-file { flex: 1; text-align: center; }
#program.nano .nano-top .nano-mod { opacity: 0.7; font-size: 0.85em; }
#program.nano .nano-body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--pad);
  white-space: pre-wrap; word-break: break-word;
  color: var(--ink);
  scrollbar-width: thin; scrollbar-color: #2c2a26 transparent;
}
#program.nano .nano-status {
  flex-shrink: 0;
  padding: 0.2em var(--pad);
  color: var(--dim);
  border-top: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
}
#program.nano .nano-keys {
  flex-shrink: 0;
  padding: 0.3em var(--pad);
  display: flex; flex-wrap: wrap; gap: 0.3em 1.6em;
  color: var(--dim);
  font-size: calc(var(--fs) * 0.9);
}
#program.nano .nano-keys .inv { background: var(--ink); color: var(--bg); padding: 0 0.15em; }

/* snake */
#program.game { align-items: center; }
#program.game .game-board {
  margin: auto;
  color: var(--ink);
  font-size: clamp(16px, 3.4vmin, 30px);
  line-height: 1.12;
  letter-spacing: 0.08em;
}
#program.game .prog-maker { align-self: flex-start; }
#program.game .prog-status { align-self: stretch; }

/* ============================================================
   THE MANUAL — paper mode
   ============================================================ */
#manual {
  position: fixed; inset: 0; z-index: 80;
  overflow-y: auto;
  color: var(--paper-ink);
  font-size: calc(var(--fs) * 0.98);
  /* a desk the sheet lies on: warm, softly lit from top-left */
  background:
    radial-gradient(140% 100% at 20% -10%, #5b5145, #3a342c 55%, #29251f 100%);
}
/* the printed sheet: real paper with a lift shadow and a fiber tint */
#manual .sheet {
  position: relative;
  max-width: 46em;
  margin: clamp(20px, 5vmin, 60px) auto clamp(40px, 8vmin, 90px);
  padding: clamp(28px, 6vmin, 66px) clamp(22px, 5vmin, 54px) 96px;
  background:
    linear-gradient(var(--paper), var(--paper)),
    repeating-linear-gradient(0deg, rgba(0,0,0,0.012) 0 2px, transparent 2px 4px);
  box-shadow:
    0 1px 1px rgba(0,0,0,0.25),
    0 18px 40px rgba(0,0,0,0.45),
    0 40px 80px rgba(0,0,0,0.35);
}
/* torn/curled top edge sells "just printed" */
#manual .sheet::before {
  content: ""; position: absolute; left: 0; right: 0; top: -6px; height: 6px;
  background: repeating-linear-gradient(90deg, var(--paper) 0 7px, transparent 7px 9px);
  filter: drop-shadow(0 -1px 0 rgba(0,0,0,0.12));
}

/* print-head reveal: content wiped in top-to-bottom with a bright bar */
#manual.printing .sheet > * { animation: none; }
#manual.printing .sheet {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 var(--print, 0%), transparent var(--print, 0%));
          mask-image: linear-gradient(to bottom, #000 0%, #000 var(--print, 0%), transparent var(--print, 0%));
  animation: print 1.25s steps(24, end) forwards;
}
#manual.printing .sheet::after {
  content: ""; position: absolute; left: 0; right: 0; height: 2px;
  top: var(--print, 0%);
  background: var(--stamp); opacity: 0.5;
  box-shadow: 0 0 12px 2px color-mix(in srgb, var(--stamp) 60%, transparent);
}
@keyframes print { from { --print: 0%; } to { --print: 102%; } }
@property --print { syntax: "<percentage>"; inherits: false; initial-value: 0%; }

#manual .m-head {
  display: flex; justify-content: space-between; align-items: baseline;
  border-bottom: 2px solid var(--paper-ink);
  padding-bottom: 6px;
}
#manual .m-head .doc { letter-spacing: 0.22em; font-size: 0.78em; }
#manual h1 {
  font-size: 2.1em; font-weight: 400; letter-spacing: 0.12em;
  margin: 0.5em 0 0.1em;
}
#manual .m-sub { color: #6b675d; margin-bottom: 2.2em; }

#manual h2 {
  font-weight: 400; font-size: 0.85em; letter-spacing: 0.22em;
  margin: 2.6em 0 0.9em;
  padding-top: 0.7em;
  border-top: 1px solid var(--paper-rule);
  color: #55524a;
}
#manual h2 .n { color: var(--stamp); margin-right: 1.2em; }

#manual p { margin: 0 0 0.9em; max-width: 62ch; }
#manual .fig-label {
  font-size: 0.75em; letter-spacing: 0.14em; color: #6b675d;
  margin: 1.4em 0 0.3em;
}
#manual table { border-collapse: collapse; width: 100%; }
#manual td, #manual th {
  text-align: left; font-weight: 400;
  border-bottom: 1px solid var(--paper-rule);
  padding: 4px 14px 4px 0; vertical-align: top;
}
#manual th { font-size: 0.78em; letter-spacing: 0.14em; color: #6b675d; }
#manual td.k { color: #6b675d; white-space: nowrap; }
#manual a { color: var(--paper-ink); text-decoration: underline; text-underline-offset: 3px; }
#manual a:hover { background: var(--paper-ink); color: var(--paper); }
#manual ::selection { background: var(--paper-ink); color: var(--paper); }

#manual .stamp {
  display: inline-block;
  border: 3px double var(--stamp); color: var(--stamp);
  padding: 2px 14px;
  letter-spacing: 0.2em; font-size: 0.8em;
  transform: rotate(-3deg);
  margin: 2.5em 0 0;
}
#manual .m-foot {
  margin-top: 4em; padding-top: 0.7em;
  border-top: 1px solid var(--paper-rule);
  display: flex; justify-content: space-between;
  font-size: 0.75em; letter-spacing: 0.14em; color: #6b675d;
}
#manual .m-return {
  position: fixed; top: 14px; right: 16px;
  font: inherit; font-size: 0.8em; letter-spacing: 0.12em;
  background: var(--paper); color: var(--paper-ink);
  border: 1px solid var(--paper-ink);
  padding: 5px 14px; cursor: pointer;
}
#manual .m-return:hover { background: var(--paper-ink); color: var(--paper); }

@media print {
  #machine, #keys, #kbd, .m-return { display: none !important; }
  #manual { position: static; background: white; }
  body { overflow: visible; }
}

/* ============================================================
   NOSCRIPT
   ============================================================ */
.noscript {
  position: fixed; inset: 0; z-index: 100;
  overflow-y: auto;
  background: var(--bg); color: var(--ink);
  padding: 8vmin;
}
.noscript h1 { letter-spacing: 0.14em; font-weight: 400; }
.noscript h2 { color: var(--accent); font-weight: 400; letter-spacing: 0.1em; margin-top: 1.6em; }
.noscript p { max-width: 62ch; margin: 0.6em 0; }

/* ============================================================
   ACCESSIBILITY / DEGRADATION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  #le-cursor { opacity: 1; }
}

@media (max-width: 700px) {
  :root { --fs: clamp(13px, 3.7vw, 17px); --pad: 12px; }
  #machine { padding: 0; }
  #bezel { border-radius: 0; padding: 4px; }
  #screen { border-radius: 10px; }
  #bezel-foot { height: 22px; }
  #badge, #rev { font-size: 9px; }
  #program .prog-mark { font-size: 0.6em; }
  /* boot/neofetch art can still exceed width — let it scroll, never break layout */
  pre.line { max-width: 100%; }
}
