Social: Modernes Design — Cards, Pill-Buttons, Shadows, SW by-v359

This commit is contained in:
rene 2026-04-25 08:19:45 +02:00
parent 8ba8f4dfa3
commit 74b6c03bb3
3 changed files with 238 additions and 146 deletions

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung. Router, State-Management, Navigation, Initialisierung.
============================================================ */ ============================================================ */
const APP_VER = '343'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VER = '344'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const App = (() => { const App = (() => {

View file

@ -43,9 +43,11 @@ window.Page_social = (() => {
function _render() { function _render() {
const lvlBar = _stats ? _levelBar(_stats) : ''; const lvlBar = _stats ? _levelBar(_stats) : '';
_el.innerHTML = ` _el.innerHTML = `
<div style="margin-bottom:var(--space-3)"> <div style="background:var(--c-surface);border-radius:var(--radius-lg);
<div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-2)"> box-shadow:var(--shadow-sm);padding:var(--space-4);
<span style="font-size:1.5em">📱</span> margin-bottom:var(--space-4)">
<div style="display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-3)">
<span style="font-size:1.6em">📱</span>
<div style="flex:1;min-width:0"> <div style="flex:1;min-width:0">
<div style="font-size:var(--text-base);font-weight:700">Social Media</div> <div style="font-size:var(--text-base);font-weight:700">Social Media</div>
<div style="font-size:11px;color:var(--c-text-muted)">Luna ist dein KI-Coach</div> <div style="font-size:11px;color:var(--c-text-muted)">Luna ist dein KI-Coach</div>
@ -60,7 +62,7 @@ window.Page_social = (() => {
<!-- Tabs --> <!-- Tabs -->
<div style="display:flex;border-bottom:2px solid var(--c-border); <div style="display:flex;border-bottom:2px solid var(--c-border);
margin-bottom:var(--space-3)"> margin-bottom:var(--space-4)">
${[['idee','✨ Ideen'],['archiv','📂 Archiv'],['bewerten','🔍 Prüfen']].map(([t,l]) => ` ${[['idee','✨ Ideen'],['archiv','📂 Archiv'],['bewerten','🔍 Prüfen']].map(([t,l]) => `
<button class="sm-tab" data-tab="${t}" style="flex:1;padding:10px 4px;border:none; <button class="sm-tab" data-tab="${t}" style="flex:1;padding:10px 4px;border:none;
background:none;cursor:pointer;font-size:13px;white-space:nowrap; background:none;cursor:pointer;font-size:13px;white-space:nowrap;
@ -86,13 +88,13 @@ window.Page_social = (() => {
((s.xp - s.xp_current_min) / (s.xp_next - s.xp_current_min)) * 100)); ((s.xp - s.xp_current_min) / (s.xp_next - s.xp_current_min)) * 100));
return `<div> return `<div>
<div style="display:flex;justify-content:space-between;font-size:12px; <div style="display:flex;justify-content:space-between;font-size:12px;
color:var(--c-text);margin-bottom:4px;font-weight:500"> color:var(--c-text);margin-bottom:6px;font-weight:500">
<span>${s.level}</span> <span>${s.level}</span>
${s.next_level ? `<span style="color:var(--c-text-secondary)">${s.xp_next - s.xp} XP bis ${s.next_level}</span>` : ''} ${s.next_level ? `<span style="color:var(--c-text-secondary)">${s.xp_next - s.xp} XP bis ${s.next_level}</span>` : ''}
</div> </div>
<div style="background:var(--c-border);border-radius:4px;height:6px;overflow:hidden"> <div style="background:var(--c-surface-2);border-radius:var(--radius-full);height:8px;overflow:hidden">
<div style="height:100%;background:var(--c-primary);width:${pct}%; <div style="height:100%;background:linear-gradient(90deg,var(--c-primary),var(--c-primary-light));
border-radius:4px;transition:width .5s"></div> width:${pct}%;border-radius:var(--radius-full);transition:width .5s"></div>
</div> </div>
</div>`; </div>`;
} }
@ -105,14 +107,15 @@ window.Page_social = (() => {
el.innerHTML = ` el.innerHTML = `
<!-- Luna --> <!-- Luna -->
<div style="background:var(--c-surface-2); <div style="background:var(--c-surface);border-radius:var(--radius-lg);
border-radius:12px;padding:12px;margin-bottom:var(--space-3); box-shadow:var(--shadow-sm);padding:var(--space-4);
display:flex;gap:10px;align-items:flex-start"> margin-bottom:var(--space-4);
<span style="font-size:1.8em;flex-shrink:0">🌙</span> display:flex;gap:var(--space-3);align-items:flex-start">
<span style="font-size:2em;flex-shrink:0">🌙</span>
<div> <div>
<div style="font-weight:700;font-size:var(--text-sm);margin-bottom:2px"> <div style="font-weight:700;font-size:var(--text-sm);margin-bottom:4px">
Hey, ich bin Luna 👋</div> Hey, ich bin Luna 👋</div>
<div style="font-size:13px;color:var(--c-text);line-height:1.5"> <div style="font-size:13px;color:var(--c-text-secondary);line-height:1.6">
Ich schlage dir Ideen vor und erkläre warum sie funktionieren. Ich schlage dir Ideen vor und erkläre warum sie funktionieren.
Lern Social Media richtig nicht nur kopieren!</div> Lern Social Media richtig nicht nur kopieren!</div>
</div> </div>
@ -120,9 +123,9 @@ window.Page_social = (() => {
<!-- Diversitäts-Warnung --> <!-- Diversitäts-Warnung -->
${_diversity?.warning ? ` ${_diversity?.warning ? `
<div style="background:var(--c-surface-2);border:2px solid var(--c-warning); <div style="background:var(--c-warning-subtle);border:1.5px solid var(--c-warning);
border-radius:12px;padding:12px;margin-bottom:var(--space-3)"> border-radius:var(--radius-lg);padding:var(--space-4);margin-bottom:var(--space-4)">
<div style="display:flex;gap:8px;align-items:flex-start"> <div style="display:flex;gap:var(--space-3);align-items:flex-start">
<span style="font-size:1.3em;flex-shrink:0"></span> <span style="font-size:1.3em;flex-shrink:0"></span>
<div> <div>
<div style="font-weight:700;font-size:var(--text-sm);color:var(--c-warning); <div style="font-weight:700;font-size:var(--text-sm);color:var(--c-warning);
@ -139,64 +142,74 @@ window.Page_social = (() => {
</div>` : ''} </div>` : ''}
<!-- Vorschläge --> <!-- Vorschläge -->
<div style="margin-bottom:var(--space-4)"> <div style="background:var(--c-surface);border-radius:var(--radius-lg);
box-shadow:var(--shadow-sm);padding:var(--space-4);
margin-bottom:var(--space-4)">
<div style="display:flex;align-items:center;justify-content:space-between; <div style="display:flex;align-items:center;justify-content:space-between;
margin-bottom:var(--space-2)"> margin-bottom:var(--space-3)">
<div style="font-weight:600;font-size:var(--text-sm)">💡 Was könntest du heute posten?</div> <div style="font-weight:700;font-size:var(--text-sm)">💡 Was könntest du heute posten?</div>
<button id="sm-refresh" class="btn btn-sm btn-secondary" <button id="sm-refresh" class="btn btn-sm btn-secondary"
style="font-size:11px;padding:3px 10px;min-height:30px"> Neue</button> style="font-size:11px;padding:4px 12px;min-height:32px;
border-radius:var(--radius-full)"> Neue</button>
</div> </div>
<div id="sm-suggestions"> <div id="sm-suggestions">
${_lunaThinking('Klein...')} ${_lunaThinking('Klein...')}
</div> </div>
</div> </div>
<div style="border-top:1px solid var(--c-border);padding-top:var(--space-3); <div style="display:flex;align-items:center;gap:var(--space-3);
margin-bottom:var(--space-2)"> margin-bottom:var(--space-3)">
<div style="font-weight:600;font-size:var(--text-sm)"> Oder eigenes Thema</div> <div style="flex:1;height:1px;background:var(--c-border)"></div>
<div style="font-weight:600;font-size:var(--text-sm);color:var(--c-text-muted);
white-space:nowrap"> Oder eigenes Thema</div>
<div style="flex:1;height:1px;background:var(--c-border)"></div>
</div> </div>
<!-- Formular --> <!-- Formular -->
<div class="card" style="padding:var(--space-3)"> <div style="background:var(--c-surface);border-radius:var(--radius-lg);
box-shadow:var(--shadow-sm);padding:var(--space-4)">
<!-- Plattform --> <!-- Plattform -->
<div style="margin-bottom:var(--space-3)"> <div style="margin-bottom:var(--space-4)">
<div class="sm-label">Plattform</div> <div class="sm-label">Plattform</div>
<div style="display:flex;gap:var(--space-2)"> <div style="display:flex;gap:var(--space-2)">
${['both','instagram','tiktok'].map((p,i) => ` ${['both','instagram','tiktok'].map((p,i) => `
<button class="btn btn-sm sm-plat ${i===0?'btn-primary':'btn-secondary'}" <button class="btn btn-sm sm-plat ${i===0?'btn-primary':'btn-secondary'}"
data-p="${p}" style="flex:1;min-height:38px;font-size:12px;padding:4px"> data-p="${p}" style="flex:1;min-height:36px;font-size:12px;padding:4px 8px;
border-radius:var(--radius-full)">
${_PL[p]}</button>`).join('')} ${_PL[p]}</button>`).join('')}
</div> </div>
</div> </div>
<!-- Format --> <!-- Format -->
<div style="margin-bottom:var(--space-3)"> <div style="margin-bottom:var(--space-4)">
<div class="sm-label">Format</div> <div class="sm-label">Format</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2)"> <div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2)">
${['post','reel','story','carousel'].map((f,i) => ` ${['post','reel','story','carousel'].map((f,i) => `
<button class="btn btn-sm sm-fmt ${i===0?'btn-primary':'btn-secondary'}" <button class="btn btn-sm sm-fmt ${i===0?'btn-primary':'btn-secondary'}"
data-f="${f}" style="min-height:38px;font-size:12px;padding:4px"> data-f="${f}" style="min-height:36px;font-size:12px;padding:4px 8px;
border-radius:var(--radius-full)">
${_FL[f]}</button>`).join('')} ${_FL[f]}</button>`).join('')}
</div> </div>
</div> </div>
<!-- Thema --> <!-- Thema -->
<div style="margin-bottom:var(--space-3)"> <div style="margin-bottom:var(--space-4)">
<div class="sm-label">Thema</div> <div class="sm-label">Thema</div>
<textarea id="sm-topic" rows="3" <textarea id="sm-topic" rows="3"
placeholder="z.B. Mein Hund beim ersten Schnee 🐾" placeholder="z.B. Mein Hund beim ersten Schnee 🐾"
style="width:100%;font-size:var(--text-sm);resize:none;line-height:1.5; style="width:100%;font-size:var(--text-sm);resize:none;line-height:1.5;
background:var(--c-surface-2);color:var(--c-text); background:var(--c-surface-2);color:var(--c-text);
border:1.5px solid var(--c-border);border-radius:8px; border:1.5px solid var(--c-border);border-radius:var(--radius-md);
padding:10px 12px;box-sizing:border-box; padding:10px 12px;box-sizing:border-box;
font-family:inherit"></textarea> font-family:inherit"></textarea>
</div> </div>
<!-- "Was jetzt?"-Banner --> <!-- "Was jetzt?"-Banner -->
<div id="sm-next-hint" style="display:none;background:var(--c-primary); <div id="sm-next-hint" style="display:none;background:var(--c-primary);
color:#fff;border-radius:8px;padding:10px 12px;margin-bottom:var(--space-3); color:#fff;border-radius:var(--radius-md);padding:10px 14px;
margin-bottom:var(--space-4);
font-size:var(--text-sm);font-weight:600;text-align:center"> font-size:var(--text-sm);font-weight:600;text-align:center">
Idee übernommen prüf die Einstellungen und tippe auf <strong>Los geht's!</strong> 👇 Idee übernommen prüf die Einstellungen und tippe auf <strong>Los geht's!</strong> 👇
</div> </div>
<!-- Medien-Upload --> <!-- Medien-Upload -->
<div style="margin-bottom:var(--space-3)"> <div style="margin-bottom:var(--space-4)">
<div class="sm-label">Foto / Video (optional)</div> <div class="sm-label">Foto / Video (optional)</div>
<div style="display:flex;gap:var(--space-2);flex-wrap:wrap"> <div style="display:flex;gap:var(--space-2);flex-wrap:wrap">
<label style="cursor:pointer;flex:1"> <label style="cursor:pointer;flex:1">
@ -204,7 +217,7 @@ window.Page_social = (() => {
capture="environment" style="display:none"> capture="environment" style="display:none">
<span class="btn btn-secondary btn-sm" <span class="btn btn-secondary btn-sm"
style="min-height:40px;display:flex;align-items:center;justify-content:center; style="min-height:40px;display:flex;align-items:center;justify-content:center;
gap:6px;font-size:12px;width:100%"> gap:6px;font-size:12px;width:100%;border-radius:var(--radius-full)">
📷 Kamera / Mediathek</span> 📷 Kamera / Mediathek</span>
</label> </label>
<label style="cursor:pointer;flex:1"> <label style="cursor:pointer;flex:1">
@ -212,32 +225,35 @@ window.Page_social = (() => {
style="display:none"> style="display:none">
<span class="btn btn-secondary btn-sm" <span class="btn btn-secondary btn-sm"
style="min-height:40px;display:flex;align-items:center;justify-content:center; style="min-height:40px;display:flex;align-items:center;justify-content:center;
gap:6px;font-size:12px;width:100%"> gap:6px;font-size:12px;width:100%;border-radius:var(--radius-full)">
📁 Dateien</span> 📁 Dateien</span>
</label> </label>
</div> </div>
<div id="sm-media-preview" style="display:none;margin-top:8px; <div id="sm-media-preview" style="display:none;margin-top:8px;
max-width:100px;max-height:100px;border-radius:8px;overflow:hidden"></div> max-width:100px;max-height:100px;border-radius:var(--radius-md);overflow:hidden"></div>
</div> </div>
<!-- Rasse Luna-Vorschlag + Suche --> <!-- Rasse Luna-Vorschlag + Suche -->
<div style="margin-bottom:var(--space-3)"> <div style="margin-bottom:var(--space-4)">
<div class="sm-label">Rasse (optional)</div> <div class="sm-label">Rasse (optional)</div>
${_unusedBreeds.length ? ` ${_unusedBreeds.length ? `
<div style="font-size:11px;color:var(--c-text-muted);margin-bottom:6px"> <div style="font-size:11px;color:var(--c-text-muted);margin-bottom:8px">
🌙 Noch nicht gezeigt: 🌙 Noch nicht gezeigt:
<div style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px">
${_unusedBreeds.map(b => ${_unusedBreeds.map(b =>
`<button class="sm-breed-chip" data-id="${b.id}" data-name="${_esc(b.name)}" `<button class="sm-breed-chip" data-id="${b.id}" data-name="${_esc(b.name)}"
style="display:inline-block;margin:2px 4px 2px 0;padding:3px 10px; style="padding:5px 12px;border-radius:var(--radius-full);
border-radius:20px;border:1.5px solid var(--c-border); border:1.5px solid var(--c-border);
background:var(--c-surface-2);color:var(--c-text); background:var(--c-surface-2);color:var(--c-text);
font-size:11px;cursor:pointer;font-family:inherit"> font-size:12px;cursor:pointer;font-family:inherit;
transition:all var(--transition-fast)">
${_esc(b.name)}</button>`).join('')} ${_esc(b.name)}</button>`).join('')}
</div>
</div>` : ''} </div>` : ''}
<input id="sm-breed-search" list="sm-breed-list" <input id="sm-breed-search" list="sm-breed-list"
placeholder="Rasse suchen oder leer lassen…" placeholder="Rasse suchen oder leer lassen…"
autocomplete="off" autocomplete="off"
style="width:100%;background:var(--c-surface-2);color:var(--c-text); style="width:100%;background:var(--c-surface-2);color:var(--c-text);
border:1.5px solid var(--c-border);border-radius:8px; border:1.5px solid var(--c-border);border-radius:var(--radius-md);
padding:9px 12px;font-size:var(--text-sm); padding:9px 12px;font-size:var(--text-sm);
font-family:inherit;box-sizing:border-box"> font-family:inherit;box-sizing:border-box">
<datalist id="sm-breed-list"> <datalist id="sm-breed-list">
@ -245,35 +261,63 @@ window.Page_social = (() => {
</datalist> </datalist>
<input type="hidden" id="sm-breed-id"> <input type="hidden" id="sm-breed-id">
</div> </div>
<button id="sm-training-tip" class="btn btn-secondary"
style="width:100%;min-height:44px;font-size:var(--text-sm); <!-- Generier-Buttons als Cards -->
margin-bottom:4px;border:1.5px solid #10b981;color:#10b981"> <div class="sm-label" style="margin-bottom:var(--space-3)">Schnell generieren</div>
🎾 Trainingstipp generieren <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--space-2);
<span style="font-size:10px;opacity:.7;margin-left:6px">104 Übungen</span> margin-bottom:var(--space-3)">
</button> <button id="sm-breed-day"
<button id="sm-pflege-tip" class="btn btn-secondary" style="display:flex;flex-direction:column;align-items:center;
style="width:100%;min-height:44px;font-size:var(--text-sm); gap:6px;padding:var(--space-3) var(--space-2);
margin-bottom:4px;border:1.5px solid #a78bfa;color:#a78bfa"> background:var(--c-primary-subtle);border:1.5px solid var(--c-primary-light);
🛁 Pflegetipp generieren border-radius:var(--radius-lg);cursor:pointer;
<span style="font-size:10px;opacity:.7;margin-left:6px">allg. oder für gewählte Rasse</span> font-family:inherit;transition:all var(--transition-fast);
</button> box-shadow:var(--shadow-xs)">
<button id="sm-show-exercises" class="btn btn-secondary" <span style="font-size:1.8em">🐾</span>
style="width:100%;min-height:36px;font-size:11px; <span style="font-size:11px;font-weight:600;color:var(--c-primary-dark);
margin-bottom:8px;color:var(--c-text-muted)"> text-align:center;line-height:1.3">Rasse des Tages</span>
📋 Alle Übungen ansehen ${_unusedBreeds.length ? `<span style="font-size:10px;color:var(--c-text-muted)">${_unusedBreeds.length} übrig</span>` : ''}
</button> </button>
<button id="sm-breed-day" class="btn btn-secondary" <button id="sm-training-tip"
style="width:100%;min-height:44px;font-size:var(--text-sm); style="display:flex;flex-direction:column;align-items:center;
margin-bottom:8px;border:1.5px solid var(--c-primary); gap:6px;padding:var(--space-3) var(--space-2);
color:var(--c-primary)"> background:#f0fdf4;border:1.5px solid #86efac;
🐾 Rasse des Tages generieren border-radius:var(--radius-lg);cursor:pointer;
${_unusedBreeds.length ? `<span style="font-size:10px;opacity:.7;margin-left:6px">(${_breeds.length - (_breeds.length - _unusedBreeds.length)} noch übrig)</span>` : ''} font-family:inherit;transition:all var(--transition-fast);
box-shadow:var(--shadow-xs)">
<span style="font-size:1.8em">🎾</span>
<span style="font-size:11px;font-weight:600;color:#15803d;
text-align:center;line-height:1.3">Trainingstipp</span>
<span style="font-size:10px;color:#4ade80">104 Übungen</span>
</button>
<button id="sm-pflege-tip"
style="display:flex;flex-direction:column;align-items:center;
gap:6px;padding:var(--space-3) var(--space-2);
background:#faf5ff;border:1.5px solid #d8b4fe;
border-radius:var(--radius-lg);cursor:pointer;
font-family:inherit;transition:all var(--transition-fast);
box-shadow:var(--shadow-xs)">
<span style="font-size:1.8em">🛁</span>
<span style="font-size:11px;font-weight:600;color:#7c3aed;
text-align:center;line-height:1.3">Pflegetipp</span>
<span style="font-size:10px;color:#c084fc">je Rasse</span>
</button>
</div>
<button id="sm-show-exercises"
style="width:100%;min-height:36px;font-size:11px;cursor:pointer;
margin-bottom:var(--space-4);color:var(--c-text-muted);
background:none;border:1px dashed var(--c-border);
border-radius:var(--radius-md);font-family:inherit;
transition:all var(--transition-fast)">
📋 Alle 104 Übungen ansehen
</button> </button>
<button id="sm-gen" class="btn btn-primary" <button id="sm-gen" class="btn btn-primary"
style="width:100%;min-height:48px;font-size:var(--text-base)"> style="width:100%;min-height:52px;font-size:var(--text-base);
border-radius:var(--radius-lg);box-shadow:var(--shadow-md)">
Los geht's! Los geht's!
</button> </button>
<div id="sm-gen-result" style="margin-top:var(--space-3)"></div> <div id="sm-gen-result" style="margin-top:var(--space-4)"></div>
</div>`; </div>`;
// Platform toggle // Platform toggle
@ -497,13 +541,15 @@ window.Page_social = (() => {
await new Promise(r => setTimeout(r, 400)); await new Promise(r => setTimeout(r, 400));
const stilLabel = {tutorial:'📹 Tutorial', community:'🙋 Community', aspirational:'💪 Aspirational'}[data.stil] || ''; const stilLabel = {tutorial:'📹 Tutorial', community:'🙋 Community', aspirational:'💪 Aspirational'}[data.stil] || '';
res.innerHTML = ` res.innerHTML = `
<div style="background:var(--c-surface-2);border-radius:10px;padding:10px; <div style="background:#f0fdf4;border:1px solid #86efac;
margin-bottom:10px;display:flex;gap:10px;align-items:center"> border-radius:var(--radius-lg);padding:var(--space-4);
<span style="font-size:2.5em;flex-shrink:0">🎾</span> margin-bottom:var(--space-3);display:flex;gap:var(--space-3);align-items:center;
box-shadow:var(--shadow-xs)">
<span style="font-size:2.2em;flex-shrink:0">🎾</span>
<div> <div>
<div style="font-size:11px;color:var(--c-text-muted)"> <div style="font-size:11px;color:#4ade80;font-weight:600;margin-bottom:2px">
Trainingstipp · ${_esc(data.exercise_kat||'')} · ${stilLabel}</div> Trainingstipp · ${_esc(data.exercise_kat||'')} · ${stilLabel}</div>
<div style="font-weight:700;font-size:var(--text-base)"> <div style="font-weight:700;font-size:var(--text-base);color:#15803d">
${_esc(data.exercise_name||'')}</div> ${_esc(data.exercise_name||'')}</div>
</div> </div>
</div> </div>
@ -535,14 +581,16 @@ window.Page_social = (() => {
_progressDone(res); _progressDone(res);
await new Promise(r => setTimeout(r, 400)); await new Promise(r => setTimeout(r, 400));
res.innerHTML = ` res.innerHTML = `
<div style="background:var(--c-surface-2);border-radius:10px;padding:10px; <div style="background:#faf5ff;border:1px solid #d8b4fe;
margin-bottom:10px;display:flex;gap:10px;align-items:center"> border-radius:var(--radius-lg);padding:var(--space-4);
<span style="font-size:2em;flex-shrink:0">🛁</span> margin-bottom:var(--space-3);display:flex;gap:var(--space-3);align-items:center;
box-shadow:var(--shadow-xs)">
<span style="font-size:2.2em;flex-shrink:0">🛁</span>
<div> <div>
<div style="font-size:11px;color:var(--c-text-muted)"> <div style="font-size:11px;color:#c084fc;font-weight:600;margin-bottom:2px">
Pflegetipp · ${_esc(data.pflege_kat||'')} Pflegetipp · ${_esc(data.pflege_kat||'')}
${data.rasse_name ? ` · speziell für ${_esc(data.rasse_name)}` : ''}</div> ${data.rasse_name ? ` · speziell für ${_esc(data.rasse_name)}` : ''}</div>
<div style="font-weight:700;font-size:var(--text-base)"> <div style="font-weight:700;font-size:var(--text-base);color:#7c3aed">
${_esc(data.pflege_titel||'')}</div> ${_esc(data.pflege_titel||'')}</div>
</div> </div>
</div> </div>
@ -572,14 +620,18 @@ window.Page_social = (() => {
// Foto anzeigen wenn vorhanden // Foto anzeigen wenn vorhanden
const mediaUrl = data.breed_foto || data.media_url || null; const mediaUrl = data.breed_foto || data.media_url || null;
res.innerHTML = ` res.innerHTML = `
<div style="background:var(--c-surface-2);border-radius:10px;padding:10px; <div style="background:var(--c-primary-subtle);border:1px solid var(--c-primary-light);
margin-bottom:10px;display:flex;gap:10px;align-items:center"> border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);display:flex;gap:var(--space-3);align-items:center;
box-shadow:var(--shadow-xs)">
${mediaUrl ? `<img src="${mediaUrl}" ${mediaUrl ? `<img src="${mediaUrl}"
style="width:64px;height:64px;border-radius:8px;object-fit:cover;flex-shrink:0" style="width:60px;height:60px;border-radius:var(--radius-md);object-fit:cover;flex-shrink:0"
onerror="this.style.display='none'">` : '<span style="font-size:2.5em">🐶</span>'} onerror="this.style.display='none'">` : '<span style="font-size:2.2em">🐶</span>'}
<div> <div>
<div style="font-size:11px;color:var(--c-text-muted)">Rasse des Tages</div> <div style="font-size:11px;color:var(--c-primary);font-weight:600;margin-bottom:2px">
<div style="font-weight:700;font-size:var(--text-base)">${_esc(data.topic?.replace('Rasse des Tages: ',''))}</div> Rasse des Tages</div>
<div style="font-weight:700;font-size:var(--text-base);color:var(--c-primary-dark)">
${_esc(data.topic?.replace('Rasse des Tages: ',''))}</div>
</div> </div>
</div> </div>
${_renderResult(data, mediaUrl)}`; ${_renderResult(data, mediaUrl)}`;
@ -724,33 +776,43 @@ window.Page_social = (() => {
return ` return `
${data.coaching ? ` ${data.coaching ? `
<div style="background:var(--c-surface-2); <div style="background:var(--c-primary-subtle);
border-radius:12px;padding:12px;margin-bottom:12px; border-radius:var(--radius-lg);padding:var(--space-4);margin-bottom:var(--space-3);
border-left:3px solid var(--c-primary)"> border-left:4px solid var(--c-primary)">
<div style="display:flex;gap:8px"> <div style="display:flex;gap:var(--space-3)">
<span style="font-size:1.2em;flex-shrink:0">🌙</span> <span style="font-size:1.3em;flex-shrink:0">🌙</span>
<div> <div>
<div style="font-size:11px;font-weight:700;color:var(--c-primary);margin-bottom:3px"> <div style="font-size:11px;font-weight:700;color:var(--c-primary);margin-bottom:4px;
Luna sagt:</div> text-transform:uppercase;letter-spacing:.5px">Luna sagt:</div>
<div style="font-size:var(--text-sm);line-height:1.5;color:var(--c-text)">${_esc(data.coaching)}</div> <div style="font-size:var(--text-sm);line-height:1.6;color:var(--c-text)">${_esc(data.coaching)}</div>
</div> </div>
</div> </div>
</div>` : ''} </div>` : ''}
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap"> <div style="display:flex;align-items:center;gap:var(--space-2);
<span style="background:#f0fdf4;color:var(--c-success);border-radius:8px; margin-bottom:var(--space-3);flex-wrap:wrap">
padding:4px 10px;font-size:11px;font-weight:600"> Gespeichert</span> <span style="background:var(--c-success-subtle);color:var(--c-success);
${score ? `<span>${score}</span>` : ''} border-radius:var(--radius-full);
<button class="btn btn-sm btn-secondary sm-preview-btn" padding:4px 12px;font-size:11px;font-weight:700"> Gespeichert</span>
${score ? `<span style="font-size:13px">${score}</span>` : ''}
</div>
<!-- Aktions-Buttons: Primär volle Breite, Sekundär nebeneinander -->
<div style="margin-bottom:var(--space-4)">
<button class="btn btn-primary sm-posted-btn"
data-id="${data.id}" data-id="${data.id}"
style="font-size:11px;padding:4px 10px;min-height:30px"> style="width:100%;min-height:48px;font-size:var(--text-sm);
👁 Vorschau</button> margin-bottom:var(--space-2);border-radius:var(--radius-lg);
<button class="btn btn-sm btn-primary sm-posted-btn" background:#10b981;border-color:#10b981;box-shadow:var(--shadow-sm)">
data-id="${data.id}"
style="margin-left:auto;font-size:11px;padding:4px 12px;min-height:30px;
background:#10b981;border-color:#10b981">
📤 Habe ich gepostet! 📤 Habe ich gepostet!
</button> </button>
<div style="display:flex;gap:var(--space-2)">
<button class="btn btn-sm btn-secondary sm-preview-btn"
data-id="${data.id}"
style="flex:1;font-size:12px;padding:6px 10px;min-height:36px;
border-radius:var(--radius-full)">
👁 Vorschau</button>
</div>
</div> </div>
<div id="sm-posted-form-${data.id}" style="display:none;background:var(--c-surface-2); <div id="sm-posted-form-${data.id}" style="display:none;background:var(--c-surface-2);
border-radius:10px;padding:12px;margin-bottom:12px"> border-radius:10px;padding:12px;margin-bottom:12px">
@ -782,49 +844,62 @@ window.Page_social = (() => {
</div> </div>
${mediaUrl ? ` ${mediaUrl ? `
<div class="card" style="padding:12px;margin-bottom:10px"> <div style="background:var(--c-surface);border:1px solid var(--c-border);
border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);box-shadow:var(--shadow-xs)">
<div class="sm-label">📎 Dein Medien-Upload</div> <div class="sm-label">📎 Dein Medien-Upload</div>
<img src="${mediaUrl}" style="max-width:100%;max-height:200px;border-radius:8px; <img src="${mediaUrl}" style="max-width:100%;max-height:200px;
object-fit:cover;margin-top:6px" onerror="this.style.display='none'"> border-radius:var(--radius-md);object-fit:cover;margin-top:8px"
onerror="this.style.display='none'">
</div>` : ''} </div>` : ''}
${_resultBlock('📝 Caption', data.caption, true)} ${_resultBlock('📝 Caption', data.caption, true)}
${data.hashtags ? ` ${data.hashtags ? `
<div class="card" style="padding:12px;margin-bottom:10px"> <div style="background:var(--c-surface);border:1px solid var(--c-border);
border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);box-shadow:var(--shadow-xs)">
<div class="sm-label">🏷 Hashtags</div> <div class="sm-label">🏷 Hashtags</div>
<div style="font-size:var(--text-sm);color:var(--c-primary);margin-bottom:8px; <div style="font-size:var(--text-sm);color:var(--c-primary);margin-bottom:var(--space-3);
line-height:1.8;word-break:break-word"> line-height:1.9;word-break:break-word">
${data.hashtags.split(',').map(h=>`#${h.trim()}`).join(' ')}</div> ${data.hashtags.split(',').map(h=>`#${h.trim()}`).join(' ')}</div>
${_copyBtn(data.hashtags.split(',').map(h=>`#${h.trim()}`).join(' '))} ${_copyBtn(data.hashtags.split(',').map(h=>`#${h.trim()}`).join(' '))}
</div>` : ''} </div>` : ''}
${(data.hook||data.cta) ? ` ${(data.hook||data.cta) ? `
<div class="card" style="padding:12px;margin-bottom:10px"> <div style="background:var(--c-surface);border:1px solid var(--c-border);
border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);box-shadow:var(--shadow-xs)">
${data.hook ? `<div class="sm-label">🎣 Hook</div> ${data.hook ? `<div class="sm-label">🎣 Hook</div>
<div style="font-size:var(--text-sm);font-style:italic;margin-bottom:8px"> <div style="font-size:var(--text-sm);font-style:italic;margin-bottom:var(--space-3);
line-height:1.6">
"${_esc(data.hook)}"</div>` : ''} "${_esc(data.hook)}"</div>` : ''}
${data.cta ? `<div class="sm-label">📣 Call-to-Action</div> ${data.cta ? `<div class="sm-label">📣 Call-to-Action</div>
<div style="font-size:var(--text-sm)">${_esc(data.cta)}</div>` : ''} <div style="font-size:var(--text-sm);line-height:1.6">${_esc(data.cta)}</div>` : ''}
</div>` : ''} </div>` : ''}
${_resultBlock('📸 Was du filmen/fotografieren solltest', data.visual_brief, false)} ${_resultBlock('📸 Was du filmen/fotografieren solltest', data.visual_brief, false)}
${data.script ? ` ${data.script ? `
<div class="card" style="padding:12px;margin-bottom:10px"> <div style="background:var(--c-surface);border:1px solid var(--c-border);
border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);box-shadow:var(--shadow-xs)">
<div class="sm-label">🎬 Video-Aufbau</div> <div class="sm-label">🎬 Video-Aufbau</div>
<div style="font-size:var(--text-sm);white-space:pre-wrap; <div style="font-size:var(--text-sm);white-space:pre-wrap;
line-height:1.5">${_esc(data.script)}</div> line-height:1.7">${_esc(data.script)}</div>
</div>` : ''} </div>` : ''}
${(data.image_prompt||data.canva_notes||unsplash) ? ` ${(data.image_prompt||data.canva_notes||unsplash) ? `
<div class="card" style="padding:12px;margin-bottom:10px"> <div style="background:var(--c-surface);border:1px solid var(--c-border);
border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);box-shadow:var(--shadow-xs)">
<div class="sm-label">🛠 Wenn du kein eigenes Bild hast</div> <div class="sm-label">🛠 Wenn du kein eigenes Bild hast</div>
${data.image_prompt ? ` ${data.image_prompt ? `
<div style="font-size:11px;color:var(--c-text-muted);margin-bottom:4px"> <div style="font-size:11px;color:var(--c-text-muted);margin-bottom:6px">
DALL-E / Midjourney:</div> DALL-E / Midjourney:</div>
<div style="font-size:11px;background:var(--c-surface-2);padding:8px; <div style="font-size:11px;background:var(--c-surface-2);padding:10px;
border-radius:6px;font-family:monospace;word-break:break-word; border-radius:var(--radius-md);font-family:monospace;word-break:break-word;
margin-bottom:8px">${_esc(data.image_prompt)}</div> margin-bottom:var(--space-3);line-height:1.5">${_esc(data.image_prompt)}</div>
${_copyBtn(data.image_prompt)}` : ''} ${_copyBtn(data.image_prompt)}` : ''}
${data.canva_notes ? ` ${data.canva_notes ? `
<div style="font-size:11px;color:var(--c-text-muted);margin:8px 0 4px">Canva:</div> <div style="font-size:11px;color:var(--c-text-muted);margin:var(--space-3) 0 6px">Canva:</div>
<div style="font-size:var(--text-sm);margin-bottom:8px">${_esc(data.canva_notes)}</div>` : ''} <div style="font-size:var(--text-sm);margin-bottom:var(--space-3);
line-height:1.6">${_esc(data.canva_notes)}</div>` : ''}
${unsplash ? `<a href="${unsplash}" target="_blank" rel="noopener" ${unsplash ? `<a href="${unsplash}" target="_blank" rel="noopener"
style="font-size:var(--text-sm);color:var(--c-primary);display:inline-block"> style="font-size:var(--text-sm);color:var(--c-primary);display:inline-block">
🔍 Kostenlose Fotos auf Unsplash </a>` : ''} 🔍 Kostenlose Fotos auf Unsplash </a>` : ''}
@ -833,10 +908,12 @@ window.Page_social = (() => {
function _resultBlock(label, text, copyable) { function _resultBlock(label, text, copyable) {
if (!text) return ''; if (!text) return '';
return `<div class="card" style="padding:12px;margin-bottom:10px"> return `<div style="background:var(--c-surface);border:1px solid var(--c-border);
border-radius:var(--radius-lg);padding:var(--space-4);
margin-bottom:var(--space-3);box-shadow:var(--shadow-xs)">
<div class="sm-label">${label}</div> <div class="sm-label">${label}</div>
<div style="font-size:var(--text-sm);white-space:pre-wrap;line-height:1.6; <div style="font-size:var(--text-sm);white-space:pre-wrap;line-height:1.7;
margin-bottom:${copyable?'8px':'0'}">${_esc(text)}</div> margin-bottom:${copyable?'var(--space-3)':'0'}">${_esc(text)}</div>
${copyable ? _copyBtn(text) : ''} ${copyable ? _copyBtn(text) : ''}
</div>`; </div>`;
} }
@ -844,7 +921,8 @@ window.Page_social = (() => {
function _copyBtn(text) { function _copyBtn(text) {
return `<button class="btn btn-sm btn-secondary sm-copy" return `<button class="btn btn-sm btn-secondary sm-copy"
data-copy="${_esc(text)}" data-copy="${_esc(text)}"
style="font-size:11px;padding:4px 10px;min-height:30px"> style="font-size:11px;padding:5px 14px;min-height:32px;
border-radius:var(--radius-full)">
📋 Kopieren</button>`; 📋 Kopieren</button>`;
} }
@ -1023,10 +1101,11 @@ window.Page_social = (() => {
Tippe auf 📤 wenn du einen Post abgesetzt hast so lernt Luna was wirklich live ging.</div> Tippe auf 📤 wenn du einen Post abgesetzt hast so lernt Luna was wirklich live ging.</div>
</div> </div>
</div>` : ''} </div>` : ''}
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:var(--space-3)"> <div style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:var(--space-4)">
${['alle','idea','draft','scheduled','published','archived'].map(s => ` ${['alle','idea','draft','scheduled','published','archived'].map(s => `
<button class="btn btn-sm ${filter===s?'btn-primary':'btn-secondary'}" <button class="btn btn-sm ${filter===s?'btn-primary':'btn-secondary'}"
data-f="${s}" style="padding:3px 10px;font-size:11px;min-height:30px"> data-f="${s}" style="padding:4px 12px;font-size:11px;min-height:30px;
border-radius:var(--radius-full)">
${fLabel[s]}</button>`).join('')} ${fLabel[s]}</button>`).join('')}
</div> </div>
${!items.length ${!items.length
@ -1139,19 +1218,22 @@ window.Page_social = (() => {
function _renderBewerten(el) { function _renderBewerten(el) {
let selPlatform = 'instagram'; let selPlatform = 'instagram';
el.innerHTML = ` el.innerHTML = `
<div style="background:var(--c-surface-2); <div style="background:var(--c-surface);border-radius:var(--radius-lg);
border-radius:12px;padding:12px;margin-bottom:var(--space-3); box-shadow:var(--shadow-sm);padding:var(--space-4);
display:flex;gap:8px"> margin-bottom:var(--space-4);
<span style="font-size:1.2em;flex-shrink:0">🌙</span> display:flex;gap:var(--space-3)">
<div style="font-size:var(--text-sm);color:var(--c-text);line-height:1.5"> <span style="font-size:1.4em;flex-shrink:0">🌙</span>
<div style="font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.6">
Zeig mir deinen Entwurf ich sage dir was gut ist und wie du ihn Zeig mir deinen Entwurf ich sage dir was gut ist und wie du ihn
noch besser machen kannst!</div> noch besser machen kannst!</div>
</div> </div>
<div class="card" style="padding:var(--space-3)"> <div style="background:var(--c-surface);border-radius:var(--radius-lg);
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-3)"> box-shadow:var(--shadow-sm);padding:var(--space-4)">
<div style="display:flex;gap:var(--space-2);margin-bottom:var(--space-4)">
${['instagram','tiktok','both'].map((p,i) => ` ${['instagram','tiktok','both'].map((p,i) => `
<button class="btn btn-sm sm-ep ${i===0?'btn-primary':'btn-secondary'}" <button class="btn btn-sm sm-ep ${i===0?'btn-primary':'btn-secondary'}"
data-p="${p}" style="flex:1;min-height:38px;font-size:12px;padding:4px"> data-p="${p}" style="flex:1;min-height:36px;font-size:12px;padding:4px 8px;
border-radius:var(--radius-full)">
${_PL[p]}</button>`).join('')} ${_PL[p]}</button>`).join('')}
</div> </div>
<textarea id="sm-draft" class="input" <textarea id="sm-draft" class="input"
@ -1159,11 +1241,12 @@ window.Page_social = (() => {
font-size:var(--text-sm);line-height:1.5" font-size:var(--text-sm);line-height:1.5"
placeholder="Schreib hier deinen Caption-Entwurf oder einfach worum es im Post geht…"></textarea> placeholder="Schreib hier deinen Caption-Entwurf oder einfach worum es im Post geht…"></textarea>
<button id="sm-eval" class="btn btn-primary" <button id="sm-eval" class="btn btn-primary"
style="margin-top:var(--space-3);width:100%;min-height:48px; style="margin-top:var(--space-4);width:100%;min-height:52px;
font-size:var(--text-base)"> font-size:var(--text-base);border-radius:var(--radius-lg);
box-shadow:var(--shadow-md)">
🔍 Luna, schau mal drüber! 🔍 Luna, schau mal drüber!
</button> </button>
<div id="sm-eval-res" style="margin-top:var(--space-3)"></div> <div id="sm-eval-res" style="margin-top:var(--space-4)"></div>
</div>`; </div>`;
el.querySelectorAll('.sm-ep').forEach(b => b.addEventListener('click', () => { el.querySelectorAll('.sm-ep').forEach(b => b.addEventListener('click', () => {
@ -1188,15 +1271,16 @@ window.Page_social = (() => {
_progressDone(res); _progressDone(res);
await new Promise(r => setTimeout(r, 400)); await new Promise(r => setTimeout(r, 400));
res.innerHTML = ` res.innerHTML = `
${data.notes ? `<div style="background:var(--c-surface-2); ${data.notes ? `<div style="background:var(--c-primary-subtle);
border-radius:12px;padding:12px;margin-bottom:12px; border-radius:var(--radius-lg);padding:var(--space-4);margin-bottom:var(--space-3);
border-left:3px solid var(--c-primary)"> border-left:4px solid var(--c-primary);box-shadow:var(--shadow-xs)">
<div style="display:flex;gap:8px"> <div style="display:flex;gap:var(--space-3)">
<span>🌙</span> <span style="font-size:1.3em;flex-shrink:0">🌙</span>
<div> <div>
<div style="font-size:11px;font-weight:700;color:var(--c-primary);margin-bottom:3px"> <div style="font-size:11px;font-weight:700;color:var(--c-primary);margin-bottom:4px;
text-transform:uppercase;letter-spacing:.5px">
Lunas Feedback:</div> Lunas Feedback:</div>
<div style="font-size:var(--text-sm);line-height:1.5">${_esc(data.notes)}</div> <div style="font-size:var(--text-sm);line-height:1.6">${_esc(data.notes)}</div>
</div> </div>
</div> </div>
</div>` : ''} </div>` : ''}
@ -1237,6 +1321,14 @@ window.Page_social = (() => {
.sm-label{font-size:11px;font-weight:700;color:var(--c-text-muted); .sm-label{font-size:11px;font-weight:700;color:var(--c-text-muted);
text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;display:block} text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;display:block}
@keyframes luna-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.15)}} @keyframes luna-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.15)}}
#sm-breed-day:hover,#sm-training-tip:hover,#sm-pflege-tip:hover{
transform:translateY(-2px);box-shadow:var(--shadow-md)!important}
#sm-breed-day:active,#sm-training-tip:active,#sm-pflege-tip:active{
transform:translateY(0)}
#sm-show-exercises:hover{background:var(--c-surface-2)!important;
border-color:var(--c-border)!important;color:var(--c-text-secondary)!important}
.sm-breed-chip:hover{background:var(--c-primary-subtle)!important;
border-color:var(--c-primary)!important;color:var(--c-primary-dark)!important}
`; `;
document.head.appendChild(style); document.head.appendChild(style);

View file

@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache Offline-Cache + Push Notifications + Tile-Cache
============================================================ */ ============================================================ */
const CACHE_VERSION = 'by-v357'; const CACHE_VERSION = 'by-v359';
const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten