/*
    A identidade visual do SecurePassword, e as primitivas de formulário que as telas compartilham.

    O que é específico de uma tela vive no CSS com escopo do componente (`.razor.css`). O que está
    aqui é o que precisa ser o mesmo em todas: os tokens de cor e tipografia, o fundo, e os controles
    de formulário — porque um campo de senha que muda de aparência entre a tela de cadastro e a de
    destravar é um campo que o usuário não reconhece como o mesmo.
*/

/* ---------------------------------------------------------------------------------------------
   Tipografia — servida daqui, nunca de um CDN. Ver wwwroot/fonts/README.md.
   --------------------------------------------------------------------------------------------- */

@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 500 700;
    font-display: swap;
    src: url('../fonts/fraunces-latin.woff2') format('woff2');
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/inter-latin.woff2') format('woff2');
}

/* ---------------------------------------------------------------------------------------------
   Tokens
   --------------------------------------------------------------------------------------------- */

:root {
    /*
        Os cinco tokens abaixo aparecem também COM TRANSPARÊNCIA no CSS com escopo dos componentes
        — a tinta de fundo de um alerta, a borda de um cartão em erro, o véu da barra de navegação.
        Por isso eles são declarados em canais, e a cor sólida é derivada deles logo abaixo.

        O que isso conserta: antes, `--danger` era `#F87171` aqui e `rgba(248, 113, 113, 0.35)`
        redigitado em quatro arquivos de componente. Trocar a cor de perigo mudava o texto do alerta
        e deixava o fundo dele na cor antiga — a paleta tinha dois donos, e o segundo era invisível.
    */
    --bg-rgb: 14 17 32;
    --brass-rgb: 201 162 75;
    --ok-rgb: 74 222 128;
    --warn-rgb: 245 184 65;
    --danger-rgb: 248 113 113;

    --bg: rgb(var(--bg-rgb));
    --bg-2: #14172A;
    --surface: #1A1E34;
    --surface-hi: #232748;
    --brass: rgb(var(--brass-rgb));
    --brass-dim: #8A733A;
    --text: #EDEDF3;
    --muted: #8B90AC;
    --ok: rgb(var(--ok-rgb));
    --warn: rgb(var(--warn-rgb));
    --danger: rgb(var(--danger-rgb));
    --line: rgba(255, 255, 255, 0.07);
    --line-hi: rgba(255, 255, 255, 0.14);

    --display: 'Fraunces', Georgia, 'Times New Roman', serif;
    --body: 'Inter', 'Segoe UI', system-ui, sans-serif;
    /*
        A pilha monoespaçada começa por 'JetBrains Mono' — a fonte que a tela de segredos de projeto
        pede — e continua exatamente como estava. Ela NÃO é servida por esta aplicação, e a ausência
        é a mesma decisão do README das fontes: um `@font-face` apontando para um CDN contaria a um
        terceiro que alguém abriu este cofre, e empacotar mais um arquivo de fonte só para exibir
        valor de variável não paga o peso. Quem a tem instalada — que é o público desta tela — vê a
        fonte pedida; quem não tem cai no monoespaçado do sistema, e nada quebra.
    */
    --mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', 'Consolas', monospace;

    --radius: 12px;
    --radius-sm: 9px;

    /*
        O RECUO LATERAL DA PÁGINA, NUM LUGAR SÓ.

        É a distância entre a borda da caixa de leitura e o texto — a margem que sobra dos dois lados
        do conteúdo. Ele cresce com a tela porque o que ele equilibra também cresce: numa janela
        larga, um parágrafo que começa a 18px da borda parece encostado nela.

        Estava redigitado em NOVE regras entre o `LandingLayout` e o `Home`, e já divergia: 18px na
        seção comum, 22px na moldura de aviso, 28px e 30px nas mesmas duas acima de 640px. Ninguém
        veria a diferença de 2px, e é exatamente por isso que ela sobreviveu — e por isso que mudar o
        recuo exigia achar as nove.

        AS MOLDURAS USAM O MESMO RECUO, e não um próprio. O que ele alinha nelas é a BORDA, não o
        texto: a moldura é recuada do mesmo tanto que as seções sem contorno, então o contorno dela
        nasce exatamente onde começa o texto de todas as outras — e é essa linha, descendo a página
        inteira, que faz as seções parecerem uma página só. O texto DENTRO da moldura continua 22px
        (30px acima de 640) mais para dentro, porque esse é o respiro próprio dela; medido em 1440px,
        a seção comum escreve de 209 a 1217 e a moldura de 240 a 1186. Quem quiser as duas colunas de
        texto na mesma linha vertical está pedindo uma moldura sem respiro interno, que é uma moldura
        com o texto colado no contorno.

        Os 2px a mais que a moldura de aviso tinha no RECUO EXTERNO não eram decisão: eram 30 escrito
        ao lado de 28, e não apareciam porque 2px não aparecem. Com o recuo maior eles virariam 5, e
        aí apareceriam.
    */
    --gutter: 22px;

    /*
        A LARGURA DA CAIXA DE LEITURA. 1120px é o limite em que uma linha ainda é confortável com o
        corpo de 15px; acima disso as seções continuam centralizadas em vez de esticarem.

        Ela é um token porque as MOLDURAS precisam dela para se recuar: a borda de uma delas nasceria
        na borda da caixa, 56px à esquerda de onde começa todo o texto da página, e o desalinhamento
        aparece justamente na seção que tem contorno para ser vista.

        Elas levam as duas medidas, e cada uma cobre um lado: `width: 100% - 2 * var(--gutter)` é
        quem as recua ABAIXO de 1120px — sem ele a moldura volta a encostar nas duas bordas da janela
        no celular —, e `max-width: var(--shell) - 2 * var(--gutter)` é quem as segura acima disso.
        Com as duas, a borda delas fica na mesma linha vertical do texto em qualquer largura, e mexer
        no `--gutter` move as molduras junto sem consulta de mídia nenhuma.

        O preço está na altura do celular: a moldura da raiz perde 44px de largura numa tela de
        375px, e a raiz cresce cerca de 490px. Foi decidido assim — uma seção que sangra enquanto o
        resto recua parece defeito, e parecer defeito custa mais do que rolar.
    */
    --shell: 1120px;

    /*
        A MEDIDA DE LEITURA, NUM LUGAR SÓ.

        Estes quatro tokens são o teto de largura de TODO texto do produto — corpo, abertura e
        título. Antes eles estavam redigitados em nove valores diferentes espalhados por sete
        arquivos com escopo (46, 52, 54, 58, 62, 64, 66, 68 e 80 `ch`), e ajustar a medida exigia
        achar os sete: quem achasse seis deixava o sétimo divergindo em silêncio, que é o defeito
        descrito no topo deste arquivo para a paleta.

        `100%` É UMA DECISÃO, E ELA TEM UM PREÇO ESCRITO. Ele significa "o teto é o contêiner": o
        parágrafo vai de ponta a ponta da caixa de leitura, e não para no meio dela. A caixa é a
        `.shell`, de 1120px, então uma linha de corpo de 15px chega a cerca de 140 caracteres — bem
        acima dos 66 a 75 em que o olho encontra sozinho o começo da linha seguinte. Em troca, o
        parágrafo que ocupava quatro linhas ocupa duas, e a página encolhe na mesma proporção.

        Foi escolhido assim de propósito, depois de as alternativas terem sido medidas: com o teto em
        62ch sobrava quase metade da largura vazia à direita de cada parágrafo, e repartir o texto em
        duas colunas devolvia altura trocando um parágrafo largo por dois estreitos — o mesmo texto
        quebrado em mais linhas noutro lugar.

        ENQUANTO VALEREM `100%`, AS 31 DECLARAÇÕES QUE OS USAM NÃO RESTRINGEM NADA — `max-width: 100%`
        num elemento de bloco é o que ele já mede. Isso foi conferido: pôr os quatro tokens em `none`
        não muda uma caixa sequer nas quatro páginas públicas. Elas não são sobra a recolher: são o
        interruptor. Apagá-las devolve a medida ao estado que este token veio desfazer — nove números
        em sete arquivos com escopo —, e a próxima pessoa a querer um teto teria de reescrever os sete
        em vez de trocar uma linha.

        QUEM QUISER VOLTAR ATRÁS TROCA AQUI, E SÓ AQUI. Um valor em `ch` volta a valer para as
        quatro páginas públicas e para as telas internas no mesmo instante — a medida tem um dono, e
        é este. E quem trocar por um valor em `ch` MEDE o resultado (largura da caixa dividida pelo
        avanço médio do caractere, com a fonte já carregada) em vez de contar `ch`: o glifo `0` do
        Inter é um terço mais largo que a média das letras, e 62ch de um corpo de 15px dão 80
        caracteres por linha, não 62. A conta de cabeça erra por um terço, e erra para o lado de
        alargar.

        A compensação clássica de uma linha longa é MAIS ENTRELINHA — o respiro extra é o que ajuda
        o olho a achar o começo da linha seguinte. Ela não está aqui de propósito: entrelinha é
        altura, e altura é o que esta escolha veio devolver. Se as linhas longas ficarem difíceis de
        acompanhar, é o primeiro lugar a mexer, e não o teto de largura.
    */
    --measure: 100%;
    --measure-lead: 100%;
    --measure-title: 100%;
    --measure-title-lg: 100%;

    color-scheme: dark;
}

