<script setup>
/*
 * MelissaPacientes — Sessão Pacientes como página fullscreen dentro de Melissa
 * --------------------------------------------------
 * Mesma convenção das "Melissa Pages" (espelha MelissaAgenda):
 *   - 6px de padding do viewport
 *   - Glass container com cantos arredondados
 *   - Bottom inset reservado pra .melissa-dock (76px)
 *
 * Layout 3-col:
 *   - COL 1 — Aside esquerda (~240px): filtros (status / grupos / tags)
 *   - COL 2 — Lista central (flex 1): search + cards de pacientes
 *   - COL 3 — Quick view direita (~320px): KPIs + paciente selecionado + ações
 *
 * Dados:
 *   - useMelissaPacientes({ onlyActive: false }) — traz todos os status
 *   - patient_groups + patient_tags do tenant + vínculos patient_group_patient
 *     e patient_patient_tag (via patientsRepository.listGroupsByPatient/Tags...)
 *
 * Integrações:
 *   - MelissaPaciente (rota /melissa/paciente?id=X) — abre via duplo-click ou
 *     botão "Abrir prontuário" da COL 3
 *   - PatientCadastroDialog — cadastro completo / edição
 *   - PatientCreatePopover + ComponentCadastroRapido — fluxo de novo paciente
 *   - conversationDrawerStore — botão WhatsApp da COL 3
 */
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';
import { useMelissaPacientes } from './composables/useMelissaPacientes';
import { useTenantStore } from '@/stores/tenantStore';
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useConversationDrawerStore } from '@/stores/conversationDrawerStore';
import {
    listGroups as repoListGroups,
    listTags as repoListTags,
    listGroupsByPatient,
    listTagsByPatient,
    getSessionCounts,
    softDeletePatient
} from '@/features/patients/services/patientsRepository';
import { usePatientLifecycle } from '@/composables/usePatientLifecycle';
import PatientCreatePopover from '@/components/ui/PatientCreatePopover.vue';
import PatientCadastroDialog from '@/components/ui/PatientCadastroDialog.vue';
import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue';
// Dialog do PrimeVue: auto-importado via PrimeVueResolver — NÃO importar
// explicitamente (causa "emitsOptions: null" por instância duplicada).

const emit = defineEmits(['close', 'patient-created', 'goto-agenda', 'goto-grupos', 'goto-tags']);

const toast = useToast();
const confirm = useConfirm();
const tenantStore = useTenantStore();
const router = useRouter();
const route = useRoute();
const { reactivatePatient } = usePatientLifecycle();
const conversationDrawerStore = useConversationDrawerStore();

// ── Pacientes (todos os status) ───────────────────────────────
const { pacientes, loading: loadingPacientes, refetch: refetchPacientes } =
    useMelissaPacientes({ onlyActive: false });

// Computed pra skeleton só na 1ª carga (pattern do blueprint §9)
const pacientesCarregandoInicial = computed(
    () => loadingPacientes.value && pacientes.value.length === 0
);

// ── Breakpoints + drawer mobile (blueprint §2/§3) ─────────────
//   <lg (≤1023px) → "mobile" — .mp-side e .mp-quick saem do layout
//                   e viajam pro drawer off-canvas via Teleport
const drawerOpen = ref(false);
const isMobile = ref(false);
const isCompact = ref(false);

let _mqMobile = null;
let _mqCompact = null;
function _onMqMobileChange(e) {
    isMobile.value = e.matches;
    if (!e.matches) drawerOpen.value = false;
}
function _onMqCompactChange(e) {
    isCompact.value = e.matches;
}
function toggleDrawer() { drawerOpen.value = !drawerOpen.value; }
function fecharDrawer() { drawerOpen.value = false; }

// ── Grupos / Tags (catálogo + vínculos por paciente) ──────────
const grupos = ref([]);   // [{ id, nome, cor, ... }]
const tags = ref([]);     // [{ id, nome, cor, ... }]
const groupsByPatient = ref(new Map());  // patientId → [{id,nome,cor}]
const tagsByPatient = ref(new Map());    // patientId → [{id,nome,cor}]
const sessionCountByPatient = ref(new Map()); // patientId → count

// Contagem reversa: groupId/tagId → nº pacientes vinculados.
// Usa Set de patientIds pra evitar contar duplicado se o vínculo aparecer
// duas vezes na lista (defesa). Recomputa quando groupsByPatient/tagsByPatient
// mudam (após loadVinculos).
const groupCounts = computed(() => {
    const map = new Map();
    for (const [pid, gs] of groupsByPatient.value) {
        for (const g of (gs || [])) {
            if (!map.has(g.id)) map.set(g.id, new Set());
            map.get(g.id).add(pid);
        }
    }
    const out = new Map();
    for (const [gid, set] of map) out.set(gid, set.size);
    return out;
});
const tagCounts = computed(() => {
    const map = new Map();
    for (const [pid, ts] of tagsByPatient.value) {
        for (const t of (ts || [])) {
            if (!map.has(t.id)) map.set(t.id, new Set());
            map.get(t.id).add(pid);
        }
    }
    const out = new Map();
    for (const [tid, set] of map) out.set(tid, set.size);
    return out;
});

async function loadCatalogos() {
    if (typeof tenantStore.ensureLoaded === 'function') {
        await tenantStore.ensureLoaded();
    }
    const tenantId = tenantStore.activeTenantId || tenantStore.tenantId || null;
    if (!tenantId) return;

    const { data: u } = await supabase.auth.getUser();
    const ownerId = u?.user?.id || null;

    try {
        const [g, t] = await Promise.all([
            repoListGroups({ tenantId, ownerId }),
            repoListTags({ tenantId, ownerId })
        ]);
        grupos.value = g || [];
        tags.value = t || [];
    } catch (e) {
        // eslint-disable-next-line no-console
        console.warn('[MelissaPacientes] catálogo grupos/tags falhou:', e?.message);
    }
}

async function loadVinculos() {
    const ids = pacientes.value.map((p) => p.id).filter(Boolean);
    if (!ids.length) {
        groupsByPatient.value = new Map();
        tagsByPatient.value = new Map();
        sessionCountByPatient.value = new Map();
        return;
    }
    const tenantId = tenantStore.activeTenantId || tenantStore.tenantId || null;

    try {
        const [pg, pt, sc] = await Promise.all([
            listGroupsByPatient(ids, { tenantId }),
            listTagsByPatient(ids, { tenantId }),
            getSessionCounts(ids)
        ]);

        const gById = new Map(grupos.value.map((g) => [g.id, g]));
        const gMap = new Map();
        for (const rel of (pg || [])) {
            const arr = gMap.get(rel.patient_id) || [];
            const g = gById.get(rel.patient_group_id);
            if (g) arr.push(g);
            gMap.set(rel.patient_id, arr);
        }
        groupsByPatient.value = gMap;

        const tById = new Map(tags.value.map((t) => [t.id, t]));
        const tMap = new Map();
        for (const rel of (pt || [])) {
            const arr = tMap.get(rel.patient_id) || [];
            const t = tById.get(rel.tag_id);
            if (t) arr.push(t);
            tMap.set(rel.patient_id, arr);
        }
        tagsByPatient.value = tMap;

        const cMap = new Map();
        for (const r of (sc || [])) {
            if (r?.patient_id) cMap.set(r.patient_id, r.session_count || 0);
        }
        sessionCountByPatient.value = cMap;
    } catch (e) {
        // eslint-disable-next-line no-console
        console.warn('[MelissaPacientes] vínculos falharam:', e?.message);
    }
}

// ── Criar grupo/tag (dialogs simples) ─────────────────────────
// Espelhado de PatientsCadastroPage: insert direto em patient_groups /
// patient_tags com owner_id + tenant_id (RLS exige), nome e cor.
const createGroupOpen = ref(false);
const createGroupSaving = ref(false);
const createGroupError = ref('');
const newGroupForm = ref({ name: '', color: '#6366F1' });

const createTagOpen = ref(false);
const createTagSaving = ref(false);
const createTagError = ref('');
const newTagForm = ref({ name: '', color: '#22C55E' });

function openCreateGroup() {
    createGroupError.value = '';
    newGroupForm.value = { name: '', color: '#6366F1' };
    createGroupOpen.value = true;
}
function openCreateTag() {
    createTagError.value = '';
    newTagForm.value = { name: '', color: '#22C55E' };
    createTagOpen.value = true;
}

async function _ownerAndTenant() {
    if (typeof tenantStore.ensureLoaded === 'function') await tenantStore.ensureLoaded();
    const tenantId = tenantStore.activeTenantId || tenantStore.tenantId || null;
    const { data: u } = await supabase.auth.getUser();
    const ownerId = u?.user?.id || null;
    if (!ownerId || !tenantId) throw new Error('Sessão não inicializada.');
    return { ownerId, tenantId };
}

async function persistGroup() {
    if (createGroupSaving.value) return;
    const name = String(newGroupForm.value.name || '').trim();
    const color = String(newGroupForm.value.color || '').trim() || '#6366F1';
    if (!name) { createGroupError.value = 'Informe um nome.'; return; }
    createGroupSaving.value = true;
    createGroupError.value = '';
    try {
        const { ownerId, tenantId } = await _ownerAndTenant();
        const { error } = await tenantDb().from('patient_groups').insert({
            owner_id: ownerId,
            nome: name, cor: color,
            is_system: false, is_active: true
        });
        if (error) throw error;
        await loadCatalogos();
        toast.add({ severity: 'success', summary: 'Grupo criado', life: 2200 });
        createGroupOpen.value = false;
    } catch (e) {
        const msg = e?.message || '';
        createGroupError.value = (e?.code === '23505' || /duplicate/i.test(msg)) ? 'Já existe esse grupo.' : (msg || 'Falha ao criar grupo.');
    } finally {
        createGroupSaving.value = false;
    }
}

async function persistTag() {
    if (createTagSaving.value) return;
    const name = String(newTagForm.value.name || '').trim();
    const color = String(newTagForm.value.color || '').trim() || '#22C55E';
    if (!name) { createTagError.value = 'Informe um nome.'; return; }
    createTagSaving.value = true;
    createTagError.value = '';
    try {
        const { ownerId, tenantId } = await _ownerAndTenant();
        const { error } = await tenantDb().from('patient_tags').insert({
            owner_id: ownerId,
            nome: name, cor: color
        });
        if (error) throw error;
        await loadCatalogos();
        toast.add({ severity: 'success', summary: 'Tag criada', life: 2200 });
        createTagOpen.value = false;
    } catch (e) {
        const msg = e?.message || '';
        createTagError.value = (e?.code === '23505' || /duplicate/i.test(msg)) ? 'Já existe essa tag.' : (msg || 'Falha ao criar tag.');
    } finally {
        createTagSaving.value = false;
    }
}

onMounted(() => {
    loadCatalogos();
    if (typeof window !== 'undefined' && window.matchMedia) {
        _mqMobile = window.matchMedia('(max-width: 1023px)');
        isMobile.value = _mqMobile.matches;
        _mqMobile.addEventListener('change', _onMqMobileChange);
        _mqCompact = window.matchMedia('(max-width: 1279px)');
        isCompact.value = _mqCompact.matches;
        _mqCompact.addEventListener('change', _onMqCompactChange);
    }
    // Fase 8 wire-up: se navegou pra ca com ?edit=<id> (vindo do
    // MelissaPaciente), abre o cadastro full direto.
    if (route.query.edit) {
        editPatientId.value = String(route.query.edit);
        cadastroFullDialog.value = true;
        router.replace({ query: { ...route.query, edit: undefined } });
    }
});
onBeforeUnmount(() => {
    if (_mqMobile) _mqMobile.removeEventListener('change', _onMqMobileChange);
    if (_mqCompact) _mqCompact.removeEventListener('change', _onMqCompactChange);
});

// Watcher: quando lista de pacientes mudar (mount inicial, refetch após
// criar/editar), recarrega vínculos.
watch(
    () => pacientes.value.length,
    () => loadVinculos()
);

async function refetchTudo() {
    await refetchPacientes();
    await loadVinculos();
    emit('patient-created'); // avisa parent pra refrescar pacientesReais
}

