const { useState, useEffect, useMemo, useRef } = React;

/* ── date globale (data.js) ── */
const CREDINTE = window.PRP_CREDINTE;
const MECANISME = window.PRP_MECANISME;
const DICTIONAR = window.PRP_DICTIONAR;

const FRECVENTE = ["Zilnic", "Săptămânal", "Lunar", "Trimestrial", "Anual", "Angajament (la nevoie)"];
const ZILE_RO = ["Lu", "Ma", "Mi", "Jo", "Vi", "Sâ", "Du"];

/* ── utilitare de timp (prototip client-only: fusul local al persoanei) ── */
const fmtISO = (d) =>
  `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
const startOfWeek = (d) => {
  const x = new Date(d); const day = (x.getDay() + 6) % 7;
  x.setDate(x.getDate() - day); x.setHours(0, 0, 0, 0); return x;
};
const addDays = (d, n) => { const x = new Date(d); x.setDate(x.getDate() + n); return x; };
const sameDay = (a, b) => fmtISO(a) === fmtISO(b);
/* cheia de inregistrare in jurnal, per frecventa */
function periodKey(frecventa, d) {
  if (frecventa === "Săptămânal") return "W" + fmtISO(startOfWeek(d));
  if (frecventa === "Lunar") return fmtISO(d).slice(0, 7);
  if (frecventa === "Trimestrial") return d.getFullYear() + "-Q" + (Math.floor(d.getMonth() / 3) + 1);
  if (frecventa === "Anual") return String(d.getFullYear());
  return fmtISO(d); // Zilnic + Angajament: pe zi
}
function periodLabel(frecventa, d) {
  if (frecventa === "Săptămânal") return "săptămâna asta";
  if (frecventa === "Lunar") return d.toLocaleDateString("ro-RO", { month: "long" });
  if (frecventa === "Trimestrial") return "trimestrul " + (Math.floor(d.getMonth() / 3) + 1);
  if (frecventa === "Anual") return String(d.getFullYear());
  return fmtISO(d);
}
const getInitials = (n) => {
  const p = (n || "").trim().split(/\s+/).filter(Boolean);
  return p.length ? p.slice(0, 2).map((w) => w[0].toUpperCase()).join("") : "?";
};

/* frecventa sugerata din chiar textul actiunii lui Petre; intai frecventa
   explicita, apoi tiparele reactive (conditionate de eveniment) */
function detectFreq(text) {
  const t = text.toLowerCase();
  if (t.includes("zilnic") || t.includes("în fiecare zi") || t.includes("in fiecare zi")) return "Zilnic";
  if (t.includes("săptămân") || t.includes("saptaman")) return "Săptămânal";
  if (t.includes("lunar")) return "Lunar";
  if (t.includes("trimestrial")) return "Trimestrial";
  if (t.includes("anual")) return "Anual";
  if (/maximum \d+ (minute|ore|de ore)|în maximum|in maximum|la primul|după fiecare|dupa fiecare|fiecărei|in fiecare situa|în fiecare situa|de la aflarea|de la confirmarea|de la observare|când celălalt|imediat/.test(t)) {
    return "Angajament (la nevoie)";
  }
  return null;
}

/* ── icons (stroke 1.7) ── */
const Ic = ({ d, size = 18, sw = 1.7, children }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
       strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    {d ? <path d={d} /> : children}
  </svg>
);
const IcHome = (p) => <Ic {...p}><path d="m3 10.5 9-7.5 9 7.5" /><path d="M5 9.5V21h14V9.5" /><path d="M10 21v-6h4v6" /></Ic>;
const IcUser = (p) => <Ic {...p}><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4 3.6-6 8-6s8 2 8 6" /></Ic>;
const IcBook = (p) => <Ic {...p}><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20V3H6.5A2.5 2.5 0 0 0 4 5.5v14z" /><path d="M4 19.5A2.5 2.5 0 0 0 6.5 22H20v-5" /></Ic>;
const IcGem = (p) => <Ic {...p}><path d="M6 3h12l4 6-10 12L2 9l4-6z" /><path d="M2 9h20" /><path d="M12 21 8 9l4-6 4 6-4 12" /></Ic>;
const IcList = (p) => <Ic {...p}><path d="m3 6 2 2 3.5-4" /><path d="m3 13 2 2 3.5-4" /><path d="m3 20 2 2 3.5-4" /><path d="M12 6h9" /><path d="M12 13h9" /><path d="M12 20h9" /></Ic>;
const IcCal = (p) => <Ic {...p}><rect x="3" y="5" width="18" height="16" rx="2" /><path d="M8 3v4M16 3v4M3 10h18" /></Ic>;
const IcTarget = (p) => <Ic {...p}><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="4.5" /><circle cx="12" cy="12" r="0.5" /></Ic>;
const IcPlus = (p) => <Ic {...p}><path d="M12 5v14M5 12h14" /></Ic>;
const IcCheck = (p) => <Ic {...p}><path d="m4.5 12.5 5 5 10-11" /></Ic>;
const IcX = (p) => <Ic {...p}><path d="M6 6l12 12M18 6L6 18" /></Ic>;
const IcChev = (p) => <Ic {...p}><path d="m9 6 6 6-6 6" /></Ic>;
const IcChevL = (p) => <Ic {...p}><path d="m15 6-6 6 6 6" /></Ic>;
const IcSearch = (p) => <Ic {...p}><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></Ic>;
const IcSun = (p) => <Ic {...p}><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4" /></Ic>;
const IcMoon = (p) => <Ic {...p}><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z" /></Ic>;
const IcArrow = (p) => <Ic {...p}><path d="M5 12h14M13 6l6 6-6 6" /></Ic>;
const IcMenu = (p) => <Ic {...p}><path d="M4 7h16M4 12h16M4 17h16" /></Ic>;

/* ── store persistat ── */
const LS_KEY = "prp-credinte-proto-v1";
const defaultStore = {
  theme: "light",
  view: "acasa",
  credinta: "bunatate",
  consola: { nume: "", dataStart: "", consultant: "Dr. Petre Nicolae", telefon: "", email: "", obs: "" },
  plan: {},
  /* care actiuni din plan au meniul de detalii deschis (cheie de plan -> true); persistat,
     ca sa nu se inchida singur la navigare/reload - cerinta Marian 25.07 */
  detaliiDeschise: {},
  log: {},
  gantt: {},
  anamneza: {},
  valori: { sel: [], plan: {} },
  chv: {},
  viewMod: "lista",
  doarAleMele: false,
  sidebarInchis: false,
  planOrizont: 30,
};
function loadStore() {
  try {
    const raw = localStorage.getItem(LS_KEY);
    if (!raw) return defaultStore;
    const s = { ...defaultStore, ...JSON.parse(raw) };
    /* 25.07: variantele „(nou)" credinte+valori au inlocuit paginile vechi si au preluat
       slugurile originale. Un store salvat inainte poate tine „acasa-nou"/„calendar-nou"/
       „plan-nou" sau vechiul „gantt" - se traduc, ca nimeni sa nu aterizeze pe un view
       inexistent (ar cadea pe Acasa si ar parea ca si-a pierdut pagina). */
    const REDENUMIRI = { "acasa-nou": "acasa", "calendar-nou": "calendar", "plan-nou": "plan", gantt: "plan" };
    if (REDENUMIRI[s.view]) s.view = REDENUMIRI[s.view];
    if (s.view === "dashboard" || !VIEWURI.includes(s.view)) {
      s.view = "acasa";
    }
    if (!s.log) s.log = {};
    if (!s.anamneza) s.anamneza = {};
    if (!s.valori || !Array.isArray(s.valori.sel)) s.valori = { sel: [], plan: {} };
    if (!s.chv) s.chv = {};
    if (!s.biblio) s.biblio = { view: "large", deschise: {} };
    /* migrare aditiva chv: campul "anterior" (o singura completare) devine "istoric"
       (toate completarile arhivate - cerinta Marian 24.07: rezultatele trecute raman vizibile) */
    Object.keys(s.chv).forEach((k) => {
      const e = s.chv[k];
      if (e && !Array.isArray(e.istoric)) {
        e.istoric = e.anterior && e.anterior.finalizat ? [e.anterior] : [];
        delete e.anterior;
      }
    });
    /* migrare aditiva: OA/OR devin CANTITATI per actiune (cerinta Marian 24.07);
       intrarile vechi primesc OA=1, iar OR mosteneste bifa "realizat" (1 sau 0);
       rutina = camp nou (antetul Excel 24.07: coloana Rutinele) */
    if (s.plan) {
      Object.keys(s.plan).forEach((k) => {
        const e = s.plan[k];
        if (typeof e.oa !== "number") e.oa = 1;
        if (typeof e.orNr !== "number") e.orNr = e.realizat ? 1 : 0;
        if (typeof e.rutina !== "string") e.rutina = "";
        /* data asumarii (pt. saptamanile rosii din Planul strategic); intrarile vechi = data start proces */
        if (typeof e.adaugat !== "string") e.adaugat = (s.consola && s.consola.dataStart) || "";
      });
    }
    /* meniurile de detalii deschise: normalizare + curatare de chei ramase fara actiune in plan
       (o actiune scoasa din plan nu trebuie sa reapara deschisa daca e re-adaugata) */
    if (!s.detaliiDeschise || typeof s.detaliiDeschise !== "object") s.detaliiDeschise = {};
    Object.keys(s.detaliiDeschise).forEach((k) => {
      if (!s.plan || !s.plan[k]) delete s.detaliiDeschise[k];
    });
    if (!["lista", "matrice"].includes(s.viewMod)) s.viewMod = "lista";
    if (![30, 60, 90, 120].includes(s.planOrizont)) s.planOrizont = 30;
    s.doarAleMele = !!s.doarAleMele;
    s.sidebarInchis = !!s.sidebarInchis;
    migreazaIdValori(s);
    return s;
  } catch (e) {
    return defaultStore;
  }
}

const VIEWURI = ["acasa", "credinte", "credinta", "anamneza", "valori", "chestionare",
  "calendar", "plan", "dictionar", "biblioteca", "consola", "date-mele"];

/* Deep-link: daca URL-ul cere explicit o pagina, ea BATE ultima pagina salvata in store.
   Inainte, aplicatia rescria hash-ul din store la incarcare, deci un link trimis cuiva il ducea
   unde apucase el sa ramana ultima data (audit 25.07). Sub-navigarile (valori / anamneza /
   chestionare / biblioteca) isi citesc singure restul hash-ului. */
function viewDinHash(s) {
  const h = (location.hash || "").replace(/^#/, "");
  if (!h || h === "reset") return s;
  const [v, sub] = h.split("/");
  if (!VIEWURI.includes(v)) return s;
  const next = { ...s, view: v };
  if (v === "credinta" && sub && CREDINTE.some((c) => c.slug === sub)) next.credinta = sub;
  return next;
}

/* Migrare aditiva 25.07: ID-urile valorilor au fost POZITIONALE (`morale-01`) si au devenit
   derivate din nume (`morale-onorabilitatea-personala`), fiindca ordinea a trecut la cea din
   masterul matricii lui Petre. Fara migrare, un plan salvat pe `morale-02` (Demnitatea) ar
   ateriza pe valoarea care ocupa acum poziția 2 (Probitatea) - date corecte, valoare gresita.
   Harta vine din date (window.PRP_VALORI.aliasId), nu e duplicata aici.
   Idempotenta: un ID care nu e in harta ramane neatins, deci o rulare a doua nu strica nimic. */
function migreazaIdValori(s) {
  const alias = (window.PRP_VALORI && window.PRP_VALORI.aliasId) || null;
  if (!alias || !s.valori) return;
  const nou = (id) => alias[id] || id;
  if (Array.isArray(s.valori.sel)) s.valori.sel = s.valori.sel.map(nou);
  const reScrieChei = (obj, cheieNoua) => {
    if (!obj) return obj;
    const out = {};
    Object.keys(obj).forEach((k) => { out[cheieNoua(k)] = obj[k]; });
    return out;
  };
  s.valori.plan = reScrieChei(s.valori.plan, nou);
  /* itemii urmaribili ai valorilor din hibrid/calendar: cheia "val|<idValoare>|<camp>" */
  const cheieItem = (k) => {
    const p = k.split("|");
    return p.length === 3 && p[0] === "val" ? "val|" + nou(p[1]) + "|" + p[2] : k;
  };
  s.plan = reScrieChei(s.plan, cheieItem);
  s.log = reScrieChei(s.log, cheieItem);
}

/* consola indeplinita = poarta de acces la instrument si la export */
const consolaOk = (s) => s.consola.nume.trim() !== "" && String(s.consola.dataStart || "").trim() !== "";

const keyOf = (slug, ariaNr, indNr, actIdx) => `${slug}|${ariaNr}|${indNr}|${actIdx}`;

/* perechile comportament <-> actiune ale unei arii (structura noua, zoom 2 din 24.07):
   comportamentul k se leaga de actiunea k in cadrul fiecarui indicator; numerotare continua pe arie */
function perechiAria(slug, aria) {
  const rez = [];
  let nr = 0;
  aria.indicatori.forEach((ind) => {
    const n = Math.min(ind.comportamente.length, ind.actiuni.length);
    for (let k = 0; k < n; k++) {
      nr += 1;
      rez.push({ nr, key: keyOf(slug, aria.nr, ind.nr, k), comp: ind.comportamente[k], act: ind.actiuni[k], ind });
    }
  });
  return rez;
}
/* Cheia unei actiuni asumate e POZITIONALA (`credinta|arie|indicator|index`). Cand Dr. Petre
   trimite un document nou si mecanismul se re-parseaza, aceeasi cheie poate ajunge pe ALTA
   actiune (dovedit la auditul din 25.07: `iubire|2|2|0` arata azi altceva decat ieri) sau poate
   ramane fara corespondent, si atunci actiunea dispare tacut din plan. De aceea, la asumare se
   retine si o AMPRENTA a textului: la citire se compara, iar nepotrivirea se semnaleaza. */
const AMPRENTA = 60;
const amprenta = (t) => String(t || "").slice(0, AMPRENTA);

function planEntries(plan) {
  return Object.entries(plan).map(([k, v]) => {
    const [slug, ariaNr, indNr, actIdx] = k.split("|");
    const cred = CREDINTE.find((c) => c.slug === slug);
    const aria = (MECANISME[slug] || []).find((a) => a.nr === +ariaNr);
    const ind = aria && aria.indicatori.find((i) => i.nr === +indNr);
    const text = ind ? ind.actiuni[+actIdx] : "";
    const e = { key: k, slug, cred, aria, ind, actIdx: +actIdx, text,
                vreau: "", nuVreau: "", ancora: "", rutina: "", oa: 1, orNr: 0, ...v };
    /* intrarile de dinaintea amprentei (fara `sursa`) nu se semnaleaza - n-avem cu ce compara */
    e.schimbat = !!(v.sursa && text && amprenta(text) !== v.sursa);
    return e;
  }).filter((e) => e.cred && e.aria && e.ind);
}
/* cheile care nu mai au corespondent in mecanismele curente (actiuni disparute la re-parsare) */
function planOrfane(plan) {
  return Object.keys(plan || {}).length - planEntries(plan || {}).length;
}
/* cate bifari are actiunea in perioada curenta a frecventei ei */
const isLogged = (log, key, pk) => !!(log[key] && log[key][pk]);

/* ziua din care un item intra la socoteala: la credinte = ziua asumarii (`adaugat`), la valori =
   ziua in care campul a fost completat (`adaugat` pus de valori.jsx). Fara ea, o actiune asumata
   azi era judecata si pe zilele in care nici nu exista, iar cifrele scadeau exact cand omul isi
   asuma mai mult (audit 25.07: 100% -> 57% si sir 7 -> 1, dupa o singura adaugare). */
function dinZiua(e) {
  const d = e.adaugat ? new Date(e.adaugat + "T00:00:00") : null;
  return d && !isNaN(d) ? d : null;
}
const activaLa = (e, d) => { const de = dinZiua(e); return !de || de <= d; };

/* conformarea pe ultimele 7 zile (doar actiuni zilnice, doar din ziua asumarii incolo) */
function conform7(entries, log, refDate) {
  const daily = entries.filter((e) => e.frecventa === "Zilnic");
  if (!daily.length) return null;
  let done = 0, expected = 0;
  for (let i = 6; i >= 0; i--) {
    const d = addDays(refDate, -i);
    const iso = fmtISO(d);
    daily.forEach((e) => {
      if (!activaLa(e, d)) return;
      expected += 1;
      if (isLogged(log, e.key, iso)) done += 1;
    });
  }
  return expected ? { done, expected, pct: Math.round((done / expected) * 100) } : null;
}
/* zile consecutive cu TOATE zilnicele bifate (azi intra doar daca e complet); intr-o zi se
   judeca doar actiunile care existau atunci */
function streakZile(entries, log, refDate) {
  const daily = entries.filter((e) => e.frecventa === "Zilnic");
  if (!daily.length) return 0;
  const complete = (d) => {
    const active = daily.filter((e) => activaLa(e, d));
    return active.length > 0 && active.every((e) => isLogged(log, e.key, fmtISO(d)));
  };
  let n = 0;
  let d = complete(refDate) ? refDate : addDays(refDate, -1);
  while (complete(d)) { n += 1; d = addDays(d, -1); if (n > 3650) break; }
  return n;
}

/* helperii expusi view-urilor hibride din hibrid.jsx (spec hibrid 24.07) - ancora ADITIVA;
   const-urile de mai sus raman sursa, aici doar referinte */
window.PRP_UTIL = { fmtISO, addDays, startOfWeek, sameDay, periodKey, periodLabel,
  isLogged, planEntries, conform7, streakZile, ZILE_RO, DICTIONAR,
  /* gettere: pkToDate si CREDINTE sunt declarate mai jos in fisier (TDZ) - se rezolva la acces */
  get pkToDate() { return pkToDate; }, get CREDINTE() { return CREDINTE; },
  IcCheck, IcArrow, IcChev, IcChevL };

/* ── shell ── */
function Sidebar({ store, set, drawer }) {
  const nav = (view, extra) => () => set((s) => ({ ...s, view, ...(extra || {}) }));
  /* doar intrarile valide (cheile orfane ale mecanismelor retrase nu se numara) */
  const planCount = planEntries(store.plan).length;
  const nume = store.consola.nume.trim();
  const gate = !consolaOk(store);
  const shownView = gate ? "consola" : store.view;
  const items = [
    /* ordinea = cea data de Marian (25.07): intai unde LUCREZI zi de zi (Acasa, Calendarul,
       Planul), apoi la ce te UITI (Dictionar, Biblioteca), apoi perechile chestionar ->
       instrument, in ordinea metodologica (intai te evaluezi, apoi lucrezi), la final Consola */
    ["acasa", "Acasă", IcHome],
    ["calendar", "Calendarul meu", IcCal],
    ["plan", "Plan strategic", IcTarget],
    ["dictionar", "Dicționar", IcBook],
    ["biblioteca", "Biblioteca metodologică", window.IcBiblio],
    ["anamneza", "Chestionare credințe", window.IcAnamneza],  /* redenumit din "Anamneza" - zoom 5, aprobat Petre */
    ["credinte", "Credințele mele", IcGem],
    ["chestionare", "Chestionare valori", window.IcChv],
    ["valori", "Valorile mele", window.IcValori],
    ["consola", "Consolă", IcUser],
    /* ce stie instrumentul despre el si ce poate controla - apare doar cand ruleaza pe web,
       fiindca doar acolo exista evidenta (pilot.jsx lipseste din standalone-ul offline) */
    ...(window.PilotDateleMele ? [["date-mele", "Datele mele", window.IcScut || IcUser]] : []),
  ];
  const active = (v) => shownView === v || (v === "credinte" && shownView === "credinta");
  return (
    <aside className={"sidebar" + (drawer ? " sidebar-drawer" : "")}>
      <div className="brand">
        <img src="logo-prp.png" alt="Logo PRP" className="brand-logo" />
        <div style={{ minWidth: 0 }}>
          <div className="brand-prp">People Reconstruction Process</div>
          <div className="brand-name">Credințele Fundamentale</div>
        </div>
      </div>

      {items.map(([v, label, Icon]) => (
        <button key={v} className={"nav-item" + (active(v) ? " active" : "")}
          disabled={gate && v !== "consola"}
          title={gate && v !== "consola" ? "Se deblochează după completarea consolei" : undefined}
          onClick={nav(v)}>
          <Icon /> {label}
          {v === "calendar" && planCount > 0 && <span className="chip" style={{ marginLeft: "auto" }}>{planCount}</span>}
        </button>
      ))}

      <div className="nav-foot">
        <div className="user-row">
          <span className="user-avatar" aria-hidden="true">{getInitials(nume)}</span>
          <span className="user-name">{nume || "Consolă necompletată"}</span>
          <button className="btn btn-ghost btn-sm" style={{ padding: "4px 7px" }}
            title={store.theme === "light" ? "Mod închis" : "Mod deschis"}
            onClick={() => set((s) => ({ ...s, theme: s.theme === "light" ? "dark" : "light" }))}>
            {store.theme === "light" ? <IcMoon size={14} /> : <IcSun size={14} />}
          </button>
        </div>
        <p className="proto-note">Prototip · 23.07.2026<br />Conținut: Dr. Petre Nicolae</p>
      </div>
    </aside>
  );
}


/* meniul orizontal cu toate credintele - saritul direct la oricare */
function CredinteTabs({ store, set }) {
  const activ = store.view === "credinta" ? store.credinta : null;
  return (
    <div className="cred-tabs" role="tablist" aria-label="Credințele">
      {CREDINTE.map((c) => (
        <button key={c.slug} role="tab" aria-selected={activ === c.slug}
          className={"cred-tab" + (activ === c.slug ? " activ" : "") + (!c.gata ? " lucru" : "")}
          title={c.gata ? c.titlu : c.titlu + " - mecanism în lucru la Dr. Petre"}
          onClick={() => set((s) => ({ ...s, view: "credinta", credinta: c.slug }))}>
          {c.nume}
        </button>
      ))}
    </div>
  );
}

/* ── Credintele mele (index) ── */
function CredinteIndexView({ store, set }) {
  const entries = planEntries(store.plan);
  return (
    <div className="page">
      <CredinteTabs store={store} set={set} />
      <div className="grid-2">
        {CREDINTE.map((c) => {
          const arii = MECANISME[c.slug] || [];
          const nPerechi = arii.reduce((n, a) => n + a.indicatori.reduce((m, i) => m + Math.min(i.comportamente.length, i.actiuni.length), 0), 0);
          const inPlan = entries.filter((e) => e.slug === c.slug);
          return (
            <div className={"panel cred-card" + (c.gata ? " cred-card-activ" : "")} key={c.slug}
              role={c.gata ? "button" : undefined} tabIndex={c.gata ? 0 : undefined}
              title={c.gata ? "Deschide " + c.titlu : undefined}
              onClick={c.gata ? () => set((s) => ({ ...s, view: "credinta", credinta: c.slug })) : undefined}
              onKeyDown={c.gata ? (ev) => {
                if (ev.key === "Enter" || ev.key === " ") {
                  ev.preventDefault();
                  set((s) => ({ ...s, view: "credinta", credinta: c.slug }));
                }
              } : undefined}>
              <div className="cred-head">
                <span className="cred-gem"><IcGem size={19} /></span>
                <div style={{ minWidth: 0 }}>
                  <div className="cred-title">{c.titlu}</div>
                  <div className="cred-meta">
                    {c.gata ? `${arii.length} arii · ${nPerechi} comportamente cu acțiuni` : "mecanism în lucru la Dr. Petre"}
                  </div>
                </div>
              </div>
              <div className="row">
                {inPlan.length > 0
                  ? <span className="chip good"><IcCheck size={12} /> {inPlan.length} în plan</span>
                  : <span className="chip outline">{c.gata ? "nicio acțiune aleasă" : "în lucru"}</span>}
                {c.gata && (
                  <button className="btn btn-ghost btn-sm" style={{ marginLeft: "auto" }} tabIndex={-1}>
                    Deschide <IcArrow size={13} />
                  </button>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ── picker frecventa ── */
function FreqPicker({ onPick, onClose, suggested, sus }) {
  const ref = useRef(null);
  useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, [onClose]);
  return (
    <div className={"freq-menu" + (sus ? " sus" : "")} ref={ref} role="menu">
      {FRECVENTE.map((f) => (
        <button key={f} className={f === suggested ? "sug" : ""} onClick={() => onPick(f)}>
          {f}{f === suggested ? <span className="sug-tag">sugerat</span> : null}
        </button>
      ))}
    </div>
  );
}

/* ── Credinta (mecanismul) ── */
/* Matricea credintei - tabelul lui Petre cu input pe randurile alocate (spec 23.07) */
function MatriceCredinta({ cred, arii, store, set, addToPlan, setNr, setRep, picker, setPicker }) {
  const [pickerSus, setPickerSus] = useState(false);
  const grupuri = [];
  arii.forEach((aria) => {
    const perechi = perechiAria(cred.slug, aria).map((p) => ({ ...p, e: store.plan[p.key] }));
    const vizibile = store.doarAleMele ? perechi.filter((p) => p.e) : perechi;
    if (vizibile.length) grupuri.push({ aria, perechi: vizibile });
  });
  return (
    <div className="panel">
      <p className="sect-label">Matricea credinței - {cred.titlu}</p>
      {grupuri.length === 0 ? (
        <div className="small" style={{ padding: "10px 0" }}>
          Nicio acțiune alocată încă - debifează „doar ale mele” sau alocă din coloana Acțiunea.
        </div>
      ) : (
        <div className="mat-scroll">
          <table className="tbl mat-tbl">
            <thead>
              <tr>
                <th rowSpan="2" className="mat-sticky mat-c1">#</th>
                <th rowSpan="2" className="mat-sticky mat-c2">Comportamentul observabil</th>
                <th rowSpan="2" className="mat-sticky mat-c3 mat-edge">Acțiunea concretă</th>
                <th colSpan="2" className="mat-group">Reperele de viață personală</th>
                <th colSpan="2" className="mat-group">Status</th>
                <th rowSpan="2">Principiul de Viață / Ancora de Integrare</th>
                <th rowSpan="2">Rutina</th>
              </tr>
              <tr>
                <th className="mat-h-vreau">Cum vreau să fac asta</th>
                <th className="mat-h-nuvreau">Cum nu trebuie să fac</th>
                <th className="mat-st" title="Obiectiv alocat - de câte ori își asumă acțiunea">OA</th>
                <th className="mat-st" title="Obiectiv realizat - de câte ori a făcut-o">OR</th>
              </tr>
            </thead>
            <tbody>
              {grupuri.map(({ aria, perechi }) => (
                <React.Fragment key={aria.nr}>
                  <tr className="mat-aria-band">
                    <td colSpan="9"><span className="mat-aria-inner">{String(aria.nr).padStart(2, "0")} - {aria.nume}</span></td>
                  </tr>
                  {perechi.map((p) => (
                    <tr key={p.key} className={p.nr % 2 === 0 ? "mat-alt" : undefined}>
                      <td className="mat-sticky mat-c1 dict-nr">{p.nr}</td>
                      <td className="mat-sticky mat-c2" title={p.ind.nume}>{p.comp}</td>
                      <td className={"mat-sticky mat-c3 mat-edge" + (picker === p.key ? " mat-pop" : "")}>
                        <div className="mat-act">
                          <span>{p.act}</span>
                          {p.e ? (
                            <span className="freq-pop">
                              <button className={"chip good" + (picker === p.key ? " deschis" : "")} title="Schimbă frecvența"
                                onClick={(ev) => {
                                  const sc = ev.currentTarget.closest(".mat-scroll");
                                  if (sc) {
                                    const r = ev.currentTarget.getBoundingClientRect();
                                    const sr = sc.getBoundingClientRect();
                                    setPickerSus(r.top - sr.top > sr.height * 0.5);
                                  }
                                  setPicker(picker === p.key ? null : p.key);
                                }}>
                                <IcCheck size={12} /> {p.e.frecventa}
                              </button>
                              {picker === p.key && (
                                <FreqPicker suggested={detectFreq(p.act)} sus={pickerSus}
                                  onPick={(f) => { set((s) => ({ ...s, plan: { ...s.plan, [p.key]: { ...s.plan[p.key], frecventa: f } } })); setPicker(null); }}
                                  onClose={() => setPicker(null)} />
                              )}
                            </span>
                          ) : (
                            <span className="freq-pop">
                              <button className="btn btn-ghost btn-sm" title="Adaugă în planul de implementare"
                                onClick={(ev) => {
                                  const sc = ev.currentTarget.closest(".mat-scroll");
                                  if (sc) {
                                    const r = ev.currentTarget.getBoundingClientRect();
                                    const sr = sc.getBoundingClientRect();
                                    setPickerSus(r.top - sr.top > sr.height * 0.5);
                                  }
                                  setPicker(picker === p.key ? null : p.key);
                                }}>
                                <IcPlus size={13} /> În plan
                              </button>
                              {picker === p.key && (
                                <FreqPicker suggested={detectFreq(p.act)} sus={pickerSus}
                                  onPick={(f) => addToPlan(p.key, f, p.act)} onClose={() => setPicker(null)} />
                              )}
                            </span>
                          )}
                        </div>
                      </td>
                      {p.e ? (
                        <React.Fragment>
                          <td className="mat-in"><textarea className="input" rows="2"
                            value={p.e.vreau || ""} onChange={setRep(p.key, "vreau")} /></td>
                          <td className="mat-in"><textarea className="input" rows="2"
                            value={p.e.nuVreau || ""} onChange={setRep(p.key, "nuVreau")} /></td>
                          <td className="mat-st">
                            <input type="number" min="0" className="input mat-nr-in mat-nr-oa"
                              title="Obiectiv alocat - de câte ori își asumă acțiunea"
                              value={p.e.oa} onChange={setNr(p.key, "oa")} />
                          </td>
                          <td className="mat-st">
                            <input type="number" min="0"
                              className={"input mat-nr-in " + (p.e.oa > 0 && p.e.orNr >= p.e.oa ? "mat-nr-plin" : "mat-nr-or")}
                              title="Obiectiv realizat - de câte ori a făcut-o până acum"
                              value={p.e.orNr} onChange={setNr(p.key, "orNr")} />
                          </td>
                          <td className="mat-in"><textarea className="input" rows="2"
                            placeholder="Principiu de viață - ex.: Bine faci, bine găsești"
                            value={p.e.ancora || ""} onChange={setRep(p.key, "ancora")} /></td>
                          <td className="mat-in"><textarea className="input" rows="2"
                            placeholder="Rutina care poartă acțiunea"
                            value={p.e.rutina || ""} onChange={setRep(p.key, "rutina")} /></td>
                        </React.Fragment>
                      ) : (
                        <React.Fragment>
                          <td className="mat-mut">-</td>
                          <td className="mat-mut">-</td>
                          <td className="mat-st">
                            <button className="mat-orbtn" title="Neasumat - apasă pentru a-l lua în plan"
                              onClick={(ev) => {
                                const sc = ev.currentTarget.closest(".mat-scroll");
                                if (sc) {
                                  const r = ev.currentTarget.getBoundingClientRect();
                                  const sr = sc.getBoundingClientRect();
                                  setPickerSus(r.top - sr.top > sr.height * 0.5);
                                }
                                setPicker(picker === p.key ? null : p.key);
                              }}>
                              <span className="mat-cifra or-off">0</span>
                            </button>
                          </td>
                          <td className="mat-st mat-mut">-</td>
                          <td className="mat-mut">-</td>
                          <td className="mat-mut">-</td>
                        </React.Fragment>
                      )}
                    </tr>
                  ))}
                </React.Fragment>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function CredintaView({ store, set }) {
  const cred = CREDINTE.find((c) => c.slug === store.credinta) || CREDINTE[0];
  const arii = MECANISME[cred.slug] || [];
  const [openAria, setOpenAria] = useState(arii.length ? arii[0].nr : null);
  const [picker, setPicker] = useState(null);
  /* la ultimele actiuni dintr-o arie meniul de frecventa nu incape sub buton si era taiat de
     `.ind-block{overflow:hidden}` - masurat la auditul din 25.07: 5 din 6 optiuni cadeau pe ce era
     dedesubt. Se deschide in sus, ca in Matrice (acolo calculul exista deja). */
  const [pickerSus, setPickerSus] = useState(false);
  const alegeSensul = (ev) => {
    const bl = ev.currentTarget.closest(".ind-block");
    if (!bl) return;
    const r = ev.currentTarget.getBoundingClientRect();
    setPickerSus(bl.getBoundingClientRect().bottom - r.bottom < 210); /* 210 = inaltimea meniului cu 6 optiuni */
  };
  useEffect(() => { setOpenAria(arii.length ? arii[0].nr : null); setPicker(null); }, [cred.slug]);

  const entries = planEntries(store.plan).filter((e) => e.slug === cred.slug);
  /* Alegerea frecventei DESCHIDE imediat meniul de detalii al actiunii (Cum vreau sa fac asta /
     Cum nu trebuie sa fac / Ancora / Rutina / OA / OR) - altfel omul aloca actiunea si ramane
     cu un rand bifat, fara sa vada ca mai are ceva de completat. Deschiderea intra in store,
     nu in state local: raman deschise si dupa navigare sau reload. Cerinta Marian 25.07. */
  const addToPlan = (key, frecventa, textActiune) => {
    set((s) => ({
      ...s,
      plan: { ...s.plan, [key]: { frecventa, realizat: false, oa: 1, orNr: 0, vreau: "", nuVreau: "", ancora: "", rutina: "",
                                  adaugat: fmtISO(new Date()), sursa: amprenta(textActiune) } },
      detaliiDeschise: { ...(s.detaliiDeschise || {}), [key]: true },
    }));
    setPicker(null);
  };
  const removeFromPlan = (key) => set((s) => {
    const p = { ...s.plan }; delete p[key];
    const d = { ...(s.detaliiDeschise || {}) }; delete d[key];
    return { ...s, plan: p, detaliiDeschise: d };
  });
  /* mai multe meniuri pot sta deschise simultan - deschiderea unuia nu-l mai inchide pe celalalt */
  const deschise = store.detaliiDeschise || {};
  const toggleDetalii = (key) => set((s) => {
    const d = { ...(s.detaliiDeschise || {}) };
    if (d[key]) delete d[key]; else d[key] = true;
    return { ...s, detaliiDeschise: d };
  });
  const setRep = (key, field) => (ev) => {
    const v = ev.target.value;
    set((s) => ({ ...s, plan: { ...s.plan, [key]: { ...s.plan[key], [field]: v } } }));
  };
  /* cantitatile OA/OR (cifre asumate/realizate) - parse cu clamp la >= 0 */
  const setNr = (key, field) => (ev) => {
    const n = Math.max(0, parseInt(ev.target.value, 10) || 0);
    set((s) => ({ ...s, plan: { ...s.plan, [key]: { ...s.plan[key], [field]: n } } }));
  };
  if (!cred.gata) {
    return (
      <div className="page">
        <CredinteTabs store={store} set={set} />
        <div className="panel empty">
          <div className="empty-title">Mecanismul este în lucru la Dr. Petre</div>
          <div className="small" style={{ maxWidth: 420 }}>
            Se completează pe modelul Bunătății: 10 arii, fiecare cu comportamente
            observabile („ce văd”) și acțiuni concrete („ce fac”).
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="page">
      <CredinteTabs store={store} set={set} />

      <div className="mod-bar">
        <div className="mod-tabs" role="tablist" aria-label="Mod de afișare">
          {[["lista", "Listă"], ["matrice", "Matrice"]].map(([m, eticheta]) => (
            <button key={m} role="tab" aria-selected={store.viewMod === m}
              className={"mod-tab" + (store.viewMod === m ? " activ" : "")}
              onClick={() => set((s) => ({ ...s, viewMod: m }))}>
              {eticheta}
            </button>
          ))}
        </div>
        <button className="mod-filtru" title="Arată doar acțiunile alocate în plan"
          onClick={() => set((s) => ({ ...s, doarAleMele: !s.doarAleMele }))}>
          <span className={"check-btn" + (store.doarAleMele ? " on" : "")}><IcCheck size={13} /></span>
          <span className="small">doar ale mele</span>
        </button>
      </div>

      {store.viewMod === "matrice" ? (
        <MatriceCredinta cred={cred} arii={arii} store={store} set={set}
          addToPlan={addToPlan} setNr={setNr} setRep={setRep}
          picker={picker} setPicker={setPicker} />
      ) : (
      arii.map((aria) => {
        const isOpen = openAria === aria.nr;
        const entriesAria = entries.filter((e) => e.aria.nr === aria.nr);
        const inPlanAria = entriesAria.length;
        const oaAria = entriesAria.reduce((n, e) => n + (e.oa || 0), 0);
        const orAria = entriesAria.reduce((n, e) => n + (e.orNr || 0), 0);
        if (store.doarAleMele && inPlanAria === 0) return null;
        return (
          <div className="aria-item" key={aria.nr}>
            <button className="aria-head" onClick={() => setOpenAria(isOpen ? null : aria.nr)}>
              <span className="aria-nr">{String(aria.nr).padStart(2, "0")}</span>
              <span className="grow">{aria.nume}</span>
              <span className="aria-meta">
                {inPlanAria > 0 && <span className="chip good">{inPlanAria} în plan · OA {oaAria} · OR {orAria}</span>}
                <span className={"chev" + (isOpen ? " open" : "")}><IcChev size={16} /></span>
              </span>
            </button>
            {isOpen && (
              <div className="aria-body">
                {/* structura noua (zoom 2): perechi plate comportament <-> actiune per arie,
                    fara blocuri de indicatori vizibile (numele indicatorului ramane in title) */}
                <div className="ind-block">
                    <div className="pair-grid">
                      <div className="cell pair-head">Comportamentul observabil - ce văd</div>
                      <div className="cell pair-head">Acțiunea concretă - ce fac</div>
                      {perechiAria(cred.slug, aria).map((p, idx) => {
                        const key = p.key;
                        const inPlan = store.plan[key];
                        if (store.doarAleMele && !inPlan) return null;
                        return (
                          <React.Fragment key={key}>
                            <div className={"cell" + (idx % 2 === 1 ? " cell-alt" : "")} title={p.ind.nume}>{p.comp}</div>
                            <div className={"cell act-cell" + (idx % 2 === 1 ? " cell-alt" : "")}>
                              <span className="txt">{p.act}</span>
                              {inPlan && inPlan.sursa && amprenta(p.act) !== inPlan.sursa && (
                                <span className="chip warn" style={{ flexShrink: 0 }}
                                  title={"La asumare, acțiunea începea cu: „" + inPlan.sursa + "”. Documentul lui Dr. Petre s-a schimbat între timp - verifică dacă mai e ce ți-ai asumat."}>
                                  text schimbat
                                </span>
                              )}
                              <span className="freq-pop">
                                {inPlan ? (
                                  <button className={"chip good" + (deschise[key] ? " deschis" : "")}
                                    title="Deschide detaliile acțiunii (repere, ancoră, frecvență)"
                                    onClick={() => toggleDetalii(key)}>
                                    <IcCheck size={12} /> {inPlan.frecventa}
                                  </button>
                                ) : (
                                  <button className="btn btn-ghost btn-sm" title="Adaugă în planul de implementare"
                                    onClick={(ev) => { alegeSensul(ev); setPicker(picker === key ? null : key); }}>
                                    <IcPlus size={13} /> În plan
                                  </button>
                                )}
                                {picker === key && (
                                  <FreqPicker suggested={detectFreq(p.act)} sus={pickerSus}
                                    onPick={(f) => addToPlan(key, f, p.act)} onClose={() => setPicker(null)} />
                                )}
                              </span>
                            </div>
                            {inPlan && deschise[key] && (
                              <div className="cell act-admin" style={{ gridColumn: "1 / -1" }}>
                                <div className="grid-2">
                                  <label className="field"><span className="field-label">Cum vreau să fac asta</span>
                                    <textarea className="input" rows="2" value={inPlan.vreau || ""} onChange={setRep(key, "vreau")} /></label>
                                  <label className="field"><span className="field-label">Cum nu trebuie să fac</span>
                                    <textarea className="input" rows="2" value={inPlan.nuVreau || ""} onChange={setRep(key, "nuVreau")} /></label>
                                  <label className="field"><span className="field-label">Principiul de Viață / Ancora de Integrare</span>
                                    <textarea className="input" rows="2" placeholder="ex.: Bine faci, bine găsești" value={inPlan.ancora || ""} onChange={setRep(key, "ancora")} /></label>
                                  <label className="field"><span className="field-label">Rutina</span>
                                    <textarea className="input" rows="2" placeholder="Rutina care poartă acțiunea" value={inPlan.rutina || ""} onChange={setRep(key, "rutina")} /></label>
                                </div>
                                <div className="row" style={{ marginTop: 10, flexWrap: "wrap" }}>
                                  <label className="field" style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
                                    <span className="field-label">Frecvența</span>
                                    <select className="input" style={{ width: "auto", padding: "4px 8px", fontSize: "var(--m-fs-2)" }}
                                      value={inPlan.frecventa}
                                      onChange={(ev) => setRep(key, "frecventa")(ev)}>
                                      {FRECVENTE.map((x) => <option key={x} value={x}>{x}</option>)}
                                    </select>
                                  </label>
                                  <label className="field" style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
                                    <span className="field-label">Obiectiv alocat (OA)</span>
                                    <input type="number" min="0" className="input" style={{ width: 68 }}
                                      value={inPlan.oa} onChange={setNr(key, "oa")} />
                                  </label>
                                  <label className="field" style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
                                    <span className="field-label">Realizat (OR)</span>
                                    <input type="number" min="0" className="input" style={{ width: 68 }}
                                      value={inPlan.orNr} onChange={setNr(key, "orNr")} />
                                  </label>
                                  {inPlan.oa > 0 && inPlan.orNr >= inPlan.oa && (
                                    <span className="chip good"><IcCheck size={12} /> Integrată</span>
                                  )}
                                  <button className="btn btn-ghost btn-sm" style={{ marginLeft: "auto", color: "var(--m-bad)" }}
                                    onClick={() => removeFromPlan(key)}>
                                    <IcX size={13} /> Scoate din plan
                                  </button>
                                </div>
                              </div>
                            )}
                          </React.Fragment>
                        );
                      })}
                    </div>
                </div>
              </div>
            )}
          </div>
        );
      })
      )}
    </div>
  );
}

/* ── Dictionar - impartit in doua sectiuni (cerinta Marian 24.07, dupa zoom 5):
   Credinte (tabelul existent, neschimbat) / Valori (window.DictionarValori din valori.jsx) ── */
function DictionarView() {
  const [sect, setSect] = useState("credinte");
  const DV = window.DictionarValori;
  return (
    <div className="page">
      <div className="cred-tabs" role="tablist" aria-label="Secțiunile dicționarului">
        {[["credinte", "Credințe"], ["valori", "Valori"]].map(([s, et]) => (
          <button key={s} role="tab" aria-selected={sect === s}
            className={"cred-tab" + (sect === s ? " activ" : "")}
            onClick={() => setSect(s)}>{et}</button>
        ))}
      </div>
      {sect === "valori" && DV ? <DV /> : <DictionarCredinte />}
    </div>
  );
}

/* tabelul credintelor - continutul de dinainte de split (structura din Excelul lui Petre:
   nr/termen/definitie/exemple), doar scos din wrapper-ul .page */
function DictionarCredinte() {
  const [q, setQ] = useState("");
  const list = useMemo(() => {
    const t = q.trim().toLowerCase();
    if (!t) return DICTIONAR;
    return DICTIONAR.filter((d) =>
      d.termen.toLowerCase().includes(t) || d.definitie.toLowerCase().includes(t));
  }, [q]);
  return (
    <React.Fragment>
      <div className="row" style={{ marginBottom: 14, maxWidth: 420 }}>
        <div className="grow" style={{ position: "relative" }}>
          <span style={{ position: "absolute", left: 11, top: 9, color: "var(--m-muted)" }}><IcSearch size={16} /></span>
          <input className="input" style={{ paddingLeft: 34 }} placeholder="Caută un concept..."
            value={q} onChange={(e) => setQ(e.target.value)} />
        </div>
      </div>
      <div className="panel" style={{ overflowX: "auto" }}>
        <p className="sect-label">Dicționar de Cuvinte și Concepte PRP® - {list.length} {list.length === 1 ? "termen" : "termeni"}</p>
        {list.length > 0 ? (
          <table className="tbl dict-tbl" style={{ minWidth: 720 }}>
            <thead>
              <tr>
                <th style={{ width: 34 }}>#</th>
                <th style={{ width: 190 }}>Termenul</th>
                <th>Definiția</th>
                <th style={{ width: 270 }}>Exemple</th>
              </tr>
            </thead>
            <tbody>
              {list.map((d) => (
                <tr key={d.nr}>
                  <td className="dict-nr">{d.nr}</td>
                  <td className="dict-termen">{d.termen}</td>
                  <td className="dict-def-cell">{d.definitie}</td>
                  <td className="dict-ex-cell">{d.exemple || "-"}</td>
                </tr>
              ))}
            </tbody>
          </table>
        ) : (
          <div className="empty">
            <div className="empty-title">Termenul nu există în dicționar</div>
          </div>
        )}
      </div>
    </React.Fragment>
  );
}



/* cheia de jurnal -> data la care se atribuie bifa (perioadele se atribuie la inceputul lor) */
function pkToDate(pk) {
  if (pk.startsWith("W")) { const d = new Date(pk.slice(1) + "T00:00:00"); return isNaN(d) ? null : d; }
  if (/^\d{4}-Q[1-4]$/.test(pk)) return new Date(+pk.slice(0, 4), (+pk.slice(6) - 1) * 3, 1);
  if (/^\d{4}-\d{2}$/.test(pk)) { const d = new Date(pk + "-01T00:00:00"); return isNaN(d) ? null : d; }
  if (/^\d{4}$/.test(pk)) return new Date(+pk, 0, 1);
  const d = new Date(pk + "T00:00:00");
  return isNaN(d) ? null : d;
}


/* ── export / import proces (plasa de siguranta a prototipului) ── */
function exportStore(store) {
  const data = {
    _tip: "credinte-fundamentale-export",
    _versiune: 1,
    _exportat: new Date().toISOString(),
    consola: store.consola,
    plan: store.plan,
    log: store.log,
    gantt: store.gantt,
    /* anamneza: raspunsuri + rezultate calculate, self-contained (definit in anamneza.jsx) */
    ...(window.anamnezaExport ? window.anamnezaExport(store) : {}),
    /* valorile: selectia + planul de implementare (definit in valori.jsx) */
    ...(window.valoriExport ? window.valoriExport(store) : {}),
    /* chestionarele de valori: raspunsuri + rezultate + decodificare (definit in chv.jsx) */
    ...(window.chvExport ? window.chvExport(store) : {}),
  };
  const nume = (store.consola.nume.trim() || "proces").toLowerCase()
    .replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
  const blob = new Blob([JSON.stringify(data, null, 1)], { type: "application/json" });
  const a = document.createElement("a");
  a.href = URL.createObjectURL(blob);
  a.download = `credinte-fundamentale_${nume}_${fmtISO(new Date())}.json`;
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(a.href);
}

/* ── comanda secreta #reset: confirmare + stergerea procesului din acest browser ── */
function ResetView({ store, onRenunta }) {
  return (
    <div className="reset-ecran">
      <div className="panel" style={{ maxWidth: 480 }}>
        <p className="sect-label">Resetarea procesului</p>
        <p style={{ margin: "0 0 6px" }}>
          Se șterg definitiv datele înregistrate în acest browser: persoana din consolă,
          planul cu repere și ancore, evidența din calendar și planul strategic.
        </p>
        <p className="small muted" style={{ margin: "0 0 14px" }}>
          Fișierul instrumentului rămâne neatins - dispare doar procesul înregistrat local.
        </p>
        <div className="row" style={{ flexWrap: "wrap" }}>
          <button className="btn btn-ghost btn-sm" onClick={() => exportStore(store)}>
            Exportă întâi (JSON)
          </button>
          <button className="btn btn-primary btn-sm" onClick={onRenunta}>Renunță</button>
          <button className="btn btn-ghost btn-sm" style={{ marginLeft: "auto", color: "var(--m-bad)" }}
            onClick={() => {
              try { localStorage.removeItem(LS_KEY); } catch (e) { /* privat/blocat - ignoram */ }
              try { history.replaceState(null, "", location.pathname + location.search); } catch (e) { /* file:// - ignoram */ }
              location.reload();
            }}>
            Da, resetează
          </button>
        </div>
      </div>
    </div>
  );
}

/* ── Consola ── */
function ConsolaView({ store, set }) {
  const upd = (k) => (e) => {
    const v = e.target.value;
    set((s) => {
      const next = { ...s, consola: { ...s.consola, [k]: v } };
      /* In clipa in care numele si data devin valide, poarta se deschide si ecranul sarea singur
         pe pagina salvata in store (de obicei Acasa), cu omul in mijlocul completarii - restul
         campurilor ramaneau necompletate (audit 25.07). Il tinem in consola pana apasa el
         „Mergi la Acasa". */
      if (!consolaOk(s) && consolaOk(next) && next.view !== "consola") next.view = "consola";
      return next;
    });
  };
  const entries = planEntries(store.plan);
  return (
    <div className="page">
      {!consolaOk(store) && (
        <div className="panel" style={{ marginBottom: 18 }}>
          <div className="row">
            <span className="cred-gem" style={{ flexShrink: 0 }}><IcUser size={18} /></span>
            <div>
              <strong>Instrumentul se deblochează după înregistrarea persoanei.</strong>
              <div className="small muted" style={{ marginTop: 2 }}>
                Câmpurile obligatorii: numele și prenumele + data de start a procesului.
              </div>
            </div>
          </div>
        </div>
      )}

      <div className="panel">
        <p className="sect-label">Persoana înregistrată</p>
        <div className="grid-2">
          <label className="field"><span className="field-label">Numele și prenumele *</span>
            <input className="input" value={store.consola.nume} onChange={upd("nume")} placeholder="Numele participantului" /></label>
          <label className="field"><span className="field-label">Data start proces *</span>
            <input className="input" type="date" value={store.consola.dataStart} onChange={upd("dataStart")} /></label>
          <label className="field"><span className="field-label">Consultant</span>
            <input className="input" value={store.consola.consultant} onChange={upd("consultant")} /></label>
          <label className="field"><span className="field-label">Telefon</span>
            <input className="input" value={store.consola.telefon} onChange={upd("telefon")} placeholder="+40 ..." /></label>
          <label className="field" style={{ gridColumn: "1 / -1" }}><span className="field-label">Email</span>
            <input className="input" value={store.consola.email} onChange={upd("email")} placeholder="email@exemplu.ro" /></label>
          <label className="field" style={{ gridColumn: "1 / -1" }}><span className="field-label">Observații</span>
            <textarea className="input" rows="2" value={store.consola.obs} onChange={upd("obs")} /></label>
        </div>
        {consolaOk(store) && (
          <div className="mt-14">
            <button className="btn btn-primary btn-sm" onClick={() => set((s) => ({ ...s, view: "acasa" }))}>
              Mergi la Acasă <IcArrow size={13} />
            </button>
          </div>
        )}
      </div>

      <div className="panel mt-18">
        <p className="sect-label">Siguranța datelor (prototip)</p>
        <p className="small muted" style={{ margin: "0 0 12px", maxWidth: 640 }}>
          În acest prototip, tot procesul trăiește doar în browserul de față. Exportă regulat
          într-un fișier - exportul conține TOT: datele persoanei, planul cu repere și ancore,
          evidența din calendar și planul strategic.
        </p>
        <div className="row" style={{ flexWrap: "wrap" }}>
          <button className="btn btn-primary btn-sm" disabled={!consolaOk(store)}
            title={consolaOk(store) ? undefined : "Exportul cere consola completată (nume + data start)"}
            onClick={() => exportStore(store)}>
            Exportă procesul (JSON)
          </button>
        </div>
        {/* semnal onest cand mecanismele s-au schimbat sub plan: altfel actiunile fie arata alt
            text decat cel asumat, fie dispar din lista fara ca omul sa afle (audit 25.07) */}
        {(() => {
          const orfane = planOrfane(store.plan);
          const schimbate = entries.filter((e) => e.schimbat).length;
          if (!orfane && !schimbate) return null;
          return (
            <p className="small" style={{ margin: "12px 0 0", color: "var(--m-warn)", maxWidth: 640 }}>
              <b>Mecanismele s-au schimbat de când ți-ai făcut planul.</b>{" "}
              {schimbate > 0 && <React.Fragment>{schimbate} {schimbate === 1 ? "acțiune are" : "acțiuni au"} alt text decât la asumare (marcate cu „text schimbat” în credință). </React.Fragment>}
              {orfane > 0 && <React.Fragment>{orfane} {orfane === 1 ? "acțiune nu mai există" : "acțiuni nu mai există"} în mecanismele actuale și nu se mai afișează nicăieri. </React.Fragment>}
              Exportă procesul înainte de orice curățare.
            </p>
          );
        })()}
      </div>

      <div className="panel mt-18">
        <p className="sect-label">Activarea credințelor</p>
        <div className="tbl-scroll">
        <table className="tbl">
          <thead><tr><th>Credința</th><th>Mecanism</th><th>Acțiuni în plan</th><th>Obiective (alocate / realizate)</th><th></th></tr></thead>
          <tbody>
            {CREDINTE.map((c) => {
              const inPlan = entries.filter((e) => e.slug === c.slug);
              const oaC = inPlan.reduce((n, e) => n + (e.oa || 0), 0);
              const orC = inPlan.reduce((n, e) => n + (e.orNr || 0), 0);
              return (
                <tr key={c.slug}>
                  <td style={{ fontWeight: 600 }}>{c.titlu}</td>
                  <td>{c.gata
                    ? <span className="chip good"><IcCheck size={12} /> complet</span>
                    : <span className="chip outline">în lucru la Dr. Petre</span>}</td>
                  <td>{inPlan.length > 0 ? inPlan.length : <span className="muted">-</span>}</td>
                  <td>{inPlan.length > 0 ? `${oaC} / ${orC}` : <span className="muted">-</span>}</td>
                  <td style={{ textAlign: "right" }}>
                    {c.gata && (
                      <button className="btn btn-ghost btn-sm" disabled={!consolaOk(store)}
                        title={consolaOk(store) ? undefined : "Se deblochează după completarea consolei"}
                        onClick={() => set((s) => ({ ...s, view: "credinta", credinta: c.slug }))}>
                        Deschide <IcArrow size={13} />
                      </button>
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        </div>
      </div>
    </div>
  );
}

/* ── harta de navigare: parintele logic + eticheta fiecarei sectiuni ── */
const VIEW_LABELS = {
  acasa: "Acasă", credinte: "Credințele mele", credinta: "Credință",
  anamneza: "Chestionare credințe", calendar: "Calendarul meu", plan: "Plan strategic",
  valori: "Valorile mele", chestionare: "Chestionare valori", dictionar: "Dicționar", biblioteca: "Biblioteca metodologică", consola: "Consolă",
  "date-mele": "Datele mele",
};
const parentOf = (view) => (view === "credinta" ? "credinte" : view === "acasa" ? null : "acasa");

function Breadcrumb({ store, set, onMenu, menuDeschis }) {
  const segments = [];
  if (store.view !== "acasa") segments.push(["acasa", "Acasă"]);
  if (store.view === "credinta") {
    const cred = CREDINTE.find((c) => c.slug === store.credinta);
    segments.push(["credinte", "Credințele mele"]);
    segments.push([null, cred ? cred.titlu : "Credință"]);
  } else if (store.view !== "acasa") {
    segments.push([null, VIEW_LABELS[store.view] || ""]);
  } else {
    segments.push([null, "Acasă"]);
  }
  const parent = parentOf(store.view);
  return (
    <nav className="crumbs" aria-label="Locația în instrument">
      <button className="crumb-back"
        title={(onMenu ? menuDeschis : !store.sidebarInchis) ? "Închide meniul" : "Deschide meniul"}
        aria-expanded={onMenu ? menuDeschis : !store.sidebarInchis}
        onClick={() => onMenu ? onMenu() : set((s) => ({ ...s, sidebarInchis: !s.sidebarInchis }))}>
        <IcMenu size={15} />
      </button>
      {parent && (
        <button className="crumb-back" title="Înapoi"
          onClick={() => set((s) => ({ ...s, view: parent }))}>
          <IcChevL size={15} />
        </button>
      )}
      {segments.map(([view, label], i) => (
        <React.Fragment key={i}>
          {i > 0 && <span className="crumb-sep">/</span>}
          {view
            ? <button className="crumb-link" onClick={() => set((s) => ({ ...s, view }))}>{label}</button>
            : <span className="crumb-here">{label}</span>}
        </React.Fragment>
      ))}
    </nav>
  );
}

/* ── App ── */
function App() {
  const [store, setStoreRaw] = useState(() => viewDinHash(loadStore()));
  /* comanda secreta de reset: #reset in URL, la deschidere sau in mers (hashchange) */
  const [resetCerut, setResetCerut] = useState(() => location.hash === "#reset");
  useEffect(() => {
    const onHash = () => {
      if (location.hash === "#reset") { setResetCerut(true); return; }
      /* hash schimbat din bara de adrese sau dintr-un link (pushState-ul propriu NU declanseaza
         hashchange), deci e o cerere explicita de navigare - o respectam */
      setStoreRaw((s) => { const next = viewDinHash(s); if (next.view !== s.view) persist(next); return next; });
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);
  const persist = (next) => {
    try { localStorage.setItem(LS_KEY, JSON.stringify(next)); } catch (e) { /* plin/privat - ignoram */ }
  };
  const set = (fn) => setStoreRaw((s) => {
    const next = typeof fn === "function" ? fn(s) : fn;
    /* navigarea interna intra in istoricul browserului: Back nu mai scoate din instrument */
    if (next.view !== s.view || next.credinta !== s.credinta) {
      const hash = "#" + next.view + (next.view === "credinta" ? "/" + next.credinta : "");
      try { history.pushState({ view: next.view, credinta: next.credinta }, "", hash); } catch (e) { /* file:// restrictiv - ignoram */ }
    }
    persist(next);
    return next;
  });
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", store.theme);
  }, [store.theme]);
  /* MOBIL (<=900px): sidebar-ul devine drawer peste continut. Stare LOCALA, ne-persistata -
     pe telefon meniul porneste mereu inchis; desktopul pastreaza exact comportamentul vechi
     (sidebarInchis din store). */
  const [eMobil, setEMobil] = useState(() => window.matchMedia("(max-width: 900px)").matches);
  const [navMobil, setNavMobil] = useState(false);
  useEffect(() => {
    const mq = window.matchMedia("(max-width: 900px)");
    /* si "resize" ca fallback - evenimentul "change" al matchMedia nu ajunge fiabil
       in toate contextele (observat in Chrome sub automatizare la schimbarea viewportului) */
    const sync = () => { setEMobil(mq.matches); if (!mq.matches) setNavMobil(false); };
    mq.addEventListener("change", sync);
    window.addEventListener("resize", sync);
    return () => { mq.removeEventListener("change", sync); window.removeEventListener("resize", sync); };
  }, []);
  useEffect(() => { setNavMobil(false); }, [store.view, store.credinta]);
  useEffect(() => {
    try { history.replaceState({ view: store.view, credinta: store.credinta }, "",
      "#" + store.view + (store.view === "credinta" ? "/" + store.credinta : "")); } catch (e) { /* ignoram */ }
    const onPop = (e) => {
      if (e.state && e.state.view) {
        setStoreRaw((s) => {
          const next = { ...s, view: e.state.view, credinta: e.state.credinta || s.credinta };
          persist(next);
          return next;
        });
      }
    };
    window.addEventListener("popstate", onPop);
    return () => window.removeEventListener("popstate", onPop);
  }, []);

  const views = {
    /* Acasa / Calendarul / Planul = view-urile credinte+valori (fostele „(nou)"), devenite
       singurele, pe slugurile ORIGINALE - asa raman valabile link-urile si store-urile vechi */
    acasa: window.AcasaHibridView ? <window.AcasaHibridView store={store} set={set} /> : null,
    credinte: <CredinteIndexView store={store} set={set} />,
    credinta: <CredintaView store={store} set={set} />,
    anamneza: <window.AnamnezaView store={store} set={set} />,
    valori: <window.ValoriView store={store} set={set} />,
    chestionare: <window.ChvView store={store} set={set} />,
    calendar: window.CalendarHibridView ? <window.CalendarHibridView store={store} set={set} /> : null,
    plan: window.PlanHibridView ? <window.PlanHibridView store={store} set={set} /> : null,
    dictionar: <DictionarView />,
    biblioteca: window.BibliotecaView ? <window.BibliotecaView store={store} set={set} /> : null,
    consola: <ConsolaView store={store} set={set} />,
    "date-mele": window.PilotDateleMele ? <window.PilotDateleMele /> : null,
  };

  /* poarta: fara consola completata, singura vedere accesibila e Consola */
  const activeView = consolaOk(store) ? (views[store.view] ? store.view : "acasa") : "consola";

  if (resetCerut) {
    return <ResetView store={store} onRenunta={() => {
      setResetCerut(false);
      try {
        history.replaceState({ view: store.view, credinta: store.credinta }, "",
          "#" + store.view + (store.view === "credinta" ? "/" + store.credinta : ""));
      } catch (e) { /* file:// restrictiv - ignoram */ }
    }} />;
  }

  return (
    <div className="shell">
      {(eMobil ? navMobil : (!store.sidebarInchis || !consolaOk(store))) &&
        <Sidebar store={store} set={set} drawer={eMobil} />}
      {eMobil && navMobil &&
        <div className="nav-backdrop" aria-hidden="true" onClick={() => setNavMobil(false)} />}
      <main className="main">
        {consolaOk(store) && <Breadcrumb store={{ ...store, view: activeView }} set={set}
          onMenu={eMobil ? () => setNavMobil((v) => !v) : null}
          menuDeschis={eMobil ? navMobil : !store.sidebarInchis} />}
        {views[activeView]}
      </main>
    </div>
  );
}

/* Poarta pilotului (pilot.jsx) infasoara aplicatia: versiune -> cod de acces -> identitate.
   Cand pilot.jsx lipseste - standalone-ul offline, care nu are nici server, nici evidenta -
   aplicatia porneste direct, exact ca inainte. */
ReactDOM.createRoot(document.getElementById("root")).render(
  window.PilotGate ? <window.PilotGate><App /></window.PilotGate> : <App />
);
