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

import { useLayout } from '@/layout/composables/layout';
import { useToast } from 'primevue/usetoast';

import { supabase } from '@/lib/supabase/client';
import { useEntitlementsStore } from '@/stores/entitlementsStore';
import { useTenantStore } from '@/stores/tenantStore';

import { useRoleGuard } from '@/composables/useRoleGuard';
const { canSee } = useRoleGuard();

import { useAjuda } from '@/composables/useAjuda';
const { openDrawer: openAjudaDrawer, closeDrawer: closeAjudaDrawer, drawerOpen: ajudaDrawerOpen } = useAjuda();

import NotificationDrawer from '@/components/notifications/NotificationDrawer.vue';
import GlobalSearch from '@/components/search/GlobalSearch.vue';
import { useNotifications } from '@/composables/useNotifications';
import { useNotificationStore } from '@/stores/notificationStore';
const notificationStore = useNotificationStore();
useNotifications();
function toggleAjuda() {
    ajudaDrawerOpen.value ? closeAjudaDrawer() : openAjudaDrawer();
}

import { useUserSettingsPersistence } from '@/composables/useUserSettingsPersistence';
import { useTopbarDevMenuExtras } from '@/composables/useTopbarDevMenuExtras';
import { applyThemeEngine } from '@/theme/theme.options';

import { fetchAllNotices } from '@/features/notices/noticeService';
import { useTenantFeaturesStore } from '@/stores/tenantFeaturesStore';
import { buildUpgradeUrl } from '@/utils/upgradeContext';

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

const { toggleMenu, toggleDarkMode, isDarkTheme, layoutConfig, changeMenuMode, isRailMobile } = useLayout();
const router = useRouter();
const route = useRoute();

const planBtn = ref(null);

/* ----------------------------
   Persistência
----------------------------- */
const { init: initUserSettings, queuePatch } = useUserSettingsPersistence();
provide('queueUserSettingsPatch', queuePatch);

/* ----------------------------
   Contexto (UID/Email/Tenant)
----------------------------- */
const sessionUid = ref(null);
const sessionEmail = ref(null);

async function loadSessionIdentity() {
    try {
        const { data, error } = await supabase.auth.getUser();
        if (error) throw error;
        sessionUid.value = data?.user?.id || null;
        sessionEmail.value = data?.user?.email || null;
    } catch (e) {
        sessionUid.value = null;
        sessionEmail.value = null;
        console.warn('[Topbar][identity] falhou:', e?.message || e);
    }
}

const tenantId = computed(() => tenantStore.activeTenantId || null);

// ✅ Admin Dev
const ctxItems = computed(() => {
    const items = [];
    // ids (sempre úteis pra debug)
    if (tenantId.value) items.push({ k: 'Tenant', v: tenantId.value });
    if (sessionUid.value) items.push({ k: 'UID', v: sessionUid.value });

    return items;
});

/* ----------------------------
   Fonte da verdade: DOM
----------------------------- */
function isDarkNow() {
    return document.documentElement.classList.contains('app-dark');
}

function setDarkMode(shouldBeDark) {
    const now = isDarkNow();
    if (shouldBeDark !== now) toggleDarkMode();
}

async function waitForDarkFlip(before, timeoutMs = 900) {
    const start = performance.now();
    while (performance.now() - start < timeoutMs) {
        await nextTick();
        await new Promise((r) => requestAnimationFrame(r));
        const now = isDarkNow();
        if (now !== before) return now;
    }
    return isDarkNow();
}

