/* ==========================================================================
   $KURONEKO — The black cat that guards Robinhood Chain
   Inspired by the Japanese urban legend of Kuroneko also known as the mystical guardian believed to ward off misfortune and bring luck prosperity and fortune to those who cross its path.
   ========================================================================== */

@font-face {
  font-family: "Press Start 2P";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/press-start-2p.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../assets/fonts/space-grotesk.woff2") format("woff2");
}

:root {
  --font-title: "Press Start 2P", monospace;
  --font-body: "Space Grotesk", ui-sans-serif, "Segoe UI", Arial, sans-serif;
  --gold: #d8b978;
  --phosphor: #8affc1;
  --phosphor-dim: #4fcf95;
  --amber: #ffbe55;
  --neon-red: #ff3b4e;
  --neon-cyan: #37f3ff;
  --ink: #05100c;
  --crt-black: #020403;
  --screen-left: 34.505%;
  --screen-top: 25.39%;
  --screen-width: 32.422%;
  --screen-height: 45.703%;
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: #000;
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

button { font-family: inherit; }

/* ============ BACKGROUND ============ */
.backdrop {
  position: fixed;
  inset: 0;
  background: url("../assets/bg.png") center 62% / cover no-repeat;
  filter: brightness(0.85) saturate(1.05);
  z-index: 0;
}
.backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,.55) 100%);
}

/* ============ SITE BRAND (fixed, top-left of the page) ============ */
.site-brand {
  position: fixed;
  top: 2.2vh;
  left: 2.2vh;
  display: flex;
  align-items: center;
  gap: 0.6em;
  z-index: 20;
}
.site-brand-logo {
  width: clamp(22px, 3.4vw, 38px);
  height: auto;
  image-rendering: pixelated;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .6));
}
.site-brand-text {
  font-family: var(--font-title);
  font-size: clamp(9px, 1.5vw, 14px);
  letter-spacing: .02em;
  color: var(--phosphor);
  text-shadow: 0 0 6px currentColor, 0 2px 4px rgba(0, 0, 0, .8);
}

.stage {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2vh;
  padding-bottom: 6vh;
  z-index: 1;
}

/* ============ TV (rigid unit — everything inside floats together, frame never drifts relative to screen) ============ */
.tv-wrap {
  position: relative;
  width: min(72vw, 72vh * 1.5, 1040px);
  aspect-ratio: 1536 / 1024;
  animation: floatTV 7s ease-in-out infinite;
  filter: drop-shadow(0 45px 70px rgba(0, 0, 0, 0.65));
}

/* Portrait phones: the TV keeps its landscape 3:2 shape, so width (not
   height) is always the scarce resource here. Lean much harder on vw —
   there's plenty of empty vertical space to spend — so the screen stays
   large enough in absolute px for its text to stay legible and untangled. */
@media (max-width: 700px) {
  .stage { padding-bottom: 1.5vh; }
  .tv-wrap { width: min(98vw, 720px); }
}
@media (max-width: 700px) and (orientation: portrait) {
  /* Portrait phones have height to spare, not width — the TV's fixed
     landscape shape means a vw-capped size leaves it tiny with most of
     the screen empty. Zoom in past 100vw and let it bleed off the
     left/right edges (html/body clip via overflow:hidden); the screen
     cutout sits centered in the middle third of the frame so it stays
     fully on-screen even at a large multiple of the viewport width.
     Kept modest (not the full available height) so the TV doesn't feel
     over-zoomed and still leaves room for the nav strip + brand mark. */
  .stage { padding-bottom: 0; }
  .tv-wrap { width: min(150vw, 700px); }
}

@keyframes floatTV {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-1%) rotate(0.2deg); }
}

/* ============ SCREEN (clipped exactly to the CRT tube hole in tv-frame.png) ============ */
.screen-container {
  position: absolute;
  left: var(--screen-left);
  top: var(--screen-top);
  width: var(--screen-width);
  height: var(--screen-height);
  border-radius: 13% / 16%;
  overflow: hidden;
  background: var(--crt-black);
  box-shadow:
    inset 0 0 6cqw 1cqw rgba(0, 0, 0, 0.85),
    inset 0 0 0.6cqw rgba(255, 255, 255, 0.06);
  z-index: 2;
  container-type: size;
  container-name: crt;
  cursor: pointer;
}

