/* SIGNAL-95 -- the look. The style board (see CLAUDE.md) is the reference;
   these tokens are its palette. Light comes from the top-left, every bevel
   is 2px, and nothing here is copied from a real operating system: the
   ground is a warm putty, not a cool gray, and the title bar is pine. */

:root {
  --putty: #C6C3BC;
  --putty-down: #BDBAB2;
  --chalk: #F4F2EC;
  --bone: #E2DFD7;
  --shade: #7D7A72;
  --ink: #2A2925;
  --ink-soft: #4A4842;
  --muted: #8E8B83;
  --pine: #23443A;
  --amber: #E8A33D;
  --tube: #12140F;
  --phosphor: #7CFF8A;
  --desk: #5E6B63;
  --tip: #F4EBC8;
  --rust: #6E2A22;

  /* The two per-station levers, set on #tuner from schemes.js. */
  --title: var(--pine);
  --led: var(--phosphor);
  --signal: 1;

  --raised: inset -1px -1px var(--ink), inset 1px 1px var(--chalk), inset -2px -2px var(--shade), inset 2px 2px var(--bone);
  --sunken: inset 1px 1px var(--shade), inset -1px -1px var(--chalk), inset 2px 2px var(--ink), inset -2px -2px var(--bone);
  --pressed: inset 1px 1px var(--ink), inset -1px -1px var(--chalk), inset 2px 2px var(--shade), inset -2px -2px var(--bone);
  --pane: inset 1px 1px var(--shade), inset -1px -1px var(--chalk);
}

* { box-sizing: border-box; }

html, body { margin: 0; min-height: 100%; }

