<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>Guitar neck diagram</title>
<style>
:root {
–tp: #1a1a18; –ts: #5f5e5a; –tt: #888780;
–bg: #ffffff; –bg2: #f5f4f0;
–border: rgba(0,0,0,0.10);
–font: system-ui,-apple-system,sans-serif;
–tf: #E1F5EE; –ts2: #0F6E56; –tt2: #085041;
–cf: #FAECE7; –cs: #993C1D; –ct: #712B13;
}
@media (prefers-color-scheme:dark) {
:root {
–tp: #e8e6dc; –ts: #b4b2a9; –tt: #888780;
–bg: #1c1c1a; –bg2: #252523; –border: rgba(255,255,255,0.08);
–tf: #085041; –ts2: #5DCAA5; –tt2: #9FE1CB;
–cf: #712B13; –cs: #F0997B; –ct: #F5C4B3;
}
}
*{ box-sizing:border-box; margin:0; padding:0; }
body{ font-family:var(–font); background:var(–bg); color:var(–tp); padding:24px; min-height:100vh; }
h1{ font-size:18px; font-weight:500; margin-bottom:4px; }
.subtitle{ font-size:13px; color:var(–ts); margin-bottom:20px; line-height:1.6; }
.controls{ display:flex; flex-wrap:wrap; gap:14px; margin-bottom:20px; align-items:flex-end; }
.ctrl-group{ display:flex; flex-direction:column; gap:5px; }
.ctrl-group label{ font-size:12px; color:var(–ts); font-weight:500; }
select, input[type=text]{
font-family:var(–font); font-size:13px; background:var(–bg2); color:var(–tp);
border:1px solid var(–border); border-radius:6px; padding:6px 10px;
outline:none; cursor:pointer; min-width:220px;
}
select:focus, input:focus{ border-color:var(–ts2); }
.tuning-row{ display:flex; gap:6px; }
.tuning-row input{ width:52px !important; min-width:unset !important; text-align:center; font-weight:500; }
.err{ color:#c0392b; font-size:12px; margin-top:4px; display:none; }
.scroll-wrap{
overflow-x:auto; border:1px solid var(–border);
border-radius:8px; padding:12px 0 4px; background:var(–bg2);
}
svg .c-teal circle, svg .c-teal rect{ fill:var(–tf); stroke:var(–ts2); stroke-width:1; }
svg .c-teal text{ fill:var(–tt2); }
svg .c-coral circle, svg .c-coral rect{ fill:var(–cf); stroke:var(–cs); stroke-width:1; }
svg .c-coral text{ fill:var(–ct); }
svg .th{ font-family:var(–font); font-size:14px; font-weight:500; fill:var(–tp); }
svg .ts{ font-family:var(–font); font-size:12px; font-weight:400; fill:var(–ts); }
.legend{ display:flex; gap:24px; margin-top:14px; align-items:center; flex-wrap:wrap; }
.legend-item{ display:flex; align-items:center; gap:7px; font-size:13px; color:var(–ts); }
.swatch{ width:20px; height:20px; border-radius:50%; border:1.5px solid; flex-shrink:0; }
.sw-root{ background:var(–cf); border-color:var(–cs); }
.sw-scale{ background:var(–tf); border-color:var(–ts2); }
.notes-label{ margin-left:auto; font-size:12px; color:var(–tt); }
optgroup{ font-weight:600; }
/* ── Piano keyboard ── */
.piano-wrap{
margin-top:28px;
}
.piano-heading{
font-size:13px; font-weight:500; color:var(–ts); margin-bottom:10px;
}
.piano-scroll{
overflow-x:auto; border:1px solid var(–border);
border-radius:8px; padding:16px 20px 12px; background:var(–bg2);
display:inline-block; max-width:100%;
}
/* ── Flute fingerings ── */
.flute-wrap{
margin-top:32px;
}
.flute-heading{
font-size:13px; font-weight:500; color:var(–ts); margin-bottom:10px;
}
.flute-scroll{
overflow-x:auto; border:1px solid var(–border);
border-radius:8px; padding:20px; background:var(–bg2);
}
.flute-row{
display:flex; gap:18px; align-items:flex-start; flex-wrap:nowrap;
}
.flute-card{
display:flex; flex-direction:column; align-items:center; gap:6px; flex-shrink:0;
}
.flute-card .note-name{
font-size:12px; font-weight:600; color:var(–tp); text-align:center; line-height:1.2;
}
.flute-card .note-name.is-root{ color:var(–cs); }
.flute-card .octave-tag{
font-size:10px; color:var(–ts); text-align:center;
}
/* key circles inside flute SVG */
svg .fk-open { fill:var(–bg); stroke:var(–ts); stroke-width:1.5; }
svg .fk-closed{ fill:var(–tp); stroke:var(–ts); stroke-width:1.5; }
svg .fk-half { fill:url(#halfFill); stroke:var(–ts); stroke-width:1.5; }
svg .fk-trill { fill:#e8d88a; stroke:#9a8a20; stroke-width:1.5; }
svg .fk-oct { fill:var(–tp); stroke:var(–ts); stroke-width:1.2; }
svg .fk-oct-o { fill:var(–bg); stroke:var(–ts); stroke-width:1.2; }
svg .fl-body { fill:none; stroke:var(–ts); stroke-width:2; opacity:0.35; }
svg .fl-label { font-family:var(–font); font-size:8px; fill:var(–ts); text-anchor:middle; }
svg .wk{ fill:#f8f7f3; stroke:#c8c6bc; stroke-width:1; }
svg .bk{ fill:#f0eeea; stroke:#b0aea4; stroke-width:1; }
svg .wk-root{ fill:var(–cf); stroke:var(–cs); stroke-width:1.5; }
svg .bk-root{ fill:var(–cs); stroke:var(–ct); stroke-width:1.5; }
svg .wk-scale{ fill:var(–tf); stroke:var(–ts2); stroke-width:1.5; }
svg .bk-scale{ fill:var(–ts2); stroke:var(–tt2); stroke-width:1.5; }
svg .key-label{ font-family:var(–font); font-size:10px; fill:var(–ts); text-anchor:middle; }
svg .key-label-dark{ font-family:var(–font); font-size:9px; fill:var(–ts); text-anchor:middle; }
svg .key-label-active{ fill:var(–ct); }
svg .key-label-scale{ fill:var(–tt2); }
</style>
</head>
<body>
<h1 id=”main-title”>Guitar neck diagram</h1>
<p class=”subtitle” id=”subtitle”></p>
<div class=”controls”>
<div class=”ctrl-group”>
<label for=”sel-key”>Key / root</label>
<select id=”sel-key”>
<option value=”C”>C</option>
<option value=”C#”>C#</option>
<option value=”D”>D</option>
<option value=”D#”>D#</option>
<option value=”E”>E</option>
<option value=”F”>F</option>
<option value=”F#”>F#</option>
<option value=”G”>G</option>
<option value=”G#”>G#</option>
<option value=”A”>A</option>
<option value=”A#”>A#</option>
<option value=”B”>B</option>
</select>
</div>
<div class=”ctrl-group”>
<label for=”sel-mode”>Mode</label>
<select id=”sel-mode”>
<option value=”scale”>Scale / mode</option>
<option value=”chord”>Chord</option>
</select>
</div>
<div class=”ctrl-group” id=”scale-ctrl”>
<label for=”sel-scale”>Scale</label>
<select id=”sel-scale”>
<optgroup label=”Messiaen — Modes of Limited Transposition”>
<option value=”messiaen_1″>Messiaen mode 1 (whole tone)</option>
<option value=”messiaen_2″>Messiaen mode 2 (octatonic)</option>
<option value=”messiaen_3″>Messiaen mode 3</option>
<option value=”messiaen_4″>Messiaen mode 4</option>
<option value=”messiaen_5″>Messiaen mode 5</option>
<option value=”messiaen_6″>Messiaen mode 6</option>
<option value=”messiaen_7″>Messiaen mode 7</option>
</optgroup>
<optgroup label=”Standard scales & modes”>
<option value=”major”>Major (Ionian)</option>
<option value=”minor”>Natural minor (Aeolian)</option>
<option value=”dorian”>Dorian</option>
<option value=”phrygian”>Phrygian</option>
<option value=”lydian”>Lydian</option>
<option value=”mixolydian”>Mixolydian</option>
<option value=”locrian”>Locrian</option>
<option value=”harmonic_minor”>Harmonic minor</option>
<option value=”melodic_minor”>Melodic minor</option>
<option value=”phrygian_dom”>Phrygian dominant</option>
<option value=”lydian_dom”>Lydian dominant</option>
<option value=”pentatonic”>Major pentatonic</option>
<option value=”minor_pent”>Minor pentatonic</option>
<option value=”blues”>Blues</option>
<option value=”diminished”>Diminished (H-W)</option>
<option value=”dim_wh”>Diminished (W-H)</option>
<option value=”augmented”>Augmented</option>
<option value=”chromatic”>Chromatic</option>
</optgroup>
</select>
</div>
<div class=”ctrl-group” id=”chord-ctrl” style=”display:none”>
<label for=”sel-chord”>Chord type</label>
<select id=”sel-chord”>
<optgroup label=”Triads”>
<option value=”major”>Major</option>
<option value=”minor”>Minor</option>
<option value=”dim”>Diminished</option>
<option value=”aug”>Augmented</option>
<option value=”sus2″>Sus2</option>
<option value=”sus4″>Sus4</option>
<option value=”power”>Power (5th)</option>
</optgroup>
<optgroup label=”Sixth chords”>
<option value=”maj6″>Major 6</option>
<option value=”min6″>Minor 6</option>
<option value=”six_nine”>6/9</option>
</optgroup>
<optgroup label=”Seventh chords”>
<option value=”maj7″>Major 7</option>
<option value=”dom7″>Dominant 7</option>
<option value=”min7″>Minor 7</option>
<option value=”minmaj7″>Minor/Major 7</option>
<option value=”half_dim”>Half-dim (m7b5)</option>
<option value=”dim7″>Diminished 7</option>
<option value=”augmaj7″>Augmented Maj7</option>
<option value=”aug7″>Augmented 7 (7#5)</option>
<option value=”dom7sus4″>Dom 7sus4</option>
<option value=”dom7b5″>Dom 7b5</option>
</optgroup>
<optgroup label=”Add chords”>
<option value=”add9″>Add9</option>
<option value=”madd9″>m(add9)</option>
<option value=”add11″>Add11</option>
</optgroup>
<optgroup label=”Ninth chords”>
<option value=”maj9″>Major 9</option>
<option value=”dom9″>Dominant 9</option>
<option value=”min9″>Minor 9</option>
<option value=”minmaj9″>Minor/Major 9</option>
<option value=”dom7b9″>Dom 7b9</option>
<option value=”dom7s9″>Dom 7#9 (Hendrix)</option>
<option value=”dom7b9s9″>Dom 7b9#9</option>
</optgroup>
<optgroup label=”Eleventh chords”>
<option value=”maj11″>Major 11</option>
<option value=”dom11″>Dominant 11</option>
<option value=”min11″>Minor 11</option>
<option value=”dom7s11″>Dom 7#11 (Lydian dom)</option>
<option value=”maj7s11″>Maj 7#11</option>
</optgroup>
<optgroup label=”Thirteenth chords”>
<option value=”maj13″>Major 13</option>
<option value=”dom13″>Dominant 13</option>
<option value=”min13″>Minor 13</option>
<option value=”dom13s11″>Dom 13#11</option>
</optgroup>
<optgroup label=”Altered / jazz”>
<option value=”alt”>Altered (7alt)</option>
<option value=”dom7b9b13″>Dom 7b9b13</option>
<option value=”dom7s9s11″>Dom 7#9#11</option>
<option value=”dom9s11″>Dom 9#11</option>
<option value=”dom9b13″>Dom 9b13</option>
</optgroup>
</select>
</div>
<div class=”ctrl-group”>
<label for=”sel-preset”>Tuning preset</label>
<select id=”sel-preset”>
<option value=””>— custom —</option>
<option value=”E,A,D,G,B,E”>Standard (E A D G B E)</option>
<option value=”D,A,D,G,B,E”>Drop D (D A D G B E)</option>
<option value=”D,G,D,G,B,D”>Open G (D G D G B D)</option>
<option value=”D,A,D,F#,A,D”>Open D (D A D F# A D)</option>
<option value=”E,B,E,G#,B,E”>Open E (E B E G# B E)</option>
<option value=”D,A,D,G,A,D”>DADGAD (D A D G A D)</option>
<option value=”Eb,Ab,Db,Gb,Bb,Eb”>Half step down (Eb Ab Db Gb Bb Eb)</option>
<option value=”D,G,C,F,A,D”>Full step down (D G C F A D)</option>
</select>
</div>
<div class=”ctrl-group”>
<label>Open strings (low → high)</label>
<div class=”tuning-row” id=”tuning-row”></div>
<div class=”err” id=”tuning-err”>Invalid note — use C, C#, D, D#, E, F, F#, G, G#, A, A#, B</div>
</div>
</div>
<div class=”scroll-wrap”>
<svg id=”neck” width=”1100″ height=”460″ viewBox=”0 0 1100 460″ xmlns=”http://www.w3.org/2000/svg”></svg>
</div>
<div class=”legend”>
<div class=”legend-item”><div class=”swatch sw-root”></div><span id=”leg-root”>Root</span></div>
<div class=”legend-item”><div class=”swatch sw-scale”></div><span id=”leg-tone-label”>Scale tone</span></div>
<div class=”notes-label” id=”leg-notes”></div>
</div>
<div class=”piano-wrap”>
<div class=”piano-heading”>Piano keyboard</div>
<div class=”piano-scroll”>
<svg id=”piano” xmlns=”http://www.w3.org/2000/svg”></svg>
</div>
</div>
<div class=”flute-wrap”>
<div class=”flute-heading”>Concert flute fingerings (Boehm system)</div>
<div class=”flute-scroll”>
<div class=”flute-row” id=”flute-row”></div>
</div>
</div>
<script>
const CHROMATIC = [“C”, “C#”, “D”, “D#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “A#”, “B”];
const SCALES = {“messiaen_1”: {“name”: “Messiaen mode 1 (whole tone)”, “desc”: “6 notes \u00b7 2 transpositions \u00b7 All whole steps”, “intervals”: [0, 2, 4, 6, 8, 10]}, “messiaen_2”: {“name”: “Messiaen mode 2 (octatonic)”, “desc”: “8 notes \u00b7 3 transpositions \u00b7 Semitone\u2013tone repeating \u2014 his most-used mode”, “intervals”: [0, 1, 3, 4, 6, 7, 9, 10]}, “messiaen_3”: {“name”: “Messiaen mode 3”, “desc”: “9 notes \u00b7 4 transpositions \u00b7 Tone\u2013semitone\u2013semitone repeating”, “intervals”: [0, 2, 3, 4, 6, 7, 8, 10, 11]}, “messiaen_4”: {“name”: “Messiaen mode 4”, “desc”: “8 notes \u00b7 6 transpositions \u00b7 Semitone\u2013semitone\u2013min3rd\u2013semitone repeating”, “intervals”: [0, 1, 2, 5, 6, 7, 8, 11]}, “messiaen_5”: {“name”: “Messiaen mode 5”, “desc”: “6 notes \u00b7 6 transpositions \u00b7 Semitone\u2013maj3rd\u2013semitone repeating”, “intervals”: [0, 1, 5, 6, 7, 11]}, “messiaen_6”: {“name”: “Messiaen mode 6”, “desc”: “8 notes \u00b7 6 transpositions \u00b7 Tone\u2013tone\u2013semitone\u2013semitone repeating”, “intervals”: [0, 2, 4, 5, 6, 8, 10, 11]}, “messiaen_7”: {“name”: “Messiaen mode 7”, “desc”: “10 notes \u00b7 6 transpositions \u00b7 Semitone\u2013semitone\u2013semitone\u2013tone\u2013semitone repeating”, “intervals”: [0, 1, 2, 3, 5, 6, 7, 8, 9, 11]}, “major”: {“name”: “Major (Ionian)”, “desc”: “7 notes \u00b7 W W H W W W H”, “intervals”: [0, 2, 4, 5, 7, 9, 11]}, “minor”: {“name”: “Natural minor (Aeolian)”, “desc”: “7 notes \u00b7 W H W W H W W”, “intervals”: [0, 2, 3, 5, 7, 8, 10]}, “dorian”: {“name”: “Dorian”, “desc”: “7 notes \u00b7 W H W W W H W”, “intervals”: [0, 2, 3, 5, 7, 9, 10]}, “phrygian”: {“name”: “Phrygian”, “desc”: “7 notes \u00b7 H W W W H W W”, “intervals”: [0, 1, 3, 5, 7, 8, 10]}, “lydian”: {“name”: “Lydian”, “desc”: “7 notes \u00b7 W W W H W W H”, “intervals”: [0, 2, 4, 6, 7, 9, 11]}, “mixolydian”: {“name”: “Mixolydian”, “desc”: “7 notes \u00b7 W W H W W H W”, “intervals”: [0, 2, 4, 5, 7, 9, 10]}, “locrian”: {“name”: “Locrian”, “desc”: “7 notes \u00b7 H W W H W W W”, “intervals”: [0, 1, 3, 5, 6, 8, 10]}, “harmonic_minor”: {“name”: “Harmonic minor”, “desc”: “7 notes \u00b7 Natural minor with raised 7th”, “intervals”: [0, 2, 3, 5, 7, 8, 11]}, “melodic_minor”: {“name”: “Melodic minor”, “desc”: “7 notes \u00b7 Natural minor with raised 6th & 7th”, “intervals”: [0, 2, 3, 5, 7, 9, 11]}, “phrygian_dom”: {“name”: “Phrygian dominant”, “desc”: “7 notes \u00b7 Phrygian with raised 3rd”, “intervals”: [0, 1, 4, 5, 7, 8, 10]}, “lydian_dom”: {“name”: “Lydian dominant”, “desc”: “7 notes \u00b7 Lydian with b7”, “intervals”: [0, 2, 4, 6, 7, 9, 10]}, “pentatonic”: {“name”: “Major pentatonic”, “desc”: “5 notes”, “intervals”: [0, 2, 4, 7, 9]}, “minor_pent”: {“name”: “Minor pentatonic”, “desc”: “5 notes”, “intervals”: [0, 3, 5, 7, 10]}, “blues”: {“name”: “Blues”, “desc”: “6 notes \u00b7 Minor pent + b5”, “intervals”: [0, 3, 5, 6, 7, 10]}, “diminished”: {“name”: “Diminished (H-W)”, “desc”: “8 notes \u00b7 Semitone\u2013tone alternating”, “intervals”: [0, 1, 3, 4, 6, 7, 9, 10]}, “dim_wh”: {“name”: “Diminished (W-H)”, “desc”: “8 notes \u00b7 Tone\u2013semitone alternating”, “intervals”: [0, 2, 3, 5, 6, 8, 9, 11]}, “augmented”: {“name”: “Augmented”, “desc”: “6 notes \u00b7 Min3rd\u2013semitone repeating”, “intervals”: [0, 3, 4, 7, 8, 11]}, “chromatic”: {“name”: “Chromatic”, “desc”: “12 notes”, “intervals”: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]}};
const CHORDS = {“major”: {“name”: “Major”, “desc”: “1 3 5”, “intervals”: [0, 4, 7]}, “minor”: {“name”: “Minor”, “desc”: “1 b3 5”, “intervals”: [0, 3, 7]}, “dim”: {“name”: “Diminished”, “desc”: “1 b3 b5”, “intervals”: [0, 3, 6]}, “aug”: {“name”: “Augmented”, “desc”: “1 3 #5”, “intervals”: [0, 4, 8]}, “sus2”: {“name”: “Sus2”, “desc”: “1 2 5”, “intervals”: [0, 2, 7]}, “sus4”: {“name”: “Sus4”, “desc”: “1 4 5”, “intervals”: [0, 5, 7]}, “power”: {“name”: “Power (5th)”, “desc”: “1 5”, “intervals”: [0, 7]}, “maj6”: {“name”: “Major 6”, “desc”: “1 3 5 6”, “intervals”: [0, 4, 7, 9]}, “min6”: {“name”: “Minor 6”, “desc”: “1 b3 5 6”, “intervals”: [0, 3, 7, 9]}, “six_nine”: {“name”: “6/9”, “desc”: “1 3 5 6 9”, “intervals”: [0, 2, 4, 7, 9]}, “maj7”: {“name”: “Major 7”, “desc”: “1 3 5 7”, “intervals”: [0, 4, 7, 11]}, “dom7”: {“name”: “Dominant 7”, “desc”: “1 3 5 b7”, “intervals”: [0, 4, 7, 10]}, “min7”: {“name”: “Minor 7”, “desc”: “1 b3 5 b7”, “intervals”: [0, 3, 7, 10]}, “minmaj7”: {“name”: “Minor/Major 7”, “desc”: “1 b3 5 7”, “intervals”: [0, 3, 7, 11]}, “half_dim”: {“name”: “Half-dim (m7b5)”, “desc”: “1 b3 b5 b7”, “intervals”: [0, 3, 6, 10]}, “dim7”: {“name”: “Diminished 7”, “desc”: “1 b3 b5 bb7”, “intervals”: [0, 3, 6, 9]}, “augmaj7”: {“name”: “Augmented Maj7”, “desc”: “1 3 #5 7”, “intervals”: [0, 4, 8, 11]}, “aug7”: {“name”: “Augmented 7 (7#5)”, “desc”: “1 3 #5 b7”, “intervals”: [0, 4, 8, 10]}, “dom7sus4”: {“name”: “Dom 7sus4”, “desc”: “1 4 5 b7”, “intervals”: [0, 5, 7, 10]}, “dom7b5”: {“name”: “Dom 7b5”, “desc”: “1 3 b5 b7”, “intervals”: [0, 4, 6, 10]}, “add9”: {“name”: “Add9”, “desc”: “1 3 5 9”, “intervals”: [0, 2, 4, 7]}, “madd9”: {“name”: “m(add9)”, “desc”: “1 b3 5 9”, “intervals”: [0, 2, 3, 7]}, “add11”: {“name”: “Add11”, “desc”: “1 3 5 11”, “intervals”: [0, 4, 5, 7]}, “maj9”: {“name”: “Major 9”, “desc”: “1 3 5 7 9”, “intervals”: [0, 2, 4, 7, 11]}, “dom9”: {“name”: “Dominant 9”, “desc”: “1 3 5 b7 9”, “intervals”: [0, 2, 4, 7, 10]}, “min9”: {“name”: “Minor 9”, “desc”: “1 b3 5 b7 9”, “intervals”: [0, 2, 3, 7, 10]}, “minmaj9”: {“name”: “Minor/Major 9”, “desc”: “1 b3 5 7 9”, “intervals”: [0, 2, 3, 7, 11]}, “dom7b9”: {“name”: “Dom 7b9”, “desc”: “1 3 5 b7 b9”, “intervals”: [0, 1, 4, 7, 10]}, “dom7s9”: {“name”: “Dom 7#9 (Hendrix)”, “desc”: “1 3 5 b7 #9”, “intervals”: [0, 3, 4, 7, 10]}, “dom7b9s9”: {“name”: “Dom 7b9#9”, “desc”: “1 3 5 b7 b9 #9”, “intervals”: [0, 1, 3, 4, 7, 10]}, “maj11”: {“name”: “Major 11”, “desc”: “1 3 5 7 9 11”, “intervals”: [0, 2, 4, 5, 7, 11]}, “dom11”: {“name”: “Dominant 11”, “desc”: “1 3 5 b7 9 11”, “intervals”: [0, 2, 4, 5, 7, 10]}, “min11”: {“name”: “Minor 11”, “desc”: “1 b3 5 b7 9 11”, “intervals”: [0, 2, 3, 5, 7, 10]}, “dom7s11”: {“name”: “Dom 7#11 (Lydian dom)”, “desc”: “1 3 5 b7 #11”, “intervals”: [0, 4, 6, 7, 10]}, “maj7s11”: {“name”: “Maj 7#11”, “desc”: “1 3 5 7 #11”, “intervals”: [0, 4, 6, 7, 11]}, “maj13”: {“name”: “Major 13”, “desc”: “1 3 5 7 9 11 13”, “intervals”: [0, 2, 4, 5, 7, 9, 11]}, “dom13”: {“name”: “Dominant 13”, “desc”: “1 3 5 b7 9 11 13”, “intervals”: [0, 2, 4, 5, 7, 9, 10]}, “min13”: {“name”: “Minor 13”, “desc”: “1 b3 5 b7 9 11 13”, “intervals”: [0, 2, 3, 5, 7, 9, 10]}, “dom13s11”: {“name”: “Dom 13#11”, “desc”: “1 3 5 b7 9 #11 13”, “intervals”: [0, 2, 4, 6, 7, 9, 10]}, “alt”: {“name”: “Altered (7alt)”, “desc”: “1 3 b7 b9 #9 b13”, “intervals”: [0, 1, 3, 4, 8, 10]}, “dom7b9b13”: {“name”: “Dom 7b9b13”, “desc”: “1 3 5 b7 b9 b13”, “intervals”: [0, 1, 4, 7, 8, 10]}, “dom7s9s11”: {“name”: “Dom 7#9#11”, “desc”: “1 3 b7 #9 #11”, “intervals”: [0, 3, 4, 6, 10]}, “dom9s11”: {“name”: “Dom 9#11”, “desc”: “1 3 5 b7 9 #11”, “intervals”: [0, 2, 4, 6, 7, 10]}, “dom9b13”: {“name”: “Dom 9b13”, “desc”: “1 3 5 b7 9 b13”, “intervals”: [0, 2, 4, 7, 8, 10]}};
const PRESETS = {“Standard (E A D G B E)”: “E,A,D,G,B,E”, “Drop D (D A D G B E)”: “D,A,D,G,B,E”, “Open G (D G D G B D)”: “D,G,D,G,B,D”, “Open D (D A D F# A D)”: “D,A,D,F#,A,D”, “Open E (E B E G# B E)”: “E,B,E,G#,B,E”, “DADGAD (D A D G A D)”: “D,A,D,G,A,D”, “Half step down (Eb Ab Db Gb Bb Eb)”: “Eb,Ab,Db,Gb,Bb,Eb”, “Full step down (D G C F A D)”: “D,G,C,F,A,D”};
const FRET_X = [72,152,232,310,386,460,532,602,670,736,800,862,922,1082];
const STRING_Y = [68,118,168,218,268,318];
const STR_WIDTHS = [3,2.4,1.9,1.4,1.0,0.7];
const DOT_R = 13;
const NECK_X0=72, NECK_X1=1082, NECK_Y0=32, NECK_Y1=348;
const ENHARMONIC = {Db:’C#’,Eb:’D#’,Fb:’E’,Gb:’F#’,Ab:’G#’,Bb:’A#’,Cb:’B’};
function norm(n) {
const s = n.trim();
const cap = s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()
.replace(‘b’,’b’).replace(‘#’,’#’);
const cap2 = s.charAt(0).toUpperCase() + s.slice(1);
return ENHARMONIC[cap2] || cap2;
}
function fretMid(f) { return Math.floor((FRET_X[f]+FRET_X[f+1])/2); }
function noteAt(open, fret) { return CHROMATIC[(CHROMATIC.indexOf(open)+fret)%12]; }
function svgEl(tag, attrs) {
const el = document.createElementNS(‘http://www.w3.org/2000/svg’, tag);
for (const [k,v] of Object.entries(attrs)) el.setAttribute(k,v);
return el;
}
function svgTxt(attrs, text) {
const el = svgEl(‘text’, attrs);
el.textContent = text;
return el;
}
function buildNeck(tuning, noteSet, root) {
const svg = document.getElementById(‘neck’);
svg.innerHTML=”;
const a = el => svg.appendChild(el);
a(svgEl(‘rect’,{x:NECK_X0,y:NECK_Y0,width:NECK_X1-NECK_X0,height:NECK_Y1-NECK_Y0,rx:6,fill:’#C8A96A’,opacity:’0.15′}));
a(svgEl(‘rect’,{x:NECK_X0,y:NECK_Y0,width:8,height:NECK_Y1-NECK_Y0,rx:2,fill:’var(–tp)’,opacity:’0.3′}));
for (let f=1;f<=12;f++)
a(svgEl(‘line’,{x1:FRET_X[f],y1:NECK_Y0,x2:FRET_X[f],y2:NECK_Y1,stroke:’var(–tp)’,’stroke-width’:’2′,opacity:’0.25′}));
[[3,192],[5,192],[7,192],[9,192],[12,150],[12,234]].forEach(([f,cy])=>
a(svgEl(‘circle’,{cx:fretMid(f),cy,r:7,fill:’var(–tp)’,opacity:’0.10′})));
STRING_Y.forEach((sy,i)=>
a(svgEl(‘line’,{x1:NECK_X0,y1:sy,x2:NECK_X1,y2:sy,stroke:’var(–ts)’,’stroke-width’:STR_WIDTHS[i],opacity:’0.5′})));
// Open string labels
STRING_Y.forEach((sy,i)=>
a(svgTxt({x:56,y:sy,’text-anchor’:’middle’,’dominant-baseline’:’central’,’font-weight’:’500′,class:’ts’}, tuning[i])));
// Fret numbers
a(svgTxt({x:fretMid(0),y:372,’text-anchor’:’middle’,class:’ts’},’open’));
for (let f=1;f<=12;f++)
a(svgTxt({x:fretMid(f),y:372,’text-anchor’:’middle’,class:’ts’}, String(f)));
// Note dots
STRING_Y.forEach((sy,si)=>{
for (let fret=0;fret<=12;fret++){
const note = noteAt(tuning[si], fret);
if (!noteSet.has(note)) continue;
const cx = fretMid(fret);
const isRoot = note===root;
const g = svgEl(‘g’,{class:isRoot?’c-coral’:’c-teal’});
g.appendChild(svgEl(‘circle’,{cx,cy:sy,r:DOT_R,’stroke-width’:’0′}));
g.appendChild(svgTxt({x:cx,y:sy,’text-anchor’:’middle’,’dominant-baseline’:’central’,class:’th’,style:’font-size:11px’}, note));
svg.appendChild(g);
}
});
}
function getTuning() {
return […document.querySelectorAll(‘#tuning-row input’)].map(i=>norm(i.value));
}
function update() {
const key = document.getElementById(‘sel-key’).value;
const mode = document.getElementById(‘sel-mode’).value;
const tuning = getTuning();
const errEl = document.getElementById(‘tuning-err’);
if (tuning.some(n=>!CHROMATIC.includes(n))) { errEl.style.display=’block’; return; }
errEl.style.display=’none’;
const rootIdx = CHROMATIC.indexOf(key);
let entry, notes, label;
if (mode === ‘chord’) {
const ckey = document.getElementById(‘sel-chord’).value;
entry = CHORDS[ckey];
notes = entry.intervals.map(i=>CHROMATIC[(rootIdx+i)%12]);
label = key + ‘ ‘ + entry.name;
document.getElementById(‘subtitle’).textContent = label + ‘ · ‘ + entry.desc;
document.getElementById(‘leg-tone-label’).textContent = ‘Chord tone’;
} else {
const skey = document.getElementById(‘sel-scale’).value;
entry = SCALES[skey];
notes = entry.intervals.map(i=>CHROMATIC[(rootIdx+i)%12]);
label = entry.name;
document.getElementById(‘subtitle’).textContent = label + ‘ · ‘ + entry.desc;
document.getElementById(‘leg-tone-label’).textContent = ‘Scale tone’;
}
const noteSet = new Set(notes);
buildNeck(tuning, noteSet, key);
if (window.buildPiano) buildPiano(noteSet, key);
if (window.buildFlute) buildFlute(notes, key);
document.getElementById(‘leg-root’).textContent = key + ‘ (root)’;
document.getElementById(‘leg-notes’).textContent = ‘Notes: ‘ + notes.join(‘ ‘);
}
function buildTuningInputs(tuning) {
const row = document.getElementById(‘tuning-row’);
row.innerHTML=”;
const labels=[‘6 (low)’,’5′,’4′,’3′,’2′,’1 (high)’];
tuning.forEach((note,i)=>{
const inp = document.createElement(‘input’);
inp.type=’text’; inp.value=note; inp.maxLength=3; inp.title=labels[i]+’ string’;
inp.addEventListener(‘input’,()=>{
document.getElementById(‘sel-preset’).value=”;
update();
});
row.appendChild(inp);
});
}
// Preset tuning handler
document.getElementById(‘sel-preset’).addEventListener(‘change’, function(){
if (!this.value) return;
buildTuningInputs(this.value.split(‘,’).map(n=>norm(n.trim())));
update();
});
document.getElementById(‘sel-key’).addEventListener(‘change’, update);
document.getElementById(‘sel-scale’).addEventListener(‘change’, update);
document.getElementById(‘sel-chord’).addEventListener(‘change’, update);
document.getElementById(‘sel-mode’).addEventListener(‘change’, function() {
const isChord = this.value === ‘chord’;
document.getElementById(‘scale-ctrl’).style.display = isChord ? ‘none’ : ”;
document.getElementById(‘chord-ctrl’).style.display = isChord ? ” : ‘none’;
update();
});
// Initialise
const initKey = “C”;
const initScale = “major”;
const initChord = “major”;
const initMode = “scale”;
const initTuning = [“E”, “A”, “D”, “G”, “B”, “E”];
document.getElementById(‘sel-key’).value = initKey;
document.getElementById(‘sel-scale’).value = initScale;
document.getElementById(‘sel-chord’).value = initChord;
document.getElementById(‘sel-mode’).value = initMode;
if (initMode === ‘chord’) {
document.getElementById(‘scale-ctrl’).style.display = ‘none’;
document.getElementById(‘chord-ctrl’).style.display = ”;
}
buildTuningInputs(initTuning);
// Mark matching preset
for (const [,val] of Object.entries(PRESETS)) {
if (val === initTuning.join(‘,’)) {
document.getElementById(‘sel-preset’).value = val; break;
}
}
// ── Concert flute fingerings (Boehm system) ──────────────────────────────
//
// Key layout (top to bottom in diagram):
// OCT — octave/register key (left thumb, upper)
// TH — B♭ thumb lever (Briccialdi) — shown as small side key
// LH1 — left index finger (covers B hole)
// LH2 — left middle finger (covers A hole)
// LH3 — left ring finger (covers G hole)
// LH4 — left pinky (G#/Ab key)
// ··· — gap between hands
// RH1 — right index finger (covers F# hole)
// RH2 — right middle finger(covers E hole)
// RH3 — right ring finger (covers D hole)
// RH4 — right pinky (Eb/D# roller key)
//
// Each note’s fingering is encoded as an object:
// oct: bool — octave key depressed
// th: bool — Briccialdi Bb thumb lever
// lh1..lh4: bool — left fingers (true = key DOWN / hole covered)
// rh1..rh4: bool — right fingers (true = key DOWN / hole covered)
//
// Fingerings cover first octave (4th octave register = add oct key).
// Register 1: C4–B4, Register 2: C5–B5 (oct key), Register 3: C6+ (oct key + overblowing)
// We show register 1 as the canonical reference diagram, noting octave above.
(function() {
// Standard Boehm fingerings for all 12 chromatic pitches (register-1 reference).
// oct=false for all here; add oct=true for register 2, specific combos for reg 3.
// Keys: oct, th(Bb lever), lh1, lh2, lh3, lh4(G#key), rh1, rh2, rh3, rh4(Eb key)
//
// Convention: lh4 being TRUE means the G#/Ab key IS pressed (LH pinky down).
// On a standard closed-G# flute this key is NORMALLY UP (open), pressing it closes G#.
//
// Fingering reference: standard Boehm closed-G# system, C foot.
const BASE = {
// oct th lh1 lh2 lh3 lh4 rh1 rh2 rh3 rh4
‘C’ : { oct:false, th:false, lh1:true, lh2:true, lh3:true, lh4:false, rh1:true, rh2:true, rh3:true, rh4:false },
‘C#’: { oct:false, th:false, lh1:true, lh2:true, lh3:true, lh4:false, rh1:true, rh2:true, rh3:false, rh4:false },
‘D’ : { oct:false, th:false, lh1:true, lh2:true, lh3:true, lh4:false, rh1:true, rh2:false, rh3:false, rh4:false },
‘D#’: { oct:false, th:false, lh1:true, lh2:true, lh3:true, lh4:false, rh1:false, rh2:false, rh3:false, rh4:true },
‘E’ : { oct:false, th:false, lh1:true, lh2:true, lh3:true, lh4:false, rh1:false, rh2:false, rh3:false, rh4:false },
‘F’ : { oct:false, th:false, lh1:true, lh2:true, lh3:false, lh4:false, rh1:false, rh2:false, rh3:false, rh4:false },
‘F#’: { oct:false, th:false, lh1:true, lh2:false, lh3:false, lh4:false, rh1:false, rh2:false, rh3:false, rh4:false },
‘G’ : { oct:false, th:false, lh1:false, lh2:false, lh3:false, lh4:false, rh1:false, rh2:false, rh3:false, rh4:false },
‘G#’: { oct:false, th:false, lh1:false, lh2:false, lh3:false, lh4:true, rh1:false, rh2:false, rh3:false, rh4:false },
‘A’ : { oct:false, th:false, lh1:false, lh2:true, lh3:true, lh4:false, rh1:true, rh2:true, rh3:true, rh4:false },
‘A#’: { oct:false, th:true, lh1:true, lh2:false, lh3:false, lh4:false, rh1:false, rh2:false, rh3:false, rh4:false },
‘B’ : { oct:false, th:false, lh1:true, lh2:false, lh3:false, lh4:false, rh1:false, rh2:false, rh3:false, rh4:false },
};
// Compute register-specific fingering.
// Reg 1 = C4–B4 (base, no oct key)
// Reg 2 = C5–B5 (add oct key to all base fingerings)
// Reg 3 = C6–B6 (oct key + specific overblown fingerings — simplified: same as reg2 for display)
function fingeringFor(note, octave) {
const base = Object.assign({}, BASE[note]);
if (octave >= 2) base.oct = true;
return base;
}
// Choose which octave to show for a given chromatic note given the scale’s root.
// We default to register 2 (middle octave) as most practical for flutists.
function chooseOctave(/* unused for now */) { return 2; }
// ── SVG drawing ──────────────────────────────────────────────────────────
// Flute diagram is drawn top-to-bottom as a stylised side view.
// The body is a narrow vertical tube; keys appear as circles on the left side.
const CARD_W = 52; // SVG width per card
const KEY_R = 7; // main key circle radius
const OCT_R = 4; // octave key radius (small)
const TH_R = 4.5; // thumb Bb lever radius
const COL_X = 26; // x centre of key column
const BODY_X1 = 22; // tube left edge
const BODY_X2 = 30; // tube right edge
const TOP_Y = 18; // y of first key centre
const KEY_GAP = 18; // vertical gap between main keys
const HAND_GAP= 10; // extra gap between LH and RH groups
const OCT_Y = TOP_Y – 14; // octave key position above LH1
// Key vertical positions (y centres), relative to SVG top
// Order: OCT, LH1, LH2, LH3, LH4, [gap], RH1, RH2, RH3, RH4
function keyPositions() {
const ys = {};
ys.oct = OCT_Y;
ys.lh1 = TOP_Y;
ys.lh2 = TOP_Y + KEY_GAP;
ys.lh3 = TOP_Y + KEY_GAP * 2;
ys.lh4 = TOP_Y + KEY_GAP * 3;
ys.rh1 = TOP_Y + KEY_GAP * 3 + HAND_GAP + KEY_GAP;
ys.rh2 = TOP_Y + KEY_GAP * 3 + HAND_GAP + KEY_GAP * 2;
ys.rh3 = TOP_Y + KEY_GAP * 3 + HAND_GAP + KEY_GAP * 3;
ys.rh4 = TOP_Y + KEY_GAP * 3 + HAND_GAP + KEY_GAP * 4;
return ys;
}
const POS = keyPositions();
const TUBE_TOP = OCT_Y – OCT_R – 4;
const TUBE_BOTTOM= POS.rh4 + KEY_R + 6;
const SVG_H = TUBE_BOTTOM + 18; // extra for label below
function fEl(tag, attrs) {
const el = document.createElementNS(‘http://www.w3.org/2000/svg’, tag);
for (const [k,v] of Object.entries(attrs)) el.setAttribute(k,v);
return el;
}
function fTxt(attrs, text) {
const el = fEl(‘text’, attrs); el.textContent = text; return el;
}
function drawFluteCard(note, isRoot, octave) {
const f = fingeringFor(note, octave);
const svg = document.createElementNS(‘http://www.w3.org/2000/svg’,’svg’);
svg.setAttribute(‘width’, CARD_W);
svg.setAttribute(‘height’, SVG_H);
svg.setAttribute(‘viewBox’, `0 0 ${CARD_W} ${SVG_H}`);
svg.setAttribute(‘xmlns’,’http://www.w3.org/2000/svg’);
// Gradient def for half-hole (not needed here but good to include)
const defs = fEl(‘defs’,{});
const grad = fEl(‘linearGradient’,{id:`hf_${note.replace(‘#’,’s’)}`,x1:’0′,y1:’0′,x2:’1′,y2:’0′});
grad.appendChild(fEl(‘stop’,{offset:’50%’,’stop-color’:’var(–tp)’,’stop-opacity’:’1′}));
grad.appendChild(fEl(‘stop’,{offset:’50%’,’stop-color’:’var(–bg)’,’stop-opacity’:’1′}));
defs.appendChild(grad);
svg.appendChild(defs);
// Tube body (vertical rectangle)
svg.appendChild(fEl(‘rect’,{
x: BODY_X1, y: TUBE_TOP,
width: BODY_X2 – BODY_X1, height: TUBE_BOTTOM – TUBE_TOP,
rx: 3, class: ‘fl-body’
}));
// Hand separator dashes
const sepY = (POS.lh4 + POS.rh1) / 2;
for (let dx = 0; dx < 3; dx++) {
svg.appendChild(fEl(‘rect’,{
x: COL_X – 5 + dx*5, y: sepY – 0.5,
width: 2, height: 1,
fill:’var(–ts)’, opacity:’0.4′
}));
}
// Helper: draw one key circle
function drawKey(cx, cy, closed, r) {
r = r || KEY_R;
const cls = closed ? ‘fk-closed’ : ‘fk-open’;
svg.appendChild(fEl(‘circle’,{cx, cy, r, class:cls}));
}
// Octave key — small circle, offset slightly left
drawKey(COL_X – 4, POS.oct, f.oct, OCT_R);
// Bb thumb lever — small circle right of tube, above LH1
const thY = (POS.oct + POS.lh1) / 2;
svg.appendChild(fEl(‘circle’,{
cx: BODY_X2 + 5, cy: thY, r: TH_R,
class: f.th ? ‘fk-closed’ : ‘fk-open’
}));
// Main finger keys
drawKey(COL_X, POS.lh1, f.lh1);
drawKey(COL_X, POS.lh2, f.lh2);
drawKey(COL_X, POS.lh3, f.lh3);
// LH4 (G# key) — smaller, offset right to show it’s a side key
svg.appendChild(fEl(‘circle’,{
cx: BODY_X2 + 5, cy: POS.lh4, r: KEY_R – 2,
class: f.lh4 ? ‘fk-closed’ : ‘fk-open’
}));
drawKey(COL_X, POS.rh1, f.rh1);
drawKey(COL_X, POS.rh2, f.rh2);
drawKey(COL_X, POS.rh3, f.rh3);
// RH4 (Eb roller) — smaller, offset right
svg.appendChild(fEl(‘circle’,{
cx: BODY_X2 + 5, cy: POS.rh4, r: KEY_R – 2,
class: f.rh4 ? ‘fk-closed’ : ‘fk-open’
}));
return svg;
}
window.buildFlute = function(notes, root) {
const row = document.getElementById(‘flute-row’);
row.innerHTML = ”;
// Sort notes chromatically
const ORDER = [‘C’,’C#’,’D’,’D#’,’E’,’F’,’F#’,’G’,’G#’,’A’,’A#’,’B’];
const sorted = […notes].sort((a,b) => ORDER.indexOf(a) – ORDER.indexOf(b));
sorted.forEach(note => {
const octave = 2; // display register 2 (middle octave)
const isRoot = note === root;
const card = document.createElement(‘div’);
card.className = ‘flute-card’;
// Note name label
const nameEl = document.createElement(‘div’);
nameEl.className = ‘note-name’ + (isRoot ? ‘ is-root’ : ”);
nameEl.textContent = note;
card.appendChild(nameEl);
// Octave label
const octEl = document.createElement(‘div’);
octEl.className = ‘octave-tag’;
octEl.textContent = `(${octave + 3}th oct)`;
card.appendChild(octEl);
// SVG diagram
card.appendChild(drawFluteCard(note, isRoot, octave));
// Key legend below diagram
const legEl = document.createElement(‘div’);
legEl.style.cssText = ‘font-size:9px;color:var(–ts);text-align:center;line-height:1.5;margin-top:2px;’;
const f = fingeringFor(note, octave);
const parts = [];
if (f.oct) parts.push(‘oct’);
if (f.th) parts.push(‘B♭lv’);
[‘lh1′,’lh2′,’lh3′,’lh4′,’rh1′,’rh2′,’rh3′,’rh4’].forEach(k => {
if (f[k]) parts.push(k.toUpperCase());
});
legEl.textContent = parts.length ? parts.join(‘ ‘) : ‘open G’;
card.appendChild(legEl);
row.appendChild(card);
});
};
})();
(function() {
// Two full octaves of white/black keys (C–B repeated twice)
const OCTAVES = 2;
const WK_W = 32; // white key width px
const WK_H = 120; // white key height px
const BK_W = 20; // black key width px
const BK_H = 76; // black key height px
const BORDER_R = 4; // bottom-corner radius on white keys
// Within one octave (root = C):
const WHITE_SEMI = [0,2,4,5,7,9,11]; // semitones of white keys C D E F G A B
const WHITE_NAMES = [‘C’,’D’,’E’,’F’,’G’,’A’,’B’];
const BLACK_SEMI = [1,3,6,8,10]; // C# D# F# G# A#
const BLACK_BEFORE= [0,1,3,4,5]; // white-key index to the left of each black
const TOTAL_WHITE = 7 * OCTAVES;
const SVG_W = TOTAL_WHITE * WK_W + 2;
const SVG_H = WK_H + 30;
const svg = document.getElementById(‘piano’);
svg.setAttribute(‘width’, SVG_W);
svg.setAttribute(‘height’, SVG_H);
svg.setAttribute(‘viewBox’, `0 0 ${SVG_W} ${SVG_H}`);
function pEl(tag, attrs) {
const el = document.createElementNS(‘http://www.w3.org/2000/svg’, tag);
for (const [k,v] of Object.entries(attrs)) el.setAttribute(k,v);
return el;
}
function pTxt(attrs, text) {
const el = pEl(‘text’, attrs); el.textContent = text; return el;
}
window.buildPiano = function(noteSet, root) {
svg.innerHTML = ”;
svg.appendChild(pEl(‘rect’,{x:0,y:0,width:SVG_W,height:SVG_H,fill:’transparent’}));
// White keys (draw first so black keys render on top)
for (let oct=0; oct<OCTAVES; oct++) {
const octX = oct * 7 * WK_W + 1;
WHITE_SEMI.forEach((semi, wi) => {
const note = CHROMATIC[semi];
const x = octX + wi * WK_W;
const isRoot = note === root;
const inScale = noteSet.has(note);
const cls = isRoot ? ‘wk-root’ : inScale ? ‘wk-scale’ : ‘wk’;
const d = `M${x},0 L${x+WK_W-1},0 L${x+WK_W-1},${WK_H-BORDER_R} ` +
`Q${x+WK_W-1},${WK_H} ${x+WK_W-1-BORDER_R},${WK_H} ` +
`L${x+BORDER_R},${WK_H} Q${x},${WK_H} ${x},${WK_H-BORDER_R} Z`;
svg.appendChild(pEl(‘path’,{d,class:cls}));
// Note name label beneath key (first octave only)
if (oct === 0) {
const lCls = isRoot ? ‘key-label key-label-active’
: inScale ? ‘key-label key-label-scale’
: ‘key-label’;
svg.appendChild(pTxt({x:x+WK_W/2, y:WK_H+18, class:lCls}, WHITE_NAMES[wi]));
}
});
}
// Black keys (drawn on top)
for (let oct=0; oct<OCTAVES; oct++) {
const octX = oct * 7 * WK_W + 1;
BLACK_SEMI.forEach((semi, bi) => {
const note = CHROMATIC[semi];
const x = octX + BLACK_BEFORE[bi] * WK_W + WK_W – BK_W/2;
const isRoot = note === root;
const inScale = noteSet.has(note);
const cls = isRoot ? ‘bk-root’ : inScale ? ‘bk-scale’ : ‘bk’;
svg.appendChild(pEl(‘rect’,{x,y:0,width:BK_W,height:BK_H,rx:3,class:cls}));
// Label inside black keys (first octave only)
if (oct === 0) {
const labelStyle = isRoot ? ‘fill:var(–ct)’
: inScale ? ‘fill:var(–tt2)’
: ‘fill:var(–ts)’;
svg.appendChild(pTxt({
x: x+BK_W/2, y: BK_H-9, class:’key-label-dark’,
style: labelStyle
}, note));
}
});
}
};
})();
update();
</script>
</body>
</html>