/* subtle barrel-glass warp — cheap, GPU-friendly approximation */
.screen-container.curved {
  transform: perspective(60cqw) rotateX(0.4deg);
}

.screen-content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  color: var(--phosphor);
  text-shadow: 0 0 1px currentColor, 0 0 0.25cqh currentColor;
  opacity: 1;
  transition: opacity .22s ease, filter .22s ease;
  z-index: 3;
}

.screen-content.hidden-out {
  opacity: 0;
}

.screen-content.rgb-split {
  filter:
    drop-shadow(0.35cqw 0 var(--neon-red))
    drop-shadow(-0.35cqw 0 var(--neon-cyan));
  animation: rgbJitter .5s steps(3) both;
}

@keyframes rgbJitter {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-0.6%, 0.3%); }
  40%  { transform: translate(0.5%, -0.2%); }
  60%  { transform: translate(-0.3%, 0); }
  80%  { transform: translate(0.2%, 0.2%); }
  100% { transform: translate(0, 0); }
}

/* ============ boot-only elements ============ */
.boot-line {
  position: absolute;
  left: 50%; top: 50%;
  width: 0%; height: 2px;
  background: var(--phosphor);
  box-shadow: 0 0 20px 4px var(--phosphor);
  transform: translate(-50%, -50%) scaleX(0);
  opacity: 0;
  z-index: 8;
  pointer-events: none;
}
.boot-line.grow {
  animation: bootLineGrow 0.55s cubic-bezier(.2,.9,.2,1) forwards;
}
@keyframes bootLineGrow {
  0%   { opacity: 1; width: 0%;   transform: translate(-50%, -50%) scaleX(0); }
  60%  { opacity: 1; width: 70%;  transform: translate(-50%, -50%) scaleX(1); }
  100% { opacity: 1; width: 100%; transform: translate(-50%, -50%) scaleX(1); }
}

.boot-flash {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  z-index: 9;
  pointer-events: none;
}
.boot-flash.pop {
  animation: bootFlashPop 0.42s ease-out forwards;
}
@keyframes bootFlashPop {
  0%   { opacity: 0; transform: scaleY(0.01); }
  35%  { opacity: 1; transform: scaleY(1.4); }
  100% { opacity: 0; transform: scaleY(1); }
}

/* ============ static noise canvas ============ */
.static-noise {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 7;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s linear;
  image-rendering: pixelated;
  mix-blend-mode: screen;
}
.static-noise.on { opacity: 0.85; }
.static-noise.burst { opacity: 1; mix-blend-mode: normal; }

/* ============ scanlines + beam ============ */
.scanlines {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.32) 0px,
    rgba(0, 0, 0, 0.32) 1px,
    transparent 1.5px,
    transparent 3px
  );
  opacity: .55;
  animation: scanDrift 9s linear infinite;
}
@keyframes scanDrift {
  0%   { background-position: 0 0; }
  100% { background-position: 0 120px; }
}

.tracking-band {
  position: absolute;
  left: 0; right: 0;
  height: 14%;
  background: linear-gradient(to bottom, transparent, rgba(255,255,255,.10), transparent);
  top: -20%;
  z-index: 6;
  pointer-events: none;
  opacity: .5;
  animation: trackingDrift 11s linear infinite;
}
@keyframes trackingDrift {
  0%   { top: -20%; }
  100% { top: 110%; }
}

/* ============ curvature / vignette ============ */
.curvature-shade {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 50%, rgba(0,0,0,.6) 100%);
}
.vignette-glow {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background: radial-gradient(ellipse at 38% 28%, rgba(255,255,255,.10), transparent 45%);
  mix-blend-mode: screen;
}

