const main = document.getElementById('mainContent');
const nav = document.getElementById('bottomNav');
const toastEl = document.getElementById('toast');
const authGate = document.getElementById('authGate');
const authContent = document.getElementById('authContent');
const roleLabelEl = document.getElementById('sessionRoleLabel');

const ROLE_LABELS={supervisor:'Supervisor propietario',admin:'Administrador',nurse:'Enfermería',assistant:'Asistente',cook:'Cocina',cleaning:'Limpieza',maintenance:'Mantenimiento',security:'Seguridad',doctor:'Médico'};
const ROLE_PREFIX={supervisor:'SUPV',admin:'ADM',nurse:'ENF',assistant:'ASIS',cook:'COC',cleaning:'LIM',maintenance:'MANT',security:'SEG',doctor:'MED'};
let users=[];
let accessCodes=[];
let currentUser=null;
Object.defineProperty(window,'currentUser',{configurable:true,get(){return currentUser},set(value){currentUser=value}});
function saveUsers(){}
function saveAccessCodes(){}
function saveSession(){}
function hashPass(value){return String(value||'');}
function roleHomeCopy(role){
  if(role==='supervisor') return {eyebrow:'PANEL SUPERVISOR',text:'Administre clientes, licencias, administradores, accesos y soporte general de Bernard Health SeniorCare.'};
  if(role==='nurse') return {eyebrow:'PANEL DE ENFERMERÍA',text:'Supervise medicamentos, signos vitales, curaciones, incidentes y cuidados del turno.'};
  if(role==='assistant') return {eyebrow:'PANEL DE ASISTENTE',text:'Revise residentes asignados, cuidados diarios, alimentación, higiene y tareas pendientes.'};
  if(role==='cook') return {eyebrow:'PANEL DE COCINA',text:'Consulte dietas, tareas asignadas, alertas e incidentes del servicio de alimentación.'};
  if(role==='cleaning') return {eyebrow:'PANEL DE LIMPIEZA',text:'Registre su jornada, revise tareas, alertas e incidentes de limpieza.'};
  if(role==='maintenance') return {eyebrow:'PANEL DE MANTENIMIENTO',text:'Registre su jornada, atienda tareas, alertas e incidentes de mantenimiento.'};
  if(role==='security') return {eyebrow:'PANEL DE SEGURIDAD',text:'Registre su jornada, revise tareas, alertas e incidentes de seguridad.'};
  if(role==='doctor') return {eyebrow:'PANEL MÉDICO',text:'Complete el expediente, revise signos y resultados, emita indicaciones y recetas.'};
  return {eyebrow:'PANEL ADMINISTRATIVO',text:'Controle residentes, agenda, medicamentos, personal, usuarios y reportes.'};
}
function isAllowed(screen){
  const role=currentUser?.role||'assistant';
  const adminScreens=['home','medicalAppointmentsAdmin','medicalDashboard','medicalConsultation','medicalOrders','medicalUrgencyNotify','medicalResults','medicalAssessments','medicalHistory','medicalPrescriptions','medicalDocuments','medicalStudies','residents','inactive','resident','admissions','medications','vitals','care','wounds','agenda','incidents','nutrition','nursing','alerts','more','staff','handoff','inventory','reports','usersAccess','medicalNotes','operationalTasks'];
  const supervisorScreens=['home','supervisorOrganizations','supervisorOrganizationDetail','supervisorLicenses','supervisorAdmins','supervisorPayments','supervisorAudit','supervisorAlerts','supervisorSupport','supervisorMore'];
  const allow={
    supervisor:supervisorScreens,
    admin:adminScreens,
    doctor:['home','medicalAppointmentsDoctor','medicalDashboard','medicalConsultation','medicalOrders','medicalResults','medicalHistory','medicalPrescriptions','medicalStudies','vitals','medicalEmergencies'],
    nurse:['home','residents','resident','medications','vitals','care','wounds','agenda','incidents','nutrition','nursing','alerts','handoff','reports','medicalNotes','medicalOrders','medicalDocuments','medicalUrgencyNotify','medicalResults','staff','more'],
    assistant:['home','residents','resident','vitals','care','nutrition','agenda','incidents','alerts','handoff','more'],
    cook:['home','nutrition','operationalTasks','operationalIncidents','operationalAlerts'],
    cleaning:['home','operationalTasks','operationalIncidents','operationalAlerts'],
    maintenance:['home','operationalTasks','operationalIncidents','operationalAlerts'],
    security:['home','operationalTasks','operationalIncidents','operationalAlerts']
  };
  return allow[role]?.includes(screen);
}
function ensureAllowed(screen){return isAllowed(screen)?screen:'home';}
function generateAccessCode(role){
  const prefix=ROLE_PREFIX[role];
  const token=Math.random().toString(36).slice(2,8).toUpperCase();
  return `${prefix}-${token}`;
}
function normalizeRole(role){return role==='administrator'?'admin':role;}
function bhscLocalDate(value=new Date()){
  const parts=new Intl.DateTimeFormat('en-CA',{timeZone:'America/Costa_Rica',year:'numeric',month:'2-digit',day:'2-digit'}).formatToParts(value);
  const map=Object.fromEntries(parts.map(x=>[x.type,x.value]));
  return `${map.year}-${map.month}-${map.day}`;
}
window.BHSC_LOCAL_DATE=bhscLocalDate;
function friendlyAppError(error,fallback='No se pudo completar la operación.'){
  return window.BHSC_FRIENDLY_ERROR?.(error,fallback)||(error?.message||fallback);
}
async function appRetry(task,attempts=2){
  if(window.BHSC_WITH_RETRY)return window.BHSC_WITH_RETRY(task,attempts,650);
  let last;for(let i=0;i<attempts;i++){try{return await task();}catch(e){last=e;if(i+1<attempts)await new Promise(r=>setTimeout(r,650*(i+1)));}}throw last;
}
async function registerSessionEntry(profile,session,resolvedRole){
  const client=window.seniorcareSupabase;
  if(!client||!profile?.id||!session?.user)return;
  const stamp=session.user.last_sign_in_at||session.user.updated_at||session.expires_at||new Date().toISOString();
  const storageKey=`bhsc-entry:${profile.id}:${stamp}`;
  try{if(sessionStorage.getItem(storageKey))return;}catch(_){ }
  const now=new Date().toISOString();
  try{
    const touch=await client.from('profiles').update({last_seen_at:now}).eq('id',profile.id);
    if(touch.error)console.warn('[BHSC] No se pudo actualizar el último acceso:',touch.error.message||touch.error);
  }catch(error){console.warn('[BHSC] No se pudo actualizar el último acceso:',error);}
  if(resolvedRole==='admin'){
    try{
      const entry=await client.from('audit_logs').insert({organization_id:profile.organization_id||null,user_id:profile.id,action:'administrator_login',table_name:'profiles',record_id:String(profile.id),details:{name:profile.full_name||'',username:profile.username||'',email:session.user.email||'',logged_at:now}});
      if(entry.error)console.warn('[BHSC] No se pudo registrar la entrada del administrador:',entry.error.message||entry.error);
    }catch(error){console.warn('[BHSC] No se pudo registrar la entrada del administrador:',error);}
  }
  try{sessionStorage.setItem(storageKey,now);}catch(_){ }
}


async function bhscAttemptStaffAutoLink({client,session,code,fullName,email}={}){
  try{
    const supa=client||window.seniorcareSupabase;
    const user=session?.user;
    if(!supa||!user?.id||!window.BHSC_CALL_RPC)return false;
    const meta=user.user_metadata||{};
    const activationCode=String(code||meta.activation_code||meta.activationCode||'').trim().toUpperCase().replace(/[–—−]/g,'-').replace(/\s+/g,'');
    const payload={
      p_code:activationCode||null,
      p_full_name:String(fullName||meta.full_name||meta.fullName||user.email||'').trim(),
      p_email:String(email||user.email||'').trim().toLowerCase()
    };
    if(!payload.p_code&&!payload.p_full_name&&!payload.p_email)return false;
    const linked=await window.BHSC_CALL_RPC(['bh_link_staff_after_registration_v4375','bh_link_staff_after_registration_v4321'],payload);
    if(linked?.error){
      if(!window.BHSC_RPC_FUNCTION_MISSING?.(linked.error))console.warn('[BHSC] Vinculación automática pendiente:',linked.error.message||linked.error);
      return false;
    }
    return true;
  }catch(error){
    console.warn('[BHSC] No se pudo validar la vinculación automática:',error?.message||error);
    return false;
  }
}

async function loadSupabaseUser(session){
  const client=window.seniorcareSupabase;
  if(!client||!session?.user)return null;
  let profile=null;
  let lastError=null;
  for(let attempt=0;attempt<5;attempt++){
    try{
      const rpc=await appRetry(()=>window.BHSC_CALL_RPC?window.BHSC_CALL_RPC(['bh_get_my_profile_v4321','get_my_profile'],{}):client.rpc('get_my_profile'),2);
      if(!rpc.error){
        profile=Array.isArray(rpc.data)?rpc.data[0]:rpc.data;
        if(profile)break;
      }else lastError=rpc.error;
    }catch(error){lastError=error;}

    if(profile)break;
    try{
      const direct=await appRetry(()=>client.from('profiles')
        .select('id,full_name,username,role,active,organization_id')
        .eq('id',session.user.id)
        .maybeSingle(),2);
      if(!direct.error&&direct.data){profile=direct.data;break;}
      if(direct.error)lastError=direct.error;
    }catch(error){lastError=error;}

    if(attempt<4)await new Promise(resolve=>setTimeout(resolve,500*(attempt+1)));
  }
  if(!profile){
    if(window.BHSC_IS_NETWORK_ERROR?.(lastError))throw new Error(friendlyAppError(lastError));
    const detail=lastError?.message?` (${lastError.message})`:'';
    throw new Error(`La cuenta inició sesión, pero no se encontró su perfil administrativo${detail}.`);
  }
  if(!profile.active)throw new Error('Esta cuenta está desactivada.');
  const resolvedRole=normalizeRole(profile.role);
  currentUser={
    id:profile.id,
    name:profile.full_name,
    username:profile.username||session.user.email,
    role:resolvedRole,
    organizationId:profile.organization_id,
    email:session.user.email
  };
  await bhscAttemptStaffAutoLink({client,session,fullName:profile.full_name,email:session.user.email});
  if(window.BHSC_SET_STORAGE_CONTEXT?.(profile.id,profile.organization_id)){
    window.__BHSC_CONTEXT_RELOAD=true;
  }
  await registerSessionEntry(profile,session,resolvedRole);
  return currentUser;
}

function renderAuth(message=''){
  authGate.classList.remove('hidden');
  document.getElementById('app').classList.add('auth-locked');
  const rememberedEmail=localStorage.getItem('bhsc-remembered-email')||'';
  authContent.innerHTML=`<div class="auth-intro"><span>ACCESO SEGURO</span><h2>Iniciar sesión</h2><p>Ingrese con el correo y la contraseña de su cuenta. El sistema abrirá automáticamente el panel correspondiente a su rol.</p>${message?`<div class="auth-message">${message}</div>`:''}</div><form id="loginForm" class="auth-form"><label>Correo electrónico<input name="email" type="email" required autocomplete="username" value="${rememberedEmail.replace(/&/g,'&amp;').replace(/"/g,'&quot;')}"></label><label>Contraseña<input name="password" type="password" required autocomplete="current-password"></label><label class="remember-access"><input name="remember" type="checkbox" ${rememberedEmail?'checked':''}><span>Recordar mi usuario en este dispositivo</span></label><small class="auth-security-note">La contraseña puede guardarse con el gestor seguro del navegador cuando este lo solicite.</small><button class="auth-primary" type="submit">Ingresar</button></form><button class="auth-secondary" id="showRegistration" type="button">Registrar acceso con código</button><div class="auth-role-note"><strong>Accesos disponibles</strong><span>SUPV · Administrador · Enfermería · Asistente · Personal operativo</span></div>`;
  document.getElementById('showRegistration')?.addEventListener('click',()=>renderRegistration());
  document.getElementById('loginForm')?.addEventListener('submit',async e=>{
    e.preventDefault();
    const btn=e.currentTarget.querySelector('button');
    const fd=new FormData(e.currentTarget);
    try{
      btn.disabled=true;btn.textContent='Ingresando…';
      const client=window.seniorcareSupabase;
      if(!client) throw new Error('No se pudo conectar con Supabase.');
      const loginEmail=String(fd.get('email')).trim();
      if(fd.get('remember'))localStorage.setItem('bhsc-remembered-email',loginEmail);else localStorage.removeItem('bhsc-remembered-email');
      const {data,error}=await client.auth.signInWithPassword({email:loginEmail,password:String(fd.get('password'))});
      if(error) throw error;
      if(!data?.session) throw new Error('No se pudo iniciar la sesión.');
      await loadSupabaseUser(data.session);
      finishLogin();
    }catch(err){
      const msg=/Invalid login credentials/i.test(err?.message||'')?'Correo o contraseña incorrectos.':friendlyAppError(err,'No se pudo iniciar sesión.');
      try{await window.seniorcareSupabase?.auth.signOut();}catch(_e){}
      renderAuth(msg);
    }
  });
}
function renderRegistration(message=''){
  authGate.classList.remove('hidden');
  document.getElementById('app').classList.add('auth-locked');
  authContent.innerHTML=`<div class="auth-intro"><span>REGISTRO AUTORIZADO</span><h2>Crear acceso</h2><p>Use el código suministrado por el supervisor o administrador.</p>${message?`<div class="auth-message">${message}</div>`:''}</div><form id="registrationForm" class="auth-form"><label>Código de activación<input name="code" required placeholder="ADM-XXXXXX / ENF-XXXXXX / ASIS-XXXXXX"></label><label>Nombre completo<input name="fullName" required></label><label>Usuario<input name="username" required></label><label>Correo electrónico<input name="email" type="email" required></label><label>Contraseña<input name="password" type="password" minlength="8" required></label><label>Confirmar contraseña<input name="confirm" type="password" minlength="8" required></label><button class="auth-primary" type="submit">Crear cuenta</button></form><button class="auth-secondary" id="backLogin" type="button">Volver a iniciar sesión</button>`;
  document.getElementById('backLogin')?.addEventListener('click',()=>renderAuth());
  document.getElementById('registrationForm')?.addEventListener('submit',async e=>{
    e.preventDefault();
    const form=e.currentTarget;
    const fd=new FormData(form);
    const code=String(fd.get('code')).trim().toUpperCase().replace(/[–—−]/g,'-').replace(/\s+/g,'');
    const fullName=String(fd.get('fullName')).trim();
    const username=String(fd.get('username')).trim();
    const email=String(fd.get('email')).trim().toLowerCase();
    const pass=String(fd.get('password'));
    if(pass!==String(fd.get('confirm'))) return renderRegistration('Las contraseñas no coinciden.');
    const btn=form.querySelector('button[type="submit"]');
    let registrationStage='validation';
    let accountWasCreated=false;
    let createdSession=null;
    try{
      btn.disabled=true;btn.textContent='Validando código…';
      const client=window.seniorcareSupabase;
      if(!client) throw new Error('No se pudo conectar con Supabase.');

      let validation=window.BHSC_CALL_RPC
        ? await window.BHSC_CALL_RPC(['bh_validate_activation_code_v4325','bh_validate_activation_code_v4321','validate_activation_code_v434','validate_activation_code'],{p_code:code})
        : await client.rpc('validate_activation_code_v434',{p_code:code});
      if(validation.error) throw validation.error;
      const validationPayload=Array.isArray(validation.data)?validation.data[0]:validation.data;
      const validRow=validationPayload?.result||validationPayload;
      const codeIsValid=validRow?.valid===true||validRow?.is_valid===true;
      if(!codeIsValid) throw new Error(validRow?.message||validationPayload?.message||'Código inválido, vencido o utilizado.');

      registrationStage='signup';
      btn.textContent='Creando cuenta…';
      let signup=await client.auth.signUp({
        email,
        password:pass,
        options:{data:{activation_code:code,full_name:fullName,username}}
      });
      let session=signup.data?.session||null;
      if(signup.data?.user)accountWasCreated=true;
      if(signup.error){
        const duplicate=/already registered|user already exists|already been registered/i.test(signup.error.message||'');
        if(!duplicate)throw signup.error;
        accountWasCreated=true;
        const recovery=await client.auth.signInWithPassword({email,password:pass});
        if(recovery.error)throw new Error('Este correo ya tiene una cuenta. Inicie sesión con el correo y la contraseña utilizados durante el registro.');
        session=recovery.data?.session||null;
      }
      if(!session){
        const signed=await client.auth.signInWithPassword({email,password:pass});
        if(signed.error){
          throw new Error('La cuenta fue creada correctamente. Confirme el correo si Supabase lo solicita y luego inicie sesión.');
        }
        session=signed.data?.session||null;
      }
      if(!session) throw new Error('La cuenta fue creada correctamente, pero no se pudo abrir la sesión automáticamente. Inicie sesión con sus datos.');
      createdSession=session;

      // Algunas instalaciones crean el perfil mediante trigger durante signUp.
      // Primero intentamos cargarlo para evitar consumir/validar el código una segunda vez.
      registrationStage='profile';
      try{
        await loadSupabaseUser(session);
        finishLogin();
        return;
      }catch(profileBeforeCompletionError){
        console.info('[BHSC] Perfil aún no disponible; se intentará completar el registro.',profileBeforeCompletionError?.message||profileBeforeCompletionError);
      }

      registrationStage='completion';
      const complete=await appRetry(()=>window.BHSC_CALL_RPC
        ? window.BHSC_CALL_RPC(['bh_complete_my_registration_v4325','bh_complete_my_registration_v4321','complete_my_registration'],{p_code:code,p_full_name:fullName,p_username:username})
        : client.rpc('complete_my_registration',{p_code:code,p_full_name:fullName,p_username:username}),2);
      if(complete.error) throw complete.error;

      registrationStage='profile';
      await loadSupabaseUser(session);
      finishLogin();
    }catch(err){
      const client=window.seniorcareSupabase;
      if(registrationStage==='validation'&&client){
        try{
          const recovered=await client.auth.signInWithPassword({email,password:pass});
          const session=recovered.data?.session||null;
          if(session){
            try{
              await loadSupabaseUser(session);
              finishLogin();
              return;
            }catch(_profileError){
              try{await client.auth.signOut();}catch(_e){}
              renderAuth('La cuenta ya fue creada. Inicie sesión con el correo y la contraseña utilizados.');
              return;
            }
          }
        }catch(_existingLoginError){}
      }
      // Si la validación inicial ya fue aprobada, nunca volvemos a presentar el problema
      // como “código inválido” por un fallo posterior de trigger, perfil o respuesta RPC.
      if(registrationStage!=='validation'&&client){
        try{
          let session=createdSession;
          if(!session){
            const recovered=await client.auth.signInWithPassword({email,password:pass});
            session=recovered.data?.session||null;
          }
          if(session){
            try{
              await loadSupabaseUser(session);
              finishLogin();
              return;
            }catch(_profileError){
              try{await client.auth.signOut();}catch(_e){}
              renderAuth('El código fue aceptado y la cuenta quedó creada. Inicie sesión con el correo y la contraseña utilizados.');
              return;
            }
          }
        }catch(_recoveryError){}
        try{await client.auth.signOut();}catch(_e){}
        const lateMessage=String(err?.message||'');
        const likelyCreated=accountWasCreated||/invalid|used|utilizado|expired|vencido|activation code|código/i.test(lateMessage);
        renderAuth(likelyCreated
          ? 'El código fue aceptado y la cuenta quedó creada. Inicie sesión con el correo y la contraseña utilizados.'
          : 'El código fue aceptado. No se pudo confirmar automáticamente el último paso; pruebe iniciar sesión con los datos ingresados.');
        return;
      }
      try{await client?.auth.signOut();}catch(_e){}
      renderRegistration(friendlyAppError(err,'No se pudo crear la cuenta.'));
    }
  });
}
function finishLogin(){if(window.__BHSC_CONTEXT_RELOAD){window.__BHSC_CONTEXT_RELOAD=false;location.reload();return;}authGate.classList.add('hidden');document.getElementById('app').classList.remove('auth-locked');activeScreen='home';residentScoped=false;navigationStack=[];applyRoleUI();renderNav();updateAlertButton();render();window.dispatchEvent(new CustomEvent('seniorcare:user-ready',{detail:{userId:currentUser?.id||null,organizationId:currentUser?.organizationId||null,role:currentUser?.role||null}}));}
function applyRoleUI(){if(roleLabelEl)roleLabelEl.textContent=currentUser?.role==='supervisor'?'Panel de supervisión':`${ROLE_LABELS[currentUser?.role]||''} · ${currentUser?.name||''}`;}
async function logout(){
  try{await window.seniorcareSupabase?.auth.signOut();}catch(_e){}
  try{window.BHSC_CLEAR_PRIVATE_STORAGE?.();}catch(error){console.warn('[BHSC] No se pudo limpiar el almacenamiento privado:',error);}
  currentUser=null;
  renderAuth();
}



