/*
 * Componentes visuais reutilizáveis do bufunfa.
 *
 * Estilos de elementos que aparecem em múltiplas páginas. Sempre
 * consomem variáveis de tokens.css. Nada de cor ou espaçamento em
 * literal aqui.
 *
 * Símbolo (.tile + .lockup) segue exatamente a tabela de tamanhos do
 * guia de marca. Os valores foram calibrados visualmente — não
 * interpolar nem recalcular.
 */


/* Símbolo da marca: ladrilho (b com ponto-acento) ======================== */

.tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 28px;
    box-shadow: var(--shadow-md);
    padding: 0 14%;
    background: var(--color-primary-700);
}

.tile .b {
    font-family: var(--font-sans);
    font-weight: 700;
    color: white;
    line-height: 0.85;
    letter-spacing: -0.05em;
    position: relative;
    display: inline-block;
}

/* O .dot é child de .b para herdar o bounding box do glifo, não do tile. */
.tile .dot {
    background: var(--color-accent);
    border-radius: var(--radius-pill);
    position: absolute;
}

.tile.size-hero { width: 160px; height: 160px; border-radius: 36px; }
.tile.size-128  { width: 128px; height: 128px; border-radius: 28px; }
.tile.size-96   { width: 96px;  height: 96px;  border-radius: 22px; }
.tile.size-64   { width: 64px;  height: 64px;  border-radius: 14px; }
.tile.size-48   { width: 48px;  height: 48px;  border-radius: 11px; }
.tile.size-32   { width: 32px;  height: 32px;  border-radius: 7px;  }
.tile.size-20   { width: 20px;  height: 20px;  border-radius: 5px;  }
.tile.size-14   { width: 14px;  height: 14px;  border-radius: 3px;  }

.tile.size-hero .b   { font-size: 110px; }
.tile.size-hero .dot { width: 16px; height: 16px; bottom: 4px;   right: -12px;  }

.tile.size-128 .b    { font-size: 88px; }
.tile.size-128 .dot  { width: 13px; height: 13px; bottom: 2px;   right: -10px;  }

.tile.size-96 .b     { font-size: 66px; }
.tile.size-96 .dot   { width: 10px; height: 10px; bottom: 1px;   right: -8px;   }

.tile.size-64 .b     { font-size: 44px; }
.tile.size-64 .dot   { width: 7px;  height: 7px;  bottom: 1px;   right: -6px;   }

.tile.size-48 .b     { font-size: 33px; }
.tile.size-48 .dot   { width: 5px;  height: 5px;  bottom: 1px;   right: -4px;   }

.tile.size-32 .b     { font-size: 22px; }
.tile.size-32 .dot   { width: 4px;  height: 4px;  bottom: 0.5px; right: -3.5px; }

.tile.size-20 .b     { font-size: 14px; padding-left: 0; }
.tile.size-20 .dot   { display: none; }

.tile.size-14 .b     { font-size: 10px; padding-left: 0; }
.tile.size-14 .dot   { display: none; }


/* Lockup horizontal: símbolo + nome ====================================== */

.lockup {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    text-decoration: none;
}

.lockup .lockup-name {
    font-family: var(--font-sans);
    font-weight: 700;
    letter-spacing: -0.04em;
    color: var(--color-brand);
    line-height: 1;
}

.lockup:has(.tile.size-48) .lockup-name { font-size: 32px; }
.lockup:has(.tile.size-32) .lockup-name { font-size: 22px; }
.lockup:has(.tile.size-20) { gap: 8px; }
.lockup:has(.tile.size-20) .lockup-name { font-size: 16px; }


/* Containers (ADR 0013) =================================================== */

.container-wide,
.container-form,
.container-reading {
    width: 100%;
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--container-padding);
    padding-right: var(--container-padding);
    box-sizing: border-box;
}

.container-wide    { max-width: var(--container-wide-max); }
.container-form    { max-width: var(--container-form-max); }
.container-reading { max-width: var(--container-reading-max); }

/* Mobile (< sm): forma a regra de "três linhas" para listas */
@media (max-width: 575.98px) {
    .container-wide,
    .container-form,
    .container-reading {
        padding-left: var(--space-md);
        padding-right: var(--space-md);
    }
}


/* App shell: header e navegação ========================================== */

body > header {
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--space-section);
    padding-top: var(--space-md);
    padding-bottom: var(--space-md);
}

body > header > .app-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
}

body > header .app-header-user {
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

body > header .app-header-user-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.2;
}

body > header .app-header-user-meta small {
    color: var(--color-text-soft);
    font-size: 13px;
}

body > header .app-header-user-meta .app-header-user-email {
    color: var(--color-text-muted);
    font-size: 12px;
}

body > header .app-header-actions a[role="button"] {
    margin: 0;
    padding: var(--space-xs) var(--space-md);
}

@media (max-width: 575.98px) {
    body > header .app-header-user-meta .app-header-user-email {
        display: none;
    }
    body > header .app-header-user-meta {
        align-items: flex-end;
    }
    body > header .app-header-user-meta small {
        font-size: 12px;
    }
}

@media (min-width: 768px) {
    body > header {
        position: sticky;
        top: 0;
        z-index: 40;
        background: var(--color-bg);
    }
}


/* Navegação principal ====================================================
 *
 * Top tabs em desktop (>= 768px), bottom tabs em mobile (< 768px). Os dois
 * navs convivem no DOM e a media query alterna a visibilidade — cada um
 * fica num lugar adequado ao gesto da plataforma. ADR documenta o padrão.
 */

.app-nav-top, .app-nav-bottom {
    display: flex;
}

.app-nav-top {
    gap: var(--space-md);
    align-items: center;
}

.app-nav-bottom {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--color-card);
    border-top: 1px solid var(--color-border);
    padding: 8px env(safe-area-inset-right) calc(8px + env(safe-area-inset-bottom)) env(safe-area-inset-left);
    justify-content: space-around;
    z-index: 50;
}

.app-nav-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: var(--radius-sm);
    color: var(--color-text-soft);
    text-decoration: none;
    font-weight: 500;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.app-nav-item:hover {
    color: var(--color-text);
    background: var(--color-border-soft);
}

.app-nav-item.active {
    color: var(--color-primary-700);
    background: var(--color-primary-100);
}

.app-nav-bottom .app-nav-item {
    flex: 1;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 6px 4px;
    font-size: 11px;
    border-radius: var(--radius-sm);
}

@media (min-width: 768px) {
    .app-nav-bottom { display: none; }
}

@media (max-width: 767.98px) {
    .app-nav-top { display: none; }

    /*
     * Espaço pra bottom nav fixed não cobrir o conteúdo. Soma altura real
     * da nav + um respiro visual de --space-lg pra que o último item do
     * conteúdo nunca apareça colado na borda da nav.
     */
    body.has-bottom-nav main {
        padding-bottom: calc(
            var(--bottom-nav-height) + var(--space-lg) + env(safe-area-inset-bottom)
        );
    }
}


/* Hub de Gerenciar ======================================================= */

.manage-hub {
    display: grid;
    gap: var(--space-md);
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

.manage-hub-card {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.manage-hub-card:hover {
    border-color: var(--color-primary-700);
    background: var(--color-border-soft);
}

.manage-hub-card .icon {
    color: var(--color-primary-700);
    flex-shrink: 0;
}

.manage-hub-card strong {
    display: block;
    color: var(--color-text);
}

.manage-hub-card small {
    color: var(--color-text-soft);
}

.manage-hub-danger {
    margin-top: var(--space-xl);
}

.manage-hub-danger h3 {
    margin: 0 0 var(--space-sm) 0;
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--color-danger);
}

.manage-hub-card-danger {
    border-color: var(--color-danger);
}

.manage-hub-card-danger:hover {
    border-color: var(--color-danger);
    background: color-mix(in srgb, var(--color-danger) 6%, var(--color-card));
}

.manage-hub-card-danger .icon,
.manage-hub-card-danger strong {
    color: var(--color-danger);
}


/* Allowlist gerenciável (feature temporária) ============================= */

/*
 * Input arranca na borda esquerda dos cards; botão Adicionar fica recuado
 * por margin-right pra alinhar com o botão Remover (que está dentro do
 * padding-x do .allowlist-item).
 */
.allowlist-add-form {
    max-width: 720px;
    margin-bottom: var(--space-md);
}

.allowlist-add-row {
    display: flex;
    align-items: flex-end;
    gap: var(--space-sm);
}

.allowlist-add-row .field {
    flex: 1;
    min-width: 0;
}

/*
 * `--field-control-height` só existe dentro de `.field`, então fixamos
 * 2.5rem direto. Zerar `margin-bottom` é essencial: o Pico aplica 1rem por
 * padrão em todo <button>, e com `align-items: flex-end` essa margin sobe
 * o botão 1rem acima do bottom do input ao lado (desalinha o baseline).
 */
.allowlist-add-row > button {
    flex: 0 0 auto;
    width: 7rem;
    height: 2.5rem;
    padding: 0;
    margin: 0 var(--space-md) 0 0;
}

.allowlist-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-width: 720px;
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.allowlist-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
}

.allowlist-item-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.allowlist-item-text small {
    color: var(--color-text-soft);
    font-size: 0.8125rem;
}

.allowlist-remove-form {
    margin: 0;
}

.allowlist-remove-form > button {
    width: 7rem;
    height: 2.5rem;
    padding: 0;
    margin: 0;
}

.allowlist-empty {
    color: var(--color-text-soft);
    padding: var(--space-md);
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-md);
    text-align: center;
}

.allowlist-section-title {
    margin-top: var(--space-lg);
    font-size: 1.0625rem;
}


/* Tipografia de tela =====================================================
 *
 * O Pico v2 escala a fonte raiz com a viewport (1rem ~ 16px no mobile e
 * 20px no desktop). Todos os tamanhos abaixo usam rem para acompanhar essa
 * escala, evitando que labels secundárias sumam em telas grandes.
 */

h1, h2, h3, h4 {
    font-family: var(--font-sans);
    letter-spacing: -0.02em;
}

h2 {
    font-size: 1.375rem;
    font-weight: 600;
    margin-bottom: var(--space-md);
}

h3 {
    font-size: 1.125rem;
    font-weight: 600;
}

.section-label {
    font-size: 0.6875rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-text-muted);
}

/* Form fields ============================================================ */

.required-mark {
    color: var(--color-danger);
    margin-left: var(--space-xs);
}

.field-error {
    color: var(--color-danger);
    display: block;
    font-size: 0.875rem;
    margin-top: calc(-1 * var(--space-sm));
    margin-bottom: var(--space-sm);
}

.field-help {
    display: block;
    font-size: 0.875rem;
    margin-top: var(--space-xs);
    margin-bottom: var(--space-sm);
    color: var(--color-text-muted);
}

/* Borda vermelha automática quando o label contém um erro de field. */
label:has(.field-error) > input,
label:has(.field-error) > select,
label:has(.field-error) > textarea {
    --pico-form-element-border-color: var(--color-danger);
    --pico-form-element-active-border-color: var(--color-danger);
    --pico-form-element-focus-color: var(--color-danger);
}


/* Form-level errors ====================================================== */

.form-errors {
    color: var(--color-danger);
    background: var(--color-danger-bg);
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
    border: 1px solid rgba(181, 72, 58, 0.2);
}


/* Valores monetários ===================================================== */

.amount-positive { color: var(--color-success); }
.amount-negative { color: var(--color-danger); }

/*
 * Inputs que carregam dados tabulares ganham IBM Plex Mono. Vale para
 * money-mask, datas (type=date) e dias do mês (type=number). Mantém
 * coluna de dígito alinhada e o zero pontilhado.
 */
input[data-mask="money"],
input[type="number"],
input[type="date"] {
    font-family: var(--font-mono);
    font-feature-settings: "zero" 0;
    font-variant-numeric: normal;
    letter-spacing: normal;
}


/* Seletor de mês ========================================================= */

/*
 * Hero de saldo do dashboard. Direção visual de "card-screen" do guia
 * de marca (preview-v2): petróleo cheio, label maiúsculo discreto,
 * valor monetário monumental em mono.
 */
