<script setup>
/*
 * MelissaAlterarPlano — Pagina nativa Melissa pra escolha/upgrade de plano.
 *
 * Substitui o redirect pra /therapist/upgrade que vinha do MelissaPlano.
 * Layout 2-col (espelha MelissaPerfil/Plano):
 *   - COL 1 (sidebar) — Card "Plano atual" (nome + valor + status do
 *     subscription corrente) + Card "Filtros" (busca + interval toggle
 *     mensal/anual) + Footer "Voltar pro Meu Plano"
 *   - COL 2 (main) — Grid responsivo de plan cards (Mensal/Anual,
 *     descricao, preco, 3 CTAs: Escolher do interval atual + Mensal + Anual)
 *
 * Logica espelhada do TherapistUpgradePage.vue (subscriptions + plans
 * target=therapist + plan_prices + RPC change_subscription_plan).
 */
import { ref, computed, onMounted } from 'vue';
import { useToast } from 'primevue/usetoast';
import { supabase } from '@/lib/supabase/client';
import { useTenantStore } from '@/stores/tenantStore';
// Tag/Skeleton: auto via PrimeVueResolver

const emit = defineEmits(['close', 'goto']);

const toast = useToast();
const tenantStore = useTenantStore();

// ── Breakpoints + drawer ───────────────────────────────────
const drawerOpen = ref(false);
const isMobile = ref(false);
let _mqMobile = null;
function _onMqMobileChange(e) {
    isMobile.value = e.matches;
    if (!e.matches) drawerOpen.value = false;
}
function toggleDrawer() { drawerOpen.value = !drawerOpen.value; }
function fecharDrawer() { drawerOpen.value = false; }

// ── Estado ─────────────────────────────────────────────────
const loading = ref(true);
const saving = ref(false);
const isFetching = ref(false);

const uid = ref(null);
const currentSub = ref(null);
const plans = ref([]);
const prices = ref([]);

const q = ref('');
const billingInterval = ref('month'); // 'month' | 'year'
const intervalOptions = [
    { label: 'Mensal', value: 'month' },
    { label: 'Anual', value: 'year' }
];

// ── Helpers ────────────────────────────────────────────────
function money(currency, amountCents) {
    if (amountCents == null) return null;
    const value = Number(amountCents) / 100;
    try {
        return new Intl.NumberFormat('pt-BR', {
            style: 'currency',
            currency: currency || 'BRL'
        }).format(value);
    } catch (_) {
        return `${value.toFixed(2)} ${currency || ''}`.trim();
    }
}
function intervalLabel(i) {
    if (i === 'month') return 'mês';
    if (i === 'year') return 'ano';
    return i || '—';
}
function statusLabel(st) {
    const s = String(st || '').toLowerCase();
    if (s === 'active') return 'Ativo';
    if (s === 'trialing') return 'Trial';
    if (s === 'past_due') return 'Atrasado';
    if (s === 'canceled' || s === 'cancelled') return 'Cancelado';
    return st || '—';
}
function statusSeverity(st) {
    const s = String(st || '').toLowerCase();
    if (s === 'active') return 'success';
    if (s === 'trialing') return 'info';
    if (s === 'past_due') return 'warning';
    if (s === 'canceled' || s === 'cancelled') return 'danger';
    return 'secondary';
}

function priceFor(planId, interval) {
    return (prices.value || []).find(
        (p) => String(p.plan_id) === String(planId) && String(p.interval) === String(interval)
    ) || null;
}
function priceLabelFor(planRow, interval) {
    const pp = priceFor(planRow?.id, interval);
    if (!pp) return null;
    return `${money(pp.currency, pp.amount_cents)} / ${intervalLabel(interval)}`;
}
function priceLabelForCard(planRow) {
    return priceLabelFor(planRow, billingInterval.value) || '—';
}

const currentPlanName = computed(() => {
    if (!currentSub.value) return null;
    const p = plans.value.find((x) => String(x.id) === String(currentSub.value.plan_id));
    return p?.name || currentSub.value.plan_key || '—';
});

const currentPriceLabel = computed(() => {
    if (!currentSub.value) return null;
    const p = plans.value.find((x) => String(x.id) === String(currentSub.value.plan_id));
    if (!p) return null;
    return priceLabelFor(p, currentSub.value.interval);
});

