// ============================================================
// PaperDeti — návrh na rozvod manželstva (s maloletými deťmi)
// § 22 a nasl. zákona č. 36/2005 Z. z. o rodine
// Placeholder: 1:1 kópia Paper.jsx; obsahové úpravy o úprave
// rodičovských práv a povinností budú doplnené samostatne.
// ============================================================

// SUDY — zoznam okresných a mestských súdov SR je definovaný v components/sudy.js
// (zdieľaný s Paper.jsx) a vystavený ako window.SUDY.

const removeDiacritics = (str) => str.normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase();

// ============================================================
// Gender helpers — prechyľovanie procesných označení (§ 60 a nasl. CSP)
// a rodinnoprávnych označení podľa pohlavia. Manželstvo je v zmysle § 1
// ods. 1 ZoR zväzok muža a ženy, takže pohlavie odporcu odvodzujeme ako
// opak navrhovateľa — len jediný vstup pre celý dokument.
// ============================================================
const POHLAVIE_FORMS = {
  navrhovatel: {
    muz:  { nom: 'navrhovateľ',   gen: 'navrhovateľa',  dat: 'navrhovateľovi', ak: 'navrhovateľa',  lok: 'navrhovateľovi', instr: 'navrhovateľom' },
    zena: { nom: 'navrhovateľka', gen: 'navrhovateľky', dat: 'navrhovateľke',  ak: 'navrhovateľku', lok: 'navrhovateľke',  instr: 'navrhovateľkou' },
  },
  odporca: {
    muz:  { nom: 'odporca',   gen: 'odporcu',   dat: 'odporcovi', ak: 'odporcu',   lok: 'odporcovi', instr: 'odporcom' },
    zena: { nom: 'odporkyňa', gen: 'odporkyne', dat: 'odporkyni', ak: 'odporkyňu', lok: 'odporkyni', instr: 'odporkyňou' },
  },
};
const oznacenie = (rola, pohlavie, pad = 'nom') => POHLAVIE_FORMS[rola][pohlavie][pad];
const oznacenieCap = (rola, pohlavie, pad = 'nom') => {
  const s = oznacenie(rola, pohlavie, pad);
  return s.charAt(0).toUpperCase() + s.slice(1);
};

const MANZEL_FORMS = {
  muz:  { nom: 'manžel',   gen: 'manžela',  dat: 'manželovi', ak: 'manžela',  lok: 'manželovi', instr: 'manželom' },
  zena: { nom: 'manželka', gen: 'manželky', dat: 'manželke',  ak: 'manželku', lok: 'manželke',  instr: 'manželkou' },
};
const manzelOznacenie = (pohlavie, pad = 'nom') => MANZEL_FORMS[pohlavie][pad];

// Sloveso v minulom čase, 1. osoba sg. — zaklad = mužský tvar (uzavrel,
// oznámil, uvedomil...), pre ženu pridáme '-a'. Pokrýva všetky pravidelné
// slovenské slovesá — slovenský minulý čas je v tomto symetrický.
const slovesoMinuly = (zaklad, pohlavie) => pohlavie === 'zena' ? zaklad + 'a' : zaklad;

// Privlastňovacie zámeno 3. osoby sg. — "jeho" / "jej".
const privlastn = (pohlavie) => pohlavie === 'muz' ? 'jeho' : 'jej';

// Rodinnoprávne role v singulári (otec/matka) — používané v opisoch
// striedavej starostlivosti a styku, kde právny jazyk pracuje s rodičovskými
// rolami a nie s procesnými označeniami. Mapping: muž ako navrhovateľ → otec,
// žena ako navrhovateľka → matka. Pohlavie odporcu = opak (manželstvo muža a ženy).
const ROLA_RODICA_FORMS = {
  otec:  { nom: 'otec',  gen: 'otca',  dat: 'otcovi', ak: 'otca',  lok: 'otcovi', instr: 'otcom' },
  matka: { nom: 'matka', gen: 'matky', dat: 'matke',  ak: 'matku', lok: 'matke',  instr: 'matkou' },
};
const rolaRodicaKey = (role, navrhovatelPohlavie) => {
  if (role === 'navrhovatel') return navrhovatelPohlavie === 'muz' ? 'otec' : 'matka';
  return navrhovatelPohlavie === 'muz' ? 'matka' : 'otec';
};
const rolaRodica = (role, navrhovatelPohlavie, pad = 'nom') =>
  ROLA_RODICA_FORMS[rolaRodicaKey(role, navrhovatelPohlavie)][pad];
const rolaRodicaCap = (role, navrhovatelPohlavie, pad = 'nom') => {
  const s = rolaRodica(role, navrhovatelPohlavie, pad);
  return s.charAt(0).toUpperCase() + s.slice(1);
};
// Tvar v páde priamo z key (matka/otec) — bez navrhovatelPohlavie.
const rolaRodicaPad = (key, pad = 'nom') => ROLA_RODICA_FORMS[key][pad];

// Sloveso "oprávnený/-á" pre rodičovskú rolu — gender-aware koncovka.
const rolaOpravneny = (role, navrhovatelPohlavie) =>
  rolaRodicaKey(role, navrhovatelPohlavie) === 'matka' ? 'oprávnená' : 'oprávnený';

// Singulár/plurál pre "maloleté dieťa" / "maloleté deti" so všetkými pádmi.
// Pre 0 detí používame plurál (rendrovať placeholder hint riešia callsite).
const DETI_SLOVO_FORMS = {
  sg: { nom: 'maloleté dieťa', gen: 'maloletého dieťaťa', dat: 'maloletému dieťaťu', ak: 'maloleté dieťa', lok: 'maloletom dieťati', instr: 'maloletým dieťaťom' },
  pl: { nom: 'maloleté deti',  gen: 'maloletých detí',    dat: 'maloletým deťom',    ak: 'maloleté deti',  lok: 'maloletých deťoch', instr: 'maloletými deťmi' },
};
const detiSlovo = (pocet, pad = 'nom') =>
  DETI_SLOVO_FORMS[pocet === 1 ? 'sg' : 'pl'][pad];

// Sloveso "byť" v 3. osobe budúceho času — "bude" (sg) / "budú" (pl).
// Používané pred detiSlovo v sampleStriedavka_* textoch (subjekt = dieťa/deti).
const bude = (pocet) => pocet === 1 ? 'bude' : 'budú';

// Sloveso "byť" v 3. osobe minulého času — "bolo" (sg neutrum) / "boli" (pl).
// Použité v sampleSpolocna pre konštrukciu "aby bolo/boli ... zverené".
const bolo = (pocet) => pocet === 1 ? 'bolo' : 'boli';

// Heuristika pohlavia z priezviska. Posledný token, prípony typické pre
// slovenské feminíny (-ová, -cká, -ská, -ná, -tá, -lá), fallback -á.
// Známe edge cases: "Eva", "Andrea", "Smola", "Procházka" (bez diakritiky)
// → muz fallback. Cudzojazyčné mená môžu byť mimo vzoru.
const FEM_NAME_RE = /(?:ová|cká|ská|ná|tá|lá|á)$/i;
const detectGenderFromName = (fullName) => {
  if (!fullName) return null;
  const tokens = fullName.trim().split(/\s+/);
  if (!tokens.length || !tokens[tokens.length - 1]) return null;
  const last = tokens[tokens.length - 1].normalize('NFC');
  return FEM_NAME_RE.test(last) ? 'zena' : 'muz';
};

// ============================================================
// Sample texty pre Čl. II — gender-aware varianty s prechyľovaním.
// pNav = pohlavie navrhovateľa (riadi ja-formy slovies),
// pOdp = pohlavie odporcu (riadi prechylenie tretej osoby).
// SAMPLE_TEXT_4 ostáva konštantou — neobsahuje gender-závislé výrazy
// (všetko v 1. pl. alebo neutrálnej forme).
// ============================================================
const sampleText1 = (pNav, pOdp) =>
  `S ${oznacenie('odporca', pOdp, 'instr')} sme sa zoznámili približne pred [počet] rokmi. Pred uzavretím manželstva sme sa spoznávali [počet] rokov a verili sme, že naše hodnoty, ciele a predstavy o spoločnom živote sú zhodné. Manželstvo sme uzavreli z lásky a so spoločnou víziou založiť harmonickú rodinu. V prvých mesiacoch nášho manželstva náš vzťah napĺňal naše očakávania — trávili sme spolu voľný čas, podporovali sa v osobných cieľoch a budovali spoločnú domácnosť.`;

const sampleText2 = (pNav, pOdp) =>
  `Postupne začali v našom manželstve vznikať nezhody, ktorých príčinou bolo predovšetkým [stručný dôvod — odlišné životné priority, problémy s rodinou jedného z manželov, nedostatok komunikácie, finančné nezhody, alebo iné]. Spočiatku sme sa snažili problémy riešiť rozhovormi a vzájomnými ústupkami. Postupom času sa však napätie stupňovalo, hádky boli čoraz častejšie a ich riešenie čoraz ťažšie. Definitívny zlom v našom vzťahu nastal približne pred [časový údaj], keď [konkrétna udalosť — napr. zistenie nevery, vážny konflikt, vzájomné odcudzenie, rozhodnutie ${oznacenie('odporca', pOdp, 'gen')} o odsťahovaní]. Po tejto udalosti som si ${slovesoMinuly('uvedomil', pNav)}, že v manželstve nedokážem ďalej zotrvať.`;

const sampleText3 = (pNav, pOdp) =>
  `Keď som ${oznacenie('odporca', pOdp, 'dat')} ${slovesoMinuly('oznámil', pNav)} svoje rozhodnutie ukončiť manželstvo, ${privlastn(pOdp)} reakcia bola [zmierená / odmietavá / bez záujmu]. Naše manželské spolužitie už dlhodobo neplní svoju funkciu. Nehospodárime spoločne — nemáme spoločný účet, každý si nakupuje potraviny samostatne a stravujeme sa oddelene. Nemáme spoločné záľuby, netrávime spolu voľný čas a postupne sa rozišli aj naši spoloční známi. Intímny styk sme mali naposledy približne pred [časový údaj] a od tej doby sme spolu nemali žiadny intímny kontakt. Hoci formálne žijeme v spoločnej domácnosti, fakticky vedieme úplne oddelené životy.`;

const SAMPLE_TEXT_4 = 'Pokúsili sme sa o obnovu nášho manželstva niekoľkými spôsobmi — [napr. absolvovali sme spoločne partnerskú poradňu, mediáciu u odborníka, viedli sme otvorené rozhovory o našich problémoch, dohodli sme si spoločnú dovolenku v snahe oživiť vzťah]. Napriek úprimnej snahe oboch strán sa nám však nepodarilo obnoviť dôveru a vzájomnú blízkosť. Obnova manželstva už podľa môjho presvedčenia nie je možná, pretože medzi nami chýba citová väzba, dôvera aj základná vôľa pokračovať v spoločnom živote. Manželstvo je z mojej strany definitívne ukončené a v rozvode vidím jediné riešenie, aby sme obaja mohli začať novú etapu života.';

// ============================================================
// Sample texty pre Čl. III — maloleté deti a úprava výkonu
// rodičovských práv. Gender-aware varianty (pNav).
// ============================================================
const SAMPLE_311_M = 'Narodenie nášho prvého dieťaťa bolo pre mňa jednou z najkrajších udalostí v živote. Spolu s manželkou sme sa intenzívne pripravovali na rodičovstvo. Od narodenia detí som sa aktívne zapájal do starostlivosti — vstával som k nim v noci, kúpal ich, kŕmil, neskôr som ich vodil do škôlky a venoval sa im pri voľnočasových aktivitách. Vzťah s deťmi je vrelý a otvorený, deti mi dôverujú a rád trávim s nimi čas. V súčasnosti sa o deti staráme spoločne s manželkou — ja zabezpečujem ranné vstávanie a odvoz do školy, popoludní sa s nimi venujem úlohám a krúžkom, manželka má na starosti zdravotné prehliadky a komunikáciu so školou. Deti sú zdravé, šťastné a v škole úspešné.';

const SAMPLE_311_Z = 'Narodenie nášho prvého dieťaťa bolo pre mňa jednou z najkrajších udalostí v živote. Spolu s manželom sme sa intenzívne pripravovali na rodičovstvo. Od narodenia detí som sa aktívne starala o ich potreby — dojčila som, vstávala k nim v noci, sprevádzala ich pri prvých krokoch a slovách, neskôr ich vodila do škôlky a venovala sa im pri voľnočasových aktivitách. Vzťah s deťmi je vrelý a otvorený, deti mi dôverujú a vyhľadávajú moju spoločnosť. V súčasnosti zabezpečujem každodennú starostlivosť — ranné vstávanie, odvozy do školy a krúžkov, prípravu jedla, kontrolu úloh, zdravotné prehliadky a komunikáciu so školou. Deti sú zdravé, šťastné a v škole úspešné.';

const SAMPLE_312_M = 'Z pozitívnych skúseností uvádzam, že manželka sa o deti dlhodobo starala s láskou — najmä v období ich raného detstva, keď bola na materskej dovolenke. Ja som sa v tom čase venoval zabezpečeniu rodiny. Postupom času sa však naša spolupráca v starostlivosti o deti zhoršila. Manželka začala v prítomnosti detí kritizovať moju osobu, napríklad pri jednej z hádok v máji 2024 pred deťmi povedala: ,Otec sa o vás nikdy poriadne nestaral.\' Považujem za dôležité uviesť, že [opíšte konkrétne príklady, ktoré chcete uviesť]. Tieto situácie negatívne pôsobia na duševný stav detí a obmedzujú môj vzťah s nimi.';

const SAMPLE_312_Z = 'Z pozitívnych skúseností uvádzam, že manžel sa do narodenia mladšieho dieťaťa zapájal do starostlivosti aktívnejšie — chodil s nami na prechádzky, hral sa s deťmi cez víkendy. Postupom času sa však jeho zapojenie znížilo. Najmä v posledných dvoch rokoch som ostala s každodennou starostlivosťou prakticky sama. Manžel pri jednej z hádok v máji 2024 pred deťmi povedal: ,Aj tak si robíš, čo chceš.\' Považujem za dôležité uviesť, že [opíšte konkrétne príklady, ktoré chcete uviesť]. Tieto situácie negatívne pôsobia na duševný stav detí.';

// 3.2 — dva smery: A = zverenie sebe, B = zverenie druhému rodičovi.
const SAMPLE_32_A_M = 'Vzhľadom na doterajší priebeh starostlivosti a vzťah, ktorý mám s deťmi, navrhujem, aby boli maloleté deti zverené do mojej osobnej starostlivosti. Som schopný a ochotný zabezpečiť všetky ich potreby — bývanie, výživu, oblečenie, vzdelanie aj voľnočasové aktivity. S manželkou som ochotný komunikovať vo veciach týkajúcich sa detí a podporujem ich pravidelný styk s ňou. Verím, že takéto usporiadanie je v najlepšom záujme detí.';

const SAMPLE_32_A_Z = 'Vzhľadom na doterajší priebeh starostlivosti a vzťah, ktorý mám s deťmi, navrhujem, aby boli maloleté deti zverené do mojej osobnej starostlivosti. Som schopná a ochotná zabezpečiť všetky ich potreby — bývanie, výživu, oblečenie, vzdelanie aj voľnočasové aktivity. S manželom som ochotná komunikovať vo veciach týkajúcich sa detí a podporujem ich pravidelný styk s ním. Verím, že takéto usporiadanie je v najlepšom záujme detí.';

const SAMPLE_32_B_M = 'Po dôkladnom zvážení doterajšieho priebehu starostlivosti, životnej situácie oboch rodičov a najmä najlepšieho záujmu detí, navrhujem, aby boli maloleté deti zverené do osobnej starostlivosti manželky. Som pripravený plniť si vyživovaciu povinnosť a aktívne sa stýkať s deťmi tak, aby bol zachovaný môj vrelý vzťah s nimi. Považujem za dôležité, aby deti mali stabilné prostredie a aby ich každodenné fungovanie nebolo narušené.';

const SAMPLE_32_B_Z = 'Po dôkladnom zvážení doterajšieho priebehu starostlivosti, životnej situácie oboch rodičov a najmä najlepšieho záujmu detí, navrhujem, aby boli maloleté deti zverené do osobnej starostlivosti manžela. Som pripravená plniť si vyživovaciu povinnosť a aktívne sa stýkať s deťmi tak, aby bol zachovaný môj vrelý vzťah s nimi. Považujem za dôležité, aby deti mali stabilné prostredie a aby ich každodenné fungovanie nebolo narušené.';

// ============================================================
// 3.3(b) — Striedavá osobná starostlivosť, vzorové texty (4 sekcie).
// Plurál-aware cez detiSlovo(pCount, pad). Symetrické (otec/matka),
// nezávisí na pohlaví navrhovateľa — stačí pCount.
// ============================================================
const sampleStriedavka_BeznyCyklus = (pCount) =>
  `S výnimkou osobitnej úpravy počas letných, zimných a veľkonočných prázdnin ${bude(pCount)} ${detiSlovo(pCount, 'nom')} v osobnej starostlivosti matky každý párny kalendárny týždeň od pondelka od 8:00 hod. do nasledujúceho pondelka nepárneho kalendárneho týždňa do 8:00 hod. a v osobnej starostlivosti otca každý nepárny kalendárny týždeň od pondelka od 8:00 hod. do nasledujúceho pondelka párneho kalendárneho týždňa do 8:00 hod.`;

const sampleStriedavka_LetnePrazdniny = (pCount) =>
  `Počas letných prázdnin ${bude(pCount)} ${detiSlovo(pCount, 'nom')} v osobnej starostlivosti matky v každom kalendárnom roku vždy od 15. 7. od 19:00 hod. do 1. 8. do 9:00 hod. a od 15. 8. od 19:00 hod. do 31. 8. do 19:00 hod. V osobnej starostlivosti otca ${bude(pCount)} ${detiSlovo(pCount, 'nom')} v každom kalendárnom roku vždy od 1. 7. od 9:00 hod. do 15. 7. do 19:00 hod. a od 1. 8. od 9:00 hod. do 15. 8. do 19:00 hod.`;

const sampleStriedavka_ZimnePrazdniny = (pCount) =>
  `Počas zimných prázdnin ${bude(pCount)} ${detiSlovo(pCount, 'nom')} v nepárnom kalendárnom roku v osobnej starostlivosti otca od 24. 12. od 16:00 hod. do 25. 12. do 18:00 hod., matky od 25. 12. od 18:00 hod. do 1. 1. nasledujúceho párneho roka do 10:00 hod., otca od 1. 1. párneho roka od 10:00 hod. do 6. 1. do 18:00 hod. V párnom kalendárnom roku ${bude(pCount)} ${detiSlovo(pCount, 'nom')} v osobnej starostlivosti matky od 24. 12. od 16:00 hod. do 25. 12. do 18:00 hod., otca od 25. 12. od 18:00 hod. do 1. 1. nasledujúceho nepárneho roka do 10:00 hod., matky od 1. 1. nepárneho roka od 10:00 hod. do 6. 1. do 18:00 hod.`;

const sampleStriedavka_VelkonocnePrazdniny = (pCount) =>
  `Počas veľkonočných prázdnin ${bude(pCount)} ${detiSlovo(pCount, 'nom')} v osobnej starostlivosti matky každý párny kalendárny rok od Zeleného štvrtka od 10:00 hod. do Veľkonočného pondelka do 14:00 hod. a v osobnej starostlivosti otca každý nepárny kalendárny rok od Zeleného štvrtka od 10:00 hod. do Veľkonočného pondelka do 14:00 hod.`;

// Záverečná veta o miestach prevzatia/odovzdania — spoločná pre striedavku
// (3.3 b) aj styk (3.5). Singulár/plurál cez detiSlovo + zhodný tvar.
const sampleVetaOdovzdanie = (pCount) =>
  `Miestom prevzatia a odovzdania ${detiSlovo(pCount, 'gen')} bude predškolské alebo školské zariadenie, ktoré ${pCount === 1 ? 'maloletý navštevuje' : 'maloletí navštevujú'}, a v čase ${pCount === 1 ? 'jeho' : 'ich'} neprítomnosti v tomto zariadení bydlisko odovzdávajúceho rodiča.`;

// 3.3(c) — spoločná osobná starostlivosť, sample text pre Ed block.
// Plural-aware cez detiSlovo + bolo/boli zhoda slovesa byť s podmetom.
const sampleSpolocna = (pCount) =>
  `Navrhujem, aby ${bolo(pCount)} ${detiSlovo(pCount, 'nom')} zverené do spoločnej osobnej starostlivosti oboch rodičov podľa § 24 ods. 2 zákona č. 36/2005 Z. z. o rodine. Vieme sa dohodnúť a komunikovať vo veciach výchovy ${detiSlovo(pCount, 'gen')}.`;

// Bežný cyklus pre "vlastné" striedanie — placeholder na vyplnenie užívateľom.
const SAMPLE_STRIEDAVKA_BEZNY_VLASTNE = '[Vyplňte vlastný režim striedania - pozor režim musí byť napísaný tak, aby bol vykonateľný.]';

// Spojený text všetkých 4 sekcií 3.3(b) + záverečná veta o odovzdaní —
// vkladá sa do Ed bloku po kliknutí "Použiť tento text". BEZ sub-headings:
// holé odseky oddelené prázdnym riadkom (Ed.block má white-space: pre-wrap,
// takže \n\n sa rendrujú ako vizuálne odsadenie odsekov).
const sample33bJoined = (typ, pCount) => {
  const bezny = typ === 'vlastne'
    ? SAMPLE_STRIEDAVKA_BEZNY_VLASTNE
    : sampleStriedavka_BeznyCyklus(pCount);
  return [
    bezny,
    sampleStriedavka_LetnePrazdniny(pCount),
    sampleStriedavka_ZimnePrazdniny(pCount),
    sampleStriedavka_VelkonocnePrazdniny(pCount),
    sampleVetaOdovzdanie(pCount),
  ].join('\n\n');
};

// ============================================================
// 3.5 — Vzor styku rodiča, ktorému deti neboli zverené (4 sekcie).
// nezverenyKey = 'otec' | 'matka'.
// ============================================================
const sampleStyk_BeznyStyk = (nezverenyKey, pCount) => {
  const opravneny = nezverenyKey === 'matka' ? 'oprávnená' : 'oprávnený';
  const rolaCap = nezverenyKey === 'matka' ? 'Matka' : 'Otec';
  return `${rolaCap} je ${opravneny} stýkať sa s ${detiSlovo(pCount, 'instr')} každý párny kalendárny týždeň od piatka od 16:00 hod. do nedele do 19:00 hod. a každý kalendárny týždeň v utorok od 15:00 hod. do 19:00 hod.`;
};

const sampleStyk_LetnePrazdniny = (nezverenyKey, pCount) => {
  const opravneny = nezverenyKey === 'matka' ? 'oprávnená' : 'oprávnený';
  const rolaCap = nezverenyKey === 'matka' ? 'Matka' : 'Otec';
  if (nezverenyKey === 'otec') {
    return `${rolaCap} je ${opravneny} stýkať sa s ${detiSlovo(pCount, 'instr')} v každom kalendárnom roku vždy od 1. 7. od 9:00 hod. do 15. 7. do 19:00 hod. a od 1. 8. od 9:00 hod. do 15. 8. do 19:00 hod.`;
  }
  return `${rolaCap} je ${opravneny} stýkať sa s ${detiSlovo(pCount, 'instr')} v každom kalendárnom roku vždy od 15. 7. od 19:00 hod. do 1. 8. do 9:00 hod. a od 15. 8. od 19:00 hod. do 31. 8. do 19:00 hod.`;
};

