/* ==========================================================================
   Phosphene — interface styles.

   Loaded by index.html. Everything the editor draws is styled here; the WebGL
   canvas itself (#stage) only needs a black backdrop.

   Colour comes entirely from the custom properties in :root. Those values are
   a first-paint placeholder only — ui.js calls applyTheme() on boot and
   rewrites every one of them from THEMES, so change a colour there, not here.

   Contents
     :root, base ............ theme variables, page reset, the GL canvas
     patch editor ........... the pannable board, its grid and its cables
     nodes .................. module cards, headers, tool buttons
     controls ............... sliders, knobs, fader banks, selects
     viewport module ........ the odd one out: a card wrapped round a screen
     ports .................. inlets and outlets
     palette ................ the add-a-module list
     transport bar .......... the bar along the bottom
     popovers ............... menu, capture, hud, help, errors
     gate, first run ........ webgl2 refusal and the intro card
     touch / no-hover ....... coarse-pointer and hoverless overrides

   The last section matters: it widens hit targets and reveals hover-only
   controls on touch devices, so it must stay at the end where it can override.
   ========================================================================== */

:root {
  /* nord, the default scheme. these are the values ui.js computes for it, and
     they only matter for the first paint: the theme is applied on boot, from
     storage if the visitor has chosen one. */
  --bg: #242933;
  --panel: rgba(46,52,64,.92);
  --panel2: rgba(52,58,70,.96);
  --line: #434c5e;
  --txt: #eceff4;
  --dim: #8590a2;
  --acc: #88c0d0;
  --gen: #8fbcbb;
  --mod: #ebcb8b;
  --fx: #b48ead;
  --mixc: #d08770;
  --out: #bf616a;
  /* derived surfaces, set per theme by ui.js */
  --field: #1e222a;
  --track: #545d6f;
  --btn: #363c48;
  --headA: #414651;
  --headB: #303642;
  --portline: #677183;
  --portbg: #1f232b;
  --accsoft: rgba(136,192,208,.28);
  --gridline: rgba(236,239,244,.05);
  --hover: rgba(236,239,244,.07);
  --danger: #cf898f;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--txt);
  overflow: hidden;
  font: 11.5px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  /* a phone would otherwise grow the type in landscape, and flash a grey box
     on every tap */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

#stage {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  background: #000;
}

/* =========================================================================
   patch editor
   ========================================================================= */

/* touch-action none is what makes the editor usable with a finger: without it
   the browser claims the first move as a scroll or a page pinch and sends
   pointercancel, which kills every drag mid-way. the gestures we want (pan,
   pinch, node drag, patching) are all built from pointer events instead. */
#patch {
  position: fixed;
  inset: 0;
  z-index: 5;
  overflow: hidden;
  background: transparent;
  touch-action: none;
  -webkit-touch-callout: none;
}

#patch.hidden {
  display: none;
}

#patch.linking {
  cursor: crosshair;
}

#grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .5;
  background-image: linear-gradient(var(--gridline) 1px,transparent 1px), linear-gradient(90deg,var(--gridline) 1px,transparent 1px);
  background-size: 28px 28px;
}

#svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

#svg g {
  pointer-events: none;
}

#layer {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
}

.cable {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  pointer-events: none;
  opacity: .85;
}

.cable.tex {
  stroke: var(--gen);
}

.cable.num {
  stroke: var(--mod);
}

.cable.temp {
  opacity: .6;
  stroke-dasharray: 4 4;
}

.cable.hit {
  stroke: transparent;
  stroke-width: 14;
  pointer-events: stroke;
  cursor: pointer;
}

.node {
  position: absolute;
  width: 224px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 7px;
  box-shadow: 0 8px 26px rgba(0,0,0,.55);
  user-select: none;
}

.node.sel {
  border-color: var(--acc);
  box-shadow: 0 0 0 1px var(--accsoft),0 8px 26px rgba(0,0,0,.6);
}

