<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/agenda/components/AgendaEventDialogV2.vue
| Data: 2026-05-05
|
| A66 sub-sessão 2 — Template V2 disruptivo (3 zonas).
| Esqueleto pra iterar visualmente em /preview/agenda-dialog-v2 antes de
| subir pra produção (sub-sessão 3 troca o V1 pelo V2).
|
| 3 zonas:
|   • PACIENTE (hero)  — avatar 64px, status, atalhos, lock visual
|   • QUANDO (hero)    — data tipográfica grande, chips duração, recorrência
|   • O QUÊ (detalhes) — commitment-grid, modalidade pill, financeiro inline
| + Sticky save bar com estado de validação inline.
|
| Contrato props/emits: 100% idêntico ao V1 (zero quebra na API externa).
| Script setup: cópia integral do V1 (mesmos 5 composables + helpers).
|--------------------------------------------------------------------------
-->
<script setup>
import { computed, ref, watch, nextTick } from 'vue';
import { generateGoogleCalendarLink, formatGCalDate, addMinutesToHHMM } from '@/utils/googleCalendarLink';
import { useRouter, useRoute } from 'vue-router';
import Select from 'primevue/select';
import Textarea from 'primevue/textarea';
import DatePicker from 'primevue/datepicker';
import InputNumber from 'primevue/inputnumber';
import Message from 'primevue/message';
import { useConfirm } from 'primevue/useconfirm';
import { useToast } from 'primevue/usetoast';
import { supabase } from '@/lib/supabase/client';
import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue';
import AgendaEventoFinanceiroPanel from '@/components/agenda/AgendaEventoFinanceiroPanel.vue';
import ServiceQuickCreateDialog from './ServiceQuickCreateDialog.vue';
import InsurancePlanQuickCreateDialog from './InsurancePlanQuickCreateDialog.vue';
import { useServices } from '@/features/agenda/composables/useServices';
import { useCommitmentServices } from '@/features/agenda/composables/useCommitmentServices';
import { usePatientDiscounts } from '@/features/agenda/composables/usePatientDiscounts';
import { useInsurancePlans } from '@/features/agenda/composables/useInsurancePlans';

import {
    patientInitials,
    fmtBRL,
    fmtJornadaHora,
    fmtDateBR,
    fmtDateBRLong,
    fmtTime,
    fmtDuracao,
    nomeDiaSemana,
    fmtWeekdayShort,
    fmtDayNum,
    fmtMonthShort,
    hhmmToMin,
    minToHHMM,
    isPast,
    isNativeSession,
    calcFinalPrice,
    labelStatusSessao,
    statusSeverity,
    statusExtraClass
} from '@/features/agenda/composables/agendaEventHelpers';

import { useAgendaEventComposer } from '@/features/agenda/composables/useAgendaEventComposer';
import { useAgendaEventActions } from '@/features/agenda/composables/useAgendaEventActions';
import { useAgendaEventPickerBilling } from '@/features/agenda/composables/useAgendaEventPickerBilling';
import { useAgendaEventLifecycle } from '@/features/agenda/composables/useAgendaEventLifecycle';

const props = defineProps({
    modelValue: { type: Boolean, default: false },
    eventRow: { type: Object, default: null },
    initialStartISO: { type: String, default: '' },
    initialEndISO: { type: String, default: '' },

    ownerId: { type: String, default: '' },
    planOwnerId: { type: String, default: '' },
    allowOwnerEdit: { type: Boolean, default: false },
    ownerOptions: { type: Array, default: () => [] },

    tenantId: { type: String, default: '' },

    commitmentOptions: { type: Array, default: () => [] },
    presetCommitmentId: { type: [String, null], default: null },
    lockCommitment: { type: Boolean, default: false },

    restrictPatientsToOwner: { type: Boolean, default: false },
    patientScopeOwnerId: { type: String, default: null },

    workRules: { type: Array, default: () => [] },
    blockedDates: { type: Array, default: () => [] },
    agendaSettings: { type: Object, default: null },
    allEvents: { type: Array, default: () => [] },
    pausasSemanais: { type: Array, default: () => [] },
    feriados: { type: Array, default: () => [] },

    newPatientRoute: { type: String, default: '' }
});

const emit = defineEmits(['update:modelValue', 'save', 'delete', 'updateSeriesEvent', 'editSeriesOccurrence', 'updated']);
const confirm = useConfirm();
const toast = useToast();
const router = useRouter();
const route = useRoute();

const commitmentItems = ref([]);
const serieEvents = ref([]);

const _composer = useAgendaEventComposer(props, emit, { commitmentItems, serieEvents });
const {
    visible, step, editScope, recorrenciaType, diasSelecionados,
    qtdSessoesMode, qtdSessoesCustom, dataLimiteManual, billingType, form,
    isEdit, allowBack, hasSerie, currentRecurrenceDate, isFirstOccurrence,
    editScopeOptions, qtdSessoesEfetiva, diaSemanaRecorrencia,
    proximasOcorrencias, dataFimCalculada, totalOcorrencias,
    sessoesForaDoPlano, ocorrenciasComConflito, totalConflitos,
    commitmentCards, selectedCommitment, selectedCommitmentName,
    selectedCommitmentFields, requiresPatient, isSessionEvent,
    patientLocked, hasInsurance, agendaPerms, isSessionFuture,
    isArchivedPastEdit, isInativoFutureEdit, statusOptionsFiltered,
    startTimeDate, inicioDateTime, fimDateTime, dataHoraDisplay,
    previewRange, computedTitulo, headerTitle, canSave, timeConflict,
    toggleDiaSelecionado, isForaDoPlano, resetForm
} = _composer;

const freqOpcoes = [
    { value: 'avulsa', label: 'Avulsa' },
    { value: 'semanal', label: 'Semanal' },
    { value: 'quinzenal', label: 'Quinzenal' },
    { value: 'diasEspecificos', label: 'Dias específicos' }
];

const diasSemanaOpcoes = [
    { value: 1, short: 'Seg' }, { value: 2, short: 'Ter' }, { value: 3, short: 'Qua' },
    { value: 4, short: 'Qui' }, { value: 5, short: 'Sex' }, { value: 6, short: 'Sáb' },
    { value: 0, short: 'Dom' }
];

function setHoje() { form.value.dia = new Date(); }

const qtdSessoesOpcoes = [
    { value: '4', label: '4 sessões' }, { value: '8', label: '8 sessões' },
    { value: '12', label: '12 sessões' }, { value: 'personalizar', label: 'Personalizar' }
];

const { services, getDefaultPrice, load: loadServices } = useServices();
const { loadItems: _csLoadItems, saveItems: saveCommitmentItems, loadItemsOrTemplate: _csLoadItemsOrTemplate } = useCommitmentServices();
const { loadActive: loadActiveDiscount } = usePatientDiscounts();
const { plans: insurancePlans, load: loadInsurancePlans } = useInsurancePlans();
const selectedPlanService = ref(null);

const activePlans = computed(() => insurancePlans.value.filter((p) => p.active !== false));
const planServices = computed(() => {
    if (!form.value.insurance_plan_id) return [];
    return (insurancePlans.value.find((p) => p.id === form.value.insurance_plan_id)?.insurance_plan_services || []).filter((s) => s.active);
});

const servicePickerSel = ref(null);
const serieValorMode = ref('multiplicar');
const isDynamic = computed(() => (props.agendaSettings?.slot_mode ?? 'fixed') === 'dynamic');

