feat(gui): gruene Nadel bei angehefteter Aufnahme, Logo fuehrt zu den Aufnahmen

Der Anheften-Knopf zeigte bei angehefteter Aufnahme nur die Zahl, die Nadel
blieb rot. Sie ist jetzt gruen (--ok, wie das "KI ✓"-Abzeichen). Dafuer
ersetzt ein SVG mit currentColor (ICON_PIN, gleiches Muster wie ICON_TABLE)
das 📌-Emoji: ein Farb-Emoji rendert immer rot, color greift daran nicht.

Klick auf Wellen-Logo und Schriftzug wechselt auf den Reiter "Aufnahmen".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
schakal00783
2026-08-02 23:14:41 +02:00
co-authored by Claude Opus 5
parent d0e02eb976
commit 3496b4a2df
4 changed files with 192 additions and 160 deletions
+12 -2
View File
@@ -33,7 +33,7 @@ function render() {
const theme = document.documentElement.dataset.theme || 'dark';
app.innerHTML = `
<header class="topbar">
<div class="brand">
<div class="brand" id="brandhome" title="Zu den Aufnahmen">
<svg class="brand-wave" viewBox="0 0 34 20" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><line x1="3" y1="7" x2="3" y2="13"/><line x1="9" y1="4" x2="9" y2="16"/><line x1="15" y1="1" x2="15" y2="19"/><line x1="21" y1="5" x2="21" y2="15"/><line x1="27" y1="8" x2="27" y2="12"/><line x1="33" y1="9.5" x2="33" y2="10.5"/></g></svg>
<h1>Aime <span class="sub">Anruf-Assistent</span></h1>
</div>
@@ -53,6 +53,12 @@ function render() {
</header>
<main id="view"></main>`;
app.querySelectorAll('.tab').forEach(b => b.onclick = () => { state.tab = b.dataset.tab; render(); });
// Logo + Schriftzug = Heimweg zurück auf die Aufnahmen.
app.querySelector('#brandhome').onclick = () => {
if (state.tab === 'recordings') return;
state.tab = 'recordings';
render();
};
app.querySelector('#themetoggle').onclick = () =>
applyTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark');
app.querySelector('#recbtn').onclick = toggleRecord;
@@ -903,7 +909,7 @@ async function refreshRecList() {
${r.summary ? `<div class="summary-snip">${escapeHtml(r.summary)}</div>` : ''}
</div>
<button class="btn icon pinbtn ${pinCounts[r.id] ? 'pinned' : ''}" data-pin="${r.id}"
title="${pinCounts[r.id] ? `In ${pinCounts[r.id]} Projekt(en) angeheftet — verwalten` : 'An ein Projekt anheften'}">📌${pinCounts[r.id] ? `<span class="pin-n">${pinCounts[r.id]}</span>` : ''}</button>
title="${pinCounts[r.id] ? `In ${pinCounts[r.id]} Projekt(en) angeheftet — verwalten` : 'An ein Projekt anheften'}">${ICON_PIN}${pinCounts[r.id] ? `<span class="pin-n">${pinCounts[r.id]}</span>` : ''}</button>
<button class="btn icon" data-ren="${r.id}" title="Titel umbenennen">✏️</button>
<button class="btn danger icon" data-del="${r.id}" title="In den Papierkorb">🗑</button>
</div>`; }).join('');
@@ -1500,6 +1506,10 @@ const BUBBLE_W = 54;
function tableSeats(n) { return SEAT_LAYOUTS[Math.min(6, Math.max(1, n))] || SEAT_LAYOUTS[6]; }
// Toggle-button icons: three people around a table / a text sheet.
// Stecknadel als SVG statt 📌: ein Farb-Emoji bleibt immer rot, `currentColor`
// lässt sich dagegen einfärben — angeheftet = grün, sonst blass wie die
// übrigen Zeilenknöpfe.
const ICON_PIN = `<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 3.5h6l-1 5 3.2 3.2H6.8L10 8.5z"/><line x1="12" y1="11.7" x2="12" y2="20.5"/></g></svg>`;
const ICON_TABLE = `<svg viewBox="0 0 24 24" width="17" height="17" aria-hidden="true"><g fill="currentColor"><rect x="6" y="10" width="12" height="6" rx="2" fill="none" stroke="currentColor" stroke-width="1.6"/><circle cx="12" cy="4.6" r="2.1"/><circle cx="4" cy="19.4" r="2.1"/><circle cx="20" cy="19.4" r="2.1"/></g></svg>`;
const ICON_SHEET = `<svg viewBox="0 0 24 24" width="17" height="17" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><rect x="5" y="3" width="14" height="18" rx="2"/><line x1="8.5" y1="8" x2="15.5" y2="8"/><line x1="8.5" y1="12" x2="15.5" y2="12"/><line x1="8.5" y1="16" x2="13" y2="16"/></g></svg>`;
+163 -155
View File
@@ -395,158 +395,166 @@ body.resizing { cursor: col-resize; user-select: none; }
@media (prefers-reduced-motion: reduce) {
* { transition: none !important; animation: none !important; }
}
/* ==========================================================================
Suche — Google-Anmutung, aber in der Aime-Palette: viel Weißraum, eine
dominante Eingabezeile, Treffer als Textblöcke ohne Karten-Rahmen.
========================================================================== */
.search-page { max-width: 46rem; margin: 0 auto; padding: 1rem 1rem 4rem; }
/* Startzustand: Suchfeld optisch mittig, wie eine leere Suchseite. */
.search-page.landing { padding-top: 12vh; }
.search-page.has-results { padding-top: 1.25rem; }
.search-box {
display: flex; align-items: center; gap: .5rem;
border: 1px solid var(--line); border-radius: 2rem;
background: var(--surface); box-shadow: var(--shadow);
padding: .35rem .35rem .35rem 1rem;
transition: box-shadow .15s, border-color .15s;
}
.search-box:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.search-ico { opacity: .55; font-size: 1rem; }
.search-input {
flex: 1; border: 0; outline: 0; background: transparent; color: var(--fg);
font: inherit; font-size: 1.05rem; padding: .55rem 0;
}
.search-clear { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: .95rem; padding: .25rem .4rem; }
.search-clear:hover { color: var(--fg); }
.search-go {
border: 0; border-radius: 1.6rem; cursor: pointer;
background: var(--accent); color: var(--accent-fg);
font: inherit; font-weight: 600; padding: .55rem 1.1rem;
}
.search-go:hover { filter: brightness(1.07); }
.search-hints { margin-top: 1.5rem; display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; }
.search-hints .example {
border: 1px solid var(--line); border-radius: 1rem; background: var(--surface-2);
color: var(--fg); font: inherit; font-size: .88rem; padding: .35rem .8rem; cursor: pointer; text-align: left;
}
.search-hints .example:hover { border-color: var(--accent); color: var(--accent); }
.searching { padding: 1.5rem 0; }
.search-empty { padding: 1.5rem 0; }
/* Antwortkasten: abgesetzt wie eine KI-Übersicht, nicht wie ein Treffer. */
.answer-box {
margin: 1.25rem 0 .5rem; padding: .9rem 1rem;
background: var(--accent-soft); border: 1px solid var(--line); border-radius: .75rem;
}
.answer-head { font-weight: 600; font-size: .82rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-bottom: .5rem; }
.answer-body { line-height: 1.55; white-space: pre-wrap; }
/* Platzhalterbalken, solange das LLM rechnet (30-90 s sind hier normal). */
.answer-body.skeleton { display: flex; flex-direction: column; gap: .45rem; }
.answer-body.skeleton span {
height: .7rem; border-radius: .35rem; background: var(--line); opacity: .55;
animation: pulse 1.4s ease-in-out infinite;
}
.answer-body.skeleton span:nth-child(1) { width: 92%; }
.answer-body.skeleton span:nth-child(2) { width: 78%; animation-delay: .18s; }
.answer-body.skeleton span:nth-child(3) { width: 45%; animation-delay: .36s; }
@keyframes pulse { 0%, 100% { opacity: .3; } 50% { opacity: .7; } }
.answer-src { margin-top: .7rem; display: flex; flex-wrap: wrap; gap: .4rem; }
.src-chip {
border: 1px solid var(--line); background: var(--surface); color: var(--fg);
border-radius: 1rem; font: inherit; font-size: .8rem; padding: .2rem .6rem; cursor: pointer;
}
.src-chip:hover { border-color: var(--accent); color: var(--accent); }
.result-meta { margin: .9rem 0 .3rem; }
.results { list-style: none; margin: 0; padding: 0; }
.result { padding: .85rem 0; cursor: pointer; border-bottom: 1px solid var(--line); }
.result:hover .result-title { text-decoration: underline; }
.result-src { color: var(--muted); font-size: .78rem; margin-bottom: .15rem; }
.result-title { display: block; color: var(--accent); font-size: 1.05rem; text-decoration: none; }
.result-at { color: var(--muted); font-size: .8rem; font-weight: 400; margin-left: .4rem; }
.result-snip { color: var(--fg); font-size: .9rem; line-height: 1.5; margin-top: .2rem; }
.result-snip mark { background: var(--warn-soft); color: inherit; font-weight: 600; padding: 0 .1em; border-radius: .15em; }
/* ==========================================================================
Papierkorb + Umbenennen
========================================================================== */
.list-bar { display: flex; justify-content: flex-end; padding: .35rem .5rem; border-bottom: 1px solid var(--line); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { color: var(--fg); border-color: var(--line); }
.btn.ghost.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.trash-hint, .trash-empty { padding: .6rem .75rem; }
.item.rec.trashed { opacity: .8; }
.item.rec.trashed b { text-decoration: line-through; text-decoration-color: var(--muted); }
.days-left { color: var(--muted); }
.days-left.urgent { color: var(--danger); font-weight: 600; }
/* Der Stift sitzt neben der H2 des Detailkopfs, ohne die Zeile umzubrechen. */
.rename-btn { vertical-align: middle; margin-left: -.25rem; opacity: .55; }
.rename-btn:hover { opacity: 1; }
.item.rec [data-ren] { opacity: .45; }
.item.rec:hover [data-ren] { opacity: 1; }
@media (max-width: 640px) {
.search-page.landing { padding-top: 6vh; }
.search-go { padding: .55rem .8rem; }
}
/* Abschnittstitel in der Zusammenfassung ("Neuer Projektleiter vorgestellt:").
Etwas Luft darüber, damit die Blöcke optisch trennen — der Text steht in
white-space: pre-line, die Zeilenumbrüche kommen also aus dem Text selbst. */
.summary .sum-head {
font-weight: 700;
color: var(--fg);
line-height: 2.2;
}
/* ---- Projektansicht ---------------------------------------------------------
Ordnergitter (Ebene 1) und darin eine Reiterleiste für die Unterreiter
(Ebene 2). Die Reiter sehen bewusst anders aus als die Kopfzeilen-Tabs, damit
klar bleibt: das ist eine Ebene INNERHALB eines Ordners. */
.proj-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.proj-head h3 { margin: 0; flex: 1; }
.proj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; margin-top: 10px; }
.proj-card {
display: flex; align-items: center; gap: 10px; cursor: pointer;
background: var(--surface-2); border: 1px solid var(--line);
border-radius: 10px; padding: 12px 14px; transition: border-color .1s, background .1s;
}
.proj-card:hover { border-color: var(--accent); }
.proj-card .grow { flex: 1; min-width: 0; }
.proj-card b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-ico { font-size: 22px; flex: none; }
.proj-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 14px 0 0; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
.ptab {
background: transparent; border: 1px solid transparent; color: var(--muted);
border-radius: 8px 8px 0 0; padding: 6px 12px; cursor: pointer; font: inherit; font-size: .9rem;
}
.ptab:hover { color: var(--fg); background: var(--surface-2); }
.ptab.active { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }
.ptab.add { color: var(--muted); border-style: dashed; border-color: var(--line); }
.ptab.add:hover { color: var(--accent); border-color: var(--accent); }
.ptab-n { font-size: 11px; opacity: .7; margin-left: 4px; }
.proj-level { margin-top: 14px; }
.proj-level-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.proj-level-head .grow { flex: 1; }
.proj-level .item.rec { cursor: pointer; }
/* 📌 in der Aufnahmenliste: blass, solange die Aufnahme nirgends hängt. */
.pinbtn { opacity: .45; position: relative; }
.item.rec:hover .pinbtn { opacity: 1; }
.pinbtn.pinned { opacity: 1; border-color: var(--accent); color: var(--accent); }
.pin-n { font-size: 10px; font-weight: 700; margin-left: 2px; vertical-align: super; }
/* ---- Modal ---- */
.modal-back {
position: fixed; inset: 0; background: rgba(0, 0, 0, .5);
display: flex; align-items: center; justify-content: center; z-index: 50; padding: 20px;
}
.modal { width: min(520px, 100%); max-height: 85vh; overflow: auto; margin: 0; }
.modal h3 { margin-top: 0; }
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.modal select[size] { height: auto; padding: 4px; }
.pin-current .item { padding: 6px 10px; }
/* ==========================================================================
Suche — Google-Anmutung, aber in der Aime-Palette: viel Weißraum, eine
dominante Eingabezeile, Treffer als Textblöcke ohne Karten-Rahmen.
========================================================================== */
.search-page { max-width: 46rem; margin: 0 auto; padding: 1rem 1rem 4rem; }
/* Startzustand: Suchfeld optisch mittig, wie eine leere Suchseite. */
.search-page.landing { padding-top: 12vh; }
.search-page.has-results { padding-top: 1.25rem; }
.search-box {
display: flex; align-items: center; gap: .5rem;
border: 1px solid var(--line); border-radius: 2rem;
background: var(--surface); box-shadow: var(--shadow);
padding: .35rem .35rem .35rem 1rem;
transition: box-shadow .15s, border-color .15s;
}
.search-box:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.search-ico { opacity: .55; font-size: 1rem; }
.search-input {
flex: 1; border: 0; outline: 0; background: transparent; color: var(--fg);
font: inherit; font-size: 1.05rem; padding: .55rem 0;
}
.search-clear { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: .95rem; padding: .25rem .4rem; }
.search-clear:hover { color: var(--fg); }
.search-go {
border: 0; border-radius: 1.6rem; cursor: pointer;
background: var(--accent); color: var(--accent-fg);
font: inherit; font-weight: 600; padding: .55rem 1.1rem;
}
.search-go:hover { filter: brightness(1.07); }
.search-hints { margin-top: 1.5rem; display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; }
.search-hints .example {
border: 1px solid var(--line); border-radius: 1rem; background: var(--surface-2);
color: var(--fg); font: inherit; font-size: .88rem; padding: .35rem .8rem; cursor: pointer; text-align: left;
}
.search-hints .example:hover { border-color: var(--accent); color: var(--accent); }
.searching { padding: 1.5rem 0; }
.search-empty { padding: 1.5rem 0; }
/* Antwortkasten: abgesetzt wie eine KI-Übersicht, nicht wie ein Treffer. */
.answer-box {
margin: 1.25rem 0 .5rem; padding: .9rem 1rem;
background: var(--accent-soft); border: 1px solid var(--line); border-radius: .75rem;
}
.answer-head { font-weight: 600; font-size: .82rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-bottom: .5rem; }
.answer-body { line-height: 1.55; white-space: pre-wrap; }
/* Platzhalterbalken, solange das LLM rechnet (30-90 s sind hier normal). */
.answer-body.skeleton { display: flex; flex-direction: column; gap: .45rem; }
.answer-body.skeleton span {
height: .7rem; border-radius: .35rem; background: var(--line); opacity: .55;
animation: pulse 1.4s ease-in-out infinite;
}
.answer-body.skeleton span:nth-child(1) { width: 92%; }
.answer-body.skeleton span:nth-child(2) { width: 78%; animation-delay: .18s; }
.answer-body.skeleton span:nth-child(3) { width: 45%; animation-delay: .36s; }
@keyframes pulse { 0%, 100% { opacity: .3; } 50% { opacity: .7; } }
.answer-src { margin-top: .7rem; display: flex; flex-wrap: wrap; gap: .4rem; }
.src-chip {
border: 1px solid var(--line); background: var(--surface); color: var(--fg);
border-radius: 1rem; font: inherit; font-size: .8rem; padding: .2rem .6rem; cursor: pointer;
}
.src-chip:hover { border-color: var(--accent); color: var(--accent); }
.result-meta { margin: .9rem 0 .3rem; }
.results { list-style: none; margin: 0; padding: 0; }
.result { padding: .85rem 0; cursor: pointer; border-bottom: 1px solid var(--line); }
.result:hover .result-title { text-decoration: underline; }
.result-src { color: var(--muted); font-size: .78rem; margin-bottom: .15rem; }
.result-title { display: block; color: var(--accent); font-size: 1.05rem; text-decoration: none; }
.result-at { color: var(--muted); font-size: .8rem; font-weight: 400; margin-left: .4rem; }
.result-snip { color: var(--fg); font-size: .9rem; line-height: 1.5; margin-top: .2rem; }
.result-snip mark { background: var(--warn-soft); color: inherit; font-weight: 600; padding: 0 .1em; border-radius: .15em; }
/* ==========================================================================
Papierkorb + Umbenennen
========================================================================== */
.list-bar { display: flex; justify-content: flex-end; padding: .35rem .5rem; border-bottom: 1px solid var(--line); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { color: var(--fg); border-color: var(--line); }
.btn.ghost.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.trash-hint, .trash-empty { padding: .6rem .75rem; }
.item.rec.trashed { opacity: .8; }
.item.rec.trashed b { text-decoration: line-through; text-decoration-color: var(--muted); }
.days-left { color: var(--muted); }
.days-left.urgent { color: var(--danger); font-weight: 600; }
/* Der Stift sitzt neben der H2 des Detailkopfs, ohne die Zeile umzubrechen. */
.rename-btn { vertical-align: middle; margin-left: -.25rem; opacity: .55; }
.rename-btn:hover { opacity: 1; }
.item.rec [data-ren] { opacity: .45; }
.item.rec:hover [data-ren] { opacity: 1; }
@media (max-width: 640px) {
.search-page.landing { padding-top: 6vh; }
.search-go { padding: .55rem .8rem; }
}
/* Abschnittstitel in der Zusammenfassung ("Neuer Projektleiter vorgestellt:").
Etwas Luft darüber, damit die Blöcke optisch trennen — der Text steht in
white-space: pre-line, die Zeilenumbrüche kommen also aus dem Text selbst. */
.summary .sum-head {
font-weight: 700;
color: var(--fg);
line-height: 2.2;
}
/* ---- Projektansicht ---------------------------------------------------------
Ordnergitter (Ebene 1) und darin eine Reiterleiste für die Unterreiter
(Ebene 2). Die Reiter sehen bewusst anders aus als die Kopfzeilen-Tabs, damit
klar bleibt: das ist eine Ebene INNERHALB eines Ordners. */
.proj-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.proj-head h3 { margin: 0; flex: 1; }
.proj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; margin-top: 10px; }
.proj-card {
display: flex; align-items: center; gap: 10px; cursor: pointer;
background: var(--surface-2); border: 1px solid var(--line);
border-radius: 10px; padding: 12px 14px; transition: border-color .1s, background .1s;
}
.proj-card:hover { border-color: var(--accent); }
.proj-card .grow { flex: 1; min-width: 0; }
.proj-card b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-ico { font-size: 22px; flex: none; }
.proj-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 14px 0 0; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
.ptab {
background: transparent; border: 1px solid transparent; color: var(--muted);
border-radius: 8px 8px 0 0; padding: 6px 12px; cursor: pointer; font: inherit; font-size: .9rem;
}
.ptab:hover { color: var(--fg); background: var(--surface-2); }
.ptab.active { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }
.ptab.add { color: var(--muted); border-style: dashed; border-color: var(--line); }
.ptab.add:hover { color: var(--accent); border-color: var(--accent); }
.ptab-n { font-size: 11px; opacity: .7; margin-left: 4px; }
.proj-level { margin-top: 14px; }
.proj-level-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.proj-level-head .grow { flex: 1; }
.proj-level .item.rec { cursor: pointer; }
/* Stecknadel in der Aufnahmenliste: blass, solange die Aufnahme nirgends
hängt — angeheftet wird sie gruen (dieselbe Farbe wie „KI ✓“, also
„erledigt/zugeordnet“). Das Icon ist ein SVG mit currentColor; ein 📌-Emoji
wäre in jedem Zustand rot geblieben. */
.pinbtn { opacity: .45; position: relative; display: inline-flex; align-items: center; gap: 1px; }
.item.rec:hover .pinbtn { opacity: 1; }
.pinbtn.pinned { opacity: 1; border-color: var(--ok); color: var(--ok); background: var(--ok-soft); }
.pin-n { font-size: 10px; font-weight: 700; vertical-align: super; }
/* ---- Modal ---- */
.modal-back {
position: fixed; inset: 0; background: rgba(0, 0, 0, .5);
display: flex; align-items: center; justify-content: center; z-index: 50; padding: 20px;
}
.modal { width: min(520px, 100%); max-height: 85vh; overflow: auto; margin: 0; }
.modal h3 { margin-top: 0; }
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.modal select[size] { height: auto; padding: 4px; }
.pin-current .item { padding: 6px 10px; }
/* Logo + Schriftzug führen zurück auf die Aufnahmen. */
.brand { cursor: pointer; user-select: none; }
.brand:hover .brand-wave { filter: brightness(1.15); }
.brand:hover h1 { color: var(--accent); }
+12
View File
@@ -3,6 +3,18 @@
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
Was, Warum, betroffene Dateien/Backups).
## 2026-08-02 (nachgereicht) — Grüne Nadel, Logo führt zurück zu den Aufnahmen
**Nadel grün statt rot:** der Anheften-Knopf in der Aufnahmenliste zeigte bei einer angehefteten Aufnahme
nur die Zahl, die Nadel selbst blieb rot. Sie ist jetzt grün (`--ok`, dieselbe Farbe wie das „KI ✓"-Abzeichen).
Dafür musste das **📌-Emoji einem SVG mit `currentColor` weichen** (`ICON_PIN`, gleiches Muster wie
`ICON_TABLE`/`ICON_SHEET`): ein Farb-Emoji rendert die Schriftart immer rot, `color` greift daran nicht.
**Logo als Heimweg:** ein Klick auf Wellen-Logo und Schriftzug „Aime" wechselt auf den Reiter „Aufnahmen"
(`#brandhome` in `render()`), mit Zeiger-Cursor und Hover-Andeutung als Hinweis darauf.
Dateien: `app/web/src/main.js`, `app/web/src/style.css`.
## 2026-08-02 (nachgereicht) — Ordner-Ebene umbenennbar
Der erste Reiter eines Projekts hieß fest „Ordner". Er trägt jetzt einen frei wählbaren Namen, genau wie
+5 -3
View File
@@ -84,9 +84,11 @@ flowchart LR
end
```
Der 📌-Knopf in der Aufnahmenliste trägt die Zahl der Projekte, in denen die Aufnahme hängt, und ist
farbig markiert, sobald sie irgendwo angeheftet ist (`GET /api/pins/counts` — ein Request für die ganze
Liste, nicht einer pro Zeile). Die Zahl steckt zusätzlich in der Listen-Signatur `state.lastListSig`, damit
Der Nadel-Knopf in der Aufnahmenliste trägt die Zahl der Projekte, in denen die Aufnahme hängt, und wird
**grün** (`--ok`, dieselbe Farbe wie „KI ✓"), sobald sie irgendwo angeheftet ist — sonst bleibt er blass
wie die übrigen Zeilenknöpfe (`GET /api/pins/counts` — ein Request für die ganze Liste, nicht einer pro
Zeile). Die Nadel ist deshalb ein **SVG mit `currentColor` (`ICON_PIN`) und kein 📌-Emoji**: ein
Farb-Emoji ist in jedem Zustand rot und lässt sich per CSS nicht umfärben. Die Zahl steckt zusätzlich in der Listen-Signatur `state.lastListSig`, damit
eine neue Anheftung die Liste neu zeichnet, ohne die 5-Sekunden-Regel („keine Änderung → DOM nicht
anfassen") aufzuweichen.