/* Flapwave web face (card 8): the v5 materials and controls from FlaptownDesign/v5/example/flapwave-controls.html
   (owner-approved 2026-11-09), copied verbatim, plus the module layout and the small-screen rules below.
   The font is the plugin's Syne Mono subset, written next to this file by gen.mjs. */
@font-face { font-family: "Syne Mono"; src: url("/SyneMono-Regular.ttf") format("truetype"); font-weight: 400; font-style: normal; font-display: block; }

:root {
  color-scheme: dark;
  --onyx: #0e1010; --plate: #161818; --plate-hi: #1b1e1e; --pocket: #080909; --mocha: #412828;
  --clay: #a46f67; --rose: #b7958c; --oak: #c9bab0; --rose2: #b19a98; --mauve: #6a4f5c; --dusty: #937f6d;
  --dim: #737078; --indigo: #3e4158;
  --done: #9ea3c8; --working: #d4b07a; --failed: #e07a62;
  --ease: cubic-bezier(.45, .1, .25, 1);
  --carve: 0 -1px 1px #000000f2, -1px -1px 1px #000000a6, 0 1px 0 #c9bab052;
  --font: "Syne Mono", ui-monospace, "DejaVu Sans Mono", monospace;
  --grain: repeating-linear-gradient(0deg, #c9bab003 0 1px, transparent 1px 3px);
  --grain-v: repeating-linear-gradient(90deg, #c9bab003 0 1px, transparent 1px 3px);
  --pocket-sh: inset 0 4px 10px -3px #000000e6, inset 0 2px 0 #000, inset 4px 0 8px -5px #000000b3, inset -4px 0 8px -5px #000000b3, inset 0 -1px 0 var(--mocha);
  --socket: 0 0 0 1.5px #050606, 0 1px 0 2px #c9bab012, inset 0 1px 2px #000;
}

/* ---------- ground and type (v5) ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { font-synthesis: none; }
body { margin: 0; min-height: 100vh; color: var(--oak); font: 400 15px/25px var(--font); text-shadow: var(--carve); -webkit-font-smoothing: antialiased;
  background: var(--plate) var(--grain); }
body, body * { font-family: var(--font) !important; font-weight: 400 !important; }
::selection { background: var(--mauve); color: var(--oak); }
h1, h2, h3, p { margin: 0; font-weight: 400; }
h1 { font-size: 32px; line-height: 40px; }
h2 { font-size: 18px; line-height: 26px; }
.lbl { font-size: 12px; line-height: 16px; letter-spacing: .08em; text-transform: uppercase; }
.cap { font-size: 11px; line-height: 16px; letter-spacing: .04em; }
.house { font-size: 11px; line-height: 16px; letter-spacing: .42em; text-transform: uppercase; color: var(--dim); }
.subtle { color: var(--dusty); } .muted { color: var(--rose); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:focus-visible { outline: 2px solid var(--oak); outline-offset: 2px; }

/* ---------- materials (v5, verbatim) ---------- */
.panel { position: relative; background: var(--plate) var(--grain); border-radius: 12px; padding: 30px;
  box-shadow: inset 0 1px 0 #c9bab014, inset 1px 0 0 #c9bab00a, inset 0 -1px 0 #00000099, 0 2px 0 #000, 0 10px 24px #00000080; }
.pocket { position: relative; background: var(--pocket); border-radius: 12px; padding: 6px; box-shadow: var(--pocket-sh); }
.window { position: relative; display: block; overflow: hidden; background: var(--onyx) linear-gradient(180deg, #c9bab012 0%, #c9bab005 40%, transparent 41%);
  border: 1px solid var(--mocha); border-radius: 8px; box-shadow: inset 0 1px 0 #c9bab01f, inset 0 -2px 6px #00000099, 0 1px 2px #000; }
.glass { position: absolute; inset: 2px; z-index: 2; border-radius: 7px; pointer-events: none;
  backdrop-filter: brightness(1.07) contrast(1.05);
  background: radial-gradient(130% 90% at 12% -10%, #c9bab017 0%, #c9bab006 40%, transparent 60%),
    linear-gradient(116deg, transparent 6%, #c9bab005 14%, #c9bab00c 20%, #c9bab012 26%, #c9bab00c 32%, #c9bab005 38%, transparent 46%),
    linear-gradient(116deg, transparent 50%, #c9bab004 56%, #c9bab008 62%, #c9bab004 68%, transparent 74%), linear-gradient(180deg, transparent 65%, #00000029 100%);
  border: 1px solid #c9bab01a;
  box-shadow: inset 0 1px 0 #c9bab040, inset 1px 0 0 #c9bab01c, inset -1px 0 0 #00000080, inset 0 -1px 0 #0000009e, inset 0 0 0 2px #c9bab007, inset 0 0 8px #c9bab00a; }
.glass::before { content: ""; position: absolute; top: 1px; left: 10%; right: 34%; height: 1px; background: linear-gradient(90deg, transparent, #e6d8cd59 35%, #e6d8cd33 70%, transparent); }
.glass::after { content: ""; position: absolute; top: 18%; bottom: 18%; left: 1px; width: 1px; background: linear-gradient(180deg, transparent, #e6d8cd26 40%, transparent); }
.cells { display: inline-block; letter-spacing: 0 !important; white-space: pre; color: var(--oak);
  background-image: repeating-linear-gradient(90deg, #c9bab00c 0 calc(1ch - 1px), transparent calc(1ch - 1px) 1ch); background-size: 100% 78%; background-position: 0 55%; background-repeat: repeat-x;
  text-shadow: 0 0 1px currentColor, 0 0 6px color-mix(in srgb, currentColor 38%, transparent); }
.live { animation: breathe 3.6s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: .55; } }

/* LED: a lamp in a drilled socket. Clay is the value colour; "cool" (done, Indigo lifted) is modulation and the playhead;
   "warm" (working, Dusty Taupe warmed) is accent. */
.lamp { display: inline-block; width: 5px; height: 5px; border-radius: 999px; flex: none; background: #0a0b0b; box-shadow: var(--socket); }
.lamp.on { background: radial-gradient(circle at 35% 35%, #f6c9b8 0%, #e07a62 55%, #a46f67 100%); box-shadow: 0 0 0 1.5px #050606, 0 1px 0 2px #c9bab012, 0 0 6px 1px #e07a6299; animation: led-on .28s var(--ease); }
.lamp.cool { background: radial-gradient(circle at 35% 35%, #e3e6f6 0%, #9ea3c8 55%, #3e4158 100%); box-shadow: 0 0 0 1.5px #050606, 0 1px 0 2px #c9bab012, 0 0 6px 1px #9ea3c899; animation: led-on .28s var(--ease); }
.lamp.warm { background: radial-gradient(circle at 35% 35%, #f6e6c6 0%, #d4b07a 55%, #937f6d 100%); box-shadow: 0 0 0 1.5px #050606, 0 1px 0 2px #c9bab012, 0 0 6px 1px #d4b07a99; animation: led-on .28s var(--ease); }
@keyframes led-on { 0% { transform: scale(.2); opacity: 0; } 60% { opacity: 1; transform: scale(1.15); } }

/* ---------- the module faceplate ---------- */
.module { display: grid; gap: 20px; padding: 0; overflow: visible; }
.module-bar { display: flex; align-items: center; gap: 15px; padding: 14px 20px; border-radius: 12px 12px 0 0;
  background: var(--plate) var(--grain); box-shadow: inset 0 1px 0 #c9bab014, inset 0 -1px 0 #000, 0 1px 0 #c9bab00a; }
.module-bar .src { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; color: var(--done); }
.module-body { display: grid; gap: 25px; padding: 0 30px 30px; }
.module-top { display: grid; grid-template-columns: 340px 1fr; gap: 30px; align-items: center; }
.module-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; padding: 25px 30px 0; border-top: 1px solid #000000a6; box-shadow: inset 0 1px 0 #c9bab00a; }
.readout { display: grid; gap: 10px; }
.readout .window { padding: 14px 16px; }

/* value window: glowing cells behind glass */
.vw .window { padding: 10px 14px; }
.vw .cells { font-size: 20px; line-height: 28px; display: block; width: max-content; }
.vw .sub { display: block; width: max-content; margin-top: 2px; font-size: 13px; line-height: 20px; color: var(--done); }
.vw.idle .cells:first-child { color: var(--rose); }

/* ---------- control + its three labels ---------- */
.ctl { position: relative; display: grid; justify-items: center; gap: 8px; }
.ctl .simple { font-size: 13px; line-height: 20px; color: var(--oak); }
/* the detail strip: the standard term on a nameplate milled into the plate */
.ctl .term { font-size: 11px; line-height: 16px; letter-spacing: .08em; text-transform: uppercase; color: var(--dusty); padding: 2px 8px 1px; border-radius: 3px;
  background: var(--pocket); box-shadow: inset 0 1px 2px #000, inset 0 -1px 0 #412828aa, 0 1px 0 #c9bab00f; white-space: nowrap; }
.ctl:has(:focus-visible) .term, .ctl:has(.s-focus) .term, .ctl:has(.s-drag) .term, .ctl:has(.drag) .term { color: var(--oak); }
/* the tooltip: a raised plate */
.tip { position: absolute; z-index: 20; left: calc(100% + 14px); top: 0; width: 290px; padding: 12px 15px 14px; border-radius: 8px; text-align: left;
  background: var(--plate-hi) var(--grain); color: var(--oak);
  box-shadow: inset 0 1px 0 #c9bab01f, inset 1px 0 0 #c9bab00a, inset 0 -1px 0 #00000099, 0 2px 0 #000, 0 12px 28px #000000cc;
  opacity: 0; visibility: hidden; transform: translateY(3px); transition: opacity .14s ease, transform .14s var(--ease), visibility 0s linear .14s; pointer-events: none; }
.tip .lbl { color: var(--rose); display: flex; justify-content: space-between; gap: 10px; }
.tip .lbl span { color: var(--dusty); }
.tip p { font-size: 13px; line-height: 20px; margin-top: 6px; }
.tip dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; margin: 10px 0 0; padding: 8px 0 0; border-top: 1px solid var(--mocha); font-size: 11px; line-height: 16px; letter-spacing: .04em; }
.tip dt { color: var(--dusty); text-transform: uppercase; letter-spacing: .08em; }
.tip dd { margin: 0; color: var(--rose); }
.tip.left { left: auto; right: calc(100% + 14px); }
.ctl:has(> .knob:hover) .tip, .ctl:has(> .fader:hover) .tip, .ctl:has(> .rsw:hover) .tip, .ctl:has(> :focus-visible) .tip, .tip.open {
  opacity: 1; visibility: visible; transform: none; transition: opacity .14s ease .35s, transform .14s var(--ease) .35s, visibility 0s linear .35s; }
.tip.open { transition: none; }
.ctl:has(.drag) .tip { opacity: 0; visibility: hidden; }

/* ---------- 1. knob: cap in a pocket, LED ring around it ---------- */
.knob { --n: 0; position: relative; width: 104px; height: 104px; border-radius: 50%; touch-action: none; cursor: ns-resize; user-select: none; -webkit-user-select: none; }
.knob.sm { width: 92px; height: 92px; }
.knob .pk { position: absolute; inset: 20px; border-radius: 50%; background: var(--pocket); box-shadow: var(--pocket-sh); }
.knob.sm .pk { inset: 18px; }
/* the cap: turned aluminium in Onyx; the turning marks and the top-left light are on this layer, which never rotates */
.knob .cap { position: absolute; inset: 26px; border-radius: 50%;
  background: radial-gradient(circle at 36% 28%, #c9bab01c 0%, transparent 46%), repeating-radial-gradient(circle at 50% 50%, #c9bab005 0 1px, transparent 1px 3px),
    radial-gradient(circle at 50% 50%, #1d2020 0%, #181a1a 62%, #121414 100%);
  border: 1.5px solid #737078b3; box-shadow: 0 2px 0 #000, 0 5px 9px #000000c0, inset 0 1px 0 #c9bab030, inset 1px 0 0 #c9bab012, inset 0 -2px 3px #00000099;
  transition: border-color .14s ease, box-shadow .14s ease; }
.knob.sm .cap { inset: 24px; }
/* the indicator: a groove filled with Pale Oak paint; only this turns */
.knob .ind { position: absolute; inset: 26px; border-radius: 50%; transform: rotate(calc(-135deg + 270deg * var(--n))); transition: transform .08s ease; pointer-events: none; }
.knob.sm .ind { inset: 24px; }
.knob .ind::before { content: ""; position: absolute; left: calc(50% - 1px); top: 4px; width: 2px; height: 15px; border-radius: 1px; background: var(--oak); box-shadow: 0 0 0 1px #00000099, 0 0 4px #c9bab033; }
.knob .lamp { position: absolute; margin: -2.5px 0 0 -2.5px; }
.knob:hover .cap, .knob.s-hover .cap { border-color: var(--rose); }
.knob:focus-visible, .knob.s-focus { outline: 2px solid var(--oak); outline-offset: 2px; }
.knob.drag, .knob.s-drag { cursor: grabbing; }
.knob.drag .cap, .knob.s-drag .cap, .knob.drag .ind, .knob.s-drag .ind { translate: 0 1px; }
.knob.drag .cap, .knob.s-drag .cap { border-color: var(--clay); box-shadow: 0 1px 0 #000, 0 3px 6px #000000c0, inset 0 1px 0 #c9bab01c, inset 0 -2px 3px #00000099, 0 0 0 3px #a46f6726; }
.knob[aria-disabled=true] { opacity: .38; cursor: default; }
.knob[aria-disabled=true] .cap { border-color: #73707866; }
.knob[aria-disabled=true] .ind::before { background: var(--dim); box-shadow: 0 0 0 1px #00000099; }

/* ---------- 2. fader: a cap riding a slot cut in a pocket ---------- */
.fader { --n: 0; --travel: 136px; position: relative; width: 60px; height: calc(var(--travel) + 40px); border-radius: 12px; touch-action: none; cursor: ns-resize; user-select: none; -webkit-user-select: none; }
.fader .pk { position: absolute; inset: 0; border-radius: 12px; background: var(--pocket); box-shadow: var(--pocket-sh); }
.fader .slot { position: absolute; left: calc(50% - 3px); top: 20px; bottom: 20px; width: 6px; border-radius: 3px; background: #050606; overflow: hidden;
  box-shadow: inset 0 2px 3px #000, inset 0 -1px 0 var(--mocha), 0 1px 0 #c9bab00f; }
.fader .fill { position: absolute; left: 1px; right: 1px; bottom: 0; height: calc(var(--n) * 100%); border-radius: 2px; background: var(--rose2); box-shadow: 0 0 6px #b19a9866; }
/* scale: carved ticks either side of the slot, every tenth, the 0 dB detent longer */
.fader .ticks { position: absolute; top: 20px; bottom: 20px; left: 9px; right: 9px; pointer-events: none;
  background: repeating-linear-gradient(180deg, #000 0 1px, #c9bab01a 1px 2px, transparent 2px calc(10% - 0.1px)) left / 9px 100% no-repeat,
    repeating-linear-gradient(180deg, #000 0 1px, #c9bab01a 1px 2px, transparent 2px calc(10% - 0.1px)) right / 9px 100% no-repeat; }
.fader .zero { position: absolute; left: 5px; right: 5px; height: 2px; bottom: calc(20px + var(--travel) * .83); background: linear-gradient(90deg, #000 0 13px, transparent 13px calc(100% - 13px), #000 calc(100% - 13px)); box-shadow: 0 1px 0 #c9bab01a; pointer-events: none; }
.fader .cap { position: absolute; left: 7px; right: 7px; height: 28px; bottom: calc(20px + var(--travel) * var(--n) - 14px); border-radius: 4px;
  background: linear-gradient(180deg, #2a2d2d 0%, #1d2020 44%, #121414 50%, #1a1c1c 56%, #151717 100%);
  border: 1.5px solid #737078b3; box-shadow: 0 3px 0 #000, 0 7px 12px #000000c0, inset 0 1px 0 #c9bab030, inset 1px 0 0 #c9bab012;
  transition: border-color .14s ease, bottom .08s ease; }
.fader .cap::after { content: ""; position: absolute; left: 5px; right: 5px; top: calc(50% - 1px); height: 2px; border-radius: 1px; background: var(--oak); box-shadow: 0 0 0 1px #00000099, 0 0 4px #c9bab033; }
.fader:hover .cap, .fader.s-hover .cap { border-color: var(--rose); }
.fader:focus-visible, .fader.s-focus { outline: 2px solid var(--oak); outline-offset: 2px; }
.fader.drag, .fader.s-drag { cursor: grabbing; }
.fader.drag .cap, .fader.s-drag .cap { border-color: var(--clay); box-shadow: 0 1px 0 #000, 0 3px 6px #000000c0, inset 0 1px 0 #c9bab01c, 0 0 0 3px #a46f6726; transition: border-color .14s ease; }
.fader[aria-disabled=true] { opacity: .38; cursor: default; }
.fader[aria-disabled=true] .fill { background: var(--dim); box-shadow: none; }
.fader[aria-disabled=true] .cap::after { background: var(--dim); }
.fv { min-width: 0; }
.fv .window { padding: 3px 8px; }
.fv .cells { font-size: 13px; line-height: 20px; display: block; }

/* ---------- 3. rotary switch: detents with a lamp at each ---------- */
.rsw { --i: 0; --k: 5; position: relative; width: 176px; height: 146px; border-radius: 12px; touch-action: none; cursor: pointer; user-select: none; -webkit-user-select: none; }
.rsw .pk { position: absolute; left: calc(50% - 32px); top: 58px; width: 64px; height: 64px; border-radius: 50%; background: var(--pocket); box-shadow: var(--pocket-sh); }
.rsw .cap { position: absolute; left: calc(50% - 26px); top: 64px; width: 52px; height: 52px; border-radius: 50%;
  background: radial-gradient(circle at 36% 28%, #c9bab01c 0%, transparent 46%), repeating-radial-gradient(circle at 50% 50%, #c9bab005 0 1px, transparent 1px 3px),
    radial-gradient(circle at 50% 50%, #1d2020 0%, #181a1a 62%, #121414 100%);
  border: 1.5px solid #737078b3; box-shadow: 0 2px 0 #000, 0 5px 9px #000000c0, inset 0 1px 0 #c9bab030, inset 1px 0 0 #c9bab012, inset 0 -2px 3px #00000099; transition: border-color .14s ease; }
.rsw .ind { position: absolute; left: calc(50% - 26px); top: 64px; width: 52px; height: 52px; transform: rotate(calc(-60deg + 30deg * var(--i))); transition: transform .12s cubic-bezier(.3, 1.6, .5, 1); pointer-events: none; }
.rsw .ind::before { content: ""; position: absolute; left: calc(50% - 1px); top: 3px; width: 2px; height: 22px; border-radius: 1px; background: var(--oak); box-shadow: 0 0 0 1px #00000099, 0 0 4px #c9bab033; }
.rsw .det { position: absolute; transform: translate(-50%, -50%); font-size: 11px; line-height: 14px; letter-spacing: .04em; color: var(--dusty); white-space: nowrap; }
.rsw .det.sel { color: var(--oak); }
.rsw:hover .cap, .rsw.s-hover .cap { border-color: var(--rose); }
.rsw:hover .det:not(.sel), .rsw.s-hover .det:not(.sel) { color: var(--rose); }
.rsw:focus-visible, .rsw.s-focus { outline: 2px solid var(--oak); outline-offset: 2px; }
.rsw.drag .cap, .rsw.s-drag .cap { border-color: var(--clay); box-shadow: 0 1px 0 #000, 0 3px 6px #000000c0, inset 0 1px 0 #c9bab01c, 0 0 0 3px #a46f6726; }
.rsw[aria-disabled=true] { opacity: .38; cursor: default; }
.rsw[aria-disabled=true] .ind::before { background: var(--dim); }

/* keys (v5) */
.key { --c: var(--dim); --f: #3e415833; display: inline-flex; align-items: center; justify-content: center; gap: 10px; font-family: inherit;
  min-height: 44px; padding: 0 20px; border-radius: 6px; cursor: pointer; font-size: 12px; line-height: 16px; letter-spacing: .08em; text-transform: uppercase;
  background: var(--f); border: 1.5px solid color-mix(in srgb, var(--c) 70%, transparent); color: var(--oak); text-shadow: var(--carve);
  box-shadow: 0 3px 0 #000, 0 6px 14px #00000099, inset 0 1px 0 #c9bab00f; white-space: nowrap;
  transition: background-color .14s ease, border-color .14s ease, transform .08s ease, box-shadow .08s ease, opacity .2s; }
.key:hover, .key.s-hover { border-color: var(--c); background: color-mix(in srgb, var(--f) 100%, #c9bab0 6%); }
.key:active, .key.s-down { transform: translateY(2px); box-shadow: 0 1px 0 #000, inset 0 1px 0 #c9bab00a; }
.key.primary { --c: var(--rose); --f: #b7958c26; }
.key.secondary { --c: var(--indigo); --f: #3e415866; }
.key[aria-disabled=true] { opacity: .38; cursor: default; transform: none; }
.key.s-focus { outline: 2px solid var(--oak); outline-offset: 2px; }

/* ---------- the generated module (card 8) ---------- */
.face { width: min(1200px, calc(100% - 60px)); margin: 0 auto; padding: 50px 0 80px; display: grid; gap: 30px; }
.module-top .say { max-width: 420px; }
.ctl .term { cursor: default; }
.tip.open { opacity: 1; visibility: visible; transform: none; transition: none; }

@media (max-width: 1000px) {
  .module-top { grid-template-columns: 1fr; }
  .module-row { flex-wrap: wrap; justify-content: center; }
  .tip { left: 50%; top: calc(100% + 10px); transform: translateX(-50%); }
  .tip.left { right: auto; }
  .tip.open, .ctl:has(> :focus-visible) .tip { transform: translateX(-50%); }
}
/* Phones: the tooltip becomes a strip across the module under the row, so it never runs off the screen. */
@media (max-width: 600px) {
  .face { width: calc(100% - 32px); padding: 30px 0 50px; }
  .panel { padding: 20px 15px; }
  .module-bar { flex-wrap: wrap; padding: 14px 15px; }
  .module-body { padding: 0 15px 20px; }
  .module-row { position: relative; padding: 20px 0 0; gap: 18px 12px; }
  .ctl { position: static; }
  .tip, .tip.left { left: 0; right: 0; width: auto; top: 100%; margin-top: 10px; transform: none; }
  .tip.open, .ctl:has(> :focus-visible) .tip { transform: none; }
}
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
.still *, .still *::before, .still *::after { animation: none !important; transition: none !important; }
/* The plugin editor's layout (?editor): the module alone on the plate, 16 px in from the window's edges. The egui face
   paints this exact page, and the screenshot diff (tools/face-module-diff.py) compares the two at 1x and 2x. */
.editor .face { width: auto; margin: 0; padding: 16px; }
.editor .module-top { grid-template-columns: 340px 1fr; }
.editor .module-row { flex-wrap: nowrap; justify-content: space-between; }
/* The editor's zoom keys (plugin chrome, so the page carries them too): small v5 keys at the bar's right end. */
.zoom { margin: -4px 0 -4px auto; display: flex; gap: 6px; }
.key.zk { width: 48px; min-height: 24px; height: 24px; padding: 0; border-width: 1px; font-size: 11px; letter-spacing: .04em; }
.key.zk[aria-pressed=true] { --c: var(--rose); --f: #b7958c1f; }