const billingTypeOptions = [
    { label: 'Gratuito', value: 'gratuito' },
    { label: 'Particular', value: 'particular' },
    { label: 'Convênio', value: 'convenio' }
];

const _actions = useAgendaEventActions({
    composer: _composer, commitmentItems, servicePickerSel,
    selectedPlanService, saveCommitmentItems, props, emit
});
const { _skipStatusWatch, _prevStatus, _restoringConvenio, samePatientConflict, onSave, onDelete, onEncerrarSerie } = _actions;

const _pickerBilling = useAgendaEventPickerBilling({
    composer: _composer, actions: _actions, commitmentItems, servicePickerSel,
    selectedPlanService, services, loadServices, getDefaultPrice, planServices,
    loadActiveDiscount, _csLoadItems, _csLoadItemsOrTemplate, isDynamic, props
});
const {
    pacientePickerOpen, pacienteSearch, pacientesLoading, pacientesError,
    patients, cadRapidoOpen, ensureServicesLoaded, resetServicesGate,
    applyDefaultPrice, addItem, removeItem, onItemChange,
    _loadCommitmentItemsForEvent, onProcedureSelect, selectCommitment,
    goBack, openPacientePicker, clearPatientsCache, loadPatients,
    selectPaciente, clearPaciente, openCadastroRapido, abrirCadastroCompleto
} = _pickerBilling;

const _lifecycle = useAgendaEventLifecycle({
    composer: _composer, actions: _actions, pickerBilling: _pickerBilling,
    commitmentItems, serieEvents, servicePickerSel, selectedPlanService,
    serieValorMode, services, loadServices, loadInsurancePlans,
    props, emit, confirm, toast
});
const {
    solicitacaoPendente, onlineSlots, loadingOnlineSlots, serieLoading,
    pillDeleteMenuRef, pillDeleteTarget, sendingReminder,
    serviceQuickDlgOpen, insuranceQuickDlgOpen, serieCountByStatus,
    pillDeleteMenuItems, loadSerieEvents, onPillEditClick, onPillStatusChange,
    onPillDeleteClick, onPillDelete, selectSlot, openServiceQuickCreate,
    onServiceCreated, openInsuranceQuickCreate, onInsuranceCreated, onSendManualReminder
} = _lifecycle;

const totalFromItems = computed(() => commitmentItems.value.reduce((sum, item) => sum + (item.final_price ?? 0), 0));
const dynamicDuration = computed(() => {
    if (!isDynamic.value) return null;
    return commitmentItems.value.reduce((sum, item) => {
        const svc = services.value.find((s) => s.id === item.service_id);
        return sum + (svc?.duration_min ?? 0);
    }, 0);
});
const displayPrice = computed(() => (commitmentItems.value.length > 0 ? totalFromItems.value : form.value.price));
const serieValorAviso = computed(() => {
    if (recorrenciaType.value === 'avulsa' || !commitmentItems.value.length) return null;
    const n = qtdSessoesEfetiva.value;
    if (!n || !totalFromItems.value) return null;
    if (serieValorMode.value === 'multiplicar') {
        return `Total da série: ${fmtBRL(totalFromItems.value * n)} (${fmtBRL(totalFromItems.value)} × ${n} sessões)`;
    }
    return `Valor por sessão: ${fmtBRL(totalFromItems.value / n)} (${fmtBRL(totalFromItems.value)} ÷ ${n} sessões)`;
});

watch(totalFromItems, (total) => { if (commitmentItems.value.length > 0) form.value.price = total; });
watch(dynamicDuration, (dur) => { if (isDynamic.value && dur != null && dur > 0) form.value.duracaoMin = dur; });

const jornadaDialog = computed(() => {
    const rules = props.workRules;
    if (!rules?.length) return null;
    const d = form.value.dia ? new Date(form.value.dia) : new Date();
    const dow = d.getDay();
    const rule = rules.find((r) => Number(r.dia_semana) === dow);
    if (!rule) return { text: 'Este é um dia de folga na sua agenda.', isOff: true };
    const inicio = String(rule.hora_inicio || '').slice(0, 5);
    const fim = String(rule.hora_fim || '').slice(0, 5);
    const [h1, m1] = inicio.split(':').map(Number);
    const [h2, m2] = fim.split(':').map(Number);
    const totalMin = h2 * 60 + m2 - (h1 * 60 + m1);
    const durH = Math.floor(totalMin / 60);
    const durM = totalMin % 60;
    const durStr = durM > 0 ? `${durH}h${String(durM).padStart(2, '0')}` : `${durH}h`;
    return { text: `Jornada: das ${fmtJornadaHora(inicio)} às ${fmtJornadaHora(fim)} (${durStr})`, isOff: false };
});

const blockedSet = computed(() => new Set(props.blockedDates || []));
const formDayISO = computed(() => {
    const d = form.value.dia ? new Date(form.value.dia) : null;
    if (!d) return '';
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
});
const isDayBlocked = computed(() => !!formDayISO.value && blockedSet.value.has(formDayISO.value));
const isSessionBlockedByDay = computed(() => isDayBlocked.value && isSessionEvent.value);
const isDiaFolga = computed(() => {
    if (!form.value.dia || !props.workRules?.length) return false;
    const dow = new Date(form.value.dia).getDay();
    return !props.workRules.some((r) => Number(r.dia_semana) === dow);
});

const timePickerOpen = ref(false);

const modalidadeOptions = [
    { label: 'Presencial', value: 'presencial' },
    { label: 'Online', value: 'online' }
];

function onPatientCreatedRapido(p) {
    if (!p) return;
    const nome = p.nome_completo || p.nome || p.name || '';
    form.value.paciente_id = p.id;
    form.value.paciente_nome = nome;
    form.value.paciente_avatar = p.avatar_url || null;
    cadRapidoOpen.value = false;
}

// Mostra TODOS os pacientes (inclusive Inativo/Arquivado) — UX intencional:
// nao-Ativos vem com badge + disabled no template, ordenados pro final.
// selectPaciente bloqueia o clique se status !== 'Ativo'.
const _aev2StatusRank = { Ativo: 0, Inativo: 1, Arquivado: 2 };
const filteredPatients = computed(() => {
    const q = String(pacienteSearch.value || '').trim().toLowerCase();
    const list = patients.value || [];
    const matched = !q
        ? [...list]
        : list.filter((p) => {
              const nome = String(p.nome || '').toLowerCase();
              const email = String(p.email || '').toLowerCase();
              const tel = String(p.telefone || '').toLowerCase();
              return nome.includes(q) || email.includes(q) || tel.includes(q);
          });
    return matched.sort((a, b) => (_aev2StatusRank[a.status] ?? 3) - (_aev2StatusRank[b.status] ?? 3));
});

function goToAgendamentosRecebidos() {
    visible.value = false;
    const prefix = route.path.startsWith('/admin') ? '/admin' : '/therapist';
    router.push(`${prefix}/agendamentos-recebidos`);
}

function goToConveniosConfig() {
    visible.value = false;
    const prefix = route.path.startsWith('/admin') ? '/admin' : '/therapist';
    router.push(`${prefix}/configuracoes/convenios`);
}

