/* ============================================================
   Consultor · Design System v1.9 — BUNDLE
   Gerado por `python manage.py build_ds`. NÃO EDITE ÀQUI.
   Para editar: mexa nos módulos em ds/ e rode o comando.
   ============================================================ */


/* ===== _tokens.css ===== */
/* ============================================================
   DS · Tokens
   Fonte única da verdade de cores, sombras e motion.
   Espelha base_style.css + adiciona novos tokens (v1.2).
   ============================================================ */

:root,
html.light {
    /* Cores de marca */
    --primary-blue:        #596589;
    --primary-blue-hover:  #4A5775;                        /* 10% escuro — substitui opacity-90 */
    --primary-blue-tint:   rgba(89, 101, 137, 0.10);       /* icon-box, hover bg */
    --primary-blue-soft:   rgba(89, 101, 137, 0.20);       /* selected, badge subtle */

    --primary-black:       #342028;
    --secondary-gray:      #5C5D5F;                        /* escurecido p/ passar WCAG AA */

    /* Cores semânticas (tokens — delegam para Tailwind semantic scale) */
    --text-main:           var(--primary-black);
    --text-muted:          var(--secondary-gray);
    --bg-page:             #F8FAFC;
    --surface:             #FFFFFF;
    --surface-raised:      #FFFFFF;                        /* = surface em light */
    --border-ui:           rgba(52, 32, 40, 0.12);
    --border-strong:       rgba(52, 32, 40, 0.20);
    --title-color:         #1e3a8a;

    /* Elevação (sombra tinted com primary-black, não preto puro) */
    --shadow-elev-1: 0 1px 2px rgba(52, 32, 40, 0.04),
                     0 1px 3px rgba(52, 32, 40, 0.06);
    --shadow-elev-2: 0 4px 6px -1px rgba(52, 32, 40, 0.08),
                     0 2px 4px -2px rgba(52, 32, 40, 0.06);
    --shadow-elev-3: 0 20px 25px -5px rgba(52, 32, 40, 0.08),
                     0 8px 10px -6px rgba(52, 32, 40, 0.06);

    /* Motion — 3 durações, 2 curvas */
    --motion-instant:    80ms cubic-bezier(0.4, 0, 0.2, 1);
    --motion-smooth:     200ms cubic-bezier(0.4, 0, 0.2, 1);
    --motion-deliberate: 400ms cubic-bezier(0.16, 1, 0.3, 1);
}

html.dark {
    --primary-blue:        #7B88B0;                        /* clareado p/ AA em dark */
    --primary-blue-hover:  #8A98C0;
    --primary-blue-tint:   rgba(123, 136, 176, 0.14);
    --primary-blue-soft:   rgba(123, 136, 176, 0.24);

    --primary-black:       #F4F4F5;
    --text-main:           var(--primary-black);
    --text-muted:          #A1A1AA;
    --bg-page:             #09090B;
    --surface:             #18181B;
    --surface-raised:      #23232A;                        /* mais claro que card em dark */
    --border-ui:           rgba(255, 255, 255, 0.12);
    --border-strong:       rgba(255, 255, 255, 0.20);
    --title-color:         #FFFFFF;

    /* Em dark, elevação vem da borda + surface-raised, não de sombra pesada */
    --shadow-elev-1: none;
    --shadow-elev-2: 0 4px 6px -1px rgba(0, 0, 0, 0.5);
    --shadow-elev-3: 0 20px 25px -5px rgba(0, 0, 0, 0.7),
                     0 8px 10px -6px rgba(0, 0, 0, 0.5);
}


/* ===== _base.css ===== */
/* ============================================================
   DS · Base
   Reset leve, focus-ring utilitário, keyframes e a11y global.
   Não contém componentes — só fundação comportamental.
   ============================================================ */

/* -------- Fonte única do site (Inter) + números tabulares --------
   v1.4: obrigatoriedade de ter uma fonte só no site inteiro.
   Inter + tabular-nums garante que números alinham por coluna
   sem precisar de monospace.

   html.light e html.dark herdam. O <body> do base_site já declara
   font-family; reforçamos aqui para templates sem extends (modais).
*/
html {
    font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
                 'Segoe UI', Roboto, sans-serif;
    font-variant-numeric: tabular-nums;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
body {
    font-family: inherit;
}
code, kbd, pre, samp {
    font-family: inherit;          /* v1.4: <code> também usa Inter para consistência */
    font-variant-numeric: tabular-nums;
}

/* -------- Keyframes canônicos -------- */
@keyframes ds-fadeIn {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes ds-slideDown {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes ds-scaleIn {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: scale(1); }
}
@keyframes ds-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position:  200% 0; }
}

/* -------- A11Y: prefers-reduced-motion (WCAG 2.3.3) -------- */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* -------- Focus-ring utilitário (só keyboard, preserva mouse) --------
   Aplicar a qualquer elemento interativo:
     <button class="btn btn-primary focus-ring">…</button>
   Já embutido em .btn, .input, .icon-btn.
*/
.focus-ring:focus-visible {
    outline: none;
    border-color: var(--primary-blue);
    box-shadow: 0 0 0 4px var(--primary-blue-tint);
}


/* ===== utilities.css ===== */
/* ============================================================
   DS · Utilities
   Atalhos de classe para tokens usados diretamente em templates.
   Equivale ao que seria `@apply` — escritos como CSS puro
   para não exigir toolchain (Tailwind CDN no projeto).
   ============================================================ */

/* -------- Elevação -------- */
.shadow-elev-1 { box-shadow: var(--shadow-elev-1); }
.shadow-elev-2 { box-shadow: var(--shadow-elev-2); }
.shadow-elev-3 { box-shadow: var(--shadow-elev-3); }

/* -------- Animações -------- */
.animate-fadeIn    { animation: ds-fadeIn    var(--motion-deliberate) both; }
.animate-slideDown { animation: ds-slideDown var(--motion-smooth)     both; }
.animate-scaleIn   { animation: ds-scaleIn   var(--motion-deliberate) both; }

/* -------- Superfícies semânticas (legibilidade em templates) -------- */
.surface          { background-color: var(--surface); }
.surface-raised   { background-color: var(--surface-raised); }
.bg-page          { background-color: var(--bg-page); }

/* -------- Texto semântico -------- */
.text-main        { color: var(--text-main); }
.text-muted       { color: var(--text-muted); }
.text-title       { color: var(--title-color); }
.text-brand       { color: var(--primary-blue); }

/* -------- Borda -------- */
.border-ui        { border: 1px solid var(--border-ui); }
.border-strong    { border: 1px solid var(--border-strong); }


/* ===== action-bar.css ===== */
/* ============================================================
   DS · Action bar
   Barra de ações primárias de um formulário longo. Mobile-first:
   gruda no rodapé da viewport para a CTA ficar sempre visível
   enquanto o usuário rola um form alto. Em ≥1024px volta a
   ser estática (fluxo normal do card).

   Uso (dentro de um .card / .card-flush):
     <div class="action-bar">
       <button class="btn btn-primary">Calcular</button>
       <button class="btn btn-secondary">Limpar</button>
     </div>

   Variante quando a barra mora dentro de um corpo `px-5 py-4`
   e deve colar nas bordas do card (sem gap visual):
     <div class="action-bar action-bar-in-card">…</div>

   Notas:
   - Cobre safe-area-inset-bottom (iOS com notch / barra de gestos).
   - Sticky é relativo à viewport — funciona dentro do .page-wrap.
   - O utilitário `.hidden` (display:none) continua valendo: como
     este arquivo é carregado depois do Tailwind no bundle, há regra
     explícita restaurando `display:none` quando ambos coexistem.
   ============================================================ */

.action-bar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;

    background-color: var(--surface);
    border-top: 1px solid var(--border-ui);
    padding: 0.75rem 1.25rem;
    padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));

    /* Sombra apontando para cima — só no mobile sticky */
    box-shadow: 0 -2px 6px rgba(15, 23, 42, 0.06);
}

/* Preserva o utilitário `.hidden` (Tailwind) sobre action-bar. */
.action-bar.hidden,
.action-bar[hidden] {
    display: none;
}

/* Variante "in-card": cola nas bordas de um corpo `px-5 py-4`. */
.action-bar-in-card {
    margin-left: -1.25rem;
    margin-right: -1.25rem;
    margin-bottom: -1rem;
}

/* Desktop: vira ações normais no fluxo do form, sem sticky. */
@media (min-width: 1024px) {
    .action-bar {
        position: static;
        z-index: auto;
        background-color: transparent;
        border-top: 0;
        padding: 0;
        padding-bottom: 0;
        box-shadow: none;
    }
    .action-bar-in-card {
        margin: 0;
    }
}


/* ===== alert.css ===== */
/* ============================================================
   DS · Alert (v1.9)
   Aviso contextual in-line, não-efêmero, dentro de cards.
   Diferente de Toast (notificação efêmera) e Empty (estado vazio).

   Uso — completo (ícone + título + descrição):
     <div class="alert alert-warning">
       <i class="ph-fill ph-warning-circle alert-icon" aria-hidden="true"></i>
       <div class="alert-body">
         <p class="alert-title">Aviso Prévio</p>
         <p class="alert-desc">Início: 12/03/2026 — 30 dias</p>
       </div>
     </div>

   Uso — compact (uma linha, ícone + texto):
     <div class="alert alert-success alert-compact">
       <i class="ph-fill ph-check-circle alert-icon" aria-hidden="true"></i>
       <p class="alert-title">Acesso Liberado</p>
     </div>

   Variantes de cor:
     .alert-success — verde, confirmação positiva
     .alert-danger  — vermelho, erro ou bloqueio
     .alert-warning — amarelo, atenção
     .alert-info    — azul, neutro informacional
     .alert-neutral — cinza, sem ênfase

   Modificador de layout:
     .alert-compact — uma linha (sem descrição, padding menor)
   ============================================================ */

.alert {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border: 1px solid transparent;
    border-radius: 0.75rem;
}

.alert-icon {
    font-size: 1.25rem;
    line-height: 1;
    flex-shrink: 0;
    margin-top: 0.125rem;
}

.alert-body {
    flex: 1;
    min-width: 0;
}

.alert-title {
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1.3;
    margin: 0;
}

.alert-desc {
    font-size: 0.75rem;
    line-height: 1.4;
    margin: 0.125rem 0 0;
    opacity: 0.85;
}

/* -------- Compact (uma linha) -------- */
.alert-compact {
    align-items: center;
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    gap: 0.5rem;
}
.alert-compact .alert-icon {
    font-size: 1rem;
    margin-top: 0;
}
.alert-compact .alert-title {
    font-size: 0.75rem;
    font-weight: 600;
}

/* -------- Variante: success -------- */
.alert-success {
    background-color: rgba(34, 197, 94, 0.08);   /* green-500/8 */
    border-color: rgba(34, 197, 94, 0.25);
    color: #15803D;                              /* green-700 */
}
html.dark .alert-success {
    background-color: rgba(34, 197, 94, 0.10);
    border-color: rgba(34, 197, 94, 0.30);
    color: #4ADE80;                              /* green-400 */
}

/* -------- Variante: danger -------- */
.alert-danger {
    background-color: rgba(239, 68, 68, 0.08);   /* red-500/8 */
    border-color: rgba(239, 68, 68, 0.25);
    color: #B91C1C;                              /* red-700 */
}
html.dark .alert-danger {
    background-color: rgba(239, 68, 68, 0.12);
    border-color: rgba(239, 68, 68, 0.30);
    color: #F87171;                              /* red-400 */
}

/* -------- Variante: warning -------- */
.alert-warning {
    background-color: rgba(234, 179, 8, 0.10);   /* yellow-500/10 */
    border-color: rgba(234, 179, 8, 0.30);
    color: #A16207;                              /* yellow-700 */
}
html.dark .alert-warning {
    background-color: rgba(234, 179, 8, 0.12);
    border-color: rgba(234, 179, 8, 0.35);
    color: #FCD34D;                              /* amber-300 */
}

/* -------- Variante: info -------- */
.alert-info {
    background-color: rgba(59, 130, 246, 0.08);  /* blue-500/8 */
    border-color: rgba(59, 130, 246, 0.25);
    color: #1D4ED8;                              /* blue-700 */
}
html.dark .alert-info {
    background-color: rgba(59, 130, 246, 0.12);
    border-color: rgba(59, 130, 246, 0.30);
    color: #60A5FA;                              /* blue-400 */
}

/* -------- Variante: neutral -------- */
.alert-neutral {
    background-color: var(--bg-page);
    border-color: var(--border-ui);
    color: var(--text-main);
}


/* ===== avatar.css ===== */
/* ============================================================
   DS · Avatar
   Escala: xs 24 · sm 32 · md 40 · lg 48 · xl 64
   Fallback: iniciais sobre bg tint. Com <img>, usar iniciais em onerror.

   Uso:
     <div class="avatar avatar-md">AF</div>
     <div class="avatar avatar-lg"><img src="..." alt="Ana Fernandes"></div>
   ============================================================ */

.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background-color: var(--primary-blue-tint);
    color: var(--primary-blue);
    font-weight: 700;
    line-height: 1;
    flex-shrink: 0;
    overflow: hidden;
    user-select: none;
}

.avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* -------- Escala -------- */
.avatar-xs { width: 24px; height: 24px; font-size: 0.625rem; }   /* 10px */
.avatar-sm { width: 32px; height: 32px; font-size: 0.6875rem; }  /* 11px */
.avatar-md { width: 40px; height: 40px; font-size: 0.875rem; }   /* 14px — default */
.avatar-lg { width: 48px; height: 48px; font-size: 1rem; }
.avatar-xl { width: 64px; height: 64px; font-size: 1.25rem; }


/* ===== badge.css ===== */
/* ============================================================
   DS · Badge & Chip
   3 variantes: pill (solid), dot (refinado), chip (quadrado).
   5 cores semânticas: success · warning · danger · info · neutral.

   Uso:
     <span class="badge badge-success">Ativo</span>
     <span class="badge-dot"><span class="badge-dot-circle badge-dot-success"></span> Ativo</span>
     <span class="chip"><i class="ph-bold ph-files"></i> 12 arquivos</span>
   ============================================================ */

/* -------- Pill (solid) — destaque em tabela -------- */
.badge {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.625rem;     /* py-1 px-2.5 */
    border-radius: 9999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
}

