// ============ Puhastid — App ============
const { useState, useEffect, useRef, useMemo, useCallback } = React;
const SIZES = window.PUHASTID_DATA.SIZES;
const PRICES = window.PUHASTID_DATA.PRICES;
const COPY = window.PUHASTID_DATA.COPY;

// Motion primitives (loaded from framer-motion UMD + motion-helpers.jsx)
const { motion, AnimatePresence, LayoutGroup, useReducedMotion, EASE_OUT } = window.PMotion;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "forest",
  "bgTone": "bone",
  "dark": false,
  "font": "dm",
  "hSize": 1.0,
  "hWeight": 500,
  "radius": 18,
  "squareBtns": false,
  "density": "compact",
  "heroLayout": "default",
  "configStyle": "elevated",
  "sizePicker": "slider",
  "tankTone": "lime",
  "showEyebrow": true,
  "showStats": false,
  "showMap": true,
  "showTrustStrip": true
} /*EDITMODE-END*/;

const TANK_TONES = {
  lime: { top: "#D5E365", mid: "#BFD53C", bot: "#8FA426", manhole1: "#5A6D1A", manhole2: "#8FA426", manhole3: "#A7BF2E", pipe: "#5A6D1A" },
  forest: { top: "#5C8466", mid: "#3B6B4A", bot: "#244A2E", manhole1: "#172E1C", manhole2: "#3B6B4A", manhole3: "#5C8466", pipe: "#172E1C" },
  steel: { top: "#C9CFD6", mid: "#8A929C", bot: "#535A64", manhole1: "#2F343B", manhole2: "#535A64", manhole3: "#8A929C", pipe: "#2F343B" },
  copper: { top: "#E8B895", mid: "#C77A4D", bot: "#8E4A26", manhole1: "#5C2D17", manhole2: "#8E4A26", manhole3: "#C77A4D", pipe: "#5C2D17" },
  charcoal: { top: "#5A5A57", mid: "#33332F", bot: "#15140F", manhole1: "#000000", manhole2: "#33332F", manhole3: "#5A5A57", pipe: "#000000" },
  cream: { top: "#FAF1DC", mid: "#E8D5A8", bot: "#B79A60", manhole1: "#7A6536", manhole2: "#B79A60", manhole3: "#E8D5A8", pipe: "#7A6536" }
};

const fmtPrice = (n, lang) => {
  // Finnish uses space as thousands separator, € after
  const s = Math.round(n).toLocaleString("fi-FI").replace(/,/g, " ");
  return s + " €";
};

// En-dash with hair spaces on either side — proper typographic range separator.
const RANGE_DASH = "\u200A\u2013\u200A";
const fmtRange = ([a, b], lang) => `${fmtPrice(a, lang)}${RANGE_DASH}${fmtPrice(b, lang)}`;

