:root{
  --bg:#f5f3ee; --surface:#ffffff; --surface-2:#efece5; --ink:#1c1b19; --muted:#6d685f; --line:#e1dcd1;
  --accent:#3d5afe; --accent-ink:#ffffff; --accent-soft:#e3e8ff;
  --ok:#2b8a3e; --ok-soft:#d3f9d8; --bad:#c92a2a; --bad-soft:#ffe3e3; --miss:#d9480f; --miss-soft:#fff0db;
  --kw:#fdfcf9; --kb:#23232a; --kw-edge:#cfc9bd;
  --shadow:0 1px 2px rgba(0,0,0,.05),0 8px 24px rgba(0,0,0,.06);
  color-scheme:light;
}
@media (prefers-color-scheme: dark){
  :root{
    --bg:#121418; --surface:#1b1e24; --surface-2:#252932; --ink:#ebe8e1; --muted:#9b978e; --line:#2f343d;
    --accent:#8198ff; --accent-ink:#0d1020; --accent-soft:#252c4a;
    --ok:#69db7c; --ok-soft:#1d3a24; --bad:#ff8787; --bad-soft:#44201f; --miss:#ffa94d; --miss-soft:#40301a;
    --kw:#e9e5dc; --kb:#0b0c0f; --kw-edge:#6f6a60;
    --shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.25);
    color-scheme:dark;
  }
}
*{box-sizing:border-box}
[hidden]{display:none!important}
body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.45 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;-webkit-tap-highlight-color:transparent}
.wrap{max-width:1180px;margin:0 auto;padding:20px 16px 40px}
.top{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px}
.top-actions{display:flex;gap:8px;flex:none}
h1{font-size:24px;margin:0;letter-spacing:-.01em}
.sub{margin:2px 0 0;color:var(--muted);font-size:14px}
.icon-btn{height:42px;min-width:42px;border-radius:12px;border:1px solid var(--line);background:var(--surface);color:var(--ink);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px;padding:0 10px;font:inherit;font-size:14px;font-weight:600;flex:none;transition:background .15s,color .15s,border-color .15s}
.icon-btn:hover{border-color:var(--accent)}
.icon-btn.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
@media (max-width:520px){#btnPianoLbl{display:none}}

.skills{margin-bottom:10px}
.skills .seg button{font-size:14px;padding:7px 16px}
.levels{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}
.lvl{border:1px solid var(--line);background:var(--surface);color:var(--ink);padding:7px 13px 7px 7px;border-radius:999px;cursor:pointer;display:flex;gap:8px;align-items:center;font:inherit;font-size:14px;transition:background .15s,border-color .15s,color .15s}
.lvl:hover{border-color:var(--accent)}
.lvl .n{display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;background:var(--surface-2);font-size:12px;font-weight:650}
.lvl.active{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.lvl.active .n{background:rgba(255,255,255,.22)}

.card{background:var(--surface);border:1px solid var(--line);border-radius:16px;padding:18px;box-shadow:var(--shadow)}
.custom{margin-bottom:14px;display:flex;flex-wrap:wrap;gap:12px 24px;align-items:center;padding:14px 18px;animation:enter .25s ease-out}
.cf{display:flex;align-items:center;gap:8px;font-size:14px;flex-wrap:wrap}
.cf>span{color:var(--muted)}
.pickrow{flex-basis:100%;animation:enter .2s ease-out}
.cf.wide{flex-basis:100%}
.weights{display:flex;flex-wrap:wrap;gap:6px 18px}
.weights label,.gapsl{display:flex;align-items:center;gap:6px;font-size:13px}
.weights input[type=range]{width:84px}
.gapsl input[type=range]{width:120px}
.weights output,.gapsl output{min-width:38px;color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
.pcpick{display:flex;gap:4px;flex-wrap:wrap}
.pcpick button{min-width:40px;padding:6px 8px;border-radius:8px;border:1px solid var(--line);background:var(--surface);color:var(--ink);font:inherit;font-size:13px;font-weight:650;cursor:pointer;transition:background .15s,color .15s,border-color .15s}
.pcpick button.blk{background:var(--surface-2)}
.pcpick button.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.presets{display:flex;gap:4px;flex-wrap:wrap}
.presets button{border:none;background:none;color:var(--accent);font:inherit;font-size:13px;cursor:pointer;padding:4px 6px;border-radius:6px}
.presets button:hover{background:var(--accent-soft)}
select{font:inherit;font-size:14px;padding:6px 8px;border-radius:8px;border:1px solid var(--line);background:var(--surface);color:var(--ink)}
.seg{display:inline-flex;background:var(--surface-2);border-radius:10px;padding:3px;gap:2px;flex-wrap:wrap}
.seg button{border:none;background:transparent;color:var(--ink);font:inherit;font-size:13px;padding:6px 11px;border-radius:8px;cursor:pointer;transition:background .15s}
.seg button.on{background:var(--surface);box-shadow:0 1px 3px rgba(0,0,0,.15);font-weight:650}
.seg button:disabled{opacity:.45;cursor:default}
.midi-controls{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px;align-items:center}
.midi-controls select{max-width:100%;min-width:0}
.midi-port{display:flex;flex-direction:column;gap:5px;width:100%;font-size:13px;color:var(--muted)}
.seg.mini button{font-size:12px;padding:3px 9px}

.grid{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:16px;align-items:start}
@media (max-width:900px){.grid{grid-template-columns:minmax(0,1fr)}}

.trainer-top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}
.level-info{display:flex;flex-wrap:wrap;gap:6px;font-size:13px;color:var(--muted)}
.tag{background:var(--surface-2);padding:3px 10px;border-radius:999px}
.linkbtn{border:none;background:none;color:var(--muted);font:inherit;font-size:13px;cursor:pointer;padding:3px 6px;border-radius:6px;white-space:nowrap}
.linkbtn:hover{color:var(--bad);background:var(--bad-soft)}
.progress{display:flex;gap:3px;margin:14px 0 0}
.progress i{flex:1;height:6px;border-radius:3px;background:var(--surface-2);transition:background .3s}
.progress i.ok{background:var(--ok)} .progress i.part{background:var(--miss)} .progress i.bad{background:var(--bad)}
.progress i.cur{background:var(--accent);animation:blink 1.4s ease-in-out infinite}
.progress i.new{animation:grow .35s ease-out}
@keyframes blink{50%{opacity:.35}}
@keyframes grow{from{transform:scaleY(2.4)}to{transform:none}}
.stage{display:flex;align-items:center;gap:18px;margin:16px 0 14px}
.play{width:84px;height:84px;border-radius:50%;border:none;background:var(--accent);color:var(--accent-ink);cursor:pointer;display:grid;place-items:center;flex:none;position:relative;transition:transform .12s}
.play:active{transform:scale(.94)}
.play::after{content:"";position:absolute;inset:-6px;border-radius:50%;border:2px solid var(--accent);opacity:0;pointer-events:none}
.play.playing::after{animation:ring 1s ease-out infinite}
.play.spent{opacity:.4;cursor:not-allowed}
.play.loading::after{opacity:.9;border-color:var(--accent) transparent transparent;animation:spin .8s linear infinite}
@keyframes ring{from{transform:scale(.92);opacity:.7}to{transform:scale(1.25);opacity:0}}
@keyframes spin{to{transform:rotate(360deg)}}
.prompt{font-size:22px;font-weight:650;line-height:1.25}
.prompt.enter{animation:enter .28s ease-out}
.prompt.good{color:var(--ok)} .prompt.part{color:var(--miss)} .prompt.badr{color:var(--bad)}
.detail{color:var(--muted);font-size:14px;min-height:1.45em;margin-top:3px}
@keyframes enter{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

.slots{display:flex;gap:8px;margin:0 0 16px;min-height:44px;flex-wrap:wrap}
.slot{min-width:64px;height:44px;padding:0 12px;border-radius:10px;border:2px dashed var(--line);display:grid;place-items:center;font-weight:650;font-size:17px;color:var(--muted);transition:background .2s,border-color .2s,color .2s}
.slot.filled{border-style:solid;border-color:var(--accent);color:var(--ink);background:var(--accent-soft)}
.slot.ok{border:2px solid var(--ok);background:var(--ok-soft);color:var(--ok)}
.slot.miss{border:2px solid var(--miss);background:var(--miss-soft);color:var(--miss)}
.slot.bad{border:2px solid var(--bad);background:var(--bad-soft);color:var(--bad);text-decoration:line-through}
.slot.pop{animation:pop .22s ease-out}
@keyframes pop{0%{transform:scale(.8)}60%{transform:scale(1.07)}100%{transform:none}}

.pcgrid{display:grid;grid-template-columns:repeat(14,minmax(0,1fr));gap:6px;margin-bottom:16px}
.pc{grid-row:2;height:54px;border-radius:10px;border:1px solid var(--line);background:var(--surface);color:var(--ink);font:inherit;font-weight:650;font-size:16px;cursor:pointer;position:relative;transition:background .18s,border-color .18s,color .18s,transform .08s,opacity .18s;padding:0}
.pc.blk{grid-row:1;background:var(--surface-2)}
.pcgrid.white-only .pc{grid-row:1}
.pcgrid.white-only .pc.blk{display:none}
.pcgrid.ivgrid{grid-template-columns:repeat(15,minmax(0,1fr))}
.pcgrid.chgrid{grid-template-columns:repeat(30,minmax(0,1fr))}
.chgrid .pc{display:flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.15;font-size:15px;overflow:hidden}
.chgrid .iq{font-size:11px;font-weight:500;opacity:.75}
@media (max-width:520px){.chgrid{gap:6px 4px}.chgrid .pc{font-size:11px;padding:0 2px}.chgrid .iq{font-size:9px;letter-spacing:-.03em}}
.ivgrid.words .pc{display:flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.15;font-size:15px;overflow:hidden}
.ivgrid .iq{font-size:11px;font-weight:500;opacity:.75}
@media (max-width:520px){.ivgrid.words{gap:6px 3px}.ivgrid.words .pc{font-size:10px;letter-spacing:-.02em}.ivgrid .iq{font-size:9px}}
.pc:hover:not(:disabled){border-color:var(--accent)}
.pc:active:not(:disabled){transform:translateY(1px)}
.pc:disabled{opacity:.28;cursor:default}
.pc .hk{position:absolute;right:5px;top:3px;font-size:10px;color:var(--muted);font-weight:500}
.pc.sel,.pc.down{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.pc.sel .hk{color:inherit;opacity:.7}
.pc.ok{background:var(--ok-soft);border-color:var(--ok);color:var(--ok)}
.pc.miss{background:var(--miss-soft);border-color:var(--miss);color:var(--miss)}
.pc.bad{background:var(--bad-soft);border-color:var(--bad);color:var(--bad);animation:shake .32s}
@keyframes shake{20%{transform:translateX(-4px)}40%{transform:translateX(4px)}60%{transform:translateX(-3px)}80%{transform:translateX(2px)}}
@media (max-width:520px){.pc{font-size:14px;height:48px}.pc .hk{display:none}}

.kbd-wrap{overflow-x:auto;padding-bottom:6px;margin-bottom:14px}
.kbd{position:relative;height:140px}
.kbd.big{height:200px;touch-action:pan-x;user-select:none;-webkit-user-select:none}
.key{position:absolute;top:0;padding:0;cursor:pointer;font:inherit;transition:background .18s}
.kbd.big .key{transition:background .05s}
.key.w{height:100%;background:var(--kw);border:1px solid var(--kw-edge);border-radius:0 0 7px 7px;z-index:1}
.key.b{height:60%;background:var(--kb);border:none;border-radius:0 0 5px 5px;z-index:2;box-shadow:inset 0 -3px 0 rgba(255,255,255,.1)}
.key .lbl{position:absolute;bottom:5px;left:0;right:0;text-align:center;font-size:10px;color:#8a8478;pointer-events:none}
.key .nm{position:absolute;left:50%;transform:translateX(-50%);bottom:22px;font-size:11px;font-weight:700;color:#1c1b19;white-space:nowrap;pointer-events:none}
.key.b .nm{bottom:8px;color:#fff;font-size:10px}
.key .hk2{position:absolute;left:0;right:0;text-align:center;bottom:42px;font-size:10px;color:#9a9488;pointer-events:none}
.key.b .hk2{bottom:auto;top:6px;color:#8d8d99}
.key.w.mapped{box-shadow:inset 0 -5px 0 #d6defc}
.key.w.soft{background:#e2e8ff} .key.b.soft{background:#3b4a8a}
.key.w.sel,.key.w.down{background:#bac8ff} .key.b.sel,.key.b.down{background:#4c6ef5}
.key.w.ok{background:#b2f2bb} .key.b.ok{background:#2f9e44}
.key.w.miss{background:#ffd8a8} .key.b.miss{background:#e8590c}
.key.w.bad{background:#ffc9c9} .key.b.bad{background:#e03131}
.key.dis{cursor:default;opacity:.3}
.key.hit{animation:press .25s ease-out}
@keyframes press{50%{filter:brightness(.85)}}

.actions{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.spacer{flex:1}
.btn{font:inherit;font-size:14px;font-weight:600;padding:10px 16px;border-radius:10px;border:1px solid var(--line);background:var(--surface);color:var(--ink);cursor:pointer;position:relative;overflow:hidden}
.btn:hover:not(:disabled){border-color:var(--accent)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);min-width:110px}
.btn:disabled{opacity:.45;cursor:default}
.btn.small{font-size:13px;padding:7px 12px}
.btn.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.btn.ready{animation:ready 1.1s ease-in-out infinite}
@keyframes ready{50%{box-shadow:0 0 0 6px var(--accent-soft)}}
.btn.countdown::before{content:"";position:absolute;inset:0;background:rgba(255,255,255,.28);transform-origin:left;animation:cd 1.4s linear forwards}
@keyframes cd{from{transform:scaleX(0)}to{transform:scaleX(1)}}

.summary{padding:18px 0 16px;animation:enter .3s ease-out}
.sum-top{display:flex;gap:22px;align-items:center;flex-wrap:wrap}
.score{font-size:60px;font-weight:750;letter-spacing:-.02em;line-height:1;font-variant-numeric:tabular-nums}
.score small{font-size:26px;color:var(--muted);font-weight:600}
.sum-title{font-size:20px;font-weight:650}
.sum-line{color:var(--muted);margin:2px 0 8px}
.badge{display:inline-block;background:var(--surface-2);padding:4px 11px;border-radius:999px;font-size:13px;font-weight:600}
.badge.good{background:var(--ok-soft);color:var(--ok)}
.sum-sec{margin-top:18px}
.sum-sec .lab{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:650;margin-bottom:8px}
.chips{display:flex;gap:6px;flex-wrap:wrap}
.chip{padding:5px 11px;border-radius:9px;background:var(--bad-soft);color:var(--bad);font-weight:650;font-size:14px}
.chip small{font-weight:500;opacity:.8;margin-left:4px}

.stats h2{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:20px 0 8px;font-weight:650}
.stats h2:first-child{margin-top:0}
.h2row{display:flex;justify-content:space-between;align-items:center;margin:20px 0 8px}
.h2row h2{margin:0!important}
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.kpi{background:var(--surface-2);border-radius:10px;padding:8px 4px;text-align:center}
.kpi b{display:block;font-size:20px;line-height:1.2;font-variant-numeric:tabular-nums;white-space:nowrap}
.kpi span{font-size:11px;color:var(--muted)}
.bump{animation:bump .35s ease-out}
@keyframes bump{40%{transform:scale(1.25)}}
.totals{font-size:14px;margin:0}
.bars{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;height:150px}
.bar{display:flex;flex-direction:column;align-items:center;gap:3px;min-width:0;transition:opacity .2s}
.bar.off{opacity:.35}
.bar .pct{font-size:9px;color:var(--muted);font-variant-numeric:tabular-nums;height:12px}
.bar .col{width:100%;flex:1;display:flex;align-items:flex-end;background:var(--surface-2);border-radius:4px;overflow:hidden}
.bar .fill{width:100%;transition:height .45s ease-out}
.bar .nm{font-size:10px;color:var(--muted);white-space:nowrap;overflow:hidden;max-width:100%}
.bar .cnt{font-size:11px;font-weight:650;font-variant-numeric:tabular-nums;height:14px}
.legend{font-size:11px;color:var(--muted);margin:6px 0 0}
.conf{margin:0;padding:0;list-style:none;font-size:14px}
.conf li{display:flex;justify-content:space-between;padding:5px 0;border-bottom:1px solid var(--line)}
.conf li:last-child{border-bottom:none}
.conf li.empty{color:var(--muted)}
.conf .arrow{color:var(--muted);margin:0 4px}
.stats .btn{margin-top:16px}

.piano-head{display:flex;flex-wrap:wrap;gap:14px 28px;align-items:flex-end;justify-content:space-between;margin-bottom:14px}
.now-lab{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:650}
.now{font-size:40px;font-weight:750;line-height:1.15;min-height:1.15em;font-variant-numeric:tabular-nums;transition:opacity .3s}
.now.dim{opacity:.35}
.pctrl{display:flex;flex-wrap:wrap;gap:12px 22px;align-items:center}
.pctrl b{min-width:1.2em;text-align:center;font-variant-numeric:tabular-nums}

.keys{margin-top:16px;color:var(--muted);font-size:13px;line-height:2}
kbd{font:12px ui-monospace,Consolas,monospace;background:var(--surface);border:1px solid var(--line);border-bottom-width:2px;border-radius:5px;padding:1px 6px;color:var(--ink)}

.note{font-size:12px;color:var(--muted);margin:8px 0 0}
.toast{position:fixed;left:50%;bottom:20px;transform:translate(-50%,20px);max-width:calc(100vw - 32px);background:var(--ink);color:var(--bg);padding:10px 16px;border-radius:10px;font-size:14px;opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;z-index:10}
.toast.show{opacity:1;transform:translate(-50%,0)}
#dlg,.rank-dlg{border:1px solid var(--line);border-radius:16px;background:var(--surface);color:var(--ink);padding:20px;width:min(480px,calc(100vw - 32px));box-shadow:var(--shadow)}
#dlg::backdrop,.rank-dlg::backdrop{background:rgba(0,0,0,.4)}
#dlg h3,.rank-dlg h3{margin:0 0 8px;font-size:18px}
.field{padding:12px 0;border-bottom:1px solid var(--line)}
.field>.lab{font-size:13px;color:var(--muted);margin-bottom:7px}
.check{display:flex;gap:10px;align-items:flex-start;padding:9px 0;cursor:pointer;font-size:14px}
.check input{margin-top:3px;accent-color:var(--accent);width:16px;height:16px;flex:none}
.check small{display:block;color:var(--muted)}
input[type=range]{width:100%;accent-color:var(--accent)}
.lg{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin-bottom:8px}
.lg span{display:inline-flex;align-items:center;gap:5px}
.chart{position:relative}
.chart-scroll{overflow-x:auto;touch-action:pan-x pan-y}
.chart svg{display:block;overflow:visible}
.chart .ax{font-size:11px;fill:var(--muted);font-family:inherit}
.chart .gl{stroke:var(--line)}
.tip{position:absolute;pointer-events:none;background:var(--ink);color:var(--bg);font-size:12px;line-height:1.4;padding:6px 10px;border-radius:8px;white-space:nowrap;z-index:2;transform:translate(-50%,calc(-100% - 12px))}
.num{width:72px;font:inherit;font-size:14px;padding:6px 8px;border-radius:8px;border:1px solid var(--line);background:var(--surface);color:var(--ink)}
.num:focus{outline:2px solid var(--accent);outline-offset:1px}
.progress.dense{gap:1px}
.dlg-foot{display:flex;justify-content:flex-end;margin-top:14px}

/* Ranked tests (SW accounts): the bar above the trainer, the box on the summary, the ranking window. */
.lvl-rank{font-size:12px}
.test-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:12px 16px;margin-bottom:14px;border-color:color-mix(in oklab,var(--accent) 35%,var(--line))}
.test-lead{font-weight:650}
.test-note{flex:1 1 260px;font-size:13px;color:var(--muted)}
.test-note .linkbtn,.test-bar>.linkbtn{color:var(--accent);padding:0 2px}
.test-note .linkbtn:hover,.test-bar>.linkbtn:hover{color:var(--accent);background:var(--accent-soft)}
.test-sum{display:grid;gap:6px;padding:12px 14px;margin-bottom:14px;border-radius:12px;background:var(--accent-soft)}
.test-sum-btns{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.rank-dlg{width:min(460px,calc(100vw - 32px))}
.rank-rows{list-style:none;margin:12px 0 0;padding:0;display:grid;gap:4px;max-height:55vh;overflow-y:auto}
.rank-rows li{display:flex;align-items:baseline;gap:10px;padding:7px 10px;border-radius:8px;background:var(--surface-2)}
.rank-rows li.mine{outline:2px solid var(--accent)}
.rank-rows li.empty{justify-content:center;color:var(--muted)}
.rank-rows .pl{width:22px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums}
.rank-rows .who{flex:1;min-width:0;display:flex;flex-direction:column}
.rank-rows .nk{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-rows .cm{font-size:12px;color:var(--muted);overflow-wrap:anywhere}
.rank-rows .cm:empty{display:none}
.comment-line,.comment-form{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px;overflow-wrap:anywhere}
.comment-line .linkbtn,.comment-form .linkbtn{color:var(--accent);padding:0 2px}
.comment-line .linkbtn:hover,.comment-form .linkbtn:hover{color:var(--accent);background:var(--accent-soft)}
.comment-hidden{flex-basis:100%;font-size:12px;color:var(--bad)}
.comment-form input{flex:1 1 220px;min-width:0;padding:6px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--ink);font:inherit}
.rank-rows .tm{font-size:12px;color:var(--muted)}
.rank-rows b{font-variant-numeric:tabular-nums;color:var(--ok)}
.rank-dlg .dlg-foot{gap:8px}
.rank-dlg .dlg-foot a.btn{text-decoration:none}
