/* ==========================================================================
   Native-SDD — landing "Spec-to-Artifact Compiler"
   Frente A (markup + CSS). Fonte de verdade: .claude/sdd/design-canvas/compiler/CONTRATO.md
   Dark-only nesta versão — os artboards aprovados não previram tema claro.
   ========================================================================== */

/* -------------------------------------------------------------------------
   Fontes — as três vêm do Google Fonts, num pedido só (ver o <link> do index.html).
   O @font-face local da JetBrains Mono saiu junto com ela: a mono passou a ser Martian Mono
   (EVOLUCAO.md D-01) e não há .woff2 dela no repo. O arquivo vendorizado continua em
   docs/assets/fonts/ porque a landing v1 ainda o usa.
   ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
   Design system — §7 do contrato. Um único tema (dark); os valores vêm
   direto dos artboards aprovados, sem arredondar para grade 4/8px.
   ------------------------------------------------------------------------- */
:root {
  --bg: #070809;
  --surface: #0F1115;
  --surface-2: #16191F;
  --line: rgba(240,243,246,0.08);
  --line-strong: rgba(240,243,246,0.18);
  --ink: #F0F3F6;
  --muted: #7E8B9B;
  --accent: #FF5500;
  --cyan: #00E5FF;
  --ok: #10B981;
  --fail: #F43F5E;

  /* Isologo (docs/assets/brand/). Duas cores, e a QUEBRA entre elas é o que faz a leitura 3D:
     face esquerda fria, topo e direita quentes (brand book §2.1). Amarradas aos tokens do site
     de propósito, e desde 2026-09-07 essa é a paleta da MARCA também: o brand book nasceu com
     #E55B3C, mas medido no header ele fica lavado ao lado do branco e a 12px de um botão
     #FF5500 — dois laranjas próximos leem como defeito. O brand book foi revisado para seguir
     estes tokens, e há teste amarrando os dois. */
  --logo-quente: var(--accent);
  --logo-frio: var(--ink);

  /* Teto de largura — os artboards foram desenhados a 1440px; acima disso o
     conteúdo centraliza em vez de esticar (bug real: sem isto, colunas e
     SVGs incham proporcionalmente em telas largas — ver #paradoxo). */
  --maxw: 1440px;

  /* Altura do header fixo, em token porque DOIS lugares dependem dela e eles divergiram: o
     `min-height` da barra e o recuo que as âncoras precisam para não parar debaixo dela.
     Medido em 2026-09-05: o header é `sticky` e todos os seis alvos da nav aterrissavam em
     `top: 0`, encobertos. Ninguém tinha reclamado porque a página não some — ela só começa
     dois títulos abaixo de onde deveria. */
  --header-h: 58px;

  /* Três papéis, duas faces (EVOLUCAO.md D-01 → D-20). A distinção que importa continua sendo
     entre o que GRITA e o que se LÊ, mas desde a D-20 ela mora na proporção, não numa terceira
     face: o display é a Archivo expandida (`--display-largura`, eixo `wdth`) em peso real, o
     corpo é a Archivo normal. A Anton que estava aqui só tinha 400 e recebia pedidos de 800. */
  --font-display: Archivo, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display-largura: 118%;
  --display-peso: 700;
  --font-corpo: Archivo, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: "Martian Mono", ui-monospace, Menlo, Consolas, monospace;

  /* ---------------------------------------------------------------------
     Tokens de MOVIMENTO — o painel de controle da personalidade do site.
     Tudo que se move, no CSS e no GSAP, sai daqui: o motion.js lê estes
     valores com getComputedStyle em vez de trazer números próprios, para
     que mudar o caráter do movimento seja editar seis linhas num lugar só,
     e não caçar durações espalhadas por 700 linhas de JavaScript.
     --------------------------------------------------------------------- */
  --dur-instantaneo: 90ms;   /* press, o que responde ao dedo               */
  --dur-rapido: 180ms;       /* hover, foco, troca de estado                */
  --dur-medio: 700ms;        /* revelar, entrar em cena                     */
  --dur-lento: 1600ms;       /* traçado, contagem, coreografia de abertura  */

  /* Sem bounce e sem elastic — postura de movimento do projeto. Estas três curvas
     são saída-forte/entrada-suave, que é o vocabulário de um instrumento, não de um brinquedo. */
  --ease-saida: cubic-bezier(0.22, 1, 0.36, 1);      /* algo chegando ao lugar */
  --ease-entrada: cubic-bezier(0.55, 0, 0.65, 1);    /* algo saindo de cena    */
  --ease-precisa: cubic-bezier(0.65, 0, 0.35, 1);    /* troca de estado seca   */

  /* Multiplicador global de amplitude: 0 = sem deslocamento (só opacidade),
     1 = o desenhado, 1.5 = exagerado. O JS multiplica seus deslocamentos por ele. */
  --motion-intensidade: 1;

  color-scheme: dark;
}

/* Quem pediu menos movimento recebe menos movimento — inclusive dos tokens. Zerar a
   intensidade aqui faz o motion.js (que lê o token) parar de deslocar, sem precisar de um
   segundo caminho de código só para reduced-motion. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-instantaneo: 0ms;
    --dur-rapido: 0ms;
    --dur-medio: 0ms;
    --dur-lento: 0ms;
    --motion-intensidade: 0;
  }
}

/* -------------------------------------------------------------------------
   Reset mínimo + base. O grão e o blueprint de fundo replicam os artboards;
   ficam fixos (position:fixed) para não recalcular em cada seção.
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* Controle de formulário NÃO herda fonte: o user-agent impõe a dele, e no Windows isso é Arial.
   Medido em 2026-09-05 — o `×` de fechar do inspetor era a única coisa da página desenhada fora
   dos três papéis do DESIGN.md, e nada acusava porque um glifo em Arial não quebra layout.
   Um seletor por botão consertaria este; a herança conserta a classe inteira, inclusive o
   próximo controle que alguém acrescentar sem pensar na fonte. */
button, input, select, textarea { font: inherit; color: inherit; }

html {
  -webkit-text-size-adjust: 100%;
  /* +1px da borda do header, +18px de respiro. `scroll-padding-top` no `html` cobre TODA
     ancoragem — os seis links da nav, o skip-link e o `#hero` da marca — numa regra só, em vez
     de um `scroll-margin` por alvo que a próxima seção esqueceria de herdar. */
  scroll-padding-top: calc(var(--header-h) + 19px);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-corpo);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: #FF7A33; }

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

/* h1/h2 gritam (Archivo expandida); h3 é subtítulo e precisa ser lido, então fica na largura
   normal. O peso e a largura saem dos tokens para nenhum título pedir à face o que ela não tem. */
h1, h2 {
  font-family: var(--font-display);
  font-weight: var(--display-peso);
  font-stretch: var(--display-largura);
  line-height: 1.04;
  letter-spacing: -0.02em;
  text-wrap: balance;
  margin: 0;
  color: var(--ink);
}
h3 { font-family: var(--font-corpo); font-weight: 600; margin: 0; color: var(--ink); }

p { margin: 0; }

/* Foco visível — regra dura de a11y do contrato (§ requisitos). */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* A seção que recebe o foco ao fim da rolagem de um link interno (nav.js) não é um controle:
   o foco está ali só para o próximo Tab partir dela. Um contorno laranja em volta da seção
   inteira apontaria para algo que não se opera. */
main [tabindex="-1"]:focus { outline: none; }

/* Skip-link: some visualmente, aparece ao focar (primeiro elemento tabável). */
.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 100;
  background: var(--accent);
  color: #000;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.08em;
  padding: 12px 18px;
  transition: top .15s ease;
}
.skip-link:focus { top: 8px; }

/* Grão global — mix-blend overlay a ~4%, camada fixa acima de tudo, mas
   pointer-events:none para não interceptar cliques/toques. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  opacity: 0.04;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Grade de fundo (blueprint) — só no hero, como nos artboards. */
.bp-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(240,243,246,0.03) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(240,243,246,0.03) 1px, transparent 1px);
  background-size: 120px 120px;
}

/* -------------------------------------------------------------------------
   Contêiner de largura + estrutura de seção comum (rail lateral + conteúdo).
   Todas as seções "internas" (não-hero) reusam o mesmo esqueleto de
   colunas: 60px de rail vertical + conteúdo. No mobile o rail vira topo.
   ------------------------------------------------------------------------- */
.wrap { max-width: var(--maxw); margin-inline: auto; }

.section { position: relative; }

/* Fundos/rail continuam full-bleed (a section em si não tem largura
   máxima); só a composição rail+conteúdo (o que corresponde ao artboard
   de 1440px) é que centraliza e para de crescer. */
.section-grid {
  display: grid;
  grid-template-columns: 60px 1fr;
  align-items: stretch;
  max-width: var(--maxw);
  margin-inline: auto;
}

.section-rail {
  display: flex;
  flex-direction: column;
  min-width: 0;
  align-items: center;
  gap: 20px;
  padding: 88px 0 48px;
  border-right: 1px solid var(--line);
}
.rail-label {
  font-size: 10px;
  letter-spacing: 0.3em;
  color: var(--muted);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
}
.rail-line {
  display: block;
  width: 1px;
  flex-grow: 1;
  background: linear-gradient(to bottom, var(--line-strong), transparent);
}

/* min-width:0 é o fix real do estouro horizontal no mobile: item de grid
   tem min-width:auto (= min-content) por padrão, então o conteúdo largo
   com overflow-x:auto (ribbon, roster, blueprint) empurrava a SEÇÃO
   inteira em vez de rolar internamente — o overflow:auto neles sozinho
   não bastava, quem precisa encolher é o item do grid que os contém. */
.section-body { padding: 88px 40px 72px 56px; min-width: 0; }

.eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 32px;
}
.eyebrow-bar { display: block; width: 28px; height: 3px; background: var(--accent); flex-shrink: 0; }
.eyebrow-label { font-size: 11px; letter-spacing: 0.24em; color: var(--muted); }

.section-head {
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 80px;
  align-items: end;
}
/* Escala da face expandida (D-20): com o mínimo de 2.4rem da Anton, a 340px os títulos de seção
   iam a cinco linhas. */
