/* css/tutorial-sitio.css — a folha das QUATRO páginas internas de tutorial
   (nextcloud, obsidian-claude-code, tailscale, whisper) no terreno do sítio.

   Carregada por último, DEPOIS de:
     /ds/sitio/tokens.css → sistema.css → elementos.css → elementos-sitio.css
     → /css/sitio-web.css
   com `class="sitio"` no <body>. Fora dessa ordem a cascata inverte.

   ── Por que uma folha nova, e não `css/tutorials.css` ────────────────────
   `css/tutorials.css` fala o pacote ANTIGO (`/ds/`, `class="mesa"`): tokens
   com os MESMOS nomes e VALORES diferentes (--mesa é #343434 lá e #04080c
   aqui). Ela continua servindo `tutoriais/index.html`, o hub, que ainda não
   migrou. Reescrevê-la trocaria a cor do hub em silêncio — nenhum erro,
   nenhum teste vermelho, só o tom errado. Por isso: folha nova, e a antiga
   intocada até o hub migrar.

   ── O que o pacote do sítio TEM, e este arquivo NÃO redesenha ────────────
   Usados como vêm, sem cópia local:
     .cromo/.cromo__*  cabeçalho          .rodape       rodapé
     .janela e .janela__  bloco de código  .medidor__   ficha técnica da capa
     .acao/--sinal/--traco  botões        .chip         etiqueta
     .secao__marcador/__numero/__nome     .sitio__miolo largura da página
     .pinta/.imprime   entrada declarativa (só na capa)

   ── O que o pacote NÃO tem, e por isso é escrito à mão aqui ──────────────
   Vazio DECLARADO, não desenho inventado que finge ser do sistema. O kit do
   sítio é de home: não existe peça de leitura longa nele. Faltam, e são
   construídos abaixo só com tokens `--sitio-*`:
     · sumário (índice lateral com posição de leitura)
     · prosa longa (medida de linha, escala de títulos, listas, código em linha)
     · passo numerado de procedimento
     · recado (dica · nota · atenção)
     · tabela
     · barra de progresso de leitura
     · o tamanho do guia na capa (contagem de seções, passos e comandos)
     · caixa de checagem, lista de checagem e contagem de "quanto falta"
     · barra de comparação dentro da célula de tabela
     · tabela empilhada em cartão no celular
   Nenhum deles ganhou nome de família do pacote (`.janela__algo` etc.): todos
   moram no prefixo `.tut-`, pra ninguém confundir folha de página com pacote.

   ── Uma duplicação conhecida, e como resolvê-la ──────────────────────────
   O bloco "Cromo" abaixo é cópia de `css/home.css` (pular-para-o-conteúdo,
   botão compacto, painel do menu, .ico). Essas regras são de CHROME, não da
   home — mas moram lá, e `css/home.css` é de outra frente.

   A conversão do HUB de tutoriais, feita em paralelo, extraiu exatamente
   essas regras para uma folha compartilhada, `css/sitio-chrome.css`. Esta
   folha NÃO a linka porque ela não existe nesta árvore: apontar pra um
   arquivo ausente daria 404 em produção se as duas frentes não fossem
   juntas, e deixaria as quatro páginas sem menu compacto aqui, onde tudo
   foi medido. Depois do merge, o acerto é de três linhas:

     1. apagar o bloco "Cromo" INTEIRO: da linha do cabeçalho `══ Cromo ══`
        até o `}` que fecha o `@media (max-width: 1180px)` logo abaixo de
        `.cromo__nav`. (A rodada 1 dizia "até a linha do `.ico`, inclusive" —
        e o `.ico` é a PRIMEIRA regra do bloco, não a última: quem seguisse ao
        pé da letra apagaria três linhas e deixaria as outras oitenta
        duplicadas.) NÃO apagar a regra `.cromo { position: sticky }` que vem
        depois do bloco: ela é divergência deliberada destas páginas, e o
        comentário dela explica por quê.
     2. pôr `<link rel="stylesheet" href="/css/sitio-chrome.css">` ANTES de
        `/css/tutorial-sitio.css` nas quatro páginas;
     3. acrescentar esse href a ORDEM_ESPERADA em
        tests/test_tutoriais_sitio.py.

   Até lá as duas cópias são idênticas e conviver com as duas é inócuo — a
   desta folha carrega depois e declara os mesmos valores. Conferido
   declaração por declaração na verificação da rodada 1: 98 tokens contra 98,
   diff vazio.

   Uma armadilha nessa troca, que outra superfície já pagou: a folha da `main`
   declara `.cromo__nav { display: grid }` abaixo de 1180px. Aqui isso é o
   comportamento CERTO e medido — abaixo de 1180 o menu vira painel revelável e
   os elos empilham dentro dele. Quem for consolidar não deve "desfazer" essa
   regra achando que ela quebrou a barra: nestas páginas a barra horizontal não
   existe abaixo de 1180.

   ── Um token do pacote que NÃO serve pra texto aqui ──────────────────────
   `--sitio-tinta-fraca` (#5b6169) sobre `--sitio-fundo` (#04080c) mede
   3,21:1 — MEDIDO, por tests/test_tutoriais_sitio.py, que reprovou a
   primeira versão desta folha. Passa o piso de 3:1 de elemento de interface
   e NÃO passa o de 4,5:1 de texto. Numa home ele cai em rótulo grande e
   esporádico; numa página de leitura longa ele cairia no sumário inteiro, no
   cabeçalho de toda tabela e na ficha da capa — texto miúdo, e muito dele.
   Aqui a tinta secundária (#8b8f94, 6,18:1) faz esse papel, e a tinta fraca
   só sobrevive onde não é texto (borda no hover do botão compacto).

   ── A armadilha que pega quatro vezes nesta base ─────────────────────────
   `.sitio a` (elementos-sitio.css) tem especificidade (0,1,1) e pinta TODO
   link de âmbar. Uma classe sozinha, `.tut-toc-link` (0,1,0), PERDE — a cor
   declarada nela nunca aplica, sem erro nenhum. Todo link com cor própria
   aqui é escopado com o elemento: `.sitio a.tut-toc-link` (0,2,1). */

/* ══ Cromo — cópia isolada de css/home.css ═══════════════════════════════ */

.ico { width: 1em; height: 1em; flex: none; }

a.cromo__marca,
a.cromo__marca:hover {
  color: var(--sitio-tinta-cheia);
  text-decoration: none;
}

.sitio__pular {
  position: absolute;
  left: -9999px;
}
.sitio__pular:focus {
  position: fixed;
  left: 16px;
  top: 16px;
  z-index: 100;
  padding: 12px 16px;
  border-radius: var(--sitio-raio-fino);
  background: var(--sitio-sinal);
  color: var(--sobre-sinal);
}

.cromo__compacto { display: none; }
.cromo__menu { display: contents; }

.cromo__compacto {
  width: 40px;
  height: 40px;
  border: 1px solid var(--sitio-traco-forte);
  border-radius: var(--sitio-raio-fino);
  background-color: var(--sitio-superficie);
  cursor: pointer;
  transition: border-color var(--t-toque) var(--e-entrada);
}
.cromo__compacto:hover { border-color: var(--sitio-tinta-fraca); }

.cromo__compacto-icone,
.cromo__compacto-icone::before,
.cromo__compacto-icone::after {
  content: "";
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 1px;
  background-color: var(--sitio-tinta-cheia);
  transition: transform var(--t-toque) var(--e-entrada), opacity var(--t-toque) var(--e-entrada), top var(--t-toque) var(--e-entrada);
}
.cromo__compacto-icone { position: relative; }
.cromo__compacto-icone::before,
.cromo__compacto-icone::after { position: absolute; left: 0; }
.cromo__compacto-icone::before { top: -6px; }
.cromo__compacto-icone::after { top: 6px; }