.hero-balance {
    position: relative;
    background: var(--color-primary-700);
    color: var(--color-white);
    border-radius: var(--radius-lg);
    padding: var(--space-lg);
    margin-bottom: var(--space-section);
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.hero-balance-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
}

.hero-balance-label {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.72);
}

.hero-month-nav {
    display: flex;
    align-items: center;
    gap: var(--space-2xs);
}

/*
 * Botões compactos (toolbar/period-nav): aperta o espaçamento interno
 * dos botões/links Pico via --pico-form-element-spacing-*. Mesma escala
 * (2xs/sm) usada nas 4 classes agrupadas abaixo pra evitar drift.
 */
.hero-month-arrow,
.hero-month-today,
.period-nav-arrow,
.period-nav-today {
    --pico-form-element-spacing-vertical: var(--space-2xs);
    --pico-form-element-spacing-horizontal: var(--space-sm);
}

.hero-month-arrow {
    margin: 0;
}

.hero-month-trigger {
    appearance: none;
    margin: 0;
    padding: var(--space-2xs) var(--space-sm);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: rgba(255, 255, 255, 0.85);
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    width: auto;
    min-height: 1.875rem;
    line-height: 1.2;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    transition: border-color 120ms, background-color 120ms, color 120ms;
}

.hero-month-trigger:hover {
    border-color: rgba(255, 255, 255, 0.4);
    color: var(--color-white);
}

.hero-month-trigger[aria-expanded="true"] {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.4);
    color: var(--color-white);
}

.hero-month-caret {
    color: currentColor;
    opacity: 0.7;
    vertical-align: middle;
}

.hero-month-today {
    margin: 0;
    margin-left: var(--space-xs);
    font-size: 0.875rem;
}

.hero-balance-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--space-sm);
}

/*
 * Pattern de popover-card (compartilhado por month-popover e
 * datepicker-popover): fundo branco em radius-md, border-soft, shadow
 * semântica e position:absolute ancorado no trigger. Cada instância
 * ajusta padding e shadow conforme o peso visual (month-popover usa
 * shadow-lg porque carrega grid 4x3; datepicker-popover usa
 * shadow-popover, mais leve). Não foi extraído pra base class porque
 * só são 2 casos e ajustes locais são fáceis de seguir.
 */
.month-popover {
    position: absolute;
    top: calc(100% - var(--space-sm));
    right: var(--space-md);
    background: var(--color-card);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-md);
    box-shadow: var(--shadow-lg);
    z-index: 20;
    min-width: 280px;
}

.month-popover[hidden] { display: none; }

.month-popover-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-sm);
}

.month-popover-year {
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-text);
}

.month-popover-year-nav {
    appearance: none;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    width: 28px;
    height: 28px;
    cursor: pointer;
    color: var(--color-text-soft);
    margin: 0;
    padding: 0;
    line-height: 1;
}

.month-popover-year-nav:hover {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.month-popover-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-2xs);
}

.month-popover-cell {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: var(--space-xs) var(--space-sm);
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text);
    margin: 0;
    text-align: center;
    transition: background-color 120ms, border-color 120ms;
}

.month-popover-cell:hover {
    background: var(--color-neutral-50);
    border-color: var(--color-border);
}

.month-popover-cell.is-today {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.month-popover-cell.is-selected {
    background: var(--color-primary-700);
    color: var(--color-white);
    border-color: var(--color-primary-700);
}

.hero-balance-amount {
    font-size: 2.25rem;
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -0.01em;
}

.hero-balance a[role="button"].outline {
    --pico-primary: rgba(255, 255, 255, 0.6);
    --pico-primary-hover: var(--color-white);
    --pico-primary-border: rgba(255, 255, 255, 0.6);
    --pico-primary-hover-border: var(--color-white);
    color: var(--color-white);
}

/*
 * Botão branco em cima de fundo brand (hero-balance). Setamos os
 * --pico-* locais ao invés de usar !important: o PicoCSS resolve as
 * cores via essas vars, então sobrescrevê-las no escopo do botão é
 * suficiente pra vencer a cascata sem armadilhas.
 */
.hero-balance-cta {
    margin: 0;
    --pico-primary-background:   var(--color-white);
    --pico-primary-border:       var(--color-white);
    --pico-primary-inverse:      var(--color-primary-700);
    --pico-primary-hover-background: var(--color-neutral-50);
    --pico-primary-hover-border:     var(--color-neutral-50);
    --pico-primary-hover-underline:  var(--color-primary-700);
}


@media (max-width: 575.98px) {
    .hero-balance { padding: var(--space-md); }
    .hero-balance-amount { font-size: 1.875rem; }
    .hero-balance-actions { justify-content: stretch; }
    .hero-balance-cta {
        flex-basis: 100%;
        text-align: center;
    }
    /*
     * Em mobile o label do hero ("Saldo disponível") empilha acima da
     * navegação de mês. Em viewports apertados (360px) row + space-between
     * fazia o arrow direito quebrar pra uma nova linha sozinho. Empilhar
     * mantém os três botões da nav sempre alinhados horizontalmente.
     */
    .hero-balance-top {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-sm);
    }
    .hero-month-nav { flex-wrap: nowrap; }
}

.month-picker {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: var(--space-md);
    margin: 0;
}

.month-picker .month-label {
    font-family: var(--font-sans);
    font-weight: 600;
    font-size: 1rem;
    text-transform: capitalize;
    min-width: 11ch;
    text-align: center;
}

.month-picker a[role="button"] {
    --pico-form-element-spacing-vertical: var(--space-xs);
    --pico-form-element-spacing-horizontal: var(--space-md);
    margin: 0;
}

.month-picker .month-today {
    font-size: 0.875rem;
}


/* Saldos do dashboard — linha inteira clicável com ícone à esquerda ======= */

.account-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-sm);
}

.account-list > li {
    list-style: none;
}

.account-row {
    background: var(--color-card);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-md);
    display: grid;
    grid-template-columns: auto 1fr auto;
    column-gap: var(--space-md);
    row-gap: var(--space-2xs);
    align-items: center;
    color: inherit;
    text-decoration: none;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}

a.account-row:hover,
a.account-row:focus-visible {
    background: var(--color-primary-100);
    border-color: var(--color-primary-700);
    text-decoration: none;
}

.account-row-static {
    cursor: default;
    opacity: 0.75;
    border-style: dashed;
    background: transparent;
}

.archived-badge {
    display: inline-block;
    margin-left: var(--space-xs);
    padding: 0.125rem 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--color-neutral-200);
    color: var(--color-text-soft);
    font-size: 0.75rem;
    font-weight: var(--font-weight-label);
    text-transform: lowercase;
    letter-spacing: 0.02em;
    vertical-align: middle;
}

.account-row-icon {
    grid-row: 1 / span 2;
    grid-column: 1;
    color: var(--color-text-soft);
    display: inline-flex;
    align-items: center;
}

.account-row-name {
    grid-row: 1;
    grid-column: 2;
    font-weight: 500;
}

.account-row-balance {
    grid-row: 1;
    grid-column: 3;
    text-align: right;
    font-weight: 500;
}

.account-row-meta {
    grid-row: 2;
    grid-column: 2;
    font-size: 0.875rem;
    color: var(--color-text-muted);
}

.account-row-forecast {
    grid-row: 2;
    grid-column: 3;
    text-align: right;
    font-size: 0.875rem;
    color: var(--color-text-muted);
}

/*
 * Em mobile a coluna 3 com "saldo previsto em 31/05: R$ ..." competia
 * com nome/tipo da conta e quebrava em múltiplas linhas, criando confusão
 * visual. Escondemos o forecast em <sm; segue acessível na tela de
 * detalhe da conta.
 */
@media (max-width: 575.98px) {
    .account-row-forecast { display: none; }
}


/* Badges de urgência de fatura (UX-3.3/UX-2.4) ============================ */

.invoice-badge {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.3;
    text-transform: lowercase;
    letter-spacing: 0.01em;
    border: 1px solid transparent;
}

