@fretfall/player 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.html CHANGED
@@ -11,7 +11,7 @@ rel="preload"
11
11
  href="https://cdn.jsdelivr.net/npm/@coderline/alphatab@1.8.4/dist/alphaTab.min.js"
12
12
  as="script"
13
13
  />
14
- <style>:root{--bg: #0e1014;--ink: #0e1014;--text: #e8eaef;--muted: #7b8190;--accent: #c8f04a;--chip: #171a20;--chip-border: #2a2f38;--done: #e8eaef;--todo: #23272f;--ui: system-ui, sans-serif;--num: system-ui, sans-serif;--lyric: system-ui, sans-serif;--lyric-style: normal}*{box-sizing:border-box}[hidden]{display:none!important}html,body{height:100%}body{margin:0;overflow:hidden;background:var(--bg);color:var(--text);font:14px/1.4 var(--ui);accent-color:var(--accent)}canvas{position:fixed;inset:0;width:100%;height:100%;display:block}button{font:inherit;color:inherit}.bar{position:fixed;z-index:3;left:32px;right:32px;top:18px;height:40px;display:flex;align-items:center;justify-content:space-between;gap:24px;transition:transform .25s ease,opacity .25s ease,visibility .25s}.group{display:flex;align-items:center;gap:10px;min-width:0}.group:last-child{flex:none}.wordmark{display:flex;align-items:center;gap:7px;font:700 15px var(--num);letter-spacing:.22em}:is(.wordmark,.welcome-mark) .fall{transform-box:fill-box;transform-origin:center;transform:rotate(14deg);animation:fall .75s .8s both}@keyframes fall{0%{transform:translate(-3.5px,-1.42px) rotate(0);animation-timing-function:cubic-bezier(.55,0,.85,.35)}40%{transform:translate(0) rotate(18deg);animation-timing-function:cubic-bezier(.2,.7,.4,1)}56%{transform:translateY(-.35px) rotate(11.5deg);animation-timing-function:ease-in-out}74%{transform:translateY(.08px) rotate(15.2deg);animation-timing-function:ease-in-out}88%{transform:translate(0) rotate(13.6deg);animation-timing-function:ease-in-out}to{transform:translate(0) rotate(14deg)}}@media(prefers-reduced-motion:reduce){.wordmark .fall{animation:none}}.seg{display:flex;gap:2px;padding:3px;border-radius:9px;background:var(--chip);border:1px solid var(--chip-border);overflow-x:auto;scrollbar-width:none}.seg button{border:0;background:none;cursor:pointer;padding:5px 12px;border-radius:6px;font:500 13px var(--ui);color:var(--muted);white-space:nowrap}.seg button[aria-pressed=true]{background:var(--text);color:var(--ink);font-weight:600}.seg select{max-width:22vw;border:0;padding:4px 6px;background:none;color:var(--text);font:600 13px var(--ui)}.seg option{background:var(--ink);color:var(--text)}.icon{flex:none;cursor:pointer;width:36px;height:36px;display:grid;place-items:center;padding:0;border-radius:8px;background:var(--chip);border:1px solid var(--chip-border);color:var(--text)}.icon[aria-pressed=true],.icon[aria-expanded=true]{background:var(--accent);border-color:var(--accent);color:var(--ink)}button:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.speed{height:36px;display:flex;align-items:center;padding:0 2px;border-radius:8px;background:var(--chip);border:1px solid var(--chip-border);color:var(--muted)}.speed button{cursor:pointer;width:28px;height:32px;display:grid;place-items:center;padding:0;border:0;background:none;color:inherit}.speed #speed{width:auto;min-width:46px;font:600 14px var(--num);color:var(--text)}.time{margin-right:6px;font:14px var(--num);color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}.divider{width:1px;height:24px;margin:0 4px;background:var(--chip-border)}.menu{display:contents}#menuButton{display:none}#phrases{position:fixed;left:32px;right:32px;top:74px;height:54px;cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none}#phrases div{position:absolute;bottom:0;min-width:2px;border-radius:2px;background:var(--todo)}#phrases div.done{background:var(--done)}#phraseTime{position:absolute;top:calc(100% + 16px);transform:translate(-50%);padding:2px 7px;border-radius:6px;background:var(--ink);border:1px solid var(--chip-border);font:600 11px var(--num);font-variant-numeric:tabular-nums;color:var(--text);pointer-events:none}#loopBox{position:absolute;top:-6px;bottom:-17px;border:1.5px solid var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--accent) 22%,transparent)}#loopBox:before,#loopBox:after{content:"";position:absolute;top:-11px;bottom:-11px;width:4px;border:4px solid transparent;border-radius:6px;background:var(--accent) padding-box;cursor:ew-resize}#loopBox:before{left:-6.75px}#loopBox:after{right:-6.75px}#progress{position:fixed;left:32px;right:32px;top:134px;height:5px;border-radius:3px;overflow:hidden;background:var(--todo)}#progress div{width:0;height:100%;background:var(--accent);opacity:.9}:root[data-docked] #phrases{top:18px}:root[data-docked] #progress{top:78px}:root[data-docked] #lyrics{top:108px}:root[data-docked] .sheet{top:18px}#lyrics{position:fixed;left:40px;top:164px;max-width:min(560px,46vw);display:flex;flex-direction:column;gap:8px;pointer-events:none;font-family:var(--lyric);font-style:var(--lyric-style);text-shadow:0 2px 14px var(--ink),0 0 4px var(--ink)}#section{min-height:16px;font:600 12px var(--num);letter-spacing:.18em;color:var(--accent)}#lines{position:relative;height:2.45em;font-size:clamp(20px,2.3vw,32px);line-height:1.15}#lines div{position:absolute;top:0;left:0;white-space:nowrap;color:var(--muted);transition:transform .45s cubic-bezier(.22,1,.36,1),opacity .35s ease}#lines .low{transform:translateY(1.3em);opacity:.5}#lines .gone{opacity:0;transition-duration:.45s,.25s}#lines .gone.up{transform:translateY(-.8em)}#lines span{transition:color .15s}#lines .sung{color:var(--text)}@media(prefers-reduced-motion:reduce){#lines div{transition-property:opacity}}#info{position:fixed;left:40px;right:226px;bottom:14px;display:flex;align-items:center;font-size:13px;white-space:nowrap;color:var(--muted);pointer-events:none}#info b{color:var(--text);font-weight:600}#info>span+span:before{content:"";display:inline-block;width:1px;height:12px;margin:0 14px;vertical-align:-1px;background:var(--chip-border)}#info .tuning{position:relative;pointer-events:auto;cursor:help}#info .tuning>b{text-decoration:underline dotted var(--muted);text-underline-offset:3px}#info .tip{left:0;right:auto;white-space:normal}#info .tuning:is(:hover,:focus)>.tip{opacity:1;visibility:visible;transform:none}.pegs{display:flex;align-items:flex-start;gap:4px;margin:10px 0 8px}.peg{display:flex;flex-direction:column;align-items:center;min-width:26px;gap:2px;font:600 13px var(--num)}.peg i{font-style:normal;font-size:11px;color:var(--muted)}.peg .move:before{content:"";display:block;width:3px;height:calc(6px + var(--d) * 3px);margin:2px auto 3px;border-radius:2px;background:var(--c)}.peg strong{color:var(--c)}.peg.same{opacity:.45}.tip small{display:block;font-size:11px}:root:fullscreen .bar{transform:translateY(calc(-100% - 18px));opacity:0;visibility:hidden;transition-delay:.4s}:root:fullscreen:has(#phrases:hover,#progress:hover,.bar:hover) .bar{transform:none;opacity:1;visibility:visible;transition-delay:0s}#tools{position:fixed;z-index:3;right:32px;bottom:6px}#tools .icon{position:relative}.icon:disabled{cursor:default;color:var(--muted)}.icon:disabled svg{opacity:.5}#loopTools{position:fixed;z-index:4;display:flex;transform:translate(-50%,calc(-50% + 3px))}#loopTools .icon{width:32px;height:26px;background:var(--ink);border-color:var(--accent)}#loopTools svg{width:15px;height:15px}#trainer{border-radius:13px 0 0 13px}#clearLoop{border-left:0;border-radius:0 13px 13px 0;color:var(--muted)}#clearLoop:hover{color:var(--text)}#loopTools .icon[aria-pressed=true]{background:var(--accent);color:var(--ink)}.tip{position:absolute;right:0;bottom:calc(100% + 10px);width:max-content;max-width:250px;padding:8px 10px;border-radius:8px;background:var(--ink);border:1px solid var(--chip-border);box-shadow:0 12px 30px #00000073;color:var(--muted);font:12px/1.45 var(--ui);text-align:left;pointer-events:none;opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease,visibility .12s}.tip b{display:flex;justify-content:space-between;gap:12px;margin-bottom:2px;color:var(--text);font-weight:600}.tip kbd{padding:0 5px;border:1px solid var(--chip-border);border-radius:4px;color:var(--muted);font:inherit}:is(.icon,.speed):hover>.tip,.icon:focus-visible>.tip,.speed:focus-within>.tip{opacity:1;visibility:visible;transform:none}:root:where([data-fretfall-dock]){display:flex;align-items:center;gap:10px}.bar :is(.icon,.speed),:root:where([data-fretfall-dock]) :is(.icon,.speed){position:relative}.bar .tip,:root:where([data-fretfall-dock]) .tip{top:calc(100% + 10px);bottom:auto;transform:translateY(-4px)}.bar [aria-expanded=true]>.tip,:root:where([data-fretfall-dock]) [aria-expanded=true]>.tip{display:none}#loopTools .tip{top:calc(100% + 10px);bottom:auto;left:var(--tip, 50%);right:auto;transform:translate(calc(-1 * var(--tip, 50%)),-4px)}#loopTools .icon:hover>.tip,#loopTools .icon:focus-visible>.tip{transform:translate(calc(-1 * var(--tip, 50%)))}:root:fullscreen :is(#info,#tools>:not(#minimal)){display:none}:root.minimal :is(.bar,#phrases,#progress,#loopTools,#info,#tools>:not(#minimal)){display:none}:root.tab2d .only-3d,:root:not(.tab2d) .only-2d{display:none}:root.tab2d .only-3d+.only-3d+h3{padding-top:0;border-top:0}:root.minimal #lyrics{top:24px}#status{position:fixed;left:50%;top:42%;transform:translate(-50%,-50%);display:flex;align-items:center;gap:12px;max-width:min(560px,90vw);padding:10px 16px;border-radius:10px;background:var(--chip);border:1px solid var(--chip-border);backdrop-filter:blur(10px);text-align:center}:root.banding :is(#highway,#phrases,#progress,#loopTools,#lyrics,#info,#intro,#time){display:none}#bandNote{position:fixed;left:50%;top:56%;transform:translate(-50%,-50%);display:grid;justify-items:center;gap:8px;max-width:min(440px,90vw);padding:14px 20px;border-radius:10px;background:var(--chip);border:1px solid var(--chip-border);text-align:center}#bandNote .text-button{justify-self:center}#status:not(.loading) .bars{display:none}.bars{flex:none;display:inline-flex;align-items:flex-end;gap:3px;height:16px}.bars i{width:3px;height:100%;border-radius:2px;background:var(--accent);transform:scaleY(.3);transform-origin:bottom}.bars.moving i{animation:bars .8s ease-in-out infinite alternate}.bars.moving i:nth-child(2){animation-duration:1.1s;animation-delay:-.5s}.bars.moving i:nth-child(3){animation-duration:.7s;animation-delay:-.2s}.bars.moving i:nth-child(4){animation-duration:1s;animation-delay:-.7s}@keyframes bars{0%{transform:scaleY(.2)}to{transform:scaleY(1)}}@media(prefers-reduced-motion:reduce){.bars.moving i{animation:none;transform:scaleY(.6)}}#intro{position:fixed;left:50%;top:36%;transform:translate(-50%,-50%);display:grid;justify-items:center;gap:6px;max-width:min(640px,90vw);padding:22px 30px;border-radius:16px;background:color-mix(in srgb,var(--ink) 72%,transparent);border:1px solid var(--chip-border);text-align:center;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .5s ease,visibility .5s}#intro.show{opacity:1;visibility:visible}#introTitle{font:700 clamp(22px,3vw,38px) / 1.15 var(--num);color:var(--text)}#introFacts{font-size:14px;color:var(--muted)}#introState{display:flex;align-items:center;gap:10px;margin-top:10px;font:600 12px var(--num);letter-spacing:.14em;text-transform:uppercase;color:var(--accent)}.sheet{position:fixed;right:32px;top:66px;z-index:2;width:min(400px,calc(100vw - 32px));max-height:calc(100vh - 118px);display:flex;flex-direction:column;border-radius:14px;overflow:hidden;background:color-mix(in srgb,var(--ink) 94%,transparent);backdrop-filter:blur(18px);border:1px solid var(--chip-border);box-shadow:0 24px 60px #0000008c}.sheet-head{display:flex;align-items:center;justify-content:space-between;padding:12px 12px 10px 18px}.sheet-head h2{margin:0;font:600 15px var(--ui)}.close{width:30px;height:30px;display:grid;place-items:center;padding:0;border:0;border-radius:8px;background:none;color:var(--muted);cursor:pointer}.close:hover{background:var(--chip);color:var(--text)}.tabs{display:grid;grid-template-columns:repeat(5,1fr);gap:2px;margin:0 14px;padding:3px;border-radius:9px;background:var(--chip);border:1px solid var(--chip-border)}.tabs button{padding:6px 0;border:0;border-radius:6px;background:none;font:500 13px var(--ui);color:var(--muted);cursor:pointer}.tabs button:hover{color:var(--text)}.tabs button[aria-selected=true]{background:var(--text);color:var(--ink);font-weight:600}.pane{display:grid;align-content:start;gap:18px;padding:18px 18px 20px;overflow:hidden auto}.pane h3{margin:0 0 -6px;font:600 11px var(--num);letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}.pane h3~h3{padding-top:16px;border-top:1px solid var(--chip-border)}.setting{display:grid;gap:8px}.pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:18px 20px}.setting-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;font-size:13px;font-weight:500}.setting-head output{font:600 12px var(--num);color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}.setting .seg{overflow:visible}.setting .seg button{flex:1}.scale{display:flex;justify-content:space-between;margin-top:-4px;font-size:11px;color:var(--muted)}.hint{margin:-2px 0 0;font-size:12px;line-height:1.4;color:var(--muted)}.text-button{justify-self:start;padding:4px 0;border:0;background:none;font:500 12px var(--ui);color:var(--muted);text-decoration:underline;text-underline-offset:3px;cursor:pointer}.text-button:hover{color:var(--text)}:is(#settings,.volume) input[type=range]{-webkit-appearance:none;appearance:none;height:18px;margin:0;background:none;cursor:pointer}#settings input[type=range]{width:100%}:is(#settings,.volume) input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(90deg,var(--accent) var(--fill, 50%),var(--chip-border) var(--fill, 50%))}:is(#settings,.volume) input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;margin-top:-6px;border-radius:50%;background:var(--text);border:3px solid var(--accent);box-shadow:0 1px 4px #0006}:is(#settings,.volume) input[type=range]::-moz-range-track{height:4px;border-radius:2px;background:var(--chip-border)}:is(#settings,.volume) input[type=range]::-moz-range-progress{height:4px;border-radius:2px;background:var(--accent)}:is(#settings,.volume) input[type=range]::-moz-range-thumb{width:10px;height:10px;border-radius:50%;background:var(--text);border:3px solid var(--accent)}.toggle{display:flex;align-items:center;justify-content:space-between;gap:16px;font-size:13px;font-weight:500;cursor:pointer}.toggle small{display:block;margin-top:2px;font-size:12px;font-weight:400;line-height:1.4;color:var(--muted)}.toggle input{-webkit-appearance:none;appearance:none;flex:none;position:relative;width:36px;height:20px;margin:0;border-radius:10px;background:var(--chip-border);cursor:pointer;transition:background .15s}.toggle input:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--text);transition:transform .15s}.toggle input:checked{background:var(--accent)}.toggle input:checked:after{transform:translate(16px);background:var(--ink)}.cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}.cards.three{grid-template-columns:repeat(3,minmax(0,1fr))}.cards button{display:grid;gap:8px;justify-items:start;padding:10px;border-radius:9px;border:1px solid var(--chip-border);background:var(--chip);font:500 12px var(--ui);color:var(--muted);text-align:left;cursor:pointer}.cards button:hover{color:var(--text)}.cards button[aria-pressed=true]{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);color:var(--text)}.dots{display:flex;gap:4px}.dots i{width:10px;height:10px;border-radius:50%;box-shadow:inset 0 0 0 1px #ffffff2e}.headstock{width:100%;height:52px}.order{font:600 12px var(--num);letter-spacing:.12em;color:var(--text)}#legend{width:min(430px,calc(100vw - 32px))}.legend-find{padding:0 14px 6px}.legend-find input{width:100%;height:34px;padding:0 12px;border-radius:9px;border:1px solid var(--chip-border);background:var(--chip);color:var(--text);font:13px var(--ui)}.legend-find input::placeholder{color:var(--muted)}.legend{gap:4px;padding-top:10px}.legend h3{margin:14px 0 4px}.legend h3:first-child{margin-top:0}.legend-item{display:grid;grid-template-columns:64px 1fr;gap:12px;align-items:center;padding:4px 0}.legend-item b{display:block;font-size:13px;font-weight:500}.legend-item span{display:block;font-size:12px;line-height:1.4;color:var(--muted)}.legend-item .keys{display:flex;justify-content:center;gap:4px}.legend-item kbd{min-width:22px;padding:2px 6px;border:1px solid var(--chip-border);border-bottom-width:2px;border-radius:5px;background:var(--chip);font:600 12px var(--num);text-align:center;white-space:nowrap}.legend-item svg{width:64px;height:36px;border-radius:8px;background:var(--chip);border:1px solid var(--chip-border);fill:none;stroke-linecap:round;stroke-linejoin:round}.legend-item text{font-family:var(--num);font-weight:700;text-anchor:middle;dominant-baseline:central}.legend-empty{margin:8px 0;font-size:13px;color:var(--muted)}.f0{fill:var(--s0)}.f1{fill:var(--s1)}.f2{fill:var(--s2)}.f3{fill:var(--s3)}.f4{fill:var(--s4)}.l0{stroke:var(--s0)}.l1{stroke:var(--s1)}.l2{stroke:var(--s2)}.l3{stroke:var(--s3)}.l4{stroke:var(--s4)}.lm{stroke:var(--muted)}.li{stroke:var(--ink)}.ft{fill:var(--text)}.lt{stroke:var(--text)}.fi{fill:var(--ink)}.fa{fill:var(--accent)}.fl{fill:var(--lane)}.ll{stroke:var(--lane)}.lw{stroke:#fff}.fm{fill:var(--muted)}.la{stroke:var(--accent)}.fw{fill:#fff}.volume{position:relative}.volume .icon.muted{color:var(--muted)}.volume-panel{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;padding:6px 14px 6px 6px;border-radius:10px;background:var(--ink);border:1px solid var(--chip-border);box-shadow:0 12px 30px #00000073}.volume-panel input{width:150px}.volume-panel output{min-width:36px;font:600 12px var(--num);color:var(--muted);text-align:right;font-variant-numeric:tabular-nums}.volume-mute{flex:none;width:30px;height:30px;display:grid;place-items:center;padding:0;border:0;border-radius:7px;background:none;color:var(--text);cursor:pointer}.volume-mute:hover{background:var(--chip)}.volume-mute[aria-pressed=true]{color:var(--muted)}#drop{position:fixed;inset:12px;z-index:5;display:grid;place-items:center;border:2px dashed var(--accent);border-radius:16px;background:#00000073;font:600 20px var(--num)}#tab{position:fixed;left:-10000px;top:0;width:1000px}@media(max-width:900px){.time{display:none}:root:where([data-fretfall-dock]) .time{display:block}#menuButton{display:grid}.volume{position:static}.volume-panel{left:auto;right:0;transform:none}.menu{display:none;position:absolute;top:calc(100% + 8px);right:0;width:230px;flex-direction:column;gap:2px;padding:6px;border-radius:12px;background:var(--ink);border:1px solid var(--chip-border);box-shadow:0 12px 30px #00000073}#menuButton[aria-expanded=true]+.menu{display:flex}.menu .icon{width:100%;height:38px;display:flex;justify-content:flex-start;gap:12px;padding:0 10px;border:0;border-radius:7px;background:none;font:500 13px var(--ui)}.menu .icon:after{content:attr(data-label)}.menu .icon:hover{background:var(--chip)}.menu .icon[aria-pressed=true],.menu .icon[aria-expanded=true]{background:none;color:var(--accent)}.menu .tip{display:none}.menu .divider{width:auto;height:1px;margin:4px}}@media(max-width:560px){.bar{flex-wrap:wrap;height:auto;row-gap:8px}.bar>.group:first-child,.bar>.group:last-child{flex:1 1 100%;height:40px}.speed{margin-left:auto}#menuButton{position:absolute;top:2px;right:0}.menu{top:48px}#phrases{top:122px}#info{flex-direction:column;align-items:flex-start;gap:2px;font-size:12px}#info>span+span:before{display:none}#info>span:first-child{max-width:100%;overflow:hidden;text-overflow:ellipsis}#progress{top:182px}#lyrics{top:212px}.sheet{top:114px;max-height:calc(100vh - 166px)}}@media(max-width:520px){.sheet{right:16px}}</style>
14
+ <style>:root{--bg: #0e1014;--ink: #0e1014;--text: #e8eaef;--muted: #7b8190;--accent: #c8f04a;--chip: #171a20;--chip-border: #2a2f38;--done: #e8eaef;--todo: #23272f;--ui: system-ui, sans-serif;--num: system-ui, sans-serif;--lyric: system-ui, sans-serif;--lyric-style: normal}*{box-sizing:border-box}[hidden]{display:none!important}html,body{height:100%}body{margin:0;overflow:hidden;background:var(--bg);color:var(--text);font:14px/1.4 var(--ui);accent-color:var(--accent)}canvas{position:fixed;inset:0;width:100%;height:100%;display:block}button{font:inherit;color:inherit}.bar{position:fixed;z-index:3;left:32px;right:32px;top:18px;height:40px;display:flex;align-items:center;justify-content:space-between;gap:24px;transition:transform .25s ease,opacity .25s ease,visibility .25s}.group{display:flex;align-items:center;gap:10px;min-width:0}.group:last-child{flex:none}.wordmark{display:flex;align-items:center;gap:7px;font:700 15px var(--num);letter-spacing:.22em}:is(.wordmark,.welcome-mark) .fall{transform-box:fill-box;transform-origin:center;transform:rotate(14deg);animation:fall .75s .8s both}@keyframes fall{0%{transform:translate(-3.5px,-1.42px) rotate(0);animation-timing-function:cubic-bezier(.55,0,.85,.35)}40%{transform:translate(0) rotate(18deg);animation-timing-function:cubic-bezier(.2,.7,.4,1)}56%{transform:translateY(-.35px) rotate(11.5deg);animation-timing-function:ease-in-out}74%{transform:translateY(.08px) rotate(15.2deg);animation-timing-function:ease-in-out}88%{transform:translate(0) rotate(13.6deg);animation-timing-function:ease-in-out}to{transform:translate(0) rotate(14deg)}}@media(prefers-reduced-motion:reduce){.wordmark .fall{animation:none}}.seg{display:flex;gap:2px;padding:3px;border-radius:9px;background:var(--chip);border:1px solid var(--chip-border);overflow-x:auto;scrollbar-width:none}.seg button{border:0;background:none;cursor:pointer;padding:5px 12px;border-radius:6px;font:500 13px var(--ui);color:var(--muted);white-space:nowrap}.seg button[aria-pressed=true]{background:var(--text);color:var(--ink);font-weight:600}.seg select{max-width:22vw;border:0;padding:4px 6px;background:none;color:var(--text);font:600 13px var(--ui)}.seg option{background:var(--ink);color:var(--text)}.icon{flex:none;cursor:pointer;width:36px;height:36px;display:grid;place-items:center;padding:0;border-radius:8px;background:var(--chip);border:1px solid var(--chip-border);color:var(--text)}.icon[aria-pressed=true],.icon[aria-expanded=true]{background:var(--accent);border-color:var(--accent);color:var(--ink)}button:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.speed{height:36px;display:flex;align-items:center;padding:0 2px;border-radius:8px;background:var(--chip);border:1px solid var(--chip-border);color:var(--muted)}.speed button{cursor:pointer;width:28px;height:32px;display:grid;place-items:center;padding:0;border:0;background:none;color:inherit}.speed #speed{width:auto;min-width:46px;font:600 14px var(--num);color:var(--text)}.time{margin-right:6px;font:14px var(--num);color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}.divider{width:1px;height:24px;margin:0 4px;background:var(--chip-border)}.menu{display:contents}#menuButton{display:none}#phrases{position:fixed;left:32px;right:32px;top:74px;height:54px;cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none}#phrases div{position:absolute;bottom:0;min-width:2px;border-radius:2px;background:var(--todo)}#phrases div.done{background:var(--done)}#phraseTime{position:absolute;top:calc(100% + 16px);transform:translate(-50%);padding:2px 7px;border-radius:6px;background:var(--ink);border:1px solid var(--chip-border);font:600 11px var(--num);font-variant-numeric:tabular-nums;color:var(--text);pointer-events:none}#loopBox{position:absolute;top:-6px;bottom:-17px;border:1.5px solid var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--accent) 22%,transparent)}#loopBox:before,#loopBox:after{content:"";position:absolute;top:-11px;bottom:-11px;width:4px;border:4px solid transparent;border-radius:6px;background:var(--accent) padding-box;cursor:ew-resize}#loopBox:before{left:-6.75px}#loopBox:after{right:-6.75px}#progress{position:fixed;left:32px;right:32px;top:134px;height:5px;border-radius:3px;overflow:hidden;background:var(--todo)}#progress div{width:0;height:100%;background:var(--accent);opacity:.9}:root[data-docked] #phrases{top:18px}:root[data-docked] #progress{top:78px}:root[data-docked] #lyrics{top:108px}:root[data-docked] .sheet{top:18px}#lyrics{position:fixed;left:40px;top:164px;max-width:min(560px,46vw);display:flex;flex-direction:column;gap:8px;pointer-events:none;font-family:var(--lyric);font-style:var(--lyric-style);text-shadow:0 2px 14px var(--ink),0 0 4px var(--ink)}#section{min-height:16px;font:600 12px var(--num);letter-spacing:.18em;color:var(--accent)}#lines{position:relative;height:2.45em;font-size:clamp(20px,2.3vw,32px);line-height:1.15}#lines div{position:absolute;top:0;left:0;white-space:nowrap;color:var(--muted);transition:transform .45s cubic-bezier(.22,1,.36,1),opacity .35s ease}#lines .low{transform:translateY(1.3em);opacity:.5}#lines .gone{opacity:0;transition-duration:.45s,.25s}#lines .gone.up{transform:translateY(-.8em)}#lines span{transition:color .15s}#lines .sung{color:var(--text)}@media(prefers-reduced-motion:reduce){#lines div{transition-property:opacity}}#info{position:fixed;left:40px;right:226px;bottom:14px;display:flex;align-items:center;font-size:13px;white-space:nowrap;color:var(--muted);pointer-events:none}#info b{color:var(--text);font-weight:600}#info>span+span:before{content:"";display:inline-block;width:1px;height:12px;margin:0 14px;vertical-align:-1px;background:var(--chip-border)}#info .tuning{position:relative;pointer-events:auto;cursor:help}#info .tuning>b{text-decoration:underline dotted var(--muted);text-underline-offset:3px}#info .tip{left:0;right:auto;white-space:normal}#info .tuning:is(:hover,:focus)>.tip{opacity:1;visibility:visible;transform:none}.pegs{display:flex;align-items:flex-start;gap:4px;margin:10px 0 8px}.peg{display:flex;flex-direction:column;align-items:center;min-width:26px;gap:2px;font:600 13px var(--num)}.peg i{font-style:normal;font-size:11px;color:var(--muted)}.peg .move:before{content:"";display:block;width:3px;height:calc(6px + var(--d) * 3px);margin:2px auto 3px;border-radius:2px;background:var(--c)}.peg strong{color:var(--c)}.peg.same{opacity:.45}.tip small{display:block;font-size:11px}:root:fullscreen .bar{transform:translateY(calc(-100% - 18px));opacity:0;visibility:hidden;transition-delay:.4s}:root:fullscreen:has(#phrases:hover,#progress:hover,.bar:hover) .bar{transform:none;opacity:1;visibility:visible;transition-delay:0s}.seg.views{margin-left:4px}.seg.views button{padding:5px 11px;font-size:12px}.icon:disabled{cursor:default;color:var(--muted)}.icon:disabled svg{opacity:.5}#loopTools{position:fixed;z-index:4;display:flex;transform:translate(-50%,calc(-50% + 3px))}#loopTools .icon{width:32px;height:26px;background:var(--ink);border-color:var(--accent)}#loopTools svg{width:15px;height:15px}#trainer{border-radius:13px 0 0 13px}#clearLoop{border-left:0;border-radius:0 13px 13px 0;color:var(--muted)}#clearLoop:hover{color:var(--text)}#loopTools .icon[aria-pressed=true]{background:var(--accent);color:var(--ink)}.tip{position:absolute;right:0;bottom:calc(100% + 10px);width:max-content;max-width:250px;padding:8px 10px;border-radius:8px;background:var(--ink);border:1px solid var(--chip-border);box-shadow:0 12px 30px #00000073;color:var(--muted);font:12px/1.45 var(--ui);text-align:left;pointer-events:none;opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease,visibility .12s}.tip b{display:flex;justify-content:space-between;gap:12px;margin-bottom:2px;color:var(--text);font-weight:600}.tip kbd{padding:0 5px;border:1px solid var(--chip-border);border-radius:4px;color:var(--muted);font:inherit}:is(.icon,.speed):hover>.tip,.icon:focus-visible>.tip,.speed:focus-within>.tip{opacity:1;visibility:visible;transform:none}:root:where([data-fretfall-dock]){display:flex;align-items:center;gap:10px}.bar :is(.icon,.speed),:root:where([data-fretfall-dock]) :is(.icon,.speed){position:relative}.bar .tip,:root:where([data-fretfall-dock]) .tip{top:calc(100% + 10px);bottom:auto;transform:translateY(-4px)}.bar [aria-expanded=true]>.tip,:root:where([data-fretfall-dock]) [aria-expanded=true]>.tip{display:none}#loopTools .tip{top:calc(100% + 10px);bottom:auto;left:var(--tip, 50%);right:auto;transform:translate(calc(-1 * var(--tip, 50%)),-4px)}#loopTools .icon:hover>.tip,#loopTools .icon:focus-visible>.tip{transform:translate(calc(-1 * var(--tip, 50%)))}:root:fullscreen #info{display:none}:root.minimal :is(.bar>:not(#minimalBack),#phrases,#progress,#loopTools,#info){display:none}:root.minimal .bar{background:none;border:0;box-shadow:none;pointer-events:none}:root.minimal #minimalBack{display:inline-flex;pointer-events:auto;margin-left:auto}#minimalBack{display:none}:root.tab2d .only-3d,:root:not(.tab2d) .only-2d{display:none}:root.tab2d .only-3d+.only-3d+h3{padding-top:0;border-top:0}:root.notation .not-notation,:root:not(.notation) .only-notation{display:none}:root.minimal #lyrics{top:24px}#status{position:fixed;left:50%;top:42%;transform:translate(-50%,-50%);display:flex;align-items:center;gap:12px;max-width:min(560px,90vw);padding:10px 16px;border-radius:10px;background:var(--chip);border:1px solid var(--chip-border);backdrop-filter:blur(10px);text-align:center}:root.banding :is(#highway,#phrases,#progress,#loopTools,#lyrics,#info,#intro,#time){display:none}#bandNote{position:fixed;left:50%;top:56%;transform:translate(-50%,-50%);display:grid;justify-items:center;gap:8px;max-width:min(440px,90vw);padding:14px 20px;border-radius:10px;background:var(--chip);border:1px solid var(--chip-border);text-align:center}#bandNote .text-button{justify-self:center}#status:not(.loading) .bars{display:none}.bars{flex:none;display:inline-flex;align-items:flex-end;gap:3px;height:16px}.bars i{width:3px;height:100%;border-radius:2px;background:var(--accent);transform:scaleY(.3);transform-origin:bottom}.bars.moving i{animation:bars .8s ease-in-out infinite alternate}.bars.moving i:nth-child(2){animation-duration:1.1s;animation-delay:-.5s}.bars.moving i:nth-child(3){animation-duration:.7s;animation-delay:-.2s}.bars.moving i:nth-child(4){animation-duration:1s;animation-delay:-.7s}@keyframes bars{0%{transform:scaleY(.2)}to{transform:scaleY(1)}}@media(prefers-reduced-motion:reduce){.bars.moving i{animation:none;transform:scaleY(.6)}}#intro{position:fixed;left:50%;top:36%;transform:translate(-50%,-50%);display:grid;justify-items:center;gap:6px;max-width:min(640px,90vw);padding:22px 30px;border-radius:16px;background:color-mix(in srgb,var(--ink) 72%,transparent);border:1px solid var(--chip-border);text-align:center;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .5s ease,visibility .5s}#intro.show{opacity:1;visibility:visible}#introTitle{font:700 clamp(22px,3vw,38px) / 1.15 var(--num);color:var(--text)}#introFacts{font-size:14px;color:var(--muted)}#introState{display:flex;align-items:center;gap:10px;margin-top:10px;font:600 12px var(--num);letter-spacing:.14em;text-transform:uppercase;color:var(--accent)}.sheet{position:fixed;right:32px;top:66px;z-index:2;width:min(400px,calc(100vw - 32px));max-height:calc(100vh - 118px);display:flex;flex-direction:column;border-radius:14px;overflow:hidden;background:color-mix(in srgb,var(--ink) 94%,transparent);backdrop-filter:blur(18px);border:1px solid var(--chip-border);box-shadow:0 24px 60px #0000008c}.sheet-head{display:flex;align-items:center;justify-content:space-between;padding:12px 12px 10px 18px}.sheet-head h2{margin:0;font:600 15px var(--ui)}.close{width:30px;height:30px;display:grid;place-items:center;padding:0;border:0;border-radius:8px;background:none;color:var(--muted);cursor:pointer}.close:hover{background:var(--chip);color:var(--text)}.tabs{display:grid;grid-template-columns:repeat(5,1fr);gap:2px;margin:0 14px;padding:3px;border-radius:9px;background:var(--chip);border:1px solid var(--chip-border)}.tabs button{padding:6px 0;border:0;border-radius:6px;background:none;font:500 13px var(--ui);color:var(--muted);cursor:pointer}.tabs button:hover{color:var(--text)}.tabs button[aria-selected=true]{background:var(--text);color:var(--ink);font-weight:600}.pane{display:grid;align-content:start;gap:18px;padding:18px 18px 20px;overflow:hidden auto}.pane h3{margin:0 0 -6px;font:600 11px var(--num);letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}.pane h3~h3{padding-top:16px;border-top:1px solid var(--chip-border)}.setting{display:grid;gap:8px}.pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:18px 20px}.setting-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;font-size:13px;font-weight:500}.setting-head output{font:600 12px var(--num);color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}.setting .seg{overflow:visible}.setting .seg button{flex:1}.scale{display:flex;justify-content:space-between;margin-top:-4px;font-size:11px;color:var(--muted)}.hint{margin:-2px 0 0;font-size:12px;line-height:1.4;color:var(--muted)}.text-button{justify-self:start;padding:4px 0;border:0;background:none;font:500 12px var(--ui);color:var(--muted);text-decoration:underline;text-underline-offset:3px;cursor:pointer}.text-button:hover{color:var(--text)}:is(#settings,.volume) input[type=range]{-webkit-appearance:none;appearance:none;height:18px;margin:0;background:none;cursor:pointer}#settings input[type=range]{width:100%}:is(#settings,.volume) input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(90deg,var(--accent) var(--fill, 50%),var(--chip-border) var(--fill, 50%))}:is(#settings,.volume) input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;margin-top:-6px;border-radius:50%;background:var(--text);border:3px solid var(--accent);box-shadow:0 1px 4px #0006}:is(#settings,.volume) input[type=range]::-moz-range-track{height:4px;border-radius:2px;background:var(--chip-border)}:is(#settings,.volume) input[type=range]::-moz-range-progress{height:4px;border-radius:2px;background:var(--accent)}:is(#settings,.volume) input[type=range]::-moz-range-thumb{width:10px;height:10px;border-radius:50%;background:var(--text);border:3px solid var(--accent)}.toggle{display:flex;align-items:center;justify-content:space-between;gap:16px;font-size:13px;font-weight:500;cursor:pointer}.toggle small{display:block;margin-top:2px;font-size:12px;font-weight:400;line-height:1.4;color:var(--muted)}.toggle input{-webkit-appearance:none;appearance:none;flex:none;position:relative;width:36px;height:20px;margin:0;border-radius:10px;background:var(--chip-border);cursor:pointer;transition:background .15s}.toggle input:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--text);transition:transform .15s}.toggle input:checked{background:var(--accent)}.toggle input:checked:after{transform:translate(16px);background:var(--ink)}.cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}.cards.three{grid-template-columns:repeat(3,minmax(0,1fr))}.cards button{display:grid;gap:8px;justify-items:start;padding:10px;border-radius:9px;border:1px solid var(--chip-border);background:var(--chip);font:500 12px var(--ui);color:var(--muted);text-align:left;cursor:pointer}.cards button:hover{color:var(--text)}.cards button[aria-pressed=true]{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);color:var(--text)}.dots{display:flex;gap:4px}.dots i{width:10px;height:10px;border-radius:50%;box-shadow:inset 0 0 0 1px #ffffff2e}.headstock{width:100%;height:52px}.order{font:600 12px var(--num);letter-spacing:.12em;color:var(--text)}#legend{width:min(430px,calc(100vw - 32px))}.legend-find{padding:0 14px 6px}.legend-find input{width:100%;height:34px;padding:0 12px;border-radius:9px;border:1px solid var(--chip-border);background:var(--chip);color:var(--text);font:13px var(--ui)}.legend-find input::placeholder{color:var(--muted)}.legend{gap:4px;padding-top:10px}.legend h3{margin:14px 0 4px}.legend h3:first-child{margin-top:0}.legend-item{display:grid;grid-template-columns:64px 1fr;gap:12px;align-items:center;padding:4px 0}.legend-item b{display:block;font-size:13px;font-weight:500}.legend-item span{display:block;font-size:12px;line-height:1.4;color:var(--muted)}.legend-item .keys{display:flex;justify-content:center;gap:4px}.legend-item kbd{min-width:22px;padding:2px 6px;border:1px solid var(--chip-border);border-bottom-width:2px;border-radius:5px;background:var(--chip);font:600 12px var(--num);text-align:center;white-space:nowrap}.legend-item svg{width:64px;height:36px;border-radius:8px;background:var(--chip);border:1px solid var(--chip-border);fill:none;stroke-linecap:round;stroke-linejoin:round}.legend-item text{font-family:var(--num);font-weight:700;text-anchor:middle;dominant-baseline:central}.legend-empty{margin:8px 0;font-size:13px;color:var(--muted)}.f0{fill:var(--s0)}.f1{fill:var(--s1)}.f2{fill:var(--s2)}.f3{fill:var(--s3)}.f4{fill:var(--s4)}.l0{stroke:var(--s0)}.l1{stroke:var(--s1)}.l2{stroke:var(--s2)}.l3{stroke:var(--s3)}.l4{stroke:var(--s4)}.lm{stroke:var(--muted)}.li{stroke:var(--ink)}.ft{fill:var(--text)}.lt{stroke:var(--text)}.fi{fill:var(--ink)}.fa{fill:var(--accent)}.fl{fill:var(--lane)}.ll{stroke:var(--lane)}.lw{stroke:#fff}.fm{fill:var(--muted)}.la{stroke:var(--accent)}.fw{fill:#fff}.volume{position:relative}.volume .icon.muted{color:var(--muted)}.volume-panel{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;padding:6px 14px 6px 6px;border-radius:10px;background:var(--ink);border:1px solid var(--chip-border);box-shadow:0 12px 30px #00000073}.volume-panel input{width:150px}.volume-panel output{min-width:36px;font:600 12px var(--num);color:var(--muted);text-align:right;font-variant-numeric:tabular-nums}.volume-mute{flex:none;width:30px;height:30px;display:grid;place-items:center;padding:0;border:0;border-radius:7px;background:none;color:var(--text);cursor:pointer}.volume-mute:hover{background:var(--chip)}.volume-mute[aria-pressed=true]{color:var(--muted)}#drop{position:fixed;inset:12px;z-index:5;display:grid;place-items:center;border:2px dashed var(--accent);border-radius:16px;background:#00000073;font:600 20px var(--num)}#tab{position:fixed;left:-10000px;top:0;width:1000px}@media(max-width:900px){.time{display:none}:root:where([data-fretfall-dock]) .time{display:block}#menuButton{display:grid}.volume{position:static}.volume-panel{left:auto;right:0;transform:none}.menu{display:none;position:absolute;top:calc(100% + 8px);right:0;width:230px;flex-direction:column;gap:2px;padding:6px;border-radius:12px;background:var(--ink);border:1px solid var(--chip-border);box-shadow:0 12px 30px #00000073}#menuButton[aria-expanded=true]+.menu{display:flex}.menu .icon{width:100%;height:38px;display:flex;justify-content:flex-start;gap:12px;padding:0 10px;border:0;border-radius:7px;background:none;font:500 13px var(--ui)}.menu .icon:after{content:attr(data-label)}.menu .icon:hover{background:var(--chip)}.menu .icon[aria-pressed=true],.menu .icon[aria-expanded=true]{background:none;color:var(--accent)}.menu .tip{display:none}.menu .divider{width:auto;height:1px;margin:4px}}@media(max-width:560px){.bar{flex-wrap:wrap;height:auto;row-gap:8px}.bar>.group:first-child,.bar>.group:last-child{flex:1 1 100%;height:40px}.speed{margin-left:auto}#menuButton{position:absolute;top:2px;right:0}.menu{top:48px}#phrases{top:122px}#info{flex-direction:column;align-items:flex-start;gap:2px;font-size:12px}#info>span+span:before{display:none}#info>span:first-child{max-width:100%;overflow:hidden;text-overflow:ellipsis}#progress{top:182px}#lyrics{top:212px}.sheet{top:114px;max-height:calc(100vh - 166px)}}@media(max-width:520px){.sheet{right:16px}}</style>
15
15
  <link rel="modulepreload" href="player.js">
16
16
  <link rel="modulepreload" href="fingering.js">
17
17
  <link rel="modulepreload" href="highway.js">
@@ -51,6 +51,16 @@ id="arrangements"
51
51
  role="group"
52
52
  aria-label="Arrangement"
53
53
  ></div>
54
+ <div
55
+ class="seg views"
56
+ id="view"
57
+ role="group"
58
+ aria-label="View"
59
+ >
60
+ <button value="highway" aria-pressed="true">Highway</button>
61
+ <button value="tablature" aria-pressed="false">Tablature</button>
62
+ <button value="notation" aria-pressed="false">Notation</button>
63
+ </div>
54
64
  </div>
55
65
  <div class="group">
56
66
  <span class="time" id="time">0:00 / 0:00</span>
@@ -133,6 +143,14 @@ aria-label="Volume"
133
143
  </div>
134
144
  <button
135
145
  class="icon"
146
+ id="minimalBack"
147
+ aria-label="Back from the minimal view"
148
+ title="Back from the minimal view (H)"
149
+ >
150
+ <svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10s2.5-4.5 7-4.5 7 4.5 7 4.5-2.5 4.5-7 4.5-7-4.5-7-4.5z"/><circle cx="10" cy="10" r="2"/></svg>
151
+ </button>
152
+ <button
153
+ class="icon"
136
154
  id="menuButton"
137
155
  aria-expanded="false"
138
156
  aria-controls="menu"
@@ -219,6 +237,93 @@ can also drop them anywhere</span
219
237
  <div class="divider"></div>
220
238
  <button
221
239
  class="icon"
240
+ id="metronome"
241
+ data-label="Metronome"
242
+ aria-pressed="false"
243
+ aria-label="Metronome"
244
+ aria-describedby="metronomeTip"
245
+ >
246
+ <svg
247
+ width="18"
248
+ height="18"
249
+ viewBox="0 0 20 20"
250
+ fill="none"
251
+ stroke="currentColor"
252
+ stroke-width="1.6"
253
+ stroke-linecap="round"
254
+ stroke-linejoin="round"
255
+ >
256
+ <path d="M7.8 3h4.4l3.3 13.5h-11z" />
257
+ <path d="M5.6 12.5h8.8M10 12.5l4-7" />
258
+ </svg>
259
+ <span class="tip" role="tooltip" id="metronomeTip"
260
+ ><b>Metronome <kbd>K</kbd></b
261
+ >A click on every beat, higher on the first of each
262
+ bar</span
263
+ >
264
+ </button>
265
+ <button
266
+ class="icon"
267
+ id="band"
268
+ data-label="Play as a band"
269
+ aria-label="Play as a band"
270
+ aria-describedby="bandTip"
271
+ disabled
272
+ >
273
+ <svg
274
+ width="18"
275
+ height="18"
276
+ viewBox="0 0 20 20"
277
+ fill="none"
278
+ stroke="currentColor"
279
+ stroke-width="1.6"
280
+ stroke-linecap="round"
281
+ stroke-linejoin="round"
282
+ >
283
+ <circle cx="7.5" cy="7" r="2.5" />
284
+ <path d="M3 16.5a4.5 4.5 0 0 1 9 0" />
285
+ <circle cx="13.8" cy="7.5" r="2" />
286
+ <path d="M13.5 12.2a3.8 3.8 0 0 1 4 4.3" />
287
+ </svg>
288
+ <span class="tip" role="tooltip" id="bandTip"
289
+ ><b>Play as a band</b>Opens every part in a window of its
290
+ own, side by side, all in time. Play, pause, jump and loop
291
+ from any of them; the sound comes from this window, which
292
+ stays open behind them</span
293
+ >
294
+ </button>
295
+ <button
296
+ class="icon"
297
+ id="minimal"
298
+ data-label="Minimal view"
299
+ aria-pressed="false"
300
+ aria-label="Minimal view"
301
+ aria-describedby="minimalTip"
302
+ >
303
+ <svg
304
+ width="18"
305
+ height="18"
306
+ viewBox="0 0 20 20"
307
+ fill="none"
308
+ stroke="currentColor"
309
+ stroke-width="1.6"
310
+ stroke-linecap="round"
311
+ stroke-linejoin="round"
312
+ >
313
+ <path
314
+ d="M2.5 10s2.8-5 7.5-5 7.5 5 7.5 5-2.8 5-7.5 5-7.5-5-7.5-5z"
315
+ />
316
+ <circle cx="10" cy="10" r="2.2" />
317
+ </svg>
318
+ <span class="tip" role="tooltip" id="minimalTip"
319
+ ><b>Minimal view <kbd>H</kbd></b
320
+ >Just the highway and the lyrics: the header, phrase bars
321
+ and song info make way. Press again to bring them back</span
322
+ >
323
+ </button>
324
+ <div class="divider"></div>
325
+ <button
326
+ class="icon"
222
327
  id="legendButton"
223
328
  data-label="Notation and shortcuts"
224
329
  aria-expanded="false"
@@ -355,117 +460,6 @@ stroke-linecap="round"
355
460
  <div id="lines"></div>
356
461
  </div>
357
462
  <div id="info"></div>
358
- <div id="tools" class="group" role="group" aria-label="Practice tools">
359
- <button
360
- class="icon"
361
- id="metronome"
362
- aria-pressed="false"
363
- aria-label="Metronome"
364
- aria-describedby="metronomeTip"
365
- >
366
- <svg
367
- width="18"
368
- height="18"
369
- viewBox="0 0 20 20"
370
- fill="none"
371
- stroke="currentColor"
372
- stroke-width="1.6"
373
- stroke-linecap="round"
374
- stroke-linejoin="round"
375
- >
376
- <path d="M7.8 3h4.4l3.3 13.5h-11z" />
377
- <path d="M5.6 12.5h8.8M10 12.5l4-7" />
378
- </svg>
379
- <span class="tip" role="tooltip" id="metronomeTip"
380
- ><b>Metronome <kbd>K</kbd></b
381
- >A click on every beat, higher on the first of each
382
- bar</span
383
- >
384
- </button>
385
- <button
386
- class="icon"
387
- id="band"
388
- aria-label="Play as a band"
389
- aria-describedby="bandTip"
390
- disabled
391
- >
392
- <svg
393
- width="18"
394
- height="18"
395
- viewBox="0 0 20 20"
396
- fill="none"
397
- stroke="currentColor"
398
- stroke-width="1.6"
399
- stroke-linecap="round"
400
- stroke-linejoin="round"
401
- >
402
- <circle cx="7.5" cy="7" r="2.5" />
403
- <path d="M3 16.5a4.5 4.5 0 0 1 9 0" />
404
- <circle cx="13.8" cy="7.5" r="2" />
405
- <path d="M13.5 12.2a3.8 3.8 0 0 1 4 4.3" />
406
- </svg>
407
- <span class="tip" role="tooltip" id="bandTip"
408
- ><b>Play as a band</b>Opens every part in a window of its
409
- own, side by side, all in time. Play, pause, jump and loop
410
- from any of them; the sound comes from this window, which
411
- stays open behind them</span
412
- >
413
- </button>
414
- <button
415
- class="icon"
416
- id="tabView"
417
- aria-pressed="false"
418
- aria-label="2D tab view"
419
- aria-describedby="tabViewTip"
420
- >
421
- <svg
422
- width="18"
423
- height="18"
424
- viewBox="0 0 20 20"
425
- fill="none"
426
- stroke="currentColor"
427
- stroke-width="1.6"
428
- stroke-linecap="round"
429
- >
430
- <path d="M2.5 5h15M2.5 10h15M2.5 15h15" />
431
- <path d="M7 3v14" stroke-width="2.2" />
432
- </svg>
433
- <span class="tip" role="tooltip" id="tabViewTip"
434
- ><b>2D tab view <kbd>D</kbd></b
435
- >The notes as tab: fret numbers on flat strings, coming in
436
- from the right to the play line. Press again for the 3D
437
- highway</span
438
- >
439
- </button>
440
- <button
441
- class="icon"
442
- id="minimal"
443
- aria-pressed="false"
444
- aria-label="Minimal view"
445
- aria-describedby="minimalTip"
446
- >
447
- <svg
448
- width="18"
449
- height="18"
450
- viewBox="0 0 20 20"
451
- fill="none"
452
- stroke="currentColor"
453
- stroke-width="1.6"
454
- stroke-linecap="round"
455
- stroke-linejoin="round"
456
- >
457
- <path
458
- d="M2.5 10s2.8-5 7.5-5 7.5 5 7.5 5-2.8 5-7.5 5-7.5-5-7.5-5z"
459
- />
460
- <circle cx="10" cy="10" r="2.2" />
461
- </svg>
462
- <span class="tip" role="tooltip" id="minimalTip"
463
- ><b>Minimal view <kbd>H</kbd></b
464
- >Just the highway and the lyrics: the header, phrase bars
465
- and song info make way. Press again to bring them back</span
466
- >
467
- </button>
468
- </div>
469
463
  <div
470
464
  id="settings"
471
465
  class="sheet"
@@ -625,8 +619,8 @@ step="0.05"
625
619
  </div>
626
620
  </div>
627
621
  </div>
628
- <h3>Notes</h3>
629
- <div class="pair">
622
+ <h3 class="not-notation">Notes</h3>
623
+ <div class="pair not-notation">
630
624
  <div class="setting">
631
625
  <div class="setting-head">
632
626
  <label for="noteSpeed">Note speed</label
@@ -678,11 +672,11 @@ aria-labelledby="tab-highway"
678
672
  hidden
679
673
  >
680
674
  <div
681
- class="setting only-2d"
675
+ class="setting only-2d not-notation"
682
676
  title="Notes scrolling in to the play line, or a page of bars that holds still while the play line moves across it"
683
677
  >
684
678
  <div class="setting-head">
685
- <span id="tabLayoutLabel">Tab</span>
679
+ <span id="tabLayoutLabel">Tablature</span>
686
680
  </div>
687
681
  <div
688
682
  class="seg"
@@ -691,7 +685,63 @@ role="group"
691
685
  aria-labelledby="tabLayoutLabel"
692
686
  ></div>
693
687
  </div>
694
- <div class="setting">
688
+ <div
689
+ class="setting only-notation"
690
+ title="The page the notation is written on: the theme's dark card, or white paper"
691
+ >
692
+ <div class="setting-head">
693
+ <span id="paperLabel">Paper</span>
694
+ </div>
695
+ <div
696
+ class="seg"
697
+ data-setting="paper"
698
+ role="group"
699
+ aria-labelledby="paperLabel"
700
+ ></div>
701
+ </div>
702
+ <label class="toggle only-notation"
703
+ ><span
704
+ >Beat highlight<small
705
+ >The beat being played, filled across the system</small
706
+ ></span
707
+ ><input id="beatBox" type="checkbox" role="switch"
708
+ /></label>
709
+ <label class="toggle only-notation"
710
+ ><span
711
+ >Notes<small
712
+ >The notes on a staff over each system, as guitar music is written</small
713
+ ></span
714
+ ><input id="sheetNotes" type="checkbox" role="switch"
715
+ /></label>
716
+ <div
717
+ class="setting only-notation"
718
+ title="Whether the page turns with the beat, keeping the system being played second from the top, or only when you scroll it"
719
+ >
720
+ <div class="setting-head">
721
+ <span id="sheetScrollLabel">Scroll</span>
722
+ </div>
723
+ <div
724
+ class="seg"
725
+ data-setting="sheetScroll"
726
+ role="group"
727
+ aria-labelledby="sheetScrollLabel"
728
+ ></div>
729
+ </div>
730
+ <div
731
+ class="setting only-2d"
732
+ title="What is written around a note: the finger to press with, and the techniques, chord names and hand positions over and under the staff"
733
+ >
734
+ <div class="setting-head">
735
+ <span id="tabMarksLabel">Marks</span>
736
+ </div>
737
+ <div
738
+ class="seg"
739
+ data-setting="tabMarks"
740
+ role="group"
741
+ aria-labelledby="tabMarksLabel"
742
+ ></div>
743
+ </div>
744
+ <div class="setting not-notation">
695
745
  <div class="setting-head">
696
746
  <span id="lookLabel">Notes</span>
697
747
  </div>
@@ -770,8 +820,8 @@ step="0.05"
770
820
  </div>
771
821
  </div>
772
822
  <div
773
- class="setting"
774
- title="The mute crosses and finger numbers on the notes"
823
+ class="setting not-notation"
824
+ title="The finger numbers on a note, and the fret numbers in the tab. The mutes' crosses are white either way"
775
825
  >
776
826
  <div class="setting-head">
777
827
  <span id="markingsLabel">Markings on notes</span>
@@ -783,7 +833,7 @@ role="group"
783
833
  aria-labelledby="markingsLabel"
784
834
  ></div>
785
835
  </div>
786
- <label class="toggle"
836
+ <label class="toggle not-notation"
787
837
  ><span
788
838
  >Hand position guides<small
789
839
  >Where your hand goes: a band down the highway, or
package/mount.d.ts CHANGED
@@ -36,10 +36,45 @@ export interface Fretfall {
36
36
  * it sounds. A copy, made on each read: read it once a song, not each frame.
37
37
  */
38
38
  readonly notes: { open: number[]; notes: { time: number; sustain: number; string: number; fret: number; midi: number }[] } | null;
39
+ /**
40
+ * The open song's own nudge in milliseconds, on top of the player's alignment of a recording and its Audio delay
41
+ * setting (the device's): positive makes the notes arrive later. Settable once the song is open; a new song starts at 0.
42
+ * It moves the song's clock: `time`, seeks and the loop go by it.
43
+ */
44
+ offset: number;
45
+ /**
46
+ * Sets `offset` so the tab's first note lands on its attack in the recording, and returns it; `null` without a
47
+ * recording the player lined up itself. Near where the player's fit puts that note when the fit is sure; else the
48
+ * recording's first loud sound, which a count-in can be: a starting point to nudge from.
49
+ */
50
+ snap(): number | null;
39
51
  /** The names of the song's parts. */
40
52
  readonly parts: string[];
41
53
  /** The part shown, -1 without one. Settable. */
42
54
  part: number;
55
+ /** How loud, 0 to 1. Settable; a volume of 0 is muted, and setting one asks for sound again. */
56
+ volume: number;
57
+ /** The mute, which a volume of 0 also turns on. Settable. */
58
+ muted: boolean;
59
+ /** What is looping, in seconds, or null. Settable: kept inside the song, and anything else clears it. */
60
+ loop: { start: number; end: number } | null;
61
+ /** The click on the chart's beats. Settable. */
62
+ metronome: boolean;
63
+ /** What the notes are drawn as: the 3D highway, the tablature, or the notation page. Settable. */
64
+ view: 'highway' | 'tablature' | 'notation';
65
+ /** The view alone with the lyrics, the bar and the phrases hidden. Settable. */
66
+ minimal: boolean;
67
+ /** Opens every other part in a window of its own, all in time. Nothing in a window that is itself following. */
68
+ band(): void;
69
+ /** Which sheet is open, or null. Settable. */
70
+ sheet: 'settings' | 'legend' | null;
71
+ /** Settable — set it from your own button's click, as browsers want a gesture behind it. */
72
+ fullscreen: boolean;
73
+ /**
74
+ * Everything a control toggles, in one object, for a bar of the page's own to draw itself from. `fretfall:controls`
75
+ * fires whenever any of it changes, whoever changed it — the page's buttons or the player's own.
76
+ */
77
+ readonly controls: FretfallControls;
43
78
  addFormat(format: FretfallFormat<any>): void;
44
79
  /** Close Settings and the notation sheet. */
45
80
  closeSheets(): void;
@@ -52,6 +87,21 @@ export interface Fretfall {
52
87
  dock(element: HTMLElement | null, more?: HTMLElement): void;
53
88
  }
54
89
 
90
+ export interface FretfallControls {
91
+ playing: boolean;
92
+ speed: number;
93
+ volume: number;
94
+ muted: boolean;
95
+ loop: { start: number; end: number } | null;
96
+ metronome: boolean;
97
+ parts: string[];
98
+ part: number;
99
+ sheet: 'settings' | 'legend' | null;
100
+ fullscreen: boolean;
101
+ view: 'highway' | 'tablature' | 'notation';
102
+ minimal: boolean;
103
+ }
104
+
55
105
  export interface FretfallSong {
56
106
  /** The file's name; null for a band window's song. */
57
107
  file: string | null;