/* =============================================================
   Solidlab.no — norsk marked, konsulentspisset
   Lys palett (Antikkhvit). Deler designsystem med solidlab.ai
   ============================================================= */
const { useState, useEffect, useRef } = React;

/* ---------- Hjelpere ---------- */
/* Summerer høyden på alt som er klebrig i toppen, slik at ankerhopp
   lander riktig uansett om innholdsmenyen finnes på siden eller ikke. */
function klebrigHoyde() {
  let h = 0;
  document.querySelectorAll(".sl-header, .sl-vk-innhold").forEach(el => {
    if (getComputedStyle(el).position === "sticky") h += el.getBoundingClientRect().height;
  });
  return h;
}

function settKlebrigVariabel() {
  const h = klebrigHoyde();
  /* Under første layout kan høyden måles til 0. Da beholder vi
     reserveverdien i CSS heller enn å skrive inn en verdi vi vet er feil. */
  if (h > 0) document.documentElement.style.setProperty("--klebrig-h", h + "px");
}

function scrollToId(id) {
  const el = document.getElementById(id);
  if (!el) { window.location.href = "/#" + id; return; }
  const y = el.getBoundingClientRect().top + window.scrollY - klebrigHoyde() - 8;
  window.scrollTo({ top: Math.max(0, y), behavior: "smooth" });
}

if (typeof window !== "undefined") {
  /* Babel kompilerer denne filen etter at "load" allerede har fyrt,
     så variabelen må settes direkte — og igjen når fonter er lastet. */
  requestAnimationFrame(() => requestAnimationFrame(settKlebrigVariabel));
  setTimeout(settKlebrigVariabel, 120);
  window.addEventListener("resize", settKlebrigVariabel);
  if (document.fonts && document.fonts.ready) document.fonts.ready.then(settKlebrigVariabel);
  /* Følger med hvis headeren endrer høyde (fontbytte, zoom, rotasjon) */
  if (window.ResizeObserver) {
    const ro = new ResizeObserver(settKlebrigVariabel);
    requestAnimationFrame(() => {
      document.querySelectorAll(".sl-header, .sl-vk-innhold").forEach(el => ro.observe(el));
    });
  }
}

/* ---------- Typewriter ---------- */
function Typewriter({ words, typeSpeed = 75, deleteSpeed = 40, pauseAfterType = 2000, pauseAfterDelete = 300, initialPause = 1000 }) {
  const [display, setDisplay] = useState("");
  const [wordIndex, setWordIndex] = useState(0);
  const [phase, setPhase] = useState("initial");

  useEffect(() => {
    const word = words[wordIndex % words.length];
    let t;
    if (phase === "initial") {
      t = setTimeout(() => setPhase("typing"), initialPause);
    } else if (phase === "typing") {
      if (display.length < word.length) {
        t = setTimeout(() => setDisplay(word.slice(0, display.length + 1)), typeSpeed);
      } else {
        t = setTimeout(() => setPhase("pausing"), pauseAfterType);
      }
    } else if (phase === "pausing") {
      t = setTimeout(() => setPhase("deleting"), 0);
    } else if (phase === "deleting") {
      if (display.length > 0) {
        t = setTimeout(() => setDisplay(word.slice(0, display.length - 1)), deleteSpeed);
      } else {
        t = setTimeout(() => { setWordIndex(i => i + 1); setPhase("typing"); }, pauseAfterDelete);
      }
    }
    return () => clearTimeout(t);
  }, [display, phase, wordIndex, words, typeSpeed, deleteSpeed, pauseAfterType, pauseAfterDelete, initialPause]);

  return (
    <span className="sl-typewriter" aria-live="polite" aria-atomic="true">
      <span className="sl-typewriter__text">{display}</span>
      <span className="sl-typewriter__cursor" aria-hidden="true">|</span>
    </span>
  );
}


/* ---------- Ikonsett (egne, strektegnede — 1.5px, 24px rutenett) ---------- */
const IKON = {
  radgivning: (
    <g><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/><circle cx="9" cy="5" r="1.6"/><circle cx="19" cy="8" r="1.6"/></g>
  ),
  systemer: (
    <g><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/>
       <path d="M10 6.5h3a2 2 0 0 1 2 2v5"/><path d="M6.5 10v3a2 2 0 0 0 2 2h5"/></g>
  ),
  nett: (
    <g><rect x="2.5" y="4" width="19" height="14" rx="2"/><path d="M2.5 8.5h19"/>
       <circle cx="5.6" cy="6.2" r="0.7"/><circle cx="8" cy="6.2" r="0.7"/><path d="M8 21h8"/></g>
  ),
  ai: (
    <g><path d="M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6 2.1 2.1m0-12.8-2.1 2.1m-8.6 8.6-2.1 2.1"/>
       <circle cx="12" cy="12" r="3.4"/></g>
  ),
  kartlegging: (<g><circle cx="10.5" cy="10.5" r="6.5"/><path d="M15.2 15.2 21 21"/></g>),
  anbefaling: (<g><path d="M6 3h9l4 4v14H6z"/><path d="M14 3v5h5"/><path d="M9.5 13h6M9.5 16.5h4"/></g>),
  bygging: (<g><path d="M3 20h18"/><path d="M6 20V9l6-4 6 4v11"/><path d="M10 20v-5h4v5"/></g>),
  overlevering: (<g><path d="M4 12h13"/><path d="m12.5 7 5 5-5 5"/><path d="M20 4v16"/></g>),
};

