:root {
    --color-primary: #003d7a;
    --color-secondary: #007f55;
    --color-danger: #dc3545;
    --color-warning: #ffc107;
    --color-bg: #f8f9fa;
    --color-surface: #ffffff;
    --color-text: #333333;
    --color-muted: #6b7280;

    /* Texto dos alertas do MudBlazor. Ele pinta o texto com a variante "darken" da cor semântica, que não
       alcança os 4,5:1 da WCAG (2,7 a 4,4:1 medidos); estes valores dão de 5,7 a 9,6:1 sobre o fundo da
       página e sobre o papel, nos dois temas. */
    --alert-info: #0b5fa5;
    --alert-warning: #8a4b00;
    --alert-success: #0b6b34;
    --alert-error: #b3261e;
}

/* O tema escuro precisa chegar também à página, e não só aos componentes: sem isto o fundo e o texto
   corrido ficavam nos valores claros, e os cartões escuros apareciam como ilhas num fundo branco.
   O script do <head> (App.razor) escreve data-theme antes da primeira pintura, escolhido ou vindo do
   sistema operacional; a mídia é só o resguardo de quem está sem JavaScript. A paleta do MudBlazor
   não mora aqui: vem do mesmo FinasstTheme do layout, escopada por este mesmo atributo. Mantenha estes
   tokens em sincronia com o tema escuro de FinasstTheme.cs. --color-primary vira um azul claro porque o
   #003d7a não se lê sobre fundo escuro (títulos das páginas legais, borda da faixa de consentimento). */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --color-secondary: #00a86b;
        --color-primary: #4a94ea;
        --color-bg: #1a1a2e;
        --color-surface: #16213e;
        --color-text: #ffffff;
        --color-muted: #9aa3b8;
        --alert-info: #7bbcff;
        --alert-warning: #ffc247;
        --alert-success: #3fd9a8;
        --alert-error: #ff8b99;
    }
}

:root[data-theme="dark"] {
    --color-secondary: #00a86b;
    --color-primary: #4a94ea;
    --color-bg: #1a1a2e;
    --color-surface: #16213e;
    --color-text: #ffffff;
    --color-muted: #9aa3b8;
    --alert-info: #7bbcff;
    --alert-warning: #ffc247;
    --alert-success: #3fd9a8;
    --alert-error: #ff8b99;
}

.mud-alert-text-info, .mud-alert-outlined-info { color: var(--alert-info); }
.mud-alert-text-warning, .mud-alert-outlined-warning { color: var(--alert-warning); }
.mud-alert-text-success, .mud-alert-outlined-success { color: var(--alert-success); }
.mud-alert-text-error, .mud-alert-outlined-error { color: var(--alert-error); }

html, body {
    font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    background-color: var(--color-bg);
    color: var(--color-text);
}

.hero-section {
    min-height: 280px;
    padding: 1.5rem 1.25rem;
}

@media (min-width: 600px) {
    .hero-section {
        padding: 2rem;
    }
}

/* O título acompanha a largura da tela em vez de saltar entre dois tamanhos: fixo em 3rem ele
   quebrava em cinco linhas no celular e empurrava os botões para fora da primeira tela. */
.hero-section .hero-title {
    font-size: clamp(1.875rem, 1.1rem + 3.4vw, 3rem);
    line-height: 1.15;
}

/* No celular os botões ocupam a linha toda, um embaixo do outro (alvos grandes, textos em uma linha só);
   a partir de 600px voltam ao tamanho natural, lado a lado. */
.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

    .hero-actions .mud-button-root {
        flex: 1 1 100%;
    }

@media (min-width: 600px) {
    .hero-actions .mud-button-root {
        flex: 0 0 auto;
    }
}

/* O mesmo para uma fileira de botões de ação fora do hero (Comparar), centralizada em tela larga. */
.action-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: center;
}

    .action-row .mud-button-root {
        flex: 1 1 100%;
    }

@media (min-width: 600px) {
    .action-row .mud-button-root {
        flex: 0 0 auto;
    }
}

/* O cartão inteiro leva ao destino (o "Explorar" é o caminho acessível). Títulos longos quebram em
   linhas parecidas em vez de deixar uma palavra sozinha ("Multi-" / "Região"). */
.feature-card {
    cursor: pointer;
}

.feature-card .mud-typography-h6 {
    text-wrap: balance;
}

/* Desktop: ícone no alto, texto centralizado, "Explorar" no pé (o CTA fica no fundo do cartão porque o
   conteúdo cresce, e fica alinhado com o dos vizinhos de linha por causa do h-100). */
.feature-card__body {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 1.5rem;
}

.feature-card__icon {
    margin-bottom: 1rem;
    background: #003d7a;
}

.feature-card__text {
    min-width: 0;
}

.feature-card__cta {
    justify-content: center;
    padding-bottom: 1rem;
}

/* Celular: ícone ao lado do texto e "Explorar" alinhado sob ele. Cada cartão cai de ~260px para ~135px;
   com seis, a seção deixa de pesar mais de uma tela e meia de rolagem. */
@media (max-width: 599px) {
    .feature-card__body {
        flex-direction: row;
        align-items: flex-start;
        gap: 1rem;
        padding: 1rem 1rem 0.25rem;
        text-align: left;
    }

    .feature-card__icon {
        flex: none;
        width: 44px;
        height: 44px;
        margin-bottom: 0;
    }

    .feature-card__cta {
        justify-content: flex-start;
        /* 1rem de borda + 44px do ícone + 1rem de intervalo: sob o início do texto. */
        padding: 0 0.5rem 0.5rem calc(2rem + 44px - 0.5rem);
    }
}

/* Linha de apoio sob a grade de ferramentas (o suporte a várias moedas e países, que não é uma tela). */
.home-support {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin: 1.5rem 0 0;
    text-align: center;
    color: var(--color-muted);
}