const svg = {
  users: '<svg viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></svg>',
  userPlus: '<svg viewBox="0 0 24 24"><path d="M15 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="8.5" cy="7" r="4"/><path d="M19 8v6M22 11h-6"/></svg>',
  bottle: '<svg viewBox="0 0 24 24"><path d="M9 2h6M10 2v4l-2 2v12a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V8l-2-2V2"/><path d="M8 10h8M10 15h4M12 13v4"/></svg>',
  shield: '<svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="m9 12 2 2 4-4"/></svg>',
  calendar: '<svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="17" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>',
  care: '<svg viewBox="0 0 24 24"><path d="M12 21s-7-4.35-7-10a4 4 0 0 1 7-2.65A4 4 0 0 1 19 11c0 5.65-7 10-7 10z"/><path d="M4 20c2-1 4-1 6 0M20 20c-2-1-4-1-6 0"/></svg>',
  report: '<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6M8 13h8M8 17h8M8 9h2"/></svg>',
  clock: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',
  home: '<svg viewBox="0 0 24 24"><path d="m3 11 9-8 9 8"/><path d="M5 10v10h14V10M9 20v-6h6v6"/></svg>',
  building: '<svg viewBox="0 0 24 24"><path d="M4 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16"/><path d="M16 9h2a2 2 0 0 1 2 2v10"/><path d="M8 7h4M8 11h4M8 15h4M9 21v-3h2v3M3 21h18"/></svg>',
  bell: '<svg viewBox="0 0 24 24"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4"/></svg>',
  more: '<svg viewBox="0 0 24 24"><circle cx="5" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/></svg>',
  heart: '<svg viewBox="0 0 24 24"><path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.6l-1-1a5.5 5.5 0 0 0-7.8 7.8l1 1L12 21l7.8-7.6 1-1a5.5 5.5 0 0 0 0-7.8z"/></svg>',
  plus: '<svg viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg>',
  wound: '<svg viewBox="0 0 24 24"><path d="m8 3 13 13-5 5L3 8z"/><path d="m8 8 8 8M10 6l2 2M6 10l2 2M14 10l2 2M10 14l2 2"/></svg>',
  food: '<svg viewBox="0 0 24 24"><path d="M3 2v8a4 4 0 0 0 4 4V2M7 14v8M15 2v20M15 2c4 0 6 3 6 7s-2 7-6 7"/></svg>',
  box: '<svg viewBox="0 0 24 24"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="m3.3 7 8.7 5 8.7-5M12 22V12"/></svg>',
  staff: '<svg viewBox="0 0 24 24"><circle cx="9" cy="7" r="4"/><path d="M3 21v-2a6 6 0 0 1 12 0v2M16 11h6M19 8v6"/></svg>',
  exchange: '<svg viewBox="0 0 24 24"><path d="M7 7h11l-3-3M17 17H6l3 3M18 7l3 3-3 3M6 17l-3-3 3-3"/></svg>',
  alert: '<svg viewBox="0 0 24 24"><path d="M10.3 2.9 1.8 17a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 2.9a2 2 0 0 0-3.4 0z"/><path d="M12 9v4M12 17h.01"/></svg>',
  check: '<svg viewBox="0 0 24 24"><path d="m5 12 4 4L19 6"/></svg>',
  search: '<svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>',
  back: '<svg viewBox="0 0 24 24"><path d="m15 18-6-6 6-6"/></svg>',
  droplet: '<svg viewBox="0 0 24 24"><path d="M12 2.7 6.6 9a7 7 0 1 0 10.8 0z"/></svg>',
  whatsapp: '<svg viewBox="0 0 24 24"><path d="M20.5 11.7a8.5 8.5 0 0 1-12.6 7.4L3 20.5l1.4-4.7A8.5 8.5 0 1 1 20.5 11.7z"/><path d="M8.2 7.7c.2-.4.4-.4.7-.4h.5c.2 0 .4.1.5.4l.8 1.9c.1.3.1.5-.1.7l-.7.8c-.2.2-.2.4-.1.6.6 1.2 1.5 2.1 2.7 2.7.2.1.4.1.6-.1l.9-1c.2-.2.4-.3.7-.2l1.8.8c.3.1.4.3.4.5 0 .5-.2 1.4-.7 1.9-.5.5-1.2.8-2.2.8-1.1 0-2.6-.4-4.4-1.9-2.2-1.8-3.7-4.5-3.8-6.1 0-.7.2-1.1.4-1.4z"/></svg>'
};

let residents = JSON.parse(localStorage.getItem('seniorcare-residents') || 'null') || [];
function saveResidents(){ localStorage.setItem('seniorcare-residents', JSON.stringify(residents)); }

let meds = JSON.parse(localStorage.getItem('seniorcare-medications') || 'null') || [];
function saveMedications(){ localStorage.setItem('seniorcare-medications', JSON.stringify(meds)); }
try{Object.defineProperty(window,'meds',{configurable:true,get:()=>meds,set:v=>{meds=Array.isArray(v)?v:[];}});}catch(_){window.meds=meds;}
function medicationTimes(m){
  if(m.immediate || m.frequency==='Inmediato') return ['Inmediato'];
  if(Array.isArray(m.times) && m.times.length) return m.times;
  if(m.time) return [m.time];
  return [];
}
function medicationScheduleLabel(m){
  const times=medicationTimes(m);
  if(m.immediate || m.frequency==='Inmediato') return 'Administrar de inmediato';
  const freq=m.frequency || 'Horario específico';
  return `${freq}${times.length?` · ${times.join(', ')}`:''}`;
}
function parseMedicationTimes(value){
  return String(value||'').split(',').map(v=>v.trim()).filter(Boolean);
}

let appointments = JSON.parse(localStorage.getItem('seniorcare-appointments') || 'null') || [];
function saveAppointments(){ localStorage.setItem('seniorcare-appointments', JSON.stringify(appointments)); }

let activeScreen = 'home';
Object.defineProperty(window,'activeScreen',{configurable:true,get(){return activeScreen},set(value){activeScreen=value}});
let selectedResident = residents[0]||null;
let residentScoped = false;
let carePlanEditing = false;
let navigationStack = [];
const inactiveResidents = JSON.parse(localStorage.getItem('seniorcare-inactive-residents') || 'null') || [];
function saveInactiveResidents(){ localStorage.setItem('seniorcare-inactive-residents', JSON.stringify(inactiveResidents)); }
let nursingNotes = JSON.parse(localStorage.getItem('seniorcare-nursing-notes') || '{}');
function saveNursingNotes(){ localStorage.setItem('seniorcare-nursing-notes', JSON.stringify(nursingNotes)); }
let vitalRecords = JSON.parse(localStorage.getItem('seniorcare-vitals') || 'null') || {};
function saveVitalRecords(){ localStorage.setItem('seniorcare-vitals', JSON.stringify(vitalRecords)); }
let woundRecords = JSON.parse(localStorage.getItem('seniorcare-wounds') || 'null') || {};
function saveWoundRecords(){ localStorage.setItem('seniorcare-wounds', JSON.stringify(woundRecords)); }
let incidents = JSON.parse(localStorage.getItem('seniorcare-incidents') || 'null') || [];
function saveIncidents(){ localStorage.setItem('seniorcare-incidents', JSON.stringify(incidents)); }
incidents=incidents.map((item,index)=>({...item,id:item.id||Date.now()+index}));
saveIncidents();
let dismissedConnectedAlertKeys = new Set(JSON.parse(localStorage.getItem('seniorcare-dismissed-alert-keys') || '[]'));
function saveDismissedAlertKeys(){ localStorage.setItem('seniorcare-dismissed-alert-keys', JSON.stringify([...dismissedConnectedAlertKeys])); }
let alertsData = JSON.parse(localStorage.getItem('seniorcare-alerts') || 'null') || [];
function saveAlerts(){ localStorage.setItem('seniorcare-alerts', JSON.stringify(alertsData)); updateAlertButton(); try{window.BHSC_ALERTS_PUSH?.()}catch(_){}}
function residentByName(name){ return residents.find(r=>r.name===name); }
function alertSourceKey(type,id){ return `${type}:${id}`; }
function upsertConnectedAlert(sourceKey,title,detail,priority,type,residentId=null,target=null){
  if(dismissedConnectedAlertKeys.has(sourceKey)) return;
  const existing=alertsData.find(a=>a.sourceKey===sourceKey && a.status!=='Resuelta');
  if(existing){ existing.title=title; existing.detail=detail; existing.priority=priority; existing.type=type; existing.residentId=residentId; existing.target=target; return; }
  alertsData.unshift({id:Date.now()+Math.random(),sourceKey,title,detail,priority,status:'Nueva',type,residentId,target,created:new Date().toISOString()});
}
function syncConnectedAlerts(){
  const activeKeys=new Set();
  meds.filter(m=>m.status==='Pendiente'||m.status==='Programado').forEach(m=>{
    const key=alertSourceKey('medication',m.id); activeKeys.add(key);
    const r=residentByName(m.resident);
    upsertConnectedAlert(key,m.status==='Pendiente'?'Medicamento pendiente':'Medicamento programado',`${m.resident} · ${m.drug} · ${medicationScheduleLabel(m)}`,m.status==='Pendiente'?'Alta':'Seguimiento','medication',r?.id||null,'medications');
  });
  appointments.filter(a=>String(a.transport).toLowerCase().includes('pend')).forEach(a=>{
    const key=alertSourceKey('appointment',a.id); activeKeys.add(key);
    const r=residentByName(a.resident);
    upsertConnectedAlert(key,'Traslado sin confirmar',`${a.resident} · ${a.place} · ${a.date} ${a.time}`,'Pendiente','appointment',r?.id||null,'agenda');
  });
  incidents.filter(i=>i.status==='Por revisar'||i.status==='En seguimiento').forEach(i=>{
    const key=alertSourceKey('incident',i.id||i.date); activeKeys.add(key);
    const r=residentByName(i.resident);
    upsertConnectedAlert(key,i.status==='Por revisar'?'Incidente por revisar':'Incidente en seguimiento',`${i.resident} · ${i.type}`,i.level==='Alta'?'Alta':'Seguimiento','incident',r?.id||null,'incidents');
  });
  Object.entries(woundRecords).forEach(([residentId,list])=>list.forEach(w=>{
    if(w.status==='Archivada') return;
    const due=w.next && new Date(`${w.next}T23:59:59`) <= new Date();
    if(!due) return;
    const key=alertSourceKey('wound',w.id); activeKeys.add(key);
    const r=residents.find(x=>residentKey(x)===String(residentId)||String(x.id)===String(residentId));
    upsertConnectedAlert(key,'Curación pendiente',`${r?.name||'Residente'} · ${w.area} · Próxima: ${w.next}`,'Seguimiento','wound',String(residentId),'wounds');
  }));
  Object.entries(carePlans).forEach(([planKey,list])=>{
    const pending=(list||[]).filter(x=>!x.done).length;
    if(!pending) return;
    const parts=String(planKey).split(':');
    const residentId=parts.shift()||'';
    const shift=parts.join(':')||'Turno';
    const key=alertSourceKey('care',planKey); activeKeys.add(key);
    const r=residents.find(x=>String(residentKey(x))===String(residentId)||String(x.id)===String(residentId));
    upsertConnectedAlert(key,'Cuidados pendientes',`${r?.name||'Residente'} · ${shift} · ${pending} actividad${pending===1?'':'es'} sin completar`,'Seguimiento','care',r?.id||residentId,'care');
  });
  alertsData=alertsData.filter(a=>!a.sourceKey || activeKeys.has(a.sourceKey) || a.status==='Resuelta' || a.status==='Archivada' || a.category || a.data?.category || /^(nursing_note|handoff|staff_incident):/.test(String(a.sourceKey)));
  let dismissedChanged=false;
  [...dismissedConnectedAlertKeys].forEach(key=>{ if(!activeKeys.has(key)){ dismissedConnectedAlertKeys.delete(key); dismissedChanged=true; } });
  if(dismissedChanged) saveDismissedAlertKeys();
  saveAlerts();
}
function familyPhone(resident){
  const raw=String(resident?.contact||'').split('·').pop().trim();
  let digits=raw.replace(/\D/g,'');
  if(digits.length===8) digits='506'+digits;
  return digits;
}
function familyName(resident){ return String(resident?.contact||'Familiar').split('·')[0].trim() || 'Familiar'; }
function openWhatsAppComposer(resident){
  const phone=familyPhone(resident);
  if(!phone){ showToast('Este residente no tiene teléfono familiar registrado.'); return; }
  const defaultMessage=`Hola ${familyName(resident)}. Le saludamos de Bernard Health SeniorCare. Queremos compartirle información sobre ${resident.name}:

[Escriba aquí la actualización]

Este mensaje corresponde al seguimiento del residente.`;
  openRecordModal('Enviar información al familiar',`<div class="whatsapp-composer"><div class="whatsapp-recipient"><span class="whatsapp-icon">${svg.whatsapp}</span><div><span>Enviar a</span><strong>${familyName(resident)}</strong><small>WhatsApp: +${phone}</small></div></div><label>Mensaje<textarea id="familyWhatsAppMessage" rows="8">${defaultMessage}</textarea></label><div class="form-actions"><button class="primary-btn whatsapp-send" id="sendFamilyWhatsApp">${svg.whatsapp}<span>Abrir WhatsApp</span></button></div><p class="whatsapp-note">Revise el mensaje antes de enviarlo. WhatsApp se abrirá con el texto preparado.</p></div>`);
  setTimeout(()=>document.getElementById('sendFamilyWhatsApp')?.addEventListener('click',()=>{
    const message=document.getElementById('familyWhatsAppMessage')?.value.trim();
    if(!message){showToast('Escriba el mensaje para el familiar.');return;}
    window.open(`https://wa.me/${phone}?text=${encodeURIComponent(message)}`,'_blank','noopener');
  }),0);
}
let nutritionRecords = JSON.parse(localStorage.getItem('seniorcare-nutrition') || '{}');
function saveNutrition(){ localStorage.setItem('seniorcare-nutrition', JSON.stringify(nutritionRecords)); }
let handoffRecords = JSON.parse(localStorage.getItem('seniorcare-handoffs') || '[]');
function saveHandoffs(){ localStorage.setItem('seniorcare-handoffs', JSON.stringify(handoffRecords)); }
let inventoryMovements = JSON.parse(localStorage.getItem('seniorcare-inventory-movements') || '[]');
function saveInventoryMovements(){ localStorage.setItem('seniorcare-inventory-movements', JSON.stringify(inventoryMovements)); }
let attendance = JSON.parse(localStorage.getItem('seniorcare-attendance') || '{}');
function saveAttendance(){ localStorage.setItem('seniorcare-attendance', JSON.stringify(attendance)); }
function getAttendanceState(id){
  const entry = attendance[id];
  if(entry && typeof entry==='object') return {present:!!entry.present,lastEntry:entry.lastEntry||'',lastExit:entry.lastExit||''};
  if(entry===true) return {present:true,lastEntry:'',lastExit:''};
  if(entry===false) return {present:false,lastEntry:'',lastExit:''};
  return {present:false,lastEntry:'',lastExit:''};
}
function attendanceLabel(value){
  if(!value) return 'Sin registro';
  try{return new Date(value).toLocaleString('es-CR',{dateStyle:'short',timeStyle:'short'});}catch(_e){return String(value);}
}
function clockStaff(id, type){
  const current = getAttendanceState(id);
  const now = new Date().toISOString();
  attendance[id] = {
    present: type==='in',
    lastEntry: type==='in' ? now : current.lastEntry || '',
    lastExit: type==='out' ? now : current.lastExit || ''
  };
  saveAttendance();
}

const defaultCareTasks = ['Baño completo','Higiene oral','Cambio de ropa','Movilización','Cambio de pañal','Hidratación','Evacuación','Actividad recreativa'];
let carePlans = JSON.parse(localStorage.getItem('seniorcare-care-plans') || '{}');
let staffMembers = JSON.parse(localStorage.getItem('seniorcare-staff') || '[]');
Object.defineProperty(window,'staffMembers',{configurable:true,get(){return staffMembers},set(value){staffMembers=Array.isArray(value)?value:[]}});
let inventoryItems = JSON.parse(localStorage.getItem('seniorcare-inventory') || 'null') || [];

let currentVitalViewId = null;
let currentWoundViewId = null;
function residentKey(r){ return String(r?.resident_key ?? r?.id ?? r?.key ?? '').trim(); }
function getResidentVitals(residentId){
  const k=String(residentId);
  if(!vitalRecords[k]) vitalRecords[k] = [];
  return vitalRecords[k];
}
function getResidentWounds(residentId){
  if(!woundRecords[residentId]) woundRecords[residentId] = [];
  return woundRecords[residentId];
}
function fmtDate(dateStr){
  if(!dateStr) return 'Sin fecha';
  const d = new Date(dateStr);
  if(Number.isNaN(d.getTime())) return dateStr;
  return d.toLocaleString('es-CR',{dateStyle:'medium', timeStyle:'short'});
}
function summarizeVital(v){
  return `PA ${v.sys||'--'}/${v.dia||'--'} · FC ${v.hr||'--'} · Temp ${v.temp||'--'}°C · SpO₂ ${v.spo2||'--'}%`;
}
function latestVital(residentId){ return getResidentVitals(residentId)[0] || null; }
function latestWound(residentId){ return getResidentWounds(residentId)[0] || null; }

