Budget panel
- Removed the inner "Budget Allocation" subtitle and the inline total
from bm-title — the outer panel header "Budget Plan" already names
the section, the inner subtitle was redundant.
- Added a Total Allocation row at the end of the breakdown using the
same .bcat layout as the category lines so label + amount columns
align. Top divider + heavier weight mark it as the summary line.
DE: Gesamtbudget. The bar slot is collapsed to height:0 on the
total row so only label + amount render.
- Bumped .bm-title (when it existed) and .bcat-label / .bcat-cost so
the budget figures read at a comfortable size.
Timeline
- Each .tl-item gets generous top + bottom padding (14px / 28px) so
the steps read as distinct moments. Padding is consistent across
every item so the connector positioning stays stable.
- Connector line is now a light dotted left-border drawn on a
zero-width pseudo, anchored top:46px / bottom:-14px so the dotted
line crosses the gap between items and reaches each next dot.
- .tl-when (step title) typeface switched from Space Mono to Barlow
(matching the CTA buttons), weight 600, 0.16em tracking, dark green
paint colour (#2a3010), vertically centred against the 32px dot via
min-height + flex centring so the title sits at the dot's mid-line.
Quiz
- Slider thumb is now a CSS-painted dark green circle: linear
gradient (#3a4220 → #2a3010 → #161a08) with an inset cream highlight
and a soft drop shadow + halo ring, approximating the SVG paint
gloss filter the CTA buttons use. Both -webkit and -moz pseudo
elements styled.
- Single-choice questions now auto-advance 220ms after a tap so the
Continue button is no longer needed on those steps. renderQuestion
drops the Continue button on single-choice, keeps Back when not on
the first question. .quiz-footer:empty hides cleanly on the very
first single-choice screen.
Result panels
- .result-panel-body top padding bumped from 0 to 20px so expanded
content has clear breathing room below the summary header.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the remaining emoji indicators on the post-quiz / assessment
side with inline SVG line-icons (Lucide-style, vendored as path
strings) sitting in dark-green-paint containers that match the CTA
button family.
Icons
- 13-icon set in ICON_PATHS — droplet, sprout, zap, cart, flame, leaf,
package, radio, brain, lock, check, mail, shield. Single-stroke
paths, currentColor for stroke so each surface tints them.
- icon(name, size) returns the SVG markup; iconForEmoji() maps the
legacy emoji values used by the rec-cards / timeline data tables to
the icon names so the data didn't need a wholesale rewrite.
Surfaces re-skinned
- Recommendation card chips (.rec-icon): 40×40 dark-green-paint chip
with the paintGlossBtn filter, warm-cream icon stroke. Per-card
inline category colour (`card.color`) dropped — every chip now reads
as one family.
- Timeline dots (.tl-dot): same green paint, 50% radius. Per-step
rainbow colours dropped.
- Affiliate button: tiny inline cart icon next to "View on Amazon".
- Narrative ("Your Personal Analysis"): brain icon in green replaces
the 🧠 emoji header.
- Protein-offer badge: lock icon prefix replaces 🔒.
- Capture-success state: 56px green check-circle replaces ✅, and the
spam-folder note becomes a flex row with a mail icon — translation
keys cleaned of the inline 📬 prefix.
Form-field emojis (e.g. "🥩 Protein access (optional)"), country flags,
and the in-form privacy 🔒 stay as-is per the explicit ask: "in
assessment, not the form fields that have them earlier".
Other tidy-up
- Scenario tabs: dropped 💀⚠️📈🌿 prefixes from tab_s1–4 (en + de) and
the inline template defaults.
- Risk banner: removed the 🔴🟠🟡🟢 dot from the eyebrow line — the
painted card colour already conveys severity.
- Panel headers stripped of emoji: "Recommendations" / "Empfehlungen",
"Budget Plan" / "Budgetplan", "Action Timeline" / "Aktionsplan"; the
📊 prefix dropped from the inner budget-meter title.
- "Tap a scenario to compare" hint moved out of the collapsed panel
header into the expanded body, restyled as a centred full-width
light-green paint banner.
- Modifier (⚙) toggle hidden via a single display:none rule — styles
preserved so we can re-enable later.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The post-quiz results page is restructured around progressive disclosure
and the embossed-paint visual language used on the homepage CTAs.
Capture form
- Moved into a viewport-scaled modal with sticky header (title + close)
and sticky footer (submit). Body scrolls between them.
- Privacy note now sits inside the form, above the newsletter checkbox,
so the message is part of the consent flow rather than a footnote.
- Close button is the secondary white-with-border style; the X glyph is
drawn from two CSS strokes so it stays pixel-centred regardless of
font metrics.
- iOS-Safari-safe scroll lock: body becomes position:fixed with the
saved scrollY pinned via inline top, restored on close.
Result panels
- Recommendations / Budget / Timeline use the white-paint container
(#FAFAFA) and inner cards switch to the #F0F0F0 paint look that the
quiz q-opt items already used. Text colours flip to the dark palette
for legibility.
- Risk banner gets four paint variants — maroon (critical), amber
(high), olive (medium), green (low / "PREPARED") — each rendered via
::before with the paintGlossBtn filter. Text is warm cream #f4ecd8.
- Narrative ("Your Personal Analysis") wears the same white-paint frame
with a slightly greyer header band.
- Headings (risk title, protein offer, panel headers, narrative title)
switched from DM Serif Display to Barlow to share the button typeface.
Scenario tabs
- Container loses its border + padding; inactive tabs are quiet text
buttons. Active tab wears the green-paint CTA fill.
- Mobile lays them out as a 2×2 grid; desktop is a single row of 4.
Other tweaks
- Results section bumped 15% wider on desktop (max-width 690px).
- Site header gets a soft white fade on results-active so content
scrolling underneath doesn't clash with the logo.
- Modifier (⚙) toggle hidden via a single display:none rule, styles
preserved so we can re-enable it later.
- Protein button has a responsive label: "Secure Source Now" on mobile,
"Secure protein source now" on desktop. Arrow icons removed from
protein, retake, send-plan buttons. Unified primary-button typography
across the site (var(--font-body), 400 weight, 13px, 0.2em tracking).
Session persistence
- Quiz progress (answers, currentQ, lang, scenario, stage) is saved to
sessionStorage under "kammergut.state.v1" — purely client-side, dies
when the tab closes. Stale sessions (>4h) are discarded on load.
- Reload mid-quiz or mid-results re-enters the right view. restartQuiz
clears the saved session.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Mobile browsers report 100vh as the viewport at its largest (URL bar
hidden), so flex-centred content sat below the visual centre whenever
the address bar was showing. Add 100dvh declarations after the existing
100vh ones on body, #app, .app and .quiz-section (and on the .mod-panel
max-height) so modern browsers track the visible viewport while older
browsers keep the vh fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The hero H1 swapped to paintGlossHover (and paintGlossWhiteHover for
the white variant) on pointer hover, repositioning the specular
lights. Drop both hover rules and the now-unused 0.6s filter
transition so the painted wordmark holds its look regardless of
pointer position. The hover-variant SVG filters stay in defs in case
we want hover back later.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Site-header .logo and quiz-progress-bar .qpb-logo now follow the
active paint variant (currently green) and read --mod-fill so they
track live changes from the modifier panel's fill picker. White
paint is intentionally excluded — a near-white logo would vanish
against the light header background. Applies on both mobile and
desktop.
- Paint H1 default updated to spec1Const=0 in both paintGloss and
paintGlossHover (matches the "Copy snippet" dump), removing the
upper-left specular highlight from the dark paint baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The /7 divisor was calibrated for the wider "Kammergut" wordmark and
left ~25-45px of unused space each side of the narrower "Deepstock".
Switch to language-aware divisors that match each wordmark's actual
rendered-width-to-font-size ratio in DM Serif Display at 0.05em
tracking:
- DE / Kammergut (default): /6 — fills with ~16px gutter at viewport
widths from 320 to 768.
- EN / Deepstock: /5.2 — narrower wordmark, smaller divisor needed
to fill the same content area without clipping at 320px.
Desktop (>=900px) uses clamp() with separate ranges per language.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CSS: hero h1 used `(100vw - 48px) / 7` on mobile and `-64px / 7` on
tablet — the wider gutter assumption left 12-16px of unused white
space inside the 16px hero padding. Tightened both to `(100vw - 32px)
/ 7` so the wordmark spans the actual hero content area. Divisor 7
preserves the safety margin for the wider "Kammergut" wordmark.
Compose: dropped the `image: kammergut:0.1.0` field. Older Portainer
Compose runtimes (pre-v2.20) ignore `pull_policy: build` and still
ran `compose pull` against the image name, hitting "pull access
denied". Without an image name there's nothing for compose pull to
attempt; build runs during `up`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The qpb-logo's "back to home" path now soft-restarts via Vue's
@click.prevent="restartQuiz", but restartQuiz never reset the inline
styles startQuiz had set on body and .app to make the quiz scrollable
(height:auto / overflow:auto). On the locked-viewport landing page
those inline overrides collapsed the hero to its content height and
left a white half-screen.
restartQuiz now clears those inline styles so the CSS-defined
height:100vh / overflow:hidden chain takes over again. The original
single-file build never hit this because its qpb-logo was a hard
href="/" reload, which reset the inline styles for free.
Also harden the Vue mount layout: #app is now an explicit 100vh flex
column so the wrapper div Vue introduces between body and main.app
forwards the body's full viewport height (fallback for the same
collapse symptom on first load).
Switch Google Fonts to display=optional + add the gstatic preconnect
to eliminate the bold-flash FOUT on cold loads — fonts now render
either immediately (cached) or stay on the system fallback rather
than swapping mid-paint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Faithful 1:1 port of the single-file index.html to a Vite + Vue 3.5
project. All visuals, behavior, translations, quiz logic, scoring,
SVG paint filters, and modifier panel preserved. The previous
single-file build is archived as index.original.html for A/B compare.
Inline onclick handlers in the static template are converted to
Vue's @click bindings — Vue 3 ignores string-valued on* attributes,
which silently broke the qpb-logo "back to landing" navigation.
Inline handlers inside dynamically-injected innerHTML strings
(quiz options, slider, nav buttons) keep working since the browser
parses them; their target functions are exposed on window from
onMounted.
Pinned: vue 3.5.13, vite 6.4.2, @vitejs/plugin-vue 5.2.1.
Zero npm audit vulnerabilities.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>