/* ==========================================================================
   FingerTrackID — landing. Ordem: reset → tipografia → layout → componentes →
   seções → motion → media queries. Tokens em tokens.css.
   While SITE-011 is open, any change to this file must ship with the `?v=` of every local
   CSS/JS references in index.html bumped together (site/README.md, "Janela de cache").
   ========================================================================== */

/* ---------- 0. Reset mínimo ------------------------------------------------ */

*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  background: var(--paper);
  color: var(--ink-1);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 16px);
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-1);
  font: 400 var(--fs-body) / 1.6 var(--font-sans);
  font-feature-settings: "tnum" 1;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
h1,
h2,
h3,
h4,
p,
ul,
ol,
dl,
dd,
figure,
pre {
  margin: 0;
}
ul,
ol {
  padding: 0;
  list-style: none;
}
a {
  color: inherit;
}
img,
svg {
  display: block;
  max-width: 100%;
}
button,
input {
  font: inherit;
  color: inherit;
}
button {
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0;
}
code,
pre,
kbd {
  font-family: var(--font-mono);
  font-variant-ligatures: none;
}
:focus-visible {
  /* The ring is a box-shadow, and forced colors drops every box-shadow. The transparent outline
     sits where the ring's outer band is and paints nothing; forced colors repaints it in a
     system color, so keyboard focus stays visible there. Rules below that only restyle the
     ring (.sinal, .campo input, .faixa--tinta) get this pair through the cascade; a rule that
     resets `outline`, or draws the ring on an element other than the focused one
     (.check__caixa), restates it. */
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: var(--focus-ring);
  border-radius: var(--r-inner);
}
::selection {
  background: var(--indigo-tint);
  color: var(--ink-1);
}
/* In dark the tint sits 1.06:1 from the ink band, so a selection there showed next to nothing
   (light: 16.7:1). On the band the selection takes the indigo fill instead. */
@media screen {
  :root[data-theme="dark"] .faixa--tinta ::selection {
    background: var(--indigo);
    color: var(--ink-on-indigo);
  }
}
[hidden] {
  display: none !important;
}

/* ---------- 1. Tipografia -------------------------------------------------- */

.t-h1 {
  font-size: var(--fs-h1);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 0.94;
  text-wrap: balance;
  max-inline-size: 24ch;
}
.h1__frase {
  display: block;
}
/* The category line inside the h1: what search engines and assistants read as the page's topic,
   set in the mono label voice so the two-phrase headline keeps its weight. */
.h1__categoria {
  display: block;
  margin-block-end: 0.6em;
  font: 500 var(--fs-label) / 1.3 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--indigo);
}
.h1__frase--eco {
  color: var(--ink-3);
}
.t-h2 {
  font-size: var(--fs-h2);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.02;
  text-wrap: balance;
  max-inline-size: 20ch;
}
.t-h3 {
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
  text-wrap: balance;
}
.t-lead {
  font-size: var(--fs-lead);
  letter-spacing: -0.005em;
  line-height: 1.45;
  max-inline-size: 48ch;
  color: var(--ink-2);
  text-wrap: pretty;
}
.t-body {
  font-size: var(--fs-body);
  line-height: 1.6;
  max-inline-size: 62ch;
  color: var(--ink-2);
  text-wrap: pretty;
}
.t-small {
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--ink-2);
}
.t-label {
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.t-code {
  font: 400 var(--fs-code) / 1.55 var(--font-mono);
  tab-size: 2;
}
.t-metric {
  font: 500 var(--fs-metric) / 1 var(--font-mono);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-1);
}
.t-numeral-xl {
  font-size: var(--fs-numeral);
  font-weight: 600;
  letter-spacing: -0.05em;
  line-height: 0.9;
  font-variant-numeric: tabular-nums;
}
.t-passo {
  font: 400 2.5rem / 1 var(--font-mono);
  color: var(--rule-strong);
}
.ink-1 {
  color: var(--ink-1);
}
.ink-2 {
  color: var(--ink-2);
}
.ink-3 {
  color: var(--ink-3);
}
.mono {
  font-family: var(--font-mono);
  font-variant-ligatures: none;
}
.wbr {
  overflow-wrap: anywhere;
}
.nowrap {
  white-space: nowrap;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- 2. Layout ------------------------------------------------------- */

.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.bento {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--gap);
  align-items: stretch;
}
.span-2 {
  --n: 2;
}
.span-3 {
  --n: 3;
}
.span-4 {
  --n: 4;
}
.span-5 {
  --n: 5;
}
.span-6 {
  --n: 6;
}
.span-7 {
  --n: 7;
}
.span-8 {
  --n: 8;
}
.span-9 {
  --n: 9;
}
.span-12 {
  --n: 12;
}
[class*="span-"] {
  grid-column: span min(var(--n), var(--cols));
  min-width: 0;
}
.row-2 {
  grid-row: span 2;
}
.self-start {
  align-self: start;
}

.panel {
  background: var(--panel);
  border: var(--hairline);
  border-radius: var(--r-panel);
  box-shadow: var(--shadow-panel);
  padding: var(--panel-pad);
  min-width: 0;
  position: relative;
}
.panel--forte {
  border-color: var(--rule-strong);
}
.panel--rebaixado {
  background: var(--paper-sunken, var(--paper-deep));
  box-shadow: none;
}
.panel__cab {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.panel__cab .t-h3 {
  margin-top: var(--sp-2);
}
.panel__cab--col {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
}
.panel__rodape {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: var(--hairline);
}
.panel .t-passo {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
}
.stack > * + * {
  margin-top: var(--sp-3);
}
.stack-lg > * + * {
  margin-top: var(--sp-5);
}

.secao {
  padding-block: var(--section-y);
}
.secao--compacta {
  padding-block: var(--sp-8);
}
.secao__cabecalho {
  position: relative;
  padding-top: var(--sp-5);
  margin-bottom: var(--sp-7);
  border-top: var(--hairline);
}
.secao__cabecalho::before {
  content: "";
  position: absolute;
  top: -3.5px;
  left: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--indigo);
  box-shadow:
    0 0 0 3px var(--paper),
    0 0 0 4.5px var(--indigo-halo);
}
.secao__cabecalho .t-h2 {
  margin-top: var(--sp-4);
}
.secao__cabecalho .t-lead {
  margin-top: var(--sp-4);
}
.folio {
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  transition: color 160ms;
}
.folio::before {
  content: "◎ ";
}
.secao.is-visivel .folio {
  color: var(--indigo);
}

/* ---------- 3. Componentes -------------------------------------------------- */

.skip {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 100;
  padding: 10px 14px;
  background: var(--panel);
  border: var(--hairline-strong);
  border-radius: var(--r-btn);
  transform: translateY(-200%);
}
.skip:focus-visible {
  transform: none;
}

/* Núcleo: ponto cheio + anel a 30 % — o "está gravando" do produto. */
/* Núcleo: o miolo da marca virado sinal de pontuação.
 *
 * Era carimbado no fim de todo rótulo de painel — cinquenta vezes na página — e aí deixou de
 * significar qualquer coisa. Ficou onde é marca ou é estrutura: a assinatura que abre (eyebrow
 * do hero) e a que fecha (wordmark do rodapé), o selo em `assessment_status` dentro do JSON, e
 * os cinco nós da linha do tempo do shadow mode. Rótulo de painel não leva núcleo. */
.nucleo {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--indigo);
  box-shadow:
    0 0 0 3px var(--paper),
    0 0 0 4.5px var(--indigo-halo);
  vertical-align: middle;
  margin-inline-start: 0.7em;
  transition: box-shadow 160ms;
}
.panel .nucleo {
  box-shadow:
    0 0 0 3px var(--panel),
    0 0 0 4.5px var(--indigo-halo);
}
.nucleo--lg {
  position: relative;
  width: 12px;
  height: 12px;
  margin: 0;
  box-shadow:
    0 0 0 4px var(--paper),
    0 0 0 6px var(--indigo-halo);
}
.nucleo--lg::after {
  content: "";
  position: absolute;
  inset: 3.5px;
  border-radius: 50%;
  background: var(--nucleus-core, var(--indigo-core));
}
/* Disc and core are backgrounds and the halo is a box-shadow, so under forced colors the
   nucleus vanished whole — the five timeline steps included. Disc in CanvasText, core back in
   Canvas: the large one reads as a ring, as its halo does elsewhere. */
@media (forced-colors: active) {
  .nucleo {
    background: CanvasText;
  }
  .nucleo--lg::after {
    background: Canvas;
  }
}