.feature-card:hover {
    box-shadow: 0 8px 24px rgba(0,61,122,0.15) !important;
}

/* A elevação só em quem tem mouse e não pediu menos movimento; no toque, :hover fica "preso" depois do
   toque, e o cartão ficaria levantado até a pessoa tocar noutro lugar. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .feature-card {
        transition: transform 0.2s;
    }

    .feature-card:hover {
        transform: translateY(-4px);
    }
}

/* Quem navega por teclado foca o "Explorar" dentro do cartão: o anel é do cartão inteiro. */
.feature-card:focus-within {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.mud-main-content {
    padding-top: 80px !important;
    /* Coluna que ocupa a janela inteira: o conteúdo cresce e empurra o rodapé para o fim, em vez de o
       rodapé ficar no meio da tela, com uma faixa vazia embaixo, nas páginas curtas (login, Pro). */
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
}

/* O <main> (MainLayout) é quem cresce e empurra o rodapé; antes era o próprio .mud-container. Recebe foco
   por programa (link "pular para o conteúdo"), mas ninguém o focou: sem contorno. */
.mud-main-content > .app-main {
    flex: 1 0 auto;
    width: 100%;
}

.app-main:focus {
    outline: none;
}

/* "Pular para o conteúdo": fora da tela até receber foco por teclado. Acima da barra fixa (1100), da faixa
   de consentimento (2000) e de tudo o mais. */
.skip-link {
    position: fixed;
    top: 0.5rem;
    left: 0.5rem;
    z-index: 3000;
    padding: 0.75rem 1rem;
    border-radius: 4px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-primary);
    font-weight: 500;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
    transform: translateY(-250%);
}

.skip-link:focus {
    transform: none;
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Enquanto o WebAssembly carrega (html.booting, ligado no <head> e desligado pelo MainLayout) a página já
   está na tela mas não responde. Uma barra fina de "carregando" no topo, depois de meio segundo para não
   piscar em quem carrega rápido, e o cursor de espera nos controles. Quem pediu menos movimento recebe a
   barra parada. */
html.booting::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    z-index: 3500;
    pointer-events: none;
    background: linear-gradient(90deg, transparent, var(--mud-palette-secondary), transparent) no-repeat;
    background-size: 40% 100%;
    opacity: 0;
    animation: finasst-boot-bar 1.4s linear 0.5s infinite;
}

@keyframes finasst-boot-bar {
    from {
        background-position: -40% 0;
        opacity: 1;
    }

    to {
        background-position: 140% 0;
        opacity: 1;
    }
}

html.booting .mud-button-root,
html.booting .mud-nav-link {
    cursor: progress;
}

@media (prefers-reduced-motion: reduce) {
    html.booting::before {
        background-size: 100% 100%;
        background-position: 0 0;
        animation: finasst-boot-show 0s linear 0.5s forwards;
    }

    @keyframes finasst-boot-show {
        to {
            opacity: 1;
        }
    }
}

.mud-table-cell {
    font-size: 0.85rem !important;
}

.text-right {
    text-align: right;
}

/* Utilitários que os componentes já usam (h-100 em SummaryCard, FeatureCard, Minhas dívidas, Comparar e na
   Simulação; text-center em FeatureCard e NotFound; text-break na tela de webhooks) mas que nenhum CSS
   carregado definia: o Bootstrap não é linkado, e o MudBlazor chama a altura total de mud-height-full.
   Sem h-100 o cartão não preenchia o item da grade, e os de uma mesma linha ficavam com alturas
   diferentes quando um tinha uma nota ou uma linha a mais de texto. */
.h-100 {
    height: 100%;
}

.text-center {
    text-align: center;
}

.text-break {
    overflow-wrap: anywhere;
}

/* A tabela simples do MudBlazor fixa text-align:start numa regra mais específica que a classe acima
   (".mud-simple-table table * tr>td"), então os números nunca ficaram à direita, em tabela nenhuma.
   Esta tem a especificidade para vencer. Nas células, sem quebra de linha: "BRL 59.785,70" partido
   em duas linhas deixa de ser um número e vira dois textos. */
.mud-simple-table table * tr > td.text-right {
    text-align: right;
    white-space: nowrap;
}

.mud-simple-table table * tr > th.text-right {
    text-align: right;
}

.fw-bold {
    font-weight: 700 !important;
}

.text-muted {
    color: var(--color-muted) !important;
}

h1:focus {
    outline: none;
}
.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}
/* ============================================================================
   Data visualisation
   ----------------------------------------------------------------------------
   Series colours were chosen by running the palette validator against the two
   surfaces this application actually renders on, not by eye. Both modes clear
   every gate with no warning:

     light on #ffffff  worst pair CVD dE 9.0, normal-vision dE 27.9
     dark  on #16213e  worst pair CVD dE 9.3, normal-vision dE 23.2

   The brand navy #003d7a is deliberately absent from the series slots: as a
   mark colour it falls below the lightness band (L 0.364) and fails the gate.
   It remains the chrome colour; the series use the step of the same family
   that passes. Dark values are a selected set for the dark surface, not a
   lightened flip of the light ones.

   Assignment is by entity and never by rank, so filtering a series out never
   repaints the survivors.
   ============================================================================ */

