/* IRC "Haunted Broadcast" — Public Viewer
 * One monitor in a dark room. The channel is on its glass (the WebGL CRT, or
 * the DOM transcript without WebGL); the state is on its chin: a typed name
 * strip, who's watching, and the power lamp (green live, amber connecting,
 * red while the channel collapses). The site's header, footer and background
 * video stand aside. ?embed=1 is the glass alone, edge to edge.
 */

/* ============================================
   Page-level: a dark room, lit by the screen
   ============================================ */
body:has(.irc-page) {
    background:
        radial-gradient(ellipse 70% 55% at 50% 44%, rgba(88, 120, 255, 0.09), transparent 70%),
        radial-gradient(ellipse 120% 90% at 50% 110%, rgba(40, 30, 60, 0.35), transparent 60%),
        #050507;
    min-height: 100dvh;
    overflow: hidden;
}
body:has(.irc-page) > header,
body:has(.irc-page) > footer,
body:has(.irc-page) .video-bg { display: none; }
body:has(.irc-page) > main { margin: 0; padding: 0; max-width: none; }

/* for screen readers only */
.irc-sr {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ============================================
   Local CRT palette (GitHub-dark + phosphor)
   ============================================ */
.irc-page {
    --irc-bg: #181522;     /* dark gray-purple */
    --irc-screen: #231f36; /* terminal fog: between dark gray and midnight purple */
    --irc-fg: #c9d1d9;
    --irc-dim: #6e7681;
    --irc-accent: #58a6ff;
    --irc-sys: #8b949e;
    --irc-quit: #f85149;
    --irc-action: #a371f7;
    --irc-join: #3fb950;
    --irc-collapse-bg: rgba(248, 81, 73, 0.07);
    --irc-phosphor: rgba(120, 200, 255, 0.35); /* glow tint */

    /* the monitor's proportions: bezel, chin, and the glass's aspect */
    --bezel: clamp(12px, 2.6vmin, 30px);
    --chin: clamp(40px, 7vmin, 66px);
    --aspect: 1.6;                                  /* 16:10 */
    --below: 44px;                                  /* the links under it */
    /* the glass as big as the room allows, never wider than 1040px */
    --glass-w: min(1040px,
                   calc(100vw - 2 * var(--bezel) - 32px),
                   calc((100dvh - 2 * var(--bezel) - var(--chin) - var(--below) - 40px) * var(--aspect)));

    height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    font-family: 'Libertinus Mono', 'JetBrains Mono', 'Fira Code', monospace;
}

/* ============================================
   The monitor: beige plastic, a recessed glass, a chin
   ============================================ */
.irc-monitor {
    position: relative;
    padding: var(--bezel) var(--bezel) 0;
    border-radius: 18px 18px 22px 22px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.10), transparent 30%),
        linear-gradient(180deg, #d9d3bf 0%, #cbc4ad 55%, #b9b198 100%);
    box-shadow:
        inset 0 2px 0 rgba(255, 255, 255, 0.35),
        inset 0 -3px 0 rgba(0, 0, 0, 0.18),
        0 0 0 1px rgba(0, 0, 0, 0.5),
        0 30px 80px rgba(0, 0, 0, 0.75),
        0 0 120px rgba(88, 120, 255, 0.06);
}

/* the glass sits in a dark recess in the plastic */
.irc-glass {
    padding: 6px;
    border-radius: 12px;
    background: #0b0a10;
    box-shadow:
        inset 0 4px 12px rgba(0, 0, 0, 0.9),
        0 1px 0 rgba(255, 255, 255, 0.35);
}

