<template>
  <!-- SVG filter defs for the glossy-paint hero title -->
  <svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
    <defs>
      <filter id="paintGloss" x="-12%" y="-30%" width="124%" height="160%" color-interpolation-filters="sRGB">
        <feMorphology in="SourceAlpha" operator="dilate" radius="2.5" result="dilated"/>
        <feGaussianBlur in="dilated" stdDeviation="6" result="puddle"/>
        <feFlood flood-color="#fff4dc" flood-opacity="0.85" result="puddleColor"/>
        <feComposite in="puddleColor" in2="puddle" operator="in" result="puddleHi"/>
        <feFlood flood-color="#1A1A18" flood-opacity="0.18" result="puddleShadowColor"/>
        <feComposite in="puddleShadowColor" in2="puddle" operator="in" result="puddleShadow"/>
        <feOffset in="puddleShadow" dx="0" dy="3" result="puddleShadowOff"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="1.4" result="bump"/>
        <!-- spec1 (upper-left) intentionally removed: at constant=0 Chromium
             rendered it as opaque-black-masked-to-text, hiding the underlying
             paint colour (green/etc) behind a black silhouette. With it gone
             the visible look is unchanged (it was already turned off) and the
             paint-variant background reads through. -->
        <feSpecularLighting in="bump" surfaceScale="4" specularConstant="0.9"
                            specularExponent="40" lighting-color="#fff2d4" result="spec2">
          <fePointLight x="600" y="-200" z="380"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="6" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.45"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
      <!-- Mobile variant of paintGloss — same gloss/specular, but the
           drop shadow is dialled back (slope 0.45 → 0.20, offset 6 → 3,
           blur 4 → 2.5) and the puddle shadow is softer too. The hero
           wordmark switches to this filter under the 767px breakpoint
           so it sits cleaner on small screens. -->
      <filter id="paintGlossLight" x="-12%" y="-30%" width="124%" height="160%" color-interpolation-filters="sRGB">
        <feMorphology in="SourceAlpha" operator="dilate" radius="2.5" result="dilated"/>
        <feGaussianBlur in="dilated" stdDeviation="6" result="puddle"/>
        <feFlood flood-color="#fff4dc" flood-opacity="0.85" result="puddleColor"/>
        <feComposite in="puddleColor" in2="puddle" operator="in" result="puddleHi"/>
        <feFlood flood-color="#1A1A18" flood-opacity="0.10" result="puddleShadowColor"/>
        <feComposite in="puddleShadowColor" in2="puddle" operator="in" result="puddleShadow"/>
        <feOffset in="puddleShadow" dx="0" dy="2" result="puddleShadowOff"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="1.4" result="bump"/>
        <feSpecularLighting in="bump" surfaceScale="4" specularConstant="0.9"
                            specularExponent="40" lighting-color="#fff2d4" result="spec2">
          <fePointLight x="600" y="-200" z="380"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="2.5" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="3" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.20"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
      <filter id="paintGlossHover" x="-12%" y="-30%" width="124%" height="160%" color-interpolation-filters="sRGB">
        <feMorphology in="SourceAlpha" operator="dilate" radius="2.5" result="dilated"/>
        <feGaussianBlur in="dilated" stdDeviation="6" result="puddle"/>
        <feFlood flood-color="#fff4dc" flood-opacity="0.85" result="puddleColor"/>
        <feComposite in="puddleColor" in2="puddle" operator="in" result="puddleHi"/>
        <feFlood flood-color="#1A1A18" flood-opacity="0.18" result="puddleShadowColor"/>
        <feComposite in="puddleShadowColor" in2="puddle" operator="in" result="puddleShadow"/>
        <feOffset in="puddleShadow" dx="0" dy="3" result="puddleShadowOff"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="1.4" result="bump"/>
        <!-- spec1 (upper-left) removed for the same reason as paintGloss above. -->
        <feSpecularLighting in="bump" surfaceScale="4" specularConstant="0.9"
                            specularExponent="40" lighting-color="#fff2d4" result="spec2">
          <fePointLight x="-200" y="-200" z="380"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="6" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.45"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
      <filter id="paintGlossBtn" x="-8%" y="-25%" width="116%" height="150%" color-interpolation-filters="sRGB">
        <feMorphology in="SourceAlpha" operator="dilate" radius="0.6" result="dilated"/>
        <feGaussianBlur in="dilated" stdDeviation="2.5" result="puddle"/>
        <feFlood flood-color="#fff4dc" flood-opacity="0.4" result="puddleColor"/>
        <feComposite in="puddleColor" in2="puddle" operator="in" result="puddleHi"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="1.2" result="bump"/>
        <feSpecularLighting in="bump" surfaceScale="4" specularConstant="1.6"
                            specularExponent="50" lighting-color="#ffffff" result="spec">
          <fePointLight x="-150" y="-300" z="280"/>
        </feSpecularLighting>
        <feComposite in="spec" in2="SourceAlpha" operator="in" result="specClip"/>
        <feSpecularLighting in="bump" surfaceScale="3" specularConstant="0.7"
                            specularExponent="60" lighting-color="#fff2d4" result="spec2">
          <fePointLight x="400" y="-150" z="260"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="2.5" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="3" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.4"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="puddleHi"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
      <filter id="paintGlossBtnHover" x="-8%" y="-25%" width="116%" height="150%" color-interpolation-filters="sRGB">
        <feMorphology in="SourceAlpha" operator="dilate" radius="0.6" result="dilated"/>
        <feGaussianBlur in="dilated" stdDeviation="2.5" result="puddle"/>
        <feFlood flood-color="#fff4dc" flood-opacity="0.4" result="puddleColor"/>
        <feComposite in="puddleColor" in2="puddle" operator="in" result="puddleHi"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="1.2" result="bump"/>
        <feSpecularLighting in="bump" surfaceScale="4" specularConstant="1.6"
                            specularExponent="50" lighting-color="#ffffff" result="spec">
          <fePointLight x="350" y="-300" z="280"/>
        </feSpecularLighting>
        <feComposite in="spec" in2="SourceAlpha" operator="in" result="specClip"/>
        <feSpecularLighting in="bump" surfaceScale="3" specularConstant="0.7"
                            specularExponent="60" lighting-color="#fff2d4" result="spec2">
          <fePointLight x="-150" y="-150" z="260"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="2.5" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="3" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.4"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="puddleHi"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>

      <filter id="paintGlossWhite" x="-12%" y="-30%" width="124%" height="160%" color-interpolation-filters="sRGB">
        <feGaussianBlur in="SourceAlpha" stdDeviation="0.8" result="bump"/>
        <feSpecularLighting in="bump" surfaceScale="7" specularConstant="3.5"
                            specularExponent="21" lighting-color="#ffffff" result="spec">
          <fePointLight x="-200" y="-350" z="380"/>
        </feSpecularLighting>
        <feComposite in="spec" in2="SourceAlpha" operator="in" result="specClip"/>
        <feSpecularLighting in="bump" surfaceScale="7" specularConstant="3.3"
                            specularExponent="19" lighting-color="#ffffff" result="spec2">
          <fePointLight x="500" y="-200" z="320"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="5.3" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="7" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.12"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
      <filter id="paintGlossWhiteHover" x="-12%" y="-30%" width="124%" height="160%" color-interpolation-filters="sRGB">
        <feGaussianBlur in="SourceAlpha" stdDeviation="0.8" result="bump"/>
        <feSpecularLighting in="bump" surfaceScale="7" specularConstant="3.5"
                            specularExponent="21" lighting-color="#ffffff" result="spec">
          <fePointLight x="500" y="-350" z="380"/>
        </feSpecularLighting>
        <feComposite in="spec" in2="SourceAlpha" operator="in" result="specClip"/>
        <feSpecularLighting in="bump" surfaceScale="7" specularConstant="3.3"
                            specularExponent="19" lighting-color="#ffffff" result="spec2">
          <fePointLight x="-200" y="-200" z="320"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="5.3" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="7" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.12"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
      <filter id="paintGlossWhiteBtn" x="-8%" y="-25%" width="116%" height="150%" color-interpolation-filters="sRGB">
        <feGaussianBlur in="SourceAlpha" stdDeviation="0.8" result="bump"/>
        <feSpecularLighting in="bump" surfaceScale="7" specularConstant="3.5"
                            specularExponent="21" lighting-color="#ffffff" result="spec">
          <fePointLight x="-150" y="-300" z="280"/>
        </feSpecularLighting>
        <feComposite in="spec" in2="SourceAlpha" operator="in" result="specClip"/>
        <feSpecularLighting in="bump" surfaceScale="7" specularConstant="3.3"
                            specularExponent="19" lighting-color="#ffffff" result="spec2">
          <fePointLight x="400" y="-150" z="260"/>
        </feSpecularLighting>
        <feComposite in="spec2" in2="SourceAlpha" operator="in" result="specClip2"/>
        <feGaussianBlur in="SourceAlpha" stdDeviation="5.3" result="dsBlur"/>
        <feOffset in="dsBlur" dx="0" dy="7" result="dsOff"/>
        <feComponentTransfer in="dsOff" result="dsFinal">
          <feFuncA type="linear" slope="0.12"/>
        </feComponentTransfer>
        <feMerge>
          <feMergeNode in="dsFinal"/>
          <feMergeNode in="SourceGraphic"/>
          <feMergeNode in="specClip"/>
          <feMergeNode in="specClip2"/>
        </feMerge>
      </filter>
    </defs>
  </svg>

  <!-- INTRO OVERLAY — three-stage typographic intro on first visit
       (sweep reveal → "Even if crisis" pause "is not here yet" → final
       pitch), then fades out to expose the hero. Skipped on subsequent
       loads in the same tab via sessionStorage. -->
  <div class="intro-overlay" id="intro-overlay" aria-hidden="true">
    <div class="intro-stage stage-1" data-stage="1">
      <svg class="stage-icon icon-storm" viewBox="0 0 96 96" aria-hidden="true">
        <circle class="badge" cx="48" cy="48" r="42"/>
        <g class="glyph filled-icon" transform="translate(19.75 21.15) scale(0.46)">
          <path class="i-cloud" d="M44.2,71.76 c2.03,0,3.68,1.65,3.68,3.68c0,2.03-1.65,3.68-3.68,3.68H23.38l-0.46-0.04c-2.67-0.34-5.09-0.97-7.29-1.88 c-2.25-0.93-4.26-2.14-6.04-3.63H9.58c-1.68-1.4-3.15-2.99-4.4-4.72C1.84,64.25,0.04,58.63,0,53.03 c-0.04-5.66,1.72-11.29,5.52-15.85c1.23-1.48,2.68-2.84,4.34-4.04c1.93-1.4,4.14-2.58,6.64-3.55c1.72-0.67,3.56-1.23,5.5-1.68 c2.2-8.74,6.89-15.47,12.92-20.14c5.64-4.37,12.43-6.92,19.42-7.59c6.96-0.67,14.12,0.51,20.55,3.6 c7.37,3.54,13.43,9.56,17.11,16.87c1.6-0.25,3.2-0.38,4.79-0.36c6.72,0.05,13.2,2.45,18.3,7.95c5.31,5.72,7.88,14.14,7.79,21.82 c-0.07,6.31-1.77,12.59-5.25,17.22c-2.27,3.02-5.18,5.47-8.67,7.42c-3.36,1.88-7.28,3.31-11.68,4.33c-1.98,0.45-3.95-0.78-4.4-2.76 c-0.45-1.98,0.78-3.95,2.76-4.4c3.71-0.86,6.97-2.04,9.72-3.58c2.63-1.47,4.78-3.26,6.39-5.41c2.5-3.33,3.73-8.04,3.78-12.87 c0.06-5.07-1.18-10.16-3.59-13.86c-0.69-1.07-1.44-2.03-2.25-2.89c-3.61-3.89-8.19-5.59-12.95-5.62 c-3.46-0.02-7.02,0.81-10.41,2.31c-0.75,0.37-1.51,0.78-2.25,1.21c-2.25,1.32-4.48,2.93-6.74,4.78l-4.84-5.54 c1.67-1.55,3.48-2.96,5.4-4.21c1.53-1,3.13-1.88,4.77-2.65c0.66-0.33,1.33-0.64,2-0.93c-3.19-5.65-7.78-9.7-12.98-12.2 c-5.2-2.49-11.02-3.45-16.69-2.9c-5.63,0.54-11.1,2.59-15.62,6.1c-5.23,4.06-9.2,10.11-10.73,18.14l-0.48,2.51l-2.5,0.44 c-2.45,0.43-4.64,1.02-6.56,1.77c-1.86,0.72-3.52,1.61-4.97,2.66c-1.16,0.84-2.16,1.78-3.01,2.8c-2.63,3.15-3.85,7.1-3.82,11.1 c0.03,4.06,1.35,8.16,3.79,11.53c0.91,1.25,1.96,2.4,3.16,3.4l-0.01,0.01c1.2,1,2.58,1.83,4.13,2.47c1.53,0.63,3.22,1.08,5.09,1.34 H44.2L44.2,71.76z"/>
        </g>
        <path class="glyph-fill i-lightning-flash" d="M47.2 49.5 L57.6 49.5 L54 56.5 L60.2 56.6 L45.2 74.9 L48.1 62.9 L43.2 62.9 Z"/>
        <g class="sun-glyph" aria-hidden="true">
          <circle class="sun-core" cx="48" cy="48" r="13"/>
          <path class="sun-rays" d="M48 24 V31 M48 65 V72 M24 48 H31 M65 48 H72 M31 31 L36 36 M60 60 L65 65 M65 31 L60 36 M36 60 L31 65"/>
        </g>
      </svg>
      <span class="intro-text" data-i18n="intro_l1">For crisis bows to him who plans with care</span>
    </div>
    <div class="intro-stage stage-2" data-stage="2">
      <svg class="stage-icon icon-clock" viewBox="0 0 96 96" aria-hidden="true">
        <circle class="badge" cx="48" cy="48" r="42"/>
        <g class="glyph">
          <!-- Face circle, centred in the badge. -->
          <circle class="i-face" cx="48" cy="48" r="22"/>
          <!-- Cardinal hour ticks. -->
          <line class="i-tick" x1="48" y1="30" x2="48" y2="34"/>
          <line class="i-tick" x1="66" y1="48" x2="62" y2="48"/>
          <line class="i-tick" x1="48" y1="66" x2="48" y2="62"/>
          <line class="i-tick" x1="30" y1="48" x2="34" y2="48"/>
          <!-- Minute hand pointing to 12 — rotates 720° over the line. -->
          <line class="i-hand" x1="48" y1="48" x2="48" y2="32"/>
          <!-- Center pin. -->
          <circle class="i-pin" cx="48" cy="48" r="2.2"/>
        </g>
      </svg>
      <span class="intro-text" data-i18n="intro_l2">And fortune favors those who well prepare</span>
    </div>
  </div>

  <header class="site-header">
    <a class="logo" data-i18n="brand" href="#" aria-label="Back to landing page" @click.prevent="restartQuiz">Deepstock</a>
    <div class="header-right">
      <button class="mod-open-btn" id="modOpenBtn" type="button" title="Open style modifier" aria-label="Open style modifier">⚙</button>
      <div id="region-indicator" style="font-family:var(--font-mono);font-size:10px;color:var(--text-dim);padding:4px 8px;background:var(--panel);border:1px solid var(--border);border-radius:4px;white-space:nowrap;cursor:pointer;" @click="showRegionPicker" title="Click to change region"></div>
      <div class="lang-toggle">
        <button class="lang-btn active" @click="setLang('en')" id="btn-en">EN</button>
        <button class="lang-btn" @click="setLang('de')" id="btn-de">DE</button>
      </div>
    </div>
  </header>

  <aside class="mod-panel" id="modPanel">
    <header class="mod-header">
      <h3>Modifier <span class="mod-paint-label" id="modPaintLabel">Dark</span></h3>
      <button class="mod-toggle" id="modCloseBtn" type="button" aria-label="Close modifier">×</button>
    </header>
    <div class="mod-body">
      <fieldset class="mod-fieldset">
        <legend>Paint</legend>
        <div class="paint-picker" role="radiogroup" aria-label="Paint color" style="padding: 4px 0;">
          <button class="paint-swatch swatch-dark active" data-paint="" title="Dark (default)" aria-label="Dark"></button>
          <button class="paint-swatch swatch-green" data-paint="paint-green" title="Army green" aria-label="Army green"></button>
          <button class="paint-swatch swatch-white" data-paint="paint-white" title="Glossy white" aria-label="Glossy white"></button>
        </div>
      </fieldset>
      <fieldset class="mod-fieldset" data-paint-only="green,white">
        <legend>Fill</legend>
        <label class="mod-row"><span>color</span><input type="color" data-var="fill"/></label>
      </fieldset>
      <fieldset class="mod-fieldset">
        <legend>Drop Shadow</legend>
        <label class="mod-row"><span>dy</span><input type="range" min="0" max="20" step="0.5" data-var="dsDy"/><output></output></label>
        <label class="mod-row"><span>blur</span><input type="range" min="0" max="10" step="0.1" data-var="dsBlur"/><output></output></label>
        <label class="mod-row"><span>alpha</span><input type="range" min="0" max="1" step="0.01" data-var="dsSlope"/><output></output></label>
      </fieldset>
      <fieldset class="mod-fieldset">
        <legend>Bump</legend>
        <label class="mod-row"><span>stdDev</span><input type="range" min="0" max="3" step="0.1" data-var="bumpStd"/><output></output></label>
      </fieldset>
      <fieldset class="mod-fieldset">
        <legend>Specular 1 (upper-left)</legend>
        <label class="mod-row"><span>scale</span><input type="range" min="0" max="30" step="1" data-var="spec1Scale"/><output></output></label>
        <label class="mod-row"><span>constant</span><input type="range" min="0" max="8" step="0.1" data-var="spec1Const"/><output></output></label>
        <label class="mod-row"><span>exponent</span><input type="range" min="0" max="100" step="1" data-var="spec1Exp"/><output></output></label>
        <label class="mod-row"><span>color</span><input type="color" data-var="spec1Color"/></label>
      </fieldset>
      <fieldset class="mod-fieldset">
        <legend>Specular 2 (upper-right)</legend>
        <label class="mod-row"><span>scale</span><input type="range" min="0" max="30" step="1" data-var="spec2Scale"/><output></output></label>
        <label class="mod-row"><span>constant</span><input type="range" min="0" max="8" step="0.1" data-var="spec2Const"/><output></output></label>
        <label class="mod-row"><span>exponent</span><input type="range" min="0" max="100" step="1" data-var="spec2Exp"/><output></output></label>
        <label class="mod-row"><span>color</span><input type="color" data-var="spec2Color"/></label>
      </fieldset>
      <div class="mod-actions">
        <button id="modCopy" type="button">Copy snippet</button>
        <span class="mod-copy-status" id="modCopyStatus"></span>
      </div>
    </div>
  </aside>

  <main class="app">

    <!-- Embossed "Plan B" page background — fixed full-viewport, sits
         behind every page (homepage, quiz, results). Hidden from screen
         readers; only the per-page content sits above this layer. -->
    <div class="page-bg-pattern" aria-hidden="true">
      <div class="bg-tilt">
        <div class="bg-row"><span>Plan B</span><span>Piano B</span><span>Plano B</span><span>แผนสำรอง</span><span>План Б</span><span>プランB</span><span>B Planı</span><span>备用计划</span></div>
        <div class="bg-row"><span>Phương án B</span><span>备用计划</span><span>Plan B</span><span>플랜 B</span><span>Suunnitelma B</span><span>योजना बी</span><span>Plano B</span><span>Plán B</span></div>
        <div class="bg-row"><span>Piano B</span><span>Plan B</span><span>Σχέδιο Β</span><span>Plano B</span><span>خطة ب</span><span>Consilium B</span><span>プランB</span><span>פּלאַן ב</span></div>
        <div class="bg-row"><span>Plan B</span><span>תוכנית ב</span><span>プランB</span><span>እቅድ ቢ</span><span>План Б</span><span>Plan B</span><span>Piano B</span><span>플랜 B</span></div>
        <div class="bg-row"><span>备用计划</span><span>পরিকল্পনা বি</span><span>Piano B</span><span>플랜 B</span><span>Plan B</span><span>Plano B</span><span>План Б</span><span>แผนสำรอง</span></div>
        <div class="bg-row"><span>Plan B</span><span>योजना बी</span><span>B Planı</span><span>خطة ب</span><span>Σχέδιο Β</span><span>Plan B</span><span>Piano B</span><span>תוכנית ב</span></div>
        <div class="bg-row"><span>Phương án B</span><span>プランB</span><span>Plan B</span><span>План Б</span><span>Suunnitelma B</span><span>Piano B</span><span>备用计划</span><span>ផែនការ B</span></div>
        <div class="bg-row"><span>플랜 B</span><span>Plan B</span><span>Plano B</span><span>Consilium B</span><span>योजना बी</span><span>Σχέδιο Β</span><span>Plan B</span><span>Piano B</span></div>
        <div class="bg-row"><span>Plán B</span><span>خطة ب</span><span>Plan B</span><span>プランB</span><span>פּלאַן ב</span><span>План Б</span><span>Piano B</span><span>እቅድ ቢ</span></div>
        <div class="bg-row"><span>Plan B</span><span>תוכנית ב</span><span>备用计划</span><span>পরিকল্পনা বি</span><span>Σχέδιο Β</span><span>Plano B</span><span>ផែនការ B</span><span>योजना बी</span></div>
      </div>
    </div>

    <!-- HERO -->
    <section class="hero" id="hero-section">
      <h1 class="paint-3d" data-i18n="brand">Deepstock</h1>
      <p class="hero-sub" data-i18n="hero_sub">Crisis Preparedness</p>
      <button class="cta-btn" @click="startQuiz">
        <span data-i18n="hero_cta">Begin</span>
      </button>
    </section>

    <!-- SCENARIO STRIP -->
    <div class="scenario-strip" id="scenario-strip">
      <div class="scenario-strip-track" id="scenario-track">
        <div class="scenario-pill pill-s1"><span class="pill-dot"></span><span data-i18n="pill_s1">📦 Supply Shock</span></div>
        <div class="scenario-pill pill-s2"><span class="pill-dot"></span><span data-i18n="pill_s2">🌾 Food Crisis</span></div>
        <div class="scenario-pill pill-s3"><span class="pill-dot"></span><span data-i18n="pill_s3">📈 Hyperinflation</span></div>
        <div class="scenario-pill pill-s4"><span class="pill-dot"></span><span data-i18n="pill_s4">🏦 Bank Crisis</span></div>
        <div class="scenario-pill pill-s5"><span class="pill-dot"></span><span data-i18n="pill_s5">⚡ Power Outage</span></div>
        <div class="scenario-pill pill-s6"><span class="pill-dot"></span><span data-i18n="pill_s6">💧 Water Failure</span></div>
        <div class="scenario-pill pill-s7"><span class="pill-dot"></span><span data-i18n="pill_s7">⚠️ Partial Collapse</span></div>
        <div class="scenario-pill pill-s8"><span class="pill-dot"></span><span data-i18n="pill_s8">🪖 War / Conflict</span></div>
        <div class="scenario-pill pill-s9"><span class="pill-dot"></span><span data-i18n="pill_s9">💀 Total Collapse</span></div>
        <div class="scenario-pill pill-s1" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s1">📦 Supply Shock</span></div>
        <div class="scenario-pill pill-s2" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s2">🌾 Food Crisis</span></div>
        <div class="scenario-pill pill-s3" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s3">📈 Hyperinflation</span></div>
        <div class="scenario-pill pill-s4" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s4">🏦 Bank Crisis</span></div>
        <div class="scenario-pill pill-s5" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s5">⚡ Power Outage</span></div>
        <div class="scenario-pill pill-s6" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s6">💧 Water Failure</span></div>
        <div class="scenario-pill pill-s7" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s7">⚠️ Partial Collapse</span></div>
        <div class="scenario-pill pill-s8" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s8">🪖 War / Conflict</span></div>
        <div class="scenario-pill pill-s9" aria-hidden="true"><span class="pill-dot"></span><span data-i18n="pill_s9">💀 Total Collapse</span></div>
      </div>
    </div>

    <!-- QUESTIONNAIRE -->
    <section class="quiz-section hidden" id="quiz-section">
      <div class="quiz-progress-bar">
        <a class="qpb-logo logo" data-i18n="brand" href="#" aria-label="Back to landing page" @click.prevent="restartQuiz">Deepstock</a>
        <div class="progress-wrap">
          <div class="progress-header">
            <span class="progress-label" data-i18n="progress_label">Assessment Progress</span>
            <span class="progress-count" id="progress-count">1 / 8</span>
          </div>
          <div class="progress-bar"><div class="progress-fill" id="progress-fill" style="width:12.5%"></div></div>
        </div>
        <div class="lang-toggle" aria-label="Language">
          <button class="lang-btn" data-lang="en" @click="setLang('en')">EN</button>
          <button class="lang-btn" data-lang="de" @click="setLang('de')">DE</button>
        </div>
      </div>
      <div class="quiz-content">
        <div id="question-container"></div>
      </div>
      <div class="quiz-footer" id="quiz-footer"></div>
    </section>

    <!-- RESULTS -->
    <section class="results-section" id="results-section">
      <div id="risk-banner-container"></div>

      <!-- PROTEIN OFFER — shown only if protein_access === uncertain -->
      <div class="protein-offer" id="protein-offer-section">
        <div class="protein-offer-badge"><span class="badge-icon" v-html="icon('lock', 12)"></span><span data-i18n="protein_offer_badge">Exclusive — DACH Region Priority Access</span></div>
        <div class="protein-offer-title" data-i18n="protein_offer_title">Secure your high-grade animal protein source</div>
        <div class="protein-offer-body" data-i18n="protein_offer_body">You indicated that your protein supply may not be secure in a crisis. We have identified an exclusive, verified source of high-grade animal protein — available with priority access for Deepstock members in Germany, Austria, and Switzerland.</div>
        <a class="protein-offer-btn" href="PROTEIN_OFFER_URL" target="_blank" rel="noopener noreferrer">
          <span class="po-label-mobile" data-i18n="protein_offer_btn_short">Secure Source Now</span>
          <span class="po-label-desktop" data-i18n="protein_offer_btn">Secure protein source now</span>
        </a>
      </div>

      <!-- AI NARRATIVE SECTION -->
      <div class="narrative-section" id="narrative-section">
        <div class="narrative-header">
          <span class="narrative-icon" v-html="icon('brain', 20)"></span>
          <div class="narrative-title" data-i18n="narrative_title">Your Personal Analysis</div>
          <div class="narrative-tag" data-i18n="narrative_tag">AI Generated</div>
        </div>
        <div id="narrative-content">
          <div class="narrative-loading" id="narrative-loading">
            <div class="narrative-progress"><div class="narrative-progress-fill" id="narrative-progress"></div></div>
            <div class="loading-dots"><span></span><span></span><span></span></div>
            <div class="loading-text" data-i18n="narrative_loading">Generating your personalised analysis...</div>
            <div style="font-size:10px;color:var(--muted);margin-top:8px;font-family:var(--font-mono);letter-spacing:0.06em" data-i18n="narrative_loading_sub">Takes up to 10 seconds</div>
          </div>
          <div class="narrative-body hidden" id="narrative-text"></div>
        </div>
        <div class="narrative-cta hidden" id="narrative-cta">
          <button class="narrative-cta-btn" @click="openCaptureModal" data-i18n="cta_scroll">
            Receive Plan by email
          </button>
        </div>
      </div>

      <!-- CAPTURE FORM (modal) -->
      <div class="form-modal" id="capture-modal" role="dialog" aria-modal="true" aria-hidden="true" aria-labelledby="capture-modal-title" @click="onModalBackdropClick">
        <div class="form-modal-panel" @click.stop>
          <div class="form-modal-header">
            <div class="modal-title" id="capture-modal-title" data-i18n="capture_title">Personal Details</div>
            <button type="button" class="form-modal-close" @click="closeCaptureModal" aria-label="Close">×</button>
          </div>

          <div class="form-modal-body" id="form-modal-body">
            <!-- Success state replaces the form after submit -->
            <div class="capture-success hidden" id="capture-success">
              <div class="success-check" v-html="icon('check', 40)"></div>
              <div style="font-family:var(--font-display);font-weight:800;font-size:22px;color:var(--green-bright);margin-bottom:8px;text-align:center" data-i18n="success_title">Plan sent!</div>
              <div style="font-size:14px;color:var(--text-dim);line-height:1.6;text-align:center" data-i18n="success_text">Check your inbox — your personalised plan is on its way.</div>
              <div class="success-spam">
                <span class="success-spam-icon" v-html="icon('mail', 16)"></span>
                <div data-i18n="success_spam">Don't see it? Check your <strong>spam or junk folder</strong>. If it's there, please mark it as <strong>"Not Spam"</strong> — this ensures future updates reach your inbox directly, and helps us improve deliverability for everyone.</div>
              </div>
              <div style="margin-top:14px;text-align:center">
                <button class="narrative-cta-btn" @click="closeAndScrollToRecs" data-i18n="success_explore">Explore Recommendations</button>
              </div>
            </div>

            <div class="capture-sub" data-i18n="capture_sub">Enter your details and we'll email your complete survival plan immediately — including all recommendations below.</div>

            <form id="capture-form" @submit="submitCapture">
              <input type="hidden" id="h_location" name="location"/>
              <input type="hidden" id="h_household" name="household_size"/>
              <input type="hidden" id="h_water" name="water_access"/>
              <input type="hidden" id="h_food" name="food_reserves"/>
              <input type="hidden" id="h_medical" name="medical_needs"/>
              <input type="hidden" id="h_sanitation" name="sanitation"/>
              <input type="hidden" id="h_budget" name="budget_eur"/>
              <input type="hidden" id="h_priority" name="priorities"/>
              <input type="hidden" id="h_protein" name="protein_access"/>
              <input type="hidden" id="h_risk_score" name="risk_score"/>
              <input type="hidden" id="h_risk_level" name="risk_level"/>
              <input type="hidden" id="h_lang" name="language_used"/>
              <input type="hidden" id="h_timestamp" name="submitted_at"/>
              <input type="hidden" id="h_scenarios" name="scenarios"/>
              <input type="hidden" id="h_protein_pref" name="protein_preference"/>
              <input type="hidden" id="h_protein_security" name="protein_security"/>

              <div class="form-grid">
                <div class="form-row">
                  <div class="form-field">
                    <label class="field-label"><span data-i18n="field_name">First Name</span> <span style="color:var(--red)">*</span></label>
                    <input class="form-input" type="text" id="f_name" name="first_name" required
                      placeholder="First name" data-ph-en="First name" data-ph-de="Vorname"/>
                  </div>
                  <div class="form-field">
                    <label class="field-label"><span data-i18n="field_lastname">Last Name</span> <span style="color:var(--red)">*</span></label>
                    <input class="form-input" type="text" id="f_lastname" name="last_name" required
                      placeholder="Last name" data-ph-en="Last name" data-ph-de="Nachname"/>
                  </div>
                </div>
                <div class="form-field">
                  <label class="field-label"><span data-i18n="field_email">Email</span> <span style="color:var(--red)">*</span></label>
                  <input class="form-input" type="email" id="f_email" name="email" required
                    placeholder="your@email.com" data-ph-en="your@email.com" data-ph-de="deine@email.de"/>
                </div>
                <div class="form-row">
                  <div class="form-field">
                    <label class="field-label"><span data-i18n="field_city">City</span> <span style="color:var(--red)">*</span></label>
                    <input class="form-input" type="text" id="f_city" name="city" required
                      placeholder="Your city" data-ph-en="Your city" data-ph-de="Deine Stadt"/>
                  </div>
                  <div class="form-field">
                    <label class="field-label"><span data-i18n="field_country">Country</span> <span style="color:var(--red)">*</span></label>
                    <select class="form-select" id="f_country" name="country" required @change="onCountryChange">
                      <option value="">—</option>
                      <option value="AT" data-i18n="country_at">🇦🇹 Austria</option>
                      <option value="DE" data-i18n="country_de_label">🇩🇪 Germany</option>
                      <option value="CH" data-i18n="country_ch">🇨🇭 Switzerland</option>
                      <option value="US" data-i18n="country_us">🇺🇸 United States</option>
                      <option value="CA" data-i18n="country_ca">🇨🇦 Canada</option>
                      <option value="GB" data-i18n="country_gb">🇬🇧 United Kingdom</option>
                      <option value="FR" data-i18n="country_fr">🇫🇷 France</option>
                      <option value="NL" data-i18n="country_nl">🇳🇱 Netherlands</option>
                      <option value="BE" data-i18n="country_be">🇧🇪 Belgium</option>
                      <option value="ES" data-i18n="country_es">🇪🇸 Spain</option>
                      <option value="IT" data-i18n="country_it">🇮🇹 Italy</option>
                      <option value="PL" data-i18n="country_pl">🇵🇱 Poland</option>
                      <option value="SE" data-i18n="country_se">🇸🇪 Sweden</option>
                      <option value="NO" data-i18n="country_no">🇳🇴 Norway</option>
                      <option value="DK" data-i18n="country_dk">🇩🇰 Denmark</option>
                      <option value="OTHER" data-i18n="country_other">Other</option>
                    </select>
                  </div>
                </div>
                <div class="form-row">
                  <div class="form-field">
                    <label class="field-label"><span data-i18n="field_phone">Phone (optional)</span></label>
                    <input class="form-input" type="tel" id="f_phone" name="phone"
                      placeholder="+43 or +1 ..." data-ph-en="+43 or +1 ..." data-ph-de="+43 oder +49 ..."/>
                  </div>
                  <div class="form-field">
                    <label class="field-label"><span data-i18n="field_pref_lang">Preferred language</span></label>
                    <select class="form-select" id="f_pref_lang" name="preferred_language">
                      <option value="en">English</option>
                      <option value="de">Deutsch</option>
                      <option value="fr">Français</option>
                      <option value="es">Español</option>
                    </select>
                  </div>
                </div>
                <div class="form-field">
                  <label class="field-label"><span data-i18n="field_protein_label">🥩 Protein access (optional)</span></label>
                  <textarea class="form-input" id="f_protein_detail" name="protein_detail" rows="3"
                    placeholder="e.g. free-range eggs from neighbour, fishing lake nearby, hunter in family..."
                    data-ph-en="e.g. free-range eggs from neighbour, fishing lake nearby, hunter in family..."
                    data-ph-de="z. B. Bio-Eier vom Nachbarn, Angelsee in der Nähe, Jäger in der Familie..."></textarea>
                  <div style="font-size:11px;color:var(--text-dim);margin-top:4px;font-style:italic" data-i18n="protein_note">Helps us personalise your food recommendations.</div>
                </div>
                <div class="form-privacy" data-i18n="privacy_note">🔒 Your data is never sold. Unsubscribe anytime. GDPR compliant.</div>
                <label class="newsletter-check">
                  <input type="checkbox" id="f_newsletter" name="newsletter" value="yes" checked/>
                  <span class="check-box"></span>
                  <span class="check-label" data-i18n="newsletter_label">Yes, send me weekly preparedness updates from Deepstock</span>
                </label>
              </div>
            </form>
          </div>

          <div class="form-modal-footer" id="form-modal-footer">
            <button class="capture-submit" type="submit" form="capture-form" id="capture-submit-btn">
              <span data-i18n="capture_btn">Send Me My Plan</span>
            </button>
          </div>
        </div>
      </div>

      <!-- RECOMMENDATIONS + SCENARIO TABS — collapsible panels -->
      <div id="recs-anchor"></div>

      <details class="result-panel reveal-section" id="panel-recs" open>
        <summary class="result-panel-header">
          <span class="rp-title" data-i18n="panel_recs">Recommendations</span>
          <span class="rp-chevron" aria-hidden="true">▾</span>
        </summary>
        <div class="result-panel-body">
          <div class="rp-hint" data-i18n="panel_recs_hint">Tap a scenario to compare</div>
          <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>

    <!-- ABOUT -->
    <section class="about-section" id="about-section">
      <h2 data-i18n="about_title">Why Deepstock?</h2>
      <p data-i18n="about_text">Built by preparedness researchers and city-dwelling practitioners. Every recommendation is sourced, tested, and city-apartment-compatible.</p>
      <p class="affiliate-note" data-i18n="affiliate_note">* This site uses affiliate links. When you purchase through our links, we may earn a commission at no extra cost to you. This helps keep the platform free.</p>
    </section>

  </main>