// ---- Tank SVG (procedural illustration; scales with size) ----
function TankSVG({ size, tone = "lime" }) {
  const c = TANK_TONES[tone] || TANK_TONES.lime;
  // visual scale by size; min vs max
  const scale = 0.55 + Math.min(1, (size - 5) / 95) * 0.45;
  const w = 320 * scale;
  const h = 150 * scale;
  const cx = 200;
  const cy = 130;
  return (
    <svg
      className="tank-svg"
      viewBox="0 0 400 240"
      preserveAspectRatio="xMidYMid meet"
      aria-hidden="true">
      
      <defs>
        <linearGradient id={`tankBody-${tone}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={c.top} />
          <stop offset="50%" stopColor={c.mid} />
          <stop offset="100%" stopColor={c.bot} />
        </linearGradient>
        <linearGradient id="tankShine" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="rgba(255,255,255,0.45)" />
          <stop offset="100%" stopColor="rgba(255,255,255,0)" />
        </linearGradient>
        <radialGradient id="tankShadow" cx="0.5" cy="0.5" r="0.5">
          <stop offset="0%" stopColor="rgba(20,18,14,0.28)" />
          <stop offset="100%" stopColor="rgba(20,18,14,0)" />
        </radialGradient>
      </defs>

      {/* ground shadow */}
      <ellipse cx={cx} cy={cy + h / 2 + 8} rx={w * 0.55} ry={10} fill="url(#tankShadow)" />

      {/* tank body — capsule */}
      <g transform={`translate(${cx - w / 2}, ${cy - h / 2})`}>
        {/* left dome */}
        <ellipse cx={h / 2} cy={h / 2} rx={h / 2} ry={h / 2} fill={`url(#tankBody-${tone})`} />
        {/* right dome */}
        <ellipse cx={w - h / 2} cy={h / 2} rx={h / 2} ry={h / 2} fill={`url(#tankBody-${tone})`} />
        {/* middle barrel */}
        <rect x={h / 2} y={0} width={w - h} height={h} fill={`url(#tankBody-${tone})`} />

        {/* highlight */}
        <rect x={h / 2} y={h * 0.1} width={w - h} height={h * 0.15} fill="url(#tankShine)" opacity="0.7" />

        {/* ribs */}
        {Array.from({ length: 4 }).map((_, i) => {
          const x = h / 2 + (w - h) * (i + 1) / 5;
          return (
            <line
              key={i}
              x1={x}
              y1={6}
              x2={x}
              y2={h - 6}
              stroke="rgba(20,18,14,0.12)"
              strokeWidth="1" />);


        })}

        {/* manhole on top */}
        <ellipse cx={w * 0.5} cy={2} rx={h * 0.16} ry={h * 0.06} fill={c.manhole1} />
        <ellipse cx={w * 0.5} cy={0} rx={h * 0.16} ry={h * 0.06} fill={c.manhole2} />
        <ellipse cx={w * 0.5} cy={-1} rx={h * 0.13} ry={h * 0.04} fill={c.manhole3} />

        {/* outlet pipe */}
        <rect x={w - h / 2 - 4} y={h * 0.45} width={h * 0.32} height={h * 0.12} fill={c.pipe} rx="2" />
      </g>
    </svg>);

}

// ---- Map of Finland (real Simplemaps outline + Estonian coast strip) ----
// FI_PATHS is defined globally in map-data.js (loaded before app.jsx).
// It's an array of 19 SVG path d-strings, one per Finnish region (FI01..FI19).
// Real bbox (computed by simulating the path commands) is
//   x:[277, 723]  y:[45.5, 954.5]  (446 wide, 909 tall)
// within the Simplemaps 1000x1000 source viewBox. We render them inside a <g>
// with translate(-140 0) so Finland centers horizontally in our 720-wide
// canvas (137px margin each side) and sits in y:[45, 955], leaving y 1000-1150
// for the hand-drawn Estonian coast strip.
function FinlandMap() {
  // Cities in the combined viewBox (720x1150). The x/y values are the
  // POST-translate display coords (i.e. native Simplemaps x minus 140).
  // Estimated by linear lat/lon→pixel mapping:
  //   y = 954.5 - (lat - 60) * 90.9
  //   x = (277 + (lon - 20) * 37) - 140        (the -140 is the FI translate)
  // Each non-Helsinki city has `tcp` = two cubic bezier control points for
  // the truck leg of its route (from the Helsinki ferry landing inland).
  const cities = [
    { x: 320, y: 939, name: "HELSINKI",  days: "1 d" },
    { x: 221, y: 913, name: "TURKU",     days: "1 d", tcp: [[280, 950], [240, 920]] },
    { x: 276, y: 818, name: "TAMPERE",   days: "2 d", tcp: [[315, 885], [285, 850]] },
    { x: 498, y: 718, name: "JOENSUU",   days: "3 d", tcp: [[400, 870], [470, 770]] },
    { x: 339, y: 499, name: "OULU",      days: "2 d", tcp: [[340, 780], [335, 620]] },
    { x: 349, y: 364, name: "ROVANIEMI", days: "3 d", tcp: [[345, 740], [350, 510]] }];


  const tallinn = { x: 313, y: 1075 }; // post-translate, just south of Helsinki
  const ferry = { x: 320, y: 939 };    // Helsinki harbor — common ferry landing

  // Hand-drawn northern Estonia coast — only a sliver is visible. The
  // Tallinn peninsula recess sits at x~313 (under Helsinki).
  const estoniaPath = `
    M 0 1150 L 0 1090
    C 50 1083, 110 1077, 175 1073
    C 215 1070, 250 1063, 285 1066
    L 305 1068 L 320 1066
    C 355 1066, 410 1072, 480 1078
    C 560 1086, 650 1093, 720 1098
    L 720 1150 Z
  `;

  // Route builder: ferry leg from Tallinn across the Gulf of Finland to
  // Helsinki harbor (slight curve to read as a sea crossing), then a road
  // leg with destination-specific bends so routes look like real driving
  // paths rather than straight arrows.
  const routePath = (c) => {
    const fLeg = `M ${tallinn.x} ${tallinn.y} C ${tallinn.x - 8} ${tallinn.y - 55}, ${ferry.x + 8} ${ferry.y + 65}, ${ferry.x} ${ferry.y}`;
    if (c.name === "HELSINKI") return fLeg;
    const [c1, c2] = c.tcp;
    return `${fLeg} C ${c1[0]} ${c1[1]}, ${c2[0]} ${c2[1]}, ${c.x} ${c.y}`;
  };

  return (
    <svg viewBox="0 0 720 1150" width="100%" height="100%" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
      {/* Sea background */}
      <rect className="map-water-bg" width="720" height="1150" />

      {/* Subtle graticule */}
      {[200, 400, 600, 800, 1000].map((y, i) =>
      <line key={"h" + i} className="map-grid" x1="0" y1={y} x2="720" y2={y} strokeWidth="0.8" strokeDasharray="2 8" />
      )}
      {[180, 360, 540].map((x, i) =>
      <line key={"v" + i} className="map-grid" x1={x} y1="0" x2={x} y2="1150" strokeWidth="0.8" strokeDasharray="2 8" />
      )}

      {/* Finland — real outline (Simplemaps, 19 region paths combined) */}
      <g transform="translate(-140 0)">
        {FI_PATHS.map((d, i) =>
        <path key={i} className="map-land" d={d} strokeWidth="1" strokeLinejoin="round" />
        )}
      </g>

      {/* Estonia north coast — sliver visible at the bottom */}
      <path className="map-land" d={estoniaPath} strokeWidth="1" strokeLinejoin="round" />

      {/* Lake Saimaa region — abstract patches in SE Finland (post-translate coords) */}
      <ellipse className="map-lake" cx="450" cy="800" rx="22" ry="13" />
      <ellipse className="map-lake" cx="425" cy="765" rx="13" ry="8" />
      <ellipse className="map-lake" cx="475" cy="760" rx="9" ry="5" />
      <ellipse className="map-lake" cx="438" cy="830" rx="11" ry="6" />

      {/* Routes — Tallinn → Helsinki ferry → city road, drawn under pins */}
      {cities.map((c) =>
      <path
        key={"r" + c.name}
        className="map-route"
        d={routePath(c)}
        strokeWidth="2"
        strokeOpacity="0.55"
        strokeLinecap="round"
        fill="none" />

      )}

      {/* Cities */}
      {cities.map((c) =>
      <g key={c.name}>
          <circle className="map-pin-ring" cx={c.x} cy={c.y} r="13" strokeWidth="1.5" opacity="0.3" />
          <circle className="map-pin" cx={c.x} cy={c.y} r="5.5" />
          <text className="map-text-city" x={c.x + 20} y={c.y - 2} fontSize="18">
            {c.name}
          </text>
          <text className="map-text-sub" x={c.x + 20} y={c.y + 18} fontSize="15">
            {c.days}
          </text>
        </g>
      )}

      {/* Tallinn origin marker */}
      <g>
        <line className="map-origin-stem" x1={tallinn.x} y1={tallinn.y - 36} x2={tallinn.x} y2={tallinn.y - 8} strokeWidth="2" />
        <circle className="map-origin-stem" cx={tallinn.x} cy={tallinn.y - 40} r="6" />
        <rect className="map-origin-bg" x={tallinn.x - 90} y={tallinn.y - 6} width="180" height="32" rx="4" />
        <text className="map-origin-text" x={tallinn.x} y={tallinn.y + 16} fontSize="17" textAnchor="middle">
          TALLINN · ORIGIN
        </text>
      </g>

      {/* Compass — top right */}
      <g transform="translate(660, 80)">
        <circle className="map-compass-bg" r="30" strokeWidth="1.4" />
        <path className="map-compass-n" d="M 0 -22 L 7 0 L 0 -4 L -7 0 Z" />
        <path className="map-compass-s" d="M 0 22 L 7 0 L 0 4 L -7 0 Z" />
        <text className="map-text-faint" y="-36" fontSize="14" textAnchor="middle">N</text>
      </g>

      {/* Scale bar — sits in the Gulf, just above the Estonian coast */}
      <g transform="translate(40, 1030)">
        <line className="map-scale" x1="0" y1="0" x2="90" y2="0" strokeWidth="2.5" />
        <line className="map-scale" x1="0" y1="-6" x2="0" y2="6" strokeWidth="2.5" />
        <line className="map-scale" x1="45" y1="-4" x2="45" y2="4" strokeWidth="2" />
        <line className="map-scale" x1="90" y1="-6" x2="90" y2="6" strokeWidth="2.5" />
        <text className="map-text-faint" x="0" y="-13" fontSize="14">0</text>
        <text className="map-text-faint" x="90" y="-13" fontSize="14" textAnchor="middle">100 KM</text>
      </g>

      {/* Legend — top left */}
      <g transform="translate(40, 58)">
        <text className="map-text-faint" fontSize="15" letterSpacing="0.16em">
          TOIMITUSVERKOSTO
        </text>
        <text className="map-text-faint" y="22" fontSize="14" opacity="0.7">
          Tallinn → Suomi · 6 kaupunkia
        </text>
      </g>
    </svg>);

}

// ---- Header ----
function Header({ lang, setLang, scrollTo }) {
  const t = COPY[lang];
  const reduced = useReducedMotion();
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <header className={`hdr ${scrolled ? "scrolled" : ""}`}>
      <div className="wrap hdr-inner">
        <a href="#top" className="logo" onClick={(e) => {e.preventDefault();window.scrollTo({ top: 0, behavior: "smooth" });}}>
          <motion.span
            className="logo-img-wrap"
            style={{ display: "inline-block", transformOrigin: "left center", lineHeight: 0 }}
            animate={reduced ? undefined : { scale: scrolled ? 0.92 : 1 }}
            transition={{ duration: 0.25, ease: EASE_OUT }}>
            <img src="puhastid-logo.svg" alt="Puhastid" className="logo-img" />
          </motion.span>
          <span className="logo-divider"></span>
          <span className="logo-tag">
            <b>Eccua.fi</b>
            <span>{lang === "fi" ? "Lasikuitusäiliöt" : "Glassfiber tanks"}</span>
          </span>
        </a>
        <nav className="nav">
          <a className="nav-link" href="#toimitus" onClick={(e) => {e.preventDefault();scrollTo("toimitus");}}>{t.nav.shipping}</a>
          <a className="nav-link" href="#tietoa" onClick={(e) => {e.preventDefault();scrollTo("tietoa");}}>{t.nav.info}</a>
          <a className="nav-link" href="#meista" onClick={(e) => {e.preventDefault();scrollTo("meista");}}>{t.nav.about}</a>
          <LayoutGroup id="lang-hdr">
            <div className="lang-toggle" role="group" aria-label="Language">
              <LangButton on={lang === "fi"} onClick={() => setLang("fi")}>FI</LangButton>
              <LangButton on={lang === "en"} onClick={() => setLang("en")}>EN</LangButton>
            </div>
          </LayoutGroup>
          <a className="btn btn-primary" href="#tarjous" onClick={(e) => {e.preventDefault();scrollTo("tarjous");}}>
            {t.nav.cta}
            <span className="arrow">→</span>
          </a>
          <button className="menu-btn" aria-label="Menu">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 6h18M3 12h18M3 18h18" /></svg>
          </button>
        </nav>
      </div>
    </header>);

}

// Shared layoutId pill backs the active language button — slides between FI/EN
function LangButton({ on, onClick, children }) {
  const reduced = useReducedMotion();
  return (
    <button className={on ? "on" : ""} onClick={onClick} style={{ position: "relative" }}>
      {on && !reduced &&
      <motion.span
        layoutId="lang-pill"
        className="lang-pill"
        transition={{ type: "tween", duration: 0.28, ease: EASE_OUT }} />
      }
      <span style={{ position: "relative", zIndex: 1 }}>{children}</span>
    </button>);
}

// ---- Size selector variants ----
function SizeChips({ size, setSize, lang, dark }) {
  const reduced = useReducedMotion();
  return (
    <LayoutGroup id="size-chips">
      <div className="chips" role="radiogroup" aria-label={COPY[lang].cfg.sizeLabel}>
        {SIZES.map((s) => {
          const on = s === size;
          return (
            <button
              key={s}
              className={`chip ${on ? "on" : ""}`}
              onClick={() => setSize(s)}
              role="radio"
              aria-checked={on}>
              {on && !reduced &&
              <motion.span
                layoutId="chip-pill"
                className="chip-pill"
                transition={{ type: "tween", duration: 0.32, ease: EASE_OUT }} />
              }
              <span className="chip-label">{s}<span className="unit">m³</span></span>
            </button>);
        })}
      </div>
    </LayoutGroup>);
}

function SizeStrip({ size, setSize, lang }) {
  const reduced = useReducedMotion();
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current?.querySelector(".chip.on");
    if (el) el.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
  }, [size]);
  return (
    <LayoutGroup id="size-strip">
      <div ref={ref} className="size-strip" role="radiogroup" aria-label={COPY[lang].cfg.sizeLabel}>
        {SIZES.map((s) => {
          const on = s === size;
          return (
            <button
              key={s}
              className={`chip ${on ? "on" : ""}`}
              onClick={() => setSize(s)}
              role="radio"
              aria-checked={on}>
              {on && !reduced &&
              <motion.span
                layoutId="chip-pill-strip"
                className="chip-pill"
                transition={{ type: "tween", duration: 0.32, ease: EASE_OUT }} />
              }
              <span className="chip-label">{s}<span className="unit">m³</span></span>
            </button>);
        })}
      </div>
    </LayoutGroup>);
}

