/* Paste-ready components. Needs tokens.css. */
body{position:relative;background:radial-gradient(1100px 560px at 18% -12%,var(--bg-glow),transparent 62%),radial-gradient(800px 420px at 100% 110%,#141a33,transparent 70%),var(--bg);color:var(--ink);font:15px/1.4 var(--font-ui)}


/* ---------- starlit sky (behind everything, panels are opaque so it only shows in the gaps and page margins) ---------- */
body::before,body::after{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;background-size:480px 480px}
body::before{background-image:url("sprites/stars-static.svg");opacity:.55}                 /* static dots */
body::after{background-image:url("sprites/stars-twinkle.svg");opacity:.3;animation:twinkle 9s ease-in-out infinite alternate}  /* 16 brighter stars + 5 four-point stars, opacity .3 to .6 only */
@keyframes twinkle{to{opacity:.6}}
.moon{width:22px;height:22px;background:url("sprites/moon-star.svg") center/contain no-repeat;display:inline-block;vertical-align:-4px;margin-right:8px;filter:drop-shadow(0 0 5px rgba(183,180,232,.55))}
.divider.arcane{height:12px;background:url("sprites/divider-star.svg") center/240px 12px no-repeat}
.runes{position:absolute;right:16px;top:12px;width:196px;height:28px;background:url("sprites/rune-strip.svg") center/contain no-repeat;opacity:.16;pointer-events:none}  /* decorative only, aria-hidden */

/* ---------- panel ---------- */
.panel,header,#recBar,#midiBar,#gameBar{position:relative;background:linear-gradient(180deg,var(--panel-top),var(--panel-bot));
  border:1px solid var(--edge);border-radius:var(--r-panel);box-shadow:inset 0 1px 0 var(--hi),0 0 0 1px rgba(138,152,255,.05),var(--sh-panel)}
.panel::after{content:"";position:absolute;left:12%;right:12%;top:-1px;height:1px;pointer-events:none;background:linear-gradient(90deg,transparent,rgba(160,170,255,.45),transparent)} /* faint moonlit top edge */
.panel::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:url("sprites/grain.svg");mix-blend-mode:overlay} /* optional brushed grain, remove if heavy */
.inset-row{background:var(--inset);border-top:1px solid var(--groove-dark);box-shadow:inset 0 1px 0 var(--groove-light),inset 0 8px 10px -8px rgba(0,0,0,.6);border-radius:0 0 12px 12px}
.divider{height:2px;border:0;background:linear-gradient(var(--groove-dark) 0 1px,var(--groove-light) 1px 2px);margin:10px 0}
.vdivider{width:2px;align-self:stretch;background:linear-gradient(90deg,var(--groove-dark) 0 1px,var(--groove-light) 1px 2px)}
.tab{display:inline-block;font:600 12px/1 var(--font-label);letter-spacing:.08em;text-transform:uppercase;color:#1a1405;background:linear-gradient(180deg,var(--brass-hi),var(--brass));
  padding:5px 12px 5px 10px;border-radius:7px 7px 0 0;box-shadow:inset 0 1px 0 rgba(255,255,255,.3)}  /* section tab, like the Avenger panels but muted brass instead of orange */
.label{font:600 12px/1.1 var(--font-label);letter-spacing:.07em;text-transform:uppercase;color:var(--label)}