.badge-success { background-color: #DCFCE7; color: #15803D; }  /* green-100 / 700 */
.badge-warning { background-color: #FEF9C3; color: #A16207; }  /* yellow-100 / 700 */
.badge-danger  { background-color: #FEE2E2; color: #B91C1C; }  /* red-100 / 700 */
.badge-info    { background-color: #DBEAFE; color: #1D4ED8; }  /* blue-100 / 700 */
.badge-neutral { background-color: #F3F4F6; color: #4B5563; }  /* gray-100 / 600 */

/* -------- Dot (refinado) — tabelas densas --------
   Uso:
     <span class="badge-dot">
       <span class="badge-dot-circle badge-dot-success"></span> Ativo
     </span>
*/
.badge-dot {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-main);
    white-space: nowrap;
}
.badge-dot-circle {
    width: 6px;
    height: 6px;
    border-radius: 9999px;
    flex-shrink: 0;
}
.badge-dot-success { background-color: #22C55E; }  /* green-500 */
.badge-dot-warning { background-color: #EAB308; }  /* yellow-500 */
.badge-dot-danger  { background-color: #EF4444; }  /* red-500 */
.badge-dot-info    { background-color: #3B82F6; }  /* blue-500 */
.badge-dot-neutral { background-color: #9CA3AF; }  /* gray-400 */

/* -------- Chip (quadrado) — tag/contador dentro de card --------
   Uso:
     <span class="chip">
       <i class="ph-bold ph-files" aria-hidden="true"></i> 12 arquivos
     </span>
*/
.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;      /* py-0.5 px-2 */
    background-color: var(--bg-page);
    border: 1px solid var(--border-ui);
    border-radius: 0.375rem;       /* rounded-md */
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-muted);
    line-height: 1.4;
}

/* Chip em tint (destaque) */
.chip-brand {
    background-color: var(--primary-blue-tint);
    border-color: transparent;
    color: var(--primary-blue);
    font-weight: 600;
}

/* Chip de alerta — vínculo salvo cujo item não existe mais na origem
   (sync atrasado, pasta removida). Mesmas cores de .badge-warning. */
.chip-warn {
    background-color: #FEF9C3;     /* yellow-100 */
    border-color: #FDE68A;         /* amber-200 */
    color: #A16207;                /* yellow-700 */
}
html.dark .chip-warn {
    background-color: rgba(161, 98, 7, 0.18);
    border-color: rgba(253, 230, 138, 0.30);
    color: #FCD34D;                /* amber-300 */
}


/* ===== breadcrumb.css ===== */
/* ============================================================
   DS · Breadcrumb (v1.3)
   Navegação hierárquica para fluxos profundos (BI > Dashboard >
   Relatório > Conta).

   Uso:
     <nav class="breadcrumb" aria-label="Breadcrumb">
       <ol>
         <li><a href="/">BI Contábil</a></li>
         <li><a href="/bi/dashboards/">Dashboards</a></li>
         <li aria-current="page">Receita 2026</li>
       </ol>
     </nav>
   ============================================================ */

.breadcrumb {
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.4;
}

.breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.breadcrumb li {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

.breadcrumb li + li::before {
    content: "/";
    color: var(--border-strong);
    margin: 0 0.25rem;
    font-weight: 400;
}

.breadcrumb a {
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--motion-instant);
    border-radius: 0.25rem;
}
.breadcrumb a:hover {
    color: var(--primary-blue);
}
.breadcrumb a:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--primary-blue-tint);
}

.breadcrumb [aria-current="page"] {
    color: var(--text-main);
    font-weight: 600;
}


/* ===== btn.css ===== */
/* ============================================================
   DS · Button — escala unificada (v1.2)
   2 tamanhos (sm 32px · md 38px default) × 5 variantes + link.

   Uso:
     <button class="btn btn-primary">Salvar</button>
     <button class="btn btn-sm btn-primary">Editar</button>
     <button class="btn btn-secondary">Cancelar</button>
     <button class="icon-btn" aria-label="Editar"><i class="ph-bold ph-pencil-simple" aria-hidden="true"></i></button>
     <a href="#" class="btn-link">Recuperar senha</a>

   Notas:
   - Todos os btn suportam <button>, <a>, <input type="submit">.
   - focus-visible já embutido, não precisa adicionar .focus-ring.
   - Hover usa --primary-blue-hover, NUNCA opacity-90.
   ============================================================ */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;

    height: 38px;                  /* md — default */
    padding: 0 1rem;
    border: 1px solid transparent;
    border-radius: 0.5rem;

    font-family: inherit;
    font-size: 0.875rem;           /* text-sm */
    font-weight: 500;              /* medium */
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    user-select: none;

    transition: background-color var(--motion-instant),
                border-color     var(--motion-instant),
                color            var(--motion-instant),
                box-shadow       var(--motion-instant);
}

.btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--primary-blue-tint);
}

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.6;
    cursor: not-allowed;
    pointer-events: none;
}

/* -------- Tamanho sm (tabela, filtro inline) -------- */
.btn-sm {
    height: 32px;
    padding: 0 0.75rem;
    font-size: 0.75rem;            /* text-xs */
    font-weight: 600;              /* semibold */
}

/* -------- Variante: Primary -------- */
.btn-primary {
    background-color: var(--primary-blue);
    color: #FFFFFF;
}
.btn-primary:hover:not(:disabled) {
    background-color: var(--primary-blue-hover);
}

/* -------- Variante: Secondary -------- */
.btn-secondary {
    background-color: var(--surface);
    border-color: var(--border-ui);
    color: var(--text-main);
}
.btn-secondary:hover:not(:disabled) {
    border-color: var(--primary-blue);
    color: var(--primary-blue);
}

/* -------- Variante: Ghost (Cancelar, dismissive) -------- */
.btn-ghost {
    background-color: transparent;
    border-color: var(--border-ui);
    color: var(--text-muted);
    font-weight: 600;
}
.btn-ghost:hover:not(:disabled) {
    background-color: var(--bg-page);
}

/* -------- Variante: Danger (destrutivo) --------
   Nunca em .btn-sm (ver §8 do design-system: Danger-sm não existe).
*/
.btn-danger {
    background-color: #DC2626;     /* red-600 */
    color: #FFFFFF;
    font-weight: 600;
}
.btn-danger:hover:not(:disabled) {
    background-color: #B91C1C;     /* red-700 */
}

/* -------- Variante: Success --------
   Ações positivas/concluir (upload finalizado, aprovar).
   Uso restrito — na maioria dos casos, use .btn-primary (azul).
*/
.btn-success {
    background-color: #16A34A;     /* green-600 */
    color: #FFFFFF;
    font-weight: 600;
}
.btn-success:hover:not(:disabled) {
    background-color: #15803D;     /* green-700 */
}

/* -------- Icon-only -------- */
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;                   /* md: 40 */
    height: 40px;
    border: 1px solid var(--border-ui);
    border-radius: 0.5rem;
    background-color: var(--bg-page);
    color: var(--text-muted);
    cursor: pointer;
    transition: color        var(--motion-instant),
                border-color var(--motion-instant),
                background   var(--motion-instant),
                box-shadow   var(--motion-instant);
}
.icon-btn:hover:not(:disabled) {
    color: var(--primary-blue);
    border-color: var(--primary-blue);
}
.icon-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--primary-blue-tint);
}
.icon-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}
.icon-btn.icon-btn-sm {
    width: 32px;
    height: 32px;
}

/* -------- Link (inline em texto corrido) --------
   Sem padding, segue line-height do parágrafo ancestral.
*/
.btn-link {
    color: var(--primary-blue);
    font-weight: 600;
    text-decoration: none;
    border-radius: 0.25rem;
    transition: text-decoration-color var(--motion-instant);
}
.btn-link:hover {
    text-decoration: underline;
    text-underline-offset: 2px;
}
.btn-link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--primary-blue-tint);
}

/* -------- Estado loading --------
   Aplicar junto com .btn-primary (ou outra variante):
     <button class="btn btn-primary btn-loading" disabled>
       <i class="ph ph-spinner" aria-hidden="true"></i> Processando…
     </button>
   O .ph-spinner já gira pelo Phosphor.
*/
.btn-loading {
    opacity: 0.6;
    cursor: not-allowed;
    pointer-events: none;
}
.btn-loading .ph-spinner {
    animation: ds-spin 0.8s linear infinite;
}
@keyframes ds-spin {
    to { transform: rotate(360deg); }
}


/* ===== card.css ===== */
/* ============================================================
   DS · Card
   Wrapper canônico para blocos de conteúdo.

   Uso:
     <div class="card">
       ... conteúdo direto (p-5) ...
     </div>

     <div class="card card-split">
       <div class="card-header"><p class="card-title">Título</p></div>
       <div class="card-body">...</div>
     </div>
   ============================================================ */

.card {
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;        /* rounded-xl */
    padding: 1.25rem;              /* p-5 */
    box-shadow: var(--shadow-elev-1);
}

/* -------- Split: header + body (sem padding no wrapper) -------- */
.card-split {
    padding: 0;
    overflow: hidden;              /* raio respeita children full-width */
}

.card-header {
    padding: 1rem 1.25rem;         /* py-4 px-5 */
    border-bottom: 1px solid var(--border-ui);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.card-body {
    padding: 1.25rem;
}

.card-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-main);
    margin: 0;
}

/* -------- Sem padding (quando o card contém tabela full-width) -------- */
.card-flush {
    padding: 0;
    overflow: hidden;
}


/* ===== combobox.css ===== */
/* ============================================================
   DS · Combobox
   Select digitavel: input visivel filtra por digitacao, dropdown
   ancorado ao body (n�o cortado por overflow:hidden de cards).
   Sucessor do `_filter_picker.html` antigo — agora componente DS.

   Markup canonico:
     <div class="combobox" data-filter-picker>
       <input type="text" class="input combobox-search" data-picker-search
              placeholder="..." autocomplete="off">
       <input type="hidden" name="..." value="..." data-picker-input>
       <div class="combobox-pop hidden" data-picker-pop>
         <div class="combobox-options" data-picker-list>
           <button type="button" class="combobox-option"
                   data-value="X" data-search-text="..."
                   data-picker-display="...">
             <span class="combobox-option-label">...</span>
             <span class="combobox-option-desc">...</span>
           </button>
         </div>
         <p class="combobox-empty hidden" data-picker-empty>Nenhum resultado.</p>
       </div>
     </div>

   Variantes:
     .combobox-sm — input usa .input-sm (32px) ao inves de 38px.
   ============================================================ */

.combobox {
    position: relative;
    width: 100%;
}

.combobox-search {
    width: 100%;
    /* Herda tudo de .input — o JS posiciona o dropdown abaixo. */
}

/* --------- Dropdown ancorado ao input (absolute, dentro do root) ---------
   Padrao: absolute logo abaixo do input. Funciona dentro de modais e cards
   normais. Para casos em que o card ancestral tem overflow:hidden cortando
   o dropdown, adicione `data-combobox-popover-body` no .combobox root — o JS
   move o pop para o <body> com z-index alto.                              */
.combobox-pop {
    position: absolute;
    top: calc(100% + 0.25rem);
    left: 0;
    right: 0;
    z-index: 30;
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;             /* rounded-xl */
    box-shadow: var(--shadow-elev-3);
    max-height: 18rem;
    overflow-y: auto;
    min-width: 12rem;
}

/* Quando o JS move para o <body> (data-combobox-popover-body), o pop vira
   position:fixed para usar o viewport como referencia. O JS seta top/left/width
   inline via getBoundingClientRect.                                        */
.combobox-pop[data-popover-body="1"] {
    position: fixed;
    z-index: 9999;
    top: auto;
    left: auto;
    right: auto;
}

.combobox-pop.hidden {
    display: none;
}

.combobox-options {
    display: flex !important;
    flex-direction: column !important;
    width: 100%;
}

/* --------- Items ---------
   `!important` em display/width porque o markup usa <button>, e algumas
   utility classes ou resets de browser podem reintroduzir display:inline-block;
   estes itens DEVEM ficar empilhados na vertical, ocupando 100% da largura
   do popover (preenchendo o input). */
.combobox-option {
    display: block !important;
    width: 100% !important;
    text-align: left;
    padding: 0.5rem 0.75rem;
    border: 0;
    border-bottom: 1px solid var(--border-ui);
    background-color: transparent;
    color: var(--text-main);
    cursor: pointer;
    transition: background-color var(--motion-fast, 120ms) ease;
    font-family: inherit;
    box-sizing: border-box;
}

.combobox-option:last-child {
    border-bottom: 0;
}

.combobox-option:hover,
.combobox-option:focus-visible {
    background-color: var(--bg-page);
    outline: none;
}

.combobox-option.hidden {
    display: none !important;
}

.combobox-option.is-active {
    background-color: var(--bg-page);
}

.combobox-option-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-main);
    line-height: 1.25;
}

.combobox-option-desc {
    display: block;
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.2;
    margin-top: 0.125rem;
}

/* Variante "neutra" — item de placeholder (Todos / Nenhum) */
.combobox-option-muted .combobox-option-label {
    font-weight: 400;
    color: var(--text-muted);
}