function SizeSlider({ size, setSize, lang }) {
  const idx = SIZES.indexOf(size);
  const max = SIZES.length - 1;
  const pct = idx / max * 100;
  return (
    <div className="size-slider">
      <div className="size-slider-head">
        <span className="cfg-label">{COPY[lang].cfg.sizeLabel}</span>
        <span className="v" aria-live="polite"><span className="num">{size}</span><span className="unit">m³</span></span>
      </div>
      <div className="size-slider-track">
        <div className="size-slider-line"></div>
        <div className="size-slider-fill" style={{ width: `${pct}%` }}></div>
        {SIZES.map((s, i) => {
          const left = i / max * 100;
          const major = [5, 25, 50, 75, 100].includes(s);
          return (
            <div
              key={s}
              className={`size-slider-tick ${major ? "major" : ""}`}
              style={{ left: `${left}%` }}
              onClick={() => setSize(s)}
              role="button"
              aria-label={`${s} m³`}>
            </div>);
        })}
        <div className="size-slider-thumb" style={{ left: `${pct}%` }}></div>
        <input
          type="range"
          min="0" max={max} step="1"
          value={idx}
          onChange={(e) => setSize(SIZES[parseInt(e.target.value, 10)])}
          style={{ position: "absolute", inset: 0, opacity: 0, cursor: "pointer", width: "100%", height: "100%" }}
          aria-label={COPY[lang].cfg.sizeLabel} />
        
      </div>
      <div className="size-slider-marks">
        <span>5</span><span>25</span><span>50</span><span>75</span><span>100
</span>
      </div>
    </div>);}