@media (min-width: 640px) {
    :root {
        --gutter: 40px;
    }
}

@media (min-width: 1000px) {
    :root {
        --gutter: 56px;
    }
}

*, *::before, *::after {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
}

body {
    min-height: 100vh;
    background:
        radial-gradient(1200px 600px at 15% -10%, rgba(201, 162, 75, 0.10), transparent 60%),
        radial-gradient(900px 500px at 90% 0%, rgba(90, 70, 180, 0.12), transparent 55%),
        var(--bg);
    background-attachment: fixed;
    color: var(--text);
    font-family: var(--body);
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/*
    `text-wrap: balance` reparte um título de duas ou três linhas em linhas do MESMO tamanho, em vez
    de deixar a última com uma palavra solta. É o que impede que alargar a medida de um título troque
    "três linhas curtas" por "duas linhas cheias e um órfão" — o navegador só faz isso até 6 linhas,
    e um título que passe disso não é um título. Onde não houver suporte, nada muda: a linha quebra
    onde quebrava antes.
*/
h1, h2, h3 {
    font-family: var(--display);
    font-weight: 600;
    margin: 0;
    text-wrap: balance;
}

a {
    color: var(--brass);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

/*
    O foco visível NUNCA é removido. Um `outline: none` numa tela de senha é o tipo de decisão
    estética que deixa de fora quem navega por teclado — e quem gerencia senhas navega por teclado.
*/
:focus-visible {
    outline: 2px solid var(--brass);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------------------------
   Formulário
   --------------------------------------------------------------------------------------------- */

.field {
    display: block;
    margin-bottom: 18px;
}

.field-label {
    display: block;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--muted);
    margin-bottom: 7px;
}

.input {
    display: block;
    width: 100%;
    padding: 11px 13px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    background: var(--bg-2);
    color: var(--text);
    font-family: inherit;
    font-size: 14.5px;
    transition: border-color .15s ease, background .15s ease;
}

.input::placeholder {
    color: rgba(139, 144, 172, 0.6);
}

.input:hover {
    border-color: var(--line-hi);
}

.input:focus {
    border-color: var(--brass);
    background: #12152a;
}

.input:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.field-hint {
    display: block;
    margin-top: 7px;
    font-size: 12.5px;
    color: var(--muted);
    line-height: 1.45;
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 12px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    background: var(--surface-hi);
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, color .15s ease, opacity .15s ease;
}

.btn:hover:not(:disabled) {
    border-color: var(--brass);
    color: var(--brass);
}

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

.btn-primary {
    background: linear-gradient(155deg, var(--brass), var(--brass-dim));
    border-color: transparent;
    color: #0E1120;
}

.btn-primary:hover:not(:disabled) {
    color: #0E1120;
    filter: brightness(1.08);
}

.btn-ghost {
    background: transparent;
    color: var(--muted);
    font-weight: 500;
}

/*
    O botão de uma ação destrutiva.

    Vermelho de contorno, e não vermelho sólido: um botão vermelho preenchido é o mais chamativo da
    tela, e a ação mais chamativa de um diálogo de exclusão não deve ser a exclusão. Quem quer
    confirmar acha; quem chegou por engano não é puxado para lá.
*/
.btn-danger {
    background: transparent;
    border-color: var(--danger);
    color: var(--danger);
}

.btn-danger:hover:not(:disabled) {
    background: rgba(248, 113, 113, 0.12);
    border-color: var(--danger);
    color: var(--danger);
}

.btn-inline {
    width: auto;
    padding: 9px 14px;
    font-size: 13px;
}

/* Girinho do botão em espera. `prefers-reduced-motion` para de girar; o botão continua desabilitado. */
.spinner {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid currentColor;
    border-top-color: transparent;
    animation: spin .7s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .spinner {
        animation: none;
    }

    * {
        transition-duration: 0.01ms !important;
    }
}

/* ---------------------------------------------------------------------------------------------
   Blocos de texto do Blazor que não passam por componente
   --------------------------------------------------------------------------------------------- */

.mono {
    font-family: var(--mono);
}

/*
    Visível apenas para leitor de tela.

    Existe porque parte da informação desta interface é puramente visual: as bolinhas do campo de
    senha são `aria-hidden`, e sem um texto ao lado delas quem usa leitor de tela ouviria um campo
    vazio — sem saber se a senha está oculta ou se o item não tem senha. `display: none` não serve:
    ele esconde de todo mundo, inclusive de quem precisa.
*/
.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;
}

#blazor-error-ui {
    background: var(--surface);
    border-top: 1px solid var(--danger);
    color: var(--text);
    bottom: 0;
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.8rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    font-size: 13.5px;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.65rem;
}

.blazor-error-boundary {
    background: var(--surface);
    border: 1px solid var(--danger);
    border-radius: var(--radius);
    padding: 1rem;
    color: var(--text);
}

.blazor-error-boundary::after {
    content: "Algo deu errado nesta tela.";
}

.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 30vh 0 auto 0;
    margin: 0 auto;
}

.loading-progress circle {
    fill: none;
    stroke: rgba(255, 255, 255, 0.08);
    stroke-width: 0.4rem;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.loading-progress circle:last-child {
    stroke: #C9A24B;
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
    transition: stroke-dasharray 0.05s ease-in-out;
}

.loading-progress-text {
    position: absolute;
    text-align: center;
    inset: calc(30vh + 3.4rem) 0 auto 0;
    font-family: 'Fraunces', Georgia, serif;
    color: #8B90AC;
    font-size: 13px;
}

.loading-progress-text:after {
    content: var(--blazor-load-percentage-text, "Carregando");
}
