/* eslint-disable */
const { useState, useMemo, useRef, useEffect } = React;

/* ============================================================
   POMOĆNE FUNKCIJE
   ============================================================ */
const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
const pct = (v, d = 0) => (v === null || v === undefined || Number.isNaN(v)) ? "—" : (v * 100).toFixed(d) + "%";
// deterministički generator (isti podaci pri svakom otvaranju)
function mulberry32(a) {
  return function () {
    a |= 0; a = a + 0x6D2B79F5 | 0;
    let t = Math.imul(a ^ a >>> 15, 1 | a);
    t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
    return ((t ^ t >>> 14) >>> 0) / 4294967296;
  };
}

/* ============================================================
   WIDGET 1 — ZAŠTO DOBRA TEHNOLOGIJA PROPADA (percepcija/usvajanje)
   ============================================================ */
function AdoptionLab() {
  const [K, setK] = useState(0.9); // kvaliteta
  const [E, setE] = useState(0.55); // edukacija tržišta
  const [N, setN] = useState(0.4);  // sklad s navikama
  const [P, setP] = useState(0.5);  // povjerenje / percepcija

  const now = K * E * N * P;
  // povjerenje koje se dugoročno može održati ograničeno je stvarnom kvalitetom
  const Psustain = clamp(P, 0, 0.2 + 0.8 * K);
  const later = K * E * N * Psustain;
  const gap = now - later;

  const romb = () => setP(0.92);

  let hint = "Pomiči četiri klizača. Prihvaćanje je njihov UMNOŽAK — ako je bilo koji blizu nule, sve pada na nulu. „Lanac je jak koliko i najslabija karika.”";
  if (K >= 0.8 && (E < 0.3 || N < 0.3))
    hint = "Proizvod je objektivno odličan, ali ga tržište ne razumije (niska edukacija) ili ne pristaje navikama — prihvaćanje ostaje nisko. Kvaliteta je nužna, ali ne i dovoljna.";
  else if (P >= 0.8 && K < 0.5)
    hint = "Visoka percepcija diže prihvaćanje DANAS, ali iza nje nema kvalitete — pogledaj stupac „za 6 mjeseci”: posuđeno povjerenje se vraća s kamatama.";
  else if (K >= 0.7 && E >= 0.6 && N >= 0.6 && P >= 0.6)
    hint = "Sve su karike jake: tehnologija se i usvaja i ostaje. Razlika između „danas” i „za 6 mjeseci” je mala jer percepciju drži stvarna kvaliteta.";

  const Bar = ({ cls, v, lab, sub }) => (
    <div className="barwrap">
      <div className="barlab"><span>{lab}</span><b>{pct(v)}</b></div>
      <div className="bartrack"><div className={"barfill " + cls} style={{ width: pct(clamp(v, 0, 1)) }}></div></div>
      {sub && <span className="ctrl"><span className="sub" style={{ marginTop: 4 }}>{sub}</span></span>}
    </div>
  );

  const factors = [
    { lab: "Kvaliteta proizvoda", v: K, set: setK, sub: "objektivno koliko je dobar" },
    { lab: "Edukacija tržišta", v: E, set: setE, sub: "razumiju li ljudi čemu služi" },
    { lab: "Sklad s navikama", v: N, set: setN, sub: "pristaje li u postojeći način rada" },
    { lab: "Povjerenje / percepcija", v: P, set: setP, sub: "vjeruju li mu i kako ga doživljavaju" },
  ];

  return (
    <div className="widget">
      <span className="wlab">usvajanje tehnologije = umnožak svih faktora</span>
      <div className="factgrid">
        {factors.map((f, i) => (
          <div className="ctrl" key={i} style={{ minWidth: "auto" }}>
            <label>{f.lab}: <span className="val">{f.v.toFixed(2)}</span></label>
            <input type="range" min="0" max="1" step="0.01" value={f.v} onChange={e => f.set(+e.target.value)} />
            <span className="sub">{f.sub}</span>
          </div>
        ))}
      </div>

      <div style={{ fontFamily: "var(--mono)", fontSize: 13, color: "var(--muted)", marginTop: 18, textAlign: "center" }}>
        {K.toFixed(2)} × {E.toFixed(2)} × {N.toFixed(2)} × {P.toFixed(2)} = <b style={{ color: "var(--accent)", fontSize: 16 }}>{now.toFixed(2)}</b>
      </div>

      <Bar cls="now" v={now} lab="Prihvaćanje danas" />
      <Bar cls="later" v={later} lab="Prihvaćanje za 6 mjeseci (kad popusti prvi dojam)" />

      <div className="readout">
        <div className="stat acc"><span className="k">Danas</span><span className="v">{pct(now)}</span></div>
        <div className={"stat " + (gap > 0.12 ? "warn" : "good")}><span className="k">Pad nakon 6 mj.</span><span className="v">{pct(gap)}</span></div>
        <div className="stat"><span className="k">Najslabija karika</span><span className="v" style={{ fontSize: 15 }}>
          {["Kvaliteta", "Edukacija", "Navike", "Povjerenje"][[K, E, N, P].indexOf(Math.min(K, E, N, P))]}</span></div>
      </div>

      <div className="wbtns" style={{ marginTop: 14 }}>
        <button className="btn-ghost" onClick={romb}>„Romb trik”: digni samo percepciju ↑</button>
        <button className="btn-ghost" onClick={() => { setK(0.9); setE(0.55); setN(0.4); setP(0.5); }}>↻ Reset</button>
      </div>
      <div className="hintline">{hint}</div>

      <div className="note">
        <strong>Tri priče, jedna pouka.</strong> <b>Instant kava</b> (1950-e): kvaliteta visoka, ali navike i percepcija niske → propast.
        <b> Kvadrat postaje romb</b>: isti proizvod okrenut za 45° djeluje „novo” — percepcija se promijenila, suština nije.
        <b> Šišanje u svemiru</b>: promijeniš jedan parametar (gravitaciju) i sve se mijenja.
        Kod nas danas: <b>samonaplatne blagajne</b> i <b>eGrađani / e-recept</b> — objektivno praktičniji, a usvajaju se sporo dok ne narastu edukacija, navika i povjerenje.
      </div>
      <div className="note warn">
        <strong>Oprez s „rombom”.</strong> Trik s percepcijom je kratkoročni hack — bez stvarne vrijednosti, jasnog uvođenja i povratne informacije korisnika
        povjerenje se ruši. Za <b>AI u poslovanju</b> to znači: model točan 99% koji nitko ne razumije, ne koristi ili mu ne vjeruje vrijedi — nula.
        Prava poluga nije „pakiranje”, nego <b>transparentnost, edukacija i pouzdanost</b>. (Model je namjerno pojednostavljen.)
      </div>
    </div>
  );
}