/* --------- Empty state --------- */
.combobox-empty {
    padding: 1rem 0.75rem;
    text-align: center;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.combobox-empty.hidden {
    display: none;
}


/* ===== container.css ===== */
/* ============================================================
   DS · Container (v1.3)
   Largura máxima para texto corrido e páginas densas.

   Uso:
     <div class="container-prose">  <!-- 65ch — texto corrido -->
     <div class="container-page">   <!-- max-w-7xl — conteúdo geral -->
     <div class="container-wide">   <!-- 100% — dashboards, grids 12col -->
   ============================================================ */

.container-prose {
    max-width: 65ch;
    margin-left: auto;
    margin-right: auto;
}
.container-page {
    max-width: 80rem;          /* 1280px */
    margin-left: auto;
    margin-right: auto;
}
.container-wide {
    max-width: 100%;
}


/* ===== curso-prose.css ===== */
/* ============================================================
   DS · Curso prose — material didático das aulas
   Folha tipográfica do HTML rico de `cursos.Content.text_content`,
   sanitizado por bleach em cursos/utils_html.py.

   Uso:
     <div class="curso-prose">{{ content.text_content|curso_html }}</div>

   Também é carregada DENTRO do editor (TinyMCE usa ds.bundle.css como
   content_css e aplica body_class="curso-prose"), então o que se edita
   no /cursos/gerenciar/ é o que o aluno vê.

   Vocabulário de classes (o único que a sanitização deixa passar):
     .curso-callout + --info/--success/--warning/--danger/--neutral
     .curso-cols / .curso-col
     .curso-table-scroll
     details/summary (FAQ) não precisam de classe — estilo pelo elemento.

   Conformidade com .claude/design-office.html v1.7:
   - R18 · só a escala Tailwind (0.75 / 0.875 / 1 / 1.125 / 1.25 / 1.5rem).
     O corpo usa 1rem (text-base), não os 0.875rem do chrome da aplicação:
     é texto longo de leitura contínua, e 1rem está na escala.
   - R19 · as 5 categorias semânticas (green/yellow/red/blue/gray), com os
     mesmos valores de `ds/alert.css` — callout e alert são a mesma família.
   - R17 · breakpoint único `lg` (64rem = 1024px), mobile-first.
   - §4 · raio: 0.75rem (xl) em bloco, 0.375rem (md) em mini-elemento.
   - §5 · motion pelos tokens; `prefers-reduced-motion` já é global no _base.
   ============================================================ */

.curso-prose {
    color: var(--text-main);
    font-size: 1rem;
    line-height: 1.75;
    overflow-wrap: break-word;
}

.curso-prose > *:first-child { margin-top: 0; }
.curso-prose > *:last-child { margin-bottom: 0; }

/* ---------- Títulos ---------- */

.curso-prose h1,
.curso-prose h2,
.curso-prose h3,
.curso-prose h4,
.curso-prose h5,
.curso-prose h6 {
    color: var(--title-color);
    font-weight: 700;
    line-height: 1.25;
    margin: 2em 0 0.75em;
    scroll-margin-top: 1rem;
}

/* O h1 da PÁGINA é o `page-title` (text-xl). Estes são títulos de dentro
   do material, então descem um degrau a partir de 1.5rem (text-2xl). */
.curso-prose h1 {
    font-size: 1.5rem;
    letter-spacing: -0.02em;
    margin-top: 0;
    padding-bottom: 0.4em;
    border-bottom: 2px solid var(--primary-blue-soft);
}

.curso-prose h2 {
    font-size: 1.25rem;
    padding-bottom: 0.3em;
    border-bottom: 1px solid var(--border-ui);
}

.curso-prose h3 { font-size: 1.125rem; }
.curso-prose h4 { font-size: 1rem; }

/* Overline do DS (§3): text-xs semibold uppercase tracking-wider muted. */
.curso-prose h5,
.curso-prose h6 {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* H2 ganha uma marca lateral discreta — dá ritmo à leitura longa. */
.curso-prose h2::before {
    content: "";
    display: inline-block;
    width: 4px;
    height: 0.85em;
    margin-right: 0.5rem;
    border-radius: 9999px;
    background: var(--primary-blue);
    vertical-align: -0.05em;
}

/* ---------- Blocos de texto ---------- */

.curso-prose p {
    margin: 0 0 1.15em;
}

.curso-prose a {
    color: var(--primary-blue);
    text-decoration: underline;
    text-underline-offset: 2px;
    font-weight: 500;
}

.curso-prose a:hover {
    color: var(--primary-blue-hover);
    text-decoration: none;
}

.curso-prose strong,
.curso-prose b { font-weight: 700; }

.curso-prose mark {
    background: rgba(234, 179, 8, 0.25);
    color: inherit;
    padding: 0.1em 0.25em;
    border-radius: 0.375rem;
}

.curso-prose hr {
    height: 1px;
    border: 0;
    background: var(--border-ui);
    margin: 2.5em 0;
}

/* ---------- Listas ---------- */

.curso-prose ul,
.curso-prose ol {
    margin: 0 0 1.15em;
    padding-left: 1.5em;
}

.curso-prose ul { list-style: disc; }
.curso-prose ol { list-style: decimal; }
.curso-prose ul ul { list-style: circle; }
.curso-prose ol ol { list-style: lower-alpha; }

.curso-prose li { margin: 0.35em 0; }
.curso-prose li > ul,
.curso-prose li > ol { margin: 0.35em 0 0; }

.curso-prose li::marker { color: var(--primary-blue); }

/* ---------- Citação ---------- */

.curso-prose blockquote {
    margin: 1.5em 0;
    padding: 0.25em 0 0.25em 1.25em;
    border-left: 4px solid var(--primary-blue-soft);
    color: var(--text-muted);
    font-style: italic;
}

.curso-prose blockquote > *:last-child { margin-bottom: 0; }

/* ---------- Código ---------- */

.curso-prose code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.875em;
    background: var(--primary-blue-tint);
    color: var(--text-main);
    padding: 0.15em 0.4em;
    border-radius: 0.375rem;
}

.curso-prose pre {
    margin: 1.5em 0;
    padding: 1rem;
    background: var(--bg-page);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    overflow-x: auto;
    line-height: 1.6;
}

.curso-prose pre code {
    background: none;
    padding: 0;
    font-size: 0.875rem;
}

/* ---------- Mídia ---------- */

.curso-prose img {
    max-width: 100%;
    height: auto;
    border-radius: 0.75rem;
}

.curso-prose figure {
    margin: 1.5em 0;
}

.curso-prose figcaption {
    margin-top: 0.6em;
    font-size: 0.75rem;
    line-height: 1.625;
    color: var(--text-muted);
    text-align: center;
}

/* Embeds (YouTube/Vimeo/Drive) — proporção 16:9 sem depender de wrapper. */
.curso-prose iframe {
    display: block;
    width: 100%;
    max-width: 100%;
    aspect-ratio: 16 / 9;
    height: auto;
    margin: 1.5em 0;
    border: 0;
    border-radius: 0.75rem;
    background: var(--bg-page);
}

/* ---------- Tabelas ---------- */

.curso-prose table {
    width: 100%;
    margin: 1.5em 0;
    border-collapse: separate;
    border-spacing: 0;
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    overflow: hidden;
    font-size: 0.875rem;
}

.curso-prose th,
.curso-prose td {
    padding: 0.75rem 1rem;
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--border-ui);
}

.curso-prose thead th {
    background: var(--bg-page);
    color: var(--title-color);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.curso-prose tbody tr:last-child th,
.curso-prose tbody tr:last-child td { border-bottom: 0; }

.curso-prose tbody tr:nth-child(even) { background: var(--primary-blue-tint); }

.curso-prose caption {
    caption-side: bottom;
    padding-top: 0.6em;
    font-size: 0.75rem;
    line-height: 1.625;
    color: var(--text-muted);
}

/* Tabela larga rola dentro do próprio bloco, nunca empurra a página. */
.curso-prose .curso-table-scroll {
    overflow-x: auto;
    margin: 1.5em 0;
}

.curso-prose .curso-table-scroll > table { margin: 0; }

/* ---------- Callouts (caixas de destaque) ----------
   Mesma paleta de `ds/alert.css` (R19), com uma borda esquerda mais
   grossa: em texto longo a barra lateral marca o bloco melhor que o
   ícone sozinho. */

.curso-prose .curso-callout {
    position: relative;
    margin: 1.75em 0;
    padding: 1rem 1rem 1rem 3rem;
    border: 1px solid transparent;
    border-left-width: 4px;
    border-radius: 0.75rem;
    line-height: 1.625;
}

.curso-prose .curso-callout > *:first-child { margin-top: 0; }
.curso-prose .curso-callout > *:last-child { margin-bottom: 0; }

/* O ícone é uma máscara SVG pintada com currentColor — acompanha a cor
   da variante e não depende do webfont do Phosphor estar carregado
   (dentro da iframe do editor ele não está). */
.curso-prose .curso-callout::before {
    content: "";
    position: absolute;
    left: 1rem;
    top: 1.1rem;
    width: 1.25rem;
    height: 1.25rem;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: center;
    mask-position: center;
}

/* -------- Variante: info (azul) — "Informação" -------- */
.curso-prose .curso-callout--info {
    background-color: rgba(59, 130, 246, 0.08);
    border-color: rgba(59, 130, 246, 0.25);
    color: #1D4ED8;
}

.curso-prose .curso-callout--info::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z'/%3E%3C/svg%3E");
}

/* -------- Variante: success (verde) — "Dica" --------
   Ícone de lâmpada em vez do check do alert: aqui a cor comunica
   "positivo", mas a intenção autoral é sugestão, não confirmação. */
.curso-prose .curso-callout--success {
    background-color: rgba(34, 197, 94, 0.08);
    border-color: rgba(34, 197, 94, 0.25);
    color: #15803D;
}

.curso-prose .curso-callout--success::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Z'/%3E%3C/svg%3E");
}

/* -------- Variante: warning (amarelo) — "Atenção" -------- */
.curso-prose .curso-callout--warning {
    background-color: rgba(234, 179, 8, 0.10);
    border-color: rgba(234, 179, 8, 0.30);
    color: #A16207;
}

.curso-prose .curso-callout--warning::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,144V104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,52a12,12,0,1,1,12-12A12,12,0,0,1,128,196Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,144V104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,52a12,12,0,1,1,12-12A12,12,0,0,1,128,196Z'/%3E%3C/svg%3E");
}

/* -------- Variante: danger (vermelho) — "Importante" -------- */
.curso-prose .curso-callout--danger {
    background-color: rgba(239, 68, 68, 0.08);
    border-color: rgba(239, 68, 68, 0.25);
    color: #B91C1C;
}

.curso-prose .curso-callout--danger::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-8,56a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm8,120a12,12,0,1,1,12-12A12,12,0,0,1,128,200Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-8,56a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm8,120a12,12,0,1,1,12-12A12,12,0,0,1,128,200Z'/%3E%3C/svg%3E");
}

/* -------- Variante: neutral (cinza) — "Observação" -------- */
.curso-prose .curso-callout--neutral {
    background-color: var(--bg-page);
    border-color: var(--border-ui);
    color: var(--text-main);
}

.curso-prose .curso-callout--neutral::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224,120v8a96,96,0,0,1-96,96H72a48,48,0,0,1-48-48V80A48,48,0,0,1,72,32h56A96,96,0,0,1,224,120ZM88,112a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Zm0,48a8,8,0,0,0,0,16h48a8,8,0,0,0,0-16Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224,120v8a96,96,0,0,1-96,96H72a48,48,0,0,1-48-48V80A48,48,0,0,1,72,32h56A96,96,0,0,1,224,120ZM88,112a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Zm0,48a8,8,0,0,0,0,16h48a8,8,0,0,0,0-16Z'/%3E%3C/svg%3E");
}

/* O texto do callout herda a cor da variante; títulos e links dentro
   também, para a caixa ler como um bloco só. */
.curso-prose .curso-callout h1,
.curso-prose .curso-callout h2,
.curso-prose .curso-callout h3,
.curso-prose .curso-callout h4,
.curso-prose .curso-callout h5,
.curso-prose .curso-callout h6 {
    color: inherit;
    border: 0;
    padding: 0;
    margin: 0 0 0.4em;
    font-size: 1rem;
    text-transform: none;
    letter-spacing: normal;
}

.curso-prose .curso-callout h2::before { display: none; }
.curso-prose .curso-callout a { color: inherit; }
.curso-prose .curso-callout li::marker { color: inherit; }

/* ---------- FAQ (details/summary) — funciona sem JS ---------- */

.curso-prose details {
    margin: 0.6em 0;
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    background: var(--surface);
    overflow: hidden;
    transition: border-color var(--motion-smooth);
}

.curso-prose details:hover { border-color: var(--border-strong); }
.curso-prose details[open] { border-color: var(--primary-blue-soft); }

.curso-prose summary {
    position: relative;
    padding: 0.75rem 3rem 0.75rem 1rem;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--title-color);
    list-style: none;
    user-select: none;
    transition: background-color var(--motion-instant);
}

/* Remove o triângulo nativo (WebKit e o resto). */
.curso-prose summary::-webkit-details-marker { display: none; }
.curso-prose summary::marker { content: ""; }

.curso-prose summary:hover { background: var(--primary-blue-tint); }

/* Anel de foco canônico do DS (_base.css .focus-ring). */
.curso-prose summary:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 4px var(--primary-blue-tint);
}

/* Seta própria, que gira ao abrir. */
.curso-prose summary::after {
    content: "";
    position: absolute;
    right: 1rem;
    top: 50%;
    width: 0.5rem;
    height: 0.5rem;
    margin-top: -0.35rem;
    border-right: 2px solid var(--primary-blue);
    border-bottom: 2px solid var(--primary-blue);
    transform: rotate(45deg);
    transform-origin: center;
    transition: transform var(--motion-smooth);
}

.curso-prose details[open] > summary::after {
    transform: rotate(-135deg);
    margin-top: -0.1rem;
}

.curso-prose details > *:not(summary) {
    padding-left: 1rem;
    padding-right: 1rem;
    font-size: 0.875rem;
}

.curso-prose details > summary + * { margin-top: 0.75rem; }
.curso-prose details > *:last-child { margin-bottom: 0.75rem; }

/* Um bloco de FAQ seguido de outro fica colado como uma lista. */
.curso-prose details + details { margin-top: 0.5em; }

/* ---------- Colunas ---------- */
/* Mobile é a base (R17): uma coluna. O par só aparece no `lg`. */

.curso-prose .curso-cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    margin: 1.75em 0;
}

.curso-prose .curso-col > *:first-child { margin-top: 0; }
.curso-prose .curso-col > *:last-child { margin-bottom: 0; }

@media (min-width: 64rem) {
    .curso-prose .curso-cols {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 1.5rem;
    }
}

/* ---------- Tema escuro ---------- */
/* Mesmos valores de ds/alert.css para as 4 variantes coloridas. */

html.dark .curso-prose .curso-callout--info {
    background-color: rgba(59, 130, 246, 0.12);
    border-color: rgba(59, 130, 246, 0.30);
    color: #60A5FA;
}

html.dark .curso-prose .curso-callout--success {
    background-color: rgba(34, 197, 94, 0.10);
    border-color: rgba(34, 197, 94, 0.30);
    color: #4ADE80;
}

html.dark .curso-prose .curso-callout--warning {
    background-color: rgba(234, 179, 8, 0.12);
    border-color: rgba(234, 179, 8, 0.35);
    color: #FCD34D;
}

html.dark .curso-prose .curso-callout--danger {
    background-color: rgba(239, 68, 68, 0.12);
    border-color: rgba(239, 68, 68, 0.30);
    color: #F87171;
}

html.dark .curso-prose mark {
    background: rgba(234, 179, 8, 0.30);
    color: #FDE68A;
}

/* ============================================================
   Chrome do editor (TinyMCE) — alinhamento com o DS
   Só o mínimo para o editor não parecer um corpo estranho dentro do
   modal do office: raio de input (§4 · rounded-lg), a borda e a fonte
   do sistema. O resto do skin oxide fica como está — brigar com ele
   quebra a cada upgrade da lib.
   ============================================================ */

.tox.tox-tinymce {
    border-radius: 0.5rem;
    border-color: var(--border-ui);
    font-family: inherit;
}

.tox .tox-editor-header,
.tox .tox-toolbar__primary {
    background-color: var(--bg-page) !important;
}

.tox .tox-statusbar {
    border-top-color: var(--border-ui);
}

/* ---------- Impressão ---------- */

