/* ============================================================
   CRT TELEVISION — TEASER SITE
   PNG overlay approach: frame-cutout.png sits at z-index 99
   with a transparent screen hole. Video plays behind it.
   ============================================================ */

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --phosphor-green: #2eff5a;
  --phosphor-dim:   rgba(46, 255, 90, 0.4);
  --power-red:      #c41a1a;
  --chat-bg:        rgba(0, 0, 0, 0.62);
  --chat-text:      rgba(255, 255, 255, 0.82);
  --chat-dim:       rgba(255, 255, 255, 0.28);
  --mono:           'Courier New', 'Lucida Console', monospace;

  /* Screen hole coordinates — derived from alpha-channel analysis of the
     CURRENT frame-cutout.png (3031×2056). PNG has been eroded by a 30 px
     circular kernel to push the transparent hole past the ~25-30 px black
     "screen recess" band the bezel art has painted inside its inner edge.
     Re-sample if the PNG is ever swapped. */
  --screen-left:   11.88%;
  --screen-top:    9.29%;
  --screen-width:  76.25%;
  --screen-height: 80.84%;
}

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
  font-family: var(--mono);
  -webkit-font-smoothing: none;
  -moz-osx-font-smoothing: grayscale;
}


/* ============================================================
   SCREEN LAYER (z-index: 10)
   Positioned to exactly match the transparent hole in the PNG.
   All screen content (video, chat, overlays) lives here.
   ============================================================ */

.screen-layer {
  position: fixed;
  top:    0;
  left:   0;
  width:  100vw;
  height: 100vh;
  z-index: 1;
  overflow: hidden;
  background: #000;
}


/* ============================================================
   VIDEO LAYER
   ============================================================ */

.video-layer {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.video-layer video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


/* ============================================================
   GRAPHICS LAYER — drop overlays and HUD elements here
   ============================================================ */

.graphics-layer {
  position: absolute;
  inset: 0;
  z-index: 15;
  pointer-events: none;
}


/* ============================================================
   STATIC / VHS TRANSITION
   Triggered by JS on channel switch via .active class
   ============================================================ */

.static-overlay {
  position: absolute;
  inset: 0;
  z-index: 25;
  pointer-events: none;
  opacity: 0;
  background:
    repeating-linear-gradient(
      to bottom,
      transparent 0px,
      transparent 1px,
      rgba(255, 255, 255, 0.025) 1px,
      rgba(255, 255, 255, 0.025) 2px
    ),
    url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 100% 100%, 200px 200px;
  mix-blend-mode: screen;
}

.static-overlay.active {
  animation: static-flicker 0.5s steps(4) forwards;
}

@keyframes static-flicker {
  0%   { opacity: 1;    background-position: 0 0,    0 0; }
  15%  { opacity: 0.88; background-position: 0 -18px, 40px 25px; }
  30%  { opacity: 1;    background-position: 0  10px, -25px -15px; }
  50%  { opacity: 0.72; background-position: 0  -4px,  70px  8px; }
  70%  { opacity: 0.9;  background-position: 0  14px, -8px  45px; }
  85%  { opacity: 0.5;  background-position: 0    0,  18px -35px; }
  100% { opacity: 0; }
}


/* ============================================================
   SCREEN EFFECTS
   Scanlines + corner vignette. Pointer-events none.
   Sits above video, below chat.
   ============================================================ */

.screen-effects {
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  /* Scanlines — CSS only, ~2px lines at 8% opacity */
  background: repeating-linear-gradient(
    to bottom,
    transparent 0px,
    transparent 2px,
    rgba(0, 0, 0, 0.08) 2px,
    rgba(0, 0, 0, 0.08) 4px
  );
}

/* Corner vignette via pseudo-element */
.screen-effects::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 88% 82% at 50% 50%,
    transparent 48%,
    rgba(0, 0, 0, 0.55) 100%
  );
}


/* ============================================================
   CRT BULGE — convex glass curvature effect
   Positioned to match the transparent screen hole in frame-cutout.png
   ============================================================ */