const filteredPlans = computed(() => {
    const term = String(q.value || '').trim().toLowerCase();
    if (!term) return plans.value || [];
    return (plans.value || []).filter((p) => {
        const a = String(p.key || '').toLowerCase();
        const b = String(p.name || '').toLowerCase();
        const c = String(p.description || '').toLowerCase();
        return a.includes(term) || b.includes(term) || c.includes(term);
    });
});

// ── Fetch ──────────────────────────────────────────────────
async function loadData() {
    if (isFetching.value) return;
    isFetching.value = true;
    loading.value = true;
    try {
        const { data: authData, error: authError } = await supabase.auth.getUser();
        if (authError) throw authError;
        uid.value = authData?.user?.id;
        if (!uid.value) throw new Error('Sessão não encontrada.');

        const sRes = await supabase
            .from('subscriptions')
            .select('*')
            .eq('user_id', uid.value)
            .order('created_at', { ascending: false })
            .limit(10);
        if (sRes.error) throw sRes.error;
        const subList = sRes.data || [];
        const priority = (st) => {
            const s = String(st || '').toLowerCase();
            if (s === 'active') return 1;
            if (s === 'trialing') return 2;
            if (s === 'past_due') return 3;
            if (s === 'unpaid') return 4;
            if (s === 'incomplete') return 5;
            if (s === 'canceled' || s === 'cancelled') return 9;
            return 8;
        };
        currentSub.value = subList.length
            ? subList.slice().sort((a, b) => {
                  const pa = priority(a?.status);
                  const pb = priority(b?.status);
                  if (pa !== pb) return pa - pb;
                  return new Date(b?.created_at || 0) - new Date(a?.created_at || 0);
              })[0]
            : null;

        const pRes = await supabase
            .from('plans')
            .select('id, key, name, description, target, is_active')
            .eq('target', 'therapist')
            .order('created_at', { ascending: true });
        if (pRes.error) throw pRes.error;
        plans.value = (pRes.data || []).filter((p) => p?.is_active !== false);

        const nowIso = new Date().toISOString();
        const ppRes = await supabase
            .from('plan_prices')
            .select('plan_id, currency, interval, amount_cents, is_active, active_from, active_to')
            .eq('is_active', true)
            .lte('active_from', nowIso)
            .or(`active_to.is.null,active_to.gte.${nowIso}`)
            .order('active_from', { ascending: false });
        if (ppRes.error) throw ppRes.error;
        prices.value = ppRes.data || [];
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || String(e), life: 5000 });
    } finally {
        loading.value = false;
        isFetching.value = false;
    }
}

// ── Preflight + escolha ────────────────────────────────────
function preflight(planRow, interval) {
    if (!uid.value) return { ok: false, msg: 'Sessão não encontrada.' };
    if (!planRow?.id) return { ok: false, msg: 'Plano inválido.' };
    if (!['month', 'year'].includes(String(interval))) {
        return { ok: false, msg: 'Intervalo inválido.' };
    }
    const pp = priceFor(planRow.id, interval);
    if (!pp) {
        return {
            ok: false,
            msg: `Este plano não tem preço ativo para ${intervalLabel(interval)}.`
        };
    }
    if (
        currentSub.value?.plan_id === planRow.id &&
        String(currentSub.value?.interval) === String(interval)
    ) {
        return { ok: false, msg: 'Você já está nesse plano/intervalo.' };
    }
    return { ok: true, msg: '' };
}

async function choosePlan(planRow, interval) {
    const pf = preflight(planRow, interval);
    if (!pf.ok) {
        toast.add({ severity: 'warn', summary: 'Atenção', detail: pf.msg, life: 4200 });
        return;
    }
    saving.value = true;
    try {
        const nowIso = new Date().toISOString();
        if (currentSub.value?.id) {
            const { error: e1 } = await supabase.rpc('change_subscription_plan', {
                p_subscription_id: currentSub.value.id,
                p_new_plan_id: planRow.id
            });
            if (e1) throw e1;

            const { error: e2 } = await supabase
                .from('subscriptions')
                .update({
                    interval,
                    updated_at: nowIso,
                    cancel_at_period_end: false,
                    status: 'active'
                })
                .eq('id', currentSub.value.id);
            if (e2) throw e2;
        } else {
            const { data: ins, error: eIns } = await supabase
                .from('subscriptions')
                .insert({
                    user_id: uid.value,
                    tenant_id: null,
                    plan_id: planRow.id,
                    plan_key: planRow.key,
                    interval,
                    status: 'active',
                    cancel_at_period_end: false,
                    provider: 'manual',
                    source: 'therapist_upgrade',
                    started_at: nowIso,
                    current_period_start: nowIso
                })
                .select('*')
                .maybeSingle();
            if (eIns) throw eIns;
            currentSub.value = ins || null;
        }

        toast.add({
            severity: 'success',
            summary: 'Plano atualizado',
            detail: 'Seu plano foi atualizado com sucesso.',
            life: 3200
        });

        await loadData();
        // Volta pro MelissaPlano pra ver o estado novo
        emit('goto', 'plano');
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || String(e), life: 5000 });
    } finally {
        saving.value = false;
    }
}