:root {
    --viz-surface: #ffffff;
    --viz-plane: #f8f9fa;
    --viz-ink: #333333;
    --viz-ink-secondary: #52565e;
    --viz-ink-muted: #6b7280;
    --viz-grid: #eceef0;
    --viz-axis: #d3d6da;

    --viz-principal: #1565c0;
    --viz-interest: #eb6834;
    --viz-charges: #00a86b;

    /* Reserved for benefit/saving, never for a series slot. */
    --viz-saving: #00a86b;

    /* Status, never reused as a series colour. Red is reserved for an actual
       loss - an overdue debt - and never for ordinary interest. */
    --viz-critical: #d03b3b;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --viz-surface: #16213e;
        --viz-plane: #1a1a2e;
        --viz-ink: #ffffff;
        --viz-ink-secondary: #c2c9da;
        --viz-ink-muted: #9aa3b8;
        --viz-grid: #243050;
        --viz-axis: #2f3d63;

        --viz-principal: #3987e5;
        --viz-interest: #c9451c;
        --viz-charges: #00a86b;
        --viz-saving: #00a86b;
        --viz-critical: #e05a5a;
    }
}

:root[data-theme="dark"] {
    --viz-surface: #16213e;
    --viz-plane: #1a1a2e;
    --viz-ink: #ffffff;
    --viz-ink-secondary: #c2c9da;
    --viz-ink-muted: #9aa3b8;
    --viz-grid: #243050;
    --viz-axis: #2f3d63;

    --viz-principal: #3987e5;
    --viz-interest: #c9451c;
    --viz-charges: #00a86b;
    --viz-saving: #00a86b;
    --viz-critical: #e05a5a;
}

.viz-figure {
    display: block;
    width: 100%;
    margin: 0;
}

.viz-figure svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}

/* Gridlines and axes are solid hairlines one shade off the surface. Dashing
   them would read as "projection" or "threshold" when it is only a grid. */
.viz-grid-line {
    stroke: var(--viz-grid);
    stroke-width: 1;
    shape-rendering: crispEdges;
}

.viz-axis-line {
    stroke: var(--viz-axis);
    stroke-width: 1;
    shape-rendering: crispEdges;
}

/* Text wears text tokens, never the series colour; the mark beside it carries
   identity. */
.viz-axis-label {
    fill: var(--viz-ink-muted);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
}

.viz-series-label {
    font-size: 12px;
    font-weight: 600;
}

.viz-crosshair {
    stroke: var(--viz-axis);
    stroke-width: 1;
    pointer-events: none;
}

.viz-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
    align-items: center;
    margin-bottom: 0.5rem;
    font-size: 0.8125rem;
    color: var(--viz-ink-secondary);
}

.viz-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.viz-swatch {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    flex: none;
}

.viz-tooltip {
    position: absolute;
    z-index: 10;
    min-width: 9rem;
    padding: 0.5rem 0.625rem;
    border-radius: 6px;
    background: var(--viz-surface);
    color: var(--viz-ink);
    border: 1px solid var(--viz-axis);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
    font-size: 0.75rem;
    pointer-events: none;
    transform: translate(-50%, calc(-100% - 12px));
}

.viz-tooltip-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    font-variant-numeric: tabular-nums;
}

.viz-plot {
    position: relative;
}

/* Stat tiles: large standalone numbers keep proportional figures, so 121 does
   not read loose at display size. */
.viz-stat-value {
    /* Encolhe com a largura da tela, até 1.5rem a partir de ~730px. Dois cartões lado a lado no celular
       têm uns 140px úteis cada, e "BRL 59.785,70" a 1.5rem não cabia neles. */
    font-size: clamp(1.0625rem, 0.5rem + 2.2vw, 1.5rem);
    font-weight: 700;
    line-height: 1.15;
    color: var(--viz-ink);
}

.viz-stat-label {
    font-size: 0.75rem;
    color: var(--viz-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

@media (prefers-reduced-motion: reduce) {
    .viz-figure * {
        transition: none !important;
    }
}

/* Type inside an SVG scales with the viewBox, so the rendered size of a label
   depends on how wide the card happens to be. The viewBox is sized close to the
   typical rendered width, and these steps keep the labels between roughly ten
   and fifteen real pixels from a phone up to a wide desktop. */
.viz-figure svg {
    font-size: 11px;
}

@media (max-width: 599px) {
    .viz-figure svg {
        font-size: 13px;
    }
}

@media (min-width: 1600px) {
    .viz-figure svg {
        font-size: 9px;
    }
}

/* End labels of a full-width scale. HTML rather than SVG text, so their size does
   not depend on how far the figure happens to be scaled. */
.viz-scale-ends {
    display: flex;
    justify-content: space-between;
    margin-top: 0.375rem;
    font-size: 0.75rem;
    color: var(--viz-ink-muted);
    font-variant-numeric: tabular-nums;
}

/* The area under the balance curve. Its opacity is set per mode rather than once:
   sixteen percent reads as a gentle wash on white and as almost nothing on the
   dark surface. */
.viz-area {
    fill: var(--viz-principal);
    fill-opacity: 0.16;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .viz-area {
        fill-opacity: 0.26;
    }
}

:root[data-theme="dark"] .viz-area {
    fill-opacity: 0.26;
}

/* ── Feedback de progresso ─────────────────────────────────────────────────
   Uma barra global sob a barra de aplicação para o tráfego da API, e um estado
   local de "recalculando" para as regiões que o navegador recomputa sozinho.
   As duas coisas são diferentes e não deveriam parecer iguais: a primeira é uma
   espera pela rede, a segunda é trabalho que termina em milissegundos e não pode
   piscar a tela a cada tecla. */

/* Ancorada logo abaixo da barra de aplicação, cujo z-index no MudBlazor é 1100.
   Fica acima do conteúdo e abaixo de menus e diálogos, que é onde uma barra de
   progresso pertence: visível sem cobrir aquilo com que o usuário interage. */
.app-busy-bar {
    position: fixed;
    top: var(--mud-appbar-height, 64px);
    left: 0;
    right: 0;
    z-index: 1101;
    pointer-events: none;
}

/* Reservado mesmo quando vazio, de modo que a região não pule para baixo no
   instante em que o cálculo começa. */
.busy-area__bar {
    height: 4px;
    margin-bottom: 0.5rem;
}

/* O recuo é deliberadamente discreto. Os números anteriores continuam legíveis
   porque a comparação com eles é justamente o que o leitor está fazendo. */
.busy-area__content {
    transition: opacity 120ms ease-out;
}

.busy-area--working .busy-area__content {
    opacity: 0.55;
}

/* Quem pediu menos animação recebe o mesmo sinal sem o esmaecimento gradual. */
@media (prefers-reduced-motion: reduce) {
    .busy-area__content {
        transition: none;
    }
}

/* O resultado de uma comparação cujos campos mudaram depois: continua legível, porque é com ele que se
   está confrontando o que acabou de ser digitado, mas deixa de parecer a resposta atual. */
.stale-results {
    opacity: 0.55;
    transition: opacity 120ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .stale-results {
        transition: none;
    }
}

/* A âncora "Saiba mais" da Home rola até aqui; sem a margem, a barra fixa cobriria o título da seção. */
#features {
    scroll-margin-top: 80px;
}

/* Alvo da rolagem até o resultado (finasstScroll.to): ganha foco programático, mas sem contorno, porque
   ninguém o focou; a margem deixa a barra fixa de fora. */
[data-scroll-target] {
    scroll-margin-top: 72px;
    outline: none;
}

/* Campos que se arrumam pela largura do cartão, e não pela da janela. Cada um pede pelo menos 11rem,
   então um cartão estreito (o celular, ou uma coluna de três cartões) fica com um campo por linha e
   os rótulos aparecem inteiros; um cartão largo ganha duas colunas. Com colunas de metade da largura
   fixas, "Valor do Empréstimo" e "Tipo de Amortização" saíam cortados com reticências. */
.field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 1rem 0.75rem;
}