const duracaoOptions = computed(() => {
    const defaultDur = props.agendaSettings?.session_duration_min || 50;
    const defaultGap = props.agendaSettings?.session_break_min || 0;
    const ALL_PRESETS = [
        { label: '30 min', dur: 30, gap: 0 }, { label: '40 min', dur: 40, gap: 0 },
        { label: '45 min', dur: 45, gap: 15 }, { label: '50 min', dur: 50, gap: 10 },
        { label: '60 min', dur: 60, gap: 0 }, { label: '90 min', dur: 90, gap: 0 },
        { label: '2h', dur: 120, gap: 0 }
    ];
    const defaultItem = {
        label: `${defaultDur} min${defaultGap > 0 ? ` + ${defaultGap}min pausa` : ''}  ✦ padrão`,
        value: defaultDur
    };
    const others = ALL_PRESETS.filter((p) => p.dur !== defaultDur);
    const wBreak = others.filter((p) => p.gap > 0);
    const noBreak = others.filter((p) => p.gap === 0);
    const groups = [{ label: 'Padrão da agenda', items: [defaultItem] }];
    if (wBreak.length) groups.push({ label: 'Com pausa', items: wBreak.map((p) => ({ label: `${p.label} + ${p.gap}min pausa`, value: p.dur })) });
    if (noBreak.length) groups.push({ label: 'Sem pausa', items: noBreak.map((p) => ({ label: p.label, value: p.dur })) });
    return groups;
});

// V2 — chips de duração rápida (presets fixos pra reduzir cliques)
const duracaoQuickChips = [30, 50, 60, 90];

const availableSlots = computed(() => {
    const dia = form.value.dia;
    if (!dia || !props.workRules?.length) return [];
    const dow = new Date(dia).getDay();
    const dur = props.agendaSettings?.session_duration_min || 50;
    const gap = props.agendaSettings?.session_break_min || 0;
    const cycle = Math.max(1, dur + gap);
    const windows = (props.workRules || [])
        .filter((r) => Number(r.dia_semana) === dow && r.ativo !== false)
        .map((r) => ({ start: String(r.hora_inicio || '').slice(0, 5), end: String(r.hora_fim || '').slice(0, 5) }))
        .sort((a, b) => a.start.localeCompare(b.start));
    if (!windows.length) return [];
    const breaks = (props.pausasSemanais || []).filter((p) => p.dia_semana == null || Number(p.dia_semana) === dow).map((p) => ({ s: hhmmToMin(p.hora_inicio || '00:00'), e: hhmmToMin(p.hora_fim || '00:00') }));
    const todayStr = dia instanceof Date ? `${dia.getFullYear()}-${String(dia.getMonth() + 1).padStart(2, '0')}-${String(dia.getDate()).padStart(2, '0')}` : String(dia).slice(0, 10);
    const busySlots = (props.allEvents || [])
        .filter((e) => {
            if (!e.inicio_em) return false;
            return e.inicio_em.slice(0, 10) === todayStr && e.id !== form.value.id;
        })
        .map((e) => ({
            s: hhmmToMin(e.inicio_em.slice(11, 16)),
            e: e.fim_em ? hhmmToMin(e.fim_em.slice(11, 16)) : hhmmToMin(e.inicio_em.slice(11, 16)) + dur
        }));
    const slots = [];
    for (const w of windows) {
        const wStart = hhmmToMin(w.start);
        const wEnd = hhmmToMin(w.end);
        let t = wStart;
        while (t + dur <= wEnd) {
            const aEnd = t + dur;
            const brk = breaks.find((b) => !(aEnd <= b.s || t >= b.e));
            if (brk) { t = brk.e; continue; }
            const busy = busySlots.some((b) => !(aEnd <= b.s || t >= b.e));
            slots.push({ hhmm: minToHHMM(t), endHhmm: minToHHMM(aEnd), busy });
            t += cycle;
        }
    }
    const seen = new Set();
    return slots.filter((s) => { if (seen.has(s.hhmm)) return false; seen.add(s.hhmm); return true; });
});

const PERIODOS = [
    { label: 'Manhã', icon: 'pi-sun', from: '05:00', to: '12:00' },
    { label: 'Tarde', icon: 'pi-cloud', from: '12:00', to: '18:00' },
    { label: 'Noite', icon: 'pi-moon', from: '18:00', to: '24:00' }
];
const selectedPeriodo = ref(null);
const activePeriodos = computed(() => PERIODOS.filter((p) => availableSlots.value.some((s) => s.hhmm >= p.from && s.hhmm < p.to)));
const onlineConfigSet = computed(() => new Set((onlineSlots.value || []).map((s) => s.hhmm)));
const filteredSlots = computed(() => {
    const base = selectedPeriodo.value ? availableSlots.value.filter((s) => s.hhmm >= selectedPeriodo.value.from && s.hhmm < selectedPeriodo.value.to) : availableSlots.value;
    return base.map((s) => ({ ...s, isOnlineConfigured: onlineConfigSet.value.has(s.hhmm) }));
});

const onlineAtivo = computed(() => !!props.agendaSettings?.online_ativo);
const onlineDisponivel = computed(() => (form.value.modalidade === 'online' ? onlineAtivo.value && onlineSlots.value.length > 0 : true));

const dayWorkRule = computed(() => {
    if (!form.value.dia || !props.workRules?.length) return null;
    const dow = new Date(form.value.dia).getDay();
    return props.workRules.find((r) => Number(r.dia_semana) === dow) ?? null;
});

const serieDiaSemana = computed(() => {
    if (props.eventRow?.serie_dia_semana != null) return Number(props.eventRow.serie_dia_semana);
    const iso = props.eventRow?.inicio_em;
    if (iso) return new Date(iso).getDay();
    return form.value.dia ? new Date(form.value.dia).getDay() : null;
});
const serieHoraDisplay = computed(() => {
    if (props.eventRow?.serie_hora) return props.eventRow.serie_hora;
    return form.value.startTime || null;
});

const statusOptions = [
    { label: 'Agendado', value: 'agendado' },
    { label: 'Realizado', value: 'realizado' },
    { label: 'Faltou', value: 'faltou' },
    { label: 'Cancelado', value: 'cancelado' },
    { label: 'Remarcar', value: 'remarcado' }
];

const googleCalendarUrl = computed(() => {
    const dia = form.value.dia;
    const hora = form.value.startTime;
    if (!dia || !hora) return null;
    const start = formatGCalDate(dia, hora);
    const endHHMM = addMinutesToHHMM(hora, form.value.duracaoMin || 50);
    const end = formatGCalDate(dia, endHHMM);
    const paciente = form.value.paciente_nome ? ` — ${form.value.paciente_nome}` : '';
    const title = (form.value.titulo_custom?.trim() || 'Sessão') + paciente;
    const location = form.value.modalidade === 'online' ? 'Atendimento Online' : '';
    return generateGoogleCalendarLink({
        title, description: form.value.observacoes?.trim() || '',
        location, start, end
    });
});

// ─── V2-only: hint de validação inline pra sticky bar ──────────
const validationHint = computed(() => {
    if (canSave.value) return null;
    const missing = [];
    if (isSessionEvent.value && !form.value.paciente_id) missing.push('paciente');
    if (!form.value.dia) missing.push('data');
    if (!form.value.startTime) missing.push('horário');
    if (timeConflict.value) missing.push('conflito de horário');
    if (!missing.length) return 'Resolva campos obrigatórios';
    return `Resolva: ${missing.join(', ')}`;
});