const sampleStyk_ZimnePrazdniny = (nezverenyKey, pCount) => {
  const opravneny = nezverenyKey === 'matka' ? 'oprávnená' : 'oprávnený';
  const rolaCap = nezverenyKey === 'matka' ? 'Matka' : 'Otec';
  if (nezverenyKey === 'otec') {
    return `${rolaCap} je ${opravneny} stýkať sa s ${detiSlovo(pCount, 'instr')} v nepárnom kalendárnom roku od 24. 12. od 16:00 hod. do 25. 12. do 18:00 hod. a od 1. 1. párneho roka od 10:00 hod. do 6. 1. do 18:00 hod. V párnom kalendárnom roku od 25. 12. od 18:00 hod. do 1. 1. nasledujúceho nepárneho roka do 10:00 hod.`;
  }
  return `${rolaCap} je ${opravneny} stýkať sa s ${detiSlovo(pCount, 'instr')} v nepárnom kalendárnom roku od 25. 12. od 18:00 hod. do 1. 1. nasledujúceho párneho roka do 10:00 hod. V párnom kalendárnom roku od 24. 12. od 16:00 hod. do 25. 12. do 18:00 hod. a od 1. 1. nepárneho roka od 10:00 hod. do 6. 1. do 18:00 hod.`;
};

const sampleStyk_VelkonocnePrazdniny = (nezverenyKey, pCount) => {
  const opravneny = nezverenyKey === 'matka' ? 'oprávnená' : 'oprávnený';
  const rolaCap = nezverenyKey === 'matka' ? 'Matka' : 'Otec';
  const parityWord = nezverenyKey === 'matka' ? 'párny' : 'nepárny';
  return `${rolaCap} je ${opravneny} stýkať sa s ${detiSlovo(pCount, 'instr')} každý ${parityWord} kalendárny rok od Zeleného štvrtka od 10:00 hod. do Veľkonočného pondelka do 14:00 hod.`;
};

// Spojený text všetkých 4 sekcií 3.5 styku + záverečná veta o odovzdaní —
// vkladá sa do Ed bloku po kliknutí "Použiť tento text". BEZ sub-headings.
const sampleStyk_Joined = (nezverenyKey, pCount) => [
  sampleStyk_BeznyStyk(nezverenyKey, pCount),
  sampleStyk_LetnePrazdniny(nezverenyKey, pCount),
  sampleStyk_ZimnePrazdniny(nezverenyKey, pCount),
  sampleStyk_VelkonocnePrazdniny(nezverenyKey, pCount),
  sampleVetaOdovzdanie(pCount),
].join('\n\n');

// Singulárové varianty pre 1 dieťa — gramatický stredný rod ("dieťa")
// + zámená "ho/mu/ním", neutrálne pre nepoznané pohlavie dieťaťa.
const SAMPLE_311_M_SG = 'Narodenie nášho dieťaťa bolo pre mňa jednou z najkrajších udalostí v živote. Spolu s manželkou sme sa intenzívne pripravovali na rodičovstvo. Od narodenia dieťaťa som sa aktívne zapájal do starostlivosti — vstával som k nemu v noci, kúpal ho, kŕmil, neskôr som ho vodil do škôlky a venoval sa mu pri voľnočasových aktivitách. Vzťah s dieťaťom je vrelý a otvorený, dieťa mi dôveruje a rád trávim s ním čas. V súčasnosti sa o dieťa staráme spoločne s manželkou — ja zabezpečujem ranné vstávanie a odvoz do školy, popoludní sa s ním venujem úlohám a krúžkom, manželka má na starosti zdravotné prehliadky a komunikáciu so školou. Dieťa je zdravé, šťastné a v škole úspešné.';

const SAMPLE_311_Z_SG = 'Narodenie nášho dieťaťa bolo pre mňa jednou z najkrajších udalostí v živote. Spolu s manželom sme sa intenzívne pripravovali na rodičovstvo. Od narodenia dieťaťa som sa aktívne starala o jeho potreby — dojčila som, vstávala k nemu v noci, sprevádzala ho pri prvých krokoch a slovách, neskôr ho vodila do škôlky a venovala sa mu pri voľnočasových aktivitách. Vzťah s dieťaťom je vrelý a otvorený, dieťa mi dôveruje a vyhľadáva moju spoločnosť. V súčasnosti zabezpečujem každodennú starostlivosť — ranné vstávanie, odvozy do školy a krúžkov, prípravu jedla, kontrolu úloh, zdravotné prehliadky a komunikáciu so školou. Dieťa je zdravé, šťastné a v škole úspešné.';

const SAMPLE_312_M_SG = 'Z pozitívnych skúseností uvádzam, že manželka sa o dieťa dlhodobo starala s láskou — najmä v období jeho raného detstva, keď bola na materskej dovolenke. Ja som sa v tom čase venoval zabezpečeniu rodiny. Postupom času sa však naša spolupráca v starostlivosti o dieťa zhoršila. Manželka začala v prítomnosti dieťaťa kritizovať moju osobu, napríklad pri jednej z hádok v máji 2024 pred dieťaťom povedala: ,Otec sa o teba nikdy poriadne nestaral.\' Považujem za dôležité uviesť, že [opíšte konkrétne príklady, ktoré chcete uviesť]. Tieto situácie negatívne pôsobia na duševný stav dieťaťa a obmedzujú môj vzťah s ním.';

const SAMPLE_312_Z_SG = 'Z pozitívnych skúseností uvádzam, že manžel sa v prvých rokoch dieťaťa zapájal do starostlivosti aktívnejšie — chodil s nami na prechádzky, hral sa s ním cez víkendy. Postupom času sa však jeho zapojenie znížilo. Najmä v posledných dvoch rokoch som ostala s každodennou starostlivosťou prakticky sama. Manžel pri jednej z hádok v máji 2024 pred dieťaťom povedal: ,Aj tak si robíš, čo chceš.\' Považujem za dôležité uviesť, že [opíšte konkrétne príklady, ktoré chcete uviesť]. Tieto situácie negatívne pôsobia na duševný stav dieťaťa.';

const SAMPLE_32_A_M_SG = 'Vzhľadom na doterajší priebeh starostlivosti a vzťah, ktorý mám s dieťaťom, navrhujem, aby bolo maloleté dieťa zverené do mojej osobnej starostlivosti. Som schopný a ochotný zabezpečiť všetky jeho potreby — bývanie, výživu, oblečenie, vzdelanie aj voľnočasové aktivity. S manželkou som ochotný komunikovať vo veciach týkajúcich sa dieťaťa a podporujem jeho pravidelný styk s ňou. Verím, že takéto usporiadanie je v najlepšom záujme dieťaťa.';

const SAMPLE_32_A_Z_SG = 'Vzhľadom na doterajší priebeh starostlivosti a vzťah, ktorý mám s dieťaťom, navrhujem, aby bolo maloleté dieťa zverené do mojej osobnej starostlivosti. Som schopná a ochotná zabezpečiť všetky jeho potreby — bývanie, výživu, oblečenie, vzdelanie aj voľnočasové aktivity. S manželom som ochotná komunikovať vo veciach týkajúcich sa dieťaťa a podporujem jeho pravidelný styk s ním. Verím, že takéto usporiadanie je v najlepšom záujme dieťaťa.';

const SAMPLE_32_B_M_SG = 'Po dôkladnom zvážení doterajšieho priebehu starostlivosti, životnej situácie oboch rodičov a najmä najlepšieho záujmu dieťaťa, navrhujem, aby bolo maloleté dieťa zverené do osobnej starostlivosti manželky. Som pripravený plniť si vyživovaciu povinnosť a aktívne sa stýkať s dieťaťom tak, aby bol zachovaný môj vrelý vzťah s ním. Považujem za dôležité, aby dieťa malo stabilné prostredie a aby jeho každodenné fungovanie nebolo narušené.';

const SAMPLE_32_B_Z_SG = 'Po dôkladnom zvážení doterajšieho priebehu starostlivosti, životnej situácie oboch rodičov a najmä najlepšieho záujmu dieťaťa, navrhujem, aby bolo maloleté dieťa zverené do osobnej starostlivosti manžela. Som pripravená plniť si vyživovaciu povinnosť a aktívne sa stýkať s dieťaťom tak, aby bol zachovaný môj vrelý vzťah s ním. Považujem za dôležité, aby dieťa malo stabilné prostredie a aby jeho každodenné fungovanie nebolo narušené.';

// Sample helpery — vyberajú variant podľa pohlavia navrhovateľa A počtu detí.
// pCount === 1 → singulárová varianta; inak (0, 2+) plurálová (defaultne).
const sample311 = (pNav, pCount) => {
  const sg = pCount === 1;
  if (pNav === 'zena') return sg ? SAMPLE_311_Z_SG : SAMPLE_311_Z;
  return sg ? SAMPLE_311_M_SG : SAMPLE_311_M;
};
const sample312 = (pNav, pCount) => {
  const sg = pCount === 1;
  if (pNav === 'zena') return sg ? SAMPLE_312_Z_SG : SAMPLE_312_Z;
  return sg ? SAMPLE_312_M_SG : SAMPLE_312_M;
};
const sample32A = (pNav, pCount) => {
  const sg = pCount === 1;
  if (pNav === 'zena') return sg ? SAMPLE_32_A_Z_SG : SAMPLE_32_A_Z;
  return sg ? SAMPLE_32_A_M_SG : SAMPLE_32_A_M;
};
const sample32B = (pNav, pCount) => {
  const sg = pCount === 1;
  if (pNav === 'zena') return sg ? SAMPLE_32_B_Z_SG : SAMPLE_32_B_Z;
  return sg ? SAMPLE_32_B_M_SG : SAMPLE_32_B_M;
};

// Controlled contentEditable — to isté pole žije na dvoch miestach (bod 1.1
// a petit) a synchronizuje sa cez zdieľaný state.
//
// Cursor preservation: písanie do tohto inputu nesmie spôsobiť prepis textContent
// (cursor by skočil na začiatok). isTypingRef príznak rozlíši, či zmena value
// prišla z tohto inputu (skip DOM write) alebo z druhej inštancie (write).
// noPersist=true → pridá class `ed-no-persist`. Persist.jsx tieto polia preskakuje
// (save aj restore), takže ich obsah riadi výlučne React state. Použité pre dynamické
// kolekcie (deti), ktorých počet/poradie sa mení a Persistov ordinálny scope by
// pri delete-and-reload prehadzoval hodnoty medzi riadkami.
const SyncedEd = ({ value, onChange, placeholder, lg, num, noPersist }) => {
  const ref = React.useRef(null);
  const isTypingRef = React.useRef(false);

  React.useEffect(() => {
    if (ref.current && !isTypingRef.current && ref.current.textContent !== value) {
      ref.current.textContent = value;
    }
    isTypingRef.current = false;
  }, [value]);

  const cls = [
    "ed",
    lg && "ed-lg",
    num && "ed-num",
    !value && "ed-empty",
    noPersist && "ed-no-persist",
  ].filter(Boolean).join(" ");

  return (
    <span
      ref={ref}
      className={cls}
      contentEditable
      suppressContentEditableWarning
      onInput={(e) => {
        isTypingRef.current = true;
        onChange(e.currentTarget.textContent);
      }}
      data-placeholder={placeholder}
      role="textbox"
      aria-label={placeholder}
    />
  );
};

// Rozbaliteľný panel so vzorovým textom pre kategórie 2.1-2.4 v Čl. II.
// onUse vloží text do Ed block poľa a panel zatvorí; onClose len zatvorí.
// Tlačidlo "Použiť tento text →" — unifikovaný oxblood štýl pre všetky
// custom sample panely v Čl. III. Rovnaký vizuál ako tlačidlo v SamplePanel
// (používaný v Čl. II 2.1–2.4) — extrahované do komponentu, aby sa štýl
// menil naraz na všetkých miestach.
// Mobile-safe trigger: onPointerDown vyvolá akciu okamžite (touch tap),
// preventDefault + stopPropagation zabránia bublinkovaniu kliku do parent
// kontajnera ešte predtým, ako sa textContent prenesie do Ed bloku.
// onClick zachovaný pre keyboard (Tab + Enter). Akcia je idempotent.
const UsePatternButton = ({ onClick, children }) => {
  const trigger = (e) => {
    e.preventDefault();
    e.stopPropagation();
    onClick && onClick(e);
  };
  return (
    <button
      type="button"
      onPointerDown={trigger}
      onClick={trigger}
      style={{
        fontSize: '0.85em',
        padding: '6px 14px',
        border: '1px solid var(--oxblood)',
        borderRadius: 'var(--r-sm)',
        background: 'var(--paper)',
        color: 'var(--oxblood)',
        cursor: 'pointer',
        fontWeight: 500,
      }}
    >{children || 'Použiť tento text →'}</button>
  );
};

const SamplePanel = ({ sampleText, onUse, onClose }) => (
  <div className="no-copy no-print" style={{
    background: 'var(--ivory-2)',
    border: '1px solid var(--rule)',
    borderRadius: 'var(--r-sm)',
    padding: '12px 16px',
    margin: '8px 0',
    fontSize: '0.88em',
    lineHeight: 1.6,
    color: 'var(--ink-2)',
    position: 'relative'
  }}>
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
      <strong style={{ fontSize: '0.85em', textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--ink-3)' }}>Vzorový text — len ako inšpirácia</strong>
      <button
        onClick={onClose}
        style={{ border: 'none', background: 'transparent', cursor: 'pointer', fontSize: '1.2em', color: 'var(--ink-3)', padding: 0, lineHeight: 1 }}
        aria-label="Skryť vzor"
      >×</button>
    </div>
    <div style={{ fontStyle: 'italic', marginBottom: 12 }}>
      {sampleText}
    </div>
    <button
      type="button"
      onPointerDown={(e) => { e.preventDefault(); e.stopPropagation(); onUse && onUse(e); }}
      onClick={(e) => { e.preventDefault(); e.stopPropagation(); onUse && onUse(e); }}
      style={{
        fontSize: '0.85em',
        padding: '6px 14px',
        border: '1px solid var(--oxblood)',
        borderRadius: 'var(--r-sm)',
        background: 'var(--paper)',
        color: 'var(--oxblood)',
        cursor: 'pointer',
        fontWeight: 500
      }}
    >Použiť tento text →</button>
  </div>
);

// Modul-level komponent — stabilná funkčná referencia, vďaka čomu si <input>
// drží focus medzi keystrokes. State žije v Paper a tečie cez props, takže
// hlavička aj bod 1.3 zdieľajú ten istý vybraný súd.
const SudAutocomplete = ({ sudQuery, setSudQuery, sudVybrany, setSudVybrany, sudDropdown, setSudDropdown, sudFiltered }) => (
  <span style={{ position: 'relative', display: 'inline-block', minWidth: 280 }}>
    <input
      type="text"
      value={sudVybrany ? sudVybrany.nazov : sudQuery}
      onChange={(e) => { setSudQuery(e.target.value); setSudVybrany(null); setSudDropdown(true); }}
      onFocus={() => setSudDropdown(true)}
      onBlur={() => setTimeout(() => setSudDropdown(false), 150)}
      placeholder="začnite písať názov súdu..."
      style={{
        padding: '3px 8px',
        border: '1px solid var(--rule)',
        borderRadius: 'var(--r-sm)',
        fontFamily: 'var(--serif)',
        fontSize: '0.95em',
        background: 'var(--ed-bg, #fefce8)',
        width: '100%',
      }}
    />
    {sudDropdown && sudFiltered.length > 0 && (
      <ul style={{
        position: 'absolute',
        top: '100%',
        left: 0,
        right: 0,
        background: 'var(--paper, #ffffff)',
        backdropFilter: 'none',
        border: '1px solid var(--rule)',
        borderRadius: 'var(--r-sm)',
        boxShadow: '0 4px 16px rgba(0,0,0,0.10)',
        listStyle: 'none',
        margin: 0,
        padding: '4px 0',
        zIndex: 1000,
        maxHeight: 220,
        overflowY: 'auto',
      }}>
        {sudFiltered.map(s => (
          <li
            key={s.nazov}
            onMouseDown={() => { setSudVybrany(s); setSudQuery(''); setSudDropdown(false); }}
            style={{
              padding: '2px 12px',
              cursor: 'pointer',
              fontSize: '0.9em',
              fontFamily: 'var(--serif)',
              background: 'var(--paper, #ffffff)',
            }}
            onMouseEnter={e => e.currentTarget.style.background = 'var(--ivory-2)'}
            onMouseLeave={e => e.currentTarget.style.background = 'var(--paper, #ffffff)'}
          >
            {s.nazov}
          </li>
        ))}
      </ul>
    )}
  </span>
);

// ============================================================
// TipBtn — floating "TIP" pin v gutteri papiera. Definovaný NA module-leveli
// (mimo Paper), aby React zachoval identitu komponentu cez Paper re-rendery.
// Inak (keď bol TipBtn definovaný vnútri Paper) každý Paper render mu pridelil
// novú function reference → React unmount + mount → useLayoutEffect zbehol
// znova a krátky frame s initial topPx=0 spôsoboval vizuálny "preskok" tipov
// pri scrolle (scroll-spy IntersectionObserver triggeruje setActiveArticle/
// setActiveTipKey, čo Paper re-renderuje).
//
// Top sa počíta RAZ pri reálnom mount-e + na zmenu výšky .paper-a cez
// ResizeObserver (otvorenie wizardu, vkladanie vzoru, edit textu, viewport
// resize). Počas scrollu sa NEPREPOČÍTAVA → tipy sú vizuálne stabilné.
// activeTipKey + onTipClick sú doručené cez TipContext, takže prop drilling
// do 13 call-sites netreba.
// ============================================================
const TipContext = React.createContext({ activeTipKey: null, onTipClick: null });

const TipBtn = ({ pointKey }) => {
  const { activeTipKey, onTipClick } = React.useContext(TipContext);
  const buttonRef = React.useRef(null);
  const [topPx, setTopPx] = React.useState(0);

  React.useLayoutEffect(() => {
    const button = buttonRef.current;
    if (!button) return;
    const anchor = button.parentNode;
    const paper = button.closest('.paper');
    if (!paper || !anchor) return;

    const update = () => {
      // offsetTop chain anchor → .paper. Po našich CSS zmenách je anchor.offsetParent
      // priamo .paper, walk je defenzívny pre prípad neskoršieho pozicovaného wrapperu.
      let top = anchor.offsetTop;
      let p = anchor.offsetParent;
      while (p && p !== paper) {
        top += p.offsetTop;
        p = p.offsetParent;
      }
      setTopPx(top + 2);
    };
    update();

    const ro = new ResizeObserver(update);
    ro.observe(paper);
    window.addEventListener('resize', update);
    return () => { ro.disconnect(); window.removeEventListener('resize', update); };
  }, []);

  return (
    <button
      ref={buttonRef}
      type="button"
      className={`tip-pin no-print ${activeTipKey === pointKey ? 'active' : ''}`}
      data-tip-key={pointKey}
      onClick={(e) => { e.stopPropagation(); onTipClick && onTipClick(pointKey); }}
      aria-label={`Zobraziť tip k bodu ${pointKey}`}
      title={`Tip k bodu ${pointKey}`}
      contentEditable={false}
      style={{ top: `${topPx}px` }}
    >
      TIP
    </button>
  );
};

// Sekcia maloletých detí — vlastná serializácia, mimo Persist.jsx.
// Persist ukladá .ed polia podľa ordinálneho indexu vo svojom scope. Pre dynamickú
// kolekciu, kde môže používateľ mazať uprostred a pridávať na konci, by to po
// reload-e prehadzovalo hodnoty medzi riadkami. Preto kids držíme ako JSON pole
// v samostatnom localStorage kľúči a Ed polia označujeme noPersist (Persist
// preskakuje class `ed-no-persist`).
// ============================================================
// Petit (rozsudok) — pure helpers + generátor výrokov.
// generujPetit() je čistá funkcia, vstup = ctx zo state-u, výstup =
// pole { label, body } pre render. Používa existujúce helpery
// (oznacenie, oznacenieCap, rolaOpravneny, rolaRodicaKey, detiSlovo,
// sampleStriedavka_*) + nové: rolaPovinny, PetitPh, orPh, formatujKidsList.
// ============================================================
const PetitPh = ({ children }) => (
  <span className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)' }}>{children}</span>
);
const orPh = (val, hint) =>
  (val && String(val).trim()) ? val : <PetitPh>[{hint}]</PetitPh>;

// Sloveso "povinný/-á" pre rodičovskú rolu — gendered koncovka.
// Analogicky k rolaOpravneny (FÁZA B).
const rolaPovinny = (role, navrhovatelPohlavie) =>
  rolaRodicaKey(role, navrhovatelPohlavie) === 'matka' ? 'povinná' : 'povinný';

// formatujKidsList — vracia ReactNode "Meno1, nar. dátum1, [a] MenoN, nar. dátumN"
// s placeholdrami pre prázdne polia. Skrátené "nar." je rod-neutrálne.
const formatujKidsList = (kids) => {
  if (!kids || kids.length === 0) return '';
  const renderKid = (k) => (
    <>
      {orPh(k.meno, 'meno?')}, nar. {orPh(k.datumNarodenia, 'dátum?')}
    </>
  );
  if (kids.length === 1) return renderKid(kids[0]);
  return (
    <>
      {kids.map((k, i) => (
        <React.Fragment key={k.id}>
          {renderKid(k)}
          {i === kids.length - 2
            ? (kids.length === 2 ? ' a ' : ', a ')
            : (i < kids.length - 1 ? ', ' : '')}
        </React.Fragment>
      ))}
    </>
  );
};

// formatujKidsListPreVyzivne — pre Výrok III: zoznam detí so sumami v jednej vete.
// "maloletého dieťaťa Anton Novák, nar. 4. 1. 2015, sumou 200 eur mesačne[, a maloletého dieťaťa ...]"
const formatujKidsListPreVyzivne = (kids, getVyzivne) => {
  if (!kids || kids.length === 0) return '';
  const renderKid = (k) => {
    const row = getVyzivne(k.id);
    return (
      <>
        maloletého dieťaťa {orPh(k.meno, 'meno?')}, nar. {orPh(k.datumNarodenia, 'dátum?')}, sumou {orPh(row && row.suma, 'suma')} eur mesačne
      </>
    );
  };
  if (kids.length === 1) return renderKid(kids[0]);
  return (
    <>
      {kids.map((k, i) => (
        <React.Fragment key={k.id}>
          {renderKid(k)}
          {i === kids.length - 2
            ? (kids.length === 2 ? ' a ' : ', a ')
            : (i < kids.length - 1 ? ', ' : '')}
        </React.Fragment>
      ))}
    </>
  );
};

// Default voľba zastupovania — VŽDY 'obaja' bez ohľadu na formu/zverenie/pohlavie.
// Súdna prax (§ 28 ods. 1 + § 31 ods. 1 ZoR) je, že obaja rodičia ostávajú
// zákonnými zástupcami, iný režim je výnimočný. userTouchedZastupovanie
// uzamkne ďalšie auto-zmeny po prvom explicit prepnutí na matka/otec.
const computeZastupovanieDefault = (_formaStarostlivosti, _zvereniePri_a, _navrhovatelPohlavie) => 'obaja';

const ROMAN_PETIT = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII'];

// Helper na splitnutie multi-paragraph Ed-content (line breaks) na ReactNodes.
const splitParagraphs = (text) =>
  String(text || '')
    .split(/\n\s*\n/)
    .map(s => s.trim())
    .filter(Boolean);

