/* skrta radio: the broadcast overlay.
   Tokens, faces, the grain tile and the casing rule are the site's
   (skrtasite/app/globals.css, BRAND_RESEARCH.md §8, §1.1). */

:root {
  --void: #000000;          /* his YouTube banner: one unique colour */
  --ink: #FBFBFB;           /* median ground of the five 1-bit covers */
  --mute: #8C8C92;          /* 6.28:1 on void */
  --rule: #26262A;          /* hairlines and unlit cells */
  --accent: #6D79AD;        /* the request mark only */
  --stipple-light: #EDEDED; /* the measured dither pair, §8.1 */
  --stipple-dark: #131313;

  --font-display: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --font-text: "Archivo", "Segoe UI Symbol", "DejaVu Sans", ui-sans-serif, system-ui, sans-serif;
  --tracking-wordmark: 1.1em; /* measured on ONTHEFLOOR, §8.3 */

  color-scheme: dark;
}

html, body {
  margin: 0;
  height: 100%;
  background: var(--void);
  color: var(--ink);
  font-family: var(--font-display);
  -webkit-font-smoothing: antialiased;
}

/* a display rule must never resurrect something the script hid */
[hidden] { display: none !important; }

.viewport {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--void);
}

/* ---- the stage ---------------------------------------------------------- */

.stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--w);
  height: var(--h);
  transform: translate(-50%, -50%) scale(var(--scale, 1));
  transform-origin: 50% 50%;
  overflow: hidden;
  box-sizing: border-box;
  padding: var(--frame);
  background: var(--void);
  display: grid;
  row-gap: var(--gap);
}

/* Portrait, 1080 x 1920: the TikTok frame. Six rows, everything flush left
   on the 5% frame line. The art row is sized by radio.js from what is left. */
.stage[data-layout="portrait"] {
  --w: 1080px;
  --h: 1920px;
  --frame: 54px;
  --gap: 28px;
  --fs-small: 32px;
  --fs-wordmark: 44px;
  --fs-ask: 36px;
  --title-max: 260px;
  --eq-h: 140px;
  --eq-rows: 12;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto auto auto auto;
}

/* Landscape, 1920 x 1080: the YouTube frame. The art on the left, the track,
   the spectrum and the up-next line stacked on the right. */
.stage[data-layout="landscape"] {
  --w: 1920px;
  --h: 1080px;
  --frame: 72px;
  --gap: 28px;
  --fs-small: 28px;
  --fs-wordmark: 40px;
  --fs-ask: 30px;
  --title-max: 250px;
  --eq-h: 120px;
  --eq-rows: 10;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas: "top top" "art main" "bottom bottom";
  column-gap: 72px;
}

.stage > *,
.stage .track, .stage .eq, .stage .next, .stage .chat {
  position: relative;
  z-index: 2;
  min-width: 0;
}

/* Paper: his other banner, the white one (§8.2). The measured light palette,
   on the stage and on the page around it. */
[data-theme="paper"],
.stage[data-theme="paper"] {
  --void: #FBFBFB;
  --ink: #0D0D0D;
  --mute: #6B6B70;
  --rule: #E2E2E4;
  --accent: #454D6E;
  color-scheme: light;
}

[data-theme="paper"] .grain { filter: invert(1); }

/* ---- the field and the grain ------------------------------------------- */

.field {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Footage, when the studio switches it on: the clips drawn through the
   stipple (or softly), behind the grain and the picture. */
.footage {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.footage[hidden] { display: none; }

.clip {
  position: fixed;
  width: 2px;
  height: 2px;
  left: -10px;
  top: -10px;
  opacity: 0.01;
  pointer-events: none;
}

/* Concrete grain, the site's exact tile: a fine grain multiplied by a slow
   second noise, alpha only, so the void underneath is untouched. Static. */
.grain {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='800' height='800'><filter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'><feTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' seed='7' stitchTiles='stitch' result='f'/><feTurbulence type='fractalNoise' baseFrequency='0.035' numOctaves='3' seed='3' stitchTiles='stitch' result='c'/><feComposite in='f' in2='c' operator='arithmetic' k1='0.65' k2='0.35' k3='0' k4='0' result='p'/><feColorMatrix in='p' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0' result='w'/><feComponentTransfer in='w'><feFuncA type='gamma' amplitude='0.4' exponent='2' offset='0'/></feComponentTransfer></filter><rect width='100%25' height='100%25' filter='url(%23g)'/></svg>");
  background-size: 800px 800px;
}

@media (prefers-contrast: more) {
  .grain { display: none; }
}

/* ---- voices ------------------------------------------------------------- */

/* The small voice: the title's family again, a touch narrower and heavier
   than the wordmark, tabular figures for the clock. */
.small {
  font-family: var(--font-text);
  font-weight: 500;
  font-stretch: 86%;
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
  letter-spacing: 0.05em;
  margin: 0;
  white-space: nowrap;
}

/* lines that carry the station's strings, which can be any length */
.meta, .extra, .next {
  overflow: hidden;
  text-overflow: ellipsis;
}

.ornament {
  font-family: var(--font-text);
  font-size: var(--fs-small);
  line-height: 1;
  letter-spacing: 0.1em;
  margin: 0;
  white-space: nowrap;
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-wordmark);
  line-height: 1;
  letter-spacing: var(--tracking-wordmark);
  margin: 10px 0 0;
  white-space: nowrap;
}

/* The work voice: condensed black Archivo, one line, sized by radio.js so the
   title hits the frame on both sides. Casing is whatever the station sent. */
.title {
  font-family: var(--font-display);
  font-weight: 900;
  font-stretch: 66%;
  line-height: 0.88;
  letter-spacing: -0.01em;
  margin: 8px 0 0;
  padding-bottom: 0.11em;
  white-space: nowrap;
  overflow: clip;
  font-size: 100px;
}

/* Over footage the small lines wear a thin dark halo, so a bright patch of
   clip behind them never takes a word. Invisible on the void itself. */
.stage[data-footage="dither"] .small,
.stage[data-footage="soft"] .small,
.stage[data-footage="dither"] .ornament,
.stage[data-footage="soft"] .ornament {
  text-shadow: 0 0 3px var(--void), 0 0 12px var(--void), 0 0 24px var(--void);
}

/* ---- top ---------------------------------------------------------------- */

/* Three rows on the left (star, wordmark, motto), two on the right (the
   place and the clock, then the on-air mark), sharing baselines. */
.top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto;
  column-gap: 24px;
  align-items: baseline;
}

