<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/features/patients/prontuario/PatientProntuario.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue';

import Chip     from 'primevue/chip';
import Accordion       from 'primevue/accordion';
import AccordionPanel  from 'primevue/accordionpanel';
import AccordionHeader from 'primevue/accordionheader';
import AccordionContent from 'primevue/accordioncontent';
import Popover from 'primevue/popover';

import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';
import { supabase } from '@/lib/supabase/client';
import { useTenantStore } from '@/stores/tenantStore';
import { useConversationDrawerStore } from '@/stores/conversationDrawerStore';

import DocumentsListPage from '@/features/documents/DocumentsListPage.vue';
import PatientConversationsTab from './PatientConversationsTab.vue';
import { registerPatientVisit } from '@/composables/useRecentPatients';

// ── PROPS / EMITS ──────────────────────────────────────────────
const props = defineProps({
    modelValue: { type: Boolean, default: false },
    patient:    { type: Object,  default: () => ({}) },
});
const emit = defineEmits(['update:modelValue', 'close', 'edit', 'add-financial']);

const toast = useToast();
const confirm = useConfirm();
const tenantStore = useTenantStore();
const conversationDrawerStore = useConversationDrawerStore();

const model = computed({
    get: () => props.modelValue,
    set: (v) => emit('update:modelValue', v),
});

// ── UTILS ──────────────────────────────────────────────────────
function isEmpty(v) {
    if (v === null || v === undefined) return true;
    return !String(v).trim();
}
function dash(v) {
    const s = String(v ?? '').trim();
    return s || '—';
}
function pick(obj, keys = []) {
    for (const k of keys) {
        const v = obj?.[k];
        if (!isEmpty(v)) return v;
    }
    return null;
}

// ── TABS PRINCIPAIS ────────────────────────────────────────────
// activeTab=0 abre o dashboard "Visão Geral" (resumo + timeline + KPIs).
// As abas seguintes mantém o que já existia, deslocadas em +1.
const activeTab = ref(0);
const mainTabs = [
    { label: 'Visão Geral', icon: 'pi pi-chart-line' },
    { label: 'Perfil',      icon: 'pi pi-user' },
    { label: 'Prontuário',  icon: 'pi pi-file-edit' },
    { label: 'Agenda',      icon: 'pi pi-calendar' },
    { label: 'Financeiro',  icon: 'pi pi-wallet' },
    { label: 'Documentos',  icon: 'pi pi-folder' },
    { label: 'Conversas',   icon: 'pi pi-whatsapp' },
];

// ── ACCORDION DA ABA PERFIL ────────────────────────────────────
const accordionValues = ['0', '1', '2', '3', '4', '5'];
const activeAccValues = ref(['0']);
const activeAccValue  = computed(() => activeAccValues.value?.[0] ?? null);

const panelHeaderRefs = ref([]);
function setPanelHeaderRef(el, idx) {
    if (!el) return;
    panelHeaderRefs.value[idx] = el;
}

const allOpen = computed(() =>
    accordionValues.every((v) => activeAccValues.value.includes(v))
);
function toggleAllAccordions() {
    activeAccValues.value = allOpen.value ? [] : [...accordionValues];
}