.field-grid__wide {
    grid-column: 1 / -1;
}

/* A ação (botão) fica na altura dos campos da linha, e não na base da célula mais alta: um campo com texto
   de apoio (o tipo de amortização) cresce para baixo, e alinhar pela base empurrava o botão para fora da
   linha. O recuo (medido na tela) centraliza o botão de 42px no campo de 56px. */
.field-grid__action {
    align-self: start;
    margin-top: 0.875rem;
}

/* O mesmo princípio para formulários que continuam em MudGrid: a largura que importa é a do cartão,
   e não a da janela. Os itens "sm=6" são metade da linha a partir de 600px de janela, e numa coluna
   estreita ao lado dos resultados isso dava campos de ~130px, com rótulos cortados. Abaixo de 23,5rem
   de cartão (dois campos de 11rem e o espaçamento não cabem) cada item ocupa a linha inteira. */
.fluid-grid {
    container-type: inline-size;
}

@container (max-width: 23.5rem) {
    .fluid-grid .mud-grid-item {
        flex-basis: 100%;
        max-width: 100%;
    }
}

/* O formulário acompanha a rolagem ao lado de resultados longos (gráficos, cronograma), para dar
   para mexer num número sem voltar ao topo. Só onde há duas colunas; se a janela for baixa demais
   para o formulário inteiro, ele rola por dentro em vez de esconder o botão de simular. */
@media (min-width: 960px) {
    .sticky-panel {
        position: sticky;
        top: 80px;
        /* 176px = os 80px de folga da barra fixa + os ~96px entre o topo da página e o painel (título e
           margens). Com menos que isso o painel começa abaixo da dobra e acaba fora da janela em
           notebooks de 768px de altura, escondendo o botão de simular na primeira tela. */
        max-height: calc(100dvh - 176px);
        overflow-y: auto;
    }

    /* A ação principal do painel acompanha o rodapé dele enquanto os campos rolam por baixo. O fundo é
       o da superfície do tema, para os campos não aparecerem através do botão. */
    .sticky-panel .sticky-panel__action {
        position: sticky;
        bottom: 0;
        z-index: 1;
        padding-top: 0.75rem;
        background: var(--mud-palette-surface);
    }
}

/* Linhas de tabela como cartões, para telas estreitas. A tabela fica no desktop e a lista de cartões
   no celular (as duas no HTML, uma escondida por classe utilitária), em vez de uma tabela reescrita por
   CSS, que perde a semântica de tabela para leitores de tela. */
.data-cards {
    display: grid;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.data-card {
    padding: 0.75rem 1rem;
    border: 1px solid var(--viz-grid);
    border-radius: 8px;
    background: var(--viz-surface);
}

.data-card__title {
    margin: 0 0 0.5rem;
    font-weight: 700;
    line-height: 1.3;
}

/* O cartão que a tela quer que se escolha (o plano Pro em /pro). */
.data-card--highlight {
    border: 2px solid var(--mud-palette-primary);
}

.data-card dl {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.25rem 1rem;
    margin: 0;
}

.data-card dt {
    color: var(--viz-ink-muted);
    font-size: 0.8125rem;
}

.data-card dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.busy-button__spinner {
    height: 1.125rem;
    width: 1.125rem;
}

/* Texto só para leitores de tela: fora da vista, mas dentro da árvore de
   acessibilidade. `display:none` o removeria das duas. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   Consentimento, publicidade e páginas legais

   Usa as mesmas variáveis do restante da interface, que já trocam com o tema, para que a faixa de
   consentimento e o espaço de anúncio não fiquem claros numa página escura.
   ========================================================================== */

.consent-banner {
    position: fixed;
    inset: auto 0 0 0;

    /* Acima da barra (1300) e do menu (1302) do MudBlazor, e ABAIXO dos diálogos (1400): com 2000 a faixa ficava por cima de um
       diálogo aberto e, no celular, escondia os botões dele (medido na importação de contrato: "Entendi e enviar" inalcançável
       para quem ainda não tinha respondido ao consentimento). A faixa continua lá depois que o diálogo fecha. */
    z-index: 1350;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-end;
    justify-content: space-between;
    padding: 1.25rem 1.5rem;
    background: var(--viz-surface);
    color: var(--viz-ink);
    border-top: 3px solid var(--color-primary);
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.18);
}