// ── Lifecycle ──────────────────────────────────────────────
onMounted(async () => {
    if (typeof window !== 'undefined' && window.matchMedia) {
        _mqMobile = window.matchMedia('(max-width: 1023px)');
        isMobile.value = _mqMobile.matches;
        try { _mqMobile.addEventListener('change', _onMqMobileChange); }
        catch { _mqMobile.addListener(_onMqMobileChange); }
    }
    await tenantStore.ensureLoaded();
    await loadData();
});
</script>

<template>
    <Transition name="map-drawer-fade">
        <div
            v-show="isMobile && drawerOpen"
            class="map-mobile-drawer"
            :class="{ 'is-open': drawerOpen }"
        >
            <div id="map-mobile-drawer-target" class="map-mobile-drawer__scroll" />
        </div>
    </Transition>
    <Transition name="map-drawer-fade">
        <div
            v-show="isMobile && drawerOpen"
            class="map-mobile-drawer__backdrop"
            @click="fecharDrawer"
        />
    </Transition>

    <section class="map-page">
        <header class="map-page__head">
            <button
                class="map-menu-btn map-menu-btn--mobile-only"
                v-tooltip.bottom="'Filtros & Plano atual'"
                @click="toggleDrawer"
            >
                <i class="pi pi-bars" />
                <span>Menu</span>
            </button>
            <div class="map-page__title">
                <i class="pi pi-arrow-up-right map-page__title-icon" />
                <span>Alterar Plano</span>
                <Tag
                    v-if="currentSub"
                    :value="`Atual: ${currentSub.plan_key}`"
                    :severity="statusSeverity(currentSub.status)"
                />
                <Tag v-else value="Sem plano" severity="warning" />
            </div>
            <div class="map-page__actions">
                <button
                    class="map-act-btn"
                    v-tooltip.bottom="'Atualizar'"
                    :disabled="loading || saving"
                    @click="loadData"
                >
                    <i :class="loading ? 'pi pi-spin pi-spinner' : 'pi pi-refresh'" />
                </button>
                <button class="map-close" v-tooltip.bottom="'Voltar (Esc)'" @click="emit('close')">
                    <i class="pi pi-times" />
                </button>
            </div>
        </header>

        <div class="map-subheader">
            <i class="pi pi-info-circle map-subheader__icon" />
            <span class="map-subheader__text">
                Escolha seu plano pessoal. Use o filtro <strong>Mensal/Anual</strong>
                no aside pra comparar preços.
            </span>
        </div>

        <div class="map-body">
            <Teleport to="#map-mobile-drawer-target" :disabled="!isMobile">
                <aside class="map-side">
                    <div class="map-side__scroll">
                        <!-- Card: Plano atual -->
                        <div class="map-w map-w--side">
                            <div class="map-w__head">
                                <div class="map-w__icon"><i class="pi pi-credit-card" /></div>
                                <div class="map-w__title">
                                    <div class="map-w__title-text">Plano atual</div>
                                    <div class="map-w__sub">Sua assinatura corrente</div>
                                </div>
                            </div>
                            <div class="map-w__body">
                                <template v-if="loading && !plans.length">
                                    <Skeleton width="60%" height="22px" class="mb-2" />
                                    <Skeleton width="80%" height="14px" />
                                </template>
                                <template v-else-if="!currentSub">
                                    <div class="map-empty">
                                        <i class="pi pi-info-circle" />
                                        <span>Você ainda não tem um plano pessoal.</span>
                                    </div>
                                </template>
                                <template v-else>
                                    <div class="map-curr">
                                        <div class="map-curr__name">{{ currentPlanName }}</div>
                                        <div class="map-curr__key">{{ currentSub.plan_key }}</div>
                                        <div class="map-curr__price">
                                            {{ currentPriceLabel || 'Preço não disponível' }}
                                        </div>
                                        <Tag
                                            :value="statusLabel(currentSub.status)"
                                            :severity="statusSeverity(currentSub.status)"
                                        />
                                    </div>
                                </template>
                            </div>
                        </div>

                        <!-- Card: Filtros -->
                        <div class="map-w map-w--side">
                            <div class="map-w__head">
                                <div class="map-w__icon"><i class="pi pi-filter" /></div>
                                <div class="map-w__title">
                                    <div class="map-w__title-text">Filtros</div>
                                    <div class="map-w__sub">Busque planos e ajuste o intervalo</div>
                                </div>
                            </div>
                            <div class="map-w__body">
                                <FloatLabel variant="on">
                                    <InputText
                                        id="map_q"
                                        v-model="q"
                                        class="w-full"
                                        :disabled="loading || saving"
                                    />
                                    <label for="map_q">Buscar plano</label>
                                </FloatLabel>

                                <div class="map-interval">
                                    <span class="map-interval__label">Preço:</span>
                                    <button
                                        v-for="opt in intervalOptions"
                                        :key="opt.value"
                                        type="button"
                                        class="map-interval__btn"
                                        :class="{ 'is-active': billingInterval === opt.value }"
                                        :disabled="loading || saving"
                                        @click="billingInterval = opt.value"
                                    >{{ opt.label }}</button>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="map-side__footer">
                        <button class="map-btn map-btn--full" @click="emit('goto', 'plano')">
                            <i class="pi pi-arrow-left" />
                            <span>Voltar pro Meu Plano</span>
                        </button>
                    </div>
                </aside>
            </Teleport>

            <div class="map-main">
                <!-- Loading -->
                <template v-if="loading">
                    <div class="map-cards">
                        <div v-for="n in 3" :key="`sk-${n}`" class="map-w">
                            <div class="map-w__body">
                                <Skeleton width="60%" height="20px" class="mb-2" />
                                <Skeleton width="100%" height="14px" class="mb-3" />
                                <Skeleton width="40%" height="36px" class="mb-3" />
                                <Skeleton width="100%" height="36px" />
                            </div>
                        </div>
                    </div>
                </template>

                <!-- Empty (filtro vazio) -->
                <div v-else-if="!filteredPlans.length" class="map-w">
                    <div class="map-w__body">
                        <div class="map-empty map-empty--big">
                            <i class="pi pi-box map-empty__icon" />
                            <div class="map-empty__title">Nenhum plano encontrado</div>
                            <div class="map-empty__hint">Tente limpar o filtro de busca.</div>
                            <button class="map-btn" @click="q = ''">
                                <i class="pi pi-filter-slash" />
                                <span>Limpar busca</span>
                            </button>
                        </div>
                    </div>
                </div>

                <!-- Grid de planos -->
                <div v-else class="map-cards">
                    <div
                        v-for="p in filteredPlans"
                        :key="p.id"
                        class="map-plan"
                        :class="{ 'is-current': currentSub?.plan_id === p.id }"
                    >
                        <div class="map-plan__head">
                            <div class="map-plan__title">
                                <div class="map-plan__name">{{ p.name || p.key }}</div>
                                <div class="map-plan__key">{{ p.key }}</div>
                            </div>
                            <Tag
                                v-if="currentSub?.plan_id === p.id"
                                value="Atual"
                                severity="success"
                            />
                        </div>

                        <div class="map-plan__body">
                            <div v-if="p.description" class="map-plan__desc">{{ p.description }}</div>

                            <div class="map-plan__price">
                                <div class="map-plan__price-val">{{ priceLabelForCard(p) }}</div>
                                <div class="map-plan__price-hint">
                                    {{ priceFor(p.id, billingInterval)
                                        ? `Preço ativo para ${intervalLabel(billingInterval)}.`
                                        : `Sem preço ativo para ${intervalLabel(billingInterval)}.` }}
                                </div>
                            </div>

                            <div class="map-plan__actions">
                                <button
                                    class="map-btn map-btn--primary map-btn--full"
                                    :disabled="loading || saving || !priceFor(p.id, billingInterval)"
                                    @click="choosePlan(p, billingInterval)"
                                >
                                    <i :class="saving ? 'pi pi-spin pi-spinner' : 'pi pi-check'" />
                                    <span>{{ billingInterval === 'month' ? 'Escolher mensal' : 'Escolher anual' }}</span>
                                </button>
                                <div class="map-plan__actions-row">
                                    <button
                                        class="map-btn"
                                        :disabled="loading || saving || !priceFor(p.id, 'month')"
                                        @click="choosePlan(p, 'month')"
                                    >
                                        <span>Mensal</span>
                                        <span class="map-plan__sub-price" v-if="priceFor(p.id, 'month')">
                                            {{ money(priceFor(p.id, 'month').currency, priceFor(p.id, 'month').amount_cents) }}
                                        </span>
                                    </button>
                                    <button
                                        class="map-btn"
                                        :disabled="loading || saving || !priceFor(p.id, 'year')"
                                        @click="choosePlan(p, 'year')"
                                    >
                                        <span>Anual</span>
                                        <span class="map-plan__sub-price" v-if="priceFor(p.id, 'year')">
                                            {{ money(priceFor(p.id, 'year').currency, priceFor(p.id, 'year').amount_cents) }}
                                        </span>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