/* ============================================================
   WIDGET 2 — CILJNA VARIJABLA LAB + CURENJE PODATAKA
   ============================================================ */
const CUSTOMERS = [
  // [id, ime, dani neaktivnosti, obnovljen(ugovor), zatražio deaktivaciju, na godišnjem]
  { id: 1, ime: "Ana", dani: 5, obn: true, deakt: false, god: false },
  { id: 2, ime: "Boris", dani: 75, obn: false, deakt: true, god: false },
  { id: 3, ime: "Cvita", dani: 90, obn: false, deakt: false, god: false },
  { id: 4, ime: "Dario", dani: 80, obn: true, deakt: false, god: true },
  { id: 5, ime: "Eva", dani: 10, obn: false, deakt: true, god: false },
  { id: 6, ime: "Filip", dani: 65, obn: true, deakt: false, god: false },
  { id: 7, ime: "Gordana", dani: 30, obn: false, deakt: false, god: false },
  { id: 8, ime: "Hrvoje", dani: 120, obn: false, deakt: true, god: false },
  { id: 9, ime: "Iva", dani: 55, obn: true, deakt: false, god: true },
  { id: 10, ime: "Jure", dani: 8, obn: true, deakt: true, god: false },
  { id: 11, ime: "Klara", dani: 70, obn: false, deakt: false, god: false },
  { id: 12, ime: "Luka", dani: 45, obn: true, deakt: false, god: false },
  { id: 13, ime: "Maja", dani: 95, obn: true, deakt: false, god: true },
  { id: 14, ime: "Nikola", dani: 62, obn: false, deakt: true, god: false },
];