.consent-banner__body {
    flex: 1 1 28rem;
    min-width: 0;
}

.consent-banner__title {
    margin: 0 0 0.35rem;
    font-size: 1rem;
    font-weight: 700;
}

.consent-banner__text {
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--viz-ink-secondary);
}

.consent-banner__options {
    margin-top: 0.75rem;
    max-height: 40vh;
    overflow-y: auto;
}

/* Os três botões partilham a linha e a largura mínima. Um "recusar" menor ou mais apagado que o
   "aceitar" é o padrão escuro que as autoridades europeias tratam como consentimento não obtido. */
.consent-banner__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

    .consent-banner__actions .mud-button-root {
        min-width: 9rem;
    }

/* No celular a faixa tinha 40% da altura da tela (três botões empilhados) e cobria o primeiro botão da
   página. Recusar e aceitar dividem a linha em partes iguais — o mesmo tamanho, que é o que importa —
   e "gerenciar" desce para uma linha própria, abaixo deles. */
@media (max-width: 600px) {
    .consent-banner {
        gap: 0.5rem;
        padding: 0.875rem 1rem;
    }

    .consent-banner__title {
        margin-bottom: 0.2rem;
        font-size: 0.9375rem;
    }

    .consent-banner__text {
        font-size: 0.8rem;
        line-height: 1.4;
    }

    .consent-banner__options {
        margin-top: 0.5rem;
    }

    .consent-banner__actions {
        width: 100%;
        gap: 0.5rem;
    }

        .consent-banner__actions .mud-button-root {
            min-width: 0;
            flex: 1 1 calc(50% - 0.25rem);
        }

        /* "Gerenciar" (ou "salvar", com os detalhes abertos) e "cancelar" ficam cada um na sua linha,
           abaixo de recusar e aceitar. */
        .consent-banner__actions .consent-banner__secondary {
            order: 3;
            flex-basis: 100%;
        }

        .consent-banner__actions .consent-banner__cancel {
            order: 4;
            flex-basis: 100%;
        }
}

/* O ✓ do idioma ativo ocupa um espaço fixo, para os nomes não saltarem de uma linha para outra. */
.menu-option__check {
    display: inline-block;
    width: 1.5rem;
    vertical-align: middle;
}

/* O afastamento é parte da política, não estética: o AdSense trata clique acidental em anúncio
   colado a um elemento interativo como motivo de suspensão. */
.ad-slot {
    display: block;
    margin: 2.5rem 0;
    padding-top: 0.25rem;
    border-top: 1px solid var(--viz-grid);
    /* Reserva a altura antes de a resposta chegar, para o conteúdo abaixo não saltar. */
    min-height: 130px;
}

.ad-slot__label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.7rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--viz-ink-muted);
}

.ad-slot__unit {
    display: block;
    width: 100%;
    min-height: 100px;
}

.app-footer {
    margin-top: 3rem;
    padding: 2rem 1.5rem 2.5rem;
    border-top: 1px solid var(--viz-grid);
    background: var(--viz-plane);
    color: var(--viz-ink-muted);
    font-size: 0.8rem;
    text-align: center;
}

/* O espaço entre as linhas vem do preenchimento dos links (alvo de toque de ~34px, e não os 18px do texto
   solto): com o texto junto, tocar num link do rodapé no celular acertava o vizinho. */
.app-footer__links {
    display: flex;
    flex-wrap: wrap;
    gap: 0 1rem;
    justify-content: center;
    margin-bottom: 0.4rem;
}

    .app-footer__links a {
        padding: 0.5rem 0.25rem;
        color: var(--color-primary);
        text-decoration: none;
    }

        .app-footer__links a:hover,
        .app-footer__links a:focus {
            text-decoration: underline;
        }

:root[data-theme="dark"] .app-footer__links a,
:root:not([data-theme="light"]) .app-footer__links a {
    color: var(--viz-principal);
}

/* ── Menu lateral ──────────────────────────────────────────────────────────
   Subtítulos dos dois grupos e o cartão do Pro. Tudo pelas variáveis do MudBlazor, que já trocam
   com o tema: no escuro o primário é um azul claro com texto escuro, e o cartão acompanha. */
/* ── Menu de conta ─────────────────────────────────────────────────────────
   A inicial vai num círculo na cor da barra (claro no fundo escuro dela e vice-versa), e o cabeçalho do
   menu leva o e-mail inteiro, que a barra não comporta. */
.account-button {
    min-width: 0 !important;
    padding-inline: 4px !important;
}

.account-avatar {
    display: inline-grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #ffffff;
    color: var(--mud-palette-appbar-background);
    font-weight: 700;
    font-size: 0.8125rem;
}

.account-menu__head {
    display: grid;
    gap: 2px;
    max-width: 18rem;
    padding: 0.5rem 1rem 0.625rem;
    margin-bottom: 0.25rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.account-menu__head strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}