.cromo__compacto[aria-expanded="true"] .cromo__compacto-icone {
  background-color: transparent;
}
.cromo__compacto[aria-expanded="true"] .cromo__compacto-icone::before {
  top: 0;
  transform: rotate(45deg);
}
.cromo__compacto[aria-expanded="true"] .cromo__compacto-icone::after {
  top: 0;
  transform: rotate(-45deg);
}

@media (max-width: 1180px) {
  .cromo__compacto { display: grid; place-items: center; }
  .cromo__menu {
    display: none;
    position: absolute;
    inset-inline: 0;
    top: var(--sitio-cromo-altura);
    padding: 16px var(--sitio-sangria) 24px;
    background: var(--sitio-cromo);
    border-block: 1px solid var(--sitio-traco);
    box-shadow: var(--sitio-relevo);
  }
  .cromo__menu.is-open { display: grid; gap: 16px; }
  .cromo__nav { display: grid; gap: 4px; }
}

/* ── O cabeçalho GRUDA, e só nestas páginas ──────────────────────────────
   Na home `.cromo` é `position:relative` e rola embora: lá a navegação está
   ao alcance porque a página é curta e termina no rodapé. Aqui a página tem
   10 mil pixels de altura e a pessoa está seguindo um procedimento — voltar
   pro hub, ou abrir o sumário compacto, não pode custar uma rolagem de volta
   ao topo. Era o comportamento da folha antiga (`chrome.css .topo`:
   sticky/top 0/z-index 20) e ele se mantém.

   O painel do menu compacto é `position:absolute` ancorado no `.cromo`
   (regra copiada acima); com o cabeçalho grudado ele acompanha, porque
   `sticky` mantém o elemento no fluxo e continua sendo o bloco contido. */
.cromo {
  position: sticky;
  top: 0;
}

/* ══ O anel de foco ══════════════════════════════════════════════════════
   Uma REGRESSÃO da conversão, achada na verificação da rodada 1 e reposta
   aqui. A trilha antiga tinha foco global (`css/ds-web.css:76`):

     :focus-visible { outline: 2px solid var(--casa-texto); outline-offset: 2px; }

   A trilha do sítio não tem equivalente: `css/sitio-web.css` só trata
   `.prompt__entrada` e `.acao--casa`, e o pacote compilado não trata nada —
   a home passa com o padrão do agente porque tem poucos pontos de foco.
   Estas páginas não: `js/tutorial.js` põe `tabindex="0"` em todo bloco de
   código e caixa de tabela que transborda — MEDIDO, 15 paradas de tabulação
   novas só no whisper a 390px. A conversão criou um monte de foco em
   elementos grandes e escuros e, na mesma passada, tirou a única regra que
   garantia que esse foco fosse visível. No Chromium o padrão ainda desenha
   um halo branco por fora; em outros navegadores o `rgb(0,95,204)` do
   padrão sobre `#04080c` é quase invisível.

   `--sitio-sinal` não é cor nova: é o MESMO anel que `.prompt__entrada` e
   `.acao--casa` já usam em `css/sitio-web.css` — o vocabulário de "isto tem
   foco de teclado" do sítio inteiro, e não o "sinal de ação" da regra "um
   por vista". Contraste calculado pela fórmula da WCAG: 8,55:1 contra
   `--sitio-fundo` (#04080c), 8,30:1 contra `--sitio-superficie` e 7,89:1
   contra `--sitio-superficie-alta`, que é o pior caso desta folha (o fundo
   do numeral do passo). Todos muito acima do piso de 3:1 de indicador não
   textual.

   Escopado em `.sitio` (e não `:focus-visible` solto) porque esta folha é
   de página: uma regra sem escopo aqui vazaria pra qualquer documento que
   um dia carregue o arquivo. `:where()` no lado esquerdo mantém a
   especificidade em (0,1,0), então quem quiser um anel próprio — como
   `.acao--casa`, com raio de cápsula — continua vencendo. */
:where(.sitio) :focus-visible {
  outline: 2px solid var(--sitio-sinal);
  outline-offset: 2px;
}

/* ══ A barra de progresso de leitura ═════════════════════════════════════
   VAZIO DECLARADO: o pacote não tem medidor de progresso de rolagem —
   `.medidor` mede VALOR de conteúdo (inscritos, vídeos), não posição.
   Escrita à mão: fio de 2px colado embaixo do cabeçalho grudado, na cor de
   sinal do sítio. `transform: scaleX()` (não `width`) porque é a única
   propriedade que anima sem forçar layout a cada quadro de rolagem.

   Nasce em 0 e SÓ é preenchida por js/tutoriais/leitura.js. Sem JS ela fica
   invisível — um fio vazio é preferível a um fio mentiroso. */
.tut-progresso {
  position: sticky;
  top: var(--sitio-cromo-altura);
  z-index: 4;
  height: 2px;
  margin-bottom: -2px;
  background: transparent;
  pointer-events: none;
}

.tut-progresso__fio {
  display: block;
  height: 100%;
  background: var(--sitio-sinal);
  box-shadow: 0 0 12px -2px var(--sitio-sinal);
  transform: scaleX(var(--tut-lido, 0));
  transform-origin: 0 50%;
}

/* ══ A moldura da página ═════════════════════════════════════════════════ */

.tut-pagina {
  position: relative;
  z-index: 1;
  display: block;
  padding-block: 56px 96px;
}

/* ══ Capa ════════════════════════════════════════════════════════════════
   Sobre o terreno, sem cartão: a capa é a abertura da página, não um objeto
   pousado nela. O que fica em superfície é o que é OBJETO — a janela do
   vídeo, o sumário, o código. */

/* O sobrescrito das duas aberturas (capa e "Próximos passos"). `.lbl` é nome
   herdado da folha antiga e ficou na marcação: renomear não daria erro
   nenhum, e daria trabalho em quatro páginas por nada. Aqui ele recebe o
   papel de `.secao__marcador` do pacote — voz de sistema, caixa alta,
   espacejamento largo, na cor de sinal. */
.tut-pagina .lbl {
  margin: 0;
  font-family: var(--voz-sistema);
  font-size: var(--sitio-rotulo-corpo);
  line-height: var(--sitio-rotulo-entrelinha);
  letter-spacing: var(--sitio-rotulo-espacamento);
  text-transform: uppercase;
  color: var(--sitio-sinal);
}

/* Duas colunas, como o herói da home: texto à esquerda, a peça à direita.
   Empilhado, o vídeo empurrava a primeira seção de texto pra ~1000px abaixo
   da dobra — quem chegou pra LER precisava rolar uma tela inteira antes de
   ver a primeira linha do tutorial. Lado a lado, a capa inteira cabe numa
   tela de 900px de altura e a leitura começa logo abaixo. */
/* `start`, e não `center`. Centralizado, o vídeo era posicionado contra a
   ALTURA DA CAPA, que muda de página pra página com o tamanho do título e
   do deck: o Tailscale e o Nextcloud (deck de 4 linhas) punham o topo do
   vídeo em 199px, o Whisper (deck de 6) em 227px e o Obsidian (título de 3
   linhas) em 233px. Cada página sozinha parecia certa; o preço aparecia só
   ao passar de um tutorial pro outro, com o vídeo saltando de lugar embaixo
   de um cabeçalho que não tinha mudado. Numa SÉRIE, a borda de cima precisa
   ser a mesma sempre. */
.tut-abertura {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 520px);
  gap: 48px;
  align-items: start;
}

.tut-capa {
  display: grid;
  gap: 24px;
  align-content: center;
}