.section-head h2 {
  font-size: clamp(2rem, 1.3rem + 2.7vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
}
.section-head .lede {
  font-size: 16px;
  line-height: 1.66;
  color: var(--muted);
}

/* -------------------------------------------------------------------------
   Header / navegação
   ------------------------------------------------------------------------- */
/* Fundo do header sangra até a borda real do viewport (sticky, blur);
   o conteúdo (.header-inner) é quem centraliza e para de crescer. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid var(--line);
  background: rgba(7,8,9,0.82);
  backdrop-filter: blur(16px);
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: var(--header-h);
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 0 24px;
}
.brand {
  display: flex;
  align-items: center;
  /* Área de respiro do brand book §4: a folga mínima é a largura da face "D" direita, que é
     metade da largura da marca — 26px de altura dá ~22,6px de largura, logo ~11,3px. */
  gap: 12px;
  color: var(--ink);
}
.brand-dot { display: block; width: 6px; height: 6px; border-radius: 9999px; background: var(--ok); }

/* O header desenha a variante REDUZIDA do isologo — cubo, sem as letras SDD. Não é
   simplificação por preguiça: medido em 22/26/30/34px no próprio Chromium, o traço duplo do
   isologo cheio vira cinza indistinto abaixo de ~44px, e as letras sólidas só se sustentam
   acima de ~30px em tela 1x (brand book §3.1/§3.2 — abaixo de 64px sobra a silhueta).
   O isologo completo vive em docs/assets/brand/ para uso ≥64px. */
.brand-marca { display: block; height: 26px; width: auto; flex-shrink: 0; }
.brand-name { font-size: 12px; font-weight: 700; letter-spacing: 0.16em; }

.site-nav { display: flex; gap: 22px; }
.site-nav a {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--muted);
  padding: 10px 2px;
}
.site-nav a:hover, .site-nav a:focus-visible { color: var(--ink); }

.header-meta { display: flex; align-items: center; gap: 16px; }

/* A nav rolava na horizontal porque nenhuma frente tinha JS de menu atribuído. O menu existe
   agora (assets/js/nav.js), e a medição a 390px mostrou o custo de não tê-lo: a marca quebrava
   em duas linhas e a faixa de links ficava cortada atrás do botão INICIALIZAR. A rolagem
   permanece só como rede: se o JS não carregar, `.site-nav` continua alcançável no desktop. */
.site-nav { overflow-x: auto; scrollbar-width: none; }
.site-nav::-webkit-scrollbar { display: none; }

.header-rail { display: contents; }

/* O toggle só existe no mobile (ver @media 768). Fora dele, não ocupa espaço nem foco. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
}
.nav-toggle-bars { display: block; width: 20px; }
.nav-toggle-bars span {
  display: block;
  height: 1px;
  background: currentColor;
  transition: transform 160ms ease, opacity 160ms ease;
}
.nav-toggle-bars span + span { margin-top: 5px; }
/* Aberto: as duas barras viram o "✕" do artboard, girando em torno do centro do par. */
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:first-child { transform: translateY(3px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:last-child { transform: translateY(-3px) rotate(-45deg); }

/* -------------------------------------------------------------------------
   Botões
   ------------------------------------------------------------------------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 44px;
  padding: 14px 24px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  background: none;
}
.btn-primary {
  background: var(--accent);
  color: #000;
}
/* "sombra mecânica" — bloco sólido deslocado 4px, sem blur (§7). */
.btn-primary::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: translate(4px, 4px);
  z-index: -1;
}
.btn-ghost {
  border: 1px solid var(--line-strong);
  color: var(--ink);
  font-weight: 500;
}
.btn-ghost:hover { border-color: var(--ink); color: var(--ink); }
.btn-quiet {
  border: 1px solid var(--line-strong);
  color: var(--muted);
  font-weight: 500;
}

/* -------------------------------------------------------------------------
   01. HERO — Main.dc.html / HeroMobile.dc.html
   ------------------------------------------------------------------------- */
#hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.hero-grid {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: 60px 1fr 560px;
  align-items: stretch;
  max-width: var(--maxw);
  margin-inline: auto;
}
.hero-rail { grid-row: 1 / -1; }
.hero-copy { padding: 96px 64px 72px 56px; min-width: 0; }

/* A cabeca de leitura da abertura (motion.js §1b) — o cursor que atravessa a primeira dobra
   da esquerda para a direita, uma vez, no load.

   Nasce INVISIVEL, e isso e a regra dura do motion.js acontecendo no CSS: sem JS nao ha
   varredura, e sem varredura nao pode sobrar marca nenhuma dela na tela. Quem acende e apaga
   e o GSAP; aqui so esta o desenho. Pelo mesmo motivo ela nao ocupa espaco (`position:
   absolute` dentro do `#hero`, que ja e `relative` e `overflow: hidden`): a cabeca nunca pode
   empurrar layout, senao entraria na conta de CLS.

   O degrade vertical existe para a barra nao terminar em corte seco contra a borda do hero —
   a 2px de largura, uma aresta dura le como defeito de render, nao como instrumento. */
.hero-cabeca {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  z-index: 4;
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    var(--accent) 14%,
    var(--accent) 86%,
    transparent 100%
  );
  box-shadow: 0 0 26px 3px rgb(255 85 0 / 0.4);
}

/* Quem pediu menos movimento nao recebe a cabeca em estado nenhum — nem apagada. O motion.js
   ja nao a anima nesse caminho; isto fecha o outro lado, para que nenhuma regressao futura a
   acenda por engano em quem pediu para nao ver movimento. */
@media (prefers-reduced-motion: reduce) {
  .hero-cabeca { display: none; }
}

/* A escala é da face expandida: com os 5.4rem da Anton, "Pare de improvisar." quebrava e o
   título ia a quatro linhas (medido em 2026-09-12). Cada <br> tem de fechar uma linha. */
.hero-title {
  font-size: clamp(2.25rem, 1rem + 3.4vw, 4rem);
  line-height: 1.04;
  text-wrap: initial;
}

.hero-sub {
  margin: 36px 0 0;
  max-width: 46ch;
  font-size: 17px;
  line-height: 1.62;
  color: var(--muted);
}
.hero-sub .mono { color: var(--ink); font-size: 15px; }

.hero-author {
  margin: 22px 0 0;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.hero-ctas { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 44px; }

.hero-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 76px;
  border-top: 1px solid var(--line);
}
.hero-stat { padding: 22px 24px 0 0; border-right: 1px solid var(--line); }
.hero-stat:last-child { border-right: 0; padding-right: 0; }
.hero-stat:not(:first-child) { padding-left: 24px; }
.hero-stat-num { font-size: 36px; font-weight: var(--display-peso); font-stretch: var(--display-largura); letter-spacing: -0.02em; font-family: var(--font-display); }
.hero-stat-num.mono { font-size: 29px; font-weight: 700; letter-spacing: -0.02em; }
.hero-stat-label { margin-top: 6px; font-size: 10px; letter-spacing: 0.2em; color: var(--muted); font-family: var(--font-mono); }

.hero-art {
  position: relative;
  padding: 56px 40px 0 0;
  border-left: 1px solid var(--line);
  min-width: 0;
}
.hero-art svg { display: block; width: 100%; height: auto; }

/* -- Palco do hero: o SVG e o canvas WebGL ocupam o mesmo lugar ------------------------
   O SVG define a altura do palco (é ele quem tem proporção intrínseca) e o canvas se
   estica por cima em `position: absolute`. A ordem importa: sem o SVG governando a
   caixa, o canvas — que não tem tamanho natural — colapsaria para 0 de altura, e o
   ResizeObserver mediria um palco inexistente.
   Sem JS, sem WebGL ou sob reduced-motion, `.is-3d` nunca é adicionada e o que sobra é
   exatamente o hero que sempre existiu. */
.hero-stage { position: relative; }
.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-lento, 1.6s) var(--ease, ease);
}
.hero-stage.is-3d .hero-canvas { opacity: 1; }
/* `visibility` além da opacidade: o SVG some do hit-testing e da árvore de foco junto com
   a tinta. `display: none` não serviria — tiraria a altura do palco com ele. */
.hero-stage.is-3d > svg { opacity: 0; visibility: hidden; }
.hero-stage > svg { transition: opacity var(--dur-medio, 0.7s) var(--ease, ease); }

/* -- Legenda das cinco fases (só quando o canvas assume) ------------------------------- */
/* Com o canvas de pé, a base do hero vira duas colunas: as cinco fases à esquerda, a cota do
   desenho à direita, alinhadas pela mesma base. Sem isto as duas disputam a mesma faixa e o
   rodapé do hero lê como duas listas embaralhadas.
   `:has()` é o seletor certo aqui porque quem ganha `.is-3d` é o palco, e o que precisa mudar
   é o pai. Onde ele não existir, nada disto se aplica: a legenda volta a empilhar sob o palco
   e a cota fica no canto absoluto de sempre — mais apertado, nunca quebrado. */
.hero-art:has(.hero-stage.is-3d) {
  display: grid;
  /* A legenda pede a largura que precisa (`auto`) e a cota fica com a sobra: invertido, o
     texto mais longo das cinco fases quebrava em duas linhas enquanto sobrava vão à direita. */
  grid-template-columns: auto 1fr;
  align-items: end;
  column-gap: 24px;
}
.hero-art:has(.hero-stage.is-3d) > .hero-stage { grid-column: 1 / -1; }
/* `min-width: 0` porque o padrão de um item de grid é `auto` — ele se recusa a ficar menor
   que o conteúdo, e uma linha de legenda com `nowrap` bastava para o palco inteiro estourar
   a coluna. Foi assim que o hero passou a ter 526px de largura num viewport de 390. */
.hero-art:has(.hero-stage.is-3d) > * { min-width: 0; }
.hero-art:has(.hero-stage.is-3d) > .hero-art-caption {
  position: static;
  margin-top: 20px;
  justify-self: end;
  white-space: nowrap;
}

.hero-phases { display: none; }
/* Seletor de irmã, não de descendente: a lista mora ao lado do palco justamente para não
   cair sobre o desenho, e é o palco que ganha `.is-3d`. */
.hero-stage.is-3d ~ .hero-phases {
  display: grid;
  gap: 2px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--muted);
}
.hero-phases li {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 3px 0;
  white-space: nowrap;
  opacity: 0.45;
  transition: opacity var(--dur-rapido, 0.18s) linear, color var(--dur-rapido, 0.18s) linear;
}
.hero-phases li.is-active { opacity: 1; color: var(--accent); }
.hero-phases b { font-weight: 700; }
.hero-phases i { font-style: normal; color: inherit; opacity: 0.7; }