function Ikon({ navn, size = 24 }) {
  return (
    <svg className="sl-ikon" width={size} height={size} viewBox="0 0 24 24" fill="none"
         stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"
         aria-hidden="true" focusable="false">
      {IKON[navn]}
    </svg>
  );
}

/* ---------- Hero-diagram: systemer som kobles sammen ---------- */
function HeroDiagram() {
  return (
    <svg className="sl-hero__diagram" viewBox="0 0 420 360" fill="none" aria-hidden="true">
      <defs>
        <linearGradient id="lg" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor="var(--linbla)" stopOpacity="0.55"/>
          <stop offset="100%" stopColor="var(--antikkgra)" stopOpacity="0.25"/>
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="418" height="358" rx="14" fill="url(#lg)"/>
      <g stroke="var(--oslo)" strokeWidth="1.25" opacity="0.5">
        <path d="M96 96h108M204 96v84M204 180h104M96 96v152M96 248h108M308 180v68M308 248H204"/>
      </g>
      <g className="sl-diagram__noder">
        {[[96,96],[204,96],[204,180],[308,180],[96,248],[204,248],[308,248]].map(([x,y],i)=>(
          <g key={i} style={{ animationDelay: (i*0.22)+"s" }}>
            <rect x={x-30} y={y-17} width="60" height="34" rx="8"
                  fill="var(--antikkhvit)" stroke="var(--oslo)" strokeWidth="1.25"/>
            <rect x={x-18} y={y-5} width={i%3===0?24:16} height="3" rx="1.5" fill="var(--oslo)" opacity="0.45"/>
            <rect x={x-18} y={y+3} width={i%2===0?30:22} height="3" rx="1.5" fill="var(--oslo)" opacity="0.22"/>
          </g>
        ))}
      </g>
      <circle cx="204" cy="180" r="26" fill="none" stroke="var(--oslo)" strokeWidth="1.25" opacity="0.35">
        <animate attributeName="r" values="26;40;26" dur="4s" repeatCount="indefinite"/>
        <animate attributeName="opacity" values="0.35;0;0.35" dur="4s" repeatCount="indefinite"/>
      </circle>
    </svg>
  );
}

/* Tekstene ligger nå i innhold.js — se INNHOLD.hero.band / .roterende. */
const BUZZ = INNHOLD.hero.band;

const ORD = INNHOLD.hero.roterende;

/* Seksjonene ligger i sidemenyen. Toppmenyen holder på det
   som peker ut av siden, pluss kontakt. Nøkler/lenker er struktur
   og ligger her; tekstene (label) hentes fra INNHOLD.meny.nav. */
const NAV = [
  { k: "verktoykassa", label: INNHOLD.meny.nav.verktoykassa, href: "/verktoykassa" },
  { k: "kontakt",      label: INNHOLD.meny.nav.kontakt },
];

/* Hamburgermenyen viser fortsatt alt */
const NAV_ALLE = [
  { k: "tjenester",    label: INNHOLD.meny.nav.tjenester },
  { k: "metode",       label: INNHOLD.meny.nav.metode },
  { k: "design",       label: INNHOLD.meny.nav.design },
  { k: "systemflyt",   label: INNHOLD.meny.nav.systemflyt },
  { k: "verktoykassa", label: INNHOLD.meny.nav.verktoykassa, href: "/verktoykassa" },
  { k: "ki",           label: INNHOLD.meny.nav.ki },
  { k: "kontakt",      label: INNHOLD.meny.nav.kontakt },
];