// ---- Hero + Configurator ----
function Hero({ lang, size, setSize, scrollToForm, tw }) {
  const t = COPY[lang];
  const reduced = useReducedMotion();
  const [flash, setFlash] = useState(false);
  const lastSize = useRef(size);

  useEffect(() => {
    if (lastSize.current !== size) {
      setFlash(true);
      const id = setTimeout(() => setFlash(false), 380);
      lastSize.current = size;
      return () => clearTimeout(id);
    }
  }, [size]);

  const range = PRICES[size];

  // Word-by-word stagger choreography for the headline.
  // We re-key on lang so a language switch re-runs the reveal (matches the
  // "language toggle does a fast fade-out/in" feel without sliding).
  const hKey = `h-${lang}`;
  // word index counter for delays across the three headline runs
  let wIdx = 0;
  const wordsOf = (s) => String(s || "").trim().split(/\s+/).filter(Boolean);
  const headPre = wordsOf(t.hero.h1Pre);
  const headEm = wordsOf(t.hero.h1Em);
  const headPost = wordsOf(t.hero.h1Post);
  const perWord = 0.05;
  const headBase = 0.05;
  const renderWord = (word, key, italic) => {
    const delay = headBase + wIdx * perWord;
    wIdx += 1;
    if (reduced) {
      return (
        <React.Fragment key={key}>
          <span style={{ display: "inline-block" }}>{italic ? <em>{word}</em> : word}</span>
          {" "}
        </React.Fragment>);
    }
    return (
      <React.Fragment key={key}>
        <motion.span
          style={{ display: "inline-block", willChange: "transform, opacity" }}
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.55, delay, ease: EASE_OUT }}>
          {italic ? <em>{word}</em> : word}
        </motion.span>
        {" "}
      </React.Fragment>);
  };
  // Estimated time when headline finishes — supporting content starts a hair later
  const headTotal = headBase + (headPre.length + headEm.length + headPost.length) * perWord + 0.3;

  return (
    <section className="hero" id="top">
      <div className="wrap hero-grid">
        {/* Left */}
        <div>
          {tw.showEyebrow && (
          reduced ?
          <div className="eyebrow"><span className="dot"></span>{t.hero.eyebrow}</div> :
          <motion.div
            className="eyebrow"
            key={`eb-${lang}`}
            initial={{ opacity: 0, y: 8 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.45, ease: EASE_OUT }}>
              <span className="dot"></span>
              {t.hero.eyebrow}
            </motion.div>)
          }
          <h1 className="h1 h1-reserve" key={hKey}>
            {headPre.map((w, i) => renderWord(w, `pre-${i}`, false))}
            {headEm.map((w, i) => renderWord(w, `em-${i}`, true))}
            {headPost.map((w, i) => renderWord(w, `post-${i}`, false))}
          </h1>
          {reduced ?
          <p className="lead">{t.hero.lead}</p> :
          <motion.p
            key={`lead-${lang}`}
            className="lead"
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.5, delay: headTotal, ease: EASE_OUT }}>
              {t.hero.lead}
            </motion.p>
          }
          {reduced ?
          <ul className="feature-list">
              {t.hero.features.map((f, i) =>
            <li key={i}>
                  <span className="tick">
                    <svg viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M2.5 6.2 L5 8.5 L9.5 3.5" />
                    </svg>
                  </span>
                  {f}
                </li>
            )}
            </ul> :
          <motion.ul
            key={`feat-${lang}`}
            className="feature-list"
            initial="hidden"
            animate="visible"
            variants={{
              hidden: {},
              visible: { transition: { staggerChildren: 0.07, delayChildren: headTotal + 0.1 } }
            }}>
              {t.hero.features.map((f, i) =>
            <motion.li
              key={i}
              variants={{
                hidden: { opacity: 0, y: 8 },
                visible: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE_OUT } }
              }}>
                  <span className="tick">
                    <svg viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M2.5 6.2 L5 8.5 L9.5 3.5" />
                    </svg>
                  </span>
                  {f}
                </motion.li>
            )}
            </motion.ul>
          }
        </div>

        {/* Right — configurator (fades in as one block, slightly delayed) */}
        {reduced ?
        <div className="configurator">
            <ConfiguratorBody lang={lang} size={size} setSize={setSize} scrollToForm={scrollToForm} tw={tw} flash={flash} range={range} />
          </div> :
        <motion.div
          className="configurator"
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.65, delay: 0.3, ease: EASE_OUT }}>
            <ConfiguratorBody lang={lang} size={size} setSize={setSize} scrollToForm={scrollToForm} tw={tw} flash={flash} range={range} />
          </motion.div>
        }
      </div>
    </section>);

}

// Body of the configurator — split out so the Hero can wrap it in motion or not.
function ConfiguratorBody({ lang, size, setSize, scrollToForm, tw, flash, range }) {
  const reduced = useReducedMotion();
  const t = COPY[lang];
  return (
    <React.Fragment>
      {tw.sizePicker !== "slider" &&
      <div className="cfg-head">
          <span className="cfg-label">{t.cfg.sizeLabel}</span>
          <span className="cfg-hint">{t.cfg.sizeHint} — 5 – 100 m³</span>
        </div>
      }
      {tw.sizePicker === "strip" && <SizeStrip size={size} setSize={setSize} lang={lang} />}
      {tw.sizePicker === "slider" && <SizeSlider size={size} setSize={setSize} lang={lang} />}
      {tw.sizePicker === "chips" && <SizeChips size={size} setSize={setSize} lang={lang} />}

      <div className="product">
        <motion.div
          className="tank-wrap"
          animate={reduced ? undefined : {
            y: [0, -4, 0, 4, 0],
            scale: flash ? [1, 1.04, 1] : 1
          }}
          transition={reduced ? undefined : flash ? {
            scale: { duration: 0.4, ease: EASE_OUT },
            y: { duration: 6, repeat: Infinity, ease: "easeInOut" }
          } : {
            y: { duration: 6, repeat: Infinity, ease: "easeInOut" }
          }}
          whileHover={reduced ? undefined : { scale: 1.02 }}>
          <AnimatePresence mode="wait" initial={false}>
            <motion.div
              key={`${size}-${tw.tankTone}`}
              initial={reduced ? false : { opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={reduced ? undefined : { opacity: 0 }}
              transition={{ duration: 0.18, ease: "easeOut" }}>
              <TankSVG size={size} tone={tw.tankTone} />
            </motion.div>
          </AnimatePresence>
        </motion.div>
        <div className="badge">ECCUA · <span className="num">{size}</span><span className="unit">m³</span></div>
        <div className="tank-meta">
          <span className="lbl">spec</span>
          <span>glassfiber · {tw.tankTone}</span>
        </div>
      </div>

      <div className="price-row">
        <div className="price-meta">
          <span className="lbl">{t.cfg.priceLabel}</span>
          <span className="sub">{t.cfg.priceSub}</span>
        </div>
        <div className="price-value">
          <AnimatedNumber value={range[0]} format={(v) => fmtPrice(v, lang)} />
          <span className="price-dash">{"\u200A\u2013\u200A"}</span>
          <AnimatedNumber value={range[1]} format={(v) => fmtPrice(v, lang)} />
        </div>
      </div>

      <div className="cta-row">
        <button className="btn btn-primary btn-lg btn-magnetic" onClick={scrollToForm}>
          {t.cfg.cta} <span className="arrow">→</span>
        </button>
      </div>
    </React.Fragment>);

}

// ---- Why cards ----
function Why({ lang, tw }) {
  const t = COPY[lang].why;
  const reduced = useReducedMotion();
  // each card gets a different tasteful icon motion
  const iconAnims = [
  { rotate: 5 }, // soil pressure: slight tilt
  { y: -2 }, // shield: lifts up
  { rotate: 30 } // clock: minute hand creep
  ];

  return (
    <Reveal as="section" amount={0.15}>
      <span className="anchor" id="tietoa-a"></span>
      <div className="wrap" id="tietoa">
        <Reveal className="sec-head" y={12}>
          <div>
            {tw.showEyebrow && <div className="sec-num">— {t.num}</div>}
            <h2 className="h2">{t.h2}</h2>
          </div>
          <p className="sec-intro">{t.intro}</p>
        </Reveal>
        <StaggerReveal className="why-grid" stagger={0.08} delay={0.05} amount={0.2}>
          {t.cards.map((c, i) =>
          <WhyCard key={i} c={c} i={i} reduced={reduced} iconAnim={iconAnims[i % iconAnims.length]} />
          )}
        </StaggerReveal>
      </div>
    </Reveal>);

}

function WhyCard({ c, i, reduced, iconAnim }) {
  const icons = [
  <svg key="0" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 8h18M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8" /><path d="M9 12v4M15 12v4" /></svg>,
  <svg key="1" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3 4 6v6c0 5 3.5 8.5 8 9 4.5-.5 8-4 8-9V6l-8-3z" /><path d="m9 12 2 2 4-4" /></svg>,
  <svg key="2" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></svg>];


  // Combine the parent StaggerReveal entrance variants with our own hover variant.
  const cardVariants = {
    hidden: { opacity: 0, y: 16 },
    visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: EASE_OUT } }
  };
  const iconVariants = reduced ? {} : {
    rest: { rotate: 0, y: 0 },
    hover: { ...iconAnim, transition: { duration: 0.35, ease: EASE_OUT } }
  };

  return (
    <motion.article
      className="why-card"
      variants={cardVariants}
      whileHover={reduced ? undefined : "hover"}
      initial={reduced ? undefined : "rest"}
      animate={reduced ? undefined : undefined}>
      <motion.div className="icon" variants={iconVariants}>
        {icons[i]}
      </motion.div>
      <span className="num">{c.n}</span>
      <h3>{c.t}</h3>
      <p>{c.d}</p>
    </motion.article>);

}