</template>

<style scoped>
/* ═══════ Page chrome ═══════ */
.map-page {
    position: absolute;
    inset: 6px 6px calc(var(--m-dock-h, 76px) + 6px) 6px;
    z-index: 40;
    display: flex;
    flex-direction: column;
    background: var(--m-bg-medium);
    backdrop-filter: blur(32px) saturate(160%);
    -webkit-backdrop-filter: blur(32px) saturate(160%);
    border: 1px solid var(--m-border);
    border-radius: 18px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
    overflow: hidden;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    color: var(--m-text);
    animation: map-page-enter 240ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes map-page-enter {
    from { opacity: 0; transform: scale(0.985); }
    to   { opacity: 1; transform: scale(1); }
}

.map-page__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    border-bottom: 1px solid var(--m-border);
    flex-shrink: 0;
    gap: 10px;
}
.map-page__title {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 1rem;
    font-weight: 700;
    color: var(--m-text);
}
.map-page__title-icon { color: var(--p-primary-color); font-size: 1.05rem; }
.map-page__actions { display: flex; align-items: center; gap: 6px; }

.map-act-btn {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    background: transparent;
    border: 1px solid var(--m-border);
    color: var(--m-text-muted);
    border-radius: 8px;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}
.map-act-btn:hover { background: var(--m-bg-soft-hover); color: var(--m-text); }
.map-act-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.map-close {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    background: transparent;
    border: 1px solid var(--m-border);
    color: var(--m-text-muted);
    border-radius: 8px;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}
