/* Qub Radio (js/qub-radio.js): a small cyan-phosphor DOS screen floating over Proof, with an FM
   dial, preset buttons and a level meter. The glass is smoked, not solid, so the page shows
   through. It stays black and cyan (the page's dark-stage --p1) on both stages. The script places
   it (side at-l/at-r, edge at-t/at-b, --off from that edge), springs it there after a drag, and
   folds it to its title bar (.min). */
.radio{--c:#4DFFEA;--c-dim:#2AB3A5;--c-faint:#1A6660;--scr:#031010;--side:calc(max(16px,4vw));
  --spring:cubic-bezier(.2,1.3,.35,1);--fold:cubic-bezier(.16,.8,.24,1);
  position:fixed;z-index:7;width:min(296px,calc(100vw - 32px));box-sizing:border-box;padding:6px 10px 8px;border-radius:8px;
  background:rgba(3,10,11,.62);-webkit-backdrop-filter:blur(8px) saturate(140%);backdrop-filter:blur(8px) saturate(140%);
  border:1px solid rgba(77,255,234,.22);box-shadow:0 10px 28px rgba(0,0,0,.28),inset 0 0 20px rgba(77,255,234,.05);
  color:var(--c);font:17px/1.1 "VT323",ui-monospace,"Courier New",monospace;text-transform:uppercase;
  text-shadow:0 0 5px rgba(77,255,234,.6),0 1px 1px rgba(0,0,0,.6);
  transition:transform .55s var(--spring),width .4s var(--fold),padding .4s var(--fold),border-radius .4s var(--fold)}
:root[data-theme="light"] .radio{background:rgba(3,10,11,.8)} /* cream shows through more, so darker glass */
.radio.at-r{right:calc(var(--side) + env(safe-area-inset-right,0px))}
.radio.at-l{left:calc(var(--side) + env(safe-area-inset-left,0px))}
.radio.at-b{bottom:calc(var(--off,16px) + env(safe-area-inset-bottom,0px))}
.radio.at-t{top:calc(var(--off,72px) + env(safe-area-inset-top,0px))}
.radio.dragging{transition:none;box-shadow:0 18px 40px rgba(0,0,0,.4),inset 0 0 20px rgba(77,255,234,.05)}

/* title bar: the handle */
.radio-bar{display:flex;align-items:center;gap:8px;white-space:nowrap;color:var(--c-dim);font-size:15px;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.radio.dragging .radio-bar{cursor:grabbing}
.radio-title::before{content:":: ";color:var(--c-faint)}
.radio-fm{color:var(--c)}
.radio-state{margin-left:auto;white-space:nowrap;overflow:hidden;transition:opacity .25s}
.radio-bar button{margin-right:-4px}

/* the body folds away (rows to 0, fading) when minimized */
.radio-body{display:grid;grid-template-rows:1fr;transition:grid-template-rows .4s var(--fold),opacity .3s}
.radio-inner{min-height:0;overflow:hidden}
.radio.min{width:236px;padding:4px 10px;border-radius:999px}
.radio.min .radio-body{grid-template-rows:0fr;opacity:0}
.radio.min .radio-bar{cursor:pointer}
.radio.min .radio-state{width:.9em;flex:none}
.radio.min:not(.on) .radio-state{opacity:0}

.radio-mid{display:flex;align-items:flex-end;gap:8px;margin:4px 0 5px}
.radio-name{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.radio-name::before{content:"C:\\> "}
.radio-name::after{content:"_";animation:radio-blink 1s steps(1) infinite}

/* level meter: eight bars in eight steps (--h, set by the script) */
.radio-meter{display:flex;align-items:flex-end;gap:2px;height:14px;flex:none}
.radio-meter i{width:3px;height:calc(var(--h,1) * 1.75px);background:var(--c);box-shadow:0 0 4px rgba(77,255,234,.5)}

/* the dial: 1 MHz ticks, numbers every 4, a mark per station, the needle */
.dial{position:relative;height:25px;margin:0 2px 5px;cursor:ew-resize;touch-action:pan-y;outline:0;border-radius:2px;
  background:repeating-linear-gradient(90deg,var(--c-dim) 0 1px,transparent 1px 5%) 0 0/100% 6px no-repeat;
  border-top:1px solid var(--c-faint)}
.dial:focus-visible{box-shadow:0 0 0 1px var(--c)}
.dial-num{position:absolute;top:8px;transform:translateX(-50%);font-size:13px;color:var(--c-dim);pointer-events:none}
.dial-num::before{content:"";position:absolute;left:50%;top:-8px;width:1px;height:8px;background:var(--c-dim)}
.dial-st{position:absolute;bottom:0;width:6px;height:3px;transform:translateX(-50%);background:var(--c-faint);pointer-events:none}
.dial-st.lit{background:var(--c);box-shadow:0 0 5px var(--c)}
.dial-needle{position:absolute;top:-4px;bottom:-1px;width:2px;transform:translateX(-50%);background:#C8FFF8;box-shadow:0 0 6px var(--c),0 0 2px #fff;pointer-events:none}

.radio-ctrl{display:flex;justify-content:space-between;align-items:center;gap:6px}
.radio-presets{display:flex;gap:2px}
.radio button{appearance:none;border:0;background:none;padding:1px 4px;margin:0;color:inherit;font:inherit;text-shadow:inherit;cursor:pointer;border-radius:2px}
.radio button:hover,.radio button:focus-visible,.radio button[aria-pressed="true"]{background:var(--c);color:var(--scr);text-shadow:none;outline:0}
.radio.on .radio-state::before{content:"\25CF  ";animation:radio-blink 1.6s steps(1) infinite}
.radio-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@keyframes radio-blink{50%{opacity:0}}
/* room under the footer so the screen never covers it */
body.has-radio .page{padding-bottom:calc(130px + env(safe-area-inset-bottom,0px))}
@media (prefers-reduced-motion:reduce){
  .radio,.radio-body,.radio-state{transition:none}
  .radio-name::after,.radio.on .radio-state::before{animation:none}}