.irc-screen {
    position: relative;
    width: var(--glass-w);
    aspect-ratio: 16 / 10;
    overflow: hidden;
    border-radius: 10px / 14px;
    background:
        radial-gradient(ellipse 120% 130% at 50% 50%, var(--irc-screen) 62%, #14111e 100%);
    display: flex;
    flex-direction: column;
    /* The whole screen breathes; collapse jacks this up. */
    animation: irc-screen-breathe 6s ease-in-out infinite;
}

@keyframes irc-screen-breathe {
    0%, 100% { filter: brightness(1) contrast(1); }
    50%      { filter: brightness(1.02) contrast(1.02); }
}

/* the chin: a typed name strip, who's watching, the power lamp */
.irc-chin {
    height: var(--chin);
    display: flex;
    align-items: center;
    gap: clamp(10px, 2vw, 22px);
    padding: 0 clamp(6px, 1.5vw, 16px);
}

.irc-plate {
    font-family: 'Love Letter Typewriter', 'Libertinus Mono', monospace;
    font-size: clamp(15px, 2.4vmin, 21px);
    color: #16161c;
    background: #efe8d2;
    padding: 0.08em 1.1em 0.02em;
    transform: rotate(-0.8deg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
    clip-path: polygon(1% 4%, 99% 0, 100% 96%, 0 100%);
}

.irc-watching {
    margin-left: auto;
    font-size: clamp(10px, 1.5vmin, 12px);
    letter-spacing: 0.12em;
    text-transform: lowercase;
    color: rgba(40, 36, 28, 0.62);
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.45);   /* embossed into the plastic */
    white-space: nowrap;
}

.irc-led {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #4a4438;
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.6), 0 1px 0 rgba(255, 255, 255, 0.4);
    flex: none;
}
.irc-led.connected {
    background: #57e08a;
    box-shadow: 0 0 6px 1px rgba(87, 224, 138, 0.7), inset 0 -1px 1px rgba(0, 0, 0, 0.3);
}
.irc-led.connecting {
    background: #f5c542;
    box-shadow: 0 0 6px 1px rgba(245, 197, 66, 0.6);
    animation: irc-dot-pulse 1s ease-in-out infinite;
}
.irc-led.error { background: #a33; box-shadow: none; }
/* the channel is dying: the lamp says so, and the set shudders */
.irc-monitor:has(.irc-screen.collapsing) .irc-led {
    background: #ff4d4d;
    box-shadow: 0 0 8px 2px rgba(255, 77, 77, 0.75);
    animation: irc-led-panic 0.35s steps(2, jump-none) infinite;
}
.irc-monitor:has(.irc-screen.collapsing) { animation: irc-shudder 0.28s linear infinite; }
@keyframes irc-led-panic { 50% { opacity: 0.25; } }
@keyframes irc-shudder {
    0%, 100% { transform: translate(0, 0); }
    25% { transform: translate(-0.6px, 0.4px); }
    50% { transform: translate(0.5px, -0.3px); }
    75% { transform: translate(-0.3px, -0.5px); }
}

/* elsewhere, under the monitor, barely there */
.irc-under {
    display: flex;
    gap: 1.6em;
    font-size: 0.72rem;
    letter-spacing: 0.1em;
}
.irc-under a { color: rgba(200, 205, 225, 0.55); text-decoration: none; }
.irc-under a:hover, .irc-under a:focus-visible {
    color: rgba(230, 235, 255, 0.9);
    outline: none;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ============================================
   Title bar (inside the screen)
   ============================================ */
.irc-titlebar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.9rem;
    font-size: 0.8rem;
    color: var(--irc-dim);
    border-bottom: 1px solid rgba(120, 200, 255, 0.12);
    background: rgba(0, 0, 0, 0.35);
    flex: 0 0 auto;
    z-index: 3;
}

.irc-channel {
    color: var(--irc-accent);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-shadow: 0 0 8px rgba(88, 166, 255, 0.5);
}

.irc-titlebar-spacer { flex: 1 1 auto; }

.irc-conn {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    text-transform: lowercase;
    letter-spacing: 0.05em;
}

.irc-conn-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--irc-dim);
    box-shadow: 0 0 6px currentColor;
}