// V2: data formatada hero ("Sex · 9 mai · 14:00")
const heroDateText = computed(() => {
    const d = form.value.dia ? new Date(form.value.dia) : null;
    if (!d) return null;
    const wd = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'][d.getDay()];
    const day = d.getDate();
    const months = ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'];
    const mo = months[d.getMonth()];
    return `${wd} · ${day} ${mo}`;
});
</script>

<template>
    <Dialog
        v-model:visible="visible"
        modal
        :draggable="false"
        :dismissableMask="true"
        :style="{ width: '1040px', maxWidth: '96vw' }"
        :breakpoints="{ '960px': '96vw', '640px': '98vw' }"
        class="aev2-dialog"
        pt:mask:class="backdrop-blur-xs"
    >
        <!-- ═════════════════ HEADER ═════════════════ -->
        <template #header>
            <div class="aev2-header">
                <div class="aev2-header__title-wrap">
                    <div
                        class="aev2-header__dot"
                        :style="selectedCommitment?.bg_color ? { background: `#${selectedCommitment.bg_color}` } : {}"
                    />
                    <div class="min-w-0">
                        <div class="aev2-header__title">{{ headerTitle }}</div>
                        <div v-if="step === 2" class="aev2-header__sub">{{ previewRange }}</div>
                    </div>
                </div>
                <!-- Edição-de-série: chips de scope inline (sem modal extra) -->
                <div v-if="isEdit && hasSerie && step === 2" class="aev2-scope-chips" role="radiogroup" aria-label="Escopo da edição">
                    <button
                        v-for="opt in editScopeOptions"
                        :key="opt.value"
                        type="button"
                        class="aev2-scope-chip"
                        :class="{ 'aev2-scope-chip--active': editScope === opt.value }"
                        :aria-pressed="editScope === opt.value"
                        @click="editScope = opt.value"
                    >
                        {{ opt.label }}
                    </button>
                </div>
            </div>
        </template>

        <!-- ════════════════ STEP 1 — escolha tipo ════════════════ -->
        <div v-if="step === 1" class="aev2-step1">
            <div class="aev2-step1__hint">Selecione o tipo de compromisso</div>
            <Message v-if="isDayBlocked" severity="warn" class="mb-4" :closable="false">
                <i class="pi pi-lock mr-1" />
                Dia bloqueado. <strong>Sessões</strong> não podem ser agendadas.
            </Message>
            <div class="aev2-commitment-grid">
                <button
                    v-for="c in commitmentCards"
                    :key="c.id"
                    type="button"
                    class="aev2-commitment-card"
                    :class="{ 'aev2-commitment-card--blocked': isDayBlocked && isNativeSession(c) }"
                    :style="c.bg_color ? { '--card-color': `#${c.bg_color}` } : {}"
                    :disabled="isDayBlocked && isNativeSession(c)"
                    @click="isDayBlocked && isNativeSession(c) ? null : selectCommitment(c)"
                >
                    <div class="aev2-commitment-card__icon" :style="c.bg_color ? { background: `#${c.bg_color}20`, color: `#${c.bg_color}` } : {}">
                        <i :class="isNativeSession(c) ? 'pi pi-user' : 'pi pi-calendar'" />
                    </div>
                    <div class="aev2-commitment-card__body">
                        <div class="aev2-commitment-card__name">{{ c.name }}</div>
                        <div v-if="c.description" class="aev2-commitment-card__desc">{{ c.description }}</div>
                        <div class="aev2-commitment-card__tags">
                            <Tag v-if="isNativeSession(c)" value="Exige paciente" severity="info" />
                            <Tag v-if="isDayBlocked && isNativeSession(c)" value="Bloqueado" severity="danger" icon="pi pi-lock" />
                        </div>
                    </div>
                    <i class="pi pi-chevron-right aev2-commitment-card__chev" />
                </button>
            </div>
        </div>

        <!-- ════════════════ STEP 2 — 3 zonas ════════════════ -->
        <div v-else class="aev2-zones">
            <!-- Avisos topo (mantido do V1) -->
            <div v-if="form.conflito || isDayBlocked || jornadaDialog || isDiaFolga || isArchivedPastEdit || (isEdit && form.paciente_status === 'Inativo' && isSessionFuture) || (isEdit && form.paciente_status === 'Arquivado' && isSessionFuture) || solicitacaoPendente" class="aev2-alerts">
                <Message v-if="form.conflito" severity="warn" :closable="false">
                    <span class="font-semibold">Conflito:</span> {{ form.conflito }}
                </Message>
                <Message v-if="isArchivedPastEdit" severity="warn" :closable="false">
                    <i class="pi pi-lock mr-1" /> <b>Paciente arquivado.</b> Histórico somente leitura.
                </Message>
                <Message v-if="isEdit && form.paciente_status === 'Inativo' && isSessionFuture" severity="warn" :closable="false">
                    <i class="pi pi-ban mr-1" /> <b>Paciente inativo.</b> Remarcação bloqueada.
                </Message>
                <Message v-if="isEdit && form.paciente_status === 'Arquivado' && isSessionFuture" severity="info" :closable="false">
                    <i class="pi pi-info-circle mr-1" /> <b>Paciente arquivado.</b> Sessão futura editável; novos agendamentos e recorrências bloqueados.
                </Message>
                <Message v-if="solicitacaoPendente && isSessionEvent && !isEdit" severity="info" :closable="false">
                    <div class="flex items-center justify-between gap-3 w-full flex-wrap">
                        <span><i class="pi pi-inbox mr-1" /> Solicitação pendente de <b>{{ solicitacaoPendente.paciente_nome }} {{ solicitacaoPendente.paciente_sobrenome }}</b></span>
                        <Button label="Ver solicitações" icon="pi pi-arrow-right" size="small" severity="info" outlined class="rounded-full shrink-0" @click="goToAgendamentosRecebidos" />
                    </div>
                </Message>
                <Message v-if="jornadaDialog" :severity="jornadaDialog.isOff ? 'warn' : 'info'" :closable="false">
                    <i :class="jornadaDialog.isOff ? 'pi pi-moon mr-1' : 'pi pi-clock mr-1'" /> {{ jornadaDialog.text }}
                </Message>
            </div>

            <!-- ─────────────── ZONA 1: PACIENTE (hero) ─────────────── -->
            <section v-if="isSessionEvent" class="aev2-zone aev2-zone--patient" :class="{ 'aev2-zone--locked': patientLocked }">
                <header class="aev2-zone__header">
                    <i class="pi pi-user aev2-zone__icon" />
                    <span class="aev2-zone__label">Paciente</span>
                    <div v-if="!patientLocked" class="aev2-zone__actions">
                        <Button label="Cadastro rápido" icon="pi pi-user-plus" size="small" severity="secondary" outlined class="rounded-full text-xs h-7" @click="cadRapidoOpen = true" />
                        <Button icon="pi pi-external-link" size="small" severity="secondary" text class="rounded-full h-7 w-7" v-tooltip.top="'Cadastro completo (nova aba)'" @click="abrirCadastroCompleto" />
                    </div>
                </header>

                <button v-if="!form.paciente_id" type="button" class="aev2-patient-empty" @click="openPacientePicker">
                    <div class="aev2-patient-empty__icon"><i class="pi pi-user-plus" /></div>
                    <div class="flex-1 text-left">
                        <div class="font-semibold">Selecionar paciente</div>
                        <div class="text-xs opacity-70">Toque para buscar</div>
                    </div>
                    <i class="pi pi-chevron-right opacity-50" />
                </button>

                <div v-else class="aev2-patient-card">
                    <Avatar v-if="form.paciente_avatar" :image="form.paciente_avatar" shape="circle" size="xlarge" class="aev2-patient-avatar" />
                    <Avatar v-else :label="patientInitials(form.paciente_nome)" shape="circle" size="xlarge" class="aev2-patient-avatar aev2-patient-avatar--initials" />

                    <div class="aev2-patient-info">
                        <div class="aev2-patient-name">{{ form.paciente_nome }}</div>
                        <div class="aev2-patient-badges">
                            <span class="aev2-badge aev2-badge--neutral">Paciente vinculado</span>
                            <span v-if="form.paciente_status === 'Inativo'" class="aev2-badge aev2-badge--warn">Inativo</span>
                            <span v-if="form.paciente_status === 'Arquivado'" class="aev2-badge aev2-badge--danger">Arquivado</span>
                        </div>
                    </div>

                    <div class="aev2-patient-actions">
                        <Button v-if="!patientLocked" icon="pi pi-pencil" severity="secondary" outlined size="small" class="rounded-full h-9 w-9" v-tooltip.top="'Trocar paciente'" @click="openPacientePicker" />
                        <Button v-if="!patientLocked" icon="pi pi-times" severity="secondary" text size="small" class="rounded-full h-9 w-9" v-tooltip.top="'Limpar'" @click="clearPaciente" />
                    </div>
                </div>

                <!-- Mini-toolbar: modalidade -->
                <div class="aev2-patient-modalidade">
                    <span class="text-xs opacity-70">Modalidade</span>
                    <div class="aev2-pill-group">
                        <button
                            v-for="opt in modalidadeOptions"
                            :key="opt.value"
                            type="button"
                            class="aev2-pill"
                            :class="{ 'aev2-pill--active': form.modalidade === opt.value }"
                            @click="form.modalidade = opt.value"
                        >
                            <i :class="opt.value === 'online' ? 'pi pi-video' : 'pi pi-home'" />
                            {{ opt.label }}
                        </button>
                    </div>
                </div>
            </section>

            <!-- ─────────────── ZONA 2: QUANDO (hero) ─────────────── -->
            <section class="aev2-zone aev2-zone--when">
                <header class="aev2-zone__header">
                    <i class="pi pi-calendar aev2-zone__icon" />
                    <span class="aev2-zone__label">Quando</span>
                </header>

                <div class="aev2-when-hero">
                    <!-- Data -->
                    <div class="aev2-when-date">
                        <DatePicker
                            v-model="form.dia"
                            dateFormat="dd/mm/yy"
                            :showIcon="false"
                            class="aev2-date-input"
                            inputClass="aev2-date-typo"
                        />
                        <button type="button" class="aev2-when-today" @click="setHoje" v-tooltip.top="'Hoje'">
                            <i class="pi pi-bullseye" />
                        </button>
                    </div>

                    <!-- Hora -->
                    <div class="aev2-when-time">
                        <DatePicker
                            v-model="startTimeDate"
                            timeOnly
                            hourFormat="24"
                            :showIcon="false"
                            class="aev2-time-input"
                            inputClass="aev2-date-typo"
                        />
                    </div>
                </div>

                <!-- Chips de duração -->
                <div class="aev2-when-duration">
                    <span class="text-xs opacity-70 mr-2">Duração</span>
                    <button
                        v-for="d in duracaoQuickChips"
                        :key="d"
                        type="button"
                        class="aev2-pill"
                        :class="{ 'aev2-pill--active': form.duracaoMin === d }"
                        @click="form.duracaoMin = d"
                    >
                        {{ d }}m
                    </button>
                    <Select
                        v-model="form.duracaoMin"
                        :options="duracaoOptions"
                        optionLabel="label"
                        optionValue="value"
                        optionGroupLabel="label"
                        optionGroupChildren="items"
                        size="small"
                        class="aev2-duration-other"
                        placeholder="Outra"
                    />
                </div>

                <!-- Recorrência colapsada -->
                <div v-if="isSessionEvent" class="aev2-when-recurrence">
                    <div class="aev2-pill-group">
                        <button
                            v-for="opt in freqOpcoes"
                            :key="opt.value"
                            type="button"
                            class="aev2-pill"
                            :class="{ 'aev2-pill--active': recorrenciaType === opt.value }"
                            @click="recorrenciaType = opt.value"
                        >
                            {{ opt.label }}
                        </button>
                    </div>

                    <!-- Sub-painel: aparece só quando há recorrência -->
                    <div v-if="recorrenciaType !== 'avulsa'" class="aev2-recurrence-sub">
                        <div v-if="recorrenciaType === 'diasEspecificos'" class="aev2-weekday-pills">
                            <button
                                v-for="d in diasSemanaOpcoes"
                                :key="d.value"
                                type="button"
                                class="aev2-pill"
                                :class="{ 'aev2-pill--active': diasSelecionados.includes(d.value) }"
                                @click="toggleDiaSelecionado(d.value)"
                            >
                                {{ d.short }}
                            </button>
                        </div>
                        <div class="aev2-recurrence-qtd">
                            <span class="text-xs opacity-70">Qtd</span>
                            <Select
                                v-model="qtdSessoesMode"
                                :options="qtdSessoesOpcoes"
                                optionLabel="label"
                                optionValue="value"
                                size="small"
                                class="aev2-qtd-select"
                            />
                            <InputNumber
                                v-if="qtdSessoesMode === 'personalizar'"
                                v-model="qtdSessoesCustom"
                                :min="1"
                                :max="365"
                                size="small"
                                inputClass="aev2-qtd-input"
                            />
                            <span v-if="dataFimCalculada" class="text-xs opacity-70 ml-auto">
                                até {{ fmtDateBR(dataFimCalculada) }}
                            </span>
                        </div>
                        <div v-if="totalConflitos > 0" class="aev2-recurrence-conflict">
                            <i class="pi pi-exclamation-triangle mr-1" />
                            {{ totalConflitos }} ocorrência{{ totalConflitos > 1 ? 's' : '' }} com conflito
                        </div>
                    </div>
                </div>
            </section>

            <!-- ─────────────── ZONA 3: O QUÊ (detalhes) ─────────────── -->
            <section class="aev2-zone aev2-zone--what">
                <header class="aev2-zone__header">
                    <i class="pi pi-tag aev2-zone__icon" />
                    <span class="aev2-zone__label">O que</span>
                    <div class="aev2-zone__actions">
                        <span class="text-xs opacity-70">{{ selectedCommitmentName }}</span>
                        <Button v-if="!isEdit && allowBack" icon="pi pi-pencil" size="small" severity="secondary" text class="rounded-full h-7 w-7" v-tooltip.top="'Trocar tipo'" @click="goBack" />
                    </div>
                </header>

                <!-- Status (só edit) -->
                <div v-if="isEdit && isSessionEvent" class="aev2-what-status">
                    <span class="text-xs opacity-70 mr-2">Status</span>
                    <Select
                        v-model="form.status"
                        :options="statusOptionsFiltered"
                        optionLabel="label"
                        optionValue="value"
                        size="small"
                        class="aev2-status-select"
                    />
                </div>

                <!-- Título customizado -->
                <div class="aev2-what-field">
                    <label class="aev2-field-label">Título</label>
                    <input
                        v-model="form.titulo_custom"
                        type="text"
                        :placeholder="computedTitulo || 'Título personalizado (opcional)'"
                        class="aev2-input"
                    />
                </div>

                <!-- Observações -->
                <div class="aev2-what-field">
                    <label class="aev2-field-label">Observações</label>
                    <Textarea
                        v-model="form.observacoes"
                        rows="2"
                        autoResize
                        class="aev2-textarea"
                        placeholder="Notas privadas (opcional)"
                    />
                </div>

                <!-- Financeiro inline -->
                <div v-if="isSessionEvent" class="aev2-what-financial">
                    <div class="aev2-pill-group">
                        <button
                            v-for="opt in billingTypeOptions"
                            :key="opt.value"
                            type="button"
                            class="aev2-pill"
                            :class="{ 'aev2-pill--active': billingType === opt.value }"
                            @click="billingType = opt.value"
                        >
                            {{ opt.label }}
                        </button>
                    </div>

                    <!-- Particular: items -->
                    <div v-if="billingType === 'particular'" class="aev2-financial-particular">
                        <div v-if="commitmentItems.length" class="aev2-items-list">
                            <div v-for="(item, idx) in commitmentItems" :key="idx" class="aev2-item-row">
                                <span class="flex-1 truncate">{{ item.service_name }} ×{{ item.quantity }}</span>
                                <span class="aev2-item-price">{{ fmtBRL(item.final_price) }}</span>
                                <Button icon="pi pi-times" severity="secondary" text size="small" class="rounded-full h-7 w-7" @click="removeItem(idx)" />
                            </div>
                            <div class="aev2-items-total">
                                <span>Total</span>
                                <span class="aev2-total-value">{{ fmtBRL(totalFromItems) }}</span>
                            </div>
                        </div>
                        <div class="aev2-financial-add-row">
                            <Select
                                v-model="servicePickerSel"
                                :options="services"
                                optionLabel="name"
                                optionValue="id"
                                placeholder="+ Adicionar serviço"
                                size="small"
                                class="flex-1"
                                @change="(e) => { const s = services.find(x => x.id === e.value); if (s) { addItem(s); servicePickerSel = null; } }"
                            />
                            <Button icon="pi pi-plus" size="small" severity="secondary" outlined class="rounded-full h-9 w-9" v-tooltip.top="'Cadastrar serviço'" @click="openServiceQuickCreate" />
                        </div>
                        <div v-if="serieValorAviso" class="aev2-serie-aviso">
                            <i class="pi pi-info-circle mr-1" /> {{ serieValorAviso }}
                        </div>
                    </div>

                    <!-- Convênio: plan + procedure + value -->
                    <div v-else-if="billingType === 'convenio'" class="aev2-financial-convenio">
                        <div class="aev2-financial-add-row">
                            <Select
                                v-model="form.insurance_plan_id"
                                :options="activePlans"
                                optionLabel="name"
                                optionValue="id"
                                placeholder="Convênio"
                                size="small"
                                class="flex-1"
                            />
                            <Button icon="pi pi-plus" size="small" severity="secondary" outlined class="rounded-full h-9 w-9" v-tooltip.top="'Cadastrar convênio'" @click="openInsuranceQuickCreate" />
                        </div>
                        <Select
                            v-if="form.insurance_plan_id"
                            v-model="form.insurance_plan_service_id"
                            :options="planServices"
                            optionLabel="name"
                            optionValue="id"
                            placeholder="Procedimento"
                            size="small"
                            class="w-full"
                            @change="onProcedureSelect($event.value)"
                        />
                        <div v-if="form.insurance_plan_service_id" class="aev2-financial-row">
                            <span class="text-xs opacity-70">Valor</span>
                            <InputNumber
                                v-model="form.insurance_value"
                                mode="currency"
                                currency="BRL"
                                size="small"
                                class="aev2-currency-input"
                            />
                            <input
                                v-model="form.insurance_guide_number"
                                type="text"
                                placeholder="Nº guia"
                                class="aev2-input flex-1"
                            />
                        </div>
                    </div>

                    <div v-else class="aev2-financial-gratis">
                        <i class="pi pi-heart mr-1" /> Sessão sem cobrança
                    </div>
                </div>
            </section>
        </div>

        <!-- ════════════════ FOOTER (sticky) ════════════════ -->
        <template v-if="step === 2" #footer>
            <div class="aev2-footer">
                <div class="aev2-footer__left">
                    <Button v-if="!isEdit && allowBack" label="Voltar" icon="pi pi-arrow-left" severity="secondary" outlined size="small" class="rounded-full" @click="goBack" />
                    <Button v-if="isEdit && hasSerie" label="Encerrar série" icon="pi pi-trash" severity="danger" outlined size="small" class="rounded-full text-xs" @click="onEncerrarSerie" />
                    <Button v-if="isEdit && !hasSerie" icon="pi pi-trash" severity="danger" outlined size="small" class="rounded-full h-9 w-9" v-tooltip.top="'Remover'" @click="onDelete" />
                    <Button
                        v-if="isEdit && isSessionEvent && form.paciente_id"
                        icon="pi pi-whatsapp"
                        severity="success"
                        outlined
                        size="small"
                        class="rounded-full h-9 w-9"
                        v-tooltip.top="'Enviar lembrete WhatsApp'"
                        :loading="sendingReminder"
                        @click="onSendManualReminder"
                    />
                    <a
                        v-if="isEdit && googleCalendarUrl"
                        :href="googleCalendarUrl"
                        target="_blank"
                        rel="noopener noreferrer"
                        class="aev2-gcal-btn"
                        v-tooltip.top="'Abrir no Google Agenda'"
                    >
                        <i class="pi pi-calendar" />
                    </a>
                </div>
                <div class="aev2-footer__right">
                    <span v-if="validationHint" class="aev2-validation-hint">
                        <i class="pi pi-info-circle mr-1" /> {{ validationHint }}
                    </span>
                    <Button
                        label="Salvar"
                        icon="pi pi-check"
                        size="small"
                        class="rounded-full aev2-save-btn"
                        :disabled="!canSave"
                        @click="onSave"
                    />
                </div>
            </div>
        </template>

        <!-- ════════════════ Sub-dialogs ════════════════ -->
        <!-- Picker paciente -->
        <Dialog v-model:visible="pacientePickerOpen" modal :style="{ width: '480px' }" header="Buscar paciente">
            <div class="aev2-picker">
                <input v-model="pacienteSearch" type="text" placeholder="Buscar por nome, e-mail ou telefone…" class="aev2-input mb-3" />
                <div v-if="pacientesLoading" class="text-center py-4 opacity-60">
                    <i class="pi pi-spinner pi-spin" />
                </div>
                <div v-else-if="pacientesError" class="text-center py-4 text-red-500">{{ pacientesError }}</div>
                <div v-else-if="filteredPatients.length === 0" class="text-center py-4 opacity-60 text-sm">
                    Nenhum paciente encontrado
                </div>
                <div v-else class="aev2-picker-list">
                    <button
                        v-for="p in filteredPatients"
                        :key="p.id"
                        type="button"
                        class="aev2-picker-item"
                        :class="{ 'aev2-picker-item--blocked': p.status && p.status !== 'Ativo' }"
                        :disabled="p.status && p.status !== 'Ativo'"
                        :title="p.status === 'Arquivado' ? 'Paciente arquivado — não é possível agendar' : p.status === 'Inativo' ? 'Paciente inativo — não é possível agendar' : ''"
                        @click="selectPaciente(p)"
                    >
                        <Avatar v-if="p.avatar_url" :image="p.avatar_url" shape="circle" size="normal" />
                        <Avatar v-else :label="patientInitials(p.nome)" shape="circle" size="normal" class="aev2-patient-avatar--initials" />
                        <div class="flex-1 text-left min-w-0">
                            <div class="font-semibold truncate">{{ p.nome }}</div>
                            <div class="text-xs opacity-60 truncate">{{ p.email || p.telefone }}</div>
                        </div>
                        <Tag v-if="p.status === 'Arquivado'" value="Arquivado" severity="danger" class="shrink-0" />
                        <Tag v-else-if="p.status === 'Inativo'" value="Inativo" severity="warn" class="shrink-0" />
                    </button>
                </div>
            </div>
        </Dialog>

        <!-- Cadastro rápido -->
        <ComponentCadastroRapido
            v-model="cadRapidoOpen"
            title="Novo Paciente"
            table-name="patients"
            name-field="nome_completo"
            email-field="email_principal"
            phone-field="telefone"
            :extra-payload="{ status: 'Ativo' }"
            hide-view-list-button
            @created="onPatientCreatedRapido"
        />

        <!-- Quick-create serviço -->
        <ServiceQuickCreateDialog
            v-model="serviceQuickDlgOpen"
            :owner-id="ownerId"
            @created="onServiceCreated"
        />

        <!-- Quick-create convênio -->
        <InsurancePlanQuickCreateDialog
            v-model="insuranceQuickDlgOpen"
            :owner-id="planOwnerId || ownerId"
            @created="onInsuranceCreated"
        />
    </Dialog>