@media print {
    .curso-prose details { border-color: #999; }
    .curso-prose details > *:not(summary) { display: block; }
    .curso-prose summary::after { display: none; }
    .curso-prose .curso-cols { gap: 1rem; }
}


/* ===== date-br.css ===== */
/* ============================================================
   DS · Date BR — campo de data sempre dd/mm/aaaa

   PROBLEMA
   `<input type="date">` nativo desenha a data no locale do
   NAVEGADOR/SO do usuário: em Chrome en-US vira mm/dd/yyyy.
   O projeto exige DIA/MES/ANO para todo mundo, sempre.

   SOLUÇÃO
   `date_br.js` faz progressive enhancement: troca o input nativo
   por um campo de texto mascarado + calendário próprio, e mantém
   um <input type="hidden"> com o MESMO name/id carregando o valor
   em ISO. Assim nenhuma view ou JS existente precisa mudar.

   MARKUP GERADO (não escrever à mão)
     <span class="datebr" data-datebr>
       <input type="text" class="input datebr-text" data-datebr-text>
       <button class="datebr-toggle" data-datebr-toggle>…</button>
       <input type="hidden" name="…" data-datebr-value>   ← ISO
       <div class="datebr-pop hidden" data-datebr-pop>…</div>
     </span>

   Ancoragem do popover segue o mesmo padrão do combobox: absolute
   dentro do root; se um ancestral tiver overflow:hidden, o JS move
   para o <body> e marca data-popover-body="1" (vira fixed).
   ============================================================ */

.datebr {
    position: relative;
    display: block;
    width: 100%;
}

/* O texto herda .input (altura, borda, foco). Só reserva espaço
   à direita para o botão do calendário. */
.datebr-text {
    padding-right: 2.25rem;
}

.datebr-sm .datebr-text {
    padding-right: 2rem;
}

/* Estado inválido enquanto o usuário digita uma data impossível
   (32/13/2026). Não usa :invalid porque o campo é type=text. */
.datebr-text[data-datebr-invalid="1"] {
    border-color: #EF4444;                       /* red-500 — mesmo erro do form.css */
}

.datebr-text[data-datebr-invalid="1"]:focus {
    box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.12);
}

html.dark .datebr-text[data-datebr-invalid="1"] {
    border-color: #F87171;                       /* red-400 */
}

/* -------- Botão do calendário -------- */
.datebr-toggle {
    position: absolute;
    top: 1px;
    right: 1px;
    bottom: 1px;
    width: 2.125rem;

    display: flex;
    align-items: center;
    justify-content: center;

    border: 0;
    background: transparent;
    border-radius: 0 0.5rem 0.5rem 0;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 1rem;

    transition: color var(--motion-instant), background-color var(--motion-instant);
}

.datebr-toggle:hover {
    color: var(--text-main);
    background-color: var(--primary-blue-tint);
}

.datebr-toggle:focus-visible {
    outline: none;
    color: var(--primary-blue);
    box-shadow: 0 0 0 2px var(--primary-blue);
}

.datebr-toggle:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.datebr-toggle:disabled:hover {
    color: var(--text-muted);
    background-color: transparent;
}

/* -------- Popover (mesmo padrão do .combobox-pop) -------- */
.datebr-pop {
    position: absolute;
    top: calc(100% + 0.25rem);
    left: 0;
    z-index: 30;
    width: 17.5rem;

    padding: 0.625rem;
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-elev-3);
}

.datebr-pop[data-popover-body="1"] {
    position: fixed;
    z-index: 9999;
}

/* Abre para cima quando não há espaço abaixo (JS decide). */
.datebr-pop[data-datebr-up="1"] {
    top: auto;
    bottom: calc(100% + 0.25rem);
}

.datebr-pop.hidden {
    display: none;
}

/* -------- Cabeçalho: ‹ Agosto 2026 › -------- */
.datebr-head {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-bottom: 0.5rem;
}

.datebr-nav {
    flex: 0 0 auto;
    width: 1.75rem;
    height: 1.75rem;
    display: flex;
    align-items: center;
    justify-content: center;

    border: 0;
    border-radius: 0.375rem;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;

    transition: background-color var(--motion-instant), color var(--motion-instant);
}

.datebr-nav:hover {
    background-color: var(--bg-page);
    color: var(--text-main);
}

.datebr-nav:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--primary-blue);
}

/* Título clicável — abre a grade de meses e depois a de anos.
   Sem isso, escolher uma data de nascimento exigiria dezenas de cliques. */
.datebr-title {
    flex: 1 1 auto;
    height: 1.75rem;
    padding: 0 0.5rem;

    border: 0;
    border-radius: 0.375rem;
    background: transparent;
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;

    transition: background-color var(--motion-instant);
}

.datebr-title:hover {
    background-color: var(--bg-page);
}

.datebr-title:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--primary-blue);
}

/* -------- Cabeçalho dos dias da semana -------- */
.datebr-dow {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 0.125rem;
    margin-bottom: 0.125rem;
}

.datebr-dow span {
    text-align: center;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--text-muted);
    padding: 0.25rem 0;
}

/* -------- Grades -------- */
.datebr-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 0.125rem;
}

/* Meses e anos usam 3 ou 4 colunas em vez de 7. */
.datebr-grid[data-datebr-view="months"] {
    grid-template-columns: repeat(3, 1fr);
    gap: 0.25rem;
}

.datebr-grid[data-datebr-view="years"] {
    grid-template-columns: repeat(4, 1fr);
    gap: 0.25rem;
}

.datebr-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 2rem;

    border: 0;
    border-radius: 0.375rem;
    background: transparent;
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.8125rem;
    cursor: pointer;

    transition: background-color var(--motion-instant), color var(--motion-instant);
}

.datebr-grid[data-datebr-view="months"] .datebr-cell,
.datebr-grid[data-datebr-view="years"] .datebr-cell {
    height: 2.25rem;
}

.datebr-cell:hover:not(:disabled) {
    background-color: var(--primary-blue-tint);
}

.datebr-cell:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--primary-blue);
}

/* Dia de outro mês — visível mas discreto (contexto da semana). */
.datebr-cell[data-datebr-outside="1"] {
    color: var(--text-muted);
    opacity: 0.55;
}

/* Fora de min/max */
.datebr-cell:disabled {
    color: var(--text-muted);
    opacity: 0.3;
    cursor: not-allowed;
}

/* Hoje — anel, sem preencher (para não competir com o selecionado). */
.datebr-cell[data-datebr-today="1"] {
    box-shadow: inset 0 0 0 1px var(--primary-blue);
    font-weight: 600;
}

/* Selecionado */
.datebr-cell[aria-selected="true"] {
    background-color: var(--primary-blue);
    color: #fff;
    font-weight: 600;
}

.datebr-cell[aria-selected="true"]:hover:not(:disabled) {
    background-color: var(--primary-blue-hover);
}

/* -------- Hora (type="datetime-local") -------- */
.datebr-time {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border-ui);
}

.datebr-time label {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.datebr-time input {
    width: 3rem;
    height: 1.875rem;
    padding: 0 0.25rem;
    text-align: center;

    font-family: inherit;
    font-size: 0.8125rem;
    color: var(--text-main);
    background-color: var(--bg-page);
    border: 1px solid var(--border-ui);
    border-radius: 0.375rem;
}

.datebr-time input:focus {
    outline: none;
    border-color: var(--primary-blue);
}

/* -------- Rodapé: Hoje / Limpar -------- */
.datebr-foot {
    display: flex;
    gap: 0.375rem;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border-ui);
}

.datebr-foot-btn {
    flex: 1 1 0;
    height: 1.875rem;

    border: 1px solid var(--border-ui);
    border-radius: 0.375rem;
    background-color: transparent;
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.75rem;
    cursor: pointer;

    transition: background-color var(--motion-instant);
}

.datebr-foot-btn:hover {
    background-color: var(--bg-page);
}

.datebr-foot-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--primary-blue);
}

/* Impressão: o campo vira texto puro, sem botão nem popover. */
@media print {
    .datebr-toggle,
    .datebr-pop {
        display: none !important;
    }
}


/* ===== dropzone.css ===== */
/* ============================================================
   DS · Dropzone (v1.3)
   Upload de arquivo com drag & drop.

   Uso:
     <label class="dropzone" for="file-input">
       <input type="file" id="file-input" class="dropzone-input" accept=".csv,.xlsx">
       <i class="ph ph-upload-simple dropzone-icon" aria-hidden="true"></i>
       <p class="dropzone-primary">Arraste ou clique para selecionar</p>
       <p class="dropzone-secondary">CSV, XLSX até 10 MB</p>
     </label>

   Estados extras (aplicar via JS ao arrastar/errar):
     .dropzone.dropzone-active    — arrastando sobre (dashed virar solid blue)
     .dropzone.dropzone-error     — arquivo inválido
   ============================================================ */

.dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1.25rem;
    border: 2px dashed var(--border-strong);
    border-radius: 0.75rem;
    background: var(--bg-page);
    color: var(--text-muted);
    cursor: pointer;
    text-align: center;
    transition: border-color var(--motion-smooth),
                background   var(--motion-smooth),
                color        var(--motion-smooth);
}

.dropzone:hover {
    border-color: var(--primary-blue);
    color: var(--primary-blue);
}

.dropzone-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.dropzone-icon {
    font-size: 2.25rem;
    opacity: 0.7;
    margin-bottom: 0.25rem;
}

.dropzone-primary {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-main);
    margin: 0;
}

.dropzone-secondary {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0;
}

/* Ativo (arquivo sendo arrastado sobre) */
.dropzone-active {
    border-style: solid;
    border-color: var(--primary-blue);
    background: var(--primary-blue-tint);
    color: var(--primary-blue);
}

/* Erro (arquivo inválido, tamanho excedido) */
.dropzone-error {
    border-color: #F87171;            /* red-400 */
    background: #FEF2F2;              /* red-50 */
    color: #B91C1C;                   /* red-700 */
}
html.dark .dropzone-error {
    background: rgba(239, 68, 68, 0.1);
}


/* ===== dual-list.css ===== */
/* dual-list.css — picker de duas listas (transferência por click)
 *
 * Classes:
 *   .dual-list                 — container grid (1col mobile / 2col lg)
 *   .dual-list-col             — coluna (header + search + items + empty)
 *   .dual-list-col-included    — modifier visual da coluna direita (opcional)
 *   .dual-list-col-header      — barra de título da coluna
 *   .dual-list-col-title       — texto "Disponíveis" / "Inclusos"
 *   .dual-list-col-count       — pill com contagem
 *   .dual-list-search          — wrapper input com ícone
 *   .dual-list-items           — <ul> rolável dos itens
 *   .dual-list-item            — <li> clicável (hover = tint + seta)
 *   .dual-list-item-label      — texto principal
 *   .dual-list-item-sub        — texto secundário (opcional)
 *   .dual-list-item-arrow      — seta direcional (→/←)
 *   .dual-list-empty           — estado vazio (ícone + texto)
 *   .dual-list-display         — strip horizontal de chips (form pai)
 *   .dual-list-display-empty   — placeholder "Aceita todos" no form pai
 */

.dual-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--border-ui);
  /* Quando o ancestral define altura (modal com flex-1), o grid herda;
   * fora de modal limitado, mantem um minimo razoavel.
   */
  min-height: 320px;
  height: 100%;
  overflow: hidden;  /* impede que itens vazem antes de cada lista rolar */
}
@media (min-width: 1024px) {
  .dual-list { grid-template-columns: 1fr 1fr; }
}

.dual-list-col {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  min-height: 0;       /* permite filho com overflow rolar */
  overflow: hidden;
}

.dual-list-col-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px 8px;
}
.dual-list-col-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-main);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.dual-list-col-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--primary-blue-tint);
  color: var(--primary-blue);
  font-size: 0.75rem;
  font-weight: 600;
}

.dual-list-search {
  position: relative;
  padding: 0 16px 12px;
}
.dual-list-search > i {
  position: absolute;
  left: 28px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}
.dual-list-search > input {
  padding-left: 36px;
  width: 100%;
}

.dual-list-items {
  flex: 1;
  overflow-y: auto;
  padding: 4px 8px 12px;
  list-style: none;
  margin: 0;
}

.dual-list-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 8px;
  cursor: pointer;
  transition: background var(--motion-instant);
  user-select: none;
  animation: ds-fadeIn 0.2s ease-out;
}
/* Zebra — aplicado por JS aos pares dentre os itens visíveis. */
.dual-list-item.is-zebra {
  background: var(--bg-page);
}
.dual-list-item:hover,
.dual-list-item:focus-visible,
.dual-list-item.is-zebra:hover,
.dual-list-item.is-zebra:focus-visible {
  background: var(--primary-blue-tint);
  outline: none;
}
.dual-list-item:focus-visible {
  box-shadow: 0 0 0 2px var(--primary-blue);
}
.dual-list-item-label {
  flex: 1;
  font-size: 0.875rem;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dual-list-item-sub {
  font-size: 0.75rem;
  color: var(--text-muted);
}
.dual-list-item-arrow {
  color: var(--primary-blue);
  opacity: 0;
  transition: opacity var(--motion-instant);
}
.dual-list-item:hover .dual-list-item-arrow,
.dual-list-item:focus-visible .dual-list-item-arrow {
  opacity: 1;
}

.dual-list-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px 16px;
  color: var(--text-muted);
  font-size: 0.875rem;
}
.dual-list-empty > i { font-size: 2rem; opacity: 0.5; }

/* Sentinel invisível usado pelo IntersectionObserver no modo server-side
 * — dispara carga da próxima página quando entra no viewport.
 */
.dual-list-sentinel {
  list-style: none;
  height: 1px;
}