// ── Estado de UI ───────────────────────────────────────────────
// Busca local — filtra a lista visivel combinada com filtros de
// status/grupo/tag. Busca global (Ctrl+K) tem botao dedicado no
// .melissa-tray, fora desta seccao.
const busca = ref('');
const statusFiltro = ref('ativos'); // 'todos' | 'ativos' | 'inativos' | 'arquivados'
const grupoFiltroId = ref(null);    // null = todos
const tagFiltroId = ref(null);      // null = todas
const pacienteSelecionadoId = ref(null);

// ── Helpers ────────────────────────────────────────────────────
function normalize(s) {
    return String(s || '').normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase().trim();
}

function pacienteIniciais(nome) {
    if (!nome) return '?';
    const partes = String(nome).trim().split(/\s+/);
    if (partes.length === 1) return partes[0][0]?.toUpperCase() || '?';
    return (partes[0][0] + partes[partes.length - 1][0]).toUpperCase();
}

function fmtUltimaSessao(iso) {
    if (!iso) return 'Sem atendimento';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return 'Sem atendimento';
    const dia = String(d.getDate()).padStart(2, '0');
    const mes = String(d.getMonth() + 1).padStart(2, '0');
    return `${dia}/${mes}`;
}

const NOVO_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;
function isPacienteNovo(p) {
    if (!p?.created_at) return false;
    const t = new Date(p.created_at).getTime();
    if (Number.isNaN(t)) return false;
    return Date.now() - t < NOVO_THRESHOLD_MS;
}

function fmtPhone(p) {
    const v = String(p || '').replace(/\D/g, '');
    if (v.length === 11) return `(${v.slice(0, 2)}) ${v.slice(2, 7)}-${v.slice(7)}`;
    if (v.length === 10) return `(${v.slice(0, 2)}) ${v.slice(2, 6)}-${v.slice(6)}`;
    return p || '';
}

// Aniversário no mês corrente — flag visual no detail
function aniversarioEsteMes(iso) {
    if (!iso) return false;
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return false;
    return d.getMonth() === new Date().getMonth();
}

// ── Status: contagens + filtragem ──────────────────────────────
const STATUS_OPTIONS = [
    { key: 'todos',       label: 'Todos',       icon: 'pi pi-users' },
    { key: 'ativos',      label: 'Ativos',      icon: 'pi pi-check-circle' },
    { key: 'inativos',    label: 'Inativos',    icon: 'pi pi-pause-circle' },
    { key: 'arquivados',  label: 'Arquivados',  icon: 'pi pi-inbox' }
];

const contagens = computed(() => {
    const c = { todos: 0, ativos: 0, inativos: 0, arquivados: 0 };
    for (const p of pacientes.value) {
        c.todos++;
        const st = String(p.status || '').toLowerCase();
        if (st === 'ativo') c.ativos++;
        else if (st === 'inativo') c.inativos++;
        else if (st === 'arquivado') c.arquivados++;
    }
    return c;
});

const pacientesFiltrados = computed(() => {
    const q = normalize(busca.value);
    const filtroStatus = statusFiltro.value;
    const filtroGrupo = grupoFiltroId.value;
    const filtroTag = tagFiltroId.value;

    return pacientes.value.filter((p) => {
        // status
        if (filtroStatus !== 'todos') {
            const st = String(p.status || '').toLowerCase();
            if (filtroStatus === 'ativos'      && st !== 'ativo')      return false;
            if (filtroStatus === 'inativos'    && st !== 'inativo')    return false;
            if (filtroStatus === 'arquivados'  && st !== 'arquivado')  return false;
        }
        // grupo
        if (filtroGrupo) {
            const gs = groupsByPatient.value.get(p.id) || [];
            if (!gs.some((g) => g.id === filtroGrupo)) return false;
        }
        // tag
        if (filtroTag) {
            const ts = tagsByPatient.value.get(p.id) || [];
            if (!ts.some((t) => t.id === filtroTag)) return false;
        }
        // busca
        if (!q) return true;
        return normalize(p.nome).includes(q) || normalize(p.email).includes(q);
    });
});

const pacientesOrdenados = computed(() => {
    const novos = [];
    const resto = [];
    for (const p of pacientesFiltrados.value) {
        if (isPacienteNovo(p)) novos.push(p);
        else resto.push(p);
    }
    novos.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
    return [...novos, ...resto];
});

// ── Paginação da lista (client-side, default 10 por página) ───────
// `useMelissaPacientes` já trouxe a lista completa em memória, então
// paginamos no client (sem round-trip). Seletor de tamanho cobre os
// presets típicos — 10/20/50/100. Se o usuário tiver clínica grande
// (>1000 ativos), o composable já capa em 1000 no SQL.
const PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
const pageMP = ref(1);
const rowsMP = ref(10);
const pacientesPaginados = computed(() => {
    const start = (pageMP.value - 1) * rowsMP.value;
    return pacientesOrdenados.value.slice(start, start + rowsMP.value);
});
function onPageMPChange(event) {
    pageMP.value = event.page + 1;
    rowsMP.value = event.rows;
}
// Reset pra página 1 quando qualquer filtro/busca mudar.
watch([busca, statusFiltro, grupoFiltroId, tagFiltroId], () => { pageMP.value = 1; });
// Clamp: se a lista filtrada encolher abaixo da página atual, recua.
watch(() => pacientesOrdenados.value.length, (len) => {
    const maxPag = Math.max(1, Math.ceil(len / rowsMP.value));
    if (pageMP.value > maxPag) pageMP.value = maxPag;
});

// ── View mode persistido (list/grid) ──────────────────────
// Lista = cards verticais empilhados (default, mostra detail panel).
// Grade = cards num grid responsivo (mais compacto, ideal pra browse).
const VIEW_MODE_KEY = 'mp.viewMode.v1';
const viewMode = ref('list');
try {
    const saved = localStorage.getItem(VIEW_MODE_KEY);
    if (saved === 'list' || saved === 'grid') viewMode.value = saved;
} catch (_) {}
function setViewMode(m) {
    if (m !== 'list' && m !== 'grid') return;
    viewMode.value = m;
    try { localStorage.setItem(VIEW_MODE_KEY, m); } catch (_) {}
}

// ── Popover de ações (mobile) ────────────────────────────
// Em desktop os 5 botões aparecem inline no card. Em mobile, só
// mostra 1 pencil que dispara este popover com as 5 opções.
const actionsPopRef = ref(null);
const actionsTarget = ref(null);
function openActionsPop(event, p) {
    actionsTarget.value = p;
    actionsPopRef.value?.toggle(event);
}
function actionsRun(fn) {
    const p = actionsTarget.value;
    actionsPopRef.value?.hide();
    if (p && typeof fn === 'function') fn(p);
}

// ── KPIs (COL 3) ────────────────────────────────────────────────
const RECENTE_THRESHOLD_MS = 14 * 24 * 60 * 60 * 1000;
const kpis = computed(() => {
    const total = pacientes.value.length;
    let novos = 0;
    let recentes = 0;
    let aniversariantesMes = 0;
    const agora = Date.now();
    const mesAtual = new Date().getMonth();
    for (const p of pacientes.value) {
        if (isPacienteNovo(p)) novos++;
        if (p.last_attended_at) {
            const t = new Date(p.last_attended_at).getTime();
            if (!Number.isNaN(t) && agora - t < RECENTE_THRESHOLD_MS) recentes++;
        }
        if (p.data_nascimento) {
            const d = new Date(p.data_nascimento);
            if (!Number.isNaN(d.getTime()) && d.getMonth() === mesAtual) aniversariantesMes++;
        }
    }
    return { total, novos, recentes, aniversariantesMes };
});

// ── Seleção ────────────────────────────────────────────────────
const pacienteSelecionado = computed(() =>
    pacientes.value.find((p) => p.id === pacienteSelecionadoId.value) || null
);

const grupoCorById = (id) => grupos.value.find((g) => g.id === id)?.color || null;
const tagCorById = (id) => tags.value.find((t) => t.id === id)?.color || null;

const selectedGroups = computed(() => {
    if (!pacienteSelecionadoId.value) return [];
    return groupsByPatient.value.get(pacienteSelecionadoId.value) || [];
});
const selectedTags = computed(() => {
    if (!pacienteSelecionadoId.value) return [];
    return tagsByPatient.value.get(pacienteSelecionadoId.value) || [];
});
const selectedSessionCount = computed(() => {
    if (!pacienteSelecionadoId.value) return 0;
    return sessionCountByPatient.value.get(pacienteSelecionadoId.value) || 0;
});

function selecionarPaciente(id) {
    pacienteSelecionadoId.value = pacienteSelecionadoId.value === id ? null : id;
}

function limparSelecao() {
    pacienteSelecionadoId.value = null;
}

function limparFiltros() {
    busca.value = '';
    statusFiltro.value = 'ativos';
    grupoFiltroId.value = null;
    tagFiltroId.value = null;
}

// ── Cadastro / edição / prontuário ─────────────────────────────
const createPopoverRef = ref(null);
const cadastroFullDialog = ref(false);
const quickDialog = ref(false);
const editPatientId = ref(null);

function openCreatePopover(e) {
    createPopoverRef.value?.toggle(e);
}
function openQuickCreate() {
    quickDialog.value = true;
}
function goCreateFull() {
    editPatientId.value = null;
    cadastroFullDialog.value = true;
}
function onPatientCreated() {
    refetchTudo();
}

// Abrir prontuario agora navega pra MelissaPaciente nativo (Fase 8 wire-up).
// O Dialog PatientProntuario.vue legacy continua existindo pros 2 callsites
// fora do Melissa (TherapistDashboard e PatientsListPage).
function abrirProntuario(p) {
    if (!p?.id) return;
    router.push({ path: '/melissa/paciente', query: { id: String(p.id) } });
}

function editarPaciente(p) {
    if (!p?.id) return;
    editPatientId.value = String(p.id);
    cadastroFullDialog.value = true;
}

function abrirWhatsapp(p) {
    if (!p?.id) {
        toast.add({ severity: 'warn', summary: 'Paciente sem id', life: 2000 });
        return;
    }
    conversationDrawerStore.openForPatient(String(p.id));
}

function confirmarRemover(p) {
    if (!p?.id) return;
    confirm.require({
        message: `Arquivar "${p.nome}"? O paciente sairá da lista ativa, mas pode ser restaurado depois.`,
        header: 'Arquivar paciente',
        icon: 'pi pi-exclamation-triangle',
        acceptLabel: 'Arquivar',
        rejectLabel: 'Cancelar',
        acceptClass: 'p-button-danger',
        accept: async () => {
            try {
                const tenantId = tenantStore.activeTenantId || tenantStore.tenantId;
                await softDeletePatient(p.id, { tenantId });
                toast.add({ severity: 'success', summary: 'Arquivado', detail: p.nome, life: 2200 });
                if (pacienteSelecionadoId.value === p.id) limparSelecao();
                await refetchTudo();
            } catch (e) {
                toast.add({
                    severity: 'error',
                    summary: 'Falha ao arquivar',
                    detail: e?.message || 'Tente novamente.',
                    life: 4000
                });
            }
        }
    });
}

// Helper: paciente está arquivado? (case-insensitive — DB pode vir
// com "Arquivado" do form ou "arquivado" lowercased de algum lugar.)
function isArquivado(p) {
    return String(p?.status || '').toLowerCase() === 'arquivado';
}

// Restaurar paciente arquivado — volta status pra 'Ativo' via
// reactivatePatient (compartilhado com PatientActionMenu/PatientsListPage,
// fonte única em usePatientLifecycle).
function restaurarPaciente(p) {
    if (!p?.id) return;
    confirm.require({
        message: `Restaurar "${p.nome}" pra lista de pacientes ativos?`,
        header: 'Restaurar paciente',
        icon: 'pi pi-undo',
        acceptLabel: 'Restaurar',
        rejectLabel: 'Cancelar',
        accept: async () => {
            try {
                const result = await reactivatePatient(p.id);
                if (!result?.ok) throw result?.error || new Error('Falha ao restaurar.');
                toast.add({ severity: 'success', summary: 'Restaurado', detail: p.nome, life: 2200 });
                await refetchTudo();
            } catch (e) {
                toast.add({
                    severity: 'error',
                    summary: 'Falha ao restaurar',
                    detail: e?.message || 'Tente novamente.',
                    life: 4000
                });
            }
        }
    });
}