.screen-bulge {
  position: absolute;
  left:   18.2%;
  top:    25.8%;
  width:  65.6%;
  height: 46.2%;
  z-index: 22;
  pointer-events: none;
  border-radius: 48% / 12%;

  /* Convex glass: bright centre fading to darker curved edges */
  background: radial-gradient(
    ellipse 80% 70% at 50% 46%,
    rgba(255, 255, 255, 0.028) 0%,
    transparent                55%,
    rgba(0, 0, 0, 0.22)        100%
  );

  /* Inset edge glow — the rim of light you see on real CRT glass */
  box-shadow:
    inset 0  0   28px 6px  rgba(255, 255, 255, 0.055),
    inset 0  0   80px 20px rgba(0,   0,   0,   0.30),
    inset 0  6px 18px 0px  rgba(255, 255, 255, 0.04),
    inset 0 -6px 18px 0px  rgba(0,   0,   0,   0.18);
}

/* ============================================================
   CHAT — exact copy of chat-test.html styles, left/bottom
   offset by the screen hole position (left 18.2%, bottom 28%)
   ============================================================ */

.chat-zone {
  position: fixed;
  left: 30px;
  bottom: 120px;
  width: min(520px, calc(100vw - 60px));
  height: min(46vh, 420px);
  z-index: 1001;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  pointer-events: none;
}

/* Full bottom-left gradient scrim — pinned to viewport edge, fades up
   and to the right so chat sits in a soft pool of darkness without a
   hard right edge. Sits behind every chat element. */
