/* ============================================================================
   CRT TV  ::  makes an image look like it is on a dying television
   ----------------------------------------------------------------------------
   Applied by wrapping the image in <div class="crt-tv">. The markup only needs
   the class; crt-tv.js builds the layers inside it.

   Layers, bottom to top:
     1. the image itself, dimmed and slightly desaturated
     2. rolling interference bar (a soft bright band sweeping down)
     3. fine grain (CSS gradients; always present, very cheap)
     4. scanlines
     5. noise canvas, hidden until a static burst (driven by the script)
     6. vignette + curved-glass shading, which also rounds the corners so the
        frame reads as a tube rather than a rectangle

   Motion is expressed as long, irregular animations rather than a steady
   flicker: a perfect sine reads as "animated", whereas uneven hold-and-jitter
   reads as failing hardware.

   Everything here is disabled under prefers-reduced-motion, except the static
   shading, so the "old television" look remains without any movement.
   ========================================================================== */

.crt-tv {
    position: relative;
    overflow: hidden;
    display: block;
    /* Curved glass: an asymmetric radius hides the corners the way a tube does. */
    border-radius: 18px / 14px;
    background: #05030a;
    isolation: isolate;
    /* Tube bezel */
    box-shadow:
        0 0 0 2px #1a1030,
        0 0 0 4px #0a0714,
        0 0 18px rgba(0, 229, 255, 0.18),
        inset 0 0 40px rgba(0, 0, 0, 0.85);
}

.crt-tv > img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Phosphor: a touch dim, slightly cool, never fully saturated */
    filter: saturate(0.85) brightness(0.92) contrast(1.08);
    animation: crtBrightness 7.3s steps(1, end) infinite;
}

/* --- 2. rolling interference bar ---------------------------------------- */
.crt-tv::before {
    content: "";
    position: absolute;
    inset: -20% 0 auto 0;
    height: 22%;
    background: linear-gradient(
        to bottom,
        transparent,
        rgba(125, 249, 255, 0.055) 35%,
        rgba(255, 255, 255, 0.09) 50%,
        rgba(125, 249, 255, 0.055) 65%,
        transparent
    );
    animation: crtRoll 5.7s linear infinite;
    pointer-events: none;
    z-index: 3;
    mix-blend-mode: screen;
}

/* --- 3+4. grain and scanlines ------------------------------------------- */
.crt-tv > .crt-grain,
.crt-tv > .crt-scan {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.crt-tv > .crt-grain {
    z-index: 4;
    opacity: 0.22;
    background-image:
        repeating-radial-gradient(circle at 17% 32%, rgba(255, 255, 255, 0.10) 0 1px, transparent 1px 3px),
        repeating-radial-gradient(circle at 71% 63%, rgba(0, 0, 0, 0.12) 0 1px, transparent 1px 4px);
    background-size: 5px 5px, 7px 7px;
    animation: crtGrainShift 0.9s steps(3) infinite;
}

.crt-tv > .crt-scan {
    z-index: 5;
    background: repeating-linear-gradient(
        0deg,
        rgba(0, 0, 0, 0.30) 0px,
        rgba(0, 0, 0, 0.30) 1px,
        transparent 1px,
        transparent 3px
    );
    animation: crtScanShift 0.12s linear infinite;
}

/* --- 5. static burst canvas --------------------------------------------- */
.crt-tv > .crt-noise {
    position: absolute;
    inset: 0;
    z-index: 6;
    width: 100%;
    height: 100%;
    opacity: 0;
    pointer-events: none;
    transition: opacity 60ms linear;
}

.crt-tv.crt-burst > .crt-noise {
    opacity: 1;
}

/* Reduced-motion bursts are held longer and dimmer so they read as a moment of
   bad reception rather than a flash of white. */
.crt-tv.crt-burst-soft > .crt-noise {
    opacity: 0.55;
}

/* --- 6. vignette / curved glass shading --------------------------------- */
.crt-tv > .crt-glass {
    position: absolute;
    inset: 0;
    z-index: 7;
    pointer-events: none;
    border-radius: inherit;
    background:
        /* corner shading, stronger at the edges than the middle */
        radial-gradient(ellipse 105% 105% at 50% 50%,
            rgba(0, 0, 0, 0) 55%,
            rgba(0, 0, 0, 0.28) 78%,
            rgba(0, 0, 0, 0.62) 100%),
        /* faint cyan bloom across the face of the tube */
        radial-gradient(ellipse 70% 55% at 50% 42%,
            rgba(0, 229, 255, 0.07),
            transparent 70%);
    box-shadow: inset 0 0 26px rgba(0, 0, 0, 0.75);
}

/* --- animations --------------------------------------------------------- */

/* Uneven brightness: a few long holds, then quick dips. Not a sine. */
@keyframes crtBrightness {
    0%   { filter: saturate(0.85) brightness(0.92) contrast(1.08); }
    18%  { filter: saturate(0.85) brightness(0.88) contrast(1.08); }
    19%  { filter: saturate(0.85) brightness(0.98) contrast(1.10); }
    20%  { filter: saturate(0.85) brightness(0.90) contrast(1.08); }
    47%  { filter: saturate(0.85) brightness(0.94) contrast(1.08); }
    48%  { filter: saturate(0.80) brightness(0.84) contrast(1.10); }
    49%  { filter: saturate(0.85) brightness(0.95) contrast(1.08); }
    76%  { filter: saturate(0.85) brightness(0.89) contrast(1.08); }
    77%  { filter: saturate(0.85) brightness(0.99) contrast(1.09); }
    78%  { filter: saturate(0.85) brightness(0.91) contrast(1.08); }
    100% { filter: saturate(0.85) brightness(0.92) contrast(1.08); }
}

@keyframes crtRoll {
    0%   { transform: translateY(-30%); }
    100% { transform: translateY(600%); }
}

@keyframes crtGrainShift {
    0%   { background-position: 0 0, 0 0; }
    33%  { background-position: 2px 1px, -1px 2px; }
    66%  { background-position: -2px 2px, 2px -1px; }
    100% { background-position: 1px -2px, -2px 1px; }
}

@keyframes crtScanShift {
    0%   { transform: translateY(0); }
    100% { transform: translateY(3px); }
}

/* A slow horizontal hold slip, like the set losing sync for a frame. */
.crt-tv > img.crt-slip {
    animation: crtSlip 180ms steps(2, end);
}

@keyframes crtSlip {
    0%   { transform: translateX(0); }
    40%  { transform: translateX(-3px); }
    70%  { transform: translateX(2px); }
    100% { transform: translateX(0); }
}

/* --- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    .crt-tv > img,
    .crt-tv::before,
    .crt-tv > .crt-grain,
    .crt-tv > .crt-scan {
        animation: none !important;
    }
    /* Keep the static frame (noise disabled by the script) but lose the
       rolling bar, which has no static reading. */
    .crt-tv::before { display: none; }
}