// ── Sessões do paciente (dialog) ───────────────────────────────
const sessoesDialogOpen = ref(false);
const sessoesPaciente = ref(null);
const sessoesLista = ref([]);
const sessoesLoading = ref(false);

async function verSessoes(p) {
    if (!p?.id) return;
    sessoesPaciente.value = p;
    sessoesDialogOpen.value = true;
    sessoesLista.value = [];
    sessoesLoading.value = true;
    try {
        const tenantId = tenantStore.activeTenantId || tenantStore.tenantId;
        const { data, error } = await tenantDb().from('agenda_eventos')
            .select('id, inicio_em, fim_em, tipo, status, titulo, modalidade')
            
            .eq('patient_id', p.id)
            .order('inicio_em', { ascending: false })
            .limit(50);
        if (error) throw error;
        sessoesLista.value = data || [];
    } catch (e) {
        toast.add({
            severity: 'error',
            summary: 'Falha ao carregar sessões',
            detail: e?.message || 'Tente novamente.',
            life: 4000
        });
    } finally {
        sessoesLoading.value = false;
    }
}

function fmtSessaoData(iso) {
    if (!iso) return '—';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return '—';
    const dia = String(d.getDate()).padStart(2, '0');
    const mes = String(d.getMonth() + 1).padStart(2, '0');
    const ano = d.getFullYear();
    const h = String(d.getHours()).padStart(2, '0');
    const min = String(d.getMinutes()).padStart(2, '0');
    return `${dia}/${mes}/${ano} ${h}:${min}`;
}

function sessaoStatusLabel(s) {
    const v = String(s || '').toLowerCase();
    if (v === 'realizado' || v === 'realizada') return 'Realizado';
    if (v === 'faltou') return 'Falta';
    if (v === 'cancelado' || v === 'cancelada') return 'Cancelado';
    if (v === 'remarcar') return 'Remarcar';
    if (v === 'agendado') return 'Agendado';
    return s || '—';
}

function sessaoStatusColor(s) {
    const v = String(s || '').toLowerCase();
    if (v === 'realizado' || v === 'realizada') return 'text-emerald-400';
    if (v === 'faltou') return 'text-red-400';
    if (v === 'cancelado' || v === 'cancelada') return 'text-white/40';
    if (v === 'remarcar') return 'text-amber-400';
    return 'text-blue-300';
}
</script>

