/* global React, Icon, ProductVisual, WPC80 */
const { useState, useEffect, useRef, useMemo } = React;

// ============ DATA (real production catalog) ============
// Sizes / flavors / variants come from window.WPC80 (built from
// data/wpc80-real.json by scripts/build-wpc80-data.mjs). Same shape as
// the previous hand-rolled D_SIZES / D_FLAVORS / D_VARIANTS so the rest of
// this file (cascading availability, discount countdown, restock CTA, etc.)
// is unchanged.
if (!window.WPC80) {
  throw new Error('WPC80 product data not loaded - include prototypes/wpc80-data.jsx before PDPDesktop.jsx');
}
const D_PRODUCT  = window.WPC80.product;
const D_SIZES    = window.WPC80.sizes;
const D_FLAVORS  = window.WPC80.flavors;
const D_VARIANTS = window.WPC80.variants;

// Mock gift picks for the giftblock thumbnail strip (real Latte:
// $activeGifts[$activeVariant->product_id] in _form.latte). Mirrors the
// 'Vybrali ste X z Y darčekov' summary row.
const D_GIFT_PICKS = [
  { id: 'g1', name: 'Shaker 700 ml',         icon: 'shaker' },
  { id: 'g2', name: 'Vzorka kreatínu 5 g',   icon: 'sample' },
];
const D_GIFT_PICKS_TOTAL = 3; // total gift slots available for this variant (mock)

// Quantity discount tiers (Latte: $productQuantityPrices)
const D_QTY_TIERS = [
  { min: 3,  max: 4,    perPack: 22.90 },
  { min: 5,  max: 9,    perPack: 21.90 },
  { min: 10, max: null, perPack: 20.90 },
];

// Helpers
const variantKey = (sId, fId) => sId + '_' + fId;
const getVariant = (sId, fId) => D_VARIANTS[variantKey(sId, fId)] || null;
const variantsForSize = (sId) => Object.entries(D_VARIANTS).filter(([k]) => k.startsWith(sId + '_'));
const variantsForFlavor = (fId) => Object.entries(D_VARIANTS).filter(([k]) => k.endsWith('_' + fId));
const countActiveForSize = (sId) => variantsForSize(sId).filter(([,v]) => v.stock !== 'out').length;
const hasGiftAnywhere = (sId) => variantsForSize(sId).some(([,v]) => v.gift);

// Gallery: slide 0 is wired to the active variant image (real CDN). Slides
// 1..N-1 stay as design placeholders for now until we wire alt photo /
// detail / scoop / video fixtures.
const D_GAL_SLIDES = [
  { kind: 'variant', label: 'WPC 80', sub: '', color: '#0077BC' },
  { kind: 'image', src: '../assets/img/generated/wpc80-lifestyle-gpt-image-2.png', label: 'SHAKE', sub: 'LIFESTYLE', color: '#F0F7FC' },
  // v0.7.4: portrait packshot 1122x1402 (0.8:1) does not fill the 1:1 stage,
  // leaving ~10% white gutters left/right when the canvas is white. Setting
  // bg to --bg-alt (#F4F4F4) matches the photo's own srgb(243,243,243) studio
  // backdrop sampled from its corners so the gutter blends invisibly. Other
  // image slides are 2048x2048 squares - they fill the canvas and need no bg.
  { kind: 'image', src: '../assets/img/generated/wpc80-lifestyle-03.png', label: 'WPC 80', sub: 'DETAIL', color: '#F0F7FC', bg: 'var(--bg-alt)' },
  { kind: 'image', src: '../assets/img/generated/wpc80-powder-detail-gpt-image-2.png', label: 'POWDER', sub: 'DETAIL', color: '#F0F7FC' },
  // v0.7.9 #4: legacy 'tub-lg' dummy SVG slides (BACK / DETAIL INFO /
  // SCOOP 30G) dropped per user feedback 'dummy produktove fotky, tieto
  // svg.. nechcem'. Only the video placeholder slide remains so the
  // video CTA chip in the gallery still has a slot to point at; the
  // ProductVisual fallback in the render branch stays as a defensive
  // path but no D_GAL_SLIDES row triggers it any more.
  { kind: 'tub-lg',  label: 'VIDEO',  sub: 'REVIEW', color: '#F96628', video: true },
];

const D_MAIN_IMAGE = '../assets/img/products/wpc-80-main.jpg';
const productImage = () => D_MAIN_IMAGE || D_PRODUCT.mainImage;
const galleryImage = (slide) => slide?.kind === 'image' ? slide.src : productImage();

// v0.7.7 C-phase: cross-sell + recently-viewed cards now feed off REAL
// namaximum.sk DB rows shipped via prototypes/cross-sell-data.jsx
// (window.CROSSSELL.products + window.RECENTLY_VIEWED.products). The
// adapter normalises DB shape (minPrice / ratingsCount / image) to the
// shape these cards already expected (price / reviews / image).
function adaptCrossSellRow(r) {
  return {
    id: r.id,
    name: r.name,
    slug: r.slug ? ('/' + r.slug.replace(/^\//, '')) : '#',
    image: r.image || null,
    price: r.minPrice,
    orig: null,
    rating: r.rating,
    reviews: r.ratingsCount,
    flag: null,
    // ProductVisual fallback (only used when image is missing):
    packColor: '#0077BC', packLabel: 'WPC', packSub: '', visual: 'tub',
  };
}
const D_CROSS = (typeof window !== 'undefined' && window.CROSSSELL?.products ? window.CROSSSELL.products : []).map(adaptCrossSellRow);

// Per-review fields:
//  - customerType: 'registered' (real Latte: customer_id != null) | 'guest'
//    Registered shows BOTH 'Overený zákazník' + 'Overený nákup' badges,
//    guest shows 'Neregistrovaný zákazník' + 'Overený nákup'.
//  - lang: ISO-2 review language (used by language filter dropdown).
//  - reply: optional { text, date } block from the NaMaximum team.
const D_REVIEWS = [
  { id: 1, name: 'Martin K.', initial: 'M', rating: 5, verified: true, customerType: 'registered', lang: 'sk', date: '18. 4. 2026', title: 'Výborná chuť, super rozpustnosť', body: 'Používam už tretie balenie. Mieša sa bez hrudiek aj v shakeri, chuť čokolády nie je prisladená. Certifikát som si overil na stránke - sedí.', size: '1 kg', flavor: 'Čokoláda', tags: ['chuť', 'rozpustnosť'], helpful: 24, reply: { text: 'Ďakujeme za skvelú spätnú väzbu, Martin! Tešíme sa, že vám WPC 80 chutí. Tím NaMaximum', date: '20. 4. 2026' } },
  { id: 2, name: 'Janka P.', initial: 'J', rating: 5, verified: true, customerType: 'registered', lang: 'sk', date: '10. 4. 2026', title: 'Cena/kvalita top', body: 'Skúšala som rôzne značky, za túto cenu je to najlepšie WPC. Vanilka nie je umelá, ani nenadúva. Odporúčam.', size: '2 kg', flavor: 'Vanilka', tags: ['cena', 'trávenie'], helpful: 18 },
  { id: 3, name: 'Peter B.', initial: 'P', rating: 4, verified: true, customerType: 'guest', lang: 'cz', date: '5. 4. 2026', title: 'Dobré, ale jahoda trochu sladká', body: 'Kvalita proteínu super, rozpustnosť výborná. Jahodovou příchuť bych pro sebe dal o něco méně sladkou, ale to je subjektivní.', size: '1 kg', flavor: 'Jahoda', tags: ['chuť'], helpful: 9, reply: { text: 'Ďakujeme za upozornenie. Skontrolujeme aktuálne výrobné šarže a v prípade potreby upravíme proces. Tím NaMaximum', date: '8. 4. 2026' } },
  { id: 4, name: 'Tomáš V.', initial: 'T', rating: 3, verified: true, customerType: 'guest', lang: 'sk', date: '2. 4. 2026', title: 'OK proteinprice ratio', body: 'Normálny WPC, nič výnimočné, ale za túto cenu nemám čo vyčítať. Banoffee je v poriadku.', size: '1 kg', flavor: 'Banoffee', tags: ['cena'], helpful: 4 },
  { id: 5, name: 'Eszter N.', initial: 'E', rating: 5, verified: true, customerType: 'registered', lang: 'hu', date: '28. 3. 2026', title: 'Kiváló oldhatóság', body: 'Egy hete használom, csomómentesen oldódik, a Vanilla & Mango íz természetes. Ajánlom!', size: '2 kg', flavor: 'Vanilla & Mango', tags: ['oldhatóság', 'íz'], helpful: 11 },
  { id: 6, name: 'Lukas H.', initial: 'L', rating: 4, verified: true, customerType: 'guest', lang: 'de', date: '24. 3. 2026', title: 'Gutes Preis-Leistungs-Verhältnis', body: 'Sehr gut löslich, der Schokoladengeschmack ist nicht zu süß. Gute Qualität für den Preis.', size: '1 kg', flavor: 'Chocolate', tags: ['chuť'], helpful: 7 },
];

// Featured "bestRating" review - mirrors {ifset $bestRating} block in real
// _reviews.latte. Pinned above the review list as a top-comment block.
const D_REV_BEST = {
  rating: 5,
  title: 'Najlepší proteín za rozumnú cenu',
  body: 'Beriem už 3 roky, kvalita konštantná, rozpustnosť výborná. Banana je TOP príchuť, deti milujú. Odporúčam!',
  author: 'Martin K.',
  date: '12. mar 2024',
  verified: true,
  helpful: 42,
  variant: '1 kg / Banana',
};

// Recently viewed products - mirrors visitorProducts list in real default.latte
// (renders only when $visitorProductsCount > 0). v0.7.7 C-phase: backed
// by window.RECENTLY_VIEWED.products (real top-8 sellers from OUTSIDE
// the WPC 80 default category, so the carousel feels like cross-category
// browsing, not 'more of the same').
const D_RECENT_VIEWED = (typeof window !== 'undefined' && window.RECENTLY_VIEWED?.products ? window.RECENTLY_VIEWED.products : []).map(adaptCrossSellRow);

const D_FAQ_REGISTER_INDEXES = [0, 1, 2, 3, 4];

const D_REV_FILTERS = [
  { id: 'all', label: 'Všetky', n: 1342 },
  { id: 'verified', label: 'Overené', n: 1198 },
  { id: '5', label: '★ 5', n: 1054 },
  { id: '4', label: '★ 4', n: 212 },
  { id: '3', label: '★ 3', n: 48 },
  { id: '2', label: '★ 2', n: 18 },
  { id: '1', label: '★ 1', n: 10 },
  { id: 'chuť', label: 'chuť', n: 412 },
  { id: 'rozpustnosť', label: 'rozpustnosť', n: 287 },
  { id: 'cena', label: 'cena', n: 198 },
];

const D_REV_DIST = [
  { s: 5, pct: 79, n: 1054 },
  { s: 4, pct: 16, n: 212 },
  { s: 3, pct: 3, n: 48 },
  { s: 2, pct: 1, n: 18 },
  { s: 1, pct: 1, n: 10 },
];

// Recommended-by-customer % - mirrors $recommendedByCustomer in _reviews.latte.
// Computed as (★★★★ + ★★★★★) / total ratings.
const D_REV_RECOMMEND_PCT = (() => {
  const total = D_REV_DIST.reduce((a, b) => a + b.n, 0);
  const positive = D_REV_DIST.filter(r => r.s >= 4).reduce((a, b) => a + b.n, 0);
  return total > 0 ? Math.round((positive / total) * 1000) / 10 : 0;
})();

const D_FREE_SHIPPING = 59;

// Top-level categories for desktop nav (mirrors live namaximum.sk header 1:1).
const D_CATEGORIES_SK = [
  { id: 'doplnky',  label: 'Doplnky výživy',          href: '/najpredavanejsie/' },
  { id: 'potraviny',label: 'Zdravé potraviny',         href: '/zdrave-potraviny/' },
  { id: 'oblec',    label: 'Oblečenie a príslušenstvo', href: '/oblecenie-a-prislusenstvo/' },
  { id: 'domac',    label: 'Domácnosť a drogéria',      href: '/domacnost-a-drogeria/' },
  { id: 'ciele',    label: 'Tvoje ciele',              href: '/products/goals' },
  { id: 'akcie',    label: 'Akcie!',                   href: '/akcia/', accent: true },
  { id: 'novinky',  label: 'Novinky',                  href: '/novinka/' },
];
const D_CATEGORIES_HU = [
  { id: 'doplnky',  label: 'Étrend-kiegészítők',     href: '/najpredavanejsie/' },
  { id: 'potraviny',label: 'Egészséges élelmiszerek',  href: '/zdrave-potraviny/' },
  { id: 'oblec',    label: 'Ruházat és kiegészítők',  href: '/oblecenie-a-prislusenstvo/' },
  { id: 'domac',    label: 'Otthon és háztartás',      href: '/domacnost-a-drogeria/' },
  { id: 'ciele',    label: 'Céljaid',                  href: '/products/goals' },
  { id: 'akcie',    label: 'Akciók!',                   href: '/akcia/', accent: true },
  { id: 'novinky',  label: 'Újdonságok',                href: '/novinka/' },
];

// Stars helper (same pattern as mobile)
const DStars = ({ n = 5, size = 14 }) => {
  const full = Math.floor(n);
  const half = n - full >= 0.5;
  return (
    <span style={{ fontSize: size, letterSpacing: 1, color: '#F9C80E', whiteSpace: 'nowrap' }}>
      {'★'.repeat(full)}{half ? '⯨' : ''}{'☆'.repeat(5 - full - (half ? 1 : 0))}
    </span>
  );
};

// ========== DISCOUNT COUNTDOWN (mirrors Latte header-counter snippet) ==========
function DCountdown({ deadline, lang }) {
  const [now, setNow] = useState(() => Date.now());
  useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(id);
  }, []);
  const diff = Math.max(0, deadline.getTime() - now);
  if (diff <= 0) return null;
  const totalH = Math.floor(diff / 3600000);
  if (totalH >= 26) {
    const days = Math.ceil(totalH / 24);
    return (
      <div className="pdp-d-countdown is-soft">
        <span className="ic"><Icon name="clock" size={14} stroke={2} /></span>
        <span>{lang === 'hu' ? ('Még ' + days + ' nap') : ('Zostáva ešte ' + days + ' dní')}</span>
      </div>
    );
  }
  const h = String(totalH).padStart(2, '0');
  const m = String(Math.floor((diff % 3600000) / 60000)).padStart(2, '0');
  const s = String(Math.floor((diff % 60000) / 1000)).padStart(2, '0');
  return (
    <div className="pdp-d-countdown">
      <span className="ic"><Icon name="clock" size={14} stroke={2} /></span>
      <span className="lbl">{lang === 'hu' ? 'Akció végéig' : 'Do konca akcie'}</span>
      <span className="time"><b>{h}</b>:<b>{m}</b>:<b>{s}</b></span>
    </div>
  );
}

// ========== PER-VARIANT STOCK CHIP (small dot indicator on pills) ==========
function DStockChip({ stock, restockDays, lang }) {
  const titles = lang === 'hu'
    ? { in: 'Raktáron', low: 'Utolsó darabok', restock: (restockDays || 0) + ' nap múlva', out: 'Elfogyott' }
    : { in: 'Skladom',  low: 'Posledné kusy',  restock: 'O ' + (restockDays || 0) + ' dní',  out: 'Vypredané' };
  if (stock === 'in')      return <span className="pdp-d-stkchip is-in"   title={titles.in} />;
  if (stock === 'low')     return <span className="pdp-d-stkchip is-low"  title={titles.low} />;
  if (stock === 'restock') return <span className="pdp-d-stkchip is-restk" title={titles.restock} />;
  return <span className="pdp-d-stkchip is-out" title={titles.out} />;
}

// ============ FEATURED REVIEW (bestRating top-comment) ============
// Mirrors {ifset $bestRating} block in real _reviews.latte: a single pinned
// review rendered above the review controls/list. Read-only visual; no
// interaction wired (helpful counter is decorative).
function DRevFeatured({ t, review, lang }) {
  if (!review) return null;
  return (
    <div className="pdp-d-rev-featured" role="complementary" aria-label={t.rev_best_label}>
      <span className="pdp-d-rev-featured-mark" aria-hidden>★</span>
      <div className="pdp-d-rev-featured-body">
        <div className="pdp-d-rev-featured-label">{t.rev_best_label}</div>
        <div className="pdp-d-rev-featured-stars"><DStars n={review.rating} size={16} /></div>
        <h4 className="pdp-d-rev-featured-title">{review.title}</h4>
        <p className="pdp-d-rev-featured-text">{review.body}</p>
        <div className="pdp-d-rev-featured-meta">
          <span className="who">{review.author}</span>
          {review.verified && (
            <span className="verified">
              <Icon name="checkCircle" size={11} stroke={2.5} />
              {t.rev_verified}
            </span>
          )}
          <span className="sep" aria-hidden>·</span>
          <span className="variant">{review.variant}</span>
          <span className="sep" aria-hidden>·</span>
          <span className="date">{review.date}</span>
        </div>
        <div className="pdp-d-rev-featured-helpful">
          <span className="plus">+1</span>
          <span className="l">{t.rev_best_helpful}</span>
          <span className="n">{review.helpful}</span>
        </div>
      </div>
    </div>
  );
}