.node.bypassed {
  opacity: .5;
}

.node.collapsed .nbody {
  display: none;
}

.nhead {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  cursor: move;
  border-radius: 6px 6px 0 0;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(var(--headA),var(--headB));
  touch-action: none;
}

.ntitle {
  flex: 1;
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cat-generator .nhead {
  border-left: 3px solid var(--gen);
}

.cat-modulator .nhead {
  border-left: 3px solid var(--mod);
}

.cat-effect .nhead {
  border-left: 3px solid var(--fx);
}

.cat-mix .nhead {
  border-left: 3px solid var(--mixc);
}

.cat-output .nhead {
  border-left: 3px solid var(--out);
}

.ntools {
  display: flex;
  gap: 2px;
  opacity: 0;
  transition: opacity .12s;
  position: relative;
  z-index: 2;
}

.node:hover .ntools,
.node.sel .ntools,
.node.bypassed .ntools {
  opacity: 1;
}

.tbtn {
  background: none;
  border: 0;
  color: var(--dim);
  cursor: pointer;
  font: inherit;
  padding: 0 3px;
  line-height: 1;
  border-radius: 3px;
}

.tbtn:hover {
  color: var(--acc);
  background: var(--hover);
}

.tbtn.del:hover {
  color: var(--danger);
}

.tbtn.off {
  color: var(--danger);
  opacity: .85;
}

.tbtn.lock {
  display: inline-flex;
  align-items: center;
  padding: 0 2px;
}

.tbtn.lock svg {
  display: block;
}

.tbtn.lock.on {
  color: var(--danger);
  opacity: 1;
}

/* locking freezes the controls only: ports, header and screen stay live */
.node.locked .nbody input,
.node.locked .nbody select,
.node.locked .nadv input,
.node.locked .nadv select,
.node.locked .knob,
.node.locked .vbank {
  pointer-events: none;
}

.node.locked .crow {
  opacity: .62;
}

.node.locked .ntools {
  opacity: 1;
}

.bbtn.inert {
  opacity: .55;
}

.node.bypassed .ntools {
  opacity: 1;
}

.nbody {
  padding: 6px 8px 10px;
  position: relative;
}

.prow {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 20px;
  margin: 2px 0;
}

.plabel {
  color: var(--txt);
  font-size: 11px;
}

.crow {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 5px 0 0;
}

.crow label {
  flex: 1;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.crow.wide select {
  flex: 1.2;
}

.ptext {
  width: 100%;
  background: var(--field);
  color: var(--txt);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 3px 6px;
  font: inherit;
  font-size: 11px;
}

.pgroup {
  position: relative;
}

.srow {
  position: relative;
  margin: 0 0 3px;
}

/* the fill is a tint of the accent, the thumb the accent itself. no ring is
   cut around the thumb, so a modulated row draws the same unbroken line. */
input[type=range] {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 14px;
  background: transparent;
  margin: 0;
  --fill: color-mix(in srgb,var(--acc) 60%,var(--track));
  --modfill: color-mix(in srgb,var(--mod) 70%,var(--track));
  --bg: var(--track);
}

/* --bg is built in script: accent up to the set value, modulation colour on
   to the live one */
input[type=range]::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  background: var(--bg);
}

/* firefox needs its own selectors: a combined rule would be dropped whole */
input[type=range]::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  border: none;
  background: var(--bg);
}

input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 9px;
  height: 9px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--acc);
  cursor: pointer;
}

input[type=range]::-moz-range-thumb {
  width: 9px;
  height: 9px;
  border: none;
  border-radius: 50%;
  background: var(--acc);
  cursor: pointer;
}

input[type=range]:hover::-webkit-slider-thumb {
  box-shadow: 0 0 0 3px var(--accsoft);
}

input[type=range]:hover::-moz-range-thumb {
  box-shadow: 0 0 0 3px var(--accsoft);
}