<template>
    <!-- Drawer host (multi-root, fora do .mp-page pra full viewport height
         e single-scroll). Pattern do blueprint §2. -->
    <aside
        class="mp-mobile-drawer"
        :class="{ 'is-open': drawerOpen }"
        v-show="isMobile"
        aria-label="Filtros e detalhes do paciente"
    >
        <div id="mp-mobile-drawer-target" class="mp-mobile-drawer__scroll" />
    </aside>
    <Transition name="mp-drawer-fade">
        <div
            v-if="isMobile && drawerOpen"
            class="mp-mobile-drawer__backdrop"
            @click="fecharDrawer"
        />
    </Transition>

    <section class="mp-page">
        <!-- Header -->
        <header class="mp-page__head">
            <!-- Menu (mobile only) — abre o drawer com filtros + quickview -->
            <button
                class="mp-menu-btn mp-menu-btn--mobile-only"
                v-tooltip.bottom="'Filtros & detalhes'"
                @click="toggleDrawer"
            >
                <i class="pi pi-bars" />
                <span>Menu Pacientes</span>
            </button>
            <div class="mp-page__title">
                <i class="pi pi-users mp-page__title-icon" />
                <span>Pacientes</span>
                <span class="mp-page__count">{{ pacientesOrdenados.length }}</span>
                <span v-if="loadingPacientes" class="mp-page__loading">
                    <i class="pi pi-spin pi-spinner text-xs" />
                </span>
            </div>
            <div class="mp-page__actions">
                <!-- Ir pra Agenda — icon-only 32×32 (blueprint §11) -->
                <button
                    class="mp-header-btn"
                    v-tooltip.bottom="'Ir pra Agenda'"
                    @click="emit('goto-agenda')"
                >
                    <i class="pi pi-calendar" />
                </button>
                <button class="mp-close" v-tooltip.bottom="'Voltar ao resumo (Esc)'" @click="emit('close')">
                    <i class="pi pi-times" />
                </button>
            </div>
        </header>

        <!-- Subheader explicativo — padrão do melissa-table-page-blueprint.md
             § 9. Diferencia visualmente esta página das outras tabulares e
             resume as ações principais em <strong>. -->
        <div class="mp-subheader">
            <i class="pi pi-info-circle mp-subheader__icon" />
            <span class="mp-subheader__text">
                Lista completa dos pacientes cadastrados. Filtre por
                <strong>status, grupo ou tag</strong> à esquerda, busque por
                nome ou contato, e clique numa linha pra abrir o
                <strong>prontuário</strong> com histórico, sessões e
                documentos.
            </span>
        </div>

        <div class="mp-body">
            <!-- ═══ COL 1: Filtros ═══════════════════════════════════════
                 Em desktop renderiza in-place. Em mobile (<lg) o Teleport
                 move pra dentro de #mp-mobile-drawer-target. -->
            <Teleport to="#mp-mobile-drawer-target" :disabled="!isMobile">
            <aside class="mp-side">
                <!-- Wrapper scrollável: cards de filtros (Status / Grupos / Tags).
                     O footer com "Limpar filtros" fica fora desse scroll
                     (flex-shrink:0 ancorado no bottom da .mp-side em desktop,
                     position:sticky no bottom do drawer em mobile). -->
                <div class="mp-side__scroll">
                <!-- Card: Status -->
                <div class="mp-w">
                    <div class="mp-w__head">
                        <span class="mp-w__title"><i class="pi pi-circle-fill text-[0.55rem]" /> Status</span>
                    </div>
                    <div class="mp-status-list">
                        <button
                            v-for="s in STATUS_OPTIONS"
                            :key="s.key"
                            class="mp-status-pill"
                            :class="[`is-${s.key}`, { 'is-active': statusFiltro === s.key }]"
                            @click="statusFiltro = s.key"
                        >
                            <i :class="s.icon" class="text-xs" />
                            <span class="flex-1 text-left">{{ s.label }}</span>
                            <span class="mp-status-pill__count">{{ contagens[s.key] }}</span>
                        </button>
                    </div>
                </div>

                <!-- Card: Grupos -->
                <div class="mp-w">
                    <div class="mp-w__head">
                        <span class="mp-w__title"><i class="pi pi-folder" /> Grupos</span>
                        <div class="mp-side__head-actions">
                            <button
                                v-if="grupoFiltroId"
                                class="mp-side__clear"
                                v-tooltip.top="'Limpar filtro de grupo'"
                                @click="grupoFiltroId = null"
                            >
                                <i class="pi pi-times text-[0.6rem]" />
                            </button>
                            <button
                                class="mp-side__cog"
                                v-tooltip.top="'Configurar grupos'"
                                @click="emit('goto-grupos')"
                            >
                                <i class="pi pi-cog text-[0.62rem]" />
                            </button>
                        </div>
                    </div>
                    <div class="mp-chip-list">
                        <button
                            v-for="g in grupos"
                            :key="g.id"
                            class="mp-chip"
                            :class="{ 'is-active': grupoFiltroId === g.id }"
                            :style="g.color ? { borderLeftColor: g.color } : null"
                            @click="grupoFiltroId = grupoFiltroId === g.id ? null : g.id"
                        >
                            <span class="mp-chip__dot" :style="{ backgroundColor: g.color || 'var(--m-text-muted)' }" />
                            <span class="mp-chip__name truncate">{{ g.nome || g.name }}</span>
                            <span class="mp-chip__count">{{ groupCounts.get(g.id) || 0 }}</span>
                        </button>
                        <div v-if="grupos.length === 0" class="mp-side__placeholder">
                            <span>Nenhum grupo</span>
                        </div>
                    </div>
                    <button
                        class="mp-side__add-btn"
                        @click="openCreateGroup"
                    >
                        <i class="pi pi-plus" />
                        <span>Grupo</span>
                    </button>
                </div>

                <!-- Card: Tags -->
                <div class="mp-w">
                    <div class="mp-w__head">
                        <span class="mp-w__title"><i class="pi pi-tag" /> Tags</span>
                        <div class="mp-side__head-actions">
                            <button
                                v-if="tagFiltroId"
                                class="mp-side__clear"
                                v-tooltip.top="'Limpar filtro de tag'"
                                @click="tagFiltroId = null"
                            >
                                <i class="pi pi-times text-[0.6rem]" />
                            </button>
                            <button
                                class="mp-side__cog"
                                v-tooltip.top="'Configurar tags'"
                                @click="emit('goto-tags')"
                            >
                                <i class="pi pi-cog text-[0.62rem]" />
                            </button>
                        </div>
                    </div>
                    <div class="mp-chip-list">
                        <button
                            v-for="t in tags"
                            :key="t.id"
                            class="mp-chip"
                            :class="{ 'is-active': tagFiltroId === t.id }"
                            :style="t.color ? { borderLeftColor: t.color } : null"
                            @click="tagFiltroId = tagFiltroId === t.id ? null : t.id"
                        >
                            <span class="mp-chip__dot" :style="{ backgroundColor: t.color || 'var(--m-text-muted)' }" />
                            <span class="mp-chip__name truncate">{{ t.nome || t.name }}</span>
                            <span class="mp-chip__count">{{ tagCounts.get(t.id) || 0 }}</span>
                        </button>
                        <div v-if="tags.length === 0" class="mp-side__placeholder">
                            <span>Nenhuma tag</span>
                        </div>
                    </div>
                    <button
                        class="mp-side__add-btn"
                        @click="openCreateTag"
                    >
                        <i class="pi pi-plus" />
                        <span>Tag</span>
                    </button>
                </div>
                </div><!-- /.mp-side__scroll -->

                <!-- Footer fixo no bottom da sidebar (fora do scroll dos cards).
                     Aparece com fade+collapse quando algum filtro é ativado. -->
                <Transition name="mp-clear">
                    <div
                        v-if="busca || grupoFiltroId || tagFiltroId || statusFiltro !== 'ativos'"
                        class="mp-side__footer"
                    >
                        <button class="mp-btn mp-btn--ghost mp-btn--block" @click="limparFiltros">
                            <i class="pi pi-filter-slash text-xs" />
                            Limpar filtros
                        </button>
                    </div>
                </Transition>
            </aside>
            </Teleport>

            <!-- ═══ COL 2: Lista central ═════════════════════════════════ -->
            <div class="mp-list">
                <div class="mp-list__toolbar">
                    <div class="mp-search">
                        <i class="pi pi-search mp-search__icon" />
                        <input
                            v-model="busca"
                            type="text"
                            placeholder="Buscar por nome ou email…"
                            class="mp-search__input"
                        />
                    </div>
                    <!-- View toggle (lista/grade) — persiste em localStorage -->
                    <div class="mp-view-toggle" role="group" aria-label="Visualização">
                        <button
                            class="mp-view-toggle__btn"
                            :class="{ 'is-active': viewMode === 'list' }"
                            v-tooltip.bottom="'Lista'"
                            aria-label="Lista"
                            @click="setViewMode('list')"
                        >
                            <i class="pi pi-list" />
                        </button>
                        <button
                            class="mp-view-toggle__btn"
                            :class="{ 'is-active': viewMode === 'grid' }"
                            v-tooltip.bottom="'Grade'"
                            aria-label="Grade"
                            @click="setViewMode('grid')"
                        >
                            <i class="pi pi-th-large" />
                        </button>
                    </div>
                    <button class="mp-btn mp-btn--primary" @click="openCreatePopover($event)">
                        <i class="pi pi-plus text-xs" />
                        <span>Novo paciente</span>
                    </button>
                </div>

                <div class="mp-list__body">
                    <!-- Skeleton enquanto carrega pela 1ª vez (sem dados ainda).
                         Pattern do blueprint §9 — usa computed pra não duplicar
                         a condição em vários v-ifs. -->
                    <template v-if="pacientesCarregandoInicial">
                        <div v-for="i in 6" :key="`mpsk-${i}`" class="mp-card mp-card--skeleton" aria-busy="true">
                            <span class="mp-card__avatar melissa-skeleton melissa-skeleton--avatar" />
                            <div class="mp-card__main" style="display:flex; flex-direction:column; gap:6px;">
                                <span class="melissa-skeleton melissa-skeleton--text" :style="{ width: `${55 + (i * 7) % 30}%` }" />
                                <span class="melissa-skeleton melissa-skeleton--text" :style="{ width: `${30 + (i * 11) % 25}%` }" />
                            </div>
                        </div>
                    </template>

                    <div v-else-if="pacientesOrdenados.length === 0" class="mp-empty-state">
                        <i class="pi pi-users mp-empty-state__icon" />
                        <div class="mp-empty-state__title">Nenhum paciente encontrado</div>
                        <div class="mp-empty-state__hint">
                            <template v-if="busca || grupoFiltroId || tagFiltroId || statusFiltro !== 'ativos'">
                                Ajuste os filtros ou limpe a busca pra ver mais resultados.
                            </template>
                            <template v-else>
                                Comece cadastrando seu primeiro paciente.
                            </template>
                        </div>
                        <div class="mp-empty-state__actions">
                            <button
                                v-if="busca || grupoFiltroId || tagFiltroId || statusFiltro !== 'ativos'"
                                class="mp-btn mp-btn--primary"
                                @click="limparFiltros"
                            >
                                <i class="pi pi-filter-slash text-xs" />
                                Limpar busca
                            </button>
                            <button class="mp-btn mp-btn--primary" @click="openCreatePopover($event)">
                                <i class="pi pi-plus text-xs" />
                                Novo paciente
                            </button>
                        </div>
                    </div>

                    <button
                        v-for="p in (pacientesCarregandoInicial || viewMode !== 'list' ? [] : pacientesPaginados)"
                        :key="p.id"
                        class="mp-card"
                        :class="{
                            'is-active': pacienteSelecionadoId === p.id,
                            'is-novo': isPacienteNovo(p)
                        }"
                        @click="selecionarPaciente(p.id)"
                        @dblclick="abrirProntuario(p)"
                    >
                        <span class="mp-card__avatar">
                            <img v-if="p.avatar_url" :src="p.avatar_url" :alt="p.nome" />
                            <span v-else>{{ pacienteIniciais(p.nome) }}</span>
                        </span>
                        <div class="mp-card__main">
                            <div class="mp-card__name-row">
                                <span class="mp-card__name">{{ p.nome }}</span>
                                <span v-if="isPacienteNovo(p)" class="mp-card__novo">novo</span>
                                <span
                                    v-if="p.status && p.status !== 'Ativo'"
                                    class="mp-card__status"
                                >
                                    {{ p.status }}
                                </span>
                            </div>
                            <!-- Tags inline (até 3) -->
                            <div
                                v-if="(tagsByPatient.get(p.id) || []).length > 0"
                                class="mp-card__tags"
                            >
                                <span
                                    v-for="t in (tagsByPatient.get(p.id) || []).slice(0, 3)"
                                    :key="t.id"
                                    class="mp-card__tag"
                                    :style="{ backgroundColor: (t.color || '#94a3b8') + '22', color: t.color || 'var(--m-text-muted)', borderColor: (t.color || '#94a3b8') + '50' }"
                                >
                                    {{ t.nome || t.name }}
                                </span>
                                <span
                                    v-if="(tagsByPatient.get(p.id) || []).length > 3"
                                    class="mp-card__tag-more"
                                >
                                    +{{ (tagsByPatient.get(p.id) || []).length - 3 }}
                                </span>
                            </div>
                        </div>
                        <!-- Email — coluna própria (separada do main pra leitura
                             tabular). Trunca com ellipsis. -->
                        <div class="mp-card__email">
                            <i class="pi pi-envelope" />
                            <span class="mp-card__email-text">{{ p.email || '—' }}</span>
                        </div>
                        <!-- Telefone — coluna própria, paralela ao email. -->
                        <div class="mp-card__phone">
                            <i class="pi pi-phone" />
                            <span class="mp-card__phone-text">{{ p.telefone ? fmtPhone(p.telefone) : '—' }}</span>
                        </div>
                        <div class="mp-card__last">
                            <div class="mp-card__last-label">Última</div>
                            <div class="mp-card__last-date">{{ fmtUltimaSessao(p.last_attended_at) }}</div>
                        </div>
                        <!-- Ações inline: 5 botões em desktop, 1 pencil que abre
                             popover em mobile. stopPropagation em todos pra não
                             disparar selecionarPaciente do botão pai. Mobile: a
                             coluna é sticky-right (fixada visualmente). -->
                        <div class="mp-card__actions" @click.stop>
                            <!-- Desktop: 5 ações inline -->
                            <button
                                class="mp-card__action mp-card__action--desktop"
                                v-tooltip.top="'Abrir prontuário'"
                                @click="abrirProntuario(p)"
                            >
                                <i class="pi pi-file" />
                            </button>
                            <button
                                class="mp-card__action mp-card__action--desktop"
                                v-tooltip.top="'Ver sessões'"
                                @click="verSessoes(p)"
                            >
                                <i class="pi pi-history" />
                            </button>
                            <button
                                class="mp-card__action mp-card__action--desktop"
                                v-tooltip.top="'Conversar (WhatsApp)'"
                                @click="abrirWhatsapp(p)"
                            >
                                <i class="pi pi-whatsapp" />
                            </button>
                            <button
                                class="mp-card__action mp-card__action--desktop"
                                v-tooltip.top="'Editar'"
                                @click="editarPaciente(p)"
                            >
                                <i class="pi pi-pencil" />
                            </button>
                            <!-- Arquivar / Restaurar — toggle condicional baseado
                                 em p.status. Arquivar quando ativo (vermelho),
                                 Restaurar quando arquivado (neutro/primary). -->
                            <button
                                v-if="!isArquivado(p)"
                                class="mp-card__action mp-card__action--desktop mp-card__action--danger"
                                v-tooltip.top="'Arquivar'"
                                @click="confirmarRemover(p)"
                            >
                                <i class="pi pi-trash" />
                            </button>
                            <button
                                v-else
                                class="mp-card__action mp-card__action--desktop mp-card__action--restore"
                                v-tooltip.top="'Restaurar'"
                                @click="restaurarPaciente(p)"
                            >
                                <i class="pi pi-undo" />
                            </button>
                            <!-- Mobile: 1 pencil que abre popover com todas as ações -->
                            <button
                                class="mp-card__action mp-card__action--mobile"
                                aria-label="Mais ações"
                                @click="openActionsPop($event, p)"
                            >
                                <i class="pi pi-pencil" />
                            </button>
                        </div>
                    </button>

                    <!-- Grid view — cards num CSS grid responsivo. Mesma fonte
                         de dados (pacientesPaginados) que a list view. -->
                    <div v-if="viewMode === 'grid' && !pacientesCarregandoInicial && pacientesOrdenados.length > 0" class="mp-grid">
                        <div
                            v-for="p in pacientesPaginados"
                            :key="p.id"
                            class="mp-grid__card"
                            :class="{
                                'is-active': pacienteSelecionadoId === p.id,
                                'is-novo': isPacienteNovo(p)
                            }"
                            role="button"
                            tabindex="0"
                            @click="selecionarPaciente(p.id)"
                            @dblclick="abrirProntuario(p)"
                            @keydown.enter.prevent="selecionarPaciente(p.id)"
                            @keydown.space.prevent="selecionarPaciente(p.id)"
                        >
                            <div class="mp-grid__top">
                                <span class="mp-card__avatar">
                                    <img v-if="p.avatar_url" :src="p.avatar_url" :alt="p.nome" />
                                    <span v-else>{{ pacienteIniciais(p.nome) }}</span>
                                </span>
                                <button
                                    class="mp-card__action mp-card__action--mobile"
                                    aria-label="Mais ações"
                                    @click.stop="openActionsPop($event, p)"
                                >
                                    <i class="pi pi-pencil" />
                                </button>
                            </div>
                            <div class="mp-grid__name-row">
                                <span class="mp-grid__name">{{ p.nome }}</span>
                                <span v-if="isPacienteNovo(p)" class="mp-card__novo">novo</span>
                            </div>
                            <div v-if="p.status && p.status !== 'Ativo'" class="mp-grid__status">
                                {{ p.status }}
                            </div>
                            <div class="mp-grid__meta">
                                <span><i class="pi pi-envelope" /> {{ p.email || '—' }}</span>
                                <span><i class="pi pi-phone" /> {{ p.telefone ? fmtPhone(p.telefone) : '—' }}</span>
                            </div>
                            <div
                                v-if="(tagsByPatient.get(p.id) || []).length > 0"
                                class="mp-card__tags"
                            >
                                <span
                                    v-for="t in (tagsByPatient.get(p.id) || []).slice(0, 3)"
                                    :key="t.id"
                                    class="mp-card__tag"
                                    :style="{ backgroundColor: (t.color || '#94a3b8') + '22', color: t.color || 'var(--m-text-muted)', borderColor: (t.color || '#94a3b8') + '50' }"
                                >
                                    {{ t.nome || t.name }}
                                </span>
                                <span
                                    v-if="(tagsByPatient.get(p.id) || []).length > 3"
                                    class="mp-card__tag-more"
                                >
                                    +{{ (tagsByPatient.get(p.id) || []).length - 3 }}
                                </span>
                            </div>
                            <div class="mp-grid__last">
                                <i class="pi pi-clock" />
                                <span>Última: {{ fmtUltimaSessao(p.last_attended_at) }}</span>
                            </div>
                        </div>
                    </div>
                </div>

                <Paginator
                    v-if="!pacientesCarregandoInicial && pacientesOrdenados.length > 0"
                    class="mp-paginator"
                    :rows="rowsMP"
                    :totalRecords="pacientesOrdenados.length"
                    :first="(pageMP - 1) * rowsMP"
                    :rowsPerPageOptions="PAGE_SIZE_OPTIONS"
                    template="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
                    currentPageReportTemplate="{first}–{last} de {totalRecords}"
                    @page="onPageMPChange"
                />
            </div>

            <!-- ═══ COL 3: Quick view ════════════════════════════════════
                 Mesma lógica da COL 1 — Teleport pro drawer em mobile. -->
            <Teleport to="#mp-mobile-drawer-target" :disabled="!isMobile">
            <aside class="mp-quick">
                <!-- KPIs sempre visíveis no topo -->
                <div class="mp-w">
                    <div class="mp-w__head">
                        <span class="mp-w__title">
                            <i class="pi pi-chart-bar" /> Visão geral
                        </span>
                    </div>
                    <div class="mp-stats">
                        <div class="mp-stat">
                            <div class="mp-stat__val">{{ kpis.total }}</div>
                            <div class="mp-stat__lbl">Total</div>
                        </div>
                        <div class="mp-stat">
                            <div class="mp-stat__val">{{ kpis.novos }}</div>
                            <div class="mp-stat__lbl">Novos<br><span class="text-[0.6rem] opacity-60">7 dias</span></div>
                        </div>
                        <div class="mp-stat">
                            <div class="mp-stat__val">{{ kpis.recentes }}</div>
                            <div class="mp-stat__lbl">Atendidos<br><span class="text-[0.6rem] opacity-60">14 dias</span></div>
                        </div>
                    </div>
                    <div v-if="kpis.aniversariantesMes > 0" class="mp-aniv">
                        <i class="pi pi-gift" />
                        <span>{{ kpis.aniversariantesMes }} aniversariante{{ kpis.aniversariantesMes > 1 ? 's' : '' }} este mês</span>
                    </div>
                </div>

                <!-- Card: Paciente selecionado (detalhes + ações) ou estado vazio -->
                <div class="mp-w mp-w--detail">
                <div v-if="pacienteSelecionado" class="mp-detail">
                    <button class="mp-detail__close" v-tooltip.left="'Limpar seleção'" @click="limparSelecao">
                        <i class="pi pi-times text-xs" />
                    </button>
                    <div class="mp-detail__avatar">
                        <img v-if="pacienteSelecionado.avatar_url" :src="pacienteSelecionado.avatar_url" :alt="pacienteSelecionado.nome" />
                        <span v-else>{{ pacienteIniciais(pacienteSelecionado.nome) }}</span>
                    </div>
                    <div class="mp-detail__name">{{ pacienteSelecionado.nome }}</div>
                    <div class="mp-detail__status">
                        <i
                            class="pi pi-circle-fill text-[0.5rem]"
                            :class="pacienteSelecionado.status === 'Ativo' ? 'text-emerald-400' : 'text-white/40'"
                        />
                        {{ pacienteSelecionado.status || 'Ativo' }}
                        <span v-if="aniversarioEsteMes(pacienteSelecionado.data_nascimento)" class="mp-detail__aniv-badge">
                            <i class="pi pi-gift text-[0.6rem]" /> aniversário
                        </span>
                    </div>

                    <div class="mp-detail__rows">
                        <div v-if="pacienteSelecionado.email" class="mp-detail__row">
                            <i class="pi pi-envelope" />
                            <span class="truncate">{{ pacienteSelecionado.email }}</span>
                        </div>
                        <div v-if="pacienteSelecionado.telefone" class="mp-detail__row">
                            <i class="pi pi-phone" />
                            <span>{{ fmtPhone(pacienteSelecionado.telefone) }}</span>
                        </div>
                        <div class="mp-detail__row">
                            <i class="pi pi-calendar" />
                            <span>Última: {{ fmtUltimaSessao(pacienteSelecionado.last_attended_at) }}</span>
                        </div>
                        <div class="mp-detail__row">
                            <i class="pi pi-history" />
                            <span>{{ selectedSessionCount }} {{ selectedSessionCount === 1 ? 'sessão' : 'sessões' }}</span>
                        </div>
                    </div>

                    <!-- Grupos + tags do paciente -->
                    <div v-if="selectedGroups.length > 0 || selectedTags.length > 0" class="mp-detail__chips">
                        <span
                            v-for="g in selectedGroups"
                            :key="'g' + g.id"
                            class="mp-detail__chip"
                            :style="{ borderLeftColor: g.color || 'var(--m-text-muted)' }"
                        >
                            <span class="mp-chip__dot" :style="{ backgroundColor: g.color || 'var(--m-text-muted)' }" />
                            {{ g.nome || g.name }}
                        </span>
                        <span
                            v-for="t in selectedTags"
                            :key="'t' + t.id"
                            class="mp-detail__chip mp-detail__chip--tag"
                            :style="{ backgroundColor: (t.color || '#94a3b8') + '20', borderColor: (t.color || '#94a3b8') + '60', color: t.color || 'var(--m-text)' }"
                        >
                            {{ t.nome || t.name }}
                        </span>
                    </div>

                    <div class="mp-detail__actions">
                        <button
                            class="mp-btn mp-btn--primary mp-btn--block"
                            @click="abrirProntuario(pacienteSelecionado)"
                        >
                            <i class="pi pi-file" />
                            Abrir prontuário
                        </button>
                        <div class="grid grid-cols-2 gap-2 mt-2">
                            <button class="mp-btn mp-btn--ghost" @click="abrirWhatsapp(pacienteSelecionado)">
                                <i class="pi pi-whatsapp" />
                                Conversar
                            </button>
                            <button class="mp-btn mp-btn--ghost" @click="editarPaciente(pacienteSelecionado)">
                                <i class="pi pi-pencil" />
                                Editar
                            </button>
                        </div>
                    </div>
                </div>

                <div v-else class="mp-detail__empty">
                    <i class="pi pi-user text-3xl opacity-30 mb-3" />
                    <div class="text-sm">Selecione um paciente</div>
                    <div class="text-xs text-white/40 mt-1 text-center">
                        Clique em um card pra ver detalhes.<br>
                        Duplo-clique abre o prontuário.
                    </div>
                </div>
                </div>
            </aside>
            </Teleport>
        </div>

        <!-- Popover + dialogs de cadastro (montados fora do scroll). -->
        <PatientCreatePopover
            ref="createPopoverRef"
            @quick-create="openQuickCreate"
            @go-complete="goCreateFull"
        />
        <PatientCadastroDialog
            v-model="cadastroFullDialog"
            :patient-id="editPatientId"
            @created="onPatientCreated"
        />
        <ComponentCadastroRapido
            v-model="quickDialog"
            title="Cadastro Rápido"
            table-name="patients"
            name-field="nome_completo"
            email-field="email_principal"
            phone-field="telefone"
            @created="onPatientCreated"
        />

        <!-- Prontuario migrado pra MelissaPaciente nativo (Fase 8 wire-up).
             abrirProntuario(p) navega pra /melissa/paciente?id=X via router. -->


        <!-- Dialog: Novo grupo (nome + cor) -->
        <Dialog
            v-model:visible="createGroupOpen"
            modal
            dismissable-mask
            :style="{ width: '380px', maxWidth: '92vw' }"
            header="Novo grupo"
        >
            <div class="flex flex-col gap-3">
                <label class="text-xs text-[var(--text-color-secondary)]">
                    Nome
                    <InputText v-model="newGroupForm.name" placeholder="Ex: Adolescentes, Casais…" class="w-full mt-1" autofocus @keydown.enter="persistGroup" />
                </label>
                <label class="text-xs text-[var(--text-color-secondary)]">
                    Cor
                    <input v-model="newGroupForm.color" type="color" class="w-full h-9 mt-1 rounded-md border border-[var(--surface-border)] bg-transparent cursor-pointer" />
                </label>
                <div v-if="createGroupError" class="text-xs text-red-400">{{ createGroupError }}</div>
            </div>
            <template #footer>
                <Button label="Cancelar" text @click="createGroupOpen = false" />
                <Button :label="createGroupSaving ? 'Salvando…' : 'Criar'" :loading="createGroupSaving" :disabled="!newGroupForm.name.trim() || createGroupSaving" @click="persistGroup" />
            </template>
        </Dialog>

        <!-- Dialog: Nova tag (nome + cor) -->
        <Dialog
            v-model:visible="createTagOpen"
            modal
            dismissable-mask
            :style="{ width: '380px', maxWidth: '92vw' }"
            header="Nova tag"
        >
            <div class="flex flex-col gap-3">
                <label class="text-xs text-[var(--text-color-secondary)]">
                    Nome
                    <InputText v-model="newTagForm.name" placeholder="Ex: TDAH, Ansiedade, VIP…" class="w-full mt-1" autofocus @keydown.enter="persistTag" />
                </label>
                <label class="text-xs text-[var(--text-color-secondary)]">
                    Cor
                    <input v-model="newTagForm.color" type="color" class="w-full h-9 mt-1 rounded-md border border-[var(--surface-border)] bg-transparent cursor-pointer" />
                </label>
                <div v-if="createTagError" class="text-xs text-red-400">{{ createTagError }}</div>
            </div>
            <template #footer>
                <Button label="Cancelar" text @click="createTagOpen = false" />
                <Button :label="createTagSaving ? 'Salvando…' : 'Criar'" :loading="createTagSaving" :disabled="!newTagForm.name.trim() || createTagSaving" @click="persistTag" />
            </template>
        </Dialog>

        <!-- Dialog de sessões do paciente — lista os últimos 50 eventos -->
        <Dialog
            v-model:visible="sessoesDialogOpen"
            modal
            dismissable-mask
            :style="{ width: '560px', maxWidth: '92vw' }"
            :header="sessoesPaciente ? `Sessões — ${sessoesPaciente.nome}` : 'Sessões'"
        >
            <div v-if="sessoesLoading" class="py-10 text-center text-[var(--text-color-secondary)]">
                <i class="pi pi-spin pi-spinner text-xl" />
                <div class="text-sm mt-2">Carregando sessões…</div>
            </div>
            <div v-else-if="sessoesLista.length === 0" class="py-10 text-center text-[var(--text-color-secondary)]">
                <i class="pi pi-calendar-times text-2xl opacity-40" />
                <div class="text-sm mt-2">Nenhuma sessão registrada.</div>
            </div>
            <div v-else class="flex flex-col gap-1.5 max-h-[60vh] overflow-y-auto">
                <div
                    v-for="s in sessoesLista"
                    :key="s.id"
                    class="flex items-center gap-3 px-3 py-2 rounded-lg border border-[var(--surface-border)] bg-[var(--surface-card)]"
                >
                    <div class="text-xs font-mono text-[var(--text-color)] tabular-nums w-[120px] shrink-0">
                        {{ fmtSessaoData(s.inicio_em) }}
                    </div>
                    <div class="flex-1 min-w-0 text-sm">
                        <div class="font-medium truncate">
                            {{ s.titulo || (s.tipo === 'sessao' ? 'Atendimento' : (s.tipo || 'Sessão')) }}
                        </div>
                        <div v-if="s.modalidade" class="text-xs text-[var(--text-color-secondary)]">
                            {{ s.modalidade }}
                        </div>
                    </div>
                    <span class="text-xs font-medium shrink-0" :class="sessaoStatusColor(s.status)">
                        {{ sessaoStatusLabel(s.status) }}
                    </span>
                </div>
            </div>
            <template #footer>
                <div class="text-[0.7rem] text-[var(--text-color-secondary)]">
                    Mostrando últimas {{ sessoesLista.length }} sessões.
                </div>
            </template>
        </Dialog>

        <!-- Popover de ações (mobile) — disparado pelo pencil único do
             card. Reusa as mesmas funções dos botões inline desktop. -->
        <Popover ref="actionsPopRef" class="mp-actions-popover">
            <div v-if="actionsTarget" class="mp-actions-menu">
                <button class="mp-actions-menu__item" @click="actionsRun(abrirProntuario)">
                    <i class="pi pi-file" />
                    <span>Abrir prontuário</span>
                </button>
                <button class="mp-actions-menu__item" @click="actionsRun(verSessoes)">
                    <i class="pi pi-history" />
                    <span>Ver sessões</span>
                </button>
                <button class="mp-actions-menu__item" @click="actionsRun(abrirWhatsapp)">
                    <i class="pi pi-whatsapp" />
                    <span>Conversar (WhatsApp)</span>
                </button>
                <button class="mp-actions-menu__item" @click="actionsRun(editarPaciente)">
                    <i class="pi pi-pencil" />
                    <span>Editar</span>
                </button>
                <div class="mp-actions-menu__divider" />
                <!-- Arquivar / Restaurar — toggle baseado em status do paciente
                     atual no actionsTarget. Substitui um pelo outro pra evitar
                     ações redundantes (arquivar paciente já arquivado é no-op). -->
                <button
                    v-if="!isArquivado(actionsTarget)"
                    class="mp-actions-menu__item is-danger"
                    @click="actionsRun(confirmarRemover)"
                >
                    <i class="pi pi-trash" />
                    <span>Arquivar</span>
                </button>
                <button
                    v-else
                    class="mp-actions-menu__item is-restore"
                    @click="actionsRun(restaurarPaciente)"
                >
                    <i class="pi pi-undo" />
                    <span>Restaurar</span>
                </button>
            </div>
        </Popover>
    </section>