function getNutritionRecords(residentId){ if(!nutritionRecords[residentId]) nutritionRecords[residentId]=[]; return nutritionRecords[residentId]; }
function updateAlertButton(){ const btn=document.querySelector('.alerts'); if(!btn) return; if(currentUser?.role==='supervisor'){ if(window.updateSupervisorAlertButton) window.updateSupervisorAlertButton(); else btn.innerHTML='<span class="dot"></span>Alertas SUPV'; return; } if(['cook','cleaning','maintenance','security'].includes(currentUser?.role)){const count=Number(window.getOperationalNoticeCount?.()||0);btn.innerHTML=`<span class="dot"></span>${count?`Avisos de tareas (${count})`:'Avisos de tareas'}`;btn.classList.toggle('has-alerts',count>0);return;} const count=alertsData.filter(a=>a.status==='Nueva').length; btn.innerHTML=`<span class="dot"></span>${count?`Alertas activas (${count})`:'Alertas activas'}`; btn.classList.toggle('has-alerts',count>0); }
function addAlert(title,detail,priority='Pendiente',type='general'){ alertsData.unshift({id:Date.now()+Math.random(),title,detail,priority,status:'Nueva',type,created:new Date().toISOString()}); saveAlerts(); }
window.BHSC_GET_ALERTS=()=>alertsData;
window.BHSC_SET_ALERTS=(rows,{render=true}={})=>{alertsData=Array.isArray(rows)?rows:[];localStorage.setItem('seniorcare-alerts',JSON.stringify(alertsData));updateAlertButton();if(render&&window.activeScreen==='alerts'){renderAlerts();bindActions();}};

function greeting(){ const h = new Date().getHours(); return h < 12 ? 'Buenos días' : h < 18 ? 'Buenas tardes' : 'Buenas noches'; }
function showToast(msg){ toastEl.textContent=msg; toastEl.classList.remove('hidden'); clearTimeout(window.__toastTimer); window.__toastTimer=setTimeout(()=>toastEl.classList.add('hidden'),2300); }
function setActiveNav(id){ nav.querySelectorAll('.nav-item').forEach(b=>b.classList.toggle('active',b.dataset.nav===id)); }

let lastRenderedRoute = null;
let suppressAutomaticRouteCapture = false;
function routeSnapshot(){
  return {screen:activeScreen,scope:!!residentScoped,residentId:selectedResident?.id??null,scrollY:window.scrollY||0};
}
function validRoute(route){ return !!route&&typeof route==='object'&&typeof route.screen==='string'; }
function sameRoute(a,b){
  return validRoute(a)&&validRoute(b)&&a.screen===b.screen&&!!a.scope===!!b.scope&&String(a.residentId??'')===String(b.residentId??'');
}
function pushRoute(route){
  if(!validRoute(route))return;
  const top=navigationStack[navigationStack.length-1];
  if(!sameRoute(top,route))navigationStack.push({...route});
}
function go(screen, extra={}, options={}){
  const nextScreen=ensureAllowed(screen);
  const nextResident=extra?.resident||selectedResident;
  const nextScope=extra?.scope==='resident';
  const current=routeSnapshot();
  const next={screen:nextScreen,scope:nextScope,residentId:nextResident?.id??null};
  const changed=!sameRoute(current,next);
  if(!options.replace&&changed)pushRoute(current);
  suppressAutomaticRouteCapture=true;
  activeScreen=nextScreen;
  if(extra?.resident) selectedResident=extra.resident;
  residentScoped=nextScope;
  render();
  requestAnimationFrame(()=>window.scrollTo({top:0,behavior:'auto'}));
}
function goBack(){
  let previous=navigationStack.pop();
  while(previous&&(!validRoute(previous)||sameRoute(previous,routeSnapshot()))){
    previous=navigationStack.pop();
  }
  if(!previous){
    previous=currentUser?.role==='supervisor'
      ? {screen:'home',scope:false,residentId:null,scrollY:0}
      : ['resident','inactive','admissions'].includes(activeScreen)
        ? {screen:'residents',scope:false,residentId:null,scrollY:0}
        : {screen:'home',scope:false,residentId:null,scrollY:0};
  }
  suppressAutomaticRouteCapture=true;
  activeScreen=ensureAllowed(previous.screen);
  residentScoped=!!previous.scope;
  if(previous.residentId!==null&&previous.residentId!==undefined){
    selectedResident=residents.find(r=>String(r.id)===String(previous.residentId))||selectedResident;
  }
  render();
  requestAnimationFrame(()=>requestAnimationFrame(()=>window.scrollTo({top:previous.scrollY||0,behavior:'auto'})));
}
function pageHeader(kicker,title,subtitle,back=true){
  const iconMap={
    residents:'users',inactive:'userPlus',resident:'users',admissions:'userPlus',
    medications:'bottle',vitals:'heart',care:'care',wounds:'wound',agenda:'calendar',
    incidents:'alert',nutrition:'food',nursing:'report',alerts:'bell',more:'more',
    staff:'staff',handoff:'exchange',inventory:'box',reports:'report'
  };
  const toneMap={
    residents:'purple',inactive:'fuchsia',resident:'purple',admissions:'fuchsia',
    medications:'amber',vitals:'cyan',care:'mint',wounds:'rose',agenda:'cyan',
    incidents:'fuchsia',nutrition:'rose',nursing:'purple',alerts:'amber',more:'purple',
    staff:'purple',handoff:'mint',inventory:'amber',reports:'purple'
  };
  const icon = iconMap[activeScreen] || 'report';
  const tone = toneMap[activeScreen] || 'purple';
  return `<section class="module-pro-head module-tone-${tone}">
    <div class="module-head-top">
      ${back?`<button class="back-btn residents-back module-back" data-back aria-label="Volver"><span class="back-icon">${svg.back}</span><span>Volver</span></button>`:''}
      <span class="module-module-tag">${kicker}</span>
    </div>
    <div class="module-head-main">
      <div class="module-head-copy"><h2>${title}</h2><p>${subtitle}</p></div>
      <div class="module-head-icon">${svg[icon]}</div>
    </div>
  </section>`
}

function empty(msg){return `<div class="empty-state">${svg.report}<strong>${msg}</strong><span>La información aparecerá aquí cuando se registre.</span></div>`}
function statusPill(text){ const t=String(text||'').toLowerCase(); let c='ok'; if(t.includes('riesgo alto')||t==='alta'||t.includes('stock bajo')||t.includes('atras')) c='danger'; else if(t.includes('riesgo medio')||t.includes('observ')||t.includes('seguimiento')||t.includes('pend')) c='warn'; else if(t.includes('riesgo bajo')||t.includes('estable')||t.includes('disponible')||t.includes('confirmado')||t.includes('presente')) c='ok'; return `<span class="status ${c}">${text}</span>`; }
function saveCarePlans(){ localStorage.setItem('seniorcare-care-plans', JSON.stringify(carePlans)); }
function getCareTasks(residentId){
  const resident = residents.find(r=>String(r.id)===String(residentId)||residentKey(r)===String(residentId));
  const stableKey = residentKey(resident)||String(residentId||'').trim();
  const legacyKey = resident?.id!=null ? String(resident.id) : '';
  if(stableKey && !carePlans[stableKey] && legacyKey && carePlans[legacyKey]){
    carePlans[stableKey]=carePlans[legacyKey];
    if(legacyKey!==stableKey) delete carePlans[legacyKey];
    saveCarePlans();
  }
  if(!carePlans[stableKey]) carePlans[stableKey] = [];
  return carePlans[stableKey];
}

function metric(icon,tone,title,value,text,screen){return `<button class="admin-stat" data-go="${screen}"><span class="stat-icon ${tone}">${svg[icon]}</span><div><small>${title}</small><strong>${value}</strong><p>${text}</p></div><span class="chevron">›</span></button>`}
function quick(icon,tone,title,text,screen){return `<button class="quick-card" data-go="${screen}"><span class="quick-icon ${tone}">${svg[icon]}</span><div><strong>${title}</strong><small>${text}</small></div></button>`}

async function injectAdministratorLicenseCountdown(){
  if(currentUser?.role!=='admin'||!currentUser?.organizationId||!window.seniorcareSupabase)return;
  try{
    const {data,error}=await window.seniorcareSupabase.from('licenses').select('status,renews_at,term_days,payment_confirmed').eq('organization_id',currentUser.organizationId).maybeSingle();
    if(error||!data)return;
    const days=data.renews_at?Math.max(0,Math.ceil((new Date(data.renews_at)-Date.now())/86400000)):0;
    const banner=document.createElement('section');
    banner.className=`admin-license-banner ${data.status==='suspended'?'suspended':days<=7?'urgent':''}`;
    banner.innerHTML=`<div><span>VIGENCIA DE LA LICENCIA</span><strong>${data.payment_confirmed?`${days} días restantes`:'Pago pendiente de confirmación'}</strong><small>${data.payment_confirmed?`Vence el ${new Date(data.renews_at).toLocaleDateString('es-CR')}`:'El contador iniciará cuando el supervisor confirme el pago.'}</small></div><b>${data.payment_confirmed?days:'—'}</b>`;
    const welcome=main.querySelector('.admin-welcome');welcome?.insertAdjacentElement('afterend',banner);
  }catch(_e){}
}

function renderHome(){
  const role=currentUser?.role||'admin';
  if(role==='supervisor' && window.renderSupervisorHome){window.renderSupervisorHome();return;}
  const copy=roleHomeCopy(role);
  if(role==='nurse'){
    main.innerHTML=`<section class="admin-welcome role-welcome nurse-welcome"><div><span class="eyebrow">${copy.eyebrow}</span><h2>${greeting()}, ${currentUser?.name?.split(' ')[0]||''}</h2><p>${copy.text}</p></div><div class="admin-mark">${svg.heart}</div></section><section class="admin-metrics">${metric('bottle','amber','Medicamentos pendientes',meds.filter(m=>m.status==='Pendiente').length,'Dosis por administrar','medications')}${metric('heart','blue','Signos del turno',Object.values(vitalRecords).flat().filter(v=>new Date(v.date).toDateString()===new Date().toDateString()).length,'Registros de hoy','vitals')}${metric('wound','rose','Curaciones',Object.values(woundRecords).flat().filter(w=>w.status!=='Archivada').length,'En seguimiento','wounds')}${metric('alert','rose','Incidentes abiertos',incidents.filter(i=>i.status!=='Resuelto').length,'Requieren revisión','incidents')}${metric('care','mint','Cuidados pendientes',Object.values(carePlans).flat().filter(x=>!x.done).length,'Actividades por completar','care')}${metric('exchange','lilac','Cambio de turno',handoffRecords.length,'Entregas registradas','handoff')}</section><section class="quick-section"><div class="quick-heading"><h2>Accesos clínicos</h2></div><div class="quick-grid">${quick('users','lilac','Residentes','Consultar expedientes','residents')}${quick('bottle','amber','Medicamentos','Administrar y registrar dosis','medications')}${quick('heart','blue','Signos vitales','Controles y evolución','vitals')}${quick('wound','rose','Curaciones','Procedimientos y seguimiento','wounds')}${quick('alert','rose','Incidentes','Acciones y seguimiento','incidents')}${quick('report','lilac','Notas','Evolución de enfermería','nursing')}</div></section>`;
    return;
  }
  if(role==='assistant'){
    main.innerHTML=`<section class="admin-welcome role-welcome assistant-welcome"><div><span class="eyebrow">${copy.eyebrow}</span><h2>${greeting()}, ${currentUser?.name?.split(' ')[0]||''}</h2><p>${copy.text}</p></div><div class="admin-mark">${svg.care}</div></section><section class="admin-metrics">${metric('users','lilac','Residentes asignados',residents.length,'Consultar indicaciones','residents')}${metric('care','mint','Cuidados pendientes',Object.values(carePlans).flat().filter(x=>!x.done).length,'Baño, higiene y movilidad','care')}${metric('food','rose','Alimentación',Object.values(nutritionRecords).flat().length,'Registros disponibles','nutrition')}${metric('calendar','blue','Agenda',appointments.length,'Citas y traslados','agenda')}${metric('alert','rose','Reportar incidente',incidents.filter(i=>i.status!=='Resuelto').length,'Novedades del turno','incidents')}${metric('exchange','lilac','Cambio de turno',handoffRecords.length,'Entregas registradas','handoff')}</section><section class="quick-section"><div class="quick-heading"><h2>Tareas del turno</h2></div><div class="quick-grid">${quick('care','mint','Cuidados diarios','Baño, higiene y movilidad','care')}${quick('food','rose','Alimentación','Ingesta e hidratación','nutrition')}${quick('users','lilac','Residentes','Indicaciones individuales','residents')}${quick('alert','rose','Incidentes','Registrar una novedad','incidents')}</div></section>`;
    return;
  }
  main.innerHTML=`<section class="admin-welcome"><div><span class="eyebrow">${copy.eyebrow}</span><h2>${greeting()}, ${currentUser?.name?.split(' ')[0]||''}</h2><p>${copy.text}</p></div><div class="admin-mark">${svg.care}</div></section>
  <section class="admin-metrics">
  ${metric('users','lilac','Residentes',residents.length,'Residentes activos','residents')}
  ${metric('userPlus','rose','Residentes inactivos',inactiveResidents.length,'Perfiles pendientes de activar','inactive')}
  ${metric('bottle','amber','Medicamentos pendientes',meds.filter(m=>m.status==='Pendiente').length,'Dosis programadas','medications')}
  ${metric('shield','mint','Incidentes nuevos',incidents.filter(i=>i.status==='Por revisar').length,'Reportes sin revisar','incidents')}
  ${metric('calendar','blue','Citas',appointments.length,'Agenda registrada','agenda')}
  ${metric('care','lilac','Cuidados pendientes',Object.values(carePlans).flat().filter(x=>!x.done).length,'Actividades por realizar','care')}
  </section>
  <section class="quick-section"><div class="quick-heading"><h2>Accesos Rápidos</h2></div><div class="quick-grid">
  ${quick('users','lilac','Residentes','Ver y gestionar residentes','residents')}
  ${quick('userPlus','rose','Admisiones','Nuevas admisiones y evaluaciones','admissions')}
  ${quick('calendar','lilac','Agenda','Actividades y citas programadas','agenda')}
  ${quick('calendar','blue','Agenda médica','Asignar pacientes a médicos por fecha y hora','medicalAppointmentsAdmin')}
  ${quick('bottle','amber','Medicamentos','Administración de medicación','medications')}
  ${quick('staff','mint','Personal y turnos','Asignaciones y asistencia','staff')}
  ${quick('report','lilac','Reportes','Informes y estadísticas','reports')}
  </div></section>`;
  setTimeout(injectAdministratorLicenseCountdown,0);
}

function renderResidents(){
 const stable=residents.filter(r=>String(r.status).toLowerCase().includes('estable')).length;
 const observation=residents.length-stable;
 main.innerHTML=`
 <section class="residents-pro-head">
   <div class="residents-head-top">
     <button class="back-btn residents-back" data-back aria-label="Volver"><span class="back-icon">${svg.back}</span><span>Volver</span></button>
     <span class="residents-module-tag">Gestión de residentes</span>
   </div>
   <div class="residents-head-main">
     <div class="residents-head-copy"><h2>Residentes</h2><p>Expediente integral y seguimiento diario</p></div>
     <div class="residents-head-icon">${svg.users}</div>
   </div>
   <div class="residents-head-stats">
     <span><b>${residents.length}</b> Activos</span>
     <span><b>${stable}</b> Estables</span>
     <span><b>${observation}</b> En observación</span>
   </div>
 </section>
 <section class="residents-actions"><label class="searchbox residents-search">${svg.search}<input id="residentSearch" placeholder="Buscar por nombre, cédula o habitación"></label><button class="primary-btn residents-new" data-go="admissions">${svg.plus}<span>Nuevo residente</span></button></section>
 <div class="resident-grid professional-resident-grid">${residents.map(r=>`<button class="resident-card professional-resident-card" data-resident="${r.id}"><div class="avatar">${r.name.split(' ').map(x=>x[0]).slice(0,2).join('')}</div><div class="resident-card-copy"><strong>${r.name}</strong><span>${r.age} años · ${r.room}</span><small>${r.identification?`Cédula ${r.identification} · `:''}${r.diet}</small></div>${statusPill(r.status)}<b class="resident-arrow">›</b></button>`).join('')}</div>`;
 setTimeout(()=>{const input=document.getElementById('residentSearch'); input?.addEventListener('input',e=>{document.querySelectorAll('.resident-card').forEach(c=>c.style.display=c.textContent.toLowerCase().includes(e.target.value.toLowerCase())?'':'none')})},0);
}

