/* =====================================================================
   GERADOR DE SENHAS — folha da página. 13/09/2026.

   A PALETA É DECLARADA AQUI, não herdada. Copiei uma vez um bloco de CSS
   entre folhas e deixei para trás as variáveis de que ele dependia: uma
   `var()` por definir invalida a propriedade inteira EM SILÊNCIO, e o botão
   ficou sem fundo nem moldura sem dar erro nenhum.

   O CARTÃO TEM TRÊS ZONAS, pela ordem da atenção de quem chega:
     1. a senha — o único artefacto da página — com a força e as acções
        logo por baixo dela;
     2. os controlos;
     3. o extra (a impressão digital), atrás de um risco.
   ===================================================================== */

#sn-generator, #sn-artigos, #sn-apoio, #sn-how, #sn-modal {
    --sn-ac:  #00acc8;   /* a acção */
    --sn-c:   #d60037;   /* a marca */
    --sn-t:   #1f2835;   /* o texto */
    --sn-l:   #edeff0;   /* o cinzento da casa */
    --sn-l2:  #e2e6ea;
    --sn-g:   #5b6879;
    --sn-g2:  #8b95a5;
    --sn-ok:  #1d8f4e;
    --sn-dig: #00788c;   /* os dígitos: o teal da casa escurecido até 5,17:1 */
}

#sn-generator, #sn-artigos, #sn-apoio { padding: 60px 0; }
#sn-generator { background: #fff; }
#sn-artigos { background: var(--sn-l); }
#sn-apoio   { background: #fff; }
#sn-generator, #sn-how, #sn-guardar, #sn-artigos, #sn-apoio { scroll-margin-top: 100px; }

/* =====================================================================
   O ESPAÇO DESENHADO NÃO É ESPAÇO DE TEXTO — apanhado pelo dono ao colar o
   cartão em texto: «Gerador de senhastudo acontece», «Forte102 bits».

   Num contentor `flex` os nós de texto que só têm espaços são deitados
   fora — não chegam a ser itens. O afastamento vem do `gap`, que é desenho
   e não texto. No ecrã lê-se bem; quando a página deixa de ser VISTA e
   passa a ser LIDA (copiar, leitor de ecrã, modo de leitura, tradutor) as
   palavras colam-se.

   A `.sn-vis` NÃO usa `position: absolute`: isso tira-a do fluxo e o
   separador ganha uma linha só para ele, que é pior. Letra de tamanho zero
   não ocupa nada, não se vê, e continua no texto e na mesma linha.
   ===================================================================== */
.sn-vis { font-size: 0; line-height: 0; letter-spacing: 0; }

/* =====================================================================
   O CARTÃO
   ===================================================================== */
/* A CAIXA E A DA CASA, lida do `gerador.css` do gerador de nomes -- branca,
   moldura fina de #dfe3e6, sombra leve, e CANTOS DIREITOS. A regra esta
   escrita no cabecalho dessa folha: «o tema nao arredonda nada: nem o campo
   de pesquisa, nem o botao, nem os cartoes. Uma pastilha arredondada no meio
   disto le-se como peca de outro sitio». O meu cartao tinha cantos de 18px,
   botoes em pastilha e uma barra escura no topo -- nada disso existe na casa.
   Tambem se foi a barra escura: a promessa que ela levava esta no subtitulo
   da seccao e no bloco «Esta senha nao sai daqui». */
.sn-cartao {
    max-width: 760px; margin: 0 auto;
    background: #fff;
    border: 1px solid #dfe3e6;
    box-shadow: 2px 12px 10px rgba(0, 0, 0, .06);
}


/* uma caixa so, com dois riscos finos -- em vez de tres faixas de cores
   diferentes, que era mais cromo do que informacao */
.sn-cartao__corpo { padding: 30px 30px 26px; background: #fff; }

/* =====================================================================
   A SENHA. É o único artefacto da página: tudo o resto é moldura.

   VISÍVEL, não escondida atrás de pontos: uma senha que se vai copiar tem
   de se poder ler para conferir, e ninguém a está a escrever — ela é
   gerada aqui.

   NÃO É UM `<input>` NEM UM `<textarea>`:
     - a 320px uma senha de 64 caracteres ocupa 571px num campo de 207, e
       um `<input>` não quebra linha;
     - um `<textarea>` quebra mas não deixa pintar caracteres um a um.

   E **NUNCA `display: flex`** — foi o erro mais caro desta página. Cada
   `<span>` de cor passava a item de flex, e o navegador mete quebra de
   linha entre itens ao extrair o texto: quem seleccionasse a senha com o
   rato copiava-a PARTIDA EM DEZ LINHAS. O botão de copiar não dava por
   nada, porque usa a cadeia guardada em memória.

   AS TRÊS CORES passaram pelo contraste antes de entrar (sobre branco):
   letras 14,86:1 · dígitos 5,17:1 · símbolos 5,36:1. E a cor nunca é a
   única pista: quem não as distinga lê a senha na mesma.
   ===================================================================== */
.sn-senha {
    display: block;
    font-family: "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
    font-size: 25px; font-weight: 700; line-height: 1.35;
    color: var(--sn-t); background: var(--sn-l);
    border: 1px solid var(--sn-l2);
    padding: 16px 18px;
    letter-spacing: .02em; font-variant-numeric: tabular-nums;
    word-break: break-all; white-space: pre-wrap;
    cursor: pointer; user-select: all; -webkit-user-select: all;
    min-height: 62px;
    transition: border-color .15s ease;
}
.sn-senha:hover { border-color: var(--sn-g2); }
.sn-senha:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; border-color: var(--sn-ac); }
.sn-senha .d { color: var(--sn-dig); }
.sn-senha .s { color: var(--sn-c); }