</template>

<style scoped>
/* ─── Convenção "Melissa Page" — espelha .ma-page do MelissaAgenda ─ */
.mp-page {
    position: absolute;
    inset: 6px 6px calc(var(--m-dock-h, 76px) + 6px) 6px;
    z-index: 40;
    display: flex;
    flex-direction: column;
    background: var(--m-bg-medium);
    backdrop-filter: blur(32px) saturate(160%);
    -webkit-backdrop-filter: blur(32px) saturate(160%);
    border: 1px solid var(--m-border);
    border-radius: 18px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
    overflow: hidden;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    color: var(--m-text);
    animation: mp-page-enter 240ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes mp-page-enter {
    from { opacity: 0; transform: scale(0.985); }
    to   { opacity: 1; transform: scale(1); }
}
.mp-page__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    border-bottom: 1px solid var(--m-border);
    flex-shrink: 0;
}
.mp-page__title {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 1rem;
    font-weight: 500;
}
.mp-page__title-icon {
    color: var(--p-primary-color);
    font-size: 1.05rem;
}
.mp-page__title > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Subheader explicativo — padrão do melissa-table-page-blueprint.md § 9.
   Faixa abaixo do page__head com bg sutil + ícone primary + texto muted.
   Diferencia esta página de outras com layout idêntico. */