.account-menu__head span {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.account-menu__muted {
    color: var(--mud-palette-text-secondary);
}

.nav-subtitle {
    padding: 0.875rem 1rem 0.25rem;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.pro-promo {
    margin: 0.75rem;
    padding: 0.875rem;
    border-radius: 8px;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.pro-promo__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 0.25rem;
    font-weight: 700;
    font-size: 0.9375rem;
}

.pro-promo__text {
    margin: 0 0 0.75rem;
    font-size: 0.8125rem;
    line-height: 1.4;
}

/* O botão inverte as cores do cartão: fundo na cor do texto, texto na cor do fundo. */
.pro-promo .pro-promo__cta {
    background: var(--mud-palette-primary-text);
    color: var(--mud-palette-primary);
}

/* "Preferências de cookies" é um botão (faz algo, não leva a outra página) com a aparência dos links
   vizinhos. --color-primary já tem a versão clara no tema escuro. */
.app-footer__action {
    padding: 0.5rem 0.25rem;
    border: 0;
    background: none;
    font: inherit;
    color: var(--color-primary);
    cursor: pointer;
}

    .app-footer__action:hover,
    .app-footer__action:focus-visible {
        text-decoration: underline;
    }

.app-footer__notice {
    max-width: 60ch;
    margin: 0 auto 0.75rem;
    line-height: 1.5;
}

.app-footer__copyright {
    margin: 0;
}

/* As páginas legais são texto corrido, e a medida de linha é o que decide se elas serão lidas.
   Cerca de 70 caracteres é a faixa em que a leitura contínua não cansa. */
.legal-document {
    max-width: 70ch;
    color: var(--viz-ink);
    line-height: 1.65;
}

    .legal-document h1 {
        font-size: 1.9rem;
        font-weight: 700;
        color: var(--color-primary);
        margin-bottom: 0.35rem;
    }

    .legal-document h2 {
        font-size: 1.15rem;
        font-weight: 700;
        margin: 2rem 0 0.5rem;
    }

    .legal-document h3 {
        font-size: 0.95rem;
        font-weight: 700;
        margin: 1.25rem 0 0.4rem;
    }

    /* :not(.mud-button-root): um botão do MudBlazor com Href (o "Entrar" de /account/delete) também é um <a>
       e herdava a cor de link, que no escuro é o azul do próprio fundo do botão (1,16:1). */
    .legal-document a:not(.mud-button-root) {
        color: var(--color-primary);
    }

:root[data-theme="dark"] .legal-document a:not(.mud-button-root),
:root:not([data-theme="light"]) .legal-document a:not(.mud-button-root) {
    color: var(--viz-principal);
}

.legal-document__date {
    font-size: 0.8rem;
    color: var(--viz-ink-muted);
    margin-bottom: 1.25rem;
}

.legal-document__intro {
    font-size: 1rem;
    color: var(--viz-ink-secondary);
}

.legal-contact dt {
    font-weight: 700;
    margin-top: 0.6rem;
}

.legal-contact dd {
    margin: 0;
}

/* ── Estado vazio ──────────────────────────────────────────────────────────
   Para telas que ainda não têm nada a mostrar (hoje, Minhas dívidas de uma conta nova): o que fazer,
   em passos, e o botão da primeira etapa. Cores pelas variáveis do MudBlazor, que acompanham o tema. */
.empty-state {
    max-width: 30rem;
    margin-inline: auto;
    padding: 1.75rem 1.5rem 1.5rem;
    border-radius: 12px;
    background: var(--mud-palette-surface);
    box-shadow: var(--mud-elevation-1);
    text-align: center;
}

.empty-state__badge {
    display: inline-grid;
    place-items: center;
    width: 3.5rem;
    height: 3.5rem;
    margin-bottom: 0.75rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 16%, transparent);
    color: var(--mud-palette-primary);
}

.empty-state__title {
    margin: 0 0 0.375rem;
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.3;
}

.empty-state__body {
    margin: 0 auto 1.125rem;
    max-width: 34ch;
    color: var(--mud-palette-text-secondary);
}

.empty-state__steps {
    display: grid;
    gap: 0.75rem;
    margin: 0 0 1.25rem;
    padding: 0;
    list-style: none;
    text-align: left;
    counter-reset: step;
}

.empty-state__steps li {
    display: grid;
    grid-template-columns: 1.75rem 1fr;
    column-gap: 0.75rem;
    counter-increment: step;
}

.empty-state__steps li::before {
    content: counter(step);
    grid-row: span 2;
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-size: 0.8125rem;
    font-weight: 700;
}

.empty-state__steps strong {
    font-weight: 500;
}

.empty-state__steps span {
    color: var(--mud-palette-text-secondary);
    font-size: 0.875rem;
}

/* ── Campo com ajuda ───────────────────────────────────────────────────────
   O "?" fica dentro do campo, à esquerda da seta, e abre o exemplo. Depois do MudSelect no HTML e com
   z-index próprio, o clique nele não chega a abrir a lista. O texto de apoio ganha margem à direita
   por precaução em telas estreitas. */
.field-help {
    position: relative;
}

.field-help .field-help__open {
    position: absolute;
    top: 12px;
    right: 36px;
    z-index: 2;
}

/* Gráfico do diálogo "PRICE ou SAC?": barras SVG pelas mesmas variáveis dos demais gráficos. */
.amort-help__summary {
    margin: 0 0 0.75rem;
}

.amort-help__figure {
    margin: 0 0 0.75rem;
}

.amort-help__chart {
    display: block;
    width: 100%;
    height: auto;
}

.amort-help__axis {
    stroke: var(--viz-axis);
    stroke-width: 1;
}

.amort-help__bar--price {
    fill: var(--viz-principal);
}

.amort-help__bar--sac {
    fill: var(--viz-charges);
}

.amort-help__figure figcaption {
    margin-top: 0.25rem;
    font-size: 0.8125rem;
    color: var(--viz-ink-secondary);
}

.amort-help__example {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--viz-ink-muted);
}

/* ── Teclado e toque ───────────────────────────────────────────────────────
   O MudBlazor sinaliza o foco de botões, links e chips só com um tom de fundo (o mesmo do hover, quase
   imperceptível sobre o escuro); os campos de texto já mudam a borda e ficam como estão. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
.mud-chip:focus-visible,
.mud-nav-link:focus-visible,
.mud-expand-panel-header:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Dentro do menu lateral um anel para fora seria cortado pela borda da gaveta. */
.mud-nav-link:focus-visible {
    outline-offset: -2px;
}