.irc-conn.connecting .irc-conn-dot { background: #facc15; animation: irc-dot-pulse 1s ease-in-out infinite; }
.irc-conn.connected  .irc-conn-dot { background: var(--irc-join); }
.irc-conn.lost       .irc-conn-dot { background: var(--irc-quit); }

@keyframes irc-dot-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

/* ============================================
   Transcript
   ============================================ */
.irc-log {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Clear the edge-feather band so DOM-fallback text stays in the opaque center. */
    padding: 58px 88px;
    font-size: 0.92rem;
    line-height: 1.55;
    color: var(--irc-fg);
    /* phosphor glow on everything drawn here */
    text-shadow: 0 0 2px var(--irc-phosphor);
    scrollbar-width: thin;
    scrollbar-color: rgba(120,200,255,0.25) transparent;
    z-index: 2;
}

.irc-log::-webkit-scrollbar { width: 8px; }
.irc-log::-webkit-scrollbar-thumb { background: rgba(120,200,255,0.2); border-radius: 4px; }

.irc-line {
    display: flex;
    gap: 0.6rem;
    word-break: break-word;
    animation: irc-line-in 0.18s ease-out;
}

@keyframes irc-line-in {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: none; }
}

.irc-line .ts {
    color: var(--irc-dim);
    opacity: 0.55;
    flex: 0 0 auto;
}

.irc-line .nick { font-weight: 600; }

.irc-line.message .body { color: var(--irc-fg); }
.irc-line.system .body,
.irc-line.join .body,
.irc-line.part .body  { color: var(--irc-sys); font-style: italic; }
.irc-line.action .body { color: var(--irc-action); font-style: italic; }
.irc-line.quit .body,
.irc-line.kick .body  { color: var(--irc-quit); }

/* ============================================
   Collapse — the channel dies
   ============================================ */
.irc-line.in-collapse {
    background: var(--irc-collapse-bg);
}

/* Once collapse begins, the whole screen destabilizes. */
.irc-screen.collapsing {
    animation: irc-screen-collapse 0.45s steps(2, end) infinite;
}

@keyframes irc-screen-collapse {
    0%   { filter: brightness(1.05) contrast(1.1); transform: translate(0, 0); }
    25%  { filter: brightness(0.9) contrast(1.3) hue-rotate(-8deg); transform: translate(-1px, 0.5px); }
    50%  { filter: brightness(1.15) contrast(0.95); transform: translate(1px, -0.5px); }
    75%  { filter: brightness(0.85) contrast(1.4) hue-rotate(6deg); transform: translate(0.5px, 1px); }
    100% { filter: brightness(1.05) contrast(1.1); transform: translate(0, 0); }
}

/* Chromatic aberration on the transcript, hard during collapse. */
.irc-screen.collapsing .irc-log {
    text-shadow:
        -1.5px 0 1px rgba(248, 81, 73, 0.6),
        1.5px 0 1px rgba(88, 166, 255, 0.6),
        0 0 3px var(--irc-phosphor);
    animation: irc-aberrate 0.2s steps(2) infinite;
}

@keyframes irc-aberrate {
    0%   { transform: translateX(0); }
    50%  { transform: translateX(-0.5px); }
    100% { transform: translateX(0.5px); }
}

/* Lines arriving during collapse jitter individually. */
.irc-screen.collapsing .irc-line.in-collapse {
    animation: irc-line-in 0.18s ease-out, irc-jitter 0.12s steps(2) infinite;
}

@keyframes irc-jitter {
    0%   { transform: translateX(0); }
    50%  { transform: translateX(-1px) skewX(-0.4deg); }
    100% { transform: translateX(1px) skewX(0.4deg); }
}

/* A roll bar that sweeps down the screen while collapsing. */
.irc-screen.collapsing::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    height: 28%;
    top: -28%;
    background: linear-gradient(to bottom, transparent, rgba(120,200,255,0.05), transparent);
    pointer-events: none;
    z-index: 5;
    animation: irc-rollbar 1.4s linear infinite;
}

@keyframes irc-rollbar {
    from { top: -28%; }
    to   { top: 100%; }
}

/* "signal lost" flash between fragments */
.irc-screen.signal-lost .irc-log { opacity: 0.15; transition: opacity 0.4s ease; }

/* ============================================
   Blinking prompt
   ============================================ */
.irc-prompt {
    flex: 0 0 auto;
    padding: 0.2rem 1rem 0.7rem;
    color: var(--irc-accent);
    text-shadow: 0 0 6px rgba(88, 166, 255, 0.6);
    z-index: 2;
}

.irc-cursor {
    display: inline-block;
    animation: irc-blink 1.05s steps(1) infinite;
}

