/* ==========================================================================
 Teseu Cybersecurity — Design System v2
 Direção: "sala de decisão, não sala de guerra" (Discovery §4).
 Navy + paper, azul como único accent de ação, dourado/teal semânticos.
 Mobile-first. Sem framework, sem dependências.
 Documentação: docs/herosite/design-system.md
 ========================================================================== */

/* --------------------------------------------------------------------------
 0. Fontes auto-hospedadas (M1)

 O Google Fonts saiu: a CSP (style-src/font-src 'self') bloqueava o CSS e os
 woff2 remotos, e as páginas caíam na pilha de fallback em
 produção. Arquivos em /assets/fonts, licença OFL em assets/fonts/LICENSE.txt.

 IBM Plex Sans é servida como fonte variável (um único arquivo cobre 100..700),
 então há uma declaração só, com o intervalo de peso — não três cópias iguais.
 -------------------------------------------------------------------------- */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-stretch: 100%;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* --------------------------------------------------------------------------
 1. Tokens globais
 -------------------------------------------------------------------------- */
:root {
  /* Paleta base — Discovery §4.2 */
  --navy-950: #070E1A;
  --navy-900: #0B1626;
  --navy-800: #12213A;
  --navy-700: #1C3050;
  --navy-600: #2A4166;
  --paper: #F6F7F9;
  --paper-2: #EDF0F4;
  --white: #FFFFFF;
  --ink: #0E1726;
  --ink-2: #3D4A5C;
  --mist: #C9D3E0;
  /* Azul: único accent de ação.
   500 = accent gráfico e foco (>=3:1). 600 = preenchimento e link em fundo
   claro (branco sobre ele = 5.83:1). 300 = link em fundo escuro. */
  --blue-500: #2E7BE6;
  --blue-600: #1F62C4;
  --blue-700: #1A5AB8;
  --blue-300: #7FB3FF;
  /* Semânticos: par claro (fundo escuro) e par escuro (fundo claro) */
  --gold-500: #C79A2B;
  /* Ouro do meio (2026-09-04): o fio atravessa superficie clara e escura na
     mesma tela, entao a tinta dourada precisa ler nas duas. 3.44:1 sobre
     --paper e 4.69:1 sobre --navy-900 — acima de 3:1 nos dois lados. */
  --gold-600: #A67C1F;
  --gold-700: #7A5E12;
  --teal-500: #1FA48A;
  --teal-700: #11705E;
  /* M7: quarto accent do portfolio (verticais 04 e 09). Contraste medido:
     5.08:1 sobre o card branco e 3.80:1 sobre --navy-950 — acima de 3:1 em
     ambos, o piso da WCAG 1.4.11 para elemento grafico (a faixa e decorativa;
     nenhum texto e escrito nesta cor). */
  --purple-500: #6E5BD6;
  --purple-700: #4A3AA8;
  --red-300: #F08A82;
  --red-700: #B3352F;
  /* Tipografia */
  --font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
  --fs-xs: 0.875rem; /* 14 */
  --fs-sm: 1rem; /* 16 */
  --fs-base: 1.0625rem; /* 17 */
  --fs-md: 1.25rem; /* 20 */
  --fs-lg: 1.5rem; /* 24 */
  --fs-h1: clamp(2.25rem, 1.45rem + 3.4vw, 3.5rem);
  /* So o H1 da Home. E a unica frase que o visitante le antes de decidir se
     continua: sobe um degrau alem do H1 padrao (36->68px no lugar de 36->56). */
  /* 2026-09-05 (item 3): o H1 passou de 9 para 24 palavras. A 68px a frase
     virava um bloco de texto, nao um titulo. A escala cai para 30-42px e o
     peso permanece: o que carrega a hierarquia agora e o peso e a medida. */
  --fs-hero: clamp(1.875rem, 1rem + 2.6vw, 2.625rem);
  --fs-h2: clamp(1.75rem, 1.3rem + 1.9vw, 2.5rem);
  --fs-h3: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
  --fs-lede: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);
  --lh-tight: 1.15;
  --lh-heading: 1.25;
  --lh-body: 1.6;
  --track-tight: -0.012em;
  --track-mono: 0.08em;
  --measure: 65ch;
  /* Espaçamento 4 / 8 / 16 / 24 / 32 / 48 / 64 / 96 */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 1rem;
  --sp-4: 1.5rem;
  --sp-5: 2rem;
  --sp-6: 3rem;
  /* 2026-09-05 (item 12, "tom minimalista"): o respiro subiu um degrau.
     Tirar ornamento sem dar espaco no lugar nao deixa a pagina minimalista,
     deixa vazia. O espaco passa a ser o separador que as bordas eram. */
  --section-py: clamp(4.25rem, 8.5vw, 7.5rem);
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --container: 74rem;
  /* 1184px */
  /* Raio e elevação (mínima — separação por borda, não por sombra) */
  --r-sm: 6px;
  --r-md: 8px;
  --shadow-nav: 0 1px 0 rgba(7, 14, 26, 0.5), 0 6px 20px -12px rgba(7, 14, 26, 0.9);
  /* Motion — 150–200ms, apenas transform/opacity/cor */
  --dur: 170ms;
  --ease: cubic-bezier(0.2, 0.6, 0.3, 1);
  /* Movimento com propósito (2026-09-04): entrada = ease-out, com direção. */
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --dur-step: 200ms;
  --dur-slow: 280ms;
  --dur-draw: 900ms;
  /* Fio — a gramatica unica dos diagramas (2026-09-04, secao 27).
     Uma espessura de traco, tres raios de no e um comprimento normalizado
     (pathLength="100") valem para o fio da calha, o funil do hero, o anel do
     CTEM, os caminhos do problema e a linha do Modelo Integrado. Trocar um
     valor aqui muda os cinco desenhos juntos — e essa e a intencao. */
  --thread-w: 1.5;
  /* O trilho do fio atravessa superficie clara e escura na mesma tela, entao
     nao pode consumir --sf-thread (que muda por secao): e o unico neutro fixo
     do sistema, calibrado para ficar discreto nos dois fundos. */
  /* Item 12 (05/09): o fio permanece — e navegacao e identidade, nao enfeite —
     mas o trilho apagado recua de 45% para 28%. Ele guia quem procura, sem
     competir com o texto de quem so esta lendo. */
  --fio-track: rgba(126, 142, 168, 0.28);
  --fio-knot-track: rgba(126, 142, 168, 0.85);
  --knot-sm: 0.5rem;
  --knot-md: 1.75rem;
  --knot-lg: 2.75rem;
  --nav-h: 4.25rem;
  --z-nav: 100;
  --z-menu: 200;
  color-scheme: light dark;
}

/* --------------------------------------------------------------------------
 2. Reset e base
 -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }
* { margin: 0; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1rem);
}
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100%;
}
:root[data-theme="dark"] body {
  background: var(--navy-900);
  color: var(--white);
}
img,
svg,
video {
  display: block;
  max-width: 100%;
}
img { height: auto; }
h1,
h2,
h3,
h4 {
  font-weight: 600;
  line-height: var(--lh-heading);
  letter-spacing: var(--track-tight);
  text-wrap: balance;
  overflow-wrap: break-word;
}
h1 {
  font-size: var(--fs-h1);
  line-height: var(--lh-tight);
  font-weight: 700;
}
h2 {
  font-size: var(--fs-h2);
  font-weight: 700;
}
h3 { font-size: var(--fs-h3); }
h4 { font-size: var(--fs-md); }
p,
li,
dd { overflow-wrap: break-word; }
p { max-width: var(--measure); }
ul,
ol {
  padding: 0;
  list-style: none;
}
a {
  color: var(--sf-link, var(--blue-600));
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}
a:hover { text-decoration-color: currentColor; }
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
button {
  background: none;
  border: 0;
  cursor: pointer;
}
strong,
b { font-weight: 600; }
:focus-visible {
  outline: 2px solid var(--blue-500);
  outline-offset: 3px;
  border-radius: 2px;
}
[data-surface="dark"] :focus-visible { outline-color: var(--blue-300); }
::selection {
  background: var(--blue-500);
  color: var(--white);
}

/* --------------------------------------------------------------------------
 3. Superfícies — tema por seção (Discovery §4.1)
 Cada seção declara data-surface e expõe tokens contextuais (--sf-*).
 Todo componente usa apenas --sf-*, por isso funciona em qualquer superfície.
 -------------------------------------------------------------------------- */