function inactiveResidentKey(item){ return String(item?.resident_key ?? item?.residentData?.resident_key ?? item?.residentData?.id ?? item?.id ?? item?.identification ?? item?.identification_number ?? '').trim(); }
function inactiveResidentName(item){ return String(item?.name || item?.residentData?.name || item?.residentData?.full_name || 'Residente').trim(); }
function ensureInactiveResidentKeys(){
 let changed=false;
 inactiveResidents.forEach(item=>{
   if(!item)return;
   const current=inactiveResidentKey(item);
   if(current)return;
   const key=(crypto.randomUUID&&crypto.randomUUID())||`inactive-${Date.now()}-${Math.random().toString(16).slice(2)}`;
   item.resident_key=key;
   item.id=item.id||key;
   item.residentData=item.residentData||{};
   item.residentData.resident_key=key;
   item.residentData.id=item.residentData.id||key;
   changed=true;
 });
 if(changed)saveInactiveResidents();
}
function inactiveResidentToActive(item){
 const base={...(item?.residentData||{}),...(item||{})};
 const key=inactiveResidentKey(item)||((crypto.randomUUID&&crypto.randomUUID())||`resident-${Date.now()}-${Math.random().toString(16).slice(2)}`);
 const name=inactiveResidentName(item);
 const previousStatus=String(base.previousStatus||base.activeStatus||base.status||'').trim();
 const status=previousStatus && !/inactivo|eliminado/i.test(previousStatus) ? previousStatus : 'Estable';
 return {
   ...base,
   id:base.id||key,
   resident_key:key,
   identification:base.identification||base.identification_number||'',
   identification_number:base.identification_number||base.identification||'',
   name,
   full_name:base.full_name||name,
   age:Number(base.age??item?.age)||0,
   room:base.room||item?.room||'Sin asignar',
   status,
   risk:base.risk||base.risk_level||'Riesgo bajo',
   diet:base.diet||base.nutrition_notes||'Corriente',
   family:base.family||'',
   phone:base.phone||'',
   contact:base.contact||base.emergency_contact||'',
   dx:base.dx||base.diagnoses||'',
   allergy:base.allergy||base.allergies||'Ninguna conocida',
   active:true,
   inactiveClassification:'',
   inactiveReason:'',
   inactiveDate:''
 };
}
function findResidentIndexByKey(key){ return residents.findIndex(r=>residentKey(r)===String(key)||String(r.id)===String(key)); }
async function reactivateInactiveResident(key){
 const idx=inactiveResidents.findIndex(r=>inactiveResidentKey(r)===String(key));
 if(idx<0){showToast('No se encontró el residente inactivo.');return;}
 const item=inactiveResidents[idx];
 const resident=inactiveResidentToActive(item);
 const expected=inactiveResidentName(item);
 if(!confirm(`¿Reactivar a ${expected}?`))return;
 const inactiveBackup=inactiveResidents.slice();
 const residentsBackup=residents.slice();
 try{
   inactiveResidents.splice(idx,1);
   const existing=findResidentIndexByKey(resident.resident_key);
   if(existing>=0)residents[existing]={...residents[existing],...resident};
   else residents.push(resident);
   saveInactiveResidents();
   saveResidents();
   if(typeof window.saveResidentToCloud==='function')await window.saveResidentToCloud(resident,{pullAfter:true});
   else if(typeof window.pushResidentsToCloud==='function')await window.pushResidentsToCloud();
   selectedResident=residents.find(r=>residentKey(r)===resident.resident_key||String(r.id)===String(resident.id))||resident;
   showToast('Residente reactivado correctamente.');
   go('resident',{resident:selectedResident},{replace:true});
 }catch(error){
   inactiveResidents.splice(0,inactiveResidents.length,...inactiveBackup);
   residents.splice(0,residents.length,...residentsBackup);
   saveInactiveResidents();
   saveResidents();
   renderInactiveResidents();
   bindActions();
   showToast(`No se pudo reactivar: ${error?.message||error}`);
 }
}
async function deleteInactiveResident(key){
 const idx=inactiveResidents.findIndex(r=>inactiveResidentKey(r)===String(key));
 if(idx<0){showToast('No se encontró el residente inactivo.');return;}
 const item=inactiveResidents[idx];
 const expected=inactiveResidentName(item);
 const typed=prompt(`Esta acción eliminará el registro inactivo y conservará la auditoría disponible en la nube.\n\nEscriba exactamente: ${expected}`);
 if(typed===null)return;
 if(typed.trim()!==expected){showToast('El nombre no coincide. No se eliminó el residente.');return;}
 const inactiveBackup=inactiveResidents.slice();
 try{
   inactiveResidents.splice(idx,1);
   saveInactiveResidents();
   if(typeof window.deleteResidentFromCloud==='function')await window.deleteResidentFromCloud(item.residentData||item);
   else if(typeof window.pushResidentsToCloud==='function')await window.pushResidentsToCloud();
   showToast('Residente inactivo eliminado correctamente.');
   renderInactiveResidents();
   bindActions();
 }catch(error){
   inactiveResidents.splice(0,inactiveResidents.length,...inactiveBackup);
   saveInactiveResidents();
   renderInactiveResidents();
   bindActions();
   showToast(`No se pudo eliminar: ${error?.message||error}`);
 }
}
window.BHSC_REACTIVATE_INACTIVE_RESIDENT=reactivateInactiveResident;
window.BHSC_DELETE_INACTIVE_RESIDENT=deleteInactiveResident;
function renderInactiveResidents(){
 ensureInactiveResidentKeys();
 main.innerHTML=pageHeader('GESTIÓN DE RESIDENTES','Residentes inactivos','Perfiles dados de baja, egresados o pendientes de reactivar')+`
 <div class="toolbar"><label class="searchbox">${svg.search}<input id="inactiveSearch" placeholder="Buscar residente inactivo"></label><button class="primary-btn" data-go="admissions">${svg.plus} Nueva admisión</button></div>
 <div class="resident-grid inactive-resident-grid">${inactiveResidents.map(r=>{const key=htmlValue(inactiveResidentKey(r)); const name=inactiveResidentName(r); const initials=name.split(' ').map(x=>x[0]).slice(0,2).join(''); const closure=/fallecid/i.test(`${r.status||''} ${r.reason||''} ${r.classification||''}`); return `<article class="resident-card inactive-card responsive-inactive-card"><div class="inactive-card-head"><div class="avatar muted-avatar">${htmlValue(initials)}</div><div class="inactive-card-copy"><strong>${htmlValue(name)}</strong><span>${htmlValue(r.age??r.residentData?.age??0)} años · ${htmlValue(r.room||r.residentData?.room||'Sin asignar')}</span><small>${htmlValue(r.reason||r.classification||'Inactivo')}</small></div></div><div class="inactive-card-side"><div class="inactive-pill-wrap">${statusPill(r.status||'Inactivo')}</div><div class="inactive-card-actions">${closure?`<button class="mini-btn" data-toast="Cierre del residente disponible.">Ver cierre</button>`:`<button class="mini-btn" data-inactive-reactivate="${key}">Reactivar</button>`}<button class="mini-btn danger-outline" data-inactive-delete="${key}">Eliminar</button></div></div></article>`}).join('')}</div>`;
 setTimeout(()=>{const input=document.getElementById('inactiveSearch'); input?.addEventListener('input',e=>{document.querySelectorAll('.inactive-card').forEach(c=>c.style.display=c.textContent.toLowerCase().includes(e.target.value.toLowerCase())?'':'none')})},0);
}

function renderResidentDetail(){ const r=selectedResident; const canEditResident=['administrator','admin','supervisor'].includes(String(currentUser?.role||'').toLowerCase()); const canDeleteResident=['administrator','admin'].includes(String(currentUser?.role||'').toLowerCase()); main.innerHTML=pageHeader('EXPEDIENTE DEL RESIDENTE',r.name,`${r.age} años · ${r.room}`)+`
 <section class="profile-hero"><div class="avatar large">${r.name.split(' ').map(x=>x[0]).slice(0,2).join('')}</div><div class="profile-main-copy"><h3>${r.name}</h3><p>${r.dx}</p><div class="tag-row">${statusPill(r.status)}${statusPill(r.risk)}</div></div><div class="resident-profile-actions">${canEditResident?`<button class="secondary-btn resident-edit-btn" id="editResidentButton">Editar información</button>`:''}${canDeleteResident?`<button class="danger-outline-btn resident-delete-btn-v4368" id="deleteResidentButton">Eliminar residente</button>`:''}${['administrator','admin','nurse'].includes(String(currentUser?.role||'').toLowerCase())?`<button class="family-whatsapp-btn" id="familyWhatsAppButton" aria-label="Enviar información al familiar por WhatsApp">${svg.whatsapp}<span>Enviar al familiar</span></button>`:''}</div></section>
 <section class="info-grid"><article><span>Número de cédula</span><strong>${r.identification||'No registrado'}</strong></article><article><span>Familiar responsable</span><strong>${r.contact}</strong></article><article><span>Dieta indicada</span><strong>${r.diet}</strong></article><article><span>Alergias</span><strong>${r.allergy}</strong></article><article><span>Estado funcional</span><strong>Dependencia moderada</strong></article></section>
 <div class="module-grid">
 ${residentModuleCard('heart','blue','Signos vitales','Controles y evolución','vitals')}
 ${residentModuleCard('bottle','amber','Medicamentos','Tratamiento y dosis','medications')}
 ${residentModuleCard('care','mint','Cuidados diarios','Higiene, baño y movilidad','care')}
 ${residentModuleCard('food','rose','Alimentación','Ingesta e hidratación','nutrition')}
 ${residentModuleCard('wound','lilac','Curaciones','Heridas y procedimientos','wounds')}
 ${residentModuleCard('calendar','blue','Citas y traslados','CCSS y hospitales','agenda')}
 ${residentModuleCard('alert','rose','Incidentes','Eventos y seguimiento','incidents')}
 ${residentModuleCard('report','lilac','Notas de enfermería','Evolución y observaciones','nursing')}
 </div>`; }
function residentModuleCard(icon,tone,title,text,screen){return `<button class="module-card" data-resident-go="${screen}">
<span class="quick-icon ${tone}">${svg[icon]}</span><div><strong>${title}</strong><small>${text}</small></div><b>›</b></button>`}
function moduleCard(icon,tone,title,text,screen){return `<button class="module-card" data-go="${screen}"><span class="quick-icon ${tone}">${svg[icon]}</span><div><strong>${title}</strong><small>${text}</small></div><b>›</b></button>`}

function htmlValue(value){return String(value??'').replace(/&/g,'&amp;').replace(/"/g,'&quot;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
function residentContactParts(r){
 const family=String(r?.family||'').trim(); const phone=String(r?.phone||'').trim();
 if(family||phone)return {family,phone};
 const parts=String(r?.contact||'').split(' · ');
 return {family:(parts[0]&&parts[0]!=='Sin familiar')?parts[0]:'',phone:(parts[1]&&parts[1]!=='Sin teléfono')?parts.slice(1).join(' · '):''};
}
function renderAdmissions(){
 const editKey=String(window.__BHSC_EDIT_RESIDENT_KEY||'').trim();
 const editResident=editKey?residents.find(r=>residentKey(r)===editKey||String(r.id)===editKey):null;
 const editing=!!editResident;
 const contact=residentContactParts(editResident);
 const selected=(value,current)=>String(value)===String(current)?' selected':'';
 main.innerHTML=pageHeader(editing?'GESTIÓN DE RESIDENTES':'ADMISIONES',editing?'Editar residente':'Nuevo residente',editing?'Actualice la información general sin alterar el expediente clínico.':'Registro inicial y valoración de ingreso')+`
 <form class="form-card" id="admissionForm"><input type="hidden" name="residentKey" value="${htmlValue(editKey)}"><div class="form-grid">
 ${field('Nombre completo','text','name',editResident?.name||'',true)}${field('Número de cédula','text','identification',editResident?.identification||editResident?.identification_number||'',false)}${field('Edad','number','age',editResident?.age??'',true)}${field('Habitación','text','room',editResident?.room||'',true)}${field('Familiar responsable','text','family',contact.family,true)}${field('Teléfono','tel','phone',contact.phone,true)}
 <label>Estado inicial<select name="status"><option${selected('Estable',editResident?.status||'Estable')}>Estable</option><option${selected('Observación',editResident?.status)}>Observación</option></select></label>
 <label>Riesgo de caídas<select name="risk"><option${selected('Riesgo bajo',editResident?.risk||'Riesgo bajo')}>Riesgo bajo</option><option${selected('Riesgo medio',editResident?.risk)}>Riesgo medio</option><option${selected('Riesgo alto',editResident?.risk)}>Riesgo alto</option></select></label>
 <label>Tipo de dieta<select name="diet"><option${selected('Corriente',editResident?.diet||'Corriente')}>Corriente</option><option${selected('Blanda',editResident?.diet)}>Blanda</option><option${selected('Diabética',editResident?.diet)}>Diabética</option><option${selected('Hiposódica',editResident?.diet)}>Hiposódica</option><option${selected('Licuada',editResident?.diet)}>Licuada</option></select></label>
 <label class="wide">Diagnósticos<textarea name="dx" rows="3" required>${htmlValue(editResident?.dx||'')}</textarea></label><label class="wide">Alergias<input name="allergy" value="${htmlValue(editResident?.allergy||'Ninguna conocida')}"></label>
 </div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelResidentForm">Cancelar</button><button class="primary-btn">${editing?'Guardar cambios':'Guardar admisión'}</button></div></form>`; }
function field(label,type,name,value='',required=true){return `<label>${label}<input type="${type}" name="${name}" value="${htmlValue(value)}"${required?' required':''}></label>`}

function renderMedications(){
 const visible = residentScoped ? meds.filter(m=>m.resident===selectedResident.name) : meds;
 const subtitle = residentScoped ? `Tratamiento y dosis de ${selectedResident.name}` : 'Administración y control de dosis de todos los residentes';
 main.innerHTML=pageHeader('SEGURIDAD DE MEDICACIÓN','Medicamentos',subtitle)+`
 <div class="toolbar compact-toolbar"><div class="toolbar-copy"><strong>${visible.length} registros</strong><span>${residentScoped?'Solo se muestra la medicación de este residente.':'Vista general del hogar.'}</span></div><button class="primary-btn" id="addMedication">${svg.plus} Añadir medicamento</button></div>
 <form class="form-card hidden" id="medicationForm"><input type="hidden" name="medicationId"><div class="form-grid">
 ${residentScoped?`<input type="hidden" name="resident" value="${selectedResident.name}"><label>Residente<input value="${selectedResident.name}" disabled></label>`:`<label>Residente<select name="resident">${residents.map(r=>`<option>${r.name}</option>`).join('')}</select></label>`}
 <label>Medicamento e indicación<input name="drug" required placeholder="Ej. Losartán 50 mg"></label>
 <label>Dosis a administrar<input name="dose" required placeholder="Ej. 1 tableta, 5 ml, 10 unidades"></label>
 <label>Frecuencia<select name="frequency" id="medFrequency"><option>Cada 6 horas</option><option>Cada 8 horas</option><option>Cada 12 horas</option><option>Cada 24 horas</option><option>Horarios específicos</option><option>Inmediato</option></select></label>
 <label class="wide" id="medTimesWrap">Horas de administración<input name="times" placeholder="Ej. 06:00, 14:00, 22:00"><small>Separe varias horas con comas.</small></label>
 <label>Vía<select name="route"><option>VO</option><option>SC</option><option>IM</option><option>IV</option><option>Tópica</option><option>Inhalada</option></select></label>
 <label>Estado<select name="status"><option>Pendiente</option><option>Programado</option><option>Administrado</option></select></label>
 </div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelMedication">Cancelar</button><button class="primary-btn">Guardar medicamento</button></div></form>
 <div class="list-stack">${visible.length?visible.map(m=>`<article class="data-row medication-row"><div class="time-badge">${m.immediate||m.frequency==='Inmediato'?'Ahora':(medicationTimes(m)[0]||'--')}</div><div class="row-main"><strong>${residentScoped?m.drug:m.resident}</strong><span>${residentScoped?`${m.dose?`${m.dose} · `:''}${medicationScheduleLabel(m)} · ${m.route}`:`${m.drug}${m.dose?` · ${m.dose}`:''} · ${medicationScheduleLabel(m)} · ${m.route}`}</span></div>${statusPill(m.status)}<div class="card-actions">${m.status!=='Administrado'?`<button class="mini-btn" data-med-admin="${m.id}">Administrar</button>`:''}<button class="mini-btn" data-med-edit="${m.id}">Editar</button><button class="icon-delete" data-med-delete="${m.id}">×</button></div></article>`).join(''):empty('No hay medicamentos registrados para este residente.')}</div>`;
}

function renderVitals(){
 const residentOptions = residentScoped ? [selectedResident] : residents;
 const allRecords = residentScoped ? getResidentVitals(residentKey(selectedResident)).map(v=>({...v,residentId:residentKey(selectedResident),residentName:selectedResident.name})) : residents.flatMap(r=>getResidentVitals(residentKey(r)).map(v=>({...v,residentId:residentKey(r),residentName:r.name}))).sort((a,b)=>new Date(b.date)-new Date(a.date));
 const records = allRecords.filter(r=>!r.archived);
 const archived = allRecords.filter(r=>r.archived);
 const latest = residentScoped ? records[0] : null;
 main.innerHTML=pageHeader('CONTROL CLÍNICO','Signos vitales',residentScoped?`Registro para ${selectedResident.name}`:'Registro y evolución de todos los residentes')+`
 ${residentScoped&&latest?`<section class="summary-strip"><article><span>Última PA</span><strong>${latest.sys}/${latest.dia}</strong></article><article><span>Saturación</span><strong>${latest.spo2}%</strong></article><article><span>Temperatura</span><strong>${latest.temp} °C</strong></article></section>`:''}
 <form class="form-card" id="vitalsForm"><input type="hidden" name="recordId"><div class="form-grid">${residentScoped?`<input type="hidden" name="residentId" value="${residentKey(selectedResident)}"><label>Residente<input value="${selectedResident.name}" disabled></label>`:`<label>Residente<select name="residentId">${residentOptions.map(r=>`<option value="${residentKey(r)}">${r.name}</option>`).join('')}</select></label>`}${field('Presión sistólica','number','sys')}${field('Presión diastólica','number','dia')}${field('Frecuencia cardíaca','number','hr')}${field('Temperatura','number','temp')}${field('Saturación O₂','number','spo2')}${field('Glucemia','number','glu')}${field('Peso (kg)','number','weight')}<label>Dolor<select name="pain"><option>0 - Sin dolor</option><option>1-3 Leve</option><option>4-6 Moderado</option><option>7-10 Intenso</option></select></label><label class="wide">Observaciones<textarea name="obs" rows="3"></textarea></label></div><div class="form-actions"><button type="button" class="secondary-btn hidden" id="cancelVitalEdit">Cancelar edición</button><button class="primary-btn">Guardar signos</button></div></form>
 <section class="history-card"><h3>Tomas anteriores</h3>${records.length?records.map(r=>`<article class="record-row"><button class="record-main" data-vital-view="${r.id}" data-vital-resident="${r.residentId}"><div><b>${r.residentName} · ${fmtDate(r.date)}</b><span>${summarizeVital(r)}</span></div><em>Ver completo</em></button><div class="record-actions"><button class="mini-btn" data-vital-edit="${r.id}" data-vital-resident="${r.residentId}">Editar</button><button class="mini-btn archive-btn" data-vital-archive="${r.id}" data-vital-resident="${r.residentId}">Archivar</button><button class="icon-delete" data-vital-delete="${r.id}" data-vital-resident="${r.residentId}">×</button></div></article>`).join(''):empty('No hay signos vitales guardados.')}</section>
 ${archived.length?`<section class="history-card archived-history"><h3>Registros archivados</h3>${archived.map(r=>`<article class="record-row archived"><button class="record-main" data-vital-view="${r.id}" data-vital-resident="${r.residentId}"><div><b>${r.residentName} · ${fmtDate(r.date)}</b><span>${summarizeVital(r)}</span></div><em>Ver</em></button><div class="record-actions"><button class="mini-btn" data-vital-restore="${r.id}" data-vital-resident="${r.residentId}">Restaurar</button><button class="icon-delete" data-vital-delete="${r.id}" data-vital-resident="${r.residentId}">×</button></div></article>`).join('')}</section>`:''}`;
}

function renderCare(){
 const tasks = getCareTasks(residentKey(selectedResident));
 const done = tasks.filter(t=>t.done).length;
 const selectedNames = new Set(tasks.map(t=>String(t.name||'').trim()));
 const catalog = [...new Set([...defaultCareTasks, ...tasks.map(t=>t.name).filter(Boolean)])];
 const editor = carePlanEditing ? `
 <section class="form-card care-plan-config"><div class="toolbar-copy"><strong>Editar plan individual</strong><span>Estas son opciones disponibles. Solo quedarán asignadas las que marque y guarde.</span></div><div class="checklist care-plan-selector">${catalog.map(name=>`<label class="check-item"><input type="checkbox" data-care-plan-option value="${String(name).replace(/&/g,'&amp;').replace(/"/g,'&quot;')}" ${selectedNames.has(name)?'checked':''}><span class="checkmark">${svg.check}</span><div><strong>${name}</strong><small>${selectedNames.has(name)?'Actualmente asignada':'Disponible, no asignada'}</small></div></label>`).join('')}</div><div class="form-actions"><button class="secondary-btn" type="button" id="addCareTask">${svg.plus} Añadir tarea personalizada</button><button class="secondary-btn" type="button" id="cancelCareSelection">Cancelar</button><button class="primary-btn" type="button" id="saveCareSelection">Guardar plan individual</button></div></section>` : '';
 main.innerHTML=pageHeader('CUIDADOS DIARIOS','Plan de cuidados',residentScoped?`Plan individual de ${selectedResident.name}`:'Planes individuales por residente')+`
 <div class="resident-context"><span class="quick-icon mint">${svg.care}</span><div><strong>${selectedResident.name}</strong><span>${selectedResident.room} · ${selectedResident.diet}</span></div>${statusPill(`${done}/${tasks.length} completadas`)}</div>
 <div class="filter-row">${residentScoped?'':`<select id="careResidentSelect">${residents.map(r=>`<option value="${residentKey(r)}" ${residentKey(r)===residentKey(selectedResident)?'selected':''}>${r.name}</option>`).join('')}</select>`}<select id="careShiftSelect"><option>Turno matutino</option><option>Turno vespertino</option><option>Turno nocturno</option></select></div>
 <div class="toolbar compact-toolbar"><div class="toolbar-copy"><strong>${tasks.length} tareas asignadas a ${selectedResident.name}</strong><span>Esta es la lista definitiva que el personal debe realizar.</span></div><button class="secondary-btn" type="button" id="editCareSelection">${svg.edit||''} Editar plan</button></div>
 ${editor}
 <section class="checklist care-checklist">${tasks.length?tasks.map(t=>`<article class="check-item editable-task"><label><input type="checkbox" data-care-check="${t.id}" ${t.done?'checked':''}><span class="checkmark">${svg.check}</span><div><strong>${t.name}</strong><small>${t.done?'Completada':'Pendiente de realizar'}</small></div></label><button class="icon-delete" type="button" data-care-delete="${t.id}">×</button></article>`).join(''):empty('No hay tareas asignadas. Pulse “Editar plan” para escoger únicamente los cuidados de esta residente.')}</section>`;
}
function renderWounds(){
 const allRecords = residentScoped ? getResidentWounds(selectedResident.id).map(w=>({...w,residentId:residentKey(selectedResident),residentName:selectedResident.name})) : residents.flatMap(r=>getResidentWounds(r.id).map(w=>({...w,residentId:residentKey(r),residentName:r.name}))).sort((a,b)=>new Date(b.date)-new Date(a.date));
 const records=allRecords.filter(r=>!r.archived);
 const archived=allRecords.filter(r=>r.archived);
 main.innerHTML=pageHeader('CURACIONES Y PROCEDIMIENTOS','Curaciones',residentScoped?`Heridas y procedimientos de ${selectedResident.name}`:'Curaciones de todos los residentes')+`
 <form class="form-card" id="woundForm"><input type="hidden" name="recordId"><div class="form-grid">${residentScoped?`<input type="hidden" name="residentId" value="${residentKey(selectedResident)}"><label>Residente<input value="${selectedResident.name}" disabled></label>`:`<label>Residente<select name="residentId">${residents.map(r=>`<option value="${residentKey(r)}">${r.name}</option>`).join('')}</select></label>`}<label>Área o lesión<input name="area" required></label><label>Tamaño<input name="size"></label><label>Exudado<select name="exudate"><option>Ausente</option><option>Escaso</option><option>Moderado</option><option>Abundante</option></select></label><label>Dolor<select name="pain"><option>0/10</option><option>1-3/10</option><option>4-6/10</option><option>7-10/10</option></select></label><label>Próxima curación<input type="date" name="next"></label><label>Estado<select name="status"><option>Pendiente</option><option>En seguimiento</option><option>Resuelta</option></select></label><label class="wide">Procedimiento<textarea name="procedure" rows="3"></textarea></label><label class="wide">Observaciones<textarea name="obs" rows="3"></textarea></label></div><div class="form-actions"><button type="button" class="secondary-btn hidden" id="cancelWoundEdit">Cancelar edición</button><button class="primary-btn">Registrar curación</button></div></form>
 <section class="history-card"><h3>Historial de curaciones</h3>${records.length?records.map(r=>`<article class="record-row"><button class="record-main" data-wound-view="${r.id}" data-wound-resident="${r.residentId}"><div><b>${r.residentName} · ${fmtDate(r.date)}</b><span>${r.area} · ${r.status}${r.size?` · ${r.size}`:''}</span></div><em>Ver detalle</em></button><div class="record-actions"><button class="mini-btn" data-wound-edit="${r.id}" data-wound-resident="${r.residentId}">Editar</button><button class="mini-btn archive-btn" data-wound-archive="${r.id}" data-wound-resident="${r.residentId}">Archivar</button><button class="icon-delete" data-wound-delete="${r.id}" data-wound-resident="${r.residentId}">×</button></div></article>`).join(''):empty('No hay curaciones registradas.')}</section>
 ${archived.length?`<section class="history-card archived-history"><h3>Curaciones archivadas</h3>${archived.map(r=>`<article class="record-row archived"><button class="record-main" data-wound-view="${r.id}" data-wound-resident="${r.residentId}"><div><b>${r.residentName} · ${fmtDate(r.date)}</b><span>${r.area} · ${r.status}</span></div><em>Ver</em></button><div class="record-actions"><button class="mini-btn" data-wound-restore="${r.id}" data-wound-resident="${r.residentId}">Restaurar</button><button class="icon-delete" data-wound-delete="${r.id}" data-wound-resident="${r.residentId}">×</button></div></article>`).join('')}</section>`:''}`;
}