async function loadAndApplyUserSettings() {
    try {
        const { data: u, error: uErr } = await supabase.auth.getUser();
        if (uErr) throw uErr;
        const uid = u?.user?.id;
        if (!uid) return;

        const { data: settings, error } = await supabase.from('user_settings').select('theme_mode, preset, primary_color, surface_color, menu_mode').eq('user_id', uid).maybeSingle();

        if (error) throw error;
        if (!settings) return;

        // 1) dark/light (DOM é a fonte da verdade)
        if (settings.theme_mode) setDarkMode(settings.theme_mode === 'dark');

        // 2) layoutConfig
        if (settings.preset) layoutConfig.preset = settings.preset;
        if (settings.primary_color) layoutConfig.primary = settings.primary_color;
        if (settings.surface_color) layoutConfig.surface = settings.surface_color;
        if (settings.menu_mode) layoutConfig.menuMode = settings.menu_mode;

        // 3) aplica engine UMA vez
        applyThemeEngine(layoutConfig);

        // 4) persiste no localStorage para carregamento instantâneo no próximo boot
        try {
            localStorage.setItem('ui_theme_config', JSON.stringify({
                preset: layoutConfig.preset,
                primary: layoutConfig.primary,
                surface: layoutConfig.surface,
                menuMode: layoutConfig.menuMode
            }));
        } catch {}

        // ✅ IMPORTANTE:
        // changeMenuMode NÃO é só "setar menuMode".
        // Ele reseta estados do sidebar/overlay/mobile e previne drift.
        // No layout Rail, não deve ser chamado — ele não usa menuMode.
        if (layoutConfig.variant !== 'rail') {
            try {
                changeMenuMode(layoutConfig.menuMode);
            } catch (e) {
                try {
                    changeMenuMode({ value: layoutConfig.menuMode });
                } catch {}
                console.warn('[Topbar][bootstrap] changeMenuMode falhou:', e?.message || e);
            }
        }
    } catch (e) {
        console.error('[Topbar][bootstrap] erro:', e?.message || e);
    }
}

async function toggleDarkAndPersistSilently() {
    try {
        const before = isDarkNow();
        toggleDarkMode();
        const after = await waitForDarkFlip(before);
        const theme_mode = after ? 'dark' : 'light';
        try { localStorage.setItem('ui_theme_mode', theme_mode); } catch {}
        await queuePatch({ theme_mode }, { flushNow: true });
    } catch (e) {
        console.error('[Topbar][theme] falhou:', e?.message || e);
    }
}

/* ----------------------------
   Plano (DEV) — popup menu
----------------------------- */
const trocandoPlano = ref(false);

const enablePlanToggle = computed(() => {
    const flag = String(import.meta.env?.VITE_ENABLE_PLAN_TOGGLE || '').toLowerCase();
    return Boolean(import.meta.env?.DEV) || flag === 'true';
});

const showPlanDevMenu = computed(() => {
    return canSee('settings.view') && enablePlanToggle.value;
});

/* ----------------------------
   Upgrade PRO — botão user-facing quando o plano ativo é gratuito.
   Reusa resolveActiveSubscriptionContext() (clínica via tenant_id,
   pessoal via user_id) e expõe só plan_key pra decidir o badge.
----------------------------- */
const activePlanKey = ref(null);
const isFreePlan = computed(() => {
    const k = String(activePlanKey.value || '').toLowerCase();
    return k.endsWith('_free') || k === 'free';
});

async function loadPlanBadge() {
    try {
        const { sub } = await resolveActiveSubscriptionContext();
        activePlanKey.value = sub?.plan_key ?? null;
    } catch {
        activePlanKey.value = null; // ausência do badge nunca pode quebrar a topbar
    }
}

function goUpgrade() {
    router.push(buildUpgradeUrl({ redirectTo: route.fullPath }));
}

const ctxMenu = ref();
const ctxMenuModel = computed(() =>
    ctxItems.value.length
        ? ctxItems.value.map((it) => ({
              label: `${it.k}: ${it.v}`,
              icon: it.k === 'Tenant' ? 'pi pi-building' : 'pi pi-user'
          }))
        : [{ label: 'Sem contexto', icon: 'pi pi-info-circle', disabled: true }]
);
function openCtxMenu(event) {
    ctxMenu.value?.toggle?.(event);
}

const planMenu = ref();
const planMenuLoading = ref(false);
const planMenuTarget = ref(null); // 'therapist' | 'clinic' | null
const planMenuSub = ref(null); // subscription ativa (obj)
const planMenuPlans = ref([]); // plans ativos do target

