/* CRT surface effects (ADR-019): scan-line/vignette overlay, the moving scan
   bar, static noise grain, chromatic aberration and the crt.js-driven glitch.
   Co-located with crt.js; depends on terminal.css for the shared :root tokens. */

body {
	/* Scan-line + vignette overlay. */

	&::before {
		content: "";
		position: fixed;
		inset: 0;
		pointer-events: none;
		z-index: 9999;
		background: repeating-linear-gradient(
			to bottom,
			var(--black-alpha-0) 0px,
			var(--black-alpha-0) 2px,
			var(--black-alpha-18) 3px,
			var(--black-alpha-18) 4px
		);
		mix-blend-mode: multiply;
	}

	&::after {
		content: "";
		position: fixed;
		inset: 0;
		pointer-events: none;
		z-index: 9998;
		background: radial-gradient(ellipse at center, var(--black-alpha-0) 55%, var(--black-alpha-55) 100%);
	}
}

/* Moving scanline bar — a bright band that sweeps top-to-bottom on a loop,
   hidden most of the cycle (see the keyframe hold). */
.lk-scanbar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 100%;
	height: 140px;
	z-index: 9997;
	pointer-events: none;
	opacity: 0.04;
	background: linear-gradient(
		0deg,
		var(--amber-alpha-0) 0%,
		var(--amber-alpha-12) 70%,
		var(--scanbar-text-alpha-20) 100%
	);
	animation: lk-scanbar 9s linear infinite;
}

@keyframes lk-scanbar {
	0%, 78% {
		bottom: 100%;
	}
	100% {
		bottom: -140px;
	}
}

/* Static noise texture — fractal-noise SVG tile, jittered each frame. */
.lk-noise {
	position: fixed;
	inset: 0;
	z-index: 9996;
	pointer-events: none;
	opacity: 0.035;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	background-repeat: repeat;
	animation: lk-noise 0.25s steps(4) infinite;
}

@keyframes lk-noise {
	0% {
		background-position: 0 0;
	}
	25% {
		background-position: 50px 50px;
	}
	50% {
		background-position: -50px 20px;
	}
	75% {
		background-position: 30px -30px;
	}
	100% {
		background-position: 0 0;
	}
}

/* Chromatic aberration — offset red/blue ghosts that drift, over the amber
   phosphor glow. Kept subtle so headings stay legible. Consumed by .lk-title
   (assets/standard-time.css) — the keyframe stays here with its CRT siblings. */
@keyframes lk-aberration {
	0% {
		text-shadow: 0.4px 0 1px var(--aberration-blue), -0.4px 0 1px var(--aberration-red), 0 0 8px var(--amber-alpha-50);
	}
	25% {
		text-shadow: 1.6px 0 1px var(--aberration-blue), -1.6px 0 1px var(--aberration-red), 0 0 8px var(--amber-alpha-50);
	}
	50% {
		text-shadow: 0.2px 0 1px var(--aberration-blue), -0.2px 0 1px var(--aberration-red), 0 0 8px var(--amber-alpha-50);
	}
	75% {
		text-shadow: 1.1px 0 1px var(--aberration-blue), -1.1px 0 1px var(--aberration-red), 0 0 8px var(--amber-alpha-50);
	}
	100% {
		text-shadow: 0.4px 0 1px var(--aberration-blue), -0.4px 0 1px var(--aberration-red), 0 0 8px var(--amber-alpha-50);
	}
}

/* Reduced-motion: the CRT effects are this site's whole point, so keep them
   on but calm the most flickery bits — freeze the noise grain (no jitter) and
   slow the scanline sweep. */
@media (prefers-reduced-motion: reduce) {
	.lk-noise {
		animation: none;
	}

	.lk-scanbar {
		animation-duration: 16s;
	}
}