.map-close:hover { background: var(--m-bg-soft-hover); color: var(--m-text); }
.map-menu-btn {
    display: none;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border-radius: 8px;
    border: 1px solid var(--m-border);
    background: var(--m-bg-soft);
    color: var(--m-text);
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 600;
    flex-shrink: 0;
}
.map-menu-btn:hover { background: var(--m-bg-soft-hover); }

.map-subheader {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 18px;
    background: var(--m-bg-soft);
    border-bottom: 1px solid var(--m-border);
    color: var(--m-text-muted);
    font-size: 0.78rem;
    flex-shrink: 0;
}
.map-subheader__icon {
    color: var(--p-primary-color);
    font-size: 0.85rem;
    margin-top: 2px;
    flex-shrink: 0;
}

/* ═══════ Body 2-col ═══════ */
.map-body {
    flex: 1;
    min-height: 0;
    display: flex;
    overflow: hidden;
}
.map-side {
    width: 320px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: var(--m-bg-soft);
    border-right: 1px solid var(--m-border);
    overflow: hidden;
}
.map-side__scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    scrollbar-width: thin;
    scrollbar-color: var(--m-border-strong) transparent;
}
.map-side__scroll::-webkit-scrollbar { width: 5px; }
.map-side__scroll::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 3px;
}
.map-side__footer {
    flex-shrink: 0;
    padding: 12px;
    background: var(--m-bg-medium);
    border-top: 1px solid var(--m-border);
}