/* Botões: nada se move em hover. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  height: 40px;
  padding: 0 16px;
  border-radius: var(--r-btn);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
  transition:
    background-color 120ms,
    border-color 120ms,
    color 120ms;
}
.btn:active {
  transform: scale(0.98);
}
.btn--primary {
  background: var(--indigo);
  color: var(--ink-on-indigo);
  border-color: var(--indigo);
}
.btn--primary:hover {
  background: var(--indigo-hover);
  border-color: var(--indigo-hover);
}
.btn--primary:active {
  background: var(--indigo-active);
}
.btn--secondary {
  background: var(--panel);
  color: var(--ink-1);
  border-color: var(--rule-strong);
}
.btn--secondary:hover {
  background: var(--indigo-tint);
  border-color: var(--indigo);
  color: var(--indigo);
}
.btn--secondary:active {
  background: var(--paper-deep);
}
.btn--sm {
  height: 36px;
  padding: 0 12px;
}
@media (pointer: coarse) {
  .btn {
    height: 44px;
  }
}

.link {
  color: var(--ink-1);
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition:
    color 120ms,
    text-decoration-color 120ms;
}
.link:hover {
  color: var(--indigo);
  text-decoration-color: var(--indigo);
  text-decoration-thickness: 1.5px;
}
.link:active {
  color: var(--indigo-active);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border-radius: var(--r-inner);
  border: var(--hairline);
  background: var(--panel);
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--ink-2);
  white-space: nowrap;
}
.chip--nota {
  background: var(--paper-sunken, var(--paper-deep));
  border-color: transparent;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: normal;
  text-align: right;
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* Glifos de estado — sempre acompanhados da palavra. */
.glifo {
  width: 10px;
  height: 10px;
  flex: none;
  display: inline-block;
  vertical-align: -1px;
}
.glifo--12 {
  width: 12px;
  height: 12px;
}
.estado-palavra {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.estado-palavra[data-state="DETECTED"] {
  color: var(--sig-presente);
}

/* Escada ordinal das cinco recomendações. */
.ladder {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
}
.ladder svg {
  width: 38px;
  height: 10px;
  flex: none;
}
.ladder svg rect {
  fill: none;
  stroke: var(--rule-strong);
  stroke-width: 1;
}
.ladder[data-rec="ALLOW"] {
  color: var(--sem-cool);
}
.ladder[data-rec="MONITOR"] {
  color: var(--ink-3);
}
.ladder[data-rec="STEP_UP"] {
  color: var(--ink-2);
}
.ladder[data-rec="REVIEW"] {
  color: var(--ink-1);
}
.ladder[data-rec="BLOCK_RECOMMENDED"] {
  color: var(--sem-warm);
  font-weight: 600;
}
.ladder[data-rec="ALLOW"] rect:nth-child(-n + 1),
.ladder[data-rec="MONITOR"] rect:nth-child(-n + 2),
.ladder[data-rec="STEP_UP"] rect:nth-child(-n + 3),
.ladder[data-rec="REVIEW"] rect:nth-child(-n + 4),
.ladder[data-rec="BLOCK_RECOMMENDED"] rect:nth-child(-n + 5) {
  fill: currentColor;
  stroke: currentColor;
}
.ladder__codigo {
  font-family: var(--font-mono);
  font-size: var(--fs-code);
  letter-spacing: 0.02em;
}
.ladder--lg .ladder__codigo {
  font-family: var(--font-sans);
  font-size: 1.125rem;
  letter-spacing: -0.01em;
}
.ladder--lg svg {
  width: 46px;
  height: 12px;
}

/* Régua de medida.
 *
 * A régua é um quadro: eixo fixo, preenchimento e marca governados por --v (0–100) e
 * --escala (a cor daquele valor). Quem escreve os dois é o JS, quadro a quadro, para que a
 * cor acompanhe o número que está na tela e não só o valor final. Sem JS, o HTML já vem com
 * --v e --escala do valor real do contrato e nada anima. Ver `medidores` em landing.js.
 */
.regua {
  width: 100%;
  height: 34px;
  overflow: visible;
}
.regua line,
.regua path {
  stroke: var(--rule-strong);
  stroke-width: 1;
  fill: none;
}
/* Traço que cresce da esquerda. pathLength=100 faz --v ser a própria porcentagem.
 * Sem `vector-effect: non-scaling-stroke` de propósito: com ele o dash passa a ser medido em
 * unidades do viewBox e o traço para muito antes da marca (72 virava 44 % da largura). Como o
 * viewBox tem 34 de altura e a régua 34 px, a escala em Y é 1 e a espessura sai em 4 px. */
.regua .regua__preenchida {
  stroke: var(--escala, var(--indigo));
  stroke-width: 2.5;
  stroke-linecap: butt;
  stroke-dasharray: var(--v, 0) 100;
}
/* A marca fica FORA do SVG.
 *
 * O SVG tem preserveAspectRatio="none", então tudo dentro dele é esticado em X pelo fator
 * largura/300 — o que é certo para a régua, que é uma escala, e errado para a seta, que é um
 * símbolo: no painel largo ela saía com 16 px e nos estreitos com 7 px, a mesma seta em dois
 * tamanhos. Em HTML ela tem o mesmo tamanho em qualquer painel, e 1cqw é 1 % da régua. */
.regua-caixa {
  position: relative;
  container-type: inline-size;
}
.regua__marca {
  position: absolute;
  top: 5px;
  left: 0;
  width: 0;
  height: 0;
  border-inline: 5px solid transparent;
  border-bottom: 8px solid var(--escala, var(--indigo));
  transform: translateX(calc(var(--v, 0) * 1cqw - 50%));
}
.regua__extremos {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: 2px;
}
.regua__extremos span:last-child {
  text-align: right;
}
/* O número da medida usa a mesma cor do traço. Só a medida contínua; nunca o estado. */
.medida__valor {
  color: var(--escala, var(--ink-1));
  display: block;
}
.medida__valor--sm {
  font-size: clamp(1.5rem, 1.3rem + 0.6vw, 1.875rem);
}
.medida__valor .medida__unidade {
  font-size: 0.5em;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  margin-left: 0.35em;
}

/* Anel de cobertura: círculo externo a 30 %, arco índigo, núcleo. */
.anel {
  width: 56px;
  height: 56px;
  flex: none;
}
.anel__halo {
  fill: none;
  stroke: var(--indigo-halo);
  stroke-width: 2;
}
.anel__arco {
  fill: none;
  stroke: var(--escala, var(--indigo));
  stroke-width: 4;
  stroke-linecap: butt;
  stroke-dasharray: var(--v, 0) 100;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
}
.anel__nucleo {
  fill: var(--indigo-core);
}
.anel[data-vazio="true"] .anel__halo {
  stroke-dasharray: 3 3;
}
.anel[data-vazio="true"] .anel__arco {
  stroke-dasharray: 0 100;
}

/* Contêiner rolável com pista de sombra interna. */
/* Every token the dark theme added to tokens.css (--scroll-hint here; --wash, --detected-edge,
   --indigo-edge, --indigo-pulse, --paper-halo, --paper-sunken, --shadow-float and
   --nucleus-core elsewhere) is read with its light value as fallback. The `?v=` on the asset
   URLs in index.html is what keeps a fresh index.html from meeting a cached tokens.css that
   predates these tokens (SITE-011, up to 4 h); this is for the deploy that forgets to bump it,
   where an undefined var() would drop the whole declaration. */
.rola {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-gutter: stable;
  background:
    linear-gradient(90deg, var(--panel) 30%, transparent),
    linear-gradient(-90deg, var(--panel) 30%, transparent) 100% 0,
    linear-gradient(90deg, var(--scroll-hint, rgb(20 24 43 / 0.08)), transparent),
    linear-gradient(-90deg, var(--scroll-hint, rgb(20 24 43 / 0.08)), transparent) 100% 0;
  background-repeat: no-repeat;
  background-size:
    40px 100%,
    40px 100%,
    24px 100%,
    24px 100%;
  background-attachment: local, local, scroll, scroll;
}
.rola--papel {
  background:
    linear-gradient(90deg, var(--paper) 30%, transparent),
    linear-gradient(-90deg, var(--paper) 30%, transparent) 100% 0,
    linear-gradient(90deg, var(--scroll-hint, rgb(20 24 43 / 0.08)), transparent),
    linear-gradient(-90deg, var(--scroll-hint, rgb(20 24 43 / 0.08)), transparent) 100% 0;
  background-repeat: no-repeat;
  background-size:
    40px 100%,
    40px 100%,
    24px 100%,
    24px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* Código. */
pre.codigo {
  font: 400 var(--fs-code) / 1.55 var(--font-mono);
  tab-size: 2;
  padding: var(--sp-4);
  border: var(--hairline);
  border-radius: var(--r-inner);
  background: var(--panel);
  color: var(--ink-1);
  /* Quebra em vez de rolar: barra lateral dentro de painel é ruído, não affordance.
     As linhas são curtas o bastante para não quebrar em tela larga. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
pre.codigo:focus-visible {
  box-shadow: none;
  border-color: var(--rule-strong);
  outline: 2px solid var(--indigo);
  outline-offset: 2px;
}
.codigo .c {
  color: var(--ink-3);
  font-style: italic;
}
.codigo .k {
  color: var(--ink-2);
}
.codigo .s {
  color: var(--ink-1);
}
.codigo .n {
  color: var(--ink-1);
  font-variant-numeric: tabular-nums;
}
.codigo .b {
  color: var(--ink-3);
  font-style: italic;
}
.codigo .p {
  color: var(--rule-strong);
}
.codigo .e {
  color: var(--indigo);
  font-weight: 500;
}
.codigo .h {
  color: var(--ink-2);
}
.codigo .ph {
  color: var(--ink-3);
  font-style: italic;
}
.codigo .kw {
  color: var(--sig-presente);
}

/* Rota HTTP dentro de rótulo: caixa alta mentiria sobre o caminho. */
.t-label code,
.t-rota {
  text-transform: none;
  letter-spacing: 0.02em;
}

/* Tabela. */
.tabela {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
}
.tabela th,
.tabela td {
  text-align: left;
  vertical-align: top;
  padding: 10px 12px;
  border-bottom: var(--hairline);
}
.tabela thead th {
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: var(--paper-sunken, var(--paper-deep));
  border-bottom: var(--hairline-strong);
}
.tabela tbody tr:nth-child(even) td {
  background: var(--paper);
}
.tabela td:first-child,
.tabela th:first-child {
  position: sticky;
  left: 0;
  background: inherit;
}
.tabela tbody tr:nth-child(odd) td:first-child {
  background: var(--panel);
}
.tabela tbody tr:nth-child(even) td:first-child {
  background: var(--paper);
}
.tabela code {
  font-size: var(--fs-code);
  color: var(--ink-1);
}

/* Definições em mono. */
.kv {
  display: grid;
  grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
  column-gap: var(--sp-4);
  row-gap: 6px;
  font: 400 var(--fs-code) / 1.5 var(--font-mono);
}
.kv dt {
  color: var(--ink-3);
}
.kv dd {
  color: var(--ink-1);
  overflow-wrap: anywhere;
}

/* Lista com glifos. */
.lista-glifo li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding-block: 8px;
  border-bottom: var(--hairline);
  color: var(--ink-2);
  font-size: var(--fs-small);
  line-height: 1.5;
}
.lista-glifo li:last-child {
  border-bottom: 0;
}
.lista-glifo .glifo {
  margin-top: 5px;
}

/* ---------- 4. Nav ----------------------------------------------------------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--paper);
  border-bottom: var(--hairline);
  height: var(--nav-h);
}
.nav__in {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ink-1);
}
.wordmark img,
.wordmark svg {
  width: 28px;
  height: 28px;
}
.wordmark__id {
  color: var(--indigo);
}
.wordmark--mono .wordmark__id {
  color: inherit;
}
.nav__links {
  display: none;
  gap: var(--sp-5);
}
.nav__link {
  position: relative;
  white-space: nowrap;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
  padding-block: 6px;
  transition: color 120ms;
}
.nav__link:hover {
  color: var(--ink-1);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--indigo);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 160ms var(--ease);
}
.nav__link.is-ativo {
  color: var(--ink-1);
}
.nav__link.is-ativo::after {
  transform: scaleX(1);
}
.nav__acoes {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.nav__acoes .btn--secondary {
  display: none;
}
/* Theme toggle. Shown only when `scripts/theme.js` ran — it writes `data-theme` on <html>
   before the first paint, so the button is there from the first frame instead of popping in
   and shifting the nav. Without JavaScript the toggle could not work, so it does not exist.
   The menu `summary`'s skin (36 px high, 1 px functional border, radius 4), squared to
   36 × 36: it reads as a button, so the pointer gives it the crosshair like every button. */
.theme-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 36px;
  height: 36px;
  border: var(--hairline-strong);
  border-radius: var(--r-btn);
  color: var(--ink-1);
  transition:
    background-color 120ms,
    border-color 120ms,
    color 120ms;
}
/* Only `display` is gated. The gate is (0,3,0); with the skin in here too, it outranked
   `.theme-toggle:hover` (0,2,0) and the hover never showed — measured. */
:root[data-theme] .theme-toggle {
  display: inline-flex;
}
.theme-toggle:hover {
  background: var(--indigo-tint);
  border-color: var(--indigo);
  color: var(--indigo);
}
.theme-toggle:active {
  background: var(--paper-deep);
}
/* The glyph is a half-filled disc: the universal "contrast" sign, drawn in the page's own
   stroke weight. In dark it sits half a turn over, so the filled side flips. Keyed on
   `data-theme`, which exists before the first paint, and not on `aria-pressed`, which
   theme.js can only write once the button is parsed: keyed on that, every dark page load
   played the half turn by itself — measured. */
.theme-toggle__glyph {
  width: 16px;
  height: 16px;
  transition: transform 240ms var(--ease);
}
@media screen {
  :root[data-theme="dark"] .theme-toggle__glyph {
    transform: rotate(180deg);
  }
}
.nav__menu {
  position: relative;
}
.nav__menu > summary {
  list-style: none;
  cursor: pointer;
  height: 36px;
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  border: var(--hairline-strong);
  border-radius: var(--r-btn);
  font-size: var(--fs-small);
  font-weight: 500;
}
.nav__menu > summary::-webkit-details-marker {
  display: none;
}
.nav__menu[open] > summary {
  background: var(--paper-deep);
}
.nav__menu__lista {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 240px;
  background: var(--panel);
  border: var(--hairline-strong);
  border-radius: var(--r-panel);
  padding: 4px 0;
}
.nav__menu__lista a {
  display: flex;
  align-items: center;
  height: 48px;
  padding: 0 16px;
  text-decoration: none;
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--ink-1);
  border-bottom: var(--hairline);
}
.nav__menu__lista li:last-child a {
  border-bottom: 0;
}
.nav__menu__lista a:hover {
  background: var(--paper-deep);
}

/* ---------- 5. Hero ---------------------------------------------------------- */

.hero {
  /* O respiro de cima já foi duas coisas: o padding do herói E a faixa onde a cena de abertura
     corria. A cena saiu, e com ela saíram a variável `--topo-do-heroi`, que existia só para
     não repetir o `clamp()` nos dois lugares, e o `position: relative`, que existia só para
     dar bloco contedor a filho absoluto. Nenhum descendente do herói é absoluto hoje —
     conferido antes de tirar, e não presumido. Sobra o padding, que é o que sempre foi. */
  padding-top: clamp(40px, 6vw, 88px);
  padding-bottom: var(--section-y);
  /* A troca da palavra do giro e o acender do chip espelhado são UM gesto, então são UM
     número. Moram aqui porque `.hero__jornadas` e `.jornadas-mostra` são irmãs e este é o
     ancestral comum mais próximo; escrever a duração nas duas abriria a porta para elas
     dessincronizarem numa edição futura que tocasse só uma.
     Era 420 ms na palavra e 320 no chip — a palavra ficava em movimento 20 % do ciclo de
     2100 ms e demorava a assentar. A 280 ms são 13 %, e a frase para de parecer que está
     sempre a meio caminho. */
  --giro-troca: 280ms;
}
.hero__eyebrow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 6px;
  max-width: 100%;
}
.hero .t-h1 {
  margin-top: var(--sp-5);
}
.hero__grade {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-7) var(--gap);
  margin-top: var(--sp-7);
  align-items: start;
}
.hero__copy,
.hero__painel {
  min-width: 0;
}
.hero__copy .t-lead {
  color: var(--ink-2);
}
.hero__acoes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}
.hero__estado {
  margin-top: var(--sp-6);
  line-height: 1.8;
}

/* Hero reading notes: how to read this response (scripts/hero-leitura.js). */
/* Below 768 px the hero stacks, and this column would push the response panel a full screen
   down; the same information is in the panel itself, so the addition only exists side by side. */
