/* === ExamCompare (hub-only), BundleStrip, Pricing, FAQ, FinalCTA, Footer === */

/* Three-up exam cards used on the hub */
function ExamCards() {
  const cards = [
    {
      href: "etablerer.html",
      num: "01",
      mark: <Glyph.Tray size={64} color="#B4541F" />,
      accent: "#B4541F",
      bg: "#F7E3D2",
      title: "Etablererprøven",
      blurb: "For deg som vil starte eller drive serveringssted — kafé, restaurant, bar, kantine.",
      bullets: ["Serveringsloven §5", "Skatt, regnskap, HMS", "50 spørsmål · 90 min", "Krav til 80% riktig"],
      law: "Serveringsloven",
    },
    {
      href: "skjenke.html",
      num: "02",
      mark: <Glyph.Glass size={64} color="#8B2D3E" />,
      accent: "#8B2D3E",
      bg: "#F4DDE1",
      title: "Skjenkebevilling",
      blurb: "For styrer/stedfortreder ved sted som skjenker alkohol — bar, restaurant, hotell, festival.",
      bullets: ["Alkoholloven kap. 1–8", "Skjenketider & aldersgrenser", "30 spørsmål · 60 min", "Krav til 80% riktig"],
      law: "Alkoholloven",
    },
    {
      href: "salg.html",
      num: "03",
      mark: <Glyph.Storefront size={64} color="#1A5A4F" />,
      accent: "#1A5A4F",
      bg: "#D5E6E0",
      title: "Salgsbevilling",
      blurb: "For styrer/stedfortreder i butikk eller virksomhet som selger alkohol — dagligvare, kiosk.",
      bullets: ["Alkoholloven kap. 1–3", "Salgstider & kontroll", "30 spørsmål · 60 min", "Krav til 80% riktig"],
      law: "Alkoholloven",
    },
  ];
  return (
    <div className="exam-cards">
      {cards.map((c,i)=>(
        <a key={i} href={c.href} className="exam-card card"
           style={{"--ec-accent": c.accent, "--ec-accent-soft": c.bg}}>
          <div className="exam-card-top exam-card-top--accent">
            <div className="exam-card-mark">{c.mark}</div>
            <div style={{textAlign:'right'}}>
              <div className="exam-card-num">PRØVE {c.num}</div>
              <div className="mono small" style={{color:'var(--muted)', marginTop:4}}>{c.law}</div>
            </div>
          </div>
          <div className="exam-card-title"><h3>{c.title}</h3></div>
          <div className="exam-card-body">
            <p>{c.blurb}</p>
          </div>
          <ul className="exam-card-list">
            {c.bullets.map((b,j)=>(<li key={j}><span className="dot" />{b}</li>))}
          </ul>
          <div className="exam-card-meta">
            <span className="mono small">Inkludert i tilgangen</span>
            <span className="exam-card-cta">Åpne landingsside →</span>
          </div>
        </a>
      ))}
    </div>
  );
}