[data-surface] {
  background: var(--sf-bg);
  color: var(--sf-fg);
}
[data-surface="dark"] {
  --sf-bg: var(--navy-900);
  --sf-fg: var(--paper);
  --sf-fg-2: var(--mist);
  --sf-line: var(--navy-700);
  --sf-line-strong: var(--navy-600);
  --sf-card: var(--navy-800);
  --sf-card-line: #22375C;
  --sf-link: var(--blue-300);
  --sf-eyebrow: var(--blue-300);
  --sf-gold: var(--gold-500);
  --sf-teal: var(--teal-500);
  --sf-purple: var(--purple-500);
  --sf-red: var(--red-300);
  --sf-field-bg: #0E1B2E;
  --sf-field-line: #5A6E90;
  --sf-btn-hover: #2A6ACF;
  --sf-ghost-line: var(--navy-600);
  --sf-ghost-hover: #16294A;
  /* Fio: traco apagado (o caminho ainda nao percorrido) e traco aceso. */
  --sf-thread: #2A4468;
  --sf-thread-ink: var(--blue-500);
}
[data-surface="dark"][data-tone="deep"] { --sf-bg: var(--navy-950); }
[data-surface="paper"],
[data-surface="paper-2"] {
  --sf-fg: var(--ink);
  --sf-fg-2: var(--ink-2);
  --sf-line: #DDE3EB;
  --sf-line-strong: #C4CDDA;
  --sf-card: var(--white);
  --sf-card-line: #E2E7EE;
  --sf-link: var(--blue-600);
  --sf-eyebrow: var(--blue-600);
  --sf-gold: var(--gold-700);
  --sf-teal: var(--teal-700);
  --sf-purple: var(--purple-700);
  --sf-red: var(--red-700);
  --sf-field-bg: var(--white);
  --sf-field-line: #7E8A9B;
  --sf-btn-hover: var(--blue-700);
  --sf-ghost-line: #C4CDDA;
  --sf-ghost-hover: #E4E9F0;
  --sf-thread: #C4CDDA;
  --sf-thread-ink: var(--blue-500);
}
[data-surface="paper"] { --sf-bg: var(--paper); }
[data-surface="paper-2"] { --sf-bg: var(--paper-2); }
/* Toggle de tema: as seções "paper" viram navy suave (dark total). */
:root[data-theme="dark"] [data-surface="paper"],
:root[data-theme="dark"] [data-surface="paper-2"] {
  --sf-fg: var(--paper);
  --sf-fg-2: var(--mist);
  --sf-line: var(--navy-700);
  --sf-line-strong: var(--navy-600);
  --sf-card: var(--navy-800);
  --sf-card-line: #22375C;
  --sf-link: var(--blue-300);
  --sf-eyebrow: var(--blue-300);
  --sf-gold: var(--gold-500);
  --sf-teal: var(--teal-500);
  --sf-red: var(--red-300);
  --sf-field-bg: #0E1B2E;
  --sf-field-line: #5A6E90;
  --sf-btn-hover: #2A6ACF;
  --sf-ghost-line: var(--navy-600);
  --sf-ghost-hover: #16294A;
  --sf-thread: #2A4468;
  --sf-thread-ink: var(--blue-500);
}
:root[data-theme="dark"] [data-surface="paper"] { --sf-bg: var(--navy-900); }
:root[data-theme="dark"] [data-surface="paper-2"] { --sf-bg: #0D1A2C; }

/* --------------------------------------------------------------------------
 4. Layout
 -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
/* QA DEF-09 (residual): a navbar sticky e o rodape encostam nas bordas em
   telas com notch/ilha. `viewport-fit=cover` ja esta na meta viewport, entao
   env() resolve de verdade; max() garante que o gutter normal nunca diminua. */
.navbar .container,
.footer .container {
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
}
.section {
  padding-block: var(--section-py);
  position: relative;
}
.section--tight { padding-block: clamp(2.25rem, 4vw, 3rem); }
.section-header {
  max-width: 46rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.section-header--wide { max-width: 60rem; }
/* Eyebrow / rótulo mono */
.section-label {
  display: block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-eyebrow, var(--blue-600));
  margin-bottom: var(--sp-3);
}
.section-title {
  font-size: var(--fs-h2);
  font-weight: 700;
  color: var(--sf-fg, var(--ink));
}
.section-description {
  margin-top: var(--sp-3);
  font-size: var(--fs-lede);
  color: var(--sf-fg-2, var(--ink-2));
  max-width: var(--measure);
}
.lede {
  font-size: var(--fs-lede);
  color: var(--sf-fg-2, var(--ink-2));
  max-width: var(--measure);
}
.stack>*+* { margin-top: var(--sp-3); }

/* --------------------------------------------------------------------------
 5. Skip link
 -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  top: 0;
  left: var(--sp-3);
  z-index: 999;
  transform: translateY(-150%);
  background: var(--blue-600);
  color: var(--white);
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  font-weight: 600;
  text-decoration: none;
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* --------------------------------------------------------------------------
 6. Botões
 -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 2.75rem;
  /* 44px */
  padding: 0.625rem 1.25rem;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    color var(--dur) var(--ease);
}
.btn svg {
  width: 1.125em;
  height: 1.125em;
  flex: none;
}
.btn-primary {
  background: var(--blue-600);
  color: var(--white);
  border-color: var(--blue-600);
}
.btn-primary:hover {
  background: var(--sf-btn-hover, var(--blue-700));
  border-color: var(--sf-btn-hover, var(--blue-700));
  color: var(--white);
}
.btn-secondary {
  background: transparent;
  color: var(--sf-fg, var(--ink));
  border-color: var(--sf-ghost-line, #C4CDDA);
}
.btn-secondary:hover {
  background: var(--sf-ghost-hover, #E4E9F0);
  border-color: var(--sf-line-strong);
}
.btn-lg {
  min-height: 3rem;
  padding: 0.8125rem 1.625rem;
  font-size: var(--fs-base);
}
.btn-block {
  display: flex;
  width: 100%;
}
.btn[aria-disabled="true"],
.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
/* Link com seta — ação terciária */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  min-height: 2.75rem;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--sf-link);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.link-arrow svg {
  width: 1rem;
  height: 1rem;
  flex: none;
  transition: transform var(--dur) var(--ease);
}
.link-arrow:hover { text-decoration: underline; }
.link-arrow:hover svg { transform: translateX(3px); }

/* --------------------------------------------------------------------------
 7. Navbar
 -------------------------------------------------------------------------- */
.navbar {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: var(--navy-950);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.navbar.is-scrolled {
  border-bottom-color: var(--navy-700);
  box-shadow: var(--shadow-nav);
}
.navbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--nav-h);
}
.navbar-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  /* QA DEF-08: o SVG do logo tem 28px de altura; o alvo clicavel precisa de 44. */
  min-height: 2.75rem;
  color: var(--paper);
  text-decoration: none;
  flex: none;
}
/* 2026-09-05: o wordmark vetorial deu lugar ao logotipo oficial (escudo +
   TESEU), fornecido pelo cliente e recortado com fundo transparente. E imagem
   e nao SVG, entao nao herda currentColor: a marca tem cor propria em qualquer
   tema, que e o comportamento correto para um logotipo. */
.navbar-logo {
  width: auto;
  height: 2.125rem;
}
.navbar-menu {
  display: none;
  align-items: center;
  gap: 0.125rem;
  margin-left: auto;
}
.navbar-link {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0.375rem 0.6875rem;
  border-radius: var(--r-sm);
  color: var(--mist);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.navbar-link:hover,
.navbar-link[aria-current="page"] {
  color: var(--paper);
  background: rgba(127, 179, 255, 0.1);
}
.navbar-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
}
.navbar-cta { display: none; }
.theme-toggle,
.navbar-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--navy-700);
  color: var(--mist);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.theme-toggle:hover,
.navbar-toggle:hover {
  color: var(--paper);
  border-color: var(--navy-600);
}
.theme-toggle svg,
.navbar-toggle svg {
  width: 1.125rem;
  height: 1.125rem;
}
.icon-sun { display: none; }
.icon-moon { display: block; }
:root[data-theme="dark"] .icon-sun { display: block; }
:root[data-theme="dark"] .icon-moon { display: none; }
@media (min-width: 62rem) {
  .navbar-menu { display: flex; }
  .navbar-cta { display: inline-flex; }
  .navbar-toggle { display: none; }
}
/* Menu mobile full-screen */
/* Fechado por padrão. Abre por classe (funciona com o markup novo e com os
   templates legados do SSG, que não usam o atributo hidden). */
.mobile-menu {
  display: none;
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  background: var(--navy-950);
  color: var(--paper);
  flex-direction: column;
  padding: calc(env(safe-area-inset-top, 0px) + var(--sp-3)) calc(env(safe-area-inset-right, 0px) + var(--gutter)) calc(env(safe-area-inset-bottom, 0px) + var(--sp-5)) calc(env(safe-area-inset-left, 0px) + var(--gutter));
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mobile-menu.is-open { display: flex; }
.mobile-menu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--nav-h);
  margin-bottom: var(--sp-4);
}
.mobile-menu-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--navy-700);
  color: var(--mist);
}
.mobile-menu-close svg {
  width: 1.25rem;
  height: 1.25rem;
}
.mobile-menu-nav {
  display: flex;
  flex-direction: column;
}
.mobile-menu-link {
  display: flex;
  align-items: center;
  min-height: 3.25rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--navy-700);
  color: var(--paper);
  font-size: var(--fs-md);
  font-weight: 600;
  text-decoration: none;
}
.mobile-menu-link:hover { color: var(--blue-300); }
.mobile-menu-foot {
  margin-top: var(--sp-5);
  display: grid;
  gap: var(--sp-3);
}
.mobile-menu-foot .btn { width: 100%; }
.mobile-menu-contact {
  color: var(--mist);
  font-size: var(--fs-sm);
}
.mobile-menu-contact a { color: var(--blue-300); }
body.is-locked { overflow: hidden; }

/* --------------------------------------------------------------------------
 8. Hero
 -------------------------------------------------------------------------- */
.hero { padding-block: clamp(4rem, 9vw, 7rem) 0; }
/* Item 5 (Joao, 05/09): o diagrama "Exposicao -> Decisao" saiu, e com ele a
   grade de duas colunas (.hero-inner) que so existia para acomoda-lo. O hero e
   coluna unica: uma coluna de texto que se le de cima a baixo, sem desvio. */
.hero-content { max-width: 48rem; }
/* R3-M7: `brand.coverTitle` do PDF (p.1) abre o hero como kicker. Ele nomeia a
   promessa ("O Seguro do Seu Negócio") antes do H1 dizer como ela se cumpre. */
/* O kicker e onde o fio comeca: um filete curto a esquerda marca a origem do
   traco que atravessa a pagina. Nao e ornamento — e a primeira ocorrencia da
   mesma linha que reaparece no funil, no anel e na calha. */
.hero-kicker {
  position: relative;
  padding-left: var(--sp-3);
  font-size: var(--fs-lede);
  font-weight: 600;
  line-height: var(--lh-tight);
  color: var(--sf-fg);
  margin-bottom: var(--sp-3);
  max-width: var(--measure);
}
.hero-kicker::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15em;
  bottom: 0.15em;
  width: calc(var(--thread-w) * 1px);
  background: var(--sf-thread-ink);
}
.hero-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--blue-300);
  margin-bottom: var(--sp-4);
}
/* Titulo longo (24 palavras): a medida e o que impede a frase de virar
   paragrafo. ~26ch mantem 5 a 6 linhas curtas e legiveis, com o mesmo peso de
   antes; `balance` iguala os comprimentos para nao sobrar uma linha orfa.
   A quebra manual (.hero-title-tail) saiu junto com o H1 antigo: forcar uma
   quebra numa frase desta extensao quebraria em telas onde nao devia. */
.hero-title {
  font-size: var(--fs-hero);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.018em;
  /* `balance` iguala o comprimento das linhas — otimo para um titulo de 2 a 4
     linhas, mas num de 5 ele encurta todas e o bloco encolhe para bem menos que
     a medida disponivel. `pretty` preenche a medida e ainda evita a linha orfa,
     que e o que este titulo precisa. */
  text-wrap: pretty;
  /* CRITIQUE 05/09: a 26ch o título quebrava em 6 linhas curtas e a metade
     direita do hero ficava vazia — sem o diagrama, o vazio lia como "faltou
     a imagem". A 36ch a própria frase preenche a composição em 4 linhas e o
     hero volta a ser uma peça tipográfica, que é o que sobrou dele. */
  max-width: 38ch;
}
/* Um degrau abaixo do que era: com o H1 maior, o apoio precisa recuar para o
   contraste de escala existir. */
.hero-subtitle {
  margin-top: var(--sp-4);
  font-size: var(--fs-base);
  color: var(--sf-fg-2);
  max-width: 48ch;
}
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}
/* Faixa de objetivo — segunda linha do hero, largura total.
   Item 12: o filete que separava daqui saiu. O espaco ja separa, e uma linha
   por cima dele era o divisor redundante que o pedido mandou cortar. */
.hero-objective {
  margin-top: clamp(3.5rem, 7vw, 5.5rem);
  padding: 0 0 var(--section-py);
}
.hero-objective p {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--sf-fg);
  max-width: 58rem;
}
/* R3-M7: `brand.tagline_en` (PDF p.1) fecha o bloco do objetivo em ingles.
   Discreta de proposito — e a versao internacional da mesma frase, nao um
   segundo argumento. `lang="en"` para o leitor de tela nao ler com fonemas
   portugueses. */