/* Quem pediu menos movimento nunca chega ao `.is-3d` — o JS não carrega. Esta regra existe
   para o caso de a preferência mudar com a página já aberta: o canvas sai de cena sem
   deixar buraco, porque o SVG volta a ser o hero. */
@media (prefers-reduced-motion: reduce) {
  .hero-stage.is-3d .hero-canvas { opacity: 0; }
  .hero-stage.is-3d > svg { opacity: 1; visibility: visible; }
  .hero-stage.is-3d ~ .hero-phases { display: none; }
}
.hero-art-caption {
  position: absolute;
  right: 40px;
  bottom: 40px;
  text-align: right;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--muted);
  line-height: 2;
}
.hero-art-caption .dot { color: var(--ok); }

/* -------------------------------------------------------------------------
   02. PARADOXO — ProblemSpace.dc.html
   ------------------------------------------------------------------------- */
.paradox-head { border-bottom: 1px solid var(--line); padding-bottom: 48px; }

.paradox-compare {
  display: grid;
  grid-template-columns: 1fr 1px 1fr;
  margin-top: 0;
}
.paradox-col { position: relative; padding: 56px; }
.paradox-col:first-child { padding-left: 0; }
.paradox-col:last-child { padding-right: 0; }
/* Desbota só no topo: embaixo ela precisa encontrar o eixo da matriz, sem emenda visível. */
.paradox-divider { background: linear-gradient(to bottom, transparent, var(--line-strong) 18%, var(--line-strong) 100%); }

.paradox-tag {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--muted);
}
.paradox-tag .fail { color: var(--fail); }
.paradox-tag .ok { color: var(--ok); }
.paradox-tag .ink { color: var(--ink); }

/* As duas identidades viram CHIP, e a cor do chip é a mesma do estado ao lado.
   Antes o lado A vinha em `--muted` e o B em `--ink`: a diferença de brilho lia-se como
   HIERARQUIA — um rótulo mais importante que o outro — e não como dois lados do mesmo eixo.
   Peso igual, cor diferente: o que distingue passa a ser a identidade, não a importância. */
.paradox-chip {
  border: 1px solid currentColor;
  padding: 6px 10px;
  line-height: 1;
  white-space: nowrap;
}
.paradox-chip-a { color: var(--fail); }
.paradox-chip-b { color: var(--ok); }

/* Teto de escala — viewBox é 560×300 (o tamanho em que o artboard foi
   desenhado); sem max-width o SVG incha proporcionalmente pra preencher
   a coluna e o traço fica solto/vazio (bug relatado em telas largas). */
.paradox-svg { margin-top: 28px; display: block; width: 100%; max-width: 560px; height: auto; }

/* Os quatro rótulos que anotavam os desenhos moravam DENTRO do SVG, em unidades de viewBox: a
   340px a coluna desenha a 54% e eles chegavam à tela com 5,4px. Em HTML não encolhem com o
   desenho, e ainda podem quebrar linha quando a coluna aperta. */
.paradox-marcas {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 10px 0 0;
  max-width: 560px;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--muted);
}

/* A marca no eixo. Sem ela, duas ilustrações lado a lado podem ser lidas como duas coisas
   diferentes em vez de dois estados da MESMA coisa — que é o argumento da seção. */
.paradox-vs {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--bg);
  border: 1px solid var(--line-strong);
  padding: 7px 9px;
  font-size: 10px;
  letter-spacing: 0.2em;
  color: var(--ink);
}
.paradox-divider { position: relative; }

/* A tabela do comparativo: a chave no eixo, um valor de cada lado, na mesma linha.
   As colunas de valor se alinham com os dois desenhos acima — é o alinhamento que faz o olho
   ler "A versus B" sem que nada precise dizer isso por escrito.

   O EIXO é contínuo de propósito. A divisa vertical parava no fim dos desenhos e a tabela
   começava 44px abaixo, sem nada no meio: eram dois blocos empilhados, e só quem já tinha
   entendido o comparativo lá em cima sabia que a tabela continuava o mesmo. A linha atravessa
   o vão (`--paradox-vao`, o mesmo número nos dois lugares) e desce até a última linha. */
.paradox-matrix {
  --paradox-vao: 44px;
  position: relative;
  margin-top: var(--paradox-vao);
}
.paradox-matrix::before {
  content: "";
  position: absolute;
  top: calc(var(--paradox-vao) * -1);
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--line-strong);
}

/* A legenda é o cabeçalho de coluna que a tabela não tinha. Mesma grade das linhas, para o
   rótulo cair exatamente sobre a coluna que ele nomeia. */
.paradox-legend {
  display: grid;
  grid-template-columns: 1fr 160px 1fr;
  gap: 20px;
  align-items: center;
  padding-bottom: 16px;
  font-size: 10px;
  letter-spacing: 0.22em;
}
.paradox-legend-a { text-align: right; color: var(--fail); }
.paradox-legend-b { text-align: left; color: var(--ok); }

.paradox-table {
  margin: 0;
  border-top: 1px solid var(--line);
}
.paradox-row {
  display: grid;
  grid-template-columns: 1fr 160px 1fr;
  align-items: center;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  /* Posicionado para pintar ACIMA do eixo: sem isto o pseudo-elemento absoluto da matriz
     riscaria a chave no meio, porque ela mora bem em cima da linha. */
  position: relative;
}
.paradox-k {
  grid-column: 2;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.2em;
  color: var(--muted);
  /* A chave mascara o eixo e vira nó dele, como o `VS` faz nos desenhos. `justify-self`
     encolhe a caixa até o texto: ocupando os 160px da coluna, a máscara apagava o eixo num
     treço largo demais e a linha parecia só tracejada, em vez de parar no rótulo. */
  justify-self: center;
  background: var(--bg);
  padding: 4px 12px;
}
.paradox-a { grid-column: 1; }
.paradox-b { grid-column: 3; }
/* `grid-row: 1` explícito nos três, e a razão é um defeito medido, não zelo.
   O `dt` vem primeiro no DOM (a ordem que o leitor de tela precisa) e pede a coluna 2. A
   colocação automática é ESPARSA: depois de assentar a chave na coluna 2, o cursor não volta
   atrás — o valor A, que pede a coluna 1, caía na linha SEGUINTE, e o B ia junto. A chave
   flutuava 43px acima do par que ela nomeia e a linha media 103px em vez de 60.
   O comentário acima dizia "na mesma linha" desde a D-08 e era falso. Medido em 2026-09-05. */
.paradox-k, .paradox-a, .paradox-b { grid-row: 1; }
.paradox-a, .paradox-b { margin: 0; font-size: 15px; font-weight: 600; }
/* Cada valor encostado no eixo: a distância entre os dois pares é o que se compara. */
.paradox-a { text-align: right; color: var(--muted); }
.paradox-b { text-align: left; color: var(--ink); }

.paradox-caption {
  margin: 48px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--muted);
}

/* -------------------------------------------------------------------------
   03. TESE — banda tipográfica de largura total, sem card (§1/§6)
   ------------------------------------------------------------------------- */
#tese { border-bottom: 1px solid var(--line); }
/* "Banda tipográfica de largura total" — a banda em si acompanha o teto
   de largura das outras seções (não fica presa a 68ch); é o texto dentro
   dela que fica em coluna de leitura, via max-width no headline/support. */
.tese-band {
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 88px 56px;
}
.tese-headline {
  max-width: 26ch;
  font-size: clamp(1.75rem, 1.3rem + 2vw, 2.75rem);
  line-height: 1.1;
}
.tese-support {
  margin-top: 24px;
  font-size: 17px;
  line-height: 1.7;
  color: var(--muted);
  max-width: 58ch;
}

/* -------------------------------------------------------------------------
   04. MOTOR — Phases.dc.html (ribbon de 5 fases + expandido + bypass)
   ------------------------------------------------------------------------- */
.ribbon-wrap { position: relative; margin-top: 72px; }

.ribbon-track {
  position: relative;
  height: 2px;
  background: var(--line);
  overflow: hidden;
}
.ribbon-packet {
  position: absolute;
  left: -160px;
  top: 0;
  width: 160px;
  height: 2px;
  background: linear-gradient(to right, rgba(255,85,0,0), var(--accent));
}

.ribbon {
  display: grid;
  grid-template-columns: repeat(5, minmax(220px, 1fr));
  gap: 1px;
  background: var(--line);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
}
.cassette {
  background: var(--surface);
  padding: 26px 24px 30px;
  /* Coluna, para a descrição poder crescer e empurrar o rodapé para a base. Sem isso os cinco
     rodapés flutuam na altura em que o texto de cada um os deixou: medido em 2026-09-06, a
     linha divisória caía em 201px num cassette e 221px no vizinho, e a base variava 36px. */
  display: flex;
  flex-direction: column;
}
.cassette[data-phase-active="true"] {
  background: var(--surface-2);
  box-shadow: inset 0 2px 0 0 var(--accent);
}
.cassette-head { display: flex; align-items: center; justify-content: space-between; }
.cassette-id { font-size: 10px; letter-spacing: 0.2em; color: var(--muted); font-family: var(--font-mono); }
.cassette-id.is-active { color: var(--accent); }
.cassette-dot { display: block; width: 6px; height: 6px; background: var(--muted); }
.cassette-dot.is-active { background: var(--accent); }
.cassette-cmd { margin-top: 26px; font-size: 17px; font-weight: 700; font-family: var(--font-mono); }
.cassette-title { margin-top: 10px; font-size: 15px; font-weight: 600; }
.cassette-desc { margin: 12px 0 0; font-size: 13px; line-height: 1.6; color: var(--muted); flex: 1; }
.cassette-foot {
  margin-top: 22px;
  padding-top: 12px;
  /* Altura de duas linhas (12px de padding + 2 × 15px de line-height) para a LINHA DIVISÓRIA
     cair na mesma altura nos cinco. Só alinhar a base não bastava: a borda superior deste
     bloco é visível, e é ela a primeira coisa que denuncia o desalinhamento. */
  min-height: 42px;
  border-top: 1px solid rgba(240,243,246,0.06);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--muted);
  font-family: var(--font-mono);
}
.cassette-foot.gate { color: var(--cyan); }
.cassette-foot.gate-ok { color: var(--ok); }