function ExamCompare() {
  const rows = [
    { label: "Hvem prøven er for",
      etablerer: "Den som vil starte/drive serveringssted",
      skjenke: "Styrer/stedfortreder ved skjenkested",
      salg: "Styrer/stedfortreder ved utsalgssted" },
    { label: "Lovgrunnlag",
      etablerer: "Serveringsloven",
      skjenke: "Alkoholloven",
      salg: "Alkoholloven" },
    { label: "Hvem holder prøven",
      etablerer: "Kommunen",
      skjenke: "Kommunen",
      salg: "Kommunen" },
    { label: "Antall spørsmål",
      etablerer: "50",
      skjenke: "30",
      salg: "30" },
    { label: "Tid på prøven",
      etablerer: "90 min",
      skjenke: "60 min",
      salg: "60 min" },
    { label: "Krav for å bestå",
      etablerer: "80 %",
      skjenke: "80 %",
      salg: "80 %" },
    { label: "Hjelpemidler",
      etablerer: "Ingen",
      skjenke: "Ingen",
      salg: "Ingen" },
    { label: "Prøvegebyr (typisk)",
      etablerer: "kr 400",
      skjenke: "kr 400",
      salg: "kr 400" },
  ];
  return (
    <section id="compare" style={{background:'var(--bg-soft)'}}>
      <div className="container">
        <div className="section-head">
          <span className="eyebrow"><span className="dot" />SAMMENLIGN PRØVENE</span>
          <h2>Hvilken prøve trenger du — egentlig?</h2>
          <p className="lead">Det er lett å gå seg vill i kommunens skjemaer. Her er forskjellene på én side, slik de praktiseres i 2026.</p>
        </div>
        <div className="compare-wrap">
          <table className="compare-table">
            <thead>
              <tr>
                <th></th>
                <th><span className="col-head"><span className="swatch" style={{background:'#B4541F'}} />Etablerer</span></th>
                <th><span className="col-head"><span className="swatch" style={{background:'#8B2D3E'}} />Skjenke</span></th>
                <th><span className="col-head"><span className="swatch" style={{background:'#1A5A4F'}} />Salg</span></th>
              </tr>
            </thead>
            <tbody>
              {rows.map((r,i)=>(
                <tr key={i}>
                  <th>{r.label}</th>
                  <td>{r.etablerer}</td>
                  <td>{r.skjenke}</td>
                  <td>{r.salg}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </section>
  );
}
window.ExamCards = ExamCards;
window.ExamCompare = ExamCompare;

/* Bundle strip — shown above pricing on niche pages */
function BundleStrip({ otherExams }) {
  return (
    <div className="bundle-strip">
      <div className="bundle-strip-icon">3</div>
      <div className="bundle-strip-text">
        <strong>Alle tre prøvene i én tilgang</strong>
        <p>Uansett hvilken prøve du tar — du får øve på alle. Ingen ekstra kostnad, ingen kupongkode.</p>
      </div>
      <div className="bundle-strip-pills">
        {otherExams.map((o,i)=>(
          <span key={i} className="pill">{o.icon} {o.label}</span>
        ))}
      </div>
    </div>
  );
}
window.BundleStrip = BundleStrip;

/* ============================================================
 * Pricing + Checkout
 * ============================================================
 * Tier data is built from window.PRICES (loaded via prices.js — the
 * shared master in frontend/websites/_shared/prices.js, mirrored into
 * this folder). planSlug comes from window.__PAGE__.planSlug, which is
 * set per HTML:
 *   - index.html  → 'bevilling' (the bundle covering all 3 prøver)
 *   - etablerer/skjenke/salg.html → their own slug
 *
 * Checkout flow: click tier → opens inline modal → email + "Betal med kort"
 * → POST to stripe-checkout edge fn → redirect to Stripe-hosted checkout.
 * On success, Stripe redirects to /Takk?session_id=...&plan=...
 * Webhook splice in supabase/functions/stripe-webhook/index.ts grants the
 * 3 underlying plan_ids when planSlug === 'bevilling'.
 *
 * Slug + tier ID contract matches Drone's pricing.jsx (see PRICING.md).
 */

// ---- Config (mirrors Drone/pricing.jsx) ----
const SUPABASE_URL = 'https://eqihrzxhrrqqpfgteqye.supabase.co';
const STRIPE_CHECKOUT_FN = `${SUPABASE_URL}/functions/v1/stripe-checkout`;
const CAPTURE_EMAIL_FN = `${SUPABASE_URL}/functions/v1/capture-email`;
const BASE_URL = typeof window !== 'undefined' ? window.location.origin + window.location.pathname.replace(/[^/]+$/, '') : '';
const CURRENCY = 'NOK';

// ---- DataLayer helper (GTM-friendly, consent-gated downstream) ----
function pushDataLayer(event, payload = {}) {
  if (typeof window === 'undefined') return;
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({ event, ...payload });
}

// ---- Attribution capture (mirrors Drone/pricing.jsx#captureAttribution) ----
// Fire-and-forget: store a valid email the moment it's entered (blur), even if
// the visitor never proceeds to payment. Store-only — no email is ever sent to
// these captures. Guarded so a given address posts at most once per page load.
let _capturedEmail = null;
function captureEmailLead(email, planSlug, tierSlug, attribution) {
  if (!/^\S+@\S+\.\S+$/.test(email || '')) return;
  const clean = email.toLowerCase().trim();
  if (clean === _capturedEmail) return;
  _capturedEmail = clean;
  try {
    fetch(CAPTURE_EMAIL_FN, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: clean, planSlug, tierSlug, attribution }),
      keepalive: true,
    }).catch(() => {});
  } catch (_) { /* ignore */ }
}