// ---- Estonia block ----
function Estonia({ lang, tw }) {
  const t = COPY[lang].estonia;
  return (
    <Reveal as="section" amount={0.12}>
      <span className="anchor" id="meista-a"></span>
      <div className="wrap" id="meista">
        <div className="estonia">
          <div>
            {tw.showEyebrow &&
            <div className="eyebrow">
                <span className="dot"></span>
                {t.eyebrow}
              </div>
            }
            <h2 style={{ whiteSpace: "pre-line" }}>{t.h2}</h2>
            <p>{t.p1}</p>
            <p>{t.p2}</p>
            {tw.showStats &&
            <div className="stats">
                {t.stats.map((s, i) =>
              <div className="stat" key={i}>
                    <div className="n">{s.n}</div>
                    <div className="lbl">{s.l}</div>
                  </div>
              )}
              </div>
            }
          </div>
          <div className="estonia-card">
            <div style={{ fontSize: 11, letterSpacing: "0.14em", color: "rgba(250,248,243,0.55)", marginBottom: 14, textTransform: "uppercase" }}>
              {t.card.title}
            </div>
            {t.card.rows.map(([k, v], i) =>
            <div className="row" key={i}>
                <span className="k">{k}</span>
                <span className="v">{v}</span>
              </div>
            )}
            <div style={{ marginTop: 18, fontSize: 11, color: "rgba(250,248,243,0.5)" }}>
              Tallinn 59.4370° N · 24.7536° E
            </div>
          </div>
        </div>
      </div>
    </Reveal>);

}

// ---- Shipping ----
function Shipping({ lang, tw }) {
  const t = COPY[lang].ship;
  return (
    <Reveal as="section" amount={0.12}>
      <span className="anchor" id="toimitus-a"></span>
      <div className="wrap" id="toimitus">
        <Reveal className="sec-head" y={12}>
          <div>
            {tw.showEyebrow && <div className="sec-num">— {t.num}</div>}
            <h2 className="h2">{t.h2}</h2>
          </div>
          <p className="sec-intro">{t.intro}</p>
        </Reveal>
        <div className="ship" style={!tw.showMap ? { gridTemplateColumns: "1fr" } : null}>
          {tw.showMap && <div className="ship-map"><FinlandMap /></div>}
          <div>
            <p>{t.p1}</p>
            <p>{t.p2}</p>
            <ul className="feature-list" style={{ marginTop: 20, gridTemplateColumns: "1fr 1fr" }}>
              {t.points.map((p, i) =>
              <li key={i}>
                  <span className="tick">
                    <svg viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M2.5 6.2 L5 8.5 L9.5 3.5" /></svg>
                  </span>
                  {p}
                </li>
              )}
            </ul>
            {t.priceFrom &&
            <div className="ship-price">
                <div className="ship-price-l">
                  <span className="ship-price-lbl">{t.priceFrom.label}</span>
                  <span className="ship-price-amt">{t.priceFrom.amount}</span>
                  <span className="ship-price-note">{t.priceFrom.note}</span>
                </div>
                <a
                className="btn btn-ghost"
                href="#tarjous"
                onClick={(e) => {e.preventDefault();const el = document.getElementById("tarjous");if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 64, behavior: "smooth" });}}>
                
                  {lang === "fi" ? "Pyydä tarjous" : "Request a quote"}
                  <span className="arrow">→</span>
                </a>
              </div>
            }
          </div>
        </div>
      </div>
    </Reveal>);

}

// ---- Downloads ----
function Downloads({ lang, tw }) {
  const t = COPY[lang].downloads;
  if (!t) return null;
  return (
    <Reveal as="section" amount={0.12}>
      <span className="anchor" id="aineistot-a"></span>
      <div className="wrap" id="aineistot">
        <Reveal className="sec-head" y={12}>
          <div>
            {tw.showEyebrow && <div className="sec-num">— {t.num}</div>}
            <h2 className="h2">{t.h2}</h2>
          </div>
          <p className="sec-intro">{t.intro}</p>
        </Reveal>
        <StaggerReveal className="dl-grid" stagger={0.08} amount={0.2}>
          {t.items.map((it, i) =>
          <StaggerItem key={i} as="div">
              <a className="dl-card" href={"downloads/" + it.file} download>
                <div className="dl-icon">
                  <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
                    <polyline points="14 2 14 8 20 8" />
                  </svg>
                </div>
                <div className="dl-body">
                  <div className="dl-title">{it.title}</div>
                  <div className="dl-meta">{it.meta}</div>
                </div>
                <div className="dl-arrow" aria-hidden="true">
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M12 3v14" />
                    <path d="m6 13 6 6 6-6" />
                    <path d="M5 21h14" />
                  </svg>
                </div>
              </a>
            </StaggerItem>
          )}
        </StaggerReveal>
      </div>
    </Reveal>);

}

// ---- Contact ----
function Contact({ lang, tw }) {
  const t = COPY[lang].contact;
  return (
    <Reveal as="section" amount={0.12} style={{ paddingTop: 0 }}>
      <div className="wrap">
        <Reveal className="sec-head" y={12}>
          <div>
            {tw.showEyebrow && <div className="sec-num">— {t.num}</div>}
            <h2 className="h2">{t.h2}</h2>
          </div>
          <p className="sec-intro">{t.intro}</p>
        </Reveal>
        <StaggerReveal className="contact-grid" stagger={0.08} amount={0.2}>
          {t.cards.map((c, i) =>
          <StaggerItem key={i} as="div" className="contact-card">
              <div className="lbl">{c.lbl}</div>
              <div className="v">{c.v}</div>
              {c.sub && <div className="v sm" style={{ marginTop: 6 }}>{c.sub}</div>}
            </StaggerItem>
          )}
        </StaggerReveal>
      </div>
    </Reveal>);

}

// ---- Form ----
// Where inquiries go. To change recipient, just edit this address.
const INQUIRY_RECIPIENT = "info@puhastid.ee";