.hero-objective .hero-tagline {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: 400;
  font-style: italic;
  color: var(--sf-fg-2);
  max-width: 58rem;
}
/* --------------------------------------------------------------------------
 8.1 Clientes — seção fora do fluxo (item 7, 2026-09-05)
 A faixa deixou de abrir a página e passou a ser um destino do menu. Sem JS
 nenhum: `display:none` esconde, `:target` devolve. Consequências que isso
 resolve de graça — o link /#clientes é compartilhável, o botão voltar do
 navegador fecha a seção, e com o JavaScript desligado o comportamento é
 exatamente o mesmo.
 -------------------------------------------------------------------------- */
#clientes { display: none; }
#clientes:target { display: block; }
/* O foco chega aqui pelo próprio navegador (tabindex="-1" na seção). É o mesmo
   padrão do skip link para #main-content: um contêiner que recebe o foco como
   destino de salto não pinta anel — a chegada é comunicada pelo título no topo
   da viewport e pela URL. CRITIQUE 05/09: a primeira versão desenhava um anel
   em volta do <h2> e parecia defeito de renderização, não indicação de foco. */
#clientes:focus { outline: none; }
.clients-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}
.clients-close {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2);
  text-decoration: none;
  padding: var(--sp-2) 0;
}
.clients-close:hover { color: var(--sf-link); text-decoration: underline; }

/* --------------------------------------------------------------------------
 9. Faixa de logos (clientes / experiência)
 -------------------------------------------------------------------------- */
.logo-strip {
  display: grid;
  gap: var(--sp-4);
  align-items: center;
}
.logo-strip-label {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2);
  flex: none;
}
.logo-strip-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
  gap: 0.5rem;
  align-items: stretch;
}
.logo-strip--sm .logo-strip-list { grid-template-columns: repeat(auto-fill, minmax(4.75rem, 1fr)); }
/* Os logotipos de origem vêm sobre branco (JPG/PNG). Uma placa clara fixa
 garante leitura em superfície clara e escura, sem inverter marcas. */
.logo-strip-item {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3.25rem;
  padding: 0.5rem 0.625rem;
  background: #E9EDF2;
  border-radius: var(--r-sm);
}
.logo-strip-item img {
  height: 1.75rem;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.92;
  mix-blend-mode: multiply;
}
.logo-strip--sm .logo-strip-item {
  min-height: 2.75rem;
  padding: 0.375rem 0.5rem;
}
.logo-strip--sm .logo-strip-item img { height: 1.375rem; }
/* CRITIQUE 05/09: a regra `grid-template-columns: auto 1fr` existia para pôr o
   rótulo à esquerda e a lista à direita. Com o rótulo "6 meses" removido (item
   7), a faixa de clientes ficou com um filho só — que caía na coluna `auto` e
   colapsava para a largura de UM logotipo, empilhando os nove na vertical. A
   única faixa que ainda tem rótulo é a de experiência (.logo-strip--sm), e essa
   já pedia coluna única. A regra morreu junto com o rótulo. */
@media (min-width: 48rem) {
  .logo-strip { gap: clamp(1.5rem, 4vw, 3rem); }
  .logo-strip--sm { gap: var(--sp-3); }
}

/* --------------------------------------------------------------------------
 10. Diferenciais (a grade de impactos virou os caminhos da secao 27.2)
 -------------------------------------------------------------------------- */

/* Diferenciais: seis frases curtas do PDF. Sem cartao nem sombra — so um filete
   a esquerda — porque a secao vizinha (portfolio) ja e uma grade de cartoes e
   duas superficies iguais seguidas achatam a leitura. */
.diff-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: var(--sp-4) var(--sp-6);
}
.diff-item {
  display: flex;
  gap: var(--sp-3);
  padding-left: var(--sp-3);
  border-left: 2px solid var(--sf-line-strong);
}
.diff-num {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: var(--track-mono);
  color: var(--sf-link);
  flex: none;
  padding-top: 0.15rem;
}
.diff-label {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.35;
  color: var(--sf-fg);
}
.diff-text {
  margin-top: 0.375rem;
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--sf-fg-2);
}

/* --------------------------------------------------------------------------
 11. Stepper CTEM (#ctem)
 -------------------------------------------------------------------------- */
.stepper { margin-top: clamp(1.5rem, 3vw, 2.5rem); }
/* Anel orbital (#ctem). O texto diz que o ciclo se retroalimenta; a fileira
   de abas dizia o contrário. O traçado virou o argumento: anel fechado, seta
   no arco de retorno, pulso que não para. Os 5 nós continuam `role=tab`
   reais — botões HTML sobre um SVG decorativo (`aria-hidden`). */
.ctem-ring {
  position: relative;
  width: min(100%, 30rem);
  margin: clamp(1.5rem, 4vw, 2.5rem) auto 0;
}
.ctem-orbit { display: none; }
.orbit-track,
.orbit-draw,
.orbit-pulse {
  fill: none;
  stroke-linecap: round;
}
.orbit-track {
  stroke: var(--sf-thread);
  stroke-width: var(--thread-w);
  vector-effect: non-scaling-stroke;
}
/* Desenha uma vez ao entrar na viewport. Sem JS (sem .reveal-ready) o anel
   já nasce inteiro: o movimento é acréscimo, nunca pré-requisito. */
.orbit-draw {
  stroke: var(--sf-thread-ink);
  stroke-width: calc(var(--thread-w) + 0.5);
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--dur-draw) var(--ease-out);
}
.reveal-ready .ctem-ring:not(.is-visible) .orbit-draw { stroke-dashoffset: 100; }
/* Único loop infinito do site: diz "isto não para", que é o que o método
   afirma em texto e o desenho antigo não dizia. */
.orbit-pulse {
  stroke: var(--blue-300);
  stroke-width: calc(var(--thread-w) * 2.5);
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 9 91;
  animation: orbit-pulse 8s linear infinite;
  animation-delay: var(--dur-draw);
}
.reveal-ready .ctem-ring:not(.is-visible) .orbit-pulse { animation-play-state: paused; }
@keyframes orbit-pulse {
  from { stroke-dashoffset: 0; }
  to { stroke-dashoffset: -100; }
}

/* --- Abaixo de 40rem o anel não cabe com legibilidade: vira lista numerada
       vertical, com o mesmo tablist e o mesmo comportamento. --- */
.ctem-ring-nodes {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.ring-node {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 2.75rem;
  padding: var(--sp-2) var(--sp-3);
  background: transparent;
  border: 1px solid var(--sf-line);
  border-left: 3px solid var(--sf-line-strong);
  border-radius: var(--r-sm);
  color: var(--sf-fg-2);
  text-align: left;
  transition: color var(--dur-step) var(--ease), background-color var(--dur-step) var(--ease),
    border-color var(--dur-step) var(--ease);
}
.ring-node:hover { color: var(--sf-fg); }
.ring-node[aria-selected="true"] .ring-node-name { color: var(--sf-fg); }
.ring-node[aria-selected="true"] {
  color: var(--sf-fg);
  background: var(--sf-card);
  border-color: var(--sf-card-line);
  border-left-color: var(--blue-500);
}
.ring-node-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  /* O no do anel e um controle: a borda continua em --sf-line-strong (>=3:1
     com a superficie), nao no fio apagado. Gramatica compartilhada nao pode
     custar contraste de UI. */
  border: calc(var(--thread-w) * 1px) solid var(--sf-line-strong);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: var(--track-mono);
  transition: transform var(--dur-step) var(--ease), border-color var(--dur-step) var(--ease),
    box-shadow var(--dur-step) var(--ease), color var(--dur-step) var(--ease);
}
.ring-node[aria-selected="true"] .ring-node-dot {
  border-color: var(--blue-600);
  background: var(--blue-600);
  color: var(--white);
  box-shadow: 0 0 0 5px rgba(46, 123, 230, 0.18);
}
.ring-node:hover .ring-node-dot { border-color: var(--blue-500); }
.ring-node-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.25;
}

/* Centro do anel: a etapa ativa por extenso. É eco visual do tabpanel (que
   guarda a mesma informação para leitores de tela), por isso aria-hidden. */
.ctem-ring-center {
  margin-top: var(--sp-4);
  padding-left: var(--sp-3);
  border-left: 3px solid var(--blue-500);
}
.ring-center-num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: var(--track-mono);
  color: var(--sf-link);
}
.ring-center-name {
  margin-top: 0.125rem;
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: var(--lh-tight);
  color: var(--sf-fg);
}
.ring-center-desc {
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2);
}
.ctem-ring-center[data-swap="out"] .ring-center-num,
.ctem-ring-center[data-swap="out"] .ring-center-name,
.ctem-ring-center[data-swap="out"] .ring-center-desc { opacity: 0; }
.ring-center-num,
.ring-center-name,
.ring-center-desc { transition: opacity var(--dur-step) var(--ease); }

/* Com o centro ativo (só com JS), nome e descrição saem da tela no painel,
   mas ficam no DOM: é ali que o leitor de tela acha o conteúdo do tabpanel.
   Sem JS o painel volta a mostrá-los. */
.stepper[data-center="on"] .stepper-panel > h3,
.stepper[data-center="on"] .stepper-panel > .stepper-panel-desc {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.stepper[data-center="on"] .stepper-panel-grid {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* Legenda do anel: alinhada à esquerda como o resto da seção — só o
   diagrama fica centrado. */
.ctem-ring-note { max-width: 44rem; }

@media (min-width: 40rem) {
  .ctem-ring { aspect-ratio: 1; }
  .ctem-orbit {
    display: block;
    width: 100%;
    height: 100%;
  }
  .ctem-ring-nodes { display: block; }
  .ring-node {
    position: absolute;
    flex-direction: column;
    gap: 0.4375rem;
    width: 6.5rem;
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    text-align: center;
    /* o centro do disco cai exatamente sobre a circunferência */
    transform: translate(-50%, -1.375rem);
  }
  .ring-node:nth-child(1) { left: 50%; top: 13%; }
  .ring-node:nth-child(2) { left: 85.19%; top: 38.57%; }
  .ring-node:nth-child(3) { left: 71.75%; top: 79.93%; }
  .ring-node:nth-child(4) { left: 28.25%; top: 79.93%; }
  .ring-node:nth-child(5) { left: 14.81%; top: 38.57%; }
  .ring-node[aria-selected="true"] { background: none; }
  /* Nos nós laterais o arco passa exatamente na altura do rótulo. O knockout
     na cor da superfície faz o traço passar POR TRÁS do texto, como num
     diagrama técnico — nos outros nós ele é invisível. */
  .ring-node-name {
    align-self: center;
    padding: 0 0.3125rem;
    background: var(--sf-bg);
  }
  .ring-node-dot {
    width: var(--knot-lg);
    height: var(--knot-lg);
    font-size: 0.8125rem;
    background: var(--sf-bg);
  }
  .ring-node[aria-selected="true"] .ring-node-dot { background: var(--blue-600); }
  .ring-node[aria-selected="true"] .ring-node-dot { transform: scale(1.16); }
  .ctem-ring-center {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 14rem;
    transform: translate(-50%, -50%);
    margin: 0;
    padding: 0;
    border: 0;
    text-align: center;
  }
  .ring-center-desc { margin-top: var(--sp-2); }
}
@media (min-width: 62rem) {
  .ctem-ring { width: min(100%, 33rem); }
  .ctem-ring-center { width: 15.5rem; }
}
/* A partir de 75rem o anel encosta no texto que ilustra, como no hero:
   argumento à esquerda, desenho à direita. Abaixo disso ele fica centrado,
   porque a coluna de texto já usa a largura toda. */
@media (min-width: 75rem) {
  #ctem .container {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 31rem;
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
    align-content: start;
  }
  #ctem .section-header {
    grid-column: 1;
    grid-row: 1;
    align-self: end;
    margin-bottom: 0;
  }
  #ctem .stepper { display: contents; }
  #ctem .ctem-ring {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    width: 31rem;
    margin: 0;
  }
  #ctem .ctem-ring-note {
    grid-column: 1;
    grid-row: 2;
    align-self: start;
    max-width: 34rem;
    margin: var(--sp-5) 0 0;
  }
  #ctem .stepper-panel {
    grid-column: 1 / -1;
    grid-row: 3;
    margin-top: clamp(2rem, 4vw, 3rem);
  }
  #ctem .ctem-foot {
    grid-column: 1 / -1;
    grid-row: 4;
  }
  #ctem .ctem-ring-center { width: 15rem; }
}