/* ============ HEADER ============ */
function Header() {
  const [menuOpen, setMenuOpen] = useState(false);

  useEffect(() => {
    document.body.style.overflow = menuOpen ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [menuOpen]);

  /* Escape lukker, og Tab holdes inne i panelet mens det er åpent */
  useEffect(() => {
    if (!menuOpen) return;
    const panel = document.getElementById("sl-panel");
    const tast = (e) => {
      if (e.key === "Escape") { setMenuOpen(false); return; }
      if (e.key !== "Tab" || !panel) return;
      const f = panel.querySelectorAll("a[href], button:not([disabled])");
      if (!f.length) return;
      const a = f[0], b = f[f.length - 1];
      if (e.shiftKey && document.activeElement === a) { e.preventDefault(); b.focus(); }
      else if (!e.shiftKey && document.activeElement === b) { e.preventDefault(); a.focus(); }
    };
    document.addEventListener("keydown", tast);
    const t = setTimeout(() => {
      const f = panel && panel.querySelector("a[href], button");
      if (f) f.focus();
    }, 320);
    return () => { document.removeEventListener("keydown", tast); clearTimeout(t); };
  }, [menuOpen]);

  const go = (item) => {
    setMenuOpen(false);
    if (item.href) { window.location.href = item.href; return; }
    setTimeout(() => scrollToId(item.k), 10);
  };

  return (
    <>
      <header className="sl-header">
        <div className="shell sl-header__inner">
          <a className="sl-wm" href="/" onClick={(e)=>{ if (window.location.pathname === "/") { e.preventDefault(); window.scrollTo({top:0,behavior:"smooth"}); } }}>
            <span className="sl-wm__solid">solid</span><span className="sl-wm__lab">lab</span><span className="sl-wm__ai">.no</span>
          </a>

          <button className="sl-meny-knapp" aria-label="Åpne meny"
                  aria-expanded={menuOpen} aria-controls="sl-panel"
                  onClick={() => setMenuOpen(true)}>
            <span className="sl-meny-knapp__strek" aria-hidden="true"><i></i><i></i></span>
            <span className="sl-meny-knapp__ord">Meny</span>
          </button>
        </div>
      </header>

      <div className={"sl-sidemenu" + (menuOpen ? " sl-sidemenu--open" : "")} aria-hidden={!menuOpen}>
        <div className="sl-sidemenu__backdrop" onClick={() => setMenuOpen(false)}></div>
        <aside className="sl-sidemenu__panel" id="sl-panel" role="dialog" aria-modal="true" aria-label="Meny">
          <div className="sl-sidemenu__head">
            <span className="sl-slash">/ meny</span>
            <button className="sl-sidemenu__close" aria-label="Lukk meny" onClick={() => setMenuOpen(false)}>
              <span className="sl-sidemenu__close-x">×</span>
              <span className="sl-sidemenu__close-label">lukk</span>
            </button>
          </div>

          <nav className="sl-sidemenu__nav">
            {NAV_ALLE.map((i, n) => (
              <a key={i.k} href={i.href || ("#" + i.k)} className="sl-sidemenu__link"
                 style={{ "--n": n }}
                 onClick={(e)=>{e.preventDefault(); go(i);}}>
                <span className="sl-sidemenu__nr">{String(n + 1).padStart(2, "0")}</span>
                <span className="sl-sidemenu__ord">{i.label.replace("/ ", "")}</span>
                <span className="sl-sidemenu__pil" aria-hidden="true">→</span>
              </a>
            ))}
          </nav>

          <div className="sl-sidemenu__bunn">
            <div className="sl-sidemenu__blokk">
              <span className="sl-slash">{INNHOLD.meny.ta_kontakt}</span>
              <a href={"mailto:" + INNHOLD.kontaktinfo.epost}>{INNHOLD.kontaktinfo.epost}</a>
              <a href={"tel:" + INNHOLD.kontaktinfo.tlf_lenke}>{INNHOLD.kontaktinfo.tlf_visning}</a>
            </div>
            <div className="sl-sidemenu__blokk">
              <span className="sl-slash">{INNHOLD.meny.mer}</span>
              <a href="https://solidlab.ai" target="_blank" rel="noopener noreferrer">{INNHOLD.meny.solidlab_ai}</a>
              <a href="https://www.linkedin.com/company/115796478" target="_blank" rel="noopener noreferrer">{INNHOLD.meny.linkedin}</a>
            </div>
          </div>

          <div className="sl-sidemenu__fot">
            <span>{INNHOLD.kontaktinfo.sted}</span>
            <span>{INNHOLD.kontaktinfo.svartid_kort}</span>
          </div>
        </aside>
      </div>
    </>
  );
}

/* ============ HERO ============ */
function Hero() {
  const [spill, setSpill] = useState(false);
  return (
    <section className="sl-hero">
      <div className="shell sl-hero__grid">
       <div className="sl-hero__left">
        <div className="sl-hero__eyebrow sl-slash">{INNHOLD.hero.eyebrow}</div>
        <h1 className="sl-hero__title sl-hero__title--stacked">
          <span><span className="sl-hero__light">{INNHOLD.hero.tittel_lys}</span><span className="sl-hero__bold">{INNHOLD.hero.tittel_uthevet}</span></span>
          <span className="sl-hero__light"><Typewriter words={ORD}/></span>
        </h1>
        <p className="sl-hero__sub">{INNHOLD.hero.undertekst}</p>
        <div className="sl-hero__cta">
          <button className="sl-btn sl-btn--primary" onClick={apneSkjema}>{INNHOLD.hero.cta_primaer}</button>
          <a className="sl-btn sl-btn--ghost" href="#tjenester" onClick={(e)=>{e.preventDefault(); scrollToId("tjenester");}}>{INNHOLD.hero.cta_sekundaer}</a>
        </div>
        <div className="sl-band" aria-label={"Fagområder: " + BUZZ.join(", ")}>
          <div className="sl-band__spor">
            {[0, 1].map(sett => (
              <span className="sl-band__sett" key={sett} aria-hidden={sett === 1 ? "true" : undefined}>
                {BUZZ.map(b => <span className="sl-band__ord" key={b}>{b}</span>)}
              </span>
            ))}
          </div>
        </div>
       </div>
       <div className="sl-hero__right">
         <button className="sl-hero__diagramknapp" onClick={() => setSpill(true)}
                 aria-label="Skjult spill">
           <HeroDiagram/>
         </button>
       </div>
       {spill && <Spill lukk={() => setSpill(false)}/>}
      </div>
    </section>
  );
}

/* ============ 01 — TJENESTER ============ */
function Tjenester() {
  /* Ikon-rekkefølgen er struktur og ligger her; tekstene i INNHOLD.tjenester.punkter. */
  const IKONER = ["radgivning", "systemer", "nett", "ai"];
  const items = INNHOLD.tjenester.punkter.map((p, i) => ({
    n: String(i + 1).padStart(2, "0"),
    ikon: IKONER[i],
    t: p.tittel,
    b: p.tekst,
  }));
  return (
    <section className="sl-section" id="tjenester">
      <div className="shell">
        <div className="sl-slash" style={{marginBottom:24}}>{INNHOLD.tjenester.slash}</div>
        <div className="sl-section__head">
          <h2 className="sl-section__title">{INNHOLD.tjenester.tittel}</h2>
          <p className="sl-section__intro">{INNHOLD.tjenester.intro}</p>
        </div>
        <div className="sl-services">
          {items.map(i => (
            <div key={i.n} className="sl-service">
              <div className="sl-service__top">
                <span className="sl-service__ikon"><Ikon navn={i.ikon}/></span>
                <span className="sl-slash sl-service__num">/ {i.n}</span>
              </div>
              <h3 className="sl-service__title">{i.t}</h3>
              <p className="sl-service__body">{i.b}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============ 02 — METODE ============ */
function Metode() {
  /* Linja tegnes først når seksjonen kommer til syne, og punktene
     tennes i takt med den. Kjøres én gang. */
  const [aktiv, setAktiv] = useState(false);
  const listeRef = useRef(null);

  useEffect(() => {
    const el = listeRef.current;
    if (!el || !window.IntersectionObserver) { setAktiv(true); return; }
    const obs = new IntersectionObserver(([post]) => {
      if (post.isIntersecting) { setAktiv(true); obs.disconnect(); }
    }, { threshold: 0.2, rootMargin: "0px 0px -60px 0px" });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  /* Ikon-rekkefølgen er struktur og ligger her; tekstene i INNHOLD.metode.steg. */
  const STEG_IKONER = ["kartlegging", "anbefaling", "bygging", "overlevering"];
  const steg = INNHOLD.metode.steg.map((s, i) => ({
    n: String(i + 1).padStart(2, "0"),
    ikon: STEG_IKONER[i],
    t: s.tittel,
    b: s.tekst,
  }));
  return (
    <section className="sl-section sl-no-metode" id="metode">
      <div className="shell">
        <div className="sl-slash" style={{marginBottom:24}}>{INNHOLD.metode.slash}</div>
        <div className="sl-section__head">
          <h2 className="sl-section__title">{INNHOLD.metode.tittel}</h2>
          <p className="sl-section__intro">{INNHOLD.metode.intro}</p>
        </div>
        <ol className={"sl-no-steps" + (aktiv ? " sl-no-steps--aktiv" : "")} ref={listeRef}>
          {steg.map(s => (
            <li key={s.n} className="sl-no-step" style={{ "--i": steg.indexOf(s) }}>
              <span className="sl-no-step__ikon"><Ikon navn={s.ikon}/></span>
              <span className="sl-slash sl-no-step__num">/ {s.n}</span>
              <h3 className="sl-no-step__title">{s.t}</h3>
              <p className="sl-no-step__body">{s.b}</p>
            </li>
          ))}
        </ol>
      </div>
    </section>
  );
}

/* ============ 03 — HVORFOR ============ */
/* ============ 05 — KI I PRAKSIS ============ */
function KiPraksis() {
  return (
    <section className="sl-advisory" id="ki">
      <Padle />
      <div className="shell">
        <div className="sl-slash sl-advisory__eyebrow">{INNHOLD.ki.slash}</div>
        <div className="sl-advisory__grid">
          <div className="sl-advisory__left">
            <h2 className="sl-advisory__title">
              {INNHOLD.ki.tittel_for}<em>{INNHOLD.ki.tittel_uthevet}</em>
            </h2>
          </div>
          <div className="sl-advisory__right">
            {INNHOLD.ki.avsnitt.map((tekst, i) => (
              <p className="sl-advisory__body" key={i}>{tekst}</p>
            ))}
            <p className="sl-advisory__body">
              {INNHOLD.ki.se_produkter}{" "}
              <a className="sl-link" href="https://solidlab.ai" target="_blank" rel="noopener noreferrer">{INNHOLD.ki.produkt_lenke}</a>
            </p>

            <button className="sl-btn sl-btn--primary sl-advisory__cta" onClick={apneKiSkjema}>
              {INNHOLD.ki.cta}
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ============ 06 — KONTAKT ============ */
/* ============ HANGTAG — skjøten mellom lys og svart ============ */
function Padle() {
  return (
    <div className="sl-padle" aria-hidden="true">
      <img src="/assets/hangtag.svg?v=2" alt="" width="1000" height="2200" />
    </div>
  );
}

function Kontakt() {
  return (
    <section className="sl-contact" id="kontakt">
      <div className="shell">
        <div className="sl-slash" style={{marginBottom:32}}>{INNHOLD.kontakt.slash}</div>
        <div className="sl-contact__grid">
          <div className="sl-contact__venstre">
            <h2 className="sl-contact__title">{INNHOLD.kontakt.tittel_for}<em>{INNHOLD.kontakt.tittel_uthevet}</em>{INNHOLD.kontakt.tittel_etter}</h2>
            <button className="sl-btn sl-btn--lys sl-contact__cta" onClick={apneSkjema}>{INNHOLD.kontakt.cta}</button>
          </div>
          <div className="sl-contact__meta">
            <div>
              <span className="sl-contact__label">{INNHOLD.kontakt.label_epost}</span>
              <a href={"mailto:" + INNHOLD.kontaktinfo.epost}>{INNHOLD.kontaktinfo.epost}</a>
            </div>
            <div>
              <span className="sl-contact__label">{INNHOLD.kontakt.label_telefon}</span>
              <a href={"tel:" + INNHOLD.kontaktinfo.tlf_lenke}>{INNHOLD.kontaktinfo.tlf_visning}</a>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ============ FOOTER ============ */
function Footer() {
  return (
    <footer className="sl-footer">
      <div className="shell sl-footer__inner">
        <div>
          {INNHOLD.footer.aar} <span className="sl-wm sl-wm--footer"><span className="sl-wm__solid">solid</span><span className="sl-wm__lab">lab</span><span className="sl-wm__ai">.no</span></span>
          {" "}<span className="sl-footer__orgnr">{INNHOLD.footer.orgnr}</span>
        </div>
        <div className="sl-footer__right">
          <a href="https://solidlab.ai" target="_blank" rel="noopener noreferrer">{INNHOLD.footer.lenke_solidlab}</a>
          <a href="https://www.linkedin.com/company/115796478" target="_blank" rel="noopener noreferrer">{INNHOLD.footer.lenke_linkedin}</a>
          <span className="sl-footer__sep" aria-hidden="true">·</span>
          <a href="/verktoykassa">{INNHOLD.footer.lenke_verktoykassa}</a>
          <a href="/legal/privacy">{INNHOLD.footer.lenke_personvern}</a>
          <a href={"mailto:" + INNHOLD.kontaktinfo.epost}>{INNHOLD.kontaktinfo.epost}</a>
        </div>
      </div>
    </footer>
  );
}

/* ============ APP ============ */
function App() {
  return (
    <>
      <Header/>
      <Hero/>
      <Tjenester/>
      <Metode/>
      <TekniskDesign/>
      <Systemflyt/>
      <KiPraksis/>
      <Kontakt/>
      <Footer/>
      <Kontaktskjema/>
      <KiSkjema/>
      <DemoSkjema/>
      <Jens/>
    </>
  );
}

/* =============================================================
   Kontaktskjema — popup i Typeform-stil, ett spørsmål om gangen
   ============================================================= */

/* Sett denne til et endepunkt (Formspree, Resend, egen API-rute)
   når backend er klar. Er den null, faller skjemaet tilbake til
   e-post med ferdig utfylt innhold. */
const SKJEMA_ENDEPUNKT = "/api/skjema";
const MOTTAKER = INNHOLD.kontaktinfo.epost;

const TEMAER = INNHOLD.skjema.temaer;

function apneSkjema() {
  window.dispatchEvent(new CustomEvent("sl:apne-skjema"));
}

function Kontaktskjema() {
  const [apen, setApen]   = useState(false);
  const [steg, setSteg]   = useState(0);
  const [sendt, setSendt] = useState(false);
  const [feil, setFeil]   = useState("");
  const [data, setData]   = useState({ navn:"", epost:"", telefon:"", firma:"", tema:"", melding:"", nyhetsbrev:false });

  const panelRef  = useRef(null);
  const forsteRef = useRef(null);
  const utloserRef = useRef(null);

  const sett = (k, v) => setData(d => ({ ...d, [k]: v }));

  /* Åpnes av knapper hvor som helst på siden */
  useEffect(() => {
    const paaApne = () => {
      utloserRef.current = document.activeElement;
      setApen(true); setSteg(0); setSendt(false); setFeil("");
    };
    window.addEventListener("sl:apne-skjema", paaApne);
    return () => window.removeEventListener("sl:apne-skjema", paaApne);
  }, []);

  /* Lås bakgrunnsrulling, og gi fokus tilbake til knappen ved lukking */
  useEffect(() => {
    document.body.style.overflow = apen ? "hidden" : "";
    if (!apen && utloserRef.current) utloserRef.current.focus();
    return () => { document.body.style.overflow = ""; };
  }, [apen]);

  useEffect(() => {
    if (apen && forsteRef.current) {
      const t = setTimeout(() => forsteRef.current && forsteRef.current.focus(), 280);
      return () => clearTimeout(t);
    }
  }, [apen, steg, sendt]);

  /* Escape lukker, Tab holdes inne i dialogen */
  useEffect(() => {
    if (!apen) return;
    const tast = (e) => {
      if (e.key === "Escape") { setApen(false); return; }
      if (e.key !== "Tab" || !panelRef.current) return;
      const f = panelRef.current.querySelectorAll("button:not([disabled]), input, textarea, [href]");
      if (!f.length) return;
      const forste = f[0], siste = f[f.length - 1];
      if (e.shiftKey && document.activeElement === forste) { e.preventDefault(); siste.focus(); }
      else if (!e.shiftKey && document.activeElement === siste) { e.preventDefault(); forste.focus(); }
    };
    document.addEventListener("keydown", tast);
    return () => document.removeEventListener("keydown", tast);
  }, [apen]);

  const gyldigEpost = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v.trim());

  const validerSteg = () => {
    if (steg === 0 && data.navn.trim().length < 2) return INNHOLD.skjema.feil_navn;
    if (steg === 1 && !gyldigEpost(data.epost))    return INNHOLD.skjema.feil_epost;
    if (steg === 3 && data.melding.trim().length < 5) return INNHOLD.skjema.feil_melding;
    return "";
  };

  const neste = () => {
    const f = validerSteg();
    if (f) { setFeil(f); return; }
    setFeil("");
    if (steg < 3) setSteg(steg + 1); else send();
  };

  const forrige = () => { setFeil(""); setSteg(Math.max(0, steg - 1)); };

  const send = async () => {
    const f = validerSteg();
    if (f) { setFeil(f); return; }
    if (SKJEMA_ENDEPUNKT) {
      try {
        const r = await fetch(SKJEMA_ENDEPUNKT, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(data),
        });
        if (!r.ok) throw new Error();
        setSendt(true);
      } catch {
        setFeil(INNHOLD.skjema.feil_generell + MOTTAKER);
      }
      return;
    }
    /* Uten endepunkt: åpne e-post med alt ferdig utfylt */
    const brodtekst =
      "Navn: " + data.navn +
      "\nE-post: " + data.epost +
      (data.telefon ? "\nTelefon: " + data.telefon : "") +
      (data.firma ? "\nFirma: " + data.firma : "") +
      (data.tema ? "\nGjelder: " + data.tema : "") +
      "\nNyhetsbrev: " + (data.nyhetsbrev ? "ja, samtykker" : "nei") +
      "\n\n" + data.melding;
    window.location.href = "mailto:" + MOTTAKER +
      "?subject=" + encodeURIComponent("Henvendelse fra solidlab.no — " + data.navn) +
      "&body=" + encodeURIComponent(brodtekst);
    setSendt(true);
  };

  const paaTast = (e) => {
    if (e.key === "Enter" && !e.shiftKey && e.target.tagName !== "TEXTAREA") {
      e.preventDefault(); neste();
    }
  };

  if (!apen) return null;

  const STEG = INNHOLD.skjema.steg;

  return (
    <div className="sl-modal" role="presentation">
      <div className="sl-modal__backdrop" onClick={() => setApen(false)}></div>

      <div className="sl-modal__panel" role="dialog" aria-modal="true"
           aria-labelledby="sl-modal-tittel" ref={panelRef}>

        <button className="sl-modal__lukk" onClick={() => setApen(false)} aria-label="Lukk skjema">×</button>

        {!sendt && (
          <div className="sl-modal__fremdrift" aria-hidden="true">
            <span style={{ width: ((steg + 1) / 4 * 100) + "%" }}></span>
          </div>
        )}

        {sendt ? (
          <div className="sl-modal__ferdig">
            <div className="sl-modal__hake" aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"
                   strokeLinecap="round" strokeLinejoin="round"><path d="m4 12.5 5.2 5.2L20 7"/></svg>
            </div>
            <h2 id="sl-modal-tittel" className="sl-modal__sporsmaal">{INNHOLD.skjema.takk_for}{data.navn.split(" ")[0]}.</h2>
            <p className="sl-modal__hjelp">
              {INNHOLD.skjema.takk_tekst}
              <a className="sl-link" href={"tel:" + INNHOLD.kontaktinfo.tlf_lenke}>{INNHOLD.kontaktinfo.tlf_visning}</a>.
              {data.nyhetsbrev && INNHOLD.skjema.takk_nyhetsbrev}
            </p>
            <div className="sl-modal__knapper">
              <button className="sl-btn sl-btn--primary" ref={forsteRef} onClick={() => setApen(false)}>{INNHOLD.skjema.knapp_lukk}</button>
            </div>
          </div>
        ) : (
          <div className="sl-modal__innhold">
            <span className="sl-slash sl-modal__teller">/ {String(steg + 1).padStart(2,"0")} av 04</span>
            <h2 id="sl-modal-tittel" className="sl-modal__sporsmaal">{STEG[steg].sporsmaal}</h2>
            <p className="sl-modal__hjelp">{STEG[steg].hjelp}</p>

            <div className="sl-modal__felt">
              {steg === 0 && (
                <input ref={forsteRef} className="sl-felt" type="text" value={data.navn}
                       onChange={e => sett("navn", e.target.value)} onKeyDown={paaTast}
                       placeholder={INNHOLD.skjema.ph_navn} autoComplete="name" aria-label="Navn"/>
              )}

              {steg === 1 && (
                <>
                  <input ref={forsteRef} className="sl-felt" type="email" value={data.epost}
                         onChange={e => sett("epost", e.target.value)} onKeyDown={paaTast}
                         placeholder={INNHOLD.skjema.ph_epost} autoComplete="email" aria-label="E-post"/>
                  <input className="sl-felt sl-felt--valgfritt" type="tel" value={data.telefon}
                         onChange={e => sett("telefon", e.target.value)} onKeyDown={paaTast}
                         placeholder={INNHOLD.skjema.ph_telefon} autoComplete="tel" aria-label="Telefon, valgfritt"/>
                  <input className="sl-felt sl-felt--valgfritt" type="text" value={data.firma}
                         onChange={e => sett("firma", e.target.value)} onKeyDown={paaTast}
                         placeholder={INNHOLD.skjema.ph_firma} autoComplete="organization" aria-label="Firma, valgfritt"/>
                </>
              )}

              {steg === 2 && (
                <div className="sl-valg">
                  {TEMAER.map((t, i) => (
                    <button key={t} ref={i === 0 ? forsteRef : null}
                            className={"sl-valg__knapp" + (data.tema === t ? " sl-valg__knapp--valgt" : "")}
                            onClick={() => { sett("tema", t); setTimeout(() => setSteg(3), 180); }}>
                      <span className="sl-valg__bokstav">{String.fromCharCode(65 + i)}</span>{t}
                    </button>
                  ))}
                </div>
              )}

              {steg === 3 && (
                <>
                  <textarea ref={forsteRef} className="sl-felt sl-felt--stor" rows="4" value={data.melding}
                            onChange={e => sett("melding", e.target.value)}
                            placeholder={INNHOLD.skjema.ph_melding}
                            aria-label="Melding"/>

                  <label className="sl-avkrys">
                    <input type="checkbox" checked={data.nyhetsbrev}
                           onChange={e => sett("nyhetsbrev", e.target.checked)}/>
                    <span className="sl-avkrys__boks" aria-hidden="true">
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"
                           strokeLinecap="round" strokeLinejoin="round"><path d="m5 12.5 4.5 4.5L19 7.5"/></svg>
                    </span>
                    <span className="sl-avkrys__tekst">
                      {INNHOLD.skjema.nyhetsbrev}
                      <span className="sl-avkrys__note">{INNHOLD.skjema.nyhetsbrev_note}</span>
                    </span>
                  </label>
                </>
              )}
            </div>

            {feil && <p className="sl-modal__feil" role="alert">{feil}</p>}

            <div className="sl-modal__knapper">
              {steg > 0 && <button className="sl-btn sl-btn--ghost" onClick={forrige}>{INNHOLD.skjema.knapp_tilbake}</button>}
              {steg !== 2 && (
                <button className="sl-btn sl-btn--primary" onClick={neste}>
                  {steg === 3 ? INNHOLD.skjema.knapp_send : INNHOLD.skjema.knapp_neste}
                </button>
              )}
              {steg !== 2 && <span className="sl-modal__hint">{INNHOLD.skjema.hint} <kbd>{INNHOLD.skjema.hint_tast}</kbd></span>}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

/* =============================================================
   Jens — kundevendt assistent, nede til høyre
   ============================================================= */
const APNINGSREPLIKK = INNHOLD.jens.apningsreplikk;
const FORSLAG = INNHOLD.jens.forslag;

function Jens() {
  const [apen, setApen]       = useState(false);
  const [meldinger, setMeld]  = useState([{ rolle: "jens", tekst: APNINGSREPLIKK }]);
  const [tekst, setTekst]     = useState("");
  const [venter, setVenter]   = useState(false);
  const [ulest, setUlest]     = useState(false);
  const [paaMorkt, setMorkt]  = useState(false);

  const logRef   = useRef(null);
  const feltRef  = useRef(null);
  const knappRef = useRef(null);

  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight;
  }, [meldinger, venter]);

  useEffect(() => {
    if (apen) {
      setUlest(false);
      const t = setTimeout(() => feltRef.current && feltRef.current.focus(), 240);
      return () => clearTimeout(t);
    }
  }, [apen]);

  /* Bytter knappen til lys når den svever over kontaktfeltet eller footeren,
     som begge er svarte. Uten dette forsvinner den i bakgrunnen. */
  useEffect(() => {
    let ventende = false;
    const sjekk = () => {
      ventende = false;
      const k = knappRef.current;
      if (!k) return;
      const boks = k.getBoundingClientRect();
      const midt = boks.top + boks.height / 2;
      let over = false;
      document.querySelectorAll(".sl-contact, .sl-footer").forEach(felt => {
        const f = felt.getBoundingClientRect();
        if (midt >= f.top && midt <= f.bottom) over = true;
      });
      setMorkt(over);
    };
    const paaScroll = () => {
      if (ventende) return;
      ventende = true;
      requestAnimationFrame(sjekk);
    };
    sjekk();
    window.addEventListener("scroll", paaScroll, { passive: true });
    window.addEventListener("resize", paaScroll);
    return () => {
      window.removeEventListener("scroll", paaScroll);
      window.removeEventListener("resize", paaScroll);
    };
  }, []);

  /* Liten pling første gang, så folk oppdager at han er der */
  useEffect(() => {
    const t = setTimeout(() => { if (!apen) setUlest(true); }, 9000);
    return () => clearTimeout(t);
  }, []);

  useEffect(() => {
    if (!apen) return;
    const tast = (e) => { if (e.key === "Escape") setApen(false); };
    document.addEventListener("keydown", tast);
    return () => document.removeEventListener("keydown", tast);
  }, [apen]);

  const send = async (innhold) => {
    const melding = (innhold != null ? innhold : tekst).trim();
    if (!melding || venter) return;
    setTekst("");
    const nye = [...meldinger, { rolle: "du", tekst: melding }];
    setMeld(nye);
    setVenter(true);
    try {
      const r = await fetch("/api/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          messages: nye
            .filter(m => m.tekst !== APNINGSREPLIKK)
            .map(m => ({ role: m.rolle === "du" ? "user" : "assistant", content: m.tekst })),
        }),
      });
      const data = await r.json();
      const raatekst = data.svar || data.feil || INNHOLD.jens.feil_svar;
      /* Jens kan avslutte med markøren [[SKJEMA]] for å tilby skjema-knappen.
         Vi fjerner markøren fra teksten og setter et flagg i stedet. */
      const vilSkjema = /\[\[\s*SKJEMA\s*\]\]/i.test(raatekst);
      const renTekst = raatekst.replace(/\[\[\s*SKJEMA\s*\]\]/ig, "").replace(/\n{3,}/g, "\n\n").trim();
      setMeld(m => [...m, {
        rolle: "jens",
        tekst: renTekst,
        skjema: vilSkjema,
      }]);
    } catch {
      setMeld(m => [...m, {
        rolle: "jens",
        tekst: INNHOLD.jens.feil_kontakt,
      }]);
    } finally {
      setVenter(false);
      setTimeout(() => feltRef.current && feltRef.current.focus(), 60);
    }
  };

  return (
    <>
      <button ref={knappRef}
              className={"sl-jens-knapp" + (apen ? " sl-jens-knapp--apen" : "")
                         + (paaMorkt && !apen ? " sl-jens-knapp--lys" : "")}
              onClick={() => setApen(!apen)}
              aria-expanded={apen} aria-controls="sl-jens-panel"
              aria-label={apen ? "Lukk chat med Jens" : "Åpne chat med Jens"}>
        {apen ? (
          <span className="sl-jens-knapp__x" aria-hidden="true">×</span>
        ) : (
          <>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"
                 strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <path d="M20 15a2 2 0 0 1-2 2H8l-4 4V6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2z"/>
            </svg>
            <span className="sl-jens-knapp__navn">{INNHOLD.jens.knapp}</span>
            {ulest && <span className="sl-jens-knapp__prikk" aria-hidden="true"></span>}
          </>
        )}
      </button>

      {apen && (
        <div className="sl-jens" id="sl-jens-panel" role="dialog" aria-label="Chat med Jens">
          <div className="sl-jens__topp">
            <div className="sl-jens__ident">
              <span className="sl-jens__merke" aria-hidden="true">J</span>
              <span>
                <strong>Jens</strong>
                <span className="sl-jens__rolle">{INNHOLD.jens.rolle}</span>
              </span>
            </div>
            <button className="sl-jens__lukk" onClick={() => setApen(false)} aria-label="Lukk">×</button>
          </div>

          <div className="sl-jens__log" ref={logRef} role="log" aria-live="polite">
            {meldinger.map((m, i) => (
              <React.Fragment key={i}>
                <div className={"sl-jens__melding sl-jens__melding--" + m.rolle}>{m.tekst}</div>
                {m.skjema && (
                  <button className="sl-jens__handling"
                          onClick={() => { setApen(false); apneSkjema(); }}>
                    Send oss en melding →
                  </button>
                )}
              </React.Fragment>
            ))}
            {venter && (
              <div className="sl-jens__melding sl-jens__melding--jens sl-jens__skriver" aria-label="Jens skriver">
                <span></span><span></span><span></span>
              </div>
            )}
            {meldinger.length === 1 && !venter && (
              <div className="sl-jens__forslag">
                {FORSLAG.map(f => (
                  <button key={f} onClick={() => send(f)}>{f}</button>
                ))}
              </div>
            )}
          </div>

          <div className="sl-jens__bunn">
            <input ref={feltRef} className="sl-jens__felt" value={tekst}
                   onChange={e => setTekst(e.target.value)}
                   onKeyDown={e => { if (e.key === "Enter") { e.preventDefault(); send(); } }}
                   placeholder={INNHOLD.jens.placeholder} aria-label="Melding til Jens" maxLength={1000}/>
            <button className="sl-jens__send" onClick={() => send()}
                    disabled={venter || !tekst.trim()} aria-label="Send melding">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"
                   strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <path d="M5 12h13M12 5l7 7-7 7"/>
              </svg>
            </button>
          </div>
          <p className="sl-jens__fot">{INNHOLD.jens.fot}</p>
        </div>
      )}
    </>
  );
}
