diff --git a/index.html b/index.html
index 2891715..f1f4e4c 100644
--- a/index.html
+++ b/index.html
@@ -1184,19 +1184,29 @@ function applyHashShare() {
}
// Demo set list (each item authored in the share language — also exercises the parser).
-const DEMOS = [
- ["Four-on-the-floor", "t120;kick:4;snare:4=.x.x;hatClosed:4/2"],
- ["Swing ride", "t150;ride:4/2s;kick:4=X..x;snare:4=.x.x"],
- ["Accents (click a pad to cycle)", "t92;kick:4=X..X;snare:4=.X.X;hatClosed:4/2"],
- ["5 over 4 polyrhythm", "t100;kick:4;claves:5~"],
- ["3 over 2 hemiola", "t96;woodblock:2;cowbell:3~"],
- ["2 & 4 & 3 over one bar", "t100;kick:3;cowbell:2~;claves:4~"],
- ["7/8 (2+2+3)", "t130;kick:2+2+3=x..x..x;hatClosed:2+2+3/2"],
- ["6/8 groove", "t100;kick:3+3=x..x..;snare:3+3=...x..;hatClosed:3+3/2"],
- ["5/4 (3+2)", "t112;kick:3+2=x..x.;snare:3+2=..x..;hatClosed:3+2/2"],
- ["Triplet hats", "t100;kick:4;snare:4=.x.x;hatClosed:4/3"],
- ["Tempo builder 80↑", "t80;woodblock:4;rmp80/4/4"],
- ["Gap trainer (play 2 / rest 2)", "t100;kick:4;hatClosed:4/2;tr2/2"],
+const SEED_SETLISTS = [
+ { title: "🥁 Styles", description: "Grooves & feels — load one, press Space, and click pads to shape the accents.", items: [
+ ["Four-on-the-floor", "t120;kick:4;snare:4=.x.x;hatClosed:4/2"],
+ ["Swing ride", "t150;ride:4/2s;kick:4=X..x;snare:4=.x.x"],
+ // Purdie half-time shuffle: triplet grid, backbeat on 3, snare ghosts (normal) around it
+ ["Purdie half-time shuffle", "t92;kick:4/3=X....x...x..;snare:4/3=..xx.xX.xx.x;hatClosed:4/3=X.xX.xX.xX.x"],
+ // Samba in 2/4 (16ths): surdo strong on beat 2, steady ganzá, tamborim teleco-teco
+ ["Samba (2/4)", "t104;tomLow:2/4=x...X...;hatClosed:2/4;woodblock:2/4=X.xx.xX."],
+ // Nañigo / 6/8 bembé bell over a 12/8 grid, low drum on the two main pulses
+ ["Nañigo (6/8 bembé)", "t130;cowbell:4/3=X.xx.x.xx.x.;kick:4/3=X.....X.....;hatClosed:4/3=..x..x..x..x"],
+ ["6/8 groove", "t100;kick:3+3=x..x..;snare:3+3=...x..;hatClosed:3+3/2"],
+ ["7/8 (2+2+3)", "t130;kick:2+2+3=x..x..x;hatClosed:2+2+3/2"],
+ ["5/4 (3+2)", "t112;kick:3+2=x..x.;snare:3+2=..x..;hatClosed:3+2/2"],
+ ] },
+ { title: "🎯 Practice", description: "Polyrhythms, independence and tempo / gap tools.", items: [
+ ["5 over 4 polyrhythm", "t100;kick:4;claves:5~"],
+ ["3 over 2 hemiola", "t96;woodblock:2;cowbell:3~"],
+ ["2 & 4 & 3 over one bar", "t100;kick:3;cowbell:2~;claves:4~"],
+ ["Triplet hats", "t100;kick:4;snare:4=.x.x;hatClosed:4/3"],
+ ["Accents — cycle the pads", "t92;kick:4=X..X;snare:4=.X.X;hatClosed:4/2"],
+ ["Tempo builder 80↑", "t80;woodblock:4;rmp80/4/4"],
+ ["Gap trainer (play 2 / rest 2)", "t100;kick:4;hatClosed:4/2;tr2/2"],
+ ] },
];
/* =========================================================================
@@ -1427,13 +1437,19 @@ window.addEventListener("keydown", (e) => {
});
/* init */
-// seed the demo set list once (first run only; not re-added if the user deletes it)
-if (!lsGet(LS.seeded, false)) {
- if (!setlists.length) {
- setlists.push({ title: "✨ Demos", description: "Click an item to load it, then press Space — meters, polyrhythms, odd time, subdivisions & practice tools.", items: DEMOS.map(([n, p]) => ({ name: n, ...patchToSetup(p) })) });
- activeSL = 0; saveSetlists();
+// Seed the demo set lists. Versioned + additive: a newer SEED_VERSION adds any
+// seed list whose title isn't already present, without clobbering the user's lists
+// (and won't re-add one they've deleted at the same version).
+const SEED_VERSION = 2;
+if ((lsGet(LS.seeded, 0) | 0) < SEED_VERSION) {
+ for (const s of SEED_SETLISTS) {
+ if (!setlists.some((x) => x.title === s.title)) {
+ setlists.push({ title: s.title, description: s.description, items: s.items.map(([n, p]) => ({ name: n, ...patchToSetup(p) })) });
+ }
}
- lsSet(LS.seeded, true);
+ if (activeSL >= setlists.length) activeSL = Math.max(0, setlists.length - 1);
+ saveSetlists();
+ lsSet(LS.seeded, SEED_VERSION);
}
// a shared link (#p=… settings / #sl=… set list) sets the state; otherwise default lanes
if (!applyHashShare()) {