.stepper-panel {
  margin-top: var(--sp-4);
  padding: clamp(1.25rem, 3vw, 2rem);
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-left: 3px solid var(--blue-500);
  border-radius: var(--r-md);
}
.stepper-panel h3 { font-size: var(--fs-h3); }
.stepper-panel-desc {
  margin-top: var(--sp-2);
  font-size: var(--fs-md);
  color: var(--sf-fg);
  max-width: var(--measure);
}
.stepper-panel-grid {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--sf-line);
}
.field-label {
  display: block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2);
  margin-bottom: var(--sp-2);
}
.stage-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
@media (min-width: 48rem) {
  .stepper-panel-grid {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 3rem);
  }
}
.method-note {
  margin-top: var(--sp-4);
  padding-left: var(--sp-3);
  border-left: 3px solid var(--sf-gold);
  color: var(--sf-fg-2);
  font-size: var(--fs-sm);
}
.ctem-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--sf-line);
}
.ctem-foot p {
  max-width: 46rem;
  color: var(--sf-fg-2);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
 12. Chips e tags
 -------------------------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.5625rem;
  border: 1px solid var(--sf-line-strong);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sf-fg-2);
  white-space: nowrap;
}
.chip::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.chip[data-stage="escopo"],
.chip[data-stage="priorizacao"] {
  color: var(--sf-link);
  border-color: currentColor;
}
.chip[data-stage="descoberta"],
.chip[data-stage="validacao"] {
  color: var(--sf-gold);
  border-color: currentColor;
}
.chip[data-stage="mobilizacao"] {
  color: var(--sf-teal);
  border-color: currentColor;
}
.chip-link {
  font-family: var(--font-sans);
  text-decoration: none;
  transition: background-color var(--dur) var(--ease);
  min-height: 1.875rem;
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 0.75rem;
  color: var(--sf-link);
  border-color: var(--sf-line-strong);
}
.chip-link::before { display: none; }
.chip-link:hover {
  background: var(--sf-ghost-hover);
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
 13. Governança + Modelo Integrado (#governanca)
 -------------------------------------------------------------------------- */
.gov-layout {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}
@media (min-width: 62rem) {
  .gov-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
}
.gov-bridge {
  margin-bottom: clamp(2rem, 4vw, 3rem);
  padding-left: var(--sp-4);
  border-left: 3px solid var(--blue-500);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--sf-fg);
  max-width: 44rem;
}
.def-list {
  display: grid;
  gap: var(--sp-4);
}
.def-block {
  padding-left: var(--sp-4);
  border-left: 3px solid var(--sf-line-strong);
}
.def-block[data-kind="problema"] { border-left-color: var(--sf-red); }
.def-block[data-kind="servico"] { border-left-color: var(--blue-500); }
.def-block[data-kind="resultado"] { border-left-color: var(--sf-teal); }
.def-block dt {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2);
  margin-bottom: var(--sp-2);
}
.def-block dd {
  margin: 0;
  color: var(--sf-fg);
  max-width: var(--measure);
}
/* Modelo Integrado */
.model {
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-radius: var(--r-md);
  padding: clamp(1.25rem, 3vw, 1.75rem);
}
.model-title { font-size: var(--fs-h3); }
.model-sub {
  margin-top: var(--sp-2);
  color: var(--sf-fg-2);
  font-size: var(--fs-sm);
}
.model-flow {
  display: grid;
  gap: 0;
  margin-top: var(--sp-4);
  counter-reset: model;
}
.model-step {
  position: relative;
  display: grid;
  grid-template-columns: var(--knot-md) minmax(0, 1fr);
  gap: var(--sp-3);
  padding-bottom: var(--sp-4);
}
.model-step:last-child { padding-bottom: 0; }
.model-step::before {
  content: "";
  position: absolute;
  left: calc(var(--knot-md) / 2 - var(--thread-w) * 0.5px);
  top: var(--knot-md);
  bottom: 0.25rem;
  width: calc(var(--thread-w) * 1px);
  background: var(--sf-thread);
}
.model-step:last-child::before { display: none; }
.model-node {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--knot-md);
  height: var(--knot-md);
  border-radius: 50%;
  border: calc(var(--thread-w) * 1px) solid var(--sf-thread);
  background: var(--sf-card);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--sf-fg-2);
}
.model-step:nth-child(3) .model-node {
  border-color: var(--sf-gold);
  color: var(--sf-gold);
}
.model-step p {
  margin-top: 0.25rem;
  font-size: var(--fs-sm);
  color: var(--sf-fg-2);
}
.model-metric {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--sf-line);
  font-size: var(--fs-sm);
  color: var(--sf-fg);
  max-width: var(--measure);
}
.model-metric .field-label { color: var(--sf-gold); }

/* --------------------------------------------------------------------------
 14. Portfólio (#portfolio)
 -------------------------------------------------------------------------- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
}
.filter-btn {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.5rem 0.9375rem;
  border: 1px solid var(--sf-line-strong);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--sf-fg-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease), transform 90ms var(--ease);
}
.filter-btn:hover {
  color: var(--sf-fg);
  background: var(--sf-card);
}
.filter-btn[aria-pressed="true"] {
  background: var(--sf-fg);
  border-color: var(--sf-fg);
  color: var(--sf-bg);
}
.portfolio-grid {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: 1fr;
}
/* R3-M2: UMA fonte de cor por card — `accent` de data/portfolio.json,
   emitido como data-accent tanto na Home quanto nos cards gerados pelo build.
   As regras por etapa do CTEM sairam: a mesma vertical aparecia azul na Home e
   dourada na pagina de servico, e o card destaque combinava numero dourado com
   faixa azul. O accent vira uma variavel para que faixa e numero nunca possam
   divergir. */
.pillar-card {
  --accent: var(--sf-line-strong);
  display: flex;
  flex-direction: column;
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-md);
  padding: var(--sp-4);
  transition: border-color var(--dur) var(--ease);
}
.pillar-card:hover { border-color: var(--sf-line-strong); }
/* --accent pinta a borda de 3px (contraste de UI, minimo 3:1) e --accent-text
   pinta o numero do card em destaque (texto, minimo 4.5:1). Sao separados
   porque --blue-500 sobre o card branco da 4.12:1: passa como borda e reprova
   como texto. As variantes --sf-* ja mudam por superficie, entao o numero
   escurece no card claro e clareia no escuro sem regra extra. */
.pillar-card[data-accent="blue"] { --accent: var(--blue-500); --accent-text: var(--sf-link); }
.pillar-card[data-accent="gold"] { --accent: var(--sf-gold, var(--gold-500)); --accent-text: var(--sf-gold, var(--gold-700)); }
.pillar-card[data-accent="teal"] { --accent: var(--sf-teal, var(--teal-500)); --accent-text: var(--sf-teal, var(--teal-700)); }
.pillar-card[data-accent="purple"] { --accent: var(--purple-500); --accent-text: var(--sf-purple, var(--purple-700)); }
.pillar-head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
}
.pillar-num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-md);
  color: var(--sf-fg-2);
  flex: none;
}
.pillar-card[data-featured="true"] .pillar-num { color: var(--accent-text, var(--sf-link)); }
.pillar-name {
  font-size: var(--fs-h3);
  font-weight: 600;
}
.pillar-sub {
  margin-top: 0.375rem;
  color: var(--sf-fg-2);
  font-size: var(--fs-sm);
}
.pillar-desc {
  margin-top: var(--sp-3);
  color: var(--sf-fg);
  font-size: var(--fs-sm);
}
.pillar-stages {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}
.pillar-details {
  margin-top: var(--sp-3);
  border-top: 1px solid var(--sf-line);
  padding-top: var(--sp-3);
}
.pillar-details>summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 2.75rem;
  list-style: none;
  cursor: pointer;
  color: var(--sf-link);
  font-size: var(--fs-xs);
  font-weight: 600;
}
.pillar-details>summary::-webkit-details-marker { display: none; }
.pillar-details>summary::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur) var(--ease);
}
.pillar-details[open]>summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.pillar-details>summary:hover { text-decoration: underline; }
.pillar-details .def-list {
  margin-top: var(--sp-3);
  gap: var(--sp-3);
}
.pillar-details .def-block dd { font-size: var(--fs-sm); }
.pillar-foot { margin-top: var(--sp-3); }
.portfolio-empty {
  padding: var(--sp-5);
  border: 1px dashed var(--sf-line-strong);
  border-radius: var(--r-md);
  color: var(--sf-fg-2);
  text-align: center;
}
@media (min-width: 48rem) {
  .portfolio-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pillar-card[data-featured="true"] { grid-column: 1 / -1; }
}
@media (min-width: 75rem) {
  .portfolio-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .pillar-card[data-featured="true"] { grid-column: span 3; }
  .pillar-card[data-featured="true"] .pillar-details .def-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
 15. MSSP (#mssp)
 -------------------------------------------------------------------------- */
.mssp-equation {
  max-width: none;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
}
.mssp-term {
  flex: 1 1 7rem;
  display: flex;
  align-items: center;
  padding: var(--sp-3);
  border: 1px solid var(--sf-card-line);
  border-top: 3px solid var(--blue-500);
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  background: var(--sf-card);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.3;
}
.mssp-plus {
  display: flex;
  align-items: center;
  color: var(--sf-fg-2);
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  flex: none;
}
.mssp-principle {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-left: var(--sp-4);
  border-left: 3px solid var(--sf-gold);
  font-size: clamp(1.125rem, 1rem + 0.8vw, 1.5rem);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: var(--track-tight);
  color: var(--sf-fg);
  max-width: 46rem;
}
.step-list {
  display: grid;
  gap: var(--sp-3);
  margin-top: clamp(2rem, 4vw, 3rem);
}
.step-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: start;
  padding: var(--sp-4);
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-radius: var(--r-md);
}
.step-num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  color: var(--sf-link);
}
.step-item h3 {
  font-size: var(--fs-sm);
  font-weight: 600;
}
.step-item p {
  margin-top: 0.25rem;
  font-size: var(--fs-sm);
  color: var(--sf-fg-2);
}
@media (min-width: 48rem) {
  .step-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
 16. Liderança (#lideranca)
 -------------------------------------------------------------------------- */
.people-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}
.person-card {
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-radius: var(--r-md);
  padding: var(--sp-4);
}
.person-photo {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  object-fit: cover;
  background: var(--sf-line);
}
.person-name {
  margin-top: var(--sp-3);
  font-size: var(--fs-md);
  font-weight: 600;
}
.person-role {
  margin-top: 0.125rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--sf-fg-2);
}
.person-bio {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2);
}
.person-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2.75rem;
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--sf-link);
}
.person-link svg {
  width: 0.875rem;
  height: 0.875rem;
}
@media (min-width: 48rem) {
  .people-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
 17. Tecnologia (#tecnologia) — subseção do Modelo MSSP desde 2026-09-05
 Item 10: deixou de ser seção própria. Herda a superfície escura de #mssp, e
 como todo componente daqui pinta por `--sf-*`, cartão, listas e chips trocam
 de tema sozinhos. O que muda de fato é a hierarquia: H3, não H2.
 -------------------------------------------------------------------------- */
.mssp-sub { margin-top: clamp(3rem, 6vw, 5rem); }
.subsection-title {
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  color: var(--sf-fg);
  max-width: var(--measure);
  margin-bottom: var(--sp-5);
}
.platform-card h4 {
  margin-top: var(--sp-3);
  font-size: var(--fs-md);
}
/* Parceiro sem categoria (APURA, CSURFACE, VALID): a linha simplesmente não
   emite o <span class="tech-cat">. Sem categoria inventada e sem célula vazia
   — o nome ocupa a linha inteira. */

.tech-layout {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  align-items: start;
}
@media (min-width: 62rem) {
  .tech-layout { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
}
.platform-card {
  padding: var(--sp-4);
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-radius: var(--r-md);
}
.platform-logo {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--r-sm);
  object-fit: contain;
}
.platform-card p {
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2);
}
.platform-features {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}
.tech-list {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--sf-line);
}
.tech-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--sf-line);
}
.tech-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--sf-fg);
}
.tech-name a {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}
.tech-name a:hover {
  color: var(--sf-link);
  text-decoration: underline;
}
.tech-name svg {
  width: 0.8125rem;
  height: 0.8125rem;
  flex: none;
  opacity: 0.75;
}
.tech-cat {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--sf-fg-2);
  text-align: right;
}
.tech-group+.tech-group { margin-top: var(--sp-5); }