.mp-subheader {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 18px;
    border-bottom: 1px solid var(--m-border);
    background: var(--m-bg-soft);
    font-size: 0.78rem;
    color: var(--m-text-muted);
    line-height: 1.45;
    flex-shrink: 0;
}
.mp-subheader__icon {
    color: var(--p-primary-color);
    font-size: 0.92rem;
    flex-shrink: 0;
    margin-top: 1px;
}
.mp-subheader__text {
    flex: 1;
    min-width: 0;
}
.mp-subheader__text strong {
    color: var(--m-text);
    font-weight: 600;
}
.mp-page__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}
.mp-page__count {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--m-accent);
    background: var(--m-accent-soft);
    border: 1px solid color-mix(in srgb, var(--m-accent) 35%, transparent);
    padding: 2px 8px;
    border-radius: 999px;
    margin-left: 4px;
}
.mp-page__loading {
    color: var(--m-text-muted);
    margin-left: 4px;
}
.mp-close {
    width: 32px; height: 32px;
    display: grid; place-items: center;
    background: var(--m-bg-soft);
    border: 1px solid var(--m-border);
    color: var(--m-text);
    border-radius: 9px;
    cursor: pointer;
    transition: background-color 140ms ease;
}
.mp-close:hover { background: var(--m-bg-soft-hover); }

/* Botão "Ir pra Agenda" no header — icon-only 32×32 (blueprint §11) */
.mp-header-btn {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    background: var(--m-bg-soft);
    border: 1px solid var(--m-border);
    color: var(--m-text);
    border-radius: 9px;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}
.mp-header-btn:hover {
    background: var(--m-accent-soft);
    border-color: var(--m-accent-strong);
    color: var(--m-text);
}
.mp-header-btn > i { font-size: 0.85rem; }

/* Menu button (mobile only, esquerda do header) — primary filled,
   abre o drawer com filtros + quickview. Aparece só em <lg. */
.mp-menu-btn {
    display: none; /* show via @media (max-width: 1023px) */
    height: 32px;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    background: var(--m-accent);
    border: 1px solid var(--m-accent);
    color: white;
    padding: 0 11px;
    border-radius: 9px;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    transition: background-color 140ms ease, transform 140ms ease;
}
.mp-menu-btn:hover {
    background: color-mix(in srgb, var(--m-accent) 88%, white);
    transform: translateY(-1px);
}
.mp-menu-btn:active { transform: translateY(0); }
.mp-menu-btn > i { font-size: 0.85rem; }

.mp-body {
    flex: 1;
    display: flex;
    min-height: 0;
}

/* ═══ COL 1: Filtros ═════════════════════════════════════════
   Layout flex column com 2 zonas: __scroll (cards, scrollável) e
   __footer (Limpar filtros, fixo no bottom). overflow: hidden no
   container externo evita que o scroll vaze pra fora. */
.mp-side {
    width: 240px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--m-border);
    background: var(--m-bg-soft);
    overflow: hidden;
}
.mp-side__scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px;
}
.mp-side__scroll::-webkit-scrollbar { width: 5px; }
.mp-side__scroll::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 3px;
}
.mp-side__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 6px 16px;
}
.mp-side__title {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--m-text-muted);
    font-weight: 600;
}
/* Cluster de ações (clear + add) à direita do título da seção */
.mp-side__head-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}
.mp-side__clear,
.mp-side__add,
.mp-side__cog {
    width: 18px; height: 18px;
    display: grid; place-items: center;
    background: transparent;
    border: 1px solid var(--m-border);
    border-radius: 4px;
    color: var(--m-text-muted);
    cursor: pointer;
    font-family: inherit;
    transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}
/* Clear (X) — vermelho pra indicar ação destrutiva (limpar filtro). */
.mp-side__clear {
    color: rgb(220, 38, 38);
    border-color: color-mix(in srgb, rgb(220, 38, 38) 30%, var(--m-border));
}
.mp-side__clear:hover {
    background: rgba(220, 38, 38, 0.10);
    border-color: rgba(220, 38, 38, 0.55);
    color: rgb(220, 38, 38);
}
.mp-side__add:hover {
    background: var(--m-accent-soft);
    border-color: color-mix(in srgb, var(--m-accent) 50%, var(--m-border));
    color: var(--m-accent);
}
/* Cog — sem borda (ghost icon), hover primary-tinted. */
.mp-side__cog {
    border-color: transparent;
}
.mp-side__cog:hover {
    background: color-mix(in srgb, var(--p-primary-color) 10%, transparent);
    color: var(--p-primary-color);
}
.mp-side__divider {
    height: 1px;
    background: var(--m-border);
    margin: 12px 12px;
}
.mp-side__placeholder {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    color: var(--m-text-faint);
    font-size: 0.74rem;
    font-style: italic;
}

/* Botão "+ Grupo" / "+ Tag" abaixo da lista — borda tracejada, vai pra
   primary no hover. Move o "Adicionar" pra área dedicada (não compete
   com o título no header como o antigo .mp-side__add fazia). */
.mp-side__add-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 10px;
    background: transparent;
    border: 1.5px dashed var(--m-border-strong);
    color: var(--m-text-muted);
    border-radius: 8px;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 500;
    transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}
.mp-side__add-btn:hover {
    background: color-mix(in srgb, var(--p-primary-color) 6%, transparent);
    border-color: var(--p-primary-color);
    color: var(--p-primary-color);
}
.mp-side__add-btn > i { font-size: 0.7rem; }
/* Footer fixo no bottom da sidebar (fora do scroll dos cards).
   Bg matching o da sidebar pra "ler" como continuação natural;
   border-top marca a separação com a área scrollável acima. */
.mp-side__footer {
    flex-shrink: 0;
    padding: 12px;
    background: var(--m-bg-soft);
    border-top: 1px solid var(--m-border);
}

/* Transition do footer "Limpar filtros" — fade + collapse vertical
   pra entrada/saída suave quando o user ativa/zera o último filtro. */
.mp-clear-enter-active,
.mp-clear-leave-active {
    transition: opacity 220ms ease, transform 220ms ease, max-height 240ms ease;
    overflow: hidden;
}
.mp-clear-enter-from,
.mp-clear-leave-to {
    opacity: 0;
    transform: translateY(6px);
    max-height: 0;
}
.mp-clear-enter-to,
.mp-clear-leave-from {
    opacity: 1;
    transform: translateY(0);
    max-height: 80px;
}

.mp-status-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0;
}
/* Status pills — coloridos por status (padrão do blueprint § 7).
   Cores Tailwind 600 (fortes pra ler em ambos os modos). 3 níveis:
   default tint 5% + hover 10% + active 16% + ring 35%.
   - Todos      = neutral (sem cor — abrange tudo)
   - Ativos     = 🟢 verde   (em tratamento)
   - Inativos   = 🟡 amber   (pausa temporária, atenção)
   - Arquivados = 🔴 vermelho (fora do ativo, finalizado) */
.mp-status-pill {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: transparent;
    border: 1px solid transparent;
    color: var(--m-text);
    border-radius: 8px;
    cursor: pointer;
    font-size: 0.82rem;
    font-family: inherit;
    transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
.mp-status-pill > i { font-size: 0.78rem; width: 14px; text-align: center; }

/* Todos — neutral (sem cor) */
.mp-status-pill.is-todos:hover { background: var(--m-bg-soft-hover); }
.mp-status-pill.is-todos.is-active {
    background: var(--m-accent-soft);
    border-color: var(--m-accent-strong);
}

/* Ativos — verde */
.mp-status-pill.is-ativos {
    background: rgba(22, 163, 74, 0.05);
    border-color: rgba(22, 163, 74, 0.18);
}
.mp-status-pill.is-ativos > i { color: rgb(22, 163, 74); }
.mp-status-pill.is-ativos:hover {
    background: rgba(22, 163, 74, 0.10);
    border-color: rgba(22, 163, 74, 0.30);
}
.mp-status-pill.is-ativos.is-active {
    background: rgba(22, 163, 74, 0.16);
    border-color: rgba(22, 163, 74, 0.55);
    box-shadow: 0 0 0 1px rgba(22, 163, 74, 0.35);
}

/* Inativos — amber (warn, paciente pausado) */
.mp-status-pill.is-inativos {
    background: rgba(217, 119, 6, 0.05);
    border-color: rgba(217, 119, 6, 0.18);
}
.mp-status-pill.is-inativos > i { color: rgb(217, 119, 6); }
.mp-status-pill.is-inativos:hover {
    background: rgba(217, 119, 6, 0.10);
    border-color: rgba(217, 119, 6, 0.30);
}
.mp-status-pill.is-inativos.is-active {
    background: rgba(217, 119, 6, 0.16);
    border-color: rgba(217, 119, 6, 0.55);
    box-shadow: 0 0 0 1px rgba(217, 119, 6, 0.35);
}

/* Arquivados — vermelho (fora do ativo) */
.mp-status-pill.is-arquivados {
    background: rgba(220, 38, 38, 0.05);
    border-color: rgba(220, 38, 38, 0.18);
}
.mp-status-pill.is-arquivados > i { color: rgb(220, 38, 38); }
.mp-status-pill.is-arquivados:hover {
    background: rgba(220, 38, 38, 0.10);
    border-color: rgba(220, 38, 38, 0.30);
}
.mp-status-pill.is-arquivados.is-active {
    background: rgba(220, 38, 38, 0.16);
    border-color: rgba(220, 38, 38, 0.55);
    box-shadow: 0 0 0 1px rgba(220, 38, 38, 0.35);
}

.mp-status-pill__count {
    font-size: 0.7rem;
    color: var(--m-text-muted);
    background: var(--m-bg-medium);
    padding: 1px 7px;
    border-radius: 999px;
    min-width: 22px;
    text-align: center;
}
.mp-status-pill.is-active .mp-status-pill__count {
    background: var(--m-accent);
    color: var(--p-primary-contrast-color, white);
}

.mp-chip-list {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 0;
}
.mp-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px 6px 8px;
    background: transparent;
    border: 1px solid transparent;
    border-left: 3px solid transparent;
    color: var(--m-text);
    border-radius: 7px;
    cursor: pointer;
    font-size: 0.78rem;
    font-family: inherit;
    text-align: left;
    transition: background-color 140ms ease, border-color 140ms ease;
}
.mp-chip:hover { background: var(--m-bg-soft-hover); }
.mp-chip.is-active {
    background: var(--m-accent-soft);
    border-color: var(--m-accent-strong);
    border-left-color: var(--m-accent);
}
.mp-chip__dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.mp-chip__name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Badge de contagem [N] — paridade com .mp-status-pill__count */
.mp-chip__count {
    font-size: 0.7rem;
    color: var(--m-text-muted);
    background: var(--m-bg-medium);
    padding: 1px 7px;
    border-radius: 999px;
    min-width: 22px;
    text-align: center;
    flex-shrink: 0;
}
.mp-chip.is-active .mp-chip__count {
    background: var(--m-accent);
    color: var(--p-primary-contrast-color, white);
}

