feat: collapse results into progressive-disclosure panels

Wrap Recommendations (scenario tabs + cards), Budget, and Timeline in
<details> accordions. Recommendations stays open by default; Budget and
Timeline collapse closed so the post-quiz page doesn't dump everything at
once. The panel becomes the white-paint container — inner .budget-meter,
.timeline, and .scenario-tabs drop their own box treatment to avoid a
nested-card look. revealSections() now staggers the panel wrappers
instead of the inner containers, and added en/de strings for the panel
headers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-05-10 06:53:48 +01:00
parent 67dfa38e04
commit d8941485f7
2 changed files with 141 additions and 24 deletions

View File

@@ -458,20 +458,47 @@
<div style="font-size:11px;color:var(--muted);margin-top:12px;text-align:center;line-height:1.7" data-i18n="privacy_note">🔒 Your data is never sold. Unsubscribe anytime. GDPR compliant.</div>
</div>
<!-- RECOMMENDATIONS + SCENARIO TABS -->
<!-- RECOMMENDATIONS + SCENARIO TABS — collapsible panels -->
<div id="recs-anchor"></div>
<div id="budget-meter-container" class="reveal-section"></div>
<div class="scenario-tabs reveal-section" id="scenario-tabs">
<button class="s-tab" id="stab-1" data-s="1" @click="showScenario(1)"><span data-i18n="tab_s1">💀 Total</span></button>
<button class="s-tab" id="stab-2" data-s="2" @click="showScenario(2)"><span data-i18n="tab_s2">⚠️ Partial</span></button>
<button class="s-tab" id="stab-3" data-s="3" @click="showScenario(3)"><span data-i18n="tab_s3">📈 Inflation</span></button>
<button class="s-tab" id="stab-4" data-s="4" @click="showScenario(4)"><span data-i18n="tab_s4">🌿 Food</span></button>
</div>
<div class="rec-cards reveal-section" id="rec-cards-container"></div>
<div class="timeline reveal-section" id="timeline-container">
<div class="tl-title" data-i18n="timeline_title">⏱ Your Action Timeline</div>
<div class="tl-items" id="timeline-items"></div>
</div>
<details class="result-panel reveal-section" id="panel-recs" open>
<summary class="result-panel-header">
<span class="rp-title" data-i18n="panel_recs">📋 Your Recommendations</span>
<span class="rp-hint" data-i18n="panel_recs_hint">Tap a scenario to compare</span>
<span class="rp-chevron" aria-hidden="true">▾</span>
</summary>
<div class="result-panel-body">
<div class="scenario-tabs" id="scenario-tabs">
<button class="s-tab" id="stab-1" data-s="1" @click="showScenario(1)"><span data-i18n="tab_s1">💀 Total</span></button>
<button class="s-tab" id="stab-2" data-s="2" @click="showScenario(2)"><span data-i18n="tab_s2">⚠️ Partial</span></button>
<button class="s-tab" id="stab-3" data-s="3" @click="showScenario(3)"><span data-i18n="tab_s3">📈 Inflation</span></button>
<button class="s-tab" id="stab-4" data-s="4" @click="showScenario(4)"><span data-i18n="tab_s4">🌿 Food</span></button>
</div>
<div class="rec-cards" id="rec-cards-container"></div>
</div>
</details>
<details class="result-panel reveal-section" id="panel-budget">
<summary class="result-panel-header">
<span class="rp-title" data-i18n="panel_budget">💰 Budget Plan</span>
<span class="rp-chevron" aria-hidden="true">▾</span>
</summary>
<div class="result-panel-body">
<div id="budget-meter-container"></div>
</div>
</details>
<details class="result-panel reveal-section" id="panel-timeline">
<summary class="result-panel-header">
<span class="rp-title" data-i18n="panel_timeline">⏱ Action Timeline</span>
<span class="rp-chevron" aria-hidden="true">▾</span>
</summary>
<div class="result-panel-body">
<div class="timeline" id="timeline-container">
<div class="tl-items" id="timeline-items"></div>
</div>
</div>
</details>
<button class="restart-btn" @click="restartQuiz" data-i18n="restart_btn">↩ Retake Assessment</button>
</section>
@@ -525,6 +552,10 @@ const T = {
tab_s3: "📈 Hyper-\ninflation",
tab_s4: "🌿 Food\nShortage",
timeline_title: "⏱ Your Action Timeline",
panel_recs: "📋 Your Recommendations",
panel_recs_hint: "Tap a scenario to compare",
panel_budget: "💰 Budget Plan",
panel_timeline: "⏱ Action Timeline",
restart_btn: "↩ Retake Assessment",
about_title: "Why Deepstock?",
about_text: "Built by preparedness researchers and city-dwelling practitioners. Every recommendation is sourced, tested, and city-apartment-compatible.",
@@ -620,6 +651,10 @@ const T = {
tab_s3: "📈 Hyper-\ninflation",
tab_s4: "🌿 Lebens-\nmittelkrise",
timeline_title: "⏱ Dein Aktionsplan",
panel_recs: "📋 Deine Empfehlungen",
panel_recs_hint: "Szenario antippen zum Vergleichen",
panel_budget: "💰 Budgetplan",
panel_timeline: "⏱ Aktionsplan",
restart_btn: "↩ Neu starten",
about_title: "Warum Kammergut?",
about_text: "Entwickelt von Vorsorge-Forschern und Stadtbewohnern. Jede Empfehlung ist recherchiert, getestet und für Stadtwohnungen geeignet.",
@@ -1510,19 +1545,18 @@ function getFallbackNarrativeText() {
}
function revealSections() {
const sections = [
{ id:'scenario-tabs', display:'flex' },
{ id:'budget-meter-container', display:'block' },
{ id:'rec-cards-container', display:'block' },
{ id:'timeline-container', display:'block' },
{ id:'capture-form-wrap', display:'block' },
// Capture form first, then the three collapsible result panels (recs is open
// by default, budget + timeline collapsed for progressive disclosure).
const ids = [
'capture-form-wrap',
'panel-recs',
'panel-budget',
'panel-timeline',
]
sections.forEach((s, i) => {
ids.forEach((id, i) => {
setTimeout(() => {
const el = document.getElementById(s.id)
if (!el) return
el.style.display = s.display
el.classList.add('revealed')
const el = document.getElementById(id)
if (el) el.classList.add('revealed')
}, i * 200)
})
}

View File

@@ -553,6 +553,82 @@ input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 22px;
.tl-action { font-size: 14px; color: var(--bright); line-height: 1.5; }
.tl-cost { font-family: var(--font-mono); font-size: 12px; color: var(--green-bright); margin-top: 4px; }
/* ── RESULT PANELS — collapsible accordions for progressive disclosure.
Recommendations open by default; Budget and Timeline collapsed so the
results page doesn't overwhelm. The panel itself becomes the white-paint
card; inner sections (.budget-meter, .timeline, .scenario-tabs) drop their
own box treatment so the panel frame is the only container. */
.result-panel {
background: #FAFAFA;
border: 1px solid rgba(0,0,0,0.06);
border-radius: var(--radius-lg);
margin-bottom: 14px;
overflow: hidden;
box-shadow: 0 7px 10.6px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.7);
}
.result-panel-header {
display: flex;
align-items: center;
gap: 12px;
padding: 16px 18px;
cursor: pointer;
list-style: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
transition: background 0.15s ease;
}
.result-panel-header::-webkit-details-marker { display: none; }
.result-panel-header:hover { background: rgba(0,0,0,0.02); }
.rp-title {
font-family: var(--font-display);
font-weight: 700;
font-size: 17px;
color: var(--text);
flex: 1;
letter-spacing: 0.01em;
line-height: 1.3;
}
.rp-hint {
font-size: 10px;
color: var(--text-dim);
font-family: var(--font-mono);
letter-spacing: 0.08em;
text-transform: uppercase;
flex-shrink: 0;
}
@media (max-width: 480px) {
.rp-hint { display: none; }
}
.rp-chevron {
font-size: 14px;
color: var(--text-dim);
transition: transform 0.2s ease;
flex-shrink: 0;
}
.result-panel[open] .rp-chevron { transform: rotate(180deg); }
.result-panel-body {
padding: 0 18px 18px;
}
/* Strip box treatment from inner cards when wrapped in a panel — the panel
is now the visible container. */
.result-panel-body .budget-meter,
.result-panel-body .timeline {
background: transparent;
border: none;
border-radius: 0;
padding: 0;
margin: 0;
box-shadow: none;
animation: none;
}
.result-panel-body .scenario-tabs {
margin-bottom: 16px;
animation: none;
}
.result-panel-body .rec-cards { animation: none; }
/* Drop the redundant inner timeline title — the panel header replaces it. */
.result-panel-body .tl-title { display: none; }
/* Results email capture */
.results-email {
background: linear-gradient(135deg, var(--red-dim), #141210);
@@ -693,6 +769,13 @@ body.paint-green .qpb-logo {
text-decoration: none;
}
.quiz-progress-bar .progress-wrap { flex: 1; max-width: none; margin: 0; }
/* Desktop — cap the progress bar at the form width (540px) so it reads
tighter and lines up with the question card below. Auto margins on the
flex item absorb leftover horizontal space symmetrically, centring the
bar between the logo (left) and lang-toggle (right). */
@media (min-width: 768px) {
.quiz-progress-bar .progress-wrap { max-width: 540px; margin: 0 auto; }
}
.quiz-progress-bar .lang-toggle { flex-shrink: 0; }
@media (max-width: 767px) {
.quiz-progress-bar .lang-toggle { display: none; }