/* --------------------------------------------------------------------------
 18. Contato + formulário (#contato)
 -------------------------------------------------------------------------- */
.contact-layout {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}
@media (min-width: 62rem) {
  .contact-layout { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
}
.contact-list {
  display: grid;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}
.contact-item {
  display: grid;
  grid-template-columns: 1.5rem minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: start;
}
.contact-item svg {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 0.25rem;
  color: var(--sf-link);
}
.contact-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2);
}
.contact-value {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--sf-fg);
}
.contact-value a {
  color: var(--sf-fg);
  text-decoration: none;
}
.contact-value a:hover {
  color: var(--sf-link);
  text-decoration: underline;
}
.contact-form {
  padding: clamp(1.25rem, 3vw, 2rem);
  background: var(--sf-card);
  border: 1px solid var(--sf-card-line);
  border-radius: var(--r-md);
}
.form-grid {
  display: grid;
  gap: var(--sp-4);
}
.form-group {
  display: grid;
  gap: var(--sp-2);
}
.form-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--sf-fg);
}
.form-label .req {
  color: var(--sf-red);
  margin-left: 0.15em;
}
.form-input,
.form-textarea {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.6875rem 0.875rem;
  background: var(--sf-field-bg);
  color: var(--sf-fg);
  border: 1px solid var(--sf-field-line);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  transition: border-color var(--dur) var(--ease);
}
.form-textarea {
  min-height: 7.5rem;
  resize: vertical;
}
.form-input::placeholder,
.form-textarea::placeholder {
  color: var(--sf-fg-2);
  opacity: 0.8;
}
.form-input:hover,
.form-textarea:hover { border-color: var(--sf-fg-2); }
.form-input[aria-invalid="true"],
.form-textarea[aria-invalid="true"] { border-color: var(--sf-red); }
.form-consent {
  display: grid;
  grid-template-columns: 1.125rem minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: start;
}
.form-consent input {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 0.2rem;
  accent-color: var(--blue-500);
}
.form-consent label {
  font-size: var(--fs-xs);
  color: var(--sf-fg-2);
  line-height: 1.5;
}
/* Honeypot Formspree — fora do fluxo e do foco */
.form-gotcha {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.form-status {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  line-height: 1.5;
}
.form-status svg {
  width: 1rem;
  height: 1rem;
  flex: none;
  margin-top: 0.15rem;
}
.form-status[data-state="error"] { color: var(--sf-red); }
.form-status[data-state="success"] { color: var(--sf-teal); }
.form-note {
  font-size: 0.75rem;
  color: var(--sf-fg-2);
}

/* --------------------------------------------------------------------------
 19. CTA genérica (contrato legado)
 -------------------------------------------------------------------------- */
.cta-section {
  padding-block: var(--section-py);
  background: var(--navy-950);
  color: var(--paper);
  --sf-fg: var(--paper);
  --sf-fg-2: var(--mist);
  --sf-link: var(--blue-300);
  --sf-ghost-line: var(--navy-600);
  --sf-ghost-hover: #16294A;
  --sf-btn-hover: #2A6ACF;
}
.cta-content { max-width: 46rem; }
.cta-title {
  font-size: var(--fs-h2);
  font-weight: 700;
}
.cta-description {
  margin-top: var(--sp-3);
  font-size: var(--fs-lede);
  color: var(--mist);
}
.cta-content .btn { margin-top: var(--sp-5); }

/* --------------------------------------------------------------------------
 20. Footer
 -------------------------------------------------------------------------- */
.footer {
  background: var(--navy-950);
  color: var(--mist);
  padding-block: clamp(3rem, 6vw, 4.5rem) var(--sp-5);
  --sf-link: var(--blue-300);
}
.footer-content {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: 1fr;
}
.footer-brand {
  display: inline-flex;
  align-items: center;
  color: var(--paper);
  text-decoration: none;
}
.footer-logo {
  height: 2.125rem;
  width: auto;
}
.footer-description {
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--mist);
  max-width: 26rem;
}
.footer-contact {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  font-size: var(--fs-xs);
}
.footer-contact a {
  color: var(--blue-300);
  text-decoration: none;
}
.footer-contact a:hover { text-decoration: underline; }
.footer-title {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--paper);
  margin-bottom: var(--sp-3);
}
.footer-links {
  display: grid;
  gap: 0.125rem;
}
.footer-link {
  display: inline-flex;
  align-items: center;
  /* QA: 2.25rem = 36px, abaixo dos 44px de alvo de toque */
  min-height: 2.75rem;
  padding-block: 0.125rem;
  color: var(--mist);
  font-size: var(--fs-xs);
  text-decoration: none;
}
/* QA DEF-08 (residual): a altura ja era 44px, mas rotulos curtos ("FAQ",
   "Blog", "DFIR") ficavam com 26-39px de LARGURA no toque. */
@media (max-width: 40rem) {
  .footer-link {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    min-width: 2.75rem;
  }
}
.footer-link:hover {
  color: var(--paper);
  text-decoration: underline;
}
.footer-link[aria-disabled="true"] {
  color: #7C8CA3;
  cursor: not-allowed;
  text-decoration: none;
}
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--navy-700);
  font-size: 0.75rem;
  color: var(--mist);
}
.footer-social {
  display: flex;
  gap: var(--sp-2);
}
.footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--navy-700);
  color: var(--mist);
}
.footer-social a:hover {
  color: var(--paper);
  border-color: var(--navy-600);
}
.footer-social svg {
  width: 1.0625rem;
  height: 1.0625rem;
}
@media (min-width: 48rem) {
  .footer-content { grid-template-columns: 1.4fr 1fr 1fr 1fr; }
}

/* --------------------------------------------------------------------------
 21. Páginas internas — contrato legado (SSG)
 -------------------------------------------------------------------------- */
.page-header {
  background: var(--navy-950);
  color: var(--paper);
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  --sf-fg: var(--paper);
  --sf-fg-2: var(--mist);
  --sf-link: var(--blue-300);
  /* DEF-04: sem esta linha o eyebrow herdava --blue-600 (3.31:1 sobre navy) */
  --sf-eyebrow: var(--blue-300);
}
.page-header h1,
.page-header .section-title {
  color: var(--paper);
  max-width: 22ch;
}
.page-header .section-description,
.page-header p { color: var(--mist); }
/* M7: mesma leitura do card do portfolio, na faixa lateral do cabecalho da
   vertical. E faixa grafica, nao texto: o eyebrow continua em --blue-300
   (9.01:1 sobre navy-950) para nao trocar legibilidade por cor. */
/* --sf-line-strong nao existe no escopo do .page-header: com a var indefinida
   a declaracao inteira caia (IACVT) e a borda ficava com style none / 0px.
   O fallback e o proprio token de linha do navy. */