function InquiryForm({ lang, size, setSize, formRef }) {
  const t = COPY[lang].form;
  const reduced = useReducedMotion();
  const [state, setState] = useState({
    name: "",
    email: "",
    purpose: "",
    desc: ""
  });
  const [errors, setErrors] = useState({});
  const [submitted, setSubmitted] = useState(false);
  const [loading, setLoading] = useState(false);
  const [submitError, setSubmitError] = useState(null);

  function validate() {
    const e = {};
    if (!state.name.trim()) e.name = t.errs.name;
    if (!state.email.trim() || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.email)) e.email = t.errs.email;
    if (!state.purpose) e.purpose = t.errs.purpose;
    return e;
  }

  // Sends the inquiry to INQUIRY_RECIPIENT via FormSubmit.co — a free,
  // no-signup form-to-email relay. FormSubmit requires a one-time
  // confirmation: the FIRST inquiry ever submitted will trigger an
  // activation email to INQUIRY_RECIPIENT; clicking the link there
  // activates the endpoint. Every subsequent submission is delivered
  // straight to the inbox.
  async function sendInquiry(formData) {
    const purposeLabel = (() => {
      if (formData.purpose === "waste") return lang === "fi" ? "Jätevesi (saostus / umpisäiliö)" : "Wastewater (septic / holding)";
      if (formData.purpose === "fire") return lang === "fi" ? "Sammutusvesi (pelastusviranomaisen vaatima)" : "Firefighting water";
      return formData.purpose || "—";
    })();

    const subjectPrefix = lang === "fi" ? "Tarjouspyyntö" : "Inquiry";
    const payload = {
      _subject: `${subjectPrefix} — ${formData.name} · ${formData.size} m³ · eccua.fi`,
      _template: "table",        // FormSubmit renders a clean HTML table
      _captcha: "false",         // disable their CAPTCHA redirect step
      _replyto: formData.email,  // so a reply from the inbox goes to the customer
      Nimi: formData.name,
      Sähköposti: formData.email,
      "Säiliön koko": `${formData.size} m³`,
      Käyttötarkoitus: purposeLabel,
      "Kuvaus ja toimitusosoite": formData.desc && formData.desc.trim() ? formData.desc : "—",
      Kieli: lang.toUpperCase()
    };

    const res = await fetch("https://formsubmit.co/ajax/" + INQUIRY_RECIPIENT, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(payload)
    });

    if (!res.ok) {
      throw new Error("Network response was not ok (" + res.status + ")");
    }
    const json = await res.json().catch(() => ({}));
    if (json && json.success === "false") {
      throw new Error(json.message || "FormSubmit returned an error");
    }
    return json;
  }

  async function onSubmit(ev) {
    ev.preventDefault();
    const e = validate();
    setErrors(e);
    if (Object.keys(e).length) return;
    setLoading(true);
    setSubmitError(null);
    try {
      await sendInquiry({ ...state, size });
      setSubmitted(true);
    } catch (err) {
      console.error("Inquiry send failed:", err);
      setSubmitError(
        lang === "fi" ?
          "Pyynnön lähetys epäonnistui. Yritä uudelleen tai ota suoraan yhteyttä: " + INQUIRY_RECIPIENT :
          "Could not send your request. Please try again or email us directly: " + INQUIRY_RECIPIENT
      );
    } finally {
      setLoading(false);
    }
  }

  return (
    <Reveal as="section" amount={0.08}>
      <span className="anchor" id="tarjous-a"></span>
      <div className="wrap" id="tarjous" ref={formRef}>
        <div className="form-section">
          <div className="form-grid">
            <div className="form-side">
              <div className="sec-num">— {t.num}</div>
              <h2>{t.h2}</h2>
              <p>{t.intro}</p>
              <ul className="meta-list">
                {t.steps.map((s, i) =>
                <li key={i}>
                    <span className="n">{String(i + 1).padStart(2, "0")}</span>
                    <span>{s}</span>
                  </li>
                )}
              </ul>
              {COPY[lang].contact &&
              <div className="form-contact">
                  <div className="form-contact-h">
                    {lang === "fi" ? "Tai ota suoraan yhteyttä" : "Or contact us directly"}
                  </div>
                  <ul className="form-contact-list">
                    {COPY[lang].contact.cards.map((c, i) => {
                    const icons = [
                    // mail
                    <svg key="e" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2" /><path d="m3 7 9 6 9-6" /></svg>,
                    <svg key="p" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" /></svg>,
                    <svg key="o" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M20 10c0 7-8 13-8 13s-8-6-8-13a8 8 0 0 1 16 0z" /><circle cx="12" cy="10" r="3" /></svg>];

                    const hrefs = [
                    "mailto:" + c.v,
                    "tel:" + c.v.replace(/\s/g, ""),
                    "https://maps.google.com/?q=" + encodeURIComponent((c.sub || "") + " " + c.v)];

                    return (
                      <li key={i}>
                          <a className="form-contact-item" href={hrefs[i]} target={i === 2 ? "_blank" : undefined} rel={i === 2 ? "noopener noreferrer" : undefined}>
                            <span className="form-contact-ico">{icons[i]}</span>
                            <span className="form-contact-text">
                              <span className="v">{c.v}</span>
                              {c.sub && <span className="s">{c.sub}</span>}
                            </span>
                          </a>
                        </li>);

                  })}
                  </ul>
                </div>
              }
            </div>
            <div className="form">
              <AnimatePresence mode="wait" initial={false}>
                {submitted ?
                <motion.div
                  key="success"
                  className="form-success"
                  initial={reduced ? { opacity: 0 } : { opacity: 0, scale: 0.96 }}
                  animate={reduced ? { opacity: 1 } : { opacity: 1, scale: 1 }}
                  exit={{ opacity: 0 }}
                  transition={{ duration: 0.4, ease: EASE_OUT }}>
                    <div className="check">
                      <svg width="36" height="36" viewBox="0 0 36 36" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round">
                        <motion.path
                        d="M8 18.5 L15 25.5 L28 11"
                        initial={reduced ? { pathLength: 1 } : { pathLength: 0 }}
                        animate={{ pathLength: 1 }}
                        transition={{ duration: 0.6, ease: EASE_OUT, delay: 0.1 }} />
                      </svg>
                    </div>
                    <h3>{t.successH}</h3>
                    <p>{t.successP}</p>
                    <button
                    className="btn btn-ghost"
                    onClick={() => {
                      setSubmitted(false);
                      setState({ name: "", email: "", purpose: "", desc: "" });
                    }}>
                      {lang === "fi" ? "Lähetä toinen pyyntö" : "Send another request"}
                    </button>
                  </motion.div> :

                <motion.form
                  key="form"
                  onSubmit={onSubmit}
                  noValidate
                  initial={reduced ? { opacity: 0 } : { opacity: 0, y: 4 }}
                  animate={reduced ? { opacity: 1 } : { opacity: 1, y: 0 }}
                  exit={reduced ? { opacity: 0 } : { opacity: 0, y: -4 }}
                  transition={{ duration: 0.25, ease: EASE_OUT }}>
                    <div className="field-row">
                      <FormField
                      id="f-name"
                      label={t.name}
                      required
                      error={errors.name}
                      reduced={reduced}>
                        <input
                        id="f-name"
                        type="text"
                        value={state.name}
                        onChange={(e) => setState({ ...state, name: e.target.value })}
                        autoComplete="name"
                        className={errors.name ? "has-err" : ""} />
                      </FormField>
                      <FormField
                      id="f-email"
                      label={t.email}
                      required
                      error={errors.email}
                      reduced={reduced}>
                        <input
                        id="f-email"
                        type="email"
                        value={state.email}
                        onChange={(e) => setState({ ...state, email: e.target.value })}
                        autoComplete="email"
                        className={errors.email ? "has-err" : ""} />
                      </FormField>
                    </div>

                    <FormField id="f-size" label={t.size} required reduced={reduced}>
                      <select
                      id="f-size"
                      value={size}
                      onChange={(e) => setSize(parseInt(e.target.value, 10))}>
                        {SIZES.map((s) =>
                      <option key={s} value={s}>{s} m³  ·  {fmtRange(PRICES[s], lang)}</option>
                      )}
                      </select>
                    </FormField>

                    <div className="field">
                      <label>{t.purpose}<span className="req">*</span></label>
                      <div className="radio-row">
                        <label className={`radio ${state.purpose === "waste" ? "on" : ""}`}>
                          <input
                          type="radio"
                          name="purpose"
                          value="waste"
                          checked={state.purpose === "waste"}
                          onChange={() => setState({ ...state, purpose: "waste" })} />
                          <span className="ring"></span>
                          <span className="t">{t.purposeWaste.t}</span>
                          <span className="s">{t.purposeWaste.s}</span>
                        </label>
                        <label className={`radio ${state.purpose === "fire" ? "on" : ""}`}>
                          <input
                          type="radio"
                          name="purpose"
                          value="fire"
                          checked={state.purpose === "fire"}
                          onChange={() => setState({ ...state, purpose: "fire" })} />
                          <span className="ring"></span>
                          <span className="t">{t.purposeFire.t}</span>
                          <span className="s" style={{ fontSize: "12px" }}>{t.purposeFire.s}</span>
                        </label>
                      </div>
                      <AnimatePresence initial={false}>
                        {errors.purpose &&
                      <motion.div
                        key="err-purpose"
                        className="err"
                        initial={reduced ? { opacity: 0 } : { opacity: 0, y: -8, height: 0 }}
                        animate={reduced ? { opacity: 1 } : { opacity: 1, y: 0, height: "auto" }}
                        exit={reduced ? { opacity: 0 } : { opacity: 0, y: -8, height: 0 }}
                        transition={{ duration: 0.22, ease: EASE_OUT }}>
                            {errors.purpose}
                          </motion.div>
                      }
                      </AnimatePresence>
                    </div>

                    <FormField id="f-desc" label={t.desc} reduced={reduced}>
                      <textarea
                      id="f-desc"
                      placeholder={t.descPh}
                      value={state.desc}
                      onChange={(e) => setState({ ...state, desc: e.target.value })} />
                    </FormField>

                    <AnimatePresence initial={false}>
                      {submitError &&
                      <motion.div
                        key="submit-err"
                        className="form-submit-err"
                        role="alert"
                        initial={reduced ? { opacity: 0 } : { opacity: 0, y: -6, height: 0 }}
                        animate={reduced ? { opacity: 1 } : { opacity: 1, y: 0, height: "auto" }}
                        exit={reduced ? { opacity: 0 } : { opacity: 0, y: -6, height: 0 }}
                        transition={{ duration: 0.22, ease: EASE_OUT }}>
                          {submitError}
                        </motion.div>
                      }
                    </AnimatePresence>
                    <div className="form-actions">
                      <span className="tos">{t.tos}</span>
                      <button className="btn btn-primary btn-lg btn-magnetic" type="submit" disabled={loading}>
                        {loading ?
                      <React.Fragment>
                            <Spinner />
                            <span>{lang === "fi" ? "Lähetetään…" : "Sending…"}</span>
                          </React.Fragment> :
                      <React.Fragment>
                            <span>{t.submit}</span>
                            <span className="arrow">→</span>
                          </React.Fragment>
                      }
                      </button>
                    </div>
                  </motion.form>
                }
              </AnimatePresence>
            </div>
          </div>
        </div>
      </div>
    </Reveal>);

}