async function getMyUserId() {
    const { data, error } = await supabase.auth.getUser();
    if (error) throw error;
    const uid = data?.user?.id;
    if (!uid) throw new Error('Sessão inválida (sem user).');
    return uid;
}

// therapist subscription: user_id — sem filtro de tenant_id (pode estar preenchido)
async function getActiveTherapistSubscription() {
    const uid = await getMyUserId();

    const { data, error } = await supabase.from('subscriptions').select('id, tenant_id, user_id, plan_id, plan_key, status, updated_at').eq('user_id', uid).order('updated_at', { ascending: false }).limit(10);

    if (error) throw error;

    const list = data || [];
    if (!list.length) return null;

    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;
    };

    return list.slice().sort((a, b) => {
        const pa = priority(a?.status);
        const pb = priority(b?.status);
        if (pa !== pb) return pa - pb;
        return new Date(b?.updated_at || 0) - new Date(a?.updated_at || 0);
    })[0];
}

async function getActiveClinicSubscription() {
    const tid = tenantId.value;
    if (!tid) return null;

    const { data, error } = await supabase.from('subscriptions').select('id, tenant_id, user_id, plan_id, plan_key, status, updated_at').eq('tenant_id', tid).eq('status', 'active').order('updated_at', { ascending: false }).limit(1).maybeSingle();

    if (error) throw error;
    return data || null;
}

async function listActivePlansByTarget(target) {
    const { data, error } = await supabase.from('plans').select('id, key, target, is_active').eq('target', target).eq('is_active', true).order('key', { ascending: true });

    if (error) throw error;
    return data || [];
}

async function refreshEntitlementsAfterToggle(target) {
    // ✅ aqui NÃO dá pra usar invalidate geral, porque precisamos dos dois caches
    // mas durante toggle, é mais seguro forçar recarga do escopo que foi alterado.

    if (target === 'clinic') {
        const tid = tenantId.value;
        if (!tid) return;
        await entitlementsStore.loadForTenant(tid, { force: true });
        return;
    }

    // therapist
    const uid = await getMyUserId();
    await entitlementsStore.loadForUser(uid, { force: true });
}

/**
 * ✅ Resolve a subscription ativa levando em conta a área da rota atual.
 *
 * Áreas de clínica (/admin, /supervisor) → contexto tenant_id (clinic)
 * Demais áreas (/therapist, /editor, /portal, etc.) → contexto user_id (pessoal)
 *
 * Isso evita que um editor que também é membro de uma clínica veja o plano
 * da clínica no botão DEV em vez do seu próprio plano.
 */
async function resolveActiveSubscriptionContext() {
    const path = route.path || '';
    const isClinicContext = path.startsWith('/admin') || path.startsWith('/supervisor');

    if (isClinicContext && tenantId.value) {
        const clinicSub = await getActiveClinicSubscription();
        if (clinicSub) return { sub: clinicSub, target: 'clinic' };
    }

    const therapistSub = await getActiveTherapistSubscription();
    if (therapistSub) return { sub: therapistSub, target: 'therapist' };

    // último fallback: clinic (caso não-clínica sem sub pessoal)
    if (tenantId.value) {
        const clinicSub = await getActiveClinicSubscription();
        return { sub: clinicSub || null, target: clinicSub ? 'clinic' : null };
    }

    return { sub: null, target: null };
}

function normalizeKey(k) {
    return String(k || '').trim();
}

// free primeiro, depois o resto por key
function sortPlansSmart(plans) {
    const arr = [...(plans || [])];
    arr.sort((a, b) => {
        const ak = normalizeKey(a?.key).toLowerCase();
        const bk = normalizeKey(b?.key).toLowerCase();

        const aIsFree = ak.endsWith('_free') || ak === 'free';
        const bIsFree = bk.endsWith('_free') || bk === 'free';
        if (aIsFree && !bIsFree) return -1;
        if (!aIsFree && bIsFree) return 1;

        return ak.localeCompare(bk);
    });
    return arr;
}