.motor-detail {
  display: grid;
  grid-template-columns: 1fr 460px;
  gap: 40px;
  margin-top: 56px;
  align-items: stretch;
}
/* O respiro interno acompanha a tela: 32/36px fixos custavam 72px de uma coluna de 350 a 390px. */
.detail-card, .bypass-card {
  border: 1px solid var(--line);
  background: var(--surface);
  padding: clamp(20px, 5vw, 32px) clamp(20px, 5.5vw, 36px);
}
.bypass-card { background: var(--bg); }
.detail-tag { font-size: 10px; letter-spacing: 0.22em; color: var(--muted); font-family: var(--font-mono); }
/* Três fatos lado a lado enquanto couberem, um sob o outro quando não. Até 2026-09-15 eram três
   colunas fixas: a 390px cada uma ficava com 47px de conteúdo, e "Requisitos + AT" (79px) vazava
   por cima da vizinha. Com `flex-wrap` e base de 11rem a quebra sai da largura do próprio quadro,
   sem breakpoint: três colunas acima de ~530px, duas mais uma entre ~355 e ~530, uma abaixo disso.
   Flex e não `auto-fit` porque o grid deixaria uma célula vazia no caso "duas mais uma", pintada
   com o `--line` do fundo; no flex o terceiro fato estica e ocupa a linha. */
.detail-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  margin-top: 28px;
  background: var(--line);
}
.detail-fact { flex: 1 1 11rem; background: var(--surface); padding: 20px 22px; }
.detail-fact-key { font-size: 10px; letter-spacing: 0.2em; color: var(--muted); font-family: var(--font-mono); }
.detail-fact-val { margin-top: 10px; font-size: 16px; font-weight: 600; }
.detail-fact-sub { margin-top: 6px; font-size: 11px; color: var(--muted); font-family: var(--font-mono); }
.detail-status {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  align-items: center;
  justify-content: space-between;
  margin-top: 28px;
  padding-top: 16px;
  border-top: 1px solid rgba(240,243,246,0.06);
  font-size: 11px;
  font-family: var(--font-mono);
}
.detail-status .path { color: rgba(240,243,246,0.5); }
.detail-status .live { color: var(--cyan); }

.bypass-cmd { margin-top: 24px; font-size: 30px; font-weight: 700; color: var(--accent); font-family: var(--font-mono); }
.bypass-desc { margin: 16px 0 0; font-size: 15px; line-height: 1.62; color: var(--muted); }
.bypass-cond {
  margin-top: 28px;
  padding-top: 16px;
  border-top: 1px solid rgba(240,243,246,0.06);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: rgba(240,243,246,0.5);
  font-family: var(--font-mono);
}

.motor-caption {
  margin: 48px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--muted);
}

/* -------------------------------------------------------------------------
   05. TOPOLOGIA — AgentTopology.dc.html (grafo + memória viva + tabela)
   ------------------------------------------------------------------------- */
.topo-panels {
  display: grid;
  /* 420px → 380px para o grafo caber em 1:1 no desktop. Com 420 o painel dava 689px para um
     viewBox de 760: escala 0.906, e um rótulo de 10 unidades chegava à tela com 9,1px. */
  grid-template-columns: 1fr 380px;
  gap: 1px;
  margin-top: 64px;
  background: var(--line);
  border: 1px solid var(--line);
}
/* Duas propriedades guardam o mesmo estouro aqui, e vale saber qual faz o trabalho hoje.
   O defeito: o head e um flex de dois rotulos mono que somam ~284px; sem quebra, ele empurrava
   o painel a 349px numa coluna de 300px e a pagina ganhava scroll lateral a 340px.
   Medido por mutacao em 2026-09-04: quem segura e o `flex-wrap: wrap` do head — tirar so ele
   devolve o overflow (documento a 372px contra 340). Tirar so o `min-width: 0` nao devolve nada.
   O `min-width: 0` fica porque item de grid nasce com `min-width: auto` e a defesa custa zero,
   mas ele e a segunda linha, nao a primeira. */
/* Quem rola é só o desenho, não o painel. Até 2026-09-15 o `overflow-x` morava no painel inteiro,
   e o `centralizarNoHub()` rolava junto o cabeçalho e a legenda: a 390px `GRAFO // .claude/…` e o
   "Clique num nó…" começavam 250px à esquerda da tela, e o que sobrava deles eram letras soltas na
   borda. Com o trilho no host, cabeçalho, breadcrumb e legenda ficam sempre inteiros. */
.topo-graph-panel { background: var(--bg); padding: 28px clamp(16px, 4vw, 32px) 24px; min-width: 0; }
.topo-graph-host { overflow-x: auto; }
.topo-panel-head { display: flex; flex-wrap: wrap; gap: 4px 16px; justify-content: space-between; font-size: 10px; letter-spacing: 0.22em; color: var(--muted); }
.topo-panel-head .live { color: var(--cyan); }
/* Mesma razão do `.blueprint-svg`: o desenho nunca renderiza abaixo de 1:1. A 390px o painel
   dava 245px — escala 0.32, e `code-reviewer` chegava à tela com 3,2px. Um rótulo que não se lê
   é pior que rótulo nenhum, e rolar é o preço de poder ler.

   880 e não 760: o `<svg>` do markup declara 760, mas quem manda é o `graph.js`, que reconstrói
   o grafo em runtime e escreve o próprio `viewBox` de 880×620. Calibrar pelo markup estático é
   calibrar por um desenho que a página descarta no primeiro frame. */
.topo-graph-svg { margin-top: 20px; display: block; width: 100%; min-width: 880px; height: auto; }
.topo-graph-note { margin: 8px 0 0; font-size: 10px; letter-spacing: 0.1em; color: var(--muted); }
.topo-graph-note .ink { color: var(--ink); }

/* --- Grafo interativo (assets/js/graph.js) -------------------------------
   O SVG e construido em runtime; o que segue e so aparencia e estado. O realce usa
   `stroke-opacity` de proposito: `opacity` pertence ao pulso continuo do GSAP
   (motion.js secao 4) e as duas propriedades se multiplicam sem brigar. */
.topo-graph-host { min-height: 320px; }

.topo-crumb[hidden], .inspector-panel[hidden] { display: none; }
.topo-crumb { display: flex; align-items: center; gap: 10px; margin-top: 16px; font-size: 10px; letter-spacing: 0.18em; color: var(--muted); }
.topo-crumb-back {
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  letter-spacing: inherit;
  padding: 6px 12px;
  cursor: pointer;
}
.topo-crumb-back:hover { border-color: var(--accent); color: var(--accent); }
/* A 340px o botão quebrava em "←" e "Voltar", uma linha cada. */
.topo-crumb-back { white-space: nowrap; }
.topo-crumb-label { color: var(--cyan); }

.g-ring { stroke: rgba(240,243,246,0.05); }

.g-edge { stroke: rgba(240,243,246,0.10); stroke-width: 1; }
.g-edge--orchestrates { stroke: var(--accent); stroke-opacity: 0.45; }
.g-edge--connects_to { stroke: var(--cyan); stroke-opacity: 0.28; }
.g-edge--uses_skill { stroke: rgba(240,243,246,0.22); }
.g-edge.is-lit { stroke-opacity: 1; stroke-width: 1.6; }
.g-edge.is-dim { stroke-opacity: 0.07; }
.g-edge.is-out { stroke-opacity: 0.03; }

.g-node { cursor: pointer; }
.g-node .g-hit { pointer-events: all; }
.g-node .g-halo, .g-node .g-dot { pointer-events: none; }
.g-node .g-halo { fill: none; stroke: var(--line-strong); stroke-width: 1; }
.g-node .g-dot { fill: var(--surface-2); stroke: var(--line-strong); stroke-width: 1; }
.g-node .g-label {
  font-family: var(--font-mono);
  /* 11 e não 10: o painel desenha o viewBox de 880 em 837px no desktop (escala 0.951), e 10
     chegaria à tela com 9,5px. */
  font-size: 11px;
  fill: var(--muted);
  letter-spacing: 0.04em;
  pointer-events: none;
}

.g-node--agent .g-halo { stroke: rgba(0,229,255,0.35); }
.g-node--agent .g-dot { fill: var(--surface-2); stroke: var(--cyan); }
.g-node--agent .g-label { fill: var(--ink); }
.g-node--skill .g-halo { stroke: rgba(240,243,246,0.14); }
.g-node--skill .g-dot { stroke: rgba(240,243,246,0.35); }
.g-node--skill.is-referenced .g-dot { fill: transparent; }

.g-hub-frame { stroke: var(--accent); stroke-width: 1; }
.g-hub-box { fill: var(--surface-2); stroke: var(--accent); stroke-width: 1; }
.g-hub-name { font-family: var(--font-mono); font-size: 15px; font-weight: 700; fill: var(--accent); pointer-events: none; }
.g-hub-role { font-family: var(--font-mono); font-size: 11px; fill: var(--muted); letter-spacing: 0.15em; pointer-events: none; }

.g-node:hover .g-halo,
.g-node:focus-visible .g-halo { stroke: var(--accent); stroke-width: 1.6; }
.g-node:hover .g-label,
.g-node:focus-visible .g-label { fill: var(--ink); }
.g-node:focus { outline: none; }
.g-node:focus-visible .g-dot { stroke: var(--accent); }

.g-node.is-lit .g-dot { fill: var(--accent); stroke: var(--accent); }
.g-node.is-lit .g-label { fill: var(--ink); }
.g-node.is-dim { opacity: 0.28; }
.g-node.is-out { opacity: 0.08; pointer-events: none; }

/* --- Grafo compacto: celular, trilho com menos de 560px (graph.js `medirModo`) ---------------
   D-26 (2026-09-15). A 390px o grafo de 880px rolava para o lado com os nomes da borda cortados.
   Compacto, ele cabe: na visão geral o max e os 11 agentes com a sigla no círculo; no foco, o nó
   tocado no centro e os vizinhos com o nome por extenso. As fontes são de 12,5 a 15 unidades
   porque a 340px o viewBox de 320 chega à tela a ~0,83, e 12 unidades dariam 9,98px, abaixo dos
   10 do `texto-minusculo`. Fora do compacto, sigla e nome não aparecem. */
.g-sigla, .g-nome { display: none; }
.topo-graph-host.is-compact .topo-graph-svg { min-width: 0; max-width: 420px; margin-inline: auto; }
.is-compact .g-ring--skill,
.is-compact .g-node .g-label { display: none; }
.is-compact .g-node .g-sigla {
  display: block;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  fill: var(--ink);
  pointer-events: none;
}
.is-compact .g-node.is-lit .g-sigla { fill: var(--bg); }
/* O contorno da cor do fundo atrás das letras: no foco, as arestas saem do nó central e passavam
   por cima do nome dele. */