function captureAttribution() {
  if (typeof window === 'undefined') return {};
  const STORAGE_KEY = 'th_attr_v1';
  try {
    const existing = sessionStorage.getItem(STORAGE_KEY);
    if (existing) {
      const cached = JSON.parse(existing);
      // Referral visits count as medium=referral unless explicitly tagged.
      if (!cached.utm_medium && readStoredRef()) cached.utm_medium = 'referral';
      // Click-IDs fill in where missing — an ad-click must not be swallowed
      // by a cached organic first-touch (CAPI needs them to match the click).
      const q = new URLSearchParams(window.location.search);
      let dirty = false;
      for (const k of ['gclid', 'gbraid', 'wbraid', 'fbclid', 'ttclid']) {
        if (!cached[k] && q.get(k)) { cached[k] = q.get(k); dirty = true; }
      }
      if (dirty) { try { sessionStorage.setItem(STORAGE_KEY, JSON.stringify(cached)); } catch (_) {} }
      return cached;
    }
  } catch (_) { /* sessionStorage disabled — fall through and recompute */ }
  const params = new URLSearchParams(window.location.search);
  const attr = {
    utm_source:   params.get('utm_source')   || null,
    utm_medium:   params.get('utm_medium')   || null,
    utm_campaign: params.get('utm_campaign') || null,
    utm_term:     params.get('utm_term')     || null,
    utm_content:  params.get('utm_content')  || null,
    gclid:        params.get('gclid')        || null,
    gbraid:       params.get('gbraid')       || null,
    wbraid:       params.get('wbraid')       || null,
    fbclid:       params.get('fbclid')       || null,
    ttclid:       params.get('ttclid')       || null,
    landing_page: window.location.href.split('?')[0],
    referrer:     document.referrer || null,
  };
  // Referral visits count as medium=referral unless explicitly tagged.
  if (!attr.utm_medium && readStoredRef()) attr.utm_medium = 'referral';
  try { sessionStorage.setItem(STORAGE_KEY, JSON.stringify(attr)); } catch (_) {}
  return attr;
}

// ---- Referral capture (v2) ----
// docs/REFERRAL_V2_PLAN.md WP-3. ?ref= (or ?vervekode=) carries the personal
// code across domains — the /r/{kode}-landing on teorihuset.no appends it to
// outbound LP links, since localStorage never crosses origins. Mirrors the
// th_attr_v1 pattern above, but in localStorage (the code must survive the
// tab) with a 90-day expiry enforced on read.
const REF_STORAGE_KEY = 'th_ref_v1';
const REF_TTL_MS = 90 * 24 * 60 * 60 * 1000;
// TH-XXXXXX (v2) or legacy-ish codes: uppercase alnum + dash, 4-16 chars.
const REF_CODE_RE = /^[A-Z0-9][A-Z0-9-]{2,14}[A-Z0-9]$/;

function normalizeRefCode(raw) {
  if (!raw) return null;
  const code = String(raw).trim().toUpperCase();
  return REF_CODE_RE.test(code) ? code : null;
}

function readStoredRef() {
  try {
    const raw = localStorage.getItem(REF_STORAGE_KEY);
    if (!raw) return null;
    const stored = JSON.parse(raw);
    const code = normalizeRefCode(stored && stored.code);
    const fresh = stored && typeof stored.ts === 'number' && (Date.now() - stored.ts) < REF_TTL_MS;
    if (!code || !fresh) {
      localStorage.removeItem(REF_STORAGE_KEY);
      return null;
    }
    return code;
  } catch (_) { return null; }
}

function captureReferral() {
  if (typeof window === 'undefined') return { code: null, fromUrl: false };
  const params = new URLSearchParams(window.location.search);
  const fromUrl = normalizeRefCode(params.get('ref') || params.get('vervekode'));
  if (fromUrl) {
    try { localStorage.setItem(REF_STORAGE_KEY, JSON.stringify({ code: fromUrl, ts: Date.now() })); } catch (_) {}
    pushDataLayer('referral_link_visit', {
      referral_code: fromUrl,
      plan_slug: (window.__PAGE__ && window.__PAGE__.planSlug) || 'bevilling',
    });
    return { code: fromUrl, fromUrl: true };
  }
  return { code: readStoredRef(), fromUrl: false };
}

// Run at load so the code persists even if the visitor doesn't buy this visit.
const CAPTURED_REF = captureReferral();