</template>

<script setup>
import { onMounted } from 'vue'

// ══════════════════════════════════════
// TRANSLATIONS
// ══════════════════════════════════════
const T = {
  en: {
    brand: "Deepstock",
    page_title: "Deepstock — Survival Preparedness Advisor",
    hero_eyebrow: "Crisis Preparedness Advisor",
    hero_sub: "Crisis Preparedness",
    hero_cta: "Begin",
    intro_l1: "For crisis bows to him who plans with care",
    intro_l2: "And fortune favors those who well prepare",
    intro_l3: "And fortune favors those who well prepare.",
    stat_scenarios: "Scenarios",
    stat_questions: "Questions",
    stat_free: "Free Forever",
    email_label: "Stay Prepared",
    email_title: "Get your weekly survival briefing",
    email_sub: "Crisis updates, product recommendations, and preparedness tips. Free. No spam.",
    email_btn: "Subscribe",
    email_success: "✓ You're in. First briefing coming shortly.",
    email_note: "No spam. Unsubscribe anytime. Your data is never sold.",
    results_email_title: "Save your plan & get updates",
    results_email_sub: "We'll email you your personalised plan plus weekly preparedness updates.",
    pill_s1:"📦 Supply Shock", pill_s2:"🌾 Food Crisis",
    pill_s3:"📈 Hyperinflation", pill_s4:"🏦 Bank Crisis",
    pill_s5:"⚡ Power Outage", pill_s6:"💧 Water Failure",
    pill_s7:"⚠️ Partial Collapse", pill_s8:"🪖 War / Conflict",
    pill_s9:"💀 Total Collapse",
    pill_1: "Total Collapse",
    pill_2: "Partial Collapse",
    pill_3: "Hyperinflation",
    pill_4: "Food Shortage",
    progress_label: "Assessment Progress",
    tab_s1: "Total\nCollapse",
    tab_s2: "Partial\nCollapse",
    tab_s3: "Hyper\ninflation",
    tab_s4: "Food\nShortage",
    timeline_title: "⏱ Your Action Timeline",
    panel_recs: "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.",
    affiliate_note: "* This site uses affiliate links. When you purchase through our links, we may earn a commission at no extra cost to you. This helps keep the platform free.",
    budget_title: "Budget Allocation",
    risk_label: "Preparedness Assessment",
    risk_critical_title: "CRITICAL",
    risk_critical_desc: "You have almost no buffer. A 48-hour supply disruption would put your household in danger.",
    risk_high_title: "HIGH RISK",
    risk_high_desc: "Significant gaps in your preparedness. A 1-week disruption would be very difficult to manage.",
    risk_medium_title: "MODERATE",
    risk_medium_desc: "Some preparation in place. A 2–3 week disruption would stretch your resources.",
    risk_low_title: "PREPARED",
    risk_low_desc: "Good foundation. Focus on extending your buffer and filling specific gaps.",
    q_step: "Question",
    back_btn: "Back",
    continue_btn: "Continue",
    finish_btn: "Get My Plan",
    narrative_title: "Your Personal Analysis",
    narrative_tag: "AI Generated",
    narrative_loading: "Generating your personalised analysis...",
    narrative_loading_sub: "Takes up to 10 seconds",
    field_lastname: "Last Name",
    scroll_hint:"↓ COMPLETE YOUR PROFILE BELOW TO RECEIVE YOUR PLAN",
    capture_required:"",
    newsletter_label:"Yes, send me weekly preparedness updates from Deepstock",
    capture_label:"📋 Get Your Full Report",
    capture_title:"Personal Details",
    capture_sub:"We send your complete survival plan to your inbox plus weekly updates.",
    field_email:"Email",field_name:"First Name",field_city:"City",field_country:"Country",
    field_pref_lang:"Preferred language",field_phone:"Phone (optional)",
    field_protein_label:"Protein access (optional)",
    protein_note:"High-quality non-commercial protein sources help us personalise your food plan.",
    capture_btn:"Send Me My Plan",
    success_title:"Plan sent to your inbox!",
    success_text:"Check your email. We included your personalised recommendations, action timeline, and product links.",
    privacy_note:"Your data is never sold. Unsubscribe anytime. GDPR compliant.",
    protein_offer_badge:"Exclusive — DACH Region Priority Access",
    protein_offer_title:"Secure your high-grade animal protein source",
    protein_offer_body:"You indicated your protein supply may not be secure in a crisis. We have identified an exclusive, verified source of high-grade animal protein — available with priority access for Deepstock members in Germany, Austria, and Switzerland.",
    protein_offer_btn:"Secure protein source now",
    protein_offer_btn_short:"Secure Source Now",
    capture_header:"Personal Details",
    cta_scroll:"Receive Plan by email",
    success_explore:"Explore Recommendations",
    success_spam:"Don't see it? Check your spam or junk folder. If it's there, please mark it as Not Spam — this ensures future updates reach your inbox directly, and helps us improve deliverability for everyone.",
    view_amazon: "View on Amazon",
    bcat_water: "Water",
    bcat_food: "Food",
    bcat_growing: "Growing",
    bcat_energy: "Energy",
    bcat_medical: "Medical",
    bcat_sanitation: "Sanitation",
    tl_week1: "This week",
    tl_week2: "Week 1–2",
    tl_month1: "Month 1",
    tl_month2: "Month 2",
    tl_month3: "Month 3",
    tl_a1: "Buy sprouting seeds + mason jars. Start sprouting TODAY.",
    tl_a2: "Stock 2-week dry food reserve: rice, lentils, oats, oil, canned fish.",
    tl_a3: "Purchase AWG water unit + basic first aid kit + antidiarrheal/ORS.",
    tl_a4: "Extend food to 3 months. Add hydroponic tower. Buy solar power bank.",
    tl_a5: "Solar generator (500Wh) + sleeping bags + Baofeng radios + cash reserve.",
    sending: "Sending...",
    country_at: "🇦🇹 Austria",
    country_de_label: "🇩🇪 Germany",
    country_ch: "🇨🇭 Switzerland",
    country_us: "🇺🇸 United States",
    country_ca: "🇨🇦 Canada",
    country_gb: "🇬🇧 United Kingdom",
    country_fr: "🇫🇷 France",
    country_nl: "🇳🇱 Netherlands",
    country_be: "🇧🇪 Belgium",
    country_es: "🇪🇸 Spain",
    country_it: "🇮🇹 Italy",
    country_pl: "🇵🇱 Poland",
    country_se: "🇸🇪 Sweden",
    country_no: "🇳🇴 Norway",
    country_dk: "🇩🇰 Denmark",
    country_other: "Other",
  },
  de: {
    brand: "Kammergut",
    page_title: "Kammergut — Krisenvorsorge-Berater",
    hero_eyebrow: "⚡ Krisenvorsorge-Berater",
    hero_sub: "Krisenvorsorge",
    hero_cta: "Beginnen",
    intro_l1: "Die Krise beugt sich dem, der wohl bedacht",
    intro_l2: "Und Glück gehört dem, der sich stark gemacht",
    intro_l3: "Und Glück gehört dem, der sich stark gemacht",
    stat_scenarios: "Szenarien",
    stat_questions: "Fragen",
    stat_free: "Kostenlos",
    email_label: "Vorbereitet bleiben",
    email_title: "Dein wöchentliches Survival-Briefing",
    email_sub: "Krisenaktualisierungen, Produktempfehlungen und Vorsorge-Tipps. Kostenlos. Kein Spam.",
    email_btn: "Abonnieren",
    email_success: "✓ Du bist dabei. Erstes Briefing folgt in Kürze.",
    email_note: "Kein Spam. Jederzeit abmeldbar. Deine Daten werden nie verkauft.",
    results_email_title: "Plan speichern & Updates erhalten",
    results_email_sub: "Wir senden dir deinen personalisierten Plan sowie wöchentliche Vorsorge-Updates per E-Mail.",
    pill_s1:"📦 Versorgungsengpass", pill_s2:"🌾 Lebensmittelkrise",
    pill_s3:"📈 Hyperinflation", pill_s4:"🏦 Bankenkrise",
    pill_s5:"⚡ Stromausfall", pill_s6:"💧 Wasserversorgung",
    pill_s7:"⚠️ Partieller Kollaps", pill_s8:"🪖 Krieg / Konflikt",
    pill_s9:"💀 Totaler Kollaps",
    pill_1: "Totaler Kollaps",
    pill_2: "Partieller Kollaps",
    pill_3: "Hyperinflation",
    pill_4: "Lebensmittelkrise",
    progress_label: "Fortschritt",
    tab_s1: "Totaler\nKollaps",
    tab_s2: "Partieller\nKollaps",
    tab_s3: "Hyper\ninflation",
    tab_s4: "Lebens\nmittelkrise",
    timeline_title: "⏱ Dein Aktionsplan",
    panel_recs: "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.",
    affiliate_note: "* Diese Website nutzt Affiliate-Links. Beim Kauf über unsere Links erhalten wir eine Provision ohne Mehrkosten für dich. So bleibt die Plattform kostenlos.",
    budget_title: "Budgetverteilung",
    risk_label: "Vorsorge-Bewertung",
    risk_critical_title: "KRITISCH",
    risk_critical_desc: "Du hast fast keinen Puffer. Eine 48-stündige Versorgungsunterbrechung würde deinen Haushalt gefährden.",
    risk_high_title: "HOHES RISIKO",
    risk_high_desc: "Erhebliche Lücken in deiner Vorbereitung. Eine 1-wöchige Unterbrechung wäre sehr schwer zu bewältigen.",
    risk_medium_title: "MÄSSIG",
    risk_medium_desc: "Einige Vorbereitungen vorhanden. Eine 2–3-wöchige Unterbrechung würde deine Ressourcen strapazieren.",
    risk_low_title: "VORBEREITET",
    risk_low_desc: "Gute Grundlage. Fokussiere auf die Erweiterung deines Puffers und das Schließen spezifischer Lücken.",
    q_step: "Frage",
    back_btn: "Zurück",
    continue_btn: "Weiter",
    finish_btn: "Meinen Plan abrufen",
    narrative_title: "Deine persönliche Analyse",
    narrative_tag: "KI-Generiert",
    narrative_loading: "Deine personalisierte Analyse wird erstellt...",
    narrative_loading_sub: "Dauert bis zu 10 Sekunden",
    field_lastname: "Nachname",
    scroll_hint:"↓ PROFIL AUSFÜLLEN UM DEINEN PLAN ZU ERHALTEN",
    capture_required:"",
    newsletter_label:"Ja, ich möchte wöchentliche Vorsorge-Updates von Kammergut erhalten",
    capture_label:"",
    capture_title:"Persönliche Angaben",
    capture_sub:"Gib deine Daten ein — wir senden dir deinen vollständigen Plan sofort per E-Mail.",
    field_email:"E-Mail",field_name:"Vorname",field_city:"Stadt",field_country:"Land",
    field_pref_lang:"Bevorzugte Sprache",field_phone:"Telefon (optional)",
    field_protein_label:"Proteinquellen (optional)",
    protein_note:"Hochwertige nicht-kommerzielle Proteinquellen helfen uns deinen Ernaehrungsplan zu personalisieren.",
    capture_btn:"Plan zusenden",
    success_title:"Plan in dein Postfach gesendet!",
    success_text:"Schau in dein E-Mail-Postfach. Wir haben deine personalisierten Empfehlungen und Aktionsplan beigefuegt.",
    privacy_note:"Deine Daten werden nie verkauft. Jederzeit abmeldbar. DSGVO-konform.",
    protein_offer_badge:"Exklusiv — DACH Region Prioritätszugang",
    protein_offer_title:"Sichere deine hochwertige tierische Proteinquelle",
    protein_offer_body:"Du hast angegeben, dass deine Proteinversorgung in einer Krise möglicherweise nicht gesichert ist. Wir haben eine exklusive, geprüfte Quelle für hochwertiges tierisches Protein identifiziert — mit Prioritätszugang für Kammergut Mitglieder in Deutschland, Österreich und der Schweiz.",
    protein_offer_btn:"Proteinquelle sichern",
    protein_offer_btn_short:"Quelle sichern",
    capture_header:"Persönliche Daten",
    cta_scroll:"Plan per E-Mail erhalten",
    success_explore:"Empfehlungen ansehen",
    success_spam:"Nicht erhalten? Schau in deinen Spam-Ordner. Falls du es dort findest, markiere es bitte als Kein Spam — so landen zukünftige Updates direkt in deinem Posteingang und du hilfst uns die Zustellbarkeit für alle zu verbessern.",
    view_amazon: "Bei Amazon ansehen",
    bcat_water: "Wasser",
    bcat_food: "Lebensmittel",
    bcat_growing: "Anbau",
    bcat_energy: "Energie",
    bcat_medical: "Medizin",
    bcat_sanitation: "Hygiene",
    tl_week1: "Diese Woche",
    tl_week2: "Woche 1–2",
    tl_month1: "Monat 1",
    tl_month2: "Monat 2",
    tl_month3: "Monat 3",
    tl_a1: "Keimsprossen-Samen + Einmachgläser kaufen. Heute mit dem Keimen beginnen.",
    tl_a2: "2-Wochen-Trockenvorrat anlegen: Reis, Linsen, Hafer, Öl, Fischkonserven.",
    tl_a3: "AWG-Wassergerät + Erste-Hilfe-Set + Durchfallmittel/ORS kaufen.",
    tl_a4: "Vorrat auf 3 Monate erweitern. Hydroponik-Turm kaufen. Solar-Powerbank holen.",
    tl_a5: "Solar-Generator (500Wh) + Schlafsäcke + Baofeng-Funkgeräte + Bargeldreserve.",
    sending: "Senden...",
    country_at: "🇦🇹 Österreich",
    country_de_label: "🇩🇪 Deutschland",
    country_ch: "🇨🇭 Schweiz",
    country_us: "🇺🇸 USA",
    country_ca: "🇨🇦 Kanada",
    country_gb: "🇬🇧 Vereinigtes Königreich",
    country_fr: "🇫🇷 Frankreich",
    country_nl: "🇳🇱 Niederlande",
    country_be: "🇧🇪 Belgien",
    country_es: "🇪🇸 Spanien",
    country_it: "🇮🇹 Italien",
    country_pl: "🇵🇱 Polen",
    country_se: "🇸🇪 Schweden",
    country_no: "🇳🇴 Norwegen",
    country_dk: "🇩🇰 Dänemark",
    country_other: "Andere",
  }
}