async function loadPlanMenuData() {
    planMenuLoading.value = true;
    try {
        const { sub, target } = await resolveActiveSubscriptionContext();
        planMenuSub.value = sub;
        planMenuTarget.value = target;

        if (!sub?.id || !target) {
            planMenuPlans.value = [];
            return;
        }

        const plans = await listActivePlansByTarget(target);
        planMenuPlans.value = sortPlansSmart(plans);
    } finally {
        planMenuLoading.value = false;
    }
}

const planMenuModel = computed(() => {
    const sub = planMenuSub.value;
    const target = planMenuTarget.value;
    const plans = planMenuPlans.value || [];

    if (!sub?.id || !target) {
        return [
            { label: 'Sem assinatura ativa', icon: 'pi pi-exclamation-triangle', disabled: true },
            { label: 'Não encontrei subscription ativa nem para therapist (user_id) nem para clinic (tenant_id).', disabled: true }
        ];
    }

    const currentPlanId = String(sub.plan_id || '');

    const header = {
        label: `Planos (${target})`,
        icon: target === 'therapist' ? 'pi pi-user' : 'pi pi-building',
        disabled: true
    };

    const subInfo = {
        label: `Sub: ${String(sub.id).slice(0, 8)}…  •  Atual: ${String(currentPlanId).slice(0, 8)}…`,
        icon: 'pi pi-info-circle',
        disabled: true
    };

    const items = [];
    let insertedSeparator = false;

    plans.forEach((p) => {
        const isCurrent = String(p.id) === currentPlanId;
        const keyLower = String(p.key || '').toLowerCase();
        const isFree = keyLower.endsWith('_free') || keyLower === 'free';

        items.push({
            label: isCurrent ? `${p.key} (atual)` : p.key,
            icon: isCurrent ? 'pi pi-check' : isFree ? 'pi pi-star' : 'pi pi-circle',
            disabled: isCurrent || planMenuLoading.value || trocandoPlano.value,
            command: async () => {
                await changePlanTo(p.id, p.key, target);
            }
        });

        if (!insertedSeparator && isFree) {
            items.push({ separator: true });
            insertedSeparator = true;
        }
    });

    if (items.length && items[items.length - 1]?.separator) items.pop();

    if (!plans.length) {
        return [header, subInfo, { separator: true }, { label: 'Nenhum plano ativo encontrado', icon: 'pi pi-info-circle', disabled: true }];
    }

    return [header, subInfo, { separator: true }, ...items];
});

// ─── Extras do menu DEV (layout switcher + atalhos M1) ────────────
const { devExtrasModel } = useTopbarDevMenuExtras();
const combinedDevMenuModel = computed(() => [
    ...planMenuModel.value,
    { separator: true },
    ...devExtrasModel.value
]);

async function openPlanMenu(event) {
    if (!showPlanDevMenu.value) return;

    try {
        await loadPlanMenuData();
    } catch (err) {
        console.error('[PLANO][DEV menu] erro:', err?.message || err);
        toast.add({
            severity: 'error',
            summary: 'Erro ao carregar planos',
            detail: err?.message || 'Falha desconhecida.',
            life: 5200
        });
    }

    const anchorEl = planBtn.value?.$el || event?.currentTarget || event?.target;
    if (!anchorEl) {
        planMenu.value?.toggle?.(event);
        return;
    }

    planMenu.value?.show?.({ currentTarget: anchorEl });
}