.invoice-badge-overdue {
    background: color-mix(in srgb, var(--color-danger, #c0392b) 12%, transparent);
    color: var(--color-danger, #c0392b);
    border-color: color-mix(in srgb, var(--color-danger, #c0392b) 30%, transparent);
}

.invoice-badge-today {
    background: color-mix(in srgb, var(--color-warning, #d97706) 14%, transparent);
    color: var(--color-warning, #d97706);
    border-color: color-mix(in srgb, var(--color-warning, #d97706) 32%, transparent);
}

.invoice-badge-tomorrow {
    background: color-mix(in srgb, var(--color-warning, #d97706) 10%, transparent);
    color: var(--color-warning, #d97706);
    border-color: color-mix(in srgb, var(--color-warning, #d97706) 25%, transparent);
}

.invoice-badge-soon {
    background: color-mix(in srgb, var(--color-text-muted) 10%, transparent);
    color: var(--color-text-muted);
    border-color: color-mix(in srgb, var(--color-text-muted) 22%, transparent);
}

.invoice-due-date {
    display: inline-block;
    margin-left: 0.375rem;
    font-size: 0.8rem;
    color: var(--color-text-muted);
}

.invoice-row-overdue .account-row-name {
    color: var(--color-danger, #c0392b);
}


/* Seções do dashboard ==================================================== */

.section + .section {
    margin-top: var(--space-section);
}

.section h2 {
    margin-bottom: var(--space-sm);
}


/* Form de novo lançamento (kind pills) ==================================== */

.kind-pills {
    display: flex;
    gap: var(--space-xs);
    border: none;
    padding: 0;
    margin: 0 0 var(--space-md);
}

.kind-pill {
    flex: 1;
    text-align: center;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md, 8px);
    padding: var(--space-sm) var(--space-md);
    cursor: pointer;
    user-select: none;
    font-size: 1rem;
    font-weight: 500;
    color: var(--color-text);
    transition: background-color 120ms, border-color 120ms;
}

.kind-pill input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.kind-pill:hover { border-color: var(--color-text); }

/*
 * Cores semânticas:
 *   EXPENSE  → danger  (saída de dinheiro)
 *   INCOME   → success (entrada)
 *   TRANSFER → primary (neutro, preserva marca)
 *
 * Inset box-shadow + cor de borda no mesmo tom semântico engrossa a
 * borda do selecionado sem causar layout shift.
 */
.kind-pill:has(input[value="EXPENSE"]:checked) {
    background-color: var(--color-danger);
    border-color: var(--color-danger);
    color: var(--color-white);
    box-shadow: inset 0 0 0 1px var(--color-danger);
}

.kind-pill:has(input[value="INCOME"]:checked) {
    background-color: var(--color-success);
    border-color: var(--color-success);
    color: var(--color-white);
    box-shadow: inset 0 0 0 1px var(--color-success);
}

.kind-pill:has(input[value="TRANSFER"]:checked) {
    background-color: var(--color-lavender);
    border-color: var(--color-lavender);
    color: var(--color-white);
    box-shadow: inset 0 0 0 1px var(--color-lavender);
}

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

[data-kind-section][hidden],
[data-period-section][hidden],
[data-repeat-section][hidden],
[data-end-kind-section][hidden] { display: none !important; }

.repeat-block {
    margin-top: var(--space-md);
}

.repeat-block fieldset {
    margin-top: var(--space-sm);
}

.end-kind-option {
    display: inline-flex;
    gap: var(--space-xs);
    align-items: center;
    margin-right: var(--space-md);
}

.transfer-icon {
    display: inline-block;
    color: var(--color-text-soft);
    font-size: 13px;
    margin-right: 2px;
}

.recurrence-icon {
    display: inline-block;
    margin-left: var(--space-xs);
    color: var(--color-text-muted);
    font-size: 13px;
    line-height: 1;
}


/* Page header e empty state (genéricos) ==================================== */

.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    flex-wrap: wrap;
    margin-bottom: var(--space-md);
}

.page-header > h2 { margin: 0; }

.page-header-cta { margin: 0; }

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-sm);
    padding: var(--space-xl) var(--space-md);
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-card);
}

.empty-state-icon {
    color: var(--color-text-muted);
    margin-bottom: var(--space-xs);
}

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

.empty-state-desc {
    margin: 0;
    font-size: 0.875rem;
    color: var(--color-text-soft);
    max-width: 36ch;
}

.empty-state-cta {
    margin-top: var(--space-sm);
}

/* Breadcrumbs (UX-2.7) ==================================================== */

.breadcrumbs {
    margin-bottom: var(--space-md);
    font-size: 0.8125rem;
    line-height: 1;
    color: var(--color-text-muted);
}

.breadcrumbs ol {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
}

.breadcrumbs li {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.breadcrumbs li + li::before {
    content: '/';
    color: var(--color-text-muted);
    opacity: 0.5;
    font-weight: 300;
    margin-inline: 2px;
}

.breadcrumbs a {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 9px;
    border-radius: 999px;
    color: var(--color-text-soft);
    text-decoration: none;
    transition: background-color 120ms ease, color 120ms ease;
}

.breadcrumbs a:hover {
    color: var(--color-text);
    background: var(--color-neutral-50);
}

.breadcrumbs-home {
    color: var(--color-primary);
}

.breadcrumbs [aria-current='page'] {
    padding: 5px 9px;
    color: var(--color-text);
    font-weight: 600;
    background: var(--color-neutral-50);
    border-radius: 999px;
}


/* Variante inline pra empty states secundários (ex: subseção sem itens). */
.empty-state-inline {
    padding: var(--space-md);
    gap: var(--space-xs);
}

.empty-state-inline .empty-state-desc {
    max-width: none;
}

.empty-state-inline .empty-state-cta {
    margin-top: var(--space-xs);
}


/* Listagem de transações ================================================== */

.transaction-filters {
    margin-bottom: var(--space-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}


/* Filtro de período por chips ============================================= */

.filter-chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 3px;
    margin: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    background: var(--color-card);
    align-self: flex-start;
    max-width: 100%;
}

.filter-chip {
    margin: 0;
    padding: 0;
    cursor: pointer;
    user-select: none;
}

.filter-chip input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 1px;
    height: 1px;
}

.filter-chip > span {
    display: inline-block;
    padding: 6px 14px;
    min-width: 3.5ch;
    text-align: center;
    border-radius: var(--radius-pill);
    font-size: 13px;
    font-weight: 500;
    color: var(--color-text-soft);
    line-height: 1;
    transition: background-color 120ms, color 120ms, box-shadow 120ms;
}

.filter-chip:hover > span {
    background: var(--color-neutral-50);
    color: var(--color-text);
}

.filter-chip:has(input:checked) > span {
    background: var(--color-primary-700);
    color: var(--color-white);
    box-shadow: var(--shadow-sm);
}

.filter-chip:has(input:checked):hover > span {
    background: var(--color-primary-500);
}

.filter-chip:focus-within > span {
    outline: 2px solid var(--color-primary-100);
    outline-offset: 2px;
}

/*
 * Em mobile os chips de grupo (3-4 chips) ficam num grid 4-col pra
 * distribuir o espaço uniformemente — wrap natural ficava 3+1 feio.
 */
@media (max-width: 575.98px) {
    .filter-chips[data-group-chips] {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        width: 100%;
    }
    .filter-chips[data-group-chips] .filter-chip > span {
        display: block;
        text-align: center;
        padding-left: var(--space-sm);
        padding-right: var(--space-sm);
    }
}

/*
 * Versão compacta do filtro de período pra viewports estreitos:
 * uma pílula com o período ativo + chevron, que abre um popover
 * listando os 9 períodos. Visualmente coerente com os chips, mas
 * ocupa só uma linha. Em desktop (>= 768px), os chips assumem.
 */
.filter-period-compact {
    display: none;
    align-items: center;
    gap: var(--space-2xs);
    flex-wrap: wrap;
}

@media (max-width: 767.98px) {
    .filter-chips[data-period-chips] {
        display: none;
    }
    .filter-period-compact {
        display: inline-flex;
    }
}

.filter-period-pill-wrapper {
    position: relative;
}

/*
 * Pill (filtro rápido) e chips extras (Mês/Ano) compartilham o mesmo
 * visual base. Apenas o modo ativo (matching o period mode atual) fica
 * filled — os outros ficam outline pra dar hierarquia.
 */
.filter-period-pill,
.filter-period-extra {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: transparent;
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    padding: 6px 14px;
    margin: 0;
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
}

.filter-period-pill:hover,
.filter-period-extra:hover {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.filter-period-pill:focus-visible,
.filter-period-extra:focus-visible {
    outline: 2px solid var(--color-primary-100);
    outline-offset: 2px;
}

.filter-period-pill.is-active,
.filter-period-extra.is-active {
    background: var(--color-primary-700);
    color: var(--color-white);
    border-color: var(--color-primary-700);
}

.filter-period-pill.is-active:hover,
.filter-period-extra.is-active:hover {
    background: var(--color-primary-500);
    border-color: var(--color-primary-500);
    color: var(--color-white);
}

.filter-period-pill-caret {
    transition: transform 150ms;
}

.filter-period-pill[aria-expanded="true"] .filter-period-pill-caret {
    transform: rotate(180deg);
}

.filter-period-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 50;
    min-width: 160px;
    padding: 6px;
    background: var(--color-card);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.filter-period-menu[hidden] {
    display: none;
}

.filter-period-option {
    appearance: none;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    padding: 8px 12px;
    margin: 0;
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 500;
    color: var(--color-text);
    text-align: left;
    line-height: 1.2;
}

.filter-period-option:hover {
    background: var(--color-neutral-50);
    color: var(--color-text);
}

.filter-period-option.is-selected {
    background: var(--color-primary-50);
    color: var(--color-primary-700);
}

.filter-aux {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-sm);
}

.filter-aux[hidden] { display: none !important; }

.filter-aux-nav {
    position: relative;
    align-items: center;
}

.period-nav {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
}

.period-nav-arrow {
    margin: 0;
    color: var(--color-text-soft);
    border-color: var(--color-border);
    line-height: 1;
}

.period-nav-arrow:hover {
    color: var(--color-primary-700);
    border-color: var(--color-primary-700);
}

.period-nav-trigger {
    appearance: none;
    margin: 0;
    padding: var(--space-2xs) var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-card);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    width: auto;
    min-height: auto;
    line-height: 1.2;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    transition: border-color 120ms, background-color 120ms, color 120ms;
}

.period-nav-trigger:hover {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.period-nav-trigger[aria-expanded="true"] {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.period-nav-caret {
    color: var(--color-text-soft);
    vertical-align: middle;
}

.period-nav-today {
    margin: 0;
    margin-left: var(--space-xs);
    font-size: 0.75rem;
}

.filter-aux-nav .month-popover {
    top: calc(100% + var(--space-2xs));
    left: 0;
    right: auto;
}

.filter-aux label {
    /* Tipografia base vem do bloco .label-secondary. Aqui só zera o
       margin-bottom porque .filter-aux usa flex-direction:column gap. */
    margin: 0;
}

.filter-aux input[type="month"],
.filter-aux input[type="number"],
.filter-aux input[type="date"] {
    margin-bottom: 0;
}

.filter-aux .filter-aux-error {
    align-self: center;
    font-size: 12px;
    color: var(--color-danger, #c44);
}

.filter-fields {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm) var(--space-md);
    align-items: flex-end;
}

.filter-fields label {
    flex: 1 1 180px;
    min-width: 160px;
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--color-text-soft);
}

.filter-fields .filter-search {
    flex: 1 1 220px;
}

.filter-fields select,
.filter-fields input {
    margin-bottom: 0;
}

/*
 * Altura fixa nos controles dos filtros garante alinhamento entre o
 * input de busca (UA-styled) e os combobox-buttons enhanced. Sem isso,
 * o Pico calcula height baseado em 1rem (17px raiz), ignorando o
 * font-size 13px local, e o search fica mais alto que o combobox.
 */
.filter-fields .combobox-button {
    box-sizing: border-box;
    height: var(--control-height-sm);
    min-height: 0;
}

/*
 * Filter-search é um wrapper custom (não usa <input type=search>) pra ter
 * controle total sobre lupa e botão clear. Resolve dois problemas do UA
 * nativo: colisão de ícones quando o input fica curto, e cursor errado
 * no botão de limpar.
 */
.filter-fields .filter-search-input {
    position: relative;
    display: flex;
    align-items: center;
}

.filter-fields .filter-search-input > input {
    box-sizing: border-box;
    width: 100%;
    height: var(--control-height-sm);
    min-height: 0;
    margin: 0;
    padding: 0 1.75rem;
    font: inherit;
    line-height: 1.4;
    border-radius: var(--radius-md);
}

.filter-search-icon {
    position: absolute;
    left: var(--space-sm);
    color: var(--color-text-soft);
    pointer-events: none;
}

.filter-search-clear {
    position: absolute;
    right: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--color-text-soft);
    cursor: pointer;
}

.filter-search-clear:hover {
    background: var(--color-border-soft);
    color: var(--color-text);
}

.filter-search-clear[hidden] {
    display: none;
}

.filter-actions {
    display: flex;
    gap: var(--space-sm);
    align-items: center;
}

.filter-clear {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    padding: 6px 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--color-text-soft);
    font-size: 13px;
    line-height: 1.2;
    text-decoration: none;
    transition: background-color 120ms, color 120ms, border-color 120ms, box-shadow 120ms;
}

.filter-clear:hover {
    background: var(--color-primary-100);
    color: var(--color-primary-700);
    border-color: var(--color-primary-300);
    box-shadow: var(--shadow-sm);
}

.filter-clear-icon {
    display: block;
    flex-shrink: 0;
    margin-top: -1px;
}


.transaction-list {
    list-style: none;
    padding: 0;
    margin: var(--space-md) 0;
}

.transaction-list-card {
    background: var(--color-card);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-lg);
    margin: var(--space-md) 0;
}

.transaction-list-header {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-md);
    margin: 0 0 var(--space-2xs);
    min-height: 40px;
}

.transaction-select-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    background: transparent;
    border: 1px solid var(--color-border);
    color: var(--color-text-soft);
    border-radius: var(--radius-sm);
    padding: 4px 12px;
    font-size: 13px;
    cursor: pointer;
}

.transaction-select-toggle:hover {
    border-color: var(--color-primary-700);
    color: var(--color-text);
}

/* Grid mobile-first ======================================================
 * `<ul.transaction-list>` é o grid container; cada `<li.transaction-row>`
 * usa `display: contents` pra que todas as células compartilhem as
 * mesmas column tracks. Garante alinhamento vertical perfeito mesmo
 * quando valores ou descrições têm tamanhos diferentes.
 *
 * Mobile (default): data | swatch (avatar 28px) | descrição | valor.
 * Desktop (≥768px): data | categoria (160px) | meta-icon (22px)
 *                   | descrição | conta (240px) | valor (130px).
 *
 * Em modo seleção, uma coluna a mais entra no início pro checkbox.
 *
 * Borda inferior: span dedicado `<span.transaction-row-sep>` por linha,
 * grid-column 1/-1, 1px. Bordas por-célula quebravam nos column gaps.
 */
.transaction-list {
    display: grid;
    grid-template-columns: auto 1fr auto;
    column-gap: var(--space-sm);
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
}

.transaction-list.is-selecting {
    grid-template-columns: auto auto 1fr auto;
}

.transaction-date {
    display: none;
}

.transaction-row {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    grid-template-rows: auto auto;
    align-items: center;
}

.transaction-row > *:not(.transaction-row-sep) {
    grid-row: 1;
}

.transaction-row > * {
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
    min-height: 48px;
    box-sizing: border-box;
}

.transaction-row-sep {
    grid-column: 1 / -1;
    grid-row: 2;
    height: 1px;
    background: var(--color-border);
    padding: 0;
    min-height: 0;
    display: block;
}

.transaction-row:last-of-type .transaction-row-sep {
    display: none;
}

.transaction-select-cell {
    display: none;
    align-items: center;
    justify-content: center;
}

.transaction-list.is-selecting .transaction-select-cell {
    display: flex;
}

.transaction-select-checkbox {
    margin: 0;
    width: 16px;
    height: 16px;
    cursor: pointer;
}

/* Mobile (default): apenas o swatch-cell aparece; cat-cell, meta-cell e
 * account-cell ficam ocultas. No desktop esses 3 cells aparecem nas
 * tracks dedicadas e o swatch-cell some. */
.transaction-swatch-cell {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.transaction-cat-cell,
.transaction-meta-cell,
.transaction-account-cell {
    display: none;
}

/* Highlight de seleção: como o `<li>` tem display:contents, o background
 * precisa pintar todas as células filhas. */
.transaction-row.is-selected {
    background: color-mix(in srgb, var(--color-primary-500) 7%, transparent);
}

/* Transferência: descrição e valor em tom soft. Sem italic, sem
 * background, sem ajuste de fonte — segue alinhamento normal. */
.transaction-row.is-transfer .transaction-description-text {
    color: var(--color-text-soft);
}

.transaction-row.is-transfer .transaction-amount {
    color: var(--color-text-soft);
}

.transaction-group {
    grid-column: 1 / -1;
    list-style: none;
    margin: 0;
    padding: var(--space-sm) var(--space-md);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-md);
}

.transaction-group-label {
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-soft);
}

.transaction-group-footer {
    grid-column: 1 / -1;
    list-style: none;
    margin: 0;
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: var(--space-md);
    padding: var(--space-2xs) var(--space-md) var(--space-sm);
    border-bottom: 1px dashed var(--color-border);
}

.transaction-group-footer-label {
    font-size: 0.75rem;
    color: var(--color-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 500;
}

.transaction-group-footer-total {
    font-size: 0.9rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.transaction-group-footer-total.is-inflow {
    color: var(--color-success, var(--color-accent, var(--color-text)));
}

.transaction-group-footer-total.is-outflow {
    color: var(--color-text);
}

.transaction-group-footer-top {
    margin-bottom: var(--space-md);
    padding-top: var(--space-sm);
    background: color-mix(in srgb, var(--color-primary-500) 5%, transparent);
    border-radius: var(--radius-sm);
    border-bottom: none;
}

.transaction-group-footer-top .transaction-group-footer-label {
    color: var(--color-primary-700);
    font-size: 0.85rem;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
}

.transaction-group-footer-top .transaction-group-footer-total {
    font-size: 1rem;
}

.transaction-group-footer-parent {
    margin-bottom: var(--space-sm);
    padding-top: var(--space-xs);
    background: color-mix(in srgb, var(--color-primary-500) 4%, transparent);
    border-radius: var(--radius-sm);
    border-bottom: none;
}

.transaction-group-footer-parent .transaction-group-footer-label {
    color: var(--color-primary-700);
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
}

.transaction-group-top,
.transaction-group-parent {
    background: color-mix(in srgb, var(--color-primary-500) 5%, transparent);
    border-radius: var(--radius-sm);
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
    margin-top: var(--space-md);
    margin-bottom: var(--space-2xs);
}

.transaction-group-top .transaction-group-label,
.transaction-group-parent .transaction-group-label {
    color: var(--color-primary-700);
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: capitalize;
}

.transaction-group:first-child {
    margin-top: 0;
}

.transaction-group-child {
    padding-top: var(--space-md);
    padding-bottom: var(--space-2xs);
    padding-left: var(--space-lg);
}

.transaction-group-child .transaction-group-label {
    color: var(--color-primary-700);
    font-size: 0.8rem;
    letter-spacing: 0.05em;
}

.filter-group-row {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    align-self: flex-start;
}

.filter-group-row-label {
    /* Tipografia base vem do bloco .label-secondary. flex-shrink evita
       que o label encolha quando o group cresce. */
    flex-shrink: 0;
}

.transaction-date {
    align-items: center;
    color: var(--color-text-muted);
    font-size: 13px;
    min-width: 36px;
    font-variant-numeric: tabular-nums;
}

/* Avatar de categoria (mobile): círculo 28x28 com a cor da categoria como
 * background suave e o ícone Lucide centralizado. Substitui o swatch antigo
 * (12x12) por algo legível sem chip, já que a chip de categoria some no
 * mobile e o usuário precisa de algum hint visual da categoria. */
.transaction-cat-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 55%, transparent);
    color: color-mix(in srgb, var(--cat-color, var(--color-neutral-600)) 100%, black 20%);
    flex-shrink: 0;
}

.transaction-cat-avatar svg { width: 14px; height: 14px; }

.transaction-cat-avatar.is-transfer {
    background: color-mix(in srgb, var(--color-neutral-50) 65%, var(--color-neutral-200));
    border-color: var(--color-border);
    color: var(--color-text-soft);
}

/* Avatar clicável (link de filtro): mostra affordance via cursor + hover/focus.
 * UX-1.6: clicar no avatar filtra a lista pela categoria correspondente,
 * preservando os demais filtros ativos. */
a.transaction-cat-avatar.is-clickable {
    cursor: pointer;
    text-decoration: none;
    transition: transform 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}

a.transaction-cat-avatar.is-clickable:hover {
    border-color: color-mix(in srgb, var(--cat-color, var(--color-neutral-400)) 85%, transparent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--cat-color, var(--color-neutral-300)) 25%, transparent);
    transform: scale(1.05);
}

a.transaction-cat-avatar.is-clickable:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}

.transaction-description {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 3px;
    min-width: 0;
}

.transaction-description-line {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    min-width: 0;
    max-width: 100%;
}

.transaction-description-text {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Linha secundária só no mobile, usada pra mostrar a rota
 * "conta-origem → conta-destino" em transferências quando a célula de conta
 * está oculta. No desktop a célula de conta resolve isso, então a sub some. */
.transaction-description-sub {
    display: none;
    font-size: 11px;
    color: var(--color-text-muted);
    font-style: italic;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.transaction-description-sub .arrow { margin: 0 3px; }

/* Meta da descrição no mobile: "Categoria · Conta" abaixo do texto principal.
 * Substitui as células dedicadas que ficam ocultas no mobile. No desktop some
 * porque cat-cell e account-cell entregam a info em colunas próprias. */
.transaction-description-meta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--color-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.transaction-description-meta-cat,
.transaction-description-meta-acc {
    overflow: hidden;
    text-overflow: ellipsis;
}

.transaction-description-meta-sep {
    opacity: 0.55;
}

/* Header de dia, visível só no mobile. Ocupa a row inteira do grid,
 * separa visualmente blocos de lançamentos por data. */
.transaction-day-header {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: var(--space-md) 0 var(--space-2xs);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--space-2xs);
}

.transaction-day-header:first-child {
    padding-top: 0;
}

.transaction-day-header-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Meta icon do desktop: pill 20×20 com tom primary, dentro do slot 22px.
 * Aparece nas linhas que têm is_fixed ou is_installment. */
.transaction-meta-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: var(--radius-pill);
    color: var(--color-primary-700);
    background: color-mix(in srgb, var(--color-primary-500) 12%, transparent);
    flex-shrink: 0;
}

.transaction-meta-icon svg { width: 12px; height: 12px; }

/* Versão inline (mobile): pílula menor entra na linha da descrição, antes
 * do texto. No desktop fica escondida porque o meta-cell dedicado assume. */
.transaction-meta-inline {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: var(--radius-pill);
    color: var(--color-primary-700);
    background: color-mix(in srgb, var(--color-primary-500) 12%, transparent);
    flex-shrink: 0;
}

.transaction-meta-inline svg { width: 10px; height: 10px; }

/* Account-pair (transferência no desktop): mostra origem e destino lado a
 * lado dentro da célula de conta. Pílulas menores pra caber nas 240px. */
.account-pair {
    display: none;
    align-items: center;
    gap: 4px;
    min-width: 0;
    max-width: 100%;
    flex-wrap: nowrap;
}

.account-pair .arrow {
    color: var(--color-text-muted);
    font-size: 12px;
    flex-shrink: 0;
}

.account-pair .account-pill {
    background: color-mix(in srgb, var(--color-neutral-50) 65%, var(--color-neutral-200));
    flex: 1 1 0;
    min-width: 0;
}

.transaction-cat-cell .cat-chip {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Edição inline: o chip/pill em si é clicável, não a célula toda. */
.transaction-row[data-tx-editable='true'] [data-tx-edit] {
    cursor: pointer;
    transition: background-color 0.1s ease-out, border-color 0.1s ease-out;
}

/* Categoria: acende background usando a cor da categoria. */
.transaction-row[data-tx-editable='true'] .cat-chip[data-tx-edit]:hover {
    background: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 40%, transparent);
    border-color: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 75%, transparent);
}

/* Conta corrente: acende como pill primário. */
.transaction-row[data-tx-editable='true'] .account-pill[data-tx-edit]:hover {
    color: var(--color-primary-700);
    background: color-mix(in srgb, var(--color-primary-500) 12%, transparent);
    border-color: color-mix(in srgb, var(--color-primary-500) 35%, transparent);
}

.transaction-row.is-locked [data-tx-edit] {
    cursor: default;
}

/* Affordance de linha não-editável (UX-2.1).
 *
 * Transferências e lançamentos de fatura (cartão de crédito) não podem ter
 * categoria/conta editadas inline. Antes o único sinal era o checkbox sumir;
 * pra reforçar visualmente, chips e pills ficam num tom drained (saturação
 * mais baixa) e a borda perde contraste — o usuário lê de relance que "essa
 * linha não responde a clique".
 */
.transaction-row.is-locked .cat-chip,
.transaction-row.is-locked .account-pill {
    opacity: 0.7;
    border-style: dashed;
}

.transaction-row.is-locked .transaction-cat-avatar:not(.is-clickable) {
    opacity: 0.7;
}

.account-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px;
    border-radius: var(--radius-pill);
    font-size: 11px;
    line-height: 1.4;
    color: var(--color-text-muted);
    background: color-mix(in srgb, var(--color-neutral-50) 65%, var(--color-neutral-200));
    border: 1px solid var(--color-border);
    max-width: 100%;
    min-width: 0;
}

.account-pill.is-credit-card {
    color: var(--color-primary-700);
    background: color-mix(in srgb, var(--color-primary-500) 8%, transparent);
    border-color: color-mix(in srgb, var(--color-primary-500) 30%, transparent);
}

.account-pill-icon {
    flex-shrink: 0;
    opacity: 0.75;
}

.account-pill-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.transaction-amount {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    text-align: right;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.transaction-amount.is-inflow { color: var(--color-success, var(--color-accent, var(--color-text))); }

/* Desktop (≥960px): mantém o mesmo pattern do mobile — data como header
 * de seção (`.transaction-day-header` ocupando a row inteira) e descrição
 * protagonista — só que com colunas dedicadas pra dar máximo de contexto
 * em telas largas. A célula `.transaction-date` segue oculta, igual no
 * mobile; o que muda é que entram cat-cell, meta-cell e account-cell.
 *
 *   cat (160px) | meta (22px) | descrição (1fr) | conta (320px) | valor (110px)
 */
/* Breakpoint conservador: a soma mínima das 5 colunas (160+22+~120+320+110)
 * mais gaps fica em torno de 800px. Abaixo disso, o `1fr` da descrição
 * colapsa pra zero e a row vira o "estado intermediário" — desktop com
 * descrição sumida. Subir o breakpoint mantém o mobile até ter espaço real. */
@media (min-width: 960px) {
    .transaction-list {
        grid-template-columns: 160px 22px 1fr 320px 110px;
        column-gap: var(--space-md);
    }

    .transaction-list.is-selecting {
        grid-template-columns: auto 160px 22px 1fr 320px 110px;
    }

    .transaction-description-meta {
        display: none;
    }

    .transaction-swatch-cell {
        display: none;
    }

    .transaction-cat-cell,
    .transaction-account-cell {
        display: flex;
        align-items: center;
        justify-content: flex-start;
    }

    .transaction-meta-cell {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .transaction-meta-inline {
        display: none;
    }

    .transaction-description {
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
    }

    .transaction-description-sub {
        display: none;
    }

    .transaction-row.is-transfer .account-pair {
        display: inline-flex;
    }
}

/* Mobile: revela a linha sub quando a row pediu (transferências precisam
 * mostrar a rota conta→conta). */
@media (max-width: 959.98px) {
    .transaction-row.has-description-sub .transaction-description-sub {
        display: inline-flex;
    }
}


/* Chip de categoria ====================================================== */

.cat-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px 3px 6px;
    border-radius: var(--radius-pill);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
    color: var(--color-neutral-900);
    background: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 55%, transparent);
    max-width: 100%;
    min-width: 0;
}

/* Variante neutra: usada por transferência (sem categoria). Tom cinza claro
 * no fundo e na borda, ícone e texto em cor soft. */
.cat-chip.is-neutral {
    background: color-mix(in srgb, var(--color-neutral-50) 65%, var(--color-neutral-200));
    border-color: var(--color-border);
    color: var(--color-text-soft);
}

.cat-chip-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: color-mix(in srgb, var(--cat-color, var(--color-neutral-600)) 100%, black 20%);
}