const WORKER_URL = 'https://planb-email.janwellmann.workers.dev/submit'
let currentLang = 'en'

function setLang(lang) {
  currentLang = lang
  document.querySelectorAll('.lang-btn').forEach(btn => {
    const matches = btn.id === 'btn-' + lang || btn.dataset.lang === lang
    btn.classList.toggle('active', matches)
  })
  document.documentElement.lang = lang
  document.querySelectorAll('[data-i18n]').forEach(el => {
    const key = el.getAttribute('data-i18n')
    if (T[lang][key]) el.textContent = T[lang][key]
  })
  if (T[lang].page_title) document.title = T[lang].page_title
  document.querySelectorAll('[data-ph-' + lang + ']').forEach(el => {
    el.placeholder = el.getAttribute('data-ph-' + lang)
  })
  if (currentQ !== null && currentQ < QUESTIONS.length) renderQuestion()
  // If the user is on the results page, re-render the JS-generated chunks
  // (risk banner, recs, budget, timeline) so they pick up the new language
  // without a reload.
  if (document.body.classList.contains('results-active')) rerenderResults()
  saveState()
}

function t(key) { return T[currentLang][key] || T['en'][key] || key }

// ══════════════════════════════════════
// QUESTIONS
// ══════════════════════════════════════
const QUESTIONS = [
  {
    id: 'location', type: 'single',
    text: { en: 'Where do you live?', de: 'Wo lebst du?' },
    sub: { en: 'Your location affects water access, heating needs, and supply chain vulnerability.', de: 'Dein Standort beeinflusst Wasserzugang, Heizungsbedarf und Versorgungskettenanfälligkeit.' },
    options: [
      { val: 'city_apt', label: { en: 'City apartment', de: 'Stadtwohnung' }, sub: { en: 'No outdoor space, shared building', de: 'Kein Außenbereich, Mehrfamilienhaus' } },
      { val: 'city_house', label: { en: 'City house', de: 'Stadthaus' }, sub: { en: 'Garden possible, urban area', de: 'Garten möglich, städtisches Gebiet' } },
      { val: 'suburban', label: { en: 'Suburban / small town', de: 'Vorstadt / Kleinstadt' }, sub: { en: 'Some outdoor space, near city', de: 'Etwas Außenbereich, stadtnah' } },
      { val: 'rural', label: { en: 'Rural / countryside', de: 'Ländlich / Land' }, sub: { en: 'Land available, remote', de: 'Grundstück vorhanden, abgelegen' } },
    ]
  },
  {
    id: 'household', type: 'single',
    text: { en: 'How many people in your household?', de: 'Wie viele Personen leben in deinem Haushalt?' },
    sub: { en: 'Including children. This sets your calorie, water, and supply targets.', de: 'Einschließlich Kinder. Damit werden deine Kalorien-, Wasser- und Vorratsziele festgelegt.' },
    options: [
      { val: '1', label: { en: '1 person', de: '1 Person' }, sub: { en: '', de: '' } },
      { val: '2', label: { en: '2 people', de: '2 Personen' }, sub: { en: '', de: '' } },
      { val: '4', label: { en: '3–4 people', de: '3–4 Personen' }, sub: { en: '', de: '' } },
      { val: '6', label: { en: '5–6 people', de: '5–6 Personen' }, sub: { en: '', de: '' } },
      { val: '8', label: { en: '7+ people', de: '7+ Personen' }, sub: { en: '', de: '' } },
    ]
  },
  {
    id: 'water', type: 'single',
    text: { en: 'What is your current water access?', de: 'Wie ist dein aktueller Wasserzugang?' },
    sub: { en: 'If city supply failed tomorrow, what do you have?', de: 'Was hättest du, wenn die städtische Versorgung morgen ausfiele?' },
    options: [
      { val: 'none', label: { en: 'Nothing stored', de: 'Nichts gelagert' }, sub: { en: 'Fully dependent on city supply', de: 'Vollständig abhängig von Stadtversorgung' } },
      { val: 'minimal', label: { en: 'A few days of bottled water', de: 'Einige Tage Flaschenwasser' }, sub: { en: '1–3 days buffer', de: '1–3 Tage Puffer' } },
      { val: 'filter', label: { en: 'Filter + some storage', de: 'Filter + etwas Vorrat' }, sub: { en: '1–2 week capability', de: '1–2 Wochen Kapazität' } },
      { val: 'solid', label: { en: 'AWG machine or large storage', de: 'AWG-Gerät oder großer Vorrat' }, sub: { en: '1+ month independent', de: '1+ Monat unabhängig' } },
    ]
  },
  {
    id: 'food', type: 'single',
    text: { en: 'How much food do you have stored?', de: 'Wie viele Lebensmittel hast du gelagert?' },
    sub: { en: 'Not including fridge contents — only shelf-stable reserves.', de: 'Ohne Kühlschrankinhalt — nur haltbare Vorräte.' },
    options: [
      { val: 'none', label: { en: 'Basically nothing', de: 'Praktisch nichts' }, sub: { en: 'Weekly grocery shopper', de: 'Wöchentlicher Einkäufer' } },
      { val: 'week', label: { en: 'About 1 week', de: 'Etwa 1 Woche' }, sub: { en: 'Some canned goods and pasta', de: 'Etwas Konserven und Nudeln' } },
      { val: 'month', label: { en: '1–3 months', de: '1–3 Monate' }, sub: { en: 'Conscious prepper basics', de: 'Bewusste Vorsorge-Grundlagen' } },
      { val: 'solid', label: { en: '3+ months', de: '3+ Monate' }, sub: { en: 'Serious preparedness', de: 'Ernsthafte Vorbereitung' } },
    ]
  },
  {
    id: 'medical', type: 'single',
    text: { en: 'Does your household have ongoing medical needs?', de: 'Hat dein Haushalt laufende medizinische Bedürfnisse?' },
    sub: { en: 'Prescription medications, chronic conditions, infants, elderly.', de: 'Verschreibungspflichtige Medikamente, chronische Erkrankungen, Säuglinge, ältere Menschen.' },
    options: [
      { val: 'none', label: { en: 'No — everyone healthy', de: 'Nein — alle gesund' }, sub: { en: 'No prescriptions needed', de: 'Keine Verschreibungen benötigt' } },
      { val: 'mild', label: { en: 'Minor — OTC medications only', de: 'Gering — nur rezeptfreie Medikamente' }, sub: { en: 'Vitamins, pain relief, allergy meds', de: 'Vitamine, Schmerzmittel, Allergiemittel' } },
      { val: 'moderate', label: { en: 'Moderate — some prescriptions', de: 'Mäßig — einige Verschreibungen' }, sub: { en: 'Manageable without hospital', de: 'Handhabbar ohne Krankenhaus' } },
      { val: 'high', label: { en: 'High — critical medications', de: 'Hoch — kritische Medikamente' }, sub: { en: 'Requires planning ahead', de: 'Erfordert vorausschauende Planung' } },
    ]
  },
  {
    id: 'sanitation', type: 'single',
    text: { en: 'What is your sanitation backup?', de: 'Wie ist deine Sanitär-Notlösung?' },
    sub: { en: "If your building's sewage and water stopped working today.", de: 'Wenn Abwasser und Wasser in deinem Gebäude heute ausfallen würden.' },
    options: [
      { val: 'none', label: { en: 'No backup plan', de: 'Kein Notfallplan' }, sub: { en: 'Fully dependent on city', de: 'Vollständig von Stadt abhängig' } },
      { val: 'basic', label: { en: 'Basic supplies only', de: 'Nur Grundbedarf' }, sub: { en: 'Soap, disinfectant', de: 'Seife, Desinfektionsmittel' } },
      { val: 'bucket', label: { en: 'Bucket toilet + chemicals', de: 'Eimer-Toilette + Chemikalien' }, sub: { en: 'Can manage without sewage', de: 'Kann ohne Kanalisation auskommen' } },
      { val: 'full', label: { en: 'Full sanitation kit', de: 'Vollständiges Hygiene-Set' }, sub: { en: 'Ready for extended outage', de: 'Bereit für langen Ausfall' } },
    ]
  },
  {
    id: 'budget', type: 'slider',
    text: { en: 'What is your total preparedness budget?', de: 'Was ist dein Gesamtbudget für Vorsorge?' },
    sub: { en: 'One-time investment for a 3-month baseline. You can build gradually.', de: 'Einmalige Investition für eine 3-Monats-Grundlage. Du kannst schrittweise aufbauen.' },
    min: 200, max: 5000, step: 100, default: 1500,
    unit: '€',
    labels: { en: ['€200 (start)', '€5,000 (full)'], de: ['€200 (Start)', '€5.000 (voll)'] }
  },
  {
    id: 'scenarios',
    type: 'multi',
    text: {
      en: 'Which scenarios are you preparing for?',
      de: 'Für welche Szenarien bereitest du dich vor?'
    },
    sub: {
      en: 'Select all that apply. Your choices shape your personalised plan and recommendations.',
      de: 'Alles Zutreffende auswählen. Deine Auswahl bestimmt deinen personalisierten Plan und die Empfehlungen.'
    },
    options: [
      { val: 'supply_shock',     label: { en: '📦 Supply Side Shock',       de: '📦 Versorgungsengpass'      }, sub: { en: 'Empty shelves, import disruptions, rationing',          de: 'Leere Regale, Importunterbrechungen, Rationierung'        } },
      { val: 'food_crisis',      label: { en: '🌾 Food Crisis / Shortage',  de: '🌾 Lebensmittelkrise'       }, sub: { en: 'Food scarcity, price spikes, distribution breakdown',    de: 'Nahrungsknappheit, Preisspitzen, Verteilungsversagen'     } },
      { val: 'hyperinflation',   label: { en: '📈 Hyperinflation',          de: '📈 Hyperinflation'          }, sub: { en: 'Rapid currency devaluation, purchasing power collapse',  de: 'Schnelle Geldentwertung, Kaufkraftverlust'                } },
      { val: 'bank_crisis',      label: { en: '🏦 Bank / Financial Crisis', de: '🏦 Banken- / Finanzkrise'   }, sub: { en: 'Capital controls, frozen accounts, bank closures',      de: 'Kapitalverkehrskontrollen, Kontosperrungen'               } },
      { val: 'power_outage',     label: { en: '⚡ Extended Power Outage',   de: '⚡ Längerer Stromausfall'    }, sub: { en: 'Grid failure, days to weeks without electricity',        de: 'Netzausfall, Tage bis Wochen ohne Strom'                  } },
      { val: 'water_failure',    label: { en: '💧 Water Supply Failure',    de: '💧 Wasserversorgungsausfall' }, sub: { en: 'Municipal water disruption, contamination',             de: 'Städtische Wasserunterbrechung, Kontamination'            } },
      { val: 'partial_collapse', label: { en: '⚠️ Partial Collapse',        de: '⚠️ Partieller Kollaps'      }, sub: { en: 'Major infrastructure disruptions, weeks to months',     de: 'Größere Infrastrukturunterbrechungen, Wochen bis Monate'  } },
      { val: 'war',              label: { en: '🪖 War / Armed Conflict',    de: '🪖 Krieg / Bewaffneter Konflikt' }, sub: { en: 'Regional conflict affecting supply and safety',     de: 'Regionaler Konflikt, der Versorgung und Sicherheit betrifft' } },
      { val: 'total_collapse',   label: { en: '💀 Total Collapse',          de: '💀 Totaler Kollaps'         }, sub: { en: 'Full breakdown of infrastructure and social order',     de: 'Vollständiger Zusammenbruch von Infrastruktur und Ordnung'} },
    ]
  },
  {
    id: 'protein_pref',
    type: 'multi',
    text: { en: 'What is your top protein preference?', de: 'Was ist deine bevorzugte Proteinquelle?' },
    sub: { en: 'Select all that apply. This shapes your food recommendations.', de: 'Alles Zutreffende auswählen. Beeinflusst deine Lebensmittelempfehlungen.' },
    options: [
      { val: 'eggs',    label: { en: '🥚 Free-range / pastured eggs',    de: '🥚 Freiland- / Weidehaltungs-Eier'   }, sub: { en: 'Local farm or own hens',            de: 'Lokaler Bauernhof oder eigene Hühner'  } },
      { val: 'dairy',   label: { en: '🥛 Raw milk / grass-fed dairy',     de: '🥛 Rohmilch / Weidemilchprodukte'   }, sub: { en: 'Direct from farm',                 de: 'Direkt vom Bauernhof'                } },
      { val: 'meat',    label: { en: '🦌 Wild game / grass-fed meat',     de: '🦌 Wild / Weidefleisch'             }, sub: { en: 'Hunting, local butcher, own farm',  de: 'Jagd, lokaler Metzger, eigener Hof'  } },
      { val: 'fish',    label: { en: '🐟 Wild-caught fish / seafood',     de: '🐟 Wildfang-Fisch / Meeresfrüchte' }, sub: { en: 'Fishing access or trusted source',  de: 'Angelzugang oder vertrauenswürdige Quelle' } },
      { val: 'legumes', label: { en: '🌱 Home-grown legumes / sprouts',   de: '🌱 Selbst angebaute Hülsenfrüchte' }, sub: { en: 'Garden, balcony, or indoor',        de: 'Garten, Balkon oder Indoor'          } },
      { val: 'none',    label: { en: '❌ No preference / not applicable', de: '❌ Keine Präferenz / trifft nicht zu' }, sub: { en: '', de: '' } },
    ]
  },
  {
    id: 'protein_access',
    type: 'single',
    text: { en: 'Is this protein source reliably available in a crisis?', de: 'Ist diese Proteinquelle in einer Krise zuverlässig verfügbar?' },
    sub: { en: 'Think: if supermarkets were closed for 4 weeks, could you still access your preferred protein?', de: 'Angenommen, Supermärkte sind 4 Wochen geschlossen — hättest du noch Zugang zu deiner bevorzugten Proteinquelle?' },
    options: [
      { val: 'yes',       label: { en: '✅ Yes — I have a trusted local source', de: '✅ Ja — ich habe eine verlässliche lokale Quelle' }, sub: { en: 'Farm, hunter, fisher, own livestock or garden', de: 'Hof, Jäger, Fischer, eigenes Vieh oder Garten' } },
      { val: 'uncertain', label: { en: '⚠️ Not sure — I depend on stores',       de: '⚠️ Unsicher — ich bin auf Geschäfte angewiesen'  }, sub: { en: 'No guaranteed access if supply chains fail',   de: 'Kein gesicherter Zugang bei Versorgungsausfall'  } },
    ]
  },
]