.stage[data-layout="landscape"] .top { grid-area: top; }

.top .ornament { grid-column: 1; grid-row: 1; }
.top .wordmark { grid-column: 1; grid-row: 2; }
.top .motto { grid-column: 1; grid-row: 3; color: var(--mute); margin-top: 10px; }
.top .place { grid-column: 2; grid-row: 1; text-align: right; color: var(--mute); }
.top .onair { grid-column: 2; grid-row: 2; text-align: right; color: var(--ink); }
.onair .mark { letter-spacing: 0; }
.stage[data-state="offline"] .onair { color: var(--mute); }

/* ---- artwork ------------------------------------------------------------ */

.art {
  position: relative;
  width: var(--art, 800px);
  height: var(--art, 800px);
  justify-self: start;
  align-self: start;
  background: transparent;
}

.stage[data-layout="landscape"] .art { grid-area: art; }

.art-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 900ms cubic-bezier(0.22, 1, 0.36, 1);
}

.art-layer.on { opacity: 1; }
.stage[data-state="offline"] .art-layer { opacity: 0; }

/* ---- the track ---------------------------------------------------------- */

.main { display: contents; }

.stage[data-layout="landscape"] .main {
  grid-area: main;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 0;
}

/* Reserved for the tallest title, so the spectrum and the foot never move
   when a short title follows a long one. */
.track {
  min-height: calc(var(--title-max) * 0.88 + var(--fs-small) * 3 + 16px);
  transition: opacity 450ms ease, transform 650ms cubic-bezier(0.22, 1, 0.36, 1);
}

.track.changing {
  opacity: 0;
  transform: translateY(14px);
}

.meta { color: var(--mute); }
.extra { color: var(--mute); min-height: calc(var(--fs-small) * 1.5); margin-top: 6px; }
.extra .req-mark, .next .req-mark { color: var(--accent); }

/* The wordmark again, fitted to the frame by radio.js: a big whisper. The
   tracking is a shade tighter than the header so it spans in one line. */
.ident-card .ident-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 100px;
  letter-spacing: 0.7em;
  line-height: 1;
  margin: 18px 0 0;
  white-space: nowrap;
  overflow: clip;
}
.ident-decode { color: var(--mute); margin-top: 18px; }

/* ---- the spectrum ------------------------------------------------------- */

.eq { height: var(--eq-h); }
.eq canvas { display: block; width: 100%; height: 100%; }

.next { color: var(--mute); }

/* The chat line: the last two things said in the room, from the bot. Two
   lines are always reserved while it is on, so nothing else moves. */
.chat {
  color: var(--mute);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 4px;
  min-height: calc(var(--fs-small) * 3 + 4px);
}

.chat p {
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transition: opacity 600ms ease;
}

.chat p.in { opacity: 1; }
.chat .who { color: var(--ink); }

/* ---- the foot ----------------------------------------------------------- */

.bottom {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-self: end;
}

.stage[data-layout="landscape"] .bottom {
  grid-area: bottom;
  flex-direction: row;
  justify-content: space-between;
  align-items: baseline;
}

.divider { color: var(--mute); }
.ask { font-size: var(--fs-ask); color: var(--ink); }
.requests { color: var(--mute); }

/* ---- audio start, only outside OBS -------------------------------------- */

.start {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 10;
  background: var(--ink);
  color: var(--void);
  border: 0;
  padding: 10px 16px;
  font-size: 13px;
  letter-spacing: 0.3em;
  cursor: pointer;
}

.start:focus-visible { outline: 1px solid var(--ink); outline-offset: 3px; }

::selection { background: var(--ink); color: var(--void); }

@media (prefers-reduced-motion: reduce) {
  .art-layer, .track { transition: none; }
}