.cat-chip.is-neutral .cat-chip-icon {
    color: var(--color-text-soft);
}

.cat-chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}


/* Lista de categorias (manage) =========================================== */

.category-list {
    list-style: none;
    padding: 0;
    margin: var(--space-sm) 0 var(--space-lg);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
}

.category-list > li {
    margin: 0;
    list-style: none;
}

.category-row {
    display: inline-flex;
    text-decoration: none;
}

.category-row .cat-chip {
    padding: 6px 14px;
    font-size: 13px;
    transition: transform 0.08s ease-out;
}

.category-row:hover .cat-chip {
    transform: translateY(-1px);
    background: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 32%, transparent);
}


/* Form de Category: preview ao vivo + pickers compactos ================== */

.category-form-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-md);
    margin: 0 0 var(--space-md);
    border-radius: var(--radius-md);
    background: var(--color-neutral-50);
    border: 1px dashed var(--color-border);
    min-height: 64px;
}

/* Cor e ícone como collapsibles: form curto por padrão, picker sob demanda */

.category-field-collapsible {
    margin: 0 0 var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    overflow: hidden;
}

.category-field-summary {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md);
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.category-field-summary::-webkit-details-marker { display: none; }

.category-field-summary::after {
    content: '';
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--color-text-soft);
    border-bottom: 2px solid var(--color-text-soft);
    transform: rotate(45deg) translateY(-2px);
    transition: transform 0.15s;
    margin-left: auto;
}