.is-compact .g-node .g-nome {
  font-family: var(--font-mono);
  font-size: 13px;
  fill: var(--ink);
  paint-order: stroke;
  stroke: var(--bg);
  stroke-width: 4px;
  stroke-linejoin: round;
  pointer-events: none;
}
.is-compact .g-node.is-named .g-nome { display: block; }
.is-compact .g-node--agent .g-dot { r: 16px; }
.is-compact .g-node--agent .g-halo { r: 22px; }
.is-compact .g-node--skill .g-dot { r: 14px; }
.is-compact .g-node--skill .g-halo { r: 19px; }
.is-compact .g-node .g-hit { r: 26px; }
.is-compact .g-hub-role { font-size: 12.5px; letter-spacing: 0; }
/* Fora do desenho, não esmaecido: no compacto o que sai do foco sai de cena. `display` e não
   `opacity` porque a opacidade das arestas é do pulso do GSAP (motion.js seção 4); e não
   `visibility`, que deixava a sigla e o círculo dos nós ocultos no lugar, empilhados no centro e
   no anel — o auditor acusava rótulo "coberto" por forma que ninguém via. */
.is-compact .g-node.is-out,
.is-compact .g-edge.is-out { display: none; }

/* --- Ficha do no (mesma coluna do painel de memoria) --------------------- */
.inspector-panel { background: var(--surface); display: flex; flex-direction: column; min-height: 0; }
.insp-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px 14px 32px;
  border-bottom: 1px solid var(--line);
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--muted);
}
.insp-close {
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
}
.insp-close:hover { color: var(--accent); }

.insp-body { padding: 24px 32px 32px; overflow-y: auto; max-height: 560px; }
.insp-name { font-size: 20px; font-weight: 700; color: var(--ink); }
.insp-kind { margin-top: 4px; font-size: 10px; letter-spacing: 0.18em; color: var(--cyan); text-transform: uppercase; }
.insp-desc { margin: 18px 0 0; font-size: 13px; line-height: 1.7; color: var(--muted); }

.insp-block { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--line); }
.insp-block-head { font-size: 10px; letter-spacing: 0.22em; color: var(--muted); }
.insp-block-body { margin-top: 10px; }
.insp-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.insp-tag, .insp-chip {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 4px 8px;
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--ink);
}
.insp-chip { cursor: pointer; color: var(--cyan); }
.insp-chip:hover { border-color: var(--accent); color: var(--accent); }
.insp-line { margin: 0; font-size: 12px; color: var(--ink); }
.insp-note { margin: 8px 0 0; font-size: 12px; line-height: 1.6; color: var(--muted); }

/* O painel acompanha a altura do grafo ao lado e sobravam 222px abaixo do rodapé (medido em
   2026-09-06). A folga vai para os quatro itens da lista, que é o conteúdo que se beneficia de
   respirar; o rodapé RETENÇÃO/SINCRONIA continua na base. */
.memory-panel { background: var(--surface); padding: 28px 32px 32px; display: flex; flex-direction: column; }
.memory-tag { font-size: 10px; letter-spacing: 0.22em; color: var(--muted); font-family: var(--font-mono); }
.memory-title {
  margin-top: 22px;
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.1;
}
/* 700, não o 800 herdado: a Martian Mono vai até 700 e o resto seria negrito sintético (D-20). */
.memory-title .mono { font-size: 23px; font-weight: 700; color: var(--accent); }

.memory-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 28px;
  flex: 1;
  background: var(--line);
  border: 1px solid var(--line);
}
.memory-row {
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--surface-2);
  padding: 16px 18px;
  flex: 1;
}
.memory-bar { display: block; width: 3px; height: 26px; background: rgba(240,243,246,0.2); flex-shrink: 0; }
.memory-bar.accent { background: var(--accent); }
.memory-row-title { font-size: 13px; font-weight: 700; font-family: var(--font-mono); }
.memory-row-desc { margin-top: 3px; font-size: 12px; color: var(--muted); }
.memory-row-status { margin-left: auto; font-size: 10px; color: var(--ok); font-family: var(--font-mono); }

.memory-meta {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  line-height: 1.9;
  color: var(--muted);
  font-family: var(--font-mono);
}
.memory-meta .live { color: var(--cyan); }

/* Tabela dos 11 agentes. Estreita, ela vira lista (o `@container roster` no fim da folha); o
   `overflow-x` fica como rede para um nome sem quebra, não como o jeito de ler a tabela. */
.roster {
  margin-top: 56px;
  border-top: 1px solid var(--line);
  overflow-x: auto;
  container: roster / inline-size;
}
.roster-table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-family: var(--font-mono);
}
.roster-table thead th {
  text-align: left;
  padding: 16px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--muted);
  font-weight: 400;
}
.roster-table tbody td {
  padding: 14px 12px;
  border-bottom: 1px solid rgba(240,243,246,0.05);
  vertical-align: top;
}
.roster-table tbody tr:last-child td { border-bottom: 0; }
.roster-name { font-size: 13px; color: var(--ink); white-space: nowrap; }
.roster-role { font-size: 12px; color: var(--accent); white-space: nowrap; }
.roster-scope { font-size: 14px; color: var(--muted); font-family: var(--font-display); }

/* -------------------------------------------------------------------------
   06. INSTRUMENTAÇÃO — Terminal.dc.html (terminal + HUD de telemetria)
   ------------------------------------------------------------------------- */
.term-layout {
  display: grid;
  grid-template-columns: 1fr 440px;
  gap: 40px;
  margin-top: 64px;
  align-items: start;
}

.term-slab { border: 1px solid var(--line-strong); background: var(--bg); }
.term-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.term-dots { display: flex; gap: 4px; }
.term-dots span { display: block; width: 10px; height: 1px; background: var(--muted); }
.term-titlebar-name { font-size: 11px; letter-spacing: 0.12em; font-family: var(--font-mono); }
.term-titlebar-meta { display: flex; align-items: center; gap: 18px; font-size: 10px; letter-spacing: 0.1em; color: var(--muted); font-family: var(--font-mono); }

.term-body {
  padding: 26px 24px 30px;
  font-size: 13px;
  font-family: var(--font-mono);
}
.term-line { display: block; white-space: pre-wrap; line-height: 1.95; }
.term-line .dim { color: var(--muted); }
.term-line .pr { color: var(--accent); }
.term-line .sl { color: var(--cyan); }
.term-line .ok { color: var(--ok); }
.term-caret {
  display: inline-block;
  width: 9px;
  height: 15px;
  vertical-align: -2px;
  background: var(--accent);
}
@media (prefers-reduced-motion: no-preference) {
  .term-caret { animation: caret 1.1s steps(1) infinite; }
}
@keyframes caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* Quebra ENTRE os dois rótulos, com vão: sem `wrap` e sem `gap`, a 390px os dois somavam
   exatamente a largura da barra e liam como "COMPILER CLIEXIT 0". */
.term-footbar {
  display: flex;
  flex-wrap: wrap; gap: 4px 24px;
  justify-content: space-between;
  padding: 12px 24px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--muted);
  font-family: var(--font-mono);
}
.term-footbar .ok { color: var(--ok); }

.hud {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.hud-block { background: var(--surface); padding: 22px 24px; }
.hud-block.quiet { background: var(--surface-2); }
.hud-tag { font-size: 10px; letter-spacing: 0.22em; color: var(--muted); font-family: var(--font-mono); }
.hud-phase {
  margin-top: 16px;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.5;
  font-family: var(--font-mono);
}
.hud-phase .cyan { color: var(--cyan); }

.hud-progress-head { display: flex; justify-content: space-between; font-size: 10px; letter-spacing: 0.18em; color: var(--muted); font-family: var(--font-mono); }
.hud-progress-head .ink { color: var(--ink); }
.hud-progress-bars { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; margin-top: 14px; }
.hud-progress-bars span { display: block; height: 6px; background: rgba(240,243,246,0.10); }
.hud-progress-bars span.done { background: var(--accent); }
.hud-progress-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--muted);
  font-family: var(--font-mono);
}

.hud-dispatch { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.hud-dispatch-row { display: flex; align-items: center; justify-content: space-between; font-family: var(--font-mono); }
.hud-dispatch-name { font-size: 12px; color: var(--ink); }
.hud-dispatch-status { font-size: 10px; }
.hud-dispatch-status.done { color: var(--ok); }
.hud-dispatch-status.active { color: var(--cyan); }
.hud-dispatch-status.queued { color: var(--muted); }

.hud-guards {
  margin-top: 16px;
  font-size: 12px;
  line-height: 2.1;
  font-family: var(--font-mono);
}
.hud-guards .ok { color: var(--ok); }
.hud-guards-foot {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(240,243,246,0.06);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--muted);
  font-family: var(--font-mono);
}

.hud-peers { margin-top: 14px; font-size: 12px; line-height: 1.9; font-family: var(--font-mono); }
.hud-peers .arrow { color: var(--accent); }

/* -------------------------------------------------------------------------
   07. EXECUÇÃO — Blueprint.dc.html (matriz + CTA quickstart + autor)
   ------------------------------------------------------------------------- */
.blueprint-frame {
  margin-top: 56px;
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 28px 32px;
  overflow-x: auto;
  container: blueprint / inline-size;
}
/* `min-width` = a largura do próprio viewBox, para o desenho nunca renderizar abaixo de 1:1.
   Antes eram 720px sobre um viewBox de 1280: escala 0.5625 fixa de 340 a 768, e um rótulo de
   8 unidades chegava à tela com 4,5px. O quadro já rola na horizontal — rolar um esquema
   legível é melhor que caber um ilegível. */
.blueprint-svg { display: block; width: 100%; min-width: 1080px; height: auto; }
/* Com menos de 1080px de quadro o esquema troca de eixo em vez de rolar. Até 2026-09-15 ele rolava
   em qualquer largura abaixo disso, 1024px inclusive, e a 390px mostrava só ENTRADA e P_00 de um
   desenho de 1120px, sem nada dizendo que havia mais. A versão vertical conta a mesma coisa (o
   pipe de cima para baixo; barramento e memória como duas espinhas que tocam toda fase) num
   viewBox de 280 unidades: a 340px ela renderiza a ~0.96, e o menor rótulo (12 unidades) chega
   à tela acima dos 10px do `texto-minusculo`. As duas versões estão no HTML; o CSS mostra uma. */
