diff --git a/index.html b/index.html
index bcd4d3d..93f4237 100644
--- a/index.html
+++ b/index.html
@@ -38,6 +38,10 @@ body { background:var(--bg); color:var(--text); font-family:-apple-system,BlinkM
.nav-badge.blk { background:var(--red-soft); color:var(--red); }
.s-reset { margin:6px 14px 0; padding:5px 10px; background:var(--surface3); border:1px solid var(--border); border-radius:5px; font-size:10px; color:var(--text-dim); cursor:pointer; text-align:center; }
.s-reset:hover { color:var(--red); border-color:var(--red); }
+.s-io { display:flex; gap:6px; margin:6px 14px 0; }
+.s-io-btn { flex:1; text-align:center; padding:5px 0; background:var(--surface3); border:1px solid var(--border); border-radius:5px; font-size:10px; color:var(--text-dim); cursor:pointer; }
+.s-io-btn:hover { color:var(--teal); border-color:var(--teal); }
+.s-io-btn.import:hover { color:var(--amber); border-color:var(--amber); }
.s-actions { display:flex; gap:6px; padding:10px 14px 0; }
.s-add-btn { flex:1; text-align:center; padding:5px 0; background:var(--surface2); border:1px solid var(--border2); border-radius:5px; font-size:10.5px; color:var(--text-dim); cursor:pointer; }
.s-add-btn:hover { color:var(--accent); border-color:var(--accent); }
@@ -393,6 +397,11 @@ body { background:var(--bg); color:var(--text); font-family:-apple-system,BlinkM
+ Gruppe
↺ Reset
+
+
@@ -825,6 +834,42 @@ const DEFAULTS = {
{id:'done', label:'Done', tasks:[{t:'Schema-Diff: source_type, author, year, isbn',note:'Frontmatter-Schema + Template dokumentiert'}]},
]
},
+ tiefgang: {
+ name:'Tiefgang', goal:'',
+ wipLimit:3, throughput:2, sle:{days:14,p:85},
+ cols:[
+ {id:'ready', label:'Ready', tasks:[]},
+ {id:'wip', label:'In Progress', tasks:[]},
+ {id:'done', label:'Done', tasks:[]},
+ ]
+ },
+ mdimmusic: {
+ name:'MDIM', goal:'mydrugismusic — Label & Artist-Kollektiv.',
+ wipLimit:3, throughput:2, sle:{days:14,p:85},
+ cols:[
+ {id:'ready', label:'Ready', tasks:[]},
+ {id:'wip', label:'In Progress', tasks:[]},
+ {id:'done', label:'Done', tasks:[]},
+ ]
+ },
+ droii: {
+ name:'DROII', goal:'',
+ wipLimit:3, throughput:2, sle:{days:14,p:85},
+ cols:[
+ {id:'ready', label:'Ready', tasks:[]},
+ {id:'wip', label:'In Progress', tasks:[]},
+ {id:'done', label:'Done', tasks:[]},
+ ]
+ },
+ soloprojekt: {
+ name:'Soloprojekt', goal:'',
+ wipLimit:3, throughput:2, sle:{days:14,p:85},
+ cols:[
+ {id:'ready', label:'Ready', tasks:[]},
+ {id:'wip', label:'In Progress', tasks:[]},
+ {id:'done', label:'Done', tasks:[]},
+ ]
+ },
};
// ── BOARD META (group + color + ring for defaults) ────────────────────────
@@ -845,16 +890,21 @@ const BOARD_META = {
degoogle: {group:'Privat', color:'#60a5fa', ring:'1p'},
bibliothek:{group:'Privat', color:'#7c6af7', ring:'1p'},
aikb: {group:'Privat', color:'#4ade80', ring:'1w'},
+ tiefgang: {group:'Musik', color:'#2dd4bf', ring:'1p'},
+ mdimmusic: {group:'Musik', color:'#c084fc', ring:'1p'},
+ droii: {group:'Musik', color:'#f87171', ring:'1p'},
+ soloprojekt:{group:'Musik', color:'#fbbf24', ring:'1p'},
};
const RINGS = ['0','1p','1w','2','3','?'];
const RING_LABELS = {'0':'R0','1p':'R1p','1w':'R1w','2':'R2','3':'R3','?':'?'};
const PICK_COLORS = ['#f87171','#fb923c','#fbbf24','#4ade80','#2dd4bf','#60a5fa','#7c6af7','#c084fc'];
-let GROUPS = ['Meta','Code','Beruflich','Web','Privat'];
+let GROUPS = ['Meta','Code','Beruflich','Web','Privat','Musik'];
function loadGroups() {
try { const g = JSON.parse(localStorage.getItem('kanban_groups')); if (Array.isArray(g)) GROUPS = g; } catch {}
- if (!GROUPS.includes('Meta')) { GROUPS.unshift('Meta'); saveGroups(); }
+ if (!GROUPS.includes('Meta')) { GROUPS.unshift('Meta'); saveGroups(); }
+ if (!GROUPS.includes('Musik')) { GROUPS.push('Musik'); saveGroups(); }
}
function saveGroups() { localStorage.setItem('kanban_groups', JSON.stringify(GROUPS)); }
@@ -2326,6 +2376,33 @@ loadIdeas();
renderIdeas();
show('doener');
setView('overview');
+
+// ── EXPORT / IMPORT ──────────────────────────────────────────────────────────
+function exportState() {
+ const keys = ['kanban_v2','kanban_groups','kanban_board_order','kanban_ideas','kanban_ideas_seeded'];
+ const snap = {};
+ keys.forEach(k => { const v = localStorage.getItem(k); if (v !== null) snap[k] = v; });
+ const blob = new Blob([JSON.stringify(snap, null, 2)], {type:'application/json'});
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(blob);
+ a.download = `kanban-backup-${new Date().toISOString().slice(0,10)}.json`;
+ a.click();
+}
+
+function importState(input) {
+ const file = input.files[0];
+ if (!file) return;
+ const reader = new FileReader();
+ reader.onload = e => {
+ try {
+ const snap = JSON.parse(e.target.result);
+ Object.entries(snap).forEach(([k, v]) => localStorage.setItem(k, v));
+ input.value = '';
+ location.reload();
+ } catch { alert('Ungültige Backup-Datei.'); }
+ };
+ reader.readAsText(file);
+}