.category-field-collapsible[open] > .category-field-summary::after {
    transform: rotate(-135deg) translateY(2px);
}

.category-field-summary-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-text-soft);
    min-width: 56px;
}

.category-field-summary-value {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    font-size: 14px;
    color: var(--color-text);
}

.category-field-summary-color {
    width: 22px;
    height: 22px;
    border-radius: var(--radius-pill);
    background: var(--cat-color, var(--color-neutral-200));
    border: 1px solid color-mix(in srgb, var(--cat-color, var(--color-neutral-400)) 65%, transparent);
    flex-shrink: 0;
}

.category-field-summary-icon {
    width: 22px;
    height: 22px;
    color: var(--cat-color, var(--color-text-soft));
    flex-shrink: 0;
}

.category-field-body {
    padding: 0 var(--space-md) var(--space-md);
    border-top: 1px solid var(--color-border);
    padding-top: var(--space-md);
}

.category-form-preview .cat-chip {
    font-size: 16px;
    padding: 8px 16px 8px 12px;
    gap: 8px;
}

.category-form-preview .cat-chip-icon {
    width: 18px;
    height: 18px;
}

.category-form-preview-empty .cat-chip-text {
    color: var(--color-text-soft);
    font-style: italic;
}

/*
 * Campo de form padrão. Label compacto e soft em cima, input abaixo.
 * Define o look base de qualquer field — usado pelo partial _field.html
 * e por construções específicas (categoria, conta etc.) que precisam
 * de markup customizado mas mesma identidade visual.
 */

.field {
    margin: 0;
    /*
     * Altura unificada de todo controle visual do field (input, select,
     * textarea, .datepicker-trigger, .combobox-button). Casa com o que
     * o datepicker-trigger renderiza por construção e elimina a
     * divergência entre Valor/Data e similares no field-grid-2.
     */
    --field-control-height: 2.5rem;
}

label.field {
    display: block;
}

/*
 * Tipografia de labels — duas escalas documentadas:
 *
 *   .label-secondary (13px/600/text-soft):
 *     Forma compacta usada como rótulo "fixo" de form field (.field-label),
 *     legendas internas (.field > legend) e labels de toolbar/filtros
 *     (.filter-aux label, .filter-group-row-label). Cor soft pra ficar
 *     discreta em forms densos.
 *
 *   .repeat-row-label (1rem/500/text):
 *     Sub-label de seção dentro de um form (ex.: "Frequência" dentro do
 *     bloco "Repetir"). Mais alto e escuro pra demarcar sub-bloco.
 *
 *   .section-label (0.6875rem/500/uppercase/text-muted):
 *     Caption de seção (ex.: "Hoje" no dashboard). Uppercase + letter
 *     spacing pra contraste com o conteúdo.
 */
.label-secondary,
.field > legend,
.field-label,
.filter-aux label,
.filter-group-row-label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--color-text-soft);
    margin: 0 0 var(--space-2xs);
    padding: 0;
}

/*
 * Inputs/selects ficam com altura fixa pra garantir alinhamento com o
 * .datepicker-trigger (que aparece no lugar de inputs type=date) e com
 * outros controles enhanced via JS (combobox).
 * O Pico aplica margin-bottom 1rem por padrão, que zerar evita espaço
 * extra entre <label class="field"> consecutivos.
 */
.field > input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
.field > select {
    box-sizing: border-box;
    height: var(--field-control-height);
    min-height: 0;
    margin: 0;
    padding: 0 0.75rem;
    line-height: 1.4;
}

.field > textarea {
    box-sizing: border-box;
    min-height: var(--field-control-height);
    margin: 0;
    padding: 0.5rem 0.75rem;
    line-height: 1.4;
}

.field .datepicker-trigger,
.field .combobox-button {
    box-sizing: border-box;
    height: var(--field-control-height);
    padding: 0 0.75rem;
    /*
     * Zera margin-bottom que o Pico aplica em todo <button> (1rem). Sem
     * isso, a margin do trigger vaza pra fora do wrapper relative do
     * datepicker/combobox e infla a altura do label.field, fazendo o
     * gap pro próximo campo no .tx-form parecer ~32px enquanto o resto
     * fica em 16px.
     */
    margin: 0;
}

/* Picker de cor: grade de círculos coloridos ============================ */

.color-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(32px, 1fr));
    gap: var(--space-xs);
    margin: 0;
    width: 100%;
}

.color-picker-option {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    cursor: pointer;
    user-select: none;
    border-radius: var(--radius-pill);
    transition: transform 0.08s ease-out;
}

.color-picker-option:hover {
    transform: scale(1.08);
}

.color-picker-option input[type='radio'] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.color-picker-dot {
    width: 22px;
    height: 22px;
    border-radius: var(--radius-pill);
    background: var(--cat-color, var(--color-neutral-200));
    border: 1px solid color-mix(in srgb, var(--cat-color, var(--color-neutral-400)) 65%, transparent);
    transition: width 0.1s, height 0.1s;
}

.color-picker-option:has(input:checked) .color-picker-dot {
    width: 24px;
    height: 24px;
    box-shadow:
        0 0 0 2px var(--color-bg),
        0 0 0 3px var(--cat-color, var(--color-primary-700));
}

/* Picker de ícone: grade de tiles =====================================
 * Quando uma cor está selecionada via JS, o picker recebe --cat-color
 * inline e o ícone selecionado herda essa cor. */

.icon-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
    gap: var(--space-xs);
    margin: 0;
    width: 100%;
}

.icon-picker-option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-card);
    color: var(--color-text-soft);
    user-select: none;
    position: relative;
    transition: background-color 0.1s, border-color 0.1s, color 0.1s;
}

.icon-picker-option:hover {
    background: var(--color-neutral-50);
    border-color: var(--color-neutral-400);
    color: var(--color-neutral-900);
}

.icon-picker-option:has(input:checked) {
    background: color-mix(in srgb, var(--cat-color, var(--color-primary-500)) 18%, transparent);
    border-color: color-mix(in srgb, var(--cat-color, var(--color-primary-700)) 80%, transparent);
    color: color-mix(in srgb, var(--cat-color, var(--color-neutral-900)) 100%, black 25%);
}

.icon-picker-option input[type='radio'] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.icon-picker-swatch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}


/* Dropdown custom de categoria =========================================== */

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


/* Bar de ações em lote (inline no topo da lista) ========================= */

.transaction-bulk-bar {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-xs) var(--space-md);
    background: color-mix(in srgb, var(--color-primary-500) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-primary-500) 25%, transparent);
    border-radius: var(--radius-sm);
}

.transaction-bulk-bar[hidden] {
    display: none;
}

.transaction-bulk-bar-count {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-primary-700);
}

.transaction-bulk-bar-actions {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
}

.transaction-bulk-bar-action {
    background: var(--color-primary-700);
    color: white;
    border: none;
    border-radius: var(--radius-sm);
    padding: 6px 14px;
    font-size: 13px;
    cursor: pointer;
}

.transaction-bulk-bar-action:hover {
    filter: brightness(1.05);
}

.transaction-bulk-bar-action[disabled] {
    background: var(--color-neutral-200);
    cursor: not-allowed;
    filter: none;
}

.transaction-bulk-bar-cancel {
    background: transparent;
    border: 1px solid var(--color-border);
    color: var(--color-text-soft);
    border-radius: var(--radius-sm);
    padding: 6px 14px;
    font-size: 13px;
    cursor: pointer;
}

.transaction-bulk-bar-cancel:hover {
    color: var(--color-text);
    border-color: var(--color-text-soft);
}

@media (max-width: 768px) {
    .transaction-bulk-bar {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-sm);
    }
    .transaction-bulk-bar-count {
        text-align: center;
        font-size: 14px;
    }
    .transaction-bulk-bar-actions {
        justify-content: center;
    }
}


/* Tela auxiliar (sem app shell) ========================================== */

.standalone-shell {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-xl);
    text-align: center;
    gap: var(--space-md);
}

.standalone-shell .lockup {
    margin-bottom: var(--space-md);
}

.standalone-shell h1 {
    font-size: 28px;
    font-weight: 600;
    letter-spacing: -0.02em;
}

.standalone-shell p {
    color: var(--color-text-soft);
    max-width: 48ch;
}

.access-denied {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-md);
}

.access-denied-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-sm);
    margin-top: var(--space-sm);
}

.access-denied-logout-form {
    margin: 0;
}

.access-denied-logout-form button {
    margin: 0;
}

/*
 * Form de signup pós-Google (allauth socialaccount/signup.html).
 *
 * Vive dentro do .standalone-shell (centralizado, text-align center) mas
 * usa .tx-form pro look padrão. Sobrescreve text-align e capa em 360px
 * pra ficar com a mesma respiração da home de login (que só mostra o
 * botão "Entrar com Google" do mesmo tamanho).
 */
.signup-form {
    max-width: 360px;
    text-align: left;
    margin-top: var(--space-sm);
}

.signup-form .form-actions {
    flex-direction: row-reverse;
    justify-content: flex-end;
}


/* Botão "Entrar com Google" no login allauth =============================
 *
 * Segue o guia do Google (caixa branca, borda neutra, glifo colorido à
 * esquerda). Não usa `role=button` do Pico pra preservar o look "social".
 */

.login-google {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 10px 20px;
    background: white;
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    font-family: var(--font-sans);
    font-weight: 500;
    font-size: 15px;
    text-decoration: none;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 120ms ease, transform 120ms ease;
}

.login-google:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

.login-google-glyph {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}


/* Form unificado — coluna única ancorada à esquerda ======================
 *
 * Todos os forms (lançamento, contas, pagar fatura) usam .tx-form pra
 * ter a mesma respiração visual: container externo é container-wide
 * (ADR 0013 revisado), e a coluna interna fica capada em 720px e
 * ancorada à esquerda — alinha com o hero do dashboard e a lista de
 * transações. Sem esticar inputs em desktops largos.
 */