.hero__leitura {
  display: none;
}
@media (min-width: 768px) {
  .hero__leitura {
    display: block;
    margin-top: var(--sp-5);
    padding-top: var(--sp-4);
    border-top: var(--hairline);
  }
}

.leitura {
  margin-top: var(--sp-2);
}
.leitura__nota {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  column-gap: var(--sp-3);
  padding-block: var(--sp-3);
  border-bottom: var(--hairline);
}
.leitura__nota:last-child {
  border-bottom: 0;
}
.leitura__nota > :not(.leitura__n) {
  grid-column: 2;
}
.leitura__n {
  grid-row: 1 / span 3;
  font: 400 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.06em;
  color: var(--ink-3);
}
.leitura__valor {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 12px;
  margin-top: var(--sp-2);
  font: 500 var(--fs-code) / 1.4 var(--font-mono);
  color: var(--ink-1);
  overflow-wrap: anywhere;
}
.leitura__meta {
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-3);
}
.leitura__texto {
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-2);
}

/* Faixa das jornadas: a lista não cabe numa linha, então gira.
 *
 * inline-grid empilha todas as palavras na mesma célula: o contêiner já nasce com a largura
 * da mais longa e nada reflui quando a palavra troca. A lista inteira também existe estática
 * logo abaixo, em .jornadas-mostra — quem não vê a animação não perde informação. */
.hero__jornadas {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: var(--hairline);
}
.hero__jornadas .t-label {
  color: var(--ink-3);
}
/* A palavra que gira é a parte variável de UMA frase, não um título ao lado de uma legenda.
   Ela vinha em `--fs-lead` sans (22 px) logo depois de um `.t-label` mono de 12 px: quase o
   dobro da altura, outra família e outra caixa, e a linha quebrava no meio em vez de correr.
   Agora ela herda a métrica exata do rótulo — mesma família, mesmo corpo, mesma caixa alta,
   mesmo `letter-spacing` — e o que a distingue é só peso e tinta, que é o mínimo necessário
   para dizer "esta parte troca". Mudar `.t-label` passa a mudar as duas juntas. */
.giro {
  display: inline-grid;
  vertical-align: baseline;
  font: 600 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-1);
}
.giro__palavra {
  grid-area: 1 / 1;
  justify-self: start;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(0.34em);
  transition:
    opacity var(--giro-troca) var(--ease),
    transform var(--giro-troca) var(--ease);
}
.giro__palavra.is-ativa {
  opacity: 1;
  transform: none;
}
/* O traço era 2 px sob uma palavra de 22 px. Sob 12 px a mesma espessura vira sublinhado de
   marca-texto e rouba a palavra; 1,5 px mantém a marca visível sem competir com o glifo. */
.giro__palavra::after {
  content: "";
  display: block;
  height: 1.5px;
  margin-top: 3px;
  background: var(--indigo);
}
.hero__jornadas .t-small {
  flex-basis: 100%;
  color: var(--ink-3);
}
/* Lista estática das jornadas. Nenhuma é "a nossa": são exemplos do que cabe. */
.jornadas-mostra {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: var(--sp-4);
  padding: 0;
  list-style: none;
}
.jornadas-mostra li {
  padding: 4px 10px;
  border: var(--hairline);
  border-radius: var(--r-pill);
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--ink-2);
  background: var(--panel);
}
/* ESPELHO. A palavra que está girando acima acende o chip correspondente aqui embaixo. As
   duas listas sempre disseram a mesma coisa em dois lugares, e nada ligava uma à outra: o
   olho lia "checkout" em cima e varria dez chips iguais embaixo procurando qual era. A classe
   entra pelo JS e o par é por TEXTO, não por índice — jornada que o visitante escreve entra
   nas duas listas em posições diferentes, e índice casaria errado exatamente aí.

   O FUNDO é o único que diz "esta é a que está girando agora", e não divide esse papel com
   ninguém: o chip que o visitante criou se identifica pela BORDA e pelo `×` — ver o bloco de
   `[data-nova]` mais abaixo. A transição existe porque a troca é automática a cada 2,1 s:
   sem ela, dez chips piscando é ruído. */
.jornadas-mostra li.is-espelho {
  border-color: var(--indigo);
  color: var(--ink-1);
  background: var(--indigo-tint);
}
.jornadas-mostra li {
  transition:
    border-color var(--giro-troca) var(--ease),
    color var(--giro-troca) var(--ease),
    background-color var(--giro-troca) var(--ease);
}
.jornadas-mostra li[data-livre] {
  border-style: dashed;
  border-color: var(--rule-strong);
  color: var(--ink-3);
  background: none;
}
/* Com JS o último chip vira campo: escreva o nome da sua jornada e dê enter. É a demonstração
   mais curta do que a página afirma — o vocabulário é seu. Sem JS continua sendo só a frase. */
.jornadas-mostra li[data-livre]:has(input) {
  padding: 0;
}
.jornadas-mostra input {
  font: inherit;
  color: var(--ink-1);
  background: none;
  border: 0;
  border-radius: var(--r-pill);
  padding: 4px 10px;
  width: 22ch; /* 18 caracteres do placeholder + os 20 px de padding, em border-box */
  min-width: 0;
}
.jornadas-mostra input::placeholder {
  color: var(--ink-3);
  opacity: 1;
}
/* O chip criado diz "esta é sua" pela BORDA índigo e pelo `×` que nenhum outro chip tem —
   nunca pela tinta. Até 17/09/2026 ele repetia as três declarações do espelho, e o comentário
   acima chamava isso de proposital. Era defeito, e fica a medição: bastava UMA jornada criada
   para que girar qualquer outra palavra acendesse dois chips ao mesmo tempo, e girar a própria
   não acendesse nada — o vínculo um-para-um morria exatamente nas jornadas que ele existe para
   servir. Não devolver `color` nem `background` aqui: `.is-espelho` vale (0,2,1) igual a este
   seletor e vem ANTES no arquivo, então qualquer uma das duas declarada aqui ganha o empate
   por ordem e apaga o espelho de novo, em silêncio. */
.jornadas-mostra li[data-nova] {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding-right: 3px;
  border-color: var(--indigo);
}
.jornada-x {
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ink-3);
  line-height: 1;
  font-size: 13px;
  transition:
    color 120ms,
    background-color 120ms;
}
.jornada-x:hover {
  color: var(--ink-1);
  background: var(--wash, rgb(20 24 43 / 0.08));
}

/* Painel de resposta */
.resposta {
  /* Contêiner de consulta: o que decide o tamanho do número e do anel é a largura DESTE
     painel, não a da janela. A partir de 768 px o resumo vai a quatro colunas enquanto o
     painel cai para ~345 px, e antes disso o "100" saía da célula e era cortado pelo
     overflow: hidden logo abaixo. */
  container-type: inline-size;
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: 100%;
}
.resposta > * {
  min-width: 0;
}
.resposta__topo {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3);
  padding: 14px var(--sp-4);
  border-bottom: var(--hairline);
}
.resposta__rota {
  font: 500 var(--fs-code) / 1.2 var(--font-mono);
  color: var(--ink-1);
  white-space: nowrap;
}
.resposta__rota .st {
  color: var(--sig-presente);
}
/* O rótulo do exemplo não pode ser cortado pelo overflow:hidden do painel: entre 768 e
   1100 px ele não cabia na linha da rota e sumia pela direita. Agora desce uma linha. */
.resposta__topo .chip--nota {
  min-width: 0;
  white-space: normal;
}
.jornada {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px var(--sp-4);
  border-bottom: var(--hairline);
}
.jornada__abas {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}
.jornada__aba {
  flex: none;
  height: 30px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  border: var(--hairline);
  font: 500 var(--fs-label) / 1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--panel);
  transition:
    background-color 120ms,
    border-color 120ms,
    color 120ms;
}
.jornada__aba:hover {
  border-color: var(--rule-strong);
  color: var(--ink-1);
}
.jornada__aba[aria-selected="true"] {
  background: var(--ink-1);
  border-color: var(--ink-1);
  color: var(--paper);
}
.resumo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-bottom: var(--hairline);
  background: var(--panel);
}
.resumo__celula {
  padding: 14px var(--sp-4);
  border-right: var(--hairline);
  border-bottom: var(--hairline);
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.resumo__celula:nth-child(2n) {
  border-right: 0;
}
.resumo__legenda {
  overflow-wrap: anywhere;
}
.resumo__valor {
  display: flex;
  align-items: center;
  gap: clamp(6px, 2cqi, 12px);
  min-width: 0;
  min-height: clamp(32px, 9cqi, 56px);
}
.resumo .t-metric {
  font-size: clamp(1.375rem, 9cqi, var(--fs-metric));
}
.resumo .anel {
  width: clamp(26px, 9cqi, 56px);
  height: clamp(26px, 9cqi, 56px);
}

/* Quatro colunas só quando o painel comporta quatro. Antes isto pendurava em
   @media (min-width: 768px), largura em que o painel cai para ~345 px: o "100" saía da
   célula e o overflow: hidden do painel comia o último dígito. */
@container (min-width: 560px) {
  .resumo {
    grid-template-columns: 1.1fr 1fr 1fr 1.2fr;
  }
  .resumo__celula {
    border-bottom: 0;
  }
  .resumo__celula:nth-child(2n) {
    border-right: var(--hairline);
  }
  .resumo__celula:nth-child(4) {
    border-right: 0;
  }
  .resumo__rec {
    border-top: var(--hairline);
  }
}
.resumo__valor[data-medida] .t-metric {
  color: var(--escala, var(--ink-1));
}
.resumo__valor .t-metric.null {
  font-style: italic;
  font-weight: 400;
  color: var(--ink-3);
  font-size: 1.5rem;
}
.resumo__legenda {
  font: 400 var(--fs-label) / 1.3 var(--font-mono);
  color: var(--ink-3);
  letter-spacing: 0.02em;
}
.resumo__rec {
  grid-column: 1 / -1;
  padding: 14px var(--sp-4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  border-bottom: var(--hairline);
}
.resumo__rec .t-small {
  color: var(--ink-3);
}
.resumo__basis {
  font: 400 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.06em;
  color: var(--ink-3);
}
.resumo__codes {
  grid-column: 1 / -1;
  padding: 10px var(--sp-4);
  font: 400 var(--fs-label) / 1.6 var(--font-mono);
  letter-spacing: 0.02em;
  color: var(--ink-3);
  overflow-wrap: anywhere;
}
.resumo__codes b {
  font-weight: 500;
  color: var(--ink-2);
}
/* JSON: um trecho legível sempre à vista e a resposta completa sob demanda.
   Nenhum dos dois rola por dentro: linha longa quebra, painel cresce. */
.json {
  margin: 0;
  font: 400 var(--fs-code) / 1.55 var(--font-mono);
  color: var(--ink-1);
  background: var(--panel);
}
.json--trecho {
  padding: 12px var(--sp-4) 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.json--trecho .json__linha {
  display: block;
  padding-right: 0;
}
.json--trecho .json__linha--foco {
  margin-inline: calc(-1 * var(--sp-4));
  padding-inline: var(--sp-4);
}
.resposta__completa {
  border-top: var(--hairline);
}
.resposta__completa > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px var(--sp-4);
  color: var(--ink-2);
}
.resposta__completa > summary::-webkit-details-marker {
  display: none;
}
.resposta__completa > summary::before {
  content: "+";
  flex: none;
  width: 14px;
  font: 500 var(--fs-code) / 1 var(--font-mono);
  color: var(--indigo);
}
.resposta__completa[open] > summary::before {
  content: "−";
}
.resposta__completa > summary:hover {
  color: var(--indigo);
}
.resposta__completa > summary:focus-visible {
  /* Inset ring, so the forced-colors outline goes inside as well. */
  outline: 2px solid transparent;
  outline-offset: -2px;
  box-shadow: inset 0 0 0 2px var(--indigo);
}
.json--completa {
  border-top: var(--hairline);
  padding: 10px 0;
}
.json--completa .json__c {
  flex: 1;
  min-width: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* Linha quebrada continua 2ch para dentro: a estrutura do JSON segue legível. */
.json--trecho .json__c,
.json--completa .json__c {
  display: block;
  padding-left: 2ch;
  text-indent: -2ch;
}
.resposta__recolher {
  display: block;
  width: 100%;
  text-align: left;
  padding: 11px var(--sp-4) 11px calc(var(--sp-4) + 24px);
  border: 0;
  border-top: var(--hairline);
  background: var(--paper-deep);
  color: var(--ink-2);
  cursor: pointer;
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.resposta__recolher:hover {
  color: var(--indigo);
}
.resposta__recolher:focus-visible {
  outline: 2px solid transparent;
  outline-offset: -2px;
  box-shadow: inset 0 0 0 2px var(--indigo);
}
.json__linha {
  display: flex;
  gap: 12px;
  padding-right: var(--sp-4);
  position: relative;
}
.json__n {
  flex: none;
  width: 32px;
  padding-left: 12px;
  text-align: right;
  color: var(--ink-3);
  user-select: none;
  font-size: var(--fs-label);
  line-height: 1.55rem;
}
.json__linha--foco,
.json__linha.is-linked {
  background: var(--indigo-tint);
}
.json__linha.is-linked::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--indigo);
}
.json__linha .k {
  color: var(--ink-2);
}
.json__linha .s {
  color: var(--ink-1);
}
.json__linha .n {
  color: var(--ink-1);
}
.json__linha .b {
  color: var(--ink-3);
  font-style: italic;
}
.json__linha .p {
  color: var(--rule-strong);
}
.json__linha .e {
  color: var(--indigo);
  font-weight: 500;
}
.json__linha .dots,
.json__linha .c {
  color: var(--ink-3);
}
.json__linha .c {
  font-style: italic;
}
.json__linha .nucleo {
  margin-inline-start: 10px;
}
.resposta__rodape {
  padding: 12px var(--sp-4);
  border-top: var(--hairline);
  display: grid;
  gap: 6px;
}
.resposta__rodape .t-label {
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.resposta__rodape .t-label b {
  font-weight: 500;
  color: var(--ink-2);
}

/* ---------- 6. Faixa de números ---------------------------------------------- */

.faixa--tinta {
  background: var(--ink-band);
  color: var(--ink-on-band);
  padding-block: var(--band-y);
}
.faixa__grade {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--sp-5);
  border-top: 1px solid var(--rule-on-band);
  border-left: 1px solid var(--rule-on-band);
}
.faixa__item {
  padding: var(--sp-5) var(--sp-4);
  border-right: 1px solid var(--rule-on-band);
  border-bottom: 1px solid var(--rule-on-band);
  min-width: 0;
}
.faixa__item .t-label {
  color: var(--indigo-core);
  margin-top: var(--sp-3);
  text-wrap: balance;
}
/* Two labelled groups (contract constants, then console and network lists). The label sits
   in the band's own ink, like the eyebrow; the numeral captions keep the nucleus colour. */
.faixa__grupo {
  margin-top: var(--sp-5);
  color: var(--ink-on-band);
}
.faixa__grupo + .faixa__grade {
  margin-top: var(--sp-3);
}
/* Os zeros deliberados. Fora da grade de numerais, com rótulo próprio, para que "nunca
   coletamos" não seja lido como "ainda não temos". */
.faixa__nunca {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--rule-on-band);
  display: grid;
  gap: var(--sp-3);
}
.faixa__nunca-rotulo {
  color: var(--indigo-core);
}
.faixa__nunca ul {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.faixa__nunca li {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-on-band);
}
.faixa__nunca li::before {
  content: "";
  width: 10px;
  height: 10px;
  margin-top: 6px;
  border: 1px solid var(--rule-on-band);
  background:
    linear-gradient(
      to bottom right,
      transparent calc(50% - 1px),
      var(--indigo-core) calc(50% - 1px) calc(50% + 1px),
      transparent calc(50% + 1px)
    ),
    linear-gradient(
      to bottom left,
      transparent calc(50% - 1px),
      var(--indigo-core) calc(50% - 1px) calc(50% + 1px),
      transparent calc(50% + 1px)
    );
}
.faixa__rodape {
  margin-top: var(--sp-5);
  color: var(--ink-on-band);
  opacity: 0.7;
}
.faixa--tinta .t-label.faixa__eyebrow {
  color: var(--ink-on-band);
}
.faixa--tinta :focus-visible {
  box-shadow: var(--focus-ring-band);
}

/* ---------- 7. Medidas ------------------------------------------------------- */

.medida .t-h3 {
  margin-top: var(--sp-2);
}
.medida__quadro {
  margin-top: var(--sp-4);
}
.medida .regua-caixa {
  margin-top: var(--sp-3);
}
.medida__valor--sm + .regua-caixa {
  margin-top: var(--sp-4);
}
.medida__def {
  margin-top: var(--sp-4);
  color: var(--ink-2);
  font-size: var(--fs-small);
  line-height: 1.55;
}
.medida__nao {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: var(--hairline);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-2);
}
.medida__nao b {
  font-weight: 600;
  color: var(--ink-1);
}
.medida--hero .t-metric {
  font-size: clamp(3rem, 2rem + 4vw, 5.5rem);
  margin-top: 0;
}