/* Spinner de loading da próxima página (modo server-side). */
.dual-list-loading {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px;
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* Display de chips no form pai — visual de "campo lista" (mesma borda dos
 * inputs text). Container sempre visível para deixar claro que ali existe
 * uma lista, mesmo vazia. Quando não há chips, mostra o placeholder
 * `.dual-list-display-empty` dentro do container.
 */
.dual-list-display {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-content: flex-start;
  min-height: 38px;
  padding: 6px 8px;
  background-color: var(--bg-page);
  border: 1px solid var(--border-ui);
  border-radius: 0.5rem;
}
.dual-list-display:empty::before {
  content: attr(data-empty);
  color: var(--text-muted);
  font-size: 0.875rem;
  font-style: italic;
  line-height: 26px;
}
.dual-list-display .chip {
  flex-shrink: 0;
}
/* Placeholder fora do container (legado/uso isolado) — herda mesmo visual
 * para casos onde o template não usa o atributo data-empty.
 */
.dual-list-display-empty {
  padding: 8px 10px;
  background-color: var(--bg-page);
  border: 1px solid var(--border-ui);
  border-radius: 0.5rem;
  color: var(--text-muted);
  font-size: 0.875rem;
  font-style: italic;
}


/* ===== empty.css ===== */
/* ============================================================
   DS · Empty state
   3 variantes: generic · search · first-time (com CTA)

   Uso — generic:
     <div class="empty">
       <i class="ph ph-folder-open empty-icon" aria-hidden="true"></i>
       <p class="empty-title">Nenhum registro encontrado</p>
       <p class="empty-desc">Tente ajustar os filtros.</p>
     </div>

   Uso — search (com ação de limpar):
     <div class="empty">
       <i class="ph ph-magnifying-glass empty-icon" aria-hidden="true"></i>
       <p class="empty-title">Sem resultados para "joão"</p>
       <p class="empty-desc">Verifique a ortografia ou limpe os filtros.</p>
       <button class="btn btn-secondary">Limpar filtros</button>
     </div>

   Uso — first-time (onboarding, com icon-box colorido e CTA primary):
     <div class="empty">
       <div class="empty-iconbox"><i class="ph-fill ph-users" aria-hidden="true"></i></div>
       <p class="empty-title">Nenhum usuário cadastrado</p>
       <p class="empty-desc">Comece adicionando o primeiro membro da equipe.</p>
       <button class="btn btn-primary"><i class="ph ph-plus"></i> Adicionar usuário</button>
     </div>
   ============================================================ */

.empty {
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-elev-1);

    padding: 3rem 1.25rem;         /* py-12 px-5 */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 0.25rem;
}

/* Ícone "leve" (generic e search) */
.empty-icon {
    font-size: 2.25rem;            /* text-4xl */
    color: var(--text-muted);
    opacity: 0.5;
    margin-bottom: 0.5rem;
}

/* Icon-box "forte" (first-time, tinted) */
.empty-iconbox {
    width: 56px;
    height: 56px;
    border-radius: 0.75rem;
    background-color: var(--primary-blue-tint);
    color: var(--primary-blue);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    margin-bottom: 0.75rem;
}

.empty-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-main);
    margin: 0;
}

.empty-desc {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0.25rem 0 0 0;
    max-width: 44ch;
    line-height: 1.5;
}

/* Espaço entre conteúdo e CTA */
.empty > .btn,
.empty > a.btn {
    margin-top: 1rem;
}


/* ===== form.css ===== */
/* ============================================================
   DS · Form
   Label, fieldset/legend, select custom, switch, radio, checkbox,
   segmented control. Contador de caracteres.
   ============================================================ */

/* -------- Label (acima do input sempre) -------- */
.form-label {
    display: block;
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 0.25rem;
    line-height: 1.4;
}
.form-label-required::after {
    content: " *";
    color: #EF4444;                /* red-500 */
}

/* -------- Helper text -------- */
.form-helper {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 0.25rem;
    line-height: 1.5;
}

/* -------- Fieldset com legend (agrupamento semântico) -------- */
.form-fieldset {
    border: 0;
    padding: 0;
    margin: 0;
}
.form-fieldset > * + * {
    margin-top: 0.75rem;           /* space-y-3 — dentro do grupo */
}
.form-legend {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.75rem;
    padding: 0;
}

/* -------- Contador de caracteres para textarea -------- */
.form-counter {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-family: ui-monospace, Menlo, Monaco, Consolas, monospace;
    text-align: right;
}

/* -------- Select custom --------
   Uso:
     <div class="select">
       <select class="input">
         <option>...</option>
       </select>
     </div>
   O wrapper adiciona o chevron via ::after (Phosphor não pode
   ser pseudo-content, então é unicode; OK para este caso).
*/
.select {
    position: relative;
}
.select select.input {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 2.25rem;        /* espaço p/ chevron */
    cursor: pointer;
}
.select::after {
    content: "";
    position: absolute;
    right: 0.875rem;
    top: 50%;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--chevron-color, var(--text-muted));
    border-bottom: 2px solid var(--chevron-color, var(--text-muted));
    transform: translateY(-75%) rotate(45deg);
    pointer-events: none;
}

/* -------- Checkbox / Radio --------
   HTML nativo, cor via accent-color (CSS moderno, ótimo suporte).
*/
.form-check {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    color: var(--text-main);
    cursor: pointer;
    user-select: none;
}
.form-check input[type="checkbox"],
.form-check input[type="radio"] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--primary-blue);
    cursor: pointer;
}
.form-check input:disabled {
    cursor: not-allowed;
}
.form-check:has(input:disabled) {
    opacity: 0.5;
    cursor: not-allowed;
}

/* -------- Switch / Toggle --------
   Uso:
     <label class="switch">
       <input type="checkbox" [checked] [disabled]>
       <span class="switch-track"></span>
     </label>
*/
.switch {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    flex-shrink: 0;
}
.switch input {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}
.switch-track {
    position: absolute;
    inset: 0;
    background-color: #CBD5E1;     /* slate-300 */
    border-radius: 9999px;
    cursor: pointer;
    transition: background-color var(--motion-smooth);
}
.switch-track::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 2px;
    width: 20px;
    height: 20px;
    background: #FFFFFF;
    border-radius: 9999px;
    box-shadow: var(--shadow-elev-1);
    transition: transform var(--motion-smooth);
}
.switch input:checked + .switch-track {
    background-color: var(--primary-blue);
}
.switch input:checked + .switch-track::before {
    transform: translateX(20px);
}
.switch input:focus-visible + .switch-track {
    box-shadow: 0 0 0 4px var(--primary-blue-tint);
}
.switch input:disabled + .switch-track {
    opacity: 0.5;
    cursor: not-allowed;
}

html.dark .switch-track {
    background-color: #3F3F46;     /* zinc-700 */
}

/* -------- Segmented Control --------
   Uso:
     <div class="seg" role="tablist">
       <button role="tab" aria-selected="true">Dia</button>
       <button role="tab" aria-selected="false">Mês</button>
     </div>
   JS deve alternar aria-selected no click.
*/
.seg {
    display: inline-flex;
    background-color: var(--bg-page);
    border: 1px solid var(--border-ui);
    border-radius: 0.5rem;
    padding: 2px;
}
.seg > button {
    padding: 0.25rem 0.75rem;
    height: 28px;
    font-size: 0.75rem;
    font-weight: 600;
    font-family: inherit;
    color: var(--text-muted);
    background: transparent;
    border: 0;
    border-radius: 0.375rem;
    cursor: pointer;
    transition: background-color var(--motion-smooth),
                color            var(--motion-smooth);
    white-space: nowrap;
}
.seg > button:hover {
    color: var(--text-main);
}
.seg > button[aria-selected="true"] {
    background-color: var(--surface);
    color: var(--primary-blue);
    box-shadow: var(--shadow-elev-1);
}
.seg > button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--primary-blue-tint);
}


/* ===== input.css ===== */
/* ============================================================
   DS · Input
   6 estados: default · focus · disabled · readonly · error · warning
   Escala: sm 32px (filtro inline) · md 38px (default)

   Uso:
     <input type="text" class="input" placeholder="Nome">
     <input class="input input-sm" placeholder="Buscar">
     <input class="input input-error" aria-invalid="true">
     <input class="input input-warning">
     <textarea class="input input-textarea"></textarea>

   Selects: ver form.css (exigem chevron custom, appearance-none).
   ============================================================ */

.input {
    display: block;
    width: 100%;
    height: 38px;
    padding: 0 0.75rem;
    line-height: 36px;             /* height - 2*border → centra texto verticalmente */

    font-family: inherit;
    /* Mobile: 16px evita o zoom automático do iOS Safari ao focar.
       Desktop (>=640px): retorna ao text-sm (14px) do design.            */
    font-size: 1rem;               /* 16px — mobile */
    color: var(--text-main);

    background-color: var(--bg-page);
    border: 1px solid var(--border-ui);
    border-radius: 0.5rem;

    transition: border-color var(--motion-instant),
                box-shadow   var(--motion-instant);
}
@media (min-width: 640px) {
    .input {
        font-size: 0.875rem;       /* text-sm — desktop */
    }
}

.input::placeholder {
    color: var(--text-muted);
}

/* -------- Tamanho sm --------
   Mantém 16px no mobile (mesmo motivo: anti-zoom iOS). Em desktop volta ao 12px do design.
*/
.input-sm {
    height: 32px;
    line-height: 30px;             /* height - 2*border */
    font-size: 1rem;               /* 16px — mobile */
    padding: 0 0.625rem;
}
@media (min-width: 640px) {
    .input-sm {
        font-size: 0.75rem;        /* text-xs — desktop */
    }
}

/* -------- State: focus -------- */
.input:focus,
.input:focus-visible {
    outline: none;
    border-color: var(--primary-blue);
    box-shadow: 0 0 0 4px var(--primary-blue-tint);
}

/* -------- State: disabled -------- */
.input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background-color: var(--bg-page);
}

/* -------- State: readonly --------
   Visual "texto" sem parecer input editável.
*/
.input[readonly],
.input-readonly {
    background-color: transparent;
    border-color: transparent;
    cursor: default;
    padding-left: 0;
    padding-right: 0;
}
.input[readonly]:focus,
.input-readonly:focus {
    border-color: transparent;
    box-shadow: none;
}

/* -------- State: error -------- */
.input-error,
.input[aria-invalid="true"] {
    border-color: #F87171;         /* red-400 */
    box-shadow: 0 0 0 2px rgba(248, 113, 113, 0.2);
}
.input-error:focus,
.input[aria-invalid="true"]:focus {
    border-color: #F87171;
    box-shadow: 0 0 0 4px rgba(248, 113, 113, 0.25);
}

/* -------- State: warning -------- */
.input-warning {
    border-color: #FACC15;         /* yellow-400 */
    box-shadow: 0 0 0 2px rgba(250, 204, 21, 0.2);
}
.input-warning:focus {
    border-color: #FACC15;
    box-shadow: 0 0 0 4px rgba(250, 204, 21, 0.25);
}