// ══════════════════════════════════════
// ICONS — Lucide-style line icons, inlined so we don't pull a runtime
// dependency. Stroke colour comes from CSS (currentColor) so each
// surface (rec card, timeline dot, narrative header, etc.) can pick
// its own tint while still feeling like one icon family.
// Form-field emojis (🥩 etc.) intentionally stay as emoji per request.
// ══════════════════════════════════════
const ICON_PATHS = {
  droplet: '<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"/>',
  sprout:  '<path d="M7 20h10"/><path d="M10 20c5.5-2.5.8-6.4 3-10"/><path d="M9.5 9.4c1.1.8 1.8 2.2 2.3 3.7-2 .4-3.5.4-4.8-.3-1.2-.6-2.3-1.9-3-4.2 2.8-.5 4.4 0 5.5.8z"/><path d="M14.1 6a7 7 0 0 0-1.1 4c1.9-.1 3.3-.6 4.3-1.4 1-1 1.6-2.3 1.7-4.6-2.7.1-4 1-4.9 2z"/>',
  zap:     '<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>',
  cart:    '<circle cx="9" cy="20" r="1.5"/><circle cx="18" cy="20" r="1.5"/><path d="M2.5 3h2.5l2.7 13.4a2 2 0 0 0 2 1.6h9a2 2 0 0 0 2-1.6L22.5 7H6"/>',
  flame:   '<path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.4-.5-2-1-3-1.1-2.1-.2-4 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.2.4-2.3 1-3a2.5 2.5 0 0 0 2.5 2.5z"/>',
  leaf:    '<path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.5 19.2 3c1.4 9.3-3.6 19.4-8.2 17z"/><path d="M2 21c0-3 1.85-5.36 5.08-6"/>',
  package: '<path d="M16.5 9.4 7.55 4.24"/><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="M3.27 6.96 12 12.01l8.73-5.05"/><path d="M12 22.08V12"/>',
  radio:   '<circle cx="12" cy="12" r="2"/><path d="M4.9 19.1A10 10 0 0 1 4.9 4.9"/><path d="M7.8 16.2a6 6 0 0 1 0-8.5"/><path d="M16.2 7.8a6 6 0 0 1 0 8.5"/><path d="M19.1 4.9a10 10 0 0 1 0 14.2"/>',
  brain:   '<path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44A2.5 2.5 0 0 1 4.5 17a2.5 2.5 0 0 1-1.32-4.24A3 3 0 0 1 4.5 7a2.5 2.5 0 0 1 2.04-4.04A2.5 2.5 0 0 1 9.5 2z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44A2.5 2.5 0 0 0 19.5 17a2.5 2.5 0 0 0 1.32-4.24A3 3 0 0 0 19.5 7a2.5 2.5 0 0 0-2.04-4.04A2.5 2.5 0 0 0 14.5 2z"/>',
  lock:    '<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
  check:   '<path d="M20 6 9 17l-5-5"/>',
  mail:    '<rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a2 2 0 0 1-2.06 0L2 7"/>',
  shield:  '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',
}
function icon(name, size = 22) {
  const paths = ICON_PATHS[name] || ICON_PATHS.shield
  return `<svg class="icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${paths}</svg>`
}
// Map the emoji we used to live with onto an icon name so the existing
// rec-card / timeline data tables don't need a wholesale rewrite.
const EMOJI_TO_ICON = {
  '💧': 'droplet',
  '🌾': 'sprout', '🥦': 'leaf', '🌱': 'sprout',
  '⚡': 'zap', '🕯️': 'flame',
  '🛒': 'cart', '📦': 'package',
  '📡': 'radio', '🧠': 'brain', '🔒': 'lock',
  '✅': 'check', '📬': 'mail',
}
function iconForEmoji(emoji, size) { return icon(EMOJI_TO_ICON[emoji] || 'shield', size) }