/* ---------- 8. Matriz dos 13 ------------------------------------------------ */

.matriz__legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-top: var(--sp-3);
}
.familia {
  margin-top: var(--sp-5);
}
.familia + .familia {
  margin-top: var(--sp-5);
}
.familia__nome {
  margin-bottom: var(--sp-2);
}
.matriz__grade {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.sinal {
  appearance: none;
  font: inherit;
  text-align: left;
  color: inherit;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 96px;
  padding: 12px 14px;
  border-radius: var(--r-inner);
  border: 1px solid var(--rule);
  background: var(--panel);
  position: relative;
  transition:
    background-color 120ms,
    border-color 120ms;
  min-width: 0;
}
.sinal:hover,
.sinal.is-linked,
.sinal[aria-pressed="true"] {
  background: color-mix(in srgb, var(--indigo-tint) 50%, var(--panel));
}
.sinal:focus-visible {
  box-shadow: inset 0 0 0 2px var(--indigo);
  border-radius: var(--r-inner);
}
.sinal[data-state="DETECTED"] {
  background: var(--indigo-tint);
  border-color: var(--detected-edge, rgb(43 47 134 / 0.4));
}
.sinal[data-state="DETECTED"]:hover,
.sinal[data-state="DETECTED"].is-linked {
  background: color-mix(in srgb, var(--indigo-tint) 80%, var(--indigo) 10%);
}
.sinal[data-state="NOT_EVALUATED"] {
  background: var(--paper-sunken, var(--paper-deep));
  border-style: dashed;
  border-color: var(--rule-strong);
}
.sinal__codigo {
  font: 500 var(--fs-code) / 1.35 var(--font-mono);
  color: var(--ink-1);
  overflow-wrap: anywhere;
}
.sinal__nome {
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.35;
}
.sinal__meta {
  margin-top: auto;
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-3);
  letter-spacing: 0.02em;
  overflow-wrap: anywhere;
}
.sinal__motivo {
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-2);
  overflow-wrap: anywhere;
}
.sinal--largo {
  grid-column: 1 / -1;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 24px;
  min-height: 0;
}
.sinal--largo .sinal__frase {
  flex: 1 1 260px;
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.5;
}
.sinal--largo .sinal__meta {
  margin-top: 0;
  flex-basis: 100%;
}
.sinal::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: var(--r-inner);
  border: 1px solid var(--indigo-halo);
  opacity: 0;
  pointer-events: none;
}
.matriz__rodape {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: var(--hairline);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 20px;
}
.matriz__rodape .t-small {
  flex: 1 1 320px;
}
.tres-estados li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 10px;
  padding-block: 12px;
  border-bottom: var(--hairline);
}
.tres-estados li:last-child {
  border-bottom: 0;
}
.tres-estados .glifo {
  margin-top: 4px;
}
.tres-estados .estado-palavra {
  grid-column: 2;
}
.tres-estados .mono-meta {
  grid-column: 2;
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-3);
  overflow-wrap: anywhere;
}
.tres-estados .mono-meta b {
  font-weight: 500;
  color: var(--ink-2);
}

/* ---------- 8a. Contexto da investigação ------------------------------------- */

/* The six themes of context-insight.v1. The column count follows the panel, not the window:
   two columns while the panel has room for two 280 px themes, one below that. The pairs are
   ordered as the console orders them (similar lengths side by side). */
.contexto__temas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17.5rem), 1fr));
  gap: var(--sp-4) var(--sp-6);
  margin-top: var(--sp-4);
}
.contexto__tema {
  padding-top: var(--sp-3);
  border-top: var(--hairline);
}
.contexto__nome span {
  letter-spacing: 0.02em;
}
.contexto__itens {
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-2);
  text-wrap: pretty;
}
.contexto__estado {
  color: var(--ink-1);
  font-weight: 600;
}

/* ---------- 9. Estados / inconclusivo --------------------------------------- */

/* Fallback por jornada.
 *
 * Era uma tabela de três colunas dentro de um painel de meia largura: no notebook a coluna
 * do código encostava na do texto e as duas se liam como uma frase só. Aqui a recomendação
 * fica na linha de cima, alinhada à direita, e o caso ocupa a largura inteira. Nada encosta
 * em nada em largura nenhuma, e some a rolagem lateral que a tabela exigia. */
.fallbacks {
  display: grid;
  margin-top: var(--sp-3);
  padding: 0;
  list-style: none;
}
.fallbacks > li {
  display: grid;
  gap: 6px;
  padding: 14px 0;
  border-top: var(--hairline);
  min-width: 0;
}
.fallbacks > li:first-child {
  border-top: 0;
  padding-top: 4px;
}
.fallback__cab {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  min-width: 0;
}
.fallback__jornada {
  font: 500 var(--fs-code) / 1.3 var(--font-mono);
  color: var(--ink-1);
  min-width: 0;
  overflow-wrap: anywhere;
}
.fallback__jornada .fallback__papel {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--ink-3);
  margin-top: 2px;
}
.fallback__cab .ladder {
  flex: none;
}
.fallback__caso {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--ink-2);
  min-width: 0;
}
.fallback__caso code {
  overflow-wrap: anywhere;
}

/* auto-fit com piso real: no painel de meia largura a 1024 px eram duas colunas de 105 px,
   e todo reason code quebrava no meio da palavra. Abaixo de ~370 px de painel vira uma só. */
.estados4 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 8px;
}
.estado {
  border: var(--hairline);
  border-radius: var(--r-inner);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.estado .t-metric {
  font-size: 1.75rem;
}
.estado .t-metric.null {
  font-style: italic;
  font-weight: 400;
  color: var(--ink-3);
}
/* `anywhere` partia INSUFFICIENT_EVIDENCE em "EVIDE / NCE". Com os <wbr> no HTML a quebra
   cai no "_", que é onde o código tem junta; `break-word` só age se ainda não couber. */
.estado__basis {
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-3);
  overflow-wrap: break-word;
}
.limites {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: var(--sp-3);
}

/* ---------- 10. Recomendações ------------------------------------------------ */

.fluxo {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}
.fluxo__col {
  border: var(--hairline);
  border-radius: var(--r-inner);
  padding: var(--sp-4);
  min-width: 0;
}
.fluxo__col--decide {
  background: var(--indigo-tint);
  border-color: var(--indigo-edge, rgb(67 56 202 / 0.35));
}
.fluxo__col .t-label {
  margin-bottom: var(--sp-3);
  overflow-wrap: anywhere;
}
.fluxo__lista li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding-block: 8px;
  border-bottom: var(--hairline);
  font: 500 var(--fs-code) / 1.4 var(--font-mono);
  color: var(--ink-1);
  min-width: 0;
}
/* A coluna é estreita e BLOCK_RECOMMENDED tem 17 caracteres em mono: o glifo sobe
   para a sua própria linha e o código ocupa a largura inteira, quebrando no "_". */
.fluxo__lista .ladder {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0;
  white-space: normal;
}
.fluxo__lista .ladder svg {
  flex: none;
}
.fluxo__lista .ladder__codigo {
  overflow-wrap: anywhere;
}
.fluxo__lista li:last-child {
  border-bottom: 0;
}
.fluxo__seta {
  display: none;
  align-self: center;
  color: var(--rule-strong);
}
.fluxo__decide-txt {
  color: var(--ink-2);
  font-size: var(--fs-small);
  line-height: 1.5;
}
.fluxo__decide-txt b {
  color: var(--ink-1);
  font-weight: 600;
}
.recs li {
  padding-block: 12px;
  border-bottom: var(--hairline);
}
.recs li:last-child {
  border-bottom: 0;
}
.recs p {
  margin-top: 6px;
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.5;
}
.recs p b {
  font-weight: 600;
  color: var(--ink-1);
}
.nunca {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: var(--hairline);
}
.nunca li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-small);
  color: var(--ink-2);
}

/* ---------- 11. Integração --------------------------------------------------- */