function TargetLab() {
  const [d1, setD1] = useState(true);   // neaktivnost ≥ prag
  const [d2, setD2] = useState(false);  // ugovor nije obnovljen
  const [d3, setD3] = useState(false);  // zatražio deaktivaciju
  const [prag, setPrag] = useState(60);
  const [leak, setLeak] = useState(false);

  const rows = CUSTOMERS.map(c => {
    const m1 = d1 && c.dani >= prag;
    const m2 = d2 && !c.obn;
    const m3 = d3 && c.deakt;
    const flag = m1 || m2 || m3;
    // "tihi odlazak": dugo neaktivan I nije obnovio, a NIJE tražio deaktivaciju
    const silent = c.dani >= 60 && !c.obn && !c.deakt;
    // sumnjivo uključen: označen, ali je na godišnjem i obnovio ugovor (vjerojatno lojalan)
    const falseAlarm = flag && c.god && c.obn;
    return { ...c, flag, silent, falseAlarm, by: { m1, m2, m3 } };
  });

  const flagged = rows.filter(r => r.flag).length;
  const falseAlarms = rows.filter(r => r.falseAlarm).length;
  const silentMissed = rows.filter(r => r.silent && !r.flag).length;
  const anyDef = d1 || d2 || d3;

  let hint = "Uključi/isključi definicije i pomiči prag. Gledaj kako se mijenja TKO je označen kao churn — a time i koga ćeš stvarno kontaktirati.";
  if (!anyDef) hint = "Nijedna definicija nije uključena — model ne zna što uopće traži. „Churn” mora imati jasnu, mjerljivu definiciju.";
  else if (falseAlarms > 0) hint = "Definicija „neaktivnost ≥ prag” uključuje korisnike koji su na godišnjem, a obnovili su ugovor — gotovo sigurno lojalne ljude. Definicija nije neutralna: ona stvara „lažne mete”.";
  else if (silentMissed > 0) hint = "Postoje „tihi odlasci” (neaktivni + neobnovljeni, ali nisu tražili deaktivaciju) koje trenutna definicija PROPUŠTA. Mijenjaš li definiciju, mijenjaš i koga vidiš.";

  return (
    <div className="widget">
      <span className="wlab">ista stvarnost, različite definicije cilja</span>

      <div className="panel">
        <span className="panel-tag">Panel A · Što uopće mjerimo?</span>
        <h4>Definicija ciljne varijable (churn = 1)</h4>
        <div className="chips">
          <span className={"chip" + (d1 ? " on" : "")} onClick={() => setD1(v => !v)}>Neaktivnost ≥ prag</span>
          <span className={"chip" + (d2 ? " on" : "")} onClick={() => setD2(v => !v)}>Ugovor nije obnovljen</span>
          <span className={"chip" + (d3 ? " on" : "")} onClick={() => setD3(v => !v)}>Zatražio deaktivaciju</span>
        </div>
        <div className={"ctrl" + (d1 ? "" : " dim")} style={{ marginTop: 14, maxWidth: 360 }}>
          <label>Prag neaktivnosti: <span className="val">{prag} dana</span> {d1 ? "" : "(vrijedi samo za prvu definiciju)"}</label>
          <input type="range" min="20" max="120" step="5" value={prag} disabled={!d1} onChange={e => setPrag(+e.target.value)} />
        </div>

        <div className="tablewrap">
          <table className="ctab">
            <thead>
              <tr><th>Korisnik</th><th>Dani neakt.</th><th>Ugovor obnovljen</th><th>Zatražio deakt.</th><th>Na godišnjem</th><th>Churn = 1?</th></tr>
            </thead>
            <tbody>
              {rows.map(r => (
                <tr key={r.id} className={r.flag ? "flag" : ""}>
                  <td className="name">{r.ime}</td>
                  <td>{r.dani}</td>
                  <td><span className={"pill " + (r.obn ? "no" : "yes")}>{r.obn ? "DA" : "NE"}</span></td>
                  <td><span className={"pill " + (r.deakt ? "yes" : "no")}>{r.deakt ? "DA" : "NE"}</span></td>
                  <td><span className={"pill " + (r.god ? "yes" : "no")}>{r.god ? "DA" : "NE"}</span></td>
                  <td>
                    {r.flag ? <b style={{ color: "var(--warn)" }}>DA</b> : "—"}
                    {r.falseAlarm && <span className="tagmini holiday">⚑ na godišnjem — vjerojatno pogrešno</span>}
                    {r.silent && !r.flag && <span className="tagmini">tihi odlazak — propušten</span>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        <div className="readout">
          <div className="stat acc"><span className="k">Označeno (kontaktiraš)</span><span className="v">{flagged}</span></div>
          <div className="stat warn"><span className="k">Vjerojatno pogrešno</span><span className="v">{falseAlarms}</span></div>
          <div className="stat warn"><span className="k">Tihi odlasci propušteni</span><span className="v">{silentMissed}</span></div>
        </div>
        <div className="hintline">{hint}</div>
      </div>

      <div className="panel">
        <span className="panel-tag">Panel B · Što uopće SMIJEMO znati u trenutku odluke?</span>
        <h4>Curenje podataka (data leakage)</h4>
        <p className="intro" style={{ marginBottom: 14 }}>
          Drugo je pitanje, posve odvojeno od definicije: model smije koristiti samo podatke koji bi <b>postojali u trenutku odluke</b>.
          Dodajmo značajku <code>kontakti podršci 30 dana NAKON datuma raskida</code> — informaciju iz budućnosti.
        </p>
        <label className="toggle" style={{ marginBottom: 12 }}>
          <input type="checkbox" checked={leak} onChange={e => setLeak(e.target.checked)} /> uključi značajku iz budućnosti
        </label>

        <div style={{ display: "flex", alignItems: "center", gap: 10, fontFamily: "var(--mono)", fontSize: 11, color: "var(--muted)", margin: "6px 0 12px" }}>
          <span>prošlost ✓ dopušteno</span>
          <span style={{ flex: 1, height: 2, background: "var(--line)" }}></span>
          <span style={{ color: "var(--accent)", fontWeight: 600 }}>▌ trenutak odluke</span>
          <span style={{ flex: 1, height: 2, background: leak ? "var(--warn)" : "var(--line)" }}></span>
          <span style={{ color: leak ? "var(--warn)" : "var(--muted)" }}>budućnost {leak ? "✗ procurilo" : "— ne diramo"}</span>
        </div>

        <div className="readout">
          <div className="stat"><span className="k">Točnost na uzorku za učenje</span><span className="v">{leak ? "99%" : "82%"}</span></div>
          <div className={"stat " + (leak ? "warn" : "good")}><span className="k">Točnost na NOVIM korisnicima</span><span className="v">{leak ? "56%" : "80%"}</span></div>
        </div>
        <div className="hintline">
          {leak
            ? "Predobro da bi bilo istinito: na uzorku model izgleda gotovo savršeno, jer „viri” u ishod. Na stvarnim novim korisnicima — gdje te informacije još NEMA — ruši se."
            : "Bez curenja model je skromniji na uzorku, ali pošten i stabilan na novim podacima. To je ono što vrijedi u praksi."}
        </div>
        <div className="note warn">
          <strong>Curenje ≠ overfitting.</strong> Nije problem da je model „prenaučio šum”; problem je da koristi značajku koja u trenutku
          predikcije <b>uopće ne bi postojala</b>. (Brojke su demonstracijski ekstrem.)
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   WIDGET 3 — PROXY PRISTRANOST LAB
   ============================================================ */
const PROXY_VARS = [
  { key: "prijave", label: "Broj prijava / aktivnost", kind: "ok", w: 1.0 },
  { key: "postal", label: "Poštanski broj", kind: "proxy", w: 0.6 },
  { key: "uredaj", label: "Vrsta uređaja", kind: "proxy", w: 0.45 },
  { key: "dob", label: "Dob", kind: "sens", w: 0.4 },
  { key: "spol", label: "Spol", kind: "sens", w: 0.3 },
];
const KIND_LABEL = { ok: "ponašajna", proxy: "proxy", sens: "osjetljiva" };
const CONTEXTS = {
  kredit: "kredit odobren",
  kandidat: "kandidat pozvan na razgovor",
  ponuda: "ponuda za zadržavanje poslana",
};

function ProxyLab() {
  const [on, setOn] = useState({ prijave: true, postal: true, uredaj: true, dob: true, spol: true });
  const [ctx, setCtx] = useState("kredit");

  const POP = useMemo(() => {
    const rng = mulberry32(20260623);
    const arr = [];
    for (let i = 0; i < 200; i++) {
      const high = rng() < 0.5;            // skupina s višim prihodom kvarta
      const inc = high ? 1 : 0;
      const prijave = clamp(0.5 + (high ? 0.05 : -0.05) + 0.5 * (rng() - 0.5), 0, 1);
      const postal = clamp((high ? 0.59 : 0.41) + 0.55 * (rng() - 0.5), 0, 1);
      const uredaj = clamp((high ? 0.58 : 0.42) + 0.6 * (rng() - 0.5), 0, 1);
      const dob = clamp(0.3 + 0.5 * rng(), 0, 1);
      const spol = rng() < 0.5 ? 0.35 : 0.65;
      const merit = clamp(0.7 * prijave + 0.3 * rng(), 0, 1);          // legitimni signal
      const histScore = 0.55 * merit + 0.45 * inc + 0.25 * (rng() - 0.5); // povijesna (pristrana) odluka
      arr.push({ i, high, vals: { prijave, postal, uredaj, dob, spol }, merit, histScore });
    }
    const cut = Math.floor(arr.length * 0.3);
    [...arr].sort((a, b) => b.histScore - a.histScore).forEach((c, idx) => c.hist = idx < cut ? 1 : 0);
    return arr;
  }, []);

  const res = useMemo(() => {
    const anyOn = PROXY_VARS.some(v => on[v.key]);
    if (!anyOn) return { anyOn: false };
    const score = c => PROXY_VARS.reduce((s, v) => on[v.key] ? s + v.w * c.vals[v.key] : s, 0);
    const cut = Math.floor(POP.length * 0.3);
    const sel = new Set([...POP].sort((a, b) => score(b) - score(a)).slice(0, cut).map(c => c.i));
    let selHigh = 0, nHigh = 0, selLow = 0, nLow = 0, agree = 0;
    POP.forEach(c => {
      const s = sel.has(c.i) ? 1 : 0;
      if (c.high) { nHigh++; selHigh += s; } else { nLow++; selLow += s; }
      if (s === c.hist) agree++;
    });
    const rHigh = selHigh / nHigh, rLow = selLow / nLow;
    const ratio = rHigh > 0 ? rLow / rHigh : 0;
    return { anyOn: true, rHigh, rLow, ratio, acc: agree / POP.length };
  }, [on, POP]);

  const sensOff = !on.dob && !on.spol;
  const proxyOff = !on.postal && !on.uredaj;
  let hint = "Uključuj i isključuj varijable. Gledaj omjer udjela odabranih između skupina (pravilo 4/5: omjer < 0,80 je znak nerazmjernog učinka).";
  if (!res.anyOn) hint = "Nijedna varijabla — nema modela. Uključi barem jednu.";
  else if (sensOff && !proxyOff) hint = "Maknuo si dob i spol, ali „poštanski broj” i „uređaj” nose isti društveni signal (proxy). Razlika između skupina ostaje — model i dalje diskriminira, samo posredno.";
  else if (sensOff && proxyOff) hint = "Maknuo si i osjetljive i proxy varijable — a razlika i dalje postoji, jer i ponašajna varijabla blago korelira s prihodom skupine. Pravednost NIJE samo brisanje stupaca.";

  return (
    <div className="widget">
      <span className="wlab">odabir varijabli → pravednost između skupina</span>
      <div className="ctrl" style={{ maxWidth: 320, marginBottom: 4 }}>
        <label>Što znači „odabran”?</label>
        <select value={ctx} onChange={e => setCtx(e.target.value)}>
          {Object.entries(CONTEXTS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
        </select>
      </div>
      <div className="chips">
        {PROXY_VARS.map(v => (
          <span key={v.key} className={"chip" + (on[v.key] ? " on" : "")} onClick={() => setOn(o => ({ ...o, [v.key]: !o[v.key] }))}>
            {v.label}<span className={"kind " + v.kind}>{KIND_LABEL[v.kind]}</span>
          </span>
        ))}
      </div>

      <div className="scen" style={{ marginTop: 16 }}>
        <span className="wlab" style={{ marginBottom: 6 }}>udio kojem je „{CONTEXTS[ctx]}” — po skupini</span>
        <div className="gbars">
          <div className="gbar">
            <div className="gl"><span>Skupina s nižim prihodom kvarta</span><b>{pct(res.rLow)}</b></div>
            <div className="gt"><div className="gf low" style={{ width: pct(clamp(res.rLow || 0, 0, 1)) }}></div></div>
          </div>
          <div className="gbar">
            <div className="gl"><span>Skupina s višim prihodom kvarta</span><b>{pct(res.rHigh)}</b></div>
            <div className="gt"><div className="gf high" style={{ width: pct(clamp(res.rHigh || 0, 0, 1)) }}></div></div>
          </div>
        </div>
      </div>

      <div className="readout">
        <div className={"stat key " + (res.ratio && res.ratio < 0.8 ? "warn" : "good")}>
          <span className="k">Omjer (pravilo 4/5)</span><span className="v">{res.anyOn ? res.ratio.toFixed(2) : "—"}</span>
        </div>
        <div className="stat acc"><span className="k">Točnost (vs povijesne odluke)</span><span className="v">{res.anyOn ? pct(res.acc) : "—"}</span></div>
      </div>
      <div className="hintline">{hint}</div>

      <div className="note warn">
        <strong>Pravednost nije „obriši spol i dob”.</strong> Proxyji (poštanski broj, uređaj, način plaćanja) prenose isti signal,
        a uklanjanje baš svih korelata zna uništiti model. Pravednost je <b>trajno mjerenje i kompromis</b>, ne jednokratni checkbox.
        Kad makneš proxyje, točnost (mjerena na <em>povijesnim</em> odlukama) zna pasti — dio te „točnosti” zapravo je dolazio iz varijabli
        koje nose neprihvatljiv društveni signal, ne nužno iz namjerne diskriminacije.
      </div>
    </div>
  );
}

/* ============================================================
   WIDGET 4 — ČOVJEK + STROJ: ZONA UPUĆIVANJA (referral band)
   ============================================================ */
function ReferralBand() {
  const [L, setL] = useState(0.32);
  const [H, setH] = useState(0.68);
  const [bias, setBias] = useState(false);
  const cv = useRef(null);

  const SCANS = useMemo(() => {
    const rng = mulberry32(170623);
    const arr = [];
    for (let i = 0; i < 220; i++) {
      const minority = rng() < 0.28;
      const cancer = rng() < 0.11 ? 1 : 0;
      const base = cancer
        ? clamp(0.6 + 0.22 * (rng() * 2 - 1), 0, 1)    // tumori: skew visoko, uz preklapanje
        : clamp(0.33 + 0.27 * (rng() * 2 - 1), 0, 1);  // zdravi: skew nisko, uz preklapanje
      arr.push({ i, minority, cancer, base });
    }
    return arr;
  }, []);

  const setLsafe = v => setL(Math.min(+v, H));
  const setHsafe = v => setH(Math.max(+v, L));

  const scans = useMemo(() => SCANS.map(s => {
    let score = s.base;
    if (bias && s.minority && s.cancer) score = clamp(score - 0.24, 0, 1); // model slabije „vidi” tumore manjine
    return { ...s, score };
  }), [SCANS, bias]);

  const m = useMemo(() => {
    let tumori = 0, uhvaceno = 0, propusteno = 0, pregled = 0, hitno = 0, lazneHitne = 0;
    let propMaj = 0, propMin = 0;
    scans.forEach(s => {
      if (s.cancer) tumori++;
      const reviewed = s.score >= L;             // sve ≥ L stigne do liječnika
      if (reviewed) pregled++;
      if (s.score > H) { hitno++; if (!s.cancer) lazneHitne++; }
      if (s.cancer) {
        if (reviewed) uhvaceno++;
        else { propusteno++; if (s.minority) propMin++; else propMaj++; }
      }
    });
    return { tumori, uhvaceno, propusteno, pregled, hitno, lazneHitne, propMaj, propMin };
  }, [scans, L, H]);

  useEffect(() => {
    const ctx = cv.current.getContext("2d");
    const W = 720, Hc = 250; ctx.clearRect(0, 0, W, Hc);
    const PADL = 16, PADR = 16, top = 30, bot = 42;
    const X = sc => PADL + sc * (W - PADL - PADR);
    const xL = X(L), xH = X(H);
    // zone pozadine
    ctx.fillStyle = "rgba(42,93,87,.10)"; ctx.fillRect(PADL, top, xL - PADL, Hc - top - bot);
    ctx.fillStyle = "rgba(201,165,102,.18)"; ctx.fillRect(xL, top, xH - xL, Hc - top - bot);
    ctx.fillStyle = "rgba(138,58,31,.10)"; ctx.fillRect(xH, top, W - PADR - xH, Hc - top - bot);
    ctx.fillStyle = "#6f6754"; ctx.font = "10px JetBrains Mono"; ctx.textAlign = "center";
    ctx.fillText("AI sam: „uredno”", (PADL + xL) / 2, Hc - 24);
    ctx.fillText("liječnik pregledava", (xL + xH) / 2, Hc - 24);
    ctx.fillText("hitno → liječnik (prioritet)", (xH + W - PADR) / 2, Hc - 24);
    // točke (beeswarm)
    const buckets = {}; const r = 5.5;
    scans.forEach(s => {
      const px = X(s.score); const key = Math.round(px / (r * 1.7));
      buckets[key] = (buckets[key] || 0); const k = buckets[key]++;
      const py = (top + (Hc - top - bot) / 2) + (k % 2 === 0 ? 1 : -1) * Math.ceil(k / 2) * (r * 1.7) * 0.6;
      ctx.beginPath(); ctx.arc(px, py, r, 0, 7);
      ctx.fillStyle = s.cancer ? "#8a3a1f" : "#2a5d57"; ctx.fill();
      if (bias && s.minority) { ctx.strokeStyle = "#1a1814"; ctx.lineWidth = 1.6; ctx.stroke(); }
      else { ctx.strokeStyle = "#fbf7ec"; ctx.lineWidth = 0.5; ctx.stroke(); }
    });
    // linije L i H
    [[xL, "L"], [xH, "H"]].forEach(([x, lab]) => {
      ctx.strokeStyle = "#1a1814"; ctx.lineWidth = 2;
      ctx.beginPath(); ctx.moveTo(x, top - 6); ctx.lineTo(x, Hc - bot); ctx.stroke();
      ctx.fillStyle = "#1a1814"; ctx.font = "600 11px JetBrains Mono"; ctx.textAlign = "center";
      ctx.fillText(lab, x, 16);
    });
    ctx.fillStyle = "#6f6754"; ctx.font = "11px JetBrains Mono"; ctx.textAlign = "center";
    ctx.fillText("sigurnost AI-a da je nalaz sumnjiv  (0 → 1)", W / 2, Hc - 6);
  }, [scans, L, H, bias]);

  const preset = (l, h) => { setL(l); setH(h); };
  let hint = "Pomiči granice L i H. Sve ispod L AI sam otpušta kao „uredno” — to je jedina potpuno samostalna odluka AI-a, i jedino tu se tumor može izgubiti, a da ga nitko ne provjeri.";
  if (m.propusteno >= 4) hint = "Visok L znači da AI agresivno otpušta nalaze — raste broj propuštenih tumora koje nitko nije pogledao. Brzo, ali opasno: „samo AI” ovdje gubi živote.";
  else if (m.pregled >= 200) hint = "Nizak L šalje gotovo sve liječniku — nula propuštenih, ali ogromno opterećenje. „Samo liječnik” je sigurno, ali neodrživo.";
  else if (m.propusteno <= 1 && m.pregled < 150) hint = "Dobra ravnoteža: AI filtrira očito uredne nalaze, liječnik vidi sve ostalo (uz prioritet za najhitnije). Malo propuštenih, podnošljivo opterećenje. AI pomaže — ne odlučuje sam.";

  return (
    <div className="widget">
      <span className="wlab">probir CT snimaka · ~10% ima tumor · AI predfiltrira, liječnik presuđuje</span>
      <canvas ref={cv} width="720" height="250"></canvas>
      <div className="legend">
        <span><span className="dotc" style={{ background: "#8a3a1f" }}></span> stvarno ima tumor</span>
        <span><span className="dotc" style={{ background: "#2a5d57" }}></span> zdrav</span>
        {bias && <span><span className="dotc" style={{ background: "#fff", border: "1.6px solid #1a1814" }}></span> manjinska skupina</span>}
      </div>

      <div className="ctrls">
        <div className="ctrl" style={{ flex: 1, minWidth: 200 }}>
          <label>Donja granica L (AI sam otpušta ispod): <span className="val">{L.toFixed(2)}</span></label>
          <input type="range" min="0" max="1" step="0.01" value={L} onChange={e => setLsafe(e.target.value)} />
        </div>
        <div className="ctrl" style={{ flex: 1, minWidth: 200 }}>
          <label>Gornja granica H (iznad = hitno): <span className="val">{H.toFixed(2)}</span></label>
          <input type="range" min="0" max="1" step="0.01" value={H} onChange={e => setHsafe(e.target.value)} />
        </div>
      </div>
      <div className="wbtns" style={{ marginTop: 4 }}>
        <button className="btn-ghost" onClick={() => preset(0.70, 0.70)}>Samo AI (otpušta agresivno)</button>
        <button className="btn-ghost" onClick={() => preset(0.0, 1.0)}>Samo liječnik</button>
        <button className="btn-prim" onClick={() => preset(0.32, 0.68)}>AI + liječnik</button>
      </div>

      <div className="readout">
        <div className="stat"><span className="k">Tumora ukupno</span><span className="v">{m.tumori}</span></div>
        <div className="stat good"><span className="k">Uhvaćeno</span><span className="v">{m.uhvaceno}</span></div>
        <div className={"stat key " + (m.propusteno > 1 ? "warn" : "good")}><span className="k">Propušteno (nitko ne provjeri)</span><span className="v">{m.propusteno}</span></div>
        <div className="stat acc"><span className="k">Liječnik pregledava</span><span className="v">{m.pregled}</span></div>
        <div className="stat"><span className="k">Nepotrebno u hitnom redu</span><span className="v">{m.lazneHitne}</span></div>
      </div>
      <div className="hintline">{hint}</div>

      <div className="scen" style={{ marginTop: 16 }}>
        <span className="wlab" style={{ marginBottom: 6 }}>Tko snosi odgovornost?</span>
        <p className="story">
          Greške u zoni „<b>AI sam: uredno</b>” nitko nije provjerio — za njih odgovara <b>sustav / proizvođač i onaj tko ga je tako postavio</b>.
          Sve što stigne liječniku presuđuje i potpisuje <b>čovjek</b>. Zato AI ovdje <b>pomaže i prioritizira, ali ne dijagnosticira sam</b>.
        </p>
        <p className="story" style={{ marginTop: 8, fontSize: 13 }}>Pojednostavljenje simulacije: pretpostavljamo da liječnik točno presudi sve što pregleda.</p>
      </div>

      <label className="toggle" style={{ marginTop: 14 }}>
        <input type="checkbox" checked={bias} onChange={e => setBias(e.target.checked)} /> uključi manjinsku skupinu (model ju je slabije „naučio”)
      </label>
      {bias && (
        <div className="note warn">
          <strong>Isti prag, nejednak ishod.</strong> Propušteni tumori — većinska skupina: <b>{m.propMaj}</b>, manjinska skupina: <b>{m.propMin}</b>.
          Model je manje siguran na skupini iz koje ima manje podataka, pa njihovi nalazi padaju u zonu „uredno” i gube se. Pravedan prag za jedne nije pravedan za druge.
        </div>
      )}
    </div>
  );
}

/* ============================================================
   WIDGET 5 — RIZICI OKO NAS: lažne vijesti, privatnost, sektori, timovi
   ============================================================ */
const RISK_CARDS = [
  { ic: "🎭", h: "Lažne vijesti i deepfake", ask: "Klikni: kako prepoznati i zašto je opasno?",
    body: <span><span className="ris">Rizik:</span> AI generira uvjerljiv lažni glas direktora koji telefonom traži „hitnu uplatu”, ili video političara koji nikad nije snimljen.
      <b>Kako se braniš?</b> Provjeri kroz drugi kanal (nazovi natrag), traži potvrdu, sumnjaj na hitnju i pritisak. Tehnologija je jeftina i brza — povjerenje u „ono što vidim i čujem” više nije dovoljno.</span> },
  { ic: "🔒", h: "Privatnost", ask: "Klikni: gdje curi i tko je odgovoran?",
    body: <span><span className="ris">Rizik:</span> medicinski, lokacijski i ponašajni podaci su osjetljivi; model ih može „zapamtiti” ili otkriti, a pristanak je često nejasan.
      <b>Kako se braniš?</b> Prikupljaj samo nužno, anonimiziraj, jasno traži pristanak, ograniči pristup. Pitanje nije samo „možemo li tehnički” nego „smijemo li i jesmo li pitali”.</span> },
];

const SEKTORI = [
  { ic: "🏦", h: "Financije", ben: "detekcija prijevara, brža procjena kreditnog rizika", ris: "pristranost prema profilima, netransparentne odluke, zloupotreba podataka" },
  { ic: "🎓", h: "Obrazovanje", ben: "personalizirano učenje, rano prepoznavanje napuštanja škole", ris: "algoritamska segregacija („manje sposoban”), praćenje bez pristanka" },
  { ic: "🌍", h: "Zaštita okoliša", ben: "predviđanje zagađenja, rano otkrivanje požara i poplava", ris: "manipulacija podacima, prevelika ovisnost o automatici" },
];

const MATCH_RISKS = [
  { id: "data", t: "Curenje osjetljivih podataka", team: "pravni" },
  { id: "bias", t: "Pristranost prema skupinama", team: "etika" },
  { id: "tech", t: "Tehnička pogreška modela", team: "it" },
  { id: "rep", t: "Reputacijska / strateška šteta", team: "uprava" },
];
const MATCH_TEAMS = [
  { id: "pravni", t: "Pravni / zaštita podataka (DPO)" },
  { id: "etika", t: "Etika + struka (npr. liječnik, pedagog)" },
  { id: "it", t: "IT / tim za podatke" },
  { id: "uprava", t: "Uprava / menadžment" },
];

function GovernanceLab() {
  const [open, setOpen] = useState({});
  const [sekOpen, setSekOpen] = useState({});
  const [selRisk, setSelRisk] = useState(null);
  const [matched, setMatched] = useState({}); // riskId -> teamId
  const [wrong, setWrong] = useState(null);

  const clickTeam = (teamId) => {
    if (!selRisk) return;
    const risk = MATCH_RISKS.find(r => r.id === selRisk);
    if (risk.team === teamId) { setMatched(m => ({ ...m, [selRisk]: teamId })); setSelRisk(null); setWrong(null); }
    else { setWrong(teamId); setTimeout(() => setWrong(null), 600); }
  };
  const allMatched = Object.keys(matched).length === MATCH_RISKS.length;

  return (
    <div className="widget">
      <span className="wlab">rizici nisu samo tehnički — i nisu posao samo jednog tima</span>

      <h4 className="wsub"><span className="n">1</span>Dvije prijetnje koje rastu najbrže</h4>
      <div className="flipgrid">
        {RISK_CARDS.map((c, i) => (
          <div key={i} className={"flip" + (open[i] ? " open" : "")} onClick={() => setOpen(o => ({ ...o, [i]: !o[i] }))}>
            <span className="ic">{c.ic}</span>
            <h4>{c.h}</h4>
            {open[i] ? <p className="rev">{c.body}</p> : <p className="ask">{c.ask}</p>}
          </div>
        ))}
      </div>

      <h4 className="wsub"><span className="n">2</span>Koji je sektor najosjetljiviji? Prvo pretpostavi, pa otkrij</h4>
      <div className="flipgrid">
        {SEKTORI.map((s, i) => (
          <div key={i} className={"flip" + (sekOpen[i] ? " open" : "")} onClick={() => setSekOpen(o => ({ ...o, [i]: !o[i] }))}>
            <span className="ic">{s.ic}</span>
            <h4>{s.h}</h4>
            {sekOpen[i]
              ? <p className="rev"><b className="ben">Korist</b><span className="ben">{s.ben}</span><b className="ris">Rizik</b><span className="ris">{s.ris}</span></p>
              : <p className="ask">Klikni za korist i rizik.</p>}
          </div>
        ))}
      </div>

      <h4 className="wsub"><span className="n">3</span>Spoji rizik s timom koji ga mora pokriti</h4>
      <div className="matchwrap">
        <div className="mcol">
          <h4>Rizik</h4>
          {MATCH_RISKS.map(r => (
            <button key={r.id}
              className={"mitem" + (matched[r.id] ? " done" : "") + (selRisk === r.id ? " sel" : "")}
              disabled={!!matched[r.id]}
              onClick={() => setSelRisk(r.id)}>
              <span className="mnum">{matched[r.id] ? "✓" : "?"}</span>{r.t}
            </button>
          ))}
        </div>
        <div className="mcol">
          <h4>Tko mora sudjelovati</h4>
          {MATCH_TEAMS.map(t => {
            const usedBy = Object.entries(matched).find(([, v]) => v === t.id);
            return (
              <button key={t.id}
                className={"mitem" + (usedBy ? " done" : "") + (wrong === t.id ? " sel" : "")}
                disabled={!!usedBy}
                onClick={() => clickTeam(t.id)}>
                <span className="mnum">{usedBy ? "✓" : "→"}</span>{t.t}
              </button>
            );
          })}
        </div>
      </div>
      {selRisk && !allMatched && <div className="hintline">Sada klikni tim koji bi morao pokrivati taj rizik.</div>}
      {allMatched && <div className="note"><strong>Sve spojeno.</strong> Nijedan tim sam ne pokriva sve rizike — zato razvoj AI rješenja nije „samo IT projekt”. Treba i pravo, i struku/etiku, i upravu, već <em>prije</em> nego što model krene u produkciju.</div>}
    </div>
  );
}

/* ============================================================
   KVIZ
   ============================================================ */
const QUIZ = [
  {
    q: "Tvrtka ima objektivno odličan AI model (točnost 95%), ali zaposlenici ga ne koriste. Što je, prema „umnošku usvajanja”, najvjerojatniji uzrok?",
    a: ["Model je premalo točan", "Nedostaje jedan od faktora: razumijevanje, sklad s navikama ili povjerenje — a oni se množe, pa jedan nula ruši sve", "Treba samo bolji marketing"],
    correct: 1, why: "Usvajanje = Kvaliteta × Edukacija × Navike × Povjerenje. Kvaliteta je samo jedan množitelj; ako ljudi ne razumiju, ne vjeruju ili im ne pristaje u rad, rezultat je nula."
  },
  {
    q: "Churn definiraš kao „60 dana neaktivnosti”. Što je glavni rizik te definicije?",
    a: ["Prespora je za izračun", "Označit će i lojalne korisnike koji su npr. na godišnjem — definicija stvara „lažne mete” i mijenja koga kontaktiraš", "Uvijek je točnija od ostalih definicija"],
    correct: 1, why: "Definicija cilja nije neutralna. „60 dana” pogađa i nekoga tko je samo na odmoru; druga definicija dala bi drugačiji popis i druge poslovne odluke."
  },
  {
    q: "Model na uzorku za učenje ima 99% točnosti, ali na novim korisnicima pada na 56%. Najvjerojatniji uzrok?",
    a: ["Overfitting — prenaučio je šum", "Curenje podataka — koristi značajku koja u trenutku odluke ne bi postojala (npr. događaj iz budućnosti)", "Premalo varijabli"],
    correct: 1, why: "Klasičan potpis curenja podataka (data leakage): „predobro da bi bilo istinito”. Značajka iz budućnosti diže točnost na uzorku, a na stvarnim podacima je nema pa se model ruši. To nije isto što i overfitting."
  },
  {
    q: "Da bi model bio pravedan, iz njega makneš „spol” i „dob”. Je li dovoljno?",
    a: ["Da, time je diskriminacija nemoguća", "Ne — proxy varijable (poštanski broj, uređaj) nose isti signal, pa razlika ostaje; pravednost se mora mjeriti, nije brisanje stupaca", "Da, ako model ima visoku točnost"],
    correct: 1, why: "Proxy diskriminacija prolazi nezapaženo: poštanski broj/uređaj koreliraju s prihodom i demografijom. Pravednost je trajno mjerenje po skupinama i kompromis, ne jednokratni checkbox."
  },
  {
    q: "U probiru CT snimaka, koja je jedina odluka koju AI u sigurnoj postavci smije donijeti potpuno sam — i zašto je baš ta najopasnija?",
    a: ["Da sam dijagnosticira tumor — jer je brz", "Da sam otpiše nalaz kao „uredno” — jer tada nitko ne provjeri eventualni propušteni tumor", "Da odredi terapiju — jer ima više podataka od liječnika"],
    correct: 1, why: "Faithful postavka: AI sam smije samo predfiltrirati očito uredne nalaze, sve ostalo ide liječniku. Upravo zato je zona „AI sam: uredno” najosjetljivija — propušteni tumor ondje nitko ne uhvati. AI pomaže, ne odlučuje sam."
  },
  {
    q: "Stiže telefonski poziv „direktora” (uvjerljiv glas) koji traži hitnu uplatu. Najbolji prvi potez?",
    a: ["Odmah izvršiti — glas je prepoznatljiv", "Provjeriti kroz drugi kanal (nazvati natrag na poznati broj) — glas i video se danas lako lažiraju (deepfake)", "Proslijediti poziv kolegi"],
    correct: 1, why: "Deepfake glas/video su jeftini i uvjerljivi. „Vidim i čujem” više nije dokaz; obrana je provjera kroz neovisan kanal i oprez na pritisak hitnje."
  },
];

function Quiz() {
  const [answered, setAnswered] = useState({});
  const [score, setScore] = useState(0);
  const pick = (qi, oi) => {
    if (answered[qi] !== undefined) return;
    setAnswered(a => ({ ...a, [qi]: oi }));
    if (oi === QUIZ[qi].correct) setScore(s => s + 1);
  };
  const done = Object.keys(answered).length === QUIZ.length;
  return (
    <div>
      <div className="quiz">
        {QUIZ.map((item, qi) => (
          <div className="q" key={qi}>
            <div className="qt">{qi + 1}. {item.q}</div>
            <div className="opts">
              {item.a.map((txt, oi) => {
                const picked = answered[qi];
                let cls = "opt";
                if (picked !== undefined) {
                  if (oi === item.correct) cls += " correct";
                  else if (oi === picked) cls += " wrong";
                }
                return <button key={oi} className={cls} disabled={picked !== undefined} onClick={() => pick(qi, oi)}>{txt}</button>;
              })}
            </div>
            {answered[qi] !== undefined && (
              <div className={"fb show " + (answered[qi] === item.correct ? "ok" : "no")}>
                {answered[qi] === item.correct ? "✔ Točno! " : "✗ Netočno. "}{item.why}
              </div>
            )}
          </div>
        ))}
      </div>
      {done && <div className="score">Rezultat: {score} / {QUIZ.length}</div>}
    </div>
  );
}

/* ============================================================
   APP
   ============================================================ */
function App() {
  return (
    <div className="wrap">
      <header className="topbar">
        <a className="brand" href="../">
          <span className="brand-mark" aria-hidden="true">D</span>
          <span><span className="brand-name">Dragutin Oreški</span>
            <span className="brand-meta">UI Suputnik · Susret 17</span></span>
        </a>
        <nav className="topbar-right"><a href="../">← Susreti</a></nav>
      </header>

      <header className="hero">
        <div className="floatword">volan</div>
        <p className="kicker">Klasa 17 · Umjetna inteligencija</p>
        <h1>AI je moćan motor —<br /><em>netko mora držati volan</em></h1>
        <p className="lede">Umjetna inteligencija nije svemoguća: njome se <b>upravlja</b>. Danas gledamo gdje ljudski izbori
          odlučuju o ishodu — kako se tehnologija usvaja, kako biramo podatke i ciljeve, gdje nastaje pristranost i tko
          ostaje odgovoran. Pojmove ne čitaš nego ih pomičeš i gledaš posljedice.</p>
        <div className="uses">
          <span className="use">📈 Percepcija i usvajanje</span>
          <span className="use">🎯 Ciljna varijabla</span>
          <span className="use">⚖️ Pristranost i proxy</span>
          <span className="use">🩺 Čovjek + stroj</span>
          <span className="use">🛡️ Rizici i odgovornost</span>
        </div>
      </header>

      <section>
        <p className="sec-tag">Pregled</p>
        <h2>Jedna nit: upravljanje</h2>
        <p className="intro">AI sam po sebi ne jamči uspjeh — <b>generička rješenja uglavnom ne rješavaju konkretne probleme</b>.
          Kroz sva tri sata vraća se isto pitanje: <b>tko drži volan</b>? Usvajanje ovisi o ljudima, pristranost ulazi kroz
          podatke i ciljeve koje <i>mi</i> biramo, a rizik se obuzdava ljudskim nadzorom i odgovornošću.</p>
        <div className="steps">
          <div className="step"><span className="ic">📈</span><h3>Percepcija</h3>
            <p>Zašto i objektivno dobra tehnologija propada bez povjerenja, edukacije i sklada s navikama.</p>
            <span className="algo">→ Zašto tehnologija propada</span></div>
          <div className="step"><span className="ic">🎯</span><h3>Podaci i ciljevi</h3>
            <p>Kako definicija cilja mijenja odluke i zašto se podaci iz budućnosti ne smiju koristiti.</p>
            <span className="algo">→ Ciljna varijabla + curenje</span></div>
          <div className="step"><span className="ic">⚖️</span><h3>Pristranost</h3>
            <p>Pristranost ne počinje u algoritmu nego u varijablama koje biramo — i u proxyjima.</p>
            <span className="algo">→ Proxy pristranost</span></div>
          <div className="step"><span className="ic">🩺</span><h3>Nadzor</h3>
            <p>AI kao pomoćnik, ne donositelj odluke; tko snosi odgovornost i tko mora sudjelovati.</p>
            <span className="algo">→ Čovjek + stroj, rizici</span></div>
        </div>
      </section>

      <section>
        <p className="sec-tag">Sat 1 · benefiti i percepcija</p>
        <h2>Zašto dobra tehnologija propada</h2>
        <p className="intro">AI donosi automatizaciju, bolje odluke i veću učinkovitost — ali sve to vrijedi tek ako se <b>usvoji</b>.
          Usvajanje nije zbroj nego <b>umnožak</b> faktora: kvaliteta, edukacija tržišta, sklad s navikama i povjerenje.
          Pomiči klizače i otkrij zašto savršen proizvod (ili model) može završiti neiskorišten.</p>
        <AdoptionLab />
      </section>

      <section>
        <p className="sec-tag">Sat 2 · izazovi (1/2)</p>
        <h2>Što uopće mjerimo — i smijemo li to znati?</h2>
        <p className="intro">Prije svakog modela donosimo dvije tihe, ali presudne odluke: <b>kako definiramo cilj</b> (što je uopće „churn”?)
          i <b>koje podatke smijemo koristiti</b> u trenutku odluke. Obje su prilike da nesvjesno iskrivimo rezultat. Isti korisnici,
          različite definicije — različite poslovne odluke.</p>
        <TargetLab />
      </section>

      <section>
        <p className="sec-tag">Sat 2 · izazovi (2/2)</p>
        <h2>Gdje zapravo nastaje pristranost</h2>
        <p className="intro">AI ne diskriminira „namjerno” — preuzima obrasce iz podataka koje <i>mi</i> biramo. Maknuti spol i dob nije dovoljno:
          <b> proxy varijable</b> (poštanski broj, uređaj) tiho prenose isti signal. Uključuj i isključuj varijable i gledaj kako se mijenja
          razlika između skupina — i zašto pravednost nije brisanje stupaca.</p>
        <ProxyLab />
      </section>

      <section>
        <p className="sec-tag">Sat 3 · rizici, etika, čovjek + stroj</p>
        <h2>AI pomaže — ne odlučuje sam</h2>
        <p className="intro">U medicini AI prepoznaje promjene nevidljive oku i ubrzava rad, ali ne smije presuđivati sam. Umjesto jednog praga,
          postavljaš <b>zonu upućivanja</b>: što je očito uredno AI otpušta, ostalo ide liječniku (uz prioritet za najhitnije). Gledaj ravnotežu
          između propuštenih tumora, opterećenja liječnika i — odgovornosti.</p>
        <ReferralBand />
      </section>

      <section>
        <p className="sec-tag">Sat 3 · rizici oko nas i upravljanje</p>
        <h2>Rizici, sektori i tko mora sudjelovati</h2>
        <p className="intro">Rizici AI-a nisu apstraktni: lažne vijesti i deepfake, privatnost, gubitak radnih mjesta, zloupotreba.
          Razlikuju se po sektorima, a obrana je uvijek <b>timska</b> — IT, pravo, struka/etika i uprava zajedno. Istraži kartice i poveži rizik s timom.</p>
        <GovernanceLab />
      </section>

      <section>
        <p className="sec-tag">Provjeri se</p>
        <h2>Kratki kviz</h2>
        <p className="intro">Šest pitanja, odgovor odmah. Klikni opciju koju misliš da je točna.</p>
        <Quiz />
        <div className="note">
          <strong>Glavna poruka susreta.</strong> AI je alat ogromne snage, ali ishod određuju ljudski izbori: kako ga predstavimo i uvedemo,
          kako definiramo cilj, koje podatke i varijable biramo, i koliko zadržimo ljudski nadzor i odgovornost. Tko drži volan — taj upravlja posljedicama.
        </div>
      </section>

      <footer>
        <p className="sent">„AI nije svemoguć — njime treba upravljati.”</p>
        <p>Klasa 17 — Benefiti, rizici i izazovi UI u poslovanju · Umjetna inteligencija (Algebra)<br />
          Radi offline u pregledniku. Brojke su poučne, ne službene statistike.</p>
      </footer>
    </div>
  );
}

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