/* ---------- raised button ---------- */
.btn{font:600 14px/1 var(--font-label);letter-spacing:.06em;text-transform:uppercase;color:var(--ink);padding:9px 16px;min-height:38px;cursor:pointer;
  border:1px solid var(--edge);border-radius:var(--r-btn);background:linear-gradient(180deg,#3c3f55,#2a2c3d);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.15),inset 0 -2px 0 rgba(0,0,0,.35),var(--sh-raised);transition:filter .15s,transform .06s,box-shadow .06s}
@media (hover:hover){.btn:hover{filter:brightness(1.1)}}
.btn:active{transform:translateY(1px);box-shadow:inset 0 1px 2px rgba(0,0,0,.4),var(--sh-pressed)}
.btn:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.btn.primary{background:linear-gradient(180deg,#6372f2,var(--accent-deep));color:#fff;border-color:#2a3590;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3),inset 0 -2px 0 rgba(0,0,0,.25),0 3px 8px rgba(40,50,160,.35),var(--sh-raised)}
.btn.primary.running{background:linear-gradient(180deg,#30334a,#252839);color:var(--ink);border-color:var(--edge)}
.btn.small{min-height:32px;padding:6px 12px;font-size:13px}
.btn.big{min-height:52px;padding:12px 30px;font-size:17px;border-radius:999px}

/* ---------- segmented control (modes) ---------- */
.seg{display:inline-flex;gap:3px;padding:3px;background:var(--well);border:1px solid var(--edge);border-radius:12px;box-shadow:inset 0 2px 4px rgba(0,0,0,.6),0 1px 0 var(--groove-light)}
.seg button{font:600 13px/1 var(--font-label);letter-spacing:.07em;text-transform:uppercase;border:0;background:transparent;color:var(--muted);padding:9px 14px;min-height:36px;border-radius:9px;cursor:pointer}
.seg button.active{color:var(--ink);background:linear-gradient(180deg,#3c3f55,#2a2c3d);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),var(--sh-raised);position:relative}
.seg button.active::after{content:"";position:absolute;left:30%;right:30%;bottom:3px;height:2px;border-radius:2px;background:var(--accent);box-shadow:0 0 6px var(--accent)}

/* ---------- toggle switch (keep the real checkbox underneath) ---------- */
.switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none;min-height:36px}
.switch input{position:absolute;opacity:0;width:1px;height:1px}
.switch .track{position:relative;width:46px;height:24px;border-radius:7px;background:var(--well);border:1px solid var(--edge);box-shadow:inset 0 2px 4px rgba(0,0,0,.7),0 1px 0 var(--groove-light)}
.switch .track::before{content:"";position:absolute;left:7px;top:50%;width:5px;height:5px;margin-top:-2.5px;border-radius:50%;background:#2a2d36;transition:background .2s,box-shadow .2s} /* LED */
.switch .track::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:18px;border-radius:5px;
  background:repeating-linear-gradient(90deg,transparent 0 5px,rgba(0,0,0,.18) 5px 6px) center/12px 100% no-repeat,linear-gradient(180deg,#8d909a,#62656e);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),0 2px 3px rgba(0,0,0,.6);transition:transform .18s var(--ease-soft)}
.switch input:checked + .track::before{background:var(--accent);box-shadow:0 0 6px var(--accent)}
.switch input:checked + .track::after{transform:translateX(22px);background:repeating-linear-gradient(90deg,transparent 0 5px,rgba(0,0,0,.15) 5px 6px) center/12px 100% no-repeat,linear-gradient(180deg,#f6eed8,#d3c7a5)}
.switch input:focus-visible + .track{outline:2px solid var(--accent);outline-offset:3px}

/* ---------- knob (88px desktop, 80px phone) ----------
   <div class="knob" style="--v:.62">           --v is 0..1, set it from the slider value
     <input type="range" min="0" max="10" step="1" aria-label="Tempo">   real control, transparent, covers the whole knob, keeps keyboard + touch
     <svg viewBox="0 0 96 96" aria-hidden="true">
       <circle class="arc-track" cx="48" cy="48" r="40"/><circle class="arc-val" cx="48" cy="48" r="40"/>
       <g class="ticks"> ...11 <line> from sprites/knob-ticks.txt... </g>
       <text x="24" y="90">0</text><text x="72" y="90">10</text>
     </svg>
     <div class="cap"><i class="ind"></i></div>
   </div>
   <span class="label">Tempo</span> <output>96</output> */
.knob{--size:88px;position:relative;width:var(--size);height:var(--size);flex:none;touch-action:none}
.knob input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:grab;z-index:2}
.knob svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.knob .arc-track,.knob .arc-val{fill:none;stroke-width:3.2;stroke-linecap:round;transform:rotate(135deg);transform-origin:48px 48px}
.knob .arc-track{stroke:#07080a;stroke-dasharray:188.5 251.3}                   /* 270deg of r=40 (circumference 251.33) */
.knob .arc-val{stroke:var(--accent);filter:drop-shadow(0 0 3px rgba(138,152,255,.55));stroke-dasharray:calc(var(--v) * 188.5) 251.3}
.knob .ticks line{stroke:var(--cream);stroke-width:1.4;stroke-linecap:round;opacity:.7}
.knob .ticks line.maj{stroke-width:1.8;opacity:.95}
.knob text{font:500 10px var(--font-label);fill:var(--muted);text-anchor:middle}
.knob .cap{position:absolute;left:50%;top:50%;width:calc(var(--size) * .44);height:calc(var(--size) * .44);margin:calc(var(--size) * -.22) 0 0 calc(var(--size) * -.22);border-radius:50%;pointer-events:none;
  background:radial-gradient(circle at 35% 28%,var(--cap-top) 0%,var(--cap-mid) 55%,var(--cap-bot) 100%);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.2),inset 0 -2px 3px rgba(0,0,0,.55),0 6px 10px rgba(0,0,0,.55),0 1px 2px rgba(0,0,0,.85),0 0 0 4px #121317}  /* last shadow = dark well ring */
.knob .ind{position:absolute;left:50%;top:0;width:100%;height:100%;margin-left:-50%;transform:rotate(calc(-135deg + 270deg * var(--v)))}
.knob .ind::after{content:"";position:absolute;left:50%;top:9%;width:3px;height:36%;margin-left:-1.5px;border-radius:2px;background:var(--cream);box-shadow:0 0 3px rgba(239,229,203,.45)}
.knob:focus-within{outline:2px solid var(--accent);outline-offset:3px;border-radius:50%}
@media (max-width:480px){.knob{--size:80px}}
.knob-wrap{display:flex;flex-direction:column;align-items:center;gap:2px;text-align:center}
.knob-wrap output{font:600 15px/1 var(--font-label);color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:.04em}

/* ---------- slider (if a flat slider is still needed) ---------- */
input[type=range].flat{appearance:none;height:6px;border-radius:4px;background:var(--well);box-shadow:inset 0 1px 3px rgba(0,0,0,.7),0 1px 0 var(--groove-light)}
input[type=range].flat::-webkit-slider-thumb{appearance:none;width:22px;height:22px;border-radius:50%;background:radial-gradient(circle at 35% 28%,var(--cap-top),var(--cap-mid) 60%,var(--cap-bot));box-shadow:inset 0 1px 1px rgba(255,255,255,.2),0 3px 6px rgba(0,0,0,.6)}

/* ---------- staff window and lanes ---------- */
#staff{background:linear-gradient(180deg,#fdfcf8,#f3f1ea);border:1px solid var(--edge);border-radius:12px;box-shadow:inset 0 2px 5px rgba(0,0,0,.3),0 0 0 3px #15161a,0 6px 16px rgba(0,0,0,.45)} /* paper colour unchanged, gets a bezel */
#lanes{background:linear-gradient(180deg,#080a12 0%,#101324 75%,#191d33 100%);border-radius:10px 10px 0 0;box-shadow:inset 0 0 0 1px rgba(255,255,255,.05),inset 0 8px 16px -8px rgba(0,0,0,.7)}
/* faint key-aligned guides drawn behind the falling bars: stroke rgba(255,255,255,.035) every white key, rgba(255,255,255,.07) on each C */

/* ---------- falling notes (one bar = one key to press) ----------
   Bars NEVER use the judging colours. Right hand: blue to violet as it falls (JS lerps --c from --rh-a to --rh-b by progress). Left hand: teal.
   Judging colours show only AFTER the hit: key flash, staff note, finger flash, sparkle. A missed bar turns grey with a thin red outline. */
.fall{--rh-a:#7f9bff;--rh-b:#a58bff;--lh:#3cc3c9;--c:var(--rh-a);position:absolute;border-radius:6px;display:flex;align-items:flex-end;justify-content:center;padding-bottom:3px;
  font:600 12px/1 var(--font-label);color:#0b0d15;                                   /* finger number sits on the bar, dark text 7:1+ */
  background:linear-gradient(180deg,rgba(255,255,255,.3),rgba(255,255,255,0) 38%),var(--c);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4),inset 0 -2px 3px rgba(0,0,0,.2),0 0 12px -2px color-mix(in srgb,var(--c) 55%,transparent),0 2px 4px rgba(0,0,0,.45)}
.fall.lh{--c:var(--lh)}
.fall.sharp{border-radius:5px}
.fall.missed{--c:#6b6f80;color:#0b0d15;box-shadow:inset 0 0 0 1.5px #f05252;background:var(--c)}
.fall.landing{animation:landing .16s ease-out forwards}
@keyframes landing{to{opacity:.0;transform:scaleY(.6)}}      /* dim and shrink 160ms at the key line, never a flash */

/* ---------- hands strip (below the keyboard, never over the keys) ----------
   <div class="hands"> <div class="hand rh"> five <i class="f" style="left:X%" data-n="1"> (X = centre of the key under that finger) + <u class="palm"> </div> ... </div>
   Light rules: .next = glow in hand colour (about 1 beat early); .ok/.soft/.loud/.bad = result flash after the hit; .hand.off = dimmed (unused hand). */
.hands{position:relative;height:84px;margin-top:6px;background:linear-gradient(180deg,#0d1020,#121528);border:1px solid var(--edge);border-radius:12px;
  box-shadow:inset 0 2px 6px rgba(0,0,0,.6),0 0 0 1px rgba(138,152,255,.06)}
.hand{--h:#8a98ff;position:absolute;inset:0}
.hand.lh{--h:#3cc3c9}
.hand.off{opacity:.35}
.hand .f{position:absolute;top:8px;width:1.7%;min-width:20px;transform:translateX(-50%);border-radius:999px 999px 8px 8px;
  background:linear-gradient(180deg,#8d89bd,#5d5a87);box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 2px 4px rgba(0,0,0,.5);transition:box-shadow .12s,background .12s}
.hand .f::after{content:attr(data-n);position:absolute;bottom:4px;left:0;right:0;text-align:center;font:600 12px/1 var(--font-label);color:#0b0d15}
.hand .f[data-n="1"]{height:44px;top:30px}.hand .f[data-n="2"]{height:56px;top:18px}.hand .f[data-n="3"]{height:62px;top:12px}.hand .f[data-n="4"]{height:56px;top:18px}.hand .f[data-n="5"]{height:44px;top:30px}
.hand .palm{position:absolute;left:var(--px);width:var(--pw);bottom:-6px;height:30px;transform:none;border-radius:14px 14px 0 0;background:linear-gradient(180deg,#6f6c9c,#4f4d78);box-shadow:inset 0 1px 0 rgba(255,255,255,.2)}
.hand .f.next{background:linear-gradient(180deg,color-mix(in srgb,var(--h) 85%,white),var(--h));box-shadow:0 0 14px 2px color-mix(in srgb,var(--h) 70%,transparent),inset 0 1px 0 rgba(255,255,255,.5)}
.hand .f.ok{background:#4ade80;box-shadow:0 0 12px 2px rgba(74,222,128,.6)}
.hand .f.soft{background:#dcef8f;box-shadow:0 0 8px 1px rgba(220,239,143,.5)}
.hand .f.loud{background:#f2a516;box-shadow:0 0 8px 1px rgba(242,165,22,.5)}
.hand .f.bad{background:#ef4444;box-shadow:0 0 8px 1px rgba(239,68,68,.5)}
.next-line{font:600 15px var(--font-label);letter-spacing:.05em;color:var(--ink)}   /* "Next: G4 · RH finger 5 · mf" */
.fact{position:relative;padding:12px 16px 12px 44px;border-radius:12px;background:var(--inset);border:1px solid var(--edge);box-shadow:inset 0 0 0 1px rgba(138,152,255,.2),inset 0 2px 6px rgba(0,0,0,.5)}
.fact::before{content:"";position:absolute;left:10px;top:10px;width:24px;height:24px;background:url("sprites/moon-star.svg") center/contain no-repeat}
.fact b{display:block;font:600 12px var(--font-label);letter-spacing:.08em;text-transform:uppercase;color:var(--moonstone)}  /* "Did you know?" shown only after an answer or run */

/* ---------- sparkle (key judged right) ---------- */
.sparkle{position:absolute;width:0;height:0;pointer-events:none}
.sparkle i{position:absolute;left:-8px;top:-8px;width:16px;height:16px;opacity:0;color:var(--c,#4ade80);
  background:url("sprites/sparkle.svg") center/contain no-repeat;filter:drop-shadow(0 0 4px currentColor);
  animation:spark .7s var(--ease-soft) forwards}
.sparkle i:nth-child(1){--dx:-26px;--dy:-30px;--s:1}
.sparkle i:nth-child(2){--dx:22px;--dy:-38px;--s:.8;animation-delay:.04s}
.sparkle i:nth-child(3){--dx:-8px;--dy:-48px;--s:1.15;animation-delay:.02s}
.sparkle i:nth-child(4){--dx:34px;--dy:-18px;--s:.65;animation-delay:.07s}
.sparkle i:nth-child(5){--dx:-36px;--dy:-14px;--s:.7;animation-delay:.05s}
@keyframes spark{0%{opacity:0;transform:translate(0,0) scale(.3) rotate(0)}25%{opacity:1}100%{opacity:0;transform:translate(var(--dx),var(--dy)) scale(var(--s)) rotate(45deg)}}

@media (prefers-reduced-motion:reduce){
  body::after{animation:none;opacity:.3}   /* static stars only */
  *{transition:none !important;animation:none !important}
  .sparkle i{animation:none;opacity:0}   /* sparkles dropped; the key colour already says right/wrong */
}
body.no-fx .sparkle{display:none}
body.no-fx::after{animation:none;opacity:.3}                                 /* the page's existing "no effects" switch */

/* ======== STONE + VELLUM LOOK (overrides the flat panels above) ========
   Panels are carved blue stone: dark overlay (keeps text contrast: --muted 5.0:1, --ink 10:1 on the brightest stone pixel) over textures/stone-tile.jpg.
   Edges are chiselled: light top-left edge, dark bottom-right edge, an inner engraved line that glows faintly. */
.panel,header.top{background:linear-gradient(180deg,rgba(8,10,20,.30),rgba(8,10,20,.55)),var(--stone-tile) center/384px;
  border:1px solid #05060b;border-radius:10px;
  box-shadow:inset 1px 1px 0 rgba(190,200,255,.16),inset -1px -2px 0 rgba(0,0,0,.55),inset 0 0 0 4px rgba(8,10,20,.18),inset 0 0 0 5px rgba(138,152,255,.14),0 10px 24px rgba(0,0,0,.5)}
.panel::before{display:none}                                    /* the stone texture replaces the grain overlay */
.inset-row,.fact,.hands{background:linear-gradient(180deg,rgba(6,8,16,.62),rgba(6,8,16,.75)),var(--stone-tile) center/384px}
.seg,.switch .track{background:linear-gradient(rgba(4,5,12,.7),rgba(4,5,12,.7)),var(--stone-tile) center/384px}
.btn,.seg button.active{background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(0,0,0,.18)),var(--stone-tile) center/384px;
  box-shadow:inset 1px 1px 0 rgba(190,200,255,.22),inset -1px -2px 0 rgba(0,0,0,.5),var(--sh-raised)}
.btn.primary{background:linear-gradient(180deg,#6372f2,var(--accent-deep))}
/* engraved glyphs: glowing runes cut into the stone */
.engraved{color:transparent;background:linear-gradient(180deg,#a7b2ff,#6a79e8);-webkit-background-clip:text;background-clip:text;filter:drop-shadow(0 0 4px rgba(138,152,255,.5));text-shadow:none}
.runes{opacity:.3;filter:drop-shadow(0 0 3px rgba(138,152,255,.6))}
/* vellum staff window: ink on worn parchment, torn-edge feel from the texture's darkened rim */
#staff{background:var(--vellum) center/100% 100% no-repeat;border:1px solid #3a2b17;border-radius:6px;
  box-shadow:inset 0 0 22px rgba(90,60,25,.55),inset 0 0 0 1px rgba(255,240,200,.18),0 0 0 3px #0c0e18,0 0 0 4px rgba(138,152,255,.22),0 6px 16px rgba(0,0,0,.5)}
#staff line{stroke:var(--vellum-ink);stroke-width:1.2}           /* staff lines MUST stay dark enough: 7.8:1 or better */
#staff ellipse,#staff .note{fill:var(--vellum-ink)} #staff .stem{stroke:var(--vellum-ink)}
/* lane: starry slate window with faint constellation lines (use sprites/stars-static.svg at .5 inside #lanes, keep it behind the bars) */
#lanes{background:linear-gradient(180deg,rgba(6,8,18,.82),rgba(14,18,40,.9)),var(--stone-tile) center/384px}