.passo .t-h3 {
  padding-right: 56px;
}
.codigo-rola {
  margin-top: var(--sp-4);
  border-top: var(--hairline);
}
.codigo-rola:focus-visible {
  box-shadow: none;
  outline: 2px solid var(--indigo);
  outline-offset: 2px;
}
.codigo-rola pre.codigo {
  border: 0;
  border-radius: 0;
  padding-inline: 0;
  background: none;
}
.passo pre.codigo {
  margin-top: 0;
  border: 0;
  border-radius: 0;
  padding-inline: 0;
  overflow-x: visible;
  background: none;
}
.passo__nota {
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: var(--hairline);
  font: 400 var(--fs-label) / 1.6 var(--font-mono);
  letter-spacing: 0.02em;
  color: var(--ink-3);
}
.espelho .kv {
  margin-top: var(--sp-4);
}
.espelho .ladder {
  margin-top: var(--sp-4);
}
.superficies {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  align-items: center;
}
.superficies li {
  display: inline-flex;
  align-items: center;
  font: 500 var(--fs-label) / 1.2 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-1);
}

/* ---------- 12. Segurança --------------------------------------------------- */

.zt {
  width: 100%;
  height: auto;
  font-family: var(--font-mono);
}
.zt .caixa {
  fill: var(--panel);
  stroke: var(--ink-2);
  stroke-width: 1.5;
}
.zt .caixa--ftid {
  fill: var(--indigo-tint);
  stroke: var(--indigo);
}
.zt .seta {
  stroke: var(--ink-2);
  stroke-width: 1.5;
  fill: none;
  marker-end: url(#ponta);
}
.zt .seta--cortada {
  stroke: var(--rule-strong);
  stroke-dasharray: 4 4;
  marker-end: none;
}
.zt text {
  font-size: 12px;
  fill: var(--ink-2);
  letter-spacing: 0.04em;
}
.zt .rotulo {
  font-weight: 500;
  fill: var(--ink-1);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.zt .cruz {
  stroke: var(--sem-warm);
  stroke-width: 1.5;
}
.zt .anot {
  fill: var(--ink-3);
  font-size: 11.5px;
}
.envelope {
  border: var(--hairline-strong);
  border-radius: var(--r-inner);
  overflow: hidden;
}
.envelope__linha {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 4px 20px;
  padding: 10px 14px;
  border-bottom: var(--hairline);
}
.envelope__linha:last-child {
  border-bottom: 0;
}
.envelope__linha--titulo {
  background: var(--paper-sunken, var(--paper-deep));
  font: 500 var(--fs-code) / 1.4 var(--font-mono);
  color: var(--ink-1);
}
.envelope__h {
  font: 400 var(--fs-code) / 1.5 var(--font-mono);
  color: var(--ink-1);
  overflow-wrap: anywhere;
}
.envelope__h .ph {
  color: var(--ink-3);
  font-style: italic;
}
.envelope__nota {
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.45;
}
.lampadas {
  display: grid;
  gap: 10px;
  margin-top: var(--sp-4);
}
.lampadas li {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: baseline;
  gap: 10px;
  font-size: var(--fs-small);
  color: var(--ink-2);
}
.lampadas .cod {
  font: 500 var(--fs-code) / 1 var(--font-mono);
  color: var(--ink-1);
}
.lampadas .glifo {
  align-self: center;
}

/* ---------- 13. Política ----------------------------------------------------- */

.policy__nome {
  font: 500 1.125rem / 1.3 var(--font-mono);
  color: var(--ink-1);
  margin-top: var(--sp-2);
  overflow-wrap: anywhere;
}
.policy .kv {
  margin-top: var(--sp-4);
}
.congela {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 16px;
  margin-top: var(--sp-3);
}
.congela li {
  display: flex;
  align-items: center;
  gap: 10px;
  font: 500 var(--fs-code) / 1.4 var(--font-mono);
  color: var(--ink-1);
  padding-block: 6px;
  border-bottom: var(--hairline);
}
.rev {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}
.rev__par {
  display: flex;
  align-items: center;
  gap: 12px;
  font: 400 var(--fs-code) / 1.5 var(--font-mono);
  overflow-wrap: anywhere;
  flex-wrap: wrap;
}
.rev__par .v {
  color: var(--ink-1);
  font-weight: 500;
}

/* ---------- 14. Shadow mode -------------------------------------------------- */

.timeline {
  display: grid;
  grid-template-columns: repeat(5, minmax(180px, 1fr));
  gap: 0;
  padding-block: var(--sp-3);
  min-width: 900px;
}
.timeline li {
  position: relative;
  padding-right: var(--sp-5);
  padding-top: 26px;
}
.timeline li::before {
  content: "";
  position: absolute;
  left: 12px;
  right: 0;
  top: 5px;
  height: 1px;
  background: var(--rule-strong);
}
.timeline li:last-child::before {
  display: none;
}
/* The connecting rule is a 1 px background bar; forced colors would repaint it as Canvas. */
@media (forced-colors: active) {
  .timeline li::before {
    background: CanvasText;
  }
}
.timeline .nucleo--lg {
  position: absolute;
  top: 0;
  left: 0;
  box-shadow:
    0 0 0 4px var(--panel),
    0 0 0 6px var(--indigo-halo);
}
.timeline__n {
  font: 400 var(--fs-label) / 1 var(--font-mono);
  color: var(--ink-3);
  letter-spacing: 0.08em;
}
.timeline__t {
  margin-top: 6px;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--ink-1);
  line-height: 1.35;
}
.timeline__d {
  margin-top: 4px;
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-3);
  overflow-wrap: anywhere;
}
.timeline__deriva {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px dashed var(--rule-strong);
  font: 400 var(--fs-label) / 1.4 var(--font-mono);
  color: var(--ink-2);
}
.timeline__deriva b {
  font-weight: 500;
  color: var(--ink-1);
}
.loop li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding-block: 10px;
  border-bottom: var(--hairline);
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.5;
}
.loop li:last-child {
  border-bottom: 0;
}
.loop b {
  color: var(--ink-1);
  font-weight: 600;
}

/* ---------- 15. Privacidade -------------------------------------------------- */

.contrato pre.codigo {
  margin-top: 0;
  padding-inline: 0;
  border: 0;
  border-radius: 0;
}
.pa {
  width: 100%;
  height: auto;
  margin-top: var(--sp-3);
  font-family: var(--font-mono);
}
.pa .no {
  fill: var(--panel);
  stroke: var(--ink-2);
  stroke-width: 1.5;
}
.pa .no--party {
  fill: var(--indigo-tint);
  stroke: var(--indigo);
}
.pa .liga {
  stroke: var(--rule-strong);
  stroke-width: 1;
  fill: none;
}
.pa text {
  font-size: 12px;
  fill: var(--ink-1);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ---------- 16. Superfícies -------------------------------------------------- */

.esquema {
  width: 100%;
  height: auto;
  margin-top: var(--sp-3);
}
.areas {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 24px;
  margin-top: var(--sp-3);
}
.areas li {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding-block: 8px;
  border-bottom: var(--hairline);
  font-size: var(--fs-small);
  color: var(--ink-1);
}
.areas li span {
  font: 400 var(--fs-label) / 1 var(--font-mono);
  color: var(--ink-3);
  letter-spacing: 0.06em;
}
.console-detalhe {
  margin-top: var(--sp-5);
  display: grid;
  gap: var(--sp-3);
}
.console-detalhe p {
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.55;
}
.console-detalhe p b {
  color: var(--ink-1);
  font-weight: 600;
}

/* ---------- 17. Cobrança ----------------------------------------------------- */

.cobranca__grade {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-6) var(--sp-7);
}
.cobranca__unidade .t-h3 {
  font-size: clamp(1.375rem, 1.1rem + 1vw, 1.875rem);
  margin-top: var(--sp-3);
}
.cobranca__unidade .t-h3 b {
  color: var(--indigo);
}
.naoconta li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding-block: 9px;
  border-bottom: var(--hairline);
  font-size: var(--fs-small);
  color: var(--ink-1);
}
.naoconta li span:last-child {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: 500 var(--fs-label) / 1 var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--ink-2);
}
.naoconta li:first-child {
  border-top: var(--hairline-strong);
}
.regras3 li {
  padding-block: 10px;
  border-bottom: var(--hairline);
  font-size: var(--fs-small);
  color: var(--ink-2);
  line-height: 1.5;
}
.regras3 li:last-child {
  border-bottom: 0;
}
.cobranca__rodape {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: var(--hairline);
}

/* ---------- 18. FAQ ---------------------------------------------------------- */

.faq {
  border-top: var(--hairline-strong);
}
.faq__item {
  border-bottom: var(--hairline);
}
.faq__item > summary {
  list-style: none;
  cursor: pointer;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 24px;
  align-items: center;
  gap: var(--sp-3);
  padding: 18px 8px 18px 0;
  transition: background-color 120ms;
}
.faq__item > summary::-webkit-details-marker {
  display: none;
}
.faq__item > summary:hover {
  background: var(--paper-deep);
}
.faq__item > summary:hover .faq__n {
  color: var(--indigo);
}
.faq__n {
  font: 500 var(--fs-label) / 1 var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--ink-3);
  padding-left: 8px;
  transition: color 120ms;
}
.faq__q {
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.faq__glifo {
  width: 12px;
  height: 12px;
  position: relative;
  justify-self: end;
  margin-right: 6px;
  transition: transform 200ms var(--ease);
}
.faq__glifo::before,
.faq__glifo::after {
  content: "";
  position: absolute;
  background: var(--ink-1);
  left: 0;
  top: 50%;
  width: 12px;
  height: 1px;
  transform: translateY(-50%);
}
.faq__glifo::after {
  transform: translateY(-50%) rotate(90deg);
}
.faq__item[open] .faq__glifo {
  transform: rotate(45deg);
}
/* The + and × are two 1 px bars drawn with background, which forced colors repaints as Canvas. */
@media (forced-colors: active) {
  .faq__glifo::before,
  .faq__glifo::after {
    background: CanvasText;
  }
}
.faq__a {
  padding: 0 44px 22px 52px;
  max-inline-size: 70ch;
  color: var(--ink-2);
  font-size: var(--fs-body);
  line-height: 1.6;
}
.faq__a code {
  font-size: var(--fs-code);
  color: var(--ink-1);
}

/* ---------- 19. CTA + formulário -------------------------------------------- */

.form {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}
.campo {
  display: grid;
  gap: 6px;
}
.campo input[type="email"],
.campo input[type="text"] {
  height: 44px;
  padding: 0 12px;
  border: var(--hairline-strong);
  border-radius: var(--r-inner);
  background: var(--panel);
  font-size: 1rem;
  transition: border-color 120ms;
}
.campo input:hover {
  border-color: var(--ink-2);
}
/* The form leaves the placeholder to the browser, and Chrome paints rgb(117 117 117) in both
   color schemes: 4.61:1 on the light panel but 4.03:1 on the dark one. Dark only, so the light
   form stays exactly as it was; screen only, like the dark palette, so print stays light. */
@media screen {
  :root[data-theme="dark"] .campo input::placeholder {
    color: var(--ink-3);
    opacity: 1;
  }
}
.campo input:focus-visible {
  border-color: var(--indigo);
  box-shadow: var(--focus-ring-panel);
}
.form[data-tentou] input:invalid {
  border-color: var(--erro);
}
.campo__erro {
  font-size: var(--fs-small);
  color: var(--erro);
  display: none;
}
.form[data-tentou] input:invalid ~ .campo__erro {
  display: block;
}
.jornadas-check {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
}
.campo__nota {
  margin-top: 10px;
  color: var(--ink-3);
  line-height: 1.5;
}
.check {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  font: 500 var(--fs-code) / 1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--ink-1);
  min-height: 44px;
}
.check input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.check__caixa {
  width: 14px;
  height: 14px;
  border: 1px solid var(--rule-strong);
  border-radius: 1px;
  position: relative;
  transition: border-color 120ms;
}
.check:hover .check__caixa {
  border-color: var(--ink-2);
}
.check input:focus-visible + .check__caixa {
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: var(--focus-ring-panel);
}
.check__caixa::after {
  content: "";
  position: absolute;
  inset: 2px;
  background: var(--indigo);
  transform: scale(0);
  transition: transform 160ms var(--ease);
}
.check input:checked + .check__caixa {
  border-color: var(--indigo);
}
.check input:checked + .check__caixa::after {
  transform: scale(1);
}
/* The mark is only a background, which forced colors repaints as Canvas, and the border is
   CanvasText checked or not: without this the checked state is indistinguishable there. The
   focus ring sits on the box, a span that is never focused itself, so forced colors would
   paint its outline CanvasText like the border; Highlight is what every focused control gets. */