.chat-scrim {
  position: fixed;
  left: 0;
  bottom: 0;
  width: min(720px, 80vw);
  height: min(70vh, 620px);
  z-index: 1000;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.62);
  -webkit-mask-image:
    linear-gradient(to top,   #000 0%, #000 35%, transparent 100%),
    linear-gradient(to right, #000 0%, #000 40%, transparent 100%);
  mask-image:
    linear-gradient(to top,   #000 0%, #000 35%, transparent 100%),
    linear-gradient(to right, #000 0%, #000 40%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

.messages {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 20px 16px 16px 20px;
  mask-image: linear-gradient(to bottom, transparent 0%, black 28%, black 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 28%, black 100%);
}

.msg {
  display: flex;
  align-items: baseline;
  gap: 0;
  line-height: 1.55;
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  /* opacity is set inline per-message by main.js (CRT phosphor falloff). */
  animation: msg-fade-in 0.25s ease-out;
}

@keyframes msg-fade-in {
  from { transform: translateY(6px); }
  to   { transform: translateY(0); }
}

.msg-name {
  font-size: 16px;
  color: var(--ooo-cyan);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  flex-shrink: 0;
}

.msg-sep {
  color: var(--ooo-cyan);
  margin: 0 10px;
  font-size: 16px;
  flex-shrink: 0;
}

.msg-text {
  font-size: 16px;
  color: var(--ooo-cyan);
  letter-spacing: 0.12em;
  word-break: break-word;
}

.msg-time {
  font-size: 13px;
  color: var(--ooo-cyan);
  margin-left: 12px;
  letter-spacing: 0.12em;
  flex-shrink: 0;
  align-self: baseline;
  opacity: 0.7;
}

/* Input wrap */
.chat-input-wrap {
  position: fixed;
  left: 30px;
  bottom: 30px;
  width: min(520px, calc(100vw - 60px));
  z-index: 1002;
  display: flex;
  flex-direction: column;
  gap: 0;
  pointer-events: auto;
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
}

.name-phase {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.name-phase.hidden,
.msg-phase.hidden {
  display: none;
}

/* Chat input restyled to match the broadcast-HUD overlay typography:
   transparent surfaces, no boxes, hard edges, cyan throughout, with
   only a single 1px cyan underline beneath the input field as the
   type target. JOIN/SEND becomes plain cyan text. */

.name-label {
  font-size: 18px;
  letter-spacing: 0.12em;
  color: var(--ooo-cyan);
  text-transform: uppercase;
  padding-left: 2px;
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  text-shadow:
    0 0 4px rgba(92, 214, 255, 0.55),
    0 0 10px rgba(92, 214, 255, 0.25);
}

.name-field,
.msg-phase {
  display: flex;
  align-items: stretch;
}

.who-prefix {
  font-size: 18px;
  letter-spacing: 0.12em;
  color: var(--ooo-cyan);
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
  padding: 10px 12px 10px 2px;
  text-transform: uppercase;
  white-space: nowrap;
  display: flex;
  align-items: center;
  border-radius: 0;
  flex-shrink: 0;
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  text-shadow:
    0 0 4px rgba(92, 214, 255, 0.55),
    0 0 10px rgba(92, 214, 255, 0.25);
}

.chat-input-wrap input {
  flex: 1;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
  border-bottom: 1px solid var(--ooo-cyan);
  color: var(--ooo-cyan);
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  font-size: 18px;
  letter-spacing: 0.12em;
  padding: 10px 4px;
  outline: none;
  caret-color: var(--ooo-cyan);
  border-radius: 0;
  transition: border-bottom-color 0.15s, box-shadow 0.15s;
}

.name-field input {
  border-radius: 0;
}

.chat-input-wrap input::placeholder {
  color: rgba(92, 214, 255, 0.6);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.chat-input-wrap input:focus {
  border-bottom-color: #b8eaff;
  box-shadow: 0 1px 0 rgba(184, 234, 255, 0.45);
}

.submit-btn {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
  color: var(--ooo-cyan);
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  font-size: 18px;
  letter-spacing: 0.12em;
  padding: 10px 0 10px 16px;
  cursor: pointer;
  text-transform: uppercase;
  transition: color 0.15s, text-shadow 0.15s;
  border-radius: 0;
  flex-shrink: 0;
  text-shadow:
    0 0 4px rgba(92, 214, 255, 0.55),
    0 0 10px rgba(92, 214, 255, 0.25);
}

.submit-btn:hover {
  background: transparent;
  color: #b8eaff;
  text-shadow:
    0 0 6px rgba(184, 234, 255, 0.75),
    0 0 14px rgba(184, 234, 255, 0.45);
}


/* ============================================================
   OOO.LAND HOLDING PAGE
   - Positioned to the TV screen aperture (the transparent
     hole baked into frame-cutout.png), so on desktop the
     video sits exactly inside the bezel.
   - Inside the aperture, a 1:1 wrap holds the video; the
     video is object-fit:contain (no crop, native aspect).
     Letterbox bars on left/right fill with black so they
     read as intentional broadcast bars.
   - PARIS/BERLIN/LONDON clocks anchor bottom-right of the
     video wrap; COMING SOON anchors bottom-centre — both
     track the video's exact bounds as it scales.
   ============================================================ */

:root {
  --ooo-cyan: #5cd6ff;
}

/* Kill the deprecated vhs.css fallback texture on #screen so nothing
   leaks behind the aperture on mobile (where .main1 is hidden). */
#screen {
  background: #000 !important;
}

/* Hide the CHANNELS overlay on the holding page. The channel-switcher
   markup + main.js wiring is kept intact for when real channel videos
   ship — un-hide this rule then. */
#vcr-menu {
  display: none !important;
}

#ooo-holding {
  position: absolute;
  top:    var(--screen-top);
  left:   var(--screen-left);
  width:  var(--screen-width);
  height: var(--screen-height);
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  overflow: hidden;
  z-index: 2;
  /* Slight CRT-glass rounded corners — matches the visible inside curve
     of the bezel PNG and softens the rectangular aperture into something
     that reads as curved glass. */
  border-radius: 3% / 4.5%;
}

/* CRT-glass bulge on the video itself. translateZ inside a tight
   perspective gives a uniform forward push (the picture grows toward
   the viewer); paired with a sizeable border-radius on the video the
   visible result reads as convex curved glass — rounded corners +
   slight scale-up = old CRT tube. The whole thing is scoped to the
   video element so the bezel and overlays stay flat. */
.ooo-video-wrap .ooo-bg-video {
  transform: perspective(500px) translateZ(40px);
  transform-origin: center center;
  border-radius: 4% / 6%;
}

/* 1:1 wrap on desktop is sized by holding.js (sizeDesktopWrap) — JS
   reads the aperture rect and sets wrap = aperture.height - 12px on
   each side. Mobile uses the 9:16 CSS formula in the @media block
   below. The base rule here only sets positioning context. */
.ooo-video-wrap {
  position: relative;
}

/* Specificity beats .video-layer video {object-fit:cover} above. */
.ooo-video-wrap .ooo-bg-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
  pointer-events: none;
  user-select: none;
}

/* Desktop layout: COMING SOON + clocks live in a SINGLE right-pillarbox
   block (.ooo-holding-rightblock), vertically centred, COMING SOON stacked
   above the clocks with a small gap, both right-aligned. The chat now
   occupies the LEFT pillarbox bar (rules further down). On mobile the
   wrapper goes `display: contents` and the children fall back to their
   own absolute positioning (under-aperture row, L+R split). */

.ooo-holding-rightblock {
  position: absolute;
  top: 50%;
  right: 24px;
  transform: translateY(-50%);
  z-index: 7;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 18px;
  pointer-events: none;
}

.ooo-holding-coming-soon {
  color: var(--ooo-cyan);
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  font-size: clamp(10px, 1.6vmin, 16px);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  white-space: nowrap;
  /* Black halo first (legibility over video), then the cyan glow.       */
  text-shadow:
    0 0 2px rgba(0, 0, 0, 0.8),
    0 0 8px rgba(0, 0, 0, 0.8),
    0 0 4px rgba(92, 214, 255, 0.55),
    0 0 10px rgba(92, 214, 255, 0.25);
  pointer-events: none;
}

.ooo-holding-clocks {
  /* Grid so all three rows align on the colon column even with
     mixed-length city names (PARIS / BERLIN / LONDON). */
  display: grid;
  grid-template-columns: auto auto;
  column-gap: 0.8em;
  row-gap: 2px;
  color: var(--ooo-cyan);
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  font-size: clamp(8px, 1.6vmin, 13px);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-shadow:
    0 0 2px rgba(0, 0, 0, 0.8),
    0 0 8px rgba(0, 0, 0, 0.8),
    0 0 4px rgba(92, 214, 255, 0.55),
    0 0 10px rgba(92, 214, 255, 0.25);
  pointer-events: none;
}

.ooo-clock-row {
  display: contents;
}

.ooo-city {
  text-align: right;
}

.ooo-time {
  font-variant-numeric: tabular-nums;
  text-align: left;
}

/* Desktop chat lives INSIDE the aperture, in the LEFT pillarbox bar.
   holding.js re-parents .chat-scrim / .chat-zone / .chat-input-wrap into
   #ooo-holding on desktop, and exposes --pillarbox-w so width-fits cleanly.
   Mobile: they go back to body children and the existing position:fixed
   rules pin them at viewport bottom-left (currently hidden by an existing
   @media rule). */

#ooo-holding > .chat-scrim {
  display: none;
}

/* Chat keeps a minimum readable width of 320 px regardless of how narrow
   the left pillarbox gets. On viewports where the pillarbox is < 352 px
   the chat extends BEYOND the pillarbox INTO the video — broadcast-ticker
   style. Text-shadows below keep cyan legible against the lit video. */
/* Anchors expressed as % of the #ooo-holding aperture so the clearance
   from the bezel inner edge stays visually proportional across desktop
   viewports. Reference: 40px from the left & bottom of a 1098×728
   aperture (1440×900 viewport) = 3.64% × 5.49%. The whole chat block
   translates: chat-zone top moves up by the same delta so the message
   stack height (above the input) stays unchanged. */
#ooo-holding > .chat-zone {
  position: absolute;
  left:   3.64%;
  right:  auto;
  top:    0%;
  bottom: 17.31%;
  width:  max(320px, calc(var(--pillarbox-w, 240px) - 32px));
  height: auto;
  overflow: hidden;
  pointer-events: none;
  z-index: 5;
}