async function openPanel(i) {
    // Aba 1 = "Perfil" (após inserção da aba 0 "Visão Geral").
    activeTab.value = 1;
    const v = String(i);
    activeAccValues.value = [v];
    await nextTick();
    const headerRef = panelHeaderRefs.value?.[i];
    const el = headerRef?.$el ?? headerRef;
    if (el && typeof el.scrollIntoView === 'function') {
        el.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
}

const profileNavItems = [
    { value: '0', label: 'Informações Pessoais', icon: 'pi pi-pencil' },
    { value: '1', label: 'Endereço',             icon: 'pi pi-map-marker' },
    { value: '2', label: 'Dados Adicionais',     icon: 'pi pi-tags' },
    { value: '3', label: 'Responsável',          icon: 'pi pi-users' },
    { value: '4', label: 'Anotações',            icon: 'pi pi-file-edit' },
    { value: '5', label: 'Sessões',              icon: 'pi pi-calendar' },
];

const navPopover = ref(null);
function toggleNav(event) { navPopover.value?.toggle(event); }
function selectNav(item) {
    openPanel(Number(item.value));
    navPopover.value?.hide();
}
const selectedNav = computed(() =>
    profileNavItems.find((i) => i.value === activeAccValue.value) || null
);

// Responsivo
const isCompact = ref(false);
let mql = null, mqlHandler = null;
function syncCompact() { isCompact.value = !!mql?.matches; }
onMounted(() => {
    mql = window.matchMedia('(max-width: 1199px)');
    mqlHandler = () => syncCompact();
    mql.addEventListener?.('change', mqlHandler);
    mql.addListener?.(mqlHandler);
    syncCompact();
});
onBeforeUnmount(() => {
    mql?.removeEventListener?.('change', mqlHandler);
    mql?.removeListener?.(mqlHandler);
});

// ── DATA LOAD ──────────────────────────────────────────────────
const loading         = ref(false);
const loadError       = ref('');
const patientFull     = ref(null);
const groups          = ref([]);
const tags            = ref([]);
const sessions        = ref([]);
const sessionsLoading = ref(false);

// Dashboard "Visão Geral" — agregações leves carregadas em paralelo.
const recentMessages   = ref([]);   // últimas 4 trocadas (in/out)
const messagesLoading  = ref(false);
const financialRecords = ref([]);   // últimos 12 lançamentos
const financialLoading = ref(false);

// Aba Documentos — só metadata pra KPIs (DocumentsListPage carrega o
// detalhe via composable próprio). Mantemos esse loader paralelo pra
// que os números apareçam imediatamente sem depender do componente embed.
const documentsList    = ref([]);
const documentsLoading = ref(false);

const patientData = computed(() => patientFull.value || props.patient || {});

// Avatar
const avatarUrl = computed(() =>
    patientData.value?.avatar_url || patientData.value?.avatar || null
);

// Grupos
const groupNames = computed(() =>
    (groups.value || []).map((g) => g?.name).filter(Boolean)
);
const groupLabel = computed(() => {
    const n = groupNames.value.length;
    if (n === 0) return '—';
    return groupNames.value.join(', ');
});
const groupCountLabel = computed(() =>
    groupNames.value.length <= 1 ? 'Grupo' : 'Grupos'
);

// ── COMPUTED FIELDS ────────────────────────────────────────────
const birthValue          = computed(() => pick(patientData.value, ['data_nascimento', 'birth_date']));
const nomeCompleto        = computed(() => pick(patientData.value, ['nome_completo', 'name']));
const telefone            = computed(() => pick(patientData.value, ['telefone', 'phone']));
const emailPrincipal      = computed(() => pick(patientData.value, ['email_principal', 'email']));
const emailAlternativo    = computed(() => pick(patientData.value, ['email_alternativo', 'email_alt', 'emailAlt']));
const telefoneAlternativo = computed(() => pick(patientData.value, ['telefone_alternativo', 'phone_alt', 'phoneAlt']));
const genero              = computed(() => pick(patientData.value, ['genero', 'gender']));
const estadoCivil         = computed(() => pick(patientData.value, ['estado_civil', 'marital_status']));
const naturalidade        = computed(() => pick(patientData.value, ['naturalidade', 'birthplace', 'place_of_birth']));
const observacoes         = computed(() => pick(patientData.value, ['observacoes', 'notes_short']));
const ondeNosConheceu     = computed(() => pick(patientData.value, ['onde_nos_conheceu', 'lead_source']));
const encaminhadoPor      = computed(() => pick(patientData.value, ['encaminhado_por', 'referred_by']));
const statusPaciente      = computed(() => pick(patientData.value, ['status']));
const convenio            = computed(() => pick(patientData.value, ['convenio']));
const patientScope        = computed(() => pick(patientData.value, ['patient_scope']));
const riscoElevado        = computed(() => !!patientData.value?.risco_elevado);

const cep         = computed(() => pick(patientData.value, ['cep', 'postal_code']));
const pais        = computed(() => pick(patientData.value, ['pais', 'country']));
const cidade      = computed(() => pick(patientData.value, ['cidade', 'city']));
const estado      = computed(() => pick(patientData.value, ['estado', 'state']));
const endereco    = computed(() => pick(patientData.value, ['endereco', 'address_line']));
const numero      = computed(() => pick(patientData.value, ['numero', 'address_number']));
const bairro      = computed(() => pick(patientData.value, ['bairro', 'neighborhood']));
const complemento = computed(() => pick(patientData.value, ['complemento', 'address_complement']));

const escolaridade         = computed(() => pick(patientData.value, ['escolaridade', 'education', 'education_level']));
const profissao            = computed(() => pick(patientData.value, ['profissao', 'profession']));
const nomeParente          = computed(() => pick(patientData.value, ['nome_parente', 'relative_name']));
const grauParentesco       = computed(() => pick(patientData.value, ['grau_parentesco', 'relative_relation']));
const telefoneParente      = computed(() => pick(patientData.value, ['telefone_parente', 'relative_phone']));

const nomeResponsavel       = computed(() => pick(patientData.value, ['nome_responsavel', 'guardian_name']));
const cpfResponsavel        = computed(() => pick(patientData.value, ['cpf_responsavel', 'guardian_cpf']));
const telefoneResponsavel   = computed(() => pick(patientData.value, ['telefone_responsavel', 'guardian_phone']));
const observacaoResponsavel = computed(() => pick(patientData.value, ['observacao_responsavel', 'guardian_note']));
const notasInternas         = computed(() => pick(patientData.value, ['notas_internas', 'notes']));

// Métricas (lidas do patientData ou fallback null)
const totalSessoes       = computed(() => patientData.value?.total_sessoes ?? null);
const comparecimentoPct  = computed(() => patientData.value?.comparecimento_pct ?? null);
const ltvTotal           = computed(() => patientData.value?.ltv_total ?? null);
const diasUltimaSessao   = computed(() => patientData.value?.dias_ultima_sessao ?? null);

// ── DASHBOARD DERIVADOS (Visão Geral) ───────────────────────────
// sessions vem ordenado DESC (mais recente primeiro). Derivamos:
//  - presentes: status realizado/presente
//  - faltas/cancel.: contagem pra contraste no card
//  - próxima: primeira futura na ordem cronológica
//  - últimas atendidas: top 6 realizadas pra timeline
const sessoesPresentes = computed(() =>
    sessions.value.filter((s) => /realiz|present/i.test(String(s.status || ''))).length
);
const sessoesFaltadas = computed(() =>
    sessions.value.filter((s) => /falta/i.test(String(s.status || ''))).length
);
const sessoesCanceladas = computed(() =>
    sessions.value.filter((s) => /cancel|remarca/i.test(String(s.status || ''))).length
);
const proximaSessao = computed(() => {
    const now = Date.now();
    // ordem DESC; pegar a primeira cuja inicio_em > now (no array, é a última futura)
    const futuras = sessions.value
        .filter((s) => s.inicio_em && new Date(s.inicio_em).getTime() > now)
        .sort((a, b) => new Date(a.inicio_em) - new Date(b.inicio_em));
    return futuras[0] || null;
});
const ultimasAtendidas = computed(() =>
    sessions.value
        .filter((s) => /realiz|present|falt|cancel|remarca/i.test(String(s.status || '')))
        .slice(0, 6)
);
function diasAteSessao(iso) {
    if (!iso) return null;
    const ms = new Date(iso).getTime() - Date.now();
    if (Number.isNaN(ms)) return null;
    return Math.ceil(ms / (1000 * 60 * 60 * 24));
}

// Status financeiro: agrega lançamentos pra dizer
//  - emDia: nenhum pendente está vencido (paid_at NULL && due_date < hoje)
//  - proxVenc: próximo pendente com due_date no futuro
//  - totalPendente / totalPago: somatório
const statusFinanceiro = computed(() => {
    const recs = financialRecords.value;
    if (!recs?.length) {
        return { emDia: null, proxVenc: null, totalPendente: 0, totalPago: 0, vencidos: 0 };
    }
    const now = Date.now();
    const pendentes = recs.filter((r) => !r.paid_at);
    const pagos     = recs.filter((r) => !!r.paid_at);
    const vencidos  = pendentes.filter((r) => r.due_date && new Date(r.due_date + 'T23:59:59').getTime() < now);
    const proxVenc  = pendentes
        .filter((r) => r.due_date && new Date(r.due_date + 'T00:00:00').getTime() >= now)
        .sort((a, b) => new Date(a.due_date) - new Date(b.due_date))[0] || null;
    const totalPendente = pendentes.reduce((acc, r) => acc + (Number(r.amount) || 0), 0);
    const totalPago     = pagos.reduce((acc, r) => acc + (Number(r.amount) || 0), 0);
    return {
        emDia: vencidos.length === 0,
        proxVenc,
        totalPendente,
        totalPago,
        vencidos: vencidos.length
    };
});

// Última atividade na conversa (data + lado: in/out)
const ultimaMensagem = computed(() => recentMessages.value[0] || null);

// ── DASHBOARD: aba Financeiro ─────────────────────────────────
// Status de cada lançamento; "vencido" considera due_date < hoje && !paid_at
function recordStatus(r) {
    if (r?.paid_at) return 'pago';
    if (r?.due_date) {
        const ms = new Date(r.due_date + 'T23:59:59').getTime();
        if (!Number.isNaN(ms) && ms < Date.now()) return 'vencido';
    }
    return 'pendente';
}
const RECORD_STATUS_LABEL = { pago: 'Pago', pendente: 'Pendente', vencido: 'Vencido' };
const recordsOrdenados = computed(() => {
    return [...financialRecords.value].sort((a, b) => {
        // due_date primeiro (DESC), depois created_at
        const da = a.due_date || a.created_at;
        const db = b.due_date || b.created_at;
        return new Date(db) - new Date(da);
    });
});
function fmtPaymentMethod(v) {
    const s = String(v || '').toLowerCase();
    if (!s) return '';
    if (s === 'pix') return 'PIX';
    if (s === 'cartao' || s === 'cartão' || s === 'credit_card') return 'Cartão';
    if (s === 'dinheiro' || s === 'cash') return 'Dinheiro';
    if (s === 'boleto') return 'Boleto';
    if (s === 'transferencia' || s === 'transfer') return 'Transferência';
    return v;
}

// ── DASHBOARD: aba Agenda ─────────────────────────────────────
// Filtro + agrupamento cronológico das sessões (DESC).
const agendaFilter = ref('all'); // all | future | past | realiz | falt | cancel
const agendaFilters = [
    { value: 'all',     label: 'Todas',      icon: 'pi pi-list' },
    { value: 'future',  label: 'Próximas',   icon: 'pi pi-calendar-plus' },
    { value: 'past',    label: 'Passadas',   icon: 'pi pi-history' },
    { value: 'realiz',  label: 'Realizadas', icon: 'pi pi-check-circle' },
    { value: 'falt',    label: 'Faltas',     icon: 'pi pi-user-minus' },
    { value: 'cancel',  label: 'Canceladas', icon: 'pi pi-ban' }
];
const agendaSessoesFiltradas = computed(() => {
    const list = sessions.value || [];
    const now = Date.now();
    switch (agendaFilter.value) {
        case 'future': return list.filter((s) => s.inicio_em && new Date(s.inicio_em).getTime() > now);
        case 'past':   return list.filter((s) => s.inicio_em && new Date(s.inicio_em).getTime() <= now);
        case 'realiz': return list.filter((s) => /realiz|present/i.test(String(s.status || '')));
        case 'falt':   return list.filter((s) => /falt/i.test(String(s.status || '')));
        case 'cancel': return list.filter((s) => /cancel|remarca/i.test(String(s.status || '')));
        default:       return list;
    }
});
// Agrupa por "MÊS de YYYY" mantendo ordem DESC (mais recente primeiro)
const agendaAgrupadas = computed(() => {
    const groups = [];
    let key = null;
    for (const ev of agendaSessoesFiltradas.value) {
        if (!ev.inicio_em) continue;
        const d = new Date(ev.inicio_em);
        const k = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
        if (k !== key) {
            key = k;
            groups.push({
                key: k,
                label: d.toLocaleDateString('pt-BR', { month: 'long', year: 'numeric' })
                    .replace(/(^|\s)\S/g, (l) => l.toUpperCase()),
                items: []
            });
        }
        groups[groups.length - 1].items.push(ev);
    }
    return groups;
});

// Atualiza status de uma sessão específica e recarrega lista.
async function updateSessionStatus(ev, novoStatus, msg) {
    if (!ev?.id || sessionBusy.value) return;
    sessionBusy.value = true;
    try {
        const { error } = await supabase
            .from('agenda_eventos')
            .update({ status: novoStatus })
            .eq('id', ev.id);
        if (error) throw error;
        toast.add({ severity: 'success', summary: msg, life: 2200 });
        const pid = patientData.value?.id;
        if (pid) await loadSessions(pid);
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha ao atualizar', detail: e?.message || 'Erro inesperado', life: 4000 });
    } finally {
        sessionBusy.value = false;
    }
}

// ── DASHBOARD: aba Conversas ─────────────────────────────────
// recentMessages traz até 200 mensagens — agregamos in/out, primeiro
// e último contato. Canais únicos pra mostrar quais foram usados.
const convTotal     = computed(() => recentMessages.value.length);
const convInbound   = computed(() => recentMessages.value.filter((m) => m.direction === 'inbound').length);
const convOutbound  = computed(() => recentMessages.value.filter((m) => m.direction === 'outbound').length);
const convLast      = computed(() => recentMessages.value[0] || null);
const convFirst     = computed(() => recentMessages.value[recentMessages.value.length - 1] || null);
const convChannels  = computed(() => {
    const set = new Set();
    for (const m of recentMessages.value) if (m.channel) set.add(m.channel);
    return [...set];
});
function chConvLabel(c) {
    const k = String(c || '').toLowerCase();
    if (k === 'whatsapp') return 'WhatsApp';
    if (k === 'sms') return 'SMS';
    if (k === 'email') return 'E-mail';
    return c || '';
}

// Adicionar telefone WhatsApp ao paciente quando não tem cadastrado.
// Sem isso, conversationDrawerStore.openForPatient falha silencioso e o
// histórico de mensagens fica vazio. Form simples só com dígitos (10 ou
// 11 — DDD + número), sem máscara pra não depender de InputMask aqui.
const phoneDlg = ref(false);
const phoneInput = ref('');
const phoneSaving = ref(false);
function openAddPhone() {
    phoneInput.value = String(patientData.value?.telefone || '').replace(/\D/g, '');
    phoneDlg.value = true;
}
// Soft-check: existe outro paciente com esse mesmo número? Considera
// tanto patients.telefone (legado) quanto contact_phones (novo).
// Retorna o paciente conflitante ou null. Errors fail-open — não
// bloqueamos save por falha no check.
async function findPhoneOwner(digits, excludeId) {
    try {
        const { data: byPat } = await supabase
            .from('patients')
            .select('id, nome_completo')
            .eq('telefone', digits)
            .neq('id', excludeId)
            .limit(1)
            .maybeSingle();
        if (byPat?.id) return byPat;

        const { data: byCp } = await supabase
            .from('contact_phones')
            .select('entity_id')
            .eq('entity_type', 'patient')
            .eq('number', digits)
            .neq('entity_id', excludeId)
            .limit(1)
            .maybeSingle();
        if (byCp?.entity_id) {
            const { data: p } = await supabase
                .from('patients')
                .select('id, nome_completo')
                .eq('id', byCp.entity_id)
                .maybeSingle();
            return p || null;
        }
    } catch { /* fail open */ }
    return null;
}

async function savePhone() {
    const id = patientData.value?.id;
    const digits = String(phoneInput.value || '').replace(/\D/g, '');
    if (!id) return;
    if (digits.length < 10 || digits.length > 11) {
        toast.add({ severity: 'warn', summary: 'Telefone inválido', detail: 'Use DDD + número (10 ou 11 dígitos).', life: 3500 });
        return;
    }
    const tenantId = tenantStore.activeTenantId;
    if (!tenantId) {
        toast.add({ severity: 'error', summary: 'Sem tenant ativo', life: 3500 });
        return;
    }
    // Soft-check de duplicidade — números compartilhados são legítimos
    // (mãe agendando pra filho, dependentes), mas avisar evita typo
    // virar bug de roteamento de mensagens recebidas via webhook.
    phoneSaving.value = true;
    const owner = await findPhoneOwner(digits, id);
    phoneSaving.value = false;
    if (owner) {
        confirm.require({
            header: 'Telefone já cadastrado',
            message: `O telefone ${fmtPhoneMobile(digits)} já está cadastrado em "${owner.nome_completo}". Salvar mesmo assim?`,
            icon: 'pi pi-exclamation-triangle',
            acceptLabel: 'Salvar mesmo assim',
            rejectLabel: 'Cancelar',
            acceptClass: 'p-button-warning',
            accept: () => _persistPhone(id, digits, tenantId),
            reject: () => {}
        });
        return;
    }
    await _persistPhone(id, digits, tenantId);
}

async function _persistPhone(id, digits, tenantId) {
    phoneSaving.value = true;
    try {
        // Caminho canônico: gravar em contact_phones. O trigger
        // sync_legacy_phone_fields cuida de atualizar patients.telefone
        // automaticamente — fazer UPDATE manual aqui criaria estado
        // inconsistente (campo legado preenchido sem contact_phone
        // correspondente, foi exatamente o bug que afetou pacientes
        // salvos antes desse refator).

        // 1) Garante o contact_type "whatsapp" (system, slug fixo via
        //    seed_014_global_data).
        const { data: ctype, error: errType } = await supabase
            .from('contact_types')
            .select('id')
            .eq('slug', 'whatsapp')
            .order('is_system', { ascending: false })
            .limit(1)
            .maybeSingle();
        if (errType) throw errType;
        if (!ctype?.id) throw new Error('Tipo de contato "WhatsApp" não encontrado.');

        // 2) Insere ou atualiza em contact_phones (entity_type=patient).
        const { data: existing } = await supabase
            .from('contact_phones')
            .select('id, is_primary')
            .eq('entity_type', 'patient')
            .eq('entity_id', id)
            .eq('contact_type_id', ctype.id)
            .limit(1)
            .maybeSingle();

        if (existing?.id) {
            const { error: errUpd } = await supabase
                .from('contact_phones')
                .update({ number: digits, whatsapp_linked_at: new Date().toISOString() })
                .eq('id', existing.id);
            if (errUpd) throw errUpd;
        } else {
            const { count } = await supabase
                .from('contact_phones')
                .select('id', { count: 'exact', head: true })
                .eq('entity_type', 'patient')
                .eq('entity_id', id);
            const isPrimary = (count || 0) === 0;
            const { error: errIns } = await supabase
                .from('contact_phones')
                .insert({
                    tenant_id: tenantId,
                    entity_type: 'patient',
                    entity_id: id,
                    contact_type_id: ctype.id,
                    number: digits,
                    is_primary: isPrimary,
                    whatsapp_linked_at: new Date().toISOString(),
                    position: 10
                });
            if (errIns) throw errIns;
        }

        // 3) Sincroniza estado local pra UI atualizar (a trigger já
        //    gravou no DB, mas patientFull aqui é uma cópia que precisa
        //    refletir a mudança).
        patientFull.value = { ...(patientFull.value || {}), telefone: digits };
        toast.add({ severity: 'success', summary: 'Telefone salvo', detail: 'Cadastrado também como WhatsApp.', life: 2400 });
        phoneDlg.value = false;

        // 5) Retoma o fluxo do drawer se foi acionado por uma tentativa
        //    de abertura sem telefone.
        if (_resumeDrawerAfterPhone.value) {
            _resumeDrawerAfterPhone.value = false;
            await conversationDrawerStore.openForPatient(String(id));
        }
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha ao salvar', detail: e?.message || 'Erro inesperado', life: 3500 });
    } finally {
        phoneSaving.value = false;
    }
}

// ── DASHBOARD: aba Documentos ─────────────────────────────────
// Labels amigáveis pra os tipos do schema (espelha TIPOS_DOCUMENTO de
// useDocuments.js — manter sincronizado se forem incluídos novos).
const DOC_TYPE_LABEL = {
    laudo: 'Laudo',
    receita: 'Receita',
    exame: 'Exame',
    termo_assinado: 'Termo assinado',
    relatorio: 'Relatório',
    declaracao: 'Declaração',
    outro: 'Outro'
};
const docTotal     = computed(() => documentsList.value.length);
const docTopType   = computed(() => {
    const por = {};
    for (const d of documentsList.value) {
        const t = d.tipo_documento || 'outro';
        por[t] = (por[t] || 0) + 1;
    }
    const entries = Object.entries(por).sort((a, b) => b[1] - a[1]);
    if (!entries.length) return null;
    const [tipo, count] = entries[0];
    return { tipo, count, label: DOC_TYPE_LABEL[tipo] || tipo };
});
const docLast      = computed(() => documentsList.value[0] || null);
const docPendentes = computed(() =>
    documentsList.value.filter((d) => d.status_revisao === 'pendente').length
);
function fmtSize(bytes) {
    const b = Number(bytes) || 0;
    if (b < 1024) return `${b} B`;
    if (b < 1024 * 1024) return `${(b / 1024).toFixed(1)} KB`;
    if (b < 1024 * 1024 * 1024) return `${(b / (1024 * 1024)).toFixed(1)} MB`;
    return `${(b / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}
const docSizeTotal = computed(() => {
    const total = documentsList.value.reduce((acc, d) => acc + (Number(d.tamanho_bytes) || 0), 0);
    return fmtSize(total);
});

// Para renderizar hora HH:MM curta nos cards
function fmtHourShort(iso) {
    if (!iso) return '';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return '';
    return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
}
function fmtDayShort(iso) {
    if (!iso) return '';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return '';
    return d.toLocaleDateString('pt-BR', { weekday: 'short' }).replace('.', '');
}

// ── FORMATTERS ─────────────────────────────────────────────────
function nameInitials(name) {
    if (!name) return '?';
    return String(name).split(' ').filter(Boolean).slice(0, 2)
        .map((w) => w[0].toUpperCase()).join('');
}
const avatarInitials = computed(() => nameInitials(nomeCompleto.value));

function onlyDigits(v) { return String(v ?? '').replace(/\D/g, ''); }

function fmtCPF(v) {
    const d = onlyDigits(v);
    if (!d) return '—';
    if (d.length !== 11) return d;
    return `${d.slice(0,3)}.${d.slice(3,6)}.${d.slice(6,9)}-${d.slice(9,11)}`;
}

function fmtRG(v) {
    const s = String(v ?? '').toUpperCase().replace(/[^0-9X]/g, '');
    if (!s) return '—';
    if (s.length === 9) return `${s.slice(0,2)}.${s.slice(2,5)}.${s.slice(5,8)}-${s.slice(8)}`;
    if (s.length === 8) return `${s.slice(0,2)}.${s.slice(2,5)}.${s.slice(5,8)}`;
    return s;
}

function parseDateLoose(v) {
    if (!v) return null;
    const s = String(v).trim();
    if (/^\d{4}-\d{2}-\d{2}/.test(s)) {
        const d = new Date(s.slice(0, 10));
        return isNaN(d) ? null : d;
    }
    let m = s.match(/^(\d{2})[/-](\d{2})[/-](\d{4})$/);
    if (m) {
        const d = new Date(Number(m[3]), Number(m[2]) - 1, Number(m[1]));
        return isNaN(d) ? null : d;
    }
    const d = new Date(s);
    return isNaN(d) ? null : d;
}

function fmtDateBR(v) {
    const d = parseDateLoose(v);
    if (!d) return v ? dash(v) : '—';
    return `${String(d.getDate()).padStart(2,'0')}/${String(d.getMonth()+1).padStart(2,'0')}/${d.getFullYear()}`;
}

function calcAge(v) {
    const d = parseDateLoose(v);
    if (!d) return null;
    const now = new Date();
    let age = now.getFullYear() - d.getFullYear();
    const m = now.getMonth() - d.getMonth();
    if (m < 0 || (m === 0 && now.getDate() < d.getDate())) age--;
    return age;
}

const ageLabel = computed(() => {
    const age = calcAge(birthValue.value);
    return age == null ? '—' : `${age} anos`;
});

function fmtPhoneMobile(v) {
    const d = onlyDigits(v);
    if (!d) return '—';
    if (d.length === 11) return `(${d.slice(0,2)}) ${d.slice(2,7)}-${d.slice(7,11)}`;
    if (d.length === 10) return `(${d.slice(0,2)}) ${d.slice(2,6)}-${d.slice(6,10)}`;
    return d;
}

function fmtGender(v) {
    const s = String(v ?? '').trim();
    if (!s) return '—';
    const x = s.toLowerCase();
    if (['m','masc','masculino','male','man','homem'].includes(x)) return 'Masculino';
    if (['f','fem','feminino','female','woman','mulher'].includes(x)) return 'Feminino';
    if (['nb','nao-binario','não-binário','nonbinary','non-binary'].includes(x)) return 'Não-binário';
    if (['outro','other'].includes(x)) return 'Outro';
    return s;
}

function fmtMarital(v) {
    const s = String(v ?? '').trim();
    if (!s) return '—';
    const x = s.toLowerCase();
    if (['solteiro','solteira','single'].includes(x)) return 'Solteiro(a)';
    if (['casado','casada','married'].includes(x)) return 'Casado(a)';
    if (['divorciado','divorciada','divorced'].includes(x)) return 'Divorciado(a)';
    if (['viuvo','viúva','viuvo(a)','widowed'].includes(x)) return 'Viúvo(a)';
    if (['uniao estavel','união estável','civil union'].includes(x)) return 'União estável';
    return s;
}

function fmtCurrency(v) {
    if (!v && v !== 0) return '—';
    return `R$ ${Number(v).toLocaleString('pt-BR')}`;
}

function fmtDateTimeBR(iso) {
    if (!iso) return '—';
    const d = new Date(iso);
    if (isNaN(d)) return iso;
    const dd = String(d.getDate()).padStart(2,'0');
    const mm = String(d.getMonth()+1).padStart(2,'0');
    const hh = String(d.getHours()).padStart(2,'0');
    const mi = String(d.getMinutes()).padStart(2,'0');
    return `${dd}/${mm}/${d.getFullYear()} ${hh}:${mi}`;
}

function sessionDuration(inicio, fim) {
    if (!inicio || !fim) return null;
    const diff = new Date(fim) - new Date(inicio);
    if (diff <= 0) return null;
    const min = Math.round(diff / 60000);
    if (min < 60) return `${min} min`;
    const h = Math.floor(min / 60);
    const m = min % 60;
    return m ? `${h}h ${m}min` : `${h}h`;
}

// Data relativa pt-BR — usada nos cards do dashboard.
// "agora", "há 5 min", "há 2 h", "ontem", "há 3 dias", "em 2 dias", "em 3 sem".
function fmtRelative(iso) {
    if (!iso) return '—';
    const target = new Date(iso).getTime();
    if (Number.isNaN(target)) return '—';
    const diff = target - Date.now(); // negativo = passado
    const abs = Math.abs(diff);
    const past = diff < 0;
    const min = Math.round(abs / 60000);
    if (min < 1) return 'agora';
    if (min < 60) return past ? `há ${min} min` : `em ${min} min`;
    const h = Math.round(min / 60);
    if (h < 24) return past ? `há ${h} h` : `em ${h} h`;
    const d = Math.round(h / 24);
    if (d === 1) return past ? 'ontem' : 'amanhã';
    if (d < 7) return past ? `há ${d} dias` : `em ${d} dias`;
    const w = Math.round(d / 7);
    if (w < 5) return past ? `há ${w} sem` : `em ${w} sem`;
    return fmtDateBR(iso);
}

// ── TAG COLORS ─────────────────────────────────────────────────
function normalizeHexColor(c) {
    const s = String(c ?? '').trim();
    if (!s) return '';
    if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(s)) return s;
    if (/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(s)) return `#${s}`;
    return s;
}
function hexToRgb(hex) {
    const h = String(hex || '').replace('#','').trim();
    if (!/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(h)) return null;
    const full = h.length === 3 ? h.split('').map(ch => ch+ch).join('') : h;
    const r = parseInt(full.slice(0,2), 16);
    const g = parseInt(full.slice(2,4), 16);
    const b = parseInt(full.slice(4,6), 16);
    if ([r,g,b].some(n => isNaN(n))) return null;
    return { r, g, b };
}
function relativeLuminance({ r, g, b }) {
    const srgb = [r,g,b].map(v => v/255).map(c => c <= 0.03928 ? c/12.92 : Math.pow((c+0.055)/1.055, 2.4));
    return 0.2126*srgb[0] + 0.7152*srgb[1] + 0.0722*srgb[2];
}
function bestTextColor(bg) {
    const rgb = hexToRgb(normalizeHexColor(bg));
    if (!rgb) return '#0f172a';
    return relativeLuminance(rgb) < 0.45 ? '#ffffff' : '#0f172a';
}
function tagStyle(t) {
    const bg = normalizeHexColor(t?.color || t?.cor);
    if (!bg) return {};
    return { background: bg, color: bestTextColor(bg), borderColor: 'transparent' };
}

// ── SESSION STATUS ─────────────────────────────────────────────
const STATUS_LABEL = {
    agendado: 'Agendado', realizado: 'Realizado', faltou: 'Faltou',
    cancelado: 'Cancelado', remarcado: 'Remarcado', bloqueado: 'Bloqueado',
};
const STATUS_SEVERITY = {
    agendado: 'info', realizado: 'success', faltou: 'danger',
    cancelado: 'warn', remarcado: 'secondary', bloqueado: 'secondary',
};

// ── SUPABASE ───────────────────────────────────────────────────
async function loadSessions(patientId) {
    sessionsLoading.value = true;
    sessions.value = [];
    try {
        const { data, error } = await supabase
            .from('agenda_eventos')
            .select('id, inicio_em, fim_em, status, modalidade, tipo, titulo, titulo_custom, observacoes')
            .eq('patient_id', patientId)
            .order('inicio_em', { ascending: false })
            .limit(100);
        if (error) throw error;
        sessions.value = data || [];
    } catch { sessions.value = []; }
    finally { sessionsLoading.value = false; }
}

// Mensagens (in+out) — alimenta card "Últimas mensagens" do Visão Geral
// (4 primeiras) e os KPIs da aba Conversas (count agregado). Limite 200
// é suficiente pra estatísticas sem carregar conversa inteira (essa fica
// no PatientConversationsTab embedded).
async function loadRecentMessages(patientId) {
    messagesLoading.value = true;
    recentMessages.value = [];
    try {
        const { data, error } = await supabase
            .from('conversation_messages')
            .select('id, body, direction, created_at, channel, kanban_status')
            .eq('patient_id', patientId)
            .order('created_at', { ascending: false })
            .limit(200);
        if (error) throw error;
        recentMessages.value = data || [];
    } catch { recentMessages.value = []; }
    finally { messagesLoading.value = false; }
}

// Documentos do paciente — só os campos pra KPIs (count, tipo, última).
// Filtra deletados (deleted_at IS NULL) pra coerência com listagem padrão.
async function loadDocumentsList(patientId) {
    documentsLoading.value = true;
    documentsList.value = [];
    try {
        const { data, error } = await supabase
            .from('documents')
            .select('id, tipo_documento, created_at, status_revisao, tamanho_bytes')
            .eq('patient_id', patientId)
            .is('deleted_at', null)
            .order('created_at', { ascending: false })
            .limit(200);
        if (error) throw error;
        documentsList.value = data || [];
    } catch { documentsList.value = []; }
    finally { documentsLoading.value = false; }
}

// Lançamentos financeiros — alimenta o card de pagamento na Visão Geral
// e a aba Financeiro completa. Schema: paid_at NULL = pendente, preenchido
// = pago. "Vencido" = paid_at IS NULL AND due_date < hoje.
async function loadFinancialRecent(patientId) {
    financialLoading.value = true;
    financialRecords.value = [];
    try {
        const { data, error } = await supabase
            .from('financial_records')
            .select('id, type, amount, due_date, paid_at, description, payment_method, category, created_at')
            .eq('patient_id', patientId)
            .eq('type', 'receita')
            .order('created_at', { ascending: false })
            .limit(100);
        if (error) throw error;
        financialRecords.value = data || [];
    } catch { financialRecords.value = []; }
    finally { financialLoading.value = false; }
}

async function getPatientById(id) {
    const { data, error } = await supabase.from('patients').select('*').eq('id', id).maybeSingle();
    if (error) throw error;
    return data;
}

async function getPatientRelations(id) {
    const { data: g, error: ge } = await supabase.from('patient_group_patient').select('patient_group_id').eq('patient_id', id);
    if (ge) throw ge;
    const { data: t, error: te } = await supabase.from('patient_patient_tag').select('tag_id').eq('patient_id', id);
    if (te) throw te;
    return {
        groupIds: (g || []).map(x => x.patient_group_id).filter(Boolean),
        tagIds:   (t || []).map(x => x.tag_id).filter(Boolean),
    };
}

async function getGroupsByIds(ids) {
    if (!ids?.length) return [];
    const { data, error } = await supabase.from('patient_groups').select('id, nome').in('id', ids).order('nome', { ascending: true });
    if (error) throw error;
    return (data || []).map(g => ({ id: g.id, name: g.nome }));
}

async function getTagsByIds(ids) {
    if (!ids?.length) return [];
    const { data, error } = await supabase.from('patient_tags').select('id, nome, cor').in('id', ids).order('nome', { ascending: true });
    if (error) throw error;
    return (data || []).map(t => ({ id: t.id, name: t.nome, color: t.cor }));
}

async function loadDetail(id) {
    loadError.value = '';
    loading.value   = true;
    patientFull.value = null;
    groups.value = [];
    tags.value   = [];
    recentMessages.value = [];
    financialRecords.value = [];
    documentsList.value = [];
    try {
        const [p, rel] = await Promise.all([getPatientById(id), getPatientRelations(id)]);
        if (!p) throw new Error('Paciente não retornou dados (RLS bloqueando ou ID não existe no banco).');
        patientFull.value = p;
        // Registra no "recentemente acessados" (localStorage)
        try { await registerPatientVisit(p); } catch { /* ignore */ }
        const [g, t] = await Promise.all([
            getGroupsByIds(rel.groupIds || []),
            getTagsByIds(rel.tagIds || []),
            loadSessions(id),
            loadRecentMessages(id),
            loadFinancialRecent(id),
            loadDocumentsList(id),
        ]);
        groups.value = g;
        tags.value   = t;
    } catch (e) {
        loadError.value = e?.message || 'Falha ao buscar dados no Supabase.';
        toast.add({ severity: 'error', summary: 'Erro ao carregar', detail: loadError.value, life: 4500 });
    } finally {
        loading.value = false;
    }
}

watch(
    [() => props.modelValue, () => props.patient?.id],
    async ([open, id], [prevOpen, prevId]) => {
        if (!open || !id) return;
        if (open === prevOpen && id === prevId) return;
        activeTab.value = 0;
        activeAccValues.value = ['0'];
        await loadDetail(id);
    },
    { immediate: true }
);

// ── AÇÕES ──────────────────────────────────────────────────────
function close() {
    model.value = false;
    emit('close');
}
function editPatient() {
    const id = patientData.value?.id;
    if (!id) return;
    close();
    emit('edit', String(id));
}

// ── AÇÕES rápidas (sidebar) ───────────────────────────────────
// Status sessão: aplicado à proximaSessao (única que faz sentido aqui;
// sem proximaSessao os botões ficam disabled). Após update, recarrega
// sessions pra refletir contagens do dashboard.
const sessionBusy = ref(false);
async function setProximaSessaoStatus(novoStatus, msgSucesso) {
    const ev = proximaSessao.value;
    if (!ev?.id || sessionBusy.value) return;
    sessionBusy.value = true;
    try {
        const { error } = await supabase
            .from('agenda_eventos')
            .update({ status: novoStatus })
            .eq('id', ev.id);
        if (error) throw error;
        toast.add({ severity: 'success', summary: msgSucesso, life: 2200 });
        const pid = patientData.value?.id;
        if (pid) await loadSessions(pid);
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha ao atualizar', detail: e?.message || 'Erro inesperado', life: 4000 });
    } finally {
        sessionBusy.value = false;
    }
}
// Solicita ao parent abrir o dialog/rota de novo lançamento financeiro
// pra esse paciente. Emit é genérico — parent decide o destino.
function onAddFinancial() {
    const id = patientData.value?.id;
    emit('add-financial', { patientId: id, patientName: nomeCompleto.value });
}

function onMarcarRealizada() { setProximaSessaoStatus('realizado', 'Sessão marcada como realizada'); }
function onMarcarFalta()     { setProximaSessaoStatus('faltou',    'Marcada como falta'); }
function onMarcarReagendar() { setProximaSessaoStatus('remarcar',  'Marcada para remarcar'); }
function onMarcarCancelar()  { setProximaSessaoStatus('cancelado', 'Sessão cancelada'); }

// Abre conversa do paciente no drawer global. Se o paciente não tem
// telefone cadastrado, abre o phoneDlg pra capturar — após salvar,
// continua o fluxo automaticamente via flag `_resumeDrawerAfterPhone`.
async function abrirWhatsappPaciente() {
    const pid = patientData.value?.id;
    if (!pid) return;
    if (!telefone.value) {
        _resumeDrawerAfterPhone.value = true;
        openAddPhone();
        return;
    }
    await conversationDrawerStore.openForPatient(String(pid));
    if (!conversationDrawerStore.isOpen) {
        const detail = conversationDrawerStore.error?.message || 'Não foi possível abrir a conversa.';
        toast.add({ severity: 'warn', summary: 'WhatsApp', detail, life: 3500 });
        conversationDrawerStore.error = null;
    }
}
const _resumeDrawerAfterPhone = ref(false);

// Vai pra aba "Perfil" e abre o accordion de Sessões (item value="5").
function abrirSessoesPaciente() {
    activeTab.value = 1;
    activeAccValues.value = ['5'];
    nextTick(() => {
        const el = panelHeaderRefs.value?.[5]?.$el ?? panelHeaderRefs.value?.[5];
        if (el?.scrollIntoView) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
    });
}

// Slug do status da próxima sessão pra destacar botão ativo
const proximaStatusSlug = computed(() => {
    const s = String(proximaSessao.value?.status || '').toLowerCase();
    if (s === 'realizada') return 'realizado';
    if (s === 'cancelada') return 'cancelado';
    return s;
});
const temProximaSessao = computed(() => !!proximaSessao.value?.id);

async function copyResumo() {
    const txt = `Paciente: ${dash(nomeCompleto.value)}
Idade: ${ageLabel.value}
${groupCountLabel.value}: ${groupLabel.value}
Telefone: ${fmtPhoneMobile(telefone.value)}
Email: ${dash(emailPrincipal.value)}
CPF: ${fmtCPF(patientData.value?.cpf)}
RG: ${fmtRG(patientData.value?.rg)}
Nascimento: ${fmtDateBR(birthValue.value)}
Tags: ${(tags.value || []).map(t => t.name).filter(Boolean).join(', ') || '—'}`;
    try {
        await navigator.clipboard.writeText(txt);
        toast.add({ severity: 'success', summary: 'Copiado', detail: 'Resumo copiado para a área de transferência.', life: 2200 });
    } catch {
        toast.add({ severity: 'error', summary: 'Falha', detail: 'Não foi possível copiar.', life: 3000 });
    }
}
</script>

<template>
    <Dialog
        v-model:visible="model"
        modal
        :draggable="false"
        maximizable
        :style="{ width: '96vw', maxWidth: '1400px' }"
        :contentStyle="{ padding: 0 }"
        pt:mask:class="backdrop-blur-sm"
        pt:title:class="text-[0.95rem] font-bold text-[var(--text-color)] truncate"
        @hide="close"
    >
        <!-- ── HEADER DO DIALOG ────────────────────────────────── -->
        <!-- Compacto: max 2 linhas, altura padrão do Dialog. Sem botões
             extras no header — ações ficam dentro do Dashboard.       -->
        <template #header>
            <div class="pp-head">
                <div v-if="avatarUrl" class="pp-head__avatar">
                    <img :src="avatarUrl" alt="" />
                </div>
                <div v-else class="pp-head__avatar pp-head__avatar--initials">
                    <span>{{ avatarInitials }}</span>
                </div>
                <div class="pp-head__id">
                    <div class="pp-head__line1">
                        <span class="pp-head__name">{{ dash(nomeCompleto) }}</span>
                        <span v-if="riscoElevado" class="pp-head__pill pp-head__pill--danger">
                            <i class="pi pi-exclamation-circle" /> risco
                        </span>
                    </div>
                    <div class="pp-head__line2">
                        <span>{{ ageLabel }}</span>
                        <span v-if="patientData.pronomes" class="pp-head__sep">·</span>
                        <span v-if="patientData.pronomes">{{ patientData.pronomes }}</span>
                        <span v-if="convenio" class="pp-head__sep">·</span>
                        <span v-if="convenio" class="pp-head__chip">{{ convenio }}</span>
                    </div>
                </div>
            </div>
        </template>

        <!-- ══ CONTEÚDO ════════════════════════════════════════════ -->
        <div class="bg-[var(--surface-ground)] min-h-[60vh]">

            <!-- Loading -->
            <div v-if="loading"
                 class="flex items-center justify-center py-20 gap-2 text-sm text-[var(--text-color-secondary)]">
                <i class="pi pi-spin pi-spinner" /> Carregando…
            </div>

            <!-- Erro -->
            <div v-else-if="loadError" class="p-4">
                <div class="flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 px-4 py-3">
                    <i class="pi pi-exclamation-circle text-red-500 mt-0.5 shrink-0" />
                    <div>
                        <p class="text-sm font-semibold text-red-700">Falha ao carregar</p>
                        <p class="text-xs text-red-500 mt-0.5">{{ loadError }}</p>
                    </div>
                </div>
            </div>

            <div v-else class="grid grid-cols-1 xl:grid-cols-[240px_1fr] gap-3 p-3 md:p-4">

                <!-- ══ SIDEBAR ══════════════════════════════════════ -->
                <aside class="rounded-xl border border-[var(--surface-border)]
                              bg-[var(--surface-card)] p-4 shadow-sm
                              xl:sticky xl:top-2 xl:self-start space-y-0">

                    <!-- Banner risco elevado (sidebar) -->
                    <div v-if="riscoElevado"
                         class="flex items-start gap-2 rounded-lg border border-red-200
                                bg-red-50 px-3 py-2 mb-4">
                        <i class="pi pi-exclamation-circle text-red-500 text-sm mt-0.5 shrink-0" />
                        <p class="text-[0.73rem] font-semibold text-red-700 leading-snug">
                            Risco elevado sinalizado
                        </p>
                    </div>

                    <!-- Avatar + nome + badges -->
                    <div class="flex items-center gap-3 pb-4 mb-4
                                border-b border-[var(--surface-border)]
                                xl:flex-col xl:items-center xl:gap-2 xl:text-center">
                        <!-- Avatar -->
                        <div class="shrink-0 w-16 h-16 xl:w-20 xl:h-20 rounded-full overflow-hidden">
                            <img v-if="avatarUrl" :src="avatarUrl" alt="avatar"
                                 class="w-full h-full object-cover" />
                            <div v-else class="w-full h-full bg-indigo-100 flex items-center justify-center">
                                <span class="text-xl font-bold text-indigo-700 tracking-tight">
                                    {{ avatarInitials }}
                                </span>
                            </div>
                        </div>
                        <!-- Info -->
                        <div class="flex-1 min-w-0 xl:text-center">
                            <div class="text-sm font-bold text-[var(--text-color)] truncate">
                                {{ dash(nomeCompleto) }}
                            </div>
                            <div class="text-xs text-[var(--text-color-secondary)] mt-0.5">
                                {{ ageLabel }}
                                <template v-if="patientData.pronomes"> · {{ patientData.pronomes }}</template>
                            </div>
                            <div v-if="naturalidade || estado"
                               class="text-xs text-[var(--text-color-secondary)]">
                                {{ dash(naturalidade) }}<template v-if="estado">, {{ estado }}</template>
                            </div>
                            <!-- Status + Convênio + Scope -->
                            <div class="flex flex-wrap gap-1 mt-2 xl:justify-center">
                                <Tag v-if="statusPaciente" :value="statusPaciente" severity="success" class="!text-[0.68rem]" />
                                <Tag v-if="convenio"       :value="convenio"       severity="info"    class="!text-[0.68rem]" />
                                <Tag v-if="patientScope"   :value="patientScope"   severity="secondary" class="!text-[0.68rem]" />
                            </div>
                            <!-- Tags coloridas -->
                            <div v-if="tags?.length" class="flex flex-wrap gap-1 mt-1.5 xl:justify-center">
                                <span v-for="t in tags" :key="t.id"
                                      class="inline-flex items-center px-2 py-0.5 rounded-full text-[0.68rem] font-medium"
                                      :style="tagStyle(t)">
                                    {{ t.name }}
                                </span>
                            </div>
                        </div>
                    </div>

                    <!-- Métricas 2×2 -->
                    <div v-if="totalSessoes != null || comparecimentoPct != null || ltvTotal != null || diasUltimaSessao != null"
                         class="grid grid-cols-2 gap-3 text-center pb-4 mb-4 border-b border-[var(--surface-border)]">
                        <div v-if="totalSessoes != null">
                            <p class="text-xl font-bold text-[var(--text-color)]">{{ totalSessoes }}</p>
                            <p class="text-[0.65rem] text-[var(--text-color-secondary)] mt-0.5">Sessões</p>
                        </div>
                        <div v-if="comparecimentoPct != null">
                            <p class="text-xl font-bold text-emerald-600">{{ comparecimentoPct }}%</p>
                            <p class="text-[0.65rem] text-[var(--text-color-secondary)] mt-0.5">Comparec.</p>
                        </div>
                        <div v-if="ltvTotal != null">
                            <p class="text-base font-bold text-[var(--text-color)]">{{ fmtCurrency(ltvTotal) }}</p>
                            <p class="text-[0.65rem] text-[var(--text-color-secondary)] mt-0.5">LTV total</p>
                        </div>
                        <div v-if="diasUltimaSessao != null">
                            <p class="text-xl font-bold text-amber-500">{{ diasUltimaSessao }}d</p>
                            <p class="text-[0.65rem] text-[var(--text-color-secondary)] mt-0.5">Últ. sessão</p>
                        </div>
                    </div>

                    <!-- Ações rápidas — espelham o MelissaEventoPanel:
                         status da próxima sessão (Realizada/Falta/Reagendar/
                         Cancelar) + atalhos (Sessões/Conversar/Editar). -->
                    <div class="pp-actions">
                        <section class="pp-actions__section">
                            <div class="pp-actions__label">
                                Marcar próxima sessão como:
                                <span v-if="!temProximaSessao" class="pp-actions__hint">(sem sessão futura)</span>
                            </div>
                            <div class="pp-actions__group">
                                <button
                                    type="button"
                                    class="pp-act pp-act--ok"
                                    :class="{ 'is-current': proximaStatusSlug === 'realizado' }"
                                    :disabled="!temProximaSessao || sessionBusy"
                                    @click="onMarcarRealizada"
                                >
                                    <i class="pi pi-check-circle" />
                                    <span class="pp-act__label">Realizada</span>
                                </button>
                                <button
                                    type="button"
                                    class="pp-act pp-act--warn"
                                    :class="{ 'is-current': proximaStatusSlug === 'faltou' }"
                                    :disabled="!temProximaSessao || sessionBusy"
                                    @click="onMarcarFalta"
                                >
                                    <i class="pi pi-user-minus" />
                                    <span class="pp-act__label">Falta</span>
                                </button>
                                <button
                                    type="button"
                                    class="pp-act"
                                    :class="{ 'is-current': proximaStatusSlug === 'remarcar' || proximaStatusSlug === 'remarcado' }"
                                    :disabled="!temProximaSessao || sessionBusy"
                                    @click="onMarcarReagendar"
                                >
                                    <i class="pi pi-calendar-clock" />
                                    <span class="pp-act__label">Reagendar</span>
                                </button>
                                <button
                                    type="button"
                                    class="pp-act pp-act--danger"
                                    :class="{ 'is-current': proximaStatusSlug === 'cancelado' }"
                                    :disabled="!temProximaSessao || sessionBusy"
                                    @click="onMarcarCancelar"
                                >
                                    <i class="pi pi-ban" />
                                    <span class="pp-act__label">Cancelar</span>
                                </button>
                            </div>
                        </section>

                        <section class="pp-actions__section">
                            <div class="pp-actions__group">
                                <button type="button" class="pp-act" @click="abrirSessoesPaciente">
                                    <i class="pi pi-history" />
                                    <span class="pp-act__label">Sessões</span>
                                </button>
                                <button type="button" class="pp-act" @click="abrirWhatsappPaciente">
                                    <i class="pi pi-whatsapp" />
                                    <span class="pp-act__label">Conversar</span>
                                </button>
                                <button type="button" class="pp-act" @click="editPatient">
                                    <i class="pi pi-pencil" />
                                    <span class="pp-act__label">Editar</span>
                                </button>
                            </div>
                        </section>
                    </div>

                    <!-- Nav tabs principais -->
                    <div class="flex flex-col gap-0.5">
                        <p class="text-[0.62rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] opacity-50 px-3 mb-1">
                            Navegação
                        </p>
                        <button
                            v-for="(tab, i) in mainTabs" :key="i"
                            type="button"
                            class="flex items-center gap-2.5 rounded-lg px-3 py-2 text-left
                                   text-[0.82rem] border transition-colors duration-100"
                            :class="activeTab === i
                                ? 'bg-indigo-50 border-indigo-200 text-indigo-700 font-semibold'
                                : 'border-transparent text-[var(--text-color)] hover:bg-[var(--surface-ground)] font-medium'"
                            @click="activeTab = i; if(i === 1) activeAccValues = ['0']"
                        >
                            <i :class="tab.icon" class="text-sm opacity-60 shrink-0" />
                            <span>{{ tab.label }}</span>
                        </button>
                    </div>

                    <!-- Submenu Perfil (desktop, aba 0) -->
                    <div v-if="activeTab === 1 && !isCompact"
                         class="mt-3 pt-3 border-t border-[var(--surface-border)] flex flex-col gap-0.5">
                        <p class="text-[0.62rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] opacity-50 px-3 mb-1">
                            Seções do perfil
                        </p>
                        <button
                            v-for="item in profileNavItems" :key="item.value"
                            type="button"
                            class="flex items-center gap-2.5 rounded-lg px-3 py-1.5 text-left
                                   text-[0.79rem] border transition-colors duration-100"
                            :class="activeAccValue === item.value
                                ? 'bg-indigo-50 border-indigo-200 text-indigo-700 font-semibold'
                                : 'border-transparent text-[var(--text-color-secondary)] hover:bg-[var(--surface-ground)] font-medium'"
                            @click="openPanel(Number(item.value))"
                        >
                            <i :class="item.icon" class="text-xs opacity-60 shrink-0" />
                            <span>{{ item.label }}</span>
                        </button>
                    </div>
                </aside>

                <!-- ══ MAIN ═══════════════════════════════════════ -->
                <main class="pp-main min-w-0 rounded-xl border border-[var(--surface-border)]
                             shadow-sm overflow-hidden">

                    <!-- Tab bar -->
                    <div class="flex border-b border-[var(--surface-border)] overflow-x-auto scrollbar-none">
                        <button
                            v-for="(tab, i) in mainTabs" :key="i"
                            type="button"
                            class="flex items-center gap-1.5 px-4 py-3 text-[0.82rem] font-medium
                                   whitespace-nowrap border-b-2 transition-colors duration-150 shrink-0"
                            :class="activeTab === i
                                ? 'border-[var(--primary-color)] text-[var(--primary-color)]'
                                : 'border-transparent text-[var(--text-color-secondary)] hover:text-[var(--text-color)]'"
                            @click="activeTab = i; if(i === 1) activeAccValues = ['0']"
                        >
                            <i :class="tab.icon" class="text-sm" />
                            {{ tab.label }}
                        </button>
                    </div>

                    <!-- ═══════════════════════════════════════════
                         ABA 0: VISÃO GERAL — dashboard resumo
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 0" class="pp-overview">
                        <div class="pp-ov__bg" aria-hidden="true">
                            <span class="pp-ov__spot pp-ov__spot--a" />
                            <span class="pp-ov__spot pp-ov__spot--b" />
                            <span class="pp-ov__line pp-ov__line--1" />
                            <span class="pp-ov__line pp-ov__line--2" />
                        </div>

                        <div class="pp-ov__inner">
                            <!-- ── KPI cards ─────────────────────────── -->
                            <div class="pp-kpis">
                                <!-- 1. Sessões presentes -->
                                <article class="pp-kpi" style="--c:#4ade80; --c-dim:rgba(74,222,128,0.1); --c-border:rgba(74,222,128,0.3)">
                                    <div class="pp-kpi__shine" />
                                    <span class="pp-kpi__num">01</span>
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-check-circle" /></div>
                                        <span class="pp-kpi__tag">Sessões</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ sessoesPresentes }}</div>
                                        <div class="pp-kpi__cap">
                                            de {{ sessions.length }} totais
                                            <span v-if="sessoesFaltadas" class="pp-kpi__cap-warn">· {{ sessoesFaltadas }} {{ sessoesFaltadas === 1 ? 'falta' : 'faltas' }}</span>
                                            <span v-if="sessoesCanceladas" class="pp-kpi__cap-dim">· {{ sessoesCanceladas }} cancel.</span>
                                        </div>
                                    </div>
                                </article>

                                <!-- 2. Pagamento -->
                                <article class="pp-kpi"
                                    :style="statusFinanceiro.emDia === false
                                        ? '--c:#f87171; --c-dim:rgba(248,113,113,0.10); --c-border:rgba(248,113,113,0.30)'
                                        : '--c:var(--primary-color); --c-dim:color-mix(in srgb, var(--primary-color) 10%, transparent); --c-border:color-mix(in srgb, var(--primary-color) 30%, transparent)'">
                                    <div class="pp-kpi__shine" />
                                    <span class="pp-kpi__num">02</span>
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-wallet" /></div>
                                        <span class="pp-kpi__tag">Pagamento</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <template v-if="financialLoading">
                                            <div class="pp-kpi__big pp-kpi__big--small">…</div>
                                            <div class="pp-kpi__cap">Carregando</div>
                                        </template>
                                        <template v-else-if="!financialRecords.length">
                                            <div class="pp-kpi__big pp-kpi__big--small">—</div>
                                            <div class="pp-kpi__cap">Sem lançamentos</div>
                                        </template>
                                        <template v-else>
                                            <div class="pp-kpi__big pp-kpi__big--small">
                                                {{ statusFinanceiro.emDia === false ? 'Em atraso' : 'Em dia' }}
                                            </div>
                                            <div class="pp-kpi__cap">
                                                <template v-if="statusFinanceiro.proxVenc">
                                                    Próx. venc. {{ fmtDateBR(statusFinanceiro.proxVenc.due_date) }}
                                                    <span class="pp-kpi__cap-dim">· {{ fmtRelative(statusFinanceiro.proxVenc.due_date) }}</span>
                                                </template>
                                                <template v-else-if="statusFinanceiro.totalPendente > 0">
                                                    {{ fmtCurrency(statusFinanceiro.totalPendente) }} pendente
                                                </template>
                                                <template v-else>
                                                    Tudo quitado
                                                </template>
                                            </div>
                                        </template>
                                    </div>
                                </article>

                                <!-- 3. Próxima sessão -->
                                <article class="pp-kpi" style="--c:#60a5fa; --c-dim:rgba(96,165,250,0.10); --c-border:rgba(96,165,250,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <span class="pp-kpi__num">03</span>
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-calendar-clock" /></div>
                                        <span class="pp-kpi__tag">Próxima</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <template v-if="proximaSessao">
                                            <div class="pp-kpi__big pp-kpi__big--small">{{ fmtRelative(proximaSessao.inicio_em) }}</div>
                                            <div class="pp-kpi__cap">
                                                {{ fmtDateTimeBR(proximaSessao.inicio_em) }}
                                                <span v-if="proximaSessao.modalidade" class="pp-kpi__cap-dim">· {{ proximaSessao.modalidade === 'online' ? 'Online' : 'Presencial' }}</span>
                                            </div>
                                        </template>
                                        <template v-else>
                                            <div class="pp-kpi__big pp-kpi__big--small">—</div>
                                            <div class="pp-kpi__cap">Sem sessão futura agendada</div>
                                        </template>
                                    </div>
                                </article>

                                <!-- 4. Mensagens -->
                                <article class="pp-kpi" style="--c:#34d399; --c-dim:rgba(52,211,153,0.10); --c-border:rgba(52,211,153,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <span class="pp-kpi__num">04</span>
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-comments" /></div>
                                        <span class="pp-kpi__tag">Mensagens</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <template v-if="messagesLoading">
                                            <div class="pp-kpi__big pp-kpi__big--small">…</div>
                                            <div class="pp-kpi__cap">Carregando</div>
                                        </template>
                                        <template v-else-if="ultimaMensagem">
                                            <div class="pp-kpi__big pp-kpi__big--small">{{ fmtRelative(ultimaMensagem.created_at) }}</div>
                                            <div class="pp-kpi__cap">
                                                Última {{ ultimaMensagem.direction === 'inbound' ? 'recebida' : 'enviada' }}
                                                <span class="pp-kpi__cap-dim">· {{ recentMessages.length }} no histórico</span>
                                            </div>
                                        </template>
                                        <template v-else>
                                            <div class="pp-kpi__big pp-kpi__big--small">—</div>
                                            <div class="pp-kpi__cap">Nenhuma conversa registrada</div>
                                        </template>
                                    </div>
                                </article>
                            </div>

                            <!-- ── Painéis: Timeline + Mensagens recentes ── -->
                            <div class="pp-grid">
                                <!-- Timeline -->
                                <section class="pp-panel">
                                    <header class="pp-panel__head">
                                        <div class="pp-panel__title"><i class="pi pi-history" /> Timeline de atendimentos</div>
                                        <span class="pp-panel__badge">{{ ultimasAtendidas.length }}</span>
                                    </header>
                                    <div class="pp-panel__body">
                                        <div v-if="sessionsLoading" class="pp-empty">Carregando…</div>
                                        <div v-else-if="!ultimasAtendidas.length" class="pp-empty pp-empty--rich">
                                            <div class="pp-empty__icon"><i class="pi pi-history" /></div>
                                            <div class="pp-empty__title">Sem atendimentos registrados</div>
                                            <div class="pp-empty__sub">As sessões realizadas com este paciente aparecerão aqui em ordem cronológica.</div>
                                        </div>
                                        <ol v-else class="pp-timeline">
                                            <li
                                                v-for="s in ultimasAtendidas"
                                                :key="s.id"
                                                class="pp-tl"
                                                :data-status="String(s.status || 'agendado').toLowerCase()"
                                            >
                                                <span class="pp-tl__dot" />
                                                <div class="pp-tl__main">
                                                    <div class="pp-tl__top">
                                                        <span class="pp-tl__when">{{ fmtDateTimeBR(s.inicio_em) }}</span>
                                                        <span class="pp-tl__rel">{{ fmtRelative(s.inicio_em) }}</span>
                                                    </div>
                                                    <div class="pp-tl__row">
                                                        <Tag
                                                            :value="STATUS_LABEL[s.status] || s.status || '—'"
                                                            :severity="STATUS_SEVERITY[s.status] || 'info'"
                                                            class="pp-tl__tag"
                                                        />
                                                        <span v-if="s.modalidade" class="pp-tl__chip">
                                                            <i :class="s.modalidade === 'online' ? 'pi pi-video' : 'pi pi-map-marker'" />
                                                            {{ s.modalidade === 'online' ? 'Online' : 'Presencial' }}
                                                        </span>
                                                        <span v-if="sessionDuration(s.inicio_em, s.fim_em)" class="pp-tl__chip pp-tl__chip--dim">
                                                            <i class="pi pi-clock" /> {{ sessionDuration(s.inicio_em, s.fim_em) }}
                                                        </span>
                                                    </div>
                                                    <p v-if="s.observacoes" class="pp-tl__note">{{ s.observacoes }}</p>
                                                </div>
                                            </li>
                                        </ol>
                                    </div>
                                </section>

                                <!-- Mensagens recentes + Notas internas -->
                                <div class="pp-grid__col">
                                    <section class="pp-panel">
                                        <header class="pp-panel__head">
                                            <div class="pp-panel__title"><i class="pi pi-comments" /> Últimas mensagens</div>
                                            <span class="pp-panel__badge">{{ recentMessages.length }}</span>
                                        </header>
                                        <div class="pp-panel__body">
                                            <div v-if="messagesLoading" class="pp-empty">Carregando…</div>
                                            <div v-else-if="!recentMessages.length" class="pp-empty pp-empty--rich">
                                                <div class="pp-empty__icon"><i class="pi pi-comments" /></div>
                                                <div class="pp-empty__title">Sem conversa registrada</div>
                                                <div class="pp-empty__sub">As últimas mensagens trocadas com o paciente aparecerão aqui.</div>
                                            </div>
                                            <ul v-else class="pp-msgs">
                                                <li v-for="m in recentMessages.slice(0, 4)" :key="m.id"
                                                    class="pp-msg"
                                                    :class="m.direction === 'inbound' ? 'pp-msg--in' : 'pp-msg--out'"
                                                >
                                                    <div class="pp-msg__meta">
                                                        <i :class="m.direction === 'inbound' ? 'pi pi-arrow-down-left' : 'pi pi-arrow-up-right'" />
                                                        <span>{{ m.direction === 'inbound' ? 'Recebida' : 'Enviada' }}</span>
                                                        <span class="pp-msg__sep">·</span>
                                                        <span>{{ fmtRelative(m.created_at) }}</span>
                                                    </div>
                                                    <p class="pp-msg__body">{{ m.body || '—' }}</p>
                                                </li>
                                            </ul>
                                        </div>
                                    </section>

                                    <section v-if="notasInternas || observacoes" class="pp-panel">
                                        <header class="pp-panel__head">
                                            <div class="pp-panel__title"><i class="pi pi-file-edit" /> Notas e observações</div>
                                        </header>
                                        <div class="pp-panel__body pp-notes">
                                            <div v-if="observacoes" class="pp-note">
                                                <p class="pp-note__label">Observações gerais</p>
                                                <p class="pp-note__text">{{ observacoes }}</p>
                                            </div>
                                            <div v-if="notasInternas" class="pp-note">
                                                <p class="pp-note__label">
                                                    <i class="pi pi-lock" /> Internas
                                                </p>
                                                <p class="pp-note__text">{{ notasInternas }}</p>
                                            </div>
                                        </div>
                                    </section>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- ═══════════════════════════════════════════
                         ABA 1: PERFIL — accordion
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 1">

                        <!-- Banner risco (no topo do conteúdo, abaixo das tabs) -->
                        <div v-if="riscoElevado"
                             class="flex items-start gap-3 border-b border-red-100 bg-red-50 px-4 py-3">
                            <i class="pi pi-exclamation-circle text-red-500 mt-0.5 shrink-0" />
                            <div>
                                <p class="text-sm font-semibold text-red-700">
                                    Atenção — paciente com risco elevado sinalizado
                                </p>
                                <p class="text-xs text-red-500 mt-0.5">
                                    Verifique as anotações internas e a seção de sessões para mais detalhes.
                                </p>
                            </div>
                        </div>

                        <!-- Nav compacto (<xl) -->
                        <div v-if="isCompact"
                             class="sticky top-0 z-10 border-b border-[var(--surface-border)]
                                    bg-[var(--surface-card)] px-4 py-2.5">
                            <Button type="button" class="w-full !rounded-full"
                                    icon="pi pi-chevron-down" iconPos="right"
                                    :label="selectedNav ? selectedNav.label : 'Selecionar seção'"
                                    @click="toggleNav($event)" />
                            <Popover ref="navPopover">
                                <div class="flex min-w-[240px] flex-col gap-0.5 p-1">
                                    <button
                                        v-for="item in profileNavItems" :key="item.value"
                                        type="button"
                                        class="flex items-center gap-2.5 rounded-lg px-3 py-2
                                               text-left text-sm border cursor-pointer"
                                        :class="activeAccValue === item.value
                                            ? 'bg-indigo-50 border-indigo-200 text-indigo-700 font-semibold'
                                            : 'border-transparent text-[var(--text-color)] hover:bg-[var(--surface-ground)] font-medium'"
                                        @click="selectNav(item)"
                                    >
                                        <i :class="item.icon" class="text-sm opacity-60 shrink-0" />
                                        <span>{{ item.label }}</span>
                                    </button>
                                </div>
                            </Popover>
                        </div>

                        <!-- Accordion -->
                        <div class="p-4">
                            <Accordion multiple v-model:value="activeAccValues" class="accordion-clean">

                                <!-- ── 1. INFORMAÇÕES PESSOAIS ───────────── -->
                                <AccordionPanel value="0">
                                    <AccordionHeader :ref="(el) => setPanelHeaderRef(el, 0)">
                                        <span class="flex items-center gap-2 text-[0.83rem] font-bold">
                                            <i class="pi pi-pencil text-indigo-500 text-sm" />
                                            1. Informações Pessoais
                                        </span>
                                    </AccordionHeader>
                                    <AccordionContent>
                                        <div class="pt-3 grid grid-cols-1 md:grid-cols-2 gap-4">

                                            <!-- Dados de cadastro -->
                                            <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Dados de cadastro</p>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Nome completo</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(nomeCompleto) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Data de nascimento</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">
                                                        {{ fmtDateBR(birthValue) }}
                                                        <span v-if="calcAge(birthValue) != null" class="text-[var(--text-color-secondary)] font-normal">({{ calcAge(birthValue) }} a)</span>
                                                    </span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Gênero</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ fmtGender(genero) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Estado civil</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ fmtMarital(estadoCivil) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">CPF</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right font-mono">{{ fmtCPF(patientData.cpf) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">RG</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right font-mono">{{ fmtRG(patientData.rg) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Naturalidade</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(naturalidade) }}</span>
                                                </div>
                                            </div>

                                            <!-- Contato + Origem -->
                                            <div class="space-y-3">
                                                <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                    <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Contato</p>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Telefone / Celular</span>
                                                        <a v-if="telefone" :href="`tel:${telefone}`" class="text-[0.8rem] font-medium text-right text-[var(--primary-color)] hover:underline">{{ fmtPhoneMobile(telefone) }}</a>
                                                        <span v-else class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Telefone alternativo</span>
                                                        <a v-if="telefoneAlternativo" :href="`tel:${telefoneAlternativo}`" class="text-[0.8rem] font-medium text-right text-[var(--primary-color)] hover:underline">{{ fmtPhoneMobile(telefoneAlternativo) }}</a>
                                                        <span v-else class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Email principal</span>
                                                        <a v-if="emailPrincipal" :href="`mailto:${emailPrincipal}`" class="text-[0.8rem] font-medium text-right text-[var(--primary-color)] hover:underline truncate max-w-[200px] inline-block">{{ emailPrincipal }}</a>
                                                        <span v-else class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Email alternativo</span>
                                                        <a v-if="emailAlternativo" :href="`mailto:${emailAlternativo}`" class="text-[0.8rem] font-medium text-right text-[var(--primary-color)] hover:underline truncate max-w-[200px] inline-block">{{ emailAlternativo }}</a>
                                                        <span v-else class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                    </div>
                                                </div>

                                                <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                    <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Origem</p>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">{{ groupCountLabel }}</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ groupLabel }}</span>
                                                    </div>
                                                    <div class="flex items-start justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Tags</span>
                                                        <div class="flex flex-wrap gap-1 justify-end">
                                                            <span v-for="t in tags" :key="t.id"
                                                                  class="inline-flex items-center px-2 py-0.5 rounded-full text-[0.72rem] font-medium"
                                                                  :style="tagStyle(t)">{{ t.name }}</span>
                                                            <span v-if="!tags?.length" class="text-[0.8rem] text-[var(--text-color)] font-medium">—</span>
                                                        </div>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Onde nos conheceu?</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(ondeNosConheceu) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Encaminhado por</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(encaminhadoPor) }}</span>
                                                    </div>
                                                </div>
                                            </div>

                                            <!-- Observações full-width -->
                                            <div v-if="observacoes"
                                                 class="md:col-span-2 rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Observações</p>
                                                <p class="text-[0.83rem] text-[var(--text-color)] leading-relaxed whitespace-pre-wrap">{{ observacoes }}</p>
                                            </div>
                                        </div>
                                    </AccordionContent>
                                </AccordionPanel>

                                <!-- ── 2. ENDEREÇO ───────────────────────── -->
                                <AccordionPanel value="1">
                                    <AccordionHeader :ref="(el) => setPanelHeaderRef(el, 1)">
                                        <span class="flex items-center gap-2 text-[0.83rem] font-bold">
                                            <i class="pi pi-map-marker text-indigo-500 text-sm" />
                                            2. Endereço
                                        </span>
                                    </AccordionHeader>
                                    <AccordionContent>
                                        <div class="pt-3">
                                            <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Localização</p>
                                                <div class="grid grid-cols-1 sm:grid-cols-2">
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">CEP</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right font-mono">{{ dash(cep) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">País</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(pais) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Cidade</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(cidade) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Estado</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(estado) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Endereço</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(endereco) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Número</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(numero) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Bairro</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(bairro) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Complemento</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(complemento) }}</span>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </AccordionContent>
                                </AccordionPanel>

                                <!-- ── 3. DADOS ADICIONAIS ───────────────── -->
                                <AccordionPanel value="2">
                                    <AccordionHeader :ref="(el) => setPanelHeaderRef(el, 2)">
                                        <span class="flex items-center gap-2 text-[0.83rem] font-bold">
                                            <i class="pi pi-tags text-indigo-500 text-sm" />
                                            3. Dados Adicionais
                                        </span>
                                    </AccordionHeader>
                                    <AccordionContent>
                                        <div class="pt-3">
                                            <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Formação & família</p>
                                                <div class="grid grid-cols-1 sm:grid-cols-2">
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Escolaridade</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(escolaridade) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Profissão</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(profissao) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Nome de um parente</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(nomeParente) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Grau de parentesco</span>
                                                        <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(grauParentesco) }}</span>
                                                    </div>
                                                    <div class="flex items-baseline justify-between gap-4 py-1.5">
                                                        <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Telefone do parente</span>
                                                        <a v-if="telefoneParente" :href="`tel:${telefoneParente}`" class="text-[0.8rem] font-medium text-right text-[var(--primary-color)] hover:underline">{{ fmtPhoneMobile(telefoneParente) }}</a>
                                                        <span v-else class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </AccordionContent>
                                </AccordionPanel>

                                <!-- ── 4. RESPONSÁVEL ────────────────────── -->
                                <AccordionPanel value="3">
                                    <AccordionHeader :ref="(el) => setPanelHeaderRef(el, 3)">
                                        <span class="flex items-center gap-2 text-[0.83rem] font-bold">
                                            <i class="pi pi-users text-indigo-500 text-sm" />
                                            4. Responsável
                                        </span>
                                    </AccordionHeader>
                                    <AccordionContent>
                                        <div class="pt-3">
                                            <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                <p class="text-[0.65rem] font-bold uppercase tracking-widest text-[var(--text-color-secondary)] mb-3 opacity-70">Dados do responsável</p>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Nome</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">{{ dash(nomeResponsavel) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">CPF</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right font-mono">{{ fmtCPF(cpfResponsavel) }}</span>
                                                </div>
                                                <div class="flex items-baseline justify-between gap-4 py-1.5 border-b border-[var(--surface-border)]">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Telefone</span>
                                                    <a v-if="telefoneResponsavel" :href="`tel:${telefoneResponsavel}`" class="text-[0.8rem] font-medium text-right text-[var(--primary-color)] hover:underline">{{ fmtPhoneMobile(telefoneResponsavel) }}</a>
                                                    <span v-else class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                </div>
                                                <div v-if="observacaoResponsavel" class="pt-2">
                                                    <p class="text-[0.75rem] text-[var(--text-color-secondary)] mb-1">Observação</p>
                                                    <p class="text-[0.83rem] text-[var(--text-color)] leading-relaxed whitespace-pre-wrap">{{ observacaoResponsavel }}</p>
                                                </div>
                                                <div v-else class="flex items-baseline justify-between gap-4 py-1.5">
                                                    <span class="text-[0.8rem] text-[var(--text-color-secondary)] shrink-0">Observação</span>
                                                    <span class="text-[0.8rem] text-[var(--text-color)] font-medium text-right">—</span>
                                                </div>
                                            </div>
                                        </div>
                                    </AccordionContent>
                                </AccordionPanel>

                                <!-- ── 5. ANOTAÇÕES INTERNAS ─────────────── -->
                                <AccordionPanel value="4">
                                    <AccordionHeader :ref="(el) => setPanelHeaderRef(el, 4)">
                                        <span class="flex items-center gap-2 text-[0.83rem] font-bold">
                                            <i class="pi pi-file-edit text-indigo-500 text-sm" />
                                            5. Anotações Internas
                                        </span>
                                    </AccordionHeader>
                                    <AccordionContent>
                                        <div class="pt-3">
                                            <div class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-4">
                                                <div class="flex items-center gap-1.5 text-xs text-[var(--text-color-secondary)] opacity-70 mb-3">
                                                    <i class="pi pi-lock text-[0.7rem]" />
                                                    Campo interno: não aparece no cadastro externo.
                                                </div>
                                                <p class="text-[0.83rem] text-[var(--text-color)] leading-relaxed whitespace-pre-wrap min-h-[4rem]">
                                                    {{ dash(notasInternas) }}
                                                </p>
                                            </div>
                                        </div>
                                    </AccordionContent>
                                </AccordionPanel>

                                <!-- ── 6. SESSÕES ────────────────────────── -->
                                <AccordionPanel value="5">
                                    <AccordionHeader :ref="(el) => setPanelHeaderRef(el, 5)">
                                        <span class="flex items-center gap-2 text-[0.83rem] font-bold">
                                            <i class="pi pi-calendar text-indigo-500 text-sm" />
                                            6. Sessões
                                        </span>
                                    </AccordionHeader>
                                    <AccordionContent>
                                        <div class="pt-3">
                                            <div v-if="sessionsLoading"
                                                 class="flex items-center gap-2 text-sm text-[var(--text-color-secondary)] py-4">
                                                <i class="pi pi-spin pi-spinner" /> Carregando sessões…
                                            </div>
                                            <div v-else-if="!sessions.length"
                                                 class="text-sm text-[var(--text-color-secondary)] py-4 text-center">
                                                Nenhuma sessão registrada para este paciente.
                                            </div>
                                            <div v-else class="flex flex-col gap-2">
                                                <div
                                                    v-for="s in sessions" :key="s.id"
                                                    class="rounded-xl border border-[var(--surface-border)]
                                                           bg-[var(--surface-ground)] px-4 py-3
                                                           flex flex-col sm:flex-row sm:items-center
                                                           sm:justify-between gap-2"
                                                >
                                                    <div class="flex flex-col gap-1">
                                                        <p class="text-[0.85rem] font-semibold text-[var(--text-color)]">
                                                            {{ s.titulo_custom || s.titulo || (s.tipo ? s.tipo : 'Sessão') }}
                                                        </p>
                                                        <div class="text-[0.76rem] text-[var(--text-color-secondary)] flex flex-wrap gap-x-3 gap-y-1">
                                                            <span><i class="pi pi-calendar mr-1 opacity-50" />{{ fmtDateTimeBR(s.inicio_em) }}</span>
                                                            <span v-if="sessionDuration(s.inicio_em, s.fim_em)">
                                                                <i class="pi pi-clock mr-1 opacity-50" />{{ sessionDuration(s.inicio_em, s.fim_em) }}
                                                            </span>
                                                            <span v-if="s.modalidade">
                                                                <i class="pi pi-video mr-1 opacity-50" />{{ s.modalidade === 'online' ? 'Online' : 'Presencial' }}
                                                            </span>
                                                        </div>
                                                        <p v-if="s.observacoes"
                                                           class="text-[0.76rem] text-[var(--text-color-secondary)] mt-0.5 line-clamp-2">
                                                            {{ s.observacoes }}
                                                        </p>
                                                    </div>
                                                    <Tag :value="STATUS_LABEL[s.status] || s.status || 'Agendado'"
                                                         :severity="STATUS_SEVERITY[s.status] || 'info'"
                                                         class="shrink-0" />
                                                </div>
                                            </div>
                                        </div>
                                    </AccordionContent>
                                </AccordionPanel>

                            </Accordion>
                        </div>
                    </div><!-- /aba perfil -->

                    <!-- ABAS PLACEHOLDER -->
                    <!-- ═══════════════════════════════════════════
                         ABA 2: PRONTUÁRIO EVOLUTIVO — em breve
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 2" class="pp-pron">
                        <div class="pp-empty pp-empty--rich">
                            <div class="pp-empty__icon"><i class="pi pi-file-edit" /></div>
                            <div class="pp-empty__title">Prontuário evolutivo</div>
                            <div class="pp-empty__sub">Em breve — anamnese, evolução das sessões e plano terapêutico em um só lugar, com histórico clínico completo do paciente.</div>
                        </div>
                    </div>
                    <!-- ═══════════════════════════════════════════
                         ABA 3: AGENDA — sessões agrupadas por mês
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 3" class="pp-ag">
                        <div v-if="sessionsLoading" class="pp-empty">
                            <i class="pi pi-spin pi-spinner" /> Carregando…
                        </div>
                        <template v-else>
                            <!-- KPIs -->
                            <div class="pp-ag__kpis">
                                <article class="pp-kpi" style="--c:var(--primary-color); --c-dim:color-mix(in srgb, var(--primary-color) 10%, transparent); --c-border:color-mix(in srgb, var(--primary-color) 30%, transparent)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-calendar" /></div>
                                        <span class="pp-kpi__tag">Total</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ sessions.length }}</div>
                                        <div class="pp-kpi__cap">sessões registradas</div>
                                    </div>
                                </article>
                                <article class="pp-kpi" style="--c:#4ade80; --c-dim:rgba(74,222,128,0.10); --c-border:rgba(74,222,128,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-check-circle" /></div>
                                        <span class="pp-kpi__tag">Realizadas</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ sessoesPresentes }}</div>
                                        <div class="pp-kpi__cap">
                                            <template v-if="sessions.length">{{ Math.round((sessoesPresentes / sessions.length) * 100) }}% do total</template>
                                            <template v-else>—</template>
                                        </div>
                                    </div>
                                </article>
                                <article class="pp-kpi" :style="sessoesFaltadas > 0
                                    ? '--c:#f87171; --c-dim:rgba(248,113,113,0.10); --c-border:rgba(248,113,113,0.30)'
                                    : '--c:#94a3b8; --c-dim:rgba(148,163,184,0.10); --c-border:rgba(148,163,184,0.25)'">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-user-minus" /></div>
                                        <span class="pp-kpi__tag">Faltas</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ sessoesFaltadas }}</div>
                                        <div class="pp-kpi__cap">
                                            <template v-if="sessoesCanceladas">+ {{ sessoesCanceladas }} cancel.</template>
                                            <template v-else>nenhuma falta</template>
                                        </div>
                                    </div>
                                </article>
                                <article class="pp-kpi" style="--c:#60a5fa; --c-dim:rgba(96,165,250,0.10); --c-border:rgba(96,165,250,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-calendar-clock" /></div>
                                        <span class="pp-kpi__tag">Próxima</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <template v-if="proximaSessao">
                                            <div class="pp-kpi__big pp-kpi__big--small">{{ fmtRelative(proximaSessao.inicio_em) }}</div>
                                            <div class="pp-kpi__cap">{{ fmtDateBR(proximaSessao.inicio_em) }} · {{ fmtHourShort(proximaSessao.inicio_em) }}</div>
                                        </template>
                                        <template v-else>
                                            <div class="pp-kpi__big pp-kpi__big--small">—</div>
                                            <div class="pp-kpi__cap">Sem futura</div>
                                        </template>
                                    </div>
                                </article>
                            </div>

                            <!-- Filtros -->
                            <div class="pp-ag__filters" role="tablist">
                                <button
                                    v-for="f in agendaFilters" :key="f.value"
                                    type="button"
                                    role="tab"
                                    :aria-selected="agendaFilter === f.value"
                                    class="pp-ag__filter"
                                    :class="{ 'is-active': agendaFilter === f.value }"
                                    @click="agendaFilter = f.value"
                                >
                                    <i :class="f.icon" />
                                    <span>{{ f.label }}</span>
                                </button>
                            </div>

                            <!-- Lista agrupada por mês -->
                            <div v-if="!agendaAgrupadas.length" class="pp-empty pp-empty--rich">
                                <div class="pp-empty__icon"><i class="pi pi-calendar-times" /></div>
                                <div class="pp-empty__title">{{ sessions.length ? 'Nenhuma sessão neste filtro' : 'Sem sessões registradas' }}</div>
                                <div class="pp-empty__sub">
                                    <template v-if="sessions.length">Tente outro filtro acima ou veja "Todas" pra listar o histórico completo.</template>
                                    <template v-else>As sessões agendadas e atendidas com este paciente aparecerão aqui.</template>
                                </div>
                            </div>
                            <section
                                v-for="g in agendaAgrupadas" :key="g.key"
                                class="pp-panel pp-ag__group"
                            >
                                <header class="pp-panel__head">
                                    <div class="pp-panel__title"><i class="pi pi-calendar" /> {{ g.label }}</div>
                                    <span class="pp-panel__badge">{{ g.items.length }}</span>
                                </header>
                                <ul class="pp-ag__list">
                                    <li
                                        v-for="s in g.items" :key="s.id"
                                        class="pp-ag__item"
                                        :data-status="String(s.status || 'agendado').toLowerCase()"
                                    >
                                        <div class="pp-ag__date">
                                            <span class="pp-ag__date-dow">{{ fmtDayShort(s.inicio_em) }}</span>
                                            <span class="pp-ag__date-day">{{ new Date(s.inicio_em).getDate() }}</span>
                                            <span class="pp-ag__date-time">{{ fmtHourShort(s.inicio_em) }}</span>
                                        </div>
                                        <div class="pp-ag__main">
                                            <div class="pp-ag__top">
                                                <Tag
                                                    :value="STATUS_LABEL[s.status] || s.status || 'Agendado'"
                                                    :severity="STATUS_SEVERITY[s.status] || 'info'"
                                                    class="pp-ag__tag"
                                                />
                                                <span v-if="s.modalidade" class="pp-ag__chip">
                                                    <i :class="s.modalidade === 'online' ? 'pi pi-video' : 'pi pi-map-marker'" />
                                                    {{ s.modalidade === 'online' ? 'Online' : 'Presencial' }}
                                                </span>
                                                <span v-if="sessionDuration(s.inicio_em, s.fim_em)" class="pp-ag__chip pp-ag__chip--dim">
                                                    <i class="pi pi-clock" /> {{ sessionDuration(s.inicio_em, s.fim_em) }}
                                                </span>
                                                <span class="pp-ag__rel">{{ fmtRelative(s.inicio_em) }}</span>
                                            </div>
                                            <div v-if="s.titulo_custom || s.titulo" class="pp-ag__title">
                                                {{ s.titulo_custom || s.titulo }}
                                            </div>
                                            <p v-if="s.observacoes" class="pp-ag__note">{{ s.observacoes }}</p>
                                        </div>
                                        <div class="pp-ag__actions">
                                            <button type="button"
                                                v-tooltip.left="'Marcar como realizada'"
                                                class="pp-ag__act pp-ag__act--ok"
                                                :disabled="sessionBusy"
                                                @click="updateSessionStatus(s, 'realizado', 'Sessão marcada como realizada')">
                                                <i class="pi pi-check-circle" />
                                            </button>
                                            <button type="button"
                                                v-tooltip.left="'Marcar como falta'"
                                                class="pp-ag__act pp-ag__act--warn"
                                                :disabled="sessionBusy"
                                                @click="updateSessionStatus(s, 'faltou', 'Marcada como falta')">
                                                <i class="pi pi-user-minus" />
                                            </button>
                                            <button type="button"
                                                v-tooltip.left="'Cancelar'"
                                                class="pp-ag__act pp-ag__act--danger"
                                                :disabled="sessionBusy"
                                                @click="updateSessionStatus(s, 'cancelado', 'Sessão cancelada')">
                                                <i class="pi pi-ban" />
                                            </button>
                                        </div>
                                    </li>
                                </ul>
                            </section>
                        </template>
                    </div>
                    <!-- ═══════════════════════════════════════════
                         ABA 4: FINANCEIRO — KPIs + tabela
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 4" class="pp-fin">
                        <div v-if="financialLoading" class="pp-empty">
                            <i class="pi pi-spin pi-spinner" /> Carregando…
                        </div>
                        <div v-else-if="!financialRecords.length" class="pp-empty pp-empty--rich">
                            <div class="pp-empty__icon"><i class="pi pi-wallet" /></div>
                            <div class="pp-empty__title">Sem lançamentos financeiros</div>
                            <div class="pp-empty__sub">Adicione o primeiro lançamento de cobrança ou recebimento deste paciente.</div>
                            <Button
                                label="Novo lançamento"
                                icon="pi pi-plus"
                                class="pp-empty__cta rounded-full"
                                @click="onAddFinancial"
                            />
                        </div>
                        <template v-else>
                            <!-- KPIs do financeiro -->
                            <div class="pp-fin__kpis">
                                <article class="pp-kpi" style="--c:#4ade80; --c-dim:rgba(74,222,128,0.10); --c-border:rgba(74,222,128,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-check-circle" /></div>
                                        <span class="pp-kpi__tag">Pago</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big pp-kpi__big--small">{{ fmtCurrency(statusFinanceiro.totalPago) }}</div>
                                        <div class="pp-kpi__cap">
                                            {{ financialRecords.filter((r) => !!r.paid_at).length }} {{ financialRecords.filter((r) => !!r.paid_at).length === 1 ? 'lançamento' : 'lançamentos' }}
                                        </div>
                                    </div>
                                </article>

                                <article class="pp-kpi" style="--c:var(--primary-color); --c-dim:color-mix(in srgb, var(--primary-color) 10%, transparent); --c-border:color-mix(in srgb, var(--primary-color) 30%, transparent)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-clock" /></div>
                                        <span class="pp-kpi__tag">Pendente</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big pp-kpi__big--small">{{ fmtCurrency(statusFinanceiro.totalPendente) }}</div>
                                        <div class="pp-kpi__cap">
                                            <template v-if="statusFinanceiro.proxVenc">
                                                Próx. venc. {{ fmtDateBR(statusFinanceiro.proxVenc.due_date) }}
                                            </template>
                                            <template v-else>A receber</template>
                                        </div>
                                    </div>
                                </article>

                                <article class="pp-kpi" :style="statusFinanceiro.vencidos > 0
                                        ? '--c:#f87171; --c-dim:rgba(248,113,113,0.10); --c-border:rgba(248,113,113,0.30)'
                                        : '--c:#94a3b8; --c-dim:rgba(148,163,184,0.10); --c-border:rgba(148,163,184,0.25)'">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-exclamation-triangle" /></div>
                                        <span class="pp-kpi__tag">Em atraso</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big pp-kpi__big--small">
                                            {{ statusFinanceiro.vencidos }}
                                        </div>
                                        <div class="pp-kpi__cap">
                                            {{ statusFinanceiro.vencidos === 0 ? 'Tudo em dia' : (statusFinanceiro.vencidos === 1 ? 'lançamento vencido' : 'lançamentos vencidos') }}
                                        </div>
                                    </div>
                                </article>
                            </div>

                            <!-- Tabela de lançamentos -->
                            <section class="pp-panel pp-fin__list">
                                <header class="pp-panel__head">
                                    <div class="pp-panel__title"><i class="pi pi-list" /> Lançamentos</div>
                                    <span class="pp-panel__badge">{{ recordsOrdenados.length }}</span>
                                </header>
                                <div class="pp-fin__table" role="table">
                                    <div class="pp-fin__row pp-fin__row--head" role="row">
                                        <span role="columnheader">Vencimento</span>
                                        <span role="columnheader">Descrição</span>
                                        <span role="columnheader">Forma</span>
                                        <span role="columnheader" class="pp-fin__col-amount">Valor</span>
                                        <span role="columnheader">Status</span>
                                    </div>
                                    <div
                                        v-for="r in recordsOrdenados" :key="r.id"
                                        class="pp-fin__row"
                                        :data-status="recordStatus(r)"
                                        role="row"
                                    >
                                        <span class="pp-fin__date" role="cell">
                                            <span class="pp-fin__date-main">{{ r.due_date ? fmtDateBR(r.due_date) : fmtDateBR(r.created_at) }}</span>
                                            <span v-if="r.due_date" class="pp-fin__date-rel">{{ fmtRelative(r.due_date) }}</span>
                                        </span>
                                        <span class="pp-fin__desc" role="cell">
                                            {{ r.description || (r.category ? r.category : 'Lançamento') }}
                                        </span>
                                        <span class="pp-fin__method" role="cell">
                                            {{ fmtPaymentMethod(r.payment_method) || '—' }}
                                        </span>
                                        <span class="pp-fin__amount" role="cell">
                                            {{ fmtCurrency(Number(r.amount) || 0) }}
                                        </span>
                                        <span class="pp-fin__status-cell" role="cell">
                                            <span class="pp-fin__status" :data-status="recordStatus(r)">
                                                <span class="pp-fin__status-dot" />
                                                {{ RECORD_STATUS_LABEL[recordStatus(r)] }}
                                            </span>
                                        </span>
                                    </div>
                                </div>
                            </section>
                        </template>
                    </div>
                    <!-- ═══════════════════════════════════════════
                         ABA 5: DOCUMENTOS — KPIs + DocumentsListPage embedded
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 5" class="pp-doc">
                        <!-- KPIs (só se tiver algo) -->
                        <div v-if="documentsLoading" class="pp-empty">
                            <i class="pi pi-spin pi-spinner" /> Carregando…
                        </div>
                        <div v-else-if="docTotal" class="pp-doc__kpis">
                            <article class="pp-kpi" style="--c:var(--primary-color); --c-dim:color-mix(in srgb, var(--primary-color) 10%, transparent); --c-border:color-mix(in srgb, var(--primary-color) 30%, transparent)">
                                <div class="pp-kpi__shine" />
                                <header class="pp-kpi__head">
                                    <div class="pp-kpi__icon"><i class="pi pi-folder" /></div>
                                    <span class="pp-kpi__tag">Total</span>
                                </header>
                                <div class="pp-kpi__body">
                                    <div class="pp-kpi__big">{{ docTotal }}</div>
                                    <div class="pp-kpi__cap">{{ docSizeTotal }} no total</div>
                                </div>
                            </article>

                            <article v-if="docTopType" class="pp-kpi" style="--c:#0ea5e9; --c-dim:rgba(14,165,233,0.10); --c-border:rgba(14,165,233,0.30)">
                                <div class="pp-kpi__shine" />
                                <header class="pp-kpi__head">
                                    <div class="pp-kpi__icon"><i class="pi pi-tag" /></div>
                                    <span class="pp-kpi__tag">Mais comum</span>
                                </header>
                                <div class="pp-kpi__body">
                                    <div class="pp-kpi__big pp-kpi__big--small">{{ docTopType.label }}</div>
                                    <div class="pp-kpi__cap">{{ docTopType.count }} {{ docTopType.count === 1 ? 'documento' : 'documentos' }}</div>
                                </div>
                            </article>

                            <article v-if="docLast" class="pp-kpi" style="--c:#4ade80; --c-dim:rgba(74,222,128,0.10); --c-border:rgba(74,222,128,0.30)">
                                <div class="pp-kpi__shine" />
                                <header class="pp-kpi__head">
                                    <div class="pp-kpi__icon"><i class="pi pi-clock" /></div>
                                    <span class="pp-kpi__tag">Último</span>
                                </header>
                                <div class="pp-kpi__body">
                                    <div class="pp-kpi__big pp-kpi__big--small">{{ fmtRelative(docLast.created_at) }}</div>
                                    <div class="pp-kpi__cap">{{ fmtDateBR(docLast.created_at) }}</div>
                                </div>
                            </article>

                            <article v-if="docPendentes > 0" class="pp-kpi" style="--c:#f59e0b; --c-dim:rgba(245,158,11,0.10); --c-border:rgba(245,158,11,0.30)">
                                <div class="pp-kpi__shine" />
                                <header class="pp-kpi__head">
                                    <div class="pp-kpi__icon"><i class="pi pi-exclamation-circle" /></div>
                                    <span class="pp-kpi__tag">Revisão</span>
                                </header>
                                <div class="pp-kpi__body">
                                    <div class="pp-kpi__big">{{ docPendentes }}</div>
                                    <div class="pp-kpi__cap">{{ docPendentes === 1 ? 'pendente' : 'pendentes' }}</div>
                                </div>
                            </article>
                        </div>

                        <!-- Lista (DocumentsListPage embedded) dentro de um panel -->
                        <section class="pp-panel pp-doc__list">
                            <DocumentsListPage
                                :patientId="patient?.id"
                                :patientName="patient?.nome_completo || patient?.nome_social || ''"
                                embedded
                            />
                        </section>
                    </div>
                    <!-- ═══════════════════════════════════════════
                         ABA 6: CONVERSAS — KPIs + PatientConversationsTab
                    ═══════════════════════════════════════════ -->
                    <div v-show="activeTab === 6" class="pp-conv">
                        <div v-if="messagesLoading" class="pp-empty">
                            <i class="pi pi-spin pi-spinner" /> Carregando…
                        </div>
                        <template v-else>
                            <div v-if="convTotal" class="pp-conv__kpis">
                                <article class="pp-kpi" style="--c:#25d366; --c-dim:rgba(37,211,102,0.10); --c-border:rgba(37,211,102,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-comments" /></div>
                                        <span class="pp-kpi__tag">Mensagens</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ convTotal }}</div>
                                        <div class="pp-kpi__cap">
                                            <template v-if="convChannels.length">via {{ convChannels.map(chConvLabel).join(', ') }}</template>
                                            <template v-else>no histórico</template>
                                        </div>
                                    </div>
                                </article>

                                <article class="pp-kpi" style="--c:#4ade80; --c-dim:rgba(74,222,128,0.10); --c-border:rgba(74,222,128,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-arrow-down-left" /></div>
                                        <span class="pp-kpi__tag">Recebidas</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ convInbound }}</div>
                                        <div class="pp-kpi__cap">
                                            <template v-if="convTotal">{{ Math.round((convInbound / convTotal) * 100) }}% do total</template>
                                            <template v-else>—</template>
                                        </div>
                                    </div>
                                </article>

                                <article class="pp-kpi" style="--c:#60a5fa; --c-dim:rgba(96,165,250,0.10); --c-border:rgba(96,165,250,0.30)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-arrow-up-right" /></div>
                                        <span class="pp-kpi__tag">Enviadas</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <div class="pp-kpi__big">{{ convOutbound }}</div>
                                        <div class="pp-kpi__cap">
                                            <template v-if="convTotal">{{ Math.round((convOutbound / convTotal) * 100) }}% do total</template>
                                            <template v-else>—</template>
                                        </div>
                                    </div>
                                </article>

                                <article class="pp-kpi" style="--c:var(--primary-color); --c-dim:color-mix(in srgb, var(--primary-color) 10%, transparent); --c-border:color-mix(in srgb, var(--primary-color) 30%, transparent)">
                                    <div class="pp-kpi__shine" />
                                    <header class="pp-kpi__head">
                                        <div class="pp-kpi__icon"><i class="pi pi-clock" /></div>
                                        <span class="pp-kpi__tag">Última</span>
                                    </header>
                                    <div class="pp-kpi__body">
                                        <template v-if="convLast">
                                            <div class="pp-kpi__big pp-kpi__big--small">{{ fmtRelative(convLast.created_at) }}</div>
                                            <div class="pp-kpi__cap">
                                                {{ convLast.direction === 'inbound' ? 'Recebida' : 'Enviada' }}
                                                <span v-if="convFirst" class="pp-kpi__cap-dim">· 1ª {{ fmtRelative(convFirst.created_at) }}</span>
                                            </div>
                                        </template>
                                        <template v-else>
                                            <div class="pp-kpi__big pp-kpi__big--small">—</div>
                                            <div class="pp-kpi__cap">Sem mensagens</div>
                                        </template>
                                    </div>
                                </article>
                            </div>

                            <!-- Atalho pra abrir o drawer (continuar a conversa) -->
                            <div class="pp-conv__cta">
                                <Button
                                    label="Abrir conversa no drawer"
                                    icon="pi pi-whatsapp"
                                    severity="success"
                                    outlined
                                    class="rounded-full"
                                    @click="abrirWhatsappPaciente"
                                />
                                <span class="pp-conv__cta-hint">Continue a conversa em tempo real sem fechar o prontuário.</span>
                            </div>

                            <!-- Histórico completo via componente original -->
                            <section class="pp-panel pp-conv__list">
                                <PatientConversationsTab
                                    :patient-id="patient?.id"
                                    :patient-name="patient?.nome_completo || patient?.nome_social || ''"
                                />
                            </section>
                        </template>
                    </div>

                </main>
            </div>
        </div>

        <!-- ── FOOTER ──────────────────────────────────────────── -->
        <template #footer>
            <div class="flex items-center justify-between gap-2 flex-wrap px-1">
                <Button
                    v-if="activeTab === 1"
                    :label="allOpen ? 'Fechar seções' : 'Abrir seções'"
                    :icon="allOpen ? 'pi pi-angle-double-up' : 'pi pi-angle-double-down'"
                    severity="secondary" outlined class="rounded-full"
                    @click="toggleAllAccordions"
                />
                <div v-else />
                <div class="flex items-center gap-2">
                    <Button label="Copiar resumo" icon="pi pi-copy"
                            severity="secondary" outlined class="rounded-full"
                            @click="copyResumo" />
                    <Button label="Editar paciente" icon="pi pi-pencil"
                            severity="secondary" outlined class="rounded-full"
                            @click="editPatient" />
                    <Button label="Fechar" icon="pi pi-times"
                            severity="secondary" class="rounded-full"
                            @click="close" />
                </div>
            </div>
        </template>

    </Dialog>

    <!-- ConfirmDialog local — garante que confirm.require funciona mesmo
         se o parent que abriu o prontuário não tiver um <ConfirmDialog>
         montado (ex: contexto fora do MelissaLayout). -->
    <ConfirmDialog />

    <!-- Dialog: adicionar telefone WhatsApp ao paciente.
         Salva em patients.telefone (campo único — usado pelo
         conversationDrawerStore.openForPatient pra criar a thread).
         Se foi acionado por uma tentativa de abrir o drawer (flag
         _resumeDrawerAfterPhone), o drawer abre automaticamente após
         o save bem-sucedido. -->
    <Dialog
        v-model:visible="phoneDlg"
        modal
        :draggable="false"
        :closable="!phoneSaving"
        header="Adicionar telefone WhatsApp"
        class="w-[94vw] max-w-md"
        pt:mask:class="backdrop-blur-sm"
        @hide="_resumeDrawerAfterPhone = false"
    >
        <div class="flex flex-col gap-3 pt-1">
            <FloatLabel variant="on">
                <InputMask
                    id="ppd-phone"
                    v-model="phoneInput"
                    mask="(99) 99999-9999"
                    slotChar="_"
                    class="w-full"
                    autofocus
                    @keydown.enter="savePhone"
                />
                <label for="ppd-phone">Telefone WhatsApp</label>
            </FloatLabel>
            <span class="text-xs text-[var(--text-color-secondary)]">
                <i class="pi pi-info-circle text-[0.7rem] mr-1 opacity-70" />
                DDD + número. Usado pra enviar/receber mensagens via WhatsApp.
            </span>
        </div>
        <template #footer>
            <Button label="Cancelar" severity="secondary" outlined class="rounded-full" :disabled="phoneSaving" @click="phoneDlg = false" />
            <Button label="Salvar" icon="pi pi-check" :loading="phoneSaving" class="rounded-full" @click="savePhone" />
        </template>
    </Dialog>