.tut-capa h1 {
  margin: 0;
  font-family: var(--voz-editorial);
  font-weight: 600;
  font-size: var(--sitio-manchete-corpo);
  line-height: var(--sitio-manchete-entrelinha);
  letter-spacing: -0.03em;
  font-variation-settings: "opsz" 92, "WONK" 0;
  color: var(--sitio-tinta-cheia);
  text-wrap: balance;
}

/* A única aparição de cor dentro da manchete. No terreno do sítio o realce
   é o âmbar do sinal, não a casa ciano da mesa de vídeo. */
.tut-capa h1 em {
  color: var(--sitio-sinal);
  font-style: normal;
}

.tut-lead {
  margin: 0;
  max-width: 60ch;
  font-size: var(--sitio-deck-corpo);
  line-height: var(--sitio-deck-entrelinha);
  color: var(--sitio-tinta-secundaria);
}

/* A ficha técnica usa `.medidor` do pacote: cada item é chave + valor, com
   fio de separação — a mesma peça que a home usa pras métricas do canal.
   Aqui as chaves são tempo de leitura, nível e revisão. */
.tut-capa .medidor {
  flex-wrap: wrap;
  gap: 12px 28px;
}

.tut-capa .medidor__valor {
  font-size: 15px;
  line-height: 24px;
  font-family: var(--voz-funcional);
}

/* A chave do medidor vem em `--sitio-tinta-fraca` do pacote — 3,21:1 sobre o
   terreno, medido. Ver a nota do topo: aqui é texto de 12px, e texto de 12px
   precisa de 4,5:1. Escopado a estas páginas; o medidor da home não é
   tocado. */
.tut-capa .medidor__chave {
  color: var(--sitio-tinta-secundaria);
}

/* ── A janela do vídeo ───────────────────────────────────────────────────
   Objeto: sobe pra superfície, com o relevo do sítio. */
.tut-video {
  border-radius: var(--sitio-raio);
  overflow: hidden;
  background: var(--sitio-superficie);
  box-shadow: var(--sitio-relevo), var(--sitio-luz-de-bordo);
}

.tut-embed {
  display: block;
  aspect-ratio: 16 / 9;
}

.tut-embed iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ══ O tamanho do guia, na capa — VAZIO DECLARADO ════════════════════════
   O pacote tem `.medidor` (a ficha de leitura/nível/data), e ele responde
   "o que é isto". Não tem nada que responda "em que eu estou me metendo" —
   quantos passos são, e quanto vai pro terminal —, que é a pergunta que
   decide começar agora ou depois de almoçar.

   Uma linha só, em voz de sistema, logo abaixo da ficha, com o numeral em
   âmbar. Deliberadamente MENOR que o `.medidor`: é informação de apoio, não
   uma segunda ficha disputando a mesma leitura. Os números são contados do
   documento por js/tutoriais/leitura.js — escritos à mão, envelheceriam. */

.tut-mapa {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 16px 0 0;
  font-family: var(--voz-sistema);
  font-size: 12px;
  color: var(--sitio-tinta-secundaria);
}

.tut-mapa span {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}

.tut-mapa b {
  color: var(--sitio-sinal);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* Ponto médio entre um dado e outro: separador que não é borda nem barra
   vertical (o `.medidor` do pacote já usa fio vertical, e repetir aqui faria
   as duas peças parecerem a mesma). */
.tut-mapa span + span::before {
  content: "·";
  color: var(--sitio-traco-forte);
}

/* ══ A grade da leitura: sumário à esquerda, prosa à direita ═════════════ */

.tut-layout {
  margin-top: 64px;
  display: grid;
  grid-template-columns: 264px minmax(0, 1fr);
  gap: 56px;
  align-items: start;
}

/* ══ Sumário — VAZIO DECLARADO ═══════════════════════════════════════════
   O pacote não tem índice de leitura. Escrito à mão, e desenhado pra
   responder a pergunta que a régua nova faz: "onde eu parei?".

   O sumário é um TRILHO, não uma lista de links. O fio à esquerda mostra o
   caminho inteiro; a parte já percorrida acende em âmbar. Cada item ganha um
   estado de três: por ler (tinta fraca), lido (tinta secundária, com traço
   curto aceso) e atual (tinta cheia, marca cheia). `is-active` é posto pelo
   scroll-spy de js/tutorial.js — contrato que já existia — e `--visto` por
   js/tutoriais/leitura.js. */

.tut-toc-win {
  position: sticky;
  /* cabeçalho grudado (64) + respiro (24) */
  top: 88px;
  padding: 24px 20px;
  border-radius: var(--sitio-raio);
  background: var(--sitio-superficie);
  box-shadow: var(--sitio-relevo-baixo), var(--sitio-luz-de-bordo);
  /* Um sumário de 14 itens não cabe numa tela baixa; rolar dentro da caixa é
     melhor que estourar a altura da tela. */
  max-height: calc(100dvh - 128px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.tut-toc-cabeca {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 16px;
  font-family: var(--voz-sistema);
  font-size: var(--sitio-rotulo-corpo);
  line-height: var(--sitio-rotulo-entrelinha);
  letter-spacing: var(--sitio-rotulo-espacamento);
  text-transform: uppercase;
  color: var(--sitio-tinta-secundaria);
}

/* "03 / 10" — a contagem que js/tutoriais/leitura.js mantém. Sem JS o
   elemento nasce com o total já escrito na marcação, nunca vazio. */
.tut-toc-conta {
  color: var(--sitio-tinta-secundaria);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
}

.tut-toc {
  list-style: none;
  margin: 0;
  padding: 0;
  /* o trilho: um fio contínuo por trás dos marcadores */
  border-left: 1px solid var(--sitio-traco);
  padding-left: 0;
}

.tut-toc li { margin: 0; }

.sitio a.tut-toc-link {
  position: relative;
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  align-items: baseline;
  gap: 4px;
  padding: 7px 4px 7px 14px;
  color: var(--sitio-tinta-secundaria);
  font-family: var(--voz-funcional);
  font-size: 13.5px;
  line-height: 20px;
  text-decoration: none;
}

/* O marcador no trilho: um traço de 2px que cobre o fio cinza. Cresce e
   acende conforme o estado — geometria e cor, nunca ícone inventado. */
.sitio a.tut-toc-link::before {
  content: "";
  position: absolute;
  left: -1px;
  top: 12px;
  width: 2px;
  height: 10px;
  border-radius: 1px;
  background: transparent;
  transition: background-color var(--t-toque) var(--e-entrada);
}

.tut-toc-num {
  font-family: var(--voz-sistema);
  font-size: 11px;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: inherit;
}

.sitio a.tut-toc-link:hover {
  color: var(--sitio-tinta-cheia);
  background: color-mix(in srgb, var(--sitio-tinta-cheia) 4%, transparent);
  border-radius: var(--sitio-raio-miudo);
}

/* Já passou por aqui. A diferença mora no MARCADOR do trilho, não na tinta:
   a primeira versão escurecia o texto dos itens por ler, e aquilo media
   3,21:1 (ver a nota do topo). Um sumário de catorze itens em que doze estão
   abaixo do piso de contraste é pior de navegar do que um sem gradação
   nenhuma — a gradação passou pro fio, que não é texto e pode ser sutil. */
.sitio a.tut-toc-link[data-visto]::before {
  background: color-mix(in srgb, var(--sitio-sinal) 45%, transparent);
}

/* Está aqui agora. Posição de leitura é INFORMAÇÃO: tinta cheia e o
   marcador inteiro aceso, sem peso extra (negrito mudaria a largura da
   linha e faria o sumário tremer a cada seção). */
.sitio a.tut-toc-link.is-active {
  color: var(--sitio-tinta-cheia);
}
.sitio a.tut-toc-link.is-active::before {
  background: var(--sitio-sinal);
  top: 8px;
  height: 18px;
  box-shadow: 0 0 10px -1px var(--sitio-sinal);
}
.sitio a.tut-toc-link.is-active .tut-toc-num {
  color: var(--sitio-sinal);
}

/* ── O sumário compacto (abaixo de 1180px) ──────────────────────────────
   Um <details> grudado logo abaixo do cabeçalho. O resumo mostra a seção
   ATUAL — é o que responde "onde eu parei" quando não há coluna lateral. */

.tut-toc-mobile {
  display: none;
  position: sticky;
  top: calc(var(--sitio-cromo-altura) + 8px);
  z-index: 2;
  margin-bottom: 32px;
  border-radius: var(--sitio-raio-fino);
  border: 1px solid var(--sitio-traco);
  background: var(--sitio-superficie);
  box-shadow: var(--sitio-relevo-baixo), var(--sitio-luz-de-bordo);
}

.tut-toc-mobile summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 8px 16px;
  cursor: pointer;
  list-style: none;
  font-family: var(--voz-sistema);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sitio-tinta-secundaria);
}

.tut-toc-mobile summary::-webkit-details-marker { display: none; }

/* Onde a pessoa está, escrito no próprio resumo. */
.tut-toc-aqui {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--voz-funcional);
  font-size: 14px;
  color: var(--sitio-tinta-cheia);
}