/* Um painel recolhido (as "Opções avançadas" da Simulação, a tabela de amortização) tem altura zero mas os
   controles de dentro continuavam no Tab: quem navega por teclado parava em campos que não via, e o leitor
   de tela os lia. visibility:hidden os tira de ambos; o atraso deixa a animação de fechar terminar, e ao
   expandir o painel volta a ser visível na hora. */
.mud-expand-panel:not(.mud-panel-expanded) > .mud-collapse-container {
    visibility: hidden;
    transition: visibility 0s linear 0.3s;
}

/* O botão de tema mostra o sol no claro e a lua no escuro (ThemeSwitcher); o atributo é escrito no <head>. */
.theme-icon--dark {
    display: none;
}

:root[data-theme="dark"] .theme-icon--light {
    display: none;
}

:root[data-theme="dark"] .theme-icon--dark {
    display: inline-block;
}

/* No escuro a superfície dos cartões (#16213e) é quase igual ao fundo da página (#1a1a2e): 1,07:1 medido. A
   sombra não aparece sobre o escuro, e os cartões se perdiam no fundo (a imagem que originou esta rodada). Um
   filete de 1px, no tom das linhas do tema, separa os dois sem mexer em nada mais. As bordas já definidas na
   própria tag (o destaque em verde de Comparar, a barra lateral dos resumos) continuam valendo. */
:root[data-theme="dark"] .mud-card,
:root[data-theme="dark"] .mud-paper.mud-elevation-1,
:root[data-theme="dark"] .mud-paper.mud-elevation-2,
:root[data-theme="dark"] .mud-paper.mud-elevation-3,
:root[data-theme="dark"] .mud-paper.mud-elevation-4 {
    border: 1px solid var(--mud-palette-lines-default);
}

/* Alvo de toque de 44px na barra superior (o botão Entrar e o menu da conta tinham 36 a 37px). */
.appbar-login,
.account-button {
    min-height: 44px;
}

/* Quem tem sessão guardada (html[data-auth="1"], escrito no <head>) ainda não é reconhecido enquanto o
   WebAssembly carrega, e a barra pré-renderizada mostrava "Entrar" a quem já entrou. O botão fica oculto, mas
   ocupando o lugar do menu da conta, para a barra não se mexer quando o avatar chegar: o menu mede 62px, e o
   botão leva 8px de margem (ml-2), então 54px de largura. Medido: com 66px os botões de idioma e de tema
   deslocavam 12px na hidratação. */
html[data-auth="1"] .appbar-login {
    visibility: hidden;
    overflow: hidden;
    min-width: 0;
    width: 54px;
}

/* A faixa do controle deslizante tinha 22px de altura, abaixo dos 24px da WCAG 2.2: a área de toque cresce para 32px
   sem mudar o desenho (a trilha e o botão ficam centralizados). */
.mud-slider .mud-slider-input {
    height: 32px;
}

/* A marca na barra superior é um link de 32px; o espaço em volta dela é livre, então a área vira 44px. */
.mud-appbar .mud-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

/* O logo (escudo + nome) da barra: a altura manda e a largura acompanha (2,875:1, pelos atributos width/height da
   tag). Menor no celular, onde a barra é de 56px e divide a linha com o menu, o idioma, o tema e o botão Entrar. */
.app-brand__logo {
    display: block;
    height: 40px;
    width: auto;
}

@media (max-width: 599.98px) {
    .app-brand__logo {
        height: 32px;
    }
}

/* No toque, todo botão com texto ocupa pelo menos 44px de altura (os de texto e os pequenos tinham 36 a 37px).
   Os de ícone são tratados à parte, e quem usa mouse continua com a densidade de antes. */
@media (pointer: coarse) {
    .mud-button-root.mud-button {
        min-height: 44px;
    }
}

/* O "?" do campo de tipo de amortização tem 26px e fica dentro do campo: no toque, a área sensível cresce
   para 42px sem mudar o desenho (o botão já é posicionado, então o pseudo-elemento herda a posição). */
@media (pointer: coarse) {
    .field-help .field-help__open::after {
        content: "";
        position: absolute;
        inset: -8px;
    }
}

/* Entrar com Google / Facebook, abaixo do formulário de e-mail e senha. */
.social-login {
    margin-top: 1rem;
}

/* Enquanto a lista de provedores não chega, o espaço do divisor e dos dois botões fica reservado: o que vem
   abaixo (o link de cadastro) não dá um salto quando os botões aparecem. */
.social-login[aria-busy="true"] {
    min-height: 9.25rem;
}

.social-login__divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
    color: var(--color-muted);
    font-size: 0.875rem;
}

.social-login__divider::before,
.social-login__divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

.social-login__buttons {
    display: grid;
    gap: 0.75rem;
}

/* O nome de uma marca em caixa alta deixa de ser o nome dela; os outros botões do app continuam como estão. */
.social-login__button.mud-button-root {
    text-transform: none;
    font-weight: 500;
}