// ---- Referral code field (v2) ----
// Collapsed link by default; auto-expanded + prefilled when a code was
// captured from ?ref=/th_ref_v1. Deliberately promises no amount client-side
// for unvalidated codes — stripe-checkout validates and shows the discount.
function ReferralField({ code, setCode, disabled }) {
  const [open, setOpen] = React.useState(!!CAPTURED_REF.code);
  if (!open) {
    return (
      <button type="button" className="bv-ref-toggle" onClick={() => setOpen(true)}>
        Har du en vervekode?
      </button>
    );
  }
  const isCaptured = !!code && code === CAPTURED_REF.code;
  return (
    <label className="bv-field">
      <span className="bv-field-label">Vervekode</span>
      <input
        type="text"
        autoComplete="off"
        autoCapitalize="characters"
        spellCheck="false"
        placeholder="TH-XXXXXX"
        value={code}
        onChange={e => setCode(e.target.value.toUpperCase())}
        disabled={disabled}
      />
      <span className="bv-field-hint">
        {isCaptured ? 'Vervekode registrert. Rabatten vises i betalingsvinduet.' : 'Rabatten vises i betalingsvinduet.'}
      </span>
    </label>
  );
}

// Build TIER cards from window.PRICES + planSlug. The display copy below
// (blurb, features) is intentionally simple — copy-pass owned by editorial.
// 14d is always anchored as "Mest populær" per PRICING.md.
function buildTiers(planSlug) {
  const prices = (window.PRICES && window.PRICES[planSlug]) || {};
  const isBundle = planSlug === 'bevilling';
  const bundleBlurbs = {
    '3d':  'Du har prøven snart og trenger en intensivkur.',
    '14d': 'Den anbefalte ruten — nok tid til å forstå loven.',
    '30d': 'For deg som vil ta tiden i bruk — eller flere prøver.',
  };
  const singleBlurbs = {
    '3d':  'Intensiv repetisjon rett før prøvedato.',
    '14d': 'Vår anbefaling — god tid til å mestre alle temaer.',
    '30d': 'Best for deg som starter helt fra bunnen.',
  };
  const blurbs = isBundle ? bundleBlurbs : singleBlurbs;
  // Feature lines — short, factual. Copy-pass owned by editorial; specific
  // counts (e.g. "609 spørsmål") deliberately not hardcoded here so a copy
  // refresh doesn't require a code change.
  const bundleFeatures = {
    '3d':  ['Tilgang i 3 dager', 'Alle tre prøvene inkludert', 'Ubegrenset prøveeksamen', 'Mobil og web'],
    '14d': ['Tilgang i 14 dager', 'Alle tre prøvene inkludert', 'Adaptiv læringsplan', 'Forklaring + lovreferanse', 'Mobil og web'],
    '30d': ['Tilgang i 30 dager', 'Alle tre prøvene inkludert', 'Adaptiv læringsplan', 'Beståttgaranti (se vilkår)', 'Prioritert support'],
  };
  const singleFeatures = {
    '3d':  ['Tilgang i 3 dager', 'Ubegrenset prøveeksamen', 'Forklaring + lovreferanse', 'Mobil og web'],
    '14d': ['Tilgang i 14 dager', 'Adaptiv læringsplan', 'Forklaring + lovreferanse', 'Mobil og web'],
    '30d': ['Tilgang i 30 dager', 'Adaptiv læringsplan', 'Beståttgaranti (se vilkår)', 'Prioritert support'],
  };
  const features = isBundle ? bundleFeatures : singleFeatures;
  return [
    { id: '3d',  name: '3 dager',  days: 3,  price: prices['3d'],  blurb: blurbs['3d'],  features: features['3d'],  cta: 'Velg 3 dager',  recommended: false, badge: null },
    { id: '14d', name: '14 dager', days: 14, price: prices['14d'], blurb: blurbs['14d'], features: features['14d'], cta: 'Velg 14 dager', recommended: true,  badge: 'MEST POPULÆR' },
    { id: '30d', name: '30 dager', days: 30, price: prices['30d'], blurb: blurbs['30d'], features: features['30d'], cta: 'Velg 30 dager', recommended: false, badge: null },
  ];
}