/* ============ flicker / glitch utility classes (toggled by JS) ============ */
.flicker-soft { animation: flickerSoft 3.2s ease-in-out infinite; }
@keyframes flickerSoft {
  0%, 100% { filter: brightness(1); }
  4%   { filter: brightness(.93); }
  6%   { filter: brightness(1.05); }
  8%   { filter: brightness(1); }
  47%  { filter: brightness(1); }
  49%  { filter: brightness(.9); }
  51%  { filter: brightness(1); }
}

.flicker-hard {
  animation: flickerHard .12s steps(2) infinite;
}
@keyframes flickerHard {
  0%   { filter: brightness(1) contrast(1); }
  50%  { filter: brightness(1.3) contrast(1.15); }
  100% { filter: brightness(.85) contrast(1); }
}

.tv-wrap.power-glitch .screen-container {
  animation: hJitter .28s steps(4) both;
}
@keyframes hJitter {
  0%   { transform: translateX(0); }
  25%  { transform: translateX(-1.2%); }
  50%  { transform: translateX(1%); }
  75%  { transform: translateX(-0.5%); }
  100% { transform: translateX(0); }
}

/* ============ OSD (on-screen display) ============ */
.osd {
  position: absolute;
  top: 5cqh;
  left: 6cqw;
  display: flex;
  gap: 0.8cqw;
  z-index: 10;
  opacity: 0;
  pointer-events: none;
}
.osd::before {
  content: "";
  position: absolute;
  top: -1.2cqh; bottom: -1.2cqh; left: -6cqw;
  width: 80cqw;
  background: linear-gradient(to right, rgba(2,4,3,.75) 55%, transparent 100%);
  z-index: -1;
}
.osd.show {
  animation: osdShow 2.2s ease forwards;
}
@keyframes osdShow {
  0%   { opacity: 0; transform: translateY(-4%); }
  10%  { opacity: 1; transform: translateY(0); }
  75%  { opacity: 1; }
  100% { opacity: 0; }
}
.osd-chip {
  font-size: clamp(7px, 2.5cqh, 11px);
  font-weight: 700;
  letter-spacing: 0;
  padding: 0.3em 0.6em;
  background: rgba(0,0,0,.45);
  border: 1px solid rgba(138,255,193,.4);
  color: var(--phosphor);
  text-shadow: 0 0 6px var(--phosphor);
}

.osd-audio {
  position: absolute;
  top: 5cqh;
  right: 5cqw;
  z-index: 11;
  background: rgba(0,0,0,.4);
  border: 1px solid rgba(138,255,193,.35);
  color: var(--phosphor);
  font-size: clamp(9px, 2.8cqh, 13px);
  line-height: 1;
  padding: 0.45em 0.55em;
  min-width: 28px;
  min-height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  pointer-events: auto;
}
.osd-audio:hover { background: rgba(138,255,193,.15); }