// Small subcomponent that handles label, child input, and animated error display.
function FormField({ id, label, required, error, children, reduced }) {
  return (
    <div className="field">
      {label &&
      <label htmlFor={id}>{label}{required && <span className="req">*</span>}</label>
      }
      {children}
      <AnimatePresence initial={false}>
        {error &&
        <motion.div
          key="err"
          className="err"
          initial={reduced ? { opacity: 0 } : { opacity: 0, y: -8, height: 0 }}
          animate={reduced ? { opacity: 1 } : { opacity: 1, y: 0, height: "auto" }}
          exit={reduced ? { opacity: 0 } : { opacity: 0, y: -8, height: 0 }}
          transition={{ duration: 0.22, ease: EASE_OUT }}>
            {error}
          </motion.div>
        }
      </AnimatePresence>
    </div>);

}

function Spinner() {
  return (
    <span className="btn-spinner" aria-hidden="true">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
        <circle cx="12" cy="12" r="9" stroke="currentColor" strokeOpacity="0.25" strokeWidth="3" />
        <path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor" strokeWidth="3" strokeLinecap="round" />
      </svg>
    </span>);
}

// ---- Footer ----
function Footer({ lang, setLang }) {
  const t = COPY[lang].footer;
  return (
    <footer>
      <div className="wrap foot">
        <div className="small">{t.rights}</div>
        <div className="foot-nav">
          {t.links.map((l, i) => <a href="#" key={i}>{l}</a>)}
        </div>
        <LayoutGroup id="lang-foot">
          <div className="lang-toggle foot-lang">
            <FootLangButton on={lang === "fi"} onClick={() => setLang("fi")}>FI</FootLangButton>
            <FootLangButton on={lang === "en"} onClick={() => setLang("en")}>EN</FootLangButton>
          </div>
        </LayoutGroup>
      </div>
    </footer>);

}

function FootLangButton({ on, onClick, children }) {
  const reduced = useReducedMotion();
  return (
    <button className={on ? "on" : ""} onClick={onClick} style={{ position: "relative" }}>
      {on && !reduced &&
      <motion.span
        layoutId="lang-pill-foot"
        className="lang-pill"
        transition={{ type: "tween", duration: 0.28, ease: EASE_OUT }} />
      }
      <span style={{ position: "relative", zIndex: 1 }}>{children}</span>
    </button>);
}

// ---- Trust strip (toggle) ----
function TrustStrip({ lang }) {
  const items = lang === "fi" ? [
  { n: "20+ vuotta", l: "Tuotantokokemusta Virossa" },
  { n: "1500+", l: "Säiliötä Suomessa" },
  { n: "19 kokoa", l: "5 – 100 m³" },
  { n: "50 v.", l: "Käyttöikä maan alla" }] :
  [
  { n: "20+ years", l: "Manufacturing in Estonia" },
  { n: "1500+", l: "Tanks installed in Finland" },
  { n: "19 sizes", l: "5 – 100 m³" },
  { n: "50 yrs", l: "Underground service life" }];

  return (
    <div className="trust-strip">
      <div className="wrap">
        <div className="trust-inner">
          {items.map((it, i) =>
          <div className="item" key={i}>
              <div className="n">{it.n}</div>
              <div className="l">{it.l}</div>
            </div>
          )}
        </div>
      </div>
    </div>);
}