@keyframes irc-blink {
    0%, 49%  { opacity: 1; }
    50%, 100% { opacity: 0; }
}

/* ============================================
   Loading overlay
   ============================================ */
.irc-loading {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--irc-screen);
    z-index: 8;
    transition: opacity 0.6s ease;
}

.irc-loading.hidden {
    opacity: 0;
    pointer-events: none;
}

.irc-loading-text {
    color: var(--irc-dim);
    font-size: 0.9rem;
    text-transform: lowercase;
    letter-spacing: 0.12em;
    text-shadow: 0 0 6px var(--irc-phosphor);
    animation: irc-blink 1.6s steps(1) infinite;
}

/* ============================================
   CRT effect layers
   ============================================ */
.irc-scanlines,
.irc-flicker,
.irc-vignette {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.irc-scanlines {
    z-index: 6;
    background: repeating-linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0) 0px,
        rgba(0, 0, 0, 0) 2px,
        rgba(0, 0, 0, 0.22) 3px,
        rgba(0, 0, 0, 0.22) 3px
    );
    mix-blend-mode: multiply;
}

.irc-flicker {
    z-index: 7;
    background: rgba(120, 200, 255, 0.02);
    animation: irc-flicker 0.18s steps(3) infinite;
}

@keyframes irc-flicker {
    0%   { opacity: 0.32; }
    50%  { opacity: 0.12; }
    100% { opacity: 0.28; }
}

.irc-vignette {
    z-index: 6;
    background: radial-gradient(ellipse 100% 100% at 50% 50%,
        transparent 55%, rgba(0, 0, 0, 0.55) 100%);
}

/* ============================================
   WebGL CRT canvas (texture-based post-process)
   ============================================ */
.irc-gl {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: none;        /* shown only when WebGL initializes */
    z-index: 4;
    background: #04060a;
}

/* When the shader is live it owns ALL the CRT effects, so drop the CSS
   layers + the DOM transcript (kept underneath only for a11y / fallback). */
.irc-screen.webgl-active .irc-gl { display: block; }
.irc-screen.webgl-active .irc-scanlines,
.irc-screen.webgl-active .irc-flicker,
.irc-screen.webgl-active .irc-vignette,
.irc-screen.webgl-active .irc-titlebar,
.irc-screen.webgl-active .irc-prompt { display: none; }

/* Keep the DOM log present for screen readers, but visually hand the screen
   to the (opaque) WebGL canvas drawn on top of it. */
.irc-screen.webgl-active .irc-log {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
}

/* ============================================
   Phones and tall windows: the glass turns 3:4
   ============================================ */
@media (max-aspect-ratio: 4 / 5) {
    .irc-page { --aspect: 0.75; }
    .irc-screen { aspect-ratio: 3 / 4; }
}
@media (max-width: 560px) {
    .irc-log { font-size: 0.85rem; padding: 16px 16px; }
    .irc-under { gap: 1.1em; font-size: 0.68rem; }
}

/* ============================================
   Embed mode: the glass alone, edge to edge
   ============================================ */
.embed-mode.irc-page { height: 100dvh; gap: 0; }
.embed-mode .irc-monitor,
.embed-mode .irc-glass {
    padding: 0;
    background: none;
    box-shadow: none;
    border-radius: 0;
    animation: none;
}
.embed-mode .irc-chin,
.embed-mode .irc-under { display: none; }
.embed-mode .irc-screen {
    width: 100vw;
    height: 100dvh;
    aspect-ratio: auto;
    border-radius: 0;
}

/* ============================================
   Reduced motion — keep it legible, drop the seizures
   ============================================ */
@media (prefers-reduced-motion: reduce) {
    .irc-screen,
    .irc-screen.collapsing,
    .irc-screen.collapsing .irc-log,
    .irc-screen.collapsing .irc-line.in-collapse,
    .irc-screen.collapsing::after,
    .irc-flicker,
    .irc-cursor,
    .irc-line,
    .irc-monitor,
    .irc-led {
        animation: none !important;
    }
    .irc-screen.collapsing .irc-log {
        text-shadow:
            -1px 0 1px rgba(248, 81, 73, 0.5),
            1px 0 1px rgba(88, 166, 255, 0.5);
    }
}