</template>

<style scoped>
:deep(.accordion-clean .p-accordionpanel) {
    border-radius: 0.75rem;
    margin-bottom: 0.5rem;
    border: 1px solid var(--surface-border);
    overflow: hidden;
}
:deep(.accordion-clean .p-accordionpanel:last-child) { margin-bottom: 0; }
:deep(.accordion-clean .p-accordionheader) {
    background: var(--surface-ground);
    border: none;
    padding: 0.875rem 1rem;
}
:deep(.accordion-clean .p-accordionheader:hover) {
    background: var(--surface-hover, #f1f5f9);
}
:deep(.accordion-clean .p-accordioncontent-content) {
    padding: 0 1rem 1rem;
    border-top: 1px solid var(--surface-border);
}
.scrollbar-none::-webkit-scrollbar { display: none; }
.scrollbar-none { -ms-overflow-style: none; scrollbar-width: none; }

/* ════════════════════════════════════════════════════════════════
   HEADER do Dialog — compacto, max 2 linhas, altura padrão.
   Sem #header slot grande; só avatar mini + nome + meta inline.
   ════════════════════════════════════════════════════════════════ */
.pp-head {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    flex: 1;
}
.pp-head__avatar {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    overflow: hidden;
    background: linear-gradient(135deg, var(--primary-color), color-mix(in srgb, var(--primary-color) 70%, white));
    display: grid;
    place-items: center;
}
.pp-head__avatar img { width: 100%; height: 100%; object-fit: cover; }
.pp-head__avatar--initials span {
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}
.pp-head__id {
    min-width: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.pp-head__line1 {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}
.pp-head__name {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--text-color);
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.pp-head__line2 {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.7rem;
    color: var(--text-color-secondary);
    flex-wrap: nowrap;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.pp-head__sep { opacity: 0.4; }
.pp-head__chip {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--primary-color) 25%, transparent);
    color: var(--primary-color);
    padding: 1px 7px;
    border-radius: 100px;
    font-size: 0.62rem;
    font-weight: 600;
    line-height: 1.4;
}
.pp-head__pill {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 7px;
    border-radius: 100px;
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    line-height: 1.4;
    flex-shrink: 0;
}
.pp-head__pill--danger {
    background: rgba(248, 113, 113, 0.12);
    border: 1px solid rgba(248, 113, 113, 0.35);
    color: #b91c1c;
}
.pp-head__pill i { font-size: 0.55rem; }

/* ════════════════════════════════════════════════════════════════
   OVERVIEW — dashboard resumo (estilo HomeCards adaptado)
   ════════════════════════════════════════════════════════════════ */
/* Tokens + background da Visão Geral vivem no <main> pra cascatear pra
   tab bar e demais abas, e pra que o background atmosférico cubra todo
   o card (não só a div da Visão Geral). */
.pp-main {
    --pp-bg: var(--surface-ground);
    --pp-surface: var(--surface-card);
    --pp-border: var(--surface-border);
    --pp-text: var(--text-color);
    --pp-muted: var(--text-color-secondary);
    --pp-dim: color-mix(in srgb, var(--text-color-secondary) 60%, transparent);
    --pp-primary: var(--primary-color, #7c6af7);
    --pp-r: 16px;
    --pp-r-lg: 20px;

    background: var(--pp-bg);
    color: var(--pp-text);
}

.pp-overview {
    position: relative;
    isolation: isolate;
    font-family: 'DM Sans', system-ui, sans-serif;
    overflow: hidden;
}

/* Camada decorativa (spots + linhas) */
.pp-ov__bg {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    overflow: hidden;
}
.pp-ov__spot {
    position: absolute;
    border-radius: 50%;
    filter: blur(80px);
}
.pp-ov__spot--a {
    width: 480px; height: 480px;
    top: -160px; right: -160px;
    background: radial-gradient(circle, color-mix(in srgb, var(--pp-primary) 14%, transparent), transparent 60%);
    animation: pp-flt 22s ease-in-out infinite alternate;
}
.pp-ov__spot--b {
    width: 420px; height: 420px;
    bottom: -120px; left: -120px;
    background: radial-gradient(circle, rgba(74, 222, 128, 0.10), transparent 60%);
    animation: pp-flt 28s ease-in-out infinite alternate-reverse;
}
@keyframes pp-flt {
    from { transform: translate(0, 0) scale(1); }
    to   { transform: translate(40px, 30px) scale(1.06); }
}
.pp-ov__line {
    position: absolute;
    left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--pp-text) 6%, transparent), transparent);
}
.pp-ov__line--1 { top: 140px; }
.pp-ov__line--2 { bottom: 220px; }