function generujPetit(ctx) {
  const {
    navrhovatelPohlavie, odporcaPohlavie,
    menoNavrhovatela, menoOdporcu,
    datumSobasa, miestoSobasa, maticnyUrad, zvazok, rocnik, strana, poradoveCislo,
    filledKids, cl3,
    ed33bContent, ed35Content,
    getVyzivne,
  } = ctx;

  const pCount = filledKids.length;
  // Každý výrok = { label, paragraphs: ReactNode[] }. Multi-paragraph používa
  // Výrok II striedavka (úvod + 4 sekcie + odovzdanie); ostatné majú 1 paragraph.
  const verdicts = [];
  let lastOuter = 0;

  // Výrok I — rozvod manželstva (vždy).
  lastOuter = 1;
  verdicts.push({
    label: ROMAN_PETIT[lastOuter],
    paragraphs: [(
      <>
        Súd rozvádza manželstvo {oznacenieCap('navrhovatel', navrhovatelPohlavie)} {orPh(menoNavrhovatela, 'meno navrhovateľa')} a {oznacenie('odporca', odporcaPohlavie)} {orPh(menoOdporcu, 'meno odporcu')}, uzavreté dňa {orPh(datumSobasa, 'dátum sobáša')} v {orPh(miestoSobasa, 'miesto sobáša')}, zapísané v knihe manželstiev matričného úradu {orPh(maticnyUrad, 'matrika')}, zväzok {orPh(zvazok, 'zväzok')}, ročník {orPh(rocnik, 'ročník')}, strana {orPh(strana, 'strana')}, pod poradovým číslom {orPh(poradoveCislo, 'poradové č.')}.
      </>
    )],
  });

  if (pCount > 0) {
    const kidsList = formatujKidsList(filledKids);

    // Výrok II — zverenie do osobnej starostlivosti. BEZ vety o zastupovaní —
    // tá je teraz samostatný Výrok III.
    lastOuter = 2;
    if (cl3.formaStarostlivosti === 'a') {
      // Rodinnoprávne označenie zvereného rodiča (matka/otec) v 2. páde —
      // bez procesných označení a bez mena. Cleaner právna formulácia.
      const zverenyKey = rolaRodicaKey(cl3.zvereniePri_a, navrhovatelPohlavie);
      verdicts.push({
        label: ROMAN_PETIT[lastOuter],
        paragraphs: [(
          <>
            Maloleté {pCount === 1 ? 'dieťa' : 'deti'} {kidsList} sa {pCount === 1 ? 'zveruje' : 'zverujú'} na čas po rozvode do osobnej starostlivosti {rolaRodicaPad(zverenyKey, 'gen')}.
          </>
        )],
      });
    } else if (cl3.formaStarostlivosti === 'b') {
      // Petit striedavka — jednotne pre 1tyz aj vlastne: petit reflektuje
      // čisto Ed-content 3.3(b). Default vzor sa už NEgeneruje automaticky;
      // ak user neklikol "Použiť tento text", inline placeholder upozorní
      // na chýbajúci obsah (no-print, v PDF zmizne).
      const paragraphs = [];
      paragraphs.push(
        <>
          Maloleté {pCount === 1 ? 'dieťa' : 'deti'} {kidsList} sa {pCount === 1 ? 'zveruje' : 'zverujú'} na čas po rozvode do striedavej osobnej starostlivosti oboch rodičov nasledovne:
        </>
      );
      if (ed33bContent && ed33bContent.trim()) {
        splitParagraphs(ed33bContent).forEach(p =>
          paragraphs.push(<span style={{ whiteSpace: 'pre-wrap' }}>{p}</span>)
        );
      } else {
        paragraphs.push(<PetitPh>[doplňte režim striedania v Čl. III bod 3.3]</PetitPh>);
      }
      verdicts.push({ label: ROMAN_PETIT[lastOuter], paragraphs });
    } else if (cl3.formaStarostlivosti === 'c') {
      verdicts.push({
        label: ROMAN_PETIT[lastOuter],
        paragraphs: [(
          <>
            Maloleté {pCount === 1 ? 'dieťa' : 'deti'} {kidsList} sa {pCount === 1 ? 'zveruje' : 'zverujú'} na čas po rozvode do spoločnej osobnej starostlivosti oboch rodičov podľa § 24 ods. 2 zákona č. 36/2005 Z. z. o rodine.
          </>
        )],
      });
    }

    // Výrok III — zastupovanie a správa majetku (NOVÝ, samostatný).
    lastOuter = 3;
    const zastText = cl3.zastupovanie === 'obaja'
      ? 'budú obaja rodičia'
      : cl3.zastupovanie === 'matka'
        ? 'bude matka'
        : 'bude otec';
    verdicts.push({
      label: ROMAN_PETIT[lastOuter],
      paragraphs: [(
        <>
          Zastupovať maloleté {pCount === 1 ? 'dieťa' : 'deti'} {kidsList} a spravovať {pCount === 1 ? 'jeho' : 'ich'} majetok {zastText}.
        </>
      )],
    });

    // Výrok IV — výživné (pôvodne III, posunuté o 1 kvôli zastupovaniu).
    lastOuter = 4;
    const rezim = cl3.formaStarostlivosti === 'a'
      ? 'i'
      : (cl3.formaStarostlivosti === 'b' ? cl3.rezimVyzivnehoPri_b : cl3.rezimVyzivnehoPri_c);

    if (rezim === 'i') {
      // JEDEN výrok bez pod-indexov — všetky deti so sumami v jednej vete.
      // Subjekt + adresát cez rolaRodica (matka/otec), žiadne procesné označenia.
      const platiRole = cl3.formaStarostlivosti === 'a'
        ? (cl3.zvereniePri_a === 'navrhovatel' ? 'odporca' : 'navrhovatel')
        : 'odporca';
      const prijemcaRole = cl3.formaStarostlivosti === 'a'
        ? cl3.zvereniePri_a
        : 'navrhovatel';
      const platiKey = rolaRodicaKey(platiRole, navrhovatelPohlavie);
      const prijemcaKey = rolaRodicaKey(prijemcaRole, navrhovatelPohlavie);
      const platiCap = platiKey === 'matka' ? 'Matka' : 'Otec';
      const platiPovinnyTvar = platiKey === 'matka' ? 'povinná' : 'povinný';
      const prijemcaGen = rolaRodicaPad(prijemcaKey, 'gen');

      verdicts.push({
        label: ROMAN_PETIT[lastOuter],
        paragraphs: [(
          <>
            {platiCap} je {platiPovinnyTvar} prispievať na výživu {formatujKidsListPreVyzivne(filledKids, getVyzivne)}, vždy do 15. dňa kalendárneho mesiaca vopred, k rukám {prijemcaGen}, počnúc dňom právoplatnosti tohto rozsudku.
          </>
        )],
      });
    } else {
      // rezim === 'ii'. Pri striedavke (b) má vlastnú formuláciu (kratšia, právne čistá).
      // Pri spoločnej (c) zachováme pôvodnú o "počas obdobia osobnej starostlivosti".
      if (cl3.formaStarostlivosti === 'b') {
        verdicts.push({
          label: ROMAN_PETIT[lastOuter],
          paragraphs: [(
            <>Počas trvania striedavej osobnej starostlivosti rodičov súd výživné neurčuje.</>
          )],
        });
      } else {
        verdicts.push({
          label: ROMAN_PETIT[lastOuter],
          paragraphs: [(
            <>Výživné na maloleté {pCount === 1 ? 'dieťa' : 'deti'} sa neurčuje.</>
          )],
        });
      }
    }

    // Výrok V — styk (len pri formaStarostlivosti='a').
    if (cl3.formaStarostlivosti === 'a') {
      lastOuter = 5;
      const nezverenyRole = cl3.zvereniePri_a === 'navrhovatel' ? 'odporca' : 'navrhovatel';
      const nezverenyPohlavie = nezverenyRole === 'navrhovatel' ? navrhovatelPohlavie : odporcaPohlavie;
      const nezverenyMeno = nezverenyRole === 'navrhovatel' ? menoNavrhovatela : menoOdporcu;

      if (cl3.styk === 'i') {
        // Multi-paragraph: úvodná veta + Ed-content rozdelený na odseky.
        const paragraphs = [];
        if (ed35Content && ed35Content.trim()) {
          // Prvý odsek prilepí úvodnú vetu so subjektom.
          const userParas = splitParagraphs(ed35Content);
          paragraphs.push(
            <>
              {oznacenieCap(nezverenyRole, nezverenyPohlavie)} {orPh(nezverenyMeno, 'meno rodiča')} je {rolaOpravneny(nezverenyRole, navrhovatelPohlavie)} stýkať sa s {detiSlovo(pCount, 'instr')} v nasledujúcom rozsahu: {userParas[0] && <span style={{ whiteSpace: 'pre-wrap' }}>{userParas[0]}</span>}
            </>
          );
          // Ďalšie odseky z Ed-content samostatne.
          userParas.slice(1).forEach(p =>
            paragraphs.push(<span style={{ whiteSpace: 'pre-wrap' }}>{p}</span>)
          );
        } else {
          paragraphs.push(
            <>
              {oznacenieCap(nezverenyRole, nezverenyPohlavie)} {orPh(nezverenyMeno, 'meno rodiča')} je {rolaOpravneny(nezverenyRole, navrhovatelPohlavie)} stýkať sa s {detiSlovo(pCount, 'instr')} v nasledujúcom rozsahu: <PetitPh>[doplňte rozsah styku v Čl. III bod 3.5]</PetitPh>.
            </>
          );
        }
        verdicts.push({ label: ROMAN_PETIT[lastOuter], paragraphs });
      } else { // styk === 'ii'
        const nezverenyKey = rolaRodicaKey(nezverenyRole, navrhovatelPohlavie);
        verdicts.push({
          label: ROMAN_PETIT[lastOuter],
          paragraphs: [(
            <>Styk {rolaRodicaPad(nezverenyKey, 'gen')} s {detiSlovo(pCount, 'instr')} sa neupravuje.</>
          )],
        });
      }
    }
  }

  // Posledný výrok — trovy konania (vždy, dynamický index).
  lastOuter += 1;
  verdicts.push({
    label: ROMAN_PETIT[lastOuter],
    paragraphs: [(
      <>O trovách konania súd rozhodne osobitným uznesením po právoplatnosti rozsudku vo veci samej.</>
    )],
  });

  return verdicts;
}

const KIDS_STORAGE_KEY = 'ziadostorozvod.kids-deti.v1';
const newKid = () => ({
  id: 'kid-' + Math.random().toString(36).slice(2, 9),
  meno: '',
  datumNarodenia: '',
  bytom: '',
});

// Meta state PaperDeti (gender + ďalšie ne-Ed nastavenia). Persist.jsx ukladá
// iba .ed contentEditable polia; pre React state s vlastnou logikou držíme
// vlastnú JSON serializáciu.
const META_STORAGE_KEY = 'ziadostorozvod.meta-deti.v1';

// ============================================================
// Čl. IV — Pomery rodičov a výdavky na maloleté deti.
// Default 9 + 9 položiek tabuliek (mesačné + ročné výdavky), per-kid sumy
// indexované cez kid.id. Status pracovnej situácie navrhovateľa pre sample.
// ============================================================
const CL4_STORAGE_KEY = 'ziadostorozvod.cl4-deti.v1';

const DEFAULT_VYDAVKY_MESACNE = {
  'mes-strava':       { nazov: 'Strava (potraviny a denné jedlo)', sumy: {} },
  'mes-byvanie':      { nazov: 'Bývanie (alikvotná časť — nájomné, energie, voda)', sumy: {} },
  'mes-hygiena':      { nazov: 'Hygienické potreby a drogéria', sumy: {} },
  'mes-doprava':      { nazov: 'Doprava (MHD, palivo na odvoz)', sumy: {} },
  'mes-skola':        { nazov: 'Školské obedy a školské potreby', sumy: {} },
  'mes-kruzky':       { nazov: 'Záujmové krúžky a športové aktivity', sumy: {} },
  'mes-tel':          { nazov: 'Telefón / internet / digitálne predplatné', sumy: {} },
  'mes-vreckove':     { nazov: 'Vreckové', sumy: {} },
  'mes-zdravie':      { nazov: 'Lieky, doplnky výživy, zdravotná starostlivosť', sumy: {} },
};
const DEFAULT_VYDAVKY_ROCNE = {
  'roc-letnyT':       { nazov: 'Letný tábor / dovolenka', sumy: {} },
  'roc-zimnyT':       { nazov: 'Zimná dovolenka / lyžiarsky výcvik', sumy: {} },
  'roc-oblec':        { nazov: 'Sezónne oblečenie a obuv', sumy: {} },
  'roc-darceky':      { nazov: 'Vianoce a narodeniny (darčeky)', sumy: {} },
  'roc-ucebnice':     { nazov: 'Učebnice a školské pomôcky na začiatok školského roka', sumy: {} },
  'roc-stomato':      { nazov: 'Stomatologická starostlivosť (preventívne aj ošetrenia)', sumy: {} },
  'roc-okuliare':     { nazov: 'Okuliare alebo ortodontický aparát', sumy: {} },
  'roc-elektronika':  { nazov: 'Elektronika pre školu (notebook, tablet)', sumy: {} },
  'roc-kurzy':        { nazov: 'Mimoškolské kurzy a doučovanie', sumy: {} },
};
const DEFAULT_CL4 = {
  vydavkyMesacne: DEFAULT_VYDAVKY_MESACNE,
  vydavkyRocne: DEFAULT_VYDAVKY_ROCNE,
  navrhPomerStatus: 'a',           // 'a' Zamestnanec | 'b' SZČO | 'c' Spoločník | 'd' Nezamestnaný | 'e' Dôchodca | 'f' Mat./rod. dovolenka | 'g' Iné
  navrhPomerInecaste: '',          // pre status 'g' vlastný popis
  uvadzamPomerOdporcu: false,      // checkbox 4.5
};

const STATUS_LABELS = {
  a: 'Zamestnanec',
  b: 'SZČO / živnostník',
  c: 'Spoločník alebo konateľ obchodnej spoločnosti',
  d: 'Nezamestnaný / evidovaný uchádzač o zamestnanie',
  e: 'Dôchodca',
  f: 'Materská alebo rodičovská dovolenka',
  g: 'Iné',
};
const statusLabel = (s) => STATUS_LABELS[s] || STATUS_LABELS.a;

// Výpočtová funkcia 4.3 — sumarizácia za jedno dieťa.
const spocitajVydavky = (vydavkyMesacne, vydavkyRocne, kidId) => {
  const sumMap = (mapa) => Object.values(mapa || {}).reduce((acc, p) => {
    const v = parseFloat(((p && p.sumy) || {})[kidId] || '0') || 0;
    return acc + v;
  }, 0);
  const mesacne = sumMap(vydavkyMesacne);
  const rocne = sumMap(vydavkyRocne);
  const rocnePrepocitane = rocne / 12;
  const priemernaSumaMesacne = mesacne + rocnePrepocitane;
  return { mesacne, rocne, rocnePrepocitane, priemernaSumaMesacne };
};

// ============================================================
// 4.4 sample texty — 3 vzory × m/f. Selektor sample44(status, pNav)
// vráti príslušný text podľa pracovného statusu navrhovateľa.
// Status 'g' → null (žiadny vzor, len Ed block).
// ============================================================
const SAMPLE_44_VZOR1_M = 'V súčasnosti som zamestnaný v spoločnosti [názov a sídlo zamestnávateľa] na pracovnej pozícii [pozícia] na základe pracovnej zmluvy uzatvorenej dňa [dátum]. Môj priemerný čistý mesačný príjem za posledných 12 mesiacov predstavuje [suma] eur. Okrem hlavného pracovného pomeru poberám [iné príjmy / žiadne iné príjmy]. Vlastním nehnuteľnosť [bytovú jednotku / rodinný dom] na adrese [adresa], motorové vozidlo [značka, rok], a finančné prostriedky vo výške [suma] eur. Mám tieto záväzky: [hypotekárny úver / spotrebný úver / žiadne]. Okrem maloletých detí, ktoré sú predmetom tohto konania, mám [aj iné vyživovacie povinnosti / žiadne iné vyživovacie povinnosti].';

const SAMPLE_44_VZOR1_Z = 'V súčasnosti som zamestnaná v spoločnosti [názov a sídlo zamestnávateľa] na pracovnej pozícii [pozícia] na základe pracovnej zmluvy uzatvorenej dňa [dátum]. Môj priemerný čistý mesačný príjem za posledných 12 mesiacov predstavuje [suma] eur. Okrem hlavného pracovného pomeru poberám [iné príjmy / žiadne iné príjmy]. Vlastním nehnuteľnosť [bytovú jednotku / rodinný dom] na adrese [adresa], motorové vozidlo [značka, rok], a finančné prostriedky vo výške [suma] eur. Mám tieto záväzky: [hypotekárny úver / spotrebný úver / žiadne]. Okrem maloletých detí, ktoré sú predmetom tohto konania, mám [aj iné vyživovacie povinnosti / žiadne iné vyživovacie povinnosti].';

const SAMPLE_44_VZOR2_M = 'V súčasnosti som samostatne zárobkovo činnou osobou — vykonávam podnikateľskú činnosť na základe živnostenského oprávnenia, IČO [IČO], v predmete podnikania [predmet podnikania]. Môj čistý zisk po zdanení podľa daňového priznania za rok [rok] predstavoval [suma] eur, čo zodpovedá priemernému mesačnému čistému príjmu [suma] eur. Okrem podnikateľskej činnosti [poberám / nepoberám] iné príjmy. Vlastním nehnuteľnosť [adresa], motorové vozidlo [značka], finančné prostriedky vo výške [suma] eur. Mám tieto záväzky: [úver / leasing / žiadne]. Okrem maloletých detí, ktoré sú predmetom tohto konania, mám [aj iné vyživovacie povinnosti / žiadne iné vyživovacie povinnosti].';

const SAMPLE_44_VZOR2_Z = 'V súčasnosti som samostatne zárobkovo činnou osobou — vykonávam podnikateľskú činnosť na základe živnostenského oprávnenia, IČO [IČO], v predmete podnikania [predmet podnikania]. Môj čistý zisk po zdanení podľa daňového priznania za rok [rok] predstavoval [suma] eur, čo zodpovedá priemernému mesačnému čistému príjmu [suma] eur. Okrem podnikateľskej činnosti [poberám / nepoberám] iné príjmy. Vlastním nehnuteľnosť [adresa], motorové vozidlo [značka], finančné prostriedky vo výške [suma] eur. Mám tieto záväzky: [úver / leasing / žiadne]. Okrem maloletých detí, ktoré sú predmetom tohto konania, mám [aj iné vyživovacie povinnosti / žiadne iné vyživovacie povinnosti].';

const SAMPLE_44_VZOR3_M = 'V súčasnosti som nezamestnaný. [Som / nie som] evidovaný ako uchádzač o zamestnanie na Úrade práce, sociálnych vecí a rodiny [príslušný úrad] od [dátum evidencie]. [Poberám dávku v nezamestnanosti vo výške [suma] eur mesačne / Nepoberám dávku v nezamestnanosti.] Okrem toho [poberám / nepoberám] [pomoc v hmotnej núdzi / dávku sociálneho poistenia / iné dávky] vo výške [suma] eur mesačne. Vlastním nehnuteľnosť [adresa / žiadnu], motorové vozidlo [značka / žiadne], finančné prostriedky vo výške [suma] eur. Mám tieto záväzky: [úver / žiadne]. Okrem maloletých detí, ktoré sú predmetom tohto konania, mám [aj iné vyživovacie povinnosti / žiadne]. Aktívne hľadám zamestnanie.';

const SAMPLE_44_VZOR3_Z = 'V súčasnosti som nezamestnaná. [Som / nie som] evidovaná ako uchádzačka o zamestnanie na Úrade práce, sociálnych vecí a rodiny [príslušný úrad] od [dátum evidencie]. [Poberám dávku v nezamestnanosti vo výške [suma] eur mesačne / Nepoberám dávku v nezamestnanosti.] Okrem toho [poberám / nepoberám] [pomoc v hmotnej núdzi / dávku sociálneho poistenia / iné dávky] vo výške [suma] eur mesačne. Vlastním nehnuteľnosť [adresa / žiadnu], motorové vozidlo [značka / žiadne], finančné prostriedky vo výške [suma] eur. Mám tieto záväzky: [úver / žiadne]. Okrem maloletých detí, ktoré sú predmetom tohto konania, mám [aj iné vyživovacie povinnosti / žiadne]. Aktívne hľadám zamestnanie.';

const sample44 = (status, pNav) => {
  const z = pNav === 'zena';
  if (status === 'b') return z ? SAMPLE_44_VZOR2_Z : SAMPLE_44_VZOR2_M;
  if (status === 'd') return z ? SAMPLE_44_VZOR3_Z : SAMPLE_44_VZOR3_M;
  if (status === 'g') return null;
  // 'a', 'c', 'e', 'f' → vzor 1 (pravidelný príjem)
  return z ? SAMPLE_44_VZOR1_Z : SAMPLE_44_VZOR1_M;
};

// Čl. III state — radio/select/checkbox voľby pre formu starostlivosti,
// zverenie, výživné a styk. Mapy výživného sú indexované cez kid.id
// (synchronizované so zoznamom detí).
const CL3_STORAGE_KEY = 'ziadostorozvod.cl3-deti.v1';
// Splatnosť výživného sa v praxi určuje fixne na 15. deň v mesiaci vopred —
// neukladáme to ako voľbu (FÁZA B simplification).
const DEFAULT_VYZIVNE_ROW = { suma: '' };
const DEFAULT_CL3 = {
  formaStarostlivosti: 'a',           // 'a' (jeden rodič) | 'b' (striedavá) | 'c' (spoločná)
  zvereniePri_a: 'navrhovatel',       // 'navrhovatel' | 'odporca'
  typStriedania: '1tyz',              // '1tyz' (predvyplnený vzor) | 'vlastne' (4 Ed bloky)
  rezimVyzivnehoPri_b: 'i',           // 'i' (od druhého) | 'ii' (nežiadame)
  rezimVyzivnehoPri_c: 'i',           // 'i' | 'ii'
  vyzivne: {},                        // { [kidId]: { suma } }
  styk: 'i',                          // 'i' (súdom) | 'ii' (mimosúdne)
  // Zastupovanie a správa majetku — § 28 ods. 1, § 31 ods. 1 ZoR.
  // Default sa odvodí z formy/zverenia/pohlavia, ale userTouchedZastupovanie
  // uzamkne ďalšie auto-zmeny po prvom explicit prepnutí radio-u.
  zastupovanie: 'obaja',              // 'obaja' | 'matka' | 'otec'
  userTouchedZastupovanie: false,
};