@media (forced-colors: active) {
  .check__caixa::after {
    background: CanvasText;
  }
  .check input:focus-visible + .check__caixa {
    outline-color: Highlight;
  }
}
.form__status {
  font-size: var(--fs-small);
  color: var(--ink-2);
  min-height: 1.5em;
}
.form__status[data-kind="error"] {
  color: var(--erro);
}
.form__status[data-kind="ok"] {
  color: var(--sem-cool);
}
.form__nota {
  margin-top: var(--sp-2);
}
.onde li {
  display: flex;
  gap: 10px;
  align-items: center;
  padding-block: 9px;
  border-bottom: var(--hairline);
  font-size: var(--fs-small);
  color: var(--ink-1);
}
.onde li[data-state="NOT_DETECTED"] {
  color: var(--ink-2);
}
.depois {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: var(--hairline);
}
.depois ol,
.passos-inicio {
  display: grid;
  gap: 8px;
  margin-top: var(--sp-3);
  counter-reset: passo;
}
.depois ol li,
.passos-inicio li {
  display: flex;
  gap: 12px;
  align-items: baseline;
  font-size: var(--fs-small);
  color: var(--ink-2);
}
.depois ol li::before,
.passos-inicio li::before {
  counter-increment: passo;
  content: "0" counter(passo);
  font: 500 var(--fs-label) / 1 var(--font-mono);
  color: var(--ink-3);
  letter-spacing: 0.08em;
}

/* ---------- 20. Footer ------------------------------------------------------- */