.tut-toc-mobile summary::after {
  content: "";
  width: 8px;
  height: 8px;
  flex: none;
  border-right: 1.5px solid var(--sitio-tinta-secundaria);
  border-bottom: 1.5px solid var(--sitio-tinta-secundaria);
  transform: translateY(-2px) rotate(45deg);
}

.tut-toc-mobile[open] summary::after {
  transform: translateY(2px) rotate(-135deg);
}

.tut-toc-mobile .tut-toc {
  margin: 0 16px 16px;
  border-left-color: var(--sitio-traco);
}

/* ══ Prosa ═══════════════════════════════════════════════════════════════
   VAZIO DECLARADO: o pacote não tem tipografia de leitura longa. As medidas
   abaixo são de leitura, não de tela de produto:

   · MEDIDA DE LINHA em `ch`, não em px. O `.tut-prose` inteiro trava em
     68ch — dentro da faixa clássica de 45–75 caracteres. Em px o mesmo
     bloco media ~90 caracteres na largura antiga (medido: 696px a 15px), e
     linha longa demais é a forma mais comum de perder a linha seguinte num
     texto que a pessoa lê enquanto digita em outra janela.
   · ENTRELINHA de 28 sobre corpo de 16 (1,75). O pacote diz 16/24 (1,5),
     que é escala de INTERFACE. Texto corrido em 1,5 fecha demais.
   · O ritmo vertical é múltiplo de 4, como o sistema pede. */

/* A coluna inteira é larga; o TEXTO dentro dela é estreito. É a distinção
   que faz a diferença numa página de execução: parágrafo tem medida de
   leitura, e bloco de código e tabela não. O código quebrado em duas linhas
   porque a coluna do texto o apertou é pior que a linha longa que ele já
   era. Então prosa na medida, e as PEÇAS (janela de comando, tabela, vídeo)
   ocupam a coluna toda.

   `--tut-medida` existe porque `60ch` NÃO servia: `ch` é relativo à fonte
   DE CADA ELEMENTO, então a mesma declaração rendia 576px no parágrafo,
   684px no h3 e 1272px no h2 (cortado pela coluna em 860). Uma regra só
   produzia quatro bordas direitas diferentes, e lia como desalinho.

   O primeiro conserto deu uma medida de leitura única (36rem) ao texto e
   deixou as peças na coluna inteira: duas bordas em vez de quatro. O dono
   pediu outra coisa, duas vezes, e a dele é que vale: o texto tem a largura
   das JANELAS. Uma borda só, para tudo. Custa linha longa (a coluna de
   860px dá cerca de 90 caracteres, acima da faixa confortável de 45 a 75),
   e é o preço de o bloco de código, a tabela e o parágrafo começarem e
   terminarem no mesmo lugar. Em tela estreita a coluna encolhe sozinha e a
   linha volta ao tamanho normal. */
.tut-prose {
  --tut-medida: 100%;
  max-width: 860px;
  font-size: var(--sitio-corpo-corpo);
  line-height: 28px;
  color: var(--sitio-tinta-secundaria);
}

.tut-prose > section > :is(p, ul, ol, h2, h3, .tut-sec-num, .tut-callout),
.tut-step-body > :is(p, ul, ol, h3) {
  max-width: var(--tut-medida);
}

.tut-prose > section {
  position: relative;
  /* o cabeçalho grudado não pode tapar o título quando o sumário salta */
  scroll-margin-top: 104px;
}

.tut-prose > section + section {
  margin-top: 88px;
}

/* O número da seção, na voz de sistema — o mesmo papel de `.secao__numero`
   do pacote, sem herdar a peça inteira (`.secao` traz padding de home). */
.tut-sec-num {
  margin: 0 0 8px;
  font-family: var(--voz-sistema);
  font-size: var(--sitio-rotulo-corpo);
  line-height: var(--sitio-rotulo-entrelinha);
  letter-spacing: var(--sitio-rotulo-espacamento);
  color: var(--sitio-sinal);
  font-variant-numeric: tabular-nums;
}

.tut-prose h2 {
  margin: 0;
  font-family: var(--voz-editorial);
  font-weight: 600;
  font-size: clamp(28px, 2.2vw, 34px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--sitio-tinta-cheia);
  text-wrap: balance;
}

/* O h3 era 15px negrito — o MESMO corpo do texto ao redor, o que fazia o
   subtítulo desaparecer numa rolagem rápida. Sobe pro corpo de deck: dá
   degrau de verdade sem chegar perto do h2. */
.tut-prose h3 {
  margin: 48px 0 0;
  font-family: var(--voz-funcional);
  font-weight: 600;
  font-size: 19px;
  line-height: 28px;
  letter-spacing: -0.01em;
  color: var(--sitio-tinta-cheia);
}

/* ── A âncora de cada título ─────────────────────────────────────────────
   Quem segue um tutorial em duas sessões precisa marcar onde parou. Cada
   <h2> de seção ganha um "#" que é link permanente pra própria seção,
   posto por js/tutoriais/leitura.js. Fica invisível até o ponteiro chegar
   perto ou o teclado focar — nunca some de vez, pra continuar alcançável. */
.sitio a.tut-ancora {
  position: relative;
  margin-left: 0.4em;
  font-family: var(--voz-sistema);
  font-size: 0.5em;
  vertical-align: 0.25em;
  color: var(--sitio-tinta-secundaria);
  text-decoration: none;
  opacity: 0;
  transition: opacity var(--t-toque) var(--e-entrada);
}

/* Mesma história do botão "Copiar": o "#" desenhado mede 8×18 (medido), que
   é menor que o mínimo de 24×24 da WCAG 2.2 — passava só pela exceção de
   espaçamento. O alvo cresce num pseudo-elemento (24×26) e o glifo continua
   do tamanho que a composição pede. Deliberadamente MODESTO: a âncora nasce
   em opacity:0 e no toque não há hover pra revelá-la, então cada pixel a
   mais de alvo invisível é um toque acidental a mais perto do título. */
.sitio a.tut-ancora::after {
  content: "";
  position: absolute;
  inset: -4px -8px;
}

.tut-prose h2:hover .tut-ancora,
.tut-prose h2 .tut-ancora:focus-visible {
  opacity: 1;
}

.sitio a.tut-ancora:hover {
  color: var(--sitio-sinal);
}

.tut-prose p {
  margin: 24px 0 0;
}

.tut-prose strong {
  color: var(--sitio-tinta-cheia);
  font-weight: 600;
}

.tut-prose em { font-style: italic; }

.tut-prose ul,
.tut-prose ol {
  margin: 24px 0 0;
  padding-left: 22px;
}