// ══════════════════════════════════════
// STATE
// ══════════════════════════════════════
let currentQ = 0
let answers = {}
let currentScenario = 1
let riskScore = 0
let riskLevelStr = ''

// Session persistence — keep the user's progress across reloads inside
// the same browser tab. `sessionStorage` is the right scope: progress
// dies when the tab closes (privacy-friendly default for a lead form),
// but reload / nav-away-and-back restores. Bump the key suffix when the
// QUESTIONS shape changes incompatibly.
const STATE_KEY = 'kammergut.state.v1'
function getStage() {
  const results = document.getElementById('results-section')
  const quiz = document.getElementById('quiz-section')
  if (results && results.classList.contains('active')) return 'results'
  if (quiz && !quiz.classList.contains('hidden')) return 'quiz'
  return 'home'
}
function saveState() {
  const stage = getStage()
  if (stage === 'home') { clearState(); return }
  try {
    sessionStorage.setItem(STATE_KEY, JSON.stringify({
      stage, currentQ, answers, currentScenario,
      currentLang, ts: Date.now(),
    }))
  } catch {}
}
function clearState() {
  try { sessionStorage.removeItem(STATE_KEY) } catch {}
}
function loadState() {
  try {
    const raw = sessionStorage.getItem(STATE_KEY)
    if (!raw) return null
    const s = JSON.parse(raw)
    // Discard sessions older than 4 hours so a stale tab doesn't drop
    // the user mid-flow on a different day.
    if (s.ts && Date.now() - s.ts > 4 * 60 * 60 * 1000) return null
    return s
  } catch { return null }
}

// ══════════════════════════════════════
// QUIZ FLOW
// ══════════════════════════════════════
function startQuiz() {
  const hide = id => { const el = document.getElementById(id) || document.querySelector('.' + id); if(el) el.classList.add('hidden') }
  const show = id => { const el = document.getElementById(id); if(el) { el.classList.remove('hidden'); el.style.display='' } }

  hide('hero-section')
  hide('about-section')
  const strip = document.querySelector('.scenario-strip')
  if(strip) strip.classList.add('hidden')

  document.body.style.overflow = 'auto'
  document.body.style.height = 'auto'
  document.querySelector('.app').style.overflow = 'visible'
  document.querySelector('.app').style.height = 'auto'

  const quizEl = document.getElementById('quiz-section')
  if(quizEl) quizEl.classList.remove('hidden')
  document.body.classList.add('quiz-active')

  window.scrollTo({ top: 0, behavior: 'smooth' })
  currentQ = 0; answers = {}
  renderQuestion()
}

function renderQuestion() {
  if(!QUESTIONS[currentQ]) { console.error('No question at index', currentQ); return }
  const q = QUESTIONS[currentQ]
  const pct = ((currentQ + 1) / QUESTIONS.length) * 100
  document.getElementById('progress-fill').style.width = pct + '%'
  document.getElementById('progress-count').textContent = (currentQ + 1) + ' / ' + QUESTIONS.length

  let html = `<div class="question-card">
    <div class="q-step">${t('q_step')} ${currentQ + 1}</div>
    <div class="q-text">${q.text[currentLang]}</div>
    <div class="q-sub">${q.sub[currentLang]}</div>`

  if (q.type === 'single') {
    html += `<div class="q-options">`
    q.options.forEach(opt => {
      const sel = answers[q.id] === opt.val ? 'selected' : ''
      html += `<div class="q-opt ${sel}" onclick="selectOption('${q.id}','${opt.val}',this)">
        <div class="opt-radio"></div>
        <div>
          <div class="opt-label">${opt.label[currentLang]}</div>
          ${opt.sub[currentLang] ? `<div class="opt-sub">${opt.sub[currentLang]}</div>` : ''}
        </div>
      </div>`
    })
    html += `</div>`
  } else if (q.type === 'multi') {
    html += `<div class="q-options">`
    const selArr = answers[q.id] || []
    q.options.forEach(opt => {
      const sel = selArr.includes(opt.val) ? 'selected' : ''
      html += `<div class="q-opt multi ${sel}" onclick="toggleMulti('${q.id}','${opt.val}',this)">
        <div class="opt-radio"></div>
        <div><div class="opt-label">${opt.label[currentLang]}</div></div>
      </div>`
    })
    html += `</div>`
  } else if (q.type === 'slider') {
    const val = answers[q.id] || q.default
    const labels = q.labels[currentLang] || q.labels['en']
    html += `<div class="slider-wrap">
      <div class="slider-labels"><span>${labels[0]}</span><span>${labels[1]}</span></div>
      <input type="range" id="slider-input" min="${q.min}" max="${q.max}" step="${q.step}" value="${val}"
        oninput="updateSlider(this.value,'${q.id}')"/>
      <div class="slider-val" id="slider-display">${q.unit}${parseInt(val).toLocaleString()}</div>
    </div>`
    if (!answers[q.id]) answers[q.id] = q.default
  }

  html += `</div>`

  const isLast = currentQ === QUESTIONS.length - 1
  // Single-choice steps auto-advance on tap, so the Continue button is
  // redundant — render only Back (if available) on those screens. Multi
  // and slider steps still need the explicit Continue.
  const showContinue = q.type !== 'single'
  const showBack = currentQ > 0
  const parts = []
  if (showBack) parts.push(`<button class="btn-back" onclick="prevQ()">${t('back_btn')}</button>`)
  if (showContinue) parts.push(`<button class="btn-next" id="btn-next" onclick="nextQ()" ${canProceed() ? '' : 'disabled'}>${isLast ? t('finish_btn') : t('continue_btn')}</button>`)
  const nav = parts.length ? `<div class="q-nav">${parts.join('')}</div>` : ''

  document.getElementById('question-container').innerHTML = html
  document.getElementById('quiz-footer').innerHTML = nav
}

function canProceed() {
  const q = QUESTIONS[currentQ]
  if (q.type === 'slider' || q.type === 'multi') return true
  return !!answers[q.id]
}

function selectOption(qid, val, el) {
  answers[qid] = val
  document.querySelectorAll('.q-opt').forEach(o => o.classList.remove('selected'))
  el.classList.add('selected')
  const nextBtn = document.getElementById('btn-next')
  if (nextBtn) nextBtn.disabled = false
  saveState()
  // Single-choice → auto-advance. Short delay so the user sees the green
  // selected state register before the screen flips. They can always go
  // Back to revise — the answer is preserved in `answers[qid]` and
  // re-applied as `selected` when renderQuestion runs again.
  setTimeout(() => {
    if (answers[qid] === val) nextQ()
  }, 220)
}

function toggleMulti(qid, val, el) {
  if (!answers[qid]) answers[qid] = []
  const idx = answers[qid].indexOf(val)
  if (idx >= 0) { answers[qid].splice(idx, 1); el.classList.remove('selected') }
  else { answers[qid].push(val); el.classList.add('selected') }
  saveState()
}

function updateSlider(val, qid) {
  answers[qid] = parseInt(val)
  document.getElementById('slider-display').innerHTML = `€${parseInt(val).toLocaleString()}`
  saveState()
}

function nextQ() {
  if (currentQ < QUESTIONS.length - 1) { currentQ++; renderQuestion(); saveState() }
  else showResults()
}

function prevQ() { if (currentQ > 0) { currentQ--; renderQuestion(); saveState() } }

function restartQuiz() {
  const rs = document.getElementById('results-section')
  if(rs) { rs.classList.remove('active'); rs.style.display = 'none' }
  const hero = document.getElementById('hero-section')
  if(hero) hero.classList.remove('hidden')
  const about = document.getElementById('about-section')
  if(about) about.classList.remove('hidden')
  const strip = document.querySelector('.scenario-strip')
  if(strip) strip.classList.remove('hidden')
  const quiz = document.getElementById('quiz-section')
  if(quiz) quiz.classList.add('hidden')
  document.body.classList.remove('quiz-active')
  document.body.classList.remove('results-active')

  // Wipe any in-progress session state so the home view is fresh.
  currentQ = 0; answers = {}; currentScenario = 1; riskScore = 0; riskLevelStr = ''
  clearState()

  // Restore the locked-viewport layout that startQuiz had to undo for
  // the scrollable quiz/results pages — without this the hero on the
  // landing page collapses to its content height and leaves a white
  // half-screen.
  document.body.style.overflow = ''
  document.body.style.height = ''
  const app = document.querySelector('.app')
  if (app) {
    app.style.overflow = ''
    app.style.height = ''
  }

  window.scrollTo({ top: 0, behavior: 'smooth' })

  // Replay the page-bg-pattern row-slide and the hero fadeUp cascade
  // when returning home from quiz/results. We remove .intro-done for
  // a frame, then re-add it on the next animation frame — the
  // animation-name change retriggers each keyframe from scratch.
  document.body.classList.remove('intro-done')
  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      document.body.classList.add('intro-done')
    })
  })
}

// ══════════════════════════════════════
// RESULTS ENGINE
// ══════════════════════════════════════
function calcRisk() {
  let s = 0
  if (answers.water === 'none') s += 3; else if (answers.water === 'minimal') s += 2; else if (answers.water === 'filter') s += 1
  if (answers.food === 'none') s += 3; else if (answers.food === 'week') s += 2; else if (answers.food === 'month') s += 1
  if (answers.medical === 'high') s += 2; else if (answers.medical === 'moderate') s += 1
  if (answers.sanitation === 'none') s += 2; else if (answers.sanitation === 'basic') s += 1
  return s
}

function getN() { const m = {'1':1,'2':2,'4':3.5,'6':5.5,'8':8}; return m[answers.household] || 4 }