// ============ RECENTLY VIEWED CAROUSEL ============
// Mirrors {if $visitorProductsCount > 0} block in real default.latte. Renders
// a row of compact product cards (~25% smaller than cross-sell) before the
// footer. UI only - no add-to-cart wiring, just a link out to the PDP.
function DRecentViewed({ items, t, toEur, lang }) {
  if (!items || items.length === 0) return null;
  return (
    <section className="pdp-d-section pdp-d-recent-section">
      <div className="pdp-d-container">
        <div className="pdp-d-section-hd">
          <h2 className="pdp-d-section-title">{t.recent_viewed_title}</h2>
          <span className="pdp-d-section-sub">{t.recent_viewed_sub}</span>
        </div>
        <div className="pdp-d-recent-grid">
          {items.map(p => (
            <a key={p.id} href={p.slug || '#'} className="pdp-d-recent-card">
              <div className="pdp-d-recent-img">
                {/* v0.7.7 C-phase: real photo when DB row carries one. */}
                {p.image
                  ? <img src={p.image} alt={p.name} loading="lazy" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} />
                  : <ProductVisual kind={p.visual} color={p.packColor} label={p.packLabel} sub={p.packSub} />
                }
              </div>
              <div className="pdp-d-recent-nm">{p.name}</div>
              <div className="pdp-d-recent-rt">
                <span className="st" aria-hidden>★</span>
                <span className="r">{p.rating.toLocaleString(lang === 'hu' ? 'hu-HU' : 'sk-SK', { minimumFractionDigits: 1 })}</span>
                <span className="c">({p.reviews})</span>
              </div>
              <div className="pdp-d-recent-pr">
                <span className="now">{toEur(p.price)}</span>
                {p.orig && <span className="orig">{toEur(p.orig)}</span>}
              </div>
            </a>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============ AI REVIEW SUMMARY (desktop) ============
function DAiReviewSummary({ t, variant, onTopicClick, showBeta = true }) {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const to = setTimeout(() => setLoading(false), 950);
    return () => clearTimeout(to);
  }, []);

  const sentiment = { pos: 83, neu: 12, neg: 5 };

  return (
    <div className={"pdp-d-ai" + (loading ? ' loading' : '') + (variant === 'minimal' ? ' variant-minimal' : '')}>
      <div className="pdp-d-ai-inner">
        <div className="pdp-d-ai-hd">
          <span className="pdp-d-ai-spark" aria-hidden="true">
            <svg viewBox="0 0 24 24" fill="none">
              <defs>
                <linearGradient id="d-ai-spark-g" x1="0" y1="0" x2="24" y2="24" gradientUnits="userSpaceOnUse">
                  <stop offset="0%" stopColor="#8A7AFE"/>
                  <stop offset="50%" stopColor="#0077BC"/>
                  <stop offset="100%" stopColor="#26BB59"/>
                </linearGradient>
              </defs>
              <path d="M12 2l1.8 5.4a4 4 0 0 0 2.8 2.8L22 12l-5.4 1.8a4 4 0 0 0-2.8 2.8L12 22l-1.8-5.4a4 4 0 0 0-2.8-2.8L2 12l5.4-1.8a4 4 0 0 0 2.8-2.8L12 2z" fill="url(#d-ai-spark-g)"/>
              <circle cx="19" cy="5" r="1.2" fill="#8A7AFE"/>
              <circle cx="5" cy="19" r="1" fill="#26BB59"/>
            </svg>
          </span>
          <span className="pdp-d-ai-badge">{t.ai_badge}</span>
          {showBeta && <span className="pdp-d-ai-beta">BETA</span>}
        </div>

        <div className="pdp-d-ai-title">{loading ? t.ai_thinking : t.ai_title}</div>
        <div className="pdp-d-ai-tldr">{t.ai_tldr}</div>

        <div className="pdp-d-ai-body">
          <div className="pdp-d-ai-col pros">
            <div className="pdp-d-ai-col-hd">
              <span className="dot-ic">+</span>
              {t.ai_pros_title}
            </div>
            <ul className="pdp-d-ai-list">
              {t.ai_pros.map(([h, sub], i) => (
                <li key={i}><span><strong>{h}</strong><small>{sub}</small></span></li>
              ))}
            </ul>
          </div>

          <div className="pdp-d-ai-col cons">
            <div className="pdp-d-ai-col-hd">
              <span className="dot-ic">!</span>
              {t.ai_cons_title}
            </div>
            <ul className="pdp-d-ai-list">
              {t.ai_cons.map(([h, sub], i) => (
                <li key={i}><span><strong>{h}</strong><small>{sub}</small></span></li>
              ))}
            </ul>
          </div>

          <div className="pdp-d-ai-col topics">
            <div className="pdp-d-ai-col-hd">
              <span className="dot-ic">#</span>
              {t.ai_topics_title}
            </div>
            <div className="pdp-d-ai-chips">
              {t.ai_topics.map((tp, i) => (
                <button key={i} className="pdp-d-ai-chip" onClick={() => onTopicClick && onTopicClick(tp.k)}>
                  {/* v0.7.5 A2: dropped '#' prefix on review-topic pills as
                      well so the topic strip and per-review tags both render
                      as clean keyword pills, matching the live eshop. */}
                  {tp.k}<span className="n">{tp.n}</span>
                </button>
              ))}
            </div>
            <div className="pdp-d-ai-sent">
              <div className="pdp-d-ai-sent-bar" aria-label={t.ai_sentiment_title}>
                <span className="pos" style={{ width: sentiment.pos + '%' }} />
                <span className="neu" style={{ width: sentiment.neu + '%' }} />
                <span className="neg" style={{ width: sentiment.neg + '%' }} />
              </div>
              <div className="pdp-d-ai-sent-legend">
                <span><span className="dot" style={{ background: '#26BB59' }} />{t.ai_sent_pos}<b>{sentiment.pos}%</b></span>
                <span><span className="dot" style={{ background: '#C9CDD6' }} />{t.ai_sent_neu}<b>{sentiment.neu}%</b></span>
                <span><span className="dot" style={{ background: '#E6452B' }} />{t.ai_sent_neg}<b>{sentiment.neg}%</b></span>
              </div>
            </div>
          </div>
        </div>

        <div className="pdp-d-ai-ft">
          <div className="pdp-d-ai-meta">{t.ai_meta(1342, t.ai_meta_date)}</div>
        </div>
        <div className="pdp-d-ai-disc">{t.ai_disclaimer}</div>
      </div>
    </div>
  );
}

// ============ TWEAK DEFAULTS + STORAGE ============
// All 28 tweak keys with their default values. Used by:
//  - reset button in <DTweakPanel>
//  - merging fallback for partial localStorage / window.__TWEAKS payloads
// F2 (v0.8.1): default-flip wave - prototype now boots in real-style
// state matching namaximum.sk WPC 80 PDP (live DOM probe 2026-05-05).
// All 17 'innovation' tweaks (group1) flip to false. All 3 'edge case'
// tweaks (group2) flip to false. sticky_tabs flips to false (real PDP
// has no sticky tabs nor sticky buy panel). bundle_promo +
// recently_viewed flip to false. UX-and-real tweaks stay ON because
// the real eshop ships them (discount_timer / gallery_flags /
// cross_sell / ship_opts / toasts).
//
// Per-category breakdown of changes vs v0.8.0:
//   group1 (17 flips): ai_summary, ai_beta_badge, savings_line,
//     social_proof, trust_strip, evidence_line, valueprops_strip,
//     alt_names, price_per_kg, qa_sort, qa_stats, review_topics,
//     review_reply_cta, sticky_tabs, bundle_promo, recently_viewed,
//     (promo_bar already false). ai_variant is a segment, untouched.
//   group2 (3 flips): qty_tiers, gift_bonus to false. expiration_warn
//     was already false.
//   demo:    no changes.
//   ux_real: no changes.
const D_TWEAK_DEFAULTS = {
  // Demo & state
  stock: 'in',
  discount: true,
  lang: 'sk',
  product_state: 'A',
  // AI features (group1) - real eshop has no AI summary / variant / badge
  ai_summary: false,
  ai_variant: 'classic',
  ai_beta_badge: false,
  // Urgency & gamification - real has discount_timer (qty_tiers / gift_bonus
  // are edge case states the customer rarely sees)
  discount_timer: true,
  expiration_warn: false,
  qty_tiers: false,
  gift_bonus: false,
  savings_line: false,
  social_proof: false,
  // Trust & content - real has gallery_flags (10 flag SVGs); the rest are
  // group1 features the eshop does not ship
  trust_strip: false,
  evidence_line: false,
  gallery_flags: true,
  valueprops_strip: false,
  alt_names: false,
  price_per_kg: false,
  // Q&A & reviews (all group1 - real PDP has plain product_questions /
  // product_reviews modules without sort, stats, topics, reply CTA)
  qa_sort: false,
  qa_stats: false,
  review_topics: false,
  review_reply_cta: false,
  // Layout & UX - real has cross_sell (single sibling link), ship_opts
  // (free-shipping progress + delivery ETA), toasts. promo_bar /
  // sticky_tabs are group1 features the eshop does not ship.
  promo_bar: false,
  sticky_tabs: false,
  cross_sell: true,
  ship_opts: true,
  toasts: true,
  // bundle_promo + recently_viewed: group1 features (real has neither on
  // PDP). F1 surfaced them in the panel; F2 flips both off so the
  // prototype ships clean and users opt in via the tweak panel.
  bundle_promo: false,
  recently_viewed: false,
  // G1 (v0.9.0): flavor selector variant. Default 'dropdown' matches the
  // real namaximum.sk parameter-box-with-select pattern (with our UX
  // upgrades: search/filter, keyboard nav, per-row badges, available
  // count). 'pills' preserves the previous default as alternative
  // design that fans out all 23 flavors at once.
  flavor_picker_variant: 'dropdown',
};
// Storage key bumped v1 -> v2 (simple migration: every user gets fresh
// real-style defaults on first reload after this build, old payload is
// garbage-collected on read).
const D_TWEAK_STORAGE_KEY = 'pdp-tweaks-v2';
const D_LEGACY_STORAGE_KEYS = ['pdp-tweaks-v1'];

function readStoredTweaks() {
  try {
    if (typeof localStorage === 'undefined') return {};
    // GC any older storage payloads from previous default sets so the
    // panel does not silently merge stale flags into a real-style boot.
    D_LEGACY_STORAGE_KEYS.forEach((k) => {
      try { localStorage.removeItem(k); } catch (_) {}
    });
    const raw = localStorage.getItem(D_TWEAK_STORAGE_KEY);
    return raw ? (JSON.parse(raw) || {}) : {};
  } catch (_) { return {}; }
}

// ============ FLOATING TWEAK PANEL ============
// Bottom-right floating action button + slide-in panel that exposes all 28
// tweak keys (12 legacy + 16 D2 wave). State lives in <DesktopPDP>; this
// component just renders the surface and bubbles changes via `onChange(k, v)`.
//
// Keyboard shortcuts: 't' toggles, 'Escape' closes (both ignored when typing
// in inputs/textareas/selects/contentEditable).
function DTweakPanel({ tweaks, onChange, onReset, t }) {
  const [open, setOpen] = useState(false);
  // Per-category collapse state. All open by default; clicking the category
  // header collapses it inside the panel.
  const [collapsed, setCollapsed] = useState({});
  const toggleCat = (id) => setCollapsed(s => ({ ...s, [id]: !s[id] }));

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'Escape' && open) { setOpen(false); return; }
      if (e.key !== 't' && e.key !== 'T') return;
      if (e.metaKey || e.ctrlKey || e.altKey) return;
      const target = e.target;
      const tag = (target && target.tagName) || '';
      if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || (target && target.isContentEditable)) return;
      e.preventDefault();
      setOpen(o => !o);
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [open]);

  // Renders one boolean toggle row.
  const renderSwitch = (k, label, desc) => (
    <label key={k} className="pdp-d-tweak-toggle">
      <span className="pdp-d-tweak-toggle-l">
        <span className="nm">{label}</span>
        {desc && <span className="ds">{desc}</span>}
      </span>
      <span className={"pdp-d-tweak-switch" + (tweaks[k] ? ' is-on' : '')}>
        <input
          type="checkbox"
          checked={!!tweaks[k]}
          onChange={(e) => onChange(k, e.target.checked)}
          aria-label={label}
        />
        <span className="thumb" aria-hidden />
      </span>
    </label>
  );

  // Renders one enum row as a segmented control.
  const renderSegment = (k, label, options) => (
    <div key={k} className="pdp-d-tweak-toggle is-segment">
      <span className="pdp-d-tweak-toggle-l">
        <span className="nm">{label}</span>
      </span>
      <div className="pdp-d-tweak-segment" role="group" aria-label={label}>
        {options.map(o => (
          <button
            key={o.v}
            type="button"
            className={tweaks[k] === o.v ? 'is-on' : ''}
            onClick={() => onChange(k, o.v)}
            aria-pressed={tweaks[k] === o.v}
          >{o.l}</button>
        ))}
      </div>
    </div>
  );

  // F1 (v0.8.0): consolidated 6 categories into 4 user-facing sections.
  // Mapping comes from docs/PHASING-PLAN.md F1 final mapping.
  //  - 'demo'    : test scenarios (lang / stock / state / discount toggle)
  //  - 'group1'  : novel features beyond real eshop (default OFF after F2)
  //  - 'group2'  : edge case states normal customer rarely sees (default OFF)
  //  - 'ux_real' : real eshop has these (default ON, demo can flip OFF)
  // Each category carries `bool: [keys]` so the bulk-toggle helper knows
  // which boolean tweaks to flip on "Všetko zapnúť / Všetko vypnúť".
  // Ai variant + lang + stock + product_state are segments and excluded.
  const categories = [
    {
      id: 'demo',
      title: t.tweak_cat_demo,
      desc:  t.tweak_cat_demo_desc,
      bool:  ['discount'],
      render: () => [
        renderSegment('lang', t.tweak_lang_label, [
          { v: 'sk', l: 'SK' }, { v: 'hu', l: 'HU' },
        ]),
        renderSegment('stock', t.tweak_stock_label, [
          { v: 'in',  l: t.tweak_stock_in },
          { v: 'low', l: t.tweak_stock_low },
          { v: 'out', l: t.tweak_stock_out },
        ]),
        renderSwitch('discount', t.tweak_discount_label, t.tweak_discount_desc),
        renderSegment('product_state', t.tweak_product_state_label, [
          { v: 'A', l: t.tweak_product_state_a },
          { v: 'P', l: t.tweak_product_state_p },
        ]),
      ],
    },
    {
      id: 'group1',
      title: t.tweak_cat_group1,
      desc:  t.tweak_cat_group1_desc,
      bool: [
        'ai_summary', 'ai_beta_badge',
        'savings_line', 'social_proof',
        'trust_strip', 'evidence_line', 'valueprops_strip',
        'alt_names', 'price_per_kg',
        'qa_sort', 'qa_stats', 'review_topics', 'review_reply_cta',
        'promo_bar', 'sticky_tabs',
        'bundle_promo', 'recently_viewed',
      ],
      render: () => [
        renderSwitch('ai_summary',       t.tweak_ai_summary_label,       t.tweak_ai_summary_desc),
        renderSegment('ai_variant', t.tweak_ai_variant_label, [
          { v: 'classic', l: t.tweak_ai_variant_classic },
          { v: 'minimal', l: t.tweak_ai_variant_minimal },
        ]),
        renderSwitch('ai_beta_badge',    t.tweak_ai_beta_badge_label,    t.tweak_ai_beta_badge_desc),
        renderSwitch('savings_line',     t.tweak_savings_line_label,     t.tweak_savings_line_desc),
        renderSwitch('social_proof',     t.tweak_social_proof_label,     t.tweak_social_proof_desc),
        renderSwitch('trust_strip',      t.tweak_trust_strip_label,      t.tweak_trust_strip_desc),
        renderSwitch('evidence_line',    t.tweak_evidence_line_label,    t.tweak_evidence_line_desc),
        renderSwitch('valueprops_strip', t.tweak_valueprops_strip_label, t.tweak_valueprops_strip_desc),
        renderSwitch('alt_names',        t.tweak_alt_names_label,        t.tweak_alt_names_desc),
        renderSwitch('price_per_kg',     t.tweak_price_per_kg_label,     t.tweak_price_per_kg_desc),
        renderSwitch('qa_sort',          t.tweak_qa_sort_label,          t.tweak_qa_sort_desc),
        renderSwitch('qa_stats',         t.tweak_qa_stats_label,         t.tweak_qa_stats_desc),
        renderSwitch('review_topics',    t.tweak_review_topics_label,    t.tweak_review_topics_desc),
        renderSwitch('review_reply_cta', t.tweak_review_reply_cta_label, t.tweak_review_reply_cta_desc),
        renderSwitch('promo_bar',        t.tweak_promo_bar_label,        t.tweak_promo_bar_desc),
        renderSwitch('sticky_tabs',      t.tweak_sticky_tabs_label,      t.tweak_sticky_tabs_desc),
        renderSwitch('bundle_promo',     t.tweak_bundle_promo_label,     t.tweak_bundle_promo_desc),
        renderSwitch('recently_viewed',  t.tweak_recently_viewed_label,  t.tweak_recently_viewed_desc),
      ],
    },
    {
      id: 'group2',
      title: t.tweak_cat_group2,
      desc:  t.tweak_cat_group2_desc,
      bool:  ['expiration_warn', 'qty_tiers', 'gift_bonus'],
      render: () => [
        renderSwitch('expiration_warn', t.tweak_expiration_warn_label, t.tweak_expiration_warn_desc),
        renderSwitch('qty_tiers',       t.tweak_qty_tiers_label,       t.tweak_qty_tiers_desc),
        renderSwitch('gift_bonus',      t.tweak_gift_bonus_label,      t.tweak_gift_bonus_desc),
      ],
    },
    {
      id: 'ux_real',
      title: t.tweak_cat_ux_real,
      desc:  t.tweak_cat_ux_real_desc,
      bool:  ['discount_timer', 'gallery_flags', 'cross_sell', 'ship_opts', 'toasts'],
      render: () => [
        renderSegment('flavor_picker_variant', t.tweak_flavor_picker_label, [
          { v: 'dropdown', l: t.tweak_flavor_picker_dropdown },
          { v: 'pills',    l: t.tweak_flavor_picker_pills },
        ]),
        renderSwitch('discount_timer', t.tweak_discount_timer_label, t.tweak_discount_timer_desc),
        renderSwitch('gallery_flags',  t.tweak_gallery_flags_label,  t.tweak_gallery_flags_desc),
        renderSwitch('cross_sell',     t.tweak_cross_sell_label,     t.tweak_cross_sell_desc),
        renderSwitch('ship_opts',      t.tweak_ship_opts_label,      t.tweak_ship_opts_desc),
        renderSwitch('toasts',         t.tweak_toasts_label,         t.tweak_toasts_desc),
      ],
    },
  ];

  // Bulk toggle: flip all boolean keys in a category to ON or OFF in one
  // call. Skips segments (lang / stock / product_state / ai_variant) since
  // they have no obvious 'on' state. Uses cat.bool list defined above.
  const bulkToggle = (cat, value) => {
    (cat.bool || []).forEach(k => onChange(k, value));
  };

  return (
    <>
      <button
        type="button"
        className={"pdp-d-tweak-fab" + (open ? ' is-open' : '')}
        onClick={() => setOpen(o => !o)}
        aria-label={(t.tweak_panel_title || 'Tweaks') + ' (T)'}
        aria-expanded={open}
        title={(t.tweak_panel_title || 'Tweaks') + ' (T)'}
      >
        <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <circle cx="12" cy="12" r="3" />
          <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.16.39.4.74.71 1a1.65 1.65 0 0 0 .9.27H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
        </svg>
      </button>
      <aside
        className={"pdp-d-tweak-panel" + (open ? ' is-open' : '')}
        role="dialog"
        aria-label={t.tweak_panel_title || 'Tweaks'}
        aria-hidden={!open}
      >
        <header className="pdp-d-tweak-panel-hd">
          <h3 className="pdp-d-tweak-panel-title">{t.tweak_panel_title}</h3>
          <button
            type="button"
            className="pdp-d-tweak-panel-reset"
            onClick={onReset}
          >{t.tweak_panel_reset}</button>
          <button
            type="button"
            className="pdp-d-tweak-panel-close"
            onClick={() => setOpen(false)}
            aria-label={t.tweak_panel_close}
            title={t.tweak_panel_close}
          >
            <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <line x1="6" y1="6" x2="18" y2="18" />
              <line x1="18" y1="6" x2="6" y2="18" />
            </svg>
          </button>
        </header>
        <div className="pdp-d-tweak-panel-body">
          {categories.map(cat => (
            <section
              key={cat.id}
              className={"pdp-d-tweak-cat" + (collapsed[cat.id] ? ' is-collapsed' : '')}
            >
              <button
                type="button"
                className="pdp-d-tweak-cat-h"
                onClick={() => toggleCat(cat.id)}
                aria-expanded={!collapsed[cat.id]}
              >
                <span>{cat.title}</span>
                <span className="chev" aria-hidden>
                  <svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <polyline points="6 9 12 15 18 9" />
                  </svg>
                </span>
              </button>
              {!collapsed[cat.id] && (
                <div className="pdp-d-tweak-cat-list">
                  {/* F1 (v0.8.0): krátky popis kategórie + bulk toggle linky
                      pre kategórie ktoré majú 2+ boolean tweakov. demo
                      kategória má len 1 boolean (discount) takže bulk
                      neukazujeme. */}
                  {(cat.desc || (cat.bool && cat.bool.length >= 2)) && (
                    <div className="pdp-d-tweak-cat-meta">
                      {cat.desc && <p className="pdp-d-tweak-cat-desc">{cat.desc}</p>}
                      {cat.bool && cat.bool.length >= 2 && (
                        <div className="pdp-d-tweak-cat-bulk">
                          <button type="button" onClick={() => bulkToggle(cat, true)}>{t.tweak_cat_bulk_on}</button>
                          <span aria-hidden>·</span>
                          <button type="button" onClick={() => bulkToggle(cat, false)}>{t.tweak_cat_bulk_off}</button>
                        </div>
                      )}
                    </div>
                  )}
                  {cat.render()}
                </div>
              )}
            </section>
          ))}
        </div>
      </aside>
    </>
  );
}