#ooo-holding > .chat-input-wrap {
  position: absolute;
  left:   3.64%;
  right:  auto;
  bottom: 5.49%;
  width:  max(320px, calc(var(--pillarbox-w, 240px) - 32px));
  z-index: 6;
}

/* Legibility shadow — black halo so the cyan text reads cleanly even
   when chat / overlays sit ON TOP of the video at narrow viewports. */
#ooo-holding > .chat-zone .msg-name,
#ooo-holding > .chat-zone .msg-sep,
#ooo-holding > .chat-zone .msg-text,
#ooo-holding > .chat-zone .msg-time,
#ooo-holding > .chat-input-wrap .name-label,
#ooo-holding > .chat-input-wrap input,
#ooo-holding > .chat-input-wrap .submit-btn,
#ooo-holding > .chat-input-wrap .who-prefix {
  text-shadow:
    0 0 2px rgba(0, 0, 0, 0.8),
    0 0 8px rgba(0, 0, 0, 0.8);
}

/* Word-wrap fix: messages were wrapping character-by-character because
   the base .msg-text rule has `word-break: break-word` (a non-standard
   property whose Webkit implementation can split inside words on narrow
   columns). Reset to normal + overflow-wrap so wraps land on word
   boundaries, with only truly unbroken long strings (URLs) breaking. */