// Inline checkout modal — opens when a tier card's CTA is clicked.
// Submit POSTs to stripe-checkout edge fn; backend creates the Stripe Checkout
// Session, returns { url }, and we redirect the browser there.
function CheckoutModal({ open, tier, planSlug, onClose }) {
  const [email, setEmail] = React.useState('');
  const [refCode, setRefCode] = React.useState(CAPTURED_REF.code || '');
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    if (open) { setEmail(''); setError(null); setLoading(false); }
  }, [open]);

  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape' && !loading) onClose(); };
    document.body.classList.add('bv-modal-locked');
    document.addEventListener('keydown', onKey);
    return () => {
      document.body.classList.remove('bv-modal-locked');
      document.removeEventListener('keydown', onKey);
    };
  }, [open, loading, onClose]);

  if (!open || !tier) return null;

  const emailValid = /^\S+@\S+\.\S+$/.test(email);
  const canPay = emailValid && !loading;

  const handlePay = async () => {
    setError(null);
    if (!emailValid) { setError('Skriv inn en gyldig e-postadresse.'); return; }
    pushDataLayer('begin_checkout', {
      ecommerce: {
        currency: CURRENCY,
        value: tier.price,
        items: [{
          item_id: `${planSlug}_${tier.id}`,
          item_name: `${tier.days} dager · ${planSlug}`,
          item_category: planSlug,
          price: tier.price,
          quantity: 1,
        }],
      },
    });
    // Referral: typed code wins; falls back to the stored ?ref= capture.
    // Backend validates and responds { url, referralApplied } — invalid
    // codes never block checkout, they just skip the discount.
    const referralCode = normalizeRefCode(refCode) || readStoredRef() || undefined;
    if (referralCode) {
      pushDataLayer('referral_code_applied', { referral_code: referralCode, plan_slug: planSlug });
    }
    setLoading(true);
    try {
      const resp = await fetch(STRIPE_CHECKOUT_FN, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          planSlug,
          tierSlug: tier.id,
          customer_email: email,
          referralCode,
          attribution: captureAttribution(),
          success_url: `${BASE_URL}Takk?session_id={CHECKOUT_SESSION_ID}&plan=${tier.id}&slug=${planSlug}`,
          cancel_url: `${BASE_URL}Priser?retry=1&plan=${tier.id}&slug=${planSlug}`,
        }),
      });
      const data = await resp.json();
      if (!resp.ok || !data.url) throw new Error(data.error || 'Kunne ikke starte betaling. Prøv igjen.');
      window.location.href = data.url;
    } catch (e) {
      console.error('Checkout error', e);
      setError(e.message || 'Noe gikk galt. Prøv igjen.');
      setLoading(false);
    }
  };

  return (
    <div className="bv-modal-overlay" role="dialog" aria-modal="true" onClick={(e)=>{ if (e.target.classList.contains('bv-modal-overlay') && !loading) onClose(); }}>
      <div className="bv-modal card">
        <button type="button" className="bv-modal-close" onClick={onClose} disabled={loading} aria-label="Lukk">✕</button>
        <div className="bv-modal-eyebrow"><span className="dot" />FULLFØR KJØP</div>
        <h3 className="bv-modal-title">{tier.days} dager — {tier.price} kr</h3>
        <p className="muted small" style={{margin:'4px 0 16px'}}>Engangsbeløp. Tilgang umiddelbart. Kvittering på e-post.</p>

        <label className="bv-field">
          <span className="bv-field-label">E-post</span>
          <input
            type="email"
            autoComplete="email"
            inputMode="email"
            placeholder="navn@eksempel.no"
            value={email}
            onChange={e=>setEmail(e.target.value)}
            onBlur={() => captureEmailLead(email, planSlug, tier.id, captureAttribution())}
            disabled={loading}
          />
          <span className="bv-field-hint">Vi sender innloggingslenke og kvittering hit.</span>
        </label>

        <ReferralField code={refCode} setCode={setRefCode} disabled={loading} />

        {error && <div className="bv-modal-error">{error}</div>}

        <button
          type="button"
          className="btn btn-primary btn-block btn-lg"
          onClick={handlePay}
          disabled={!canPay}
          style={{marginTop:14}}
        >
          {loading ? 'Sender til betaling…' : <>Betal med kort <span className="arrow">→</span></>}
        </button>

        <div className="bv-modal-trust mono small muted">
          🔒 Sikker betaling via Stripe{tier.id === '30d' && <> · 🛡 Bestått-garanti (se <a href="Vilkar">vilkår</a>)</>}
        </div>
        <div className="bv-modal-legal small muted" style={{marginTop:10, textAlign:'center'}}>
          Ved å gå videre godtar du <a href="Vilkar">Vilkår</a> og <a href="Personvern">Personvern</a>.
        </div>
      </div>
    </div>
  );
}
window.CheckoutModal = CheckoutModal;