.tut-prose li { margin: 8px 0 0; }
.tut-prose li:first-child { margin-top: 0; }

.tut-prose li::marker {
  color: var(--sitio-sinal);
}

/* Link no meio do texto: o âmbar de `.sitio a` já vem do pacote; o que falta
   é o sublinhado que separa link de palavra realçada. */
.tut-prose a:not([class]) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--sitio-sinal) 45%, transparent);
  text-underline-offset: 0.18em;
}

.tut-prose a:not([class]):hover,
.tut-prose a:not([class]):focus-visible {
  text-decoration-color: var(--sitio-sinal-forte);
  text-decoration-thickness: 2px;
}

/* Código em linha. `line-height: 0` não é enfeite — é o que segura a fase do
   ritmo vertical: uma caixa em linha com OUTRA família tipográfica participa
   da altura da linha pela própria base, e meio pixel por parágrafo vira
   defasagem visível três seções abaixo. Com altura zerada os glifos seguem
   desenhados e o parágrafo fecha no múltiplo certo. Padding só horizontal,
   pela mesma razão. */
.tut-prose code,
.tut-callout code,
.tut-step code,
.tut-table code {
  font-family: var(--voz-sistema);
  font-size: 0.86em;
  line-height: 0;
  color: var(--sitio-tinta-cheia);
  background: color-mix(in srgb, var(--sitio-tinta-cheia) 9%, transparent);
  border-radius: 4px;
  padding-inline: 0.34em;
  overflow-wrap: anywhere;
}

/* ══ Passo numerado — VAZIO DECLARADO ════════════════════════════════════
   O pacote não tem peça de procedimento. Escrito à mão como TRILHO: os
   números são contas ligadas por um fio, e o fio é o que diz "isto é uma
   sequência, e ela continua abaixo". É a peça que a régua da conversão
   cobra de verdade — a pessoa está executando com o terminal ao lado, e o
   que ela precisa é achar de volta o passo onde parou. */

.tut-step {
  position: relative;
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 20px;
  margin-top: 32px;
}

/* O fio que liga um passo ao seguinte, e SÓ quando existe um seguinte.
   `:has(+ .tut-step)` em vez de `:not(:last-child)` porque o passo não é
   necessariamente o último filho da seção — costuma vir um recado ou um
   bloco de código depois, e aí o fio desceria da última conta pra lugar
   nenhum. Se o navegador não entender `:has()`, a regra inteira é
   descartada: o trilho some, as contas continuam. Falha pro lado seguro. */
.tut-step:has(+ .tut-step)::before {
  content: "";
  position: absolute;
  left: 16px;
  top: 34px;
  /* alcança a conta do passo seguinte, atravessando o vão de 32 */
  bottom: -32px;
  width: 1px;
  background: var(--sitio-traco-forte);
}

.tut-step-num {
  position: relative;
  z-index: 1;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--sitio-traco-forte);
  background: var(--sitio-superficie-alta);
  color: var(--sitio-tinta-cheia);
  font-family: var(--voz-sistema);
  font-size: 13px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  box-shadow: var(--sitio-luz-de-bordo);
}

.tut-step-body > :first-child { margin-top: 0; }
.tut-step-body > h3 {
  font-size: 17px;
  line-height: 26px;
  /* alinha a base do título com o centro óptico do numeral */
  padding-top: 4px;
}

/* ══ Marcar o que já foi feito — VAZIO DECLARADO ═════════════════════════
   O pacote do sítio não tem caixa de seleção, nem lista de checagem, nem
   contagem de progresso de tarefa: ele é um kit de HOME, e home não tem
   ninguém executando nada. As três peças abaixo são escritas à mão, só com
   tokens `--sitio-*`, sob o prefixo `.tut-`.

   O QUE ELAS RESOLVEM. Um tutorial é uma sequência de coisas a fazer, e a
   página contava isso em prosa: parágrafos numerados e uma <ul> que só o olho
   separava do resto. "Quantos são, em qual estou, quanto falta" não tinha
   resposta em lugar nenhum — e é a pergunta que quem executa faz o tempo todo,
   porque sai da página pro terminal e volta.

   O ÚNICO ícone é o `ico-check` do sprite do site, que já existe. Nada de
   glifo desenhado à mão fingindo ser do sistema. */

/* ── A contagem, antes do grupo que ela conta ──────────────────────────── */
.tut-feitos {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 32px 0 0;
  font-family: var(--voz-sistema);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sitio-tinta-secundaria);
}

.tut-feitos-nome { flex: none; }

/* O fio enche na proporção do feito. É o mesmo vocabulário do trilho do
   sumário e da barra de leitura: posição contada em fio, não em número
   grande. `--tut-feito` é escrito pelo JS a cada clique. */
.tut-feitos-fio {
  position: relative;
  flex: 1 1 auto;
  height: 1px;
  background: var(--sitio-traco);
}

.tut-feitos-fio::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--tut-feito, 0) * 100%);
  background: var(--sitio-sinal);
  transition: width var(--t-toque) var(--e-entrada);
}

.tut-feitos-conta {
  flex: none;
  color: var(--sitio-tinta-cheia);
  font-variant-numeric: tabular-nums;
}

.tut-feitos[data-completo] .tut-feitos-conta { color: var(--sitio-realce-verde); }
.tut-feitos[data-completo] .tut-feitos-fio::before { background: var(--sitio-realce-verde); }

@media (prefers-reduced-motion: reduce) {
  .tut-feitos-fio::before { transition: none; }
}

/* ── O botão de estado ─────────────────────────────────────────────────── */
/* Duas formas do mesmo controle: redonda quando é PASSO (herda
   `.tut-step-num`, que já era o alvo de 34px com o numeral dentro — virar
   controle não acrescentou elemento nenhum à composição) e quadrada quando é
   item de CHECAGEM. */
.sitio button.tut-marca {
  padding: 0;
  cursor: pointer;
  appearance: none;
  transition: border-color var(--t-toque) var(--e-entrada),
              background-color var(--t-toque) var(--e-entrada),
              color var(--t-toque) var(--e-entrada);
}

.sitio button.tut-marca:hover { border-color: var(--sitio-sinal); }

/* O visto e o numeral ocupam a MESMA célula da grade: trocar um pelo outro
   não pode mudar o tamanho do botão, senão o trilho de passos "pula" a cada
   clique. `.tut-step-num` já é `display:grid; place-items:center`. */
.tut-marca > * { grid-area: 1 / 1; }
.tut-marca-visto { opacity: 0; font-size: 16px; }
.tut-marca[aria-pressed="true"] .tut-marca-num { opacity: 0; }
.tut-marca[aria-pressed="true"] .tut-marca-visto { opacity: 1; }

.sitio button.tut-marca[aria-pressed="true"] {
  border-color: var(--sitio-realce-verde);
  color: var(--sitio-realce-verde);
}

/* O feito é dito pelo VISTO e por um risco no título — e NÃO por opacidade.
   Foi a primeira tentativa: `opacity: 0.55` sobre `--sitio-tinta-secundaria`
   (#8b8f94) em `--sitio-fundo` (#04080c) resulta em ~#4e5155, que mede 2,6:1
   e reprova o piso de 4,5:1 de texto. Um passo feito continua sendo conteúdo
   que a pessoa volta a ler ("o que mesmo eu fiz no passo 3?"), então
   apagá-lo até ficar ilegível troca um problema por outro pior — e um que a
   prova de contraste desta suíte não pegaria, porque ela mede a página em
   repouso, não depois de um clique. */
.tut-step[data-feito] .tut-step-body h3 {
  text-decoration: line-through;
  text-decoration-color: var(--sitio-tinta-fraca);
}