async function changePlanTo(newPlanId, newPlanKey, target) {
    if (trocandoPlano.value) return;
    trocandoPlano.value = true;

    try {
        const sub = planMenuSub.value;
        if (!sub?.id) throw new Error('Subscription inválida.');

        const { error: rpcError } = await supabase.rpc('change_subscription_plan', {
            p_subscription_id: sub.id,
            p_new_plan_id: newPlanId
        });
        if (rpcError) throw rpcError;

        planMenuSub.value = { ...sub, plan_id: newPlanId };

        // ✅ recarrega o escopo certo (tenant ou user)
        await refreshEntitlementsAfterToggle(target);

        toast.add({
            severity: 'success',
            summary: 'Plano alterado (DEV)',
            detail: `${String(newPlanKey).toUpperCase()} aplicado (${target})`,
            life: 3200
        });
    } catch (err) {
        console.error('[PLANO] Erro ao trocar:', err?.message || err);
        toast.add({
            severity: 'error',
            summary: 'Erro ao trocar plano',
            detail: err?.message || 'Falha desconhecida.',
            life: 6000
        });
    } finally {
        trocandoPlano.value = false;
    }
}

/* ----------------------------
   SaaS — indicador de avisos ativos
----------------------------- */
const isSaasArea = computed(() => String(route.path || '').startsWith('/saas'));
const saasActiveCount = ref(0);

async function loadSaasNoticeCount() {
    try {
        const all = await fetchAllNotices();
        saasActiveCount.value = all.filter((n) => n.is_active).length;
    } catch {
        /* silencioso */
    }
}

watch(
    isSaasArea,
    (is) => {
        if (is) loadSaasNoticeCount();
    },
    { immediate: true }
);

/* ----------------------------
   Logout
----------------------------- */
async function logout() {
    const tenant = useTenantStore();
    const ent = useEntitlementsStore();
    const tf = useTenantFeaturesStore();

    try {
        await supabase.auth.signOut();
    } finally {
        tenant.reset();
        ent.invalidate();
        tf.invalidate();
        notificationStore.reset(); // pegadinha #4: limpa sino ao trocar de usuário

        sessionStorage.clear();
        localStorage.clear();

        router.replace('/auth/login');
    }
}

/**
 * ✅ Bootstrap entitlements (resolve "menu não alterna" sem depender do guard)
 * - se tem tenant ativo => carrega tenant entitlements
 * - senão => carrega user entitlements
 */
async function bootstrapEntitlements() {
    try {
        const uid = sessionUid.value || (await getMyUserId());
        const tid = tenantId.value;

        if (tid) {
            await entitlementsStore.loadForTenant(tid, { force: false, maxAgeMs: 60_000 });
        } else if (uid) {
            await entitlementsStore.loadForUser(uid, { force: false, maxAgeMs: 60_000 });
        }
    } catch (e) {
        console.warn('[Topbar][entitlements bootstrap] falhou:', e?.message || e);
    }
}

onMounted(async () => {
    await initUserSettings();
    await loadAndApplyUserSettings();
    await loadSessionIdentity();
    await bootstrapEntitlements();
    loadPlanBadge();
});

// recarrega o badge de plano só ao trocar de tenant ou de contexto (clínica vs
// pessoal) — não a cada navegação, pra evitar queries desnecessárias.
const isClinicArea = computed(() => {
    const p = route.path || '';
    return p.startsWith('/admin') || p.startsWith('/supervisor');
});
watch([tenantId, isClinicArea], () => { loadPlanBadge(); });
</script>

