/** Sticky nav, vocab search/filter, practice toggles — all lessons */ const $ = (sel, root = document) => root.querySelector(sel); const $$ = (sel, root = document) => [...root.querySelectorAll(sel)]; function normalize(s) { return (s || "") .toLowerCase() .normalize("NFD") .replace(/\p{M}/gu, ""); } function initStickyNav() { const nav = $(".lesson-nav"); if (!nav) return; const tabs = $$(".lesson-tab", nav); const sections = tabs .map((t) => { const id = (t.getAttribute("href") || "").slice(1); return id ? document.getElementById(id) : null; }) .filter(Boolean); const onScroll = () => { const y = window.scrollY + nav.offsetHeight + 24; let current = sections[0]?.id; for (const sec of sections) { if (sec.offsetTop <= y) current = sec.id; } tabs.forEach((t) => { const active = (t.getAttribute("href") || "") === `#${current}`; t.classList.toggle("is-active", active); }); }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); } function initVocabTools() { const grid = $("#vocab-grid"); const search = $("#vocab-search"); const chips = $$(".filter-chip"); const countEl = $("#vocab-count"); if (!grid) return; const cards = $$(".vocab-card", grid); let filter = "all"; const update = () => { const q = normalize(search?.value || ""); let visible = 0; cards.forEach((card) => { const cat = card.dataset.category || "otros"; const hay = normalize(card.dataset.search || card.textContent || ""); const okCat = filter === "all" || cat === filter; const okQ = !q || hay.includes(q); const show = okCat && okQ; card.hidden = !show; if (show) visible++; }); if (countEl) { countEl.textContent = visible === cards.length ? `${cards.length} palabras` : `${visible} de ${cards.length}`; } const empty = $("#vocab-empty"); if (empty) empty.hidden = visible > 0; }; search?.addEventListener("input", update); chips.forEach((chip) => { chip.addEventListener("click", () => { filter = chip.dataset.filter || "all"; chips.forEach((c) => c.classList.toggle("is-active", c === chip)); update(); }); }); update(); } function initPracticeToggle() { const btn = $("#practice-toggle"); const list = $("#practice-list"); if (!btn || !list) return; const items = $$("details", list); btn.addEventListener("click", () => { const open = btn.dataset.open !== "1"; btn.dataset.open = open ? "1" : "0"; btn.textContent = open ? "Ocultar respuestas" : "Mostrar todas las respuestas"; items.forEach((d) => { d.open = open; }); }); } function initSectionToggles() { $$("[data-toggle-section]").forEach((btn) => { const id = btn.dataset.toggleSection; const sec = id ? document.getElementById(id) : null; if (!sec) return; btn.addEventListener("click", () => { const collapsed = sec.classList.toggle("is-collapsed"); btn.setAttribute("aria-expanded", collapsed ? "false" : "true"); btn.textContent = collapsed ? btn.dataset.labelExpand || "Mostrar" : btn.dataset.labelCollapse || "Ocultar"; }); }); } function initDialogExpand() { const btn = $("#dialog-expand-all"); const root = $("#vocab-dialog-root"); if (!btn || !root) return; btn.addEventListener("click", () => { $$(".ant-collapse-header", root).forEach((h) => { if (!h.closest(".ant-collapse-item-active")) h.click(); }); }); } initStickyNav(); initVocabTools(); initPracticeToggle(); initSectionToggles(); initDialogExpand();