.tx-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    max-width: 720px;
    width: 100%;

    /*
     * Alinha altura/padding de inputs nativos com o .datepicker-trigger
     * (que renderiza no lugar de inputs type=date). Sem isso, inputs de
     * money/text ficam ~10px mais altos que o datepicker no field-grid-2.
     */
    --pico-form-element-spacing-vertical: 0.5rem;
    --pico-form-element-spacing-horizontal: 0.75rem;
    --pico-line-height: 1.4;
}

.tx-form > h2 {
    margin: 0;
}

.tx-form .field-grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-sm);
}

.tx-form .field-grid-2 > label {
    margin-bottom: 0;
}

/*
 * Dentro do .tx-form quem controla o espaçamento vertical é o `gap` do
 * próprio form (16px uniforme). Neutraliza margens de blocos auxiliares
 * que tinham margin própria histórica e somavam ao gap, criando
 * afastamentos inconsistentes entre campos.
 */
.tx-form > .kind-pills,
.tx-form > .form-errors,
.tx-form > .category-field-collapsible,
.tx-form > .repeat-block,
.tx-form > .form-actions {
    margin: 0;
}

.form-actions {
    display: flex;
    gap: var(--space-sm);
    margin-top: var(--space-md);
}

.form-actions > button,
.form-actions > a[role="button"] {
    flex: 1;
    margin: 0;
}

.tx-form .form-meta {
    color: var(--color-text-soft);
    margin: 0;
}

.tx-form .form-danger {
    margin-top: var(--space-md);
}

/*
 * Botão destrutivo com cor de marca danger. Usamos --pico-* locais em vez
 * de !important pra que o outline e hover sigam o sistema do Pico.
 *
 * Variante sólida (sem .outline): fundo danger, texto branco. Variante
 * outline (.outline.form-danger): borda e texto danger, fundo transparente —
 * passa a sólido no hover/focus.
 */
.form-danger {
    --pico-primary:                  var(--color-danger);
    --pico-primary-background:       var(--color-danger);
    --pico-primary-border:           var(--color-danger);
    --pico-primary-underline:        var(--color-danger);
    --pico-primary-hover:            var(--color-danger);
    --pico-primary-hover-background: var(--color-danger);
    --pico-primary-hover-border:     var(--color-danger);
    --pico-primary-hover-underline:  var(--color-danger);
    --pico-primary-focus:            rgba(181, 72, 58, 0.25);
    --pico-primary-inverse:          var(--color-white);
}

.outline.form-danger {
    color: var(--color-danger);
}

.outline.form-danger:hover,
.outline.form-danger:focus-visible {
    background: var(--color-danger);
    color: var(--color-white);
    border-color: var(--color-danger);
}

.account-type-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-sm);
}

.account-type-card {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.account-type-card:hover {
    border-color: var(--color-primary-700);
    background: var(--color-border-soft);
}

.account-type-card .icon {
    color: var(--color-primary-700);
    flex-shrink: 0;
}

.account-type-card strong {
    display: block;
    color: var(--color-text);
}

.account-type-card small {
    color: var(--color-text-soft);
}


/* Switch iOS ============================================================= */

.toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    background: var(--color-card);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-md);
}

.toggle-row-label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 1rem;
    font-weight: 500;
    color: var(--color-text);
}

.toggle-row-label small {
    color: var(--color-text-muted);
    font-size: 0.875rem;
    font-weight: 400;
}

.toggle-switch {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    margin: 0;
    flex-shrink: 0;
}

.toggle-switch input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 1px;
    height: 1px;
}

.toggle-track {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    background: var(--color-neutral-200);
    border-radius: var(--radius-pill);
    transition: background-color 150ms;
}

.toggle-thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 20px;
    height: 20px;
    background: var(--color-white);
    border-radius: 50%;
    box-shadow: var(--shadow-sm);
    transition: left 150ms;
}

.toggle-switch:has(input:checked) .toggle-track {
    background: var(--color-primary-700);
}

.toggle-switch:has(input:checked) .toggle-thumb {
    left: 22px;
}

.toggle-switch:focus-within .toggle-track {
    outline: 2px solid var(--color-primary-100);
    outline-offset: 2px;
}


/* Bloco de configuração da recorrência =================================== */

.repeat-config {
    margin-top: var(--space-sm);
    padding: var(--space-md);
    background: var(--color-card);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.repeat-row {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.repeat-row-label {
    font-size: 1rem;
    font-weight: 500;
    color: var(--color-text);
    margin-bottom: var(--space-xs);
}


/* Chips de frequência ==================================================== */

.freq-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    border: 0;
}

.freq-chips legend {
    padding: 0;
}

/*
 * .radio-pill: base unificada pra grupos de rádios renderizados como
 * pílulas independentes (cada pill com border próprio, sem container
 * segmented).
 *
 * Usado em:
 *   - Frequência (DAILY/WEEKLY/MONTHLY/...) no form de transação
 *   - Termina (NEVER/DATE/COUNT) no mesmo form
 *
 * Convenções diferentes vivem em classes próprias:
 *   - .filter-chip   variante segmented (vive dentro de border container)
 *   - .kind-pill     caso especial com cores semânticas por value
 *                    (EXPENSE/INCOME/TRANSFER) e flex:1 distribuído
 */
.radio-pill {
    margin: 0;
    cursor: pointer;
    user-select: none;
}

.radio-pill input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 1px;
    height: 1px;
}

.radio-pill > span {
    display: inline-block;
    padding: 0.4rem 0.8rem;
    border-radius: var(--radius-pill);
    border: 1px solid var(--color-border);
    background: var(--color-card);
    font-size: 0.875rem;
    font-weight: var(--font-weight-label);
    color: var(--color-text-soft);
    line-height: 1.2;
    transition: background-color 120ms, color 120ms, border-color 120ms;
}

.radio-pill:hover > span {
    border-color: var(--color-primary-700);
    color: var(--color-text);
}

.radio-pill:has(input:checked) > span {
    background: var(--color-primary-700);
    border-color: var(--color-primary-700);
    color: var(--color-white);
}

.radio-pill:focus-within > span {
    outline: 2px solid var(--color-primary-100);
    outline-offset: 2px;
}


/* Custom: a cada N <unidade> ============================================= */

.freq-custom {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    color: var(--color-text-soft);
    font-size: 0.875rem;
}

.freq-custom[hidden] { display: none !important; }

.freq-custom .freq-custom-interval {
    width: 80px;
    margin: 0;
}

.freq-custom .freq-custom-frequency {
    width: auto;
    margin: 0;
}


/* Termina (end_kind) — usa .radio-pill ==================================== */

.end-kind-group {
    margin: 0;
    padding: 0;
    border: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.end-kind-group legend {
    float: none;
    padding: 0;
    font-size: 1rem;
    font-weight: var(--font-weight-label);
    color: var(--color-text);
    margin-bottom: var(--space-xs);
}

.end-kind-group .end-kind-pills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
}


/* Grid de Ocorrências + Começar a partir da parcela ====================== */

.count-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-md);
    align-items: start;
}

.count-grid > label {
    margin: 0;
}


/* Toggle parcela / total ================================================= */

.amount-mode {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.amount-mode[hidden] { display: none !important; }

.amount-mode-toggle {
    display: inline-flex;
    background: var(--color-card);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    padding: 3px;
    gap: 2px;
    align-self: flex-start;
}

.amount-mode-toggle label {
    margin: 0;
    cursor: pointer;
    user-select: none;
}

.amount-mode-toggle input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 1px;
    height: 1px;
}

.amount-mode-toggle label > span {
    display: inline-block;
    padding: 0.35rem 0.8rem;
    border-radius: var(--radius-pill);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-soft);
    line-height: 1.2;
    transition: background-color 120ms, color 120ms;
}

.amount-mode-toggle label:has(input:checked) > span {
    background: var(--color-primary-700);
    color: var(--color-white);
}

.amount-mode-toggle label:focus-within > span {
    outline: 2px solid var(--color-primary-100);
    outline-offset: 2px;
}


/* Resumo e hint da recorrência =========================================== */

.recurrence-summary {
    margin: 0;
    font-size: 0.875rem;
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-feature-settings: "zero" 0;
    font-variant-numeric: normal;
    letter-spacing: 0;
    line-height: 1.4;
}

.recurrence-summary:empty { display: none; }

.recurrence-hint {
    display: block;
    margin-top: calc(-1 * var(--space-sm));
    margin-bottom: var(--space-xs);
    color: var(--color-text-muted);
    font-size: 0.875rem;
    font-family: var(--font-mono);
    font-feature-settings: "zero" 0;
    font-variant-numeric: normal;
}

.recurrence-hint[hidden] { display: none !important; }


/* Diálogo de 1 ocorrência ================================================ */

.single-occurrence-dialog,
.danger-zone {
    margin-top: var(--space-lg);
    padding: var(--space-md);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
    background: var(--color-card);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    max-width: 720px;
}

.danger-zone-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.danger-zone-title {
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--color-danger);
}

.danger-zone-desc {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--color-text-soft);
}

.danger-zone-action {
    flex-shrink: 0;
    margin: 0;
}

.archive-confirm-dialog {
    border: 0;
    padding: 0;
    background: transparent;
    max-width: 420px;
    width: calc(100% - 2 * var(--space-md));
}

.single-occurrence-dialog::backdrop,
.archive-confirm-dialog::backdrop {
    background: var(--overlay-bg);
}

.single-occurrence-dialog article,
.archive-confirm-dialog article {
    background: var(--color-card);
    border-radius: var(--radius-lg);
    padding: var(--space-lg);
    border: 1px solid var(--color-border-soft);
    box-shadow: var(--shadow-popover);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    margin: 0;
}

.single-occurrence-dialog h3,
.archive-confirm-dialog h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
}

.single-occurrence-dialog p,
.archive-confirm-dialog p {
    margin: 0;
    font-size: 0.875rem;
    color: var(--color-text-soft);
    line-height: 1.5;
}

.single-occurrence-dialog .form-actions,
.archive-confirm-dialog .form-actions {
    display: flex;
    gap: var(--space-sm);
    margin-top: var(--space-sm);
}

.single-occurrence-dialog .form-actions > button,
.archive-confirm-dialog .form-actions > button {
    flex: 1;
    margin: 0;
}

.archive-confirm-name {
    font-family: var(--font-mono, monospace);
    color: var(--color-danger);
    background: color-mix(in srgb, var(--color-danger) 12%, transparent);
    padding: 0 var(--space-2xs);
    border-radius: var(--radius-sm);
}

.archive-confirm-input {
    width: 100%;
    font-family: var(--font-mono, monospace);
}

.archive-confirm-actions {
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-md);
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
    background: var(--color-bg-soft, var(--color-card));
}

.archive-confirm-legend {
    font-size: 0.85rem;
    color: var(--color-text);
    padding: 0 var(--space-2xs);
    font-weight: 500;
}

.archive-confirm-action {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    font-size: 0.9rem;
    color: var(--color-text);
    cursor: pointer;
    padding: var(--space-2xs) 0;
    margin: 0;
}

.archive-confirm-action input[type='radio'] {
    margin: 0;
    flex-shrink: 0;
}

.archive-confirm-target {
    margin: var(--space-2xs) 0 var(--space-2xs) calc(1.25rem + var(--space-sm));
}

.archive-confirm-target select {
    margin: 0;
    width: 100%;
}

.archive-confirm-hint {
    font-size: 0.78rem !important;
    color: var(--color-text-soft) !important;
    margin-top: var(--space-2xs) !important;
    padding: 0;
}

.account-row-actions {
    display: flex;
    align-items: center;
    margin: 0;
    margin-left: auto;
}

.account-row-unarchive {
    margin: 0;
    padding: var(--space-2xs) var(--space-sm);
    font-size: 0.85rem;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
}

/* Combobox genérico ======================================================
 * Progressive enhancement em cima de qualquer <select data-combobox> via
 * combobox.js. Compartilha a linguagem visual (cartão branco, sombra
 * leve, hover suave). Suporta multi-seleção, ícones Lucide por opção e
 * auto-submit do form.
 */
.combobox {
    position: relative;
    font-size: 13px;
}