</template>

<style scoped>
/* ══════════════════════════════════════════════════════════════
   V2 design tokens
   ══════════════════════════════════════════════════════════════ */
.aev2-dialog {
    --aev2-radius: 14px;
    --aev2-radius-sm: 10px;
    --aev2-bg-zone: var(--surface-card);
    --aev2-border: var(--surface-border);
    --aev2-accent: var(--p-primary-500, #6366f1);
    --aev2-pill-bg: var(--surface-100);
    --aev2-pill-bg-hover: var(--surface-200);
    --aev2-pill-bg-active: var(--p-primary-500);
    --aev2-pill-fg-active: #fff;
    --aev2-zone-pad: 1rem 1.25rem;
}

/* ─── Header ─── */
.aev2-header {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
}
.aev2-header__title-wrap {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-width: 0;
}
.aev2-header__dot {
    width: 12px;
    height: 12px;
    border-radius: 999px;
    background: var(--aev2-accent);
    flex-shrink: 0;
}
.aev2-header__title {
    font-weight: 600;
    font-size: 1rem;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.aev2-header__sub {
    font-size: .75rem;
    opacity: .65;
    white-space: nowrap;
}

/* ─── Edit-scope chips (header) ─── */
.aev2-scope-chips {
    display: inline-flex;
    background: var(--aev2-pill-bg);
    border-radius: 999px;
    padding: 2px;
    gap: 2px;
}
.aev2-scope-chip {
    border: 0;
    background: transparent;
    padding: .35rem .85rem;
    font-size: .75rem;
    border-radius: 999px;
    cursor: pointer;
    color: var(--text-color);
    transition: background .15s;
}
.aev2-scope-chip:hover { background: var(--aev2-pill-bg-hover); }
.aev2-scope-chip--active {
    background: var(--aev2-pill-bg-active);
    color: var(--aev2-pill-fg-active);
    font-weight: 600;
}

/* ─── Step 1 ─── */
.aev2-step1 { padding: .5rem 0; }
.aev2-step1__hint {
    font-size: .85rem;
    opacity: .65;
    margin-bottom: 1rem;
}
.aev2-commitment-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: .75rem;
}
.aev2-commitment-card {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: 1rem;
    background: var(--aev2-bg-zone);
    border: 1px solid var(--aev2-border);
    border-radius: var(--aev2-radius);
    cursor: pointer;
    transition: all .15s;
    text-align: left;
}
.aev2-commitment-card:hover:not(:disabled) {
    border-color: var(--card-color, var(--aev2-accent));
    transform: translateY(-1px);
    box-shadow: 0 6px 20px rgb(0 0 0 / .08);
}
.aev2-commitment-card--blocked { opacity: .55; cursor: not-allowed; }
.aev2-commitment-card__icon {
    width: 40px; height: 40px;
    border-radius: 10px;
    display: grid; place-items: center;
    background: color-mix(in srgb, var(--aev2-accent) 12%, transparent);
    color: var(--aev2-accent);
    flex-shrink: 0;
}
.aev2-commitment-card__body { flex: 1; min-width: 0; }
.aev2-commitment-card__name { font-weight: 600; }
.aev2-commitment-card__desc {
    font-size: .8rem;
    opacity: .7;
    margin-top: .15rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.aev2-commitment-card__tags {
    display: flex; flex-wrap: wrap; gap: .25rem;
    margin-top: .5rem;
}
.aev2-commitment-card__chev {
    opacity: .4;
    align-self: center;
    flex-shrink: 0;
}

/* ─── Layout das 3 zonas ─── */
.aev2-zones {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
        "alerts alerts"
        "patient when"
        "what what";
    gap: 1rem;
    padding: .25rem 0;
}
.aev2-alerts { grid-area: alerts; display: flex; flex-direction: column; gap: .5rem; }
.aev2-zone--patient { grid-area: patient; }
.aev2-zone--when { grid-area: when; }
.aev2-zone--what { grid-area: what; }
@media (max-width: 880px) {
    .aev2-zones {
        grid-template-columns: 1fr;
        grid-template-areas:
            "alerts"
            "patient"
            "when"
            "what";
    }
}

.aev2-zone {
    background: var(--aev2-bg-zone);
    border: 1px solid var(--aev2-border);
    border-radius: var(--aev2-radius);
    padding: var(--aev2-zone-pad);
    display: flex;
    flex-direction: column;
    gap: .75rem;
}
.aev2-zone--locked { opacity: .8; }
.aev2-zone__header {
    display: flex;
    align-items: center;
    gap: .5rem;
}
.aev2-zone__icon { color: var(--aev2-accent); }
.aev2-zone__label {
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 600;
    opacity: .8;
}
.aev2-zone__actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: .25rem;
}

/* ─── Pills genéricas (modalidade, frequência, billing, duração) ─── */
.aev2-pill-group {
    display: inline-flex;
    flex-wrap: wrap;
    gap: .35rem;
    background: var(--aev2-pill-bg);
    border-radius: 999px;
    padding: 3px;
}
.aev2-pill {
    border: 0;
    background: transparent;
    padding: .4rem .9rem;
    border-radius: 999px;
    font-size: .8rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    color: var(--text-color);
    transition: all .15s;
}
.aev2-pill:hover { background: var(--aev2-pill-bg-hover); }
.aev2-pill--active {
    background: var(--aev2-pill-bg-active);
    color: var(--aev2-pill-fg-active);
    font-weight: 600;
}

/* ─── Zona PACIENTE ─── */
.aev2-patient-empty {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .85rem 1rem;
    background: color-mix(in srgb, var(--aev2-accent) 6%, transparent);
    border: 2px dashed color-mix(in srgb, var(--aev2-accent) 35%, transparent);
    border-radius: var(--aev2-radius-sm);
    cursor: pointer;
    width: 100%;
    transition: all .15s;
}
.aev2-patient-empty:hover {
    background: color-mix(in srgb, var(--aev2-accent) 10%, transparent);
    border-color: var(--aev2-accent);
}
.aev2-patient-empty__icon {
    width: 38px; height: 38px;
    border-radius: 10px;
    display: grid; place-items: center;
    background: color-mix(in srgb, var(--aev2-accent) 18%, transparent);
    color: var(--aev2-accent);
}
.aev2-patient-card {
    display: flex;
    align-items: center;
    gap: .85rem;
}
.aev2-patient-avatar {
    width: 64px; height: 64px;
    flex-shrink: 0;
}
.aev2-patient-avatar--initials {
    background: linear-gradient(135deg, var(--aev2-accent), color-mix(in srgb, var(--aev2-accent) 60%, #ec4899));
    color: #fff;
    font-weight: 600;
}
.aev2-patient-info { flex: 1; min-width: 0; }
.aev2-patient-name {
    font-weight: 700;
    font-size: 1.05rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.aev2-patient-badges {
    display: flex; flex-wrap: wrap; gap: .25rem;
    margin-top: .25rem;
}
.aev2-badge {
    display: inline-block;
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    padding: 2px 7px;
    border-radius: 4px;
    line-height: 1.4;
}
.aev2-badge--neutral { background: var(--surface-200); color: var(--text-color-secondary); }
.aev2-badge--warn { background: #f97316; color: #fff; }
.aev2-badge--danger { background: #ef4444; color: #fff; }
.aev2-patient-actions { display: flex; gap: .25rem; flex-shrink: 0; }
.aev2-patient-modalidade {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding-top: .5rem;
    border-top: 1px dashed var(--aev2-border);
}

/* ─── Zona QUANDO ─── */
.aev2-when-hero {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: .5rem;
    align-items: center;
}
.aev2-when-date,
.aev2-when-time {
    display: flex;
    align-items: center;
    gap: .35rem;
}
:deep(.aev2-date-typo) {
    font-size: 1.4rem !important;
    font-weight: 600 !important;
    letter-spacing: -.01em;
    border: 0 !important;
    background: transparent !important;
    padding: .25rem .5rem !important;
}
.aev2-when-today {
    border: 0;
    background: transparent;
    width: 32px; height: 32px;
    border-radius: 999px;
    cursor: pointer;
    color: var(--aev2-accent);
}
.aev2-when-today:hover { background: var(--aev2-pill-bg); }
.aev2-when-duration {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem;
}
.aev2-duration-other { width: 110px; }
.aev2-when-recurrence {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding-top: .5rem;
    border-top: 1px dashed var(--aev2-border);
}
.aev2-recurrence-sub {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding: .65rem .75rem;
    background: color-mix(in srgb, var(--aev2-accent) 5%, transparent);
    border-radius: var(--aev2-radius-sm);
}
.aev2-weekday-pills { display: flex; flex-wrap: wrap; gap: .25rem; }
.aev2-recurrence-qtd {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}
.aev2-qtd-select { width: 130px; }
:deep(.aev2-qtd-input) { width: 70px; text-align: center; }
.aev2-recurrence-conflict {
    color: #f97316;
    font-size: .8rem;
}

/* ─── Zona O QUÊ ─── */
.aev2-what-status {
    display: flex; align-items: center; gap: .5rem;
}
.aev2-status-select { width: 180px; }
.aev2-what-field {
    display: flex;
    flex-direction: column;
    gap: .25rem;
}
.aev2-field-label {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .65;
    font-weight: 600;
}
.aev2-input {
    border: 1px solid var(--aev2-border);
    border-radius: var(--aev2-radius-sm);
    padding: .45rem .65rem;
    background: var(--surface-card);
    color: var(--text-color);
    font-size: .9rem;
    width: 100%;
}
.aev2-input:focus {
    outline: none;
    border-color: var(--aev2-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--aev2-accent) 20%, transparent);
}
:deep(.aev2-textarea) {
    width: 100%;
    border-radius: var(--aev2-radius-sm) !important;
}

/* ─── Zona O QUÊ — financeiro ─── */
.aev2-what-financial {
    display: flex;
    flex-direction: column;
    gap: .65rem;
    padding-top: .5rem;
    border-top: 1px dashed var(--aev2-border);
}
.aev2-financial-add-row {
    display: flex;
    align-items: center;
    gap: .35rem;
}
.aev2-items-list {
    display: flex; flex-direction: column;
    gap: .25rem;
    background: color-mix(in srgb, var(--aev2-accent) 4%, transparent);
    border-radius: var(--aev2-radius-sm);
    padding: .5rem;
}
.aev2-item-row {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .85rem;
}
.aev2-item-price {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.aev2-items-total {
    display: flex;
    justify-content: space-between;
    border-top: 1px solid var(--aev2-border);
    padding-top: .35rem;
    margin-top: .25rem;
    font-weight: 600;
}
.aev2-total-value {
    color: var(--aev2-accent);
    font-variant-numeric: tabular-nums;
}
.aev2-financial-row {
    display: flex; align-items: center; gap: .5rem;
}
.aev2-currency-input { width: 130px; }
.aev2-financial-gratis {
    color: var(--text-color-secondary);
    font-size: .85rem;
    font-style: italic;
}
.aev2-serie-aviso {
    font-size: .75rem;
    color: var(--text-color-secondary);
    background: var(--surface-100);
    padding: .35rem .55rem;
    border-radius: var(--aev2-radius-sm);
}

/* ─── Footer (sticky save bar) ─── */
.aev2-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    width: 100%;
}
.aev2-footer__left,
.aev2-footer__right {
    display: flex;
    align-items: center;
    gap: .5rem;
}
.aev2-validation-hint {
    font-size: .75rem;
    color: #f97316;
    background: color-mix(in srgb, #f97316 12%, transparent);
    padding: .35rem .75rem;
    border-radius: 999px;
}
.aev2-save-btn { min-width: 120px; }
.aev2-gcal-btn {
    width: 36px; height: 36px;
    border-radius: 999px;
    border: 1px solid var(--aev2-border);
    display: grid; place-items: center;
    color: var(--text-color);
    text-decoration: none;
    transition: all .15s;
}
.aev2-gcal-btn:hover {
    background: var(--aev2-pill-bg);
    border-color: var(--aev2-accent);
    color: var(--aev2-accent);
}

/* ─── Sub-dialog: paciente picker ─── */
.aev2-picker { display: flex; flex-direction: column; }
.aev2-picker-list {
    display: flex; flex-direction: column;
    gap: .25rem;
    max-height: 380px;
    overflow-y: auto;
}
.aev2-picker-item {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .5rem .65rem;
    border: 0;
    background: transparent;
    border-radius: var(--aev2-radius-sm);
    cursor: pointer;
    text-align: left;
    transition: background .15s;
}
.aev2-picker-item:hover { background: var(--aev2-pill-bg); }
.aev2-picker-item--blocked {
    opacity: .6;
    cursor: not-allowed;
}
.aev2-picker-item--blocked:hover { background: transparent; }
</style>