<template>
    <header class="rail-topbar">
        <!-- Esquerda -->
        <div class="rail-topbar__left">
            <!-- Hamburguer: só aparece em ≤ xl (1280px) no Rail -->
            <button class="layout-menu-button rail-topbar__btn rail-topbar__hamburger" @click="toggleMenu">
                <i class="pi pi-bars"></i>
            </button>

            <router-link to="/" class="layout-topbar-logo ml-3">
                <span>Agência PSI</span>
            </router-link>

            <!-- Indicador de avisos globais ativos — SaaS only -->
            <router-link v-if="isSaasArea && saasActiveCount > 0" to="/saas/global-notices" class="topbar-notice-chip ml-3" :title="`${saasActiveCount} aviso(s) global(is) ativo(s)`">
                <span class="topbar-notice-chip__dot" />
                <i class="pi pi-megaphone topbar-notice-chip__icon" />
                <span class="topbar-notice-chip__label"> {{ saasActiveCount }} aviso{{ saasActiveCount !== 1 ? 's' : '' }} ativo{{ saasActiveCount !== 1 ? 's' : '' }} </span>
            </router-link>

            <!-- Pills: visíveis apenas em > xl (1280px) -->
            <div class="topbar-ctx-row ml-2">
                <span v-for="(it, idx) in ctxItems" :key="`${it.k}-${idx}`" class="topbar-ctx-pill" :title="`${it.k}: ${it.v}`">
                    <b class="topbar-ctx-k">{{ it.k }}:</b>
                    <span class="topbar-ctx-v">{{ it.v }}</span>
                </span>
            </div>

            <!-- Botão Tenant/UID: visível apenas em ≤ xl (1280px) -->
            <button type="button" class="rail-topbar__btn topbar-ctx-btn ml-2" title="Tenant / UID" @click="openCtxMenu">
                <i class="pi pi-id-card" />
                <span class="topbar-ctx-btn__label">Tenant / UID</span>
            </button>
            <Menu ref="ctxMenu" :model="ctxMenuModel" popup appendTo="body" :baseZIndex="3000" />
        </div>

        <!-- Busca global (Ctrl+K) -->
        <div class="rail-topbar__search">
            <GlobalSearch />
        </div>

        <!-- Ações -->
        <div class="rail-topbar__actions">
            <!-- Upgrade PRO — só quando o plano ativo é gratuito -->
            <Button v-if="isFreePlan" label="Upgrade PRO" icon="pi pi-star-fill" size="small" class="rail-topbar__upgrade-btn" @click="goUpgrade" />

            <!-- Plan Dev Button -->
            <Button v-if="showPlanDevMenu" ref="planBtn" outlined :loading="planMenuLoading || trocandoPlano" :disabled="planMenuLoading || trocandoPlano" @click="openPlanMenu" class="rail-topbar__btn">
                <i class="pi pi-sliders-h" />
            </Button>

            <Menu ref="planMenu" :model="combinedDevMenuModel" popup appendTo="body" :baseZIndex="3000" />

            <!-- Notificações -->
            <div class="relative">
                <button type="button" class="rail-topbar__btn" title="Notificações" @click="notificationStore.drawerOpen = true">
                    <i class="pi pi-bell" />
                    <span v-if="notificationStore.unreadCount > 0" class="rail-topbar__notification-badge">
                        {{ notificationStore.unreadCount > 99 ? '99+' : notificationStore.unreadCount }}
                    </span>
                </button>
                <NotificationDrawer />
            </div>

            <!-- Ajuda — data-ajuda-toggle ignora este botao no
                 click-outside do AjudaDrawer (senao fecha + reabre). -->
            <button type="button" class="rail-topbar__btn" :class="{ 'rail-topbar__btn--active': ajudaDrawerOpen }" :title="ajudaDrawerOpen ? 'Fechar ajuda' : 'Ajuda'" data-ajuda-toggle @click="toggleAjuda">
                <i class="pi pi-question-circle" />
            </button>

            <!-- Dark mode -->
            <button type="button" class="rail-topbar__btn" :title="isDarkTheme ? 'Modo claro' : 'Modo escuro'" @click="toggleDarkAndPersistSilently">
                <i :class="['pi', { 'pi-moon': isDarkTheme, 'pi-sun': !isDarkTheme }]"></i>
            </button>

        </div>
    </header>
</template>

<style scoped>
.rail-topbar {
    position: fixed;
    top: var(--notice-banner-height, 0px);
    left: 0;
    right: 0;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 1.25rem;
    border-bottom: 1px solid var(--surface-border);
    background: var(--surface-card);
    z-index: 100;
}

.rail-topbar__left {
    display: flex;
    align-items: center;
    min-width: 0;
}

/* Hamburguer: visível apenas em ≤ xl (1280px)
   !important necessário para sobrescrever CSS do tema (.layout-menu-button) */