.footer {
  background: var(--paper-sunken, var(--paper-deep));
  border-top: var(--hairline);
  padding-block: var(--sp-8) var(--sp-6);
}
.footer__grade {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-6);
}
.footer .wordmark {
  font-size: 1.125rem;
}
.footer__tag {
  margin-top: var(--sp-3);
  max-inline-size: 30ch;
}
.footer__col .t-label {
  margin-bottom: var(--sp-3);
}
.footer__col li {
  padding-block: 5px;
  font-size: var(--fs-small);
}
.footer__col a {
  color: var(--ink-2);
  text-decoration: none;
}
.footer__col a:hover {
  color: var(--indigo);
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* Language switcher, written into the footer by `.site-i18n/i18n.py` on every published page:
   plain links, one per language, each named in its own language and script. */
.idiomas {
  margin-top: var(--sp-5);
  max-inline-size: 34ch;
}
.idiomas .t-label {
  margin-bottom: var(--sp-2);
}
.idiomas ul {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding: 0;
  margin: 0;
  list-style: none;
  font-size: var(--fs-small);
}
.idiomas a {
  color: var(--ink-2);
  text-decoration: none;
}
.idiomas a:hover,
.idiomas a:focus-visible {
  color: var(--indigo);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.idiomas a[aria-current="page"] {
  color: var(--ink-1);
  font-weight: 600;
}
.footer__legal {
  margin-top: var(--sp-7);
  padding-top: var(--sp-4);
  border-top: var(--hairline-strong);
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  justify-content: space-between;
}

/* ---------- 21. Motion ------------------------------------------------------- */

/* Theme swap. Every color token changes in the same frame, but each element would run its own
   `transition` on background/color/border and, for 120-280 ms, the page would show half of one
   palette and half of the other. `scripts/theme.js` puts this class on <html> for the swap
   only and removes it two frames later, so the page's own motion is untouched. Two
   exceptions: the toggle's glyph, whose half turn IS the feedback of the click, and the
   `human` badge text, whose fade-out ends only on `transitionend` (landing.js,
   armarFimDoSelo) — cancelling that transition fires `transitioncancel` instead and the badge
   would never be retired. */
.theme-switching,
.theme-switching *:not(.theme-toggle__glyph):not(.selo__texto),
.theme-switching *::before,
.theme-switching *::after {
  /* biome-ignore lint/complexity/noImportantStyles: must outrank every element's own transition for the two frames of the swap */
  transition: none !important;
}

@keyframes sobe {
  from {
    opacity: 0;
    transform: translateY(var(--dy, 16px));
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes aparece {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes cresce {
  from {
    opacity: 0;
    transform: scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes pulso {
  0% {
    box-shadow:
      0 0 0 3px var(--panel),
      0 0 0 4.5px var(--indigo-halo);
  }
  40% {
    box-shadow:
      0 0 0 3px var(--panel),
      0 0 0 9px var(--indigo-pulse, rgb(67 56 202 / 0.5));
  }
  100% {
    box-shadow:
      0 0 0 3px var(--panel),
      0 0 0 4.5px var(--indigo-halo);
  }
}
@keyframes halo {
  from {
    opacity: 0.8;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(1.06);
  }
}
@keyframes entra-celula {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Tudo com opacity 0 inicial é gateado por html.js: sem script, tudo visível. */
html.js .anim {
  opacity: 0;
  animation: sobe 520ms var(--ease) forwards;
  animation-delay: var(--d, 0ms);
}
html.js .anim--fade {
  animation-name: aparece;
  animation-duration: 240ms;
}
html.js .anim--painel {
  animation-duration: 600ms;
}
html.js .resposta.is-impressa .json__linha {
  opacity: 0;
  --dy: 3px;
  animation: sobe 260ms var(--ease) forwards;
  animation-delay: calc(480ms + var(--i, 0) * 28ms);
}
html.js .resposta.is-impressa .resumo__celula {
  opacity: 0;
  animation: cresce 300ms var(--ease) forwards;
  animation-delay: calc(520ms + var(--i, 0) * 50ms);
}
html.js .resposta.is-impressa .json__selo {
  animation: pulso 700ms var(--ease) 1300ms 1;
}
.resposta.is-trocando .resumo__valor,
.resposta.is-trocando .resumo__rec,
.resposta.is-trocando .resumo__codes,
.resposta.is-trocando .json--trecho,
.resposta.is-trocando .resposta__completa {
  opacity: 0;
  transform: translateY(-4px);
  transition:
    opacity 120ms,
    transform 120ms;
}
.resposta .resumo__valor,
.resposta .resumo__rec,
.resposta .resumo__codes,
.resposta .json--trecho,
.resposta .resposta__completa {
  transition:
    opacity 180ms var(--ease),
    transform 180ms var(--ease);
}
html.js .matriz.is-pendente .sinal {
  opacity: 0;
}
html.js .matriz.is-in .sinal {
  animation: entra-celula 260ms var(--ease) forwards;
  animation-delay: calc(var(--i, 0) * 40ms);
}
html.js .matriz.is-in .sinal[data-state="DETECTED"]::after {
  animation: halo 600ms var(--ease) 640ms 1;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .anim,
  .nucleo,
  .nucleo--lg,
  .resposta *,
  .jornada *,
  .sinal,
  .sinal::after,
  .faq__glifo,
  .nav__link::after,
  .check__caixa::after,
  .giro__palavra,
  .anel__arco,
  .theme-toggle__glyph {
    animation: none !important;
    transition-duration: 0ms !important;
  }
  /* Sem movimento a lista não gira: a primeira palavra fica, e a lista estática abaixo
     continua sendo a fonte completa. */
  .giro__palavra:not(.is-ativa) {
    display: none;
  }
  html.js .anim,
  html.js .matriz.is-pendente .sinal,
  html.js .resposta.is-impressa .json__linha,
  html.js .resposta.is-impressa .resumo__celula {
    opacity: 1;
    transform: none;
  }
}

/* ---------- 22. Media queries ------------------------------------------------ */

@media (min-width: 768px) {
  .span-7,
  .span-8,
  .span-9,
  .span-12 {
    --n: 6;
  }
  .span-5,
  .span-4 {
    --n: 3;
  }
  .hero__grade {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* Four columns from 768 px: the groups hold 8 and 4 numerals, so every row is full. */
  .faixa__grade {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .faixa__nunca {
    grid-template-columns: minmax(0, 220px) minmax(0, 1fr);
    gap: var(--sp-5);
    align-items: start;
  }
  .matriz__grade {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .fluxo {
    grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1fr) 24px minmax(0, 1fr);
    align-items: stretch;
  }
  .fluxo__seta {
    display: flex;
    justify-content: center;
  }
  .envelope__linha {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  }
  .cobranca__grade {
    grid-template-columns: 5fr 7fr;
  }
  .footer__grade {
    grid-template-columns: 3fr 2fr 2fr 2fr;
  }
  .rev {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .nav__acoes .btn--secondary {
    display: inline-flex;
  }
}

@media (min-width: 1024px) {
  .span-7 {
    --n: 7;
  }
  .span-8 {
    --n: 8;
  }
  .span-9 {
    --n: 9;
  }
  .span-12 {
    --n: 12;
  }
  .span-5 {
    --n: 5;
  }
  .span-4 {
    --n: 4;
  }
  .nav__links {
    display: flex;
  }
  .nav__menu {
    display: none;
  }
  .hero__grade {
    grid-template-columns: 5fr 7fr;
    gap: var(--gap);
  }
  .hero__painel {
    margin-top: var(--sp-6);
  }
  .matriz__grade {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .hero .t-h1 {
    max-inline-size: 24ch;
  }
}

/* The theme toggle costs the nav 44 px (36 + one 8 px gap). From 1024 px, where the section
   links appear, to ~1035 px that was enough to squeeze the links container and wrap "Shadow
   mode" onto two lines — measured. Tightening the gap between links from 24 to 16 px only in
   this band gives back 40 px; above it the container has room and the rhythm stays 24. Gated
   like the toggle itself: without JavaScript there is no toggle and the nav stays as it was. */
@media (min-width: 1024px) and (max-width: 1119.98px) {
  :root[data-theme] .nav__links {
    gap: var(--sp-4);
  }
}

/* The bar keeps five section links; "Product" and "Shadow mode" stay in the menu and the footer.
   With translated labels (D246) seven links ran into the wordmark at 1440 px, measured in German. */
.nav__links .nav__link[data-nav-link="medidas"],
.nav__links .nav__link[data-nav-link="shadow"] {
  display: none;
}
.nav__links {
  min-inline-size: 0;
  overflow: hidden;
}
.wordmark {
  flex-shrink: 0;
}

/* Seven section links, and translated labels run longer than the English ones (D246): below
   1280 px the links stay in the menu, so no label ever wraps onto two lines. */
@media (min-width: 1024px) and (max-width: 1279.98px) {
  .nav__links {
    display: none;
  }
  .nav__menu {
    display: block;
  }
}

@media (max-width: 479px) {
  .nav__acoes .btn--primary {
    display: none;
  }
  .wordmark {
    font-size: 1.125rem;
  }
  .json,
  .t-code,
  pre.codigo {
    font-size: 0.75rem;
  }
  .resposta__topo .chip--nota {
    text-align: left;
  }
  .faq__item > summary {
    grid-template-columns: 36px minmax(0, 1fr) 20px;
  }
  .faq__a {
    padding-left: 0;
    padding-right: 0;
  }
  .estados4 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------- 23. Véu de rolagem e cursor de bancada ---------------------------- */

/*
 * Duas camadas de acabamento que só existem para quem tem ponteiro fino, e que nunca
 * mexem no layout: se qualquer uma não puder rodar, a página fica exatamente como antes.
 *
 * O VÉU é uma pilha de três faixas fixas logo abaixo da nav. Cada uma tem um raio de
 * desfoque maior e uma máscara que termina mais cedo, então o topo recebe os três
 * desfoques somados e a base recebe só o menor — é daí que vem a progressão. Uma camada
 * só, com máscara de opacidade, produz névoa uniforme, que é outra coisa.
 *
 * Em repouso o véu fica em opacidade 0. A primeira dobra tem de imprimir exatamente como
 * foi aprovada; quem acende é o `data-rolado`, escrito pelo JS ao sair do topo.
 */

.veu {
  position: fixed;
  top: var(--nav-h);
  left: 0;
  right: 0;
  height: clamp(56px, 9vh, 104px);
  z-index: 9;
  pointer-events: none;
  opacity: 0;
  transition: opacity 280ms var(--ease);
}
html[data-rolado] .veu {
  opacity: 1;
}
.veu > span {
  position: absolute;
  inset: 0;
  display: block;
  -webkit-backdrop-filter: blur(var(--b));
  backdrop-filter: blur(var(--b));
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 var(--ate), transparent var(--fim));
  mask-image: linear-gradient(to bottom, #000 0, #000 var(--ate), transparent var(--fim));
}
.veu > span:nth-child(1) {
  --b: 1px;
  --ate: 58%;
  --fim: 100%;
}
.veu > span:nth-child(2) {
  --b: 4px;
  --ate: 24%;
  --fim: 70%;
}
.veu > span:nth-child(3) {
  --b: 10px;
  --ate: 0%;
  --fim: 38%;
}

/* Sem backdrop-filter as três faixas seriam três camadas de composição sem efeito. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .veu {
    display: none;
  }
}
/* Quem pediu menos transparência pediu menos vidro, não menos contraste. */
@media (prefers-reduced-transparency: reduce) {
  .veu {
    display: none;
  }
}

/*
 * CURSOR. Dois caminhos para o mesmo vocabulário, e quatro estados.
 *
 * O vocabulário tem duas palavras: SETA para andar na página, MIRA para ler dado dentro de
 * uma caixa de informação. Um painel não é clicável e não é prosa — é instrumento —, e é o
 * cursor que diz isso antes de qualquer hover.
 *
 * Sem JavaScript, a imagem de cursor do compositor: desenhada no lugar exato, sem o atraso
 * de um quadro que todo ponteiro feito em JS carrega.
 *
 * Com JavaScript, o ponteiro do DOM mais abaixo, que inverte o que está embaixo dele. Isso
 * uma imagem de cursor não faz, e é o motivo de existir a segunda camada: o desenho nunca
 * precisa adivinhar o fundo, porque ele é o oposto exato do fundo.
 *
 * A troca é uma classe só, `ponteiro-vivo`, posta pelo JS no <html>. Ela reescreve as TRÊS
 * variáveis de desenho abaixo para `none`, e só elas — as regras de campo de texto e de
 * desabilitado continuam intactas, porque `cursor: text` e `cursor: not-allowed` dizem
 * coisas que um desenho não substitui. Esquecer `--seta-medir` nessa lista é o defeito que a
 * terceira variável trouxe de graça, e ele é o INVERSO do que parece: não sobra `cursor: none`
 * sem desenho — sobram DOIS ponteiros, a imagem da mira desenhada pelo compositor e a mira do
 * DOM desenhada em cima dela, que é o que o estado `proprio` existe para impedir. Sem a
 * classe, nada de `cursor: none` em lugar nenhum: página sem JS continua com ponteiro
 * visível.
 *
 * Tela de toque não recebe nada, porque não há cursor.
 */
@media (hover: hover) and (pointer: fine) {
  html {
    --seta-ler: var(--cursor-ler), default;
    --seta-agir: var(--cursor-agir), pointer;
    --seta-medir: var(--cursor-mira), crosshair;
    /* Herdada, então um <span> dentro de um link também responde "agir". É ela que o JS lê
       para engordar a seta e para trocar a silhueta — a cor não pode mais carregar esse
       sinal, porque a inversão devolve o oposto do fundo, não a cor que eu escolher. */
    --estado-ponteiro: ler;
    cursor: var(--seta-ler);
  }
  html.ponteiro-vivo {
    --seta-ler: none;
    --seta-agir: none;
    --seta-medir: none;
  }

  /* ACOMODAÇÃO DE PONTEIRO, de verdade. Sem este bloco, `forced-colors` só fazia o JS
     esconder o desenho do DOM e deixava no lugar a IMAGEM de cursor — 24 px fixos que não
     escalam com o tamanho de ponteiro do sistema, que é justamente a configuração da pessoa.
     E `cursor` não está na lista de propriedades que `forced-colors` força, logo a imagem
     entra com as cores escritas nela, contra um Canvas que a pessoa escolheu. Calculado, não
     estimado: papel #f7f5f0 sobre Canvas #ffffff dá 1,09:1, e tinta #0b0d14 sobre Canvas
     #000000 dá 1,08:1. Em cada um dos dois temas de alto contraste um dos dois tons do
     desenho COLAPSA no fundo, e qual deles sobra depende do tema — num deles a seta fica só
     o contorno de papel de 1,2 px, no outro a mira fica só o halo com o miolo invisível por
     cima. E era o único ponteiro que essa pessoa tinha. (Aqui já se leu "~1,05:1" com uma
     conclusão presa à silhueta antiga, de traço fino; a conta dá 1,09 e a conclusão de agora
     não depende de espessura nenhuma.)
     Palavra-chave devolve o ponteiro do sistema, que é o que estava prometido. `crosshair`
     preserva o sentido da mira sem desenhar nada: o significado sobrevive à acomodação.
     `prefers-reduced-motion` NÃO entra aqui de propósito. Ali o que se tira é o desenho do
     DOM, que carrega um quadro de atraso — argumento de movimento, e válido. Imagem de
     cursor é estática e não tem movimento a reduzir, então quem pediu menos movimento
     continua com o desenho da casa. O README dizia que nos dois caminhos "o ponteiro do
     sistema fica", e isso era falso nos dois. */
  @media (forced-colors: active) {
    html {
      --seta-ler: default;
      --seta-agir: pointer;
      --seta-medir: crosshair;
    }
  }

  /* A CAIXA PERDEU A MIRA — e o que vem abaixo é o registro do que se mediu enquanto ela a
     tinha, porque quem for mexer no alcance de novo reencontra as mesmas armadilhas. Até
     17/09/2026 havia aqui um `:where(.panel) { --estado-ponteiro: medir }`; o dono mandou
     tirar a mira das caixas e a regra saiu inteira, então hoje `.panel` não declara estado
     nenhum e herda `ler`. Para dimensionar um alcance futuro: os 34 `.panel` da página são
     33 `<article>` e um `<div>`, e o `<div>` é justamente o `.panel--forte.resposta` do
     contrato.

     O `:where()` daquela regra zerava a especificidade do seletor, e o caso que ele fechava
     era de MESMO ELEMENTO, não de descendente — esta distinção já foi escrita errada aqui e
     foi medida em navegador. Especificidade só desempata declarações que caem no mesmo
     elemento; um descendente com regra própria vence o valor herdado do ancestral em qualquer
     especificidade do ancestral. Medido: injetando `.panel { --estado-ponteiro: medir }` sem
     `:where()` como ÚLTIMA regra da folha, os 24 clicáveis dentro dos painéis (4 `a`,
     19 `button`, 1 `summary`) continuavam todos em `agir` — delta zero. O que mudava eram os
     `a.panel`/`button.panel` plantados: 4 de 4 viravam `medir`. Esse era o caso real, era
     LATENTE (zero deles) e o `design-spec.md` §7 documenta `Painel com link (a.panel)` como
     padrão suportado — quem devolver qualquer regra de estado a `.panel` precisa do `:where()`
     pelo mesmo motivo.

     O outro cuidado NÃO é histórico, vale hoje, e é sobre o lado `agir`: subir a
     especificidade dele em vez de excluir seria pior. `:is(a, button, …,
     [tabindex]:not([tabindex="-1"]))` vale 0,2,0 — o `:not()` carrega a especificidade do
     próprio argumento, e é ele que manda —, e 0,2,0 ganharia de `[disabled]` (0,1,0),
     devolvendo `agir` para controle desabilitado. A conta de hoje, com o alcance já estreito:
     `[disabled]` (0,1,0) vence `button` (0,0,1) e mantém o `not-allowed` do lado da MIRA, mas
     PERDE do ramo `[tabindex]:not([tabindex="-1"]):not(button):not(.btn)`, que vale 0,3,1.
     Medido nesta página: zero elementos casam os dois lados — não há um só `[disabled]` nem um
     `[tabindex]` fora de botão. A colisão é latente, não viva; está escrita justamente por
     isso. */
  /* BOTÃO: a mira. Ela mirava a CAIXA — os 34 `.panel` da página — e o resultado era que a
     silhueta trocava ao entrar em quase qualquer região de conteúdo, porque painel é o
     contêiner de tudo aqui. Mira sobre um bloco de texto não diz nada: não há o que mirar.
     Agora ela marca o que se APERTA, que é onde mirar quer dizer alguma coisa, e o alcance
     saiu de 34 regiões grandes para os controles que de fato recebem o clique.

     O critério é APARÊNCIA e não tag, e isso foi decisão do dono depois de ver a primeira
     versão: `.btn` são 6 elementos — 5 `<a>` e 1 `<button>` — com o mesmo fundo, a mesma borda
     de 1 px e o mesmo raio de 4, e três deles dizendo "Book a demo". Quem olha vê seis botões
     iguais; que um seja `<a>` é verdade do DOM e invisível na tela. Pela regra da tag, os seis
     se dividiriam em dois cursores sem nada que explicasse a diferença. Então `.btn` entra
     inteira, e `.nav__menu > summary` entra pelo mesmo motivo: medido, 63 × 36 com borda de
     1 px e raio 4 — é o botão "Menu", com pele de `.btn--secondary` e tag de disclosure.

     Os outros dez `<summary>` ficam em `agir` porque a medição os separa: 350 × 51 e
     716 × 60, borda 0 e raio 0. São linhas de acordeão, não botões, e a diferença está na
     tela e não só no DOM.

     Link de navegação fica em `agir`: `a.nav__link`, `a.link` e a wordmark não têm pele de
     botão, e levar a outro lugar é outro gesto. `[role="tab"]` sai da lista por redundância —
     as três abas já são `<button>`. */
  button,
  input[type="submit"],
  .btn,
  .nav__menu > summary {
    cursor: var(--seta-medir);
    --estado-ponteiro: medir;
  }
  a,
  summary,
  label,
  select,
  input[type="checkbox"],
  input[type="radio"],
  /* `:not(button):not(.btn)` NÃO é enfeite, e o defeito que ele fecha foi medido: o seletor
     base vale 0,2,0 e ganha de `button` (0,0,1). Com a roving tabindex das abas, a ATIVA
     carrega `tabindex="0"` e as outras `-1` — então a ativa caía em `agir` e as inativas em
     `medir`, e o cursor trocava a cada clique, no mesmo controle. Excluir aqui é melhor que
     subir a especificidade do lado da mira: `[disabled]` vale 0,1,0 e precisa continuar
     ganhando de `button`, o que só vale enquanto o lado da mira ficar em 0,0,1. */
  [tabindex]:not([tabindex="-1"]):not(button):not(.btn) {
    cursor: var(--seta-agir);
    --estado-ponteiro: agir;
  }
  /* `proprio` = este elemento tem cursor melhor que o nosso desenho. O I-beam diz "dá
     para digitar aqui" e o not-allowed diz "não adianta clicar"; nenhum desenho substitui
     isso. O JS lê este estado e tira o ponteiro da frente, em vez de empilhar dois. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
  textarea {
    cursor: text;
    --estado-ponteiro: proprio;
  }
  [disabled],
  [aria-disabled="true"] {
    cursor: not-allowed;
    --estado-ponteiro: proprio;
  }

  /* Seletores de elemento perdem para os de classe que já fixavam `pointer` antes.
     Estes repetem a especificidade original e vêm depois, então ganham. */
  .resposta__completa > summary,
  .faq__item > summary,
  .check {
    cursor: var(--seta-agir);
    --estado-ponteiro: agir;
  }
  /* Os dois `<button>` que a lista acima segurava em `agir` por serem classe. Contados, não
     presumidos: `.sinal` são 13 `<button>` e `.resposta__recolher` é 1. Deixá-los de fora
     daria mira em botão de aba e seta em botão de célula — a mesma coisa com dois cursores,
     sem nada que a pessoa possa perceber para explicar a diferença. */
  .sinal,
  .resposta__recolher {
    cursor: var(--seta-medir);
    --estado-ponteiro: medir;
  }
}

/*
 * PONTEIRO. O desenho é branco e o elemento inteiro entra em `difference`, então o que
 * aparece na tela é o oposto exato do que está embaixo: sobre papel #f7f5f0 sai (8,10,15),
 * que é praticamente a nossa tinta; sobre a faixa de tinta sai (244,242,235), praticamente
 * o nosso papel. A seta é MASSA CHEIA e a mira é cruz PURA — as duas silhuetas foram
 * escolhidas pelo dono num catálogo de arquétipos, e não deduzidas daqui.
 *
 * As duas trocas melhoram a inversão de verdade, e isso foi MEDIDO por pixel a DPR 1, no
 * blend real, sobre as três superfícies. A fração é idêntica nas três, porque é propriedade
 * da geometria e não do fundo — pixels com tinta que invertem EXATO, contra parciais:
 *
 *     seta    antes 28,1% (43 exatos / 110 parciais)   agora 47,4% (54 / 60)
 *     mira    antes  2,7% ( 5 exatos / 182 parciais)   agora 85,7% (48 /  8)
 *
 * Cobertura parcial sob `difference` devolve CINZA e não inversão: meia cobertura sobre
 * painel branco dá rgb(128,128,128), contraste 3,95:1, contra 21:1 da inversão exata. O salto
 * da mira é o mais bruto e tem causa simples: o braço antigo tinha traço 1,4 centrado em
 * x=16, isto é a faixa [15,3; 16,7], que não enche coluna NENHUMA; o novo, a 2, cai em
 * [15; 17] — duas colunas inteiras, contadas na captura.
 *
 * A seta, honestamente, continua com metade da tinta na borda: é um dardo de 3,06 px de
 * espessura média, e nessa escala perímetro pesa. O que mudou é que o MIOLO agora inverte,
 * porque agora existe miolo — antes ele era vazado e tudo que havia era traço fino em ângulo,
 * cuja espessura precisava ser calculada contra a grade de pixels para que a promessa do
 * parágrafo acima valesse para mais de 6% do braço principal.
 *
 * O branco é literal, não token: `difference` com #fff é inversão exata; com o papel
 * (247,245,240) seria quase-inversão, e o quase apareceria justamente sobre a faixa escura.
 *
 * O blend mora NESTE elemento, o mesmo que o JS transforma, e não num filho. Medido, não
 * deduzido: com o blend no filho o desenho sai branco sobre papel, isto é, não inverte
 * nada. Pai transformado abre grupo próprio e prende a mistura lá dentro — e `will-change:
 * transform` sozinho, sem transform nenhum, faz o mesmo. Por isso o selo é irmão, e não
 * filho: dentro daqui ele inverteria junto e perderia o índigo.
 *
 * É também o motivo de a seta e a mira morarem no MESMO SVG e não em dois irmãos. Dois
 * elementos em `difference` que se sobrepõem durante a troca invertem duas vezes na área
 * comum, e duas inversões devolvem o fundo: apareceria um buraco no meio do cruzamento,
 * exatamente onde o olho está. Num SVG só, as duas formas compõem primeiro e o grupo inverte
 * uma vez — e opacidade parcial sobreposta vira um branco um pouco mais claro, não um furo.
 */
.ponteiro {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 300;
  pointer-events: none;
  will-change: transform;
  mix-blend-mode: difference;
}
.ponteiro__desenho {
  display: block;
}

/* A TROCA. Só `opacity` e `transform`, as duas do compositor; nada aqui força layout.
   As duas silhuetas escalam em torno de (16,16) — o pixel do hotspot, que é a ponta da seta
   E o centro da mira. Daí a leitura: a mira não aparece do lado, ela nasce crescendo de onde
   a seta estava apontando, e a seta recolhe para o mesmo ponto. `transform-box: view-box`
   é obrigatório: sem ele, `transform-origin` num <g> de SVG mede a partir da caixa de
   preenchimento do próprio grupo, que é diferente para cada um dos dois.

   `--espera` é HISTERESE, e conserta um defeito medido: varrer uma linha de `.matriz__grade`
   dá SEIS trocas de estado em 682 px — `a:164px m:8px a:164px m:8px a:164px m:8px a:162px`.
   As células `.sinal` são `<button>`, logo `agir`, e o `gap: 8px` entre elas é superfície de
   painel, logo `medir`. A 600 px/s um vão de 8 px é atravessado em 13 ms, contra 150 ms de
   opacidade e 220 ms de transform: sem atraso nenhuma das duas silhuetas chega ao fim e o
   ponteiro PULSA três vezes por passada, no painel que o `design-spec` §7 anota com a
   palavra "sem movimento".

   O mecanismo é a semântica de interrupção: uma transição cancelada AINDA DENTRO do atraso
   não moveu um pixel, porque o valor apresentado continua sendo o de partida. Entrar em
   `medir` arma as duas com 90 ms; sair devolve 0 na hora, porque voltar para a seta é
   resposta a um clicável e não pode hesitar. Limite honesto: varredura muito lenta — um vão
   de 8 px levando mais de 90 ms, isto é abaixo de ~90 px/s — deixa a mira começar a
   aparecer. A essa velocidade quem move o mouse está mirando, não varrendo.

   `--espera` mora no PAI porque é uma decisão só, lida pelas DUAS silhuetas: escrevê-la duas
   vezes abriria a porta para as duas hesitarem por tempos diferentes. Uma razão que já foi
   escrita aqui e é falsa, para não voltar: não é para escapar do `transition: none` de
   `prefers-reduced-motion`. Aquela regra zera a propriedade `transition` inteira, atraso
   incluído, e `--espera` é outra propriedade — não há especificidade a comparar entre as
   duas. Medido sob `prefers-reduced-motion`: duração 0s e atraso 0s, com `--espera` no pai. */
.ponteiro__seta,
.ponteiro__mira {
  transform-box: view-box;
  transform-origin: 16px 16px;
  transition:
    opacity 150ms var(--ease) var(--espera, 0ms),
    transform 220ms var(--ease) var(--espera, 0ms);
}
.ponteiro__mira {
  opacity: 0;
  transform: scale(0.52);
}
/* A ESPERA TROCOU DE LADO, e o motivo é que o alcance da mira trocou de lado.
   Quando `medir` era a superfície do painel, o estado TRANSITÓRIO numa varredura era a mira:
   o vão de 8 px entre células. O atraso ficava na ENTRADA da mira e segurava esse pisca.
   Agora `medir` é o botão, e o transitório inverteu — medido no harness (`varrer=1`) sobre
   `.matriz__grade`: corridas de 164 px de célula contra 8 px de vão, 6 trocas em 682 px. O
   que pisca agora é a VOLTA para a seta, 13 ms a 600 px/s. Manter o atraso na entrada
   protegeria o lado que já não precisa e deixaria o pisca solto no outro.
   Então: entrar na mira responde na hora, porque responde a um botão e não pode hesitar;
   sair dela espera 90 ms, e uma transição cancelada ainda dentro do atraso não moveu um
   pixel. Limite honesto, igual e espelhado ao de antes: abaixo de ~90 px/s o vão passa dos
   90 ms e a seta começa a voltar — e a essa velocidade quem move o mouse está mirando. */
.ponteiro {
  --espera: 90ms;
}
.ponteiro[data-estado="medir"] {
  --espera: 0ms;
}
.ponteiro[data-estado="medir"] .ponteiro__seta {
  opacity: 0;
  transform: scale(0.74);
}
.ponteiro[data-estado="medir"] .ponteiro__mira {
  opacity: 1;
  transform: scale(1);
}

/* PESO é o único canal que sobra para dizer "isto é clicável": a cor foi para as mãos da
   inversão, que devolve o oposto do fundo e não o índigo que eu pediria. Numa massa cheia não
   há traço a engrossar, então o peso vem por DILATAÇÃO: o mesmo caminho ganha um traço da
   própria cor, e metade dele cresce para fora da silhueta. `--engorda-seta` é essa largura,
   e é ZERO em repouso — a seta de `ler` é só massa.

   1,1 em `agir`, e o número saiu de conta. A silhueta é um dardo FINO: área 83,21 px² sobre
   perímetro 54,44 px, isto é 3,06 px de espessura média. Dilatar um dardo desses custa caro
   por décimo — 0,55 px de cada lado já leva a área a 114,07 px², +37,1% de tinta (integrado
   numa grade de 0,005 px, e 0,015 devolve o mesmo; dilatação de Minkowski = união do
   preenchimento com a faixa do
   traço, que é exatamente o que fill+stroke no mesmo caminho desenha). +37% é de propósito:
   é o mesmo salto de tinta que a silhueta anterior dava ao ir de 1,7 para 2,3 de traço. A
   2,2 seriam +76,4%, e o ponteiro daria um pulo de peso a cada link.

   O TETO é o hotspot: a junta é redonda, logo a dilatação também avança w/2 ALÉM do vértice
   da ponta, e o bico visível desencosta do pixel apontado nessa medida — 0,55 px a 1,1, que é
   METADE do que a silhueta anterior já gastava (traço centrado no caminho, 1,15 px em `agir`).
   Junta redonda, e não mitra: a razão de mitra no bico vale 1/sen 21° = 2,790, abaixo do
   limite padrão 4, então a mitra seria MANTIDA e o avanço viraria 0,77 px sem ganhar peso.

   A MIRA não é dilatada em estado nenhum, porque ela não tem estado: `medir` é um estado só.
   Seu traço é 2 e os quatro braços são alinhados aos eixos sobre coordenada inteira (x=16,
   y=16), então a faixa cai em [15; 17] — duas colunas de pixel INTEIRAS em DPR 1, com o
   elemento em posição inteira. Conferido na captura: um corte horizontal no braço de cima dá
   exatamente dois pixels de inversão exata e zero parciais, nas três superfícies. É também
   por isso que a tampa é reta: tampa redonda borraria as duas extremidades de cada braço sem
   ganhar nada. */
.ponteiro__seta path {
  stroke-width: var(--engorda-seta, 0);
  transition: stroke-width 120ms var(--ease);
}
.ponteiro[data-estado="agir"] .ponteiro__seta {
  --engorda-seta: 1.1;
}

/* Selo, em duas camadas. O pai só posiciona — o JS reescreve o transform dele a cada
   quadro. O filho só reage: pressão do clique e inércia da rolagem. Num transform só, a
   posição apagaria o efeito no quadro seguinte.
   Fora do blend: é identidade, e identidade não pode virar verde-limão sobre o índigo.
   Fica acima do anel de clique (z 200) porque é identidade, não retorno de gesto. */
.selo {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 300;
  pointer-events: none;
  will-change: transform;
}
.selo__texto {
  display: block;
  padding: 4px 9px 5px;
  border: var(--hairline);
  border-color: var(--indigo);
  border-radius: 8px;
  background: var(--panel);
  color: var(--indigo);
  font: 500 0.6875rem / 1 var(--font-mono);
  letter-spacing: 0.06em;
  white-space: nowrap;
  box-shadow: var(--shadow-float, 0 1px 7px rgb(11 13 20 / 0.12));
  transform-origin: 0 0;
  /* --inercia: quanto o rótulo fica para trás na rolagem. --pressao: o recuo do clique. */
  transform: translateY(var(--inercia, 0)) scale(var(--pressao, 1));
  transition: transform 260ms var(--ease);
}
/* Clique: recuo curto e seco, sem a suavização da inércia — gesto tem de responder na hora. */
.selo[data-pressionado] .selo__texto {
  --pressao: 0.86;
  background: var(--indigo);
  color: var(--paper);
  transition:
    transform 90ms var(--ease),
    background-color 90ms,
    color 90ms;
}
/* O FIM DO SELO. `--esmaece-selo` é a duração do adeus, e mora aqui e só aqui: o JS espera
   `transitionend` de `opacity` em vez de repetir o número, para não existirem dois valores
   que precisam concordar para sempre.

   600 ms é longo de propósito. A saudação dura 4 s e sai devagar porque sair é a parte que
   carrega o sentido: um corte seco leria como falha de renderização, e o que se quer dizer é
   que o rótulo cumpriu a função e se retirou. Opacidade só — nada de encolher ou deslizar,
   que puxariam o olho de volta para o canto que está justamente sendo abandonado. */
.selo[data-expirado] .selo__texto {
  opacity: 0;
  transition: opacity var(--esmaece-selo, 600ms) var(--ease);
}
.ponteiro[hidden],
.selo[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .selo__texto {
    transition: none;
    transform: none;
  }
  /* O desenho do ponteiro nem chega a aparecer aqui — `semDesenho` no JS o mantém escondido e
     valem as imagens de cursor. Estas linhas cobrem o caso em que ele apareça de outro jeito:
     a troca de silhueta continua acontecendo, o que some é a animação dela. */
  .ponteiro__seta,
  .ponteiro__mira,
  .ponteiro__seta path {
    transition: none;
  }
}

/*
 * CLIQUE. Um anel que abre e some no ponto exato, como uma leitura sendo tomada. Só
 * transform e opacity, então não força layout; o elemento se remove sozinho no
 * animationend e nunca intercepta ponteiro.
 */

.clique {
  position: fixed;
  z-index: 200;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border: 1px solid var(--indigo);
  border-radius: var(--r-pill);
  box-shadow: 0 0 0 1px var(--paper-halo, rgb(247 245 240 / 0.55));
  pointer-events: none;
  animation: clique 460ms var(--ease) forwards;
}
@keyframes clique {
  from {
    transform: scale(0.35);
    opacity: 0.85;
  }
  to {
    transform: scale(3.2);
    opacity: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  /* O retorno do clique continua existindo; o que some é a expansão. */
  .clique {
    animation: clique-parado 220ms linear forwards;
  }
  @keyframes clique-parado {
    from {
      opacity: 0.7;
    }
    to {
      opacity: 0;
    }
  }
}

/* Right-to-left pages (Arabic): prose and layout follow `dir="rtl"`; code, contract values and
   JSON stay left to right, as they are written. */
[dir="rtl"] pre,
[dir="rtl"] code,
[dir="rtl"] .json,
[dir="rtl"] .kv,
[dir="rtl"] .t-rota,
[dir="rtl"] .sinal__codigo,
[dir="rtl"] .ladder__codigo {
  direction: ltr;
  unicode-bidi: isolate;
}
[dir="rtl"] pre,
[dir="rtl"] .json {
  text-align: left;
}