.map-main {
    flex: 1;
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    scrollbar-width: thin;
    scrollbar-color: var(--m-border-strong) transparent;
}
.map-main::-webkit-scrollbar { width: 5px; }
.map-main::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 3px;
}

/* ═══════ Card-base ═══════ */
.map-w {
    background: var(--m-bg-soft);
    border: 1px solid var(--m-border);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    display: flex;
    flex-direction: column;
}
.map-w--side {
    background: var(--m-bg-medium);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
}
.map-w__head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--m-border);
}
.map-w__icon {
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border-radius: 9px;
    flex-shrink: 0;
    background: color-mix(in srgb, var(--p-primary-color) 15%, transparent);
    color: var(--p-primary-color);
}
.map-w__icon > i { font-size: 0.95rem; }
.map-w__title { flex: 1; min-width: 0; }
.map-w__title-text {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--m-text);
    line-height: 1.2;
}
.map-w__sub {
    font-size: 0.74rem;
    color: var(--m-text-muted);
    margin-top: 2px;
    line-height: 1.3;
}
.map-w__body {
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* ═══════ Sidebar: Plano atual ═══════ */
.map-curr {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px;
    border-radius: 9px;
    background: color-mix(in srgb, var(--p-primary-color) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--p-primary-color) 25%, transparent);
}
.map-curr__name {
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--p-primary-color);
    line-height: 1.1;
}
.map-curr__key {
    font-size: 0.7rem;
    color: var(--m-text-muted);
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}
.map-curr__price {
    font-size: 0.85rem;
    color: var(--m-text);
    font-weight: 600;
    margin-top: 4px;
}

/* ═══════ Sidebar: Filtros ═══════ */
.map-interval {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.map-interval__label {
    font-size: 0.74rem;
    color: var(--m-text-muted);
    font-weight: 600;
}
.map-interval__btn {
    flex: 1;
    padding: 7px 12px;
    border-radius: 999px;
    border: 1.5px solid var(--m-border);
    background: var(--m-bg-soft);
    color: var(--m-text);
    cursor: pointer;
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    transition: all 140ms ease;
}
.map-interval__btn:hover { background: var(--m-bg-soft-hover); }
.map-interval__btn.is-active {
    background: var(--p-primary-color);
    border-color: var(--p-primary-color);
    color: var(--p-primary-contrast-color, #fff);
}
.map-interval__btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* ═══════ Buttons ═══════ */
.map-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: 8px;
    border: 1px solid var(--m-border);
    background: var(--m-bg-soft);
    color: var(--m-text);
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 600;
    font-family: inherit;
    transition: background-color 120ms ease, opacity 120ms ease;
}
.map-btn:hover { background: var(--m-bg-soft-hover); }
.map-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.map-btn--primary {
    background: var(--p-primary-color);
    border-color: var(--p-primary-color);
    color: var(--p-primary-contrast-color, #fff);
}
.map-btn--primary:hover {
    background: color-mix(in srgb, var(--p-primary-color) 88%, black);
}
.map-btn--full { width: 100%; }

/* ═══════ Plan cards (main) ═══════ */
.map-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
    align-content: start;
}
@media (min-width: 768px) {
    .map-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1280px) {
    .map-cards { grid-template-columns: repeat(3, 1fr); }
}
.map-plan {
    background: var(--m-bg-soft);
    border: 1.5px solid var(--m-border);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    display: flex;
    flex-direction: column;
    transition: border-color 140ms ease, box-shadow 140ms ease;
}
.map-plan:hover {
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.14);
}
.map-plan.is-current {
    border-color: color-mix(in srgb, var(--p-primary-color) 55%, transparent);
    box-shadow: 0 4px 18px color-mix(in srgb, var(--p-primary-color) 12%, transparent);
}
.map-plan__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--m-border);
}
.map-plan__title { min-width: 0; flex: 1; }
.map-plan__name {
    font-size: 0.96rem;
    font-weight: 700;
    color: var(--m-text);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.map-plan__key {
    font-size: 0.7rem;
    color: var(--m-text-muted);
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    margin-top: 2px;
}
.map-plan__body {
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    flex: 1;
}
.map-plan__desc {
    font-size: 0.82rem;
    color: var(--m-text-muted);
    line-height: 1.4;
}
.map-plan__price {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.map-plan__price-val {
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--m-text);
    line-height: 1.1;
}
.map-plan__price-hint {
    font-size: 0.7rem;
    color: var(--m-text-muted);
}
.map-plan__actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: auto;
}
.map-plan__actions-row {
    display: flex;
    gap: 6px;
}
.map-plan__actions-row .map-btn {
    flex: 1;
    flex-direction: column;
    gap: 2px;
    padding: 8px 6px;
    font-size: 0.74rem;
}
.map-plan__sub-price {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--m-text-muted);
}