.rail-topbar__hamburger {
    display: none !important;
}
@media (width <= theme(--breakpoint-xl, 1280px)) {
    .rail-topbar__hamburger {
        display: grid !important;
    }
}

.rail-topbar__actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* Busca global — centralizada entre left e actions */
.rail-topbar__search {
    display: flex;
    align-items: center;
    flex: 1 1 auto;
    justify-content: center;
    min-width: 0;
    padding: 0 1rem;
    max-width: 520px;
    margin: 0 auto;
}
@media (max-width: 640px) {
    .rail-topbar__search {
        padding: 0 0.5rem;
    }
}
@media (max-width: 480px) {
    .rail-topbar__search {
        padding: 0 0.25rem;
        flex: 0 0 auto;
    }
}

.rail-topbar__btn {
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--text-color-secondary);
    display: grid;
    place-items: center;
    cursor: pointer;
    font-size: 1rem;
    transition:
        background 0.15s,
        color 0.15s;
}
.rail-topbar__btn:hover {
    background: var(--surface-ground);
    color: var(--text-color);
}
.rail-topbar__btn--highlight {
    color: var(--primary-color);
}
.rail-topbar__btn--active {
    background: var(--surface-ground);
    color: var(--primary-color);
}

/* ── Botão Upgrade PRO (plano gratuito) ──────────────────── */
.rail-topbar__upgrade-btn {
    background: linear-gradient(135deg, #f59e0b, #d97706);
    border: none;
    color: #fff;
    font-weight: 600;
    border-radius: 999px;
    box-shadow: 0 1px 3px rgba(217, 119, 6, 0.35);
}
.rail-topbar__upgrade-btn:hover {
    filter: brightness(1.05);
}
.config-panel {
    z-index: 200;
}

/* ── Chip de avisos ativos (SaaS) ────────────────────────── */
.topbar-notice-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.28rem 0.75rem 0.28rem 0.55rem;
    border-radius: 999px;
    background: #f59e0b;
    color: #fff;
    font-size: 0.78rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55);
    animation: topbar-notice-pulse 2s ease-in-out infinite;
    transition: filter 0.15s;
}
.topbar-notice-chip:hover {
    filter: brightness(1.1);
}
.topbar-notice-chip__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #fff;
    flex-shrink: 0;
    animation: topbar-dot-blink 1.4s ease-in-out infinite;
}
.topbar-notice-chip__icon {
    font-size: 0.8rem;
}
@keyframes topbar-notice-pulse {
    0%,
    100% {
        box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55);
    }
    50% {
        box-shadow: 0 0 0 6px rgba(245, 158, 11, 0);
    }
}
@keyframes topbar-dot-blink {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0.35;
    }
}
/* Mobile: oculta o texto, mantém ícone + dot */
@media (max-width: 600px) {
    .topbar-notice-chip__label {
        display: none;
    }
    .topbar-notice-chip {
        padding: 0.28rem 0.5rem;
    }
}

/* Badge de notificações */
.rail-topbar__notification-badge {
    position: absolute;
    top: 0;
    right: 0;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 0.62rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    pointer-events: none;
    transform: translate(25%, -25%);
}
.topbar-ctx-row {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-wrap: wrap;
}
.topbar-ctx-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.45rem;
    border-radius: 999px;
    border: 1px solid var(--surface-border);
    background: var(--surface-card);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.02);
}

/* Botão Tenant/UID: só em ≤ xl (1280px) */
.topbar-ctx-btn {
    display: none !important;
    width: auto !important;
    border-radius: 999px !important;
    padding: 0 0.65rem !important;
    gap: 0.35rem;
    font-size: 0.8rem;
    border: 1px solid var(--surface-border) !important;
}
.topbar-ctx-btn__label {
    font-size: 0.8rem;
    color: var(--text-color-secondary);
}
@media (width <= theme(--breakpoint-xl, 1280px)) {
    .topbar-ctx-row {
        display: none !important;
    }
    .topbar-ctx-btn {
        display: inline-flex !important;
    }
}
</style>