function Pricing({ examConfig }) {
  const planSlug = examConfig.planSlug || 'bevilling';
  const TIERS = React.useMemo(() => buildTiers(planSlug), [planSlug]);
  const [selected, setSelected] = React.useState(TIERS.find(t=>t.recommended)?.id || TIERS[0].id);
  const [modalTier, setModalTier] = React.useState(null);

  // Fire view_item_list once on mount
  React.useEffect(() => {
    pushDataLayer('view_item_list', {
      ecommerce: {
        item_list_name: `${planSlug}_pricing`,
        items: TIERS.filter(t => t.price != null).map(t => ({
          item_id: `${planSlug}_${t.id}`,
          item_name: `${t.days} dager`,
          item_category: planSlug,
          price: t.price,
          quantity: 1,
        })),
      },
    });
  }, [planSlug, TIERS]);

  const handleSelect = (id) => {
    if (id === selected) return;
    setSelected(id);
    const t = TIERS.find(x => x.id === id);
    if (t && t.price != null) {
      pushDataLayer('select_item', {
        ecommerce: {
          item_list_name: `${planSlug}_pricing`,
          items: [{ item_id: `${planSlug}_${t.id}`, item_name: `${t.days} dager`, item_category: planSlug, price: t.price, quantity: 1 }],
        },
      });
    }
  };

  const handleCta = (tier) => {
    if (tier.price == null) return;
    setSelected(tier.id);
    setModalTier(tier);
  };

  return (
    <section id="pricing" className="pricing">
      <div className="container">
        <div className="section-head pricing-head">
          <span className="eyebrow"><span className="dot" />PRISER {planSlug === 'bevilling' ? '· ALLE TRE PRØVENE' : '· ' + planSlug.toUpperCase()}</span>
          <h2>Én engangspris. Ingen abonnement, ingen fornyelse.</h2>
          <p className="lead">{planSlug === 'bevilling' ? 'Alle tre prøvene er inkludert i hver plan. Full tilgang fra dag én — betal enkelt med kort.' : 'Velg perioden som passer deg. Full tilgang fra dag én — betal enkelt med kort.'}</p>
        </div>

        {examConfig.otherExams && (
          <BundleStrip otherExams={examConfig.otherExams} />
        )}

        <div className="pricing-grid">
          {TIERS.map(p => {
            const isSel = selected === p.id;
            const perDay = p.price != null ? Math.round(p.price / p.days) : null;
            return (
              <div key={p.id}
                   className={"plan card " + (p.recommended ? 'plan--rec ' : '') + (isSel ? 'plan--sel' : '')}
                   onClick={()=>handleSelect(p.id)}>
                {p.badge && <div className="plan-badge">{p.badge}</div>}
                <div className="plan-head">
                  <h3>{p.name}</h3>
                  <p className="muted">{p.blurb}</p>
                </div>
                <div className="plan-price">
                  <span className="plan-price-num">{p.price ?? '—'}</span>
                  <span className="plan-price-cur">kr</span>
                </div>
                <div className="plan-perday mono small muted">{perDay != null ? `≈ ${perDay} kr / dag · engangskjøp` : 'Pris kommer'}</div>
                <ul className="plan-features">
                  {p.features.map((f,i)=>(
                    <li key={i}><span className="check-circle">✓</span>{f}</li>
                  ))}
                </ul>
                <button
                  type="button"
                  className={"btn btn-block " + (p.recommended ? 'btn-accent' : 'btn-primary')}
                  onClick={(e)=>{ e.stopPropagation(); handleCta(p); }}
                  disabled={p.price == null}
                >
                  {p.cta} <span className="arrow">→</span>
                </button>
                <div className="plan-foot mono small muted">
                  Ingen automatisk fornyelse · Kortbetaling
                </div>
              </div>
            );
          })}
        </div>

        {/* Bundle upsell card — only on niche pages, points to the bundle deal */}
        {planSlug !== 'bevilling' && window.PRICES && window.PRICES['bevilling'] && (
          <a href="index.html#pricing" className="bv-bundle-upsell card">
            <div className="bv-bundle-upsell-icon">3</div>
            <div className="bv-bundle-upsell-body">
              <strong>Trenger du flere prøver?</strong>
              <p>Bundle dekker etablerer + skjenke + salg for {window.PRICES['bevilling']['14d']} kr (14 dager). Spar mot å kjøpe hver for seg.</p>
            </div>
            <span className="bv-bundle-upsell-cta">Se bundle <span className="arrow">→</span></span>
          </a>
        )}

        <div className="pricing-trust">
          <div className="pt-item">
            <span className="pt-icon" style={{color:'var(--accent)'}}>🛡</span>
            <div>
              <strong>Beståttgaranti</strong>
              <p className="small muted">Gjelder 30-dagers pakken. Aktiv bruk + bestått prøvekrav i app-en — <a href="Vilkar">se §9 i vilkår</a>.</p>
            </div>
          </div>
          <div className="pt-item">
            <span className="pt-icon" style={{color:'var(--accent)'}}>🔒</span>
            <div>
              <strong>Trygg betaling</strong>
              <p className="small muted">Kortbetaling via Stripe. Vi lagrer ikke kortdata. GDPR-kompatibel.</p>
            </div>
          </div>
          <div className="pt-item">
            <span className="pt-icon" style={{color:'var(--accent)'}}>↺</span>
            <div>
              <strong>Angrerett</strong>
              <p className="small muted">14 dager før første pålogging. Bortfaller når Tjenesten tas i bruk (<a href="Vilkar">§6</a>).</p>
            </div>
          </div>
        </div>
      </div>

      <CheckoutModal open={modalTier != null} tier={modalTier} planSlug={planSlug} onClose={()=>setModalTier(null)} />
    </section>
  );
}