/* O PISCAR DA SENHA no cartao. Nao se animam os `<span>` um a um aqui: eles
   sao em linha e para os mexer teriam de ser `inline-block`, o que impede a
   quebra DENTRO de cada troco -- e a senha de 64 caracteres deixava de caber
   num telemovel. Anima-se o campo inteiro, que nao mexe com a quebra. */
@keyframes sn-pisca { from { background: #e6f6f9; } to { background: var(--sn-l); } }
.sn-senha--nova { animation: sn-pisca .45s ease-out; }

.sn-legenda { margin: 8px 2px 0; font-size: 12px; color: var(--sn-g); letter-spacing: .02em; }
.sn-legenda b { font-weight: 700; }
.sn-legenda b:first-of-type { color: var(--sn-dig); }
.sn-legenda b:last-of-type  { color: var(--sn-c); }

/* ---- a força ---- */
.sn-forca { margin: 18px 0 0; }
.sn-barra { height: 8px; background: var(--sn-l2); overflow: hidden; }
.sn-barra > i { display: block; height: 100%; width: 0; transition: width .25s ease, background .25s ease; }
.sn-barra--fraca    > i { background: #d93025; }
.sn-barra--razoavel > i { background: #f2a33c; }
.sn-barra--forte    > i { background: #2ecc71; }
.sn-barra--muito    > i { background: var(--sn-ok); }

/* TEXTO CORRIDO, NÃO FLEX — ver o bloco do espaço desenhado, acima. */
.sn-medida { margin: 10px 0 0; font-size: 14px; line-height: 1.7; color: var(--sn-g); }
.sn-medida b { color: var(--sn-t); font-size: 15px; }
.sn-medida span { font-size: 13px; }
.sn-medida .sn-supos b { font-size: 13px; }
.sn-ponto { color: var(--sn-g2); }

/* =====================================================================
   AS ACÇÕES, LOGO POR BAIXO DA SENHA.

   Na versão anterior o botão principal estava no FUNDO do cartão, a uns
   300px de onde se está a olhar, e havia um ícone de refazer em cima a
   fazer o mesmo que ele. Agora é uma fila só, colada ao artefacto.

   E os botões têm PALAVRAS. Um botão só com ícone obriga a adivinhar ou a
   passar o rato por cima — num telemóvel não há «por cima».
   ===================================================================== */
.sn-accoes { display: flex; gap: 10px; margin: 18px 0 0; flex-wrap: wrap; }

.sn-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 9px;
    height: 54px; padding: 0 26px;
    border: 1px solid var(--sn-l2); background: #fff; color: var(--sn-t);
    font-family: inherit; font-size: 14px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .02em; line-height: 1;
    cursor: pointer; text-decoration: none;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.sn-btn:hover, .sn-btn:focus-visible { background: var(--sn-t); border-color: var(--sn-t); color: #fff; text-decoration: none; }
.sn-btn:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }
.sn-btn[disabled] { opacity: .45; cursor: not-allowed; }
.sn-btn svg { flex: 0 0 auto; }

.sn-btn--p { flex: 1 1 auto; background: var(--sn-ac); border-color: var(--sn-ac); color: #fff; }
.sn-btn--p:hover, .sn-btn--p:focus-visible { background: #0bbdd9; border-color: #0bbdd9; color: #fff; }
.sn-btn--i { flex: 0 0 auto; width: 54px; padding: 0; }

/* O SINAL DE «COPIADO» NASCE NO PRÓPRIO BOTÃO. Antes só havia a linha de
   aviso: carregava-se em cima e a resposta aparecia longe dali. O aviso
   fica, porque é o que os leitores de ecrã anunciam. */
.sn-btn .sn-ico-b, .sn-icone .sn-ico-b { display: none; }
.sn-btn .sn-ico-a, .sn-btn .sn-ico-b,
.sn-icone .sn-ico-a, .sn-icone .sn-ico-b { align-items: center; justify-content: center; }
.sn-btn--feito, .sn-btn--feito:hover, .sn-btn--feito:focus-visible { background: var(--sn-ok); border-color: var(--sn-ok); color: #fff; }
.sn-btn--feito .sn-ico-a, .sn-icone--feito .sn-ico-a { display: none; }
.sn-btn--feito .sn-ico-b, .sn-icone--feito .sn-ico-b { display: inline-flex; }
.sn-icone--feito, .sn-icone--feito:hover, .sn-icone--feito:focus-visible { background: var(--sn-ok); border-color: var(--sn-ok); color: #fff; }

.sn-aviso { margin: 12px 0 0; font-size: 13px; text-align: center; }
.sn-aviso--bom { color: var(--sn-ok); }
.sn-aviso--mau { color: var(--sn-c); }
.sn-aviso[hidden] { display: none; }

/* =====================================================================
   OS CONTROLOS
   ===================================================================== */
.sn-controlos { padding: 24px 30px; background: #fff; border-top: 1px solid var(--sn-l2); }

.sn-comp { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 18px; }
.sn-comp label { flex: 0 0 auto; margin: 0; font-size: 14px; font-weight: 700; color: var(--sn-t); }
.sn-comp output {
    flex: 0 0 auto; min-width: 44px; text-align: center;
    font-size: 15px; font-weight: 700; color: #fff; background: var(--sn-t);
    padding: 5px 10px; font-variant-numeric: tabular-nums;
}

/* O cursor. O `accent-color` resolve os navegadores novos; a parte pintada à
   esquerda do puxador não é nativa em lado nenhum, por isso vai à mão com um
   gradiente cortado em `--sn-pc`, que o JS actualiza. */
/* OS CONTROLOS SAO CIANOS, NAO VERMELHOS. No gerador de nomes o ciano e a
   interaccao e o vermelho e a marca; ter aqui o cursor e as caixas em
   vermelho e o botao principal em ciano era dizer duas coisas ao mesmo
   tempo. O vermelho fica para a marca e para os simbolos da senha. */
#sn-comp {
    flex: 1 1 180px; min-width: 0; height: 6px;
    -webkit-appearance: none; appearance: none; accent-color: var(--sn-ac);
    background: var(--sn-l2);
    background-image: linear-gradient(var(--sn-ac), var(--sn-ac));
    background-size: var(--sn-pc, 50%) 100%; background-repeat: no-repeat;
    cursor: pointer;
}
#sn-comp::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 22px; height: 22px; border-radius: 50%;
    background: var(--sn-ac); border: 3px solid #fff;
    box-shadow: 0 2px 8px rgba(31, 40, 53, .3); cursor: pointer;
}
#sn-comp::-moz-range-thumb {
    width: 16px; height: 16px; border-radius: 50%;
    background: var(--sn-ac); border: 3px solid #fff;
    box-shadow: 0 2px 8px rgba(31, 40, 53, .3); cursor: pointer;
}
#sn-comp:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 4px; }

/* ATALHOS DE COMPRIMENTO. Arrastar um cursor até 32 é trabalho; os valores
   que as pessoas realmente escolhem são meia dúzia. */
.sn-atalhos { flex: 0 0 auto; display: flex; gap: 6px; }
/* as pastilhas dos atalhos passam a caixas direitas, como as dos estilos do
   gerador de nomes (9px 16px, moldura fina, sem raio) */
.sn-atalhos button {
    min-width: 44px; height: 34px; padding: 0 12px;
    border: 1px solid var(--sn-l2); background: #fff;
    font-size: 13px; font-weight: 700; color: var(--sn-g); cursor: pointer;
    font-variant-numeric: tabular-nums;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.sn-atalhos button:hover { border-color: var(--sn-t); color: var(--sn-t); }
.sn-atalhos button:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }
.sn-atalhos button[aria-pressed="true"] { background: var(--sn-ac); border-color: var(--sn-ac); color: #fff; }

.sn-caixas {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 10px 22px; margin: 0; padding: 0; list-style: none;
}
.sn-caixas li { margin: 0; }
.sn-caixas label { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 14px; font-weight: 400; color: var(--sn-t); cursor: pointer; }
.sn-caixas input { width: 18px; height: 18px; accent-color: var(--sn-ac); flex: 0 0 auto; margin: 0; cursor: pointer; }
/* O RÓTULO E O EXEMPLO NUM ITEM SÓ: eram dois itens de flex e o espaço entre
   eles vinha do `gap` — ao copiar saía «MaiúsculasA-Z». */
.sn-cx { min-width: 0; }
.sn-caixas code { font-size: 12px; color: var(--sn-g2); background: transparent; border: 0; padding: 0; white-space: nowrap; }

/* A ÚLTIMA OPÇÃO OCUPA A LINHA INTEIRA: não é um tipo de caractere como as
   outras quatro, é um filtro que se aplica a todas. E o rótulo é longo —
   numa coluna de 223px partia-se em três linhas. */
.sn-caixas li:last-child {
    grid-column: 1 / -1; margin-top: 4px; padding-top: 14px;
    border-top: 1px solid var(--sn-l2);
}

/* =====================================================================
   O EXTRA: a impressão digital. É secundária, por isso é a última.
   Vem escondida do servidor e só o JS a mostra, depois de confirmar que o
   navegador tem `crypto.subtle` — assim não fica um campo vazio à espera
   de nada num navegador que não o tenha.
   ===================================================================== */
.sn-extra { padding: 20px 30px 24px; background: #fff; border-top: 1px solid var(--sn-l2); }
.sn-hash { display: flex; align-items: center; gap: 10px; }
.sn-hash__r { flex: 0 0 auto; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--sn-g); }
.sn-alg {
    flex: 0 0 auto; height: 34px; padding: 0 8px;
    border: 1px solid var(--sn-l2); background: #fff;
    font-size: 12px; font-weight: 700; color: var(--sn-t); cursor: pointer;
}
.sn-alg:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 1px; }
/* `min-width: 0` porque um item de flex não encolhe abaixo do seu conteúdo
   sem isso — e um SHA-512 tem 128 caracteres, que rasgavam o cartão. */
.sn-hash__v {
    flex: 1 1 auto; min-width: 0;
    font-family: "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
    font-size: 12px; line-height: 1.5; color: var(--sn-t);
    background: transparent; border: 0; padding: 0;
    word-break: break-all; max-height: 4.5em; overflow-y: auto;
}
.sn-hash__nota { margin: 10px 2px 0; font-size: 12px; line-height: 1.55; color: var(--sn-g); }
.sn-hash__nota b { color: var(--sn-t); }

.sn-icone {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px;
    border: 1px solid var(--sn-l2); background: #fff; color: var(--sn-t);
    font-size: 16px; cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.sn-icone:hover, .sn-icone:focus-visible { background: var(--sn-t); border-color: var(--sn-t); color: #fff; outline: none; }
.sn-icone:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }
.sn-icone[disabled] { opacity: .45; cursor: not-allowed; }

/* =====================================================================
   A JANELA «VER EM GRANDE».

   PARA QUE SERVE: o momento em que uma senha gerada dói a sério é
   transcrevê-la para onde não se pode colar — um router, uma TV, outro
   computador, ou a ditá-la ao telefone. Em letra grande e de quatro em
   quatro não se perde o sítio.

   O NÚMERO DE CADA GRUPO VAI EM `::after` COM `attr()`, e não em texto:
   conteúdo gerado não entra na selecção nem no que se copia. Se fosse um
   `<span>` normal, seleccionar a senha trazia os números atrás — que é
   exactamente o defeito que já corrigi uma vez nesta página.

   E OS GRUPOS SÃO SEPARADOS POR MARGEM, NÃO POR ESPAÇOS: um espaço a
   sério ia parar à área de transferência e a senha copiada deixava de ser
   a senha.

   Vive no fim do conteúdo, fora do cartão: uma janela dentro de um
   elemento com `overflow` ou `transform` fica presa lá dentro, e o tema
   tem os dois por todo o lado.
   ===================================================================== */
.sn-modal { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: center; justify-content: center; padding: 20px; }
.sn-modal[hidden] { display: none; }
/* =====================================================================
   A ANIMACAO DA JANELA.

   Tinha so entrada na CAIXA: o fundo escuro aparecia de repente, o que da
   um salto, e ao fechar tudo desaparecia num fotograma. Agora o fundo
   esbate e a caixa sobe, e ao fechar fazem o contrario -- o JS espera que a
   animacao acabe antes de esconder (com um travao de tempo, para o caso de
   o `animationend` nao chegar).

   Duracoes curtas de proposito: 220ms a abrir, 160ms a fechar. Uma janela
   lenta e uma janela que estorva.
   ===================================================================== */
.sn-modal__fundo { position: absolute; inset: 0; background: rgba(16, 22, 30, .72); }

@keyframes sn-fundo-entra { from { opacity: 0; } to { opacity: 1; } }
@keyframes sn-fundo-sai   { from { opacity: 1; } to { opacity: 0; } }
@keyframes sn-cx-sai      { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(8px); } }

.sn-modal--abre  .sn-modal__cx    { animation: sn-entra .22s cubic-bezier(.2, .8, .3, 1); }
.sn-modal--abre  .sn-modal__fundo { animation: sn-fundo-entra .22s ease-out; }
.sn-modal--fecha .sn-modal__fundo { animation: sn-fundo-sai .16s ease-in forwards; }
.sn-modal--fecha .sn-modal__cx    { animation: sn-cx-sai .16s ease-in forwards; }

/* MOVIMENTO REDUZIDO: A JANELA CONTINUA A ANIMAR, SÓ QUE DISCRETA.

   A política da casa (26/08/2026) é «onde obedecer à definição apaga a
   funcionalidade, passa-se por cima; onde ela continua a cumprir o seu papel,
   respeita-se». Uma janela que aparece de repente não diz de onde veio nem
   que a página não mudou — o aparecer É a informação. Por isso fica: o que
   sai é o MOVIMENTO (o subir e o crescer), não o aparecer. Só opacidade, e em
   metade do tempo.

   Quem decide é o JS e não esta folha, porque só ele vê a chave
   `?rlxmotion=1` que o resto da casa usa para ver as animações mesmo com a
   definição ligada. */
@keyframes sn-entra-discreta { from { opacity: 0; } to { opacity: 1; } }
.sn-modal--discreto.sn-modal--abre  .sn-modal__cx    { animation: sn-entra-discreta .12s ease-out; }
.sn-modal--discreto.sn-modal--abre  .sn-modal__fundo { animation: sn-fundo-entra .12s ease-out; }
.sn-modal--discreto.sn-modal--fecha .sn-modal__cx    { animation: sn-fundo-sai .1s ease-in forwards; }
.sn-modal--discreto.sn-modal--fecha .sn-modal__fundo { animation: sn-fundo-sai .1s ease-in forwards; }

.sn-modal__cx {
    position: relative; z-index: 1;
    width: 100%; max-width: 720px; max-height: calc(100vh - 40px); overflow-y: auto;
    background: #fff; padding: 30px 32px 28px;
    box-shadow: 0 30px 80px rgba(0, 0, 0, .45);
    /* A ENTRADA NAO VIVE AQUI. Estava nesta regra base, e por isso a caixa
       levava a animacao SEMPRE -- inclusive depois de a classe passageira
       `sn-modal--abre` ser tirada. Como a animacao comeca em `opacity: 0`,
       bastava ela nao andar para a caixa ficar invisivel de vez. Agora a
       entrada so existe enquanto a classe existe, e o estado natural desta
       caixa e opaco. */
}
@keyframes sn-entra { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }

.sn-modal__x {
    position: absolute; top: 14px; right: 14px;
    width: 40px; height: 40px;
    border: 1px solid var(--sn-l2); background: #fff; color: var(--sn-g);
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
.sn-modal__x:hover, .sn-modal__x:focus-visible { background: var(--sn-t); border-color: var(--sn-t); color: #fff; outline: none; }
.sn-modal__x:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }

.sn-modal__cx h2 { margin: 0 46px 6px 0; font-size: 24px; line-height: 1.2; color: var(--sn-t); font-weight: 700; }
.sn-modal__p { margin: 0 0 20px; font-size: 14px; line-height: 1.6; color: var(--sn-g); max-width: 52ch; }
.sn-modal__h3 { margin: 26px 0 12px; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--sn-g); }

.sn-grande {
    background: var(--sn-l);
    font-family: "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
    font-size: 34px; font-weight: 700; line-height: 1.9;
    color: var(--sn-t);
    border: 1px solid var(--sn-l2);
    padding: 26px 22px 30px;
    letter-spacing: .04em; font-variant-numeric: tabular-nums;
    user-select: all; -webkit-user-select: all;
    word-break: break-all;
}
.sn-grande:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }
.sn-grande .g { position: relative; display: inline-block; margin: 0 22px 14px 0; }
.sn-grande .g::after {
    content: attr(data-n);
    position: absolute; left: 0; top: 100%; margin-top: -6px;
    font-size: 11px; font-weight: 400; letter-spacing: .04em;
    color: var(--sn-g2); user-select: none; -webkit-user-select: none;
}
.sn-grande .d { color: var(--sn-dig); }
.sn-grande .s { color: var(--sn-c); }

/* ---- as duas vistas: em grupos, ou soletrada ---- */
.sn-vistas { display: inline-flex; gap: 6px; margin: 0 0 14px; }
.sn-vistas button {
    border: 1px solid var(--sn-l2); background: #fff;
    height: 34px; padding: 0 16px; cursor: pointer;
    font-size: 13px; font-weight: 700; color: var(--sn-g);
    transition: background .15s ease, color .15s ease;
}
.sn-vistas button:hover { color: var(--sn-t); }
.sn-vistas button[aria-selected="true"] { background: var(--sn-ac); border-color: var(--sn-ac); color: #fff; }
.sn-vistas button:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }

/* SOLETRAR. É para isto que a janela existe: ditar a senha ao telefone ou
   escrevê-la noutro aparelho sem confundir o `l` com o `1`. Cada linha traz
   a posição, o caractere e o NOME dele — «cardinal», não «aquele
   quadradinho». A posição e o nome levam `user-select: none` para que
   seleccionar a lista continue a dar só a senha. */
.sn-soletra {
    margin: 0; padding: 14px; list-style: none;
    background: var(--sn-l); border: 1px solid var(--sn-l2);
    max-height: 46vh; overflow-y: auto;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 2px 14px;
    counter-reset: sn-pos;
}
.sn-soletra[hidden] { display: none; }
/* A LISTA INTEIRA NAO SE SELECCIONA, de propósito. Cada linha é um bloco,
   por isso seleccioná-la dava a senha com uma quebra de linha entre CADA
   caractere — «F\n5\nP\n$…» — que é a mesma armadilha que já corrigi no
   campo da senha. Aqui não há forma de a evitar sem desfazer a lista, e uma
   lista que copia mal é pior do que uma lista que não copia: o botão de
   copiar está logo por baixo e copia a senha certa. */
.sn-soletra { user-select: none; -webkit-user-select: none; }
.sn-soletra li {
    display: flex; align-items: baseline; gap: 10px;
    padding: 5px 8px; margin: 0;
}
.sn-soletra li:nth-child(odd) { background: rgba(255,255,255,.7); }
.sn-soletra li::before {
    content: counter(sn-pos); counter-increment: sn-pos;
    flex: 0 0 22px; text-align: right;
    font-size: 11px; color: var(--sn-g2); font-variant-numeric: tabular-nums;
    user-select: none; -webkit-user-select: none;
}
.sn-soletra .c {
    flex: 0 0 auto;
    font-family: "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
    font-size: 19px; font-weight: 700; color: var(--sn-t);
}
.sn-soletra .c.d { color: var(--sn-dig); }
.sn-soletra .c.s { color: var(--sn-c); }
.sn-soletra .n { flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--sn-g); user-select: none; -webkit-user-select: none; }

@keyframes sn-vista { from { opacity: 0; } to { opacity: 1; } }

/* =====================================================================
   AS ENTRADAS ESCALONADAS — ao gerar e ao soletrar.

   Cada grupo de quatro, e cada linha da soletração, sobe 6px e aparece com
   um atraso crescente. Não é enfeite: é o que diz «isto é novo, foi agora
   que mudou». Sem nada, gerar outra senha parecida não dá sinal nenhum.

   O ATRASO É LIMITADO no JS: numa senha de 64 seriam 16 grupos ou 64
   linhas, e um escalonamento por item punha a última a aparecer quase um
   segundo depois. Corta-se ao fim de uns quantos.

   A TRAVA É A MESMA DA JANELA, e pela mesma razão: a animação começa em
   opacidade zero, por isso só existe enquanto a classe `sn-entrada` estiver
   posta. O JS tira-a por relógio — que corre onde as animações não correm.
   Sem isto, uma animação que não ande deixava a SENHA invisível, que é o
   pior que esta página pode fazer.
   ===================================================================== */
@keyframes sn-sobe { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.sn-mov .sn-grande.sn-entrada .g,
.sn-mov .sn-soletra.sn-entrada li { animation: sn-sobe .26s ease-out backwards; }

/* =====================================================================
   O TOQUE. Tudo o que se carrega afunda um pixel enquanto o dedo (ou o
   rato) lá está. É a resposta mais barata que existe e a que falta mais
   vezes: sem ela não se sabe se o clique chegou a apanhar o botão.
   ===================================================================== */
.sn-mov .sn-btn, .sn-mov .sn-icone, .sn-mov .sn-atalhos button,
.sn-mov .sn-vistas button, .sn-mov .sn-abtn, .sn-mov .sn-modal__x,
.sn-mov .sn-senha { transition: transform .08s ease, background .15s ease, color .15s ease, border-color .15s ease; }

.sn-mov .sn-btn:active, .sn-mov .sn-icone:active, .sn-mov .sn-atalhos button:active,
.sn-mov .sn-vistas button:active, .sn-mov .sn-abtn:active,
.sn-mov .sn-modal__x:active, .sn-mov .sn-senha:active { transform: translateY(1px) scale(.995); }

/* a seta do «gerar outra» dá uma volta quando gera */
@keyframes sn-roda { from { transform: rotate(0); } to { transform: rotate(360deg); } }
.sn-mov .sn-btn--roda svg { animation: sn-roda .45s cubic-bezier(.3, .8, .3, 1); }
.sn-mov .sn-grande, .sn-mov .sn-soletra { animation: sn-vista .18s ease-out; }

.sn-modal__forca { margin: 12px 2px 0; font-size: 13px; color: var(--sn-g); }
.sn-modal__forca b { color: var(--sn-t); }

/* ---- as impressões digitais, fechadas por omissão ---- */
.sn-det { margin: 24px 0 0; border-top: 1px solid var(--sn-l2); padding-top: 16px; }
.sn-det > summary {
    cursor: pointer; list-style: none;
    font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: var(--sn-g); padding: 6px 0;
}
.sn-det > summary::-webkit-details-marker { display: none; }
.sn-det > summary::before { content: "▸ "; color: var(--sn-g2); }

.sn-det > summary:hover { color: var(--sn-t); }
.sn-det > summary:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }
/* A GAVETA CORRE A ALTURA. Um `<details>` nativo nao se anima -- o navegador
   troca o `display` do conteudo e pronto. O JS mede a altura do invólucro e
   corre-a de 0 ate ela (e ao contrario a fechar); estas duas linhas sao o que
   torna isso possivel sem saltos. */
.sn-det__cx { overflow: hidden; }
/* QUEM DECIDE E O JS, atraves da classe `sn-mov` na raiz: so ele ve a chave
   `?rlxmotion=1`, e uma consulta de media nao a pode ver. */
.sn-mov .sn-det--anima .sn-det__cx { transition: height .24s ease; }
.sn-det .sn-hashes { margin-top: 12px; }
.sn-det > summary::before { display: inline-block; }
.sn-mov .sn-det > summary::before { transition: transform .2s ease; }
.sn-det[open] > summary::before { content: "\25B8 "; transform: rotate(90deg); }

.sn-modal__accoes { display: flex; gap: 10px; margin: 18px 0 0; flex-wrap: wrap; }

.sn-hashes { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.sn-hashes li {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; background: var(--sn-l);
}
.sn-hashes b { flex: 0 0 74px; font-size: 12px; font-weight: 700; color: var(--sn-g); letter-spacing: .03em; }
.sn-hashes code {
    flex: 1 1 auto; min-width: 0;
    font-family: "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
    font-size: 11.5px; line-height: 1.5; color: var(--sn-t);
    background: transparent; border: 0; padding: 0; word-break: break-all;
}

/* =====================================================================
   AS TRÊS PORTAS DO FIM e os artigos
   ===================================================================== */
/* OS TRES CARTOES ACABAM TODOS NA MESMA LINHA.

   O que se via: os titulos dos artigos da base de conhecimento tem
   comprimentos muito diferentes (uns cabem numa linha, outros em duas), e o
   botao de cada cartao ficava a uma altura diferente -- tres «Ler o artigo»
   em escada. Medido a 13/09/2026: 457px, 479px e 479px.

   A receita e a da pagina de migracao, que foi onde este bloco nasceu: o
   cartao e uma COLUNA de flex, o titulo fica presoa DUAS linhas com
   `min-height` (para os curtos ocuparem o mesmo que os longos), o paragrafo
   leva `flex: 1` e empurra o botao para o fundo. Assim alinham mesmo quando
   o texto e desigual. */
.sn-apoio { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; margin: 0; padding: 0; list-style: none; align-items: stretch; }
.sn-apoio > li {
    border: 1px solid var(--sn-l2); padding: 24px 26px; background: #fff;
    display: flex; flex-direction: column;
}
.sn-apoio h3 {
    margin: 0 0 8px; font-size: 16px; line-height: 1.35; color: var(--sn-t);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; min-height: calc(1.35em * 2);
}
.sn-apoio p {
    margin: 0 0 16px; font-size: 14px; line-height: 1.6; color: var(--sn-g);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; min-height: calc(1.6em * 2);
    flex: 1 1 auto;
}
.sn-apoio .sn-abtn { margin-top: auto; align-self: flex-start; }
.sn-abtn {
    display: inline-flex; align-items: center; justify-content: center;
    height: 46px; padding: 0 22px;
    border: 1px solid var(--sn-ac); background: #fff;
    font-size: 13px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
    line-height: 1; color: var(--sn-ac); text-decoration: none;
    transition: background .15s ease, color .15s ease;
}
.sn-abtn:hover, .sn-abtn:focus { background: var(--sn-ac); color: #fff; text-decoration: none; }
.sn-abtn:focus-visible { outline: 3px solid var(--sn-ac); outline-offset: 2px; }

/* OS QUATRO BLOCOS ACABAM TODOS NA MESMA LINHA.

   Os textos foram escritos para caber em CINCO linhas na coluna de 210px, e
   os títulos numa. Isso não se mede em caracteres: «Nem vemos nem gravamos»
   e «Feita no seu navegador» têm os mesmos 22 caracteres e um deles parte em
   duas linhas, porque o que conta é a LARGURA das palavras. Mediu-se cada um
   com a fonte real da página, a 13/09/2026.

   O `min-height` é a rede: se um dia alguém escrever um texto mais curto,
   o bloco não encolhe e a fila não fica em escada. Se escrever um mais
   longo, cresce — e vê-se logo, que é o que se quer. */
/* =====================================================================
   OS QUATRO BLOCOS ACABAM NA MESMA LINHA POR DISPOSICAO, NAO POR CONTAGEM.

   Andei a afinar os textos ate darem o mesmo numero de linhas numa coluna de
   210px. Funciona a essa largura e desfaz-se em qualquer outra: a 768px o
   portugues dava 3 e 4 linhas, porque a coluna passa a 349px e as palavras
   nao quebram nos mesmos sitios. Perseguir isso com `min-height` por faixa e
   afinar texto para larguras que ninguem consegue prever.

   O tema poe os itens a `display: inline-table`, que os deixa cada um na sua
   altura. Passando a lista a `flex` com quebra, os itens da MESMA FILA
   esticam ate a altura do mais alto -- e ficam iguais com qualquer texto, em
   qualquer lingua e a qualquer largura. O `min-height` deixa de ser preciso.
   ===================================================================== */
#sn-how .list, #sn-guardar .list {
    display: flex; flex-wrap: wrap; align-items: stretch;
}
#sn-how .list > .item, #sn-guardar .list > .item {
    display: block;          /* era `inline-table`, que nao estica */
    float: none;
}

/* =====================================================================
   DUAS COLUNAS ENTRE OS 601 E OS 991px.

   O tema poe os quatro itens a `width: 25%` e nunca os reagrupa: a coluna
   vai encolhendo com a janela. Medido a 14/09/2026 na `/ng`:

     >= 992px   4 por fila, coluna 210px  — titulos numa linha, textos em 5,
                alturas iguais
        900px   4 por fila, coluna 193px  — titulos 1 e 2 linhas, 299/319px
        768px   4 por fila, coluna 160px  — titulos 1 e 2, textos 7 e 8,
                alturas 322/364/341
     <= 600px   1 por fila, coluna 560px  — tudo igual outra vez

   Uma coluna de 160px sao umas vinte letras por linha. E a mesma escolha do
   FAQ: ou se torce a redaccao ate caber em 160px, ou se deixa de insistir em
   quatro colunas onde quatro nao cabem. A 768px duas colunas dao uns 340px
   cada, que e onde o texto volta a respirar.

   Os itens sao `inline-table`, por isso muda-se a largura e eles reagrupam-se
   sozinhos. */
@media (min-width: 601px) and (max-width: 991px) {
    #sn-how .list > .item, #sn-guardar .list > .item { width: 50%; }
}

/* o `::after` fantasma do tema esconde-se (lição da /meu-ip e da /ai) */
#sn-how .extendable-list, #sn-guardar .extendable-list { padding-top: 50px; padding-bottom: 44px; }
#sn-how .item::after, #sn-guardar .item::after { display: none; }

/* =====================================================================
   ECRÃS ESTREITOS
   ===================================================================== */
/* A LINHA DA IMPRESSAO DIGITAL QUEBRA EM ECRA ESTREITO.

   Medido a 320px: a linha tem 262px, e o rotulo (127) mais o selector (87)
   mais o botao (40) mais os espacos ja pedem 294. O `<code>` encolhe a zero
   -- tem `min-width: 0` -- mas o rotulo e o selector nao encolhem, e o botao
   era empurrado 3px para FORA do ecra.

   Esta regra ja ca esteve e foi apagada por uma substituicao minha demasiado
   larga, sem dar erro nenhum. Ver a lista de regras obrigatorias no
   `instala.py`, que passou a recusar instalar sem ela. */
@media (max-width: 560px) {
    .sn-hash { flex-wrap: wrap; }
    .sn-hash__r { flex: 0 1 auto; }
    .sn-hash__v { flex: 1 1 100%; order: 3; margin-top: 8px; }
    .sn-icone--s { order: 2; margin-left: auto; }
}

/* AS PERGUNTAS EM COLUNA UNICA ABAIXO DOS 1200px.

   Onde as perguntas apertam nao e no ecra largo: e na faixa dos 992 aos
   1199px. Medido a 13/09/2026: a 1280 cada pergunta tem 498px e so uma
   partia; a 1100 tem 413px e partiam QUATRO. Abaixo dos 992 o tema ja
   empilha sozinho e a largura salta para 678.

   A escolha e entre torcer a redaccao de doze perguntas ate caberem em
   413px, ou deixar de insistir em duas colunas onde duas nao cabem. A
   segunda e a certa: o texto fica legivel e a regra vale para as perguntas
   que se acrescentarem amanha. */
@media (max-width: 1199px) {
    #sn-faq .col-md-6 { width: 100%; float: none; }
}

@media (max-width: 991px) {
    .sn-apoio { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
    #sn-generator, #sn-artigos, #sn-apoio { padding: 40px 0; }
    .sn-apoio { grid-template-columns: minmax(0, 1fr); gap: 18px; }
    .sn-apoio > li { padding: 20px 18px 16px; }
    .sn-abtn { display: flex; width: 100%; }

    .sn-cartao__corpo { padding: 22px 18px 20px; }
    .sn-controlos, .sn-extra { padding: 20px 18px; }
    .sn-senha { font-size: 19px; padding: 14px; min-height: 52px; }

    /* os dois botões com palavras lado a lado, o de ícone a seguir */
    .sn-btn { height: 50px; padding: 0 16px; font-size: 13px; }
    .sn-btn--p { flex: 1 1 100%; }
    .sn-btn--i { width: 50px; }
    #sn-refazer { flex: 1 1 auto; }

    .sn-comp { gap: 10px; }
    #sn-comp { flex: 1 1 100%; order: 4; margin-top: 4px; }
    .sn-atalhos { margin-left: auto; }

    .sn-modal { padding: 0; }
    .sn-modal__cx { max-width: none; max-height: 100vh; height: 100%; border-radius: 0; padding: 22px 18px 26px; overflow-y: auto; }
    .sn-modal__cx h2 { font-size: 20px; }
    .sn-grande { font-size: 26px; line-height: 1.95; padding: 20px 16px 26px; }
    .sn-grande .g { margin-right: 16px; }
    /* A 320px o botao de copiar de cada hash saia do ecra: o `<code>` nao
       encolhia porque um item de flex nao desce abaixo do seu conteudo sem
       `min-width: 0`, e o botao era empurrado para fora. Medido a
       13/09/2026. */
    .sn-hashes li { flex-wrap: wrap; gap: 4px 10px; }
    .sn-hashes b { flex: 1 1 100%; }
    .sn-hashes code { flex: 1 1 100%; }
    .sn-hashes .sn-icone { margin-left: auto; }
    .sn-soletra { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); max-height: 40vh; }
    .sn-vistas { display: flex; width: 100%; }
    .sn-vistas button { flex: 1 1 0; }
}

@media (max-width: 400px) {
    .sn-senha { font-size: 16px; }
    .sn-grande { font-size: 22px; }
    .sn-atalhos button { min-width: 36px; padding: 0 6px; }
}

@media (prefers-reduced-motion: reduce) {
    .sn-barra > i, .sn-btn, .sn-abtn, .sn-icone, .sn-atalhos button, .sn-senha { transition-duration: .01s; }
    /* O PISCAR DA SENHA FICA, tambem para quem pede menos movimento: e uma
       mudanca de COR, nao um movimento, e e o unico sinal de que a senha
       mudou quando a nova se parece com a velha. O que sai daqui e o que se
       MEXE -- o subir dos grupos, a volta da seta, o afundar dos botoes. */
    /* a janela NAO entra aqui: ver o bloco «movimento reduzido» acima --
       continua a esbater, so sem se mexer, e a chave `?rlxmotion=1` tem de
       poder passar por cima disto, o que o CSS sozinho nao sabe fazer */
    /* as vistas tambem saem: a classe `sn-mov` ja as cobre */
    /* a gaveta e a seta saem daqui: quem manda e a classe `sn-mov` posta
       pelo JS, que e o unico que ve a chave `?rlxmotion=1` */
    .sn-vistas button { transition-duration: .01s; }
    .wow, .animated { animation: none !important; visibility: visible !important; }
}

/* =====================================================================
   O `main#main` MEDIA ZERO — a secção do herói é `float: left` e o
   `article.content` que a contém não a fecha. Como o `#wrapper` da casa é
   `display: table`, o float a fugir parte a célula anónima e o `main#main`
   cai numa segunda coluna com largura 0. Fecha-se o float, que é a causa.
   ===================================================================== */
#home > article.content::after { content: ""; display: table; clear: both; }

/* a página não rola por trás da janela aberta */
body.sn-preso { overflow: hidden; }