function renderAgenda(){ const visibleAppointments=residentScoped?appointments.filter(a=>a.resident===selectedResident.name):appointments; main.innerHTML=pageHeader('AGENDA Y TRASLADOS','Agenda',residentScoped?`Citas y traslados de ${selectedResident.name}`:'Citas médicas, CCSS, hospitales y actividades')+`
 <div class="toolbar"><div class="toolbar-copy"><strong>${visibleAppointments.length} actividades registradas</strong><span>Puede añadir, editar o eliminar citas y traslados.</span></div><button class="primary-btn" id="addAppointment">${svg.plus} Nueva cita</button></div>
 <form class="form-card hidden" id="appointmentForm"><input type="hidden" name="appointmentId"><div class="form-grid">
 ${residentScoped?`<input type="hidden" name="resident" value="${selectedResident.name}"><label>Residente<input value="${selectedResident.name}" disabled></label>`:`<label>Residente<select name="resident">${residents.map(r=>`<option>${r.name}</option>`).join('')}</select></label>`}<label>Fecha<input name="date" type="date" required></label><label>Hora<input name="time" type="time" required></label><label>Tipo de cita<input name="type" required></label><label>Lugar<input name="place" required></label><label>Transporte<select name="transport"><option>Confirmado</option><option>Pendiente</option><option>No requiere</option></select></label><label>Acompañante<input name="companion"></label><label class="wide">Notas<textarea name="notes" rows="3"></textarea></label>
 </div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelAppointment">Cancelar</button><button class="primary-btn">Guardar cita</button></div></form>
 <div class="list-stack">${visibleAppointments.sort((a,b)=>`${a.date} ${a.time}`.localeCompare(`${b.date} ${b.time}`)).map(a=>`<article class="data-row appointment-row"><div class="time-badge blue-bg">${a.time}</div><div class="row-main"><strong>${a.resident}</strong><span>${a.type} · ${a.place}</span><small>${a.date} · Transporte: ${a.transport} · Acompañante: ${a.companion||'Sin asignar'}</small></div>${statusPill(a.transport)}<div class="card-actions"><button class="mini-btn" data-appointment-edit="${a.id}">Editar</button><button class="icon-delete" data-appointment-delete="${a.id}">×</button></div></article>`).join('')}</div>`; }

function renderIncidents(){
 const visible=residentScoped?incidents.filter(i=>i.resident===selectedResident.name):incidents;
 const high = visible.filter(i=>String(i.level).toLowerCase().includes('alta')).length;
 const pending = visible.filter(i=>String(i.status).toLowerCase().includes('revis')).length;
 main.innerHTML=pageHeader('SEGURIDAD Y SEGUIMIENTO','Incidentes',residentScoped?`Eventos y seguimiento de ${selectedResident.name}`:'Registro, revisión y acciones correctivas')+`
 <div class="alert-summary"><article class="danger-box"><strong>${visible.length}</strong><span>Registrados</span></article><article class="warn-box"><strong>${pending}</strong><span>Por revisar</span></article><article class="ok-box"><strong>${high}</strong><span>Alta prioridad</span></article></div>
 <form class="form-card" id="incidentForm"><input type="hidden" name="incidentId"><div class="form-grid">${residentScoped?`<input type="hidden" name="resident" value="${selectedResident.name}"><label>Residente<input value="${selectedResident.name}" disabled></label>`:`<label>Residente<select name="resident">${residents.map(r=>`<option>${r.name}</option>`).join('')}</select></label>`}<label>Tipo<select name="type"><option>Caída</option><option>Rechazo de medicamento</option><option>Rechazo de alimento</option><option>Golpe</option><option>Agitación</option><option>Error de medicación</option><option>Otro</option></select></label><label>Nivel<select name="level"><option>Alta</option><option>Media</option><option>Baja</option></select></label><label>Fecha y hora<input name="date" value="Hoy · ${new Date().toLocaleTimeString('es-CR',{hour:'2-digit',minute:'2-digit'})}"></label><label class="wide">Descripción<textarea name="description" rows="3" required></textarea></label><label class="wide">Acción tomada<textarea name="action" rows="3" placeholder="Describa la intervención realizada, notificaciones y seguimiento"></textarea></label><label>Estado<select name="status"><option>Por revisar</option><option>En seguimiento</option><option>Resuelto</option></select></label></div><div class="form-actions"><button type="button" class="secondary-btn hidden" id="cancelIncidentEdit">Cancelar edición</button><button class="primary-btn" id="saveIncidentButton">Registrar incidente</button></div></form>
 <div class="list-stack incident-list">${visible.length?visible.map(i=>`<article class="incident-card"><div class="incident-icon">${svg.alert}</div><div><strong>${i.type}</strong><span>${i.resident} · ${i.date}</span><small>Nivel: ${i.level} · Estado: ${i.status}</small>${i.action?`<p class="incident-action"><b>Acción tomada:</b> ${i.action}</p>`:''}</div><div class="card-actions"><button class="mini-btn" data-incident-edit="${i.id||i.date}">Editar</button><button class="mini-btn" data-incident-review-id="${i.id||i.date}">Cambiar estado</button><button class="icon-delete" data-incident-delete-id="${i.id||i.date}">×</button></div></article>`).join(''):empty('No hay incidentes registrados para este residente.')}</div>`;
}

function renderNutrition(){
 const records=getNutritionRecords(selectedResident.id);
 main.innerHTML=pageHeader('NUTRICIÓN E HIDRATACIÓN','Alimentación',residentScoped?`Seguimiento exclusivo de ${selectedResident.name}`:'Seleccione un residente para registrar y consultar')+`
 ${residentScoped?'':`<div class="filter-row"><select id="nutritionResidentSelect">${residents.map(r=>`<option value="${residentKey(r)}" ${r.id===selectedResident.id?'selected':''}>${r.name}</option>`).join('')}</select></div>`}
 <section class="summary-strip"><article><span>Residente</span><strong>${selectedResident.name}</strong></article><article><span>Dieta</span><strong>${selectedResident.diet}</strong></article><article><span>Registros</span><strong>${records.length}</strong></article></section>
 <form class="form-card" id="nutritionForm"><div class="form-grid"><label>Tiempo de comida<select name="meal"><option>Desayuno</option><option>Merienda</option><option>Almuerzo</option><option>Cena</option></select></label><label>Porcentaje consumido<select name="percent"><option>100%</option><option>75%</option><option>50%</option><option>25%</option><option>No consumió</option></select></label><label>Líquidos (ml)<input name="liquids" type="number"></label><label>Suplemento<select name="supplement"><option>No</option><option>Sí</option></select></label><label class="wide">Observaciones<textarea name="obs" rows="3"></textarea></label></div><div class="form-actions"><button class="primary-btn">Guardar registro</button></div></form>
 <section class="history-card"><h3>Historial de ${selectedResident.name}</h3>${records.length?records.map((r,i)=>`<article class="note-card"><div><b>${fmtDate(r.date)} · ${r.meal}</b><span>${r.percent} · ${r.liquids} ml · Suplemento: ${r.supplement}</span><p>${r.obs||'Sin observaciones'}</p></div><button class="icon-delete" data-nutrition-delete="${i}">×</button></article>`).join(''):empty('No hay registros de alimentación.')}</section>`;
}

function renderNursing(){
 const notes=nursingNotes[selectedResident.id]||[];
 main.innerHTML=pageHeader('EVOLUCIÓN DE ENFERMERÍA','Notas de enfermería',residentScoped?`Historial exclusivo de ${selectedResident.name}`:'Seleccione un residente para consultar su evolución')+`
 ${residentScoped?'':`<div class="filter-row"><select id="nursingResidentSelect">${residents.map(r=>`<option value="${residentKey(r)}" ${r.id===selectedResident.id?'selected':''}>${r.name}</option>`).join('')}</select></div>`}
 <form class="form-card" id="nursingForm"><div class="form-grid"><label>Residente<input value="${selectedResident.name}" disabled></label><label>Turno<select name="shift"><option>Matutino</option><option>Vespertino</option><option>Nocturno</option></select></label><label>Estado general<select name="status"><option>Estable</option><option>En observación</option><option>Requiere valoración</option></select></label><label class="wide">Nota de evolución<textarea name="note" rows="7" required></textarea></label></div><div class="form-actions"><button class="primary-btn">Guardar nota</button></div></form>
 <section class="history-card"><h3>Notas de ${selectedResident.name}</h3>${notes.length?notes.map((n,i)=>`<article class="note-card"><div><b>${n.date} · ${n.shift}</b><span>${n.author} · ${n.status}</span><p>${n.note}</p></div><button class="icon-delete" data-note-delete="${i}">×</button></article>`).join(''):empty('No hay notas registradas para este residente.')}</section>`;
}

function renderAlerts(){
 syncConnectedAlerts();
 const open=alertsData.filter(a=>a.status!=='Resuelta');
 const high=open.filter(a=>a.priority==='Alta').length;
 const follow=open.filter(a=>a.priority!=='Alta').length;
 const resolved=alertsData.filter(a=>a.status==='Resuelta').length;
 const iconFor={medication:'bottle',wound:'wound',appointment:'calendar',incident:'alert',care:'care',general:'bell'};
 main.innerHTML=pageHeader('CENTRO DE ALERTAS','Alertas','Pendientes conectados con los registros de la aplicación')+`
 <div class="alert-summary"><article class="danger-box"><strong>${high}</strong><span>Alta prioridad</span></article><article class="warn-box"><strong>${follow}</strong><span>Seguimiento</span></article><article class="ok-box"><strong>${resolved}</strong><span>Resueltas</span></article></div>
 <div class="alerts-toolbar"><p>Las alertas se actualizan automáticamente según medicamentos, incidentes, citas, curaciones y cuidados.</p><button class="secondary-btn" id="markAllAlerts">Marcar nuevas como vistas</button></div>
 <div class="list-stack connected-alert-list">${alertsData.length?alertsData.map(a=>`<article class="data-row connected-alert-card ${a.status==='Resuelta'?'resolved-alert':''}" data-alert-card="${a.id}"><span class="quick-icon ${a.priority==='Alta'?'rose':a.type==='appointment'?'blue':'amber'}">${svg[iconFor[a.type]||'bell']}</span><div class="row-main"><strong>${a.title}</strong><span>${a.detail}</span><small>${fmtDate(a.created)} · ${a.status}</small></div>${statusPill(a.priority)}<div class="card-actions alert-card-actions">${a.target?`<button class="mini-btn alert-action-btn" data-alert-open="${a.id}">Abrir</button>`:`<button class="mini-btn alert-action-btn" disabled>Sin enlace</button>`}<button class="mini-btn alert-action-btn" data-alert-seen="${a.id}" ${a.status!=='Nueva'?'disabled':''}>Vista</button><button class="mini-btn alert-action-btn" data-alert-resolve="${a.id}" ${a.status==='Resuelta'?'disabled':''}>Resolver</button><button class="icon-delete alert-dismiss-btn" data-alert-delete="${a.id}" aria-label="Cerrar alerta" title="Cerrar alerta">×</button></div></article>`).join(''):empty('No hay alertas pendientes.')}</div>`;
}

function renderMore(){ main.innerHTML=pageHeader('GESTIÓN DEL HOGAR','Más módulos','Administración, personal y documentación')+`
 <div class="more-grid">${moduleCard('staff','lilac','Personal y turnos','Asignaciones y asistencia','staff')}${moduleCard('check','mint','Operación del hogar','Asignar tareas, prioridades y fechas','operationalTasks')}${moduleCard('exchange','mint','Cambio de turno','Entrega y recepción','handoff')}${moduleCard('box','amber','Inventario','Medicamentos e insumos','inventory')}${moduleCard('food','rose','Nutrición','Dietas e ingesta','nutrition')}${moduleCard('wound','blue','Curaciones','Procedimientos y heridas','wounds')}${moduleCard('report','lilac','Reportes','PDF e indicadores','reports')}${['admin','nurse','doctor'].includes(currentUser?.role)?moduleCard('report','blue','Indicaciones médicas','Lectura y seguimiento','medicalOrders'):''}${['admin','nurse','doctor'].includes(currentUser?.role)?moduleCard('calendar','mint','Documentos médicos','Consultas, recetas y órdenes','medicalDocuments'):''}</div>`; }