function FAQ({ examConfig }) {
  const baseItems = [
    {
      q: 'Er innholdet oppdatert mot kommunens prøve?',
      a: 'Ja. Spørsmålene og forklaringene gjenspeiler praksis for kunnskapsprøvene og etablererprøven slik de holdes av kommunene i 2026. Vi oppdaterer banken kontinuerlig når Helsedirektoratet eller kommunene endrer rutiner.',
    },
    {
      q: 'Hva er forskjellen på dette og en gratis side?',
      a: 'Gratisalternativene kjører deg gjennom et knippe gjentakende spørsmål uten plan. Bevillingen er adaptiv — den lærer hva du sliter med, forklarer på norsk med lovreferanser, og lar deg ta full prøveeksamen som speiler den ekte. Du betaler for å bestå raskere.',
    },
    {
      q: 'Hva betyr "Bestå-garantien"?',
      a: 'Hvis du har fullført læringsplanen vår og består tre prøveeksamener på rad i appen, men likevel stryker på den offisielle prøven hos kommunen — får du hele beløpet tilbake. Send oss en kopi av resultatet, så fikser vi resten.',
    },
    {
      q: 'Får jeg tilgang til alle tre prøvene?',
      a: 'Ja — en lisens åpner Etablererprøven, Skjenkebevilling og Salgsbevilling. Du kan øve på alle, eller fokusere på den ene du trenger akkurat nå. Spørsmålsbankene er separate men deler samme tilgang.',
    },
    {
      q: 'Hvor mye må jeg øve hver dag?',
      a: 'De fleste bruker 15–20 minutter daglig. Med 30-dagers planen vår kommer du gjennom alle tre prøvene før møtet med kommunen. Du kan også kjøre intensivt i 7 dager hvis du har det travelt.',
    },
    {
      q: 'Trenger jeg å laste ned en app?',
      a: 'Nei. Bevillingen fungerer i nettleseren på mobil, nettbrett og PC — ingen nedlasting nødvendig. Fremgangen din lagres på kontoen din, så du kan bytte enhet når du vil.',
    },
    {
      q: examConfig.examFaqQ || 'Hvor og hvordan tar jeg den faktiske prøven?',
      a: examConfig.examFaqA || 'Prøven tas hos kommunen der virksomheten skal drives. Du bestiller tid via kommunens nettside, betaler prøvegebyret (typisk 400 kr) og møter opp med legitimasjon. Prøven er digital, og du får svaret samme dag.',
    },
    {
      q: 'Kan jeg dele kontoen min med en kollega?',
      a: 'Hver lisens er knyttet til én person fordi læringsplanen er personlig. Trenger dere flere tilganger, kjøper hver person sin egen — eller ta kontakt på hei@teorihuset.no hvis dere er mange.',
    },
  ];
  const [open, setOpen] = React.useState(0);
  return (
    <section id="faq" className="faq">
      <div className="container">
        <div className="faq-grid">
          <div className="faq-side">
            <span className="eyebrow"><span className="dot" />FAQ</span>
            <h2>Spørsmål før du<br/>melder deg opp.</h2>
            <p className="lead">Finner du ikke svaret? Skriv til <a href="mailto:hei@teorihuset.no" className="link">hei@teorihuset.no</a> — vi svarer raskt på hverdager.</p>
            <div className="faq-side-card card">
              <div className="row gap-3">
                <Glyph.Stamp size={48} />
                <div>
                  <strong>Stryker du på første forsøk?</strong>
                  <p className="small muted">Du får 100% tilbake. Bare videresend kvitteringen fra kommunen.</p>
                </div>
              </div>
            </div>
          </div>
          <div className="faq-list">
            {baseItems.map((it,i)=>(
              <button key={i}
                      className={"faq-item " + (open===i?'open':'')}
                      onClick={()=>setOpen(open===i?-1:i)}>
                <div className="faq-q">
                  <span>{it.q}</span>
                  <span className="faq-toggle" aria-hidden>{open===i?'−':'+'}</span>
                </div>
                {open===i && <div className="faq-a">{it.a}</div>}
              </button>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

function FinalCTA({ examConfig }) {
  const slug = (examConfig && examConfig.planSlug) || 'bevilling';
  const floorPrice = (window.PRICES && window.PRICES[slug] && window.PRICES[slug]['3d']) || 249;
  return (
    <section className="final-cta">
      <div className="container">
        <div className="final-cta-card">
          <div className="final-cta-bg" aria-hidden>
            <Glyph.Glass size={120} fill={0.6} />
            <Glyph.Storefront size={120} />
            <Glyph.Tray size={120} />
            <Glyph.Document size={120} />
            <Glyph.Clock size={120} />
            <Glyph.Age size={120} value={18} />
          </div>
          <div className="final-cta-inner">
            <span className="eyebrow" style={{color:'rgba(255,255,255,0.7)'}}><span className="dot" style={{background:'var(--signal)'}}/>KLAR FOR Å BESTÅ?</span>
            <h2>{examConfig.finalCtaTitle || 'Du kan booke kommunens prøve om 10 dager.'}</h2>
            <p className="lead">Start i dag for {floorPrice} kr. Ingen abonnement. Pengene tilbake hvis du stryker.</p>
            <div className="row gap-3" style={{flexWrap:'wrap', marginTop:24}}>
              <a href="#pricing" className="btn btn-accent btn-lg">Kom i gang nå <span className="arrow">→</span></a>
              <a href="#demo" className="btn btn-ghost btn-lg" style={{borderColor:'rgba(255,255,255,0.25)', color:'#fff'}}>Prøv gratis først</a>
            </div>
            <div className="row gap-6" style={{marginTop:24, flexWrap:'wrap', color:'rgba(255,255,255,0.7)'}}>
              <span>✓ Sikker kortbetaling</span>
              <span>✓ Engangskjøp</span>
              <span>✓ Trygg betaling</span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function Footer() {
  // Brand mark "Bevillingen" preserved as visible sub-brand text — copy-pass
  // decision lives with editorial. Org.nr + selskap-fakta er ekte (Blue Media
  // AS, 933 421 120) — endring her krever oppdatering av Vilkar §1 også.
  return (
    <footer className="ft">
      <div className="container">
        <div className="ft-grid">
          <div className="ft-brand">
            <a href="index.html" className="bv-logo">
              <span className="bv-logo-mark"><BevLogo size={32} /></span>
              <span className="bv-logo-word">Bevillingen</span>
            </a>
            <p className="muted small" style={{marginTop:16, maxWidth:300}}>
              Norsk eksamenstrening for de tre bevillings­prøvene — del av Teorihuset.
            </p>
            <div className="row gap-2" style={{marginTop:16}}>
              <span className="no-flag-strip"><i className="r"/><i className="w"/><i className="b"/><i className="w2"/><i className="r2"/></span>
              <span className="mono small muted">Made in Norway</span>
            </div>
          </div>
          <div className="ft-col">
            <h4>Prøvene</h4>
            <a href="etablerer.html">Etablererprøven</a>
            <a href="skjenke.html">Skjenkebevilling</a>
            <a href="salg.html">Salgsbevilling</a>
            <a href="index.html">Sammenlign</a>
          </div>
          <div className="ft-col">
            <h4>Produkt</h4>
            <a href="#how">Slik fungerer det</a>
            <a href="#features">Funksjoner</a>
            <a href="Priser">Priser</a>
            <a href="Sample">Prøv gratis</a>
          </div>
          <div className="ft-col">
            <h4>Selskap</h4>
            <a href="https://teorihuset.no/">Teorihuset</a>
            <a href="mailto:hei@teorihuset.no">Kontakt</a>
          </div>
          <div className="ft-col">
            <h4>Juridisk</h4>
            <a href="Vilkar">Vilkår</a>
            <a href="Personvern">Personvern</a>
            <button type="button" className="bv-link-btn" onClick={() => window.openConsentPreferences && window.openConsentPreferences()}>Endre samtykke</button>
          </div>
        </div>
        <div className="ft-foot">
          <span className="mono small muted">© 2026 teorihuset.no — Made in Norway</span>
          <span className="mono small muted">Ikke tilknyttet kommunen eller Helsedirektoratet</span>
        </div>
      </div>
    </footer>
  );
}

window.Pricing = Pricing;
window.FAQ = FAQ;
window.FinalCTA = FinalCTA;
window.Footer = Footer;