function getScenarioRecs(scenario) {
  const n = getN()
  const lang = currentLang
  const amzDomain = lang === 'de' ? 'amazon.de' : 'amazon.com'

  const data = {
    1: {
      label: { en: 'Total Supply Collapse', de: 'Totaler Versorgungskollaps' },
      cards: [
        { icon: 'droplet', cat: { en: 'Water', de: 'Wasser' }, title: { en: 'Atmospheric Water Generator', de: 'Atmosphärischer Wassergenerator' },
          priority: { en: 'CRITICAL', de: 'KRITISCH' }, pCls: 'p-critical', color: '#1A4A5A',
          items: [
            { name: { en: 'Solaris WaterGen A10 (10L/day)', de: 'Solaris WaterGen A10 (10L/Tag)' },
              why: { en: 'Extracts drinking water from air humidity. No plumbing needed. City apartment essential.', de: 'Gewinnt Trinkwasser aus Luftfeuchtigkeit. Kein Anschluss erforderlich. Unverzichtbar für Stadtwohnungen.' },
              cost: '~€420', link: `https://www.${amzDomain}/s?k=atmospheric+water+generator+10L` },
            { name: { en: '5L food-grade jerrycans x6 (buffer)', de: '5L Lebensmittelkanister x6 (Puffer)' },
              why: { en: 'AWG needs power. Store 3-day drinking buffer for power outage gaps.', de: 'AWG benötigt Strom. 3-Tage-Trinkwasserpuffer für Stromausfall-Lücken.' },
              cost: '~€30', link: `https://www.${amzDomain}/s?k=food+grade+jerrycan+5L` },
          ]},
        { icon: 'sprout', cat: { en: 'Food', de: 'Lebensmittel' }, title: { en: 'Caloric Base + Indoor Growing', de: 'Kalorienbasis + Indoor-Anbau' },
          priority: { en: 'CRITICAL', de: 'KRITISCH' }, pCls: 'p-critical', color: '#3A1A00',
          items: [
            { name: { en: `White rice 25kg x${Math.max(2,Math.round(n))} bags`, de: `Weißer Reis 25kg x${Math.max(2,Math.round(n))} Säcke` },
              why: { en: '25-year shelf life sealed. 3,600 cal/kg. Caloric backbone of any long-term food reserve.', de: 'Versiegelt 25 Jahre haltbar. 3.600 kcal/kg. Kalorienbasis jeder Langzeitvorsorge.' },
              cost: `~€${Math.round(n*20)}`, link: `https://www.${amzDomain}/s?k=white+rice+25kg+bulk` },
            { name: { en: '30-pod vertical hydroponic tower', de: '30-Pod-Vertikal-Hydroponik-Turm' },
              why: { en: 'Continuous fresh greens year-round. Closes the vitamin gap that dried food cannot fill.', de: 'Kontinuierlich frisches Grünzeug ganzjährig. Schließt die Vitaminlücke, die Trockennahrung nicht füllt.' },
              cost: '~€280–350', link: `https://www.${amzDomain}/s?k=hydroponic+tower+indoor+garden` },
            { name: { en: 'Sprouting seeds (lentil, mung, alfalfa)', de: 'Keimsprossen-Samen (Linsen, Mungbohnen, Alfalfa)' },
              why: { en: 'Fresh Vitamin C in 3 days. Zero equipment. Fastest food possible.', de: 'Frisches Vitamin C in 3 Tagen. Keine Ausrüstung. Die schnellste Nahrung überhaupt.' },
              cost: '~€18', link: `https://www.${amzDomain}/s?k=sprouting+seeds+kit` },
          ]},
        { icon: 'zap', cat: { en: 'Energy', de: 'Energie' }, title: { en: 'Solar Power System', de: 'Solar-Energiesystem' },
          priority: { en: 'CRITICAL', de: 'KRITISCH' }, pCls: 'p-critical', color: '#1A1A3A',
          items: [
            { name: { en: 'Portable solar generator 500Wh (EcoFlow RIVER 2)', de: 'Tragbarer Solar-Generator 500Wh (EcoFlow RIVER 2)' },
              why: { en: 'Powers AWG for 2.5 hrs, hydroponic LED for 10+ hrs, charges all devices. City energy backbone.', de: 'Betreibt AWG 2,5 Std., Hydroponik-LED 10+ Std., lädt alle Geräte. Städtische Energiegrundlage.' },
              cost: '~€380', link: `https://www.${amzDomain}/s?k=EcoFlow+RIVER+2+solar+generator` },
            { name: { en: '60W foldable solar panel (balcony)', de: '60W Faltbares Solarpanel (Balkon)' },
              why: { en: 'Charges generator via balcony railing. No installation needed.', de: 'Lädt Generator über Balkongeländer. Keine Installation erforderlich.' },
              cost: '~€120', link: `https://www.${amzDomain}/s?k=60W+foldable+solar+panel+balcony` },
          ]},
      ]
    },
    2: {
      label: { en: 'Partial Supply Collapse', de: 'Partieller Versorgungskollaps' },
      cards: [
        { icon: 'droplet', cat: { en: 'Water', de: 'Wasser' }, title: { en: 'Water Buffer + Filtration', de: 'Wasserpuffer + Filtration' },
          priority: { en: 'CRITICAL', de: 'KRITISCH' }, pCls: 'p-critical', color: '#1A3A4A',
          items: [
            { name: { en: '5L food-grade jerrycans x10 (50L)', de: '5L Lebensmittelkanister x10 (50L)' },
              why: { en: '50L covers 3 days drinking water for 4 people. Minimum safe buffer.', de: '50L decken 3 Tage Trinkwasser für 4 Personen. Mindest-Sicherheitspuffer.' },
              cost: '~€50', link: `https://www.${amzDomain}/s?k=5L+jerrycan+food+grade` },
            { name: { en: 'Big Berkey water filter', de: 'Big Berkey Wasserfilter' },
              why: { en: 'Gravity-fed, no electricity. Purifies any water source. Last-resort security.', de: 'Schwerkraftbetrieben, kein Strom. Reinigt jede Wasserquelle. Letzte Sicherheitslinie.' },
              cost: '~€280', link: `https://www.${amzDomain}/s?k=Big+Berkey+water+filter` },
          ]},
        { icon: 'cart', cat: { en: 'Food', de: 'Lebensmittel' }, title: { en: '4-Week Pantry Reserve', de: '4-Wochen-Vorratskammer' },
          priority: { en: 'HIGH', de: 'HOCH' }, pCls: 'p-high', color: '#2A1500',
          items: [
            { name: { en: 'Rice, lentils, beans, oats — 4-week supply', de: 'Reis, Linsen, Bohnen, Hafer — 4-Wochen-Vorrat' },
              why: { en: 'Complete protein: rice + legumes. Cheap, calorie-dense, long shelf life. Buy now.', de: 'Vollständiges Protein: Reis + Hülsenfrüchte. Günstig, kalorienreich, lange haltbar. Jetzt kaufen.' },
              cost: `~€${Math.round(n*25)}`, link: `https://www.${amzDomain}/s?k=bulk+rice+lentils+oats` },
            { name: { en: 'Sprouting seeds (3-day fresh food)', de: 'Keimsprossen-Samen (3-Tage-Frischkost)' },
              why: { en: 'Fresh produce disappears first in partial collapse. Sprouts give Vitamin C in 3 days.', de: 'Frische Produkte verschwinden zuerst. Sprossen liefern Vitamin C in 3 Tagen.' },
              cost: '~€18', link: `https://www.${amzDomain}/s?k=sprouting+seeds+lentil+mung` },
          ]},
        { icon: 'flame', cat: { en: 'Energy', de: 'Energie' }, title: { en: 'Power & Heat Backup', de: 'Strom- & Wärme-Backup' },
          priority: { en: 'HIGH', de: 'HOCH' }, pCls: 'p-high', color: '#1A1A2A',
          items: [
            { name: { en: 'Solar power bank 40,000mAh + 20W panel', de: 'Solar-Powerbank 40.000mAh + 20W-Panel' },
              why: { en: 'Keeps phones, lights, radio running through multi-day outage.', de: 'Hält Handys, Lichter, Radio bei mehrtägigem Ausfall am Laufen.' },
              cost: '~€90', link: `https://www.${amzDomain}/s?k=solar+power+bank+40000mAh` },
            { name: { en: `Thermal sleeping bags -10°C x${Math.round(n)}`, de: `Thermische Schlafsäcke -10°C x${Math.round(n)}` },
              why: { en: 'City apartments lose heat fast without heating. A bag survives Central European winters.', de: 'Stadtwohnungen verlieren schnell Wärme. Ein Schlafsack übersteht mitteleuropäische Winter.' },
              cost: `~€${Math.round(n)*45}`, link: `https://www.${amzDomain}/s?k=sleeping+bag+minus+10+degrees` },
          ]},
      ]
    },
    3: {
      label: { en: 'Hyperinflation', de: 'Hyperinflation' },
      cards: [
        { icon: 'sprout', cat: { en: 'Food Hedge', de: 'Lebensmittel-Absicherung' }, title: { en: 'Buy Now While Prices Are Low', de: 'Jetzt kaufen, solange Preise niedrig sind' },
          priority: { en: 'CRITICAL', de: 'KRITISCH' }, pCls: 'p-critical', color: '#2A1A00',
          items: [
            { name: { en: `Rice 25kg x${Math.max(4,Math.round(n*1.5))} bags (buy immediately)`, de: `Reis 25kg x${Math.max(4,Math.round(n*1.5))} Säcke (sofort kaufen)` },
              why: { en: 'In hyperinflation, food is the best hard asset. Rice at €0.80/kg today may cost €4/kg in 6 months.', de: 'Bei Hyperinflation ist Nahrung das beste Sachgut. Reis für €0,80/kg heute kann in 6 Monaten €4/kg kosten.' },
              cost: `~€${Math.round(n*1.5*20)}`, link: `https://www.${amzDomain}/s?k=rice+25kg+white` },
            { name: { en: 'Freeze-dried meals x60 (25-year shelf life)', de: 'Gefriergetrocknete Mahlzeiten x60 (25 Jahre haltbar)' },
              why: { en: "Locks in today's food cost for 25 years. Best inflation hedge in existence.", de: "Sichert die heutigen Lebensmittelkosten für 25 Jahre. Beste Inflationsabsicherung überhaupt." },
              cost: '~€300', link: `https://www.${amzDomain}/s?k=freeze+dried+food+emergency+meals` },
            { name: { en: 'Physical silver coins (1oz)', de: 'Physische Silbermünzen (1 oz)' },
              why: { en: 'Historically proven inflation hedge. Divisible and recognisable for local barter.', de: 'Historisch bewährte Inflationsabsicherung. Teilbar und für lokalen Tauschhandel erkennbar.' },
              cost: '~€30–35/coin', link: `https://www.${amzDomain}/s?k=silver+coin+1+oz` },
          ]},
        { icon: 'leaf', cat: { en: 'Self-Sufficiency', de: 'Selbstversorgung' }, title: { en: 'Grow Your Own — City', de: 'Selbst anbauen — Stadt' },
          priority: { en: 'HIGH', de: 'HOCH' }, pCls: 'p-high', color: '#0A1A0A',
          items: [
            { name: { en: 'Indoor hydroponic tower (30 pods)', de: 'Indoor-Hydroponik-Turm (30 Pods)' },
              why: { en: 'Eliminates grocery spend on herbs and greens permanently. €280 upfront vs. €15+/week at inflated prices.', de: 'Eliminiert dauerhaft Ausgaben für Kräuter und Salat. €280 einmalig vs. €15+/Woche bei Inflationspreisen.' },
              cost: '~€280', link: `https://www.${amzDomain}/s?k=indoor+hydroponic+tower+30+pod` },
            { name: { en: 'Heirloom seed bank (50+ varieties)', de: 'Erbsamen-Bank (50+ Sorten)' },
              why: { en: 'Ability to grow food is wealth in hyperinflation. Heirloom seeds replant each season forever.', de: 'Die Fähigkeit, Nahrung anzubauen, ist Reichtum bei Hyperinflation. Erbsamen können jede Saison neu gepflanzt werden.' },
              cost: '~€35', link: `https://www.${amzDomain}/s?k=heirloom+vegetable+seed+bank` },
          ]},
      ]
    },
    4: {
      label: { en: 'Food Shortage', de: 'Lebensmittelkrise' },
      cards: [
        { icon: 'leaf', cat: { en: 'Fresh Food', de: 'Frische Lebensmittel' }, title: { en: 'Indoor Food Production', de: 'Indoor-Lebensmittelproduktion' },
          priority: { en: 'HIGH', de: 'HOCH' }, pCls: 'p-high', color: '#0A2A0A',
          items: [
            { name: { en: '30-pod hydroponic tower', de: '30-Pod-Hydroponik-Turm' },
              why: { en: 'Leafy greens, herbs, cherry tomatoes continuously. What disappears first from shelves = what you grow.', de: 'Kontinuierlich Blattgemüse, Kräuter, Kirschtomaten. Was zuerst aus den Regalen verschwindet = was du anbaust.' },
              cost: '~€280', link: `https://www.${amzDomain}/s?k=indoor+hydroponic+tower` },
            { name: { en: 'Sprouting kit + seeds (5 varieties)', de: 'Keimsprossen-Set + Samen (5 Sorten)' },
              why: { en: 'During shortages, fresh produce disappears first. Lentil/mung sprouts ready in 3 days, any time.', de: 'Bei Engpässen verschwinden frische Produkte zuerst. Linsen-/Mungbohnen-Sprossen in 3 Tagen fertig.' },
              cost: '~€25', link: `https://www.${amzDomain}/s?k=sprouting+seeds+kit+jars` },
          ]},
        { icon: 'package', cat: { en: 'Storage', de: 'Vorratshaltung' }, title: { en: '90-Day Food Reserve', de: '90-Tage-Lebensmittelvorrat' },
          priority: { en: 'HIGH', de: 'HOCH' }, pCls: 'p-high', color: '#1A1200',
          items: [
            { name: { en: 'Rice + legumes 90-day supply (buy now)', de: 'Reis + Hülsenfrüchte 90-Tage-Vorrat (jetzt kaufen)' },
              why: { en: 'Food shortage = prices rise before shelves empty. Buy 90-day supply this week at current prices.', de: 'Lebensmittelknappheit = Preise steigen bevor Regale leer sind. Jetzt kaufen zum aktuellen Preis.' },
              cost: `~€${Math.round(n*40)}`, link: `https://www.${amzDomain}/s?k=bulk+rice+lentils+beans` },
            { name: { en: 'Mylar bags + oxygen absorbers (seal grains)', de: 'Mylar-Beutel + Sauerstoffabsorber (Getreide versiegeln)' },
              why: { en: "Seal bulk grains in Mylar = 20-year shelf life. One afternoon's work, permanent upgrade.", de: 'Getreide in Mylar versiegeln = 20 Jahre haltbar. Ein Nachmittag Arbeit, dauerhafter Vorteil.' },
              cost: '~€30', link: `https://www.${amzDomain}/s?k=mylar+bags+oxygen+absorbers` },
          ]},
      ]
    }
  }
  return data[scenario]
}

function renderRiskBanner() {
  const score = riskScore
  let riskCls, riskTitle, riskDesc
  if (score >= 8) { riskCls='risk-critical'; riskTitle=t('risk_critical_title'); riskDesc=t('risk_critical_desc'); riskLevelStr='CRITICAL' }
  else if (score >= 5) { riskCls='risk-high'; riskTitle=t('risk_high_title'); riskDesc=t('risk_high_desc'); riskLevelStr='HIGH RISK' }
  else if (score >= 3) { riskCls='risk-medium'; riskTitle=t('risk_medium_title'); riskDesc=t('risk_medium_desc'); riskLevelStr='MODERATE' }
  else { riskCls='risk-low'; riskTitle=t('risk_low_title'); riskDesc=t('risk_low_desc'); riskLevelStr='PREPARED' }

  const el = document.getElementById('risk-banner-container')
  if (!el) return
  el.innerHTML = `
    <div class="risk-banner ${riskCls}">
      <div class="risk-level">${t('risk_label')}</div>
      <div class="risk-title">${riskTitle}</div>
      <div class="risk-desc">${riskDesc}</div>
    </div>`
}

// Re-renders every JS-generated chunk on the results page so a mid-flight
// language switch updates risk banner / recs / budget / timeline / narrative
// without needing a reload. The narrative swaps to the new-language fallback
// (instant) — a fresh AI narrative in the other language requires a retake,
// since refetching adds a 5–10s loading flash on every language toggle.
function rerenderResults() {
  renderRiskBanner()
  showScenario(currentScenario || 1)
  renderBudgetMeter()
  renderTimeline()
  const narrativeText = document.getElementById('narrative-text')
  if (narrativeText && !narrativeText.classList.contains('hidden')) {
    renderNarrative(getFallbackNarrativeText())
  }
}

function showResults() {
  document.getElementById('quiz-section').classList.add('hidden')
  document.body.classList.remove('quiz-active')
  document.body.classList.add('results-active')
  const results = document.getElementById('results-section')
  results.style.display = 'block'
  results.classList.add('active')
  window.scrollTo({ top: 0, behavior: 'smooth' })
  saveState()

  riskScore = calcRisk()
  checkProteinOffer()
  renderRiskBanner()

  const scenarioTabMap = {
    total_collapse: 1, partial_collapse: 2, hyperinflation: 3,
    supply_shock: 2, food_crisis: 4, bank_crisis: 3
  }
  const selectedScenarios = answers.scenarios || []
  const firstSelected = Array.isArray(selectedScenarios) ? selectedScenarios[0] : selectedScenarios.split(',')[0]
  const defaultTab = scenarioTabMap[firstSelected] || 1
  showScenario(defaultTab)
  updateRegionIndicator()
  renderBudgetMeter()
  fetchNarrative()
  renderTimeline()

  setTimeout(() => { document.getElementById('about-section').classList.remove('hidden') }, 300)
}