.combobox-button {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    width: 100%;
    margin: 0;
    padding: var(--form-element-spacing-vertical, 0.5rem) var(--form-element-spacing-horizontal, 0.75rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    color: var(--color-text);
    text-align: left;
    cursor: pointer;
    font: inherit;
    line-height: 1.4;
}

.combobox-button:hover {
    border-color: var(--color-primary-700);
}

.combobox-button:focus-visible {
    outline: 2px solid var(--color-primary-300);
    outline-offset: -1px;
    border-color: var(--color-primary-500);
}

.combobox-button-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.combobox-caret {
    margin-left: auto;
    color: var(--color-text-soft);
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
}

.combobox-placeholder {
    color: var(--color-text-soft);
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.combobox-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 16px;
    padding: 0 5px;
    margin: -2px 0;
    border-radius: var(--radius-pill);
    background: var(--color-primary-100);
    color: var(--color-primary-700);
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1;
    flex-shrink: 0;
}

.combobox-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 320px;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: var(--space-xs);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    box-shadow: var(--shadow-popover);
    font-family: var(--pico-font-family);
    font-size: 13px;
}

/* Variante ancorada: monta no body com top/left calculados via JS
   (popover de edição inline e batch). Z-index e sombra mais fortes
   pra destacar sobre conteúdo da página. */
.combobox-menu.is-anchored {
    z-index: 60;
    right: auto;
    box-shadow: var(--shadow-popover);
}

/* Fallback fixed: select-combobox padrão (sem `anchored:true`) que está
   dentro de `<dialog>` aberto. JS promove o menu pro <body> com
   position:fixed pra escapar do overflow do dialog body. Z-index acima
   do dialog (top layer). */
.combobox-menu.is-fixed {
    position: fixed;
    z-index: 60;
    right: auto;
    box-shadow: var(--shadow-popover);
}

/* Flip pra cima: JS aplica essa classe no modo default quando o menu
   estouraria a viewport por baixo. Inverte a âncora pra bottom mantendo
   o mesmo wrapper como containing-block. */
.combobox-menu.is-flip-up {
    top: auto;
    bottom: calc(100% + 4px);
}

.combobox-hint {
    margin: 0 0 var(--space-xs);
    padding: var(--space-xs) var(--space-sm);
    font-size: 11px;
    line-height: 1.35;
    color: var(--color-text-soft);
    background: var(--color-bg);
    border-radius: var(--radius-sm);
}

.combobox-error {
    margin-top: var(--space-xs);
    padding: var(--space-xs) var(--space-sm);
    font-size: 12px;
    color: var(--color-text);
    background: color-mix(in srgb, var(--color-danger, #c44) 12%, transparent);
    border-radius: var(--radius-sm);
}

.combobox-search {
    margin: 0 0 var(--space-xs);
    padding: var(--space-xs) var(--space-sm);
    font-size: 14px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
}

.combobox-search:focus {
    outline: 2px solid var(--color-primary-300, var(--color-primary-500));
    outline-offset: -1px;
    border-color: var(--color-primary-500);
}

.combobox-list {
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

.combobox-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--radius-sm);
    cursor: pointer;
    outline: none;
}

.combobox-item:hover,
.combobox-item:focus-visible {
    background: var(--color-border-soft);
}

.combobox-item[aria-selected='true'] {
    color: var(--color-primary-700);
}

.combobox:not(.is-multi) .combobox-item[aria-selected='true'] {
    font-weight: 600;
    background: var(--color-primary-100);
}

.combobox:not(.is-multi) .combobox-item[aria-selected='true']::after {
    content: '✓';
    position: absolute;
    right: var(--space-sm);
    color: var(--color-primary-700);
    font-weight: 700;
}

.combobox-glyph {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-soft);
}

.combobox-glyph-empty {
    visibility: hidden;
}

.combobox-glyph-cat {
    width: 18px;
    height: 18px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 55%, transparent);
    color: var(--cat-color, var(--color-text-soft));
}

.combobox-glyph-cat svg {
    width: 12px;
    height: 12px;
}

.combobox-item[aria-selected='true'] .combobox-glyph {
    color: var(--color-primary-700);
}

.combobox-item[aria-selected='true'] .combobox-glyph-cat {
    color: var(--cat-color, var(--color-primary-700));
}

.combobox-check {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    color: transparent;
    background: var(--color-card);
}

.combobox-item[aria-selected='true'] .combobox-check {
    background: var(--color-primary-700);
    border-color: var(--color-primary-700);
    color: var(--color-white);
}

.combobox-item-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.combobox-item-placeholder {
    color: var(--color-text-soft);
    font-style: italic;
}

.combobox-item-clear {
    font-weight: 500;
    border-bottom: 1px solid var(--color-border-soft);
    margin-bottom: var(--space-2xs);
    padding-bottom: var(--space-2xs);
}

.combobox-group-header {
    list-style: none;
    padding: var(--space-2xs) var(--space-sm);
    margin-top: var(--space-2xs);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-soft);
    cursor: default;
    user-select: none;
    pointer-events: none;
}

.combobox-group-header:first-child {
    margin-top: 0;
}

.combobox-item-clear .combobox-item-label,
.combobox-item-clear .combobox-item-placeholder {
    color: var(--color-text);
    font-style: normal;
}

.combobox-swatch {
    width: 14px;
    height: 14px;
    border-radius: var(--radius-pill);
    flex-shrink: 0;
    background: color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--cat-color, var(--color-neutral-200)) 55%, transparent);
}

.combobox-footer {
    display: flex;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
    padding-top: var(--space-xs);
    border-top: 1px solid var(--color-border-soft);
}

.combobox-action {
    appearance: none;
    background: transparent;
    border: none;
    color: var(--color-primary-700);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    padding: var(--space-2xs) var(--space-xs);
    margin: 0;
    border-radius: var(--radius-sm);
}

.combobox-action:hover {
    background: var(--color-primary-100);
}

.combobox-action-clear {
    color: var(--color-text-soft);
}

.combobox-action-clear:hover {
    background: var(--color-neutral-50);
    color: var(--color-danger);
}

.combobox-action-apply {
    font-weight: 600;
}

/* Datepicker custom ======================================================
 * Popover próprio para <input type="date" data-datepicker>. Mesma
 * linguagem visual do combobox e do month-popover.
 */
.datepicker {
    position: relative;
}

.datepicker-trigger {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    width: 100%;
    padding: var(--form-element-spacing-vertical, 0.5rem) var(--form-element-spacing-horizontal, 0.75rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    color: var(--color-text);
    text-align: left;
    cursor: pointer;
    font: inherit;
    line-height: 1.4;
}

.datepicker-trigger:hover {
    border-color: var(--color-primary-700);
}

.datepicker-trigger:focus-visible {
    outline: 2px solid var(--color-primary-300);
    outline-offset: -1px;
    border-color: var(--color-primary-500);
}

.datepicker-trigger-text {
    font-family: var(--font-mono);
    font-feature-settings: "zero" 0;
    font-variant-numeric: normal;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.datepicker-trigger-placeholder {
    color: var(--color-text-soft);
    font-family: var(--font-sans);
}

.datepicker-trigger-icon {
    color: var(--color-text-soft);
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

.datepicker-popover {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 30;
    width: 280px;
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-card);
    box-shadow: var(--shadow-popover);
}

.datepicker-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-xs);
    margin-bottom: var(--space-sm);
}

.datepicker-month-label {
    flex: 1;
    text-align: center;
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--color-text);
}

.datepicker-nav {
    appearance: none;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    width: 28px;
    height: 28px;
    cursor: pointer;
    color: var(--color-text-soft);
    margin: 0;
    padding: 0;
    line-height: 1;
    font-size: 1.1rem;
}

.datepicker-nav:hover {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.datepicker-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: var(--space-2xs);
    margin-bottom: var(--space-2xs);
}

.datepicker-weekdays > span {
    text-align: center;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase;
    padding: var(--space-2xs) 0;
}

.datepicker-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: var(--space-2xs);
}

.datepicker-cell {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 0;
    height: 32px;
    cursor: pointer;
    font-family: var(--font-mono);
    font-feature-settings: "zero" 0;
    font-variant-numeric: normal;
    font-size: 0.85rem;
    color: var(--color-text);
    margin: 0;
    text-align: center;
    transition: background-color 120ms, border-color 120ms;
}

.datepicker-cell:hover:not(.is-disabled) {
    background: var(--color-neutral-50);
    border-color: var(--color-border);
}

.datepicker-cell.is-outside {
    color: var(--color-text-muted);
}

.datepicker-cell.is-today {
    border-color: var(--color-primary-700);
    color: var(--color-primary-700);
}

.datepicker-cell.is-selected {
    background: var(--color-primary-700);
    color: var(--color-white);
    border-color: var(--color-primary-700);
}

.datepicker-cell.is-disabled {
    color: var(--color-text-muted);
    cursor: not-allowed;
    opacity: 0.5;
}

.datepicker-footer {
    display: flex;
    justify-content: space-between;
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--color-border-soft);
}

.datepicker-action {
    appearance: none;
    background: transparent;
    border: none;
    color: var(--color-primary-700);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    padding: var(--space-2xs) var(--space-xs);
    margin: 0;
    border-radius: var(--radius-sm);
}

.datepicker-action:hover {
    background: var(--color-primary-100);
}

.datepicker-action-clear {
    color: var(--color-text-soft);
}

.datepicker-action-clear:hover {
    background: var(--color-neutral-50);
    color: var(--color-danger);
}

.datepicker-hidden {
    display: none !important;
}

/*
 * Toasts (Django messages framework).
 *
 * Container fixo no topo, centralizado, stack vertical. Cada toast tem
 * ícone, mensagem e botão de fechar. Auto-dismiss em 5s via JS; hover
 * pausa o timer. Click no body OU no botão fecha.
 *
 * z-index alto pra ficar acima de <dialog> e popovers.
 */
.toast-container {
    position: fixed;
    top: var(--space-md);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    z-index: 10000;
    pointer-events: none;
    width: min(420px, calc(100% - 2rem));
}

.toast {
    pointer-events: auto;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    background: var(--color-card);
    box-shadow: var(--shadow-md);
    border-left: 4px solid var(--color-text-soft);
    font-size: 0.9375rem;
    line-height: 1.4;
    color: var(--color-text);
    animation: toast-enter 200ms ease-out;
}

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

.toast.toast-leaving {
    animation: toast-leave 180ms ease-in forwards;
}

@keyframes toast-leave {
    to {
        opacity: 0;
        transform: translateY(-8px);
    }
}

.toast-success {
    border-left-color: var(--color-success);
}
.toast-success .toast-icon {
    color: var(--color-success);
}

.toast-error {
    border-left-color: var(--color-danger);
    background: var(--color-danger-bg);
}
.toast-error .toast-icon {
    color: var(--color-danger);
}

.toast-warning {
    border-left-color: var(--color-warning);
}
.toast-warning .toast-icon {
    color: var(--color-warning);
}

.toast-info {
    border-left-color: var(--color-info);
}
.toast-info .toast-icon {
    color: var(--color-info);
}

.toast-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.toast-body {
    min-width: 0;
}

.toast-close {
    /* sobrescreve estilo de button do Pico pra virar ícone limpo */
    appearance: none;
    background: transparent;
    border: none;
    padding: var(--space-2xs);
    margin: 0;
    color: var(--color-text-soft);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
}

.toast-close:hover {
    background: var(--color-neutral-50);
    color: var(--color-text);
}

/* --- Detalhe de conta (UX-1.7) ---
 * Página /accounts/<pk>/ : header com os fatos da conta + lista enxuta das
 * últimas transações. Pra editar/arquivar o usuário clica em "Editar".
 */
.account-detail-header {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
}

.account-detail-headline {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.account-detail-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--color-neutral-50);
    color: var(--color-text-soft);
    flex-shrink: 0;
}

.account-detail-title {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1;
}

.account-detail-title h2 {
    margin: 0;
    line-height: 1.2;
}

.account-detail-meta {
    font-size: 13px;
    color: var(--color-text-soft);
}

.account-detail-edit {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
}

.account-detail-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: var(--space-md);
    margin: 0;
    padding: var(--space-md);
    background: var(--color-neutral-50);
    border-radius: var(--radius-md);
}