/* otherwise a checkbox takes the operating system accent, not the theme */
input[type=checkbox] {
  accent-color: color-mix(in srgb,var(--acc) 70%,var(--track));
  width: 13px;
  height: 13px;
  cursor: pointer;
}

/* vertical fader bank (step sequencer) */
.vbank {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 76px;
  margin: 6px 0 2px;
  padding: 4px;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 5px;
  touch-action: none;
  cursor: crosshair;
}

.vstep {
  position: relative;
  flex: 1 1 0;
  height: 100%;
  background: var(--track);
  border-radius: 3px;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.vfill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--acc);
  opacity: .55;
  border-radius: 3px;
  pointer-events: none;
}

.vstep.on .vfill {
  opacity: 1;
}

.vstep.on {
  box-shadow: inset 0 0 0 1px var(--mod);
}

.vstep.past {
  opacity: .32;
}

.vnum {
  position: relative;
  font-size: 9px;
  line-height: 1;
  padding-bottom: 2px;
  color: var(--txt);
  opacity: .75;
  pointer-events: none;
}

.vbank.drawing .vstep {
  transition: none;
}

/* knob control */
.krow {
  gap: 8px;
  min-height: 44px;
  margin: 4px 0;
}

.knob {
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  cursor: ns-resize;
  touch-action: none;
  outline: none;
  overflow: visible;
}

.ktrack {
  fill: none;
  stroke: var(--track);
  stroke-width: 2.4;
  stroke-linecap: round;
}

.kfill {
  fill: none;
  stroke: var(--acc);
  stroke-width: 2.4;
  stroke-linecap: round;
}

.kmod {
  fill: none;
  stroke: var(--mod);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: .95;
}

.kdial {
  fill: var(--field);
  stroke: var(--line);
  stroke-width: 1;
}

.kptr {
  stroke: var(--txt);
  stroke-width: 1.5;
  stroke-linecap: round;
}

.knob:hover .kptr,
.knob.dragging .kptr {
  stroke: var(--acc);
}

.knob.dragging .kdial,
.knob:focus-visible .kdial {
  stroke: var(--acc);
}

select,
input[type=text] {
  background: var(--field);
  border: 1px solid var(--line);
  color: var(--txt);
  border-radius: 4px;
  padding: 2px 4px;
  font: inherit;
}

span.num {
  flex: 0 0 auto;
  width: 58px;
  text-align: right;
  color: var(--txt);
  font-variant-numeric: tabular-nums;
  padding: 2px 4px;
  user-select: none;
}

span.num.modulated {
  color: var(--mod);
}

select {
  max-width: 112px;
}

.advtoggle {
  margin-top: 8px;
  color: var(--dim);
  cursor: pointer;
  letter-spacing: .06em;
  font-size: 10.5px;
  border-top: 1px dashed var(--line);
  padding-top: 5px;
  user-select: none;
}

.advtoggle:hover {
  color: var(--acc);
}

.nadv {
  display: none;
}

.nadv.open {
  display: block;
}

.pbtn {
  width: 100%;
  background: var(--btn);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 3px 6px;
}

.npanel {
  display: block;
  width: 100%;
  margin: 6px 0 2px;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 4px;
}

.readout {
  margin-top: 6px;
  padding: 3px 5px;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--mod);
  text-align: right;
}

/* =========================================================================
   viewport module
   ========================================================================= */

.node.vp {
  width: auto;
  background: transparent;
  box-shadow: none;
}

.node.vp .nhead {
  background: var(--panel2);
  box-shadow: 0 6px 20px rgba(0,0,0,.5);
}

.node.vp .nbody {
  padding: 0;
  background: transparent;
}

.node.vp .crow {
  padding: 4px 8px 6px;
  background: var(--panel2);
  margin: 0;
  box-shadow: 0 6px 20px rgba(0,0,0,.5);
}