/* ── A lista de checagem ───────────────────────────────────────────────── */
.tut-prose ul.tut-checagem {
  list-style: none;
  padding-left: 0;
}

.tut-prose ul.tut-checagem > li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}

.tut-prose ul.tut-checagem > li::marker { content: none; }

/* O conteúdo original do item, embrulhado pelo JS. Ver o comentário lá: sem
   o embrulho a grade de duas colunas trata cada nó do <li> como item
   próprio, e um item com link mais texto vira uma coluna de palavras. */
.tut-checagem-corpo { min-width: 0; }

.sitio button.tut-marca--caixa {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  /* alinha o topo da caixa com a primeira linha do item (28px de entrelinha) */
  margin-top: 3px;
  border: 1px solid var(--sitio-traco-forte);
  border-radius: var(--sitio-raio-miudo);
  background: var(--sitio-superficie-alta);
  color: var(--sitio-tinta-cheia);
}

/* Área de toque: a caixa desenhada tem 22px, abaixo do mínimo de 24×24 da
   WCAG 2.2. Cresce o ALVO num pseudo-elemento, sem esticar a linha do item —
   mesma solução do "Copiar" e da âncora, e pela mesma razão. */
.sitio button.tut-marca--caixa { position: relative; }
.sitio button.tut-marca--caixa::after {
  content: "";
  position: absolute;
  inset: -5px -6px;
}

/* Mesma razão do passo: risco, não apagamento. */
.tut-prose ul.tut-checagem > li[data-feito] {
  text-decoration: line-through;
  text-decoration-color: var(--sitio-tinta-fraca);
}

/* ══ Recado (dica · nota · atenção) — VAZIO DECLARADO ════════════════════
   O pacote tem `.recado`, mas é outro objeto: um papelzinho amarelo
   rotacionado, da faixa clara da home. Não serve pra aviso dentro de texto
   escuro. Escrito à mão: superfície um degrau acima, fio de cor na aresta
   esquerda e rótulo em voz de sistema.

   A cor vem dos realces que o pacote JÁ declara (--sitio-realce-*), nunca
   do âmbar do sinal: `--sitio-sinal` é o "ligado" da AÇÃO, um por vista, e
   gastá-lo em aviso apagaria a distinção. O rótulo em texto carrega o
   sentido; a cor só reforça — sem ícone inventado, que o sprite do site não
   tem símbolo de aviso e acrescentar um é outro escopo. */

.tut-callout {
  --tut-recado-cor: var(--sitio-realce-azul);
  margin-top: 40px;
  padding: 20px 24px;
  border-radius: var(--sitio-raio-fino);
  border-left: 2px solid var(--tut-recado-cor);
  background: color-mix(in srgb, var(--tut-recado-cor) 7%, var(--sitio-superficie));
}

.tut-callout--tip { --tut-recado-cor: var(--sitio-realce-verde); }
.tut-callout--info { --tut-recado-cor: var(--sitio-realce-azul); }
.tut-callout--warning { --tut-recado-cor: var(--sitio-realce-coral); }

.tut-callout-kind {
  margin: 0 0 8px;
  font-family: var(--voz-sistema);
  font-size: var(--sitio-rotulo-corpo);
  line-height: var(--sitio-rotulo-entrelinha);
  letter-spacing: var(--sitio-rotulo-espacamento);
  text-transform: uppercase;
  color: var(--tut-recado-cor);
}

.tut-callout-body > strong:first-child {
  display: block;
  margin-bottom: 4px;
  color: var(--sitio-tinta-cheia);
  font-weight: 600;
}

.tut-callout-body p { margin: 0; }
.tut-callout-body p + p { margin-top: 16px; }

/* ══ Bloco de código — a JANELA do pacote ════════════════════════════════
   Aqui o pacote TEM a peça, e ela é usada como é: `.janela` +
   `.janela__cromo` + `.janela__sinal` (a marca VK em máscara) +
   `.janela__titulo` + `.janela__campo`. O que esta folha acrescenta é só o
   que a peça não previa: a margem no fluxo do texto, o botão de copiar e um
   corpo um degrau maior.

   `.tut-code` fica na marcação porque js/tutorial.js procura `.tut-code pre`
   pra marcar as regiões que rolam na horizontal como alcançáveis por
   teclado. Trocar o nome não dá erro: só tira a parada de tabulação. */

.tut-code {
  position: relative;
  margin-top: 32px;
}

.tut-code .janela__cromo {
  /* o botão de copiar mora na barra da janela */
  padding-right: 8px;
}

.tut-code .janela__titulo {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A calibragem do pacote (`.sitio .janela__campo`, 12,5px/21) é da janela de
   BUSCA da home — quatro linhas de eco. Aqui é comando pra copiar e digitar,
   e 12,5px lê pequeno demais ao lado de um terminal. Sobe pra 13,5/22.

   Vence por ESPECIFICIDADE, não por ordem de carga: `.sitio .tut-code
   .janela__campo` é (0,3,0) contra os (0,2,0) do pacote. A nota da seção
   "Famílias compartilhadas" de css/sitio-web.css conta o que acontece quando
   alguém tenta ganhar essa disputa só carregando depois. */
.sitio .tut-code .janela__campo {
  margin: 0;
  padding: 18px 20px;
  font-size: 13.5px;
  line-height: 22px;
  white-space: pre;
  overflow-x: auto;
  tab-size: 4;
}

.tut-code .janela__campo code {
  padding: 0;
  background: none;
  border-radius: 0;
  color: inherit;
  font-size: inherit;
  /* dentro do <pre> a família já é a mesma: não há duas bases concorrendo */
  line-height: inherit;
  overflow-wrap: normal;
}

/* ── Copiar ──────────────────────────────────────────────────────────────
   Posto por js/tutoriais/leitura.js, nunca na marcação servida: sem
   `navigator.clipboard` o botão seria um controle morto, e controle morto é
   pior que controle ausente. */
.sitio button.tut-copiar {
  position: relative;
  flex: none;
  height: 26px;
  padding: 0 10px;
  border: 1px solid var(--sitio-traco-forte);
  border-radius: var(--sitio-raio-miudo);
  background: color-mix(in srgb, var(--janela-tinta-cheia) 8%, transparent);
  color: var(--janela-tinta-secundaria);
  font-family: var(--voz-sistema);
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: color var(--t-toque) var(--e-entrada), border-color var(--t-toque) var(--e-entrada);
}

/* A área de TOQUE, que não é a área desenhada. O corpo do botão mede 64×26
   (medido) — os 26px passam raspando o mínimo de 24×24 da WCAG 2.2, e num
   tutorial lido no celular com o terminal do lado "Copiar" é a ação
   principal da página. Crescer o corpo esticaria a barra da janela, que é
   peça do pacote (`.janela__cromo`, 38px de altura fixa); então cresce só o
   alvo, num pseudo-elemento que não ocupa layout. `inset: -6px -8px` leva o
   alvo a 80×38 — a altura INTEIRA da barra, sem transbordar pro campo de
   código embaixo, onde o toque erraria pro texto. */
.sitio button.tut-copiar::after {
  content: "";
  position: absolute;
  inset: -6px -8px;
}

.sitio button.tut-copiar:hover {
  color: var(--janela-tinta-cheia);
  border-color: var(--janela-tinta-secundaria);
}

.sitio button.tut-copiar[data-copiado] {
  color: var(--sitio-realce-verde);
  border-color: var(--sitio-realce-verde);
}

/* ══ Tabela — VAZIO DECLARADO ════════════════════════════════════════════
   O pacote não tem tabela. Escrita à mão, sem caixa e sem zebra: cabeçalho
   em voz de sistema com fio embaixo, linhas abertas por fio. A caixa rola na
   horizontal quando não cabe, e js/tutorial.js marca a que de fato rola como
   região alcançável por teclado — por isso `.tut-table-wrap` fica no nome. */

.tut-table-wrap {
  margin-top: 32px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border-radius: var(--sitio-raio-fino);
}

.tut-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14.5px;
  line-height: 22px;
}