#ooo-holding > .chat-zone .msg-text {
  word-break: normal;
  overflow-wrap: break-word;
}

/* Tighter type so messages stay legible in a 150–400 px pillarbox. */
#ooo-holding > .chat-zone .msg-name,
#ooo-holding > .chat-zone .msg-text {
  font-size: 13px;
  letter-spacing: 0.08em;
}
#ooo-holding > .chat-zone .msg-sep {
  font-size: 13px;
}
#ooo-holding > .chat-zone .msg-time {
  font-size: 11px;
}

/* Chat INPUT area font scaling for inside-aperture pillarbox. The label
   "ENTER YOUR NAME TO JOIN" is 22 chars — at the default 18px font it
   wraps in narrow pillarbox bars. Scale with viewport so it fits on a
   single line at all desktop sizes. */
#ooo-holding > .chat-input-wrap .name-label,
#ooo-holding > .chat-input-wrap input,
#ooo-holding > .chat-input-wrap .submit-btn,
#ooo-holding > .chat-input-wrap .who-prefix {
  font-size: clamp(10px, 0.7vw, 14px);
  letter-spacing: 0.04em;
  padding-top: 8px;
  padding-bottom: 8px;
}

#ooo-holding > .chat-input-wrap .name-label {
  white-space: normal;
  /* Allow wrap as fallback at very narrow viewports — fonts above are
     scaled so the label fits on one line at 1440+ in practice. */
}

/* Inside the aperture the mask gradient on .messages used to fade the top
   28%, which made messages disappear ~5 lines up. JS now drives a
   position-based opacity falloff that runs the full visible height, so
   the mask is no longer needed here. Tight padding too — every pixel of
   vertical space is message room. */
#ooo-holding > .chat-zone .messages {
  mask-image: none;
  -webkit-mask-image: none;
  padding: 0 2px;
}

/* Mobile (<=768px): the TV frame PNG is hidden via existing rule, so
   the aperture isn't constrained by a bezel. Expand #ooo-holding to a
   larger box (90vw × 60vh) centred on the viewport and widen the wrap's
   base accordingly. The 24px cap rule still applies. */
@media (max-width: 768px) {
  /* Allow overlays to render below the aperture box on mobile (where
     the TV bezel PNG is hidden, so there's nothing to clip against). */
  #ooo-holding {
    top: 50%;
    left: 50%;
    width:  95vw;
    height: 75vh;
    transform: translate(-50%, -50%);
    overflow: visible;
  }

  /* Mobile uses the 9:16 portrait cut. Size height-first: target almost
     the full aperture height (with 6px bezel clearance on every side),
     width derives from the 9:16 aspect, capped by the aperture width
     less clearance so it never bleeds past either bezel edge. */
  .ooo-video-wrap {
    aspect-ratio: 9 / 16;
    width:  min(calc(95vw - 12px), calc((75vh - 12px) * 9 / 16));
    height: auto;
  }

  /* Unwrap the desktop right-block so the two children can be positioned
     independently below the aperture, L+R split — preserving the existing
     mobile layout exactly as it shipped before. */
  .ooo-holding-rightblock {
    position: static;
    transform: none;
    display: contents;
  }

  .ooo-holding-coming-soon {
    position: absolute;
    top: calc(100% + 30px);
    left: 24px;
    right: auto;
    transform: translateY(-50%);
    writing-mode: horizontal-tb;
  }

  .ooo-holding-clocks {
    position: absolute;
    top: calc(100% + 30px);
    right: 24px;
    left: auto;
    transform: translateY(-50%);
  }
}