.node.vp .prow {
  padding: 0 8px;
  margin: 0;
  background: var(--panel2);
}

.vpscreen {
  position: relative;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 0 0 6px 6px;
  box-shadow: 0 8px 26px rgba(0,0,0,.55);
}

.vpgrip {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 16px;
  height: 16px;
  cursor: nwse-resize;
  touch-action: none;
  background: linear-gradient(135deg,transparent 48%,var(--dim) 48%,var(--dim) 60%,transparent 60%, transparent 72%,var(--dim) 72%,var(--dim) 84%,transparent 84%);
  opacity: .6;
}

.vpgrip:hover {
  opacity: 1;
}

.port {
  position: absolute;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1.5px solid var(--portline);
  background: var(--portbg);
  cursor: crosshair;
  flex: 0 0 auto;
  touch-action: none;
}

/* inlets sit in the gutter, out of flow, so rows with and without a port
   align. the offset is a variable because a viewport pads its own rows. */
/* centred with a margin, not a transform: cable ends read offsetTop, which
   a transform would not move */
.port.in {
  position: absolute;
  left: var(--portx,-15px);
  top: 50%;
  margin: -5.5px 0 0;
}

.node.vp .crow,
.node.vp .prow {
  --portx: -7px;
}

.port.tex {
  border-color: var(--gen);
}

.port.num {
  border-color: var(--mod);
}

.port.linked {
  background: currentColor;
}

.port.tex.linked {
  background: var(--gen);
}

.port.num.linked {
  background: var(--mod);
}

/* 2px smaller, nudged so every inlet centre shares one vertical line */
.port.modport {
  width: 9px;
  height: 9px;
  left: calc(var(--portx,-15px) + 1px);
  margin-top: -4.5px;
}

.port.outport {
  position: absolute;
  right: -6px;
  top: 9px;
  background: var(--portbg);
}

.port:hover {
  box-shadow: 0 0 0 3px var(--accsoft);
}

/* =========================================================================
   palette
   ========================================================================= */

.palette {
  position: fixed;
  z-index: 40;
  width: min(278px,calc(100vw - 16px));
  max-height: min(530px, calc(100vh - 24px));
  max-height: min(530px, calc(100dvh - 24px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 12px 40px rgba(0,0,0,.6);
  padding: 8px;
}

/* only the list scrolls: search and hint stay put */
.plist {
  overflow: auto;
  flex: 1;
  min-height: 0;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.phint {
  flex: none;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  color: var(--dim);
  font-size: 10px;
  line-height: 1.35;
  min-height: 2.7em;
}

.psearch {
  width: 100%;
  margin-bottom: 6px;
}

.pcat {
  color: var(--dim);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  margin: 10px 0 3px;
}

.pcat:first-child {
  margin-top: 0;
}

.pitem {
  padding: 4px 6px;
  border-radius: 4px;
  cursor: pointer;
  border-left: 3px solid transparent;
}

.pitem:hover {
  background: var(--hover);
}

.pitem.cat-generator {
  border-left-color: var(--gen);
}

.pitem.cat-modulator {
  border-left-color: var(--mod);
}

.pitem.cat-effect {
  border-left-color: var(--fx);
}

.pitem.cat-mix {
  border-left-color: var(--mixc);
}

.pitem.cat-output {
  border-left-color: var(--out);
}

/* =========================================================================
   transport bar
   ========================================================================= */

#bar {
  position: fixed;
  left: 50%;
  bottom: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 5px 6px;
  max-width: calc(100vw - 20px);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 11px;
  box-shadow: 0 10px 34px rgba(0,0,0,.5);
  backdrop-filter: blur(12px);
  /* narrow screens cannot show five groups at once, so the bar scrolls
     sideways instead of spilling off the edge */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  overscroll-behavior: contain;
}

#bar::-webkit-scrollbar {
  display: none;
}

#bar.dim {
  opacity: .22;
}

#bar.dim:hover {
  opacity: 1;
}