/* ============ nav strip (sits above the TV, outside its frame) ============ */
.nav-strip {
  position: relative;
  display: flex;
  gap: 4px;
  z-index: 10;
  max-width: 92vw;
  overflow-x: auto;
  scrollbar-width: none;
  background: rgba(0,0,0,.4);
  padding: 6px 8px;
  border: 1px solid rgba(138,255,193,.25);
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity .4s ease, transform .4s ease;
  pointer-events: none;
  flex: 0 0 auto;
}
.nav-strip::-webkit-scrollbar { display: none; }
.nav-strip.show {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.nav-btn {
  background: transparent;
  border: none;
  color: var(--phosphor-dim);
  font-size: clamp(7px, 1.3vw, 9.5px);
  letter-spacing: 0;
  padding: 0.4em 0.5em;
  min-height: 30px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.25em;
  white-space: nowrap;
  flex: 0 0 auto;
}
.nav-btn:hover { color: var(--phosphor); }
.nav-btn.active {
  color: var(--ink);
  background: var(--phosphor);
  text-shadow: none;
}
.nav-num { opacity: .7; font-weight: 700; }
.nav-link { color: var(--phosphor-dim); text-decoration: none; }
.nav-link:hover { color: var(--phosphor); }

/* ============ GLASS OVERLAY (reflections; sits above screen, below frame) ============ */
.glass-overlay {
  position: absolute;
  inset: 0;
  background: url("../assets/screen-glass.png") center center / 100% 100% no-repeat;
  z-index: 4;
  pointer-events: none;
  mix-blend-mode: screen;
  /* clipped to the exact screen-hole rect so the glass shine can never
     bleed onto the bezel, independent of tv-frame.png's own alpha edges */
  clip-path: inset(
    var(--screen-top) 33.073% 28.907% var(--screen-left)
    round 13% / 16%
  );
}

/* ============ TV FRAME (topmost, fixed, masks all screen-layer overflow) ============ */
.frame-overlay {
  position: absolute;
  inset: 0;
  background: url("../assets/tv-frame.png") center center / 100% 100% no-repeat;
  z-index: 5;
  pointer-events: none;
}

/* ============================================================
   Shared channel-content typography helpers (used by channels.js)
   ============================================================ */
.ch {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  /* top padding must clear the OSD readout even when the CRT shrinks to a
     tiny absolute size (portrait phones): its own font-size px floor
     doesn't shrink with cqh, so the reserved space can't be purely
     percentage-based or the two start overlapping the content. The nav
     strip now lives outside the TV, so the bottom just needs breathing room. */
  padding: max(13cqh, 46px) 7cqw max(4cqh, 16px);
  gap: 1.4cqh;
  overflow: hidden;
}
.ch-title {
  font-family: var(--font-title);
  font-size: clamp(15px, 5cqh, 26px);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 0 1px currentColor, 0 0 0.4cqh currentColor;
  flex: 0 0 auto;
}
.ch-kicker {
  font-size: clamp(7.5px, 1.9cqh, 10px);
  letter-spacing: .04em;
  color: var(--phosphor-dim);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  flex: 0 0 auto;
}
.ch-body {
  font-size: clamp(9px, 2.7cqh, 12.5px);
  line-height: 1.35;
  color: var(--phosphor);
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  flex: 1 1 auto;
  min-height: 0;
  padding-right: 0.6cqw;
}
.ch-body p { margin: 0 0 0.7em; }
.ch-row { display: flex; gap: 1.4cqw; }
.ch-col { flex: 1; min-width: 0; }

/* retro-styled scrollbar, only appears when content actually overflows */
.ch-body {
  scrollbar-width: thin;
  scrollbar-color: var(--phosphor-dim) transparent;
}
.ch-body::-webkit-scrollbar { width: 5px; }
.ch-body::-webkit-scrollbar-track { background: transparent; }
.ch-body::-webkit-scrollbar-thumb {
  background: var(--phosphor-dim);
  border-radius: 3px;
}
.ch-body::-webkit-scrollbar-thumb:hover { background: var(--phosphor); }

/* ============ game channel (Kuroneko Run) ============ */
.game-hud {
  display: flex;
  justify-content: space-between;
  flex: 0 0 auto;
  font-size: clamp(7.5px, 1.9cqh, 10px);
  letter-spacing: .04em;
  color: var(--phosphor-dim);
  text-transform: uppercase;
  margin-bottom: .5cqh;
}
.game-hud strong { color: var(--phosphor); font-weight: 700; }
.game-stage-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.game-stage {
  position: relative;
  height: 100%;
  width: auto;
  max-width: 100%;
  aspect-ratio: 320 / 160;
  border: 1px solid var(--phosphor-dim);
  overflow: hidden;
  background: #fff;
  box-shadow: inset 0 0 1.4cqh rgba(0, 0, 0, .25);
  touch-action: none;
  cursor: pointer;
}
.game-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
  background: #fff;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
.game-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .5em;
  text-align: center;
  padding: 0 1em;
  background: rgba(0, 0, 0, .55);
  transition: opacity .15s ease;
}
.game-overlay.hidden { opacity: 0; pointer-events: none; }
.game-duck-btn {
  position: absolute;
  right: .6cqw;
  bottom: .6cqh;
  min-height: 0;
  padding: .4em .7em;
  font-size: clamp(7px, 1.7cqh, 8.5px);
  background: rgba(0, 0, 0, .35);
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

.blink { animation: blinkText 1.1s steps(1) infinite; }
@keyframes blinkText { 50% { opacity: 0; } }

.crt-btn {
  font-family: inherit;
  background: transparent;
  border: 1px solid var(--phosphor);
  color: var(--phosphor);
  text-shadow: 0 0 6px currentColor;
  padding: .5em .9em;
  font-size: clamp(7.5px, 2cqh, 9.5px);
  min-height: 30px;
  letter-spacing: .02em;
  cursor: pointer;
  text-transform: uppercase;
  align-self: flex-start;
}
.crt-btn:hover { background: rgba(138,255,193,.12); }
.crt-btn:active { transform: translateY(1px); }

/* ============ marquee (memes ticker) ============ */
.marquee-track {
  animation: marqueeScroll 14s linear infinite;
  padding-left: 100%;
}
@keyframes marqueeScroll {
  0%   { transform: translateX(0); }
  100% { transform: translateX(-100%); }
}

.meme-card { transition: transform .15s ease, border-color .15s ease; }
.meme-card:hover { transform: translateY(-2px); border-color: var(--phosphor); }

.menu-row { transition: color .15s ease, transform .15s ease; }
.menu-row:hover { color: var(--amber); transform: translateX(0.4cqw); }

/* ============ random tracking tear glitch (JS-triggered, short-lived) ============ */
.screen-container.tear .screen-content {
  animation: tearSlice .22s steps(1) both;
}
@keyframes tearSlice {
  0%   { clip-path: inset(0 0 0 0); transform: translateX(0); }
  20%  { clip-path: inset(22% 0 61% 0); transform: translateX(1.5%); }
  40%  { clip-path: inset(65% 0 8% 0);  transform: translateX(-1.8%); }
  60%  { clip-path: inset(10% 0 80% 0); transform: translateX(1.2%); }
  100% { clip-path: inset(0 0 0 0); transform: translateX(0); }
}

::selection { background: var(--phosphor); color: #000; }

@media (max-width: 640px) {
  .nav-btn .nav-num { display: none; }
  .nav-btn { padding: 0.4em 0.3em; }
}

/* ============================================================
   Tiny-screen mode: on portrait phones the TV keeps its fixed 3:2
   shape, so the CRT tube itself is physically capped around
   ~110-130px tall no matter how much viewport width we spend on it.
   Below that size the normal (touch-friendly, cqh-scaled) chrome no
   longer fits at all, so shrink it directly via a container query —
   this targets the screen's own rendered size, not the viewport,
   so it kicks in correctly regardless of orientation or TV width. */
@container crt (max-height: 195px) {
  .ch { padding: max(13cqh, 26px) 6cqw max(11cqh, 30px); gap: 0.4em; }
  .ch-title { font-size: 11px !important; }
  .ch-kicker { font-size: 5.5px; letter-spacing: 0; }
  .ch-body { font-size: 7px; line-height: 1.3; }
  .osd { top: 3px; left: 4px; gap: 4px; }
  .osd-chip { font-size: 5.5px; padding: .2em .35em; }
  .osd-audio {
    top: 3px; right: 4px;
    font-size: 7px;
    min-width: 18px; min-height: 18px;
    padding: .2em;
  }
  .menu-row { min-height: 18px !important; padding: .15em 0 !important; }
  .crt-btn { min-height: 20px; font-size: 6.5px; padding: .3em .5em; }
}

/* Short viewports (landscape phones): the nav strip lives outside the TV
   now, so shrink it directly off viewport height rather than the CRT. */
@media (max-height: 420px) {
  .stage { gap: 0.6vh; }
  .nav-strip { padding: 2px 4px; gap: 2px; }
  .nav-btn { min-height: 18px; font-size: 6px; padding: .2em .3em; }
}