function saveStaff(){ localStorage.setItem('seniorcare-staff',JSON.stringify(staffMembers)); }
function renderStaff(){
 const presentCount=staffMembers.filter(m=>getAttendanceState(m.id).present).length;
 const scheduledCount=staffMembers.filter(m=>m.employmentStatus!=='Inactivo').length;
 const fmtDays=m=>Array.isArray(m.workDays)&&m.workDays.length?m.workDays.join(', '):'Sin días definidos';
 const fmtShift=m=>m.shiftName?`${m.shiftName} · ${m.startTime||'--:--'}–${m.endTime||'--:--'}`:(m.shift||'Sin turno');
 main.innerHTML=pageHeader('GESTIÓN DE PERSONAL','Personal y turnos','Colaboradores, horarios estructurados, asignaciones y asistencia')+`
 <section class="staff-dashboard-pro">
   <article><span>Colaboradores</span><strong>${staffMembers.length}</strong><small>Registrados</small></article>
   <article><span>Activos</span><strong>${scheduledCount}</strong><small>Con acceso operativo</small></article>
   <article><span>Presentes</span><strong>${presentCount}</strong><small>Con entrada marcada</small></article>
   <button class="primary-btn staff-add-pro" id="addStaff">${svg.plus} Añadir personal</button>
 </section>
 <section class="staff-attendance-banner"><div><strong>Turnos y asistencia integrados</strong><span>El horario programado es independiente de la entrada y salida real. Las marcas se sincronizan entre dispositivos.</span></div><small>Supabase · Realtime</small></section>
 <form class="form-card staff-form hidden" id="staffForm"><input type="hidden" name="staffId"><div class="form-grid">
   <label>Nombre completo<input name="name" required></label>
   <label>Puesto o función<select name="role"><option>Enfermería</option><option>Asistente</option><option>Cuidador</option><option>Cocina</option><option>Guarda de seguridad</option><option>Miscelánea</option><option>Mantenimiento</option><option>Médico</option><option>Administración</option></select></label>
   <label>Turno<select name="shiftName"><option>Matutino</option><option>Vespertino</option><option>Nocturno</option><option>Rotativo</option><option>Administrativo</option></select></label>
   <label>Estado laboral<select name="employmentStatus"><option>Activo</option><option>Libre</option><option>Vacaciones</option><option>Permiso</option><option>Inactivo</option></select></label>
   <label>Hora de entrada<input name="startTime" type="time" required></label>
   <label>Hora de salida<input name="endTime" type="time" required></label>
   <fieldset class="wide staff-days-field"><legend>Días programados</legend><div class="staff-days-grid">${['Lun','Mar','Mié','Jue','Vie','Sáb','Dom'].map(d=>`<label><input type="checkbox" name="workDays" value="${d}"><span>${d}</span></label>`).join('')}</div></fieldset>
   <label class="wide">Asignación principal<input name="assignment" placeholder="Residentes, habitaciones, cocina, vigilancia o responsabilidades"></label>
 </div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelStaff">Cancelar</button><button class="primary-btn">Guardar colaborador y turno</button></div></form>
 <div class="staff-grid-pro global-staff-grid">${staffMembers.map(m=>{const rec=getAttendanceState(m.id);const present=rec.present;return `<article class="staff-card-pro global-staff-card">
   <div class="staff-card-pro-head"><div class="avatar staff-avatar">${m.name.split(' ').map(x=>x[0]).slice(0,2).join('')}</div><div><strong>${m.name}</strong><span>${m.role}</span></div>${statusPill(present?'Presente':(m.employmentStatus||m.status||'Activo'))}</div>
   <div class="staff-card-pro-body"><div><span>Turno programado</span><strong>${fmtShift(m)}</strong></div><div><span>Días</span><strong>${fmtDays(m)}</strong></div><div><span>Asignación</span><strong>${m.assignment||'Sin asignación'}</strong></div></div>
   <div class="attendance-log"><div><span>Última entrada</span><strong>${attendanceLabel(rec.lastEntry)}</strong></div><div><span>Última salida</span><strong>${attendanceLabel(rec.lastExit)}</strong></div></div>
   <div class="staff-card-pro-actions"><button class="clock-btn clock-in" data-clock-in="${m.id}">Marcar entrada</button><button class="clock-btn clock-out" data-clock-out="${m.id}">Marcar salida</button><button class="mini-btn" data-staff-edit="${m.id}">Editar</button><button class="icon-delete" data-staff-delete="${m.id}" aria-label="Eliminar">×</button></div>
 </article>`}).join('')}</div>`;
}

function renderHandoff(){
 const records=handoffRecords;
 main.innerHTML=pageHeader('CONTINUIDAD DEL CUIDADO','Cambio de turno','Entrega formal e inalterable de la información del turno')+`
 <section class="handoff-explainer">
   <div class="handoff-explainer-icon">${svg.exchange}</div>
   <div><strong>¿Cómo funciona?</strong><p>La persona que termina el turno registra las novedades y pendientes. Al entregar, se crea una ficha permanente con fecha y hora. Después de guardada puede consultarse, pero no editarse.</p></div>
 </section>
 <form class="form-card handoff-form-pro" id="handoffForm">
   <div class="handoff-form-title"><div><span>NUEVA ENTREGA</span><h3>Registrar cambio de turno</h3></div><span class="handoff-lock">Registro permanente</span></div>
   <div class="form-grid">
     <label>Turno que entrega<select name="shift" required><option value="">Seleccione</option><option>Matutino</option><option>Vespertino</option><option>Nocturno</option></select></label>
     <label>Turno que recibe<select name="incomingShift" required><option value="">Seleccione</option><option>Matutino</option><option>Vespertino</option><option>Nocturno</option></select></label>
     <label>Entrega el turno<input name="author" placeholder="Nombre completo" required></label>
     <label>Recibe el turno<input name="receiver" placeholder="Nombre completo" required></label>
     <label class="wide">Novedades del turno<textarea name="news" rows="5" placeholder="Estado de residentes, cambios clínicos, incidencias y observaciones relevantes" required></textarea></label>
     <label class="wide">Medicamentos o cuidados pendientes<textarea name="pending" rows="4" placeholder="Indique qué debe completarse en el siguiente turno"></textarea></label>
     <label class="wide">Indicaciones especiales<textarea name="instructions" rows="3" placeholder="Vigilancia, citas, traslados, comunicación familiar u otras instrucciones"></textarea></label>
   </div>
   <div class="handoff-warning">Al presionar “Entregar turno”, la ficha quedará cerrada y no podrá modificarse.</div>
   <div class="form-actions"><button class="primary-btn" type="submit">Entregar y cerrar turno</button></div>
 </form>
 <section class="handoff-history-section">
   <div class="handoff-history-title"><div><span>HISTORIAL</span><h3>Entregas registradas</h3></div><b>${records.length}</b></div>
   <div class="handoff-record-grid">${records.length?records.map((r,i)=>`<button class="handoff-record-card" data-handoff-view="${i}">
     <div class="handoff-record-top"><span class="handoff-shift">${r.shift||'Turno'}</span><span class="handoff-closed">Cerrado</span></div>
     <strong>${r.author||'Sin nombre'} <span>→</span> ${r.receiver||'Sin registrar'}</strong>
     <p>${String(r.news||'Sin novedades').slice(0,110)}${String(r.news||'').length>110?'…':''}</p>
     <div class="handoff-record-foot"><span>${fmtDate(r.date)}</span><span>Ver ficha ›</span></div>
   </button>`).join(''):empty('No hay entregas de turno registradas.')}</div>
 </section>`;
}

function saveInventory(){ localStorage.setItem('seniorcare-inventory',JSON.stringify(inventoryItems)); }
function renderInventory(){
 const low=inventoryItems.filter(i=>Number(i.stock)<=Number(i.min)).length;
 const total=inventoryItems.reduce((a,i)=>a+Number(i.stock||0),0);
 main.innerHTML=pageHeader('CONTROL DE EXISTENCIAS','Inventario','Medicamentos, insumos y movimientos')+`
 <div class="inventory-grid"><article><span class="quick-icon amber">${svg.bottle}</span><div><strong>Productos registrados</strong><small>Medicamentos e insumos</small></div><b>${inventoryItems.length}</b></article><article><span class="quick-icon mint">${svg.box}</span><div><strong>Existencia total</strong><small>Unidades registradas</small></div><b>${total}</b></article><article><span class="quick-icon lilac">${svg.alert}</span><div><strong>Stock bajo</strong><small>Requieren reposición</small></div><b>${low}</b></article></div>
 <div class="inventory-toolbar"><div><strong>Listado de inventario</strong><div class="note">Añada productos y registre entradas o salidas.</div></div><div class="toolbar-actions"><button class="secondary-btn" id="addMovement">Registrar movimiento</button><button class="primary-btn" id="addInventory">${svg.plus} Añadir producto</button></div></div>
 <form class="form-card hidden" id="movementForm"><div class="form-grid"><label>Producto<select name="itemId">${inventoryItems.map(i=>`<option value="${i.id}">${i.name}</option>`).join('')}</select></label><label>Tipo<select name="type"><option>Entrada</option><option>Salida</option></select></label><label>Cantidad<input name="qty" type="number" min="1" required></label><label>Motivo<input name="reason" required></label></div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelMovement">Cancelar</button><button class="primary-btn">Guardar movimiento</button></div></form>
 <div class="inventory-table">${inventoryItems.map(i=>`<article class="inventory-row"><div><strong>${i.name}</strong><small>${i.category}</small></div><div><span>Existencia</span><strong class="${Number(i.stock)<=Number(i.min)?'stock-low':'stock-ok'}">${i.stock} ${i.unit}</strong></div><div><span>Mínimo</span><strong>${i.min}</strong></div><div>${statusPill(Number(i.stock)<=Number(i.min)?'Stock bajo':'Disponible')}</div><div class="inventory-actions"><button class="edit" data-inventory-edit="${i.id}">Editar</button><button class="delete" data-inventory-delete="${i.id}">Eliminar</button></div></article>`).join('')}</div>
 <section class="history-card"><h3>Movimientos recientes</h3>${inventoryMovements.length?inventoryMovements.slice(0,10).map(m=>`<div class="history-line"><b>${m.type} · ${m.item}</b><span>${m.qty} · ${m.reason} · ${m.date}</span></div>`).join(''):empty('No hay movimientos registrados.')}</section>`;
}
function editInventoryItem(id){
 const current=inventoryItems.find(i=>i.id===id)||{id:Date.now(),name:'',category:'Insumos clínicos',stock:0,min:0,unit:'unidades'};
 const name=prompt('Nombre del producto:',current.name); if(name===null||!name.trim()) return;
 const category=prompt('Categoría:',current.category); if(category===null) return;
 const stock=prompt('Existencia actual:',current.stock); if(stock===null||isNaN(Number(stock))) return;
 const min=prompt('Existencia mínima:',current.min); if(min===null||isNaN(Number(min))) return;
 const unit=prompt('Unidad (tabletas, cajas, unidades):',current.unit); if(unit===null) return;
 Object.assign(current,{name:name.trim(),category:category.trim(),stock:Number(stock),min:Number(min),unit:unit.trim()});
 if(!inventoryItems.some(i=>i.id===current.id)) inventoryItems.push(current);
 saveInventory(); renderInventory(); bindActions(); showToast('Inventario actualizado.');
}

function renderReports(){
 const reports=['Reporte diario del hogar','Hoja de medicamentos','Signos vitales','Cuidados diarios','Curaciones','Incidentes','Citas y traslados','Cumplimiento del personal'];
 main.innerHTML=pageHeader('DOCUMENTACIÓN Y CONTROL','Reportes','Informes clínicos y operativos')+`
 <div class="report-grid">${reports.map((r,i)=>`<button type="button" data-report="${i}"><span class="quick-icon ${i%3===0?'lilac':i%3===1?'mint':'amber'}">${svg.report}</span><div><strong>${r}</strong><small>Vista previa, impresión o PDF</small></div><b>›</b></button>`).join('')}</div>
 <section id="reportPreview" class="report-preview hidden"></section>`;
}

function openRecordModal(title, body, actions=''){
  document.querySelector('.record-modal')?.remove();
  const wrap=document.createElement('div');
  wrap.className='record-modal';
  wrap.innerHTML=`<div class="record-modal-backdrop" data-modal-close></div><section class="record-modal-card" role="dialog" aria-modal="true"><div class="record-modal-head"><div><span>Detalle del registro</span><h3>${title}</h3></div><button class="modal-close" data-modal-close>×</button></div><div class="record-modal-body">${body}</div>${actions?`<div class="record-modal-actions">${actions}</div>`:''}</section>`;
  document.body.appendChild(wrap);
  wrap.querySelectorAll('[data-modal-close]').forEach(b=>b.addEventListener('click',()=>wrap.remove()));
}
function vitalModal(record,residentName){
  openRecordModal('Signos vitales',`<div class="detail-grid"><article><span>Residente</span><strong>${residentName}</strong></article><article><span>Fecha y hora</span><strong>${fmtDate(record.date)}</strong></article><article><span>Presión arterial</span><strong>${record.sys}/${record.dia} mmHg</strong></article><article><span>Frecuencia cardíaca</span><strong>${record.hr} lpm</strong></article><article><span>Temperatura</span><strong>${record.temp} °C</strong></article><article><span>Saturación</span><strong>${record.spo2}%</strong></article><article><span>Glucemia</span><strong>${record.glu||'--'} mg/dL</strong></article><article><span>Peso</span><strong>${record.weight||'--'} kg</strong></article><article><span>Dolor</span><strong>${record.pain||'--'}</strong></article><article class="wide"><span>Observaciones</span><strong>${record.obs||'Sin observaciones'}</strong></article></div>`);
}
function woundModal(record,residentName){
  openRecordModal('Detalle de curación',`<div class="detail-grid"><article><span>Residente</span><strong>${residentName}</strong></article><article><span>Fecha y hora</span><strong>${fmtDate(record.date)}</strong></article><article><span>Área</span><strong>${record.area}</strong></article><article><span>Tamaño</span><strong>${record.size||'--'}</strong></article><article><span>Exudado</span><strong>${record.exudate||'--'}</strong></article><article><span>Dolor</span><strong>${record.pain||'--'}</strong></article><article><span>Estado</span><strong>${record.status||'--'}</strong></article><article><span>Próxima curación</span><strong>${record.next||'Sin fecha'}</strong></article><article class="wide"><span>Procedimiento</span><strong>${record.procedure||'Sin detalle'}</strong></article><article class="wide"><span>Observaciones</span><strong>${record.obs||'Sin observaciones'}</strong></article></div>`);
}

function renderUsersAccess(){
  if(!['admin','supervisor'].includes(currentUser?.role)){main.innerHTML=pageHeader('ACCESO RESTRINGIDO','Sin autorización','Este módulo está disponible únicamente para administración.');return;}
  const activeCodes=accessCodes.filter(c=>!c.used&&new Date(c.expires)>new Date());
  main.innerHTML=pageHeader('SEGURIDAD Y PERMISOS','Usuarios y accesos','Gestione cuentas, roles y códigos de inscripción')+`<section class="access-summary"><article><span>Usuarios activos</span><strong>${users.filter(u=>u.active!==false).length}</strong></article><article><span>Códigos disponibles</span><strong>${activeCodes.length}</strong></article><article><span>Roles configurados</span><strong>3</strong></article></section><section class="form-card access-generator"><h3>Generar código de inscripción</h3><p>El código define el panel del nuevo usuario y puede utilizarse una sola vez.</p><form id="accessCodeForm" class="form-grid"><label>Rol<select name="role"><option value="nurse">Enfermería</option><option value="assistant">Asistente</option><option value="admin">Administrador</option></select></label><label>Vigencia<select name="days"><option value="1">24 horas</option><option value="3">3 días</option><option value="7" selected>7 días</option></select></label><div class="wide form-actions"><button class="primary-btn" type="submit">${svg.plus} Generar código</button></div></form></section><section class="history-card"><h3>Códigos de acceso</h3><div class="access-code-list">${accessCodes.length?accessCodes.map(c=>`<article class="access-code-card ${c.used?'used':''}"><div><span>${ROLE_LABELS[c.role]}</span><strong>${c.code}</strong><small>${c.used?'Utilizado':new Date(c.expires)>new Date()?`Vence ${fmtDate(c.expires)}`:'Vencido'}</small></div>${!c.used?`<button class="mini-btn" data-copy-code="${c.code}">Copiar</button>`:''}</article>`).join(''):empty('No hay códigos generados')}</div></section><section class="history-card"><h3>Usuarios registrados</h3><div class="user-access-list">${users.map(u=>`<article class="user-access-card"><div class="avatar">${u.name.split(' ').map(x=>x[0]).slice(0,2).join('')}</div><div><strong>${u.name}</strong><span>${ROLE_LABELS[u.role]} · @${u.username}</span><small>${u.active===false?'Acceso desactivado':'Acceso activo'}</small></div>${u.id!==currentUser.id?`<button class="mini-btn" data-toggle-user="${u.id}">${u.active===false?'Activar':'Desactivar'}</button>`:'<span class="status ok">Sesión actual</span>'}</article>`).join('')}</div></section>`;
}

function render(){
 activeScreen=ensureAllowed(activeScreen);
 const currentRoute=routeSnapshot();
 if(lastRenderedRoute&&!suppressAutomaticRouteCapture&&!sameRoute(lastRenderedRoute,currentRoute)){
   pushRoute(lastRenderedRoute);
 }
 suppressAutomaticRouteCapture=false;
 syncConnectedAlerts();
 const screens={home:renderHome,residents:renderResidents,inactive:renderInactiveResidents,resident:renderResidentDetail,admissions:renderAdmissions,medications:renderMedications,vitals:renderVitals,care:()=>((typeof window.renderCare==='function'?window.renderCare:renderCare)()),wounds:renderWounds,agenda:renderAgenda,incidents:renderIncidents,nutrition:()=>((typeof window.renderNutrition==='function'?window.renderNutrition:renderNutrition)()),nursing:renderNursing,alerts:renderAlerts,more:renderMore,staff:()=>((typeof window.renderStaffGlobal==='function'?window.renderStaffGlobal:renderStaff)()),handoff:renderHandoff,inventory:renderInventory,reports:renderReports,usersAccess:renderUsersAccess,medicalNotes:()=>window.renderMedicalNotes?.(),medicalAppointmentsAdmin:()=>window.renderMedicalAppointmentsAdmin?.(),medicalAppointmentsDoctor:()=>window.renderMedicalAppointmentsDoctor?.(),medicalDashboard:()=>window.renderMedicalDashboard?.(),medicalConsultation:()=>window.renderMedicalConsultation?.(),medicalOrders:()=>window.renderMedicalOrders?.(),medicalResults:()=>window.renderMedicalResults?.(),medicalAssessments:()=>window.renderMedicalAssessments?.(),medicalHistory:()=>window.renderMedicalHistory?.(),medicalPrescriptions:()=>window.renderMedicalPrescriptions?.(),medicalDocuments:()=>window.renderMedicalDocuments?.(),medicalStudies:()=>window.renderMedicalStudies?.(),medicalEmergencies:()=>window.renderMedicalEmergencies?.(),medicalUrgencyNotify:()=>window.renderMedicalUrgencyNotify?.(),operationalTasks:window.renderOperationalTasks,operationalIncidents:window.renderOperationalIncidentsGlobal,operationalAlerts:window.renderOperationalAlertsGlobal,supervisorOrganizations:window.renderSupervisorOrganizations,supervisorLicenses:window.renderSupervisorLicenses,supervisorAdmins:window.renderSupervisorAdmins,supervisorPayments:window.renderSupervisorPayments,supervisorAudit:window.renderSupervisorAudit,supervisorAlerts:window.renderSupervisorAlerts,supervisorSupport:window.renderSupervisorSupport,supervisorOrganizationDetail:window.renderSupervisorOrganizationDetail,supervisorMore:window.renderSupervisorMore};
 (screens[activeScreen]||renderHome)(); bindActions(); setActiveNav(currentUser?.role==='doctor'?(activeScreen==='medicalHistory'?'medicalHistory':activeScreen==='medicalOrders'?'medicalOrders':activeScreen==='medicalResults'?'medicalResults':activeScreen==='medicalPrescriptions'?'medicalPrescriptions':'medicalDashboard'):currentUser?.role==='supervisor'?(activeScreen==='supervisorOrganizations'?'supervisorOrganizations':activeScreen==='supervisorLicenses'?'supervisorLicenses':activeScreen==='supervisorPayments'?'supervisorPayments':activeScreen==='supervisorAudit'?'supervisorAudit':activeScreen==='supervisorAlerts'?'supervisorAlerts':activeScreen==='supervisorMore'?'supervisorMore':'home'):['cook','cleaning','maintenance','security'].includes(currentUser?.role)?(['operationalTasks','operationalIncidents','operationalAlerts','nutrition'].includes(activeScreen)?activeScreen:'home'):['residents','inactive','resident','admissions'].includes(activeScreen)?'residents':activeScreen==='agenda'?'agenda':activeScreen==='alerts'?'alerts':['more','staff','handoff','inventory','nutrition','wounds','reports','operationalTasks','medicalUrgencyNotify'].includes(activeScreen)?'more':['medicalNotes'].includes(activeScreen)?'residents':'home');
 lastRenderedRoute=routeSnapshot();
}