/* Segurança da conta: a lista de formas de entrar (senha e provedores), uma linha por forma. */
.security-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.security-list__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    padding: 0.75rem 0;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.security-list__row > div {
    flex: 1 1 14rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.security-list__hint {
    font-size: 0.8125rem;
}

/* Tela de atualização obrigatória (Components/UpdateRequired.razor): ocupa a janela inteira no lugar do aplicativo
   quando o servidor já não aceita esta versão (ver ClientVersionState). 100dvh, e não 100vh: no Android a barra do
   sistema muda a altura visível, e 100vh cortaria o botão. Fundo e texto vêm dos tokens do tema, que valem nos dois modos. */
.update-required {
    min-height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem 1rem;
    box-sizing: border-box;
    background: var(--color-bg);
    color: var(--color-text);
}

.update-required:focus {
    outline: none;
}

.update-required__card {
    width: 100%;
    max-width: 28rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* O MudIcon tem tamanho fixo em px; em rem o ícone acompanha a fonte grande do sistema. */
.update-required__icon.mud-icon-root {
    font-size: 3.5rem;
    width: 1em;
    height: 1em;
}

.update-required__note {
    opacity: 0.8;
}

/* Fonte grande do sistema em tela estreita (html[data-text-scale="large"], escrito pelo finasst-shell.js quando a fonte
   passa de 125%). A barra superior não cabia: em 360px com a fonte no máximo ela media 440px, e como a barra é fixa e
   mais larga que a janela, o "Entrar" ficava para fora da tela, sem como alcançá-lo (medido no emulador). Aqui a
   marca vira só o escudo (o logo é uma imagem de 2,875:1 com o escudo à esquerda, então basta recortá-la) e o botão
   Entrar fica só com o ícone, que tem o nome acessível no aria-label. Só abaixo de 480px: em tela larga a barra cabe.
   Media query e container query não enxergam o zoom de texto (medem em px/em especificados), por isso o atributo. */
@media (max-width: 480px) {
    html[data-text-scale="large"] .app-brand__logo {
        width: 30px;
        object-fit: cover;
        object-position: left center;
    }

    html[data-text-scale="large"] .appbar-login {
        min-width: 0;
        padding-inline: 8px;
    }

    html[data-text-scale="large"] .appbar-login .mud-button-label {
        font-size: 0;
    }

    html[data-text-scale="large"] .appbar-login .mud-button-icon-start {
        margin: 0;
    }
}

/* ---- Importação de contrato (PDF ou fotos) ---- */

/* O botão de importar fica na linha do título da Simulação, e não numa faixa acima do formulário: o painel fixo tem a altura
   medida para o Simular continuar à vista em notebooks de 768 px, e uma linha a mais antes dele o empurraria para baixo da
   dobra. Com a linha quebrando abaixo de uns 460 px, o botão desce para baixo do título no celular. */
.page-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1rem;
}

.page-heading > h1 {
    margin: 0;
}

.import-dialog p {
    margin: 0 0 0.75rem;
}

.import-dialog .import-dialog__muted {
    color: var(--viz-ink-muted);
}

.import-notice {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--viz-grid);
    border-radius: 8px;
}

.import-notice p {
    margin: 0;
    font-size: 0.875rem;
}

.import-notice .mud-icon-root {
    flex: none;
    margin-top: 2px;
}

/* A faixa de revisão ganha foco programático depois de uma importação (finasstA11y.focusId), para o leitor de tela anunciá-la.
   Sem contorno, como os alvos de rolagem: ninguém a focou, e um quadro preto em volta de um aviso parece erro. */
.import-review {
    scroll-margin-top: 72px;
    outline: none;
}

.import-picker {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.import-picker__label {
    font-weight: 500;
}

/* O <input type=file> nativo, estilizado, e não um botão que o imita: o teclado, o leitor de tela e o arrastar-e-soltar já
   funcionam. O botão de dentro é desenhado como os do MudBlazor. */
.import-picker input[type="file"] {
    box-sizing: border-box;
    width: 100%;
    padding: 0.75rem;
    border: 2px dashed var(--viz-grid);
    border-radius: 8px;
    color: inherit;
    font: inherit;
    background: transparent;

    /* Sem o texto nativo ("Nenhum arquivo escolhido"): numa tela estreita ele aparecia cortado ("Nenhu…olhido"), e os arquivos
       escolhidos já são listados logo abaixo, com tamanho e botão de remover. O botão de dentro volta ao tamanho normal. */
    font-size: 0;
}

.import-picker input[type="file"]:hover {
    border-color: var(--color-primary);
}

.import-picker input[type="file"]::file-selector-button {
    min-height: 36px;
    margin-right: 0.75rem;
    padding: 0 1rem;
    border: 1px solid var(--color-primary);
    border-radius: 4px;
    background: transparent;
    color: var(--color-primary);
    font: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
}

.import-picker input[type="file"]:disabled {
    opacity: 0.6;
}

.import-picker__hint {
    color: var(--viz-ink-muted);
    font-size: 0.8125rem;
}

.import-files {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin: 0.75rem 0 0;
    padding: 0;
    list-style: none;
}

.import-files__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

/* O nome é do arquivo da pessoa e pode ser longo: corta com reticências, e o tamanho e o botão de remover ficam sempre à vista. */
.import-files__name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.import-files__size {
    flex: none;
    color: var(--viz-ink-muted);
    font-size: 0.8125rem;
}

.import-warnings {
    margin: 0.25rem 0 0;
    padding-left: 1.25rem;
}

.import-warnings li {
    margin: 0.25rem 0;
}

/* A nota sob um campo importado diz de onde veio o valor. A cor é por token de alerta (contraste conferido nos dois temas), e a
   nota é sempre texto: a cor nunca é o único sinal. */
.import-note .mud-input-helper-text,
.import-note .import-note__text {
    font-weight: 500;
}

.import-note--assumed .mud-input-helper-text,
.import-note--assumed .import-note__text {
    color: var(--alert-warning);
}

.import-note--inferred .mud-input-helper-text,
.import-note--inferred .import-note__text {
    color: var(--alert-info);
}

.import-note--missing .mud-input-helper-text,
.import-note--missing .import-note__text {
    color: var(--alert-error);
}

.import-note__text {
    font-size: 0.75rem;
}

/* Editor de encargos. */
.charges-editor {
    padding-top: 0.5rem;
}

.charges-editor__empty {
    margin: 0.25rem 0 0.5rem;
    color: var(--viz-ink-muted);
    font-size: 0.875rem;
}

.charge-row {
    margin-bottom: 0.75rem;
    padding: 0.75rem;
    border: 1px solid var(--viz-grid);
    border-radius: 8px;
}