/* ═══════ Empty states ═══════ */
.map-empty {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px;
    border-radius: 9px;
    background: var(--m-bg-soft);
    border: 1px dashed var(--m-border);
    color: var(--m-text-muted);
    font-size: 0.82rem;
}
.map-empty > i { color: var(--p-primary-color); font-size: 0.92rem; }
.map-empty--big {
    flex-direction: column;
    text-align: center;
    padding: 36px 24px;
    gap: 10px;
}
.map-empty--big > i { font-size: 2rem; opacity: 0.6; }
.map-empty__icon {
    font-size: 2rem;
    color: var(--m-text-faint);
    opacity: 0.6;
}
.map-empty__title {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--m-text);
}
.map-empty__hint {
    font-size: 0.78rem;
    color: var(--m-text-muted);
    line-height: 1.4;
}

/* ═══════ Mobile drawer ═══════ */
.map-mobile-drawer {
    position: fixed;
    top: 0; left: 0;
    height: 100vh;
    height: 100dvh;
    width: min(360px, 88vw);
    z-index: 80;
    background: var(--m-bg-medium);
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    border-right: 1px solid var(--m-border);
    transform: translateX(-100%);
    transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);
    color: var(--m-text);
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    display: flex;
    flex-direction: column;
}
.map-mobile-drawer.is-open { transform: translateX(0); }
.map-mobile-drawer__scroll {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.map-mobile-drawer__scroll .map-side {
    flex: 1;
    min-height: 0;
    width: 100%;
    overflow: hidden;
    background: transparent;
    border-right: none;
    display: flex;
    flex-direction: column;
}
.map-mobile-drawer__scroll .map-side__scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    scrollbar-width: thin;
    scrollbar-color: var(--m-border-strong) transparent;
}
.map-mobile-drawer__scroll .map-side__scroll::-webkit-scrollbar { width: 5px; }
.map-mobile-drawer__scroll .map-side__scroll::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 3px;
}
.map-mobile-drawer__scroll .map-w--side {
    margin: 0;
    flex-shrink: 0;
}
.map-mobile-drawer__scroll .map-side__footer {
    flex-shrink: 0;
    margin: 0;
    padding: 12px;
    background: var(--m-bg-medium);
    border-top: 1px solid var(--m-border);
}

.map-mobile-drawer__backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 79;
}
.map-drawer-fade-enter-active,
.map-drawer-fade-leave-active { transition: opacity 200ms ease; }
.map-drawer-fade-enter-from,
.map-drawer-fade-leave-to { opacity: 0; }

/* Desktop (>=1024): cards da sidebar (Plano atual + Filtros) ganham
   min-h 300 + max-h 100% + body com overflow-y: auto pra nao
   crescerem demais quando tem texto longo. Plan cards do main
   (.map-plan) ficam fora — sao product cards com layout proprio. */
@media (min-width: 1024px) {
    .map-side > .map-side__scroll > .map-w--side {
        min-height: 300px;
        max-height: 100%;
        display: flex;
        flex-direction: column;
    }
    .map-side .map-w--side > .map-w__body {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        scrollbar-width: thin;
        scrollbar-color: var(--m-border-strong) transparent;
    }
    .map-side .map-w--side > .map-w__body::-webkit-scrollbar { width: 5px; }
    .map-side .map-w--side > .map-w__body::-webkit-scrollbar-thumb {
        background: var(--m-border-strong);
        border-radius: 3px;
    }
}

/* ═══════ Mobile (<1024px) ═══════ */
@media (max-width: 1023px) {
    .map-body { flex-direction: column; padding: 0; }
    .map-side { display: none; }
    .map-main { width: 100%; padding: 8px; }
    .map-page__title > span:first-of-type { display: none; }
    .map-page__title-icon { display: none; }
    .map-menu-btn--mobile-only { display: inline-flex; }
}
</style>