.pp-ov__inner {
    position: relative;
    z-index: 1;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

/* ─── KPI CARDS ─── */
.pp-kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}
@media (max-width: 1100px) { .pp-kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px)  { .pp-kpis { grid-template-columns: 1fr; } }

.pp-kpi {
    --c: var(--pp-primary);
    --c-dim: color-mix(in srgb, var(--pp-primary) 10%, transparent);
    --c-border: color-mix(in srgb, var(--pp-primary) 30%, transparent);
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 18px 18px 16px;
    border-radius: var(--pp-r-lg);
    border: 1px solid var(--pp-border);
    background: var(--pp-surface);
    transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1),
                border-color 0.22s ease,
                box-shadow 0.22s ease;
    animation: pp-fade 0.5s ease both;
}
.pp-kpi:hover {
    transform: translateY(-3px);
    border-color: var(--c-border);
    box-shadow: 0 14px 36px -14px color-mix(in srgb, var(--c) 26%, transparent),
                inset 0 1px 0 color-mix(in srgb, var(--pp-text) 4%, transparent);
}
.pp-kpi:hover .pp-kpi__shine { opacity: 1; }
.pp-kpi:hover .pp-kpi__num { opacity: 0.06; }
.pp-kpi:hover .pp-kpi__icon { background: color-mix(in srgb, var(--c) 18%, transparent); }