.account-detail-fact {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
}

.account-detail-fact dt {
    font-size: 12px;
    color: var(--color-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.account-detail-fact dd {
    margin: 0;
    font-size: 1rem;
    font-weight: 500;
}

/*
 * Hint encostado no card de facts. Usa o mesmo background neutro do
 * card e cor primária na borda esquerda pra ancorar visualmente —
 * sem isso ficava "perdido" no meio do header entre as facts e os
 * filtros, com peso visual baixo demais pra ser percebido.
 */
.account-detail-hint {
    display: flex;
    align-items: flex-start;
    gap: var(--space-xs);
    margin: var(--space-sm) 0 0;
    padding: var(--space-sm) var(--space-md);
    background: var(--color-primary-100);
    border-left: 3px solid var(--color-primary-700);
    border-radius: var(--radius-md);
    font-size: 0.875rem;
    color: var(--color-text);
    line-height: 1.45;
}

.account-detail-hint-icon {
    flex-shrink: 0;
    margin-top: 2px;
    color: var(--color-primary-700);
}

.account-detail-hint a {
    color: var(--color-primary-700);
    font-weight: 500;
}

.account-detail-section {
    margin-top: var(--space-lg);
}

.account-detail-section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}

.account-detail-section-header h3 {
    margin: 0;
}

.account-detail-section-link {
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
}

.account-detail-tx-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--color-border);
}

.account-detail-tx-row {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--color-border);
}

.account-detail-tx-date {
    color: var(--color-text-soft);
    font-size: 13px;
    min-width: 40px;
}

.account-detail-tx-desc {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.account-detail-tx-cat {
    font-size: 13px;
    color: var(--color-text-soft);
    min-width: 0;
    display: flex;
    align-items: center;
    overflow: hidden;
}

.account-detail-tx-cat .cat-chip {
    max-width: 100%;
}

.account-detail-tx-cat .cat-chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.account-detail-tx-amount {
    font-weight: 500;
}

.account-detail-tx-amount.is-expense { color: var(--color-danger, #c0392b); }
.account-detail-tx-amount.is-income { color: var(--color-success, #1e7f4f); }

.account-detail-tx-more {
    margin: var(--space-sm) 0 0;
    color: var(--color-text-soft);
    font-size: 13px;
}

@media (max-width: 600px) {
    .account-detail-tx-row {
        grid-template-columns: auto 1fr auto;
    }
    .account-detail-tx-cat { display: none; }
}

/* Link auxiliar logo abaixo do título de um form (ex: "Ver lançamentos
 * desta conta →" em UX-1.8). Não compete com os campos. */
.form-aux-link {
    margin: calc(-1 * var(--space-xs)) 0 var(--space-sm);
    font-size: 14px;
}

.form-aux-link a {
    color: var(--color-text-soft);
}

.form-aux-link a:hover {
    color: var(--color-primary-700, var(--color-text));
}


/* Drawer/sheet de edição de transação (ADR 0035) ========================== */

/* Especificidade `dialog.tx-edit-dialog` (0,1,1) é necessária pra vencer
   as regras de elemento do Pico (`dialog { top/right/bottom/left:0;
   min-width:100%; min-height:100%; ... }`). Sem isso a dialog estica
   pra viewport inteira mesmo com `width:480px` no desktop. */
dialog.tx-edit-dialog {
    border: 0;
    padding: 0;
    background: var(--color-card);
    color: var(--color-text);
    box-shadow: var(--shadow-popover);
    /* Mobile-first: bottom sheet ocupando largura toda. */
    margin: 0;
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    min-width: 0;
    max-width: 100%;
    height: auto;
    min-height: 0;
    max-height: 90vh;
    border-top-left-radius: var(--radius-lg);
    border-top-right-radius: var(--radius-lg);
    overflow: hidden;
    /* Pico aplica `backdrop-filter: blur(...)` no <dialog>, o que cria um
       containing block pra descendentes com `position: fixed` (datepicker
       e combobox-menu em modo fallback). Sem isso o popover sai posicionado
       relativo ao box do dialog em vez do viewport. O efeito blur "atrás
       do dialog" já é coberto pelo ::backdrop. */
    backdrop-filter: none;
}

dialog.tx-edit-dialog::backdrop {
    background: var(--overlay-bg);
    /* `backdrop-filter` aqui afeta só o conteúdo atrás do ::backdrop (a
       página), não os descendentes do <dialog>. O containing-block trap
       que motivou o `backdrop-filter: none` no próprio <dialog> não se
       aplica ao pseudo-elemento. */
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

dialog.tx-edit-dialog[open] {
    /* Pico aplica `align-items: center; justify-content: center` no
       <dialog>, o que centraliza o conteúdo verticalmente. Aqui forçamos
       o flow normal (conteúdo cola no topo, ocupa largura toda). */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
}

.tx-edit-dialog-body {
    overflow-y: auto;
    padding: var(--space-lg);
    max-height: 90vh;
}

.tx-edit-form-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}

.tx-edit-form-title {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
}

.tx-edit-form-close {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--color-text-soft);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    padding: var(--space-xs) var(--space-sm);
    margin: 0;
    border-radius: var(--radius-sm);
}

.tx-edit-form-close:hover {
    background: var(--color-bg);
    color: var(--color-text);
}

.tx-edit-page {
    max-width: 560px;
    margin: 0 auto;
}

/* Desktop: drawer ancorado à direita. */
@media (min-width: 768px) {
    dialog.tx-edit-dialog {
        top: 0;
        right: 0;
        bottom: 0;
        left: auto;
        width: 480px;
        max-width: 90vw;
        height: 100vh;
        max-height: 100vh;
        border-top-left-radius: 0;
        border-top-right-radius: 0;
    }

    .tx-edit-dialog-body {
        max-height: 100vh;
    }
}

/* Linha inteira clicável: o `<li.transaction-row>` carrega `data-tx-open`
   e abre o drawer. Hover acende com o primário em opacidade baixa, o
   mesmo padrão dos chips/cards interativos — neutral-50 (var(--color-bg))
   tinha contraste insuficiente contra o card branco. Foco por teclado
   cai no outline default do browser. */
.transaction-row[data-tx-open] {
    cursor: pointer;
}

.transaction-row[data-tx-open]:hover {
    background: color-mix(in srgb, var(--color-primary-500) 10%, transparent);
    border-radius: var(--radius-sm);
}

/* Modal de confirmação de escopo (recorrência, a1 do spec) ================ */

/* Pico estende o <dialog> pra 100% da viewport com
   `align-items:center; justify-content:center` (vide pico.min.css).
   Em vez de lutar contra isso (no <dialog> em modal o browser ignora
   `top:auto`/`margin:auto` mesmo com !important), aproveitamos: o
   dialog vira o overlay transparente full-viewport, e o `>body` é o
   card centralizado naturalmente pelo flex do Pico. */
dialog.tx-recur-confirm {
    background: transparent;
    border: 0;
    padding: 0;
    box-shadow: none;
    color: var(--color-text);
}

dialog.tx-recur-confirm::backdrop {
    background: var(--overlay-bg);
}

.tx-recur-confirm-body {
    background: var(--color-card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-popover);
    width: 100%;
    max-width: 480px;
    margin: var(--space-md);
    padding: var(--space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.tx-recur-confirm-body h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
}

.tx-recur-confirm-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.tx-recur-choice {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-align: left;
    gap: var(--space-2xs);
    padding: var(--space-md);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-bg);
    color: var(--color-text);
    cursor: pointer;
    width: 100%;
}

.tx-recur-choice:hover,
.tx-recur-choice:focus-visible {
    border-color: var(--color-brand);
    background: var(--color-card);
}

.tx-recur-choice strong {
    font-weight: 600;
}

.tx-recur-choice-hint {
    font-size: 0.875rem;
    color: var(--color-text-soft);
    font-weight: 400;
    line-height: 1.35;
}

.tx-recur-confirm-actions {
    display: flex;
    justify-content: flex-end;
}

.tx-recur-confirm-actions [data-tx-recur-cancel] {
    margin: 0;
}

/* Segundo passo do modal "Todas": só aparece quando a série tem
 * exceções (customized_at != NULL). Pergunta se preserva ou sobrescreve. */
.tx-recur-exceptions {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    padding: var(--space-md);
    background: var(--color-neutral-50);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-md);
}

.tx-recur-exceptions[hidden] {
    display: none;
}

.tx-recur-exceptions-hint {
    margin: 0;
    color: var(--color-text-soft);
    font-size: 0.95rem;
}

.tx-recur-exceptions-toggle {
    display: flex;
    gap: var(--space-sm);
    align-items: flex-start;
    cursor: pointer;
    font-size: 0.95rem;
}

.tx-recur-exceptions-toggle input {
    margin: 0;
    flex: 0 0 auto;
}

.tx-recur-exceptions-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-sm);
}

.tx-recur-exceptions-actions button {
    margin: 0;
}

/* Botão "Excluir" no form de edição (#96). Outline danger: borda visível
 * em estado normal pra sinalizar ação destrutiva, sem competir com Salvar
 * (primary). Hover preenche o fundo. */
.tx-edit-delete {
    --pico-color: var(--color-danger);
    --pico-background-color: transparent;
    --pico-border-color: var(--color-danger);
    margin: 0;
    margin-left: auto;
    padding: var(--space-sm) var(--space-md);
    background: transparent;
    color: var(--color-danger);
    border: 1px solid var(--color-danger);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-weight: 500;
}

.tx-edit-delete:hover,
.tx-edit-delete:focus-visible {
    --pico-background-color: var(--color-danger-bg);
    --pico-border-color: var(--color-danger);
    background: var(--color-danger-bg);
    border-color: var(--color-danger);
}

/* Dialog de confirmação simples (avulsa / transferência).
 * Mesma estratégia do .tx-recur-confirm: dialog é overlay transparente
 * full-viewport (Pico aplica flex+center), body é o card. */
dialog.tx-delete-confirm {
    background: transparent;
    border: 0;
    padding: 0;
    box-shadow: none;
    color: var(--color-text);
}

dialog.tx-delete-confirm::backdrop {
    background: var(--overlay-bg);
}

.tx-delete-confirm-body {
    background: var(--color-card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-popover);
    width: 100%;
    max-width: 420px;
    margin: var(--space-md);
    padding: var(--space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.tx-delete-confirm-body h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
}

.tx-delete-confirm-hint {
    margin: 0;
    color: var(--color-text-soft);
    font-size: 0.875rem;
    line-height: 1.4;
}

.tx-delete-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-sm);
}

.tx-delete-confirm-actions button {
    margin: 0;
}

.tx-delete-confirm-actions [data-tx-delete-confirm-go] {
    --pico-background-color: var(--color-danger);
    --pico-border-color: var(--color-danger);
    background: var(--color-danger);
    border-color: var(--color-danger);
    color: #fff;
}


/* Reports ============================================================== */

/* Estilos da tela /reports/ moveram pra static/css/reports.css (carregado
 * só naquela rota via extra_head). Mantemos aqui apenas o bloco P4 que
 * vive no template de listagem de transações. */

/* P4 — totais por dimensão na listagem de transações */

.tx-dimension-totals {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    background: var(--color-neutral-50);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-soft);
    margin-bottom: var(--space-md);
}

.tx-dimension-totals-item {
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
}

.tx-dimension-totals-label {
    font-size: 0.8rem;
    color: var(--color-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.tx-dimension-totals-value {
    font-family: var(--font-mono);
    font-feature-settings: "zero" 0;
    font-variant-numeric: lining-nums;
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-text);
}

.tx-dimension-totals-item.dim-fixed .tx-dimension-totals-value {
    color: var(--color-primary-700);
}

.tx-dimension-totals-item.dim-installment .tx-dimension-totals-value {
    color: var(--color-info);
}

.tx-dimension-totals-item.dim-variable .tx-dimension-totals-value {
    color: var(--color-text);
}

.tx-dimension-totals-item.dim-total {
    border-left: 1px solid var(--color-border);
    padding-left: var(--space-sm);
}

.tx-dimension-totals-item.dim-total .tx-dimension-totals-value {
    color: var(--color-danger);
}