function bindActions(){
 document.getElementById('accessCodeForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);const role=String(fd.get('role'));const days=Number(fd.get('days'))||7;const code={id:Date.now(),code:generateAccessCode(role),role,created:new Date().toISOString(),expires:new Date(Date.now()+days*86400000).toISOString(),used:false};accessCodes.unshift(code);saveAccessCodes();renderUsersAccess();bindActions();showToast(`Código ${code.code} generado.`);});
 main.querySelectorAll('[data-copy-code]').forEach(el=>el.addEventListener('click',async()=>{const code=el.dataset.copyCode;try{await navigator.clipboard.writeText(code);showToast('Código copiado.');}catch{prompt('Copie este código:',code);}}));
 main.querySelectorAll('[data-toggle-user]').forEach(el=>el.addEventListener('click',()=>{const u=users.find(x=>x.id===Number(el.dataset.toggleUser));if(u){u.active=u.active===false?true:false;saveUsers();renderUsersAccess();bindActions();showToast('Acceso actualizado.');}}));
 main.querySelectorAll('[data-go]').forEach(el=>el.addEventListener('click',()=>go(el.dataset.go)));
 main.querySelectorAll('[data-resident-go]').forEach(el=>el.addEventListener('click',()=>go(el.dataset.residentGo,{resident:selectedResident,scope:'resident'})));
 main.querySelectorAll('[data-back]').forEach(el=>el.addEventListener('click',goBack));
 main.querySelectorAll('[data-toast]').forEach(el=>el.addEventListener('click',()=>showToast(el.dataset.toast)));
 main.querySelectorAll('[data-inactive-reactivate]').forEach(el=>el.addEventListener('click',async()=>reactivateInactiveResident(el.dataset.inactiveReactivate)));
 main.querySelectorAll('[data-inactive-delete]').forEach(el=>el.addEventListener('click',async()=>deleteInactiveResident(el.dataset.inactiveDelete)));
 main.querySelectorAll('[data-resident]').forEach(el=>el.addEventListener('click',()=>go('resident',{resident:residents.find(r=>residentKey(r)===String(el.dataset.resident)||String(r.id)===String(el.dataset.resident))})));
 main.querySelectorAll('form').forEach(f=>f.addEventListener('submit',e=>{ if(['incidentForm','admissionForm','appointmentForm','nursingForm','movementForm','vitalsForm','woundForm','medicationForm','nutritionForm','handoffForm'].includes(f.id)) return; e.preventDefault(); showToast('Información guardada correctamente.'); }));
/* V2.1.1: acciones de cuidados manejadas por clinical-sync-global-v211.js */
/* V2.1.1: acciones de cuidados manejadas por clinical-sync-global-v211.js */
 document.getElementById('editCareSelection')?.addEventListener('click',()=>{carePlanEditing=true;renderCare();bindActions();});
 document.getElementById('cancelCareSelection')?.addEventListener('click',()=>{carePlanEditing=false;renderCare();bindActions();});
 document.getElementById('addCareTask')?.addEventListener('click',()=>{const name=prompt('Nombre de la nueva tarea de cuidado:'); if(name?.trim()){const tasks=getCareTasks(residentKey(selectedResident)); if(!tasks.some(t=>String(t.name).toLowerCase()===name.trim().toLowerCase()))tasks.push({id:(crypto.randomUUID?.()||String(Date.now()+Math.random())),name:name.trim(),done:false});saveCarePlans();carePlanEditing=true;renderCare();bindActions();showToast('Tarea personalizada añadida. Revise y guarde el plan.');}});
 document.getElementById('saveCareSelection')?.addEventListener('click',()=>{const rid=residentKey(selectedResident);const current=getCareTasks(rid);const byName=new Map(current.map(t=>[String(t.name||'').trim(),t]));const names=[...main.querySelectorAll('[data-care-plan-option]:checked')].map(el=>String(el.value||'').trim()).filter(Boolean);carePlans[rid]=names.map(name=>byName.get(name)||{id:(crypto.randomUUID?.()||String(Date.now()+Math.random())),name,done:false});saveCarePlans();carePlanEditing=false;renderCare();bindActions();setTimeout(()=>window.BHSC_SAVE_CARE_PLAN?.(rid),0);showToast('Plan individual guardado. Solo quedaron las tareas seleccionadas.');});
/* V2.1.1: acciones de cuidados manejadas por clinical-sync-global-v211.js */
 document.getElementById('careResidentSelect')?.addEventListener('change',e=>{ const found = residents.find(r=>residentKey(r)===String(e.target.value)||String(r.id)===String(e.target.value)); if(found){ selectedResident = found; renderCare(); bindActions(); } });
 document.getElementById('nutritionResidentSelect')?.addEventListener('change',e=>{selectedResident=residents.find(r=>residentKey(r)===String(e.target.value)||String(r.id)===String(e.target.value))||selectedResident;renderNutrition();bindActions();});
 document.getElementById('nursingResidentSelect')?.addEventListener('change',e=>{selectedResident=residents.find(r=>residentKey(r)===String(e.target.value)||String(r.id)===String(e.target.value))||selectedResident;renderNursing();bindActions();});

/* V2.1.1: incidentForm manejado por clinical-sync-global-v211.js */
 document.getElementById('editResidentButton')?.addEventListener('click',()=>{window.__BHSC_EDIT_RESIDENT_KEY=residentKey(selectedResident);go('admissions',{resident:selectedResident});});
 document.getElementById('deleteResidentButton')?.addEventListener('click',async e=>{
   const resident=selectedResident;
   if(!resident)return;
   const expected=String(resident.name||'').trim();
   const typed=prompt(`Esta acción quitará al residente de la aplicación y conservará su historial clínico para auditoría.\n\nEscriba exactamente: ${expected}`);
   if(typed===null)return;
   if(typed.trim()!==expected){showToast('El nombre no coincide. No se eliminó el residente.');return;}
   const button=e.currentTarget;button.disabled=true;
   try{
     if(typeof window.deleteResidentFromCloud!=='function')throw new Error('La función de eliminación no está disponible.');
     await window.deleteResidentFromCloud(resident);
     selectedResident=null;residentScoped=false;window.__BHSC_EDIT_RESIDENT_KEY='';
     showToast('Residente eliminado correctamente.');
     go('residents',{}, {replace:true});
   }catch(error){showToast(`No se pudo eliminar: ${error?.message||error}`);button.disabled=false;}
 });
 document.getElementById('cancelResidentForm')?.addEventListener('click',()=>{const editing=!!window.__BHSC_EDIT_RESIDENT_KEY;window.__BHSC_EDIT_RESIDENT_KEY='';if(editing&&selectedResident)go('resident',{resident:selectedResident},{replace:true});else go('residents',{}, {replace:true});});
 document.getElementById('admissionForm')?.addEventListener('submit',async e=>{ e.preventDefault(); e.stopImmediatePropagation(); const fd=new FormData(e.currentTarget); const name=fd.get('name')?.toString().trim(); if(!name){showToast('Digite el nombre del residente.');return;} const editKey=fd.get('residentKey')?.toString().trim()||''; const existingIndex=editKey?residents.findIndex(r=>residentKey(r)===editKey||String(r.id)===editKey):-1; const existing=existingIndex>=0?residents[existingIndex]:null; const identification=fd.get('identification')?.toString().trim()||''; if(identification){ const duplicate=residents.find(r=>(residentKey(r)!==editKey&&String(r.id)!==editKey)&&String(r.identification||r.identification_number||'').trim().toLowerCase()===identification.toLowerCase()); if(duplicate){showToast('Ya existe otro residente registrado con ese número de cédula.');return;} } const key=editKey||((crypto.randomUUID&&crypto.randomUUID())||`resident-${Date.now()}-${Math.random().toString(16).slice(2)}`); const family=fd.get('family')?.toString().trim()||''; const phone=fd.get('phone')?.toString().trim()||''; const resident={...(existing||{}),id:existing?.id||key,resident_key:key,identification,identification_number:identification,name,full_name:name,age:Number(fd.get('age'))||0,room:fd.get('room')?.toString().trim()||'Sin asignar',status:fd.get('status')?.toString()||'Estable',risk:fd.get('risk')?.toString()||'Riesgo medio',diet:fd.get('diet')?.toString()||fd.get('nutrition')?.toString()||'Corriente',family,phone,contact:`${family||'Sin familiar'} · ${phone||'Sin teléfono'}`,dx:fd.get('dx')?.toString().trim()||'Sin diagnósticos registrados',allergy:fd.get('allergy')?.toString().trim()||'Ninguna conocida'}; const backup=existing?{...existing}:null; if(existingIndex>=0)residents[existingIndex]=resident; else residents.push(resident); saveResidents(); try{ if(!window.saveResidentToCloud)throw new Error('El sincronizador de residentes no está disponible.'); await window.saveResidentToCloud(resident,{pullAfter:true}); }catch(err){console.error('[BHSC residentes]',err); if(existingIndex>=0&&backup)residents[existingIndex]=backup; else {const removeIndex=residents.findIndex(r=>residentKey(r)===key);if(removeIndex>=0)residents.splice(removeIndex,1);} saveResidents(); showToast(err.message||'No se pudo guardar en Supabase.'); return;} selectedResident=residents.find(r=>residentKey(r)===key||String(r.id)===String(resident.id))||resident; const wasEditing=!!editKey; window.__BHSC_EDIT_RESIDENT_KEY=''; showToast(wasEditing?'Información del residente actualizada.':'Residente admitido y sincronizado correctamente.'); go('resident',{resident:selectedResident},{replace:true}); });
 document.getElementById('addAppointment')?.addEventListener('click',()=>document.getElementById('appointmentForm')?.classList.remove('hidden'));
 document.getElementById('cancelAppointment')?.addEventListener('click',()=>document.getElementById('appointmentForm')?.classList.add('hidden'));
 main.querySelectorAll('[data-appointment-edit]').forEach(el=>el.addEventListener('click',()=>{const a=appointments.find(x=>x.id===Number(el.dataset.appointmentEdit));const f=document.getElementById('appointmentForm');if(!a||!f)return;f.classList.remove('hidden');Object.entries(a).forEach(([k,v])=>{if(f.elements[k])f.elements[k].value=v??'';});f.elements.appointmentId.value=a.id;}));
/* V2.1.1: acciones de agenda manejadas por clinical-sync-global-v211.js */
/* V2.1.1: appointmentForm manejado por clinical-sync-global-v211.js */
 document.getElementById('nursingForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);const note=fd.get('note')?.toString().trim();if(!note){showToast('Escriba la nota de enfermería.');return;}if(!nursingNotes[selectedResident.id])nursingNotes[selectedResident.id]=[];nursingNotes[selectedResident.id].unshift({date:new Date().toLocaleString('es-CR'),shift:fd.get('shift')?.toString(),status:fd.get('status')?.toString(),author:currentUser?.name||'Enfermería',note});saveNursingNotes();renderNursing();bindActions();showToast('Nota guardada.');});
 main.querySelectorAll('[data-note-delete]').forEach(el=>el.addEventListener('click',()=>{if(confirm('¿Eliminar esta nota?')){(nursingNotes[selectedResident.id]||[]).splice(Number(el.dataset.noteDelete),1);saveNursingNotes();renderNursing();bindActions();showToast('Nota eliminada.');}}));
/* V2.1.1: vitalsForm manejado por clinical-sync-global-v211.js */
main.querySelectorAll('[data-vital-view]').forEach(el=>el.addEventListener('click',()=>{const rid=String(el.dataset.vitalResident);const rec=getResidentVitals(rid).find(r=>String(r.id)===String(el.dataset.vitalView));const resident=residents.find(r=>residentKey(r)===rid||String(r.id)===rid);if(rec)vitalModal(rec,resident?.name||'Residente');}));
main.querySelectorAll('[data-vital-edit]').forEach(el=>el.addEventListener('click',()=>{const rid=String(el.dataset.vitalResident);const rec=getResidentVitals(rid).find(r=>String(r.id)===String(el.dataset.vitalEdit));const f=document.getElementById('vitalsForm');if(!rec||!f)return;if(f.elements.residentId)f.elements.residentId.value=rid;f.elements.recordId.value=rec.id;['sys','dia','hr','temp','spo2','glu','weight','pain','obs'].forEach(k=>{if(f.elements[k])f.elements[k].value=rec[k]??'';});document.getElementById('cancelVitalEdit')?.classList.remove('hidden');f.scrollIntoView({behavior:'smooth',block:'start'});}));
document.getElementById('cancelVitalEdit')?.addEventListener('click',()=>{const f=document.getElementById('vitalsForm');f?.reset();if(f?.elements.recordId)f.elements.recordId.value='';document.getElementById('cancelVitalEdit')?.classList.add('hidden');});
/* V2.1.1: acciones de signos manejadas por clinical-sync-global-v211.js */
/* V2.1.1: acciones de signos manejadas por clinical-sync-global-v211.js */
/* V2.1.1: acciones de signos manejadas por clinical-sync-global-v211.js */
function resolveWoundResident(ref){
 const key=String(ref??'').trim();
 return residents.find(r=>residentKey(r)===key||String(r.id)===key||String(r.name||'')===key)||selectedResident||null;
}
function woundLocalId(ref){const r=resolveWoundResident(ref);return r?.id??ref;}
document.getElementById('woundForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);const selectedRef=fd.get('residentId')??residentKey(selectedResident);const resident=resolveWoundResident(selectedRef);if(!resident){showToast('Seleccione una residente válida.');return;}const residentId=resident.id;const recordId=String(fd.get('recordId')||'').trim();const area=fd.get('area')?.toString().trim();if(!area){showToast('Indique el área de la curación.');return;}const arr=getResidentWounds(residentId);const existing=arr.find(r=>String(r.id)===recordId);const record={id:recordId||((crypto.randomUUID&&crypto.randomUUID())||`${Date.now()}-${Math.random().toString(16).slice(2)}`),date:existing?.date||new Date().toISOString(),area,size:fd.get('size')?.toString().trim(),exudate:fd.get('exudate')?.toString(),pain:fd.get('pain')?.toString(),next:fd.get('next')?.toString(),status:fd.get('status')?.toString(),procedure:fd.get('procedure')?.toString().trim(),obs:fd.get('obs')?.toString().trim(),archived:false};const idx=arr.findIndex(r=>String(r.id)===String(record.id));if(idx>=0)arr[idx]={...arr[idx],...record};else arr.unshift(record);saveWoundRecords();e.currentTarget.reset();if(e.currentTarget.elements.residentId)e.currentTarget.elements.residentId.value=residentKey(resident);e.currentTarget.elements.recordId.value='';document.getElementById('cancelWoundEdit')?.classList.add('hidden');renderWounds();bindActions();showToast(recordId?'Curación actualizada.':'Curación registrada correctamente.');});
main.querySelectorAll('[data-wound-view]').forEach(el=>el.addEventListener('click',()=>{const rid=woundLocalId(el.dataset.woundResident);const rec=getResidentWounds(rid).find(r=>String(r.id)===String(el.dataset.woundView));const resident=resolveWoundResident(el.dataset.woundResident);if(rec)woundModal(rec,resident?.name||'Residente');}));
main.querySelectorAll('[data-wound-edit]').forEach(el=>el.addEventListener('click',()=>{const rid=woundLocalId(el.dataset.woundResident);const rec=getResidentWounds(rid).find(r=>String(r.id)===String(el.dataset.woundEdit));const f=document.getElementById('woundForm');if(!rec||!f)return;const resident=resolveWoundResident(el.dataset.woundResident);if(f.elements.residentId)f.elements.residentId.value=residentKey(resident);f.elements.recordId.value=rec.id;['area','size','exudate','pain','next','status','procedure','obs'].forEach(k=>{if(f.elements[k])f.elements[k].value=rec[k]??'';});document.getElementById('cancelWoundEdit')?.classList.remove('hidden');f.scrollIntoView({behavior:'smooth',block:'start'});}));
document.getElementById('cancelWoundEdit')?.addEventListener('click',()=>{const f=document.getElementById('woundForm');f?.reset();if(f?.elements.recordId)f.elements.recordId.value='';document.getElementById('cancelWoundEdit')?.classList.add('hidden');});
main.querySelectorAll('[data-wound-archive]').forEach(el=>el.addEventListener('click',()=>{const rid=woundLocalId(el.dataset.woundResident);const rec=getResidentWounds(rid).find(r=>String(r.id)===String(el.dataset.woundArchive));if(rec){rec.archived=true;saveWoundRecords();renderWounds();bindActions();showToast('Curación archivada.');}}));
main.querySelectorAll('[data-wound-restore]').forEach(el=>el.addEventListener('click',()=>{const rid=woundLocalId(el.dataset.woundResident);const rec=getResidentWounds(rid).find(r=>String(r.id)===String(el.dataset.woundRestore));if(rec){rec.archived=false;saveWoundRecords();renderWounds();bindActions();showToast('Curación restaurada.');}}));
main.querySelectorAll('[data-wound-delete]').forEach(el=>el.addEventListener('click',()=>{if(confirm('¿Eliminar definitivamente este registro de curación?')){const rid=woundLocalId(el.dataset.woundResident);woundRecords[rid]=getResidentWounds(rid).filter(r=>String(r.id)!==String(el.dataset.woundDelete));saveWoundRecords();renderWounds();bindActions();showToast('Registro de curación eliminado.');}}));
function updateMedicationFrequencyFields(){
 const f=document.getElementById('medicationForm');if(!f)return;const immediate=f.elements.frequency?.value==='Inmediato';document.getElementById('medTimesWrap')?.classList.toggle('hidden',immediate);if(immediate&&f.elements.times)f.elements.times.value='';
}
document.getElementById('medFrequency')?.addEventListener('change',updateMedicationFrequencyFields);
main.querySelectorAll('[data-incident-edit]').forEach(el=>el.addEventListener('click',()=>{const item=incidents.find(i=>String(i.id||i.date)===String(el.dataset.incidentEdit));const f=document.getElementById('incidentForm');if(!item||!f)return;f.elements.incidentId.value=item.id||'';if(f.elements.resident)f.elements.resident.value=item.resident;const typeParts=String(item.type||'').split(' · ');f.elements.type.value=typeParts[0]||'Otro';f.elements.level.value=item.level||'Media';f.elements.date.value=item.date||'';f.elements.description.value=typeParts.slice(1).join(' · ')||item.type||'';f.elements.action.value=item.action||'';f.elements.status.value=item.status||'Por revisar';document.getElementById('cancelIncidentEdit')?.classList.remove('hidden');const btn=document.getElementById('saveIncidentButton');if(btn)btn.textContent='Guardar cambios';f.scrollIntoView({behavior:'smooth',block:'start'});}));
document.getElementById('cancelIncidentEdit')?.addEventListener('click',()=>{const f=document.getElementById('incidentForm');f?.reset();if(f?.elements.incidentId)f.elements.incidentId.value='';document.getElementById('cancelIncidentEdit')?.classList.add('hidden');const btn=document.getElementById('saveIncidentButton');if(btn)btn.textContent='Registrar incidente';});
document.getElementById('addMedication')?.addEventListener('click',()=>{const f=document.getElementById('medicationForm');f?.classList.remove('hidden');updateMedicationFrequencyFields();});
document.getElementById('cancelMedication')?.addEventListener('click',()=>{const f=document.getElementById('medicationForm');f?.reset();if(f?.elements.medicationId)f.elements.medicationId.value='';f?.classList.add('hidden');});
main.querySelectorAll('[data-med-admin]').forEach(el=>el.addEventListener('click',()=>{const m=meds.find(x=>String(x.id)===String(el.dataset.medAdmin));if(m){m.status='Administrado';saveMedications();addAlert('Medicamento administrado',`${m.resident} · ${m.drug}`,'Seguimiento','medication');renderMedications();bindActions();showToast('Dosis registrada.');}}));
main.querySelectorAll('[data-med-edit]').forEach(el=>el.addEventListener('click',()=>{const m=meds.find(x=>String(x.id)===String(el.dataset.medEdit));const f=document.getElementById('medicationForm');if(!m||!f)return;f.classList.remove('hidden');f.elements.medicationId.value=m.id;if(f.elements.resident)f.elements.resident.value=m.resident;f.elements.drug.value=m.drug;if(f.elements.dose)f.elements.dose.value=m.dose||'';f.elements.frequency.value=m.immediate?'Inmediato':(m.frequency||'Horarios específicos');f.elements.times.value=medicationTimes(m).filter(t=>t!=='Inmediato').join(', ');f.elements.route.value=m.route;f.elements.status.value=m.status;updateMedicationFrequencyFields();f.scrollIntoView({behavior:'smooth',block:'start'});}));
main.querySelectorAll('[data-med-delete]').forEach(el=>el.addEventListener('click',()=>{if(confirm('¿Eliminar este medicamento?')){meds=meds.filter(m=>String(m.id)!==String(el.dataset.medDelete));saveMedications();renderMedications();bindActions();showToast('Medicamento eliminado.');}}));
document.getElementById('medicationForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);const id=Number(fd.get('medicationId'))||Date.now();const frequency=fd.get('frequency')?.toString()||'Horarios específicos';const immediate=frequency==='Inmediato';const times=immediate?[]:parseMedicationTimes(fd.get('times'));if(!immediate&&!times.length){showToast('Ingrese al menos una hora de administración.');return;}const data={id,resident:fd.get('resident')?.toString(),drug:fd.get('drug')?.toString().trim(),dose:fd.get('dose')?.toString().trim(),frequency,immediate,times,time:times[0]||'Ahora',route:fd.get('route')?.toString(),status:fd.get('status')?.toString()};const idx=meds.findIndex(m=>m.id===id);if(idx>=0)meds[idx]=data;else meds.push(data);saveMedications();renderMedications();bindActions();showToast('Medicamento guardado.');});
/* V2.1.1: nutritionForm manejado por clinical-sync-global-v211.js */
/* V2.1.1: acciones de nutrición manejadas por clinical-sync-global-v211.js */
document.getElementById('handoffForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);if(!confirm('¿Confirma la entrega del turno? Una vez guardada, la ficha no podrá editarse.'))return;handoffRecords.unshift({id:Date.now(),date:new Date().toISOString(),shift:fd.get('shift')?.toString(),incomingShift:fd.get('incomingShift')?.toString(),author:fd.get('author')?.toString().trim(),receiver:fd.get('receiver')?.toString().trim(),news:fd.get('news')?.toString().trim(),pending:fd.get('pending')?.toString().trim(),instructions:fd.get('instructions')?.toString().trim(),locked:true});saveHandoffs();renderHandoff();bindActions();showToast('Turno entregado y ficha cerrada.');});
main.querySelectorAll('[data-handoff-view]').forEach(el=>el.addEventListener('click',()=>{const r=handoffRecords[Number(el.dataset.handoffView)];if(!r)return;openRecordModal('Entrega de turno',`<div class="handoff-detail-status"><span>Ficha cerrada</span><strong>${r.shift||'Turno'} → ${r.incomingShift||'Siguiente turno'}</strong></div><div class="detail-grid"><article><span>Fecha y hora</span><strong>${fmtDate(r.date)}</strong></article><article><span>Estado</span><strong>Entregado</strong></article><article><span>Entregó</span><strong>${r.author||'Sin registrar'}</strong></article><article><span>Recibió</span><strong>${r.receiver||'Sin registrar'}</strong></article><article class="wide"><span>Novedades del turno</span><strong>${r.news||'Sin novedades'}</strong></article><article class="wide"><span>Medicamentos o cuidados pendientes</span><strong>${r.pending||'Sin pendientes'}</strong></article><article class="wide"><span>Indicaciones especiales</span><strong>${r.instructions||'Sin indicaciones especiales'}</strong></article></div><p class="locked-record-note">Este registro es permanente y no puede editarse.</p>`);}));
const refreshAlertsInPlace=(message='')=>{const y=window.scrollY;saveAlerts();renderAlerts();bindActions();requestAnimationFrame(()=>window.scrollTo(0,y));if(message)showToast(message);};
document.getElementById('markAllAlerts')?.addEventListener('click',ev=>{ev.preventDefault();ev.stopPropagation();alertsData.forEach(a=>{if(a.status==='Nueva')a.status='Vista'});refreshAlertsInPlace('Alertas nuevas marcadas como vistas.');});
main.querySelectorAll('[data-alert-seen]').forEach(el=>el.addEventListener('click',ev=>{ev.preventDefault();ev.stopPropagation();const a=alertsData.find(x=>x.id==el.dataset.alertSeen);if(a&&a.status==='Nueva'){a.status='Vista';refreshAlertsInPlace('Alerta marcada como vista.');}}));
main.querySelectorAll('[data-alert-resolve]').forEach(el=>el.addEventListener('click',ev=>{ev.preventDefault();ev.stopPropagation();const a=alertsData.find(x=>x.id==el.dataset.alertResolve);if(a&&a.status!=='Resuelta'){a.status='Resuelta';refreshAlertsInPlace('Alerta resuelta.');}}));
main.querySelectorAll('[data-alert-delete]').forEach(el=>el.addEventListener('click',ev=>{ev.preventDefault();ev.stopPropagation();const a=alertsData.find(x=>x.id==el.dataset.alertDelete);if(!a)return;if(a.sourceKey){dismissedConnectedAlertKeys.add(a.sourceKey);saveDismissedAlertKeys();}alertsData=alertsData.filter(x=>x.id!=a.id);try{window.BHSC_ALERT_DELETE?.(a.id)}catch(_){}refreshAlertsInPlace('Alerta cerrada.');}));
main.querySelectorAll('[data-alert-open]').forEach(el=>el.addEventListener('click',ev=>{ev.preventDefault();ev.stopPropagation();const a=alertsData.find(x=>x.id==el.dataset.alertOpen);if(!a)return;const resident=a.residentId?residents.find(r=>residentKey(r)===String(a.residentId)||String(r.id)===String(a.residentId)):null;if(resident){selectedResident=resident;residentScoped=true;}else{residentScoped=false;}if(a.status==='Nueva')a.status='Vista';saveAlerts();go(a.target||'alerts',resident?{resident,scope:'resident'}:{scope:'global'});}));
if(['administrator','admin','nurse'].includes(String(currentUser?.role||'').toLowerCase())) document.getElementById('familyWhatsAppButton')?.addEventListener('click',()=>openWhatsAppComposer(selectedResident));
main.querySelectorAll('[data-report]').forEach(el=>el.addEventListener('click',()=>{const idx=Number(el.dataset.report);const box=document.getElementById('reportPreview');const report=buildReportData(idx);box.classList.remove('hidden');box.innerHTML=renderReportPreview(report);box.scrollIntoView({behavior:'smooth',block:'start'});document.getElementById('closeReport')?.addEventListener('click',()=>box.classList.add('hidden'));document.getElementById('printReport')?.addEventListener('click',()=>window.print());}));
 main.querySelectorAll('[data-attendance]').forEach(el=>el.addEventListener('click',()=>{const id=Number(el.dataset.attendance);attendance[id]=attendance[id]===false?true:false;saveAttendance();renderStaff();bindActions();showToast('Asistencia actualizada.');}));
 main.querySelectorAll('[data-clock-in]').forEach(el=>el.addEventListener('click',()=>{const id=Number(el.dataset.clockIn);clockStaff(id,'in');renderStaff();bindActions();showToast('Entrada registrada correctamente.');}));
 main.querySelectorAll('[data-clock-out]').forEach(el=>el.addEventListener('click',()=>{const id=Number(el.dataset.clockOut);clockStaff(id,'out');renderStaff();bindActions();showToast('Salida registrada correctamente.');}));
 document.getElementById('addMovement')?.addEventListener('click',()=>document.getElementById('movementForm')?.classList.remove('hidden'));
 document.getElementById('cancelMovement')?.addEventListener('click',()=>document.getElementById('movementForm')?.classList.add('hidden'));
 document.getElementById('movementForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);const item=inventoryItems.find(i=>i.id===Number(fd.get('itemId')));const qty=Number(fd.get('qty'));const type=fd.get('type')?.toString();if(!item||qty<=0){showToast('Movimiento inválido.');return;}if(type==='Salida'&&qty>item.stock){showToast('La salida supera la existencia disponible.');return;}item.stock += type==='Entrada'?qty:-qty;inventoryMovements.unshift({id:Date.now(),item:item.name,type,qty,reason:fd.get('reason')?.toString().trim()||'Sin detalle',date:new Date().toLocaleString('es-CR')});saveInventory();saveInventoryMovements();renderInventory();bindActions();showToast('Movimiento registrado.');});

/* V2.1.1: acciones de incidentes manejadas por clinical-sync-global-v211.js */
/* V2.1.1: acciones de incidentes manejadas por clinical-sync-global-v211.js */
 document.getElementById('addStaff')?.addEventListener('click',()=>editStaffMember());
 document.getElementById('cancelStaff')?.addEventListener('click',()=>{document.getElementById('staffForm')?.classList.add('hidden');});
 document.getElementById('staffForm')?.addEventListener('submit',e=>{e.preventDefault();const fd=new FormData(e.currentTarget);const raw=fd.get('staffId')?.toString();const id=raw||String(Date.now());const shiftName=fd.get('shiftName')?.toString()||'Matutino';const startTime=fd.get('startTime')?.toString()||'06:00';const endTime=fd.get('endTime')?.toString()||'14:00';const workDays=fd.getAll('workDays').map(String);const data={id,name:fd.get('name')?.toString().trim(),role:fd.get('role')?.toString(),shiftName,startTime,endTime,shift:`${startTime}–${endTime}`,workDays,assignment:fd.get('assignment')?.toString().trim(),employmentStatus:fd.get('employmentStatus')?.toString()||'Activo',status:fd.get('employmentStatus')?.toString()||'Activo'};const idx=staffMembers.findIndex(m=>String(m.id)===String(id));if(idx>=0)staffMembers[idx]={...staffMembers[idx],...data};else staffMembers.push(data);saveStaff();renderStaff();bindActions();showToast('Personal y turno actualizados.');});
 main.querySelectorAll('[data-staff-edit]').forEach(el=>el.addEventListener('click',()=>editStaffMember(Number(el.dataset.staffEdit))));
 main.querySelectorAll('[data-staff-delete]').forEach(el=>el.addEventListener('click',()=>{if(confirm('¿Eliminar este colaborador?')){staffMembers=staffMembers.filter(m=>m.id!==Number(el.dataset.staffDelete));saveStaff();renderStaff();bindActions();showToast('Colaborador eliminado.');}}));
 document.getElementById('addInventory')?.addEventListener('click',()=>editInventoryItem());
 main.querySelectorAll('[data-inventory-edit]').forEach(el=>el.addEventListener('click',()=>editInventoryItem(Number(el.dataset.inventoryEdit))));
 main.querySelectorAll('[data-inventory-delete]').forEach(el=>el.addEventListener('click',()=>{if(confirm('¿Eliminar este producto del inventario?')){inventoryItems=inventoryItems.filter(i=>i.id!==Number(el.dataset.inventoryDelete));saveInventory();renderInventory();bindActions();showToast('Producto eliminado.');}}));
}
function editStaffMember(id){
 const current=staffMembers.find(m=>m.id===id);
 const f=document.getElementById('staffForm');
 if(!f)return;
 f.classList.remove('hidden');
 f.elements.staffId.value=current?.id||'';
 f.elements.name.value=current?.name||'';
 f.elements.role.value=current?.role||'Asistente';
 f.elements.shiftName.value=current?.shiftName||'Matutino';
 f.elements.startTime.value=current?.startTime||String(current?.shift||'06:00–14:00').slice(0,5)||'06:00';
 f.elements.endTime.value=current?.endTime||String(current?.shift||'06:00–14:00').slice(-5)||'14:00';
 f.elements.assignment.value=current?.assignment||'';
 f.elements.employmentStatus.value=current?.employmentStatus||current?.status||'Activo';
 const days=Array.isArray(current?.workDays)?current.workDays:['Lun','Mar','Mié','Jue','Vie'];
 f.querySelectorAll('input[name="workDays"]').forEach(box=>box.checked=days.includes(box.value));
 f.scrollIntoView({behavior:'smooth',block:'start'});
}

function renderNav(){
  const role=currentUser?.role||'admin';
  const sets={
    doctor:[['medicalDashboard','Inicio',svg.home],['medicalHistory','Expediente',svg.users],['medicalOrders','Indicaciones',svg.report],['medicalResults','Resultados',svg.heart],['medicalPrescriptions','Recetas',svg.calendar]],
    supervisor:[['home','Inicio',svg.home],['supervisorOrganizations','Organizaciones',svg.building],['supervisorLicenses','Licencias',svg.calendar],['supervisorPayments','Pagos',svg.report],['supervisorMore','Más',svg.more]],
    admin:[['home','Inicio',svg.home],['residents','Residentes',svg.users],['agenda','Agenda',svg.calendar],['alerts','Alertas',svg.bell],['more','Más',svg.more]],
    nurse:[['home','Inicio',svg.home],['residents','Residentes',svg.users],['medications','Medicamentos',svg.bottle],['alerts','Alertas',svg.bell],['more','Más',svg.more]],
    assistant:[['home','Inicio',svg.home],['residents','Residentes',svg.users],['vitals','Signos',svg.heart],['care','Cuidados',svg.care],['more','Más',svg.more]],
    cook:[['home','Inicio',svg.home],['operationalTasks','Tareas',svg.check],['nutrition','Dietas',svg.food],['operationalIncidents','Reportar',svg.alert]],
    cleaning:[['home','Inicio',svg.home],['operationalTasks','Tareas',svg.check],['operationalIncidents','Reportar',svg.alert],['operationalAlerts','Avisos',svg.bell]],
    maintenance:[['home','Inicio',svg.home],['operationalTasks','Tareas',svg.check],['operationalIncidents','Reportar',svg.alert],['operationalAlerts','Avisos',svg.bell]],
    security:[['home','Inicio',svg.home],['operationalTasks','Tareas',svg.check],['operationalIncidents','Reportar',svg.alert],['operationalAlerts','Avisos',svg.bell]]
  };
  const items=sets[role]||sets.admin;
  nav.classList.toggle('operational-nav',['cook','cleaning','maintenance','security'].includes(role));
  nav.innerHTML=items.map(([id,label,icon])=>`<button class="nav-item" data-nav="${id}"><span class="nav-icon">${icon}</span><span>${label}</span></button>`).join('');
  nav.querySelectorAll('[data-nav]').forEach(b=>b.addEventListener('click',()=>{
    navigationStack=[];
    go(b.dataset.nav,{scope:'global'},{replace:true});
  }));
}


// Puente global para los módulos cargados por separado (Supervisor/Supabase)
window.svg = svg;
window.main = main;
window.empty = empty;
window.fmtDate = fmtDate;
window.residentKey = residentKey;
window.saveCarePlans = saveCarePlans;
Object.defineProperty(window,'defaultCareTasks',{configurable:true,get:()=>defaultCareTasks});
window.go = go;
window.goBack = goBack;
window.pageHeader = pageHeader;
window.showToast = showToast;
window.bindActions = bindActions;
window.renderNav = renderNav;
window.render = render;
window.renderStaffGlobal = renderStaff;
Object.defineProperty(window, 'currentUser', {
  configurable: true,
  get: () => currentUser,
  set: value => { currentUser = value; }
});
Object.defineProperty(window,'activeScreen',{configurable:true,get:()=>activeScreen,set:value=>{activeScreen=value;}});
Object.defineProperty(window,'residentScoped',{configurable:true,get:()=>residentScoped,set:value=>{residentScoped=Boolean(value);}});
Object.defineProperty(window,'selectedResident',{configurable:true,get:()=>selectedResident,set:value=>{selectedResident=value;}});
Object.defineProperty(window,'navigationStack',{configurable:true,get:()=>navigationStack,set:value=>{navigationStack=Array.isArray(value)?value:[];}});

document.querySelector('.alerts').addEventListener('click',()=>go(currentUser?.role==='supervisor'?'supervisorAlerts':currentUser?.role==='doctor'?'medicalEmergencies':['cook','cleaning','maintenance','security'].includes(currentUser?.role)?'operationalAlerts':'alerts',{scope:'global'}));
document.querySelector('.logout').addEventListener('click',()=>{if(confirm('¿Desea cerrar la sesión?'))logout();});
(async function bootstrapAuth(){
  try{
    const client=window.seniorcareSupabase;
    if(!client){renderAuth('No se pudo conectar con Supabase.');return;}
    const {data:{session}}=await client.auth.getSession();
    if(session){await loadSupabaseUser(session);finishLogin();}
    else renderAuth();
    client.auth.onAuthStateChange((event,newSession)=>{
      if(event==='SIGNED_OUT'&&!newSession){
        try{window.BHSC_CLEAR_PRIVATE_STORAGE?.();}catch(_e){}
        currentUser=null;
        renderAuth();
      }
      // SIGNED_IN lo procesa exclusivamente el formulario/bootstrap para evitar carreras.
    });
  }catch(err){try{await window.seniorcareSupabase?.auth.signOut({scope:'local'});}catch(_e){} renderAuth(friendlyAppError(err,'No se pudo validar la sesión.'));}
})();
window.addEventListener('unhandledrejection',event=>{
  const reason=event.reason;
  if(window.BHSC_IS_NETWORK_ERROR?.(reason)){
    event.preventDefault();
    console.warn('[BHSC red]',reason);
    window.showToast?.(friendlyAppError(reason));
  }
});
window.addEventListener('offline',()=>window.showToast?.('Sin conexión a internet. Los datos en línea no pueden actualizarse.'));
window.addEventListener('online',()=>window.showToast?.('Conexión restablecida.'));

if ('serviceWorker' in navigator) {
  window.addEventListener('load', async () => {
    try {
      const registration = await navigator.serviceWorker.register('sw.js?v=4.3.77', { updateViaCache: 'none' });
      window.BHSC_SW_REGISTRATION=registration;
      await registration.update();
    } catch (error) { console.warn('No se pudo actualizar el service worker:', error); }
  });
}