/* ═══ COL 2: Lista central ═══════════════════════════════════ */
.mp-list {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    /* min-height: 0 é CRÍTICO pra que .mp-list__body (flex:1 + overflow-y:auto)
       constrinja altura e scrolle de verdade — sem isso, o body cresce
       indefinidamente e o scroll nunca dispara, especialmente em mobile
       onde .mp-body vira flex-direction:column. */
    min-height: 0;
}
.mp-list__toolbar {
    display: flex;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--m-border);
}
.mp-search {
    position: relative;
    flex: 1;
}
.mp-search__icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--m-text-muted);
    font-size: 0.85rem;
    pointer-events: none;
}
.mp-search__input {
    width: 100%;
    background: var(--m-bg-soft);
    border: 1px solid var(--m-border);
    color: var(--m-text);
    padding: 9px 12px 9px 34px;
    border-radius: 9px;
    font-size: 0.88rem;
    font-family: inherit;
    outline: none;
    transition: background-color 140ms ease, border-color 140ms ease;
}
.mp-search__input::placeholder { color: var(--m-text-faint); }
.mp-search__input:focus {
    background: var(--m-bg-soft-hover);
    border-color: var(--m-border-strong);
}

.mp-list__body {
    flex: 1;
    overflow-y: auto;
    padding: 8px 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    scrollbar-width: thin;
    scrollbar-color: var(--m-border-strong) transparent;
}
.mp-list__body::-webkit-scrollbar { width: 6px; }
.mp-list__body::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 3px;
}

/* Paginator da lista — fixo no rodapé da coluna 2, com seletor de tamanho
   de página. Sobrescrevo o visual default do PrimeVue pra alinhar com a
   estética Melissa (transparente, ícones com border do tema). */
.mp-paginator.p-paginator {
    background: transparent;
    border: none;
    border-top: 1px solid var(--m-border);
    padding: 8px 12px;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px;
}
.mp-paginator.p-paginator .p-paginator-current {
    color: var(--m-text-muted);
    font-size: 0.78rem;
    background: transparent;
    border: none;
    padding: 0 4px;
    height: 30px;
    min-width: auto;
}
.mp-paginator.p-paginator .p-paginator-first,
.mp-paginator.p-paginator .p-paginator-prev,
.mp-paginator.p-paginator .p-paginator-next,
.mp-paginator.p-paginator .p-paginator-last,
.mp-paginator.p-paginator .p-paginator-page {
    min-width: 30px;
    height: 30px;
    color: var(--m-text);
    background: transparent;
    border: 1px solid var(--m-border);
    border-radius: 8px;
    font-size: 0.8rem;
    transition: background-color 140ms ease, border-color 140ms ease;
}
.mp-paginator.p-paginator .p-paginator-page.p-paginator-page-selected {
    background: var(--m-accent-soft);
    border-color: var(--m-accent-strong);
    color: var(--m-accent);
}
.mp-paginator.p-paginator .p-paginator-first:not(.p-disabled):hover,
.mp-paginator.p-paginator .p-paginator-prev:not(.p-disabled):hover,
.mp-paginator.p-paginator .p-paginator-next:not(.p-disabled):hover,
.mp-paginator.p-paginator .p-paginator-last:not(.p-disabled):hover,
.mp-paginator.p-paginator .p-paginator-page:not(.p-paginator-page-selected):hover {
    background: var(--m-bg-soft-hover);
    border-color: var(--m-border-strong);
}
.mp-paginator.p-paginator .p-paginator-first.p-disabled,
.mp-paginator.p-paginator .p-paginator-prev.p-disabled,
.mp-paginator.p-paginator .p-paginator-next.p-disabled,
.mp-paginator.p-paginator .p-paginator-last.p-disabled {
    opacity: 0.35;
}
/* Dropdown de "rows per page" — combina com inputs do tema */
.mp-paginator.p-paginator .p-select {
    background: var(--m-bg-soft);
    border: 1px solid var(--m-border);
    border-radius: 8px;
    height: 30px;
    font-size: 0.78rem;
    color: var(--m-text);
}
.mp-paginator.p-paginator .p-select:hover {
    border-color: var(--m-border-strong);
}
.mp-paginator.p-paginator .p-select-label {
    padding: 0 8px;
    color: var(--m-text);
    font-size: 0.78rem;
}
/* Empty state — borda tracejada, ícone grande centralizado, textos confortáveis
   e CTAs primários (Limpar busca aparece só quando há filtro ativo). */
.mp-empty-state {
    margin: 24px 8px;
    padding: 56px 28px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--m-text-muted);
    border: 2px dashed var(--m-border-strong);
    border-radius: 12px; /* teto blueprint §12 */
    background: color-mix(in srgb, var(--m-bg-soft) 40%, transparent);
}
.mp-empty-state__icon {
    font-size: 3.5rem;
    color: var(--m-text-muted);
    opacity: 0.55;
    margin-bottom: 18px;
}
.mp-empty-state__title {
    font-size: 1.15rem;
    font-weight: 500;
    color: var(--m-text);
    letter-spacing: -0.01em;
}
.mp-empty-state__hint {
    font-size: 0.92rem;
    color: var(--m-text-muted);
    margin-top: 6px;
    max-width: 360px;
    line-height: 1.45;
}
.mp-empty-state__actions {
    display: flex;
    gap: 10px;
    margin-top: 22px;
    flex-wrap: wrap;
    justify-content: center;
}

/* Skeleton — sem hover/cursor */
.mp-card--skeleton {
    cursor: default;
    pointer-events: none;
    opacity: 0.95;
}
.mp-card--skeleton:hover { background: transparent; }

.mp-card {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 10px;
    color: var(--m-text);
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 140ms ease, border-color 140ms ease;
}
.mp-card:hover {
    background: var(--m-bg-soft);
    border-color: var(--m-border);
}
.mp-card.is-active {
    background: var(--m-accent-soft);
    border-color: var(--m-accent-strong);
}
.mp-card.is-novo {
    background: color-mix(in srgb, var(--p-primary-color) 8%, transparent);
}
.mp-card.is-novo.is-active {
    background: var(--m-accent-soft);
    border-color: var(--m-accent);
}
.mp-card__avatar {
    width: 40px; height: 40px;
    border-radius: 50%;
    background: var(--m-accent);
    border: 1px solid var(--m-accent);
    color: var(--p-primary-contrast-color, white);
    display: grid;
    place-items: center;
    font-size: 0.85rem;
    font-weight: 600;
    flex-shrink: 0;
    overflow: hidden;
}
.mp-card__avatar img {
    width: 100%; height: 100%;
    object-fit: cover;
}
.mp-card__main {
    flex: 1;
    min-width: 0;
}
.mp-card__name-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
.mp-card__name {
    font-size: 0.92rem;
    font-weight: 500;
    color: var(--m-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mp-card__novo {
    font-size: 0.55rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--m-accent);
    color: var(--p-primary-contrast-color, white);
    flex-shrink: 0;
    line-height: 1.2;
}
.mp-card__status {
    font-size: 0.6rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--m-bg-soft);
    color: var(--m-text-muted);
    border: 1px solid var(--m-border);
    flex-shrink: 0;
    line-height: 1.2;
}
.mp-card__meta {
    display: flex;
    gap: 12px;
    margin-top: 2px;
    font-size: 0.74rem;
    color: var(--m-text-muted);
    overflow: hidden;
}
.mp-card__meta-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Email — coluna própria do card. Width fixa pra alinhar visualmente
   entre rows. Trunca com ellipsis quando longo. Em mobile, esconde
   (info migra pro detail panel). */
.mp-card__email {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 220px;
    min-width: 0;
    flex-shrink: 1;
    font-size: 0.78rem;
    color: var(--m-text-muted);
}
.mp-card__email > i { font-size: 0.7rem; flex-shrink: 0; }
.mp-card__email-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Telefone — coluna própria, width menor (formato fixo). */
.mp-card__phone {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 140px;
    flex-shrink: 0;
    font-size: 0.78rem;
    color: var(--m-text-muted);
}
.mp-card__phone > i { font-size: 0.7rem; flex-shrink: 0; }
.mp-card__phone-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.mp-card__tags {
    display: flex;
    gap: 4px;
    margin-top: 5px;
    flex-wrap: nowrap;
    overflow: hidden;
}
.mp-card__tag {
    font-size: 0.65rem;
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid transparent;
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100px;
}
.mp-card__tag-more {
    font-size: 0.65rem;
    color: var(--m-text-faint);
    line-height: 1.4;
    align-self: center;
}
.mp-card__last {
    flex-shrink: 0;
    text-align: right;
    padding-left: 8px;
    border-left: 1px solid var(--m-border);
}
.mp-card__last-label {
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--m-text-faint);
}
.mp-card__last-date {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--m-text-muted);
    font-variant-numeric: tabular-nums;
    margin-top: 1px;
}

/* Ações inline do card — visíveis no hover do .mp-card e sempre no ativo.
   Em mobile/touch (≤ 768px) ficam sempre visíveis. */
.mp-card__actions {
    display: flex;
    gap: 2px;
    margin-left: 4px;
    padding-left: 8px;
    border-left: 1px solid var(--m-border);
    opacity: 0;
    transform: translateX(4px);
    transition: opacity 160ms ease, transform 160ms ease;
    flex-shrink: 0;
}
.mp-card:hover .mp-card__actions,
.mp-card.is-active .mp-card__actions,
.mp-card:focus-within .mp-card__actions {
    opacity: 1;
    transform: translateX(0);
}
.mp-card__action {
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    background: transparent;
    border: 1px solid transparent;
    color: var(--m-text-muted);
    border-radius: 7px;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 140ms ease, color 140ms ease, border-color 140ms ease;
}
.mp-card__action i { font-size: 0.78rem; }
.mp-card__action:hover {
    background: var(--m-bg-soft-hover);
    border-color: var(--m-border);
    color: var(--m-text);
}
.mp-card__action--danger:hover {
    background: rgba(239, 68, 68, 0.14);
    border-color: rgba(239, 68, 68, 0.4);
    color: rgb(248, 113, 113);
}
/* Restaurar — primary-tinted (ação positiva, oposto de danger). */
.mp-card__action--restore {
    color: var(--p-primary-color);
}
.mp-card__action--restore:hover {
    background: color-mix(in srgb, var(--p-primary-color) 14%, transparent);
    border-color: color-mix(in srgb, var(--p-primary-color) 40%, var(--m-border));
    color: var(--p-primary-color);
}
/* Mobile-only action button — pencil único que abre o popover.
   Sempre visível, com bg-medium pra ler bem com o sticky-right.
   Esconde por default; mostra só em mobile via media query abaixo. */
.mp-card__action--mobile {
    display: none;
    background: var(--p-content-background);
    border-color: color-mix(in srgb, var(--p-primary-color) 30%, var(--m-border));
    color: var(--p-primary-color);
}
.mp-card__action--mobile:hover {
    background: color-mix(in srgb, var(--p-primary-color) 12%, var(--p-content-background));
    border-color: var(--p-primary-color);
    color: var(--p-primary-color);
}

/* View toggle (lista/grade) — mesmo segmented control do MCR/MAR. */
.mp-view-toggle {
    flex-shrink: 0;
    display: inline-flex;
    background: var(--m-bg-medium);
    border: 1px solid var(--m-border);
    border-radius: 10px;
    padding: 2px;
    gap: 2px;
}
.mp-view-toggle__btn {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    background: transparent;
    border: none;
    color: var(--m-text-muted);
    border-radius: 8px;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 140ms ease, color 140ms ease;
}
.mp-view-toggle__btn:hover {
    background: var(--m-bg-soft-hover);
    color: var(--m-text);
}
.mp-view-toggle__btn.is-active {
    background: var(--m-accent-soft);
    color: var(--m-accent);
}
.mp-view-toggle__btn > i { font-size: 0.85rem; }

/* ═══ Grid view — cards num grid responsivo ═════════════════ */
.mp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
    padding: 4px 0;
}
.mp-grid__card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    background: var(--m-bg-soft);
    border: 1px solid var(--m-border);
    border-radius: 10px;
    color: var(--m-text);
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: background-color 140ms ease, border-color 140ms ease, transform 140ms ease;
}
.mp-grid__card:hover {
    background: var(--m-bg-soft-hover);
    border-color: var(--m-border-strong);
    transform: translateY(-1px);
}
.mp-grid__card:focus-visible {
    outline: 2px solid var(--p-primary-color);
    outline-offset: 2px;
}
.mp-grid__card.is-active {
    background: var(--m-accent-soft);
    border-color: var(--m-accent-strong);
}
.mp-grid__card.is-novo {
    background: color-mix(in srgb, var(--p-primary-color) 8%, var(--m-bg-soft));
}
.mp-grid__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
/* No grid card o pencil sempre visível (mesmo desktop), pra dar acesso
   às ações sem precisar passar mouse — o card é mais compacto que o
   da lista. */