.page-header[data-accent] { border-left: 4px solid var(--navy-700); }
.page-header[data-accent="blue"] { border-left-color: var(--blue-500); }
.page-header[data-accent="gold"] { border-left-color: var(--gold-500); }
.page-header[data-accent="teal"] { border-left-color: var(--teal-500); }
.page-header[data-accent="purple"] { border-left-color: var(--purple-500); }
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--mist);
}
.breadcrumb a {
  color: var(--blue-300);
  text-decoration: none;
}
.breadcrumb a:hover { text-decoration: underline; }
/* DEF-05: --navy-600 sobre navy-950 dava 1.88:1; --mist a 70% passa de 3:1 */
.breadcrumb-separator {
  color: var(--mist);
  opacity: 0.7;
}
.breadcrumb-current { color: var(--paper); }
/* Blog / notícias */
.blog-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.blog-card {
  display: flex;
  flex-direction: column;
  background: var(--sf-card, var(--white));
  border: 1px solid var(--sf-card-line, #E2E7EE);
  border-radius: var(--r-md);
  overflow: hidden;
}
.blog-card-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--paper-2);
}
.blog-card-content {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4);
  flex: 1;
}
.blog-card-category {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-link, var(--blue-600));
}
.blog-card-title {
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.3;
}
.blog-card-title a {
  color: inherit;
  text-decoration: none;
}
.blog-card-title a:hover { text-decoration: underline; }
.blog-card-excerpt {
  font-size: var(--fs-sm);
  color: var(--sf-fg-2, var(--ink-2));
  /* DEF-03: excerpt vem do CMS e pode trazer URL sem espaço */
  overflow-wrap: anywhere;
  word-break: break-word;
}
.blog-card-footer,
.blog-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin-top: auto;
  padding-top: var(--sp-3);
  font-size: 0.75rem;
  color: var(--sf-fg-2, var(--ink-2));
}
.blog-card-reading-time,
.reading-time {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--sf-fg-2, var(--ink-2));
  /* DEF-03 (mesma classe de defeito): `sourceName` do CMS as vezes e a URL
     crua da fonte e estourava o card, que tem overflow hidden. */
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.blog-card-link {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  height: 100%;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}
.blog-card-link:hover .blog-card-title { text-decoration: underline; }
.blog-card-link:focus-visible {
  outline: 2px solid var(--sf-link, var(--blue-600));
  outline-offset: 2px;
}
/* Artigo */
.article-container {
  max-width: 46rem;
  margin-inline: auto;
}
.article-header { margin-bottom: var(--sp-5); }
.article-title {
  font-size: var(--fs-h2);
  font-weight: 700;
}
.article-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--sf-fg-2, var(--ink-2));
}
.article-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}
.article-excerpt-hero {
  margin-top: var(--sp-4);
  font-size: var(--fs-lede);
  color: var(--sf-fg-2, var(--ink-2));
}
.article-cover,
.article-cover-image {
  width: 100%;
  border-radius: var(--r-md);
  margin-bottom: var(--sp-5);
}
.article-body {
  font-size: var(--fs-base);
  line-height: 1.7;
}
.article-body> :not(:first-child) { margin-top: var(--sp-4); }
.article-body h2 {
  font-size: var(--fs-lg);
  margin-top: var(--sp-6);
}
.article-body h3 {
  font-size: var(--fs-md);
  margin-top: var(--sp-5);
}
.article-body ul,
.article-body ol {
  padding-left: 1.25rem;
  list-style: disc;
  display: grid;
  gap: var(--sp-2);
}
.article-body ol { list-style: decimal; }
.article-body img { border-radius: var(--r-md); }
.article-body blockquote {
  padding-left: var(--sp-4);
  border-left: 3px solid var(--blue-500);
  color: var(--sf-fg-2, var(--ink-2));
}
.article-body pre {
  padding: var(--sp-3);
  background: var(--navy-900);
  color: var(--paper);
  border-radius: var(--r-sm);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
}
.article-body code {
  font-family: var(--font-mono);
  font-size: 0.9em;
}
.article-original-content { margin-top: var(--sp-5); }
.article-source {
  margin-top: var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--sf-fg-2, var(--ink-2));
}
.article-navigation {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  justify-content: space-between;
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--sf-line, #DDE3EB);
}
.author-box {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  align-items: flex-start;
  margin-top: var(--sp-6);
  padding: var(--sp-4);
  background: var(--sf-card, var(--white));
  border: 1px solid var(--sf-card-line, #E2E7EE);
  border-radius: var(--r-md);
}
.author-avatar {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
}
.author-info { flex: 1 1 14rem; }
.author-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2, var(--ink-2));
}
.author-name {
  font-size: var(--fs-md);
  font-weight: 600;
}
.author-bio {
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2, var(--ink-2));
}
.related-posts { border-top: 1px solid var(--sf-line, #DDE3EB); }
/* FAQ */
.faq-categories {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
}
.faq-filter-btn {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.5rem 0.9375rem;
  border: 1px solid var(--sf-line-strong, #C4CDDA);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--sf-fg-2, var(--ink-2));
  font-size: var(--fs-xs);
  font-weight: 600;
}
.faq-filter-btn:hover { color: var(--sf-fg, var(--ink)); }
.faq-filter-btn.active {
  background: var(--sf-fg, var(--ink));
  border-color: var(--sf-fg, var(--ink));
  color: var(--sf-bg, var(--paper));
}
.faq-category-group+.faq-category-group { margin-top: var(--sp-6); }
.faq-category-title {
  font-size: var(--fs-lg);
  margin-bottom: var(--sp-4);
}
.faq-list {
  display: grid;
  gap: var(--sp-2);
}
.faq-item {
  background: var(--sf-card, var(--white));
  border: 1px solid var(--sf-card-line, #E2E7EE);
  border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4);
}
.faq-item+.faq-item { margin-top: var(--sp-2); }
.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: 2.75rem;
  list-style: none;
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question::after {
  content: "";
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}
.faq-item[open] .faq-question::after { transform: rotate(-135deg); }
.faq-answer {
  padding-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2, var(--ink-2));
}
.faq-answer> :not(:first-child) { margin-top: var(--sp-3); }
/* 404 */
.error-page {
  display: flex;
  align-items: center;
  min-height: 60vh;
  padding-block: var(--section-py);
  padding-inline: var(--gutter);
}
/* Centraliza mesmo sem .container no markup legado do 404 */
.error-page>* {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
}
.error-code {
  font-family: var(--font-mono);
  font-size: clamp(3rem, 10vw, 5rem);
  font-weight: 500;
  color: var(--sf-link, var(--blue-600));
  letter-spacing: var(--track-mono);
}
.error-title {
  margin-top: var(--sp-3);
  font-size: var(--fs-h2);
}
.error-description {
  margin-top: var(--sp-3);
  color: var(--sf-fg-2, var(--ink-2));
}
.error-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}
.error-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: 0.625rem 1.25rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--sf-ghost-line, #C4CDDA);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  color: var(--sf-fg, var(--ink));
}
.error-link--primary {
  background: var(--blue-600);
  border-color: var(--blue-600);
  color: var(--white);
}
.error-link--primary:hover {
  background: var(--blue-700);
  border-color: var(--blue-700);
  color: var(--white);
}
.error-link--secondary:hover { background: var(--sf-ghost-hover, #E4E9F0); }
/* Features / about — contrato legado */
.features-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
.feature-card {
  padding: var(--sp-4);
  background: var(--sf-card, var(--white));
  border: 1px solid var(--sf-card-line, #E2E7EE);
  border-left: 3px solid var(--blue-500);
  border-radius: var(--r-md);
}
.feature-title {
  font-size: var(--fs-md);
  font-weight: 600;
}
.feature-description {
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2, var(--ink-2));
}
.feature-list {
  display: grid;
  gap: var(--sp-2);
}
.feature-list li {
  display: grid;
  grid-template-columns: 1.125rem minmax(0, 1fr);
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--sf-fg-2, var(--ink-2));
}
.feature-list svg {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 0.2rem;
  color: var(--sf-teal, var(--teal-700));
}
.about-content {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
}
.about-text { max-width: var(--measure); }
@media (min-width: 62rem) {
  .about-content { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
 22. Diagramas SVG inline
 -------------------------------------------------------------------------- */

/* Ponta de seta do arco de retorno do anel do CTEM. Dividia esta regra com o
   .dg-arrow do diagrama do hero, que saiu no item 5. */
.orbit-arrow { fill: var(--sf-thread-ink); }

/* --------------------------------------------------------------------------
 23. Motion e reveal
 -------------------------------------------------------------------------- */
.reveal-ready [data-reveal]:not(.is-visible) {
  opacity: 0;
  transform: translateY(12px);
}
[data-reveal].is-visible {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* LOW: aqui existia um override de `.reveal-ready [data-reveal]` inalcancavel:
   sob prefers-reduced-motion o main.js marca tudo com .is-visible e sai SEM
   adicionar .reveal-ready, entao o seletor nunca casava. */

/* TODO(review): há blocos de regras duplicados entre as seções 19-21 (contrato
   legado do SSG) e as seções de componentes da Home. Consolidar exige repassar
   a cascata inteira e sair do escopo desta rodada de correções. */

/* --------------------------------------------------------------------------
 24. Utilitários
 -------------------------------------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
[hidden] { display: none !important; }

/* --------------------------------------------------------------------------
 25. Complementos de componentes
 -------------------------------------------------------------------------- */
/* Equação do Modelo MSSP — o texto é a frase literal do PDF, o layout é a leitura visual */
.mssp-lead {
  flex: 1 0 100%;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-eyebrow);
  margin-bottom: var(--sp-1);
}
/* Subtítulo do pilar dentro do <details> */
.pillar-lead {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--sf-fg);
}
/* TODO(review) [rodada 2, LOW]: o round2 listou este bloco como duplicado e
   morto. Conferido regra a regra: ele NAO e morto — vem depois das definicoes
   das secoes 6-20 e e a declaracao vencedora (.link-arrow svg passa de 1rem
   para 1em, .tech-name svg de 0.8125rem para 0.875em). Remover mudaria o
   tamanho renderizado de 9 icones. Consolidar exige repassar a cascata inteira,
   igual ao TODO da secao 23. */
/* Ícones: dimensionados pelo contexto de uso */
.link-arrow svg,
.person-link svg,
.tech-name svg,
.form-status svg {
  width: 1em;
  height: 1em;
}
.person-link svg,
.tech-name svg {
  width: 0.875em;
  height: 0.875em;
}
.contact-item svg {
  width: 1.125rem;
  height: 1.125rem;
}
.btn svg {
  width: 1.125em;
  height: 1.125em;
}
.footer-social svg {
  width: 1.0625rem;
  height: 1.0625rem;
}
.theme-toggle svg,
.navbar-toggle svg {
  width: 1.125rem;
  height: 1.125rem;
}
.mobile-menu-close svg {
  width: 1.25rem;
  height: 1.25rem;
}
/* Modificadores de espaçamento (evitam style inline no HTML) */
.section-header--flush { margin-bottom: 0; }
.logo-strip--spaced { margin-top: clamp(2rem, 4vw, 3rem); }
.method-note--lead {
  margin-top: 0;
  margin-bottom: clamp(2rem, 4vw, 2.5rem);
}
.platform-cta { margin-top: var(--sp-4); }
.step-list-label {
  display: block;
  margin-top: clamp(2rem, 4vw, 3rem);
}
.closing-statement { margin-top: clamp(2.5rem, 5vw, 4rem); }
.mobile-menu-head .section-label { margin-bottom: 0; }

/* --------------------------------------------------------------------------
 24. Fase B — páginas internas geradas pelo SSG
 Acréscimos mínimos: nenhum token novo, apenas modificadores de classes já
 documentadas em docs/herosite/design-system.md.
 -------------------------------------------------------------------------- */

/* Problema / Serviço / Resultado lado a lado nas páginas de serviço e método. */
@media (min-width: 62rem) {
  .def-list--cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Card de blog/notícia sem imagem de capa: o conteúdo assume o topo do card
   (evita a faixa vazia onde antes havia <img> quebrada — bug BLD5). */
.blog-card--no-image .blog-card-content { padding-top: var(--sp-4); }

/* Bloco recolhível com o conteúdo original de uma notícia traduzida.
   Substitui o style="..." inline emitido pelo build.js (§7.2). */
.article-original-content {
  padding-top: var(--sp-4);
  border-top: 1px solid var(--sf-line, #DDE3EB);
}
.article-original-summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 2.75rem;
  list-style: none;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--sf-fg-2, var(--ink-2));
}
.article-original-summary::-webkit-details-marker { display: none; }
.article-original-summary::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}
.article-original-content[open] .article-original-summary::after { transform: rotate(-135deg); }
.article-original-content[open] .article-original-summary { color: var(--sf-fg, var(--ink)); }
.article-original-title {
  font-size: var(--fs-lg);
  margin-top: var(--sp-4);
}

/* O Modelo Integrado da Home usa <h4> (dentro de uma seção com h2+h3); em
   /metodo-ctem o mesmo bloco é <h3>. Mesma aparência, hierarquia correta. */
.model-step h3 {
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* Nota de fechamento: fecha um bloco de conteúdo (o oposto de --lead, que
   abre). Usada nas páginas de serviço e na Zero Trust & SASE. */
.method-note--close {
  margin-top: clamp(2rem, 4vw, 3rem);
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
 26. Movimento com propósito e profundidade
 Se a animação sair e a compreensão não piorar, ela é decoração e não entra.
 Tudo aqui explica fluxo, sequência, continuidade ou resposta ao toque. Nada
 nasce oculto sem JS: todo estado escondido vive sob `.reveal-ready`, classe
 que só o main.js adiciona. 26.6 desliga o movimento sob reduced-motion.
 -------------------------------------------------------------------------- */

/* --- 26.2 Modelo Integrado: a linha percorre e os nós acendem --------------
   A lista já era uma sequência; o traço que desce e os nós que acendem em
   cascata mostram que uma etapa alimenta a próxima. Uma vez só, na entrada. */
.model-step::before { transform-origin: top; }
.reveal-ready .model-flow[data-reveal]:not(.is-visible) .model-step::before { transform: scaleY(0); }
.reveal-ready .model-flow[data-reveal]:not(.is-visible) .model-node { opacity: 0; }
.model-flow[data-reveal].is-visible .model-step::before {
  transform: scaleY(1);
  transition: transform 620ms var(--ease-out);
}
.model-flow[data-reveal].is-visible .model-node { animation: node-in var(--dur-slow) var(--ease-out) backwards; }
@keyframes node-in {
  from { opacity: 0; transform: scale(0.82); }
  to { opacity: 1; transform: none; }
}
.model-flow[data-reveal].is-visible .model-step:nth-child(1) .model-node { animation-delay: 60ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(2) .model-node { animation-delay: 180ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(3) .model-node { animation-delay: 300ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(4) .model-node { animation-delay: 420ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(5) .model-node { animation-delay: 540ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(1)::before { transition-delay: 120ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(2)::before { transition-delay: 240ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(3)::before { transition-delay: 360ms; }
.model-flow[data-reveal].is-visible .model-step:nth-child(4)::before { transition-delay: 480ms; }

/* --- 26.3 Reveal escalonado ------------------------------------------------
   O container com `data-reveal-stagger` não se move: entram os filhos, em
   ordem de leitura, 60ms entre um e outro. Sem stagger a grade inteira
   "pisca" junto e o olho não sabe por onde começar. */
.reveal-ready [data-reveal-stagger]:not(.is-visible) {
  opacity: 1;
  transform: none;
}
.reveal-ready [data-reveal-stagger]:not(.is-visible) > * { opacity: 0; }
/* Fill "backwards", nunca "forwards"/"both": animação ganha da cascata, então
   um valor animado que persistisse venceria o :hover do card e a elevação
   simplesmente deixaria de funcionar depois do reveal. */
[data-reveal-stagger].is-visible > * { animation: reveal-up var(--dur-slow) var(--ease-out) backwards; }
@keyframes reveal-up {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
[data-reveal-stagger].is-visible > *:nth-child(2) { animation-delay: 60ms; }
[data-reveal-stagger].is-visible > *:nth-child(3) { animation-delay: 120ms; }
[data-reveal-stagger].is-visible > *:nth-child(4) { animation-delay: 180ms; }
[data-reveal-stagger].is-visible > *:nth-child(5) { animation-delay: 240ms; }
[data-reveal-stagger].is-visible > *:nth-child(6) { animation-delay: 300ms; }
[data-reveal-stagger].is-visible > *:nth-child(n+7) { animation-delay: 360ms; }
/* O anel desenha o próprio arco na entrada; não precisa também deslizar. */
.reveal-ready .ctem-ring:not(.is-visible) {
  opacity: 1;
  transform: none;
}

/* --- 26.4 Micro-interações com peso ---------------------------------------
   Card do portfólio: a elevação responde ao ponteiro e a faixa de accent
   engrossa por dentro (box-shadow inset), sem empurrar o texto 2px para o
   lado — mudar `border-width` no hover causaria reflow visível. */
.pillar-card {
  transition: border-color var(--dur) var(--ease), transform var(--dur-step) var(--ease),
    box-shadow var(--dur-step) var(--ease);
}
/* Item 12: mesma ideia, amplitude menor — 2px de elevacao e uma sombra mais
   rasa. O card ainda responde ao ponteiro; so nao pula. */
.pillar-card:hover,
.pillar-card:focus-within {
  transform: translateY(-2px);
  box-shadow: inset 2px 0 0 var(--accent), 0 6px 16px -14px rgba(7, 14, 26, 0.45);
}
/* Botões e alvos afundam 1px no toque — confirmação física do clique. */
.btn {
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    color var(--dur) var(--ease), transform 90ms var(--ease);
}
.btn:active,
.filter-btn:active,
.ring-node:active { transform: translateY(1px); }
/* Navegação: sublinhado que cresce da esquerda no lugar da pastilha de fundo.
   O crescimento tem direção; a pastilha só acendia. */
.navbar-link {
  position: relative;
  transition: color var(--dur) var(--ease);
}
.navbar-link::after {
  content: "";
  position: absolute;
  left: 0.6875rem;
  right: 0.6875rem;
  bottom: 0.25rem;
  height: 2px;
  background: var(--blue-300);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 160ms var(--ease-out);
}
.navbar-link:hover,
.navbar-link[aria-current="page"] {
  color: var(--paper);
  background: none;
}
.navbar-link:hover::after,
.navbar-link[aria-current="page"]::after { transform: scaleX(1); }
/* Card que entra no filtro do portfólio: fade + escala curta. A saída é
   síncrona de propósito — `hidden` precisa valer no mesmo tick do clique,
   senão o contrato do filtro (aria-pressed + contagem anunciada) mentiria. */
@keyframes card-in {
  from { opacity: 0; transform: scale(0.98); }
  to { opacity: 1; transform: none; }
}
.pillar-card.is-entering { animation: card-in 180ms var(--ease-out); }
/* <details> do card: altura animada onde o browser suporta interpolate-size;
   onde não suporta, abre instantâneo como sempre abriu. */
@supports (interpolate-size: allow-keywords) {
  .pillar-details { interpolate-size: allow-keywords; }
  .pillar-details::details-content {
    block-size: 0;
    overflow: clip;
    transition: block-size var(--dur-slow) var(--ease-out),
      content-visibility var(--dur-slow) allow-discrete;
  }
  .pillar-details[open]::details-content { block-size: auto; }
}


/* --- 26.6 prefers-reduced-motion -------------------------------------------
   O estado final passa a ser o inicial. O que era loop sai de cena: um traço
   parado no meio do arco seria ruído, não informação. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-delay: 0ms !important;
    animation-delay: 0ms !important;
  }
  .orbit-pulse { display: none; }
  .orbit-draw { stroke-dashoffset: 0 !important; }
  .model-step::before { transform: none !important; }
}

/* --------------------------------------------------------------------------
 27. O fio — identidade e wayfinding (2026-09-04)
 O nome da empresa e o metodo sao a mesma ideia: atravessar muitos caminhos
 possiveis seguindo um so. Aqui isso vira desenho, nunca palavra — nenhuma
 copy nova entra no site. Uma linha atravessa a pagina na calha esquerda, a
 secao do problema vira caminhos que convergem e os numeros que ja existiam
 viram ritmo editorial. Tudo compartilha a mesma gramatica de traco (secao 1:
 --thread-w, --knot-sm/md/lg, pathLength="100").
 -------------------------------------------------------------------------- */

/* --- 27.1 O fio na calha ---------------------------------------------------
   Nao e barra de progresso: e um mapa. Cada no fica na proporcao em que a
   secao aparece no documento, entao as distancias sao desiguais, e o traco
   aceso vai do topo ate o ponto de leitura. Clicar num no navega. */
.fio { display: none; }

@media (min-width: 78rem) {
  /* Abaixo de 78rem sobra menos de 30px de calha entre o no e a primeira letra
     do texto — o fio comecaria a disputar o respiro da leitura. Ali ele some, e
     a navbar cobre a mesma navegacao (medido em scripts/fio-calha.js).
     `.fio-ready` so entra pelo JS — as posicoes dependem da altura do
     documento, que o CSS nao conhece. */
  .fio-ready .fio {
    display: block;
    position: sticky;
    top: var(--nav-h);
    z-index: 2;
    height: 0;
    pointer-events: none;
  }
  .fio-rail {
    position: absolute;
    left: max(1.25rem, calc(50% - var(--container) / 2 - 0.5rem));
    top: 2.25rem;
    width: 0.5rem;
    height: calc(100vh - var(--nav-h) - 5.5rem);
  }
  .fio-thread {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
  }
  /* Neutro fixo de proposito: o trilho atravessa superficies claras e escuras
     ao mesmo tempo, entao nenhuma cor de superficie serve para ele. */
  .fio-track {
    stroke: var(--fio-track);
    stroke-width: var(--thread-w);
  }
  /* O traco aceso herda a tinta da secao que o fio atravessa: o JS copia
     --sf-thread-ink da secao para --fio-ink. A troca e suave. */
  .fio-drawn {
    stroke: var(--fio-ink, var(--blue-500));
    stroke-width: var(--thread-w);
    stroke-dasharray: 100 100;
    stroke-dashoffset: var(--fio-dash, 100);
    transition: stroke 420ms var(--ease);
  }
  .fio-knots {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .fio-knot {
    position: absolute;
    left: 50%;
    top: var(--knot-pos, 0%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin: -0.875rem 0 0 -0.875rem;
    border-radius: 50%;
    pointer-events: auto;
    text-decoration: none;
    color: inherit;
  }
  /* Contas num fio: o traco passa por dentro do anel. */
  .fio-knot-mark {
    width: var(--knot-sm);
    height: var(--knot-sm);
    border-radius: 50%;
    box-shadow: inset 0 0 0 calc(var(--thread-w) * 1px) var(--fio-knot-track);
    transition: box-shadow var(--dur-step) var(--ease),
      background-color var(--dur-step) var(--ease), width var(--dur-step) var(--ease),
      height var(--dur-step) var(--ease);
  }
  .fio-knot[data-state="past"] .fio-knot-mark {
    box-shadow: inset 0 0 0 calc(var(--thread-w) * 1px) var(--fio-ink, var(--blue-500));
  }
  .fio-knot[data-state="current"] .fio-knot-mark {
    width: 0.6875rem;
    height: 0.6875rem;
    background: var(--fio-ink, var(--blue-500));
    box-shadow: none;
  }
  .fio-knot:hover .fio-knot-mark,
  .fio-knot:focus-visible .fio-knot-mark {
    background: var(--fio-ink, var(--blue-500));
    box-shadow: none;
  }
  /* O nome da secao aparece so no ponteiro ou no foco: o fio nao pode virar
     um segundo menu permanente na frente do texto. */
  .fio-knot-name {
    position: absolute;
    left: 1.375rem;
    white-space: nowrap;
    padding: 0.3125rem 0.625rem;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: var(--track-mono);
    text-transform: uppercase;
    color: var(--ink);
    background: var(--white);
    border: 1px solid #C4CDDA;
    border-radius: var(--r-sm);
    box-shadow: 0 6px 18px -12px rgba(7, 14, 26, 0.7);
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
    pointer-events: none;
  }
  .fio-knot:hover .fio-knot-name,
  .fio-knot:focus-visible .fio-knot-name {
    opacity: 1;
    transform: none;
  }
}

/* --- 27.2 O problema como caminhos ----------------------------------------
   Oito impactos, oito curvas, um destino. A secao que fala de caminhos de
   ataque desenha caminhos: mesmas curvas do funil do hero, mesma espessura,
   mesmo pathLength. O texto continua literal (site.json). */
#problema { --sf-thread-ink: var(--gold-600); }
.paths {
  display: grid;
  gap: var(--sp-4);
}
.paths-list {
  position: relative;
  list-style: none;
  margin: 0;
  /* Reserva a coluna do no de chegada: em telas estreitas a espinha e o
     destino ficam dentro do container, sem escapar pela direita. */
  padding: 0 var(--knot-lg) 0 0;
  display: grid;
  /* Item 9: passaram a ser 10 origens. A altura minima da linha desce de
     3,25rem para 3rem e o `gap` some — com duas curvas a mais, o que impede o
     leque de apertar é a altura total crescer, não cada linha encolher. */
  grid-template-rows: repeat(10, minmax(3rem, 1fr));
}
.path-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.path-num {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: var(--track-mono);
  color: var(--sf-fg-2);
  flex: none;
}
.path-name {
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.25;
  color: var(--sf-fg);
}
/* A guia horizontal e o comeco da curva: o traco sai do rotulo, nao de um
   ponto arbitrario. */
.path-item::after {
  content: "";
  flex: 1 1 1.5rem;
  min-width: 1.5rem;
  height: calc(var(--thread-w) * 1px);
  background: var(--sf-thread);
}
.path-item::before {
  content: "";
  position: absolute;
  right: calc(var(--knot-sm) / -2);
  top: 50%;
  width: var(--knot-sm);
  height: var(--knot-sm);
  margin-top: calc(var(--knot-sm) / -2);
  border-radius: 50%;
  background: var(--sf-bg);
  box-shadow: 0 0 0 calc(var(--thread-w) * 1px) var(--sf-thread-ink);
}
.paths-wire { display: none; }
.paths-wire .path-wire {
  fill: none;
  stroke: var(--sf-thread-ink);
  stroke-width: var(--thread-w);
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 0;
}
/* O destino: onde os oito caminhos viram uma decisao. Dourado porque e a cor
   de priorizacao/decisao do design system, nao porque combina. */
.paths-target {
  display: block;
  width: var(--knot-lg);
  height: var(--knot-lg);
  border-radius: 50%;
  background: var(--sf-thread-ink);
  box-shadow: 0 0 0 5px var(--sf-bg), 0 0 0 calc(5px + var(--thread-w) * 1px) var(--sf-thread-ink);
  margin-left: auto;
  margin-right: calc(var(--knot-lg) / 2);
}
.paths-note { max-width: 34rem; }
/* Item 9: o destino da convergencia deixou de ser um ponto mudo. O texto fica
   colado ao no de chegada — a frase e o que as dez linhas produzem, entao ela
   e o unico elemento em escala de titulo deste bloco. */
.paths-destination {
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: var(--track-tight);
  color: var(--sf-fg);
  text-wrap: balance;
}
/* Sem o filete de .method-note: o no dourado de chegada ja e a marca do bloco,
   e dois marcadores encostados viravam ruido (item 12). */
.paths-approach {
  margin-top: var(--sp-3);
  color: var(--sf-fg-2);
  font-size: var(--fs-sm);
}

/* Coluna unica: os oito nos se alinham a direita e uma espinha vertical os
   leva ao destino. Mesma convergencia, girada 90 graus — nunca um leque
   espremido. */
.paths-list::after {
  content: "";
  position: absolute;
  right: var(--knot-lg);
  top: 5%;
  /* Desce ate encostar no destino: a espinha nao pode parar no ar. */
  bottom: calc(var(--sp-4) * -1);
  width: calc(var(--thread-w) * 1px);
  background: var(--sf-thread-ink);
  transform: translateX(50%);
}

@media (min-width: 62rem) {
  /* Wire e destino dividem a mesma coluna: as curvas terminam exatamente no
     centro do no, sem folga entre o desenho e o ponto de chegada. */
  .paths {
    grid-template-columns: minmax(0, 1fr) clamp(7rem, 13vw, 11rem) minmax(0, 0.95fr);
    grid-template-areas: "list wire note";
    column-gap: 0;
    align-items: stretch;
  }
  .paths-list {
    grid-area: list;
    padding-right: 0;
  }
  .paths-list::after { display: none; }
  .paths-wire {
    display: block;
    grid-area: wire;
    align-self: stretch;
    width: 100%;
    height: 100%;
  }
  .paths-target {
    grid-area: wire;
    justify-self: end;
    align-self: center;
    margin: 0;
    transform: translateX(50%);
  }
  /* Sem o filete da .method-note: o proprio no de chegada e a marca dourada
     do bloco, e dois marcadores dourados encostados viravam ruido. */
  .paths-note {
    grid-area: note;
    align-self: center;
    margin-top: 0;
    padding-left: calc(var(--knot-lg) / 2 + var(--sp-5));
  }
}

/* Desenho na entrada: as curvas correm do rotulo ao destino, uma vez so.
   Sem JS (sem .reveal-ready) elas ja nascem inteiras. */
.reveal-ready .paths[data-reveal]:not(.is-visible) .path-wire { stroke-dashoffset: 100; }
.paths[data-reveal].is-visible .path-wire { transition: stroke-dashoffset 700ms var(--ease-out); }
.paths[data-reveal].is-visible .path-wire:nth-child(2) { transition-delay: 70ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(3) { transition-delay: 140ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(4) { transition-delay: 210ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(5) { transition-delay: 280ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(6) { transition-delay: 350ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(7) { transition-delay: 420ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(8) { transition-delay: 490ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(9) { transition-delay: 560ms; }
.paths[data-reveal].is-visible .path-wire:nth-child(10) { transition-delay: 630ms; }
.reveal-ready .paths[data-reveal]:not(.is-visible) {
  opacity: 1;
  transform: none;
}

/* --- 27.4 prefers-reduced-motion -------------------------------------------
   O fio fica inteiro desenhado e estatico; as curvas do problema idem. */
@media (prefers-reduced-motion: reduce) {
  .fio-drawn { stroke-dashoffset: 0 !important; }
  .path-wire { stroke-dashoffset: 0 !important; }
}

/* --------------------------------------------------------------------------
 28. Sobre nos (/sobre-nos) — missao, visao e manifesto (2026-09-13)
 Pagina propria (templates/about.html), no molde de /metodo-ctem, com texto
 literal de data/site.json > about. Missao e visao moram dentro do page-header,
 logo abaixo do H1; o manifesto fica no paper, entre o cabecalho e o CTA
 escuros, com o unico ornamento da pagina: um filete na tinta do fio (secao
 27), desenhado quando o bloco entra. O historico dos espacos esta em
 docs/changelog/2026-09-13-herosite-espacos-menu-clientes.md.
 -------------------------------------------------------------------------- */
.sobre-pillars {
  display: grid;
  gap: var(--sp-5) var(--sp-6);
  margin-top: var(--sp-6);
}
@media (min-width: 48rem) {
  .sobre-pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Respiro entre visao e manifesto so nesta pagina: com os paddings globais eram
   ~190px e, no tema escuro, o intervalo lia como vazio. Duas classes para vencer
   `.page-header` e `.section` pela especificidade, nao pela ordem do arquivo. */
.page-header.page-header--sobre { padding-bottom: clamp(2.5rem, 4vw, 3.5rem); }
.section.section--sobre-manifesto { padding-block: clamp(3rem, 6vw, 5rem); }
/* Na pagina os rotulos sao h2 (o H1 e o titulo). A classe vence o `h2` global
   por especificidade, mas so nas propriedades que declara: por isso cada uma
   que `h1, h2, h3, h4` e `h2` definem (tamanho, peso, entrelinha, tracking e
   text-wrap) esta reescrita aqui, senao o rotulo sairia no corpo de titulo.
   A cor vem da superficie: --blue-300 no page-header, --blue-600 no paper claro
   e --blue-300 no paper escuro. */
.sobre-kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  text-wrap: wrap;
  color: var(--sf-eyebrow);
}
/* Sem cor propria, de proposito: no page-header vale `.page-header p { color:
   var(--mist) }`, que deixa o H1 em --paper e as frases um passo abaixo. */
.sobre-statement {
  margin-top: var(--sp-2);
  font-size: var(--fs-h3);
  line-height: 1.45;
}
/* Sem max-width proprio: a medida de leitura vem do `p { max-width:
   var(--measure) }` global, que em ch se resolve no corpo do proprio texto. */
.sobre-manifesto {
  position: relative;
  padding-left: var(--sp-4);
}
.sobre-manifesto::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--thread-w) * 1px);
  background: var(--sf-thread-ink);
  transform-origin: top;
}
/* Desenho na entrada, como os .path-wire da 27.3: a transicao so existe no
   estado visivel e espera o fade do bloco (--dur-slow), senao o traco corre
   escondido dentro dele. Sem JS nao ha .reveal-ready e o filete nasce inteiro;
   em prefers-reduced-motion o main.js marca .is-visible sem .reveal-ready, entao
   ele tambem nasce inteiro e nao precisa de override. */
.reveal-ready .sobre-manifesto[data-reveal]:not(.is-visible)::before { transform: scaleY(0); }
.sobre-manifesto[data-reveal].is-visible::before {
  transition: transform var(--dur-draw) var(--ease-out) var(--dur-slow);
}
.sobre-manifesto-text {
  margin-top: var(--sp-3);
  font-size: var(--fs-lede);
  line-height: 1.6;
  color: var(--sf-fg);
}
/* O manifesto tem uma secao inteira: a partir de 48rem ganha o corpo das frases
   de missao e visao. */
@media (min-width: 48rem) {
  .sobre-manifesto-text {
    font-size: var(--fs-h3);
    line-height: 1.55;
  }
}