function showScenario(n) {
  currentScenario = n
  saveState()
  document.querySelectorAll('.s-tab').forEach(tab => {
    tab.classList.remove('active-s1','active-s2','active-s3','active-s4')
    if (parseInt(tab.dataset.s) === n) tab.classList.add(`active-s${n}`)
  })

  const rec = getScenarioRecs(n)
  let html = ''
  rec.cards.forEach((card, ci) => {
    const viewTxt = t('view_amazon')
    html += `<div class="rec-card" style="animation-delay:${ci*0.08}s">
      <div class="rec-header">
        <div class="rec-icon">${icon(card.icon, 22)}</div>
        <div>
          <div class="rec-cat">${card.cat[currentLang]}</div>
          <div class="rec-title">${card.title[currentLang]}</div>
        </div>
        <span class="priority-badge ${card.pCls}">${card.priority[currentLang]}</span>
      </div>
      <div class="rec-body"><div class="rec-items">`
    card.items.forEach(item => {
      html += `<div class="rec-item">
        <div class="item-name">${item.name[currentLang]}</div>
        <div class="item-why">${item.why[currentLang]}</div>
        <div class="rec-item-foot">
          <div class="item-cost">${item.cost}</div>
          ${item.link ? `<a class="affiliate-btn" href="${item.link}" target="_blank" rel="noopener noreferrer">${icon('cart', 14)} ${viewTxt}</a>` : ''}
        </div>
      </div>`
    })
    html += `</div></div></div>`
  })
  document.getElementById('rec-cards-container').innerHTML = html
}

function renderBudgetMeter() {
  const budget = answers.budget || 1500
  const lang = currentLang
  const cats = [
    { label: t('bcat_water'), pct: 22, color: '#20A8A0' },
    { label: t('bcat_food'), pct: 28, color: '#E07B20' },
    { label: t('bcat_growing'), pct: 18, color: '#28A060' },
    { label: t('bcat_energy'), pct: 18, color: '#4A8FE0' },
    { label: t('bcat_medical'), pct: 9, color: '#E03A3A' },
    { label: t('bcat_sanitation'), pct: 5, color: '#D4A820' },
  ]
  let html = `<div class="budget-meter">
    <div class="budget-cats">`
  cats.forEach(c => {
    html += `<div class="bcat">
      <div class="bcat-label">${c.label}</div>
      <div class="bcat-bar-wrap"><div class="bcat-bar" style="width:${c.pct}%;background:${c.color}"></div></div>
      <div class="bcat-cost">€${Math.round(budget*c.pct/100)}</div>
    </div>`
  })
  // Total row at the end of the table — same .bcat layout so alignment
  // matches the per-category lines.
  const totalLabel = lang === 'de' ? 'Gesamtbudget' : 'Total Allocation'
  html += `<div class="bcat bcat-total">
    <div class="bcat-label">${totalLabel}</div>
    <div class="bcat-bar-wrap" aria-hidden="true"></div>
    <div class="bcat-cost">€${budget.toLocaleString()}</div>
  </div>`
  html += `</div></div>`
  document.getElementById('budget-meter-container').innerHTML = html
}

function renderTimeline() {
  const items = [
    { when: t('tl_week1'),  action: t('tl_a1'), cost: '~€25', icon: 'sprout' },
    { when: t('tl_week2'),  action: t('tl_a2'), cost: `~€${Math.round(getN()*20)}`, icon: 'cart' },
    { when: t('tl_month1'), action: t('tl_a3'), cost: '~€520', icon: 'droplet' },
    { when: t('tl_month2'), action: t('tl_a4'), cost: '~€700', icon: 'zap' },
    { when: t('tl_month3'), action: t('tl_a5'), cost: '~€600', icon: 'radio' },
  ]
  let html = ''
  items.forEach(item => {
    html += `<div class="tl-item">
      <div class="tl-dot">${icon(item.icon, 16)}</div>
      <div class="tl-content">
        <div class="tl-when">${item.when}</div>
        <div class="tl-action">${item.action}</div>
        <div class="tl-cost">${item.cost}</div>
      </div>
    </div>`
  })
  document.getElementById('timeline-items').innerHTML = html
}

// ── CAPTURE FORM SUBMIT ──
function submitCapture(e) {
  e.preventDefault()

  const g = id => { const el = document.getElementById(id); return el ? el.value.trim() : '' }
  const gc = id => { const el = document.getElementById(id); return el ? el.checked : false }

  const firstName  = g('f_name')
  const lastName   = g('f_lastname')
  const email      = g('f_email')
  const city       = g('f_city')
  const country    = g('f_country')
  const phone      = g('f_phone')
  const prefLang   = g('f_pref_lang') || currentLang
  const protein    = g('f_protein_detail')
  const newsletter = gc('f_newsletter') ? 'yes' : 'no'

  const score = calcRisk()
  const lvl   = score >= 8 ? 'CRITICAL' : score >= 5 ? 'HIGH RISK' : score >= 3 ? 'MODERATE' : 'PREPARED'

  const btn = document.getElementById('capture-submit-btn')
  if(btn) { btn.disabled = true; btn.innerHTML = `<span>${t('sending')}</span>` }

  const payload = {
    first_name:         firstName,
    last_name:          lastName,
    email:              email,
    city:               city,
    country:            country,
    phone:              phone,
    preferred_language: prefLang,
    newsletter:         newsletter,
    newsletter_subscriber: newsletter === 'yes' ? '✅ YES — send weekly updates' : '❌ NO — do not send',
    protein_detail:     protein,
    location:           answers.location    || '',
    household_size:     answers.household   || '',
    water_access:       answers.water       || '',
    food_reserves:      answers.food        || '',
    medical_needs:      answers.medical     || '',
    sanitation:         answers.sanitation  || '',
    budget_eur:         answers.budget      || 1500,
    priorities:         (answers.scenarios  || []).join(', '),
    protein_access:     (answers.protein    || '') + (protein ? ' | ' + protein : ''),
    scenarios:          (answers.scenarios || []).join(', '),
    protein_preference: (answers.protein_pref || []).join(', '),
    protein_security:   answers.protein_access || '',
    protein_offer_sent: answers.protein_access === 'uncertain' ? 'yes' : 'no',
    risk_score:         score,
    risk_level:         lvl,
    language_used:      currentLang,
    submitted_at:       new Date().toISOString(),
    send_email:         'yes',
    _subject: (T[currentLang].brand || 'Deepstock') + ' — ' + lvl + ' — ' + firstName + ' ' + lastName + ' — ' + city + ', ' + country
  }

  const showSuccess = () => {
    const form = document.getElementById('capture-form')
    const sub = document.querySelector('#capture-modal .capture-sub')
    const success = document.getElementById('capture-success')
    const footer = document.getElementById('form-modal-footer')
    if(form) form.style.display = 'none'
    if(sub) sub.style.display = 'none'
    if(footer) footer.style.display = 'none'
    if(success) { success.classList.remove('hidden'); success.style.display = 'block' }
  }

  fetch('https://formspree.io/f/maqlddel', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
    body: JSON.stringify(payload)
  }).catch(() => {})

  const workerTimeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('timeout')), 12000)
  )
  Promise.race([
    fetch(WORKER_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
      mode: 'cors',
      body: JSON.stringify(payload)
    }),
    workerTimeout
  ]).catch(() => {})

  setTimeout(showSuccess, 1500)
}

// ══════════════════════════════════════
// LOCATION-AWARE AFFILIATE SYSTEM
// ══════════════════════════════════════
function detectUserCountry() {
  const lang = navigator.language || navigator.userLanguage || 'en'
  const tz = Intl.DateTimeFormat().resolvedOptions().timeZone || ''

  if (lang.startsWith('de') || tz.includes('Europe/Berlin') || tz.includes('Europe/Vienna') || tz.includes('Europe/Zurich')) return 'DACH'
  if (lang.startsWith('fr') || tz.includes('Europe/Paris')) return 'FR'
  if (lang.includes('GB') || lang.includes('en-GB') || tz.includes('Europe/London')) return 'UK'
  if (tz.includes('America/Toronto') || tz.includes('America/Vancouver') || lang.includes('en-CA')) return 'CA'
  if (tz.includes('Europe/Amsterdam') || tz.includes('Europe/Brussels') || tz.includes('Europe/Stockholm') || tz.includes('Europe/Oslo') || tz.includes('Europe/Copenhagen')) return 'NLNORDIC'
  if (tz.includes('Europe/')) return 'EU_OTHER'
  if (tz.includes('America/')) return 'US'
  return 'US'
}

let userRegion = detectUserCountry()

function updateRegionFromCountry(countryCode) {
  const dach = ['AT','DE','CH']
  const uk = ['GB']
  const fr = ['FR','BE']
  const ca = ['CA']
  const nlnordic = ['NL','SE','NO','DK','FI']
  const us = ['US']
  if (dach.includes(countryCode)) userRegion = 'DACH'
  else if (uk.includes(countryCode)) userRegion = 'UK'
  else if (fr.includes(countryCode)) userRegion = 'FR'
  else if (ca.includes(countryCode)) userRegion = 'CA'
  else if (nlnordic.includes(countryCode)) userRegion = 'NLNORDIC'
  else if (us.includes(countryCode)) userRegion = 'US'
  else if (countryCode && countryCode !== 'OTHER') userRegion = 'EU_OTHER'
}

function getAmazonDomain() {
  const map = { DACH:'amazon.de', UK:'amazon.co.uk', FR:'amazon.fr', CA:'amazon.ca', NLNORDIC:'amazon.de', EU_OTHER:'amazon.de', US:'amazon.com' }
  return map[userRegion] || 'amazon.com'
}

function getRegionLabel() {
  const map = { DACH:'🇩🇪 DE/AT/CH', UK:'🇬🇧 UK', FR:'🇫🇷 France', CA:'🇨🇦 Canada', NLNORDIC:'🇳🇱 NL/Nordic', EU_OTHER:'🇪🇺 Europe', US:'🇺🇸 USA' }
  return map[userRegion] || '🌍 Global'
}

function updateRegionIndicator() {
  const el = document.getElementById('region-indicator')
  if (el) el.textContent = getRegionLabel()
}

function showRegionPicker() { /* hidden in this build */ }

function onCountryChange(e) {
  updateRegionFromCountry(e.target.value)
  updateRegionIndicator()
}

// ── FETCH + RENDER NARRATIVE ──
async function fetchNarrative() {
  const bar = document.getElementById('narrative-progress')
  let pct = 0
  const progressInterval = setInterval(() => {
    pct = Math.min(pct + (100 / 20), 95)
    if (bar) bar.style.width = pct + '%'
  }, 120)

  const completeProgress = () => {
    clearInterval(progressInterval)
    if (bar) { bar.style.width = '100%'; bar.style.transition = 'width 0.3s' }
    setTimeout(() => {
      const loading = document.getElementById('narrative-loading')
      if (loading) loading.style.display = 'none'
    }, 300)
  }

  const quizData = {
    first_name: answers._first_name || '',
    city: answers._city || '',
    country: answers._country || '',
    location: answers.location || '',
    household_size: answers.household || '',
    water_access: answers.water || '',
    food_reserves: answers.food || '',
    medical_needs: answers.medical || '',
    sanitation: answers.sanitation || '',
    budget_eur: answers.budget || 1500,
    priorities: (answers.priority || []).join(', '),
    protein_access: answers.protein || '',
    scenarios: (answers.scenarios || []).join(', '),
    risk_score: riskScore || 0,
    risk_level: riskLevelStr || '',
    language_used: currentLang,
    preferred_language: currentLang
  }

  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('timeout')), 8000)
  )

  try {
    const fetchPromise = fetch('https://planb-email.janwellmann.workers.dev/narrative', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
      mode: 'cors',
      body: JSON.stringify(quizData)
    })

    const res = await Promise.race([fetchPromise, timeout])
    if (res.ok) {
      const data = await res.json()
      if (data.narrative) { completeProgress(); renderNarrative(data.narrative); return }
    }
    completeProgress(); renderNarrative(getFallbackNarrativeText())
  } catch (err) {
    completeProgress(); renderNarrative(getFallbackNarrativeText())
  }
}

function renderNarrative(text) {
  document.getElementById('narrative-loading').classList.add('hidden')
  const cta = document.getElementById('narrative-cta')
  if (cta) cta.classList.remove('hidden')
  revealSections()
  const el = document.getElementById('narrative-text')

  const html = text
    .split(/\n\n+/)
    .filter(p => p.trim())
    .map(p => {
      if (p.startsWith('**') && p.split('\n').length <= 2) {
        const heading = p.replace(/\*\*(.+?)\*\*/g, '$1').trim()
        return `<h4>${heading}</h4>`
      }
      if (p.includes('\n•') || p.trimStart().startsWith('•')) {
        const lines = p.split('\n').filter(l => l.trim())
        const items = lines.map(l => {
          l = l.trim()
          const text = l.startsWith('•') ? l.slice(1).trim() : l
          const bolded = text.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
          return l.startsWith('•') ? `<li>${bolded}</li>` : `<p>${bolded}</p>`
        }).join('')
        return `<ul>${items}</ul>`
      }
      const bolded = p.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
      return `<p>${bolded}</p>`
    }).join('')

  el.innerHTML = html
  el.classList.remove('hidden')
}

function getFallbackNarrativeText() {
  const isDE = currentLang === 'de'
  return isDE
    ? '**DEINE LAGE**\n\nDein Assessment zeigt, wo die wichtigsten Lücken sind. Die gute Nachricht: Du hast den ersten Schritt gemacht.\n\n**NÄCHSTE SCHRITTE**\n\n• Wasser zuerst: AWG oder Berkey-Filter\n• Lebensmittelvorrat: 2 Wochen Grundvorrat\n• Energie: Solar-Powerbank für Stromausfall'
    : "**YOUR SITUATION**\n\nYour assessment shows where the key gaps are. The good news: you've taken the first step.\n\n**NEXT STEPS**\n\n• Water first: AWG or Berkey filter\n• Food reserve: 2-week dry goods\n• Energy: Solar power bank for outages"
}

function revealSections() {
  // The three collapsible result panels (recs is open by default,
  // budget + timeline collapsed for progressive disclosure). The capture
  // form lives in a modal now and reveals on click instead of scroll.
  const ids = ['panel-recs', 'panel-budget', 'panel-timeline']
  ids.forEach((id, i) => {
    setTimeout(() => {
      const el = document.getElementById(id)
      if (el) el.classList.add('revealed')
    }, i * 200)
  })
}