.bbtn {
  background: none;
  border: 1px solid transparent;
  color: var(--txt);
  border-radius: 7px;
  padding: 4px 9px;
  cursor: pointer;
  font: inherit;
  white-space: nowrap;
}

.bbtn:hover {
  background: var(--hover);
  color: var(--acc);
}

.bbtn.on {
  border-color: var(--mod);
  color: var(--mod);
}

.bbtn.recording {
  color: var(--out);
  border-color: var(--out);
}

.bbtn.open {
  background: var(--hover);
  border-color: var(--line);
}

.bsel {
  max-width: 150px;
  border: 1px solid transparent;
  background: none;
  border-radius: 7px;
  padding: 3px 4px;
}

.bsel:hover {
  background: var(--hover);
}

.bbtn.scoped {
  color: var(--acc);
  border-color: var(--acc);
}

.node.flash {
  animation: flash .42s ease-out;
}

@keyframes flash {
  from {
    box-shadow: 0 0 0 2px var(--acc);
  }

  to {
    box-shadow: 0 0 0 2px transparent;
  }
}

.bsep {
  width: 1px;
  align-self: stretch;
  background: var(--line);
  margin: 1px 5px;
  opacity: .7;
  flex: 0 0 auto;
}

/* the bar is five groups: build, chance, examples, output, everything else */
.bgrp {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
}

.blab {
  color: var(--dim);
  font-size: 11px;
  letter-spacing: .05em;
  padding: 0 4px 0 2px;
  pointer-events: none;
  user-select: none;
}

.blab.stats {
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  padding-right: 6px;
  white-space: nowrap;
  flex: 0 0 auto;
}

.bbtn.icon {
  padding: 4px 8px;
  color: var(--dim);
}

.bbtn.icon:hover {
  color: var(--acc);
}

/* =========================================================================
   popovers (menu, capture)
   ========================================================================= */

.pop {
  position: fixed;
  left: 50%;
  bottom: 58px;
  bottom: calc(58px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 41;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0,0,0,.6);
  padding: 10px 12px 11px;
  display: none;
  max-height: calc(100vh - 96px);
  max-height: calc(100dvh - 96px);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.pop.open {
  display: block;
}

#menu {
  width: min(344px,calc(100vw - 16px));
}

#capture {
  width: min(252px,calc(100vw - 16px));
}

.pop .mrow {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 5px 0;
  min-width: 0;
}

.pop .mrow>span {
  flex: 0 0 92px;
  color: var(--dim);
  white-space: nowrap;
}

.pop .mrow .bbtn,
.pop .mrow select {
  flex: 1 1 0;
  min-width: 0;
  width: auto;
  max-width: none;
  border-color: var(--line);
  background: var(--btn);
  padding: 4px 6px;
  text-align: center;
}

.pop .mrow .bbtn {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pop hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 7px 0;
}

#hud {
  position: fixed;
  left: 10px;
  top: 8px;
  z-index: 31;
  color: var(--dim);
  opacity: .45;
  pointer-events: none;
  letter-spacing: .04em;
  transition: opacity .2s;
}

#hud:empty {
  display: none;
}

#help {
  position: fixed;
  left: 50%;
  bottom: 58px;
  transform: translateX(-50%);
  z-index: 31;
  color: var(--dim);
  background: var(--panel2);
  border: 1px solid var(--line);
  padding: 9px 13px;
  border-radius: 8px;
  box-shadow: 0 12px 40px rgba(0,0,0,.6);
  pointer-events: none;
  line-height: 1.75;
  display: none;
  max-width: calc(100vw - 16px);
}

#help.open {
  display: block;
}

#help b {
  color: var(--txt);
  font-weight: 400;
}

#err {
  position: fixed;
  inset: auto 0 62px 0;
  background: #3a1216;
  color: #ffd9dc;
  padding: 10px;
  white-space: pre-wrap;
  font-size: 11px;
  max-height: 40%;
  overflow: auto;
  z-index: 50;
  display: none;
  cursor: pointer;
}