.blueprint-svg--vertical { display: none; min-width: 0; max-width: 360px; margin-inline: auto; }
@container blueprint (max-width: 1079px) {
  .blueprint-svg--horizontal { display: none; }
  .blueprint-svg--vertical { display: block; }
}

/* A legenda que morava dentro do SVG. Em HTML ela não encolhe com o viewBox e não exige rolar
   o quadro inteiro para ser lida. */
.blueprint-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 40px;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 16px;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.blueprint-notas { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px; margin: 0; }
.blueprint-notas dt { letter-spacing: 0.2em; color: var(--muted); }
.blueprint-notas dd { margin: 0; }
.blueprint-notas dd::before { content: "— "; color: var(--line-strong); }
.blueprint-rev { display: flex; gap: 18px; white-space: nowrap; }
.blueprint-rev .ok { color: var(--ok); }

/* O autor tinha 480px fixos (400 de conteúdo) e quebrava a stack no meio de "modelagem
   dimensional"; o quickstart, com três passos, já não precisa de 764px. Divisão quase ao meio. */
.exec-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 40px;
  margin-top: 48px;
  align-items: stretch;
}

.quickstart-card, .author-card {
  position: relative;
  border: 1px solid var(--line);
  background: var(--surface);
  padding: clamp(24px, 6vw, 36px) clamp(20px, 5vw, 40px);
  /* mesma razao do `.topo-graph-panel`: item de grid com `min-width: auto` nao encolhe abaixo
     do comando mais longo do quickstart (a linha de instalação com a URL do bootstrap). */
  min-width: 0;
}
/* Coluna flexível para a frase de fechamento descer até a base: os dois cards dividem a altura, e
   a folga do autor (~290px a 1440) ficava toda depois da última linha. Assim ela fica entre os
   fatos e a assinatura, e a assinatura alinha com o rodapé do quickstart. */
.author-card { background: var(--bg); display: flex; flex-direction: column; }

/* O card divide a linha do grid com o do autor. Até 2026-09-12 a folga ia para três vãos de
   ~140px (`align-content: space-between`), e o card lia como vazio. Com os três passos o
   conteúdo ocupa a altura, e a folga que sobrar fica numa linha só, acima do rodapé.

   O cabeçalho é o motivo de ser grid e não flex-column: o rótulo `ID_REF //` e o seletor de SO
   fluíam na MESMA linha de texto, e qualquer contexto de coluna os empilharia. Os dois declaram
   a linha 1, e o seletor vai para a borda direita do card — o mesmo desenho de cabeçalho que o
   painel do grafo já usa. Um wrapper resolveria igual, mas quebraria os seletores
   `#osWin:checked ~ .quickstart-route`, que exigem os radios irmãos de tudo que comandam.

   Toda célula é declarada, nenhuma deduzida. Com a coluna do seletor implícita e as linhas em
   auto, a colocação esparsa do grid mandou o bloco de comandos para uma coluna de 31px de
   largura e o rodapé para 217px de altura — medido, e é a mesma armadilha que já tinha custado
   um ciclo inteiro ao comparativo do §paradoxo. */
.quickstart-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto 1fr;
}
.quickstart-tag { grid-area: 1 / 1; align-self: center; }
.qs-os-toggle { grid-area: 1 / 2; margin: 0 0 0 24px; }
.qs-passos { grid-column: 1 / -1; grid-row: 2; }
.quickstart-cta-row { grid-column: 1 / -1; grid-row: 3; }
.quickstart-foot { grid-column: 1 / -1; grid-row: 4; align-self: end; }

/* Os passos são uma sequência de verdade (instalar antes de criar, criar antes de abrir o
   Claude Code), então o número carrega informação e não é enfeite de seção. */
.qs-passos { list-style: none; margin: 32px 0 0; padding: 0; display: grid; gap: 28px; container: qs-passos / inline-size; }
.qs-passo { display: grid; grid-template-columns: 26px minmax(0, 1fr); column-gap: 16px; }
.qs-num {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--line-strong);
  font-size: 11px;
  color: var(--accent);
}
.qs-corpo { min-width: 0; }
.qs-titulo { font-size: 17px; font-weight: 600; line-height: 26px; color: var(--ink); }
.qs-desc { margin-top: 4px; font-size: 14px; line-height: 1.55; color: var(--muted); max-width: 62ch; }
.qs-desc .mono, .qs-req .mono { font-size: 13px; color: var(--ink); }
.qs-req { margin-top: 8px; font-size: 13px; line-height: 1.5; color: var(--muted); }
.qs-aviso { margin-top: 12px; font-size: 14px; color: var(--ink); }
.qs-aviso::before { content: "→ "; color: var(--accent); }
.qs-claude .pr { color: var(--cyan); }
/* Estreita, a coluna do número custava 42px de cada linha do passo; no bloco de instalação isso
   somava com os respiros do card, e a 390px a URL quebrava a cada 19 caracteres. Com menos de
   420px de lista o número flutua ao lado do título e o resto do passo usa a largura inteira. */
@container qs-passos (max-width: 419px) {
  .qs-passo { display: block; }
  .qs-num { float: left; margin-right: 12px; }
}
/* Estreito, o seletor de sistema não cabe ao lado do rótulo: a 390px ele se sobrepunha a
   "COMO COMEÇAR" (visto em 2026-09-12). Desce para uma linha própria, e as de baixo descem junto. */
@media (max-width: 560px) {
  .quickstart-card { grid-template-rows: auto auto auto auto 1fr; }
  .qs-os-toggle { grid-area: 2 / 1 / 3 / -1; justify-self: start; margin: 16px 0 0; }
  .qs-passos { grid-row: 3; }
  .quickstart-cta-row { grid-row: 4; }
  .quickstart-foot { grid-row: 5; }
}
.quickstart-guia {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
}

.quickstart-tag, .author-tag { font-size: 10px; letter-spacing: 0.22em; color: var(--muted); font-family: var(--font-mono); }

/* Toggle Windows/Linux — funciona sem JS via radio + seletor de irmãos;
   motion.js/track.js só leem data-os-toggle, não precisam implementar a
   troca de painel para o site continuar íntegro com JS desligado. */
.qs-os-toggle {
  display: inline-flex;
  gap: 1px;
  margin-top: 20px;
  background: var(--line);
  border: 1px solid var(--line);
}
.qs-os-radio {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}
.qs-os-toggle label {
  display: inline-flex;
  align-items: center;
  background: var(--surface-2);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  padding: 0 16px;
  min-height: 44px;
  cursor: pointer;
}
#osWin:checked ~ .qs-os-toggle label[for="osWin"],
#osLin:checked ~ .qs-os-toggle label[for="osLin"] {
  background: var(--surface);
  color: var(--ink);
}
#osWin:focus-visible ~ .qs-os-toggle label[for="osWin"],
#osLin:focus-visible ~ .qs-os-toggle label[for="osLin"] {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* Título da §execução. Morava num `style=""` inline com 800 sobre a Anton (negrito sintético) e
   `max-width: 20ch`, que o partia em duas linhas. Pedido de 2026-09-12: uma linha no desktop.
   A escala cabe em uma linha de 1024px para cima; abaixo disso quebra naturalmente. */
.section-head-solo { font-size: clamp(2rem, 1.2rem + 2.6vw, 3.75rem); }

.quickstart-route { display: none; }
#osWin:checked ~ .qs-passos .quickstart-route#routeWin,
#osLin:checked ~ .qs-passos .quickstart-route#routeLin { display: block; }

.quickstart-block {
  margin-top: 12px;
  padding: clamp(14px, 3.5vw, 20px) clamp(14px, 4vw, 22px);
  border: 1px solid var(--line);
  background: var(--bg);
  font-size: 13px;
  line-height: 1.8;
  font-family: var(--font-mono);
  /* O comando de instalação tem ~115 caracteres e uma URL sem espaço. Rolando dentro do bloco,
     a 390px ele saía cortado na borda sem nada indicar que havia mais; quebrando só nos espaços,
     a URL ia inteira para linhas próprias. `anywhere` mostra o comando todo, partido onde couber.
     Quem copia usa o botão (`#copyQs`), que lê o `data-copy` e não o texto quebrado.
     O `overflow-x` fica como rede: nada aqui deve rolar, mas um token sem quebra não empurra a
     página para fora do viewport. */
  overflow-wrap: anywhere;
  overflow-x: auto;
}
.quickstart-block .pr { color: var(--accent); }
.quickstart-route[hidden] { display: none; }

.quickstart-cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; margin-top: 32px; }

.quickstart-foot {
  margin-top: 32px;
  padding-top: 18px;
  border-top: 1px solid rgba(240,243,246,0.06);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-family: var(--font-mono);
}

/* Cabeçalho de perfil (D-22): marca, nome, título e local, e logo abaixo os links como botões,
   na ordem em que um perfil do LinkedIn se lê. */
.author-head { display: flex; align-items: center; gap: 20px; margin-top: 24px; }
.author-mark { flex-shrink: 0; width: 64px; height: 64px; }
.author-id { min-width: 0; }
.author-name { font-size: 24px; font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; }
.author-role { margin-top: 6px; font-size: 15px; line-height: 1.4; color: var(--ink); }
.author-local { margin-top: 6px; font-size: 11px; letter-spacing: 0.1em; color: var(--muted); }

.author-facts { display: flex; flex-direction: column; margin-top: 28px; }
/* A chave fica ACIMA do valor em toda largura, e o motivo é medição, não gosto: o card mede
   480px (400px de conteúdo) mesmo num viewport de 2560px, porque divide a linha com o
   quickstart. A coluna fixa de 150px mais a coluna de 104px da raia da stack comiam 282px
   desses 400 — sobravam 127px para o valor, e a stack saía um item por linha. Medido em
   2026-09-05. Rótulo em cima devolve a largura inteira ao conteúdo. */
.author-fact {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  padding: 20px 0;
  border-top: 1px solid rgba(240,243,246,0.06);
}
.author-fact:last-child { border-bottom: 1px solid rgba(240,243,246,0.06); }
.author-fact-key { font-size: 10px; letter-spacing: 0.18em; color: var(--muted); font-family: var(--font-mono); }
.author-fact-val { font-size: 14px; color: var(--ink); }
.author-fact-val.mono { font-size: 13px; font-family: var(--font-mono); }
/* Experiência como linha do tempo: o quadrado cheio marca o cargo atual, o vazado o anterior, e
   o fio liga os dois. `overflow-wrap: anywhere` herdado da regra das provas (D-08): a 340px um
   token longo sem quebra empurrava a página para fora do viewport. */
