(function () {
    "use strict";
    const root = document.querySelector("[data-h4bs-staff-admin]");
    if (!root || typeof h4bsStaffData !== "object") return;
    const clone = (value) => JSON.parse(JSON.stringify(value));
    let workspace = clone(h4bsStaffData.workspace);
    let savedWorkspace = clone(workspace);
    let ownerConfirmation = "";
    let history = [], future = [], dirty = false, editingId = "", modalDirty = false, saving = false, editorTrigger = null, editingIsNew = false, editorApplied = false, editorSnapshot = null, editorDirtyBefore = false, editorHistoryBefore = [], editorFutureBefore = [], pendingRequestId = "", lastMovedId = "";
    const tiers = h4bsStaffData.tiers || {};
    const list = root.querySelector("[data-staff-list]");
    const editor = root.querySelector("[data-staff-editor]");
    const fields = root.querySelector("[data-staff-editor-fields]");
    const validation = root.querySelector("[data-staff-validation]");
    const saveState = root.querySelector("[data-staff-save-state]");
    const undo = root.querySelector("[data-staff-undo]");
    const redo = root.querySelector("[data-staff-redo]");
    root.querySelector("[data-staff-save]").textContent="Save changes";
    const esc = (value) => String(value == null ? "" : value).replace(/[&<>'"]/g, (char) => ({"&":"&amp;","<":"&lt;",">":"&gt;","'":"&#039;",'"':"&quot;"}[char]));
    const uid = () => "staff-" + Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
    const lines = (value) => Array.isArray(value) ? value.join("\n") : "";
    const split = (value) => String(value || "").split(/\r?\n/).map((item) => item.trim()).filter(Boolean);
    const syncDirty = () => {dirty=JSON.stringify(workspace)!==JSON.stringify(savedWorkspace);saveState.textContent=dirty?"Unsaved changes":"All changes saved";const saveButton=root.querySelector("[data-staff-save]");if(saveButton)saveButton.hidden=!dirty;};
    const mark = (previous) => { history.push(previous); history = history.slice(-50); future = []; syncDirty(); updateCommands(); render(); };
    const updateCommands = () => { undo.disabled = history.length === 0; redo.disabled = future.length === 0; };
    const change = (fn) => { const before = clone(workspace); fn(workspace); mark(before); };
    const profile = (id) => workspace.profiles.find((item) => item.id === id);
    const restoreEditorFocus = () => { const target=editorTrigger?.isConnected?editorTrigger:list.querySelector(`[data-profile-id="${CSS.escape(editingId)}"] [data-action="edit"]`);target?.focus(); };
    const updateBulk = () => { const count=list.querySelectorAll('[data-staff-select]:checked').length,label=root.querySelector('[data-staff-bulk-action]')?.closest('label'),button=root.querySelector('[data-staff-bulk-apply]');if(label)label.hidden=count===0;if(button)button.hidden=count===0;if(label)label.querySelector('span').textContent=count?`${count} selected`:"Selected profiles"; };

    function render() {
        const query = root.querySelector("[data-staff-search]").value.toLowerCase();
        const tier = root.querySelector("[data-staff-tier-filter]").value;
        const state = root.querySelector("[data-staff-state-filter]").value;
        const tierRank=Object.keys(tiers),shown = workspace.profiles.filter((item) => (!query || [item.name, ...(item.title_lines || []), ...(item.disciplines || [])].join(" ").toLowerCase().includes(query)) && (!tier || item.tier === tier) && (!state || item.state === state)).sort((a,b)=>{const tierDelta=tierRank.indexOf(a.tier)-tierRank.indexOf(b.tier);return tierDelta||Number(a.sort_order||0)-Number(b.sort_order||0)||a.name.localeCompare(b.name);});
        list.innerHTML = shown.map((item) => `<article class="h4bs-staff-row" draggable="${item.tier !== "owner"}" data-profile-id="${esc(item.id)}"><button type="button" class="h4bs-staff-drag" aria-label="Drag to reorder ${esc(item.name)}" ${item.tier === "owner" ? "disabled" : ""}>⋮⋮</button><div class="h4bs-staff-thumb">${item.portrait_url ? `<img src="${esc(item.portrait_url)}" alt="">` : ""}</div><div class="h4bs-staff-summary"><strong>${esc(item.name)}</strong><span>${esc((item.title_lines || []).join(" · "))}</span><small>${esc(tiers[item.tier] || item.tier)} · ${esc(item.state)}${item.owner_locked ? " · Protected owner" : ""}</small></div><div class="h4bs-staff-actions"><button type="button" class="button button-primary" data-action="edit">Edit profile</button>${item.tier === "owner" ? `<span class="description">Owner profile is protected</span>` : `<details class="h4bs-staff-more"><summary>More actions</summary><button type="button" class="button" data-action="duplicate">Duplicate</button><button type="button" class="button" data-action="transfer">Change protected owner</button><button type="button" class="button" data-action="archive">${item.state === "archived" ? "Restore" : "Archive"}</button><button type="button" class="button button-link-delete" data-action="remove">Remove</button></details>`}</div></article>`).join("");
        list.querySelectorAll("[data-profile-id]").forEach((row) => {
            const item = profile(row.dataset.profileId);
            const select = document.createElement("label");
            select.className = "h4bs-staff-select";
            select.innerHTML = `<input type="checkbox" data-staff-select aria-label="Select ${esc(item.name)}" ${item.tier === "owner" ? "disabled" : ""}>`;
            row.insertBefore(select, row.firstChild);
            const thumb=row.querySelector('.h4bs-staff-thumb');if(thumb&&!thumb.querySelector('img')){const initials=item.name.split(/\s+/).filter(Boolean).slice(0,2).map(part=>part[0]).join('').toUpperCase()||'?';thumb.innerHTML=`<span aria-hidden="true">${esc(initials)}</span>`;thumb.classList.add('is-fallback');}
            row.classList.toggle('is-owner',item.tier==='owner');row.classList.toggle('is-leadership',item.tier==='leadership');
            const meta=row.querySelector('.h4bs-staff-summary small');if(meta)meta.innerHTML=`<span class="h4bs-staff-badge is-tier">${esc(tiers[item.tier]||item.tier)}</span><span class="h4bs-staff-badge is-${esc(item.state)}">${esc(item.state==='published'?'Visible':item.state[0].toUpperCase()+item.state.slice(1))}</span>${item.owner_locked?'<span class="h4bs-staff-badge is-protected">Protected owner</span>':''}`;
            if(item.tier!=="owner"){const peers=workspace.profiles.filter(value=>value.tier===item.tier).sort((a,b)=>a.sort_order-b.sort_order),position=peers.findIndex(value=>value.id===item.id),order=document.createElement('div');order.className='h4bs-staff-order';order.setAttribute('aria-label',`Reorder ${item.name}`);order.innerHTML=`<button type="button" class="button" data-action="up" aria-label="Move ${esc(item.name)} up" ${position===0?"disabled":""}>↑</button><button type="button" class="button" data-action="down" aria-label="Move ${esc(item.name)} down" ${position===peers.length-1?"disabled":""}>↓</button>`;row.insertBefore(order,row.querySelector('.h4bs-staff-drag').nextSibling);}
        });
        [...new Set(shown.map(item=>item.tier))].forEach(tierKey=>{const firstItem=shown.find(item=>item.tier===tierKey),first=firstItem?list.querySelector(`[data-profile-id="${CSS.escape(firstItem.id)}"]`):null;if(!first)return;const count=shown.filter(item=>item.tier===tierKey).length,heading=document.createElement('h2');heading.className='h4bs-staff-tier-heading';heading.innerHTML=`<span>${esc(tiers[tierKey]||tierKey)}</span><small>${count} ${count===1?'person':'people'}</small>`;first.before(heading);});
        root.querySelector("[data-staff-empty]").hidden = shown.length > 0;
        updateBulk();
        if(editorTrigger&&!editorTrigger.isConnected&&editingId)editorTrigger=list.querySelector(`[data-profile-id="${CSS.escape(editingId)}"] [data-action="edit"]`);
        renderPresentation();
    }

    function blank() {
        return {id:uid(),name:"",slug:"",tier:"faculty",sort_order:workspace.profiles.length,state:"draft",owner_locked:false,featured:false,portrait_id:0,portrait_url:"",portrait_alt:"",focal_desktop:"50% 35%",focal_tablet:"50% 35%",focal_mobile:"50% 30%",crop_mode:"cover",span_desktop:4,span_tablet:6,span_mobile:12,title_lines:[],disciplines:[],credentials:[],short_bio:"",full_bio:"",email:"",phone:"",cta_label:"View profile",cta_url:"",social_links:[],seo_title:"",seo_description:"",schema_job_title:"",schema_works_for:"",schema_same_as:[],internal_links:[],extensions:{}};
    }

    function openEditor(item, isNew = false) {
        editorSnapshot=clone(workspace);editorDirtyBefore=dirty;editorHistoryBefore=clone(history);editorFutureBefore=clone(future);editingIsNew=isNew;editorApplied=false;if(isNew)workspace.profiles.push(item);
        editingId = item.id;
        modalDirty = false;
        validation.hidden = true;
        const option = (value, label) => `<option value="${esc(value)}" ${item.tier === value ? "selected" : ""}>${esc(label)}</option>`;
        const focal = String(item.focal_desktop || "50% 35%").match(/(\d+)%\s+(\d+)%/) || [0,50,35];
        const portrait = item.portrait_url ? `<img src="${esc(item.portrait_url)}" alt="">` : `<span>No portrait selected</span>`;
        fields.innerHTML = `<div class="h4bs-staff-editor-layout">
        <section class="h4bs-staff-editor-section"><h3>Person and role</h3><div class="h4bs-staff-field-grid"><label><span>Name *</span><input name="name" value="${esc(item.name)}" required></label><label><span>Team group</span><select name="tier" ${item.owner_locked ? "disabled" : ""}>${Object.entries(tiers).map(([key,label])=>option(key,label)).join("")}</select></label><label class="wide"><span>Public role or title</span><textarea name="title_lines">${esc(lines(item.title_lines))}</textarea></label><label><span>Public visibility</span><select name="state" ${item.owner_locked ? "disabled" : ""}>${["published","draft","hidden","archived"].map(value=>`<option value="${value}" ${item.state===value?"selected":""}>${value[0].toUpperCase()+value.slice(1)}</option>`).join("")}</select></label><label class="h4bs-check"><input type="checkbox" name="featured" ${item.featured?"checked":""}><span>Feature this person</span></label></div>${item.owner_locked?`<div class="h4bs-owner-note"><strong>Protected owner profile</strong><p>This profile stays published and cannot be archived accidentally. Changing the protected owner is a separate confirmed task.</p></div>`:""}<p class="h4bs-duplicate-warning" data-duplicate-warning hidden></p></section>
        <section class="h4bs-staff-editor-section" data-h4bs-image-profile="portrait"><h3>Portrait</h3><div class="h4bs-portrait-tools"><div class="h4bs-portrait-preview" data-portrait-preview>${portrait}</div><div><button type="button" class="button" data-select-portrait>${item.portrait_url?"Replace":"Choose"} portrait</button> <button type="button" class="button" data-remove-portrait ${item.portrait_url?"":"disabled"}>Remove from profile</button><p class="description">Removing it here never deletes the Media Library original.</p></div></div><input type="hidden" name="portrait_id" value="${esc(item.portrait_id)}"><input type="hidden" name="portrait_url" value="${esc(item.portrait_url)}"><label><span>Image description</span><input name="portrait_alt" value="${esc(item.portrait_alt)}" aria-describedby="portrait-alt-help"></label><p id="portrait-alt-help" class="description">Describe the person when the photo adds meaning; leave blank only when it is decorative.</p><div class="h4bs-focal-controls"><label><span>Move focus left or right</span><input type="range" min="0" max="100" value="${esc(focal[1])}" data-focal-x></label><label><span>Move focus up or down</span><input type="range" min="0" max="100" value="${esc(focal[2])}" data-focal-y></label></div><div class="h4bs-public-previews"><figure><figcaption>Desktop card</figcaption><div class="h4bs-crop-preview is-desktop" data-crop-preview>${portrait}</div></figure><figure><figcaption>Mobile card</figcaption><div class="h4bs-crop-preview is-mobile" data-crop-preview>${portrait}</div></figure></div><input type="hidden" name="focal_desktop" value="${esc(item.focal_desktop)}"><input type="hidden" name="focal_tablet" value="${esc(item.focal_tablet)}"><input type="hidden" name="focal_mobile" value="${esc(item.focal_mobile)}"></section>
        <section class="h4bs-staff-editor-section"><h3>Bio and programs</h3><label><span>Short introduction</span><textarea name="short_bio" maxlength="320">${esc(item.short_bio)}</textarea></label><small data-bio-count>${String(item.short_bio||"").length} of 320 characters</small><label><span>Full biography</span><textarea name="full_bio">${esc(item.full_bio)}</textarea></label><label><span>Programs or specialties</span><textarea name="disciplines">${esc(lines(item.disciplines))}</textarea></label></section>
        <section class="h4bs-staff-editor-section"><h3>Contact</h3><div class="h4bs-staff-field-grid"><label><span>Email</span><input type="email" name="email" value="${esc(item.email)}"></label><label><span>Phone</span><input name="phone" value="${esc(item.phone)}"></label><label><span>Profile button text</span><input name="cta_label" value="${esc(item.cta_label)}"></label><label><span>Profile button link</span><input type="text" name="cta_url" value="${esc(item.cta_url)}" placeholder="/team/name/ or https://"></label></div></section>
        <details class="h4bs-staff-editor-advanced"><summary>Advanced display and search settings</summary><p>These values normally inherit from the site design. Change them only when this profile needs an exception.</p><div class="h4bs-staff-field-grid"><label><span>Photo fit</span><select name="crop_mode">${["cover","contain","natural"].map(value=>`<option ${item.crop_mode===value?"selected":""}>${value}</option>`).join("")}</select></label><label><span>Desktop card width (1–12)</span><input type="number" min="1" max="12" name="span_desktop" value="${esc(item.span_desktop)}"></label><label><span>Tablet card width (1–12)</span><input type="number" min="1" max="12" name="span_tablet" value="${esc(item.span_tablet)}"></label><label class="wide"><span>Credentials</span><textarea name="credentials">${esc(lines(item.credentials))}</textarea></label><label class="wide"><span>Social links, one per line as Name::https://address</span><textarea name="social_links">${esc((item.social_links||[]).map(link=>link.label+"::"+link.url).join("\n"))}</textarea></label><label><span>Search result title</span><input name="seo_title" value="${esc(item.seo_title)}"></label><label><span>Search result description</span><textarea name="seo_description">${esc(item.seo_description)}</textarea></label><label><span>Structured job title</span><input name="schema_job_title" value="${esc(item.schema_job_title)}"></label><label><span>Organization</span><input name="schema_works_for" value="${esc(item.schema_works_for)}"></label><label class="wide"><span>Verified profile URLs</span><textarea name="schema_same_as">${esc(lines(item.schema_same_as))}</textarea></label><label class="wide"><span>Related site pages</span><textarea name="internal_links">${esc(lines(item.internal_links))}</textarea></label></div></details></div>`;
        const altInput=fields.querySelector('[name="portrait_alt"]');
        altInput.closest('label').insertAdjacentHTML('beforebegin',`<label class="h4bs-check"><input type="checkbox" name="portrait_decorative" ${item.portrait_url&&!item.portrait_alt?"checked":""}><span>Photo is decorative; screen readers should skip it</span></label>`);
        fields.querySelector('#portrait-alt-help').textContent='If the photo adds information, uncheck decorative and briefly describe it.';
        const updateFocal=()=>{const x=fields.querySelector('[data-focal-x]').value,y=fields.querySelector('[data-focal-y]').value;fields.querySelectorAll('[data-crop-preview] img,[data-portrait-preview] img').forEach(image=>image.style.objectPosition=`${x}% ${y}%`);fields.querySelector('[name=focal_desktop]').value=`${x}% ${y}%`;fields.querySelector('[name=focal_tablet]').value=`${x}% ${y}%`;fields.querySelector('[name=focal_mobile]').value=`${x}% ${y}%`;};
        fields.querySelectorAll('input[type=range]').forEach(input=>input.addEventListener('input',updateFocal)); updateFocal();
        fields.querySelector('[name=short_bio]').addEventListener('input',event=>fields.querySelector('[data-bio-count]').textContent=`${event.target.value.length} of 320 characters`);
        fields.querySelector('[name=name]').addEventListener('input',event=>{const duplicate=workspace.profiles.some(value=>value.id!==editingId&&value.name.trim().toLowerCase()===event.target.value.trim().toLowerCase()),note=fields.querySelector('[data-duplicate-warning]');note.hidden=!duplicate;note.textContent=duplicate?"Another person has this name. Confirm their role and photo so visitors can tell them apart.":"";});
        fields.querySelector('[data-remove-portrait]').addEventListener('click',event=>{fields.querySelector('[name=portrait_id]').value='0';fields.querySelector('[name=portrait_url]').value='';fields.querySelector('[name=portrait_alt]').value='';fields.querySelector('[name=portrait_decorative]').checked=false;fields.querySelectorAll('[data-crop-preview],[data-portrait-preview]').forEach(box=>box.innerHTML='<span>No portrait selected</span>');event.target.disabled=true;fields.querySelector('[data-select-portrait]').textContent='Choose portrait';modalDirty=true;});
        editor.showModal();
        fields.addEventListener("input",()=>{modalDirty=true;}, {once:true});
        fields.querySelector('[name="name"]').focus();
    }

    function applyEditor() {
        const form = root.querySelector("[data-staff-editor-form]");
        const data = new FormData(form), current = profile(editingId), errors = [];
        const name = String(data.get("name") || "").trim();
        const portrait = String(data.get("portrait_url") || "");
        let alt = String(data.get("portrait_alt") || "").trim();
        if (!name) errors.push("Enter the staff member's name.");
        if (portrait && data.get("portrait_decorative")!=="on" && !alt) errors.push("Describe the portrait or mark it decorative.");
        const email=String(data.get("email")||"").trim(),url=String(data.get("cta_url")||"").trim(),phone=String(data.get("phone")||"").trim();
        if(email&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))errors.push("Enter a valid email address.");
        if(url){let valid=/^\/(?!\/)[a-z0-9_\-./?=#%]+$/i.test(url)&&!/[\\\u0000-\u001f]/.test(url);if(!valid){try{const parsed=new URL(url);valid=(parsed.protocol==='http:'||parsed.protocol==='https:')&&!/[\\\u0000-\u001f]/.test(url);}catch(error){valid=false;}}if(!valid)errors.push("Enter a site path such as /team/name/ or a complete http/https link.");}
        if(phone&&(!/^[+()\-\s.\d]+$/.test(phone)||(phone.match(/\d/g)||[]).length<7))errors.push("Enter a phone number with at least seven digits.");
        if (errors.length) { validation.innerHTML=`<strong>Check ${errors.length===1?"this field":"these fields"}:</strong><ul>${errors.map(error=>`<li>${esc(error)}</li>`).join("")}</ul>`; validation.hidden = false; validation.focus(); return false; }
        if(data.get("portrait_decorative")==="on")alt="";
        change(() => Object.assign(current, {
            name, slug:current.slug || name.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""), tier:current.owner_locked?"owner":String(data.get("tier")||"faculty"), state:current.owner_locked?"published":String(data.get("state")||"draft"), featured:data.get("featured")==="on", portrait_id:Number(data.get("portrait_id")||0), portrait_url:portrait, portrait_alt:alt, crop_mode:String(data.get("crop_mode")||"cover"), focal_desktop:String(data.get("focal_desktop")||"50% 35%"), focal_tablet:String(data.get("focal_tablet")||"50% 35%"), focal_mobile:String(data.get("focal_mobile")||"50% 30%"), span_desktop:Number(data.get("span_desktop")||4), span_tablet:Number(data.get("span_tablet")||6), title_lines:split(data.get("title_lines")), disciplines:split(data.get("disciplines")), credentials:split(data.get("credentials")), short_bio:String(data.get("short_bio")||""), full_bio:String(data.get("full_bio")||""), email:String(data.get("email")||""), phone:String(data.get("phone")||""), cta_label:String(data.get("cta_label")||"View profile"), cta_url:String(data.get("cta_url")||""), social_links:split(data.get("social_links")).map(line=>{const pair=line.split("::");return {label:(pair.shift()||"Profile").trim(),url:pair.join("::").trim()};}).filter(link=>link.url), seo_title:String(data.get("seo_title")||""), seo_description:String(data.get("seo_description")||""), schema_job_title:String(data.get("schema_job_title")||""), schema_works_for:String(data.get("schema_works_for")||""), schema_same_as:split(data.get("schema_same_as")), internal_links:split(data.get("internal_links"))
        }));
        editorApplied=true;return true;
    }

    function renderPresentation() {
        const box = root.querySelector("[data-staff-presentation]");
        box.innerHTML = `<div class="h4bs-staff-field-grid"><label><span>Desktop columns</span><input type="number" min="1" max="6" data-presentation="columns" value="${workspace.presentation.columns}"></label><label><span>Tablet columns</span><input type="number" min="1" max="4" data-presentation="columns_tablet" value="${workspace.presentation.columns_tablet}"></label><label class="h4bs-check"><input type="checkbox" data-presentation="show_tier_headings" ${workspace.presentation.show_tier_headings?"checked":""}><span>Show tier headings</span></label><label class="h4bs-check"><input type="checkbox" data-presentation="show_search" ${workspace.presentation.show_search?"checked":""}><span>Show staff search</span></label><label class="wide"><span>Empty-state message</span><input data-presentation="empty_text" value="${esc(workspace.presentation.empty_text)}"></label></div>`;
        const published=workspace.profiles.filter(item=>item.state==="published").sort((a,b)=>a.sort_order-b.sort_order).slice(0,8),card=item=>{const initials=item.name.split(/\s+/).filter(Boolean).slice(0,2).map(part=>part[0]).join('').toUpperCase();return `<article class="h4bs-team-preview-card ${item.owner_locked?'is-owner':''}"><div class="h4bs-team-preview-photo">${item.portrait_url?`<img src="${esc(item.portrait_url)}" alt="${esc(item.portrait_alt||'')}">`:`<span aria-hidden="true">${esc(initials)}</span>`}</div><div><strong>${esc(item.name)}</strong><span>${esc((item.title_lines||[])[0]||tiers[item.tier])}</span>${item.owner_locked?'<small>Founder / owner</small>':item.featured?'<small>Featured</small>':''}</div></article>`;};
        root.querySelector("[data-staff-preview]").innerHTML = `<div class="h4bs-team-preview"><section><h3>Desktop preview</h3><div class="h4bs-staff-preview-grid is-desktop">${published.map(card).join("")||"<p>No visible profiles yet.</p>"}</div></section><section><h3>Mobile preview</h3><div class="h4bs-staff-preview-grid is-mobile">${published.slice(0,4).map(card).join("")||"<p>No visible profiles yet.</p>"}</div></section></div>`;
    }

    function renderRecovery() {
        const box = root.querySelector("[data-staff-recovery]");
        const points = Array.isArray(h4bsStaffData.recovery) ? h4bsStaffData.recovery : [];
        box.innerHTML = points.length ? points.map((point,index)=>{const prior=point.workspace||{},profiles=Array.isArray(prior.profiles)?prior.profiles:[],currentIds=new Set(workspace.profiles.map(item=>item.id)),priorIds=new Set(profiles.map(item=>item.id)),added=workspace.profiles.filter(item=>!priorIds.has(item.id)).length,removed=profiles.filter(item=>!currentIds.has(item.id)).length,changed=profiles.filter(item=>{const now=profile(item.id);return now&&JSON.stringify(now)!==JSON.stringify(item);}).length,date=point.created_at?new Date(String(point.created_at).replace(' ','T')+'Z'):null,human=date&&!Number.isNaN(date.valueOf())?date.toLocaleString(undefined,{dateStyle:'medium',timeStyle:'short'}):'Saved version';return `<article class="h4bs-recovery-card"><div><strong>${esc(human)}</strong><p>${changed} changed · ${added} added · ${removed} removed</p>${point.user_id?`<small>Saved by user #${Number(point.user_id)}</small>`:'<small>Editor information was not recorded.</small>'}</div><details><summary>Preview this version</summary><p>${profiles.length} profiles total; revision ${Number(prior.revision||0)}. Restoring first saves the current directory as a recovery point.</p><button type="button" class="button" data-staff-recover="${index}">Restore this version</button></details></article>`;}).join("") : "<div class=\"h4bs-empty-recovery\"><strong>No saved versions yet</strong><p>Versions appear here after directory changes are saved.</p></div>";
        box.querySelectorAll('.h4bs-recovery-card').forEach((card,index)=>{const point=points[index]||{},prior=Array.isArray(point.workspace?.profiles)?point.workspace.profiles:[],currentById=new Map(workspace.profiles.map(item=>[item.id,item])),priorById=new Map(prior.map(item=>[item.id,item])),items=[];workspace.profiles.filter(item=>!priorById.has(item.id)).forEach(item=>items.push(`Added ${item.name}`));prior.filter(item=>!currentById.has(item.id)).forEach(item=>items.push(`Removed ${item.name}`));prior.filter(item=>currentById.has(item.id)&&JSON.stringify(currentById.get(item.id))!==JSON.stringify(item)).forEach(item=>items.push(`Changed ${item.name}`));const details=card.querySelector('details');if(details&&items.length)details.querySelector('p').insertAdjacentHTML('afterend',`<ul>${items.slice(0,6).map(item=>`<li>${esc(item)}</li>`).join('')}${items.length>6?`<li>+${items.length-6} more changes</li>`:''}</ul>`);const small=card.querySelector('small');if(small)small.textContent=point.actor_name?`Saved by ${point.actor_name}`:'Editor information was not recorded.';});
    }

    async function save() {
        if (saving) return false;
        if (!dirty) return true;
        saving = true;
        const saveButton = root.querySelector("[data-staff-save]"); saveButton.disabled = true;
        const body = new URLSearchParams({action:"h4bs_staff_save",nonce:h4bsStaffData.nonce,revision:String(workspace.revision),workspace:JSON.stringify(workspace),owner_confirmation:ownerConfirmation});
        const payloadKey=body.toString();
        if(!pendingRequestId||save.pendingPayload!==payloadKey){pendingRequestId="staff-"+Date.now()+"-"+Math.random().toString(36).slice(2);save.pendingPayload=payloadKey;}
        saveState.textContent = "Saving…";
        try {
            const response=await fetch(h4bsStaffData.ajaxUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded","X-H4BS-Request-ID":pendingRequestId},body});
            const result=await response.json();
            if(response.status===409){const conflict=new Error("Someone else saved this directory. Your entered values are still here.");conflict.code=409;throw conflict;}
            if(!response.ok||!result.success)throw new Error(result.data?.message||"Save failed. Your changes are still here; try again.");
            workspace=result.data.workspace;savedWorkspace=clone(workspace);ownerConfirmation="";dirty=false;history=[];future=[];saveState.textContent=result.data.message||"Saved";saveButton.hidden=true;pendingRequestId="";save.pendingPayload="";updateCommands();render();return true;
        } catch(error) {
            saveState.textContent=error.message||"Save failed. Your changes are still here; try again.";
            if(error.code===409){validation.innerHTML='<strong>Review a newer saved version before retrying.</strong><p>Your form remains open and unchanged.</p><button type="button" class="button" data-copy-profile-draft>Copy my entered values</button> <button type="button" class="button" data-open-latest>Open latest in a new tab</button>';validation.hidden=false;validation.querySelector('[data-copy-profile-draft]').addEventListener('click',async()=>{const data=new FormData(root.querySelector('[data-staff-editor-form]'));await navigator.clipboard.writeText([...data].map(([key,value])=>`${key}: ${value}`).join('\n'));saveState.textContent='Entered values copied';});validation.querySelector('[data-open-latest]').addEventListener('click',()=>window.open(window.location.href,'_blank','noopener'));validation.focus();}
            return false;
        } finally {saving=false;saveButton.disabled=false;}
    }

    root.querySelector("[data-staff-add]").addEventListener("click",event=>{editorTrigger=event.currentTarget;openEditor(blank(),true);});
    list.addEventListener("click",event=>{const edit=event.target.closest('[data-action="edit"]');if(edit)editorTrigger=edit;},true);
    list.addEventListener("click",event=>{const move=event.target.closest('[data-action="up"],[data-action="down"]');if(move)lastMovedId=move.closest('[data-profile-id]').dataset.profileId;},true);
    list.addEventListener("click",event=>{const move=event.target.closest('[data-action="up"],[data-action="down"]');if(!move)return;const id=move.closest('[data-profile-id]').dataset.profileId,direction=move.dataset.action;setTimeout(()=>{const item=profile(id),peers=workspace.profiles.filter(value=>value.tier===item.tier).sort((a,b)=>a.sort_order-b.sort_order),position=peers.findIndex(value=>value.id===id)+1;saveState.textContent=`Moved ${item.name} to ${position} of ${peers.length} in ${tiers[item.tier]||item.tier}. Unsaved ordering.`;const focus=list.querySelector(`[data-profile-id="${CSS.escape(id)}"] [data-action="${direction}"]:not(:disabled)`)||list.querySelector(`[data-profile-id="${CSS.escape(id)}"] [data-action="${direction==='up'?'down':'up'}"]:not(:disabled)`)||list.querySelector(`[data-profile-id="${CSS.escape(id)}"] [data-action="edit"]`);focus?.focus();},0);},true);
    list.addEventListener("change",event=>{if(event.target.matches('[data-staff-select]'))updateBulk();});
    root.querySelector("[data-staff-editor-form]").addEventListener("submit",async event=>{event.preventDefault();if(saving||!applyEditor())return;const button=event.submitter,state=root.querySelector('[data-staff-editor-save-state]');button.disabled=true;state.textContent="Saving…";const saved=await save();button.disabled=false;if(saved){modalDirty=false;editorApplied=false;editingIsNew=false;state.textContent="Saved";editor.close();editorTrigger?.focus();}else{state.textContent="Not saved. Your entries are still here; try again.";if(validation.hidden){validation.textContent=saveState.textContent;validation.hidden=false;validation.focus();}}});
    const closeEditor=()=>{if((modalDirty||editorApplied)&&!confirm(`Discard unsaved edits to ${profile(editingId)?.name||"this profile"}?`))return;if(editingIsNew||editorApplied){workspace=clone(editorSnapshot);dirty=editorDirtyBefore;history=clone(editorHistoryBefore);future=clone(editorFutureBefore);saveState.textContent=dirty?"Unsaved changes":"All changes saved";root.querySelector('[data-staff-save]').hidden=!dirty;render();updateCommands();}modalDirty=false;editorApplied=false;editingIsNew=false;editor.close();editorTrigger?.focus();};root.querySelector("[data-staff-editor-close]").addEventListener("click",closeEditor); root.querySelector("[data-staff-editor-cancel]").addEventListener("click",closeEditor);editor.addEventListener("cancel",event=>{if(modalDirty||editorApplied){event.preventDefault();closeEditor();}});
    root.querySelector("[data-staff-save]").addEventListener("click",save);
    root.querySelector("[data-staff-bulk-apply]").addEventListener("click",()=>{const state=root.querySelector("[data-staff-bulk-action]").value;const ids=[...list.querySelectorAll("[data-staff-select]:checked")].map(input=>input.closest("[data-profile-id]").dataset.profileId);if(!state||!ids.length){saveState.textContent="Select profiles and an action first.";return;}if(!confirm(`Apply ${state} to ${ids.length} selected profiles? The protected owner is always excluded.`))return;change(data=>data.profiles.forEach(item=>{if(ids.includes(item.id)&&item.tier!=="owner")item.state=state;}));});
    root.querySelector("[data-staff-recovery]").addEventListener("click",async event=>{const button=event.target.closest("[data-staff-recover]");if(!button||!confirm("Restore this saved directory revision? The current directory will be saved first."))return;const body=new URLSearchParams({action:"h4bs_staff_recover",nonce:h4bsStaffData.nonce,index:button.dataset.staffRecover});const response=await fetch(h4bsStaffData.ajaxUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body});const result=await response.json();if(!result.success){saveState.textContent=result.data?.message||"Recovery failed";return;}workspace=result.data.workspace;savedWorkspace=clone(workspace);dirty=false;history=[];future=[];pendingRequestId="";save.pendingPayload="";root.querySelector('[data-staff-save]').hidden=true;saveState.textContent=result.data.message;render();updateCommands();});
    undo.addEventListener("click",()=>{if(!history.length)return;future.push(clone(workspace));workspace=history.pop();syncDirty();render();updateCommands();requestAnimationFrame(()=>{if(!undo.disabled)undo.focus();else if(lastMovedId)list.querySelector(`[data-profile-id="${CSS.escape(lastMovedId)}"] [data-action="edit"]`)?.focus();});}); redo.addEventListener("click",()=>{if(!future.length)return;history.push(clone(workspace));workspace=future.pop();syncDirty();render();updateCommands();requestAnimationFrame(()=>{if(!redo.disabled)redo.focus();else if(lastMovedId)list.querySelector(`[data-profile-id="${CSS.escape(lastMovedId)}"] [data-action="edit"]`)?.focus();});});
    list.addEventListener("click",event=>{const button=event.target.closest("button[data-action]");if(!button)return;const row=button.closest("[data-profile-id]"),item=profile(row.dataset.profileId),action=button.dataset.action;if(action==="edit")openEditor(item);if(action==="duplicate")change(data=>{const copy=clone(item);copy.id=uid();copy.name+=" copy";copy.slug+="-copy";copy.state="draft";copy.owner_locked=false;copy.tier=copy.tier==="owner"?"leadership":copy.tier;data.profiles.push(copy);});if(action==="transfer"){const current=workspace.profiles.find(value=>value.tier==="owner");const required=`TRANSFER ${current?.name||"OWNER"}`;if(prompt(`Type ${required} to make ${item.name} the protected owner/founder.`)!==required)return;ownerConfirmation=required;change(()=>{current.tier="leadership";current.owner_locked=false;current.sort_order=0;item.tier="owner";item.owner_locked=true;item.state="published";item.sort_order=0;});}if(action==="archive")change(()=>item.state=item.state==="archived"?"draft":"archived");if(action==="remove"&&confirm(`Remove ${item.name}? This can be recovered until the next five saves rotate.`))change(data=>data.profiles=data.profiles.filter(value=>value.id!==item.id));if(action==="up"||action==="down")change(data=>{const tierItems=data.profiles.filter(value=>value.tier===item.tier).sort((a,b)=>a.sort_order-b.sort_order);const at=tierItems.findIndex(value=>value.id===item.id),swap=action==="up"?at-1:at+1;if(swap<0||swap>=tierItems.length)return;[tierItems[at].sort_order,tierItems[swap].sort_order]=[tierItems[swap].sort_order,tierItems[at].sort_order];});});
    fields.addEventListener("click",event=>{if(!event.target.matches("[data-select-portrait]"))return;const frame=wp.media({title:"Select staff portrait",button:{text:"Use portrait"},multiple:false,library:{type:"image"}});frame.on("select",()=>{const image=frame.state().get("selection").first().toJSON();fields.querySelector('[name="portrait_id"]').value=image.id;fields.querySelector('[name="portrait_url"]').value=image.url;const alt=fields.querySelector('[name="portrait_alt"]');if(alt&&!alt.value)alt.value=image.alt||image.caption||"";fields.querySelectorAll("[data-portrait-preview],[data-crop-preview]").forEach(box=>box.innerHTML=`<img src="${esc(image.url)}" alt="">`);event.target.textContent="Replace portrait";fields.querySelector('[data-remove-portrait]').disabled=false;fields.querySelector('[data-focal-x]').dispatchEvent(new Event('input'));modalDirty=true;});frame.open();});
    let draggingId = "";
    list.addEventListener("dragstart",event=>{const row=event.target.closest("[data-profile-id]");if(!row||profile(row.dataset.profileId)?.tier==="owner"){event.preventDefault();return;}draggingId=row.dataset.profileId;event.dataTransfer.effectAllowed="move";});
    list.addEventListener("dragover",event=>{const row=event.target.closest("[data-profile-id]");if(!row||!draggingId||profile(row.dataset.profileId)?.tier!==profile(draggingId)?.tier)return;event.preventDefault();event.dataTransfer.dropEffect="move";});
    list.addEventListener("drop",event=>{const row=event.target.closest("[data-profile-id]");if(!row||!draggingId)return;event.preventDefault();const target=profile(row.dataset.profileId),source=profile(draggingId);if(!target||!source||target.tier!==source.tier||target.id===source.id)return;change(data=>{const ordered=data.profiles.filter(item=>item.tier===source.tier).sort((a,b)=>a.sort_order-b.sort_order);const from=ordered.findIndex(item=>item.id===source.id),to=ordered.findIndex(item=>item.id===target.id);ordered.splice(to,0,ordered.splice(from,1)[0]);ordered.forEach((item,index)=>item.sort_order=index);});draggingId="";});
    root.addEventListener("change",event=>{if(event.target.matches("[data-presentation]")){const key=event.target.dataset.presentation,value=event.target.type==="checkbox"?event.target.checked:event.target.value;change(data=>data.presentation[key]=value);}});
    ["[data-staff-search]","[data-staff-tier-filter]","[data-staff-state-filter]"].forEach(selector=>root.querySelector(selector).addEventListener(selector.includes("search")?"input":"change",render));
    root.querySelectorAll("[data-staff-tab]").forEach(button=>button.addEventListener("click",()=>{root.querySelectorAll("[data-staff-tab]").forEach(item=>item.classList.toggle("nav-tab-active",item===button));root.querySelectorAll("[data-staff-panel]").forEach(panel=>panel.hidden=panel.dataset.staffPanel!==button.dataset.staffTab);}));
    document.addEventListener("keydown",event=>{if((event.metaKey||event.ctrlKey)&&event.key.toLowerCase()==="s"){event.preventDefault();save();}if((event.metaKey||event.ctrlKey)&&event.key.toLowerCase()==="z"){event.preventDefault();event.shiftKey?redo.click():undo.click();}});
    window.addEventListener("beforeunload",event=>{if(dirty){event.preventDefault();event.returnValue="";}});
    const tierFilter=root.querySelector("[data-staff-tier-filter]");Object.entries(tiers).forEach(([key,label])=>tierFilter.insertAdjacentHTML("beforeend",`<option value="${esc(key)}">${esc(label)}</option>`));
    render(); renderRecovery(); updateCommands();
}());