.pp-kpi__num {
    position: absolute;
    top: 8px; right: 14px;
    font-size: 3rem;
    font-weight: 900;
    letter-spacing: -0.06em;
    line-height: 1;
    color: var(--pp-text);
    opacity: 0.025;
    pointer-events: none;
    user-select: none;
    transition: opacity 0.22s ease;
}
.pp-kpi__shine {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    background: radial-gradient(ellipse at 25% 0%, color-mix(in srgb, var(--c) 12%, transparent), transparent 55%);
}
.pp-kpi__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.pp-kpi__icon {
    width: 36px; height: 36px;
    display: grid;
    place-items: center;
    border-radius: 10px;
    font-size: 0.95rem;
    background: var(--c-dim);
    border: 1px solid var(--c-border);
    color: var(--c);
    transition: background 0.22s ease;
}
.pp-kpi__tag {
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--c);
    opacity: 0.75;
}
.pp-kpi__body { flex: 1; }
.pp-kpi__big {
    font-size: 1.85rem;
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1.1;
    color: var(--pp-text);
}
.pp-kpi__big--small {
    font-size: 1.05rem;
    line-height: 1.2;
    letter-spacing: -0.02em;
}
.pp-kpi__cap {
    margin-top: 6px;
    font-size: 0.74rem;
    color: var(--pp-muted);
    line-height: 1.5;
}
.pp-kpi__cap-warn { color: #f87171; font-weight: 600; }
.pp-kpi__cap-dim { opacity: 0.6; }

/* ─── GRID (timeline + side col) ─── */
.pp-grid {
    display: grid;
    grid-template-columns: 1fr 360px;
    gap: 16px;
}
.pp-grid__col {
    display: flex;
    flex-direction: column;
    gap: 16px;
}
@media (max-width: 1100px) {
    .pp-grid { grid-template-columns: 1fr; }
}

/* ─── PANELS ─── */
.pp-panel {
    border: 1px solid var(--pp-border);
    border-radius: var(--pp-r-lg);
    background: var(--pp-surface);
    overflow: hidden;
    animation: pp-fade 0.5s ease both;
}
.pp-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 13px 18px;
    border-bottom: 1px solid var(--pp-border);
}
.pp-panel__title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--pp-text);
    opacity: 0.85;
}
.pp-panel__title .pi { font-size: 0.78rem; opacity: 0.6; }
.pp-panel__badge {
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 2px 9px;
    border-radius: 100px;
    background: var(--pp-bg);
    border: 1px solid var(--pp-border);
    color: var(--pp-muted);
}
.pp-panel__body {
    padding: 16px 18px;
}