.author-xp { list-style: none; margin: 2px 0 0; padding: 0; display: grid; gap: 20px; }
.author-xp-item { position: relative; padding-left: 22px; overflow-wrap: anywhere; }
.author-xp-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
  width: 9px;
  height: 9px;
  border: 1px solid var(--line-strong);
  background: var(--bg);
}
.author-xp-item.is-atual::before { background: var(--accent); border-color: var(--accent); }
.author-xp-item:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 19px;
  bottom: -16px;
  width: 1px;
  background: var(--line);
}
.author-xp-topo { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; }
.author-xp-cargo { font-size: 15px; font-weight: 600; color: var(--ink); }
.author-xp-periodo { font-size: 11px; letter-spacing: 0.06em; color: var(--muted); white-space: nowrap; }
.author-xp-empresa { margin-top: 2px; font-size: 14px; color: var(--ink); }
.author-xp-desc { margin: 6px 0 0; font-size: 14px; line-height: 1.6; color: var(--muted); }

.author-cred { list-style: none; margin: 2px 0 0; padding: 0; display: grid; gap: 12px; }
.author-cred li { display: grid; gap: 2px; overflow-wrap: anywhere; }
.author-cred-nome { font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--ink); }
.author-cred-meta { font-size: 11px; letter-spacing: 0.06em; color: var(--muted); }

.author-chips { list-style: none; margin: 2px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.author-chips li {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
}
.author-links-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 20px; }
.author-links-row a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--line-strong);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink);
}
.author-links-row a:hover { border-color: var(--accent); color: var(--accent); }
.author-links-row svg { width: 15px; height: 15px; }
.author-closing .mono { color: var(--ink); }

.author-closing { margin: auto 0 0; padding-top: 26px; font-size: 15px; line-height: 1.6; color: var(--muted); }

/* -------------------------------------------------------------------------
   Pix / rodapé — id="author" vive dentro de #execucao (§1); o Pix e o
   rodapé geral seguem aqui, dentro da mesma seção, como um bloco final.
   ------------------------------------------------------------------------- */
.pix-block {
  margin-top: 40px;
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 28px 32px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}
.pix-copy p { font-size: 14px; line-height: 1.6; color: var(--muted); max-width: 52ch; }
.pix-copy h3 { font-size: 17px; font-weight: 700; margin-bottom: 8px; }
.pix-actions-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pix-key {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
  padding: 10px 14px;
  border: 1px solid var(--line-strong);
  word-break: break-all;
}
.pix-tag, .pix-qr-btn {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink);
  background: none;
  border: 1px solid var(--line-strong);
  min-height: 44px;
  min-width: 44px;
  padding: 0 16px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.pix-qr-btn { padding: 0 12px; }
.pix-qr-btn svg { width: 18px; height: 18px; }

.pix-qr-dialog {
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  padding: 0;
  max-width: 360px;
}
.pix-qr-dialog::backdrop { background: rgba(7,8,9,0.7); }
.pix-qr-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
}
.pix-qr-head h3 { font-size: 14px; }
.pix-qr-close {
  background: none;
  border: 0;
  color: var(--ink);
  min-width: 44px;
  min-height: 44px;
  cursor: pointer;
}
.pix-qr-close svg { width: 18px; height: 18px; }
.pix-qr-img-wrap { padding: 20px; display: flex; justify-content: center; }

/* Mesmo padrão do header: a borda/fundo do rodapé sangra, o conteúdo
   (.footer-inner) centraliza dentro do teto de largura. */
.site-footer {
  border-top: 1px solid var(--line);
}
.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 48px 40px;
}
.foot-links { display: flex; flex-wrap: wrap; gap: 20px; }
.foot-links a { font-size: 12px; color: var(--muted); font-family: var(--font-mono); }
.foot-links a:hover { color: var(--ink); }
.foot-meta { font-size: 11px; color: var(--muted); font-family: var(--font-mono); }

/* -------------------------------------------------------------------------
   Motion — estado inicial = estado FINAL (regra dura do contrato §2).
   motion.js só regride para o estado de partida da animação quando GSAP
   existe e prefers-reduced-motion não é reduce. Nada aqui esconde conteúdo.
   ------------------------------------------------------------------------- */
[data-motion] { opacity: 1; }
.reveal { opacity: 1; transform: none; }

/* -------------------------------------------------------------------------
   Responsivo — 1440 é a referência dos artboards; 768 comprime as colunas
   duplas em pilha; 390 remove o rail lateral e empilha tudo.
   ------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .hero-grid { grid-template-columns: 60px 1fr; }
  .hero-rail { grid-row: auto; }
  .hero-art {
    grid-column: 1 / -1;
    border-left: 0;
    border-top: 1px solid var(--line);
    padding: 40px 20px 32px;
  }
  /* O limite de largura passa a ser do PALCO, não do SVG: quem define a caixa que o canvas
     cobre é o palco, e um SVG estreito dentro de um palco largo deixaria o monólito
     desenhado numa área maior que o desenho que ele substitui. */
  .hero-stage { max-width: 420px; margin-inline: auto; }
  .hero-art svg { max-width: 420px; margin-inline: auto; }
  /* A 58% de escala as cotas dariam 5,8px na tela, e os rótulos de camada 5,8px também.
     As cotas são ornamento. Os rótulos de camada não são — mas o mesmo conteúdo já está logo
     abaixo do desenho, em HTML de verdade, na lista `[data-hero-phases]`: `L_00 · Intenção
     ambígua · ENTROPIA`. Não se perde informação escondendo a cópia ilegível da legível. */
  .hero-cotas, .hero-rotulo-camada { display: none; }
  /* Duas colunas não cabem aqui — legenda e cota empilham. */
  .hero-art:has(.hero-stage.is-3d) { grid-template-columns: 1fr; }
  .hero-art:has(.hero-stage.is-3d) > .hero-art-caption { justify-self: start; white-space: normal; }
  .hero-stage.is-3d ~ .hero-phases { justify-self: start; }
  .hero-art-caption { position: static; text-align: left; margin-top: 16px; }
  .section-head, .paradox-compare, .motor-detail, .topo-panels, .term-layout, .exec-layout {
    grid-template-columns: 1fr;
  }
  .section-head { gap: 32px; }
  .paradox-col { padding: 40px 0; }
  /* A 768px as três colunas da linha não cabem. A chave sobe para rótulo e os dois lados viram
     duas linhas, cada uma dizendo de qual lado é — sem o alinhamento horizontal, "A" e "B"
     precisam ser ditos, não mostrados. */
  .paradox-matrix { --paradox-vao: 32px; }
  /* Sem lado a lado não há eixo, e cabeçalho de coluna sobre uma pilha mentiria: cada valor
     passa a dizer de que lado é, logo abaixo, no `::before`. */
  .paradox-matrix::before, .paradox-legend { display: none; }
  .paradox-row { grid-template-columns: 1fr; gap: 6px; padding: 16px 0; }
  .paradox-k, .paradox-a, .paradox-b { grid-column: 1; grid-row: auto; }
  .paradox-k { text-align: left; justify-self: start; background: none; padding: 0; }
  .paradox-a, .paradox-b { text-align: left; font-size: 14px; }
  .paradox-a::before, .paradox-b::before {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.16em;
    margin-right: 8px;
  }
  .paradox-a::before { content: "A ·"; color: var(--fail); }
  .paradox-b::before { content: "B ·"; color: var(--ok); }
  .paradox-col:first-child { border-bottom: 1px solid var(--line); }
  .paradox-divider { display: none; }
}

@media (max-width: 768px) {


  /* Header mobile do HeroMobile.dc.html: 52px, marca à esquerda, hambúrguer à direita.
     Tudo aqui está sob `html.has-js` (classe posta no <head>, antes do paint): sem JS o
     hambúrguer não apareceria e o painel ficaria fechado para sempre, então a página sem
     script mantém a faixa rolável de antes — nenhum link some quando o script falha. */
  .site-nav { gap: 16px; }

  html.has-js .header-inner { padding: 0 20px; }
  :root { --header-h: 52px; }
  .brand-marca { height: 23px; }
  /* Escopado ao header: `.brand-name` também é a marca do rodapé, e lá o texto é a URL do
     repo — sem o escopo o nowrap esticava o rodapé a 349px e devolvia o scroll lateral. */
  html.has-js .site-header .brand-name { white-space: nowrap; }
  html.has-js .nav-toggle { display: flex; }

  html.has-js .header-rail { display: none; }
  html.has-js .site-header.is-open .header-rail {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    max-height: calc(100dvh - 52px);
    overflow-y: auto;
    padding: 8px 20px 24px;
    border-bottom: 1px solid var(--line);
    /* Opaco, não os 0.82 translúcidos do header: a 0.97 o `Pare de improvisar` do hero ainda
       atravessava o painel e brigava com os rótulos da nav (medido a 390px). */
    background: var(--bg);
  }
  html.has-js .site-header.is-open .site-nav { flex-direction: column; gap: 0; overflow-x: visible; }
  html.has-js .site-header.is-open .site-nav a { padding: 14px 0; font-size: 13px; border-bottom: 1px solid var(--line); }
  html.has-js .site-header.is-open .header-meta { margin-top: 20px; }
  html.has-js .site-header.is-open .header-meta .btn { width: 100%; }

  .hero-grid { grid-template-columns: 1fr; }
  .hero-rail { flex-direction: row; padding: 0; border-right: 0; border-bottom: 1px solid var(--line); }
  .hero-rail .rail-line { display: none; }
  .hero-rail .rail-label { writing-mode: horizontal-tb; transform: none; padding: 16px 20px; }

  .section-grid { grid-template-columns: 1fr; }
  .section-rail { flex-direction: row; padding: 20px 20px 0; border-right: 0; border-bottom: 1px solid var(--line); }
  .rail-line { display: none; }
  .rail-label { writing-mode: horizontal-tb; transform: none; letter-spacing: 0.2em; }
  .section-body { padding: 40px 20px 56px; }

  .hero-copy { padding: 40px 20px 32px; }
  .hero-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hero-stat, .hero-stat:not(:first-child) { padding: 18px 12px 0 0; }

  .tese-band { padding: 56px 20px; }

  .ribbon { grid-template-columns: repeat(5, minmax(200px, 1fr)); }

  .roster-table { min-width: 620px; }

  .insp-body { max-height: none; }
  .insp-bar { padding-left: 20px; }
  .topo-graph-host { min-height: 260px; }

  /* Coluna unica: o SVG cai para ~300px de largura e o viewBox encolhe tudo junto.
     Compensa-se DENTRO do viewBox — texto maior e nos mais gordos — em vez de tentar
     esticar o SVG. `r` como propriedade CSS e SVG2; onde nao pegar, valem os atributos. */
  /* Aqui havia uma compensação mobile (17/26/13) para o grafo encolhido, e METADE DELA NUNCA
     FUNCIONOU: `.g-label` tem especificidade 0,1,0 e perde para `.g-node .g-label` (0,2,0) da
     regra base — o rótulo dos agentes continuou em 10px, medido. As outras duas funcionavam e
     mascaravam o problema. Com o `min-width` acima o desenho não encolhe mais, então não há o
     que compensar: o bloco saiu inteiro em vez de ser consertado.
     Regra escrita e nunca verificada contra a tela vale zero — e ainda mente sobre estar coberto. */
  .g-node--agent .g-dot { r: 13px; }
  .g-node--agent .g-halo { r: 26px; }
  .g-node--skill .g-dot { r: 9px; }
  .g-node--skill .g-halo { r: 20px; }
  .g-node .g-hit { r: 34px; }
  .g-edge { stroke-width: 1.6; }

  .exec-layout, .term-layout { gap: 24px; }
  .blueprint-frame { padding: clamp(14px, 4vw, 20px); }

  .pix-block { flex-direction: column; align-items: flex-start; }
  .footer-inner { padding: 32px 20px; }
}