.mp-grid__card .mp-card__action--mobile {
    display: grid;
}
.mp-grid__name-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.mp-grid__name {
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--m-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.mp-grid__status {
    font-size: 0.6rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--m-bg-medium);
    color: var(--m-text-muted);
    border: 1px solid var(--m-border);
    align-self: flex-start;
}
.mp-grid__meta {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.74rem;
    color: var(--m-text-muted);
    min-width: 0;
}
.mp-grid__meta i { margin-right: 5px; font-size: 0.7rem; }
.mp-grid__meta span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mp-grid__last {
    margin-top: auto;
    padding-top: 6px;
    border-top: 1px solid var(--m-border);
    font-size: 0.7rem;
    color: var(--m-text-faint);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.mp-grid__last i { font-size: 0.65rem; }

/* ═══ Popover de ações (mobile) ════════════════════════════ */
.mp-actions-popover :deep(.p-popover-content) {
    padding: 6px;
}
.mp-actions-menu {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 200px;
}
.mp-actions-menu__item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    background: transparent;
    border: 1px solid transparent;
    color: var(--m-text);
    border-radius: 8px;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.85rem;
    text-align: left;
    transition: background-color 140ms ease, color 140ms ease;
}
.mp-actions-menu__item > i {
    font-size: 0.85rem;
    color: var(--m-text-muted);
    width: 16px;
    text-align: center;
}
.mp-actions-menu__item:hover {
    background: var(--m-bg-soft-hover);
}
.mp-actions-menu__item:hover > i { color: var(--p-primary-color); }
.mp-actions-menu__item.is-danger {
    color: rgb(220, 38, 38);
}
.mp-actions-menu__item.is-danger > i { color: rgb(220, 38, 38); }
.mp-actions-menu__item.is-danger:hover {
    background: rgba(220, 38, 38, 0.10);
}
/* Restore — primary, semanticamente positivo. */
.mp-actions-menu__item.is-restore {
    color: var(--p-primary-color);
}
.mp-actions-menu__item.is-restore > i { color: var(--p-primary-color); }
.mp-actions-menu__item.is-restore:hover {
    background: color-mix(in srgb, var(--p-primary-color) 10%, transparent);
}
.mp-actions-menu__divider {
    height: 1px;
    background: var(--m-border);
    margin: 4px 6px;
}

@media (max-width: 768px) {
    .mp-card__actions {
        opacity: 1;
        transform: none;
        /* Sticky-right pra fixar visualmente a coluna de ação enquanto
           o user scrolla horizontalmente o conteúdo do card. */
        position: sticky;
        right: 0;
        background: var(--m-bg-medium);
        padding-left: 6px;
    }
    /* Em mobile, esconde os 5 botões inline e mostra só o pencil. */
    .mp-card__action--desktop { display: none; }
    .mp-card__action--mobile { display: grid; }
    /* Esconde email e phone columns em mobile (muito apertado). Email
       fica só no detail panel e no popover do paciente. */
    .mp-card__email,
    .mp-card__phone { display: none; }
}

/* ═══ COL 3: Quick view ══════════════════════════════════════ */
.mp-quick {
    width: 320px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    border-left: 1px solid var(--m-border);
    background: var(--m-bg-soft);
    padding: 14px;
    overflow-y: auto;
}
/* Card-base — espelha .ma-w da MelissaAgenda. Usado nas duas colunas
   laterais (Status/Grupos/Tags na col 1, Visão geral/Detalhes na col 3).
   Surface --m-bg-medium pra destacar das colunas (que usam --m-bg-soft) e
   diferente do dialog (também --m-bg-soft). */
.mp-w {
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var(--m-bg-medium);
    border: 1px solid var(--m-border);
    border-radius: 12px;
    padding: 12px;
}
/* Sombra sutil pros cards de ambas as colunas laterais (igual MCR/MAR).
   Eleva visualmente os cards sobre os bgs das asides. */
.mp-side .mp-w,
.mp-quick .mp-w {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}
.mp-w__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0;
}
.mp-w__title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--m-text-muted);
    font-weight: 600;
}
.mp-w__divider {
    height: 1px;
    background: var(--m-border);
    margin: 16px 0 14px;
}
/* Variante pro card de detalhes do paciente: zera o gap padrão (.mp-detail
   já tem espaçamento interno próprio entre avatar/nome/rows/ações). */
.mp-w--detail {
    gap: 0;
}

.mp-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}
.mp-stat {
    background: var(--m-bg-medium);
    border: 1px solid var(--m-border);
    border-radius: 10px;
    padding: 10px 6px;
    text-align: center;
}
.mp-stat__val {
    font-size: 1.5rem;
    font-weight: 200;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--m-text);
    font-variant-numeric: tabular-nums;
}
.mp-stat__lbl {
    font-size: 0.7rem;
    color: var(--m-text-muted);
    margin-top: 4px;
    line-height: 1.15;
}
.mp-aniv {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 10px;
    background: color-mix(in srgb, #f59e0b 14%, var(--m-bg-medium));
    border: 1px solid color-mix(in srgb, #f59e0b 32%, transparent);
    border-radius: 8px;
    font-size: 0.78rem;
    color: var(--m-text);
}
.mp-aniv i {
    color: #f59e0b;
}

/* Detail card */
.mp-detail {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 8px 4px;
}
.mp-detail__close {
    position: absolute;
    top: 0;
    right: 0;
    width: 26px; height: 26px;
    display: grid; place-items: center;
    background: transparent;
    border: 1px solid transparent;
    color: var(--m-text-muted);
    border-radius: 7px;
    cursor: pointer;
    transition: background-color 140ms ease;
}
.mp-detail__close:hover {
    background: var(--m-bg-soft-hover);
    color: var(--m-text);
}
.mp-detail__avatar {
    width: 72px; height: 72px;
    border-radius: 50%;
    background: var(--m-accent);
    border: 2px solid var(--m-accent-strong);
    color: var(--p-primary-contrast-color, white);
    display: grid;
    place-items: center;
    font-size: 1.4rem;
    font-weight: 600;
    overflow: hidden;
    margin-bottom: 10px;
}
.mp-detail__avatar img {
    width: 100%; height: 100%;
    object-fit: cover;
}
.mp-detail__name {
    font-size: 1rem;
    font-weight: 500;
    color: var(--m-text);
}
.mp-detail__status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    font-size: 0.74rem;
    color: var(--m-text-muted);
}
.mp-detail__aniv-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-left: 6px;
    padding: 2px 7px;
    border-radius: 999px;
    background: color-mix(in srgb, #f59e0b 18%, transparent);
    border: 1px solid color-mix(in srgb, #f59e0b 40%, transparent);
    color: #f59e0b;
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.mp-detail__rows {
    width: 100%;
    margin-top: 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    text-align: left;
}
.mp-detail__row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 10px;
    background: var(--m-bg-medium);
    border: 1px solid var(--m-border);
    border-radius: 8px;
    font-size: 0.78rem;
    color: var(--m-text);
}
.mp-detail__row i {
    color: var(--m-text-muted);
    font-size: 0.78rem;
    flex-shrink: 0;
}
.mp-detail__row span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mp-detail__chips {
    width: 100%;
    margin-top: 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    justify-content: center;
}
.mp-detail__chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px 3px 7px;
    border-radius: 999px;
    border: 1px solid var(--m-border);
    border-left-width: 3px;
    background: var(--m-bg-medium);
    font-size: 0.7rem;
    color: var(--m-text);
}
.mp-detail__chip--tag {
    border-left-width: 1px;
}
.mp-detail__actions {
    width: 100%;
    margin-top: 14px;
}
.mp-detail__empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    color: var(--m-text-muted);
}

/* ─── Botões compartilhados ────────────────────────────────── */
.mp-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: 9px;
    font-size: 0.82rem;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background-color 140ms ease, border-color 140ms ease;
    border: 1px solid transparent;
}
.mp-btn--block { width: 100%; }
.mp-btn--primary {
    background: var(--m-accent);
    border-color: var(--m-accent);
    color: var(--p-primary-contrast-color, white);
}
.mp-btn--primary:hover {
    background: color-mix(in srgb, var(--m-accent) 82%, white);
}
.mp-btn--ghost {
    background: var(--m-bg-medium);
    border-color: var(--m-border);
    color: var(--m-text);
}
.mp-btn--ghost:hover {
    background: var(--m-bg-soft-hover);
    border-color: var(--m-border-strong);
}

/* ═══════════════════════════════════════════════════════════════
   Drawer mobile (blueprint §6) — paridade total com .ma-mobile-drawer
   ═══════════════════════════════════════════════════════════════ */
.mp-mobile-drawer {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    height: 100dvh;
    width: min(360px, 88vw);
    z-index: 80; /* acima do ψ (70) — blueprint §4 */
    background: var(--m-bg-medium);
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    border-right: 1px solid var(--m-border);
    transform: translateX(-100%);
    transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);
    color: var(--m-text);
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    display: flex;
    flex-direction: column;
}
.mp-mobile-drawer.is-open {
    transform: translateX(0);
}
.mp-mobile-drawer__scroll {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* Pattern espelha AppMenu/layout-sidebar: drawer = flex column, host
   pass-through (overflow hidden), .mp-side é flex column com scroll
   interno e __footer flex-shrink: 0 pinado no bottom.
   .mp-quick fica fixo no topo (flex-shrink: 0). */
.mp-mobile-drawer__scroll .mp-quick {
    width: 100%;
    flex-shrink: 0;
    height: auto;
    overflow-y: auto;
    overflow-x: hidden;
    border-right: none;
    border-left: none;
    background: transparent;
    padding: 12px;
    max-height: 50%;
}
.mp-mobile-drawer__scroll .mp-side {
    width: 100%;
    flex: 1;
    min-height: 0;
    overflow: hidden;
    border-right: none;
    border-left: none;
    background: transparent;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.mp-mobile-drawer__scroll .mp-side__scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    scrollbar-width: thin;
    scrollbar-color: var(--m-border-strong) transparent;
}
.mp-mobile-drawer__scroll .mp-side__scroll::-webkit-scrollbar { width: 5px; }
.mp-mobile-drawer__scroll .mp-side__scroll::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 3px;
}
.mp-mobile-drawer__scroll .mp-side__footer {
    flex-shrink: 0;
    margin: 0;
    padding: 12px;
    background: var(--m-bg-medium);
    border-top: 1px solid var(--m-border);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
}

/* Reordena dentro do drawer: Visão geral (.mp-quick) vem PRIMEIRO,
   filtros (.mp-side) depois. Em desktop o template mantém a ordem
   natural (filtros à esquerda, quickview à direita) — order só
   afeta o .mp-mobile-drawer__scroll que é flex column. */
.mp-mobile-drawer__scroll .mp-quick { order: 0; }
.mp-mobile-drawer__scroll .mp-side  { order: 1; }

.mp-mobile-drawer__backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 79; /* acima do ψ (70), abaixo do drawer (80) */
}
.mp-drawer-fade-enter-active,
.mp-drawer-fade-leave-active { transition: opacity 200ms ease; }
.mp-drawer-fade-enter-from,
.mp-drawer-fade-leave-to { opacity: 0; }

/* ═══════════════════════════════════════════════════════════════
   Responsivo <lg (≤1023px) — "mobile" (blueprint §3)
   ───────────────────────────────────────────────────────────────
   - .mp-side e .mp-quick somem do .mp-body (Teleport os move pro
     .mp-mobile-drawer fora do layout)
   - .mp-list vira fullwidth
   - Botão "Menu" aparece à esquerda do header
   - Título da página some (Menu já carrega o nome da seção)
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
    .mp-body {
        flex-direction: column;
    }
    .mp-list {
        width: 100%;
    }
    .mp-page__title { display: none; }
    .mp-menu-btn--mobile-only { display: inline-flex; }
}
</style>