.tut-table th {
  padding: 0 20px 10px 0;
  text-align: left;
  vertical-align: bottom;
  color: var(--sitio-tinta-secundaria);
  font-family: var(--voz-sistema);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--sitio-traco-forte);
}

.tut-table td {
  padding: 14px 20px 14px 0;
  color: var(--sitio-tinta-secundaria);
  vertical-align: top;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--sitio-traco);
}

.tut-table tbody tr:last-child td { border-bottom: 0; }

.tut-table th:last-child,
.tut-table td:last-child { padding-right: 0; }

.tut-table td strong { color: var(--sitio-tinta-cheia); font-weight: 600; }

/* ── A coluna comparável vira figura — VAZIO DECLARADO ─────────────────────
   O pacote não tem gráfico (nem barra, nem eixo, nem legenda). Esta é a peça
   mais próxima disso que existe aqui, e ela é deliberadamente MÍNIMA: um fio
   proporcional atrás do número, na própria célula. Sem eixo, sem escala, sem
   rótulo — quem lê o número exato lê o número; a barra só responde "qual é
   maior, e por quanto".

   De onde vem o dado: da própria tabela. `js/tutoriais/leitura.js` lê as
   células, só aceita a coluna quando TODAS as linhas trazem número com a
   MESMA unidade, e escreve `--tut-barra` como fração do maior valor. Nenhum
   número é inventado, nenhum é reescrito, e coluna que não é grandeza
   comparável ("Reunião de 30 min" ao lado de "Aula de 1 h") fica sem barra —
   fingir comparação onde não há é pior que não desenhar nada.

   Por que importa: a tabela de modelos do whisper é o argumento central
   daquele guia (36,77 s contra 66,55 s; 771 MB contra 1.654 MB). Lida como
   texto, ela obriga a pessoa a fazer a divisão de cabeça enquanto rola de
   lado no celular. A barra faz a conta.

   É um FIO de 3px na base da célula, e não um preenchimento atrás do número.
   A diferença importa: preenchimento mudaria o fundo sob o texto e derrubaria
   o contraste do valor (que é o dado, e o dado é o que a pessoa veio ler);
   o fio ocupa a faixa vazia abaixo da linha de base e não encosta em glifo
   nenhum. `z-index: -1` com `isolation: isolate` mantém ele atrás do
   conteúdo mesmo se um dia a célula ganhar fundo próprio. */
.tut-table td[data-barra] {
  position: relative;
  isolation: isolate;
}

.tut-table td[data-barra]::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  bottom: 6px;
  height: 3px;
  width: calc(var(--tut-barra, 0) * 100% - 20px);
  min-width: 2px;
  border-radius: 2px;
  background: var(--sitio-sinal);
  opacity: 0.55;
}

/* ── A tabela larga vira cartão no celular — VAZIO DECLARADO ───────────────
   Nada disto existe no pacote. Vale só para tabelas de TRÊS colunas ou mais,
   e só abaixo de 680px.

   O caso que motivou: "sintoma · causa provável · o que fazer" do whisper —
   oito linhas de três colunas de texto longo, numa caixa de 350px que rola de
   lado. Ler um caso ali exigia arrastar, voltar, arrastar de novo, guardando
   na cabeça o sintoma da coluna 1. Empilhada, cada linha vira um caso inteiro
   numa tela.

   `display` trocado em elemento de tabela APAGA os papéis implícitos na
   árvore de acessibilidade — quem usa leitor de tela perderia a estrutura no
   exato momento em que quem enxerga a ganha. Por isso o JS escreve
   `role="table"/"rowgroup"/"row"/"cell"` explícito nas tabelas marcadas, e o
   cabeçalho não é apagado: sai da vista mas continua na árvore. */
@media (max-width: 680px) {
  .tut-table-wrap[data-cartoes] {
    overflow-x: visible;
    /* sem rolagem lateral não há borda que esmaecer */
    -webkit-mask-image: none;
    mask-image: none;
  }

  [data-cartoes] .tut-table,
  [data-cartoes] .tut-table tbody,
  [data-cartoes] .tut-table tr,
  [data-cartoes] .tut-table td {
    display: block;
    width: auto;
  }

  [data-cartoes] .tut-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  [data-cartoes] .tut-table tbody tr {
    margin-top: 16px;
    padding: 16px 18px;
    border: 1px solid var(--sitio-traco);
    border-radius: var(--sitio-raio-fino);
    background: var(--sitio-superficie);
  }

  [data-cartoes] .tut-table tbody td {
    padding: 0;
    border-bottom: 0;
  }

  [data-cartoes] .tut-table tbody td + td { margin-top: 12px; }

  /* O rótulo da coluna vem do <thead>, escrito em `data-rotulo` pelo JS.
     Sem ele o cartão seria uma pilha de valores sem dizer de que são.

     `::before` num td que é `display: block`, e NÃO um td virado contêiner
     flex com `order: -1`: essa foi a primeira tentativa e ela QUEBRA o
     conteúdo. Num contêiner flex todo filho vira item de bloco — inclusive
     os pedaços de texto solto ao redor de um <code> —, e a célula "Rode
     `source .../activate` de novo. O prompt tem que mostrar `(.venv)`."
     virou três blocos desenhados um por cima do outro. Sintoma puramente
     visual, console limpo. Por isso a barra da célula mudou pra `::after`:
     este `::before` é do rótulo. */
  [data-cartoes] .tut-table tbody td::before {
    content: attr(data-rotulo);
    display: block;
    margin-bottom: 4px;
    color: var(--sitio-tinta-secundaria);
    font-family: var(--voz-sistema);
    font-size: 10px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  /* A barra some no cartão: sem as linhas lado a lado ela não compara nada. */
  [data-cartoes] .tut-table td[data-barra]::after { content: none; }
}

/* ══ A borda que avisa que ainda tem conteúdo ════════════════════════════
   Vale pros DOIS que rolam de lado — a caixa da tabela e o bloco de código.

   O defeito que isto conserta: a caixa rolava e era alcançável por teclado,
   mas nada dizia que rolava. Medido no whisper a 390px, o cabeçalho da
   tabela terminava cortado no meio da palavra ("PICO DE RA…") encostado na
   borda direita, sem sombra e sem fio. Quem lê no celular entende isso como
   "a página quebrou", não como "arraste" — e a tabela do whisper é o dado
   central do guia (o comparativo de modelos). Ler duas das cinco colunas e
   não desconfiar que há mais três é perder o argumento do tutorial.

   `js/tutorial.js` escreve `data-rola` com o lado que ainda tem conteúdo, e
   aqui a borda correspondente esmaece. É máscara e não gradiente pintado por
   cima porque a caixa não tem fundo próprio: ela senta direto sobre
   `--sitio-fundo` no caso da tabela e sobre `--janela-campo` no do código —
   um gradiente precisaria saber a cor de trás, a máscara não precisa.

   A máscara é aplicada à CAIXA, não ao conteúdo: em elemento com rolagem ela
   fica presa ao box e o conteúdo desliza por baixo, que é justamente o que se
   quer. Sem `data-rola` (JS ausente, ou nada transbordando) nenhuma máscara é
   declarada e a caixa fica inteira — a marcação servida nunca depende disto.

   24px é o dobro do vão da coluna da tabela: menos que isso passa por
   antisserrilhado, mais come uma coluna estreita inteira.

   O `black` dos gradientes abaixo NÃO é cor: numa máscara só o canal alfa
   conta, e `black` quer dizer "opaco" como `transparent` quer dizer
   "invisível". Escrito por palavra-chave, e não `#000`, pra não parecer uma
   cor literal contrabandeada — `test_a_folha_da_pagina_nao_declara_cor_solta`
   não tem exceção nenhuma, e não deve voltar a ter. */

.tut-table-wrap[data-rola="fim"],
.tut-code pre[data-rola="fim"] {
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
  mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
}

.tut-table-wrap[data-rola="ambos"],
.tut-code pre[data-rola="ambos"] {
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
}

.tut-table-wrap[data-rola="inicio"],
.tut-code pre[data-rola="inicio"] {
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 24px, black 100%);
  mask-image: linear-gradient(to right, transparent 0, black 24px, black 100%);
}