// ---- Tweaks panel ----
function AppTweaks({ tw, setTweak, lang }) {
  const L = lang === "fi";
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Theme" />
      {(() => {
        const PAL_NAMES = ["forest", "navy", "rust", "olive", "clay", "charcoal"];
        const PAL_SWATCHES = [
        ["#2F5D3A", "#1A1815", "#FAF8F3"],
        ["#1F3A6B", "#1A1815", "#FAF8F3"],
        ["#A8431F", "#1A1815", "#FAF8F3"],
        ["#5A6B2E", "#1A1815", "#FAF8F3"],
        ["#8A4E3B", "#1A1815", "#FAF8F3"],
        ["#1A1815", "#3A352E", "#FAF8F3"]];

        return (
          <TweakColor
            label="Palette"
            value={PAL_SWATCHES[PAL_NAMES.indexOf(tw.palette)] || PAL_SWATCHES[0]}
            options={PAL_SWATCHES}
            onChange={(v) => {
              const idx = PAL_SWATCHES.findIndex((p) => JSON.stringify(p) === JSON.stringify(v));
              if (idx >= 0) setTweak("palette", PAL_NAMES[idx]);
            }} />);


      })()}
      <TweakSelect
        label="Background"
        value={tw.bgTone}
        options={["bone", "paper", "clay", "stone", "mist"]}
        onChange={(v) => setTweak("bgTone", v)} />
      
      <TweakToggle label="Dark mode" value={tw.dark} onChange={(v) => setTweak("dark", v)} />

      <TweakSection label="Typography" />
      <TweakSelect
        label="Display font"
        value={tw.font}
        options={[
        { value: "inter-tight", label: "Inter Tight" },
        { value: "fraunces", label: "Fraunces (serif)" },
        { value: "grotesk", label: "Space Grotesk" },
        { value: "serif-mix", label: "Instrument Serif" },
        { value: "dm", label: "DM Sans" }]
        }
        onChange={(v) => setTweak("font", v)} />
      
      <TweakSlider
        label="Headline scale" min={0.7} max={1.4} step={0.05}
        value={tw.hSize} unit="×"
        onChange={(v) => setTweak("hSize", v)} />
      
      <TweakSlider
        label="Headline weight" min={300} max={700} step={100}
        value={tw.hWeight}
        onChange={(v) => setTweak("hWeight", v)} />
      

      <TweakSection label="Shape" />
      <TweakSlider
        label="Corner radius" min={0} max={28} step={2} unit="px"
        value={tw.radius}
        onChange={(v) => setTweak("radius", v)} />
      
      <TweakToggle
        label="Square buttons"
        value={tw.squareBtns}
        onChange={(v) => setTweak("squareBtns", v)} />
      
      <TweakRadio
        label="Density"
        value={tw.density}
        options={["compact", "regular", "spacious"]}
        onChange={(v) => setTweak("density", v)} />
      

      <TweakSection label="Layout" />
      <TweakSelect
        label="Hero layout"
        value={tw.heroLayout}
        options={[
        { value: "default", label: "Text left, config right" },
        { value: "rev", label: "Config left, text right" },
        { value: "50", label: "50 / 50 split" },
        { value: "stack", label: "Stacked (one column)" }]
        }
        onChange={(v) => setTweak("heroLayout", v)} />
      
      <TweakRadio
        label="Configurator"
        value={tw.configStyle}
        options={[
        { value: "elevated", label: "Card" },
        { value: "flat", label: "Flat" },
        { value: "outlined", label: "Out." },
        { value: "dark", label: "Dark" }]
        }
        onChange={(v) => setTweak("configStyle", v)} />
      
      <TweakRadio
        label="Size picker"
        value={tw.sizePicker}
        options={[
        { value: "chips", label: "Chips" },
        { value: "strip", label: "Strip" },
        { value: "slider", label: "Slider" }]
        }
        onChange={(v) => setTweak("sizePicker", v)} />
      

      <TweakSection label="Product" />
      <TweakSelect
        label="Tank tone"
        value={tw.tankTone}
        options={[
        { value: "lime", label: "Lime (default)" },
        { value: "forest", label: "Forest green" },
        { value: "steel", label: "Steel grey" },
        { value: "copper", label: "Copper" },
        { value: "charcoal", label: "Charcoal" },
        { value: "cream", label: "Cream" }]
        }
        onChange={(v) => setTweak("tankTone", v)} />
      

      <TweakSection label="Modules" />
      <TweakToggle label="Eyebrow tags" value={tw.showEyebrow} onChange={(v) => setTweak("showEyebrow", v)} />
      <TweakToggle label="Stats grid" value={tw.showStats} onChange={(v) => setTweak("showStats", v)} />
      <TweakToggle label="Finland map" value={tw.showMap} onChange={(v) => setTweak("showMap", v)} />
      <TweakToggle label="Trust strip" value={tw.showTrustStrip} onChange={(v) => setTweak("showTrustStrip", v)} />

      <TweakSection label="Presets" />
      <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
        <TweakButton secondary label="Editorial" onClick={() => setTweak({
          palette: "charcoal", bgTone: "paper", dark: false, font: "serif-mix",
          hSize: 1.2, hWeight: 400, radius: 4, squareBtns: true, density: "spacious",
          configStyle: "outlined", sizePicker: "slider", tankTone: "charcoal",
          showEyebrow: false, showTrustStrip: false
        })} />
        <TweakButton secondary label="Industrial" onClick={() => setTweak({
          palette: "forest", bgTone: "stone", dark: false, font: "grotesk",
          hSize: 0.95, hWeight: 600, radius: 6, squareBtns: true, density: "compact",
          configStyle: "flat", sizePicker: "strip", tankTone: "steel",
          showEyebrow: true, showTrustStrip: true
        })} />
        <TweakButton secondary label="Premium dark" onClick={() => setTweak({
          palette: "olive", bgTone: "bone", dark: true, font: "inter-tight",
          hSize: 1.05, hWeight: 500, radius: 20, squareBtns: false, density: "spacious",
          configStyle: "dark", sizePicker: "chips", tankTone: "lime",
          showEyebrow: true, showTrustStrip: true
        })} />
        <TweakButton secondary label="Reset" onClick={() => setTweak(TWEAK_DEFAULTS)} />
      </div>
    </TweaksPanel>);

}

// ---- App ----
function App() {
  const [lang, setLang] = useState("fi");
  const [size, setSize] = useState(10);
  const [tw, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const formRef = useRef(null);

  const scrollTo = useCallback((id) => {
    const el = document.getElementById(id);
    if (el) {
      const y = el.getBoundingClientRect().top + window.scrollY - 64;
      window.scrollTo({ top: y, behavior: "smooth" });
    }
  }, []);

  const scrollToForm = useCallback(() => scrollTo("tarjous"), [scrollTo]);

  // Apply body classes for tweaks
  useEffect(() => {
    const body = document.body;
    body.className = [
    `pal-${tw.palette}`,
    `bg-${tw.bgTone}`,
    tw.dark ? "dark" : "",
    `font-${tw.font}`,
    `density-${tw.density}`,
    `cfg-${tw.configStyle}`,
    `hero-${tw.heroLayout}`,
    tw.squareBtns ? "square-btns" : ""].
    filter(Boolean).join(" ");
  }, [tw]);

  // Apply CSS variables for sliders
  useEffect(() => {
    const r = document.documentElement.style;
    r.setProperty("--tw-h-scale", tw.hSize);
    r.setProperty("--tw-h-weight", tw.hWeight);
    r.setProperty("--tw-radius", tw.radius + "px");
    r.setProperty("--tw-radius-sm", Math.max(4, tw.radius * 0.55) + "px");
  }, [tw.hSize, tw.hWeight, tw.radius]);

  // Set document title/lang
  useEffect(() => {
    document.documentElement.lang = lang;
    document.title = lang === "fi" ?
    "Puhastid — Lasikuitusäiliöt Suomeen" :
    "Puhastid — Glassfiber tanks for Finland";
  }, [lang]);

  return (
    <React.Fragment>
      <Header lang={lang} setLang={setLang} scrollTo={scrollTo} />
      <main>
        <Hero lang={lang} size={size} setSize={setSize} scrollToForm={scrollToForm} tw={tw} />
        {tw.showTrustStrip && <TrustStrip lang={lang} />}
        <hr className="rule" />
        <Why lang={lang} tw={tw} />
        <Estonia lang={lang} tw={tw} />
        <Shipping lang={lang} tw={tw} />
        <Downloads lang={lang} tw={tw} />
        <InquiryForm lang={lang} size={size} setSize={setSize} formRef={formRef} />
      </main>
      <Footer lang={lang} setLang={setLang} />
      <AppTweaks tw={tw} setTweak={setTweak} lang={lang} />
    </React.Fragment>);

}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);