/* -------- Mensagem auxiliar abaixo do input --------
   Uso:
     <p class="input-help">Usado para recuperar senha.</p>
     <p class="input-error-msg"><i class="ph-fill ph-warning-circle"></i> Campo obrigatório.</p>
     <p class="input-warning-msg"><i class="ph-fill ph-warning"></i> CNPJ não encontrado.</p>
*/
.input-help,
.input-error-msg,
.input-warning-msg {
    font-size: 0.75rem;
    margin-top: 0.25rem;
    display: flex;
    align-items: center;
    gap: 0.25rem;
    line-height: 1.4;
}
.input-help         { color: var(--text-muted); }
.input-error-msg    { color: #DC2626; }            /* red-600 */
.input-warning-msg  { color: #A16207; }            /* yellow-700 */

/* -------- Textarea --------
   Multi-linha: mantém padding vertical, altura mínima = 2 linhas md.
*/
.input-textarea {
    height: auto;
    min-height: 76px;
    padding: 0.5rem 0.75rem;
    resize: vertical;
    line-height: 1.5;
}

/* -------- Input com tipografia de código (CPF/CNPJ/valor numérico estruturado) --------
   v1.4.1: fonte idêntica ao input padrão. Só reforça tabular-nums
   (já vem do html via _base.css) para garantir alinhamento de dígitos.
*/
.input-code,
.input-mono {                /* .input-mono alias legado */
    font-variant-numeric: tabular-nums;
}

/* -------- Busca com ícone à esquerda --------
   Uso:
     <div class="input-group">
       <i class="ph ph-magnifying-glass input-group-icon" aria-hidden="true"></i>
       <input class="input input-with-icon" placeholder="Buscar…">
     </div>
*/
.input-group {
    position: relative;
}
.input-group-icon {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
    font-size: 1rem;
}
.input-with-icon {
    padding-left: 2.5rem;
}


/* ===== kpi.css ===== */
/* ============================================================
   DS · KPI card
   Dashboard metric card — label + valor grande + contexto.

   Uso:
     <div class="kpi">
       <div class="kpi-header">
         <span class="kpi-label">Receita total</span>
         <i class="ph ph-trend-up kpi-icon kpi-icon-success" aria-hidden="true"></i>
       </div>
       <p class="kpi-value">R$ 1.234.567,89</p>
       <p class="kpi-hint">Este mês</p>
     </div>

   Grid recomendado: usar Tailwind
     <div class="grid grid-cols-1 lg:grid-cols-4 gap-6"> ... kpis ... </div>
   ============================================================ */

.kpi {
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    padding: 1.25rem;
    box-shadow: var(--shadow-elev-1);
}

.kpi-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.kpi-label {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.kpi-icon {
    font-size: 1.25rem;
    color: var(--primary-blue);
}
.kpi-icon-success { color: #16A34A; }
.kpi-icon-danger  { color: #DC2626; }
.kpi-icon-warning { color: #CA8A04; }

.kpi-value {
    font-size: 1.5rem;             /* text-2xl */
    font-weight: 700;
    color: var(--title-color);
    margin: 0;
    line-height: 1.2;
}

.kpi-hint {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0.25rem 0 0 0;
}


/* ===== meta.css ===== */
/* ============================================================
   DS · Meta (v1.4)
   Tipografia canônica de metadado — CPF, CNPJ, IDs, códigos,
   emails, datas, telefones — dentro de listas ou cards.

   v1.4: eliminamos monospace. Agora tudo usa Inter com
   `font-variant-numeric: tabular-nums` para alinhar dígitos e
   `letter-spacing` sutil em valores-código. Uma única fonte
   no site inteiro.

   Uso — par label/valor:
     <div class="meta-row">
       <span class="meta-label">CNPJ</span>
       <span class="meta-value meta-value-code">12.345.678/0001-90</span>
     </div>

   Uso — valores em bloco (vertical):
     <div class="meta-block">
       <span class="meta-label">CNPJ</span>
       <span class="meta-value meta-value-code">{{ c.inscricao }}</span>
     </div>

   Uso — item de lista compacta (com truncate):
     <div class="meta-item">
       <p class="meta-primary">Razão Social</p>
       <p class="meta-secondary meta-value-code">12.345.678/0001-90</p>
     </div>

   Uso — valor em destaque (CNPJ do header da empresa):
     <span class="meta-value-code-prominent">{{ cnpj }}</span>
   ============================================================ */

/* -------- Label (tag à esquerda) -------- */
.meta-label {
    font-size: 0.75rem;            /* text-xs */
    color: var(--text-muted);
    font-weight: 500;
    line-height: 1.4;
}

/* -------- Valor (padrão, texto corrido) -------- */
.meta-value {
    font-size: 0.875rem;           /* text-sm */
    color: var(--text-main);
    line-height: 1.5;
}

/* -------- Valor-código — CNPJ/CPF/ID/código contábil --------
   v1.4.1: fonte e peso idênticos ao resto do site.
   Só mantém `tabular-nums` (garantido pela regra global do <html>
   em _base.css, mas reforçado aqui por clareza).
*/
.meta-value-code {
    font-size: 0.75rem;            /* text-xs */
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* -------- Valor-código em destaque — documento-âncora do header (CNPJ principal) --------
   Uso: quando o valor do documento é o "título" secundário da tela.
   v1.4.1: idêntico à tipografia padrão text-sm semibold — o destaque
   vem da posição (header) e tamanho, não da fonte.
*/
.meta-value-code-prominent {
    font-size: 0.875rem;           /* text-sm */
    font-weight: 600;              /* semibold, igual a .meta-primary */
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

/* -------- Alias legado: .meta-value-mono e .meta-value-mono-prominent --------
   Mantidos por compatibilidade. Comportamento idêntico às novas.
*/
.meta-value-mono {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.meta-value-mono-prominent {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

/* -------- Row horizontal (label + valor lado a lado) -------- */
.meta-row {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    line-height: 1.4;
}

/* -------- Row com label esquerda + valor direita (justify-between) --------
   Usar dentro de `.meta-list` para listas de chave/valor (CPF/CNPJ, endereço,
   dados pessoais). Valor trunca se não couber.
*/
.meta-row.meta-row-justify {
    width: 100%;
    justify-content: space-between;
    gap: 0.75rem;
}
.meta-row.meta-row-justify .meta-label {
    flex-shrink: 0;
}
.meta-row.meta-row-justify .meta-value {
    text-align: right;
    font-weight: 600;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.meta-row.meta-row-justify .meta-value.meta-value-code,
.meta-row.meta-row-justify .meta-value-code {
    font-weight: 600;
    color: var(--text-main);
}

/* -------- Lista vertical de meta-rows (substitui <dl class="divide-y ..."> -------- */
.meta-list {
    margin: 0;
}
.meta-list > .meta-row {
    padding: 0.375rem 0;
    border-bottom: 1px solid var(--border-ui);
}
.meta-list > .meta-row:last-child {
    border-bottom: 0;
}

/* -------- Block vertical (label em cima, valor embaixo) -------- */
.meta-block {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

/* -------- Item de lista (título principal + metadado abaixo) -------- */
.meta-item {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.meta-primary {
    font-size: 0.875rem;           /* text-sm */
    font-weight: 600;
    color: var(--title-color);
    margin: 0;
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.meta-secondary {
    font-size: 0.75rem;            /* text-xs */
    color: var(--text-muted);
    margin: 0;
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* ===== modal.css ===== */
/* ============================================================
   DS · Modal
   Estrutura de 3 seções: header + body + footer. Usa elev-3.
   Animação de entrada: scaleIn (400ms ease-out dramático).

   IMPORTANTE: a ABERTURA/FECHAMENTO do modal é feita pelo
   modal_utils.js (overlay, open/close, iframe delegation).
   Este CSS define APENAS a aparência interna do partial.

   Uso (partial — SEM extends):
     {# design-system: v1.2 #}
     <form method="post" action="{% url 'minha_view' obj.pk %}">
       {% csrf_token %}
       <div class="modal-header">
         <div class="modal-header-icon">
           <i class="ph-fill ph-pencil-simple" aria-hidden="true"></i>
         </div>
         <h3 class="modal-title">Editar usuário</h3>
         <button type="button" class="modal-close" onclick="closeModal()" aria-label="Fechar">
           <i class="ph ph-x" aria-hidden="true"></i>
         </button>
       </div>
       <div class="modal-body">
         ... form ...
       </div>
       <div class="modal-footer">
         <button type="button" class="btn btn-ghost" onclick="closeModal()">Cancelar</button>
         <button type="submit" class="btn btn-primary">Salvar</button>
       </div>
     </form>

   Variante exclusão: substitua .modal-header-icon por .modal-header-icon-danger
   e o botão submit por <button class="btn btn-danger">Excluir</button>.
   ============================================================ */

/* -------- Header -------- */
.modal-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1.25rem;              /* p-5 */
    border-bottom: 1px solid var(--border-ui);
}

.modal-header-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.75rem;
    background-color: var(--primary-blue-tint);
    color: var(--primary-blue);
    font-size: 1.125rem;
}
.modal-header-icon-danger {
    background-color: #FEE2E2;     /* red-100 */
    color: #DC2626;                /* red-600 */
}

.modal-title {
    flex: 1;
    min-width: 0;
    font-size: 1rem;               /* text-base */
    font-weight: 700;
    color: var(--title-color);
    margin: 0;
    line-height: 1.4;
}

.modal-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 0;
    background: transparent;
    border-radius: 0.5rem;
    color: var(--text-muted);
    cursor: pointer;
    transition: color      var(--motion-instant),
                background var(--motion-instant);
}
.modal-close:hover {
    color: var(--text-main);
    background-color: var(--bg-page);
}
.modal-close:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--primary-blue-tint);
}

/* -------- Body -------- */
.modal-body {
    padding: 1.25rem;
}
.modal-body > * + * {
    margin-top: 1rem;              /* space-y-4 default */
}

/* -------- Footer -------- */
.modal-footer {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 0.5rem;
    padding: 1rem 1.25rem;         /* py-4 px-5 */
    border-top: 1px solid var(--border-ui);
    flex-wrap: wrap;
}

/* -------- Dialog (shell que envolve o partial — criado pelo modal_utils.js) --------
   Se modal_utils.js não aplicar essas classes automaticamente, elas servem
   de referência para quem construir o shell.
*/
.modal-dialog {
    background-color: var(--surface-raised);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-elev-3);
    animation: ds-scaleIn var(--motion-deliberate) both;
}


/* ===== office.css ===== */
/* ============================================================
   DS · Office (v1.5)
   Ajustes específicos para o shell `/office/` — iframes confinados.

   O `_base_office.html` já aplica `p-6` no container do conteúdo,
   então NÃO usar `.container-page` aqui (gera padding duplo).

   Tipografia mais compacta: o iframe office tem altura limitada
   (depto 40px + ribbon ~92px no topo + barra de scroll), então
   reduzimos espaçamentos verticais para caber mais informação
   na tela útil.

   Uso (substitui `container-page` em páginas do `/office/obrigacoes/`,
   `/office/bicontabil/`, `/office/cpanel/`, etc.):

     <div class="office-page">
       <header class="office-header">
         <div class="page-header-main">
           <div class="office-icon"><i class="ph-fill ph-[X]"></i></div>
           <div>
             <h1 class="office-title">Título</h1>
             <p class="office-subtitle">Subtítulo</p>
           </div>
         </div>
         <div class="page-actions">...</div>
       </header>
       <div class="card">...</div>
     </div>

   Diferenças vs `.page-wrap` (cliente, R8):
     - Sem max-width (já confinado no iframe).
     - Spacing vertical 1rem (em vez de 1.5rem).
     - Title 1.125rem (em vez de 1.25rem) — menos volumoso no iframe.
     - Icon 40px (em vez de 48px) — proporcional ao header menor.
     - Margin-bottom do header reduzido para 0.25rem.

   ============================================================ */

/* -------- Wrapper -------- */
.office-page {
    width: 100%;
    animation: ds-fadeIn var(--motion-deliberate) both;
}
.office-page > * + * {
    margin-top: 1rem;
}

/* -------- Header -------- */
.office-header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.25rem;
}
@media (min-width: 1024px) {
    .office-header {
        flex-direction: row;
        align-items: center;
    }
}

/* -------- Icon box compacto (40px) -------- */
.office-icon {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border-radius: 0.5rem;
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    box-shadow: var(--shadow-elev-1);
    color: var(--primary-blue);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
}

/* -------- Título compacto -------- */
.office-title {
    font-size: 1.125rem;            /* text-lg */
    font-weight: 700;
    color: var(--title-color);
    margin: 0;
    line-height: 1.3;
}

.office-subtitle {
    font-size: 0.8125rem;           /* 13px — só nessa zona, headers do office */
    color: var(--text-muted);
    margin: 0.125rem 0 0 0;
    line-height: 1.4;
}

/* -------- Ações do header (mesmas do .page-actions, replicadas
            só para conveniência caso o caller queira escopar) -------- */
.office-page-actions {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: 100%;
}
@media (min-width: 1024px) {
    .office-page-actions {
        flex-direction: row;
        width: auto;
    }
}

/* -------- KPIs compactos no office --------
   No iframe office, os KPIs precisam ser mais baixos para 5 caberem
   numa linha sem scroll horizontal. */
.office-page .kpi {
    padding: 0.75rem 1rem;
}
.office-page .kpi-value {
    font-size: 1.5rem;              /* 24px — em vez do default text-2xl */
    line-height: 1.1;
}
.office-page .kpi-label {
    font-size: 0.6875rem;           /* 11px */
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* -------- Tabelas em padding reduzido para caber no iframe -------- */
.office-page .table th,
.office-page .table td {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}
.office-page .table th {
    font-size: 0.75rem;             /* 12px */
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* -------- Empty state compacto -------- */
.office-page .empty {
    padding: 1.5rem 1rem;
}
.office-page .empty-iconbox {
    width: 48px;
    height: 48px;
}
.office-page .empty-icon {
    font-size: 1.5rem;
}

/* -------- Espaçamento de cards mais conservador no office -------- */
.office-page .card-header {
    padding: 0.75rem 1rem;
}


/* ===== page.css ===== */
/* ============================================================
   DS · Page structure (v1.3)
   Wrapper canônico de página + header padrão (R8).
   Substitui o Tailwind inline `w-full space-y-6 animate-fadeIn`
   + toda a estrutura de header de página.

   Uso:
     <div class="page-wrap">
       <header class="page-header">
         <div class="page-header-main">
           <div class="page-icon"><i class="ph-fill ph-[ICON]"></i></div>
           <div>
             <h1 class="page-title">Título</h1>
             <p class="page-subtitle">Subtítulo</p>
           </div>
         </div>
         <div class="page-actions">
           <button class="btn btn-secondary">Exportar</button>
           <button class="btn btn-primary">Novo</button>
         </div>
       </header>

       <!-- Conteúdo: cards, tabelas, etc. -->
       <div class="card">...</div>
     </div>
   ============================================================ */

.page-wrap {
    width: 100%;
    animation: ds-fadeIn var(--motion-deliberate) both;
}
.page-wrap > * + * {
    margin-top: 1.5rem;           /* space-y-6 */
}

/* -------- Header da página -------- */
.page-header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.5rem;
}
@media (min-width: 1024px) {
    .page-header {
        flex-direction: row;
        align-items: center;
    }
}

.page-header-main {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-width: 0;
}

/* -------- Icon box do header (48px, sempre `ph-fill` no ícone) -------- */
.page-icon {
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    border-radius: 0.75rem;
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    box-shadow: var(--shadow-elev-1);
    color: var(--primary-blue);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
}

/* -------- Título e subtítulo -------- */
.page-title {
    font-size: 1.25rem;            /* text-xl */
    font-weight: 700;
    color: var(--title-color);
    margin: 0;
    line-height: 1.3;
}

.page-subtitle {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin: 0.125rem 0 0 0;
    line-height: 1.4;
}

/* -------- Ações do header (botões à direita) -------- */
.page-actions {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: 100%;
}
@media (min-width: 1024px) {
    .page-actions {
        flex-direction: row;
        width: auto;
    }
}


/* ===== rich-content.css ===== */
/* ============================================================
   DS · Rich content (sanitized HTML)
   Wrapper para HTML rich-text vindo do banco (sanitizado por
   bleach na camada Python — ver office/obrigacoes/utils_html.py).

   Uso:
     <div class="rich-content">{{ valor|rich_html }}</div>

   Tags suportadas pelo whitelist (ver utils_html.ALLOWED_TAGS):
     b, strong, i, em, u, s, strike, br, p, div, span,
     ul, ol, li, a, sub, sup, font

   Resolve quirks comuns:
   - <font color="red"> herdado do legado mantém cor.
   - <p>/<div> não geram margem dupla quando usados como wrappers
     simples (caso comum: legado wrappa tudo em <div>).
   - Texto puro (sem tags de bloco) preserva quebras de linha
     via white-space: pre-wrap como fallback.
   ============================================================ */

.rich-content {
  white-space: normal;
}

.rich-content > *:first-child { margin-top: 0; }
.rich-content > *:last-child  { margin-bottom: 0; }

.rich-content p,
.rich-content div {
  margin: 0;
}

.rich-content p + p,
.rich-content div + div {
  margin-top: 0.5em;
}

.rich-content ul,
.rich-content ol {
  margin: 0.25em 0 0.25em 1.25em;
  padding: 0;
}

.rich-content li { margin: 0.1em 0; }

.rich-content a {
  color: var(--primary-blue);
  text-decoration: underline;
}

.rich-content a:hover { text-decoration: none; }

/* Compat com legado: <font color="..."> e <font color="#..."> mantêm a cor.
   O browser interpreta o atributo color do <font>, mas regras CSS de pais
   com `color: ...` ganham por especificidade — não adicionar nada aqui. */

/* Quando o texto contém apenas \n e nenhuma tag de bloco,
   preserva quebras (caso de campos curtos digitados sem rich). */
.rich-content:not(:has(p, div, br, ul, ol)) {
  white-space: pre-wrap;
}

/* ============================================================
   Editor inline (rich_text.js — contenteditable + toolbar)
   ============================================================ */

.rich-editor {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-ui);
  border-radius: 8px;
  background: var(--surface);
  overflow: hidden;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.rich-editor:focus-within {
  border-color: var(--primary-blue);
  box-shadow: 0 0 0 3px var(--primary-blue-tint);
}

.rich-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 4px 6px;
  background: var(--bg-page);
  border-bottom: 1px solid var(--border-ui);
}

.rich-toolbar-compact {
  padding: 2px 4px;
}

.rich-btn {
  background: transparent;
  border: 1px solid transparent;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--text-main);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
}

.rich-btn:hover {
  background: var(--surface-raised, var(--surface));
  border-color: var(--border-ui);
}

.rich-editor-area {
  padding: 8px 10px;
  font-size: 0.875rem;
  color: var(--text-main);
  outline: none;
  min-height: 1.5em;
  white-space: normal;
}

.rich-editor-area:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  pointer-events: none;
}

.rich-editor-single .rich-editor-area {
  min-height: 1.5em;
  max-height: 2.5em;
  overflow-y: auto;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Aplica todos os estilos do .rich-content também no editor (quando
   visualizando dentro do contenteditable). */
.rich-editor-area p,
.rich-editor-area div { margin: 0; }
.rich-editor-area p + p,
.rich-editor-area div + div { margin-top: 0.5em; }
.rich-editor-area a { color: var(--primary-blue); text-decoration: underline; }

/* Color popover */
.rich-color-popover {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border-ui);
  border-radius: 8px;
  box-shadow: var(--shadow-elev-2);
}

.rich-color-swatch {
  width: 22px;
  height: 22px;
  border-radius: 4px;
  border: 1px solid var(--border-ui);
  cursor: pointer;
  padding: 0;
}

.rich-color-swatch:hover { transform: scale(1.1); }

/* Imagens manipuláveis no editor rico (rich_text.js, data-allow-images="1") */
.rich-img-wrap {
  position: relative;
  display: inline-block;
  cursor: move;
  margin: 2px;
  outline: 1px dashed transparent;
  vertical-align: middle;
}
.rich-img-wrap:hover,
.rich-img-wrap:focus-within {
  outline-color: var(--primary-blue);
}
.rich-img-wrap img {
  display: block;
  max-width: 100%;
  height: auto;
  user-select: none;
}
.rich-img-del {
  position: absolute;
  top: -10px;
  right: -10px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgb(220 38 38);
  color: white;
  border: 2px solid white;
  display: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 0.7rem;
  line-height: 1;
  padding: 0;
  z-index: 2;
}
.rich-img-wrap:hover .rich-img-del,
.rich-img-wrap:focus-within .rich-img-del {
  display: flex;
}
.rich-img-del:hover {
  background: rgb(185 28 28);
}
.rich-img-resize {
  position: absolute;
  bottom: -6px;
  right: -6px;
  width: 14px;
  height: 14px;
  background: var(--primary-blue);
  border: 2px solid white;
  border-radius: 2px;
  cursor: nwse-resize;
  display: none;
  z-index: 2;
}
.rich-img-wrap:hover .rich-img-resize,
.rich-img-wrap:focus-within .rich-img-resize {
  display: block;
}


/* ===== selectable-list.css ===== */
/* ============================================================
   DS · Selectable List (v1.5)
   Lista de itens selecionáveis com filtro digitável (client-side).

   Estrutura mínima:

     <div class="selectable-list" data-mode="single">
       <div class="selectable-list-search">
         <i class="ph ph-magnifying-glass"></i>
         <input type="text" class="selectable-list-input"
                placeholder="Filtrar..." data-sel-list-filter>
       </div>

       <div class="selectable-list-body" role="listbox">
         <button type="button" class="sel-list-item"
                 data-search-text="abc def" data-value="1">
           <span class="sel-list-marker"></span>
           <span class="sel-list-content">
             <span class="sel-list-label">Texto principal</span>
             <span class="sel-list-desc">Descrição opcional</span>
           </span>
         </button>
         ...
       </div>

       <div class="selectable-list-empty hidden">Nenhum resultado.</div>
     </div>

   Variantes:
     .selectable-list-compact      → padding/altura reduzidos (uso /office/)
     .selectable-list[data-mode="multi"]  → checkboxes em vez de radio

   Estados de item:
     .is-selected, .is-disabled

   Filtro digitável:
     - Cada item declara `data-search-text` (texto plano lowercase, sem
       acento) com tudo que deve casar.
     - O JS fica a cargo do consumidor (ver template office/components/_selectable_list_demo.html).
   ============================================================ */

/* -------- Wrapper -------- */
.selectable-list {
    display: flex;
    flex-direction: column;
    background-color: var(--surface);
    border: 1px solid var(--border-ui);
    border-radius: 0.625rem;
    overflow: hidden;
}

/* -------- Search header -------- */
.selectable-list-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--border-ui);
    background-color: var(--surface);
}
.selectable-list-search > i {
    color: var(--text-muted);
    font-size: 1rem;
    flex-shrink: 0;
}
.selectable-list-input {
    flex: 1;
    background: transparent;
    border: 0;
    outline: none;
    font-size: 0.875rem;
    color: var(--text-main);
}
.selectable-list-input::placeholder {
    color: var(--text-muted);
}

/* -------- Body (lista rolável) -------- */
.selectable-list-body {
    display: flex;
    flex-direction: column;
    max-height: 320px;
    overflow-y: auto;
    padding: 0.25rem;
}

/* -------- Item -------- */
.sel-list-item {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    width: 100%;
    text-align: left;
    padding: 0.625rem 0.75rem;
    border: 1px solid transparent;
    border-radius: 0.5rem;
    background: transparent;
    cursor: pointer;
    transition: background-color var(--motion-instant), border-color var(--motion-instant);
    color: var(--text-main);
    font: inherit;
}
.sel-list-item:hover {
    background-color: var(--primary-blue-tint);
}
.sel-list-item:focus-visible {
    outline: none;
    border-color: var(--primary-blue);
    background-color: var(--primary-blue-tint);
}
.sel-list-item.is-selected {
    background-color: var(--primary-blue-tint);
    border-color: var(--primary-blue);
}
.sel-list-item.is-disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.sel-list-item.is-disabled:hover {
    background-color: transparent;
}

/* Item escondido pelo filtro */
.sel-list-item.is-hidden {
    display: none;
}

/* -------- Marker (radio/checkbox visual) -------- */
.sel-list-marker {
    flex-shrink: 0;
    width: 1.125rem;
    height: 1.125rem;
    margin-top: 0.125rem;
    border: 1.5px solid var(--border-strong);
    background-color: var(--surface);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: border-color var(--motion-instant), background-color var(--motion-instant);
}
/* single → radio (round) */
.selectable-list[data-mode="single"] .sel-list-marker {
    border-radius: 999px;
}
.selectable-list[data-mode="single"] .sel-list-item.is-selected .sel-list-marker {
    border-color: var(--primary-blue);
}
.selectable-list[data-mode="single"] .sel-list-item.is-selected .sel-list-marker::after {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 999px;
    background-color: var(--primary-blue);
}
/* multi → checkbox (square) */
.selectable-list[data-mode="multi"] .sel-list-marker {
    border-radius: 0.25rem;
}
.selectable-list[data-mode="multi"] .sel-list-item.is-selected .sel-list-marker {
    border-color: var(--primary-blue);
    background-color: var(--primary-blue);
}
.selectable-list[data-mode="multi"] .sel-list-item.is-selected .sel-list-marker::after {
    content: "\2713";
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1;
}

/* -------- Conteúdo -------- */
.sel-list-content {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
    flex: 1;
}
.sel-list-label {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-main);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sel-list-desc {
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.35;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* -------- Trailing slot (badge, ícone, atalho à direita) -------- */
.sel-list-trailing {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--text-muted);
    font-size: 0.75rem;
}

/* -------- Empty state -------- */
.selectable-list-empty {
    padding: 1rem 0.75rem;
    text-align: center;
    font-size: 0.8125rem;
    color: var(--text-muted);
    border-top: 1px solid var(--border-ui);
}
.selectable-list-empty.hidden {
    display: none;
}

/* -------- Footer opcional (contagem, ações) -------- */
.selectable-list-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--border-ui);
    background-color: var(--bg-page);
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* ============================================================
   Variante COMPACT — padrão para uso no /office/
   ============================================================ */
.selectable-list-compact .selectable-list-search {
    padding: 0.5rem 0.625rem;
}
.selectable-list-compact .selectable-list-input {
    font-size: 0.8125rem;
}
.selectable-list-compact .selectable-list-body {
    max-height: 260px;
    padding: 0.125rem;
}
.selectable-list-compact .sel-list-item {
    padding: 0.4375rem 0.5rem;
    gap: 0.5rem;
}
.selectable-list-compact .sel-list-marker {
    width: 1rem;
    height: 1rem;
}
.selectable-list-compact .sel-list-label {
    font-size: 0.8125rem;
}
.selectable-list-compact .sel-list-desc {
    font-size: 0.6875rem;
}

/* ============================================================
   Inline (sem borda externa, encaixa dentro de outro card)
   ============================================================ */
.selectable-list-inline {
    border: 0;
    border-radius: 0;
    background: transparent;
}
.selectable-list-inline .selectable-list-search {
    background: transparent;
}


/* ===== skeleton.css ===== */
/* ============================================================
   DS · Skeleton
   Loading de listas/tabelas pesadas. Para ação pontual (botão
   submit), usar .btn-loading com ph-spinner.

   Uso:
     <div class="skeleton" style="width: 200px; height: 12px"></div>
     <div class="skeleton skeleton-circle" style="width: 36px; height: 36px"></div>
     <div class="skeleton skeleton-line"></div>
   ============================================================ */

.skeleton {
    background: linear-gradient(
        90deg,
        var(--bg-page) 0%,
        var(--border-ui) 50%,
        var(--bg-page) 100%
    );
    background-size: 200% 100%;
    animation: ds-shimmer 1.6s ease-in-out infinite;
    border-radius: 0.5rem;
}

.skeleton-circle {
    border-radius: 9999px;
}

/* Linha de texto padrão (imita text-sm) */
.skeleton-line {
    height: 12px;
    width: 100%;
    border-radius: 0.25rem;
}


/* ===== stepper.css ===== */
/* ============================================================
   DS · Stepper (v1.3)
   Progresso em fluxo multi-passo (onboarding, wizard de import).

   Uso:
     <ol class="stepper" role="list">
       <li class="step step-done">
         <span class="step-marker">1</span>
         <span class="step-label">Dados básicos</span>
       </li>
       <li class="step step-current" aria-current="step">
         <span class="step-marker">2</span>
         <span class="step-label">Configuração</span>
       </li>
       <li class="step">
         <span class="step-marker">3</span>
         <span class="step-label">Revisão</span>
       </li>
     </ol>
   ============================================================ */

.stepper {
    display: flex;
    align-items: center;
    gap: 0;
    list-style: none;
    margin: 0;
    padding: 0;
    width: 100%;
}

.step {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 1;
    min-width: 0;
    position: relative;
}

.step:not(:last-child)::after {
    content: "";
    flex: 1;
    height: 2px;
    background: var(--border-ui);
    margin: 0 0.5rem;
    transition: background-color var(--motion-smooth);
}

.step-marker {
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: 9999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
    background: var(--bg-page);
    border: 2px solid var(--border-ui);
    color: var(--text-muted);
    transition: background-color var(--motion-smooth),
                border-color     var(--motion-smooth),
                color            var(--motion-smooth);
}

.step-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Estado: passo concluído */
.step-done .step-marker {
    background: var(--primary-blue);
    border-color: var(--primary-blue);
    color: white;
}
.step-done:not(:last-child)::after {
    background: var(--primary-blue);
}
.step-done .step-label {
    color: var(--text-main);
}

/* Estado: passo atual */
.step-current .step-marker {
    background: var(--surface);
    border-color: var(--primary-blue);
    color: var(--primary-blue);
    box-shadow: 0 0 0 4px var(--primary-blue-tint);
}
.step-current .step-label {
    color: var(--primary-blue);
}


/* ===== subtabs.css ===== */
/* ============================================================
   DS · Subtabs (v1.5)
   Navegação secundária dentro de uma seção ou aba.
   Estilo default: chip (pill preenchido quando ativo).
   Distingue do nível pai por peso, não por cor.

   Uso:
     <div class="subtabs" role="tablist">
       <button type="button" class="subtab-btn is-active"
               role="tab" aria-selected="true" data-subtab="app">
         <i class="ph-bold ph-device-mobile" aria-hidden="true"></i>
         <span>APP</span>
       </button>
       <button type="button" class="subtab-btn"
               role="tab" aria-selected="false" data-subtab="salario">
         <i class="ph-bold ph-currency-dollar" aria-hidden="true"></i>
         <span>Salários</span>
       </button>
     </div>

     <div class="subtab-panel" role="tabpanel" id="subpanel-app">...</div>

   Variante:
     .subtabs-underline — underline leve em vez de pill preenchido.
     Usar quando o container pai já tem destaque (dentro de card).
   ============================================================ */

/* -------- Container (pill default) -------- */
.subtabs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem;
}

/* -------- Subtab button (pill default) -------- */
.subtab-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;

    height: 28px;
    padding: 0 0.75rem;
    border: 1px solid var(--border-ui);
    border-radius: 9999px;

    background-color: var(--bg-page);
    color: var(--text-muted);

    font-family: inherit;
    font-size: 0.75rem;            /* text-xs */
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;

    transition: background-color var(--motion-instant),
                color            var(--motion-instant),
                border-color     var(--motion-instant);
}

.subtab-btn i {
    font-size: 0.875rem;
    line-height: 1;
}

/* -------- State: hover -------- */
.subtab-btn:hover:not(.is-active):not([aria-selected="true"]) {
    color: var(--text-main);
    border-color: var(--border-strong);
}

/* -------- State: active -------- */
.subtab-btn.is-active,
.subtab-btn[aria-selected="true"] {
    background-color: var(--primary-blue);
    color: #FFFFFF;
    border-color: var(--primary-blue);
}

/* -------- State: focus -------- */
.subtab-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--primary-blue-tint);
}