.pp-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 8px;
    padding: 28px 12px;
    color: var(--pp-dim);
    font-size: 0.82rem;
    text-align: center;
}
.pp-empty .pi { font-size: 1.3rem; opacity: 0.5; }

/* Variante rica — border tracejada, ícone grande, CTA. Usada quando
   o empty state precisa convidar a uma ação (ex: financeiro vazio). */
.pp-empty--rich {
    gap: 14px;
    padding: 48px 24px;
    border: 2px dashed color-mix(in srgb, var(--primary-color) 35%, var(--surface-border));
    border-radius: 16px;
    background:
        radial-gradient(ellipse at top, color-mix(in srgb, var(--primary-color) 5%, transparent), transparent 70%),
        var(--surface-card);
    color: var(--text-color-secondary);
}
.pp-empty--rich .pp-empty__icon {
    width: 72px;
    height: 72px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: color-mix(in srgb, var(--primary-color) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--primary-color) 25%, transparent);
    color: var(--primary-color);
    margin-bottom: 4px;
}
.pp-empty--rich .pp-empty__icon .pi {
    font-size: 2rem;
    opacity: 1;
}
.pp-empty--rich .pp-empty__title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-color);
    letter-spacing: -0.02em;
}
.pp-empty--rich .pp-empty__sub {
    font-size: 0.82rem;
    color: var(--text-color-secondary);
    max-width: 340px;
    line-height: 1.5;
}
.pp-empty--rich .pp-empty__cta {
    margin-top: 6px;
}