// ---------------------------------------------------------------------------
// G1 (v0.9.0): DFlavorPicker - dropdown variant of the flavor selector,
// matching real namaximum.sk's parameter-box-with-select pattern but with
// UX upgrades the real eshop does not have:
//   - search/filter input (instant filter as you type)
//   - keyboard navigation (↑ / ↓ / Enter / Esc, mouse hover updates active)
//   - per-row badges (gift / discount / low stock / unavailable / out)
//   - available count in header ("12 z 23 dostupných v 1 kg")
//   - smooth open animation, click-outside / Esc to close
//   - selected row highlighted with primary accent rail + checkmark
//   - 26px swatch dot per row (same DS swatch as pills variant)
// Pills variant is preserved as alternative design via tweak
// `flavor_picker_variant: 'pills'` (see ux_real category in DTweakPanel).
// ---------------------------------------------------------------------------
function DFlavorPicker({ flavors, currentSize, sizeLabel, current, getVariant, t, lang, onPick }) {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');
  const [active, setActive] = useState(0);
  const ref = useRef(null);
  const inputRef = useRef(null);
  const listRef = useRef(null);

  const rows = flavors.map((f) => {
    const variant = getVariant(currentSize, f.id);
    const exists  = !!variant;
    const isOut   = exists && variant.stock === 'out';
    const isLow   = exists && variant.stock === 'low';
    const isRestk = exists && variant.stock === 'restock';
    const hasDisc = exists && variant.orig && variant.orig > variant.price;
    const discPct = hasDisc ? Math.round((1 - variant.price / variant.orig) * 100) : 0;
    const label   = (t.flavors && t.flavors[f.id]) || f.label;
    return { ...f, variant, exists, isOut, isLow, isRestk, hasDisc, discPct, label };
  });

  const q = query.trim().toLowerCase();
  const visible = rows.filter(r => !q || r.label.toLowerCase().includes(q));
  const availCount = rows.filter(r => r.exists && !r.isOut).length;
  const totalCount = rows.length;
  const selected = rows.find(r => r.id === current) || rows[0];

  // Close on outside click
  useEffect(() => {
    if (!open) return;
    const handler = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [open]);

  // Reset query + focus search input on open. Highlight active = current.
  useEffect(() => {
    if (open) {
      setQuery('');
      const idx = rows.findIndex(r => r.id === current);
      setActive(idx >= 0 ? idx : 0);
      const tmr = setTimeout(() => { if (inputRef.current) inputRef.current.focus(); }, 60);
      return () => clearTimeout(tmr);
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  // Scroll active row into view as user navigates
  useEffect(() => {
    if (!open || !listRef.current) return;
    const el = listRef.current.querySelector('.is-active');
    if (el && el.scrollIntoView) el.scrollIntoView({ block: 'nearest' });
  }, [active, open]);

  const selectFlavor = (id) => {
    onPick(id);
    setOpen(false);
  };

  const onKeyDown = (e) => {
    if (e.key === 'Escape') { e.preventDefault(); setOpen(false); return; }
    if (e.key === 'ArrowDown') {
      e.preventDefault();
      setActive(a => Math.min(visible.length - 1, a + 1));
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      setActive(a => Math.max(0, a - 1));
    } else if (e.key === 'Enter') {
      e.preventDefault();
      const r = visible[active];
      if (r && r.exists && !r.isOut) selectFlavor(r.id);
    }
  };

  const fmt = (n) => n.toFixed(2).replace('.', ',') + ' €';
  const giftLabel = t.flavor_gift_short || (lang === 'hu' ? '+ ajándék' : '+ darček');
  const lowLabel = t.flavor_stock_low || (lang === 'hu' ? 'kevés' : 'málo');
  const restkLabel = t.flavor_stock_restock || (lang === 'hu' ? 'úton' : 'na ceste');
  const outLabel = t.flavor_stock_out || (lang === 'hu' ? 'kifogyott' : 'vypredané');
  const noneLabel = t.flavor_unavail || (lang === 'hu' ? 'nem elérhető' : 'nedostupné');
  const placeholder = t.flavor_search_placeholder || (lang === 'hu' ? 'Íz keresése...' : 'Hľadať príchuť...');
  const noResults = t.flavor_no_results || (lang === 'hu' ? 'Nincs találat' : 'Žiadne výsledky');
  const countLabel = (lang === 'hu')
    ? (availCount + ' / ' + totalCount + (sizeLabel ? (' (' + sizeLabel + ')') : ''))
    : (availCount + ' z ' + totalCount + (sizeLabel ? (' v ' + sizeLabel) : ''));

  return (
    <div className={"pdp-d-flavorpicker" + (open ? ' is-open' : '')} ref={ref}>
      <button
        type="button"
        className="pdp-d-flavorpicker-trigger"
        onClick={() => setOpen(o => !o)}
        aria-expanded={open}
        aria-haspopup="listbox"
      >
        <span className="swatch" style={{ background: selected.color }} aria-hidden="true" />
        <span className="lbl">{selected.label}</span>
        <span className="meta">
          {selected.hasDisc && <span className="disc">{'-' + selected.discPct + ' %'}</span>}
          {selected.variant && selected.variant.gift && (
            <span className="gift" title={lang === 'hu' ? 'Ajándékkal' : 'S darčekom'} aria-hidden="true">✰</span>
          )}
          {selected.variant && (
            <span className="price">{fmt(selected.variant.price)}</span>
          )}
          <svg className="chev" viewBox="0 0 16 16" aria-hidden="true">
            <path d="M4 6l4 4 4-4" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </span>
      </button>

      {open && (
        <div className="pdp-d-flavorpicker-pop" role="listbox" aria-label={t.flavor}>
          <div className="pdp-d-flavorpicker-hd">
            <span className="hd-lbl">{t.flavor}</span>
            <span className="hd-count">{countLabel}</span>
          </div>
          <div className="pdp-d-flavorpicker-search">
            <svg viewBox="0 0 16 16" aria-hidden="true" className="ico">
              <circle cx="7" cy="7" r="5" fill="none" stroke="currentColor" strokeWidth="1.5" />
              <path d="M11 11l3 3" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
            </svg>
            <input
              ref={inputRef}
              type="text"
              placeholder={placeholder}
              value={query}
              onChange={(e) => { setQuery(e.target.value); setActive(0); }}
              onKeyDown={onKeyDown}
              autoComplete="off"
              spellCheck={false}
            />
            {query && (
              <button
                type="button"
                className="clear"
                onClick={() => { setQuery(''); inputRef.current && inputRef.current.focus(); }}
                aria-label={lang === 'hu' ? 'Törlés' : 'Vymazať'}
              >
                ×
              </button>
            )}
          </div>
          <div className="pdp-d-flavorpicker-list" ref={listRef}>
            {visible.length === 0 && (
              <div className="empty">{noResults}</div>
            )}
            {visible.map((r, i) => {
              const dis = !r.exists || r.isOut;
              const isCur = r.id === current;
              return (
                <button
                  key={r.id}
                  type="button"
                  className={
                    'pdp-d-flavorpicker-row'
                    + (isCur ? ' is-current' : '')
                    + (i === active ? ' is-active' : '')
                    + (dis ? ' is-disabled' : '')
                  }
                  role="option"
                  aria-selected={isCur}
                  aria-disabled={dis}
                  onClick={() => !dis && selectFlavor(r.id)}
                  onMouseEnter={() => setActive(i)}
                  disabled={dis}
                >
                  <span className="row-swatch" style={{ background: r.color }} aria-hidden="true" />
                  <span className="row-name">{r.label}</span>
                  <span className="row-tags">
                    {r.hasDisc && (<span className="tag disc">{'-' + r.discPct + ' %'}</span>)}
                    {r.variant && r.variant.gift && (<span className="tag gift">{giftLabel}</span>)}
                    {r.isLow && (<span className="tag low">{lowLabel}</span>)}
                    {r.isRestk && (<span className="tag restock">{restkLabel}</span>)}
                    {r.isOut && (<span className="tag out">{outLabel}</span>)}
                    {!r.exists && (<span className="tag none">{noneLabel}</span>)}
                  </span>
                  <span className="row-price">
                    {r.variant && (
                      <>
                        <span className="cur">{fmt(r.variant.price)}</span>
                        {r.hasDisc && (<del className="orig">{fmt(r.variant.orig)}</del>)}
                      </>
                    )}
                  </span>
                  <span className="row-mark" aria-hidden="true">
                    {isCur && (
                      <svg viewBox="0 0 16 16">
                        <path d="M3 8l3 3 7-7" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    )}
                  </span>
                </button>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

// ============ MAIN COMPONENT ============
function DesktopPDP() {
  // Resolve the initial tweak snapshot once per mount: defaults <- window.__TWEAKS
  // <- localStorage. The panel writes to localStorage, so user edits survive a
  // reload while the showcase shell can still seed via window.__TWEAKS.
  const initialTweaks = (() => {
    const base = (typeof window !== 'undefined' && window.__TWEAKS) || {};
    const stored = readStoredTweaks();
    return { ...D_TWEAK_DEFAULTS, ...base, ...stored };
  })();
  const [stock, setStock] = useState(initialTweaks.stock);
  const [discount, setDiscount] = useState(initialTweaks.discount !== false);
  const [lang, setLang] = useState(initialTweaks.lang);
  const [galIdx, setGalIdx] = useState(0);
  // v0.7.1 polish: gallery image lightbox. null = closed, number = active
  // slide index. Opened by clicking the hero stage; closed via X, backdrop
  // click, or ESC. Prev/next arrows + ArrowLeft/ArrowRight wrap GAL_SLIDES.
  const [lightbox, setLightbox] = useState(null);
  const [size, setSize] = useState('1kg');
  // Default flavor = highest-stock 1kg variant in the real catalog.
  const [flavor, setFlavor] = useState('chocolate-deluxe');
  const [qty, setQty] = useState(1);
  const [fav, setFav] = useState(false);
  const [added, setAdded] = useState(false);
  const [filter, setFilter] = useState('all');
  const [sort, setSort] = useState('recent');
  // Customer Q&A state (replaces the old static FAQ).
  const [qaSort, setQaSort]       = useState('helpful');     // 'helpful' | 'recent' | 'unanswered'
  const [qaVisible, setQaVisible] = useState(5);            // "show more" pagination
  const [qaLiked, setQaLiked]     = useState(new Set());    // qids the user upvoted in this session
  const [qaFormOpen, setQaFormOpen] = useState(false);
  const [qaForm, setQaForm]       = useState({ name: '', email: '', variantId: '', question: '', consent: false });
  const [qaSubmitting, setQaSubmitting] = useState(false);
  const [toasts, setToasts] = useState([]);
  const [addedCross, setAddedCross] = useState(new Set());
  const [showSticky, setShowSticky] = useState(false);
  const [cartCount, setCartCount] = useState(3);
  const [helpful, setHelpful] = useState(new Set());
  // Review enhancements (P2)
  const [langFilter, setLangFilter] = useState('all');     // 'all' | 'sk' | 'cz' | 'hu' | 'de'
  const [langDropOpen, setLangDropOpen] = useState(false); // dropdown open/close
  const [addRatingOpen, setAddRatingOpen] = useState(false);
  // Mock logged-in customer state (real Latte: $isCustomerLoggedIn). When true,
  // the add-rating form omits the name field; when false, the form is replaced
  // by a login hint, mirroring the real eshop.
  const [loggedIn, setLoggedIn] = useState(true);
  const [revFormRating, setRevFormRating] = useState(5);
  const [revFormForm, setRevFormForm] = useState({ name: '', variantId: '', short: '', summary: '' });
  const [aiEnabled, setAiEnabled] = useState(initialTweaks.ai_summary !== false);
  const [aiVariant, setAiVariant] = useState(initialTweaks.ai_variant || 'classic');
  const [promoBar, setPromoBar] = useState(!!initialTweaks.promo_bar);
  const [qtyTiers, setQtyTiers] = useState(initialTweaks.qty_tiers !== false);
  const [giftBonus, setGiftBonus] = useState(initialTweaks.gift_bonus !== false);
  const [discountTimer, setDiscountTimer] = useState(initialTweaks.discount_timer !== false);
  const [expirationWarn, setExpirationWarn] = useState(!!initialTweaks.expiration_warn);
  // Cross-sell + bundle row above the tab nav. Default ON; tweak panel UI for
  // the `cross_sell` key is owned by another agent, but the state and listener
  // are wired here so flipping the tweak takes effect live.
  const [showCrossSell, setShowCrossSell] = useState(initialTweaks.cross_sell !== false);
  // ----- D2 wave: 16 additional proto-extra tweak gates -----
  // All default ON (match current hardcoded behaviour). Each is gated below in
  // the JSX with `{<flag> && (...)}` so flipping the tweak hides the feature.
  const [socialProof, setSocialProof] = useState(initialTweaks.social_proof !== false);
  const [galleryFlags, setGalleryFlags] = useState(initialTweaks.gallery_flags !== false);
  const [evidenceLine, setEvidenceLine] = useState(initialTweaks.evidence_line !== false);
  const [altNames, setAltNames] = useState(initialTweaks.alt_names !== false);
  const [pricePerKgOn, setPricePerKgOn] = useState(initialTweaks.price_per_kg !== false);
  const [savingsLine, setSavingsLine] = useState(initialTweaks.savings_line !== false);
  const [trustStrip, setTrustStrip] = useState(initialTweaks.trust_strip !== false);
  const [shipOptsOn, setShipOptsOn] = useState(initialTweaks.ship_opts !== false);
  const [qaSortShow, setQaSortShow] = useState(initialTweaks.qa_sort !== false);
  const [qaStatsShow, setQaStatsShow] = useState(initialTweaks.qa_stats !== false);
  const [reviewTopics, setReviewTopics] = useState(initialTweaks.review_topics !== false);
  const [reviewReplyCta, setReviewReplyCta] = useState(initialTweaks.review_reply_cta !== false);
  const [stickyTabsMini, setStickyTabsMini] = useState(initialTweaks.sticky_tabs !== false);
  const [valuepropsStrip, setValuepropsStrip] = useState(initialTweaks.valueprops_strip !== false);
  const [aiBetaBadge, setAiBetaBadge] = useState(initialTweaks.ai_beta_badge !== false);
  const [toastsOn, setToastsOn] = useState(initialTweaks.toasts !== false);
  // F2 (v0.8.1): bundle_promo + recently_viewed promoted to real React
  // state so the panel can flip them and the render can guard on the
  // current value. Both default false in D_TWEAK_DEFAULTS - ?? false
  // ensures legacy storage payloads without these keys still resolve
  // to the new real-style default.
  const [bundlePromo, setBundlePromo] = useState(initialTweaks.bundle_promo === true);
  const [recentlyViewed, setRecentlyViewed] = useState(initialTweaks.recently_viewed === true);
  // G1 (v0.9.0): flavor picker variant - 'dropdown' (default, real namaximum
  // pattern) | 'pills' (alternative design, all 23 flavors as pills).
  const [flavorPickerVariant, setFlavorPickerVariant] = useState(initialTweaks.flavor_picker_variant || 'dropdown');
  const [restockOpen, setRestockOpen] = useState(false);
  const [shipOpen, setShipOpen] = useState(false);
  const [activeTab, setActiveTab] = useState('descr');
  const [tabsStuck, setTabsStuck] = useState(false);
  const [descExpanded, setDescExpanded] = useState(false);
  // Share dropdown (real Latte: .toggle-share-box mobile, hoisted to desktop hero column)
  const [shareOpen, setShareOpen] = useState(false);
  // Sale-terminated state (real Latte: $product->state == 'P'). Default 'A'
  // (active). When 'P', the buy panel is replaced by a soldout overlay and the
  // cross-sell section gets the 'Alternatívy' header. Tweak panel UI for the
  // `product_state` key is owned by Agent 4; we just wire the state + listener.
  const [productState, setProductState] = useState(initialTweaks.product_state || 'A');

  const heroRef = useRef(null);
  const tabsAnchorRef = useRef(null);
  const langDropRef = useRef(null);
  const shareRef = useRef(null);
  const sectionRefs = {
    descr: useRef(null),
    certs: useRef(null),
    variants: useRef(null),
    reviews: useRef(null),
    qa: useRef(null),
    files: useRef(null),
    video: useRef(null),
  };

  // Tweaks listener (mirrors mobile). Accepts both legacy showcase-shell
  // payloads (subset of keys) and the full 28-key snapshot dispatched by
  // <DTweakPanel> below.
  useEffect(() => {
    const handler = (e) => {
      const t = e.detail || window.__TWEAKS || {};
      if (t.stock) setStock(t.stock);
      if (typeof t.discount === 'boolean') setDiscount(t.discount);
      if (t.lang) setLang(t.lang);
      if (typeof t.ai_summary === 'boolean') setAiEnabled(t.ai_summary);
      if (t.ai_variant) setAiVariant(t.ai_variant);
      if (typeof t.promo_bar === 'boolean') setPromoBar(t.promo_bar);
      if (typeof t.qty_tiers === 'boolean') setQtyTiers(t.qty_tiers);
      if (typeof t.gift_bonus === 'boolean') setGiftBonus(t.gift_bonus);
      if (typeof t.discount_timer === 'boolean') setDiscountTimer(t.discount_timer);
      if (typeof t.expiration_warn === 'boolean') setExpirationWarn(t.expiration_warn);
      if (typeof t.cross_sell === 'boolean') setShowCrossSell(t.cross_sell);
      if (t.product_state) setProductState(t.product_state);
      // D2 wave
      if (typeof t.social_proof === 'boolean') setSocialProof(t.social_proof);
      if (typeof t.gallery_flags === 'boolean') setGalleryFlags(t.gallery_flags);
      if (typeof t.evidence_line === 'boolean') setEvidenceLine(t.evidence_line);
      if (typeof t.alt_names === 'boolean') setAltNames(t.alt_names);
      if (typeof t.price_per_kg === 'boolean') setPricePerKgOn(t.price_per_kg);
      if (typeof t.savings_line === 'boolean') setSavingsLine(t.savings_line);
      if (typeof t.trust_strip === 'boolean') setTrustStrip(t.trust_strip);
      if (typeof t.ship_opts === 'boolean') setShipOptsOn(t.ship_opts);
      if (typeof t.qa_sort === 'boolean') setQaSortShow(t.qa_sort);
      if (typeof t.qa_stats === 'boolean') setQaStatsShow(t.qa_stats);
      if (typeof t.review_topics === 'boolean') setReviewTopics(t.review_topics);
      if (typeof t.review_reply_cta === 'boolean') setReviewReplyCta(t.review_reply_cta);
      if (typeof t.sticky_tabs === 'boolean') setStickyTabsMini(t.sticky_tabs);
      if (typeof t.valueprops_strip === 'boolean') setValuepropsStrip(t.valueprops_strip);
      if (typeof t.ai_beta_badge === 'boolean') setAiBetaBadge(t.ai_beta_badge);
      if (typeof t.toasts === 'boolean') setToastsOn(t.toasts);
      if (t.flavor_picker_variant) setFlavorPickerVariant(t.flavor_picker_variant);
    };
    window.addEventListener('tweakschange', handler);
    return () => window.removeEventListener('tweakschange', handler);
  }, []);

  const t = (window.PDP_I18N && window.PDP_I18N[lang]) || window.PDP_I18N.sk;

  // ---- Tweak panel plumbing ------------------------------------------------
  // Snapshot of all 28 tweak values (keys mirror D_TWEAK_DEFAULTS). Recomputed
  // every render but cheap; passed to <DTweakPanel> as `tweaks`.
  const tweaks = {
    stock, discount, lang, product_state: productState,
    ai_summary: aiEnabled, ai_variant: aiVariant, ai_beta_badge: aiBetaBadge,
    discount_timer: discountTimer, expiration_warn: expirationWarn,
    qty_tiers: qtyTiers, gift_bonus: giftBonus,
    savings_line: savingsLine, social_proof: socialProof,
    trust_strip: trustStrip, evidence_line: evidenceLine,
    gallery_flags: galleryFlags, valueprops_strip: valuepropsStrip,
    alt_names: altNames, price_per_kg: pricePerKgOn,
    qa_sort: qaSortShow, qa_stats: qaStatsShow,
    review_topics: reviewTopics, review_reply_cta: reviewReplyCta,
    promo_bar: promoBar, sticky_tabs: stickyTabsMini,
    cross_sell: showCrossSell, ship_opts: shipOptsOn, toasts: toastsOn,
    // F2: gating new tweaks (bundle_promo banner, recently_viewed widget)
    bundle_promo: bundlePromo, recently_viewed: recentlyViewed,
    // G1 (v0.9.0): flavor picker variant
    flavor_picker_variant: flavorPickerVariant,
  };
  // Stable map of tweak key -> setter. setState references are stable across
  // renders, so the empty-deps useMemo is safe.
  const TWEAK_SETTERS = useMemo(() => ({
    stock: setStock, discount: setDiscount, lang: setLang,
    product_state: setProductState,
    ai_summary: setAiEnabled, ai_variant: setAiVariant, ai_beta_badge: setAiBetaBadge,
    discount_timer: setDiscountTimer, expiration_warn: setExpirationWarn,
    qty_tiers: setQtyTiers, gift_bonus: setGiftBonus,
    savings_line: setSavingsLine, social_proof: setSocialProof,
    trust_strip: setTrustStrip, evidence_line: setEvidenceLine,
    gallery_flags: setGalleryFlags, valueprops_strip: setValuepropsStrip,
    alt_names: setAltNames, price_per_kg: setPricePerKgOn,
    qa_sort: setQaSortShow, qa_stats: setQaStatsShow,
    review_topics: setReviewTopics, review_reply_cta: setReviewReplyCta,
    promo_bar: setPromoBar, sticky_tabs: setStickyTabsMini,
    cross_sell: setShowCrossSell, ship_opts: setShipOptsOn,
    toasts: setToastsOn,
    // F2 (v0.8.1): NEW tweak setters
    bundle_promo: setBundlePromo, recently_viewed: setRecentlyViewed,
    // G1 (v0.9.0): NEW tweak setter
    flavor_picker_variant: setFlavorPickerVariant,
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }), []);
  // Debounced localStorage write (300ms) so a rapid string of toggles only
  // results in one persistence call.
  const persistTimerRef = useRef(null);
  const schedulePersist = (snapshot) => {
    if (persistTimerRef.current) clearTimeout(persistTimerRef.current);
    persistTimerRef.current = setTimeout(() => {
      try { localStorage.setItem(D_TWEAK_STORAGE_KEY, JSON.stringify(snapshot)); } catch (_) {}
    }, 300);
  };
  const handleTweakChange = (key, value) => {
    const setter = TWEAK_SETTERS[key];
    if (setter) setter(value);
    if (typeof window !== 'undefined') {
      window.__TWEAKS = { ...(window.__TWEAKS || {}), [key]: value };
    }
    schedulePersist({ ...tweaks, [key]: value });
  };
  const handleTweakReset = () => {
    Object.entries(D_TWEAK_DEFAULTS).forEach(([k, v]) => {
      const setter = TWEAK_SETTERS[k];
      if (setter) setter(v);
    });
    if (typeof window !== 'undefined') window.__TWEAKS = { ...D_TWEAK_DEFAULTS };
    try { localStorage.removeItem(D_TWEAK_STORAGE_KEY); } catch (_) {}
  };

  // Close the language filter dropdown when the user clicks outside it.
  useEffect(() => {
    if (!langDropOpen) return;
    const onDoc = (e) => {
      const root = langDropRef.current;
      if (!root) return;
      if (!root.contains(e.target)) setLangDropOpen(false);
    };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [langDropOpen]);

  // Close the share dropdown on outside click (mirrors language dropdown pattern).
  useEffect(() => {
    if (!shareOpen) return;
    const onDoc = (e) => {
      const root = shareRef.current;
      if (!root) return;
      if (!root.contains(e.target)) setShareOpen(false);
    };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [shareOpen]);

  // Sticky tab bar + active tab tracking on scroll
  useEffect(() => {
    const onTabsScroll = () => {
      const anchor = tabsAnchorRef.current;
      if (anchor) {
        const top = anchor.getBoundingClientRect().top;
        setTabsStuck(top <= 0);
      }
      // active tab via section visibility
      const sects = Object.entries(sectionRefs);
      const viewportMid = window.innerHeight * 0.35;
      let bestId = activeTab;
      let bestDist = Infinity;
      for (const [id, ref] of sects) {
        const el = ref.current;
        if (!el) continue;
        const r = el.getBoundingClientRect();
        if (r.bottom < 0 || r.top > window.innerHeight) continue;
        const dist = Math.abs(r.top - viewportMid);
        if (dist < bestDist) { bestDist = dist; bestId = id; }
      }
      if (bestId !== activeTab) setActiveTab(bestId);
    };
    window.addEventListener('scroll', onTabsScroll, { passive: true });
    onTabsScroll();
    return () => window.removeEventListener('scroll', onTabsScroll);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeTab]);

  // Sticky mini bar - appears when hero scrolls fully out of view
  useEffect(() => {
    const onScroll = () => {
      const hero = heroRef.current;
      if (!hero) return;
      const heroBottom = hero.getBoundingClientRect().bottom;
      // show mini bar when hero bottom passes top of viewport
      setShowSticky(heroBottom < 140);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  // v0.7.1 polish: lightbox keyboard shortcuts. ESC closes; arrows step
  // through slides while open. Listener only attaches when the lightbox
  // is mounted to keep idle pages free of global handlers.
  useEffect(() => {
    if (lightbox === null) return;
    const total = D_GAL_SLIDES.length;
    const onKey = (e) => {
      if (e.key === 'Escape') { setLightbox(null); return; }
      if (e.key === 'ArrowLeft')  { setLightbox(i => (i - 1 + total) % total); return; }
      if (e.key === 'ArrowRight') { setLightbox(i => (i + 1) % total); return; }
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [lightbox]);

  const selSize = D_SIZES.find(s => s.id === size) || D_SIZES[1];
  const selFlavor = D_FLAVORS.find(f => f.id === flavor) || D_FLAVORS[0];
  // Active variant resolved from the (size, flavor) matrix - mirrors backend $activeVariant.
  const activeVariant = getVariant(size, flavor) || { price: 0, orig: null, stock: 'out', gift: false };
  const rawPrice = activeVariant.price;
  const origPrice = discount ? (activeVariant.orig || null) : null;
  const pricePerKg = selSize.kg ? rawPrice / selSize.kg : 0;
  const unitPrice = rawPrice;
  const totalPrice = unitPrice * qty;
  const savings = origPrice ? (origPrice - unitPrice) * qty : 0;

  // Active discount countdown (per variant). null when no discount.
  const discountTo = activeVariant.discountTo ? new Date(activeVariant.discountTo) : null;

  const toEur = (n) => {
    if (t.currency === 'HUF') {
      const huf = Math.round(n * t.rate);
      return huf.toLocaleString(t.locale) + ' Ft';
    }
    return n.toLocaleString(t.locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €';
  };

  const push = (msg, kind = 'ok') => {
    // Tweak gate: when `toasts` is disabled, swallow the dispatch entirely so
    // listeners (cart adds, language switches, etc.) never see a notification.
    if (!toastsOn) return;
    const id = Math.random().toString(36).slice(2);
    setToasts(t => [...t, { id, msg, kind }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 2200);
  };

  const addToCart = () => {
    if (stock === 'out') { push(t.toast_out, 'err'); return; }
    setAdded(true);
    setCartCount(c => c + qty);
    push(t.toast_added);
    setTimeout(() => setAdded(false), 1400);
  };

  const addCross = (p) => {
    setAddedCross(s => { const n = new Set(s); n.add(p.id); return n; });
    setCartCount(c => c + 1);
    push(t.toast_added_short);
    setTimeout(() => setAddedCross(s => { const n = new Set(s); n.delete(p.id); return n; }), 1200);
  };

  // Share helpers ------------------------------------------------------
  // shareUrl is computed lazily so SSR / non-browser contexts stay safe even
  // though this prototype always runs in the browser.
  const getShareUrl = () => {
    if (typeof window !== 'undefined' && window.location && window.location.href) {
      return window.location.href;
    }
    return '';
  };
  const copyShareLink = async () => {
    const url = getShareUrl();
    try {
      if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
        await navigator.clipboard.writeText(url);
      } else {
        // Fallback path for older browsers / restricted contexts.
        const ta = document.createElement('textarea');
        ta.value = url;
        ta.setAttribute('readonly', '');
        ta.style.position = 'absolute';
        ta.style.left = '-9999px';
        document.body.appendChild(ta);
        ta.select();
        document.execCommand('copy');
        document.body.removeChild(ta);
      }
      push(t.share_copied);
    } catch (_) {
      push(t.share_copied);
    }
    setShareOpen(false);
  };
  // ---------------------------------------------------------------------

  // Q&A helpers ----------------------------------------------------------
  const QA_ALL = (window.WPC80 && window.WPC80.questions) || [];
  const QA_META = (window.WPC80 && window.WPC80.questionsMeta) || { total: QA_ALL.length, withReply: 0, verifiedBuyers: 0, guests: 0 };
  const qaSorted = useMemo(() => {
    const arr = [...QA_ALL];
    if (qaSort === 'recent') {
      arr.sort((a, b) => (a.createdISO < b.createdISO ? 1 : -1));
    } else if (qaSort === 'unanswered') {
      // unanswered first (stable: newest among the group goes up)
      arr.sort((a, b) => {
        const aw = a.hasReply ? 1 : 0;
        const bw = b.hasReply ? 1 : 0;
        if (aw !== bw) return aw - bw;
        return a.createdISO < b.createdISO ? 1 : -1;
      });
    } else {
      // helpful (default) - highest valuation first
      arr.sort((a, b) => (b.valuation - a.valuation) || (a.createdISO < b.createdISO ? 1 : -1));
    }
    return arr;
  }, [QA_ALL, qaSort]);
  // Reset "show more" cursor when the user changes sort.
  useEffect(() => { setQaVisible(5); }, [qaSort]);

  const fmtDate = (iso) => {
    if (!iso) return '';
    const d = new Date(iso);
    if (isNaN(d.getTime())) return '';
    const day   = d.getDate();
    const month = d.getMonth() + 1;
    const year  = d.getFullYear();
    return lang === 'hu' ? `${year}. ${month}. ${day}.` : `${day}. ${month}. ${year}`;
  };
  const initials = (full) => {
    const parts = (full || '').trim().split(/\s+/).filter(Boolean);
    if (parts.length === 0) return '?';
    if (parts.length === 1) return parts[0].charAt(0).toUpperCase();
    return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
  };
  const fmtValuation = (n) => (n || 0).toLocaleString(lang === 'hu' ? 'hu-HU' : 'sk-SK');
  const toggleQaLike = (qid) => {
    setQaLiked(s => { const n = new Set(s); n.has(qid) ? n.delete(qid) : n.add(qid); return n; });
  };
  const submitQuestion = (e) => {
    e.preventDefault();
    if (qaSubmitting) return;
    if (!qaForm.question.trim()) { push(t.qa_err_empty || 'Prosím vyplnte otázku.', 'err'); return; }
    setQaSubmitting(true);
    setTimeout(() => {
      setQaSubmitting(false);
      setQaFormOpen(false);
      setQaForm({ name: '', email: '', variantId: '', question: '', consent: false });
      push(t.qa_toast_sent || 'Otazka odoslaná. Odpovieme čo najskôr.');
    }, 600);
  };
  // ----------------------------------------------------------------------

  const toggleHelpful = (id) => {
    setHelpful(s => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  };

  // ---- Review enhancements helpers --------------------------------------
  // Language filter options (real Latte: $availableLanguageRating loop).
  // Order mirrors the live eshop language dropdown.
  const REV_LANGS = [
    { id: 'sk', code: 'SK', src: '../assets/flags/sk.svg', tKey: 'rev_lang_sk' },
    { id: 'cz', code: 'CZ', src: '../assets/flags/cz.svg', tKey: 'rev_lang_cz' },
    { id: 'hu', code: 'HU', src: '../assets/flags/hu.svg', tKey: 'rev_lang_hu' },
    { id: 'de', code: 'DE', src: '../assets/flags/de.svg', tKey: 'rev_lang_de' },
  ];

  // Visible reviews after applying the language filter.
  const visibleReviews = langFilter === 'all'
    ? D_REVIEWS
    : D_REVIEWS.filter(r => r.lang === langFilter);

  // Add-rating form submit (mock). Resets form, closes panel, fires toast.
  const submitRevForm = (e) => {
    e.preventDefault();
    setRevFormForm({ name: '', variantId: '', short: '', summary: '' });
    setRevFormRating(5);
    setAddRatingOpen(false);
    push(t.rev_form_thanks);
  };

  const freePct = Math.min(100, (totalPrice / D_FREE_SHIPPING) * 100);
  const freeRemain = Math.max(0, D_FREE_SHIPPING - totalPrice);

  // Effective stock for the active variant. Tweak `stock` (when set to low/out) overrides; otherwise variant value.
  const effectiveStock = (stock && stock !== 'in') ? stock : (activeVariant.stock || 'in');
  const stockLabel =
    effectiveStock === 'restock' && activeVariant.restockDays
      ? (lang === 'hu'
          ? `Elérhető ${activeVariant.restockDays} nap múlva`
          : `Dostupné o ${activeVariant.restockDays} dní`)
      : effectiveStock === 'in'  ? t.stock_in
      : effectiveStock === 'low' ? t.stock_low
      : t.stock_out;
  const stockCls =
    effectiveStock === 'in'        ? ''
    : effectiveStock === 'low'     ? 'low'
    : effectiveStock === 'restock' ? 'restock'
    : 'out';

  const activeSlide = D_GAL_SLIDES[galIdx] || D_GAL_SLIDES[0];

  const D_CATEGORIES = lang === 'hu' ? D_CATEGORIES_HU : D_CATEGORIES_SK;

  return (
    <div className="pdp-d-stage">
      {/* TOP ANNOUNCEMENT BAR - optional (tweak: promo_bar) */}
      {promoBar && (
        <div className="pdp-d-top">
          <div className="pdp-d-container pdp-d-top-row">
            <div className="pdp-d-top-msg">
              <span className="ic"><Icon name="truck" size={14} stroke={2} /></span>
              <span><strong>{lang === 'hu' ? 'Ingyenes szállítás' : 'Doprava zadarmo'}</strong> {lang === 'hu' ? '15 000 Ft felett' : 'nad 59 €'} · {lang === 'hu' ? 'Kiszállítás 24 óra alatt' : 'Doručenie do 24 hodín'}</span>
            </div>
            <div className="pdp-d-top-links">
              <a href="#">{lang === 'hu' ? 'Ügyfélszolgálat' : 'Zákaznícky servis'}</a>
              <span className="sep">·</span>
              <a href="#">{lang === 'hu' ? 'Üzletek' : 'Predajne'}</a>
              <span className="sep">·</span>
              <a href="#">{lang === 'hu' ? 'Magyar' : 'Slovensky'} 🇸🇰</a>
              <span className="sep">·</span>
              <a href="#">B2B</a>
            </div>
          </div>
        </div>
      )}

      {/* HEADER - mirrors live namaximum.sk: logo · search · heureka · account/wishlist/cart */}
      <header className="pdp-d-hd">
        <div className="pdp-d-container pdp-d-hd-row">
          <a href="#" className="pdp-d-hd-logo" aria-label="NaMaximum">
            <img src="../assets/logo-namaximum.svg" alt="NaMaximum" />
          </a>
          <div className="pdp-d-search">
            <span className="pdp-d-search-ic"><Icon name="search" size={18} stroke={2} /></span>
            <input type="text" placeholder={t.search_ph} aria-label={t.search_ph} />
            <span className="pdp-d-search-kbd">⌘ K</span>
          </div>
          <a
            href="https://obchody.heureka.sk/namaximum-sk/recenzie/"
            target="_blank"
            rel="noopener"
            className="pdp-d-heureka"
            aria-label="Overené zákazníkmi na Heuréke"
            title="Overené zákazníkmi na Heuréke"
          >
            <img src="../assets/heureka.png" alt="Heuréka.sk - overené zákazníkmi" width={48} height={48} />
          </a>
          <div className="pdp-d-hd-tools">
            <button className="pdp-d-hd-tool" aria-label="Účet">
              <span className="ic-wrap"><Icon name="user" size={20} stroke={1.8} /></span>
              <span className="lbl">{lang === 'hu' ? 'Bejelentkezés' : 'Prihlásiť'}</span>
            </button>
            <button className="pdp-d-hd-tool" aria-label="Obľúbené">
              <span className="ic-wrap"><Icon name="heart" size={20} stroke={1.8} /></span>
              <span className="lbl">{lang === 'hu' ? 'Kedvencek' : 'Obľúbené'}</span>
            </button>
            <button className="pdp-d-hd-tool" aria-label="Košík" onClick={addToCart}>
              <span className="ic-wrap">
                <Icon name="cart" size={20} stroke={1.8} />
                {cartCount > 0 && <span className="pdp-d-hd-badge">{cartCount}</span>}
              </span>
              <span className="lbl">{lang === 'hu' ? 'Kosár' : 'Košík'}</span>
            </button>
          </div>
        </div>
        <div className="pdp-d-hd-nav">
          <div className="pdp-d-container pdp-d-hd-nav-row">
            {D_CATEGORIES.map(c => (
              <a key={c.id} href={c.href || '#'} className={"pdp-d-nav-item" + (c.accent ? ' is-accent' : '')}>
                {c.label}
                <span className="chev"><Icon name="chev" size={11} stroke={2} /></span>
              </a>
            ))}
          </div>
        </div>
      </header>

      {/* STICKY MINI BAR */}
      <div className={"pdp-d-mini" + (showSticky ? ' on' : '')}>
        <div className="pdp-d-mini-inner">
          <div className="pdp-d-mini-thumb">
            {D_PRODUCT.mainImage ? (
              <img src={productImage()} alt={t.product_title} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
            ) : (
              <ProductVisual kind="tub-lg" color="#0077BC" label="WPC 80" sub={selSize.label.toUpperCase()} />
            )}
          </div>
          <div className="pdp-d-mini-name">
            <div className="nm">{t.product_title}</div>
            <div className="meta">
              <span className="stars">★</span>{D_PRODUCT.averageRating.toFixed(2).replace('.', ',')} · {selSize.label} · {t.flavors[selFlavor.id] || selFlavor.label}
            </div>
          </div>
          <div className="pdp-d-mini-price">{toEur(totalPrice)}</div>
          <button
            className={"pdp-d-mini-cta" + (stock === 'out' ? ' out' : '')}
            onClick={addToCart}
            disabled={stock === 'out'}
          >
            {stock === 'out' ? t.sticky_out : <><Icon name="cart" size={16} /> {t.add_to_cart}</>}
          </button>
        </div>
      </div>

      {/* CONTENT */}
      <main>
        {/* VALUE-PROPS STRIP - mirrors live namaximum.sk under-header strip */}
        {valuepropsStrip && (
          <div className="pdp-d-vp-strip">
            <div className="pdp-d-container">
              <ul className="pdp-d-vp-list">
                {(t.valueprops || []).map((vp, i) => (
                  <li key={i} className="pdp-d-vp-it">
                    <span className="vp-ic"><Icon name={vp.ic} size={16} stroke={2} /></span>
                    <span className="vp-tx">{vp.t}</span>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        )}

        {/* Breadcrumbs */}
        <div className="pdp-d-container">
          <nav className="pdp-d-bc" aria-label="Breadcrumb">
            <a href="#">{t.bc_home}</a>
            <span className="sep">›</span>
            <a href="#">{t.bc_proteins}</a>
            <span className="sep">›</span>
            <a href="#">{t.bc_whey}</a>
            <span className="sep">›</span>
            <span className="cur">WPC 80 - {selSize.label} · {t.flavors[selFlavor.id] || selFlavor.label}</span>
          </nav>
        </div>

        {/* HERO */}
        <div className="pdp-d-container">
          <div className="pdp-d-hero" ref={heroRef}>
            {/* GALLERY */}
            <div className="pdp-d-gal">
              <div
                className="pdp-d-gal-main"
                style={activeSlide?.bg ? { background: activeSlide.bg } : undefined}
              >
                {galleryFlags && (
                  <div className="pdp-d-gal-flags">
                    <img src="../assets/badges/gmo-free.svg" alt="GMO-free" />
                    <img src="../assets/badges/lacto-free.svg" alt="Lacto-free" />
                  </div>
                )}
                {origPrice && (
                  <div className="pdp-d-gal-discount">
                    -{Math.round((1 - rawPrice / origPrice) * 100)} %
                  </div>
                )}
                {/* Gift ribbon overlay (real Latte: <i n:if="$canHaveGifts" class="icon-gift">).
                    Slightly offset down when a discount badge already occupies the top-right slot. */}
                {activeVariant?.gift && (
                  <div className={"pdp-d-gal-gift" + (origPrice ? " has-disc" : "")} aria-hidden="false">
                    <span className="pdp-d-gal-gift-ic" aria-hidden="true" />
                    <span className="pdp-d-gal-gift-tx">{t.gallery_gift_ribbon}</span>
                  </div>
                )}
                {/* Social-proof ribbon - "O tento produkt sa práve zaujíma X ľudí" */}
                {socialProof && (
                  <div className="pdp-d-gal-watching" title="Live counter">
                    <span className="dot" />
                    {typeof t.social_proof === 'function' ? t.social_proof(3910) : t.social_proof}
                  </div>
                )}
                <div
                  className="pdp-d-gal-stage"
                  key={galIdx + ':' + D_PRODUCT.mainImage}
                  onClick={() => setLightbox(galIdx)}
                  style={{ cursor: 'zoom-in' }}
                  role="button"
                  aria-label={t.lightbox_close /* opens viewer */}
                >
                  {(activeSlide.kind === 'variant' && D_PRODUCT.mainImage) || activeSlide.kind === 'image' ? (
                    <img
                      src={galleryImage(activeSlide)}
                      alt={t.product_title + ' - ' + selSize.label + ' · ' + (t.flavors[selFlavor.id] || selFlavor.label)}
                      style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
                    />
                  ) : (
                    <ProductVisual
                      kind={activeSlide.kind === 'variant' ? 'tub-lg' : activeSlide.kind}
                      color={activeSlide.color}
                      label={activeSlide.label}
                      sub={activeSlide.sub || selSize.label.toUpperCase()}
                    />
                  )}
                </div>
                <button className="pdp-d-gal-video" type="button">
                  <span className="play" />
                  {lang === 'hu' ? 'VIDEÓÉRTÉKELÉS' : 'VIDEORECENZIA'}
                </button>
                <button className="pdp-d-gal-zoom" aria-label="Zväčšiť">
                  <Icon name="search" size={18} stroke={2} />
                </button>
              </div>
              <div className="pdp-d-gal-thumbs">
                {D_GAL_SLIDES.map((s, i) => (
                  <button
                    key={i}
                    className={"pdp-d-gal-thumb" + (i === galIdx ? ' on' : '') + (s.video ? ' video' : '')}
                    onClick={() => setGalIdx(i)}
                    aria-label={`Slide ${i + 1}`}
                    type="button"
                  >
                    {s.video ? null
                      : (s.kind === 'variant' && D_PRODUCT.mainImage) || s.kind === 'image'
                        ? <img src={galleryImage(s)} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                        : <ProductVisual kind={s.kind === 'variant' ? 'tub-lg' : s.kind} color={s.color} label={s.label} sub={s.sub || selSize.label.toUpperCase()} />}
                  </button>
                ))}
              </div>

              <div className="pdp-d-gal-loop" aria-label="WPC 80 prášok - krátka produktová ukážka">
                <video
                  src="../assets/video/generated/wpc80-powder-editorial-cut-seedance20.mp4"
                  poster="../assets/img/generated/wpc80-powder-detail-gpt-image-2.png"
                  autoPlay
                  muted
                  loop
                  playsInline
                  preload="metadata"
                />
              </div>

              {/* Trust strip below gallery */}
              {trustStrip && (
              <div className="pdp-d-trust">
                <div className="pdp-d-trust-item">
                  <span className="ic"><Icon name="truck" size={18} stroke={2} /></span>
                  <div className="body">
                    <div className="t">{lang === 'hu' ? 'Szállítás 24 óra' : 'Doručenie 24 h'}</div>
                    <div className="d">{lang === 'hu' ? '14:00-ig rendelés esetén' : 'Pri objednávke do 14:00'}</div>
                  </div>
                </div>
                <div className="pdp-d-trust-item">
                  <span className="ic"><Icon name="shield" size={18} stroke={2} /></span>
                  <div className="body">
                    <div className="t">{lang === 'hu' ? '30 napos visszaküldés' : '30 dní na vrátenie'}</div>
                    <div className="d">{lang === 'hu' ? 'Bontatlan árura' : 'Bez udania dôvodu'}</div>
                  </div>
                </div>
                <div className="pdp-d-trust-item">
                  <span className="ic"><Icon name="flask" size={18} stroke={2} /></span>
                  <div className="body">
                    <div className="t">{lang === 'hu' ? 'Labor tesztelt' : 'Lab testované'}</div>
                    <div className="d">{lang === 'hu' ? 'Független tanúsítvány' : 'Nezávislý certifikát'}</div>
                  </div>
                </div>
                <div className="pdp-d-trust-item">
                  <span className="ic"><Icon name="package" size={18} stroke={2} /></span>
                  <div className="body">
                    <div className="t">{lang === 'hu' ? 'SK gyártás' : 'Výroba v SR'}</div>
                    <div className="d">{lang === 'hu' ? 'Spišská Nová Ves' : 'Spišská Nová Ves'}</div>
                  </div>
                </div>
              </div>
              )}
            </div>

            {/* BUY PANEL (sticky) */}
            <aside className="pdp-d-buy">
              {productState === 'P' ? (
                /* Sale-terminated overlay (real Latte: $product->state == 'P').
                   Replaces the entire buy panel content; cross-sell section
                   below is forced visible and re-headed as 'Alternatívy'. */
                <div className="pdp-d-soldout" role="status">
                  <span className="pdp-d-soldout-ic" aria-hidden="true" />
                  <h2 className="pdp-d-soldout-title">{t.soldout_title}</h2>
                  <p className="pdp-d-soldout-msg">{t.soldout_msg}</p>
                </div>
              ) : (
              <>
              {/* Brands above title (live: "Značka: Warrior, Natural Nutrition") */}
              <div className="pdp-d-brandrow">
                <span className="brand-lbl">{t.brand_label}:</span>
                {(t.brands || []).map((b, i) => (
                  <a key={b} href="#" className="brand-link">
                    {b}{i < (t.brands.length - 1) ? ',' : ''}
                  </a>
                ))}
              </div>
              <h1 className="pdp-d-title">{t.product_title}</h1>

              <div className="pdp-d-flags">
                {discount && origPrice && <span className="pdp-d-flag is-sale">{t.flag_sale}</span>}
                <span className="pdp-d-flag is-rec">{t.flag_recommend}</span>
              </div>

              <div className="pdp-d-meta">
                <div className="pdp-d-rating">
                  <span className="stars"><DStars n={4.89} size={14} /></span>
                  <span className="num">4,89</span>
                  <a href="#reviews">{t.reviews_count(1342)}</a>
                  {QA_META.total > 0 && (
                    <>
                      <span className="sep" aria-hidden>·</span>
                      <a href="#qa">{t.qa_count(QA_META.total)}</a>
                    </>
                  )}
                </div>
              </div>

              <span className={"pdp-d-stock " + stockCls}>
                <span className="dot" />
                {stockLabel}
                {stock === 'in' && <span className="extra">· {t.ship_today}</span>}
              </span>

              <div className="pdp-d-price">
                <span className="now">{toEur(rawPrice)}</span>
                {origPrice && <span className="orig">{toEur(origPrice)}</span>}
                {origPrice && <span className="flag">-{Math.round((1 - rawPrice / origPrice) * 100)} %</span>}
              </div>
              <div className="pdp-d-price-sub">
                {t.vat}
                {pricePerKgOn && (
                  <> · {t.price_per_kg} <span className="num">{toEur(pricePerKg)}</span></>
                )}
                {savingsLine && savings > 0 && (
                  <span className="saved">· {lang === 'hu' ? 'Megtakarítás' : 'Ušetríš'} {toEur(savings)}</span>
                )}
              </div>

              {/* Discount countdown (per active variant) */}
              {discountTimer && discountTo && origPrice && (
                <DCountdown deadline={discountTo} lang={lang} />
              )}

              {/* Product expiration warning (Latte: $productExpiration) */}
              {expirationWarn && (
                <div className="pdp-d-expiration">
                  <span className="ic"><Icon name="shield" size={14} stroke={2} /></span>
                  {lang === 'hu'
                    ? 'A választott változat minimális eltarthatósági ideje 30. 6. 2026-án jár le.'
                    : 'Doba minimálnej trvánlivosti vybraného variantu končí 30. 6. 2026!'}
                </div>
              )}

              {/* Bullets */}
              <ul className="pdp-d-bullets">
                {t.bullets.map((b, i) => (
                  <li key={i}>
                    <span className="ic"><Icon name="check" size={18} stroke={2.5} /></span>
                    <span><strong>{b[0]}</strong> {b[1]}</span>
                  </li>
                ))}
              </ul>

              {evidenceLine && (
                <div className="pdp-d-evidence">
                  <span className="ic"><Icon name="flask" size={16} stroke={2} /></span>
                  <div>
                    {t.evidence} <a href="#">{t.evidence_link}</a> {t.evidence_tail}
                  </div>
                </div>
              )}

              {/* Alternatívne názvy + EAN (mirrors live below bullets) */}
              {altNames && (
                <div className="pdp-d-altnames">
                  <em>{t.alt_label}:</em> {t.alt_names}
                </div>
              )}
              <div className="pdp-d-ean">
                <span className="k">{t.ean_label}:</span>
                <span className="v">{activeVariant.ean || t.ean}</span>
              </div>

              {/* Sizes - cascading availability against current flavor + per-variant data */}
              <div>
                <div className="pdp-d-vlabel">
                  <span className="lbl">{t.packaging} <span className="count">({D_SIZES.length})</span></span>
                  <span className="chosen">{selSize.label}</span>
                </div>
                <div className="pdp-d-sizes">
                  {D_SIZES.map(s => {
                    const variant = getVariant(s.id, flavor);
                    const exists  = !!variant;
                    const isOut   = exists && variant.stock === 'out';
                    const isRestk = exists && variant.stock === 'restock';
                    const disabled = !exists;
                    const pricePer = variant && s.kg ? variant.price / s.kg : 0;
                    const hasDisc  = exists && variant.orig && variant.orig > variant.price;
                    const discPct  = hasDisc ? Math.round((1 - variant.price / variant.orig) * 100) : 0;
                    const flavorCount = countActiveForSize(s.id);
                    return (
                      <button
                        key={s.id}
                        className={
                          'pdp-d-size'
                          + (s.id === size ? ' on' : '')
                          + (isOut    ? ' out'   : '')
                          + (isRestk  ? ' restock' : '')
                          + (disabled ? ' is-unavailable' : '')
                        }
                        onClick={() => exists && setSize(s.id)}
                        disabled={disabled}
                        type="button"
                        title={disabled ? (lang === 'hu' ? 'Nem elérhető ezzel az ízzel' : 'Nedostupné s touto príchuťou') : ''}
                      >
                        {/* Top-right badges */}
                        {hasDisc && <span className="badge save">{'-' + discPct + ' %'}</span>}
                        {!hasDisc && s.badge && <span className="badge">{s.badge}</span>}
                        {variant && variant.gift && <span className="giftbadge" title={lang === 'hu' ? 'Ajándékkal' : 'S darčekom'}>✰</span>}

                        <span className="sz">
                          {exists && <DStockChip stock={variant.stock} restockDays={variant.restockDays} lang={lang} />}
                          {s.label}
                        </span>
                        {exists ? (
                          <>
                            <span className="pr">{toEur(variant.price)}</span>
                            {hasDisc && <span className="orig">{toEur(variant.orig)}</span>}
                            <span className="per"><span style={{ fontVariantNumeric: 'tabular-nums' }}>{toEur(pricePer)}</span>/kg</span>
                            <span className="meta">
                              {flavorCount > 0
                                ? (lang === 'hu' ? (flavorCount + ' íz') : (flavorCount + ' príchuť' + (flavorCount >= 5 ? 'í' : (flavorCount >= 2 ? 'i' : ''))))
                                : (lang === 'hu' ? 'Elfogyott' : 'Vypredané')}
                            </span>
                          </>
                        ) : (
                          <span className="pr unavail">{lang === 'hu' ? 'Nem elérhető' : 'Nedostupné'}</span>
                        )}
                      </button>
                    );
                  })}
                </div>
              </div>

              {/* Flavors - cascading availability against current size + per-variant data.
                  G1 (v0.9.0): default = dropdown (real namaximum.sk pattern with UX upgrades).
                  Pills variant remains selectable via tweak `flavor_picker_variant: 'pills'`. */}
              <div>
                <div className="pdp-d-vlabel">
                  <span className="lbl">{t.flavor} <span className="count">({D_FLAVORS.length})</span></span>
                  {flavorPickerVariant === 'pills' && (
                    <span className="chosen">{t.flavors[selFlavor.id] || selFlavor.label}</span>
                  )}
                </div>
                {flavorPickerVariant === 'pills' ? (
                <div className="pdp-d-flavors">
                  {D_FLAVORS.map(f => {
                    const variant = getVariant(size, f.id);
                    const exists  = !!variant;
                    const isOut   = exists && variant.stock === 'out';
                    const isRestk = exists && variant.stock === 'restock';
                    const isLow   = exists && variant.stock === 'low';
                    const disabled = !exists;
                    const hasDisc = exists && variant.orig && variant.orig > variant.price;
                    const discPct = hasDisc ? Math.round((1 - variant.price / variant.orig) * 100) : 0;
                    return (
                      <button
                        key={f.id}
                        className={
                          'pdp-d-flavor'
                          + (f.id === flavor ? ' on' : '')
                          + (isOut    ? ' out'   : '')
                          + (isLow    ? ' low'   : '')
                          + (isRestk  ? ' restock' : '')
                          + (disabled ? ' is-unavailable' : '')
                        }
                        onClick={() => exists && setFlavor(f.id)}
                        disabled={disabled}
                        type="button"
                        title={disabled ? (lang === 'hu' ? 'Nem elérhető ebben a kiszerelésben' : 'Nedostupné v tomto balení') : ''}
                      >
                        <span className="swatch" style={{ background: f.color }}>
                          {exists && <DStockChip stock={variant.stock} restockDays={variant.restockDays} lang={lang} />}
                        </span>
                        <span className="name">{t.flavors[f.id] || f.label}</span>
                        {hasDisc && <span className="discpill">{'-' + discPct + ' %'}</span>}
                        {variant && variant.gift && <span className="giftpill" title={lang === 'hu' ? 'Ajándékkal' : 'S darčekom'}>✰</span>}
                      </button>
                    );
                  })}
                </div>
                ) : (
                <DFlavorPicker
                  flavors={D_FLAVORS}
                  currentSize={size}
                  sizeLabel={selSize.label}
                  current={flavor}
                  getVariant={getVariant}
                  t={t}
                  lang={lang}
                  onPick={(id) => setFlavor(id)}
                />
                )}

                {/* Gift bonus block (Latte: $activeGifts[$activeVariant->product_id]) */}
                {giftBonus && activeVariant.gift && (
                  <div className="pdp-d-giftblock">
                    <div className="pdp-d-giftblock-top">
                      <div className="gh">
                        <span className="giftic">✰</span>
                        <div>
                          <strong>{lang === 'hu' ? 'Limitált akció!' : 'Limitovaná akcia!'}</strong>
                          <span>{lang === 'hu' ? 'Adjon hozzá ajándékokat a változathoz.' : 'Pridaj darek k variantu, zadarmo k tomuto baleníu.'}</span>
                        </div>
                      </div>
                      <a href="#" className="gp-btn">{lang === 'hu' ? 'Válasszon ajándékot →' : 'Vybrať darček →'}</a>
                    </div>
                    {/* Selected gift picks thumbnail strip + counter (real Latte:
                        product-bonus__items + 'Vybrali ste %s z %s darčekov'). */}
                    {D_GIFT_PICKS.length > 0 && (
                      <>
                        <div className="pdp-d-giftblock-picks" role="list">
                          {D_GIFT_PICKS.map(g => (
                            <span
                              key={g.id}
                              role="listitem"
                              className={"pdp-d-giftblock-pick is-" + g.icon}
                              title={g.name}
                            >
                              <span className="pdp-d-giftblock-pick-shape" aria-hidden="true" />
                            </span>
                          ))}
                        </div>
                        <div className="pdp-d-giftblock-counter">
                          {t.gift_picked_label(D_GIFT_PICKS.length, D_GIFT_PICKS_TOTAL)}
                        </div>
                      </>
                    )}
                  </div>
                )}
              </div>

              {/* ATC row */}
              <div className="pdp-d-atc-row">
                <div className="pdp-d-qty">
                  <button onClick={() => setQty(q => Math.max(1, q - 1))} disabled={qty <= 1} aria-label="Znížiť" type="button">
                    <Icon name="minus" size={14} stroke={2.5} />
                  </button>
                  <span className="val">{qty}</span>
                  <button onClick={() => setQty(q => Math.min(99, q + 1))} aria-label="Zvýšiť" type="button">
                    <Icon name="plus" size={14} stroke={2.5} />
                  </button>
                </div>
                {effectiveStock === 'out' || effectiveStock === 'restock' ? (
                  <button
                    className="pdp-d-atc-btn out"
                    onClick={() => setRestockOpen(true)}
                    type="button"
                  >
                    <Icon name="clock" size={18} stroke={2} />
                    <span>{lang === 'hu' ? 'Mikor lesz raktáron?' : 'Keď bude skladom?'}</span>
                  </button>
                ) : (
                  <button
                    className={'pdp-d-atc-btn' + (added ? ' added' : '')}
                    onClick={addToCart}
                    type="button"
                  >
                    {added ? (
                      <><Icon name="check" size={20} stroke={2.5} /> <span>{t.added}</span></>
                    ) : (
                      <>
                        <Icon name="cart" size={20} />
                        <span className="stack">
                          <span>{t.add_to_cart}</span>
                          <span className="total">{toEur(totalPrice)}</span>
                        </span>
                      </>
                    )}
                  </button>
                )}
                {/* Share dropdown trigger (real Latte: .toggle-share-box mobile,
                    hoisted into the desktop hero column next to favourites). */}
                <div className="pdp-d-share-wrap" ref={shareRef}>
                  <button
                    type="button"
                    className={"pdp-d-share" + (shareOpen ? ' on' : '')}
                    aria-haspopup="menu"
                    aria-expanded={shareOpen}
                    aria-label={t.share_btn}
                    title={t.share_btn}
                    onClick={() => setShareOpen(o => !o)}
                  >
                    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <circle cx="18" cy="5" r="3" />
                      <circle cx="6" cy="12" r="3" />
                      <circle cx="18" cy="19" r="3" />
                      <line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />
                      <line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
                    </svg>
                  </button>
                  {shareOpen && (
                    <div className="pdp-d-share-pop" role="menu" aria-label={t.share_btn}>
                      <button
                        type="button"
                        role="menuitem"
                        className="pdp-d-share-pop-item"
                        onClick={copyShareLink}
                      >
                        <span className="pdp-d-share-pop-ic is-link" aria-hidden="true">
                          <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                            <path d="M10 13a5 5 0 0 0 7.07 0l3-3a5 5 0 0 0-7.07-7.07l-1.5 1.5" />
                            <path d="M14 11a5 5 0 0 0-7.07 0l-3 3a5 5 0 0 0 7.07 7.07l1.5-1.5" />
                          </svg>
                        </span>
                        <span>{t.share_copy}</span>
                      </button>
                      <a
                        role="menuitem"
                        className="pdp-d-share-pop-item"
                        href={'mailto:?subject=' + encodeURIComponent(t.product_title) + '&body=' + encodeURIComponent(getShareUrl())}
                        onClick={() => setShareOpen(false)}
                      >
                        <span className="pdp-d-share-pop-ic is-mail" aria-hidden="true">
                          <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                            <rect x="3" y="5" width="18" height="14" rx="2" />
                            <path d="m3 7 9 6 9-6" />
                          </svg>
                        </span>
                        <span>{t.share_email}</span>
                      </a>
                      <a
                        role="menuitem"
                        className="pdp-d-share-pop-item"
                        href={'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(getShareUrl())}
                        target="_blank"
                        rel="noopener noreferrer"
                        onClick={() => setShareOpen(false)}
                      >
                        <span className="pdp-d-share-pop-ic is-fb" aria-hidden="true" />
                        <span>{t.share_fb}</span>
                      </a>
                      <a
                        role="menuitem"
                        className="pdp-d-share-pop-item"
                        href={'https://wa.me/?text=' + encodeURIComponent(getShareUrl())}
                        target="_blank"
                        rel="noopener noreferrer"
                        onClick={() => setShareOpen(false)}
                      >
                        <span className="pdp-d-share-pop-ic is-wa" aria-hidden="true" />
                        <span>{t.share_wa}</span>
                      </a>
                    </div>
                  )}
                </div>
                <button
                  className={"pdp-d-fav" + (fav ? ' on' : '')}
                  onClick={() => setFav(f => !f)}
                  aria-label="Obľúbené"
                  type="button"
                >
                  <Icon name="heart" size={22} />
                </button>
              </div>

              {/* Quantity discount tiers (Latte: $productQuantityPrices) */}
              {qtyTiers && (
                <div className="pdp-d-qtytiers">
                  <div className="pdp-d-qtytiers-h">
                    <span className="ic"><Icon name="package" size={14} stroke={2} /></span>
                    {lang === 'hu' ? 'Mennyiségi kedvezmény' : 'Množstevná zľava'}
                  </div>
                  <ul>
                    {D_QTY_TIERS.map((tier, i) => {
                      const active = qty >= tier.min && (tier.max === null || qty <= tier.max);
                      const label = tier.max
                        ? (lang === 'hu' ? (tier.min + '-' + tier.max + ' db') : ('Pri kúpe ' + tier.min + '-' + tier.max + ' bal.'))
                        : (lang === 'hu' ? ('Min. ' + tier.min + ' db felett') : ('Pri kúpe ' + tier.min + '+ balení'));
                      const save = activeVariant.price ? Math.round((1 - tier.perPack / activeVariant.price) * 100) : 0;
                      return (
                        <li key={i} className={active ? 'is-active' : ''}>
                          <span className="qt-range">{label}</span>
                          <span className="qt-prc">
                            <strong>{toEur(tier.perPack)}</strong>
                            <em>/{lang === 'hu' ? 'db' : 'bal.'}</em>
                            {save > 0 && <span className="qt-save">{'-' + save + ' %'}</span>}
                          </span>
                        </li>
                      );
                    })}
                  </ul>
                </div>
              )}

              {effectiveStock !== 'out' && effectiveStock !== 'restock' && (
                <>
                  <div className="pdp-d-ship">
                    <span className="ic"><Icon name="truck" size={18} stroke={2} /></span>
                    <div>
                      <strong>{t.delivery_by}</strong> {t.delivery_cutoff}
                    </div>
                  </div>

                  {/* Možnosti dopravy expander (live: clickable shipping options) */}
                  {shipOptsOn && (
                  <div className={"pdp-d-shipopts" + (shipOpen ? ' is-open' : '')}>
                    <button
                      type="button"
                      className="pdp-d-shipopts-tg"
                      onClick={() => setShipOpen(o => !o)}
                      aria-expanded={shipOpen}
                    >
                      <span className="ic"><Icon name="package" size={14} stroke={2} /></span>
                      <span>{t.ship_options_title}</span>
                      <span className="chev"><Icon name="chev" size={14} stroke={2} /></span>
                    </button>
                    {shipOpen && (
                      <ul className="pdp-d-shipopts-list">
                        {(t.ship_options || []).map((s, i) => (
                          <li key={i} className="pdp-d-shipopt">
                            <span className="so-ic"><Icon name={s.ic} size={14} stroke={2} /></span>
                            <span className="so-nm">{s.nm}</span>
                            <span className="so-tm">{s.t}</span>
                            <span className={"so-pr" + (s.pr.toLowerCase().includes('zdarma') || s.pr.toLowerCase().includes('ingyenes') ? ' is-free' : '')}>{s.pr}</span>
                          </li>
                        ))}
                      </ul>
                    )}
                  </div>
                  )}

                  <div className="pdp-d-free">
                    <div className="pdp-d-free-top">
                      <span>
                        {freeRemain > 0 ? (
                          <>
                            {t.free_remain_pre} <strong style={{ color: 'var(--ink-2)', fontVariantNumeric: 'tabular-nums' }}>{toEur(freeRemain)}</strong> {t.free_remain_post} <strong style={{ color: 'var(--color-1-darker)' }}>{t.free_shipping}</strong>
                          </>
                        ) : (
                          <span style={{ color: 'var(--color-ok)', fontWeight: 700 }}>{t.free_ship_done}</span>
                        )}
                      </span>
                      <span style={{ fontVariantNumeric: 'tabular-nums', fontWeight: 700, color: 'var(--ink-2)' }}>
                        {toEur(totalPrice)} / {toEur(D_FREE_SHIPPING)}
                      </span>
                    </div>
                    <div className="pdp-d-free-bar">
                      <div className="pdp-d-free-fill" style={{ width: freePct + '%' }} />
                    </div>
                  </div>
                </>
              )}

              {/* Restock notification modal (Latte: #sizing-guide modal + restockForm) */}
              {restockOpen && (
                <div className="pdp-d-restock-overlay" onClick={() => setRestockOpen(false)}>
                  <div className="pdp-d-restock-modal" onClick={e => e.stopPropagation()}>
                    <button className="close" onClick={() => setRestockOpen(false)} aria-label="Zavrieť">×</button>
                    <div className="hd">
                      <span className="ic"><Icon name="truck" size={20} stroke={2} /></span>
                      <div>
                        <strong>{lang === 'hu' ? 'Szóljon, ha újra raktáron lesz!' : 'Dám vedieť, keď bude sklad doplnený'}</strong>
                        <span>{selSize.label} · {t.flavors[selFlavor.id] || selFlavor.label}</span>
                      </div>
                    </div>
                    <p className="copy">
                      {lang === 'hu'
                        ? 'Email címére egyszeri értesítést küldünk, amint a változat újra elérhető.'
                        : 'Pošleme jeden e-mail, keď bude tento variant opäť dostupný. Žiadny spam.'}
                    </p>
                    <div className="row">
                      <input type="email" placeholder={lang === 'hu' ? 'Email címe' : 'Tvoj e-mail'} />
                      <button className="submit" onClick={() => { push(lang === 'hu' ? 'Felvéve' : 'Budeš informovaný', 'ok'); setRestockOpen(false); }}>
                        {lang === 'hu' ? 'Bekérem' : 'Daj mi vedieť'}
                      </button>
                    </div>
                  </div>
                </div>
              )}

              {/* Inline certs */}
              <div className="pdp-d-buy-certs">
                <span className="lbl">{t.certs_title}</span>
                <div className="row">
                  <a href="#" title="HACCP"><img src="../assets/certifications/HACCP-certified-icon-new.svg?v=2" alt="HACCP" /></a>
                  <a href="#" title="GMP"><img src="../assets/certifications/GMP-certified-icon-new.svg?v=2" alt="GMP" /></a>
                  <a href="#" title="Lab tested"><img src="../assets/certifications/Independent-laboratory-tested-new.svg?v=2" alt="Lab tested" /></a>
                  <a href="#" title="EU Organic"><img src="../assets/certifications/EU_Organic_Logo_Colour_54x36mm-new.svg?v=2" alt="EU Organic" /></a>
                </div>
              </div>
              </>
              )}
            </aside>
          </div>
        </div>

        {/* CROSS-SELL + BUNDLE: "Skvele dopĺňajú" / "Často kupované spolu".
            Real default.latte renders this row BEFORE the tab nav. Default ON,
            tweakable via cross_sell key (panel UI lives in another agent).
            When productState === 'P' the section is forced visible and the
            header is re-labelled to 'Alternatívy k tomuto produktu'. */}
        {(showCrossSell || productState === 'P') && (
          <section className="pdp-d-section pdp-d-section--xsell">
            <div className="pdp-d-container">
              <div className="pdp-d-section-hd">
                <h2 className="pdp-d-section-title">
                  {productState === 'P' ? t.soldout_alts : t.cross_title}
                </h2>
                {/* F3 (v0.8.2): only render the subtitle when t.cross_sub
                    has content. Real eshop has no subtitle on the
                    detailCombination heading; we emptied cross_sub in
                    pdp-i18n.jsx so this becomes a no-op for SK + HU. */}
                {productState !== 'P' && t.cross_sub && (
                  <span className="pdp-d-section-sub">{t.cross_sub}</span>
                )}
              </div>

              {/* Bundle banner. v0.7.11: items render real CDN photos
                  from window.BUNDLE.items (sourced from production
                  MySQL via data/wpc80-bundle.json - see
                  scripts/build-cross-sell-data.mjs). Was 2 hardcoded
                  ProductVisual paint mocks ('WPC 80 / 1 KG' blue tub +
                  'CREATINE / 500 G' dark-blue tub). The mobile twin in
                  PDPMobile.jsx received the same swap. Falls back to
                  ProductVisual if window.BUNDLE is unavailable so the
                  prototype still renders without the data file.
                  F2 (v0.8.1): now gated behind tweaks.bundle_promo
                  (default false). Real eshop has no banner; only the
                  sibling product-detail__detailCombination link list
                  (cross_sell). F3 will render that link list as the
                  default and keep this banner as opt-in. */}
              {tweaks.bundle_promo && (
              <div className="pdp-d-bundle">
                <div className="pdp-d-bundle-left">
                  <span className="pdp-d-bundle-tag">{t.bundle_tag}</span>
                  <h3 className="pdp-d-bundle-name">{t.bundle_name}</h3>
                  <div className="pdp-d-bundle-items">
                    {((typeof window !== 'undefined' && window.BUNDLE && window.BUNDLE.items) || []).map((it, idx, arr) => (
                      <React.Fragment key={it.id}>
                        <div className="pdp-d-bundle-it">
                          <img src={it.image} alt={it.fullName || it.name} loading="lazy" />
                          <span className="pdp-d-bundle-it-size">{it.size}</span>
                        </div>
                        {idx < arr.length - 1 && <span className="pdp-d-bundle-plus">+</span>}
                      </React.Fragment>
                    ))}
                    {!(typeof window !== 'undefined' && window.BUNDLE) && (
                      <>
                        <div className="pdp-d-bundle-it">
                          <ProductVisual kind="tub" color="#0077BC" label="WPC 80" sub="1 KG" />
                        </div>
                        <span className="pdp-d-bundle-plus">+</span>
                        <div className="pdp-d-bundle-it">
                          <ProductVisual kind="tub" color="#1A5282" label="CREATINE" sub="500 G" />
                        </div>
                      </>
                    )}
                  </div>
                </div>
                <div className="pdp-d-bundle-right">
                  <div className="pdp-d-bundle-pricerow">
                    <span className="now">{toEur(37.80)}</span>
                    <span className="orig">{toEur(41.80)}</span>
                    <span className="pdp-d-bundle-vs">{t.bundle_vs}</span>
                  </div>
                  <div className="pdp-d-bundle-saving">
                    {t.bundle_save_pre} <strong>{toEur(4.00)}</strong> {t.bundle_save_post}
                  </div>
                  <button className="pdp-d-bundle-cta" type="button">
                    <Icon name="cart" size={16} stroke={2} />
                    {t.bundle_add}
                  </button>
                </div>
              </div>
              )}

              {/* F3 (v0.8.2): cross-sell renders the real combinations.latte
                  card grid. (Linklist variant explored briefly and removed -
                  real eshop only ever ships cards.) */}
              <div className="pdp-d-cross-grid">
                {D_CROSS.slice(0, 4).map(p => {
                  // F3: derive a sale-flag percentage when the row carries
                  // a higher 'orig' price than 'price'. Live data does not
                  // ship orig today so most cards skip this overlay; the
                  // hook is here for parity with combinations.latte
                  // <span class="sale-flag--new">-X%</span>.
                  const pct = (p.orig && p.orig > p.price)
                    ? Math.round((1 - p.price / p.orig) * 100)
                    : null;
                  return (
                  <article key={p.id} className="pdp-d-cross-card">
                    <a href={p.slug || '#'} className="img">
                      {p.flag && <div className={"flag" + (p.flag === 'NOVÉ' ? ' new' : '')}>{p.flag}</div>}
                      {/* F3: -X% sale flag overlay (top-right) when discount
                          is present. Mirrors real .sale-flag--new c-variant. */}
                      {pct && <div className="sale-flag">-{pct}%</div>}
                      {/* v0.7.7 C-phase: real photo when DB row carries one
                          (greenmedical.bwcdn.net CDN); ProductVisual stays
                          as the no-image fallback. */}
                      {p.image
                        ? <img src={p.image} alt={p.name} loading="lazy" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} />
                        : <ProductVisual kind={p.visual} color={p.packColor} label={p.packLabel} sub={p.packSub} />
                      }
                    </a>
                    <a href={p.slug || '#'} className="nm">{p.name}</a>
                    <div className="rt"><span className="s">★</span> {p.rating.toLocaleString(lang === 'hu' ? 'hu-HU' : 'sk-SK', { minimumFractionDigits: 1 })} ({p.reviews})</div>
                    <div className="bot">
                      <div>
                        {/* F3: 'od X,XX €' prefix on variant products (real
                            eshop renders {_"od"} <span class="info-price-num"/>
                            for variant_product type cross-sell rows). */}
                        <span className="price-from">{t.cross_price_from}</span>
                        {' '}
                        <span className="pr">{toEur(p.price)}</span>
                        {p.orig && <span className="orig">{toEur(p.orig)}</span>}
                      </div>
                      {/* F3: replaced inline ATC "+" with a Detail pseudo-link
                          to mirror real combinations.latte
                          <span class="btn btn-detail">Detail</span>. The whole
                          card already links via the wrapping anchor; the
                          button here is decorative + accessible. */}
                      <a href={p.slug || '#'} className="detail" aria-label={t.cross_detail}>
                        <span>{t.cross_detail}</span>
                        <Icon name="search" size={14} stroke={2} />
                      </a>
                    </div>
                  </article>
                  );
                })}
              </div>
            </div>
          </section>
        )}

        {/* STICKY TAB ANCHOR NAV - mirrors live PDP tab bar (Popis, Certifikáty, Varianty, Recenzie, Otázky, Prílohy, Video) */}
        <div ref={tabsAnchorRef} />
        <nav className={"pdp-d-tabnav" + (tabsStuck ? ' is-stuck' : '')} aria-label="Sekcie produktu">
          <div className="pdp-d-container pdp-d-tabnav-inner">
            <ul className="pdp-d-tabnav-list">
              {[
                { id: 'descr',    label: t.tab_descr },
                { id: 'certs',    label: t.tab_certs },
                { id: 'variants', label: t.tab_variants },
                { id: 'reviews',  label: typeof t.tab_reviews === 'function' ? t.tab_reviews(1342) : t.tab_reviews },
                { id: 'qa',       label: typeof t.tab_qa === 'function' ? t.tab_qa(QA_META.total) : t.tab_qa },
                { id: 'files',    label: t.tab_files },
                { id: 'video',    label: t.tab_video },
              ].map(tab => (
                <li key={tab.id}>
                  <a
                    href={'#' + tab.id}
                    className={"pdp-d-tabnav-link" + (activeTab === tab.id ? ' is-active' : '')}
                    onClick={(e) => {
                      e.preventDefault();
                      const el = sectionRefs[tab.id]?.current;
                      if (el) {
                        const tabsH = 56;
                        const top = window.scrollY + el.getBoundingClientRect().top - tabsH - 12;
                        window.scrollTo({ top, behavior: 'smooth' });
                      }
                    }}
                  >
                    {tab.label}
                  </a>
                </li>
              ))}
            </ul>
            {stickyTabsMini && tabsStuck && (
              <div className="pdp-d-tabnav-mini">
                <span className="nm">{t.product_title}</span>
                <button
                  className={"pdp-d-tabnav-cta" + (effectiveStock === 'out' || effectiveStock === 'restock' ? ' is-out' : '')}
                  onClick={effectiveStock === 'out' || effectiveStock === 'restock' ? () => setRestockOpen(true) : addToCart}
                  type="button"
                >
                  <Icon name="cart" size={14} stroke={2} />
                  {effectiveStock === 'out' || effectiveStock === 'restock'
                    ? (lang === 'hu' ? 'Mikor lesz?' : 'Keď bude?')
                    : (lang === 'hu' ? 'Kosárba' : 'Do košíka')}
                </button>
              </div>
            )}
          </div>
        </nav>

        {/* PRODUCT INFO - long description + side boxes (mirrors namaximum #info Latte tab) */}
        <section className="pdp-d-section" id="descr" ref={sectionRefs.descr}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.desc_section_title}</h2>
              <span className="pdp-d-section-sub">{t.desc_section_sub}</span>
            </div>

            <div className="pdp-d-info-grid">
              {/* LEFT: full long description (collapsible) */}
              <div className="pdp-d-info-main">
                <article className={
                  "pdp-d-info-box pdp-d-info-box--collapsible" +
                  (descExpanded ? " is-expanded" : "")
                }>
                  <header><h3>{t.desc_main_title}</h3></header>
                  <div
                    className="pdp-d-info-body pdp-d-prose"
                    dangerouslySetInnerHTML={{ __html: D_PRODUCT.descriptionHtml }}
                  />
                  <button
                    type="button"
                    className="pdp-d-info-toggle"
                    aria-expanded={descExpanded}
                    onClick={() => setDescExpanded(v => !v)}
                  >
                    <span>{descExpanded ? t.desc_show_less : t.desc_show_more}</span>
                    <span className="chev" aria-hidden>▾</span>
                  </button>
                </article>
              </div>

              {/* RIGHT: stacked side boxes (use & dosing, storage & alerts) */}
              <aside className="pdp-d-info-side">
                <article className="pdp-d-info-box">
                  <header><h3>{t.desc_use_dosing}</h3></header>
                  <div
                    className="pdp-d-info-body pdp-d-prose pdp-d-prose--compact"
                    dangerouslySetInnerHTML={{ __html: D_PRODUCT.useDosingHtml }}
                  />
                </article>
                <article className="pdp-d-info-box">
                  <header><h3>{t.desc_storage}</h3></header>
                  <div
                    className="pdp-d-info-body pdp-d-prose pdp-d-prose--compact"
                    dangerouslySetInnerHTML={{ __html: D_PRODUCT.storageAndAlertsHtml }}
                  />
                </article>
              </aside>
            </div>
          </div>
        </section>

        {/* CERTIFICATIONS BAND */}
        <section className="pdp-d-section alt" id="certs" ref={sectionRefs.certs}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.certs_title}</h2>
              <span className="pdp-d-section-sub">{t.certs_sub}</span>
            </div>
            <div className="pdp-d-certs-grid">
              <a className="pdp-d-cert" href="#"><img src="../assets/certifications/HACCP-certified-icon-new.svg?v=2" alt="HACCP" /></a>
              <a className="pdp-d-cert" href="#"><img src="../assets/certifications/GMP-certified-icon-new.svg?v=2" alt="GMP" /></a>
              <a className="pdp-d-cert" href="#"><img src="../assets/certifications/Independent-laboratory-tested-new.svg?v=2" alt="Lab tested" /></a>
              <a className="pdp-d-cert" href="#"><img src="../assets/certifications/EU_Organic_Logo_Colour_54x36mm-new.svg?v=2" alt="EU Organic" /></a>
            </div>
            <div className="pdp-d-cert-note">
              {t.certs_note} <a href="#">{t.certs_more}</a>
            </div>
          </div>
        </section>

        {/* REVIEWS */}
        <section className="pdp-d-section" id="reviews" ref={sectionRefs.reviews}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.rev_title}</h2>
              <span className="pdp-d-section-sub">{t.rev_sub}</span>
            </div>

            {/* Summary card */}
            <div className="pdp-d-rev-summary">
              <div className="pdp-d-rev-score-big">
                <div className="num">4,89</div>
                <div className="stars"><DStars n={4.89} size={18} /></div>
                <div className="cnt">{t.reviews_count(1342)}</div>
              </div>
              <div className="pdp-d-rev-dist">
                {D_REV_DIST.map(d => (
                  <div key={d.s} className="pdp-d-rev-dist-row">
                    <span className="s"><span className="st" aria-hidden>★</span> {d.s}</span>
                    <div className="bar"><div className="fill" style={{ width: d.pct + '%' }} /></div>
                    <span className="n">{d.n}</span>
                  </div>
                ))}
              </div>
              <div className="pdp-d-rev-recommend">
                <div className="num">{D_REV_RECOMMEND_PCT.toLocaleString(lang === 'hu' ? 'hu-HU' : 'sk-SK', { minimumFractionDigits: 1 })} %</div>
                <div className="msg">{t.rev_recommend_msg}</div>
              </div>
            </div>

            {/* AI summary card */}
            {aiEnabled && <DAiReviewSummary t={t} variant={aiVariant} onTopicClick={() => setFilter('all')} showBeta={aiBetaBadge} />}

            {/* Featured top-comment (real _reviews.latte $bestRating block) */}
            <DRevFeatured t={t} review={D_REV_BEST} lang={lang} />

            {/* Write-review CTA + add-rating form (real Latte: addRatingForm) */}
            <div className="pdp-d-rev-controls">
              <span className="ask">{t.rev_cta_q}</span>
              <button
                className={'write' + (addRatingOpen ? ' on' : '')}
                type="button"
                onClick={() => loggedIn ? setAddRatingOpen(o => !o) : push(t.rev_form_login_hint, 'err')}
                aria-expanded={addRatingOpen}
              >
                {addRatingOpen ? t.rev_form_close : t.rev_cta_btn}
              </button>
            </div>

            {addRatingOpen && (
              loggedIn ? (
                <form className="pdp-d-rev-form" onSubmit={submitRevForm} noValidate>
                  <div className="pdp-d-rev-form-hd">
                    <h4>{t.rev_form_title}</h4>
                    <p>{t.rev_form_lead}</p>
                  </div>
                  <div className="pdp-d-rev-form-grid">
                    {/* Name field shown only when not logged in (mirrors Latte). */}
                    {!loggedIn && (
                      <label className="pdp-d-rev-fld">
                        <span>{t.rev_form_name} <em>*</em></span>
                        <input
                          type="text"
                          required
                          value={revFormForm.name}
                          onChange={e => setRevFormForm(f => ({ ...f, name: e.target.value }))}
                          placeholder={t.rev_form_name_ph}
                        />
                      </label>
                    )}
                    <label className="pdp-d-rev-fld">
                      <span>{t.rev_form_variant} <em>*</em></span>
                      <select
                        required
                        value={revFormForm.variantId}
                        onChange={e => setRevFormForm(f => ({ ...f, variantId: e.target.value }))}
                      >
                        <option value="">{t.rev_form_variant_none}</option>
                        {Object.entries(D_VARIANTS).map(([key, v]) => {
                          const [sId, fId] = key.split('_');
                          const sLabel = (D_SIZES.find(s => s.id === sId) || {}).label || sId;
                          const fLabel = (t.flavors && t.flavors[fId]) || (D_FLAVORS.find(f => f.id === fId) || {}).label || fId;
                          return (
                            <option key={key} value={v.productId || key}>
                              {fLabel} · {sLabel}
                            </option>
                          );
                        })}
                      </select>
                    </label>
                    <label className="pdp-d-rev-fld">
                      <span>{t.rev_form_short} <em>*</em></span>
                      <input
                        type="text"
                        required
                        maxLength={80}
                        value={revFormForm.short}
                        onChange={e => setRevFormForm(f => ({ ...f, short: e.target.value }))}
                        placeholder={t.rev_form_short_ph}
                      />
                    </label>
                    <label className="pdp-d-rev-fld pdp-d-rev-fld-rating">
                      <span>{t.rev_form_rating} <em>*</em></span>
                      <div className="pdp-d-rev-form-stars" role="radiogroup" aria-label={t.rev_form_rating}>
                        {[1,2,3,4,5].map(n => (
                          <button
                            key={n}
                            type="button"
                            role="radio"
                            aria-checked={revFormRating === n}
                            className={'pdp-d-rev-form-star' + (n <= revFormRating ? ' on' : '')}
                            onClick={() => setRevFormRating(n)}
                            aria-label={n + ' / 5'}
                          >★</button>
                        ))}
                        <span className="pdp-d-rev-form-stars-n">{revFormRating}/5</span>
                        {revFormRating > 3 && (
                          <span className="pdp-d-rev-item-recommend in-form" aria-hidden>
                            <span className="ic" />
                            {t.rev_recommend_badge}
                          </span>
                        )}
                      </div>
                    </label>
                    <label className="pdp-d-rev-fld span-2">
                      <span>{t.rev_form_summary} <em>*</em></span>
                      <textarea
                        rows={4}
                        required
                        value={revFormForm.summary}
                        onChange={e => setRevFormForm(f => ({ ...f, summary: e.target.value }))}
                        placeholder={t.rev_form_summary_ph}
                      />
                    </label>
                  </div>
                  <div className="pdp-d-rev-form-bot">
                    <button type="submit" className="pdp-d-rev-form-submit">{t.rev_form_submit}</button>
                  </div>
                </form>
              ) : (
                <div className="pdp-d-rev-form-login">
                  {t.rev_form_login_hint} <a href="#" onClick={(e) => { e.preventDefault(); setLoggedIn(true); }}>{t.rev_form_login_link}</a>
                </div>
              )
            )}

            {/* Filters - star/verified chips always shown; topic chips (chuť, rozpustnosť, cena)
                are gated by the `review_topics` tweak. */}
            <div className="pdp-d-rev-filters">
              {D_REV_FILTERS.filter(f => {
                const isTopic = !['all','verified','5','4','3','2','1'].includes(f.id);
                return reviewTopics || !isTopic;
              }).map(f => (
                <button
                  key={f.id}
                  className={"pdp-d-rev-chip" + (filter === f.id ? ' on' : '')}
                  onClick={() => setFilter(f.id)}
                  type="button"
                >
                  {f.label}<span className="n">{f.n}</span>
                </button>
              ))}
            </div>

            <div className="pdp-d-rev-sort">
              <span>{t.rev_showing(1, visibleReviews.length, 1342)}</span>
              <div className="pdp-d-rev-sort-ctrls">
                {/* Language filter (real Latte: dropdown__box.language) */}
                <div
                  className={'pdp-d-rev-lang-filter' + (langDropOpen ? ' on' : '')}
                  ref={langDropRef}
                >
                  <span className="pdp-d-rev-lang-lbl">{t.rev_lang_label}:</span>
                  <button
                    type="button"
                    className="pdp-d-rev-lang-btn"
                    onClick={() => setLangDropOpen(o => !o)}
                    aria-haspopup="listbox"
                    aria-expanded={langDropOpen}
                  >
                    {langFilter === 'all' ? (
                      <span className="current">{t.rev_lang_all}</span>
                    ) : (
                      <span className="current">
                        <img
                          className="flag"
                          src={(REV_LANGS.find(l => l.id === langFilter) || {}).src}
                          alt=""
                          width="20"
                          height="14"
                        />
                        {t[(REV_LANGS.find(l => l.id === langFilter) || {}).tKey]}
                      </span>
                    )}
                    <span className="chev" aria-hidden><Icon name="chev" size={11} stroke={2} /></span>
                  </button>
                  {langDropOpen && (
                    <div className="pdp-d-rev-lang-pop" role="listbox">
                      <button
                        type="button"
                        role="option"
                        aria-selected={langFilter === 'all'}
                        className={'pdp-d-rev-lang-opt' + (langFilter === 'all' ? ' on' : '')}
                        onClick={() => { setLangFilter('all'); setLangDropOpen(false); }}
                      >
                        <span className="flag flag-all" aria-hidden />
                        {t.rev_lang_all}
                      </button>
                      {REV_LANGS.map(l => (
                        <button
                          key={l.id}
                          type="button"
                          role="option"
                          aria-selected={langFilter === l.id}
                          className={'pdp-d-rev-lang-opt' + (langFilter === l.id ? ' on' : '')}
                          onClick={() => { setLangFilter(l.id); setLangDropOpen(false); }}
                        >
                          <img className="flag" src={l.src} alt="" width="20" height="14" />
                          {t[l.tKey]}
                        </button>
                      ))}
                    </div>
                  )}
                </div>
                <select value={sort} onChange={e => setSort(e.target.value)}>
                  <option value="recent">{t.sort_recent}</option>
                  <option value="helpful">{t.sort_helpful}</option>
                  <option value="rating_desc">{t.sort_best}</option>
                  <option value="rating_asc">{t.sort_worst}</option>
                </select>
              </div>
            </div>

            {/* Review grid */}
            {visibleReviews.length === 0 ? (
              <div className="pdp-d-rev-empty">{t.rev_lang_filter_empty}</div>
            ) : (
            <div className="pdp-d-rev-grid">
              {visibleReviews.map(r => {
                const isRegistered = (r.customerType || (r.verified ? 'registered' : 'guest')) === 'registered';
                return (
                <article key={r.id} className="pdp-d-rev-card">
                  <header className="pdp-d-rev-card-hd">
                    <div className="pdp-d-rev-avatar">{r.initial}</div>
                    <div className="nm-block">
                      <div className="nm">
                        {r.name}
                        {r.rating > 3 && (
                          <span className="pdp-d-rev-item-recommend" title={t.rev_recommend_badge}>
                            <span className="ic" aria-hidden />
                            {t.rev_recommend_badge}
                          </span>
                        )}
                      </div>
                      <div className="date">{r.date} · {r.size} · {r.flavor}</div>
                    </div>
                    <div className="item-stars"><DStars n={r.rating} size={14} /></div>
                  </header>
                  {/* Customer-type + purchase-verified badges (real Latte:
                      .customer-type.active-cust / .active-order rows). */}
                  <div className="pdp-d-rev-cust">
                    <div className={'pdp-d-rev-cust-row' + (isRegistered ? ' is-cust' : ' is-guest')}>
                      <span className={'pdp-d-rev-cust-ic' + (isRegistered ? ' is-check' : ' is-cross')} aria-hidden />
                      <span>{isRegistered ? t.rev_cust_registered : t.rev_cust_guest}</span>
                    </div>
                    <div className="pdp-d-rev-cust-row is-purchase">
                      <span className="pdp-d-rev-cust-ic is-check" aria-hidden />
                      <span>{t.rev_cust_purchase}</span>
                    </div>
                  </div>
                  <div className="title">{r.title}</div>
                  <div className="body">{r.body}</div>
                  <div className="tags">
                    {/* v0.7.5 A2: dropped the '#' prefix on review tags. The
                        real namaximum.sk review widget renders tags as plain
                        pills, not Twitter-style hashtags. */}
                    {r.tags.map(tag => <span key={tag} className="tag">{tag}</span>)}
                  </div>
                  <div className="helpful">
                    <button onClick={() => toggleHelpful(r.id)} style={{ color: helpful.has(r.id) ? 'var(--color-1)' : undefined }} type="button">
                      <Icon name="check" size={12} stroke={2.5} />
                      {t.rev_helpful(r.helpful + (helpful.has(r.id) ? 1 : 0))}
                    </button>
                    {reviewReplyCta && <button type="button">{t.rev_reply}</button>}
                  </div>
                  {/* Reply by NaMaximum team (real Latte: .rating-answer block) */}
                  {r.reply && (
                    <div className="pdp-d-rev-reply">
                      <div className="pdp-d-rev-reply-hd">
                        <span className="pdp-d-rev-reply-logo" aria-hidden>
                          <img src="../assets/logo-min.svg" alt="" />
                        </span>
                        <div className="pdp-d-rev-reply-meta">
                          <span className="l">{t.rev_reply_label}</span>
                          <span className="d">{r.reply.date}</span>
                        </div>
                      </div>
                      <p className="pdp-d-rev-reply-body">{r.reply.text}</p>
                    </div>
                  )}
                </article>
              );})}
            </div>
            )}

            <button className="pdp-d-rev-more" type="button">{t.rev_more(1342)}</button>
          </div>
        </section>

        {/* VARIANT MATRIX - real-style "Varianty" tab.
            Mirrors _table.latte: every (size × flavor) row from WPC80.variants
            with stock chip, discount badge, per-kg unit price and an inline
            add-to-cart button (UI only, no real cart wiring). */}
        <section className="pdp-d-section alt" id="variants" ref={sectionRefs.variants}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.var_title}</h2>
              <span className="pdp-d-section-sub">{t.var_sub(Object.keys(D_VARIANTS).length)}</span>
            </div>

            <div className="pdp-d-vartab-wrap">
              <table className="pdp-d-vartab">
                <thead>
                  <tr>
                    <th className="col-flavor">{t.var_col_flavor}</th>
                    <th className="col-size">{t.var_col_size}</th>
                    <th className="col-price">{t.var_col_price}</th>
                    <th className="col-perkg">{t.var_col_per_kg}</th>
                    <th className="col-stock">{t.var_col_stock}</th>
                    <th className="col-action">{t.var_col_action}</th>
                  </tr>
                </thead>
                <tbody>
                  {D_SIZES.map((sDef) => {
                    const sId = sDef.id;
                    const variantsInSize = Object.entries(D_VARIANTS).filter(([k]) => k.startsWith(sId + '_'));
                    if (variantsInSize.length === 0) return null;
                    return (
                    <React.Fragment key={'grp-' + sId}>
                      <tr className="pdp-d-vartab-group">
                        <td colSpan={6}>
                          <span className="gh">
                            <span className="gh-size">{sDef.label}</span>
                            <span className="gh-count">{t.var_group_count(variantsInSize.length)}</span>
                          </span>
                        </td>
                      </tr>
                      {variantsInSize.map(([key, v]) => {
                    const [, fId] = key.split('_');
                    const fDef    = D_FLAVORS.find(f => f.id === fId);
                    if (!fDef) return null;
                    const fLabel  = (t.flavors && t.flavors[fId]) || fDef.label;
                    const sLabel  = sDef.label;
                    const hasDisc = v.orig && v.orig > v.price;
                    const discPct = hasDisc ? Math.round((1 - v.price / v.orig) * 100) : 0;
                    const perKg   = sDef.kg ? v.price / sDef.kg : 0;
                    const isOut   = v.stock === 'out';
                    const isLow   = v.stock === 'low';
                    const isRestk = v.stock === 'restock';
                    const isActive = sId === size && fId === flavor;
                    const stockTxt =
                      isOut   ? t.var_sold_out :
                      isRestk ? (lang === 'hu'
                                  ? ((v.restockDays || 0) + ' nap múlva')
                                  : ('O ' + (v.restockDays || 0) + ' dní'))
                      : isLow ? t.stock_low
                      : t.stock_in;
                    return (
                      <tr
                        key={key}
                        className={
                          'pdp-d-vartab-row'
                          + (isOut ? ' is-out' : '')
                          + (isLow ? ' is-low' : '')
                          + (isRestk ? ' is-restock' : '')
                          + (isActive ? ' is-active' : '')
                        }
                      >
                        <td className="col-flavor">
                          <div className="flavor-inner">
                            <span className="swatch" style={{ background: fDef.color }} aria-hidden />
                            <span className="nm">{fLabel}</span>
                          </div>
                        </td>
                        <td className="col-size">{sLabel}</td>
                        <td className="col-price">
                          <span className="now">{toEur(v.price)}</span>
                          {hasDisc && <span className="orig">{toEur(v.orig)}</span>}
                          {hasDisc && <span className="badge">{'-' + discPct + ' %'}</span>}
                        </td>
                        <td className="col-perkg">
                          <span className="perkg">{toEur(perKg)}</span>
                        </td>
                        <td className="col-stock">
                          <span className={'pdp-d-vartab-chip ' + (isOut ? 'is-out' : isRestk ? 'is-restock' : isLow ? 'is-low' : 'is-in')}>
                            <span className="dot" aria-hidden />
                            {stockTxt}
                          </span>
                        </td>
                        <td className="col-action">
                          {isOut ? (
                            <button
                              type="button"
                              className="pdp-d-vartab-btn is-notify"
                              onClick={() => { setSize(sId); setFlavor(fId); setRestockOpen(true); }}
                            >
                              <Icon name="clock" size={14} stroke={2} />
                              <span>{lang === 'hu' ? 'Ha raktáron lesz' : 'Keď bude'}</span>
                            </button>
                          ) : (
                            <button
                              type="button"
                              className={'pdp-d-vartab-btn' + (isActive ? ' is-active' : '')}
                              onClick={() => {
                                setSize(sId);
                                setFlavor(fId);
                                addToCart();
                              }}
                            >
                              <Icon name="cart" size={14} stroke={2} />
                              <span>{t.var_add_btn}</span>
                            </button>
                          )}
                        </td>
                      </tr>
                    );
                  })}
                    </React.Fragment>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        </section>

        {/* CUSTOMER Q&A - "Otázky a odpovede" (real product_questions data) */}
        <section className="pdp-d-section" id="qa" ref={sectionRefs.qa}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.qa_title}</h2>
              <span className="pdp-d-section-sub">{t.qa_sub_count(QA_META.total, QA_META.withReply)}</span>
            </div>

            {/* Summary strip + ask CTA */}
            <div className="pdp-d-qa-strip">
              {qaStatsShow && (
                <div className="pdp-d-qa-strip-stats">
                  <div className="pdp-d-qa-stat">
                    <span className="n">{QA_META.total}</span>
                    <span className="l">{t.qa_stat_total}</span>
                  </div>
                  <div className="pdp-d-qa-stat">
                    <span className="n with-ic">
                      <Icon name="checkCircle" size={14} stroke={2.5} />
                      {QA_META.withReply}
                    </span>
                    <span className="l">{t.qa_stat_answered}</span>
                  </div>
                  <div className="pdp-d-qa-stat">
                    <span className="n">{QA_META.verifiedBuyers}</span>
                    <span className="l">{t.qa_stat_verified}</span>
                  </div>
                </div>
              )}
              <button
                type="button"
                className={"pdp-d-qa-ask" + (qaFormOpen ? ' on' : '')}
                onClick={() => setQaFormOpen(o => !o)}
              >
                <Icon name={qaFormOpen ? 'x' : 'plus'} size={16} stroke={2.5} />
                {qaFormOpen ? t.qa_close : t.qa_ask_cta}
              </button>
            </div>

            {/* Inline form panel - collapsed by default */}
            {qaFormOpen && (
              <form className="pdp-d-qa-form" onSubmit={submitQuestion} noValidate>
                <div className="pdp-d-qa-form-hd">
                  <h4>{t.qa_form_title}</h4>
                  <p>{t.qa_form_lead}</p>
                </div>
                <div className="pdp-d-qa-form-grid">
                  <label className="pdp-d-qa-fld">
                    <span>{t.qa_field_name} <em>*</em></span>
                    <input
                      type="text"
                      required
                      value={qaForm.name}
                      onChange={e => setQaForm(f => ({ ...f, name: e.target.value }))}
                      placeholder={t.qa_field_name_ph}
                    />
                  </label>
                  <label className="pdp-d-qa-fld">
                    <span>{t.qa_field_email} <em>*</em></span>
                    <input
                      type="email"
                      required
                      value={qaForm.email}
                      onChange={e => setQaForm(f => ({ ...f, email: e.target.value }))}
                      placeholder="meno@example.com"
                    />
                  </label>
                  <label className="pdp-d-qa-fld span-2">
                    <span>{t.qa_field_variant}</span>
                    <select
                      value={qaForm.variantId}
                      onChange={e => setQaForm(f => ({ ...f, variantId: e.target.value }))}
                    >
                      <option value="">{t.qa_field_variant_none}</option>
                      {Object.entries(D_VARIANTS).map(([key, v]) => {
                        const [sId, fId] = key.split('_');
                        const sLabel = (D_SIZES.find(s => s.id === sId) || {}).label || sId;
                        const fLabel = (D_FLAVORS.find(f => f.id === fId) || {}).label || fId;
                        return (
                          <option key={key} value={v.productId || key}>
                            {fLabel} · {sLabel}
                          </option>
                        );
                      })}
                    </select>
                  </label>
                  <label className="pdp-d-qa-fld span-2">
                    <span>{t.qa_field_question} <em>*</em></span>
                    <textarea
                      rows={4}
                      required
                      value={qaForm.question}
                      onChange={e => setQaForm(f => ({ ...f, question: e.target.value }))}
                      placeholder={t.qa_field_question_ph}
                    />
                  </label>
                  {/* Honeypot field (real Latte: addQuestionForm > additional_email).
                      Visually hidden; spam bots auto-fill it and the form submission
                      can be silently dropped server-side. No i18n by design. */}
                  <div className="pdp-d-qa-honey" aria-hidden="true">
                    <label>
                      Email confirm
                      <input
                        type="email"
                        name="additional_email"
                        tabIndex={-1}
                        autoComplete="off"
                      />
                    </label>
                  </div>
                </div>
                <div className="pdp-d-qa-form-bot">
                  <label className="pdp-d-qa-consent">
                    <input
                      type="checkbox"
                      checked={qaForm.consent}
                      onChange={e => setQaForm(f => ({ ...f, consent: e.target.checked }))}
                    />
                    <span>{t.qa_consent}</span>
                  </label>
                  <button
                    type="submit"
                    className="pdp-d-qa-submit"
                    disabled={qaSubmitting || !qaForm.consent}
                  >
                    {qaSubmitting ? t.qa_submitting : t.qa_submit}
                  </button>
                </div>
              </form>
            )}

            {QA_ALL.length === 0 ? (
              <div className="pdp-d-qa-empty">
                <Icon name="note" size={28} stroke={1.6} />
                <p>{t.qa_empty}</p>
              </div>
            ) : (
              <>
                {/* Sort tabs (matches review pattern but slightly tighter).
                    Gated by `qa_sort` tweak; the question list itself stays. */}
                {qaSortShow && (
                  <div className="pdp-d-qa-sort">
                    <button
                      type="button"
                      className={'pdp-d-qa-sort-chip' + (qaSort === 'helpful' ? ' on' : '')}
                      onClick={() => setQaSort('helpful')}
                    >
                      {t.qa_sort_helpful}
                    </button>
                    <button
                      type="button"
                      className={'pdp-d-qa-sort-chip' + (qaSort === 'recent' ? ' on' : '')}
                      onClick={() => setQaSort('recent')}
                    >
                      {t.qa_sort_recent}
                    </button>
                    <button
                      type="button"
                      className={'pdp-d-qa-sort-chip' + (qaSort === 'unanswered' ? ' on' : '')}
                      onClick={() => setQaSort('unanswered')}
                    >
                      {t.qa_sort_unanswered} ({QA_META.total - QA_META.withReply})
                    </button>
                    <span className="pdp-d-qa-sort-info">
                      {t.qa_showing(Math.min(qaVisible, qaSorted.length), QA_META.total)}
                    </span>
                  </div>
                )}

                {/* Question stack */}
                <div className="pdp-d-qa-list">
                  {qaSorted.slice(0, qaVisible).map((q) => {
                    const liked = qaLiked.has(q.id);
                    const baseValuation = q.valuation || 0;
                    return (
                      <article key={q.id} className="pdp-d-qa-card">
                        <header className="pdp-d-qa-card-hd">
                          <div className="pdp-d-qa-avatar" aria-hidden>
                            {initials(q.displayName)}
                          </div>
                          <div className="pdp-d-qa-id">
                            <div className="pdp-d-qa-nm">
                              {q.displayName}
                              {q.isVerified ? (
                                <span className="pdp-d-qa-badge verified" title={t.qa_verified_long}>
                                  <Icon name="checkCircle" size={11} stroke={2.5} />
                                  {t.qa_verified}
                                </span>
                              ) : (
                                <span className="pdp-d-qa-badge guest">
                                  {t.qa_guest}
                                </span>
                              )}
                            </div>
                            <div className="pdp-d-qa-meta">
                              <span>{t.qa_added} {fmtDate(q.createdISO)}</span>
                              {q.variantLabel && (
                                <>
                                  <span className="dot">·</span>
                                  <span className="pdp-d-qa-vchip">{q.variantLabel}</span>
                                </>
                              )}
                            </div>
                          </div>
                          <button
                            type="button"
                            className={'pdp-d-qa-helpful' + (liked ? ' on' : '')}
                            onClick={() => toggleQaLike(q.id)}
                            aria-pressed={liked}
                          >
                            <span className="plus">+1</span>
                            <span className="l">{t.qa_helpful}</span>
                            <span className="n">({fmtValuation(baseValuation + (liked ? 1 : 0))})</span>
                          </button>
                        </header>

                        <div className="pdp-d-qa-body">
                          {q.question}
                        </div>

                        {q.hasReply ? (
                          <div className="pdp-d-qa-reply">
                            <div className="pdp-d-qa-reply-mark">
                              <span className="pdp-d-qa-reply-logo" aria-hidden>
                                <img src="../assets/logo-min.svg" alt="" />
                              </span>
                              <div>
                                <div className="nm">{t.qa_reply_team}</div>
                                <div className="date">
                                  <Icon name="check" size={11} stroke={2.5} />
                                  {t.qa_reply_official} · {fmtDate(q.replyCreatedISO)}
                                </div>
                              </div>
                            </div>
                            <div className="pdp-d-qa-reply-body">
                              {q.reply}
                            </div>
                          </div>
                        ) : (
                          <div className="pdp-d-qa-pending">
                            <Icon name="clock" size={13} stroke={2} />
                            {t.qa_pending}
                          </div>
                        )}
                      </article>
                    );
                  })}
                </div>

                {qaVisible < qaSorted.length && (
                  <button
                    type="button"
                    className="pdp-d-qa-more"
                    onClick={() => setQaVisible(v => v + 5)}
                  >
                    {t.qa_more(Math.min(5, qaSorted.length - qaVisible), qaSorted.length - qaVisible)}
                    <Icon name="chev" size={14} stroke={2} />
                  </button>
                )}
              </>
            )}
          </div>
        </section>
        {/* FILES / ATTACHMENTS - "Súbory na stiahnutie" / Prílohy */}
        <section className="pdp-d-section alt" id="files" ref={sectionRefs.files}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.files_title}</h2>
              <span className="pdp-d-section-sub">{t.files_sub}</span>
            </div>
            <div className="pdp-d-files">
              {(t.files || []).map((f, i) => (
                <a key={i} href="#" className="pdp-d-file" download>
                  <span className="file-ic">
                    <svg width="32" height="40" viewBox="0 0 32 40" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M4 4 L20 4 L28 12 L28 36 L4 36 Z" fill="#FCFDFE" />
                      <path d="M20 4 L20 12 L28 12" />
                      <text x="16" y="26" textAnchor="middle" fontFamily="system-ui" fontSize="7" fontWeight="700" stroke="none" fill="#DD3030">{f.kind}</text>
                    </svg>
                  </span>
                  <div className="file-body">
                    <div className="file-nm">{f.nm}</div>
                    <div className="file-meta">
                      <span>{f.kind}</span>
                      <span>·</span>
                      <span>{f.sz}</span>
                      <span>·</span>
                      <span>{f.dt}</span>
                    </div>
                  </div>
                  <span className="file-dl" aria-label="Download">
                    <Icon name="chev" size={16} stroke={2} />
                  </span>
                </a>
              ))}
            </div>
          </div>
        </section>

        {/* VIDEO REVIEWS: raw description_video HTML from product_translations.
            Renders Froala-authored <figure><iframe ...youtube/embed...></figure>
            blocks 1:1 with the real eshop. Width/height attrs are overridden
            by .pdp-d-video-real CSS for responsive 16:9 sizing. */}
        <section className="pdp-d-section" id="video" ref={sectionRefs.video}>
          <div className="pdp-d-container">
            <div className="pdp-d-section-hd">
              <h2 className="pdp-d-section-title">{t.videos_title}</h2>
              <span className="pdp-d-section-sub">{t.videos_sub}</span>
            </div>
            {D_PRODUCT.descriptionVideoHtml ? (
              <div
                className="pdp-d-video-real"
                dangerouslySetInnerHTML={{ __html: D_PRODUCT.descriptionVideoHtml }}
              />
            ) : (
              <div className="pdp-d-videos">
                {(t.videos || []).map(v => (
                  <article key={v.id} className="pdp-d-video">
                    <div className="pdp-d-video-thumb">
                      <div className="pdp-d-video-mock" />
                      <button type="button" className="pdp-d-video-play" aria-label={lang === 'hu' ? 'Lejátszás' : 'Púšťať'}>
                        <svg width="56" height="56" viewBox="0 0 56 56" aria-hidden>
                          <circle cx="28" cy="28" r="28" fill="#DD3030" />
                          <polygon points="22,18 22,38 40,28" fill="#fff" />
                        </svg>
                      </button>
                      <span className="pdp-d-video-len">{v.len}</span>
                      <span className="pdp-d-video-yt">YouTube</span>
                    </div>
                    <div className="pdp-d-video-meta">
                      <div className="pdp-d-video-nm">{v.nm}</div>
                      <div className="pdp-d-video-ch">
                        <span className="ch-dot" />
                        {v.ch}
                      </div>
                    </div>
                  </article>
                ))}
              </div>
            )}
          </div>
        </section>

        {/* RECENTLY VIEWED PRODUCTS: last main-content row before footer.
            F2 (v0.8.1): now gated behind tweaks.recently_viewed (default
            false). Real PDP has no such widget; lives only on home /
            category pages. Toggle in 'Nove vylepsenia' surfaces it. */}
        {tweaks.recently_viewed && (
          <DRecentViewed items={D_RECENT_VIEWED} t={t} toEur={toEur} lang={lang} />
        )}
      </main>

      {/* FOOTER */}
      <footer className="pdp-d-ft">
        <div className="pdp-d-container">
          <div className="pdp-d-ft-grid">
            <div className="pdp-d-ft-brand">
              <a href="#" className="lg" aria-label="NaMaximum">
                <img src="../assets/logo-namaximum.svg" alt="NaMaximum" style={{ height: 24, width: 'auto' }} />
              </a>
              {/* v0.7.10: copy comes from i18n foot_about so SK + HU
                  bundles can drift independently from the JSX. */}
              <p>{t.foot_about}</p>
              <h4 className="pdp-d-ft-soc-title">{t.foot_social_title}</h4>
              {/* v0.7.5 A4: real footer social. See Icons.jsx + PDPMobile
                  twin block - dropped 'f / ig / yt / tt' plain text and
                  the TikTok pill (real eshop wires only FB / IG / YT via
                  $socialsLinks in @base.latte). v0.7.10 added 'Sleduj
                  nas' h4 above the social pills (mirrors real h3 in
                  @base.latte). */}
              <div className="pdp-d-ft-soc">
                <a href="#" aria-label="Facebook"><Icon name="facebook" size={18} /></a>
                <a href="#" aria-label="Instagram"><Icon name="instagram" size={18} stroke={1.6} /></a>
                <a href="#" aria-label="YouTube"><Icon name="youtube" size={18} /></a>
              </div>
            </div>
            {/* v0.7.10: standalone Kontakt column matches real
                footer-contact / control text.'-'.contacts. Tel + mail
                are linked so click + tap fire native dialer / mailer. */}
            <div className="pdp-d-ft-contact">
              <h4>{t.foot_contact_title}</h4>
              <p className="addr">{t.foot_contact_addr}</p>
              <p><a href={'tel:' + t.foot_contact_tel.replace(/\s+/g, '')}>{t.foot_contact_tel}</a></p>
              <p><a href={'mailto:' + t.foot_contact_mail}>{t.foot_contact_mail}</a></p>
            </div>
            {/* v0.7.10: 4 menu sections come from i18n foot_sections
                array (same source mobile uses) so the columns cannot
                drift between platforms. Was: 3 hard-coded blocks. */}
            {(t.foot_sections || []).map((sec, idx) => (
              <div key={idx}>
                <h4>{sec.title}</h4>
                <ul>
                  {sec.links.map((lnk, i) => (
                    <li key={i}><a href="#">{lnk}</a></li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
          {/* v0.7.10: copyright + legal labels read from i18n so the
              real 'Copyright 2026 namaximum.sk - Vytvorenie e-shopu
              na mieru od Blueweb s.r.o.' string stays single-sourced
              with mobile. */}
          <div className="pdp-d-ft-bottom">
            <span>{t.foot_copy}</span>
            <span className="legal">
              <a href="#">{t.foot_legal_privacy}</a>
              <a href="#">{t.foot_legal_cookies}</a>
              <a href="#">{t.foot_legal_terms}</a>
            </span>
          </div>
        </div>
      </footer>

      {/* TOAST */}
      <div className="pdp-d-toast-wrap">
        {toasts.map(tst => (
          <div key={tst.id} className={"pdp-d-toast" + (tst.kind === 'err' ? ' err' : '')}>
            <span className="ic"><Icon name={tst.kind === 'err' ? 'x' : 'checkCircle'} size={16} stroke={2.5} /></span>
            {tst.msg}
          </div>
        ))}
      </div>

      {/* v0.7.1 polish: gallery LIGHTBOX. Click the hero stage to open
          a fullscreen viewer with prev/next arrows + close affordances
          (X button, backdrop click, ESC + arrow keys). Mirrors the
          mobile .p-lightbox markup; class names are .pdp-d-lightbox
          for desktop scoping. Z-index 9000 so it stacks above the
          legacy showcase tweak panel and the new floating one. */}
      {lightbox !== null && (() => {
        const idx = lightbox;
        const slide = D_GAL_SLIDES[idx] || D_GAL_SLIDES[0];
        const total = D_GAL_SLIDES.length;
        const prev = () => setLightbox((idx - 1 + total) % total);
        const next = () => setLightbox((idx + 1) % total);
        return (
          <div
            className="pdp-d-lightbox"
            role="dialog"
            aria-modal="true"
            aria-label={t.lightbox_close}
            onClick={(e) => { if (e.target === e.currentTarget) setLightbox(null); }}
          >
            <button
              type="button"
              className="pdp-d-lightbox-close"
              onClick={() => setLightbox(null)}
              aria-label={t.lightbox_close}
              title={t.lightbox_close}
            >
              <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <line x1="6" y1="6" x2="18" y2="18" />
                <line x1="18" y1="6" x2="6" y2="18" />
              </svg>
            </button>
            <button
              type="button"
              className="pdp-d-lightbox-nav is-prev"
              onClick={(e) => { e.stopPropagation(); prev(); }}
              aria-label={t.lightbox_prev}
              title={t.lightbox_prev}
            >
              <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <polyline points="15 6 9 12 15 18" />
              </svg>
            </button>
            <div className="pdp-d-lightbox-stage" onClick={(e) => e.stopPropagation()}>
              {(slide.kind === 'variant' && D_PRODUCT.mainImage) || slide.kind === 'image'
                ? <img src={galleryImage(slide)} alt={t.product_title} />
                : <ProductVisual kind={slide.kind === 'variant' ? 'tub-lg' : slide.kind} color={slide.color} label={slide.label} sub={slide.sub || selSize.label.toUpperCase()} />}
            </div>
            <button
              type="button"
              className="pdp-d-lightbox-nav is-next"
              onClick={(e) => { e.stopPropagation(); next(); }}
              aria-label={t.lightbox_next}
              title={t.lightbox_next}
            >
              <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <polyline points="9 6 15 12 9 18" />
              </svg>
            </button>
            <div className="pdp-d-lightbox-counter" aria-hidden="true">{idx + 1} / {total}</div>
          </div>
        );
      })()}

      {/* FLOATING TWEAK PANEL (D3) - bottom-right FAB + slide-in panel for all
          28 tweak keys. Coexists with the legacy showcase-shell tweak panel
          (templates/pdp-desktop.html); both write to window.__TWEAKS and
          dispatch tweakschange, so they stay in sync. */}
      <DTweakPanel
        tweaks={tweaks}
        onChange={handleTweakChange}
        onReset={handleTweakReset}
        t={t}
      />
    </div>
  );
}

window.DesktopPDP = DesktopPDP;