/* -------- State: disabled -------- */
.subtab-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* -------- Variante: underline (dentro de card) -------- */
.subtabs-underline {
    border-bottom: 1px solid var(--border-ui);
    gap: 0.25rem;
}

.subtabs-underline .subtab-btn {
    height: auto;
    padding: 0.5rem 0.75rem;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    margin-bottom: -1px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.subtabs-underline .subtab-btn:hover:not(.is-active):not([aria-selected="true"]) {
    color: var(--text-main);
    background: transparent;
    border-bottom-color: var(--border-ui);
}

.subtabs-underline .subtab-btn.is-active,
.subtabs-underline .subtab-btn[aria-selected="true"] {
    background: transparent;
    color: var(--primary-blue);
    border-bottom-color: var(--primary-blue);
}

/* -------- Panel -------- */
.subtab-panel {
    /* sem estilo adicional — "hidden" controla visibilidade */
}


/* ===== table.css ===== */
/* ============================================================
   DS · Table
   3 densidades (compact/default/comfortable) + zebra + sticky header.
   Sempre dentro de um wrapper com overflow-x-auto para mobile.

   Uso:
     <div class="card card-flush">
       <div class="table-scroll">
         <table class="table">
           <thead class="table-head">
             <tr>
               <th>Usuário</th> ...
             </tr>
           </thead>
           <tbody>
             <tr><td>...</td></tr>
           </tbody>
         </table>
       </div>
     </div>

   Variantes:
     .table-compact     — px-4 py-2 text-xs
     .table-comfortable — px-5 py-4 text-sm
     .table-zebra       — listrado em linhas pares
     .table-sticky      — thead fixo no scroll vertical
   ============================================================ */

.table-scroll {
    overflow-x: auto;
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;           /* text-sm */
}

/* -------- Thead -------- */
.table-head {
    background-color: rgba(248, 250, 252, 0.5);  /* --bg-page/50 */
    border-bottom: 1px solid var(--border-ui);
}
html.dark .table-head {
    background-color: rgba(9, 9, 11, 0.5);
}
.table-head th {
    padding: 0.75rem 1.25rem;      /* py-3 px-5 */
    text-align: left;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
}

/* -------- Tbody -------- */
.table tbody tr {
    border-bottom: 1px solid var(--border-ui);
    transition: background-color var(--motion-instant);
}
.table tbody tr:hover {
    background-color: rgba(248, 250, 252, 0.4);  /* --bg-page/40 */
}
html.dark .table tbody tr:hover {
    background-color: rgba(255, 255, 255, 0.03);
}
.table td {
    padding: 0.75rem 1.25rem;
    color: var(--text-main);
    vertical-align: middle;
}

/* Alinhamento por classe (semântico) */
.table th.text-right,
.table td.text-right { text-align: right; }
.table th.text-center,
.table td.text-center { text-align: center; }

/* -------- Densidade: compact -------- */
.table-compact th,
.table-compact td {
    padding: 0.5rem 1rem;          /* py-2 px-4 */
    font-size: 0.75rem;            /* text-xs */
}

/* -------- Densidade: comfortable -------- */
.table-comfortable th,
.table-comfortable td {
    padding: 1rem 1.25rem;         /* py-4 px-5 */
}

/* -------- Zebra -------- */
.table-zebra tbody tr:nth-child(even) {
    background-color: rgba(248, 250, 252, 0.3);
}
html.dark .table-zebra tbody tr:nth-child(even) {
    background-color: rgba(255, 255, 255, 0.02);
}

/* -------- Sticky header (lista longa dentro de container com altura fixa) -------- */
.table-sticky thead {
    position: sticky;
    top: 0;
    z-index: 1;
    backdrop-filter: blur(4px);
}

/* -------- Wrapper de tabela ampla (scroll horizontal robusto) --------
   Use quando a tabela tem muitas colunas e precisa rolar dentro do card,
   sem extravasar o ancestral em mobile.

   Truque chave: width:0 + min-width:100% + display:block. Isso obriga o
   wrapper a usar a largura do parent flex/block (e nao a largura
   intrinseca dos descendentes). Combinado com overflow:auto, garante
   que a barra de scroll aparece DENTRO do wrapper, e que o wrapper
   nunca excede o pai — mesmo com tabelas wider que a viewport.

   Uso:
     <div class="card card-flush">
       <div class="af-scroll-wrap">
         <table>...</table>
       </div>
     </div>
*/
.af-scroll-wrap {
    display: block;
    width: 0;
    min-width: 100%;
    max-width: 100%;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
}


/* ===== tabs.css ===== */
/* ============================================================
   DS · Tabs (v1.5)
   Navegação raiz de seções de uma página ou modal.
   Estilo: underline horizontal (padrão da indústria — Material 3,
   Carbon, Ant, Atlassian).

   Toggle: classe .is-active + aria-selected="true". O dev aplica
   os dois; o CSS aceita qualquer um dos dois seletores.

   Uso:
     <div class="tabs" role="tablist">
       <button type="button" class="tab-btn is-active"
               role="tab" aria-selected="true" data-tab="contrato">
         <i class="ph-bold ph-briefcase" aria-hidden="true"></i>
         <span>Contrato</span>
       </button>
       <button type="button" class="tab-btn"
               role="tab" aria-selected="false" data-tab="pessoal">
         <i class="ph-bold ph-user" aria-hidden="true"></i>
         <span>Pessoal</span>
       </button>
     </div>

     <div class="tab-panel" role="tabpanel" id="panel-contrato">...</div>
     <div class="tab-panel hidden" role="tabpanel" id="panel-pessoal">...</div>

   Variantes:
     .tabs-stacked — ícone em cima + label embaixo (modais apertados)
     .tabs-equal   — cada tab recebe flex:1 (full-width dividido)
   ============================================================ */

/* -------- Container -------- */
.tabs {
    display: flex;
    align-items: stretch;
    gap: 0.25rem;
    border-bottom: 1px solid var(--border-ui);
    overflow-x: auto;
    scrollbar-width: thin;
}
.tabs::-webkit-scrollbar { height: 4px; }
.tabs::-webkit-scrollbar-thumb { background: var(--border-ui); border-radius: 2px; }

/* -------- Tab button -------- */
.tab-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;

    padding: 0.75rem 1rem;
    border: 0;
    background: transparent;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;           /* cola no border-bottom do container */

    font-family: inherit;
    font-size: 0.875rem;           /* text-sm */
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
    cursor: pointer;

    transition: color              var(--motion-instant),
                border-bottom-color var(--motion-instant),
                background-color   var(--motion-instant);
}