/* ============================================================
   PNG FRAME OVERLAY — .main1 (z-index: 99)
   Technique: background-size: 100% 100% stretches the PNG
   to fill the full viewport. The transparent screen hole
   lets .screen-layer content show through.
   pointer-events: none so it doesn't block chat/controls.
   ============================================================ */

.main1 {
  position: fixed;
  top:    0;
  left:   0;
  width:  100vw;
  height: 100vh;
  z-index: 999;
  pointer-events: none;
  background-image: url("frame-cutout.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  /* No mix-blend-mode — frame-cutout.png has a transparent screen hole,
     so it sits as a solid opaque layer above the VHS effects and video.
     Only the hole lets content show through. */
}


/* ============================================================
   INTERACTIVE BEZEL CONTROLS (z-index: 100)
   Above the PNG. Positioned to match the baked-in controls
   in the PNG's chin area. Adjust percentages to align.
   ============================================================ */

.bezel-controls {
  position: fixed;
  inset: 0;
  z-index: 1000;
  pointer-events: none; /* container pass-through */
}

/* Power indicator — dim red dot, pulsing */
.power-indicator {
  position: absolute;
  /* POSITION — adjust to align with the power LED on the PNG chin */
  left:   47%;
  bottom: 20%;
  transform: translate(-50%, 50%);

  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--power-red);
  opacity: 0.5;
  animation: power-pulse 3.5s ease-in-out infinite;
  box-shadow: 0 0 5px rgba(196, 26, 26, 0.4);
  pointer-events: none;
}

@keyframes power-pulse {
  0%, 100% { opacity: 0.3; }
  50%       { opacity: 0.65; }
}

/* ── VCR CHANNEL MENU ── */
#vcr-menu {
  position: absolute;
  bottom: 24%;
  right: 18%;
  z-index: 500;
  pointer-events: auto;
  padding: 12px 20px 14px;
  min-width: 300px;
  border-radius: 10px;
  background: rgba(18, 18, 180, 0.38);
  backdrop-filter: blur(24px) saturate(1.4);
  -webkit-backdrop-filter: blur(24px) saturate(1.4);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.12);
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0px, transparent 1px,
    rgba(0,0,0,0.08) 1px, rgba(0,0,0,0.08) 2px
  );
  font-family: 'VCR OSD Mono', 'Courier New', monospace;
  overflow: hidden;
}

.vcr-header {
  font-size: 20px;
  color: rgba(232, 232, 232, 0.9);
  letter-spacing: 1px;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  padding: 2px 0;
}

.vcr-header:hover {
  color: #fff;
}

/* Expandable body — hidden when collapsed */
.vcr-body {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.28s ease, opacity 0.28s ease, margin-top 0.28s ease;
  opacity: 1;
  margin-top: 14px;
}

#vcr-menu.collapsed .vcr-body {
  grid-template-rows: 0fr;
  opacity: 0;
  margin-top: 0;
}

.vcr-body-inner {
  overflow: hidden;
}

.vcr-channels {
  list-style: none;
  margin-bottom: 14px;
}

.vcr-channels li {
  font-size: 20px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: rgba(232, 232, 232, 0.9);
  padding: 4px 8px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.vcr-channels li:hover {
  background: rgba(232, 232, 232, 0.12);
}

.vcr-channels li.active {
  background: #e8e8e8;
  color: #0a0a80;
}

.vcr-channels li.active:hover {
  background: #e8e8e8;
}

.vcr-keys {
  font-size: 20px;
  letter-spacing: 1px;
  color: rgba(232, 232, 232, 0.45);
  text-transform: uppercase;
  line-height: 2;
}

.vcr-keys span {
  color: rgba(232, 232, 232, 0.9);
}


/* ============================================================
   RESPONSIVE — below 768px
   PNG bezel gone. Full-screen video. Minimal channel tap.
   ============================================================ */

@media (max-width: 768px) {
  body {
    background: #080604;
  }

  /* Screen already full viewport — no override needed */

  /* Hide the PNG frame on mobile */
  .main1 {
    display: none;
  }

  /* Hide desktop controls */
  .bezel-controls {
    display: none;
  }

  .chat-zone,
  .chat-input-wrap {
    display: none;
  }
}

/* Mobile — menu hidden when frame is gone (full-screen video mode) */
@media (max-width: 768px) {
  #vcr-menu {
    display: none;
  }
}
