:root {
  color-scheme: light dark;
  --paper: #eeebe4;
  --ink: #1a1917;
  --faint: rgba(26, 25, 23, 0.5);
  --dim: rgba(26, 25, 23, 0.38);
  --soft: rgba(26, 25, 23, 0.8);
  --rule: rgba(26, 25, 23, 0.3);
  --prop: #8a3b2a;
  --text-l: 0.27;            /* the page's ink, as an oklch lightness */
  /* what the canvas draws with */
  --jack: #d6d3cc;
  --hole: #1d1c1a;
  --plate: #8f8a82;
  --tip: #b9b6af;
  --shadow: rgba(20, 18, 15, 0.28);
  --gutter: clamp(16px, 5vw, 64px);
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #171614;
    --ink: #e9e5dc;
    --faint: rgba(233, 229, 220, 0.5);
    --dim: rgba(233, 229, 220, 0.4);
    --soft: rgba(233, 229, 220, 0.82);
    --rule: rgba(233, 229, 220, 0.3);
    --prop: #e39479;
    --text-l: 0.92;
    --jack: #57534d;
    --hole: #0b0a09;
    --plate: #36332f;
    --tip: #8d8880;
    --shadow: rgba(0, 0, 0, 0.6);
  }
}
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--paper); color: var(--ink); }
body {
  font: clamp(13px, 3.5vw, 17px)/1.4 var(--mono);
  -webkit-font-smoothing: antialiased;
  touch-action: none;
}
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }
canvas.stage { position: fixed; left: 0; top: 0; z-index: 2; pointer-events: none; }
body.dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }

:root { --rec: "Recursive", var(--mono); }

/* the page: the thing being patched. the custom properties at the top are
   what the louder jacks move; they feed the declarations below them */
.page {
  --slant: 0; --mono: 1;
  --tilt: 0deg; --turn: 0deg; --skew: 0deg; --blur: 0px; --hue: 0; --echo: 0;
  position: fixed; left: var(--gutter); top: clamp(40px, 12vh, 120px);
  width: min(30em, calc(100vw - 2 * var(--gutter) - 720px));
  font-family: var(--rec);
  font-size: clamp(14px, 1.4vw, 18px);
  font-weight: 400;
  line-height: 1.5;
  /* slant counts up from upright; the font's own axis counts down */
  font-variation-settings: "slnt" calc(var(--slant) * -1), "MONO" var(--mono);
  transform: perspective(800px) rotateX(var(--tilt)) rotateY(var(--turn)) skewX(var(--skew));
  transform-origin: 50% 40%;
  filter: blur(var(--blur));
  /* ink until the hue moves, then more and more colour */
  color: oklch(var(--text-l) clamp(0, calc(var(--hue) / 150), 0.17) var(--hue));
  /* two coloured copies of the text, pushed apart by the echo */
  text-shadow:
    calc(var(--echo) * 1px) calc(var(--echo) * 0.6px) 0 oklch(0.72 0.19 calc(var(--hue) + 140) / clamp(0, calc(var(--echo) / 3), 0.85)),
    calc(var(--echo) * -1px) calc(var(--echo) * -0.6px) 0 oklch(0.72 0.19 calc(var(--hue) + 260) / clamp(0, calc(var(--echo) / 3), 0.85));
}
.page h1 { font: inherit; margin: 0; }
.page p { margin: 0 0 1em; }
.page .sub { opacity: 0.55; margin: 0; }
.page nav { margin: 1em 0 1.6em; }
.page nav a { text-decoration-color: var(--rule); }
.page nav a[aria-current] { text-decoration-color: currentColor; text-decoration-thickness: 2px; }
.page section:not(.on) { display: none; }
.page article { margin: 0 0 1.4em; }
.page article p { margin: 0; opacity: 0.7; }
.page h2 { font: inherit; margin: 0; }
.page .year { opacity: 0.45; }
/* now listening (js/listening.js): quieter than the rest of about, with a
   dot that breathes while something's actually playing */
.page .listening { opacity: 0.7; }
.page .listening.on-air::before {
  content: ""; display: inline-block; width: 0.45em; height: 0.45em; margin-right: 0.5em;
  border-radius: 50%; background: currentColor; vertical-align: 0.1em;
  animation: breathe 1.6s ease-in-out infinite;
}
@keyframes breathe { 50% { opacity: 0.25; } }
/* a jack in the page, playing the text next to it (drawn by the canvas) */
.page i.jack { display: inline-block; width: 1.05em; height: 1.05em; vertical-align: -0.2em; margin-left: 0.35em; }
/* the word a patched jack is playing, underlined in the colour of the
   cable coming out of it */
.page .playing { text-decoration: underline 2px var(--playhead); text-underline-offset: 4px; }
/* a long section scrolls inside the page, never under the stylesheet
   (main.js works out how tall it can be) */
.page { overflow-y: auto; scrollbar-width: none; touch-action: pan-y; }
.page::-webkit-scrollbar { display: none; }

/* the stylesheet: sources on one side, the rule on the other, and the
   cables hang in the gap between them */
.sheet {
  position: fixed; right: var(--gutter); top: clamp(40px, 12vh, 120px);
  display: flex; gap: 84px; align-items: flex-start;
  font: 400 13px/32px var(--rec);
  font-variation-settings: "MONO" 1;
  color: var(--soft);
}
/* fixed widths, so values changing length never move a jack */
.sources { width: 17em; flex: none; }
.rules { width: 31em; flex: none; }
.line { position: relative; white-space: nowrap; }
.line i.jack { position: absolute; top: 50%; width: 24px; height: 24px; margin-top: -12px; }
.sources .line { padding-right: 36px; text-align: right; }
.sources i.jack { right: 0; }
.rules .line { padding-left: 38px; }
.rules .line.in { padding-left: 56px; }
.rules i.jack { left: 0; }
.c, .m { color: var(--dim); }
.sel { color: var(--ink); }
.p { color: var(--prop); }
.v { color: var(--ink); }
.num { cursor: ew-resize; border-bottom: 1px dotted var(--rule); }
.num:hover { border-bottom-style: solid; }
.live { color: var(--dim); white-space: pre; }
.live::before { content: "→ "; }

/* not enough room for three columns: the page on top, the sheet below it */
@media (max-width: 1099px) {
  .page { width: auto; right: var(--gutter); top: 36px; font-size: clamp(14px, 2.2vw, 17px); }
  .sheet { top: auto; bottom: calc(24px + env(safe-area-inset-bottom)); left: var(--gutter); right: var(--gutter); justify-content: center; font-size: 12px; line-height: 27px; }
}
/* a phone: everything in one column, patching straight down */
@media (max-width: 699px) {
  .sheet { flex-direction: column; gap: 4px; justify-content: flex-start; font-size: 11px; line-height: 23px; }
  .sources, .rules { width: auto; }
  .line i.jack { width: 18px; height: 18px; margin-top: -9px; }
  .sources .line { padding: 0 0 0 30px; text-align: left; }
  /* two sources to a row, so the list stays short */
  .sources { display: grid; grid-template-columns: 1fr 1fr; column-gap: 10px; }
  .sources .line.c { grid-column: 1 / -1; }
  .live::before { content: ""; }
  .sources i.jack { left: 0; right: auto; }
  .rules .line { padding-left: 30px; }
  .rules .line.in { padding-left: 44px; }
}
