Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
28 kB · 719 lines
HTML
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720<!doctype html><html><head><meta charset="utf-8"><style> /* AC web fonts — YWFT Processing for display, Berkeley Mono for keys. Loaded from system/public/type/webfonts via the build script. */ @font-face { font-family: "YWFT Processing"; src: url("__YWFT_BOLD__") format("woff2"); font-weight: 800; font-style: normal; } @font-face { font-family: "YWFT Processing"; src: url("__YWFT_LIGHT__") format("woff2"); font-weight: 300; font-style: normal; } @font-face { font-family: "Berkeley Mono"; src: url("__BERKELEY__") format("woff2"); font-weight: normal; font-style: normal; }
html, body { margin: 0; padding: 0; } body { width: 2400px; height: 1350px; background: #fafafa; color: #121012; font-family: "YWFT Processing", -apple-system, "Helvetica Neue", sans-serif; box-sizing: border-box; padding: 32px 40px; overflow: hidden; display: flex; flex-direction: column; position: relative; } .connectors { position: absolute; inset: 0; width: 2400px; height: 1350px; pointer-events: none; z-index: 50; }
/* ---------------- Header ---------------- */ .header { display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 18px; } .title { font-family: "YWFT Processing"; font-weight: 800; font-size: 110px; letter-spacing: -0.015em; margin: 0; line-height: 0.95; color: #121012; } .title .dot { color: #cd5c9b; } .title .accent-r { color: #c8324b; } .title .accent-o { color: #ff9000; } .title .accent-y { color: #d4b400; } .title .accent-g { color: #2a9a3a; } .title .accent-b { color: #2a64d4; } .title .accent-p { color: #8232c8; } .title .accent-v { color: #b450ff; } .subtitle { font-family: "YWFT Processing"; font-weight: 300; font-size: 30px; color: #444; margin: 14px 0 0 0; max-width: 1900px; line-height: 1.3; } .subtitle b { font-weight: 800; color: #121012; }
/* ---------------- Piano ---------------- */ .piano-wrap { display: flex; justify-content: center; margin-bottom: 18px; } .piano { position: relative; height: 340px; width: 2076px; padding-left: 36px; box-sizing: border-box; } .wkey, .bkey { position: absolute; box-sizing: border-box; border-radius: 0 0 10px 10px; border: 2px solid #121012; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; padding-bottom: 16px; } /* White (natural) key — body stays white so the QWERTY letter reads in plain dark ink (Berkeley Mono); a saturated colored stripe at the BOTTOM acts as the note-color tab, matching how menuband draws its keys. */ .wkey { width: 120px; height: 320px; background: #fff; color: #121012; overflow: hidden; } .wkey .keyswatch { position: absolute; left: 0; right: 0; bottom: 0; height: 44px; border-top: 2px solid rgba(0,0,0,0.22); } .wkey .qkey { font-family: "Berkeley Mono", "SF Mono", monospace; font-size: 64px; font-weight: 800; line-height: 1; color: #121012; position: absolute; top: 96px; left: 0; right: 0; text-align: center; } .wkey .nname { position: absolute; bottom: 60px; left: 0; right: 0; text-align: center; font-family: "Berkeley Mono", "SF Mono", monospace; font-size: 22px; color: #2a2a2a; letter-spacing: 0.05em; margin: 0; font-weight: 700; z-index: 2; } /* Note color tints — saturated on top, white below for label legibility */ .wkey[data-pn="c"] .keyswatch { background: #ff3232; } .wkey[data-pn="d"] .keyswatch { background: #ffa000; } .wkey[data-pn="e"] .keyswatch { background: #ffe600; } .wkey[data-pn="f"] .keyswatch { background: #32c832; } .wkey[data-pn="g"] .keyswatch { background: #3278ff; } .wkey[data-pn="a"] .keyswatch { background: #8232c8; } .wkey[data-pn="b"] .keyswatch { background: #b450ff; } /* Upper octave — neon/dayglo variants */ .wkey[data-pn="C5"] .keyswatch { background: #ff2850; } .wkey[data-pn="D5"] .keyswatch { background: #ffb400; } .wkey[data-pn="E5"] .keyswatch { background: #ffff32; } .wkey[data-pn="F5"] .keyswatch { background: #32ff64; } .wkey[data-pn="G5"] .keyswatch { background: #32c8ff; } .wkey[data-pn="A5"] .keyswatch { background: #b432ff; } .wkey[data-pn="B5"] .keyswatch { background: #ff50ff; }
/* Black (sharp/flat) keys — pitch-black with subtle color edge so they read as semitones rather than dead space. */ .bkey { width: 72px; height: 210px; background: #0a0a0a; color: #fff; border-color: #000; z-index: 2; } .bkey .qkey { font-family: "Berkeley Mono", "SF Mono", monospace; font-size: 38px; font-weight: 800; line-height: 1; } .bkey .nname { font-family: "Berkeley Mono", "SF Mono", monospace; font-size: 16px; color: #bbb; letter-spacing: 0.05em; margin-top: 6px; font-weight: 700; }
/* Extended-range — aged-paper / muted. Not core. */ .wkey.ext { background: #fff4d6; color: #8a7330; border-color: #d4c075; opacity: 0.78; } .wkey.ext .qkey { color: #8a7330; text-shadow: none; position: static; padding-top: 22px; } .wkey.ext .keyswatch { display: none; } .wkey.ext .nname { position: static; color: #a89855; text-shadow: none; font-size: 22px; font-weight: 700; } .bkey.ext { background: #5a4818; color: #f8e7a0; border-color: #4a3814; opacity: 0.78; } .bkey.ext .nname { color: #d8c878; } .wkey.ext .ext-tag, .bkey.ext .ext-tag { font-family: "Berkeley Mono", monospace; font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; margin-top: 4px; opacity: 0.85; font-weight: 700; }
/* ---------------- QWERTY ---------------- */ .below { display: flex; gap: 36px; flex: 1; align-items: stretch; min-height: 0; } .below-left { flex: 0 0 1380px; display: flex; flex-direction: column; } .below-right { flex: 1; display: flex; flex-direction: column; }
.hand-labels { display: flex; justify-content: space-between; margin-bottom: 10px; font-family: "YWFT Processing"; font-size: 22px; letter-spacing: 0.22em; text-transform: uppercase; font-weight: 800; padding: 0 24px; } .hand-labels .l { color: #2a64d4; } .hand-labels .r { color: #c8324b; } /* YWFT Processing has no arrow/middle-dot glyphs (renders as `&`); use system font just for those characters so labels read correctly. */ .glyph { font-family: -apple-system, "Helvetica Neue", "Arial Unicode MS", sans-serif; font-weight: 800; }
.qwerty-bg { position: relative; padding: 18px 20px; border-radius: 16px; background: linear-gradient(to right, rgba(42, 100, 212, 0.10) 0%, rgba(42, 100, 212, 0.10) 48%, rgba(200, 50, 75, 0.10) 52%, rgba(200, 50, 75, 0.10) 100%); box-sizing: border-box; flex: 1; display: flex; align-items: center; } .qwerty-wrap { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; width: 100%; } .qrow { display: flex; gap: 12px; } .qrow.r0 { padding-left: 0; } .qrow.r1 { padding-left: 28px; } .qrow.r2 { padding-left: 84px; } .qcap { width: 100px; height: 100px; border-radius: 14px; border: 3px solid #121012; display: flex; align-items: center; justify-content: center; font-family: "Berkeley Mono", "SF Mono", monospace; font-size: 46px; font-weight: 800; text-transform: uppercase; flex-shrink: 0; box-shadow: 0 4px 0 rgba(0,0,0,0.18); } /* Default + neutral caps */ .qcap.white { background: #fff; color: #121012; } .qcap.black { background: #121012; color: #fff; border-color: #000; }
/* Note-colored caps — each lights up in its notepat color. */ .qcap[data-qn="c"] { background: #ff3232; color: #fff; border-color: #a51c1c; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="d"] { background: #ffa000; color: #fff; border-color: #b56b00; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="e"] { background: #ffe600; color: #3a2a00; border-color: #b89c00; text-shadow: 0 2px 0 rgba(255,255,255,0.4); } .qcap[data-qn="f"] { background: #32c832; color: #fff; border-color: #1d7a1d; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="g"] { background: #3278ff; color: #fff; border-color: #1c4ba8; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="a"] { background: #8232c8; color: #fff; border-color: #4f1d80; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="b"] { background: #b450ff; color: #fff; border-color: #6f2faa; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } /* Upper octave — dayglo variants */ .qcap[data-qn="C5"] { background: #ff2850; color: #fff; border-color: #b01a37; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="D5"] { background: #ffb400; color: #fff; border-color: #b58000; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="E5"] { background: #ffff32; color: #4a4400; border-color: #b8b400; text-shadow: 0 2px 0 rgba(255,255,255,0.4); } .qcap[data-qn="F5"] { background: #32ff64; color: #0a3a14; border-color: #1a9a3a; text-shadow: 0 2px 0 rgba(255,255,255,0.35); } .qcap[data-qn="G5"] { background: #32c8ff; color: #06283d; border-color: #1a7ab0; text-shadow: 0 2px 0 rgba(255,255,255,0.35); } .qcap[data-qn="A5"] { background: #b432ff; color: #fff; border-color: #6f1cb0; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } .qcap[data-qn="B5"] { background: #ff50ff; color: #fff; border-color: #b02db0; text-shadow: 0 2px 0 rgba(0,0,0,0.22); } /* Sharp QWERTY caps (V/S/W/R/Q/T/Y/U/O/P) — black with thin colored glow so they read as semitones tied to their adjacent natural. */ .qcap.sharp { background: #121012; color: #fff; border-color: #000; } .qcap.sharp[data-sharp-of="c"] { box-shadow: 0 4px 0 rgba(0,0,0,0.18), inset 0 0 0 2px rgba(255,50,50,0.55); } .qcap.sharp[data-sharp-of="d"] { box-shadow: 0 4px 0 rgba(0,0,0,0.18), inset 0 0 0 2px rgba(255,160,0,0.55); } .qcap.sharp[data-sharp-of="f"] { box-shadow: 0 4px 0 rgba(0,0,0,0.18), inset 0 0 0 2px rgba(50,200,50,0.55); } .qcap.sharp[data-sharp-of="g"] { box-shadow: 0 4px 0 rgba(0,0,0,0.18), inset 0 0 0 2px rgba(50,120,255,0.55); } .qcap.sharp[data-sharp-of="a"] { box-shadow: 0 4px 0 rgba(0,0,0,0.18), inset 0 0 0 2px rgba(130,50,200,0.55); }
.qcap.ext-white { background: #fff4d6; color: #8a7330; border-color: #d4c075; opacity: 0.78; flex-direction: column; } .qcap.ext-black { background: #5a4818; color: #f8e7a0; border-color: #4a3814; opacity: 0.78; flex-direction: column; } .qcap .ext-tag { font-family: "Berkeley Mono", monospace; font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; margin-top: 5px; opacity: 0.9; font-weight: 700; } .qcap.ghost { background: transparent; color: #c8c8c8; border: 2.5px dashed #d4d4d4; font-weight: 600; font-size: 30px; box-shadow: none; } .qcap.octshift { background: #f4ecff; color: #6b3fc0; border: 2.5px solid #b89df0; font-weight: 800; font-size: 26px; flex-direction: column; } .qcap.octshift .lbl { font-size: 13px; letter-spacing: 0.1em; opacity: 0.75; margin-top: 3px; font-family: "YWFT Processing"; }
/* ---------------- Right panel ---------------- */ .rationale { flex: 1; } .rationale h3, .impls h3 { font-family: "YWFT Processing"; font-size: 24px; letter-spacing: 0.2em; text-transform: uppercase; color: #555; margin: 0 0 14px 0; font-weight: 800; } .rationale h3 .accent { color: #c8324b; } .rationale ul { list-style: none; padding: 0; margin: 0; font-family: "YWFT Processing"; font-size: 26px; line-height: 1.35; color: #1a1a1a; font-weight: 300; } .rationale li { padding: 11px 0 11px 32px; border-bottom: 1px solid #eee; position: relative; } .rationale li:last-child { border-bottom: none; } .rationale li::before { content: "▸"; position: absolute; left: 0; top: 11px; color: #c8324b; font-weight: 800; font-size: 26px; } .rationale li b { color: #000; font-weight: 800; } .rationale li .keys { font-family: "Berkeley Mono", "SF Mono", monospace; background: #f0eff0; padding: 2px 8px; border-radius: 5px; font-size: 22px; color: #121012; font-weight: 700; }
.below-bottom { display: flex; flex-direction: row; align-items: flex-start; gap: 28px; margin-top: 18px; border-top: 2px solid #ddd; padding-top: 16px; } .impls { flex: 1; min-width: 0; } .impls .impl-list { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: stretch; } .impls .impl-list li { background: #f6f5f1; border: 1px solid #e3e0d8; border-radius: 10px; padding: 7px 12px; display: flex; flex-direction: column; line-height: 1.05; min-width: 0; } .impls .impl-list b { font-family: "YWFT Processing"; font-weight: 800; font-size: 21px; color: #121012; white-space: nowrap; } .impls .impl-list .where { color: #777; font-family: "Berkeley Mono", monospace; font-size: 13px; margin-top: 4px; white-space: nowrap; letter-spacing: 0.02em; }
.qrs { display: flex; gap: 22px; flex-shrink: 0; } .qrs .qr { display: flex; flex-direction: column; align-items: center; gap: 7px; } .qrs .qr img { width: 150px; height: 150px; image-rendering: pixelated; border: 1px solid #ddd; border-radius: 8px; background: #fff; } .qrs .qr .label { font-family: "Berkeley Mono", monospace; font-size: 15px; color: #121012; font-weight: 700; }
.brand-block { position: absolute; top: 18px; right: 32px; display: flex; align-items: flex-start; gap: 20px; } .brand-block .marks { position: relative; width: 160px; height: 160px; } .brand-block .marks #jeffrey { position: absolute; inset: 0; width: 160px; height: 160px; border-radius: 8px; object-fit: cover; object-position: center top; border: 2px solid #ddd; z-index: 1; } .brand-block .marks #pals { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 150px; height: 150px; opacity: 0.95; z-index: 2; filter: drop-shadow(0 0 6px rgba(255,255,255,0.95)) drop-shadow(0 0 2px rgba(255,255,255,1)); } .brand-block .brand-text { display: flex; flex-direction: column; gap: 6px; align-items: flex-end; padding-top: 6px; } .brand-block .brand-text .top { font-family: "YWFT Processing"; font-size: 36px; color: #333; letter-spacing: 0.04em; white-space: nowrap; font-weight: 800; line-height: 1; } .brand-block .brand-text .author { font-family: "Berkeley Mono", monospace; font-size: 22px; color: #888; white-space: nowrap; font-weight: 500; } .brand-block .brand-text .author b { color: #c8324b; font-weight: 800; }</style></head><body> <!-- HEADER --> <div class="header"> <div> <div class="title"> notepat<span class="dot">.com</span> <span style="font-weight:300;">Keymap</span> </div> <div class="subtitle"> A chromatic keyboard instrument. <b><span class="title-c">C</span><span class="glyph">·</span><span class="title-d">D</span><span class="glyph">·</span><span class="title-e">E</span><span class="glyph">·</span><span class="title-f">F</span><span class="glyph">·</span><span class="title-g">G</span><span class="glyph">·</span><span class="title-a">A</span><span class="glyph">·</span><span class="title-b">B</span></b> play the notes they name. Sharps <i>mostly</i> sit one row above their natural — like piano black keys. </div> </div> <div class="brand-block"> <div class="brand-text"> <div class="top">Aesthetic.Computer</div> <div class="author">by <b>@jeffrey</b></div> </div> <div class="marks"> <img id="jeffrey" alt="@jeffrey"> <img id="pals" alt=""> </div> </div> </div>
<!-- PIANO --> <div class="piano-wrap"> <div class="piano"> <div class="wkey ext" style="left:36px;"> <div class="qkey">X</div><div class="nname">B3</div><div class="ext-tag">ext</div></div> <div class="wkey" data-pn="c" style="left:156px;"> <div class="keyswatch"></div><div class="qkey">C</div><div class="nname">C4</div></div> <div class="wkey" data-pn="d" style="left:276px;"> <div class="keyswatch"></div><div class="qkey">D</div><div class="nname">D4</div></div> <div class="wkey" data-pn="e" style="left:396px;"> <div class="keyswatch"></div><div class="qkey">E</div><div class="nname">E4</div></div> <div class="wkey" data-pn="f" style="left:516px;"> <div class="keyswatch"></div><div class="qkey">F</div><div class="nname">F4</div></div> <div class="wkey" data-pn="g" style="left:636px;"> <div class="keyswatch"></div><div class="qkey">G</div><div class="nname">G4</div></div> <div class="wkey" data-pn="a" style="left:756px;"> <div class="keyswatch"></div><div class="qkey">A</div><div class="nname">A4</div></div> <div class="wkey" data-pn="b" style="left:876px;"> <div class="keyswatch"></div><div class="qkey">B</div><div class="nname">B4</div></div> <div class="wkey" data-pn="C5" style="left:996px;"> <div class="keyswatch"></div><div class="qkey">H</div><div class="nname">C5</div></div> <div class="wkey" data-pn="D5" style="left:1116px;"><div class="keyswatch"></div><div class="qkey">I</div><div class="nname">D5</div></div> <div class="wkey" data-pn="E5" style="left:1236px;"><div class="keyswatch"></div><div class="qkey">J</div><div class="nname">E5</div></div> <div class="wkey" data-pn="F5" style="left:1356px;"><div class="keyswatch"></div><div class="qkey">K</div><div class="nname">F5</div></div> <div class="wkey" data-pn="G5" style="left:1476px;"><div class="keyswatch"></div><div class="qkey">L</div><div class="nname">G5</div></div> <div class="wkey" data-pn="A5" style="left:1596px;"><div class="keyswatch"></div><div class="qkey">M</div><div class="nname">A5</div></div> <div class="wkey" data-pn="B5" style="left:1716px;"><div class="keyswatch"></div><div class="qkey">N</div><div class="nname">B5</div></div> <div class="wkey ext" style="left:1836px;"><div class="qkey">;</div><div class="nname">C6</div><div class="ext-tag">ext</div></div> <div class="wkey ext" style="left:1956px;"><div class="qkey">]</div><div class="nname">D6</div><div class="ext-tag">ext</div></div>
<!-- Sharps --> <div class="bkey ext" style="left:0px;"> <div class="qkey">Z</div><div class="nname">A♯3</div></div> <div class="bkey" style="left:240px;"> <div class="qkey">V</div><div class="nname">C♯4</div></div> <div class="bkey" style="left:360px;"> <div class="qkey">S</div><div class="nname">D♯4</div></div> <div class="bkey" style="left:600px;"> <div class="qkey">W</div><div class="nname">F♯4</div></div> <div class="bkey" style="left:720px;"> <div class="qkey">R</div><div class="nname">G♯4</div></div> <div class="bkey" style="left:840px;"> <div class="qkey">Q</div><div class="nname">A♯4</div></div> <div class="bkey" style="left:1080px;"> <div class="qkey">T</div><div class="nname">C♯5</div></div> <div class="bkey" style="left:1200px;"> <div class="qkey">Y</div><div class="nname">D♯5</div></div> <div class="bkey" style="left:1440px;"> <div class="qkey">U</div><div class="nname">F♯5</div></div> <div class="bkey" style="left:1560px;"> <div class="qkey">O</div><div class="nname">G♯5</div></div> <div class="bkey" style="left:1680px;"> <div class="qkey">P</div><div class="nname">A♯5</div></div> <div class="bkey ext" style="left:1920px;"> <div class="qkey">'</div><div class="nname">C♯6</div></div> </div> </div>
<!-- BELOW --> <div class="below"> <div class="below-left"> <div class="hand-labels"> <div class="l"><span class="glyph">←</span> Left hand <span class="glyph">·</span> lower octave</div> <div class="r">Right hand <span class="glyph">·</span> upper octave <span class="glyph">→</span></div> </div> <div class="qwerty-bg"> <div class="qwerty-wrap"> <div class="qrow r0"> <div class="qcap sharp" data-sharp-of="a">Q</div> <div class="qcap sharp" data-sharp-of="f">W</div> <div class="qcap" data-qn="e">E</div> <div class="qcap sharp" data-sharp-of="g">R</div> <div class="qcap sharp" data-sharp-of="c">T</div> <div class="qcap sharp" data-sharp-of="d">Y</div> <div class="qcap sharp" data-sharp-of="f">U</div> <div class="qcap" data-qn="D5">I</div> <div class="qcap sharp" data-sharp-of="g">O</div> <div class="qcap sharp" data-sharp-of="a">P</div> <div class="qcap ghost">[</div> <div class="qcap ext-white">]<div class="ext-tag">ext</div></div> </div> <div class="qrow r1"> <div class="qcap" data-qn="a">A</div> <div class="qcap sharp" data-sharp-of="d">S</div> <div class="qcap" data-qn="d">D</div> <div class="qcap" data-qn="f">F</div> <div class="qcap" data-qn="g">G</div> <div class="qcap" data-qn="C5">H</div> <div class="qcap" data-qn="E5">J</div> <div class="qcap" data-qn="F5">K</div> <div class="qcap" data-qn="G5">L</div> <div class="qcap ext-white">;<div class="ext-tag">ext</div></div> <div class="qcap ext-black">'<div class="ext-tag">ext</div></div> </div> <div class="qrow r2"> <div class="qcap ext-black">Z<div class="ext-tag">ext</div></div> <div class="qcap ext-white">X<div class="ext-tag">ext</div></div> <div class="qcap" data-qn="c">C</div> <div class="qcap sharp" data-sharp-of="c">V</div> <div class="qcap" data-qn="b">B</div> <div class="qcap" data-qn="A5">N</div> <div class="qcap" data-qn="B5">M</div> <div class="qcap octshift">,<div class="lbl">oct−</div></div> <div class="qcap octshift">.<div class="lbl">oct+</div></div> <div class="qcap ghost">/</div> </div> </div> </div> </div>
<div class="below-right"> <div class="rationale"> <h3>Why this <span class="accent">layout</span></h3> <ul> <li><b>Notes that name themselves.</b> <span class="keys">C D E F G A B</span> play the notes they name — anyone who knows the Western scale already knows it.</li> <li><b>Sharps <i>mostly</i> sit above their naturals.</b> <span class="keys">V S W R Q</span> = C♯ D♯ F♯ G♯ A♯ — close to piano black keys, with a few exceptions.</li> <li><b>Two-handed by default.</b> Lower octave under the left hand; upper octave (<span class="keys">H J K L ;</span>) mirrors it under the right.</li> </ul> </div>
<div class="below-bottom"> <div class="impls"> <h3>Notepat lives in</h3> <ul class="impl-list"> <li><b>notepat.com</b><span class="where">web</span></li> <li><b>AC Native</b><span class="where">AC OS</span></li> <li><b>MenuBand</b><span class="where">macOS</span></li> <li><b>AC-Notepat</b><span class="where">Max for Live</span></li> <li><b>Remote</b><span class="where">phone</span></li> </ul> </div> <div class="qrs"> <div class="qr"> <img id="qr1" alt="notepat.com"> <div class="label">notepat.com</div> </div> <div class="qr"> <img id="qr2" alt="prompt.ac/menuband"> <div class="label">prompt.ac/menuband</div> </div> </div> </div> </div> </div>
<!-- Connector overlay: piano white key → QWERTY note cap, color-matched --> <svg class="connectors" id="connectors"></svg>
<script> document.getElementById("qr1").src = "__QR_NOTEPAT__"; document.getElementById("qr2").src = "__QR_MENUBAND__"; document.getElementById("pals").src = "__PALS_LOGO__"; document.getElementById("jeffrey").src = "__JEFFREY_PIC__";
// Wait for fonts to load so the rendered PNG has glyphs. document.fonts.ready.then(() => { drawConnectors(); });
function drawConnectors() { const svg = document.getElementById("connectors"); // Both octaves — color-matched to the note. Lower octave saturated, // upper neon-tinted to match the dayglo swatches above. const naturals = [ // Lower octave: most prominent — these are the "self-naming" keys { pn: "c", qn: "c", color: "#ff3232", op: 0.85 }, { pn: "d", qn: "d", color: "#ffa000", op: 0.65 }, { pn: "e", qn: "e", color: "#d4b400", op: 0.55 }, { pn: "f", qn: "f", color: "#32c832", op: 0.50 }, { pn: "g", qn: "g", color: "#3278ff", op: 0.45 }, { pn: "a", qn: "a", color: "#8232c8", op: 0.40 }, { pn: "b", qn: "b", color: "#b450ff", op: 0.35 }, // Upper octave: shorter visual rhyme — dayglo to match neon swatches { pn: "C5", qn: "C5", color: "#ff2850", op: 0.55 }, { pn: "D5", qn: "D5", color: "#ffb400", op: 0.45 }, { pn: "E5", qn: "E5", color: "#b8b400", op: 0.40 }, { pn: "F5", qn: "F5", color: "#32ff64", op: 0.40 }, { pn: "G5", qn: "G5", color: "#32c8ff", op: 0.40 }, { pn: "A5", qn: "A5", color: "#b432ff", op: 0.35 }, { pn: "B5", qn: "B5", color: "#ff50ff", op: 0.32 }, ]; const NS = "http://www.w3.org/2000/svg"; for (const { pn, qn, color, op } of naturals) { const piano = document.querySelector(`.wkey[data-pn="${pn}"]`); const qwerty = document.querySelector(`.qcap[data-qn="${qn}"]`); if (!piano || !qwerty) continue; const pr = piano.getBoundingClientRect(); const qr = qwerty.getBoundingClientRect(); const x1 = pr.left + pr.width / 2; const y1 = pr.bottom - 12; const x2 = qr.left + qr.width / 2; const y2 = qr.top + 12; const line = document.createElementNS(NS, "line"); line.setAttribute("x1", x1); line.setAttribute("y1", y1); line.setAttribute("x2", x2); line.setAttribute("y2", y2); line.setAttribute("stroke", color); line.setAttribute("stroke-width", "4"); line.setAttribute("stroke-dasharray", "10 8"); line.setAttribute("stroke-linecap", "round"); line.setAttribute("opacity", op); svg.appendChild(line); const dotOp = Math.min(0.7, op * 0.8); for (const [cx, cy] of [[x1, y1], [x2, y2]]) { const dot = document.createElementNS(NS, "circle"); dot.setAttribute("cx", cx); dot.setAttribute("cy", cy); dot.setAttribute("r", 5); dot.setAttribute("fill", color); dot.setAttribute("opacity", dotOp); svg.appendChild(dot); } } } </script></body></html>