@media (max-width: 480px) {
  .hero-ctas { flex-direction: column; align-items: stretch; }
  .hero-ctas .btn { justify-content: center; }

  /* A barra do terminal tem três blocos disputando a largura, e abaixo de 480px eles param de
     caber lado a lado: medido em 2026-09-06, a 390px tanto `pwsh — native-sdd` quanto
     `branch: main` quebravam NO MEIO, cada um em duas linhas desencontradas, e a barra ia de
     42px para 58px de altura parecendo amassada.

     Quebrar entre os blocos em vez de dentro deles: cada rótulo fica inteiro numa linha, e a
     meta desce para a sua. Nada é escondido — `branch` e versão são cenário, mas cenário que
     alguém escreveu de propósito. */
  .term-titlebar { flex-wrap: wrap; justify-content: flex-start; gap: 6px 12px; }
  .term-titlebar-name { white-space: nowrap; }
  .term-titlebar-meta { width: 100%; gap: 14px; }
  .term-titlebar-meta span { white-space: nowrap; }
}

/* =========================================================================
   MICRO-INTERAÇÃO — o movimento entre estados
   =========================================================================
   Antes desta seção a folha tinha 17 seletores :hover/:focus e apenas DUAS
   transições: os estados existiam, o movimento entre eles não. Tudo aqui sai
   dos tokens do :root, então mudar o caráter do site é editar seis linhas lá
   em cima — e sob `prefers-reduced-motion: reduce` os tokens já valem 0ms,
   o que desliga esta seção inteira sem um segundo caminho de código.
   ========================================================================= */

a,
.site-nav a,
.btn,
.btn-ghost,
.btn-quiet,
.foot-links a,
.topo-crumb-back,
.insp-close,
.insp-chip {
  transition:
    color var(--dur-rapido) var(--ease-precisa),
    border-color var(--dur-rapido) var(--ease-precisa),
    background-color var(--dur-rapido) var(--ease-precisa),
    transform var(--dur-instantaneo) var(--ease-precisa);
}

/* O grafo é SVG: as propriedades são `fill`/`stroke`, não `color`/`background`. */
.g-halo, .g-label, .g-dot {
  transition:
    fill var(--dur-rapido) var(--ease-precisa),
    stroke var(--dur-rapido) var(--ease-precisa),
    stroke-width var(--dur-rapido) var(--ease-precisa);
}

/* -------------------------------------------------------------------------
   Press — o botão primário tem um bloco sólido deslocado 4px como sombra
   mecânica (§7 do contrato). Ao ser pressionado ele ANDA até encostar nela:
   o deslocamento que já existe no desenho vira a distância do movimento, em
   vez de inventarmos um efeito novo. Nada de escala, nada de blur.
   ------------------------------------------------------------------------- */
.btn-primary { transform: translate(0, 0); }
.btn-primary:active { transform: translate(4px, 4px); }
.btn-primary:active::before { transform: translate(0, 0); }

.btn-ghost:active,
.btn-quiet:active { transform: translate(1px, 1px); }

.btn-ghost:hover,
.btn-quiet:hover { border-color: var(--ink); color: var(--ink); }

/* -------------------------------------------------------------------------
   Alvos de toque — o §7 exige ≥44×44 e sete controles estavam abaixo disso.
   A correção é sempre a MESMA e é área, não tamanho de letra: o texto fica
   como está, a caixa clicável cresce em volta dele. Onde o alvo é inline
   dentro de uma frase, o padding é compensado com margem negativa para o
   texto não deslocar da linha de base.
   ------------------------------------------------------------------------- */

/* skip-link: errava por 2px de altura, e é o primeiro foco da página. */
.skip-link { min-height: 44px; display: inline-flex; align-items: center; }

/* Marca do header (era 107×18) e do rodapé (era 350×36). */
.brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* Links de documentação do rodapé, empilhados (eram 36×18, 22×18, 115×18).
   O espaçamento entre eles também estava abaixo do confortável para o dedo. */
.foot-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: 2px;
}

/* O link do autor no hero (era 158×16) é inline no meio de uma frase: aqui a
   área cresce sem deslocar o texto, e por isso o padding vertical é compensado
   com margem negativa. */
.hero-author a,
.hero-credit a {
  display: inline-block;
  padding: 13px 4px;
  margin: -13px -4px;
}

/* -------------------------------------------------------------------------
   Rolagem horizontal anunciada — a tabela dos 11 agentes rola 654px no
   mobile e não avisava nem recebia foco: quem navega por teclado não
   alcançava as colunas seguintes. `tabindex` no HTML resolve o alcance; a
   máscara abaixo resolve o aviso, escurecendo a borda de onde ainda há
   conteúdo para o lado.
   ------------------------------------------------------------------------- */
.roster {
  position: relative;
  --borda-fade: 28px;
}
.roster[data-rola="1"]::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--borda-fade);
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--bg));
  transition: opacity var(--dur-rapido) var(--ease-precisa);
}
.roster[data-rola="fim"]::after { opacity: 0; }
.roster:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.roster-dica {
  display: none;
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--muted);
}
.roster[data-rola="1"] .roster-dica,
.roster[data-rola="fim"] .roster-dica { display: block; }

/* Palavra curta continua sendo alvo curto: "Uso" media 25px de largura mesmo com os 44px de
   altura já corrigidos. `min-width` cuida da outra dimensão sem esticar o texto. */
.foot-links a { min-width: 44px; justify-content: flex-start; }

/* O ribbon das 5 fases tem exatamente o problema da tabela de agentes: rola 654px na
   horizontal no mobile sem avisar e sem receber foco. Mesma solução, mesmo desenho —
   por isso a máscara e a dica saíram de `.roster` para uma classe compartilhada. */
.rola-lateral {
  position: relative;
  --borda-fade: 28px;
}
.rola-lateral[data-rola="1"]::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--borda-fade);
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--bg));
  transition: opacity var(--dur-rapido) var(--ease-precisa);
}
.rola-lateral[data-rola="fim"]::after { opacity: 0; }
.rola-lateral:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* A marca do header quebrava em duas linhas entre 820px e 1100px depois da troca da mono:
   Martian Mono é mais larga que JetBrains, e a `.brand` não tinha proteção contra o flex
   comprimi-la (media 74px onde o texto precisa de ~103px). A soma dos três blocos cabia
   folgada no header — quem encolhia era o flex, não a falta de espaço.
   Escopado ao `.site-header` de propósito: `.brand-name` também é a marca do RODAPÉ, e lá o
   texto é a URL do repositório, que com `nowrap` estica a página e devolve o scroll lateral
   (aconteceu no ciclo anterior). */
.site-header .brand { flex-shrink: 0; }
.site-header .brand-name { white-space: nowrap; }

/* -------------------------------------------------------------------------
   Tabela dos agentes em lista, quando o próprio bloco tem menos de 640px.
   Até 2026-09-15 a tabela rolava para o lado abaixo de ~660px de tela, e a coluna que explica
   cada agente (ESCOPO) era justamente a que ficava de fora: a 390px sobravam 55px dela à vista, e
   a dica "arraste" só aparecia ~840px abaixo, depois das onze linhas. Em lista, nome e papel
   dividem uma linha e o escopo vem embaixo; nada rola. O critério é a largura do bloco
   (`@container`), não a da tela. Os `role` do HTML seguram a semântica de tabela que o
   `display: block` tiraria em alguns leitores de tela.
   ------------------------------------------------------------------------- */
@container roster (max-width: 639px) {
  .roster-table { min-width: 0; }
  .roster-table,
  .roster-table tbody,
  .roster-table tr,
  .roster-table td { display: block; }
  .roster-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
  .roster-table tbody tr {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 14px;
    align-items: baseline;
    padding: 16px 0;
    border-bottom: 1px solid rgba(240,243,246,0.05);
  }
  .roster-table tbody tr:last-child { border-bottom: 0; }
  .roster-table tbody td { padding: 0; border-bottom: 0; }
  .roster-scope { grid-column: 1 / -1; margin-top: 6px; }
}

/* O trilho do grafo usa a mesma avaliação do `affordance.js`, mas não a máscara: ele abre rolado
   até o meio, e uma máscara `absolute` dentro de quem rola anda junto com o conteúdo — viraria
   uma faixa escura no meio do desenho. O aviso é a linha abaixo, que só aparece quando há o que
   rolar. */
.topo-graph-host.rola-lateral[data-rola]::after { content: none; }
.topo-graph-dica {
  display: none;
  margin: 10px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--muted);
}
.topo-graph-host[data-rola] ~ .topo-graph-dica { display: block; }