.tab-btn i {
    font-size: 1rem;
    line-height: 1;
}

/* -------- State: hover -------- */
.tab-btn:hover:not(.is-active):not([aria-selected="true"]) {
    color: var(--text-main);
    border-bottom-color: var(--border-ui);
}

/* -------- State: active -------- */
.tab-btn.is-active,
.tab-btn[aria-selected="true"] {
    color: var(--primary-blue);
    border-bottom-color: var(--primary-blue);
}

/* -------- State: focus -------- */
.tab-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--primary-blue-tint);
    border-radius: 0.25rem;
}

/* -------- State: disabled -------- */
.tab-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* -------- Variante: stacked (ícone em cima + label embaixo) -------- */
.tabs-stacked .tab-btn {
    flex-direction: column;
    gap: 0.25rem;
    min-width: 84px;
    padding: 0.625rem 0.75rem;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.tabs-stacked .tab-btn i {
    font-size: 1.125rem;
}

/* -------- Variante: equal (flex:1 por tab) -------- */
.tabs-equal .tab-btn {
    flex: 1;
    justify-content: center;
}

/* -------- Variante: equal só a partir de ≥640px (mobile-first) --------
   Em <sm, container fica scrollable horizontalmente. Cada tab mantém
   largura natural (não apertada) e o usuário rola para ver as abas.
*/
@media (min-width: 640px) {
    .tabs-equal-sm .tab-btn {
        flex: 1;
        justify-content: center;
    }
}

/* -------- Panel -------- */
.tab-panel {
    /* sem estilo adicional — o Tailwind "hidden" controla visibilidade */
}


/* ===== toast.css ===== */
/* ============================================================
   DS · Toast
   Stack top-right, auto-dismiss. 4 tipos: success · error · warning · info.

   Uso (estrutura que showToast() deve criar):
     <div class="toast-stack">
       <div class="toast toast-success" role="status">
         <div class="toast-icon"><i class="ph-fill ph-check-circle"></i></div>
         <div class="toast-content">
           <p class="toast-title">Usuário salvo</p>
           <p class="toast-desc">As alterações foram aplicadas.</p>
         </div>
         <button class="toast-close" aria-label="Fechar"><i class="ph ph-x"></i></button>
       </div>
     </div>
   ============================================================ */

.toast-stack {
    position: fixed;
    top: 1rem;
    right: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    z-index: 10000;
    max-width: 100vw;
    pointer-events: none;          /* wrapper — children recebem events */
}

.toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    min-width: 320px;
    max-width: 420px;
    padding: 0.75rem 0.875rem;
    background-color: var(--surface-raised);
    border: 1px solid var(--border-ui);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-elev-3);
    animation: ds-slideDown var(--motion-deliberate) both;
}

.toast-icon {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.5rem;
    font-size: 1.125rem;
}
.toast-success .toast-icon { background-color: #DCFCE7; color: #16A34A; }
.toast-error   .toast-icon { background-color: #FEE2E2; color: #DC2626; }
.toast-warning .toast-icon { background-color: #FEF9C3; color: #CA8A04; }
.toast-info    .toast-icon { background-color: #DBEAFE; color: #2563EB; }

.toast-content {
    flex: 1;
    min-width: 0;
}
.toast-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-main);
    margin: 0;
    line-height: 1.4;
}
.toast-desc {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0.125rem 0 0 0;
    line-height: 1.5;
}

.toast-close {
    flex-shrink: 0;
    background: transparent;
    border: 0;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0.25rem;
    transition: color var(--motion-instant);
}
.toast-close:hover  { color: var(--text-main); }


/* ===== tooltip.css ===== */
/* ============================================================
   DS · Tooltip (CSS-only)
   Substitui o title="" nativo (feio, lento, inconsistente).

   Uso:
     <button
       class="icon-btn tooltip"
       data-tooltip="Editar usuário"
       aria-label="Editar">
       <i class="ph-bold ph-pencil-simple" aria-hidden="true"></i>
     </button>

   Aparece em hover e focus-visible. Posição: acima, centralizado.
   Para tooltips longos ou posicionamento dinâmico, use Popper/Floating UI.
   ============================================================ */

.tooltip {
    position: relative;
}
.tooltip::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);

    background-color: var(--primary-black);
    color: #FFFFFF;
    font-size: 0.6875rem;          /* ~11px */
    font-weight: 500;
    padding: 0.25rem 0.5rem;
    border-radius: 0.375rem;
    white-space: nowrap;
    pointer-events: none;

    opacity: 0;
    transition: opacity   var(--motion-smooth),
                transform var(--motion-smooth);
    z-index: 50;
}
.tooltip:hover::after,
.tooltip:focus-visible::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* -------- Variante multi-linha --------
   O tooltip base é `nowrap`: bom para "Editar", péssimo para 3-4 dados
   (vira uma faixa que estoura a lateral do iframe do /office/). Aqui o
   `data-tooltip` quebra em `&#10;` e o bloco ganha largura máxima.

   Uso:
     <span class="tooltip tooltip-multiline"
           data-tooltip="Competência 01/2026&#10;Vence 31/01/2026">
*/
.tooltip.tooltip-multiline::after {
    white-space: pre-line;
    text-align: left;
    max-width: 260px;
    line-height: 1.45;
}

/* Em dark, tooltip fica claro (invertido) */
html.dark .tooltip::after {
    background-color: #F4F4F5;
    color: #09090B;
}


/* ===== tree-picker.css ===== */
/* ============================================================
   DS · Tree Picker
   Modal de seleção em árvore com herança de subárvore.
   Irmão de dual-list.css; o campo (chips) reusa .dual-list-display.

   Classes:
     .tree-picker-filters   — barra de filtros do topo
     .tree-picker-list      — lista rolável de nós
     .tree-picker-row       — uma pasta
     .tree-picker-row.is-parent    — pasta com subpastas na árvore emitida
     .tree-picker-row.is-inherited — filha coberta por um pai marcado
     .tree-picker-icon      — ícone de pasta (cheio no pai, vazado na folha)
     .tree-picker-count     — "+N" de subpastas que a marcação leva junto
     .tree-picker-badge     — selo "herdada"

   Gutter: 20px à esquerda (12px da lista + 8px da linha), o mesmo 1.25rem do
   .modal-header/.modal-footer — as linhas ficam alinhadas com o título do modal.
   A indentação de nível entra por `--tp-indent`: o JS só informa a profundidade,
   o recuo base e a régua de hierarquia moram aqui.
   ============================================================ */

.tree-picker-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    padding: 12px 20px;
    border-bottom: 1px solid var(--border-ui);
    background-color: var(--bg-page);
}
.tree-picker-filters .input { min-width: 200px; flex: 1 1 200px; }
.tree-picker-filters .select { flex: 0 0 auto; }
/* O toggle "somente marcadas" usa .form-check do DS (form.css) — aqui só o
   que é específico da barra de filtros. */
.tree-picker-filters .form-check { white-space: nowrap; }

.tree-picker-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 6px 12px 12px;
    list-style: none;
    margin: 0;
}

.tree-picker-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    padding-left: calc(8px + var(--tp-indent, 0px));
    border-radius: 8px;
    font-size: 0.8125rem;
    color: var(--text-main);
    cursor: pointer;
    transition: background-color var(--motion-instant);
    /* Régua de hierarquia: um fio por nível de ancestral, dentro da faixa de
       indentação. Sem `--tp-indent` (lista plana no modo filtrado) a faixa tem
       largura 0 e nada é desenhado. */
    background-image: repeating-linear-gradient(
        to right, var(--border-ui) 0 1px, transparent 1px 18px);
    background-repeat: no-repeat;
    background-position: 16px 0;   /* centro do checkbox do nível 0 (8px + 16px/2) */
    background-size: var(--tp-indent, 0px) 100%;
}
.tree-picker-row:hover { background-color: var(--primary-blue-tint); }
.tree-picker-row:focus-visible {
    outline: none;
    background-color: var(--primary-blue-tint);
    box-shadow: 0 0 0 2px var(--primary-blue);
}
/* Mesmas medidas do checkbox de .form-check (form.css): a linha da árvore não
   é um .form-check (é item de lista com label próprio), mas o controle tem que
   ficar do mesmo tamanho dos checkboxes do resto do sistema. */
.tree-picker-row input[type="checkbox"] {
    flex-shrink: 0;
    width: 1rem;
    height: 1rem;
    accent-color: var(--primary-blue);
    cursor: pointer;
}
.tree-picker-row input[type="checkbox"]:disabled { cursor: not-allowed; }

.tree-picker-row.is-inherited {
    color: var(--text-muted);
    cursor: default;
}
.tree-picker-row.is-inherited:hover { background-color: transparent; }

.tree-picker-row.is-orphan { color: #A16207; }
html.dark .tree-picker-row.is-orphan { color: #FCD34D; }

/* -------- Pai × filha --------
   A indentação sozinha não basta: com filtro ativo a lista vira plana e a
   hierarquia sumiria. Pai = ícone cheio azul + rótulo semibold + contador das
   subpastas que a marcação leva junto; folha = ícone vazado e peso normal. */
.tree-picker-icon {
    flex-shrink: 0;
    font-size: 1rem;
    color: var(--text-muted);
}
.tree-picker-row.is-parent .tree-picker-icon { color: var(--primary-blue); }
.tree-picker-row.is-parent .tree-picker-label {
    font-weight: 600;
    color: var(--title-color);
}
.tree-picker-row.is-inherited .tree-picker-icon,
.tree-picker-row.is-inherited.is-parent .tree-picker-icon,
.tree-picker-row.is-inherited.is-parent .tree-picker-label { color: inherit; }
.tree-picker-row.is-orphan .tree-picker-icon { color: inherit; }

.tree-picker-count {
    flex-shrink: 0;
    padding: 0.0625rem 0.375rem;
    border-radius: 0.25rem;
    background-color: var(--bg-page);
    border: 1px solid var(--border-ui);
    color: var(--text-muted);
    font-size: 0.6875rem;
    font-weight: 600;
}

.tree-picker-label { flex: 1 1 auto; min-width: 0; }

.tree-picker-badge {
    flex-shrink: 0;
    padding: 0.0625rem 0.375rem;
    border-radius: 0.25rem;
    background-color: var(--primary-blue-tint);
    color: var(--primary-blue);
    font-size: 0.6875rem;
    font-weight: 600;
}

.tree-picker-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.875rem;
}