// Three-stage intro overlay played on the user's first home-page visit
// in this tab. Skipped on subsequent loads (sessionStorage flag), and
// also skipped when restoring a saved quiz/results stage so a refresh
// mid-flow doesn't replay the intro. Each stage shows for `enter +
// hold` ms, then fades out before the next enters.
const INTRO_KEY = 'kammergut.intro.shown.v1'
const sleep = ms => new Promise(r => setTimeout(r, ms))
async function playIntro() {
  const overlay = document.getElementById('intro-overlay')
  if (!overlay) return
  // Pacing — entry durations match the introSmoke keyframe (1.8s for
  // stages 1 and 3). Stage 2 needs ~2.6s to land both staggered lines
  // (line-a 0.1+1.5s, line-b 1.1+1.5s). Holds are tuned so the viewer
  // can read each line after it lands.
  // Every stage word-cascades. Entry = words × stagger + per-word
  // duration + base delay. JS rebuilds spans per play (so language
  // switches still split correctly) and measures entry from live word
  // count. Each word carries the introWord blur resolve.
  const SPEED = 1.25
  const STAGGER = 0.28 * SPEED
  const PER_WORD = 1.2 * SPEED
  const BASE = 0.05 * SPEED
  const stages = []
  for (let n = 1; n <= 2; n++) {
    const stageEl = overlay.querySelector('.stage-' + n)
    const textEl = stageEl ? stageEl.querySelector('.intro-text') : null
    let words = []
    if (textEl) {
      const text = textEl.textContent.trim()
      textEl.innerHTML = ''
      words = text.split(/\s+/)
      const stripPunct = w => w.replace(/[.,;:!?]+$/, '')
      const boldFromIdx = currentLang === 'de' && n === 1
        ? Math.max(0, words.length - 2)
        : Math.max(0, words.length - 3)
      words.forEach((word, i) => {
        const span = document.createElement('span')
        const isBold = i >= boldFromIdx
        span.className = 'word' + (isBold ? ' bold' : '')
        const delay = (BASE + i * STAGGER) + 's'
        span.style.animationDelay = delay
        span.style.setProperty('--word-delay', delay)
        span.textContent = word
        textEl.appendChild(span)
      })
    }
    const entryMs = Math.round((BASE + (Math.max(0, words.length - 1)) * STAGGER + PER_WORD) * 1000)
    const hold = n === 1 ? 2600 : 100
    stages.push({ sel: '.stage-' + n, enter: entryMs, hold })
  }
  const exit = 1000 // default matches the slowed introOut smoke-out duration
  let activeLead = 0
  for (let i = 0; i < stages.length; i++) {
    const s = stages[i]
    const el = overlay.querySelector(s.sel)
    el.classList.add('active')
    await sleep(Math.max(0, s.enter + s.hold - activeLead))
    activeLead = 0
    // Skip the smoke-out on the last stage — the overlay's own fade
    // dissolves the final line, so we don't get two competing outros
    // (one on the text, one on the FAFAFA panel).
    if (i < stages.length - 1) {
      // Keep .active alongside .leaving so the per-word `introWord`
      // animation's `forwards` end-state holds during the fade.
      // Removing .active here would drop the words back to opacity:0
      // instantly and the smoke-out on the parent would dissolve into
      // an already-empty wrapper.
      const next = overlay.querySelector(stages[i + 1].sel)
      if (next) next.classList.add('active')
      el.classList.add('leaving')
      const transitionWait = i === 0 ? 2800 : exit
      activeLead = transitionWait
      await sleep(transitionWait)
      el.classList.remove('leaving')
      el.classList.remove('active')
    }
  }
  // Fade overlay out and let the hero animations run via body class.
  // The last stage is still .active here, so its text rides the
  // overlay fade-out as one motion.
  overlay.classList.add('done')
  document.body.classList.add('intro-done')
  await sleep(350)
  overlay.classList.add('gone')
}
function maybePlayIntro({ skip = false } = {}) {
  if (skip || sessionStorage.getItem(INTRO_KEY)) {
    document.body.classList.add('intro-done')
    const ov = document.getElementById('intro-overlay')
    if (ov) ov.classList.add('gone')
    return
  }
  try { sessionStorage.setItem(INTRO_KEY, '1') } catch {}
  playIntro()
}

// Scroll-lock the page behind the modal. Saving and restoring scrollY +
// position:fixed on body is the iOS-Safari-safe pattern; plain
// overflow:hidden alone doesn't stop touch-driven body scroll there.
let savedScrollY = 0
function openCaptureModal() {
  const modal = document.getElementById('capture-modal')
  if (!modal) return
  savedScrollY = window.scrollY || window.pageYOffset || 0
  modal.classList.add('open')
  modal.setAttribute('aria-hidden', 'false')
  document.body.style.top = `-${savedScrollY}px`
  document.body.classList.add('modal-open')
}
function closeCaptureModal() {
  const modal = document.getElementById('capture-modal')
  if (!modal) return
  modal.classList.remove('open')
  modal.setAttribute('aria-hidden', 'true')
  document.body.classList.remove('modal-open')
  document.body.style.top = ''
  window.scrollTo(0, savedScrollY)
}
function onModalBackdropClick(e) {
  // Only close when the click is on the overlay itself (the panel stops
  // propagation so clicks inside the form don't bubble up).
  if (e.target === e.currentTarget) closeCaptureModal()
}
function scrollToRecs() {
  const el = document.getElementById('recs-anchor')
  if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
function closeAndScrollToRecs() {
  closeCaptureModal()
  setTimeout(() => scrollToRecs(), 250)
}

function checkProteinOffer() {
  const offerEl = document.getElementById('protein-offer-section')
  if (!offerEl) return
  if (answers.protein_access === 'uncertain') {
    offerEl.classList.add('show')
    setLang(currentLang)
  }
}

// ── SCENARIO STRIP TOUCH DRAG ──
function initScenarioStrip() {
  const strip = document.getElementById('scenario-strip')
  const track = document.getElementById('scenario-track')
  if (!strip || !track) return

  let isDragging = false

  strip.addEventListener('mousedown', () => {
    isDragging = true
    track.style.animationPlayState = 'paused'
  })
  strip.addEventListener('touchstart', () => {
    track.style.animationPlayState = 'paused'
  }, { passive: true })
  strip.addEventListener('mouseleave', () => {
    if (isDragging) {
      isDragging = false
      track.style.animationPlayState = 'running'
    }
  })
  strip.addEventListener('mouseup', () => {
    isDragging = false
    track.style.animationPlayState = 'running'
  })
  strip.addEventListener('touchend', () => {
    setTimeout(() => { track.style.animationPlayState = 'running' }, 3000)
  }, { passive: true })
}

// ── Paint picker + modifier panel ──
function initPaintPicker() {
  const swatches = document.querySelectorAll('.paint-swatch')
  if (!swatches.length) return

  const FILTER_IDS = {
    dark:  ['paintGloss', 'paintGlossHover'],
    green: ['paintGloss', 'paintGlossHover'],
    white: ['paintGlossWhite', 'paintGlossWhiteHover', 'paintGlossWhiteBtn']
  }
  const VARS = {
    dsDy:        { sel: 'feOffset[result="dsOff"]',           attr: 'dy' },
    dsBlur:      { sel: 'feGaussianBlur[result="dsBlur"]',    attr: 'stdDeviation' },
    dsSlope:     { sel: 'feFuncA',                            attr: 'slope' },
    bumpStd:     { sel: 'feGaussianBlur[result="bump"]',      attr: 'stdDeviation' },
    spec1Scale:  { sel: 'feSpecularLighting[result="spec"]',  attr: 'surfaceScale' },
    spec1Const:  { sel: 'feSpecularLighting[result="spec"]',  attr: 'specularConstant' },
    spec1Exp:    { sel: 'feSpecularLighting[result="spec"]',  attr: 'specularExponent' },
    spec1Color:  { sel: 'feSpecularLighting[result="spec"]',  attr: 'lighting-color' },
    spec2Scale:  { sel: 'feSpecularLighting[result="spec2"]', attr: 'surfaceScale' },
    spec2Const:  { sel: 'feSpecularLighting[result="spec2"]', attr: 'specularConstant' },
    spec2Exp:    { sel: 'feSpecularLighting[result="spec2"]', attr: 'specularExponent' },
    spec2Color:  { sel: 'feSpecularLighting[result="spec2"]', attr: 'lighting-color' },
  }
  const PAINT_LABEL = { dark: 'Dark', green: 'Army Green', white: 'Glossy White' }

  function activePaint() {
    if (document.body.classList.contains('paint-white')) return 'white'
    if (document.body.classList.contains('paint-green')) return 'green'
    return 'dark'
  }
  function primaryFilter() { return document.getElementById(FILTER_IDS[activePaint()][0]) }

  function applyVar(name, value) {
    const def = VARS[name]; if (!def) return
    FILTER_IDS[activePaint()].forEach(id => {
      const f = document.getElementById(id); if (!f) return
      const el = f.querySelector(def.sel); if (el) el.setAttribute(def.attr, value)
    })
  }
  function readActiveFill() {
    if (activePaint() === 'dark') return null
    const h1 = document.querySelector('.hero h1.paint-3d')
    return h1 ? getComputedStyle(h1).backgroundColor : null
  }
  function rgbToHex(rgb) {
    if (!rgb) return '#000000'
    if (rgb.startsWith('#')) return rgb
    const m = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/)
    if (!m) return '#000000'
    return '#' + [1,2,3].map(i => Number(m[i]).toString(16).padStart(2,'0')).join('')
  }
  function applyFill(hex) {
    if (activePaint() === 'dark') return
    const h1 = document.querySelector('.hero h1.paint-3d')
    if (h1) h1.style.background = hex
    document.body.style.setProperty('--mod-fill', hex)
    if (!document.getElementById('modFillStyle')) {
      const s = document.createElement('style')
      s.id = 'modFillStyle'
      s.textContent =
        'body.paint-green .cta-btn::before, body.paint-white .cta-btn::before {' +
        '  background: var(--mod-fill, inherit) !important;' +
        '}'
      document.head.appendChild(s)
    }
  }
  function clearModifierOverrides() {
    const h1 = document.querySelector('.hero h1.paint-3d')
    if (h1) h1.style.background = ''
    document.body.style.removeProperty('--mod-fill')
  }
  function readAll() {
    const filter = primaryFilter(); if (!filter) return
    Object.entries(VARS).forEach(([name, def]) => {
      const input = document.querySelector('[data-var="' + name + '"]'); if (!input) return
      const el = filter.querySelector(def.sel)
      if (el) { const v = el.getAttribute(def.attr); if (v !== null) input.value = v }
    })
    const fillInput = document.querySelector('[data-var="fill"]')
    if (fillInput) { const fill = readActiveFill(); if (fill) fillInput.value = rgbToHex(fill) }
    document.querySelectorAll('.mod-row output').forEach(out => {
      const input = out.previousElementSibling
      if (input && input.type === 'range') out.textContent = input.value
    })
  }
  function refreshSectionVisibility() {
    const paint = activePaint()
    document.querySelectorAll('.mod-fieldset[data-paint-only]').forEach(fs => {
      const allowed = fs.dataset.paintOnly.split(',').map(s => s.trim())
      if (allowed.includes(paint)) fs.removeAttribute('data-hide')
      else fs.setAttribute('data-hide', 'true')
    })
    const label = document.getElementById('modPaintLabel')
    if (label) label.textContent = PAINT_LABEL[paint]
  }

  swatches.forEach(btn => {
    btn.addEventListener('click', () => {
      document.body.classList.remove('paint-green', 'paint-white')
      const paint = btn.dataset.paint
      if (paint) document.body.classList.add(paint)
      swatches.forEach(b => b.classList.remove('active'))
      btn.classList.add('active')
      clearModifierOverrides()
      refreshSectionVisibility()
      readAll()
    })
  })
  document.querySelectorAll('[data-var]').forEach(input => {
    input.addEventListener('input', () => {
      const name = input.dataset.var
      if (name === 'fill') applyFill(input.value)
      else applyVar(name, input.value)
      const out = input.nextElementSibling
      if (out && out.tagName === 'OUTPUT') out.textContent = input.value
    })
  })

  const openBtn = document.getElementById('modOpenBtn')
  const closeBtn = document.getElementById('modCloseBtn')
  if (openBtn) {
    openBtn.addEventListener('click', () => { document.body.classList.toggle('mod-open') })
  }
  if (closeBtn) {
    closeBtn.addEventListener('click', () => { document.body.classList.remove('mod-open') })
  }

  const copyBtn = document.getElementById('modCopy')
  const copyStatus = document.getElementById('modCopyStatus')
  if (copyBtn) {
    copyBtn.addEventListener('click', () => {
      const filter = primaryFilter(); if (!filter) return
      const dump = { paint: activePaint(), filter: FILTER_IDS[activePaint()][0] }
      Object.entries(VARS).forEach(([name, def]) => {
        const el = filter.querySelector(def.sel)
        if (el && el.hasAttribute(def.attr)) dump[name] = el.getAttribute(def.attr)
      })
      const fill = readActiveFill()
      if (fill && activePaint() !== 'dark') dump.fill = rgbToHex(fill)
      const text = JSON.stringify(dump, null, 2)
      navigator.clipboard.writeText(text).then(() => {
        if (copyStatus) {
          copyStatus.textContent = 'Copied'
          setTimeout(() => { copyStatus.textContent = '' }, 1500)
        }
      }).catch(() => { if (copyStatus) copyStatus.textContent = 'Copy failed' })
    })
  }

  refreshSectionVisibility()
  readAll()
}

// ══════════════════════════════════════
// MOUNT
// ══════════════════════════════════════
onMounted(() => {
  // Expose functions referenced by inline onclick / onsubmit / onchange handlers
  window.startQuiz = startQuiz
  window.restartQuiz = restartQuiz
  window.setLang = setLang
  window.submitCapture = submitCapture
  window.selectOption = selectOption
  window.toggleMulti = toggleMulti
  window.updateSlider = updateSlider
  window.nextQ = nextQ
  window.prevQ = prevQ
  window.showScenario = showScenario
  window.openCaptureModal = openCaptureModal
  window.closeCaptureModal = closeCaptureModal
  window.scrollToRecs = scrollToRecs
  window.closeAndScrollToRecs = closeAndScrollToRecs
  window.updateRegionFromCountry = updateRegionFromCountry
  window.updateRegionIndicator = updateRegionIndicator
  window.showRegionPicker = showRegionPicker

  // ESC closes the capture modal
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') {
      const modal = document.getElementById('capture-modal')
      if (modal && modal.classList.contains('open')) closeCaptureModal()
    }
  })

  // Initial render — pull saved session state (if any) so reload mid-quiz
  // restores the user where they left off. Lang sets first so renderQuestion
  // / renderResults pick up the right strings. If no saved language, sniff
  // navigator.language so German speakers land on the German copy without
  // having to click the toggle.
  const saved = loadState()
  const detectLang = () => {
    const nav = (navigator.language || navigator.userLanguage || 'en').toLowerCase()
    return nav.startsWith('de') ? 'de' : 'en'
  }
  const lang = (saved && saved.currentLang) || detectLang()
  setLang(lang)
  updateRegionIndicator()

  // Intro overlay — only on the very first home-page visit in this tab.
  // If we're resuming a saved quiz/results stage, or the intro has already
  // played in this session, jump straight to the hero with no animation.
  const resumingMidFlow = !!(saved && saved.stage && saved.stage !== 'home')
  maybePlayIntro({ skip: resumingMidFlow })

  if (saved && saved.stage && saved.stage !== 'home') {
    answers = saved.answers || {}
    currentQ = typeof saved.currentQ === 'number' ? saved.currentQ : 0
    currentScenario = saved.currentScenario || 1
    if (saved.stage === 'quiz') {
      // Re-enter quiz mode without resetting state — startQuiz wipes
      // answers, so call its DOM-only side effects then renderQuestion.
      const hide = id => { const el = document.getElementById(id) || document.querySelector('.' + id); if(el) el.classList.add('hidden') }
      hide('hero-section'); hide('about-section')
      const strip = document.querySelector('.scenario-strip')
      if(strip) strip.classList.add('hidden')
      document.body.style.overflow = 'auto'
      document.body.style.height = 'auto'
      const app = document.querySelector('.app')
      if (app) { app.style.overflow = 'visible'; app.style.height = 'auto' }
      const quizEl = document.getElementById('quiz-section')
      if(quizEl) quizEl.classList.remove('hidden')
      document.body.classList.add('quiz-active')
      renderQuestion()
    } else if (saved.stage === 'results') {
      // Same DOM unwind as quiz, then jump straight to results.
      document.body.style.overflow = 'auto'
      document.body.style.height = 'auto'
      const app = document.querySelector('.app')
      if (app) { app.style.overflow = 'visible'; app.style.height = 'auto' }
      const hero = document.getElementById('hero-section')
      if(hero) hero.classList.add('hidden')
      const strip = document.querySelector('.scenario-strip')
      if(strip) strip.classList.add('hidden')
      showResults()
    }
  }

  // Wire up scenario strip + paint picker after DOM is mounted
  initScenarioStrip()
  initPaintPicker()
})
</script>