/* ─── TIMELINE ─── */
.pp-timeline {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}
.pp-timeline::before {
    content: '';
    position: absolute;
    left: 7px;
    top: 6px;
    bottom: 6px;
    width: 1px;
    background: linear-gradient(180deg, var(--pp-border) 0%, transparent 100%);
}
.pp-tl {
    position: relative;
    padding: 0 0 14px 28px;
    --tl-c: #94a3b8;
}
.pp-tl:last-child { padding-bottom: 0; }
.pp-tl[data-status*="realiz"] { --tl-c: #4ade80; }
.pp-tl[data-status*="present"] { --tl-c: #4ade80; }
.pp-tl[data-status*="falt"] { --tl-c: #f87171; }
.pp-tl[data-status*="cancel"], .pp-tl[data-status*="remarc"] { --tl-c: #f59e0b; }
.pp-tl[data-status*="agend"] { --tl-c: #60a5fa; }

.pp-tl__dot {
    position: absolute;
    left: 0;
    top: 4px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--pp-surface);
    border: 2px solid var(--tl-c);
    box-shadow: 0 0 0 3px var(--pp-surface), 0 0 12px color-mix(in srgb, var(--tl-c) 50%, transparent);
}
.pp-tl__main { display: flex; flex-direction: column; gap: 6px; }
.pp-tl__top {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}
.pp-tl__when {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--pp-text);
}
.pp-tl__rel {
    font-size: 0.7rem;
    color: var(--pp-muted);
    opacity: 0.75;
}
.pp-tl__row {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}
.pp-tl__tag :deep(.p-tag) {
    font-size: 0.62rem !important;
    padding: 2px 8px !important;
    border-radius: 100px !important;
}
.pp-tl__chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.66rem;
    color: var(--pp-muted);
    padding: 2px 8px;
    border-radius: 100px;
    background: var(--pp-bg);
    border: 1px solid var(--pp-border);
}
.pp-tl__chip i { font-size: 0.6rem; opacity: 0.7; }
.pp-tl__chip--dim { opacity: 0.7; }
.pp-tl__note {
    margin: 0;
    font-size: 0.74rem;
    color: var(--pp-muted);
    line-height: 1.5;
    padding: 6px 10px;
    background: var(--pp-bg);
    border-left: 2px solid var(--tl-c);
    border-radius: 4px;
}

/* ─── MENSAGENS ─── */
.pp-msgs {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.pp-msg {
    background: var(--pp-bg);
    border: 1px solid var(--pp-border);
    border-radius: 12px;
    padding: 10px 12px;
    transition: border-color 0.16s ease, transform 0.16s ease;
}
.pp-msg:hover {
    transform: translateX(2px);
    border-color: color-mix(in srgb, var(--pp-primary) 30%, var(--pp-border));
}
.pp-msg--in  { border-left: 3px solid #4ade80; }
.pp-msg--out { border-left: 3px solid #60a5fa; }
.pp-msg__meta {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.66rem;
    color: var(--pp-muted);
    margin-bottom: 5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
}
.pp-msg__meta i { font-size: 0.65rem; }
.pp-msg--in .pp-msg__meta i { color: #4ade80; }
.pp-msg--out .pp-msg__meta i { color: #60a5fa; }
.pp-msg__sep { opacity: 0.4; }
.pp-msg__body {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--pp-text);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ─── NOTAS ─── */
.pp-notes {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.pp-note {
    padding: 12px 14px;
    background: var(--pp-bg);
    border: 1px solid var(--pp-border);
    border-radius: 12px;
}
.pp-note__label {
    margin: 0 0 6px 0;
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-weight: 700;
    color: var(--pp-muted);
    opacity: 0.65;
    display: flex;
    align-items: center;
    gap: 5px;
}
.pp-note__label i { font-size: 0.6rem; }
.pp-note__text {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.55;
    color: var(--pp-text);
    white-space: pre-wrap;
    word-break: break-word;
}

@keyframes pp-fade {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ════════════════════════════════════════════════════════════════
   ABA CONVERSAS — KPIs + CTA + PatientConversationsTab.
   ════════════════════════════════════════════════════════════════ */
.pp-conv {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.pp-conv__kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}
@media (max-width: 1100px) { .pp-conv__kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px)  { .pp-conv__kpis { grid-template-columns: 1fr; } }

.pp-conv__cta {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: 1px dashed color-mix(in srgb, var(--primary-color) 30%, var(--surface-border));
    border-radius: 14px;
    background: color-mix(in srgb, var(--primary-color) 4%, transparent);
}
.pp-conv__cta-hint {
    font-size: 0.74rem;
    color: var(--text-color-secondary);
    line-height: 1.4;
    flex: 1;
    min-width: 0;
}
@media (max-width: 520px) {
    .pp-conv__cta { flex-direction: column; align-items: stretch; }
    .pp-conv__cta-hint { text-align: center; }
}

.pp-conv__list { padding: 14px 16px; animation: pp-fade 0.4s ease both; }

/* ════════════════════════════════════════════════════════════════
   ABA DOCUMENTOS — KPIs + DocumentsListPage embedded num panel.
   ════════════════════════════════════════════════════════════════ */
.pp-doc {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.pp-doc__kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}
@media (max-width: 1100px) { .pp-doc__kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px)  { .pp-doc__kpis { grid-template-columns: 1fr; } }

.pp-doc__list { padding: 14px 16px; animation: pp-fade 0.4s ease both; }

/* O DocumentsListPage embedded já tem header próprio — só refinamos
   pra integrar com o panel: removemos seu margin-bottom default e
   usamos as cores do tema. */
.pp-doc__list :deep(.pi-spinner) { color: var(--primary-color); }

/* ════════════════════════════════════════════════════════════════
   ABA PRONTUÁRIO EVOLUTIVO — wrapper só pra dar respiro ao empty.
   ════════════════════════════════════════════════════════════════ */
.pp-pron {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* ════════════════════════════════════════════════════════════════
   ABA AGENDA — KPIs + filtros pill + lista agrupada por mês.
   ════════════════════════════════════════════════════════════════ */
.pp-ag {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.pp-ag__kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}
@media (max-width: 1100px) { .pp-ag__kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px)  { .pp-ag__kpis { grid-template-columns: 1fr; } }

/* Filtros pill */
.pp-ag__filters {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.pp-ag__filter {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 100px;
    border: 1px solid var(--surface-border);
    background: var(--surface-card);
    color: var(--text-color-secondary);
    font-size: 0.74rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 140ms ease;
}
.pp-ag__filter i { font-size: 0.7rem; opacity: 0.7; }
.pp-ag__filter:hover {
    color: var(--text-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--surface-border));
}
.pp-ag__filter.is-active {
    color: var(--primary-color);
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 35%, transparent);
    font-weight: 600;
}
.pp-ag__filter.is-active i { opacity: 1; }

.pp-ag__group { animation: pp-fade 0.4s ease both; }

.pp-ag__list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.pp-ag__item {
    --st-c: #94a3b8;
    display: grid;
    grid-template-columns: 80px 1fr auto;
    gap: 14px;
    padding: 12px 18px;
    border-top: 1px solid var(--surface-border);
    transition: background-color 140ms ease;
}
.pp-ag__item:hover {
    background: color-mix(in srgb, var(--text-color) 3%, transparent);
}
.pp-ag__item:hover .pp-ag__actions { opacity: 1; }
.pp-ag__item[data-status*="realiz"] { --st-c: #4ade80; }
.pp-ag__item[data-status*="present"] { --st-c: #4ade80; }
.pp-ag__item[data-status*="falt"] { --st-c: #f87171; }
.pp-ag__item[data-status*="cancel"], .pp-ag__item[data-status*="remarca"] { --st-c: #f59e0b; }
.pp-ag__item[data-status*="agend"] { --st-c: #60a5fa; }

.pp-ag__date {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--surface-border);
    border-left: 3px solid var(--st-c);
    border-radius: 10px;
    padding: 6px 4px;
    background: var(--surface-card);
    min-width: 72px;
}
.pp-ag__date-dow {
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-color-secondary);
}
.pp-ag__date-day {
    font-size: 1.4rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.04em;
    color: var(--text-color);
    margin: 2px 0;
}
.pp-ag__date-time {
    font-size: 0.7rem;
    font-variant-numeric: tabular-nums;
    color: var(--text-color-secondary);
}

.pp-ag__main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    justify-content: center;
}
.pp-ag__top {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.pp-ag__tag :deep(.p-tag) {
    font-size: 0.62rem !important;
    padding: 2px 8px !important;
    border-radius: 100px !important;
}
.pp-ag__chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.66rem;
    color: var(--text-color-secondary);
    padding: 2px 8px;
    border-radius: 100px;
    background: var(--surface-ground);
    border: 1px solid var(--surface-border);
}
.pp-ag__chip i { font-size: 0.6rem; opacity: 0.75; }
.pp-ag__chip--dim { opacity: 0.7; }
.pp-ag__rel {
    margin-left: auto;
    font-size: 0.66rem;
    color: var(--text-color-secondary);
    opacity: 0.75;
}
.pp-ag__title {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pp-ag__note {
    margin: 0;
    font-size: 0.74rem;
    color: var(--text-color-secondary);
    line-height: 1.5;
    padding: 6px 10px;
    background: var(--surface-ground);
    border-left: 2px solid var(--st-c);
    border-radius: 4px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.pp-ag__actions {
    display: flex;
    flex-direction: column;
    gap: 4px;
    opacity: 0;
    transition: opacity 140ms ease;
    align-self: center;
}
.pp-ag__act {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border: 1px solid var(--surface-border);
    background: var(--surface-card);
    border-radius: 8px;
    color: var(--text-color-secondary);
    cursor: pointer;
    transition: all 140ms ease;
    font-size: 0.78rem;
}
.pp-ag__act:hover:not(:disabled) {
    transform: translateX(-1px);
}
.pp-ag__act:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.pp-ag__act--ok:hover:not(:disabled)     { color: rgb(16, 185, 129); border-color: rgba(16, 185, 129, 0.5); background: rgba(16, 185, 129, 0.10); }
.pp-ag__act--warn:hover:not(:disabled)   { color: rgb(245, 158, 11); border-color: rgba(245, 158, 11, 0.5); background: rgba(245, 158, 11, 0.10); }
.pp-ag__act--danger:hover:not(:disabled) { color: rgb(239, 68, 68);  border-color: rgba(239, 68, 68, 0.5);  background: rgba(239, 68, 68, 0.10); }

@media (max-width: 760px) {
    .pp-ag__item { grid-template-columns: 64px 1fr; padding: 10px 14px; }
    .pp-ag__actions { grid-column: 1 / -1; flex-direction: row; opacity: 1; justify-self: end; }
    .pp-ag__rel { margin-left: 0; }
}

/* ════════════════════════════════════════════════════════════════
   ABA FINANCEIRO — KPIs no topo + tabela de lançamentos.
   ════════════════════════════════════════════════════════════════ */
.pp-fin {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.pp-fin__kpis {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 14px;
}
@media (max-width: 760px) { .pp-fin__kpis { grid-template-columns: 1fr; } }

.pp-fin__list { animation: pp-fade 0.4s ease both; }

.pp-fin__table {
    display: flex;
    flex-direction: column;
}
.pp-fin__row {
    display: grid;
    grid-template-columns: 130px 1fr 110px 110px 110px;
    align-items: center;
    gap: 12px;
    padding: 10px 18px;
    border-top: 1px solid var(--surface-border);
    transition: background-color 140ms ease;
    font-size: 0.78rem;
}
.pp-fin__row:not(.pp-fin__row--head):hover {
    background: color-mix(in srgb, var(--text-color) 3%, transparent);
}
.pp-fin__row--head {
    border-top: none;
    padding: 10px 18px;
    background: var(--surface-ground);
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-color-secondary);
    opacity: 0.7;
}
@media (max-width: 760px) {
    .pp-fin__row {
        grid-template-columns: 1fr 1fr;
        gap: 6px 12px;
    }
    .pp-fin__row--head { display: none; }
    .pp-fin__date { grid-column: 1 / 2; order: 1; }
    .pp-fin__amount { grid-column: 2 / 3; order: 2; text-align: right; }
    .pp-fin__desc { grid-column: 1 / -1; order: 3; }
    .pp-fin__method { grid-column: 1 / 2; order: 4; }
    .pp-fin__status-cell { grid-column: 2 / 3; order: 5; justify-self: end; }
}

.pp-fin__col-amount { text-align: right; }
.pp-fin__date {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.pp-fin__date-main {
    font-weight: 600;
    color: var(--text-color);
    font-variant-numeric: tabular-nums;
}
.pp-fin__date-rel {
    font-size: 0.66rem;
    color: var(--text-color-secondary);
    opacity: 0.75;
}
.pp-fin__desc {
    color: var(--text-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pp-fin__method {
    color: var(--text-color-secondary);
    font-size: 0.74rem;
}
.pp-fin__amount {
    font-weight: 700;
    color: var(--text-color);
    text-align: right;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.pp-fin__row[data-status="vencido"] .pp-fin__amount { color: rgb(239, 68, 68); }
.pp-fin__row[data-status="pago"]    .pp-fin__amount { color: rgb(16, 185, 129); }

.pp-fin__status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 100px;
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    border: 1px solid;
    --st-c: #94a3b8;
    --st-bg: rgba(148, 163, 184, 0.10);
    --st-border: rgba(148, 163, 184, 0.30);
    color: var(--st-c);
    background: var(--st-bg);
    border-color: var(--st-border);
}
.pp-fin__status[data-status="pago"] {
    --st-c: rgb(16, 185, 129);
    --st-bg: rgba(16, 185, 129, 0.10);
    --st-border: rgba(16, 185, 129, 0.30);
}
.pp-fin__status[data-status="pendente"] {
    --st-c: var(--primary-color);
    --st-bg: color-mix(in srgb, var(--primary-color) 10%, transparent);
    --st-border: color-mix(in srgb, var(--primary-color) 30%, transparent);
}
.pp-fin__status[data-status="vencido"] {
    --st-c: rgb(239, 68, 68);
    --st-bg: rgba(239, 68, 68, 0.10);
    --st-border: rgba(239, 68, 68, 0.30);
}
.pp-fin__status-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--st-c);
    box-shadow: 0 0 6px var(--st-c);
}

/* ════════════════════════════════════════════════════════════════
   AÇÕES da sidebar — espelha .evento-actions do MelissaEventoPanel.
   Status da próxima sessão (Realizada/Falta/Reagendar/Cancelar)
   + atalhos (Sessões/Conversar/Editar).
   ════════════════════════════════════════════════════════════════ */
.pp-actions {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-bottom: 14px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--surface-border);
}
.pp-actions__section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.pp-actions__label {
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-color-secondary);
    opacity: 0.7;
    padding-left: 2px;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.pp-actions__hint {
    font-size: 0.6rem;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.7;
    font-style: italic;
}
.pp-actions__group {
    display: flex;
    gap: 4px;
    background: var(--surface-ground);
    border: 1px solid var(--surface-border);
    border-radius: 12px;
    padding: 4px;
}
.pp-act {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 8px 4px;
    background: transparent;
    border: none;
    color: var(--text-color);
    border-radius: 9px;
    cursor: pointer;
    font-size: 1rem;
    font-family: inherit;
    transition: background-color 140ms ease, color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}
.pp-act__label {
    font-size: 0.68rem;
    line-height: 1.1;
    font-weight: 500;
    letter-spacing: 0.01em;
    white-space: nowrap;
}
.pp-act:hover:not(:disabled) {
    background: color-mix(in srgb, var(--text-color) 6%, transparent);
    transform: translateY(-1px);
}
.pp-act:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}
.pp-act:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.pp-act--ok:hover:not(:disabled) {
    color: rgb(16, 185, 129);
    background: rgba(16, 185, 129, 0.12);
}
.pp-act--warn:hover:not(:disabled) {
    color: rgb(245, 158, 11);
    background: rgba(245, 158, 11, 0.12);
}
.pp-act--danger:hover:not(:disabled) {
    color: rgb(239, 68, 68);
    background: rgba(239, 68, 68, 0.12);
}
/* Estado .is-current — destaca o status atual da próxima sessão */
.pp-act.is-current {
    background: color-mix(in srgb, var(--text-color) 10%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-color) 20%, transparent);
}
.pp-act--ok.is-current {
    color: rgb(16, 185, 129);
    background: rgba(16, 185, 129, 0.16);
    box-shadow: inset 0 0 0 1px rgba(16, 185, 129, 0.5);
}
.pp-act--warn.is-current {
    color: rgb(245, 158, 11);
    background: rgba(245, 158, 11, 0.16);
    box-shadow: inset 0 0 0 1px rgba(245, 158, 11, 0.5);
}
.pp-act--danger.is-current {
    color: rgb(239, 68, 68);
    background: rgba(239, 68, 68, 0.16);
    box-shadow: inset 0 0 0 1px rgba(239, 68, 68, 0.5);
}
</style>