/* ══ Próximos passos ═════════════════════════════════════════════════════
   Duas saídas, lado a lado, cada uma em superfície própria. O cartão inteiro
   é o link — e por isso a cor tem que ser escopada com o elemento (a
   armadilha do topo deste arquivo). */

.tut-proximos {
  max-width: 68rem;
  margin-top: 96px;
  scroll-margin-top: 104px;
}

.tut-proximos .section-head { margin-bottom: 24px; }

.tut-proximos h2 {
  margin: 8px 0 0;
  font-family: var(--voz-editorial);
  font-weight: 600;
  font-size: clamp(28px, 2.2vw, 34px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--sitio-tinta-cheia);
}

.tut-proximos .lbl {
  margin: 0;
  font-family: var(--voz-sistema);
  font-size: var(--sitio-rotulo-corpo);
  line-height: var(--sitio-rotulo-entrelinha);
  letter-spacing: var(--sitio-rotulo-espacamento);
  text-transform: uppercase;
  color: var(--sitio-sinal);
}

.tut-proximos .section-intro {
  margin: 12px 0 0;
  max-width: 68ch;
  color: var(--sitio-tinta-secundaria);
}

.tut-prox-cells {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}

.sitio a.tut-prox-cell {
  display: grid;
  align-content: start;
  gap: 8px;
  padding: 24px;
  border-radius: var(--sitio-raio);
  background: var(--sitio-superficie);
  box-shadow: var(--sitio-relevo-baixo), var(--sitio-luz-de-bordo);
  color: var(--sitio-tinta-secundaria);
  text-decoration: none;
  transition: background-color var(--t-toque) var(--e-entrada);
}

.sitio a.tut-prox-cell:hover {
  background: var(--sitio-superficie-alta);
  color: var(--sitio-tinta-secundaria);
}

.tut-cell-eyebrow {
  font-family: var(--voz-sistema);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sitio-tinta-secundaria);
}

.tut-prox-cell h3 {
  margin: 0;
  font-family: var(--voz-funcional);
  font-weight: 600;
  font-size: 18px;
  line-height: 26px;
  color: var(--sitio-tinta-cheia);
}

.tut-prox-cell p {
  margin: 0;
  font-size: 14.5px;
  line-height: 22px;
}

.tut-cell-cta {
  margin-top: 8px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--voz-sistema);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sitio-sinal);
}

.tut-prox-cell:hover .tut-cell-cta { color: var(--sitio-sinal-forte); }

/* ══ Rodapé ══════════════════════════════════════════════════════════════
   `.rodape` é do pacote e `.rodape .sitio__miolo` vem de css/sitio-web.css.
   O que falta é só o que a home resolve na própria folha: o nav legal em
   linha. Os links de /privacy/ e /terms/ são AMARRA — o Google exige que o
   site linke a política pra aprovar a verificação do app OAuth, e o login da
   área de membros depende dela. */

.rodape__legal {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* `.rodape__coracao` NÃO ganha regra aqui, e isso é a decisão, não o
   esquecimento. A rodada 1 desta folha pintava o ♥ de `#b8483c` — uma cor
   que o design system não declara, numa classe com nome de família do
   pacote, apresentada como se viesse da home. Ela não vinha: na home
   (`LandingPage/index.html` + `css/home.css`) essa classe não tem regra
   nenhuma, o ♥ herda a tinta do rodapé e sai cinza; no hub de tutoriais o
   elemento nem existe. O rodapé é cromo COMPARTILHADO, e uma cor a mais só
   aqui é o modo de falha mais silencioso que existe — ninguém abre as duas
   abas lado a lado pra conferir um coração.

   Sem regra, as três superfícies concordam pelo PACOTE: o ♥ herda
   `--sitio-tinta-secundaria` como o resto da linha do rodapé, na home e
   aqui. Se um dia o coração dever ser colorido, a regra nasce no pacote (ou
   na camada compartilhada) e vale nas três de uma vez — não numa folha de
   página. Vazio declarado, nunca desenho inventado.
   Medido por `test_o_coracao_do_rodape_herda_a_tinta_do_pacote`. */

/* `.rodape` (elementos-sitio.css) é uma linha só, com `white-space: nowrap`,
   calibrada pra prancha de 1440. Com marca + frase + dois links legais +
   copyright isso ESTOURA a largura visível bem antes do celular: medido a
   390px, 603px de conteúdo em 390 de tela — e o sintoma não é o rodapé feio,
   é a PÁGINA INTEIRA rolando de lado. A home resolve o mesmo em css/home.css,
   no mesmo 1180 que já colapsa o menu; aqui a regra precisa alcançar o
   `.sitio__miolo`, que é quem carrega o flex (css/sitio-web.css, seção 8). */
@media (max-width: 1180px) {
  .rodape {
    white-space: normal;
    text-align: center;
  }
  .rodape .sitio__miolo {
    flex-wrap: wrap;
    justify-content: center;
    row-gap: 8px;
  }
  .rodape__legal {
    justify-content: center;
  }
}

/* ══ Reflow ══════════════════════════════════════════════════════════════ */

@media (max-width: 1180px) {
  /* Coluna única. O sumário lateral sai inteiro (nada fica preso no topo em
     tela pequena) e o <details> compacto entra no lugar dele. */
  .tut-layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    margin-top: 48px;
  }

  .tut-toc-win { display: none; }
  .tut-toc-mobile { display: block; }

  .tut-prose { max-width: none; }

  .tut-prose > section { scroll-margin-top: 128px; }
  .tut-proximos { scroll-margin-top: 128px; }
}

@media (max-width: 680px) {
  .tut-pagina { padding-block: 32px 64px; }

  .tut-layout { margin-top: 32px; }

  .tut-capa .medidor { gap: 10px 20px; }
  .tut-capa .medidor__item { padding-left: 20px; }

  .tut-prose > section + section { margin-top: 64px; }

  /* A coluna do numeral encolhe: em 342px de largura útil, 34px de bolha
     mais 20 de vão comem quase um quinto da linha. */
  .tut-step { grid-template-columns: 26px minmax(0, 1fr); gap: 14px; }
  .tut-step-num { width: 26px; height: 26px; font-size: 12px; }
  .tut-step:not(:last-child)::before { left: 12px; top: 26px; }

  .tut-callout { padding: 16px 18px; }

  .sitio .tut-code .janela__campo { padding: 14px 16px; }

  .tut-proximos { margin-top: 64px; }
}

/* ══ Rolagem ═════════════════════════════════════════════════════════════
   `html { scroll-behavior: smooth }` vinha de css/ds-web.css, que estas
   páginas não carregam mais. Ele importa aqui: um salto instantâneo do
   sumário pro meio de um texto de dez mil pixels não diz de onde a pessoa
   veio, e ela perde a referência. Reposto — e desligado sob
   `prefers-reduced-motion`, como a folha antiga fazia.

   O progresso de leitura NÃO entra nesse portão: ele não é animação, é um
   mostrador de posição, escrito pelo JS a cada rolagem sem transição
   declarada. Esconder o mostrador de quem pediu menos movimento tiraria
   informação, não movimento. */

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