/* ============================================================
   CRT live surface — textured panel fills (#7) and the random
   signal glitch (#5, driven by assets/crt.js).

   Self-contained block: everything below is additive and can be
   lifted out wholesale (along with crt.js and its enqueue) to
   revert. Nothing here lands on live-typed text, so the readout
   and item-picker stay crisp.
   ============================================================ */

/* ── #7 · Textured dark fills ─────────────────────────────────────────────
   Re-declare the fill colour alongside the texture layers so the longhand
   background-image doesn't fight the earlier `background:` shorthand. */
.lk-panel,
.lk-pane {
	background-color: var(--bg-panel);
	background-image: var(--crt-surface-sheen), var(--crt-surface-scan);
}

.lk-output {
	position: relative;
}

/* ── #5 · Random signal glitch ────────────────────────────────────────────
   crt.js flips body.hmb-glitch + a variant class on for a moment and seeds
   the --glitch-* vars. Two variants, picked at random per fire:
     · hmb-glitch-bar   — a static strip at a random height that jumps sideways
     · hmb-glitch-sweep — a scanline that runs top→bottom once
   The rest of the frame never moves; only the strip distorts the UI beneath
   it (backdrop-filter), so it reads as a torn band rather than a shake. */

/* Shared strip — both variants share the look; only the placement and the
   animation differ below. */
body.hmb-glitch .lk-screen::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	height: var(--glitch-h, 10px);
	z-index: 4;
	pointer-events: none;
	/* Distort just the slice of UI behind the strip — brighter, punchier,
	   slightly hue-shifted — so it looks like that band lost sync. */
	backdrop-filter: brightness(1.5) contrast(1.25) hue-rotate(8deg);
	-webkit-backdrop-filter: brightness(1.5) contrast(1.25) hue-rotate(8deg);
	background: var(--glitch-fill);
	/* Chromatic fringe on the strip's edges — the misconverged-tube tell. */
	box-shadow: inset 2px 0 0 var(--glitch-red-edge), inset -2px 0 0 var(--glitch-blue-edge);
}

/* Bar: parked at a random height, jumps sideways in hard steps. */
body.hmb-glitch-bar .lk-screen::after {
	top: var(--glitch-y, 40%);
	animation: lk-glitch-tear var(--glitch-dur, 0.2s) steps(1) both;
}

/* Sweep: a scanline that runs the full height once, smoothly. */
body.hmb-glitch-sweep .lk-screen::after {
	top: 0;
	animation: lk-glitch-sweep var(--glitch-dur, 0.9s) linear both;
}

/* Slide the strip sideways in a few hard steps (--glitch-x is the throw). */
@keyframes lk-glitch-tear {
	0% {
		transform: translateX(0);
	}
	30% {
		transform: translateX(var(--glitch-x, -8px));
	}
	55% {
		transform: translateX(calc(var(--glitch-x, -8px) * -0.5));
	}
	80% {
		transform: translateX(var(--glitch-x, -8px));
	}
	100% {
		transform: translateX(0);
	}
}

/* Run the strip from just above the top edge to just past the bottom. */
@keyframes lk-glitch-sweep {
	0% {
		top: -3%;
	}
	100% {
		top: 103%;
	}
}

/* Grain spikes briefly during the glitch. */
body.hmb-glitch .lk-noise {
	opacity: 0.09;
}

/* Reduced motion: keep both variants but calm them — drop the chromatic
   fringe, soften the distortion, and kill the bar's sideways jump. The sweep
   keeps running (it's smooth, not flickery) and crt.js already slows it. */
@media (prefers-reduced-motion: reduce) {
	body.hmb-glitch .lk-screen::after {
		backdrop-filter: brightness(1.25);
		-webkit-backdrop-filter: brightness(1.25);
		box-shadow: none;
	}

	body.hmb-glitch-bar .lk-screen::after {
		animation: none;
		transform: none;
	}

	body.hmb-glitch .lk-noise {
		opacity: 0.05;
	}
}