#err::after {
  content: ' (click to dismiss)';
  opacity: .55;
}

/* =========================================================================
   unsupported browser / gpu
   ========================================================================= */

/* shown instead of the editor: without webgl2 nothing else can start */
#gate {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  padding: 24px;
}

#gate.open {
  display: flex;
}

#gate .gcard {
  max-width: 440px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 60px rgba(0,0,0,.7);
  padding: 18px 20px;
  line-height: 1.7;
  color: var(--dim);
}

#gate h1 {
  margin: 0 0 9px;
  font-size: 13px;
  font-weight: 400;
  color: var(--txt);
  letter-spacing: .08em;
  text-transform: uppercase;
}

#gate p {
  margin: 0 0 9px;
}

#gate ul {
  margin: 0;
  padding-left: 17px;
}

#gate b {
  color: var(--txt);
  font-weight: 400;
}

/* =========================================================================
   first run
   ========================================================================= */

#intro {
  position: fixed;
  inset: 0;
  z-index: 45;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(6,8,11,.6);
  backdrop-filter: blur(3px);
  padding: 12px;
}

#intro.open {
  display: flex;
}

#intro .icard {
  width: min(334px,100%);
  max-height: calc(100dvh - 24px);
  overflow: auto;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 60px rgba(0,0,0,.7);
  padding: 15px 17px 12px;
}

#intro h1 {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 400;
  color: var(--txt);
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* every step reserves the same height, so the card does not jump on next */
.istep {
  display: none;
  color: var(--dim);
  line-height: 1.8;
  min-height: 92px;
}

.istep.on {
  display: block;
}

.istep b {
  color: var(--txt);
  font-weight: 400;
}

.istep .kk {
  color: var(--acc);
}

#intro .ifoot {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
}

.idots {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: 1 1 auto;
}

.idot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line);
}

.idot.on {
  background: var(--acc);
}

#intro .bbtn {
  border-color: var(--line);
  background: var(--btn);
  padding: 4px 10px;
}

/* =========================================================================
   touch / no-hover
   ========================================================================= */

/* a finger has no hover, so anything that only appears on hover would be
   invisible and unreachable. it is also blunt, so the small hit targets are
   widened without changing how anything looks. */
@media (hover:none) {
  .ntools {
    opacity: 1;
  }

  .vpgrip {
    opacity: 1;
  }

  #bar.dim {
    opacity: .6;
  }
}

@media (pointer:coarse) {
  .tbtn {
    padding: 3px 6px;
  }

  .knob {
    cursor: default;
  }

  /* a fingertip is a poor pointer: the cable a tap cuts is the one nearby */
  .cable.hit {
    stroke-width: 26;
  }

  /* the dot stays 11px; only the area that answers a touch grows, and it
     grows outwards, away from the sliders and knobs inside the card */
  .port::after {
    content: '';
    position: absolute;
    inset: -8px;
  }

  .port.in::after {
    inset: -8px -1px -8px -14px;
  }

  .port.outport::after {
    inset: -8px -14px -8px -1px;
  }

  .vpgrip {
    width: 24px;
    height: 24px;
  }

  input[type=range] {
    height: 26px;
  }

  input[type=range]::-webkit-slider-thumb {
    width: 15px;
    height: 15px;
    margin-top: -6px;
  }

  input[type=range]::-moz-range-thumb {
    width: 15px;
    height: 15px;
  }

  input[type=checkbox] {
    width: 17px;
    height: 17px;
  }

  .pitem {
    padding: 7px 6px;
  }

  .pop .mrow .bbtn,
  .pop .mrow select {
    padding: 7px 6px;
  }

  .bbtn {
    padding: 7px 10px;
  }

  .advtoggle {
    padding-top: 8px;
    padding-bottom: 4px;
  }
}