const PaperDeti = ({ doctype, navrhovatel, setNavrhovatel, odporca, setOdporca, setActiveArticle, setActiveTipKey, onTipClick, activeTipKey }) => {
  const [menoNavrhovatela, setMenoNavrhovatela] = React.useState('');
  const [menoOdporcu, setMenoOdporcu] = React.useState('');
  const [rodnePriezvisko, setRodnePriezvisko] = React.useState('');
  const [dalsieDokazy, setDalsieDokazy] = React.useState('');
  // Hydrácia kids zo storage pri prvom rendere — vždy aspoň jedno dieťa.
  const [kids, setKids] = React.useState(() => {
    try {
      const raw = localStorage.getItem(KIDS_STORAGE_KEY);
      if (raw) {
        const parsed = JSON.parse(raw);
        if (Array.isArray(parsed) && parsed.length > 0) {
          return parsed.map(k => (k && typeof k === 'object' && k.id)
            ? { id: k.id, meno: k.meno || '', datumNarodenia: k.datumNarodenia || '', bytom: k.bytom || '' }
            : newKid());
        }
      }
    } catch (e) {}
    return [newKid()];
  });
  React.useEffect(() => {
    try { localStorage.setItem(KIDS_STORAGE_KEY, JSON.stringify(kids)); } catch (e) {}
  }, [kids]);
  const addKid = () => setKids(prev => [...prev, newKid()]);
  const removeKid = (id) => setKids(prev => prev.length > 1 ? prev.filter(k => k.id !== id) : prev);
  const updateKid = (id, field, value) => setKids(prev => prev.map(k => k.id === id ? { ...k, [field]: value } : k));
  // Derivovaný pohľad: dieťa sa považuje za "vyplnené" ak má aspoň jeden
  // non-empty údaj. Prázdne defaultné dieťa (zo state inicializácie alebo
  // čerstvo pridané, ale needitované) sa do textu Čl. I 1.1 neprenesie.
  const filledKids = kids.filter(k =>
    k.meno.trim() !== '' || k.datumNarodenia.trim() !== '' || k.bytom.trim() !== ''
  );

  // Pohlavie navrhovateľa (jediný vstup; pohlavie odporcu = opak, § 1 ZoR).
  // Hydrácia + perzistencia v META_STORAGE_KEY; userTouchedGender uzamkne
  // autodetekciu z priezviska potom, čo používateľ explicitne prepol radio.
  const [navrhovatelPohlavie, setNavrhovatelPohlavieRaw] = React.useState(() => {
    try {
      const raw = localStorage.getItem(META_STORAGE_KEY);
      if (raw) {
        const m = JSON.parse(raw);
        if (m && (m.navrhovatelPohlavie === 'muz' || m.navrhovatelPohlavie === 'zena')) {
          return m.navrhovatelPohlavie;
        }
      }
    } catch (e) {}
    return 'muz';
  });
  const [userTouchedGender, setUserTouchedGender] = React.useState(() => {
    try {
      const raw = localStorage.getItem(META_STORAGE_KEY);
      if (raw) {
        const m = JSON.parse(raw);
        return !!(m && m.userTouchedGender);
      }
    } catch (e) {}
    return false;
  });
  React.useEffect(() => {
    try {
      localStorage.setItem(META_STORAGE_KEY, JSON.stringify({ navrhovatelPohlavie, userTouchedGender }));
    } catch (e) {}
  }, [navrhovatelPohlavie, userTouchedGender]);

  // User-facing setter (UI radio) — uzamkne autodetekciu.
  const setNavrhovatelPohlavie = (g) => {
    setNavrhovatelPohlavieRaw(g);
    setUserTouchedGender(true);
  };

  // Autodetekcia z priezviska — beží iba kým user nestlačí radio. Po explicit
  // prepnutí ostáva flag userTouchedGender = true, autodetekcia ďalej nebeží.
  React.useEffect(() => {
    if (userTouchedGender) return;
    const detected = detectGenderFromName(menoNavrhovatela);
    if (detected && detected !== navrhovatelPohlavie) {
      setNavrhovatelPohlavieRaw(detected);
    }
  }, [menoNavrhovatela, userTouchedGender]);

  // Pohlavie odporcu = opak navrhovateľa. Manželstvo = zväzok muža a ženy
  // (§ 1 ods. 1 ZoR), takže pri zmene pohlavia navrhovateľa sa odporca
  // automaticky prepne. Žiadny samostatný vstup pre odporcu.
  const odporcaPohlavie = navrhovatelPohlavie === 'muz' ? 'zena' : 'muz';

  // Pre-rendered sample texty pre Čl. II — počítané pri každom rendere
  // (jednorazové string konkatenácie, lacné).
  const sample1 = sampleText1(navrhovatelPohlavie, odporcaPohlavie);
  const sample2 = sampleText2(navrhovatelPohlavie, odporcaPohlavie);
  const sample3 = sampleText3(navrhovatelPohlavie, odporcaPohlavie);

  // ----------------------------------------------------------------
  // Čl. III — refs pre Ed bloky, state radio/select/checkbox volieb,
  // toggles pre sample panely, helpers pre tabuľky výživného.
  // ----------------------------------------------------------------
  const cl3_311_Ref = React.useRef(null);
  const cl3_312_Ref = React.useRef(null);
  const cl3_32_Ref = React.useRef(null);
  const cl3_33c_Ref = React.useRef(null);   // opis fungovania spoločnej starostlivosti
  // 3.3(b) striedavá — JEDEN Ed block. Sample obsah (4 sekcie) sa generuje
  // dynamicky a vkladá cez "Použiť tento text" (rovnaký pattern ako 2.1–2.4).
  const cl3_33b_Ref = React.useRef(null);
  // Auto-clear pri prepnutí radio typStriedania — predošlú hodnotu držíme
  // v useRef. POZOR: ref sa inicializuje na `undefined` sentinel, NIE na
  // `cl3.typStriedania` — `cl3` je definované cez useState NIŽŠIE v komponente
  // (TDZ by inak hodil ReferenceError a celý komponent by sa zrútil).
  // Prvý beh useEffectu sentinel vymení za aktuálnu hodnotu a skipne čistenie.
  const cl3_33b_typPrev = React.useRef();
  const cl3_35_Ref = React.useRef(null);    // opis styku (3.5(i))
  const [showSample311, setShowSample311] = React.useState(false);
  const [showSample312, setShowSample312] = React.useState(false);
  const [showSample32, setShowSample32] = React.useState(false);
  const [showSample33b, setShowSample33b] = React.useState(false);
  const [showSample33c, setShowSample33c] = React.useState(false);
  const [showSample35, setShowSample35] = React.useState(false);

  // Obsah Ed blokov 3.3(b) striedavky-vlastné a 3.5 styk — uncontrolled
  // .ed[contentEditable] elementy ich nedržia v React state (Persist.jsx
  // ich ukladá na input event). Pre petit potrebujeme ich obsah, takže
  // držíme zrkadlový state cez document-level input listener (matching
  // podľa unikátneho data-placeholder atribútu).
  const [ed33bContent, setEd33bContent] = React.useState('');
  const [ed33cContent, setEd33cContent] = React.useState('');
  const [ed35Content, setEd35Content] = React.useState('');
  const [ed4DokazyContent, setEd4DokazyContent] = React.useState('');
  React.useEffect(() => {
    const PH_33B = "Sem vložte text striedavej osobnej starostlivosti — kliknite na 'Zobraziť vzor textu' a 'Použiť tento text'.";
    const PH_33C = "Sem vložte opis dohodnutého fungovania spoločnej osobnej starostlivosti — kliknite na 'Zobraziť vzor textu' a 'Použiť tento text'.";
    const PH_35 = 'Opis navrhovaného styku (3.5) — váš text alebo použite vzor vyššie...';
    const PH_4DOKAZY = 'Sem napíšte zoznam dôkazov, každý dôkaz na samostatný riadok. Napríklad: potvrdenie o priemernom čistom mesačnom zárobku od zamestnávateľa, daňové priznanie za minulý rok, výpis z katastra nehnuteľností, potvrdenie z úradu práce o evidencii a výške dávky v nezamestnanosti.';
    const sync = (el) => {
      if (!el || !el.dataset) return;
      const ph = el.dataset.placeholder;
      if (ph === PH_33B) setEd33bContent(el.textContent || '');
      else if (ph === PH_33C) setEd33cContent(el.textContent || '');
      else if (ph === PH_35) setEd35Content(el.textContent || '');
      else if (ph === PH_4DOKAZY) setEd4DokazyContent(el.textContent || '');
    };
    const handler = (e) => sync(e.target);
    document.addEventListener('input', handler, true);
    // Initial sync — po Persist.jsx hydrácii (~150ms timeout interne)
    // prejdeme všetky .ed elementy a syncneme ich obsah do state-u.
    const tInit = setTimeout(() => {
      document.querySelectorAll('.ed[data-placeholder]').forEach(sync);
    }, 300);
    return () => {
      document.removeEventListener('input', handler, true);
      clearTimeout(tInit);
    };
  }, []);

  // Hydrácia + perzistencia cl3 state z vlastného localStorage kľúča
  // (Persist.jsx ukladá iba contentEditable; non-Ed state má vlastnú JSON
  // serializáciu, analogicky k META_STORAGE_KEY a KIDS_STORAGE_KEY).
  const [cl3, setCl3] = React.useState(() => {
    try {
      const raw = localStorage.getItem(CL3_STORAGE_KEY);
      if (raw) {
        const parsed = JSON.parse(raw);
        if (parsed && typeof parsed === 'object') {
          return { ...DEFAULT_CL3, ...parsed };
        }
      }
    } catch (e) {}
    return DEFAULT_CL3;
  });
  React.useEffect(() => {
    try { localStorage.setItem(CL3_STORAGE_KEY, JSON.stringify(cl3)); } catch (e) {}
  }, [cl3]);

  // Pri odstránení dieťaťa z parties-table sa zahodia jeho záznamy výživného.
  React.useEffect(() => {
    const validIds = new Set(kids.map(k => k.id));
    setCl3(prev => {
      const filterMap = (m) => Object.fromEntries(
        Object.entries(m || {}).filter(([k]) => validIds.has(k))
      );
      const nextVyzivne = filterMap(prev.vyzivne);
      // Pri rovnosti nemeníme referenciu — predíde infinite loopu.
      if (Object.keys(nextVyzivne).length === Object.keys(prev.vyzivne || {}).length) return prev;
      return { ...prev, vyzivne: nextVyzivne };
    });
  }, [kids]);

  // Helpers pre výživné mapu (suma per kid).
  const getVyzivne = (kidId) => ({ ...DEFAULT_VYZIVNE_ROW, ...((cl3.vyzivne || {})[kidId] || {}) });
  const setVyzivneSuma = (kidId, value) => {
    setCl3(prev => ({
      ...prev,
      vyzivne: {
        ...(prev.vyzivne || {}),
        [kidId]: { ...DEFAULT_VYZIVNE_ROW, ...((prev.vyzivne || {})[kidId] || {}), suma: value },
      },
    }));
  };
  const setCl3Field = (field, value) => setCl3(prev => ({ ...prev, [field]: value }));

  // Setter pre zastupovanie — uzamkne flag userTouchedZastupovanie, takže
  // ďalšie zmeny formy/zverenia/pohlavia už nepreklopia voľbu späť.
  const setZastupovanie = (val) =>
    setCl3(prev => ({ ...prev, zastupovanie: val, userTouchedZastupovanie: true }));

  // Default zastupovania sa updatuje pri zmene formaStarostlivosti / zverenia /
  // navrhovatelPohlavie — ALE iba kým userTouchedZastupovanie === false.
  React.useEffect(() => {
    if (cl3.userTouchedZastupovanie) return;
    const next = computeZastupovanieDefault(
      cl3.formaStarostlivosti,
      cl3.zvereniePri_a,
      navrhovatelPohlavie
    );
    if (cl3.zastupovanie !== next) {
      setCl3(prev => ({ ...prev, zastupovanie: next }));
    }
  }, [cl3.formaStarostlivosti, cl3.zvereniePri_a, navrhovatelPohlavie, cl3.userTouchedZastupovanie]);

  // ----------------------------------------------------------------
  // Čl. IV state — pomery rodičov a výdavky.
  // ----------------------------------------------------------------
  const [cl4, setCl4] = React.useState(() => {
    try {
      const raw = localStorage.getItem(CL4_STORAGE_KEY);
      if (raw) {
        const parsed = JSON.parse(raw);
        if (parsed && typeof parsed === 'object') {
          return {
            ...DEFAULT_CL4,
            ...parsed,
            // Hlboký spread máp výdavkov — predchádza strate pridaných položiek po DEFAULT spread.
            vydavkyMesacne: (parsed.vydavkyMesacne && Object.keys(parsed.vydavkyMesacne).length > 0)
              ? parsed.vydavkyMesacne : DEFAULT_VYDAVKY_MESACNE,
            vydavkyRocne: (parsed.vydavkyRocne && Object.keys(parsed.vydavkyRocne).length > 0)
              ? parsed.vydavkyRocne : DEFAULT_VYDAVKY_ROCNE,
          };
        }
      }
    } catch (e) {}
    return DEFAULT_CL4;
  });
  React.useEffect(() => {
    try { localStorage.setItem(CL4_STORAGE_KEY, JSON.stringify(cl4)); } catch (e) {}
  }, [cl4]);

  // Pri odstránení dieťaťa z parties-table cleanup .sumy[zaniknutyKidId]
  // vo všetkých položkách oboch máp (mesačné aj ročné).
  React.useEffect(() => {
    const validIds = new Set(kids.map(k => k.id));
    setCl4(prev => {
      let changed = false;
      const cleanMap = (mapa) => {
        const out = {};
        Object.entries(mapa || {}).forEach(([pid, polozka]) => {
          const oldSumy = polozka.sumy || {};
          const newSumy = Object.fromEntries(
            Object.entries(oldSumy).filter(([kid]) => validIds.has(kid))
          );
          if (Object.keys(newSumy).length !== Object.keys(oldSumy).length) changed = true;
          out[pid] = { ...polozka, sumy: newSumy };
        });
        return out;
      };
      const nextMes = cleanMap(prev.vydavkyMesacne);
      const nextRoc = cleanMap(prev.vydavkyRocne);
      if (!changed) return prev;
      return { ...prev, vydavkyMesacne: nextMes, vydavkyRocne: nextRoc };
    });
  }, [kids]);

  // Helpers pre Čl. IV.
  const setCl4Field = (field, value) => setCl4(prev => ({ ...prev, [field]: value }));
  const setVydavokSuma = (typ, polozkaId, kidId, sumaStr) => {
    const mapKey = typ === 'mesacne' ? 'vydavkyMesacne' : 'vydavkyRocne';
    setCl4(prev => ({
      ...prev,
      [mapKey]: {
        ...(prev[mapKey] || {}),
        [polozkaId]: {
          ...((prev[mapKey] || {})[polozkaId] || { nazov: '', sumy: {} }),
          sumy: {
            ...(((prev[mapKey] || {})[polozkaId] || {}).sumy || {}),
            [kidId]: sumaStr,
          },
        },
      },
    }));
  };
  const setVydavokNazov = (typ, polozkaId, nazov) => {
    const mapKey = typ === 'mesacne' ? 'vydavkyMesacne' : 'vydavkyRocne';
    setCl4(prev => ({
      ...prev,
      [mapKey]: {
        ...(prev[mapKey] || {}),
        [polozkaId]: {
          ...((prev[mapKey] || {})[polozkaId] || { sumy: {} }),
          nazov,
        },
      },
    }));
  };
  const addPolozka = (typ) => {
    const mapKey = typ === 'mesacne' ? 'vydavkyMesacne' : 'vydavkyRocne';
    const prefix = typ === 'mesacne' ? 'mes-custom-' : 'roc-custom-';
    const id = prefix + Math.random().toString(36).slice(2, 8);
    setCl4(prev => ({
      ...prev,
      [mapKey]: { ...(prev[mapKey] || {}), [id]: { nazov: '', sumy: {} } },
    }));
  };
  const removePolozka = (typ, polozkaId) => {
    const mapKey = typ === 'mesacne' ? 'vydavkyMesacne' : 'vydavkyRocne';
    setCl4(prev => {
      const next = { ...(prev[mapKey] || {}) };
      delete next[polozkaId];
      return { ...prev, [mapKey]: next };
    });
  };

  // Čl. IV refs + showSample + Ed-content listener pre 4.4 a 4.5.
  const cl4_44_Ref = React.useRef(null);
  const cl4_45_Ref = React.useRef(null);
  const cl4_dokazy_Ref = React.useRef(null);
  const [showSample44, setShowSample44] = React.useState(false);

  // Auto-clear Ed bloku 3.3(b) pri prepnutí typStriedania (1tyz ↔ vlastne).
  // Prvý beh: typPrev.current === undefined → zapíšeme aktuálnu hodnotu
  // a skipneme (Persist medzitým obnoví obsah, nesmieme ho prepísať).
  // Reálne prepnutie: typPrev drží starú, cl3.typStriedania má novú →
  // mismatch → vyčistíme Ed a aktualizujeme typPrev.
  React.useEffect(() => {
    if (cl3_33b_typPrev.current === undefined) {
      cl3_33b_typPrev.current = cl3.typStriedania;
      return;
    }
    if (cl3_33b_typPrev.current === cl3.typStriedania) return;
    cl3_33b_typPrev.current = cl3.typStriedania;
    if (cl3_33b_Ref.current) {
      cl3_33b_Ref.current.textContent = '';
      cl3_33b_Ref.current.dispatchEvent(new Event('input', { bubbles: true }));
    }
  }, [cl3.typStriedania]);

  const [q1, setQ1] = React.useState(null); // null | 'ano' | 'nie'
  const [q2, setQ2] = React.useState(null); // null | 'ano' | 'nie'
  const [q3, setQ3] = React.useState(null); // null | 'ano' | 'nie'
  const [sudQuery, setSudQuery] = React.useState('');
  const [sudVybrany, setSudVybrany] = React.useState(null);
  const [sudDropdown, setSudDropdown] = React.useState(false);
  // Údaje o sobáši — zdieľané medzi bodom 1.1 a petitom v Čl. III.
  const [datumSobasa, setDatumSobasa] = React.useState('');
  const [miestoSobasa, setMiestoSobasa] = React.useState('');
  const [maticnyUrad, setMaticnyUrad] = React.useState('');
  const [zvazok, setZvazok] = React.useState('');
  const [rocnik, setRocnik] = React.useState('');
  const [strana, setStrana] = React.useState('');
  const [poradoveCislo, setPoradoveCislo] = React.useState('');
  const kategoria1Ref = React.useRef(null);
  const kategoria2Ref = React.useRef(null);
  const kategoria3Ref = React.useRef(null);
  const kategoria4Ref = React.useRef(null);
  const [showSample1, setShowSample1] = React.useState(false);
  const [showSample2, setShowSample2] = React.useState(false);
  const [showSample3, setShowSample3] = React.useState(false);
  const [showSample4, setShowSample4] = React.useState(false);

  const fillSampleText = (refName, text) => {
    const refMap = {
      kategoria1Ref, kategoria2Ref, kategoria3Ref, kategoria4Ref,
      cl3_311_Ref, cl3_312_Ref, cl3_32_Ref, cl3_33b_Ref, cl3_33c_Ref, cl3_35_Ref,
      cl4_44_Ref, cl4_45_Ref, cl4_dokazy_Ref,
    };
    const ref = refMap[refName];
    if (ref?.current) {
      ref.current.textContent = text;
      ref.current.dispatchEvent(new Event('input', { bubbles: true }));
    }
  };
  const sudFiltered = sudQuery.length > 0
    ? window.SUDY.filter(s => removeDiacritics(s.nazov).includes(removeDiacritics(sudQuery)))
    : [];

  // Pre prehľadnosť — props pre <SudAutocomplete {...sudProps} /> obalíme do jedného objektu.
  const sudProps = { sudQuery, setSudQuery, sudVybrany, setSudVybrany, sudDropdown, setSudDropdown, sudFiltered };

  // TipBtn je definovaný na module-leveli (viď vyššie). Tu len obalíme paper
  // do TipContext.Provider-a, aby všetky <TipBtn> dostali aktuálny activeTipKey
  // + onTipClick. Memoize-ujeme value, aby sa Provider re-rendery zbytočne
  // netriggerovali pri identických hodnotách.
  const tipCtx = React.useMemo(() => ({ activeTipKey, onTipClick }), [activeTipKey, onTipClick]);

  // Scroll-spy: activeArticle sleduje článok v čítacej zóne viewport-u;
  // activeTipKey sleduje top-most TipBtn v užšej zóne (20–40% viewport-u).
  // Pozorujeme PRIAMO tlačidlá s [data-tip-key] (všetky tipy, nielen tie
  // v p.has-tip) — po refaktoringu má každé tlačidlo position: absolute
  // s top podľa offsetTop rodiča, takže jeho pozícia v viewport-e verne
  // odráža miesto kde tip patrí v dokumente.
  // Deps obsahujú q1/q2/q3 — keď user prepne wizard, conditional q3 tip
  // mountne a treba ho re-observovať.
  React.useEffect(() => {
    const articles = document.querySelectorAll('.paper .article[id]');
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) setActiveArticle(e.target.id); });
    }, { rootMargin: '-35% 0px -55% 0px' });
    articles.forEach(a => obs.observe(a));

    const tipButtons = document.querySelectorAll('.paper [data-tip-key]');
    let currentKey = null;
    const pObs = new IntersectionObserver((entries) => {
      const hits = entries
        .filter(e => e.isIntersecting)
        .map(e => ({ key: e.target.dataset.tipKey, top: e.boundingClientRect.top }))
        .sort((a, b) => a.top - b.top);
      if (hits.length && hits[0].key !== currentKey) {
        currentKey = hits[0].key;
        setActiveTipKey && setActiveTipKey(currentKey);
      }
    }, { rootMargin: '-20% 0px -60% 0px' });
    tipButtons.forEach(btn => pObs.observe(btn));

    return () => { obs.disconnect(); pObs.disconnect(); };
  }, [doctype, q1, q2, q3]);

  return (
    <TipContext.Provider value={tipCtx}>
    <div className="paper-stage">
      <article className="paper" aria-label="Návrh na rozvod — editovateľný dokument">

        {/* Hlavička dokumentu — ľavý stĺpec prázdny (miesto pre podpis advokáta), pravý: adresát súdu + dátum */}
        <header className="paper-header" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 48 }}>
          <div className="paper-header-left"></div>
          <div className="paper-header-right">
            <div style={{ borderBottom: '1px solid var(--ink)', width: '100%', marginBottom: 16 }}></div>
            <div className="no-copy no-print" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <SudAutocomplete {...sudProps} />
              <TipBtn pointKey="header-sud" />
            </div>
            {sudVybrany && (
              <>
                {/* Zarovnanie pod text v inpute — input má padding-left 8px + border 1px,
                    takže adresa zarovnaná na 9px. */}
                <div className="no-print" style={{ fontSize: '0.95em', fontStyle: 'italic', paddingLeft: 9, marginTop: 2 }}>{sudVybrany.ulica}</div>
                <div className="no-print" style={{ fontSize: '0.95em', fontStyle: 'italic', paddingLeft: 9 }}>{sudVybrany.mesto}</div>
              </>
            )}
            <div className="ed-select-print-block">{sudVybrany ? sudVybrany.nazov : ''}</div>
            <div className="ed-select-print-block">{sudVybrany ? sudVybrany.ulica : ''}</div>
            <div className="ed-select-print-block">{sudVybrany ? sudVybrany.mesto : ''}</div>
            <div style={{ borderBottom: '1px solid var(--ink)', width: '100%', margin: '16px 0 8px' }}></div>
            <p style={{ margin: 0 }}>
              V{' '}
              <Ed defaultValue="" placeholder="miesto" />
              , dňa{' '}
              <Ed defaultValue="" placeholder="DD. MM. RRRR" />
            </p>
          </div>
        </header>

        {/* Účastníci konania */}
        <div className="parties-table" style={{ display: 'flex', flexDirection: 'column', gap: 20, padding: '24px 0', borderTop: '1px solid var(--rule)', borderBottom: '1px solid var(--rule)', margin: '64px 0 32px' }}>
          {/* Voľba pohlavia navrhovateľa — UI control mimo PDF/Word.
              Pohlavie odporcu sa odvodí automaticky (§ 1 ZoR). */}
          <div className="no-copy no-print" style={{ display: 'flex', gap: 16, alignItems: 'center', fontSize: '0.85em', color: 'var(--ink-3)' }}>
            <span style={{ fontFamily: 'var(--mono)', letterSpacing: '0.04em', textTransform: 'uppercase' }}>Navrhovateľ je:</span>
            <label style={{ display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer' }}>
              <input
                type="radio"
                name="navrhovatel-pohlavie"
                value="muz"
                checked={navrhovatelPohlavie === 'muz'}
                onChange={() => setNavrhovatelPohlavie('muz')}
              />
              <span>muž</span>
            </label>
            <label style={{ display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer' }}>
              <input
                type="radio"
                name="navrhovatel-pohlavie"
                value="zena"
                checked={navrhovatelPohlavie === 'zena'}
                onChange={() => setNavrhovatelPohlavie('zena')}
              />
              <span>žena</span>
            </label>
          </div>

          <div style={{ marginBottom: 20 }}>
            <div style={{ fontWeight: 'bold', marginBottom: 8 }}>{oznacenieCap('navrhovatel', navrhovatelPohlavie)}:</div>
            <div className="party-grid">
              <span>Meno a priezvisko:</span>
              <div style={{ display: 'flex', gap: 8, alignItems: 'baseline' }}>
                <SyncedEd value={menoNavrhovatela} onChange={setMenoNavrhovatela} placeholder="meno a priezvisko" />
                <span style={{ whiteSpace: 'nowrap' }}>rod.:</span>
                <SyncedEd value={rodnePriezvisko} onChange={setRodnePriezvisko} placeholder="rodné priezvisko" />
              </div>
              <span>Dátum narodenia:</span> <Ed defaultValue="" placeholder="DD. MM. RRRR" />
              <span>Trvalý pobyt:</span> <Ed defaultValue="" placeholder="ulica, PSČ mesto" />
              <span>Občianstvo:</span> <Ed defaultValue="" placeholder="uveďte občianstvo" />
            </div>
            <div style={{ fontStyle: 'italic', marginTop: 6 }}>(ďalej len „{oznacenie('navrhovatel', navrhovatelPohlavie)}")</div>
          </div>

          <div>
            <div style={{ fontWeight: 'bold', marginBottom: 8 }}>{oznacenieCap('odporca', odporcaPohlavie)}:</div>
            <div className="party-grid">
              <span>Meno a priezvisko:</span>
              <div style={{ display: 'flex', gap: 8, alignItems: 'baseline' }}>
                <SyncedEd value={menoOdporcu} onChange={setMenoOdporcu} placeholder="meno a priezvisko" />
                <span style={{ whiteSpace: 'nowrap' }}>rod.:</span>
                <Ed defaultValue="" placeholder="rodné priezvisko" />
              </div>
              <span>Dátum narodenia:</span> <Ed defaultValue="" placeholder="DD. MM. RRRR" />
              <span>Trvalý pobyt:</span> <Ed defaultValue="" placeholder="ulica, PSČ mesto" />
              <span>Občianstvo:</span> <Ed defaultValue="" placeholder="uveďte občianstvo" />
            </div>
            <div style={{ fontStyle: 'italic', marginTop: 6 }}>(ďalej len „{oznacenie('odporca', odporcaPohlavie)}")</div>
          </div>
        </div>

        {/* Maloleté deti — placeholder sekcia. V tomto kroku iba state + UI;
            žiadna synchronizácia s textom Čl. I ani petitom (pridá sa neskôr).
            Persist.jsx preskakuje tieto polia (noPersist) — celý array kids
            serializujeme do KIDS_STORAGE_KEY ako JSON. */}
        {/* TipBtn pre kids-section — bez position:relative na wrapperi, aby
            TipBtn pozicoval voči .paper (jediný pozicovaný predok). useLayoutEffect
            v TipBtn počíta top cez offsetTop chain anchor → .paper, takže tip
            sa vertikálne zarovná s kids-table a horizontálne ostáva v pravom
            gutteri papiera (right: 18px voči .paper). */}
        <div className="kids-table has-tip" style={{ display: 'flex', flexDirection: 'column', gap: 24, padding: '0 0 24px 0', borderBottom: '1px solid var(--rule)', margin: '0 0 32px' }}>
          <TipBtn pointKey="kids-section" />
          {kids.map((kid) => (
            <div key={kid.id} className="kid-row party-grid" style={{ position: 'relative', alignItems: 'baseline' }}>
              <span style={{ fontWeight: 'bold' }}>za účasti mal. dieťaťa:</span>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                <span style={{ fontWeight: 'bold' }}>
                  <SyncedEd
                    value={kid.meno}
                    onChange={(v) => updateKid(kid.id, 'meno', v)}
                    placeholder="meno a priezvisko"
                    lg
                    noPersist
                  />
                </span>
                <div style={{ display: 'flex', gap: 6, alignItems: 'baseline' }}>
                  <span style={{ whiteSpace: 'nowrap' }}>nar.:</span>
                  <SyncedEd
                    value={kid.datumNarodenia}
                    onChange={(v) => updateKid(kid.id, 'datumNarodenia', v)}
                    placeholder="DD. MM. RRRR"
                    noPersist
                  />
                </div>
                <div style={{ display: 'flex', gap: 6, alignItems: 'baseline' }}>
                  <span style={{ whiteSpace: 'nowrap' }}>bytom:</span>
                  <SyncedEd
                    value={kid.bytom}
                    onChange={(v) => updateKid(kid.id, 'bytom', v)}
                    placeholder="ulica, PSČ obec"
                    noPersist
                  />
                </div>
              </div>
              {kids.length > 1 && (
                <button
                  type="button"
                  className="kid-remove no-print no-copy"
                  onClick={() => removeKid(kid.id)}
                  aria-label="Odstrániť dieťa"
                  title="Odstrániť dieťa"
                  style={{
                    position: 'absolute',
                    right: 0,
                    top: 0,
                    background: 'transparent',
                    border: 0,
                    cursor: 'pointer',
                    color: 'var(--ink-4)',
                    fontSize: 14,
                    lineHeight: 1,
                    padding: '2px 6px',
                  }}
                >✕</button>
              )}
            </div>
          ))}
          <button
            type="button"
            className="party-add no-print no-copy"
            onClick={addKid}
            style={{ alignSelf: 'flex-start' }}
          >+ Pridať maloleté dieťa</button>
        </div>

        {/* Názov dokumentu — dlhá variant pre s-deti návrh.
            .doc-title--long zmenšuje font/letter-spacing a povoluje viacriadkové
            zalomenie (definované v generator.css pre web aj print). */}
        <h1 className="doc-title doc-title--long" style={{ marginTop: 48 }}>Návrh na rozvod manželstva a úpravu výkonu práv a povinností rodičov k maloletým deťom na čas po rozvode</h1>
        <div className="doc-sub">podľa § 22 a nasl. a § 24 ods. 1 zákona č. 36/2005 Z. z. o rodine</div>
        <p className="small" style={{ textAlign: 'left' }}>
          Súdny poplatok{' '}
          <Ed
            select
            options={[
              { v: 'vyzva', label: 'bude uhradený na výzvu súdu.' },
              { v: 'kolok', label: 'je uhradený spolu s návrhom formou kolku.' },
            ]}
          />
          <TipBtn pointKey="header-poplatok" />
        </p>

        {/* Čl. I — Manželstvo účastníkov */}
        <section className="article" id="art-1">
          <div className="article-intro">
          <div className="article-head">
            <div className="article-num">Článok I</div>
            <span className="article-title">Manželstvo účastníkov</span>
          </div>

          <p className="has-tip">
            <TipBtn pointKey="1.1" />
            <strong>1.1</strong>&nbsp;&nbsp;S {oznacenie('odporca', odporcaPohlavie, 'instr')} som {slovesoMinuly('uzavrel', navrhovatelPohlavie)} manželstvo dňa{' '}
            <SyncedEd value={datumSobasa} onChange={setDatumSobasa} placeholder="DD. MM. RRRR" />
            {' '}v{' '}
            <SyncedEd value={miestoSobasa} onChange={setMiestoSobasa} placeholder="mesto" />
            . Zapísané je v knihe manželstiev matričného úradu{' '}
            <SyncedEd value={maticnyUrad} onChange={setMaticnyUrad} placeholder="názov matričného úradu" lg />
            , zväzok{' '}
            <SyncedEd value={zvazok} onChange={setZvazok} placeholder="č." num />
            , ročník{' '}
            <SyncedEd value={rocnik} onChange={setRocnik} placeholder="RRRR" num />
            , strana{' '}
            <SyncedEd value={strana} onChange={setStrana} placeholder="č." num />
            {' '}pod poradovým číslom{' '}
            <SyncedEd value={poradoveCislo} onChange={setPoradoveCislo} placeholder="č." num />
            .
          </p>
          </div>{/* /article-intro */}

          {/* Maloleté deti — sumarizácia odvodená zo state-u kids zo sekcie
              účastníkov vyššie. Empty case: viditeľný placeholder pre používateľa
              (gray italic), no-copy + no-print zaručia, že sa NEDOSTANE do
              PDF (cez @media print display:none) ani Word exportu (kill list
              v downloadAsDoc). Singulár/plurál podľa počtu vyplnených detí. */}
          {filledKids.length === 0 ? (
            <p className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0' }}>
              [Doplňte aspoň jedno maloleté dieťa v sekcii účastníkov vyššie]
            </p>
          ) : (
            <>
              <p style={{ margin: '8px 0 4px' }}>
                S {oznacenie('odporca', odporcaPohlavie, 'instr')} máme spoločne maloleté {filledKids.length === 1 ? 'dieťa' : 'deti'}:
              </p>
              {filledKids.map((kid) => {
                const parts = [];
                if (kid.meno.trim()) parts.push(kid.meno.trim());
                if (kid.datumNarodenia.trim()) parts.push('nar. ' + kid.datumNarodenia.trim());
                if (kid.bytom.trim()) parts.push('bytom ' + kid.bytom.trim());
                return (
                  <p key={kid.id} style={{ margin: '0 0 4px', paddingLeft: 16 }}>
                    – {parts.join(', ')}
                  </p>
                );
              })}
            </>
          )}

          <p style={{ margin: '16px 0 8px' }}>
            <strong>1.2 Miestna príslušnosť súdu na rozhodnutie</strong>
          </p>

          <div className="no-copy no-print" style={{ margin: '12px 0', padding: '16px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)' }}>

            <p style={{ fontStyle: 'italic', color: 'var(--ink-2)', marginBottom: 16, fontSize: '0.9em' }}>
              Teraz spolu určíme príslušnosť súdu. Prosím odpovedzte na otázky:
            </p>

            {/* Otázka 1 */}
            <div style={{ marginBottom: 12 }}>
              <TipBtn pointKey="1.2-q1" />
              <div style={{ fontWeight: 500, marginBottom: 8 }}>Mali ste s {oznacenie('odporca', odporcaPohlavie, 'instr')} spoločné bydlisko?</div>
              <div style={{ display: 'flex', gap: 8 }}>
                <button className={q1 === 'ano' ? 'btn btn-sm btn-oxblood' : 'btn btn-sm btn-ghost'} onClick={() => { setQ1('ano'); setQ2(null); setQ3(null); }}>Áno</button>
                <button className={q1 === 'nie' ? 'btn btn-sm btn-oxblood' : 'btn btn-sm btn-ghost'} onClick={() => { setQ1('nie'); setQ2(null); setQ3(null); }}>Nie</button>
              </div>
            </div>

            {/* Otázka 2 — ak q1 === 'ano' */}
            {q1 === 'ano' && (
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontWeight: 500, marginBottom: 8 }}>Býva niektorý z vás na tej adrese dodnes?</div>
                <div style={{ display: 'flex', gap: 8 }}>
                  <button className={q2 === 'ano' ? 'btn btn-sm btn-oxblood' : 'btn btn-sm btn-ghost'} onClick={() => setQ2('ano')}>Áno</button>
                  <button className={q2 === 'nie' ? 'btn btn-sm btn-oxblood' : 'btn btn-sm btn-ghost'} onClick={() => setQ2('nie')}>Nie</button>
                </div>
              </div>
            )}

            {/* Otázka 3 — ak q1 === 'nie' alebo q2 === 'nie' */}
            {(q1 === 'nie' || q2 === 'nie') && (
              <div style={{ marginBottom: 12 }}>
                <TipBtn pointKey="1.2-q3" />
                <div style={{ fontWeight: 500, marginBottom: 8 }}>Má {oznacenie('odporca', odporcaPohlavie, 'nom')} trvalý pobyt na Slovensku?</div>
                <div style={{ display: 'flex', gap: 8 }}>
                  <button className={q3 === 'ano' ? 'btn btn-sm btn-oxblood' : 'btn btn-sm btn-ghost'} onClick={() => setQ3('ano')}>Áno</button>
                  <button className={q3 === 'nie' ? 'btn btn-sm btn-oxblood' : 'btn btn-sm btn-ghost'} onClick={() => setQ3('nie')}>Nie</button>
                </div>
              </div>
            )}

          </div>

          {/* Výsledok — text do návrhu + adresové pole + hint o príslušnosti.
              Mimo wizardu, aby ostal viditeľný v PDF/Word exporte. */}
          {/* Vetva A — q1=áno, q2=áno: spoločné bydlisko, dodnes tam niekto býva */}
          {q1 === 'ano' && q2 === 'ano' && (
            <div style={{ marginTop: 8, padding: '12px', background: 'var(--paper)', borderRadius: 'var(--r-sm)' }}>
              <p style={{ margin: '0 0 8px' }}>
                Posledným spoločným bydliskom účastníkov je <Ed placeholder="adresa posledného spoločného bydliska" /> a v obvode tohto súdu má bydlisko aspoň jeden z účastníkov.
              </p>
              <div className="no-copy no-print" style={{ fontSize: '0.82em', color: 'var(--ink-3)' }}>→ Príslušný súd: súd v obvode tejto adresy (§ 92 zák. č. 161/2015 Z. z. – CMP)</div>
            </div>
          )}

          {/* Vetva B1 — q1=áno, q2=nie, q3=áno: bývali spolu, už tam nikto, odporca má TP na SR */}
          {q1 === 'ano' && q2 === 'nie' && q3 === 'ano' && (
            <div style={{ marginTop: 8, padding: '12px', background: 'var(--paper)', borderRadius: 'var(--r-sm)' }}>
              <p style={{ margin: '0 0 8px' }}>
                Posledným spoločným bydliskom účastníkov bolo <Ed placeholder="adresa posledného spoločného bydliska" />. Účastníci nemajú v obvode toho istého súdu bydlisko, preto sa miestna príslušnosť súdu určuje podľa trvalého pobytu {oznacenie('odporca', odporcaPohlavie, 'gen')}, ktorým je <Ed placeholder={'trvalý pobyt ' + oznacenie('odporca', odporcaPohlavie, 'gen')} />.
              </p>
              <div className="no-copy no-print" style={{ fontSize: '0.82em', color: 'var(--ink-3)' }}>→ Príslušný súd: všeobecný súd {oznacenie('odporca', odporcaPohlavie, 'gen')} (§ 92 CMP)</div>
            </div>
          )}

          {/* Vetva B2 — q1=áno, q2=nie, q3=nie: bývali spolu, už tam nikto, odporca nemá TP na SR */}
          {q1 === 'ano' && q2 === 'nie' && q3 === 'nie' && (
            <div style={{ marginTop: 8, padding: '12px', background: 'var(--paper)', borderRadius: 'var(--r-sm)' }}>
              <p style={{ margin: '0 0 8px' }}>
                Posledným spoločným bydliskom účastníkov bolo <Ed placeholder="adresa posledného spoločného bydliska" />. {oznacenieCap('odporca', odporcaPohlavie, 'nom')} nemá trvalý pobyt na území Slovenskej republiky, preto sa miestna príslušnosť súdu určuje podľa trvalého pobytu {oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')}, ktorým je <Ed placeholder={'trvalý pobyt ' + oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')} />.
              </p>
              <div className="no-copy no-print" style={{ fontSize: '0.82em', color: 'var(--ink-3)' }}>→ Príslušný súd: všeobecný súd {oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')} (§ 92 CMP)</div>
            </div>
          )}

          {/* Vetva C — q1=nie, q3=áno: nemali spoločné bydlisko, odporca má TP na SR */}
          {q1 === 'nie' && q3 === 'ano' && (
            <div style={{ marginTop: 8, padding: '12px', background: 'var(--paper)', borderRadius: 'var(--r-sm)' }}>
              <p style={{ margin: '0 0 8px' }}>
                Účastníci nemali spoločné bydlisko v obvode toho istého súdu, preto sa miestna príslušnosť súdu určuje podľa trvalého pobytu {oznacenie('odporca', odporcaPohlavie, 'gen')}, ktorým je <Ed placeholder={'trvalý pobyt ' + oznacenie('odporca', odporcaPohlavie, 'gen')} />.
              </p>
              <div className="no-copy no-print" style={{ fontSize: '0.82em', color: 'var(--ink-3)' }}>→ Príslušný súd: všeobecný súd {oznacenie('odporca', odporcaPohlavie, 'gen')} (§ 92 CMP)</div>
            </div>
          )}

          {/* Vetva D — q1=nie, q3=nie: nemali spoločné bydlisko, odporca nemá TP na SR */}
          {q1 === 'nie' && q3 === 'nie' && (
            <div style={{ marginTop: 8, padding: '12px', background: 'var(--paper)', borderRadius: 'var(--r-sm)' }}>
              <p style={{ margin: '0 0 8px' }}>
                Účastníci nemali spoločné bydlisko v obvode toho istého súdu. {oznacenieCap('odporca', odporcaPohlavie, 'nom')} nemá trvalý pobyt na území Slovenskej republiky, preto sa miestna príslušnosť súdu určuje podľa trvalého pobytu {oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')}, ktorým je <Ed placeholder={'trvalý pobyt ' + oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')} />.
              </p>
              <div className="no-copy no-print" style={{ fontSize: '0.82em', color: 'var(--ink-3)' }}>→ Príslušný súd: všeobecný súd {oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')} (§ 92 CMP)</div>
            </div>
          )}

          <p className="autocomplete-host" style={{ margin: '8px 0 6px' }}>
            Miestne príslušným súdom je{'  '}
            <span className="no-copy no-print">
              <SudAutocomplete {...sudProps} />
            </span>
            <span className="ed-select-print">{sudVybrany ? sudVybrany.nazov : ''}</span>
          </p>

          <p className="evidence"><em>Dôkaz:</em> sobášny list</p>
          {/* Rodné listy maloletých detí — jeden riadok dôkazu na dieťa.
              Striktne: dôkaz vznikne iba pri vyplnenom MENE aj DÁTUME
              NARODENIA. Bytom sa do dôkazu nepremieta (právne irelevantné
              pre rodný list ako dôkaz). Neúplné dieťa (chýba meno alebo
              dátum) — riadok sa preskočí. */}
          {filledKids
            .filter(k => k.meno.trim() !== '' && k.datumNarodenia.trim() !== '')
            .map(kid => (
              <p key={kid.id} className="evidence">
                <em>Dôkaz:</em> rodný list maloletého dieťaťa - {kid.meno.trim()}, nar. {kid.datumNarodenia.trim()}
              </p>
            ))
          }
        </section>

        {/* Čl. II — Rozvrat manželstva */}
        <section className="article" id="art-2">
          <div className="article-intro">
            <div className="article-head">
              <div className="article-num">Článok II</div>
              <span className="article-title">Rozvrat manželstva</span>
            </div>

            <p className="has-tip">
              <TipBtn pointKey="art-2" />
              Vzťahy medzi účastníkmi sú vážne narušené a trvalo rozvrátené, pričom nie je nádej na obnovenie manželského spolužitia z nasledovných dôvodov:
            </p>
          </div>{/* /article-intro */}

          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>2.1 História a začiatok manželstva</strong>
              <TipBtn pointKey="2.1" />
              <button
                className="no-copy no-print"
                onClick={() => setShowSample1(!showSample1)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample1 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Ako dlho ste sa poznali pred manželstvom? Prečo ste sa zosobášili? Aké bolo manželstvo na začiatku?
            </p>
            {showSample1 && (
              <SamplePanel
                sampleText={sample1}
                onUse={() => { fillSampleText('kategoria1Ref', sample1); setShowSample1(false); }}
                onClose={() => setShowSample1(false)}
              />
            )}
            <Ed block ref={kategoria1Ref} placeholder="Tu napíšte vlastnú odpoveď..." />
          </div>

          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>2.2 Vznik a vývoj problémov</strong>
              <TipBtn pointKey="2.2" />
              <button
                className="no-copy no-print"
                onClick={() => setShowSample2(!showSample2)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample2 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Kedy nastali prvé problémy a čo ich spôsobilo? Snažili ste sa ich riešiť — ak áno, ako? Kedy nastal zlom, že ste si povedali, že už nechcete zotrvať v manželstve, a čo bolo tým zlomom?
            </p>
            {showSample2 && (
              <SamplePanel
                sampleText={sample2}
                onUse={() => { fillSampleText('kategoria2Ref', sample2); setShowSample2(false); }}
                onClose={() => setShowSample2(false)}
              />
            )}
            <Ed block ref={kategoria2Ref} placeholder="Tu napíšte vlastnú odpoveď..." />
          </div>

          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>2.3 Súčasný stav vzťahu</strong>
              <TipBtn pointKey="2.3" />
              <button
                className="no-copy no-print"
                onClick={() => setShowSample3(!showSample3)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample3 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Keď ste manželovi/manželke povedali, že chcete rozvod, aká bola jeho/jej reakcia? Hospodárite spoločne — máte spoločný účet, kto kupuje potraviny, kto varí? Máte spoločných známych, záľuby, spoločné akcie? Kedy ste mali naposledy intímny styk?
            </p>
            {showSample3 && (
              <SamplePanel
                sampleText={sample3}
                onUse={() => { fillSampleText('kategoria3Ref', sample3); setShowSample3(false); }}
                onClose={() => setShowSample3(false)}
              />
            )}
            <Ed block ref={kategoria3Ref} placeholder="Tu napíšte vlastnú odpoveď..." />
          </div>

          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>2.4 Pokusy o obnovu a výhľad do budúcnosti</strong>
              <TipBtn pointKey="2.4" />
              <button
                className="no-copy no-print"
                onClick={() => setShowSample4(!showSample4)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample4 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Snažili ste sa o obnovu manželstva — ak áno, akým spôsobom? Prečo podľa Vás obnova manželstva už nie je možná?
            </p>
            {showSample4 && (
              <SamplePanel
                sampleText={SAMPLE_TEXT_4}
                onUse={() => { fillSampleText('kategoria4Ref', SAMPLE_TEXT_4); setShowSample4(false); }}
                onClose={() => setShowSample4(false)}
              />
            )}
            <Ed block ref={kategoria4Ref} placeholder="Tu napíšte vlastnú odpoveď..." />
          </div>

          <p>
            Na základe vyššie uvedeného je zrejmé, že manželstvo účastníkov je hlboko a trvalo rozvrátené v zmysle § 23 ods. 1 zákona č. 36/2005 Z. z. o rodine a nemôže plniť svoj účel.
          </p>
        </section>

        {/* Čl. III — Maloleté deti a úprava výkonu rodičovských práv.
            Voľby (forma starostlivosti, zverenie, výživné, styk) sa premietajú
            do JSX cez cl3 state; do petitu (Čl. IV.3 + výrok) sa zatiaľ
            nepremietajú — refaktor petita príde vo fáze B.
            Page-break-before zaisťuje začiatok na novej strane v PDF/Word. */}
        <section className="article" id="art-3">
          <div className="article-intro">
            <div className="article-head">
              <div className="article-num">Článok III</div>
              <span className="article-title">Maloleté deti a úprava výkonu rodičovských práv a povinností</span>
            </div>

            <p className="has-tip">
              <TipBtn pointKey="art-3" />
              <strong>3.1</strong>&nbsp;&nbsp;Skutkový opis vzťahu {filledKids.length === 1 ? 'k dieťaťu' : 'k deťom'}
            </p>
          </div>{/* /article-intro */}

          {/* 3.1.1 — narodenie a doterajší život */}
          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>3.1.1 Narodenie a doterajší život {filledKids.length === 1 ? 's dieťaťom' : 's deťmi'}</strong>
              <button
                className="no-copy no-print"
                onClick={() => setShowSample311(!showSample311)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample311 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              {filledKids.length === 1
                ? 'Aké to bolo, keď sa narodilo Vaše dieťa? Akým spôsobom prebieha starostlivosť o maloleté dieťa v súčasnosti?'
                : 'Aké to bolo, keď sa narodili Vaše deti? Akým spôsobom prebieha starostlivosť o maloleté deti v súčasnosti?'}
            </p>
            {showSample311 && (
              <SamplePanel
                sampleText={sample311(navrhovatelPohlavie, filledKids.length)}
                onUse={() => { fillSampleText('cl3_311_Ref', sample311(navrhovatelPohlavie, filledKids.length)); setShowSample311(false); }}
                onClose={() => setShowSample311(false)}
              />
            )}
            <Ed block ref={cl3_311_Ref} placeholder="Doterajší život s deťmi (3.1.1) — váš text..." />
          </div>

          {/* 3.1.2 — konkrétne príklady starostlivosti */}
          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>3.1.2 Konkrétne príklady starostlivosti</strong>
              <button
                className="no-copy no-print"
                onClick={() => setShowSample312(!showSample312)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample312 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Uveďte konkrétne príklady starostlivosti o maloleté {filledKids.length === 1 ? 'dieťa' : 'deti'} — pozitívne aj negatívne. Popíšte ich tak, ako sa odohrali. Ak máte negatívne skúsenosti so starostlivosťou druhého rodiča, napíšte ich, podľa možnosti aj s priamou rečou.
            </p>
            {showSample312 && (
              <SamplePanel
                sampleText={sample312(navrhovatelPohlavie, filledKids.length)}
                onUse={() => { fillSampleText('cl3_312_Ref', sample312(navrhovatelPohlavie, filledKids.length)); setShowSample312(false); }}
                onClose={() => setShowSample312(false)}
              />
            )}
            <Ed block ref={cl3_312_Ref} placeholder="Konkrétne príklady starostlivosti (3.1.2) — váš text..." />
          </div>

          {/* 3.2 — predstava o úprave po rozvode (dva vzory: zverenie sebe / druhému) */}
          <div style={{ marginBottom: 24 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
              <strong>3.2 Predstava o úprave po rozvode</strong>
              <button
                className="no-copy no-print"
                onClick={() => setShowSample32(!showSample32)}
                style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
              >{showSample32 ? 'Skryť vzory' : 'Zobraziť vzory textu (A/B)'}</button>
            </div>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              {filledKids.length === 1
                ? 'Ako si predstavujete starostlivosť o dieťa po rozvode? Komu by malo byť zverené, aké výživné navrhujete a ako si predstavujete styk druhého rodiča s dieťaťom?'
                : 'Ako si predstavujete starostlivosť o deti po rozvode? Komu by mali byť zverené, aké výživné navrhujete a ako si predstavujete styk druhého rodiča s deťmi?'}
            </p>
            {showSample32 && (
              <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 12, margin: '0 0 12px' }}>
                {[
                  { label: 'Vzor A — zverenie do mojej starostlivosti', text: sample32A(navrhovatelPohlavie, filledKids.length) },
                  { label: 'Vzor B — zverenie druhému rodičovi', text: sample32B(navrhovatelPohlavie, filledKids.length) },
                ].map(({ label, text }) => (
                  <div key={label} style={{ background: 'var(--ivory-2)', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', padding: '12px 16px' }}>
                    <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 8 }}>{label}</div>
                    <div style={{ fontStyle: 'italic', fontSize: '0.92em', color: 'var(--ink-2)', marginBottom: 12, lineHeight: 1.55 }}>{text}</div>
                    <UsePatternButton
                      onClick={() => { fillSampleText('cl3_32_Ref', text); setShowSample32(false); }}
                    />
                  </div>
                ))}
              </div>
            )}
            <Ed block ref={cl3_32_Ref} placeholder="Predstava po rozvode (3.2) — váš text..." />
          </div>

          {/* 3.3 — forma osobnej starostlivosti */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="3.3-forma" />
            <p style={{ margin: '12px 0 8px' }}><strong>3.3 Forma osobnej starostlivosti</strong></p>

            {/* UI prepínač — mimo PDF/Word */}
            <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)' }}>
              {[
                { v: 'a', label: 'Osobná starostlivosť jedného rodiča (§ 24 ods. 1 ZoR)' },
                { v: 'b', label: 'Striedavá osobná starostlivosť oboch rodičov (§ 24 ods. 2 ZoR)' },
                { v: 'c', label: 'Spoločná osobná starostlivosť oboch rodičov (§ 24 ods. 2 ZoR)' },
              ].map(opt => (
                <label key={opt.v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                  <input
                    type="radio"
                    name="cl3-forma"
                    value={opt.v}
                    checked={cl3.formaStarostlivosti === opt.v}
                    onChange={() => setCl3Field('formaStarostlivosti', opt.v)}
                  />
                  <span>{opt.label}</span>
                </label>
              ))}
            </div>

            {/* Vetva (a) — jeden rodič */}
            {cl3.formaStarostlivosti === 'a' && (
              <>
                <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)', marginTop: 8 }}>
                  <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>Komu má byť dieťa/deti zverené:</div>
                  {[
                    { v: 'navrhovatel', label: `do mojej osobnej starostlivosti (${oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')})` },
                    { v: 'odporca', label: `do osobnej starostlivosti druhého rodiča (${oznacenie('odporca', odporcaPohlavie, 'gen')})` },
                  ].map(opt => (
                    <label key={opt.v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                      <input
                        type="radio"
                        name="cl3-zverenie-a"
                        value={opt.v}
                        checked={cl3.zvereniePri_a === opt.v}
                        onChange={() => setCl3Field('zvereniePri_a', opt.v)}
                      />
                      <span>{opt.label}</span>
                    </label>
                  ))}
                </div>
                {/* Materializovaná veta do dokumentu — gendered podľa zvereného
                    rodiča. Pri zverení navrhovateľovi prvá osoba ("do mojej... ako
                    matky/otca"), pri zverení odporcovi tretia osoba. */}
                <p style={{ margin: '12px 0 0' }}>
                  {cl3.zvereniePri_a === 'navrhovatel' ? (
                    <>
                      Navrhujem, aby {bolo(filledKids.length)} {detiSlovo(filledKids.length, 'nom')} zverené do mojej osobnej starostlivosti ako {rolaRodica('navrhovatel', navrhovatelPohlavie, 'gen')}.
                    </>
                  ) : (
                    <>
                      Navrhujem, aby {bolo(filledKids.length)} {detiSlovo(filledKids.length, 'nom')} zverené do osobnej starostlivosti {oznacenie('odporca', odporcaPohlavie, 'gen')} ako {rolaRodica('odporca', navrhovatelPohlavie, 'gen')}.
                    </>
                  )}
                </p>
              </>
            )}

            {/* Vetva (b) — striedavá osobná starostlivosť */}
            {cl3.formaStarostlivosti === 'b' && (
              <>
                {/* Voľba typu striedania */}
                <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)', marginTop: 8 }}>
                  <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>Typ striedania:</div>
                  {[
                    { v: '1tyz', label: 'Týždenné striedanie' },
                    { v: 'vlastne', label: 'Vlastné striedanie' },
                  ].map(opt => (
                    <label key={opt.v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                      <input
                        type="radio"
                        name="cl3-typStriedania"
                        value={opt.v}
                        checked={cl3.typStriedania === opt.v}
                        onChange={() => setCl3Field('typStriedania', opt.v)}
                      />
                      <span>{opt.label}</span>
                    </label>
                  ))}
                </div>

                {filledKids.length === 0 ? (
                  <p className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0' }}>
                    [doplňte aspoň jedno maloleté dieťa v sekcii účastníkov vyššie, aby sa zobrazil vzor striedania]
                  </p>
                ) : (
                  <>
                    {/* Materializovaný úvodný odsek (do PDF/Word) */}
                    <p style={{ margin: '12px 0 8px' }}>
                      Navrhujem, aby boli {detiSlovo(filledKids.length, 'nom')} zverené do striedavej osobnej starostlivosti oboch rodičov v nasledujúcom rozsahu:
                    </p>

                    {/* JEDEN Ed block + sample button + SamplePanel — rovnaký
                        UX pattern ako 2.1–2.4. Obsah sample-u sa derivuje
                        z typStriedania (1tyz | vlastne) a pCount. */}
                    <div style={{ marginBottom: 8 }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
                        <strong>Opis navrhovaného striedania</strong>
                        <button
                          className="no-copy no-print"
                          onClick={() => setShowSample33b(!showSample33b)}
                          style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
                        >{showSample33b ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
                      </div>
                      {showSample33b && (() => {
                        const pCount = filledKids.length;
                        const beznyText = cl3.typStriedania === 'vlastne'
                          ? SAMPLE_STRIEDAVKA_BEZNY_VLASTNE
                          : sampleStriedavka_BeznyCyklus(pCount);
                        const joined = sample33bJoined(cl3.typStriedania, pCount);
                        return (
                          <div className="no-copy no-print" style={{ background: 'var(--ivory-2)', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', padding: '14px 18px', margin: '0 0 8px' }}>
                            <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 12 }}>
                              Vzorový text — len ako inšpirácia
                            </div>
                            <div style={{ display: 'flex', flexDirection: 'column', gap: 12, fontSize: '0.92em', color: 'var(--ink-2)', lineHeight: 1.55 }}>
                              <div>
                                <div><strong>Bežný cyklus</strong></div>
                                <p style={{ margin: '4px 0 0' }}>{beznyText}</p>
                              </div>
                              <div>
                                <div><strong>Letné prázdniny</strong></div>
                                <p style={{ margin: '4px 0 0' }}>{sampleStriedavka_LetnePrazdniny(pCount)}</p>
                              </div>
                              <div>
                                <div><strong>Zimné prázdniny</strong></div>
                                <p style={{ margin: '4px 0 0' }}>{sampleStriedavka_ZimnePrazdniny(pCount)}</p>
                              </div>
                              <div>
                                <div><strong>Veľkonočné prázdniny</strong></div>
                                <p style={{ margin: '4px 0 0' }}>{sampleStriedavka_VelkonocnePrazdniny(pCount)}</p>
                              </div>
                              <p style={{ margin: '4px 0 0' }}>{sampleVetaOdovzdanie(pCount)}</p>
                            </div>
                            <div style={{ marginTop: 14, display: 'flex', gap: 8 }}>
                              <UsePatternButton
                                onClick={() => { fillSampleText('cl3_33b_Ref', joined); setShowSample33b(false); }}
                              />
                              <button
                                onClick={() => setShowSample33b(false)}
                                style={{ fontSize: '0.82em', padding: '6px 14px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'transparent', cursor: 'pointer', color: 'var(--ink-3)' }}
                              >Zatvoriť</button>
                            </div>
                          </div>
                        );
                      })()}
                      <Ed block ref={cl3_33b_Ref} placeholder="Sem vložte text striedavej osobnej starostlivosti — kliknite na 'Zobraziť vzor textu' a 'Použiť tento text'." />
                    </div>
                  </>
                )}
              </>
            )}

            {/* Vetva (c) — spoločná osobná starostlivosť */}
            {cl3.formaStarostlivosti === 'c' && (
              <>
                <div className="no-copy no-print" style={{ marginTop: 8, padding: '12px 14px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)', fontSize: '0.88em', color: 'var(--ink-2)', fontStyle: 'italic' }}>
                  Spoločná osobná starostlivosť vyžaduje dohodu oboch rodičov. Predpokladá sa, že rodičia žijú v rovnakej oblasti a sú schopní komunikovať vo veciach výchovy detí.
                </div>
                {filledKids.length === 0 ? (
                  <p className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0' }}>
                    [doplňte aspoň jedno maloleté dieťa v sekcii účastníkov vyššie, aby sa zobrazil vzor opisu]
                  </p>
                ) : (
                  <div style={{ marginTop: 8 }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
                      <strong>Stručný opis dohodnutého fungovania</strong>
                      <button
                        className="no-copy no-print"
                        onClick={() => setShowSample33c(!showSample33c)}
                        style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
                      >{showSample33c ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
                    </div>
                    {showSample33c && (() => {
                      const text = sampleSpolocna(filledKids.length);
                      return (
                        <div className="no-copy no-print" style={{ background: 'var(--ivory-2)', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', padding: '14px 18px', margin: '0 0 8px' }}>
                          <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 12 }}>
                            Vzorový text — len ako inšpirácia
                          </div>
                          <p style={{ margin: 0, fontSize: '0.92em', color: 'var(--ink-2)', lineHeight: 1.55 }}>
                            {text}
                          </p>
                          <div style={{ marginTop: 14, display: 'flex', gap: 8 }}>
                            <UsePatternButton
                              onClick={() => { fillSampleText('cl3_33c_Ref', text); setShowSample33c(false); }}
                            />
                            <button
                              onClick={() => setShowSample33c(false)}
                              style={{ fontSize: '0.82em', padding: '6px 14px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'transparent', cursor: 'pointer', color: 'var(--ink-3)' }}
                            >Zatvoriť</button>
                          </div>
                        </div>
                      );
                    })()}
                    <Ed block ref={cl3_33c_Ref} placeholder="Sem vložte opis dohodnutého fungovania spoločnej osobnej starostlivosti — kliknite na 'Zobraziť vzor textu' a 'Použiť tento text'." />
                  </div>
                )}
              </>
            )}
          </div>

          {/* 3.3.1 — zastupovanie a správa majetku.
              Default sa odvodí z formy a zverenia (matka/otec/obaja),
              userTouchedZastupovanie uzamkne ďalšie auto-zmeny po explicit prepnutí. */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="3.3-zastupovanie" />
            <p style={{ margin: '12px 0 8px' }}><strong>3.3.1 Zastupovanie a správa majetku</strong></p>
            <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)' }}>
              <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>Kto bude {detiSlovo(filledKids.length || 1, 'ak')} zastupovať a spravovať {filledKids.length === 1 ? 'jeho' : 'ich'} majetok:</div>
              {[
                { v: 'obaja', label: 'Obaja rodičia spoločne' },
                { v: 'matka', label: 'Iba matka' },
                { v: 'otec',  label: 'Iba otec' },
              ].map(opt => (
                <label key={opt.v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                  <input
                    type="radio"
                    name="cl3-zastupovanie"
                    value={opt.v}
                    checked={cl3.zastupovanie === opt.v}
                    onChange={() => setZastupovanie(opt.v)}
                  />
                  <span>{opt.label}</span>
                </label>
              ))}
            </div>

            {/* Materializovaná veta do dokumentu — preview na obrazovke aj v PDF/Word.
                Zhoda subjekt + sloveso podľa voľby zastupovania, plurálovo-singulárna
                zhoda objektu cez detiSlovo. */}
            <p style={{ margin: '12px 0 0' }}>
              Navrhujem, aby zastupovanie {detiSlovo(filledKids.length, 'gen')} a správu {filledKids.length === 1 ? 'jeho' : 'ich'} majetku {cl3.zastupovanie === 'matka' ? 'vykonávala matka' : cl3.zastupovanie === 'otec' ? 'vykonával otec' : 'vykonávali obaja rodičia'}.
            </p>
          </div>

          {/* 3.4 — výživné */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="3.4-vyzivne" />
            <p style={{ margin: '12px 0 8px' }}><strong>3.4 Návrh na určenie výživného</strong></p>

            {filledKids.length === 0 ? (
              <p className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0' }}>
                [Doplňte aspoň jedno maloleté dieťa v sekcii účastníkov vyššie, aby sa zobrazila tabuľka výživného.]
              </p>
            ) : (
              <>
                {/* Pri (b)/(c) voľba režimu výživného — 2 možnosti (FÁZA B
                    odstránila variant 'iii' obaja navzájom). */}
                {(cl3.formaStarostlivosti === 'b' || cl3.formaStarostlivosti === 'c') && (
                  <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)', marginBottom: 8 }}>
                    <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>Žiadate určiť výživné?</div>
                    {[
                      { v: 'i', label: filledKids.length === 1 ? 'Áno, žiadam výživné na dieťa od druhého rodiča.' : 'Áno, žiadam výživné na deti od druhého rodiča.' },
                      { v: 'ii', label: 'Nie, výživné nežiadame. Každý rodič živí dieťa počas času, keď je u neho.' },
                    ].map(opt => {
                      const stateField = cl3.formaStarostlivosti === 'b' ? 'rezimVyzivnehoPri_b' : 'rezimVyzivnehoPri_c';
                      return (
                        <label key={opt.v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                          <input
                            type="radio"
                            name={'cl3-rezim-' + cl3.formaStarostlivosti}
                            value={opt.v}
                            checked={cl3[stateField] === opt.v}
                            onChange={() => setCl3Field(stateField, opt.v)}
                          />
                          <span>{opt.label}</span>
                        </label>
                      );
                    })}
                  </div>
                )}

                {/* Tabuľka výživného — splatnosť je fixne "do 15. dňa kalendárneho
                    mesiaca vopred" (FÁZA B simplification, § 62 ZoR praxe). */}
                {(() => {
                  const rezim = cl3.formaStarostlivosti === 'a'
                    ? 'i'
                    : (cl3.formaStarostlivosti === 'b' ? cl3.rezimVyzivnehoPri_b : cl3.rezimVyzivnehoPri_c);

                  if (rezim === 'ii') {
                    return (
                      <p style={{ margin: '8px 0 0' }}>
                        Výživné nežiadame. Každý z rodičov si plní vyživovaciu povinnosť počas obdobia, keď má {detiSlovo(filledKids.length, 'ak')} v osobnej starostlivosti.
                      </p>
                    );
                  }

                  // rezim === 'i' — tabuľka výživného (jediná, mapa cl3.vyzivne).
                  // Vstupná tabuľka (Ed num polia) zabalená v bledohnedom rámčeku
                  // (rovnaký štýl ako 3.3.1). Materializovaný preview pod rámčekom.
                  return (
                    <div style={{ marginBottom: 12 }}>
                      <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 8, padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)' }}>
                        {filledKids.map(kid => {
                          const row = getVyzivne(kid.id);
                          return (
                            // Flex layout — label dostane potrebnú šírku (white-space: nowrap),
                            // input + jednotka idú vpravo. flexWrap: 'wrap' chrání proti extrémne
                            // dlhému menu — vtedy input padne pod label, ale label sám sa nezlomí.
                            <div key={kid.id} style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
                              <span style={{ whiteSpace: 'nowrap' }}>
                                {kid.meno || '(meno?)'}{kid.datumNarodenia ? ', nar. ' + kid.datumNarodenia : ''}:
                              </span>
                              <div style={{ display: 'flex', gap: 8, alignItems: 'baseline' }}>
                                <input
                                  type="text"
                                  inputMode="decimal"
                                  value={row.suma}
                                  onChange={(e) => setVyzivneSuma(kid.id, e.target.value)}
                                  placeholder="suma"
                                  style={{ width: 80, padding: '4px 8px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', fontFamily: 'var(--serif)', fontSize: '0.95em', textAlign: 'right' }}
                                />
                                <span style={{ whiteSpace: 'nowrap' }}>€/mesiac</span>
                              </div>
                            </div>
                          );
                        })}
                      </div>
                      {/* Print/Word verzia — vety za sebou. Splatnosť fixne. */}
                      {/* Materializovaný preview — viditeľný na obrazovke aj v exporte.
                          Jeden úvodný odsek + zoznam detí + záverečná veta o splatnosti.
                          Renderuje všetky vyplnené deti (aj s prázdnou sumou — vtedy
                          inline placeholder no-print). */}
                      <div style={{ marginTop: 8 }}>
                        <p style={{ margin: '0 0 6px' }}>
                          Navrhujem, aby súd po vykonaní dokazovania stanovil mesačné výživné nasledovne:
                        </p>
                        {filledKids.map(kid => {
                          const row = getVyzivne(kid.id);
                          return (
                            <p key={kid.id} style={{ margin: '0 0 4px', paddingLeft: 16 }}>
                              – maloleté dieťa {orPh(kid.meno, 'meno?')}, nar. {orPh(kid.datumNarodenia, 'dátum?')} vo výške {orPh(row && row.suma, 'suma')} eur mesačne
                            </p>
                          );
                        })}
                        <p style={{ margin: '8px 0 0' }}>
                          Výživné je splatné vždy do 15. dňa kalendárneho mesiaca vopred, počnúc dňom právoplatnosti rozsudku.
                        </p>
                      </div>
                    </div>
                  );
                })()}
              </>
            )}
          </div>

          {/* 3.5 — styk */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="3.5-styk" />
            <p style={{ margin: '12px 0 8px' }}><strong>3.5 Styk s rodičom, ktorému {filledKids.length === 1 ? 'dieťa nebolo' : 'deti neboli'} zverené</strong></p>

            {cl3.formaStarostlivosti === 'a' && (() => {
              // "Druhý rodič" v inštrumentáli (s otcom / s matkou) — pre label
              // pri voľbe (ii) aj pre materializovaný text. Nezverený rodič =
              // opačná procesná rola od zvereniePri_a; matka/otec podľa pohlavia.
              const nezverenyRoleAt = cl3.zvereniePri_a === 'navrhovatel' ? 'odporca' : 'navrhovatel';
              const nezverenyKeyAt = rolaRodicaKey(nezverenyRoleAt, navrhovatelPohlavie);
              const druhyRodicInstr = rolaRodicaPad(nezverenyKeyAt, 'instr');
              return (
              <>
                <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)' }}>
                  <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>Návrh na úpravu styku s druhým rodičom:</div>
                  {[
                    { v: 'i', label: 'Žiadam súd, aby styk s druhým rodičom upravil v rozsudku.' },
                    { v: 'ii', label: `Súdom upravený styk nepožadujem, s ${druhyRodicInstr} sa vieme dohodnúť na úprave styku bez nutnosti zásahu súdu.` },
                  ].map(opt => (
                    <label key={opt.v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                      <input
                        type="radio"
                        name="cl3-styk"
                        value={opt.v}
                        checked={cl3.styk === opt.v}
                        onChange={() => setCl3Field('styk', opt.v)}
                      />
                      <span>{opt.label}</span>
                    </label>
                  ))}
                </div>

                {cl3.styk === 'i' && (() => {
                  // "Nezverený" rodič = ten druhý ako pri 3.3(a) zverenie.
                  // navrhovatel zverený → odporca nezverený a naopak.
                  const nezverenaRole = cl3.zvereniePri_a === 'navrhovatel' ? 'odporca' : 'navrhovatel';
                  const nezverenyKey = rolaRodicaKey(nezverenaRole, navrhovatelPohlavie);
                  const pCount = Math.max(1, filledKids.length);
                  const joined = sampleStyk_Joined(nezverenyKey, pCount);
                  return (
                    <>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 12, marginBottom: 6 }}>
                        <span className="no-copy no-print" style={{ fontSize: '0.85em', color: 'var(--ink-3)', fontStyle: 'italic' }}>Opis navrhovaného styku:</span>
                        <button
                          className="no-copy no-print"
                          onClick={() => setShowSample35(!showSample35)}
                          style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
                        >{showSample35 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
                      </div>
                      {showSample35 && (
                        <div className="no-copy no-print" style={{ background: 'var(--ivory-2)', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', padding: '14px 18px', margin: '0 0 8px' }}>
                          <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 12 }}>
                            Styk druhého rodiča — vzor s prázdninovým režimom
                          </div>
                          <div style={{ display: 'flex', flexDirection: 'column', gap: 12, fontSize: '0.92em', color: 'var(--ink-2)', lineHeight: 1.55 }}>
                            <div>
                              <div><strong>Bežný styk</strong></div>
                              <p style={{ margin: '4px 0 0' }}>{sampleStyk_BeznyStyk(nezverenyKey, pCount)}</p>
                            </div>
                            <div>
                              <div><strong>Letné prázdniny</strong></div>
                              <p style={{ margin: '4px 0 0' }}>{sampleStyk_LetnePrazdniny(nezverenyKey, pCount)}</p>
                            </div>
                            <div>
                              <div><strong>Zimné prázdniny</strong></div>
                              <p style={{ margin: '4px 0 0' }}>{sampleStyk_ZimnePrazdniny(nezverenyKey, pCount)}</p>
                            </div>
                            <div>
                              <div><strong>Veľkonočné prázdniny</strong></div>
                              <p style={{ margin: '4px 0 0' }}>{sampleStyk_VelkonocnePrazdniny(nezverenyKey, pCount)}</p>
                            </div>
                            <p style={{ margin: '4px 0 0' }}>{sampleVetaOdovzdanie(pCount)}</p>
                          </div>
                          <div style={{ marginTop: 14, display: 'flex', gap: 8 }}>
                            <UsePatternButton
                              onClick={() => { fillSampleText('cl3_35_Ref', joined); setShowSample35(false); }}
                            />
                            <button
                              onClick={() => setShowSample35(false)}
                              style={{ fontSize: '0.82em', padding: '6px 14px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'transparent', cursor: 'pointer', color: 'var(--ink-3)' }}
                            >Zatvoriť</button>
                          </div>
                        </div>
                      )}
                      <Ed block ref={cl3_35_Ref} placeholder="Opis navrhovaného styku (3.5) — váš text alebo použite vzor vyššie..." />
                    </>
                  );
                })()}

                {cl3.styk === 'ii' && (
                  <p style={{ margin: '12px 0 0' }}>
                    Súdom upravený styk nepožadujem, s {druhyRodicInstr} sa vieme dohodnúť na úprave styku bez nutnosti zásahu súdu.
                  </p>
                )}
              </>
              );
            })()}

            {cl3.formaStarostlivosti === 'b' && (
              <p style={{ margin: '12px 0 0', fontStyle: 'italic', color: 'var(--ink-2)' }}>
                Pri striedavej osobnej starostlivosti sa styk podľa § 25 zákona o rodine osobitne neupravuje.
              </p>
            )}

            {cl3.formaStarostlivosti === 'c' && (
              <p style={{ margin: '12px 0 0', fontStyle: 'italic', color: 'var(--ink-2)' }}>
                Pri spoločnej osobnej starostlivosti sa styk osobitne neupravuje, fungovanie je dohodnuté medzi rodičmi (bod 3.3 vyššie).
              </p>
            )}
          </div>
        </section>

        {/* Čl. IV — Pomery rodičov a výdavky na maloleté deti.
            § 62 ods. 2 ZoR (potreby/možnosti), § 117 CMP (vyšetrovacia zásada). */}
        <section className="article" id="art-4">
          <div className="article-intro">
            <div className="article-head">
              <div className="article-num">Článok IV</div>
              <span className="article-title">Pomery rodičov a výdavky na maloleté deti</span>
            </div>

            <p className="has-tip">
              <TipBtn pointKey="art-4-pomery" />
              Na účely posúdenia odôvodnených potrieb maloletých detí podľa § 62 ods. 2 zákona č. 36/2005 Z. z. o rodine a v súlade s článkom 6 základných princípov zákona č. 161/2015 Z. z. (Civilný mimosporový poriadok) uvádzam priemerné mesačné a mimoriadne ročné výdavky vynakladané na maloleté {filledKids.length === 1 ? 'dieťa' : 'deti'}, ako aj svoje majetkové pomery.
            </p>
          </div>{/* /article-intro */}

          {/* 4.1 — Mesačné výdavky tabuľka */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="4.1-vydavky-mesacne" />
            <p style={{ margin: '12px 0 6px' }}><strong>4.1 Mesačné výdavky na maloleté {filledKids.length === 1 ? 'dieťa' : 'deti'}</strong></p>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Uvádzam priemerné mesačné výdavky na každé maloleté dieťa samostatne. Sumy zahŕňajú alikvotnú časť spoločných výdavkov domácnosti pripadajúcu na dieťa.
            </p>
            {filledKids.length === 0 ? (
              <p className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0' }}>
                [doplňte aspoň jedno maloleté dieťa v sekcii účastníkov vyššie]
              </p>
            ) : (
              <>
                <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.92em', marginBottom: 8 }}>
                  <thead>
                    <tr>
                      <th style={{ textAlign: 'left', padding: '6px', borderBottom: '1px solid var(--rule)', fontWeight: 600 }}>Položka</th>
                      {filledKids.map(kid => (
                        <th key={kid.id} style={{ textAlign: 'right', padding: '6px', borderBottom: '1px solid var(--rule)', fontWeight: 600 }}>
                          {kid.meno || '(meno?)'}
                        </th>
                      ))}
                      <th className="no-copy no-print" style={{ width: '32px', borderBottom: '1px solid var(--rule)' }}></th>
                    </tr>
                  </thead>
                  <tbody>
                    {Object.entries(cl4.vydavkyMesacne).map(([polozkaId, polozka]) => (
                      <tr key={polozkaId} style={{ borderBottom: '1px solid var(--rule-soft, #eee)' }}>
                        <td style={{ padding: '4px 6px', verticalAlign: 'top' }}>
                          <input
                            type="text"
                            className="no-copy no-print"
                            value={polozka.nazov}
                            onChange={(e) => setVydavokNazov('mesacne', polozkaId, e.target.value)}
                            style={{ width: '100%', padding: '4px 0', border: 'none', borderBottom: '1px dotted var(--rule)', background: 'transparent', fontFamily: 'var(--serif)', fontSize: '0.95em' }}
                          />
                          <span className="ed-select-print">{polozka.nazov}</span>
                        </td>
                        {filledKids.map(kid => {
                          const suma = (polozka.sumy || {})[kid.id] || '';
                          return (
                            <td key={kid.id} style={{ padding: '4px 6px', textAlign: 'right', verticalAlign: 'top' }}>
                              <input
                                type="text"
                                inputMode="decimal"
                                className="no-copy no-print"
                                value={suma}
                                onChange={(e) => setVydavokSuma('mesacne', polozkaId, kid.id, e.target.value)}
                                placeholder="—"
                                style={{ width: 70, padding: '4px 6px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', fontFamily: 'var(--serif)', fontSize: '0.95em', textAlign: 'right' }}
                              />
                              <span className="ed-select-print">{suma ? suma + ' €' : '—'}</span>
                            </td>
                          );
                        })}
                        <td className="no-copy no-print" style={{ verticalAlign: 'top', padding: '4px 0' }}>
                          <button
                            type="button"
                            onClick={() => removePolozka('mesacne', polozkaId)}
                            aria-label="Odstrániť položku"
                            title="Odstrániť položku"
                            style={{ background: 'transparent', border: 0, cursor: 'pointer', color: 'var(--ink-4)', fontSize: 14, padding: '0 6px' }}
                          >✕</button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
                <button
                  type="button"
                  className="party-add no-copy no-print"
                  onClick={() => addPolozka('mesacne')}
                  style={{ alignSelf: 'flex-start' }}
                >+ Pridať položku</button>
              </>
            )}
          </div>

          {/* 4.2 — Ročné/mimoriadne výdavky tabuľka s prepočtom 1/12 */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="4.2-vydavky-rocne" />
            <p style={{ margin: '12px 0 6px' }}><strong>4.2 Mimoriadne a ročné výdavky na maloleté {filledKids.length === 1 ? 'dieťa' : 'deti'}</strong></p>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Okrem mesačných výdavkov vznikajú aj výdavky, ktoré sa neopakujú každý mesiac, ale počítajú sa za celý kalendárny rok. Sumy uvádzam za rok.
            </p>
            {filledKids.length === 0 ? (
              <p className="no-copy no-print" style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0' }}>
                [doplňte aspoň jedno maloleté dieťa v sekcii účastníkov vyššie]
              </p>
            ) : (
              <>
                <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.92em', marginBottom: 8 }}>
                  <thead>
                    <tr>
                      <th style={{ textAlign: 'left', padding: '6px', borderBottom: '1px solid var(--rule)', fontWeight: 600 }}>Položka</th>
                      {filledKids.map(kid => (
                        <th key={kid.id} style={{ textAlign: 'right', padding: '6px', borderBottom: '1px solid var(--rule)', fontWeight: 600 }}>
                          {kid.meno || '(meno?)'}
                        </th>
                      ))}
                      <th className="no-copy no-print" style={{ width: '32px', borderBottom: '1px solid var(--rule)' }}></th>
                    </tr>
                  </thead>
                  <tbody>
                    {Object.entries(cl4.vydavkyRocne).map(([polozkaId, polozka]) => (
                      <tr key={polozkaId} style={{ borderBottom: '1px solid var(--rule-soft, #eee)' }}>
                        <td style={{ padding: '4px 6px', verticalAlign: 'top' }}>
                          <input
                            type="text"
                            className="no-copy no-print"
                            value={polozka.nazov}
                            onChange={(e) => setVydavokNazov('rocne', polozkaId, e.target.value)}
                            style={{ width: '100%', padding: '4px 0', border: 'none', borderBottom: '1px dotted var(--rule)', background: 'transparent', fontFamily: 'var(--serif)', fontSize: '0.95em' }}
                          />
                          <span className="ed-select-print">{polozka.nazov}</span>
                        </td>
                        {filledKids.map(kid => {
                          const suma = (polozka.sumy || {})[kid.id] || '';
                          const sumaNum = parseFloat(suma) || 0;
                          return (
                            <td key={kid.id} style={{ padding: '4px 6px', textAlign: 'right', verticalAlign: 'top' }}>
                              <input
                                type="text"
                                inputMode="decimal"
                                className="no-copy no-print"
                                value={suma}
                                onChange={(e) => setVydavokSuma('rocne', polozkaId, kid.id, e.target.value)}
                                placeholder="—"
                                style={{ width: 70, padding: '4px 6px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', fontFamily: 'var(--serif)', fontSize: '0.95em', textAlign: 'right' }}
                              />
                              {sumaNum > 0 && (
                                <div className="no-copy no-print" style={{ fontSize: '0.72em', color: 'var(--ink-3)', textAlign: 'right', marginTop: 2 }}>
                                  = {(sumaNum / 12).toFixed(2)} €/mes.
                                </div>
                              )}
                              <span className="ed-select-print">
                                {suma ? suma + ' € / rok = ' + (sumaNum / 12).toFixed(2) + ' € / mes.' : '—'}
                              </span>
                            </td>
                          );
                        })}
                        <td className="no-copy no-print" style={{ verticalAlign: 'top', padding: '4px 0' }}>
                          <button
                            type="button"
                            onClick={() => removePolozka('rocne', polozkaId)}
                            aria-label="Odstrániť položku"
                            title="Odstrániť položku"
                            style={{ background: 'transparent', border: 0, cursor: 'pointer', color: 'var(--ink-4)', fontSize: 14, padding: '0 6px' }}
                          >✕</button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
                <button
                  type="button"
                  className="party-add no-copy no-print"
                  onClick={() => addPolozka('rocne')}
                  style={{ alignSelf: 'flex-start' }}
                >+ Pridať položku</button>
              </>
            )}
          </div>

          {/* 4.3 — Súčty a priemery */}
          {filledKids.length > 0 && (
            <div style={{ marginBottom: 24 }}>
              <p style={{ margin: '12px 0 6px' }}><strong>4.3 Súčty výdavkov</strong></p>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {filledKids.map(kid => {
                  const v = spocitajVydavky(cl4.vydavkyMesacne, cl4.vydavkyRocne, kid.id);
                  return (
                    <div key={kid.id} style={{ padding: '10px 14px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)' }}>
                      <div style={{ fontWeight: 600, marginBottom: 6 }}>
                        {kid.meno || '(meno?)'}{kid.datumNarodenia ? ', nar. ' + kid.datumNarodenia : ''}
                      </div>
                      <div style={{ fontSize: '0.92em', lineHeight: 1.6 }}>
                        Mesačné výdavky spolu: <strong>{v.mesacne.toFixed(2)} €</strong><br />
                        Ročné výdavky spolu: <strong>{v.rocne.toFixed(2)} €</strong><br />
                        Ročné prepočítané mesačne (1/12): <strong>{v.rocnePrepocitane.toFixed(2)} €</strong><br />
                        <span style={{ fontWeight: 600, color: 'var(--oxblood)' }}>
                          Priemerné mesačné výdavky na dieťa: {v.priemernaSumaMesacne.toFixed(2)} €
                        </span>
                      </div>
                    </div>
                  );
                })}
                {filledKids.length > 1 && (() => {
                  const total = filledKids.reduce((acc, kid) => {
                    const v = spocitajVydavky(cl4.vydavkyMesacne, cl4.vydavkyRocne, kid.id);
                    return acc + v.priemernaSumaMesacne;
                  }, 0);
                  return (
                    <div style={{ padding: '10px 14px', background: 'var(--paper)', borderRadius: 'var(--r-sm)', border: '1px solid var(--oxblood)', fontWeight: 600 }}>
                      Priemerné mesačné výdavky na všetky maloleté deti spolu: <span style={{ color: 'var(--oxblood)' }}>{total.toFixed(2)} €</span>
                    </div>
                  );
                })()}
              </div>
            </div>
          )}

          {/* 4.4 — Majetkové pomery navrhovateľa */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="4.4-pomery-navrh" />
            <p style={{ margin: '12px 0 6px' }}><strong>4.4 Majetkové pomery {oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')}</strong></p>
            <p className="no-copy no-print" style={{ fontStyle: 'italic', fontSize: '0.85em', color: 'var(--ink-3)', margin: '0 0 8px' }}>
              Uvádzam svoje aktuálne majetkové pomery na účel posúdenia určenia výšky vyživovacej povinnosti podľa § 62 ods. 2 zákona č. 36/2005 Z. z. o rodine.
            </p>

            {/* Status radio */}
            <div className="no-copy no-print" style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: '0.92em', padding: '10px 12px', background: 'var(--ivory-2)', borderRadius: 'var(--r-sm)', border: '1px solid var(--rule)', marginBottom: 8 }}>
              <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>Aktuálny pracovný a ekonomický status:</div>
              {Object.entries(STATUS_LABELS).map(([v, label]) => (
                <label key={v} style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer' }}>
                  <input
                    type="radio"
                    name="cl4-pomer-status"
                    value={v}
                    checked={cl4.navrhPomerStatus === v}
                    onChange={() => setCl4Field('navrhPomerStatus', v)}
                  />
                  <span>{label}</span>
                </label>
              ))}
              {cl4.navrhPomerStatus === 'g' && (
                <div style={{ marginTop: 6, display: 'flex', gap: 8, alignItems: 'baseline' }}>
                  <span>Vlastný popis:</span>
                  <input
                    type="text"
                    value={cl4.navrhPomerInecaste}
                    onChange={(e) => setCl4Field('navrhPomerInecaste', e.target.value)}
                    style={{ flex: 1, padding: '4px 8px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', fontFamily: 'var(--serif)', fontSize: '0.95em' }}
                  />
                </div>
              )}
            </div>

            {/* Materializovaný status pre PDF/Word. Pri statuse 'g' (Iné) sa zobrazí
                len obsah Ed poľa navrhPomerInecaste, bez prefixu "Iné — ". Ak je
                Ed prázdny, inline placeholder no-print upozorní na chýbajúci údaj. */}
            <p style={{ margin: '8px 0' }}>
              <strong>Pracovný a ekonomický status:</strong>{' '}
              {cl4.navrhPomerStatus === 'g'
                ? (cl4.navrhPomerInecaste.trim()
                    ? cl4.navrhPomerInecaste
                    : <PetitPh>[doplňte status v Čl. IV bod 4.4]</PetitPh>)
                : statusLabel(cl4.navrhPomerStatus)}.
            </p>

            {/* Štruktúrované polia (vždy zobrazené) */}
            <p style={{ margin: '8px 0' }}>
              Zamestnávateľ / firma / inštitúcia: <Ed defaultValue="" placeholder="názov a sídlo zamestnávateľa, firmy alebo inštitúcie" lg />
            </p>
            <p style={{ margin: '8px 0' }}>
              Pozícia / predmet podnikania: <Ed defaultValue="" placeholder="pozícia alebo predmet podnikania" lg />
            </p>
            <p style={{ margin: '8px 0' }}>
              Mesačný čistý príjem (priemer za posledných 12 mesiacov): <Ed defaultValue="" placeholder="priemerný mesačný čistý príjem" num /> €
            </p>

            {/* Súhrnný opis — Ed block + sample */}
            <div style={{ marginTop: 12 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
                <strong>Súhrnný opis pomerov {oznacenie('navrhovatel', navrhovatelPohlavie, 'gen')}</strong>
                <button
                  className="no-copy no-print"
                  onClick={() => setShowSample44(!showSample44)}
                  style={{ fontSize: '0.78em', padding: '3px 10px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'var(--paper)', cursor: 'pointer', color: 'var(--ink-2)' }}
                >{showSample44 ? 'Skryť vzor' : 'Zobraziť vzor textu'}</button>
              </div>
              {showSample44 && (() => {
                const text = sample44(cl4.navrhPomerStatus, navrhovatelPohlavie);
                if (!text) {
                  return (
                    <div className="no-copy no-print" style={{ background: 'var(--ivory-2)', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', padding: '12px 16px', margin: '0 0 8px', fontSize: '0.88em', fontStyle: 'italic', color: 'var(--ink-3)' }}>
                      Pri statuse „Iné" nie je k dispozícii predvyplnený vzor — vyplňte vlastnými slovami.
                    </div>
                  );
                }
                return (
                  <div className="no-copy no-print" style={{ background: 'var(--ivory-2)', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', padding: '14px 18px', margin: '0 0 8px' }}>
                    <div style={{ fontFamily: 'var(--mono)', fontSize: '0.78em', letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 8 }}>
                      Vzorový text — len ako inšpirácia ({statusLabel(cl4.navrhPomerStatus)})
                    </div>
                    <p style={{ margin: 0, fontSize: '0.92em', color: 'var(--ink-2)', lineHeight: 1.55, fontStyle: 'italic' }}>{text}</p>
                    <div style={{ marginTop: 14, display: 'flex', gap: 8 }}>
                      <UsePatternButton onClick={() => { fillSampleText('cl4_44_Ref', text); setShowSample44(false); }} />
                      <button
                        onClick={() => setShowSample44(false)}
                        style={{ fontSize: '0.82em', padding: '6px 14px', border: '1px solid var(--rule)', borderRadius: 'var(--r-sm)', background: 'transparent', cursor: 'pointer', color: 'var(--ink-3)' }}
                      >Zatvoriť</button>
                    </div>
                  </div>
                );
              })()}
              <Ed block ref={cl4_44_Ref} placeholder="Sem vložte podrobnejší opis svojich majetkových pomerov — kliknite na 'Zobraziť vzor textu' a 'Použiť tento text'." />
            </div>
          </div>

          {/* 4.5 — Majetkové pomery odporcu (voliteľné) */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="4.5-pomery-odp" />
            <p style={{ margin: '12px 0 6px' }}><strong>4.5 Majetkové pomery {oznacenie('odporca', odporcaPohlavie, 'gen')} (voliteľné)</strong></p>
            <p style={{ margin: '0 0 8px' }}>
              Údaje o majetkových pomeroch {oznacenie('odporca', odporcaPohlavie, 'gen')} sú navrhovateľovi známe len v obmedzenom rozsahu. Súd ich v zmysle zákona č. 161/2015 Z. z. (Civilný mimosporový poriadok) zistí samostatne, najmä výzvou {oznacenie('odporca', odporcaPohlavie, 'dat')} na predloženie dôkazov o príjmoch a majetkových pomeroch.
            </p>
            <div className="no-copy no-print" style={{ marginTop: 8 }}>
              <label style={{ display: 'flex', gap: 8, alignItems: 'baseline', cursor: 'pointer', fontSize: '0.92em' }}>
                <input
                  type="checkbox"
                  checked={cl4.uvadzamPomerOdporcu}
                  onChange={() => setCl4Field('uvadzamPomerOdporcu', !cl4.uvadzamPomerOdporcu)}
                />
                <span>Uvádzam aj približné majetkové pomery {oznacenie('odporca', odporcaPohlavie, 'gen')} (voliteľné)</span>
              </label>
            </div>
            {cl4.uvadzamPomerOdporcu && (
              <div style={{ marginTop: 8 }}>
                <strong>Opis pomerov {oznacenie('odporca', odporcaPohlavie, 'gen')}</strong>
                <Ed
                  block
                  ref={cl4_45_Ref}
                  placeholder="Uveďte, čo viete o pracovnej situácii, príjmoch a majetkových pomeroch druhého rodiča. Ak presné údaje nepoznáte, uveďte približne."
                />
              </div>
            )}
          </div>

          {/* Sub-blok Dôkazy — analogický k Dôkaz v Čl. I, ale ako voľné Ed
              pole. Riadky sa konsolidujú do prílohovej sekcie na konci dokumentu. */}
          <div className="has-tip" style={{ marginBottom: 24 }}>
            <TipBtn pointKey="4-dokazy" />
            <p style={{ margin: '12px 0 6px' }}><strong>Dôkazy</strong></p>
            <p style={{ margin: '0 0 8px' }}>
              Na preukázanie skutočností uvedených v tomto článku predkladám súdu tieto dôkazy:
            </p>
            {/* Wrapper s CSS var pre kratšie min-height (cca 2 riadky).
                Persist scope identifikácia ide cez data-placeholder text Ed
                elementu, ktorý je rovnaký ako PH_4DOKAZY constant v listenere. */}
            <div style={{ '--ed-block-min-height': '60px' }}>
              <Ed
                block
                ref={cl4_dokazy_Ref}
                placeholder="Sem napíšte zoznam dôkazov, každý dôkaz na samostatný riadok. Napríklad: potvrdenie o priemernom čistom mesačnom zárobku od zamestnávateľa, daňové priznanie za minulý rok, výpis z katastra nehnuteľností, potvrdenie z úradu práce o evidencii a výške dávky v nezamestnanosti."
              />
            </div>
          </div>
        </section>

        {/* Čl. V — Právny základ a návrh výroku (pôvodne Čl. IV; po zavedení
            nového Čl. IV "Pomery rodičov a výdavky" sa renumberoval na V).
            Page-break: žiadny forced break-before; .article-intro drží header
            a prvý odsek 5.1 (§ 23) pohromade cez page-break-inside: avoid. */}
        <section className="article" id="art-5">
          <div className="article-intro">
            <div className="article-head">
              <div className="article-num">Článok V</div>
              <span className="article-title">Právny základ a návrh výroku</span>
            </div>

            <p>
              <strong>5.1</strong>&nbsp;&nbsp;Podľa § 23 ods. 1 zákona č. 36/2005 Z. z. o rodine súd môže manželstvo na návrh niektorého z manželov rozviesť, ak sú vzťahy medzi manželmi tak vážne narušené a trvalo rozvrátené, že manželstvo nemôže plniť svoj účel a od manželov nemožno očakávať obnovenie manželského spolužitia.
            </p>
          </div>

          <p>
            Podľa § 24 ods. 1 zákona č. 36/2005 Z. z. o rodine v rozhodnutí o rozvode súd zároveň upraví výkon rodičovských práv a povinností k maloletým deťom na čas po rozvode, najmä určí, komu sa maloleté deti zverujú do osobnej starostlivosti, kto ich bude zastupovať a spravovať ich majetok, ako má rodič, ktorému dieťa nebolo zverené, prispievať na jeho výživu, prípadne schváli dohodu rodičov o styku alebo upraví styk dieťaťa s rodičom, ktorému nebolo zverené.
          </p>

          <p>
            Podľa § 62 ods. 2 zákona č. 36/2005 Z. z. o rodine pri určení výživného súd prihliada na odôvodnené potreby oprávneného, ako aj na schopnosti, možnosti a majetkové pomery povinného.
          </p>

          <p>
            Podľa § 25 zákona č. 36/2005 Z. z. o rodine rodičia sa môžu o úprave styku s maloletým dieťaťom dohodnúť. Ak sa rodičia nedohodnú alebo ak to vyžaduje záujem na výchove dieťaťa, súd styk rodičov s maloletým dieťaťom upraví.
          </p>

          <p>
            <strong>5.2</strong>&nbsp;&nbsp;S ohľadom na uvedené žiadame súd, aby manželstvo rozviedol a zároveň upravil výkon rodičovských práv a povinností k maloletým deťom na čas po rozvode podľa § 24 a nasl. zákona č. 36/2005 Z. z. o rodine.
          </p>

          <p className="has-tip" style={{ margin: '12px 0' }}>
            <TipBtn pointKey="5.3" />
            <strong>5.3</strong> Na základe vyššie uvedeného navrhujem, aby súd po vykonanom dokazovaní vydal tento:
          </p>
        </section>

        {/* Návrh výroku — dynamicky generovaný cez generujPetit() na základe
            volieb v Čl. III a kids/sobáš state-u. Indexácia výrokov (I, II,
            III, IV, V) je pure-function výsledok; chýbajúce výroky (napr. IV
            pri striedavke) sa preskočia a posledný výrok sa preindexuje. */}
        <section className="proposed-verdict" id="art-verdict">
          <h3 className="verdict-heading">r o z s u d o k :</h3>

          {filledKids.length === 0 && (
            <p style={{ fontStyle: 'italic', color: 'var(--ink-3)', margin: '8px 0 16px', textAlign: 'center' }}>
              [doplňte aspoň jedno maloleté dieťa v sekcii účastníkov]
            </p>
          )}

          {generujPetit({
            navrhovatelPohlavie, odporcaPohlavie,
            menoNavrhovatela, menoOdporcu,
            datumSobasa, miestoSobasa, maticnyUrad, zvazok, rocnik, strana, poradoveCislo,
            filledKids, cl3,
            ed33bContent, ed35Content,
            getVyzivne,
          }).map((vyrok, i) => (
            <div key={vyrok.label + '-' + i} style={{ margin: '12px 0' }}>
              {vyrok.paragraphs.map((para, j) => (
                <p key={j} style={{ margin: j === 0 ? '0 0 6px' : '6px 0', textAlign: 'justify' }}>
                  {j === 0 && <><strong>{vyrok.label}.</strong>&nbsp;&nbsp;</>}
                  {para}
                </p>
              ))}
            </div>
          ))}
        </section>

        {/* Záverečná časť — podpis + prílohy spolu, aby sa nezalomili na rôzne strany */}
        <div style={{ pageBreakInside: 'avoid', breakInside: 'avoid' }}>
          <div className="signature-row" style={{ marginTop: 24, display: 'flex', justifyContent: 'flex-end' }}>
            <div style={{ textAlign: 'center', minWidth: 240 }}>
              <div style={{ borderBottom: '1px solid var(--ink)', marginBottom: 6, height: 28 }}></div>
              <div className="no-print" style={{ fontFamily: 'var(--serif)' }}>{menoNavrhovatela}</div>
              <span className="ed-select-print">{menoNavrhovatela}</span>
            </div>
          </div>

          {/* Prílohy */}
          <div className="prilohy" style={{ marginTop: 36 }}>
            <p><TipBtn pointKey="prilohy" /><strong>Prílohy:</strong></p>
            <p>– sobášny list</p>
            {/* Rodné listy maloletých detí — pre každé vyplnené dieťa s menom
                aj dátumom narodenia. Analogicky k blokom dôkazov v Čl. I. */}
            {filledKids
              .filter(k => k.meno.trim() !== '' && k.datumNarodenia.trim() !== '')
              .map(kid => (
                <p key={'rodlist-' + kid.id}>– rodný list maloletého dieťaťa - {kid.meno.trim()}, nar. {kid.datumNarodenia.trim()}</p>
              ))
            }
            {/* Konsolidácia dôkazov z Čl. IV — každý non-empty riadok ako "Dôkaz: {text}". */}
            {ed4DokazyContent.split('\n').map(line => line.trim()).filter(Boolean).map((line, i) => (
              <p key={'4dokaz-' + i}>– {line}</p>
            ))}
            <p>
              {dalsieDokazy && (
                <span className="ed-select-print">– {dalsieDokazy}</span>
              )}
              <span className="no-print">– <SyncedEd value={dalsieDokazy} onChange={setDalsieDokazy} placeholder="ďalšie dôkazy" /></span>
            </p>
          </div>
        </div>

      </article>

      {/* Actions — obrazovka only, print/Word skrýva (CSS ich rieši cez @media print) */}
      <div className="paper-actions no-print" role="group" aria-label="Akcie s návrhom">
        <div className="paper-actions__row">
          <button type="button" className="btn-download" onClick={() => window.print()}>
            <span className="btn-download__glyph" aria-hidden="true">↓</span>
            <span className="btn-download__main">Stiahnuť ako PDF</span>
            <span className="btn-download__meta">A4</span>
          </button>
          <button type="button" className="btn-download btn-download--ghost" onClick={() => window.__downloadAsDocDeti && window.__downloadAsDocDeti()}>
            <span className="btn-download__glyph" aria-hidden="true">↓</span>
            <span className="btn-download__main">Stiahnuť ako Word</span>
            <span className="btn-download__meta">.doc</span>
          </button>
          <button type="button" className="btn-download btn-download--danger" onClick={() => window.__clearFormFields && window.__clearFormFields()}>
            <span className="btn-download__glyph" aria-hidden="true">✕</span>
            <span className="btn-download__main">Vymazať údaje</span>
            <span className="btn-download__meta">natrvalo</span>
          </button>
        </div>
        <p className="paper-actions__note">
          PDF sa otvorí v dialógu tlače prehliadača — v cieli zvoľte <em>Uložiť ako PDF</em>. Word (.doc) otvoríte v MS Word alebo LibreOffice a môžete návrh ďalej upraviť.
        </p>
      </div>
    </div>
    </TipContext.Provider>
  );
};

// ============================================================
// downloadAsDoc — export paper HTML to .doc (Word)
// Class names referenced: .paper, .article, .article-head, .article-num,
// .article-title, .doc-title, .doc-sub, .ed, .ed-select, .ed-select-print,
// .paper-actions, .signatures, .sig-block, .sig-person, .sig-cap, .sig-name,
// .sig-line, .doc-footer-meta, .party-alias, .party-alias-term, .tip-pin
// ============================================================
function downloadAsDoc() {
  const article = document.querySelector('article.paper');
  if (!article) return;
  const clone = article.cloneNode(true);

  // 1) Remove chrome that has no meaning on paper
  const killSelectors = [
    '.tip-pin', '.tip-pin-inline', '.tip-back',
    '.seg-toggle', '.seg-add',
    '.party-add', '.party-type-switch', '.party-type-switch-sub',
    '.party-type-switch-wrap', '.inflation-variant-picker',
    '.legal-hint',
    '.no-copy', '.no-print',
  ];
  clone.querySelectorAll(killSelectors.join(',')).forEach(el => el.remove());

  // 2) Word ignoruje flex layout — .kid-row v parties-table sa renderuje
  // ako inline reťazec (meno + nar. + bytom na jednom riadku). Prepisujeme
  // každý .kid-row na sériu block-level <p> tagov (label + meno + nar. + bytom)
  // tak, aby Word zalomil každú časť na vlastný riadok.
  clone.querySelectorAll('.kid-row').forEach(row => {
    // Štruktúra: <div.kid-row><span>label</span><div(stack)>meno-span, nar-div, bytom-div</div>...</div>
    const labelSpan = row.querySelector(':scope > span');
    const stackDiv = row.querySelector(':scope > div');
    if (!labelSpan || !stackDiv) return;
    const labelText = (labelSpan.textContent || '').trim();
    // Meno = prvý priamy <span> v stack
    const menoSpan = stackDiv.querySelector(':scope > span');
    const menoText = menoSpan ? (menoSpan.textContent || '').trim() : '';
    // Sub-divy nar. + bytom — kompletný text vrátane prefixu
    const subDivs = Array.from(stackDiv.querySelectorAll(':scope > div'));
    const subTexts = subDivs.map(d => (d.textContent || '').replace(/\s+/g, ' ').trim());

    const newRow = document.createElement('div');
    newRow.style.marginBottom = '12px';
    const lines = [
      { text: labelText, bold: true, indent: false },
      { text: menoText,  bold: true, indent: true },
      ...subTexts.map(t => ({ text: t, bold: false, indent: true })),
    ];
    lines.forEach(({ text, bold, indent }) => {
      if (!text) return;
      const p = document.createElement('p');
      p.style.margin = '0';
      if (bold) p.style.fontWeight = 'bold';
      if (indent) p.style.marginLeft = '16px';
      p.textContent = text;
      newRow.appendChild(p);
    });
    row.replaceWith(newRow);
  });

  // 3) Replace <select.ed-select> with its selected option's label (plain text)
  clone.querySelectorAll('select.ed-select').forEach(sel => {
    const liveSel = findMatchingLiveElement(article, clone, sel);
    let label = '';
    if (liveSel && liveSel.options && liveSel.selectedIndex >= 0) {
      label = liveSel.options[liveSel.selectedIndex].textContent || '';
    } else {
      const first = sel.querySelector('option');
      label = first ? first.textContent : '';
    }
    const span = document.createElement('span');
    span.textContent = label;
    sel.parentNode.replaceChild(span, sel);
  });

  // 3b) Signature-row → align="right" tabuľka. MUSÍ bežať PRED step 4, ktorý unwrap-uje
  // .ed-select-print spany na text nody — inak by sme z signature-row už nevedeli prečítať
  // menoNavrhovatela (jediný element nesúci hodnotu po killovaní .no-print v step 2).
  // Word table layout: explicitné `width: 200pt` na <table> a `height: 36pt` na hornej
  // bunke — Word ignoruje `min-width` na <td>, takže bez tohto by sa bunka zmrštila na
  // šírku &nbsp; a podpisová čiara by vyzerala ako tenká pomlčka.
  clone.querySelectorAll('.signature-row').forEach(row => {
    const printSpan = row.querySelector('.ed-select-print');
    const meno = printSpan ? (printSpan.textContent || '').trim() : '';
    const wrap = document.createElement('div');
    wrap.setAttribute('align', 'right');
    wrap.style.cssText = 'margin-top:36pt;margin-bottom:18pt;';
    wrap.innerHTML =
      '<table align="right" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;width:200pt;">' +
        '<tr><td style="border-bottom:1px solid #000;height:36pt;line-height:36pt;padding:0;">&nbsp;</td></tr>' +
        '<tr><td style="text-align:center;padding-top:6pt;font-family:Georgia,serif;">' + meno + '</td></tr>' +
      '</table>';
    row.parentNode.replaceChild(wrap, row);
  });

  // 4) Mirror elements for selects (Ed komponent ich označuje aria-hidden="true")
  // — odstrániť úplne, lebo step 3 už nahradil <select> tým istým textom.
  // Ostatné .ed-select-print (autocomplete sud nazov, dalsie dokazy …) unwrap na text,
  // aby sa hodnota dostala do dokumentu (na obrazovke sú display:none).
  clone.querySelectorAll('.ed-select-print').forEach(el => {
    if (el.getAttribute('aria-hidden') === 'true') {
      el.remove();
      return;
    }
    const textNode = document.createTextNode(el.textContent || '');
    el.parentNode.replaceChild(textNode, el);
  });
  // Block-variant tej istej veci (adresa súdu v hlavičke) — unwrap so zachovaním
  // line-breaks (každý <div class="ed-select-print-block"> sa nahradí odsekom,
  // aby v Worde každý zostal na vlastnom riadku).
  clone.querySelectorAll('.ed-select-print-block').forEach(el => {
    const text = (el.textContent || '').trim();
    if (!text) { el.remove(); return; }
    const p = document.createElement('p');
    p.setAttribute('align', 'right');
    p.style.cssText = 'margin:0;line-height:1.5;text-align:right;';
    p.textContent = text;
    el.parentNode.replaceChild(p, el);
  });

  // 4d) Hlavička dokumentu — pravý stĺpec má byť zarovnaný vpravo a medzi
  // adresou súdu a riadkom „Bratislava, [dátum]" má byť prázdny odsek.
  const headerRight = clone.querySelector('.paper-header-right');
  if (headerRight) {
    headerRight.setAttribute('align', 'right');
    headerRight.style.textAlign = 'right';
    // Prázdny riadok pred odsekom obsahujúcim "Bratislava," (posledný <p> v stĺpci)
    const ps = headerRight.querySelectorAll(':scope > p');
    const dateP = ps[ps.length - 1];
    if (dateP) {
      dateP.setAttribute('align', 'right');
      dateP.style.textAlign = 'right';
      const spacer = document.createElement('p');
      spacer.style.cssText = 'margin:0;line-height:1.5;';
      spacer.innerHTML = '&nbsp;';
      dateP.parentNode.insertBefore(spacer, dateP);
    }
  }

  // 4c) party-grid → HTML tabuľka. CSS Grid je v Worde nespoľahlivý, label
  // a hodnota sa zlepujú. Tabuľka má každý label v ľavom stĺpci, hodnotu v
  // pravom; každý pár na vlastnom riadku. Spúšťa sa pred krokom 5 (unwrap .ed),
  // aby textContent .ed polí bol stále dostupný.
  clone.querySelectorAll('.party-grid').forEach(grid => {
    const children = Array.from(grid.children);
    const tbl = document.createElement('table');
    tbl.setAttribute('cellpadding', '0');
    tbl.setAttribute('cellspacing', '0');
    tbl.setAttribute('border', '0');
    tbl.style.cssText = 'border-collapse:collapse;width:100%;margin:0 0 8pt;';
    for (let i = 0; i < children.length; i += 2) {
      const labelEl = children[i];
      const valueEl = children[i + 1];
      if (!labelEl || !valueEl) break;
      // Hodnota zložená z viacerých detí (napr. meno + "rod.:" + rodné priezvisko)
      // spojí children textContent medzerou; jednoduché Ed pole použije svoj textContent.
      const elementChildren = Array.from(valueEl.children);
      const valueText = elementChildren.length > 0
        ? elementChildren.map(c => (c.textContent || '').trim()).filter(Boolean).join(' ')
        : (valueEl.textContent || '').trim();
      const tr = document.createElement('tr');
      const tdLabel = document.createElement('td');
      tdLabel.style.cssText = 'width:160px;vertical-align:baseline;padding:1pt 12pt 1pt 0;';
      tdLabel.textContent = (labelEl.textContent || '').trim();
      const tdValue = document.createElement('td');
      tdValue.style.cssText = 'vertical-align:baseline;padding:1pt 0;';
      tdValue.textContent = valueText;
      tr.appendChild(tdLabel);
      tr.appendChild(tdValue);
      tbl.appendChild(tr);
    }
    grid.parentNode.replaceChild(tbl, grid);
  });

  // 4e) Page-break-before — pred každý element s touto triedou vlož Word-specific
  // <br> s mso-special-character, ktorý Word interpretuje ako tvrdé zalomenie strany.
  // CSS page-break-before sa v staršom HTML-Word renderingu spoľahlivo neuplatní.
  clone.querySelectorAll('.page-break-before').forEach(el => {
    const br = document.createElement('br');
    br.setAttribute('clear', 'all');
    br.style.cssText = 'mso-special-character:line-break;page-break-before:always;';
    el.parentNode.insertBefore(br, el);
    // Doplniť aj inline style, nech moderný Word/LibreOffice zachytí oba mechanizmy.
    el.style.pageBreakBefore = 'always';
  });

  // 5) Turn contentEditable .ed spans into plain text.
  // .ed-block (Čl. II — kategórie 2.1-2.4, viacriadkový text) konvertujeme na <p>,
  // nie na <span>, aby Word korektne aplikoval text-align: justify (Word ho na
  // inline elementoch nehonoruje). white-space: pre-wrap zachová newliny.
  clone.querySelectorAll('.ed').forEach(ed => {
    const text = ed.textContent || '';
    if (ed.classList.contains('ed-block')) {
      const p = document.createElement('p');
      p.style.cssText = 'text-align:justify;white-space:pre-wrap;margin:0 0 10pt;';
      p.textContent = text;
      ed.parentNode.replaceChild(p, ed);
    } else {
      const span = document.createElement('span');
      span.textContent = text;
      ed.parentNode.replaceChild(span, ed);
    }
  });

  // 6) Remove download actions footer if it slipped in
  clone.querySelectorAll('.paper-actions').forEach(el => el.remove());

  // 6a) Convert signatures block into a 2-column TABLE — Word renders tables reliably
  //     (CSS grid & inline-block with fixed % are flaky in .doc HTML)
  const sigGrid = clone.querySelector('.signatures');
  if (sigGrid) {
    const blocks = Array.from(sigGrid.querySelectorAll(':scope > .sig-block'));
    const [left, right] = [blocks[0], blocks[1]];
    const table = document.createElement('table');
    table.setAttribute('width', '100%');
    table.setAttribute('cellpadding', '0');
    table.setAttribute('cellspacing', '0');
    table.setAttribute('border', '0');
    table.style.cssText = 'margin-top:48pt;width:100%;border-collapse:collapse;';
    const tr = document.createElement('tr');
    [left, right].forEach(b => {
      const td = document.createElement('td');
      td.setAttribute('width', '50%');
      td.style.cssText = 'width:50%;vertical-align:top;text-align:center;padding:0 12pt;';
      if (b) td.appendChild(b);
      tr.appendChild(td);
    });
    table.appendChild(tr);
    sigGrid.parentNode.replaceChild(table, sigGrid);
  }

  // 6b) Rebuild sig-block as a single table — Word respects table-cell padding
  // but applies automatic paragraph spacing to <div>s. Tables reliably stay tight.
  clone.querySelectorAll('.sig-block').forEach(block => {
    const outerCap = block.querySelector(':scope > .sig-cap');
    const persons = Array.from(block.querySelectorAll(':scope > .sig-person'));

    const tbl = document.createElement('table');
    tbl.setAttribute('width', '100%');
    tbl.setAttribute('cellpadding', '0');
    tbl.setAttribute('cellspacing', '0');
    tbl.setAttribute('border', '0');
    tbl.style.cssText = 'width:100%;border-collapse:collapse;';

    const mkRow = (html, css, innerCss) => {
      const tr = document.createElement('tr');
      const td = document.createElement('td');
      td.setAttribute('align', 'center');
      td.style.cssText = 'padding:0;text-align:center;line-height:1;' + (css || '');
      td.innerHTML =
        '<p align="center" style="margin:0;padding:0;text-align:center;' +
        'mso-margin-top-alt:0;mso-margin-bottom-alt:0;' +
        'mso-line-height-rule:exactly;line-height:115%;' + (innerCss || '') + '">' +
        html + '</p>';
      tr.appendChild(td);
      tbl.appendChild(tr);
    };

    if (outerCap) {
      mkRow(
        outerCap.textContent.trim().toUpperCase(),
        'padding:0 0 44pt;text-align:center;',
        "font-family:'IBM Plex Sans',Arial,sans-serif;font-size:9pt;letter-spacing:1.5pt;color:#555;text-align:center;"
      );
    }

    persons.forEach((person, idx) => {
      const cap  = person.querySelector('.sig-cap');
      const name = person.querySelector('.sig-name');
      if (idx > 0) {
        mkRow('&nbsp;', 'padding:28pt 0 0;', 'font-size:1pt;line-height:1pt;');
      }
      mkRow('&nbsp;', 'border-bottom:1px solid #0f1116;height:1pt;line-height:1pt;font-size:1pt;');
      mkRow(
        cap ? cap.textContent.trim().toUpperCase() : '',
        'padding-top:6pt;text-align:center;',
        "font-family:'IBM Plex Sans',Arial,sans-serif;font-size:9pt;letter-spacing:1.5pt;color:#555;text-align:center;"
      );
      mkRow(
        name ? name.textContent.trim() : '',
        'padding-top:3pt;text-align:center;',
        'font-size:10pt;font-style:italic;color:#666;text-align:center;'
      );
    });

    block.innerHTML = '';
    block.appendChild(tbl);
  });

  // 6c) Footer meta — Word doesn't flex; render as inline with dot separators
  const meta = clone.querySelector('.doc-footer-meta');
  if (meta) {
    const spans = Array.from(meta.querySelectorAll(':scope > span'));
    meta.innerHTML = spans.map(s => s.textContent.trim()).join(' &nbsp;·&nbsp; ');
  }

  // 7) Inline minimal styling — Word understands a subset of CSS
  const styles = `
    @page WordSection1 { size: A4; margin: 2cm 2cm 2.2cm 2cm; mso-footer: f1; mso-footer-margin: 1.2cm; }
    div.WordSection1 { page: WordSection1; }
    p.MsoFooter, li.MsoFooter, div.MsoFooter { margin: 0; padding: 0; mso-pagination: widow-orphan; text-align: center; font-family: "IBM Plex Mono", Consolas, monospace; font-size: 9pt; color: #888888; }
    body { font-family: "Libre Caslon Text", Georgia, serif; color: #0f1116; font-size: 12pt; line-height: 1.5; }
    .sig-block, .sig-block div, .sig-block p { mso-margin-top-alt: 0; mso-margin-bottom-alt: 0; }
    h1.doc-title { font-size: 16pt; text-align: center; letter-spacing: 2pt; margin: 0 0 6pt; text-transform: uppercase; font-weight: 700; }
    .doc-sub { text-align: center; font-family: "IBM Plex Mono", Consolas, monospace; font-size: 9pt; letter-spacing: 1.5pt; text-transform: uppercase; color: #555; margin: 0 0 18pt; }
    .doc-note { text-align: center; font-size: 9pt; color: #666; margin: 0 0 24pt; font-style: italic; }
    .article { margin: 0 0 22pt; }
    .article-head { text-align: center; margin: 22pt 0 10pt; }
    .article-num { font-family: "Libre Caslon Text", Georgia, serif; font-size: 13pt; font-weight: 700; letter-spacing: 3pt; text-transform: uppercase; }
    .article-title { display: block; font-style: italic; color: #333; font-size: 11pt; margin-top: 2pt; letter-spacing: 1pt; }
    p { margin: 0 0 10pt; text-align: justify; }
    strong { font-weight: 700; }
    em, i { font-style: italic; }
    .signatures { margin-top: 48pt; width: 100%; }
    .sig-block { display: inline-block; width: 48%; vertical-align: top; text-align: center; }
    .sig-block .sig-cap { margin: 0; padding: 0; }
    .sig-block .sig-cap + .sig-person .sig-line { margin-top: 36pt; }
    .sig-cap { font-family: "IBM Plex Sans", Arial, sans-serif; font-size: 9pt; letter-spacing: 1.5pt; text-transform: uppercase; color: #555; margin: 0; padding: 0; line-height: 1.3; }
    .sig-line { border-bottom: 1px solid #0f1116; margin: 36pt 0 4pt; height: 1pt; line-height: 1pt; font-size: 1pt; }
    .sig-name { font-size: 10pt; font-style: italic; color: #666; margin: 2pt 0 0; padding: 0; line-height: 1.3; }
    .sig-person { margin: 0; padding: 0; }
    .sig-person + .sig-person .sig-line { margin-top: 36pt; }
    .sig-person .sig-cap { margin-top: 2pt; }
    .doc-footer-meta { margin-top: 36pt; padding-top: 10pt; border-top: 1px solid #ccc; font-family: "IBM Plex Mono", Consolas, monospace; font-size: 8pt; letter-spacing: 1.5pt; text-transform: uppercase; color: #555; }
    .doc-footer-meta span { margin-right: 24pt; }
    .party-alias { font-style: italic; color: #555; margin-top: 6pt; font-size: 11pt; }
    .party-alias-term { font-style: normal; font-weight: 600; color: #0f1116; }
    .parties { margin: 18pt 0 24pt; }
    .party-line { margin: 0 0 4pt; }
    .paper-header { margin: 0 0 24pt; }
    .doc-date { margin-top: 24pt; }
    .proposed-verdict { margin: 24pt 0; padding: 18pt; border: 1pt solid #0f1116; background: #fafafa; }
    .verdict-heading { text-align: center; font-family: "Libre Caslon Text", Georgia, serif; font-size: 14pt; letter-spacing: 4pt; text-transform: uppercase; margin: 0 0 12pt; font-weight: 700; }
    .evidence { font-style: italic; color: #555; margin-top: 6pt; }
    .prilohy p { margin: 0 0 4pt; }
  `;

  // 8) Compose the Word HTML shell.
  // Footer cez @page mso-footer + <div mso-element:footer id="f1"> — Word renderuje
  // ako pravú pätičku na každej strane. Štýly riadi p.MsoFooter v <style> bloku
  // (center, mono 9pt, šedá). Footer div MUSÍ byť sibling .WordSection1, nie dieťa
  // — Word jeho obsah nezobrazí v toku dokumentu, len ho pripojí ako page footer.
  const body = clone.outerHTML;
  const footer = `<div style='mso-element:footer' id="f1"><p class="MsoFooter">Vytvorené pomocou webovej stránky - ziadostorozvod.sk</p></div>`;
  const html =
`<html xmlns:o="urn:schemas-microsoft-com:office:office"
       xmlns:w="urn:schemas-microsoft-com:office:word"
       xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta charset="utf-8" />
<title>Návrh na rozvod manželstva a úpravu výkonu práv a povinností rodičov k maloletým deťom na čas po rozvode</title>
<!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:Zoom>100</w:Zoom></w:WordDocument></xml><![endif]-->
<style>${styles}</style>
</head>
<body>
<div class="WordSection1">${body}</div>
${footer}
</body>
</html>`;

  // 9) Trigger download
  window.__lastDocHtml = html;
  const blob = new Blob(['﻿', html], { type: 'application/msword' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'navrh-na-rozvod-a-upravu-prav-k-detom.doc';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

// Helper: given cloned node, find corresponding live node in source tree
// (same relative position in the DOM).
function findMatchingLiveElement(liveRoot, cloneRoot, cloneEl) {
  const path = [];
  let n = cloneEl;
  while (n && n !== cloneRoot) {
    const p = n.parentNode;
    if (!p) break;
    path.unshift(Array.prototype.indexOf.call(p.children, n));
    n = p;
  }
  let cur = liveRoot;
  for (const idx of path) {
    if (!cur || !cur.children || !cur.children[idx]) return null;
    cur = cur.children[idx];
  }
  return cur;
}

window.PaperDeti = PaperDeti;
window.__downloadAsDocDeti = downloadAsDoc;