body {
  background: var(--desk);
  color: var(--ink);
  font-family: 'Pixelify Sans', monospace;
  font-size: 14px;
  /* Pixelify Sans's fi ligature draws as an A: "Shift for fine" rendered
     as "Shift for Ane" in the shortcuts dialog. */
  font-variant-ligatures: none;
  display: flex;
  justify-content: center;
  /* Centred on the desk, both ways (2026-10-13): pinned to the top, the
     window read as a web page with a lot of nothing under it. */
  align-items: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 32px 16px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.raised { background: var(--putty); box-shadow: var(--raised); }
.sunken { box-shadow: var(--sunken); }
.pane { box-shadow: var(--pane); }

.btn {
  font: inherit; color: var(--ink); border: 0; background: var(--putty);
  box-shadow: var(--raised); cursor: pointer; padding: 0 10px; min-height: 26px;
}
.btn:active, .btn[aria-pressed="true"] { box-shadow: var(--pressed); background: var(--putty-down); }
.btn:active { padding-top: 1px; padding-left: 11px; padding-right: 9px; }
.btn:focus-visible { outline: 1px dotted var(--ink); outline-offset: -5px; }
.btn.def { box-shadow: 0 0 0 1px var(--ink), var(--raised); }
.btn:disabled { color: var(--muted); text-shadow: 1px 1px var(--chalk); cursor: default; }
.btn svg { display: block; }

/* ---- the window ---- */

/* The frame holds the window's place on the desk; app.js (fitWindow)
   scales the window up in steps on a big screen and sizes the frame to
   match. A transform, not `zoom`: every hit test here (the dial, the
   volume slider) measures getBoundingClientRect against clientX, and a
   transform keeps those two in the same space in every browser. */
.frame { width: 100%; max-width: 720px; }
main { width: 100%; max-width: 720px; transform-origin: top left; }

.window { width: 100%; max-width: 720px; padding: 4px; display: flex; flex-direction: column; gap: 3px; }

.titlebar {
  background: var(--title); color: var(--chalk);
  display: flex; align-items: center; gap: 8px; padding: 3px 4px 3px 6px;
}
.titlebar h1 { margin: 0; font-size: 14px; font-weight: 700; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.titlebar .btn { width: 22px; min-height: 20px; padding: 0; display: grid; place-items: center; }
.titlebar .btn:active { padding: 1px 0 0 1px; }

.menubar { position: relative; display: flex; flex-wrap: wrap; padding: 1px 2px; }
.menutitle { font: inherit; color: var(--ink); background: transparent; border: 0; padding: 3px 9px; cursor: pointer; }
.menutitle[aria-expanded="true"] { background: var(--title); color: var(--chalk); }
.menutitle:focus-visible { outline: 1px dotted var(--ink); outline-offset: -3px; }
.menu {
  position: absolute; z-index: 10; min-width: 210px; padding: 3px;
  background: var(--putty); box-shadow: var(--raised), 4px 4px 0 rgba(18, 20, 15, 0.35); outline: none;
}
.menu.context { position: fixed; z-index: 15; }
.menu .item {
  display: grid; grid-template-columns: 14px 1fr auto; gap: 0 10px; align-items: center;
  padding: 4px 12px 4px 6px; cursor: pointer; white-space: nowrap;
}
.menu .item.hi { background: var(--title); color: var(--chalk); }
.menu .item[aria-disabled="true"] { color: var(--muted); text-shadow: 1px 1px var(--chalk); cursor: default; }
.menu .item .mark svg { display: block; }
.menu .shortcut { color: var(--ink-soft); padding-left: 18px; }
.menu .item.hi .shortcut { color: var(--chalk); }
.menu .heading { font-size: 11px; color: var(--ink-soft); padding: 5px 12px 2px 30px; text-transform: uppercase; letter-spacing: 1px; }
.menu .sepline { height: 2px; margin: 3px 2px; box-shadow: inset 0 1px var(--shade), inset 0 -1px var(--chalk); }

.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 5px 6px; }
.toolbar .icon { width: 32px; display: grid; place-items: center; padding: 0; }
.presets { display: flex; gap: 4px; flex-wrap: wrap; }
.toolbar .preset { width: 28px; padding: 0; }
.toolbar .preset[aria-pressed="true"] { font-weight: 700; }
.sep { width: 2px; height: 22px; margin: 0 4px; box-shadow: inset 1px 0 var(--shade), inset -1px 0 var(--chalk); }
.spacer { flex: 1; }

/* The volume slider: a sunken track with a wedge of fill -- louder is
   taller, the way the era drew it -- and the same raised thumb as the dial. */
.volume { position: relative; width: 96px; height: 26px; cursor: pointer; touch-action: none; user-select: none; }
.volume:focus-visible { outline: 1px dotted var(--ink); outline-offset: 2px; }
.voltrack { position: absolute; left: 0; right: 0; top: 9px; height: 8px; background: var(--bone); overflow: hidden; }
.volfill { height: 100%; background: var(--title); clip-path: polygon(0 100%, 100% 0, 100% 100%); }
.volume.muted .volfill { background: var(--shade); }
.volthumb { position: absolute; top: 3px; width: 10px; height: 20px; margin-left: -5px; background: var(--putty); box-shadow: var(--raised); }

.tabs { display: flex; padding: 6px 6px 0; margin-bottom: -3px; position: relative; z-index: 1; }
.tab {
  font: inherit; color: var(--ink-soft); border: 0; background: var(--putty); cursor: pointer;
  padding: 3px 14px; margin-top: 3px;
  box-shadow: inset 1px 1px var(--chalk), inset -1px 0 var(--ink), inset 2px 2px var(--bone), inset -2px 0 var(--shade);
}
.tab[aria-selected="true"] { color: var(--ink); font-weight: 700; padding: 4px 14px 6px; margin-top: 0; }
.tab:focus-visible { outline: 1px dotted var(--ink); outline-offset: -4px; }

.dialpanel { margin: 0 6px; padding: 16px 22px 14px; }

.dial { position: relative; height: 80px; cursor: pointer; touch-action: none; user-select: none; }
.dial:focus-visible { outline: 1px dotted var(--ink); outline-offset: 4px; }
.dial .scale { position: absolute; left: 0; right: 0; top: 0; display: flex; justify-content: space-between; font-size: 11px; color: var(--ink-soft); }
.dial .track { position: absolute; left: 0; right: 0; top: 40px; height: 6px; background: var(--bone); box-shadow: var(--sunken); }
.dial .ticks { position: absolute; left: 0; right: 0; top: 50px; height: 8px; background: repeating-linear-gradient(90deg, var(--ink) 0 1px, transparent 1px 2.5%); }
.dial .mark { position: absolute; font-size: 11px; transform: translateX(-50%); white-space: nowrap; }
.dial .mark.up { top: 18px; }
.dial .mark.down { top: 62px; }
.dial .mark.on { font-weight: 700; }
.dial .mark.crowded { visibility: hidden; }
.dial .thumb { position: absolute; top: 32px; width: 12px; height: 22px; margin-left: -6px; background: var(--putty); box-shadow: var(--raised); }

.lower { display: flex; gap: 10px; padding: 4px 6px; }

.led {
  position: relative;
  flex: 1; min-height: 132px; background: var(--tube); padding: 10px 14px;
  font-family: 'VT323', monospace; color: var(--led);
  display: flex; flex-direction: column; gap: 2px;
}
.led .glow { opacity: calc(0.25 + 0.75 * var(--signal)); text-shadow: 0 0 6px var(--led); }
.led .line1 { display: flex; justify-content: space-between; gap: 12px; font-size: 22px; }
.led .title { font-size: 26px; color: var(--chalk); text-shadow: none; }
.led .artist { font-size: 20px; }
.led .tagline { font-size: 18px; opacity: 0.6; margin-top: auto; }
/* Lyrics mode: the current line takes the title row, the next line the
   artist row, dimmer; the song moves down to the small row. Lines wrap
   rather than truncate -- a cut-off lyric is worse than a taller panel. */
.led.lyrics .title { font-size: 24px; }
.led.lyrics .artist { opacity: 0.55; text-shadow: none; }

/* The way in while the set is off: the whole display, as a button. The
   first version left a 22px icon in the title bar's corner as the only way
   in, with a hint in dim green on black that was hard to read. */
.ledpower {
  /* z-index: the display's rows are translucent (.glow), and opacity puts
     them in a later paint layer than an earlier positioned sibling -- the
     first version had "Press P..." showing through this panel. */
  position: absolute; inset: 0; z-index: 2; border: 0; background: var(--tube); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  font-family: 'VT323', monospace; color: var(--led);
}
.ledpower[hidden] { display: none; }
.ledpower .big { display: flex; align-items: center; gap: 10px; font-size: 42px; text-shadow: 0 0 10px var(--led); }
.ledpower .hint { font-size: 20px; color: var(--chalk); }
.ledpower:hover .big, .ledpower:focus-visible .big { color: var(--chalk); }
.ledpower:focus-visible { outline: 1px dotted var(--chalk); outline-offset: -6px; }
@media (prefers-reduced-motion: no-preference) {
  .ledpower .big { animation: ledpulse 2.4s ease-in-out infinite; }
  @keyframes ledpulse { 50% { text-shadow: 0 0 2px var(--led); } }
}

.meters { width: 128px; padding: 8px 10px; display: flex; flex-direction: column; gap: 6px; font-size: 12px; }
.bars { display: flex; align-items: flex-end; gap: 3px; height: 44px; }
.bars span { width: 12px; box-shadow: var(--pane); }
.bars span.on { background: var(--pine); box-shadow: none; }
.buffer { height: 16px; padding: 3px; display: flex; gap: 2px; background: var(--bone); }
.buffer span { width: 9px; background: var(--pine); }

.statusbar { display: flex; gap: 3px; font-size: 12px; }
.statusbar > div { padding: 3px 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.statusbar .wide { flex: 2; }
.statusbar .mid { flex: 1; }
.statusbar .clock { min-width: 72px; text-align: right; }
.statusbar [hidden] { display: none; }

/* ---- the Signal Lost dialog ---- */

/* Above everything in the window: the band tabs are lifted (z-index 1) to
   overlap the dial panel, and once drew through an open dialog. */
.scrim { position: fixed; inset: 0; z-index: 20; display: grid; place-items: center; padding: 16px; }
.scrim[hidden] { display: none; }
.dialog { width: 100%; max-width: 390px; padding: 4px; display: flex; flex-direction: column; gap: 3px; box-shadow: var(--raised), 6px 6px 0 rgba(18, 20, 15, 0.35); }
.dialog.alert .titlebar { background: var(--rust); }
.dialog.wide { max-width: 560px; }
.dialog a { color: var(--title); }
.dialog .well { margin: 10px 12px 4px; background: var(--chalk); max-height: 60vh; overflow: auto; padding: 4px; }
.dialog.guide { max-width: 680px; }
.guidebody { display: flex; gap: 8px; padding: 10px 12px 4px; height: min(420px, 62vh); }
.stationlist { width: 200px; flex: none; background: var(--chalk); padding: 4px; overflow-y: auto; outline: none; }
.stationlist:focus-visible { outline: 1px dotted var(--ink); outline-offset: -4px; }
.stationlist .group { font-size: 11px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 1px; padding: 6px 6px 2px; }
.stationlist .opt { display: flex; justify-content: space-between; gap: 8px; padding: 3px 6px 3px 18px; cursor: pointer; position: relative; white-space: nowrap; font-size: 13px; }
.stationlist .opt .f { color: var(--ink-soft); }
.stationlist .opt.on::before { content: ""; position: absolute; left: 7px; top: 50%; width: 5px; height: 5px; margin-top: -2.5px; border-radius: 50%; background: currentColor; }
.stationlist .opt.sel { background: var(--title); color: var(--chalk); }
.stationlist .opt.sel .f { color: var(--chalk); }
.stationlist:focus-visible .opt.sel { outline: 1px dotted var(--chalk); outline-offset: -2px; }
.detail { flex: 1; min-width: 0; background: var(--chalk); padding: 10px 14px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.detail h2 { margin: 0; font-size: 20px; }
.detail p { margin: 0; }
.detail .soft { font-size: 12px; color: var(--ink-soft); }
.detail .tagline { font-family: 'VT323', monospace; font-size: 20px; color: var(--accent, var(--title)); }
.detail .tracks { margin: 2px 0 0; padding-left: 26px; font-size: 13px; display: flex; flex-direction: column; gap: 2px; }
.detail .tracks .by { color: var(--ink-soft); }

/* The weather window. The reading itself sits on a tube panel, the same
   phosphor display the tuner uses -- the forecast is something the set
   receives, so it reads like the station does. */
.wxbody { padding: 12px 14px 4px; display: flex; flex-direction: column; gap: 10px; }
.wxbody p { margin: 0; }
.wxbody .soft { font-size: 12px; color: var(--ink-soft); }
.wxnow { background: var(--tube); padding: 10px 14px; font-family: 'VT323', monospace; color: var(--led); display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.wxnow .t { font-size: 44px; text-shadow: 0 0 8px var(--led); }
.wxnow .c { font-size: 24px; color: var(--chalk); }
.wxparts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.wxpart { background: var(--chalk); padding: 8px 10px; display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.wxpart .n { font-size: 11px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 1px; }
.wxpart .t { font-size: 20px; }
.wxpart.now { outline: 2px solid var(--title); outline-offset: -2px; }

.keys { width: 100%; border-collapse: collapse; font-size: 13px; }
.keys th { text-align: left; font-size: 11px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 1px; padding: 4px 8px; }
.keys td { padding: 5px 8px; vertical-align: top; border-top: 1px solid var(--bone); }
.keys td:nth-child(2) { white-space: nowrap; }
.keys .soft { color: var(--ink-soft); font-size: 12px; margin-left: 2px; }
kbd { display: inline-block; font: inherit; font-variant-ligatures: none; font-size: 12px; padding: 0 6px; background: var(--putty); box-shadow: var(--raised); line-height: 20px; }
.dialog .body { display: flex; gap: 14px; padding: 16px 16px 8px; }
.dialog .body p { margin: 0 0 6px; }
.dialog .body .soft { font-size: 13px; color: var(--ink-soft); }
.dialog .actions { display: flex; justify-content: flex-end; gap: 8px; padding: 6px 12px 12px; }
.dialog .actions .btn { min-width: 96px; min-height: 30px; }

/* The screensaver: the whole window, black, no cursor. The canvas is drawn
   at one device pixel per CSS pixel and scaled up chunky -- the era's
   savers were never sharper than the screen they ran on. */
#saverWrap { position: fixed; inset: 0; z-index: 40; background: #000; cursor: none; overflow: hidden; }
#saverWrap[hidden] { display: none; }
#saver { width: 100%; height: 100%; display: block; image-rendering: pixelated; }
.saverlabel {
  position: absolute; left: 0; top: 0; display: flex; flex-direction: column; gap: 2px;
  padding: 6px 10px; background: var(--putty); box-shadow: var(--raised); font-size: 13px; color: var(--ink);
  max-width: min(420px, 80vw); will-change: transform;
}
.saverlabel .t { background: var(--title); color: var(--chalk); font-weight: 700; margin: -6px -10px 2px; padding: 3px 10px; }
.saverlyric {
  position: absolute; left: 0; right: 0; bottom: 14%; text-align: center; padding: 0 16px;
  font-family: 'VT323', monospace; font-size: clamp(28px, 5vw, 56px); color: var(--led); text-shadow: 0 0 12px var(--led);
}

/* VECTOR SCAN, the hidden game: a window in the radio's own chrome over a
   dimmed desk. The playfield is SIGNAL's 160x76 dot space at an integer
   scale (set by app.js), pixel for pixel -- the era's DOS shooters looked
   exactly like this. The power meter is a row of beveled boxes: a row of
   labelled boxes was always the arcade original's meter, and it is the one
   part of the game a desktop app draws better than SIGNAL's grid did. */
#gameWrap { position: fixed; inset: 0; z-index: 35; background: rgba(18, 20, 15, 0.82); display: grid; place-items: center; padding: 12px; }
#gameWrap[hidden] { display: none; }
.gamewin { width: auto; max-width: none; }
.gamewin .titlebar .btn { width: 22px; min-height: 20px; padding: 0; display: grid; place-items: center; }
.gamehud { background: var(--tube); color: var(--led); font-family: 'VT323', monospace; font-size: 22px; display: flex; gap: 22px; padding: 4px 10px; text-shadow: 0 0 6px var(--led); white-space: nowrap; }
.gamehud .hi { color: var(--chalk); text-shadow: none; }
.gamefield { position: relative; background: var(--tube); padding: 4px; line-height: 0; }
#gameCanvas { image-rendering: pixelated; display: block; }
.gamebanner { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: 6px; font-family: 'VT323', monospace; color: var(--chalk); line-height: 1.1; }
.gamebanner[hidden] { display: none; }
.gamebanner .big { font-size: 40px; color: var(--led); text-shadow: 0 0 10px var(--led); }
.gamebanner .sub { font-size: 22px; }
.gamemeter { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 4px; padding: 6px 4px 2px; }
.gamemeter .box { text-align: center; font-size: 12px; padding: 5px 2px; background: var(--putty); box-shadow: var(--raised); color: var(--ink-soft); white-space: nowrap; }
.gamemeter .box.owned { color: var(--ink); font-weight: 700; }
.gamemeter .box.cursor { background: var(--title); color: var(--chalk); box-shadow: var(--pressed); }
.gamemeter .box.wiped { background: var(--putty-down); color: var(--muted); box-shadow: var(--pane); }
.gamehelp { font-size: 12px; color: var(--ink-soft); padding: 2px 6px 4px; }

#ytDock { position: fixed; left: -9999px; top: 0; width: 260px; height: 200px; }

/* A finger, not a pointer (an iPad, upright or not): toolbar buttons and
   tabs at a size a thumb can hit. Before the phone block below, which
   lays the presets out its own way and wins where both apply. */
@media (pointer: coarse) {
  .toolbar .btn { min-height: 38px; }
  .toolbar .icon { width: 44px; }
  .toolbar .preset { width: 40px; }
  .tab { padding-top: 8px; padding-bottom: 8px; }
  .menutitle { padding: 8px 12px; }
}

/* The toolbar on a phone (2026-10-13, reported: "the presets wrap/look
   odd"). Left to flex-wrap, it broke wherever the space ran out: the
   separator dangling at the end of row one, the presets on row two, and
   the volume slider and speaker stranded on a third. Now it is two rows
   on purpose: transport on the left and sound on the right, then the
   presets as an even strip across the full width -- equal columns for
   however many the band has, and taller, for a thumb. */
@media (max-width: 600px) {
  .toolbar .sep { display: none; }
  .toolbar .presets {
    order: 10; flex-basis: 100%;
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px;
  }
  .toolbar .preset { width: auto; min-height: 38px; }
  .toolbar .volume { width: 84px; }
}

/* A phone, or a tablet held upright: the window takes the screen's width
   and height, and the display -- the thing worth looking at -- takes what
   is spare. Both used to float a window with half the screen empty under
   it (2026-10-13); an upright iPad was a 720px window in 1180px of desk. */
@media (max-width: 560px), (max-width: 1100px) and (orientation: portrait) {
  body { align-items: stretch; }
  .frame { display: flex; flex-direction: column; min-height: calc(100dvh - 2 * var(--gutter, 32px)); max-width: 900px; }
  main, .window { flex: 1; display: flex; flex-direction: column; max-width: none; }
  .lower { flex: 1; flex-direction: column; }
  .led { min-height: 190px; }
  .led .title { font-size: 30px; }
  .meters { width: auto; flex-direction: row; align-items: center; flex-wrap: wrap; }
  .meters .buffer { flex: 1; min-width: 90px; }
}
/* An upright tablet's display is big enough to read across a room, so its
   text grows to match; the meters sit under it, as on a phone, rather than
   stretching into a tall thin column beside it. */
@media (min-width: 561px) and (max-width: 1100px) and (orientation: portrait) {
  .led { padding: 18px 24px; }
  .led .line1 { font-size: 28px; }
  .led .title { font-size: 44px; }
  .led .artist { font-size: 30px; }
  .led .tagline { font-size: 26px; }
  .ledpower .big { font-size: 64px; }
  .ledpower .hint { font-size: 28px; }
}
@media (max-width: 560px) {
  :root { --gutter: 12px; }
}

@media (max-width: 560px) {
  .guidebody { flex-direction: column; height: 70vh; }
  .stationlist { width: auto; height: 34%; }
  .stationlist .opt { padding-top: 9px; padding-bottom: 9px; }
  .menu .item { padding-top: 10px; padding-bottom: 10px; }
  .menutitle { padding: 8px 9px; }
  .keys td:nth-child(3), .keys th:nth-child(3) { display: none; }
  .wxparts { grid-template-columns: 1fr; }
  body { padding: 12px; }
  #stSn { display: none; }
}
