/* public.css — bundle PÚBLICO (layouts application, blog, bio, material).
   Arquivo único de propósito: Propshaft não concatena, e @import encadeado
   vira requisição render-blocking em cascata. Ver DESIGN.md.
   Isolado do admin: nada aqui importa tokens.css nem components/*.
   Ordem das seções é contratual — ver docs/superpowers/plans/2026-08-27-redesign-publico-vodafone.md */

/* ============================================================
   TOKENS — dialeto Vodafone, paleta "autoridade humana"
   Spec: docs/superpowers/specs/2026-08-27-redesign-publico-vodafone-design.md
   ============================================================ */
:root {
  /* ---- cor: base escura ---- */
  --navy: #0B1F3A;
  --navy-deep: #071528;

  /* ---- cor: acento ----
     TRAVA: --coral sobre claro dá 2.8:1 e reprova AA. Coral SÓ como fundo.
     Texto/link de acento sobre claro usa --coral-ink (5.9:1). */
  --coral: #FF5A5F;
  /* O hover CLAREIA em vez de escurecer, ao contrário do padrão: a superfície
     coral exige texto escuro (--on-coral), e escurecer o fundo derrubava o par
     pra 3.97:1, abaixo de AA. Clareando dá 6.35:1. */
  --coral-hover: #FF7478;
  --coral-ink: #B3252A;
  --on-coral: #3D0D10;

  /* ---- cor: superfícies claras ---- */
  --canvas: #F7F5F0;
  --surface: #FFFFFF;
  --ice: #DCEAF4;

  /* ---- cor: texto sobre claro ---- */
  --ink: #0B1F3A;
  --body: #3A4653;
  --mute: #5C6875;
  --hairline: #D8D3C9;

  /* ---- cor: sobre navy ---- */
  --on-dark: #F7F5F0;
  --on-dark-mute: #9FB3C8;
  --on-dark-hairline: rgba(247, 245, 240, 0.18);

  /* ---- cor: estados de formulário ---- */
  --ok: #0F6E42;
  --err: #B3252A;
  --err-soft: #FBE9E9;

  /* ---- tipo ---- */
  --font-display: "Archivo", "Inter", system-ui, -apple-system, sans-serif;
  --font: "Inter", system-ui, -apple-system, sans-serif;

  --display-hero: 800 clamp(44px, 7vw, 88px) / 0.98 var(--font-display);
  --display-xl:   800 clamp(34px, 4.6vw, 56px) / 1.03 var(--font-display);
  --display-lg:   700 clamp(28px, 3.4vw, 40px) / 1.08 var(--font-display);
  --display-md:   700 clamp(22px, 2.6vw, 28px) / 1.15 var(--font-display);
  --title-lg:     700 20px / 1.3 var(--font-display);
  --title-sm:     600 17px / 1.4 var(--font);
  --body-lg:      400 17px / 1.6 var(--font);
  --body-md:      400 15px / 1.5 var(--font);
  --caption:      500 13px / 1.35 var(--font);
  --eyebrow-font: 600 12px / 1.3 var(--font);
  --button:       600 15px / 1 var(--font);
  --prose:        400 19px / 1.72 var(--font);

  --tracking-hero: -0.03em;
  --tracking-xl: -0.02em;
  --tracking-lg: -0.015em;
  --tracking-caps: 0.14em;

  /* ---- raio: pílula existe, e só no CTA ---- */
  --r-none: 0;
  --r-sm: 4px;
  --r-md: 10px;
  --r-pill: 999px;

  /* ---- espaço: base 4px ---- */
  --s-xxs: 4px;
  --s-xs: 8px;
  --s-sm: 12px;
  --s-md: 16px;
  --s-lg: 24px;
  --s-xl: 32px;
  --s-xxl: 48px;
  --s-section: 112px;

  --container: 1200px;
  --gutter: var(--s-xxl);
  --measure: 68ch;

  /* ---- ritmo ---- */
  --t-fast: 120ms;
  --t-base: 200ms;
}

@media (max-width: 768px) { :root { --s-section: 72px; --gutter: var(--s-lg); } }
@media (max-width: 480px) {
  :root {
    --s-section: 56px;
    --gutter: var(--s-md);
    /* A prosa cai pra 17px no celular. Não é estética: com 375px de tela e os
       gutters, 19px rende 29 caracteres por linha — abaixo do confortável até
       pro padrão mais curto de mobile. A 17px são 32. Medido, não estimado. */
    --prose: 400 17px / 1.7 var(--font);
  }
}

/* ============================================================
   RESET
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font: var(--body-lg);
  color: var(--body);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
h1, h2, h3, h4 { color: var(--ink); font-family: var(--font-display); font-weight: 700; }
ul, ol { padding: 0; list-style: none; }
img, svg, video, iframe { max-width: 100%; display: block; }
/* height:auto é obrigatório: width/height do HTML sobrepõem aspect-ratio,
   que só vale quando a altura é auto. */
img { height: auto; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
/* O anel de foco NÃO usa coral. Indicador não-textual tem piso de 3:1 (WCAG
   1.4.11) e coral dá 2.81:1 sobre --canvas e 2.49:1 sobre --ice — some
   justamente na banda do formulário de newsletter. --ink dá 15.2:1 sobre
   canvas; sobre navy o anel vira --on-dark. A mesma trava do texto vale aqui:
   é o par que reprova, não a cor. */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.band--navy :focus-visible,
.bio :focus-visible,
.auth-shell :focus-visible,
.consent :focus-visible,
.pub-footer :focus-visible { outline-color: var(--on-dark); }
[hidden] { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   UTILITÁRIOS
   ============================================================ */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.sr-only {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.eyebrow {
  font: var(--eyebrow-font);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--mute);
}
.stack > * + * { margin-top: var(--s-md); }

/* ============================================================
   BOTÕES
   Pílula existe, e só aqui. Um CTA primário por dobra.
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-xs);
  min-height: 48px;
  padding: 0 var(--s-lg);
  border-radius: var(--r-pill);
  font: var(--button);
  text-align: center;
  cursor: pointer;
  border: 1.5px solid transparent;
  transition: background-color var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.btn--sm { min-height: 40px; padding: 0 var(--s-md); font-size: 14px; }

.btn--primary { background: var(--coral); color: var(--on-coral); }
.btn--primary:hover { background: var(--coral-hover); }

.btn--secondary { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--secondary:hover { background: var(--ink); color: var(--canvas); }

.btn--on-dark { background: var(--on-dark); color: var(--navy); }
.btn--on-dark:hover { background: var(--ice); }


/* Ghost: ação terciária, sem peso visual. Usado nas páginas de estado da
   newsletter (confirm/unsubscribe), onde o CTA é um convite, não uma ação. */
.btn--ghost { background: transparent; color: var(--coral-ink); padding-inline: 0; }
.btn--ghost:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* Secundário dentro de banda escura vira contorno claro. */
.band--navy .btn--secondary { color: var(--on-dark); border-color: var(--on-dark); }
.band--navy .btn--secondary:hover { background: var(--on-dark); color: var(--navy); }
/* Dentro de banda coral o primário coral sumiria — vira sólido escuro. */
.band--coral .btn--primary { background: var(--on-coral); color: var(--coral); }
.band--coral .btn--primary:hover { background: var(--navy-deep); color: var(--on-dark); }
.band--coral .btn--secondary { color: var(--on-coral); border-color: var(--on-coral); }

/* ============================================================
   FORMULÁRIOS
   ============================================================ */
.input {
  width: 100%;
  min-height: 48px;
  padding: 0 var(--s-md);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
}
.input::placeholder { color: var(--mute); }
.input:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; border-color: transparent; }

.field { display: block; flex: 1 1 260px; }

.form-row { display: flex; flex-wrap: wrap; gap: var(--s-sm); align-items: stretch; }
.form-row .btn { flex: 0 0 auto; }

.form-field { display: block; margin-bottom: var(--s-md); }
.form-field__label { display: block; font: var(--caption); color: var(--ink); margin-bottom: var(--s-xxs); }
.form-field__input { width: 100%; min-height: 48px; padding: 0 var(--s-md);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: var(--r-sm); }
.form-field__input:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.form-field__hint { display: block; font: var(--caption); color: var(--mute); margin-top: var(--s-xxs); }
.form-field__error { display: block; font: var(--caption); color: var(--err); margin-top: var(--s-xxs); }
/* Markup real (shared/_form_field partial) põe .is-invalid no wrapper
   .form-field, não no input — descendente, não mesmo elemento, ao contrário
   do texto literal do brief. Sem isso o estado de erro do Devise não pinta. */
.form-field.is-invalid .form-field__input { border-color: var(--err); }

.alert-banner {
  padding: var(--s-sm) var(--s-md);
  border-radius: var(--r-sm);
  background: var(--ice);
  color: var(--ink);
  font: var(--body-md);
  margin-bottom: var(--s-md);
}
.alert-banner--err { background: var(--err-soft); color: var(--err); }

/* Formulário dentro de banda escura: rótulo e dica ganham contraste. */
.band--navy .form-field__label { color: var(--on-dark); }
.band--navy .form-field__hint { color: var(--on-dark-mute); }

/* ============================================================
   TAGS E CHIPS

   Decisão de design: blog_helper.rb emite tag/tag--1..4 (N por
   category.id % 4). No dialeto anterior isso eram 4 cores signature
   diferentes; numa grade de cards, 4 acentos competindo na mesma dobra viola
   a regra de 1 acento por dobra. Categoria é metadado, não acento — as 4
   variantes renderizam idênticas. Classes preservadas pro helper (fora de
   escopo desta tarefa), só param de codificar cor.
   ============================================================ */
.tag, .tag--1, .tag--2, .tag--3, .tag--4,
.chip, .tag-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-xxs);
  min-height: 32px;
  padding: 0 var(--s-sm);
  background: var(--ice);
  color: var(--navy);
  border-radius: var(--r-sm);
  font: var(--caption);
}
.tag-link:hover { background: var(--navy); color: var(--on-dark); }
.tag-link__count { color: var(--mute); }
.tag-link:hover .tag-link__count { color: var(--on-dark-mute); }
/* Categoria ativa no trilho do blog. blog/index.html.erb marca aria-current
   na categoria corrente; sem isto o trilho não mostra onde o leitor está. */
.tag-link[aria-current="page"] { background: var(--navy); color: var(--on-dark); }
.tag-link[aria-current="page"] .tag-link__count { color: var(--on-dark-mute); }
.chip-row { display: flex; flex-wrap: wrap; gap: var(--s-xs); }
.caps { text-transform: uppercase; letter-spacing: var(--tracking-caps); }

/* ============================================================
   CARDS
   Card é superfície de conteúdo: branco, hairline, sem sombra.
   ============================================================ */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--s-xs);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: var(--s-md);
  height: 100%;
}
.card__thumb { width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--r-sm); margin-bottom: var(--s-xs); }
.card__thumb--empty { background: var(--ice); }
.card__title { font: var(--title-sm); color: var(--ink); }
.card__title a { transition: color var(--t-fast); }
.card__title a:hover { color: var(--mute); }
/* Card de destaque (shared/_article_card, hero: true): título sobe pra
   --display-md, mesma escala do título de EMPTY STATE. */
.card--hero .card__title { font: var(--display-md); }
.card__desc { font: var(--body-md); color: var(--body); }
.card__meta { font: var(--caption); color: var(--mute); }
.card:hover { border-color: var(--ink); }

.card-grid { display: grid; gap: var(--s-lg); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.card-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .card-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .card-grid--3 { grid-template-columns: minmax(0, 1fr); } }

/* ============================================================
   EMPTY STATE
   ============================================================ */

.empty { text-align: center; padding-block: var(--s-xxl); }
.empty__icon { font-size: 40px; color: var(--coral-ink); margin-bottom: var(--s-sm); }
.empty__title { font: var(--display-md); color: var(--ink); margin-bottom: var(--s-xs); }
.empty__body { font: var(--body-lg); color: var(--mute); }
/* O CTA é filho direto do .empty — link_to rende um .btn, button_to rende um
   <form>. Sem esta margem o botão encosta no corpo do texto. */
.empty > .btn, .empty > form { margin-top: var(--s-lg); }

/* ============================================================
   NAV
   ============================================================ */
/* nav_controller.js alterna `is-open` e `is-scrolled` na própria <nav>, não no
   menu — por isso os seletores de estado descem a partir de .pub-nav, e não de
   .pub-nav__mobile. Não mexa no JS pra "consertar" isso.
   Sticky é herdado do dialeto anterior de propósito: o controller mantém
   `is-scrolled` enquanto scrollY > 8, e a sombra desse estado só faz sentido
   se a barra acompanha a rolagem. */
.pub-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--canvas);
  border-bottom: 1px solid var(--hairline);
}
.pub-nav__inner { display: flex; align-items: center; gap: var(--s-lg); min-height: 72px; }
.pub-nav__brand { display: inline-flex; align-items: center; gap: var(--s-xs);
  font-family: var(--font-display); font-weight: 800; color: var(--ink); }
.orb {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--r-sm);
  background: var(--coral); color: var(--on-coral);
  font-family: var(--font-display); font-weight: 800; font-size: 22px;
  line-height: 1; padding-top: 10px;
}
.pub-nav__links { display: flex; gap: var(--s-lg); margin-left: auto; font: var(--title-sm); }
.pub-nav__links a { color: var(--ink); padding-block: var(--s-xs); }
.pub-nav__links a:hover { color: var(--coral-ink); }
.pub-nav__links a[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--coral); }
.pub-nav__cta { flex: 0 0 auto; }
.pub-nav__burger { display: none; flex-direction: column; gap: 5px; width: 44px; height: 44px;
  align-items: center; justify-content: center; margin-left: auto; }
.pub-nav__burger span { display: block; width: 22px; height: 2px; background: var(--ink); }
.pub-nav__mobile { display: none; flex-direction: column; padding: var(--s-md) var(--gutter) var(--s-lg);
  border-top: 1px solid var(--hairline); }
.pub-nav__mobile a { padding-block: var(--s-sm); font: var(--title-sm); color: var(--ink); }

/* ATENÇÃO: nav_controller.js alterna `is-open` e `is-scrolled` na própria <nav>,
   não no menu. O seletor precisa descer a partir dela. */
.pub-nav.is-open .pub-nav__mobile { display: flex; }
.pub-nav.is-scrolled { box-shadow: 0 1px 0 var(--hairline); }

@media (max-width: 860px) {
  .pub-nav__links, .pub-nav__cta { display: none; }
  .pub-nav__burger { display: flex; }
}

/* ============================================================
   RODAPÉ
   ============================================================ */
.pub-footer { background: var(--navy-deep); color: var(--on-dark-mute); padding-block: var(--s-section) var(--s-xl); }
.pub-footer__grid { display: grid; gap: var(--s-xl);
  grid-template-columns: minmax(0, 1.6fr) repeat(auto-fit, minmax(140px, 1fr)); }
.pub-footer__brand { display: inline-flex; align-items: center; gap: var(--s-xs);
  font-family: var(--font-display); font-weight: 800; font-size: 20px; color: var(--on-dark); }
.pub-footer__desc { font: var(--body-md); color: var(--on-dark-mute); margin-top: var(--s-sm); max-width: 42ch; }
.pub-footer__col-title { font: var(--caption); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--on-dark); margin-bottom: var(--s-sm); }
.pub-footer__col a { display: block; padding-block: var(--s-xxs); color: var(--on-dark-mute); }
.pub-footer__col a:hover { color: var(--on-dark); }
.pub-footer__bottom { margin-top: var(--s-xxl); padding-top: var(--s-md);
  border-top: 1px solid var(--on-dark-hairline); font: var(--caption); color: var(--on-dark-mute); }
@media (max-width: 700px) { .pub-footer__grid { grid-template-columns: minmax(0, 1fr); } }

/* ============================================================
   CONSENTIMENTO
   ============================================================ */
.consent {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 60;
  background: var(--navy); color: var(--on-dark-mute);
  border-top: 1px solid var(--on-dark-hairline);
  padding: var(--s-md) var(--gutter);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-md);
}
.cb-consent__text { flex: 1 1 320px; font: var(--body-md); }
.cb-consent__link { color: var(--on-dark); text-decoration: underline; }
.consent__actions { display: flex; gap: var(--s-xs); margin-left: auto; }

/* Barra é sempre navy — .btn--secondary padrão (tinta ink sobre borda ink)
   some contra o fundo escuro. Mesmo tratamento de .band--navy .btn--secondary. */
.consent .btn--secondary { color: var(--on-dark); border-color: var(--on-dark); }
.consent .btn--secondary:hover { background: var(--on-dark); color: var(--navy); }

/* ============================================================
   BANDA E MOTIVO
   A página é uma pilha de bandas full-bleed, não uma grade de
   cards. Banda não tem raio, sombra nem borda — só cor chapada.
   ============================================================ */
.band {
  padding-block: var(--s-section);
  background: var(--canvas);
  color: var(--body);
  border-radius: var(--r-none);
}
.band--tight { padding-block: var(--s-xxl); }

.band--navy { background: var(--navy); color: var(--on-dark-mute); }
.band--navy h1, .band--navy h2, .band--navy h3, .band--navy h4 { color: var(--on-dark); }
.band--navy .eyebrow { color: var(--on-dark-mute); }
/* :not(.btn) é essencial: sem ele esta regra vence as classes de botão por
   especificidade e pinta o texto do CTA da cor do próprio fundo dele. Um link
   de texto na banda herda a cor; um botão fica com a sua. */
.band--navy a:not(.btn) { color: var(--on-dark); }

.band--coral { background: var(--coral); color: var(--on-coral); }
.band--coral h1, .band--coral h2, .band--coral h3, .band--coral h4 { color: var(--on-coral); }
/* Sólido, sem opacity: --on-coral a 72% de opacidade sobre --coral mede
   3.44:1 e reprova AA — a mesma trava de contraste de TOKENS vale aqui.
   band--navy e band--ice já usam token maciço (--on-dark-mute / --mute) pro
   eyebrow; aqui não existe token "mute sobre coral" dedicado, então o
   eyebrow usa --on-coral sólido (5.45:1) como o resto do texto da banda. */
.band--coral .eyebrow { color: var(--on-coral); }
.band--coral a:not(.btn) { color: var(--on-coral); }

.band--ice { background: var(--ice); color: var(--body); }
.band--ice .eyebrow { color: var(--mute); }

.band--canvas { background: var(--canvas); }

/* Banda dividida: texto à esquerda, ação/mídia à direita. */
.band__split {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: var(--s-xxl);
  align-items: center;
}
@media (max-width: 900px) {
  .band__split { grid-template-columns: minmax(0, 1fr); gap: var(--s-xl); }
}

/* Conteúdo de banda. Herdam cor do modificador da banda — nunca fixam cor. */
.band__title { font: var(--display-xl); letter-spacing: var(--tracking-xl); max-width: 18ch; }
.band__body { font: var(--body-lg); margin-top: var(--s-md); max-width: 52ch; }
.band__actions { display: flex; flex-wrap: wrap; gap: var(--s-sm); }

/* ---- motivo de aspas ----
   O ” do logo em escala grande. É o que amarra as bandas entre si.
   Decorativo: sempre aria-hidden. Nunca entra no fluxo. */
.band__has-mark { position: relative; overflow: hidden; }
.quote-mark {
  position: absolute;
  top: -0.14em;
  right: var(--s-lg);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(120px, 18vw, 280px);
  line-height: 0.7;
  color: var(--coral);
  pointer-events: none;
  user-select: none;
}
.quote-mark--ink { color: var(--ink); }
.quote-mark--soft { color: var(--on-coral); opacity: 0.22; }
.quote-mark--left { right: auto; left: var(--s-lg); }
.quote-mark--inline {
  position: static;
  font-size: clamp(56px, 7vw, 96px);
  display: block;
  margin-bottom: calc(var(--s-md) * -1);
}
@media (max-width: 600px) {
  .quote-mark { font-size: clamp(88px, 26vw, 140px); right: var(--s-xs); }
}

/* ============================================================
   NEWSLETTER
   ============================================================ */

.pub-news__legal { font: var(--caption); color: var(--mute); margin-top: var(--s-sm); max-width: 46ch; }
.pub-news__legal a { text-decoration: underline; }

/* Retorno do turbo_stream depois de inscrever. */
.pub-news__success {
  font: var(--body-lg);
  color: var(--ink);
  padding: var(--s-md) 0;
}
.pub-news__success::before { content: "✓"; color: var(--ok); margin-right: var(--s-xs); }

/* Páginas de chegada do double opt-in (confirm/unsubscribe) — canvas, texto
   centrado, medida curta. Sem nav de conteúdo. */
.news-state { padding-block: var(--s-section); text-align: center; }
.news-state__title { font: var(--display-lg); letter-spacing: var(--tracking-lg);
  color: var(--ink); margin-top: var(--s-sm); }
.news-state__body { font: var(--body-lg); color: var(--body);
  max-width: 52ch; margin: var(--s-md) auto 0; }
.news-state__cta { margin-top: var(--s-lg); }

/* ============================================================
   HOME
   ============================================================ */
.pub-hero__inner { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: var(--s-xxl); align-items: center; position: relative; z-index: 1; }
.pub-hero__title { font: var(--display-hero); letter-spacing: var(--tracking-hero);
  color: var(--on-dark); margin-block: var(--s-sm) var(--s-md); max-width: 15ch; }
.pub-hero__lede { font: var(--body-lg); color: var(--on-dark-mute); max-width: 46ch; margin-bottom: var(--s-lg); }
.pub-hero__form { max-width: 520px; }
.pub-hero__cred { font: var(--caption); color: var(--on-dark-mute); margin-top: var(--s-sm); }
.pub-hero__media img { border-radius: var(--r-md); }
@media (max-width: 900px) {
  .pub-hero__inner { grid-template-columns: minmax(0, 1fr); }
  .pub-hero__media { order: -1; max-width: 260px; }
}

/* Tira de credenciais: divisor entre hairlines, não banda. */
.pub-facts { border-block: 1px solid var(--hairline); background: var(--canvas); }
.pub-facts__inner { display: flex; flex-wrap: wrap; gap: var(--s-lg);
  padding-block: var(--s-md); font: var(--caption); color: var(--mute); }
.pub-facts__item { display: flex; align-items: center; gap: var(--s-xs); }
.pub-facts__item::before { content: "”"; font-family: var(--font-display);
  font-weight: 800; color: var(--coral-ink); font-size: 18px; line-height: 0; }

/* Cabeçalho de seção sobre canvas. */
.pub-section__head { display: flex; flex-wrap: wrap; gap: var(--s-lg);
  align-items: end; justify-content: space-between; margin-bottom: var(--s-xl); }
.pub-section__title { font: var(--display-lg); letter-spacing: var(--tracking-lg); color: var(--ink); }
.pub-section__sub { font: var(--body-lg); color: var(--mute); margin-top: var(--s-xs); max-width: 52ch; }
.pub-section__grid { margin-top: var(--s-xl); }
.pub-section__foot { margin-top: var(--s-xl); }
.pub-tabs { display: flex; flex-wrap: wrap; gap: var(--s-xs); }
.pub-tabs__link { display: inline-flex; align-items: center; min-height: 36px;
  padding: 0 var(--s-sm); border-radius: var(--r-sm); background: var(--ice);
  color: var(--navy); font: var(--caption); }
.pub-tabs__link:hover { background: var(--navy); color: var(--on-dark); }

/* Revista: chamada grande + lista lateral. */
.pub-mag { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--s-xxl); }
.pub-mag__lead-media img { border-radius: var(--r-md); margin-bottom: var(--s-sm); }
.pub-mag__lead-title { font: var(--display-md); color: var(--ink); margin-block: var(--s-xs); }
.pub-mag__lead-title a:hover { color: var(--coral-ink); }
.pub-mag__lead-excerpt { font: var(--body-lg); color: var(--body); margin-bottom: var(--s-xs); }
.pub-mag__list { display: flex; flex-direction: column; }
.pub-mag__item + .pub-mag__item { border-top: 1px solid var(--hairline); }
.pub-mag__item-link { display: flex; gap: var(--s-sm); padding-block: var(--s-md); align-items: center; }
.pub-mag__item-thumb { width: 72px; height: 72px; object-fit: cover;
  border-radius: var(--r-sm); flex: 0 0 auto; }
.pub-mag__item-thumb--empty { background: var(--ice); display: block; }
/* Sem min-width:0 o filho flex herda min-width:auto e o título comprido
   estoura a largura do container, causando rolagem horizontal. */
.pub-mag__item-body { min-width: 0; }
.pub-mag__item-title { display: block; font: var(--title-sm); color: var(--ink); }
.pub-mag__item-link:hover .pub-mag__item-title { color: var(--coral-ink); }
.pub-mag__item-date { display: block; font: var(--caption); color: var(--mute); margin-top: var(--s-xxs); }
@media (max-width: 900px) { .pub-mag { grid-template-columns: minmax(0, 1fr); gap: var(--s-xl); } }

/* Retrato da banda "quem escreve". */
.pub-about__photo-wrap { display: flex; justify-content: center; }
.pub-about__photo { width: 100%; max-width: 320px; border-radius: var(--r-md); }

/* Vídeos. */
.pub-videos__grid { display: grid; gap: var(--s-lg);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
/* Sem min-width:0 o item de grid herda min-width:auto e um título comprido
   estoura a coluna, causando rolagem horizontal. */
.pub-videos__card { min-width: 0; }
.pub-videos__thumb-link { position: relative; display: block; }
.pub-videos__thumb { width: 100%; border-radius: var(--r-md); }
.pub-videos__play { position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center; font-size: 40px; color: var(--on-dark); }
.pub-videos__title { font: var(--title-sm); color: var(--ink); margin-top: var(--s-xs); }
.pub-videos__title a:hover { color: var(--coral-ink); }
.pub-videos__date { font: var(--caption); color: var(--mute); margin-top: var(--s-xxs); }

/* ============================================================
   BLOG
   ============================================================ */
.pub-blog-hero__inner { position: relative; z-index: 1; }
.pub-blog-hero__eyebrow { font: var(--eyebrow-font); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--on-dark-mute); }
.pub-blog-hero__title { font: var(--display-xl); letter-spacing: var(--tracking-xl);
  color: var(--on-dark); margin-block: var(--s-sm) var(--s-md); max-width: 18ch; }
.pub-blog-hero__sub { font: var(--body-lg); color: var(--on-dark-mute); max-width: 52ch; }

.pub-blog { padding-block: var(--s-section); }
.pub-blog__rail { display: flex; flex-wrap: wrap; gap: var(--s-xs);
  padding-bottom: var(--s-lg); margin-bottom: var(--s-xl);
  border-bottom: 1px solid var(--hairline); }
.pub-blog__rail-title { font: var(--caption); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--mute);
  width: 100%; margin-bottom: var(--s-xs); }
/* NÃO transformar em grade: o markup já traz um .card-grid--3 aqui dentro, e
   duas grades aninhadas espremem os cards a ~101px. Quem faz as colunas é o
   .card-grid; esta seção só empilha e dá o ritmo vertical. */
.pub-blog__list { display: block; }
.pub-blog__list > * + * { margin-top: var(--s-lg); }

/* .pub-ad é declarado uma vez só, na seção ARTIGO. Aqui fica APENAS o delta do
   índice, escopado — antes as duas seções declaravam a mesma classe e a de
   ARTIGO vencia por vir depois, deixando estes valores mortos e dando 48px de
   respiro onde a intenção era 16px. */
.pub-blog__list .pub-ad { margin-block: var(--s-md); }
.pub-blog__list .pub-ad--bottom { margin-top: var(--s-xl); margin-bottom: var(--s-xxl); }
.card-grid .pub-ad { grid-column: 1 / -1; }

/* ============================================================
   ARTIGO
   Superfície de leitura: medida curta, sem banda de cor no corpo.
   ============================================================ */
.pub-article { padding-block: var(--s-xxl) var(--s-section); }

/* ---- cabeçalho ---- */
.pub-article__header { margin-bottom: var(--s-xl); }
.pub-article__header-inner { max-width: calc(var(--measure) + var(--gutter) * 2); margin-inline: auto; }
.pub-article__title { font: var(--display-xl); letter-spacing: var(--tracking-xl);
  color: var(--ink); margin-block: var(--s-sm); }
.pub-article__meta { font: var(--caption); color: var(--mute); display: flex;
  flex-wrap: wrap; gap: var(--s-xs); margin-top: var(--s-md); padding-bottom: var(--s-lg);
  border-bottom: 1px solid var(--hairline); }
.pub-article__meta a { color: var(--ink); }

/* ---- coluna de leitura ----
   font: var(--prose) aqui (não só em .pub-article__body) porque `ch` resolve
   contra o font-size do PRÓPRIO elemento — herdar o --body-lg do body (17px)
   faria 68ch medir a largura de 68 caracteres a 17px, não a 19px da prosa
   real, e a coluna renderizaria ~61ch em vez de 68ch. Filhos com texto (tldr,
   meta, fontes, autor etc.) já fixam a própria fonte, então isso não vaza. */
/* O elemento também é .container, e com box-sizing:border-box os dois gutters
   entram dentro do max-width — 68ch de caixa rendiam só 60ch de texto. O calc
   devolve a medida ao TEXTO, que é o que --measure quer dizer. */
.pub-article__col { max-width: calc(var(--measure) + var(--gutter) * 2);
  margin-inline: auto; font: var(--prose); color: var(--body); }

.pub-article__cover { border-radius: var(--r-md); margin-bottom: var(--s-xl); overflow: hidden; }
/* aspect-ratio + object-fit vinham do dialeto anterior e se perderam na
   migração: sem eles a capa depende só dos atributos width/height do
   image_tag, e uma imagem fora de proporção deforma a dobra do artigo. */
.pub-article__cover img { width: 100%; display: block;
  aspect-ratio: 40 / 21; object-fit: cover; }

/* Resumo: callout claro, a superfície suave do sistema — antes do corpo,
   nunca dentro dele (regra do dialeto: nenhuma banda de cor corta a prosa). */
.pub-article__tldr { background: var(--ice); border-radius: var(--r-md);
  padding: var(--s-lg); font: var(--body-lg); color: var(--ink); margin-top: var(--s-xl); }
.pub-article__tldr p + p { margin-top: var(--s-xs); }

/* ---- prosa ---- */
.pub-article__body { font: var(--prose); color: var(--body); margin-top: var(--s-xl); }

.md-content > * + * { margin-top: var(--s-lg); }
.md-content h2 { font: var(--display-md); color: var(--ink); margin-top: var(--s-xxl); }
.md-content h3 { font: var(--title-lg); color: var(--ink); margin-top: var(--s-xl); }
/* :not() é a mesma trava de .band--navy a: esta regra tem a especificidade de
   um seletor de classe e vem depois de .btn/.tag no arquivo, então repintaria
   um botão embutido no corpo do artigo com a cor de link. */
.md-content a:not(.btn):not(.tag):not(.tag-link) {
  color: var(--coral-ink); text-decoration: underline; text-underline-offset: 2px; }
.md-content strong { font-weight: 600; color: var(--ink); }
.md-content ul, .md-content ol { padding-left: var(--s-lg); }
.md-content li { list-style: disc; margin-top: var(--s-xs); }
.md-content ol li { list-style: decimal; }
.md-content img { border-radius: var(--r-md); }
.md-content code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.88em; }
.md-content pre { background: var(--navy); color: var(--on-dark);
  padding: var(--s-md); border-radius: var(--r-md); overflow-x: auto; }
.md-content pre code { background: none; padding: 0; color: inherit; }
.md-content blockquote {
  border-left: 4px solid var(--coral);
  padding-left: var(--s-md);
  color: var(--ink);
  font-style: normal;
}
.md-content table { width: 100%; border-collapse: collapse; font: var(--body-lg); }
.md-content th, .md-content td {
  text-align: left;
  padding: var(--s-xs) var(--s-sm);
  border-bottom: 1px solid var(--hairline);
}
.md-content th { color: var(--ink); font-weight: 500; }
/* .md-anchor: link "#" que BlogHelper::HeadingAnchorRenderer injeta em todo
   h2..h6 do markdown. Ficou órfão na migração — o arquivo que o estilizava
   (pages/article.css) não faz parte de nenhum bundle carregado hoje. */
.md-content .md-anchor { color: var(--mute); margin-right: var(--s-xs); text-decoration: none; }
.md-content h2:hover .md-anchor, .md-content h3:hover .md-anchor { color: var(--coral-ink); }

.pub-article__h2 { font: var(--display-md); color: var(--ink); }

/* ---- vídeo ---- */
.pub-article__video { margin-top: var(--s-xl); }
.pub-article__video-frame { aspect-ratio: 16 / 9; border-radius: var(--r-md); overflow: hidden;
  position: relative; background: var(--navy); margin-top: var(--s-xs); }
.pub-article__video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ---- FAQ ---- */
.pub-article__faq { margin-top: var(--s-xxl); }
.pub-article__faq dt { font: var(--title-sm); color: var(--ink); margin-top: var(--s-md); }
.pub-article__faq dd { font: var(--prose); color: var(--body); margin: var(--s-xxs) 0 0; }

/* ---- fontes ---- */
.pub-article__sources { margin-top: var(--s-xxl); font: var(--body-md); color: var(--mute);
  padding-top: var(--s-md); border-top: 1px solid var(--hairline); }
.pub-article__sources .caps { font: var(--caption); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--ink); }
.pub-article__sources li { margin-top: var(--s-xxs); }
.pub-article__sources a { color: var(--coral-ink); text-decoration: underline; }

/* ---- anúncios: posição e comportamento preservados ---- */
.pub-ad { margin-block: var(--s-xxl); }
.pub-ad--bottom { margin-bottom: 0; }
.adsense-block { display: block; }

/* ---- reações ---- */
.pub-reactions { margin-top: var(--s-xxl); }
.pub-reactions__title { font: var(--title-lg); color: var(--ink); margin-bottom: var(--s-sm); }

/* ---- assinatura do autor ---- */
.pub-author { display: flex; gap: var(--s-md); align-items: center;
  margin-top: var(--s-xxl); padding-top: var(--s-lg); border-top: 1px solid var(--hairline); }
.pub-author__photo { width: 64px; height: 64px; border-radius: var(--r-pill); flex: 0 0 auto; object-fit: cover; }
.pub-author__name { font: var(--title-sm); color: var(--ink); }
.pub-author__desc { font: var(--body-md); color: var(--mute); max-width: 56ch; }

/* ---- relacionados ---- */
.pub-related { margin-top: var(--s-section); }
.pub-related .card-grid { margin-top: var(--s-lg); }

@media (max-width: 600px) {
  .pub-author { flex-direction: column; align-items: flex-start; }
}

/* ============================================================
   LEGAIS E PÁGINAS DE TEXTO
   Documento é documento: canvas, prosa, sem banda de cor.
   ============================================================ */
.pub-page-hero { padding-block: var(--s-xxl) var(--s-lg); border-bottom: 1px solid var(--hairline); }
.pub-page-hero__title { font: var(--display-xl); letter-spacing: var(--tracking-xl); color: var(--ink); }
.pub-page-hero__sub { font: var(--body-lg); color: var(--mute); margin-top: var(--s-xs); max-width: 52ch; }

.pub-legal { padding-block: var(--s-xxl) var(--s-section); }
/* O elemento é `pub-legal__body md-content` — as DUAS classes valem ao mesmo
   tempo. Toda a prosa (títulos, listas, links, código, citação, tabela) já vem
   de .md-content na seção ARTIGO; redeclarar aqui não sobrescrevia, SOMAVA:
   margin-left daqui + padding-left de lá indentavam a lista em dobro, e um
   `a` sem guarda anulava o :not(.btn) de .md-content a.
   Esta seção só declara o que a página legal tem de diferente do artigo: a
   medida e o corpo em 17px, porque documento não é leitura longa. */
.pub-legal__body { max-width: var(--measure); font: var(--body-lg); color: var(--body); }

.pub-about-page { padding-block: var(--s-section); }
.pub-about-page__body { max-width: var(--measure); font: var(--prose); color: var(--body); }
.pub-about-page__body > * + * { margin-top: var(--s-lg); }
.pub-about-page__body a:not(.btn):not(.tag):not(.tag-link) { color: var(--coral-ink); text-decoration: underline; }
.pub-about-page__list li { list-style: disc; margin-left: var(--s-lg); margin-top: var(--s-xs); }
.pub-about-page__photo-wrap { margin-bottom: var(--s-xl); }
.pub-about-page__photo-wrap img { border-radius: var(--r-md); max-width: 320px; }

/* ============================================================
   BIO — /@handle
   Exceção ao claro dominante: superfície de link-in-bio, navy inteira.
   Lida em segundos no celular, não é superfície de leitura.
   ============================================================ */
.bio-body { background: var(--navy); }
.bio {
  max-width: 560px;
  margin-inline: auto;
  padding: var(--s-section) var(--gutter);
  position: relative;
  overflow: hidden;
}

/* ---- hero ---- */
.bio__hero { text-align: center; margin-bottom: var(--s-xl); }
.bio__avatar {
  width: 112px;
  height: 112px;
  border-radius: var(--r-pill);
  margin-inline: auto;
  object-fit: cover;
}
.bio__avatar--placeholder {
  background: var(--ice);
  display: flex;
  align-items: center;
  justify-content: center;
  font: var(--display-md);
  color: var(--navy);
}
.bio__headline {
  font: var(--display-lg);
  letter-spacing: var(--tracking-lg);
  color: var(--on-dark);
  margin-top: var(--s-md);
}
.bio__subheadline { font: var(--body-lg); color: var(--on-dark-mute); margin-top: var(--s-xs); }

/* ---- grupos de links ---- */
.bio__groups { display: flex; flex-direction: column; gap: var(--s-xl); }
.bio__group-label {
  font: var(--caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--on-dark-mute);
  margin-bottom: var(--s-sm);
}
.bio__group-links { display: flex; flex-direction: column; gap: var(--s-sm); }

.bio__link {
  display: flex;
  align-items: center;
  gap: var(--s-sm);
  min-height: 56px;
  padding: 0 var(--s-md);
  background: var(--on-dark);
  color: var(--navy);
  border-radius: var(--r-md);
}
.bio__link:hover { background: var(--ice); }
.bio__link-icon { flex: 0 0 auto; font-size: 20px; }
.bio__link-title { font: var(--title-sm); flex: 1 1 auto; }
.bio__link-arrow { color: var(--coral-ink); }

/* ---- captura de e-mail ---- */
.bio__capture { margin-top: var(--s-xl); padding: var(--s-lg); background: var(--navy-deep); border-radius: var(--r-md); }
.bio__capture-label { font: var(--title-sm); color: var(--on-dark); display: block; margin-bottom: var(--s-xs); }
.bio__capture-hint { font: var(--caption); color: var(--on-dark-mute); margin-bottom: var(--s-sm); }
/* Link inline sobre superfície escura: mesma trava de .band--navy a — herda
   var(--on-dark), nunca coral-ink (que só passa AA sobre claro). */
.bio__capture-hint a { color: var(--on-dark); text-decoration: underline; text-underline-offset: 2px; }
.bio__capture-row { display: flex; flex-wrap: wrap; gap: var(--s-xs); }
.bio__input {
  flex: 1 1 200px;
  min-height: 48px;
  padding: 0 var(--s-md);
  background: var(--on-dark);
  color: var(--ink);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
}
.bio__capture-btn { min-height: 48px; padding: 0 var(--s-lg); border-radius: var(--r-pill); background: var(--coral); color: var(--on-coral); font: var(--button); }
.bio__capture-btn:hover { background: var(--coral-hover); }
.bio__capture-error { font: var(--caption); color: var(--coral); margin-top: var(--s-xs); }

/* Retorno do turbo_stream. As classes de sucesso precisam existir: o form é
   substituído por este bloco e sem estilo o retorno cairia num vazio. */
.bio__capture--success { text-align: center; }
.bio__capture-check { font-size: 32px; color: var(--ice); }
.bio__capture-success { font: var(--body-lg); color: var(--on-dark); }

/* ---- rodapé ---- */
.bio__footer { margin-top: var(--s-section); text-align: center; }
.bio__footer-nav { display: flex; justify-content: center; gap: var(--s-md); font: var(--caption); color: var(--on-dark-mute); }
.bio__footer-nav a:hover { color: var(--on-dark); }
.bio__footer-copy { font: var(--caption); color: var(--on-dark-mute); margin-top: var(--s-xs); }

/* ============================================================
   MATERIAL
   ============================================================ */

.mat-body { background: var(--canvas); }
.mat-page { color: var(--body); }

.mat-container {
  width: 100%;
  max-width: 900px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.mat-container--narrow { max-width: 720px; }

/* ---- hero ---- */
.mat-hero {
  padding-block: var(--s-section) var(--s-xxl);
  border-bottom: 1px solid var(--hairline);
}
.mat-hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-md);
}
.mat-eyebrow {
  font: var(--caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--mute);
}
.mat-eyebrow--light { color: var(--on-dark-mute); }

.mat-print-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-xxs);
  min-height: 40px;
  padding: var(--s-xs) var(--s-sm);
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
  font: var(--body-md);
  color: var(--mute);
}
.mat-print-btn:hover { color: var(--ink); border-color: var(--ink); }

.mat-h1 { font: var(--display-lg); color: var(--ink); margin-top: var(--s-md); }
.mat-subhead { font: var(--body-lg); color: var(--body); margin-top: var(--s-md); max-width: 60ch; }
.mat-support { font: var(--caption); color: var(--mute); margin-top: var(--s-sm); }
.mat-signature { font: var(--caption); color: var(--mute); margin-top: var(--s-md); }

/* ---- botões ---- */
.mat-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-xs);
  min-height: 48px;
  margin-top: var(--s-md);
  padding: var(--s-md) var(--s-lg);
  border-radius: var(--r-md);
  font: var(--button);
  border: 1px solid transparent;
  transition: background-color var(--t-base), border-color var(--t-base);
}
/* Mesmo papel do CTA primário do resto do site — mesmos tokens, pra não
   divergir do .btn--primary de BOTÕES (coral só como fundo, nunca como texto
   sobre claro; hover CLAREIA por causa da trava de contraste em TOKENS). */
.mat-btn--primary { background: var(--coral); color: var(--on-coral); }
.mat-btn--primary:hover, .mat-btn--primary:active { background: var(--coral-hover); }
/* Usado dentro do .mat-card-ink (fundo navy): mesmo tratamento do
   .band--navy .btn--secondary — contorno claro, inverte no hover. */
.mat-btn--ghost-light { background: transparent; color: var(--on-dark); border-color: var(--on-dark); }
.mat-btn--ghost-light:hover { background: var(--on-dark); color: var(--navy); }

.mat-top-btn {
  display: inline-block;
  margin-top: var(--s-lg);
  font: var(--body-md);
  color: var(--coral-ink);
  text-decoration: underline;
}

/* ---- seções ---- */
.mat-section { padding-block: var(--s-xxl); }
.mat-section--soft { background: var(--ice); }
.mat-section--ink { background: var(--navy); color: var(--on-dark); }
.mat-section--ink .mat-h2 { color: var(--on-dark); }

.mat-h2 { font: var(--display-md); color: var(--ink); }
.mat-intro { font: var(--prose); color: var(--body); margin-top: var(--s-md); }
.mat-note { font: var(--body-md); color: var(--mute); margin-top: var(--s-sm); }
.mat-mistake {
  background: var(--ice);
  border-radius: var(--r-md);
  padding: var(--s-md);
  margin-top: var(--s-md);
  font: var(--body-lg);
  color: var(--ink);
}
.mat-plan { font: var(--prose); color: var(--body); margin-top: var(--s-md); }

/* Card escuro de destaque. */
.mat-card-ink {
  background: var(--navy);
  color: var(--on-dark);
  border-radius: var(--r-md);
  padding: var(--s-xxl);
}
.mat-card-ink .mat-h2 { color: var(--on-dark); }
.mat-card-ink p { color: var(--on-dark-mute); margin-top: var(--s-sm); }

/* ---- índice das funções ---- */
.mat-index-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-lg);
  margin-top: var(--s-lg);
}
.mat-index-col { min-width: 0; }
.mat-index-title { font: var(--title-sm); color: var(--ink); }
.mat-index-sub { font: var(--body-md); color: var(--mute); margin-top: var(--s-xxs); }
.mat-index-list {
  list-style: decimal;
  padding-left: var(--s-lg);
  margin-top: var(--s-xs);
  font: var(--body-lg);
  color: var(--body);
}
.mat-index-list li { margin-top: var(--s-xxs); }
.mat-index-list a { color: var(--coral-ink); }

/* ---- funções ---- */
.mat-fn {
  padding-top: var(--s-xl);
  margin-top: var(--s-xl);
  border-top: 1px solid var(--hairline);
}
.mat-fn--star { border-top-color: var(--ink); }
.mat-fn-head { display: flex; align-items: baseline; gap: var(--s-sm); }
.mat-fn-num { font: var(--caption); color: var(--mute); flex: none; }
.mat-fn-title { font: var(--title-lg); color: var(--ink); }
.mat-fn-tease { font: var(--body-lg); color: var(--mute); margin-top: var(--s-xxs); }
.mat-fn-body { font: var(--prose); color: var(--body); margin-top: var(--s-sm); }
.mat-fn-body > * + * { margin-top: var(--s-sm); }
.mat-fn-body ul { list-style: disc; padding-left: var(--s-lg); }
.mat-fn-body a { color: var(--coral-ink); text-decoration: underline; }

/* ---- tabela ---- */
.mat-table-wrap { overflow-x: auto; margin-top: var(--s-md); }
.mat-table { width: 100%; border-collapse: collapse; font: var(--body-lg); }
.mat-table th, .mat-table td {
  text-align: left;
  padding: var(--s-xs) var(--s-sm);
  border-bottom: 1px solid var(--hairline);
}
.mat-table th { color: var(--ink); font-weight: 500; }

/* ---- rodapé ---- */
.mat-footer {
  padding-block: var(--s-xxl);
  border-top: 1px solid var(--hairline);
  font: var(--body-md);
  color: var(--mute);
}
.mat-footer-name { font: var(--caption); color: var(--ink); }

@media (max-width: 700px) {
  .mat-index-grid { grid-template-columns: 1fr; }
}

/* Impressão: a página tem botão de "salvar em PDF". */
@media print {
  .mat-print-btn, .mat-top-btn, .consent { display: none !important; }
  .mat-section--ink, .mat-card-ink { background: var(--canvas); color: var(--ink); }
  .mat-card-ink .mat-h2, .mat-section--ink .mat-h2 { color: var(--ink); }
  .mat-card-ink p { color: var(--body); }
}

/* ============================================================
   AUTH
   ============================================================ */

.auth-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-md);
  padding: var(--s-lg);
  background: var(--ice);
}

.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: var(--s-xl);
}

.auth-card__head { margin-bottom: var(--s-lg); }
.auth-card__brand {
  display: inline-block;
  font: var(--caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--mute);
}
.auth-card__title { font: var(--display-md); color: var(--ink); margin-top: var(--s-xs); }
.auth-card__sub { font: var(--body-lg); color: var(--body); margin-top: var(--s-xs); }

.auth-form { display: flex; flex-direction: column; gap: var(--s-md); }

.auth-checkbox {
  display: flex;
  align-items: center;
  gap: var(--s-xs);
  min-height: 44px;
  font: var(--body-lg);
  color: var(--body);
}

.auth-submit { width: 100%; margin-top: var(--s-sm); }

.auth-links { margin-top: var(--s-md); text-align: center; display: flex; flex-direction: column; gap: var(--s-xs); }
.auth-link { font: var(--body-md); color: var(--coral-ink); text-decoration: underline; }

.auth-footer { font: var(--caption); color: var(--mute); }
.auth-footer a { color: var(--coral-ink); text-decoration: underline; }

/* Zona de perigo — cancelamento de conta (devise/registrations/edit). Rota
   está sob skip: [:registrations] em routes.rb (inacessível hoje), mas a
   view existe e usa estas classes; sem regra ela renderiza sem estilo se a
   rota voltar a ser habilitada. */
.auth-danger {
  margin-top: var(--s-lg);
  border: 1px solid var(--err);
  border-radius: var(--r-sm);
  padding: var(--s-md);
}
.auth-danger__title { font: var(--title-sm); color: var(--err); }
.btn-danger { background: var(--err); color: var(--surface); }

/* Banner de erro/aviso do flash e dos erros de validação do Devise.
   Reaproveita .alert-banner/.alert-banner--err de FORMULÁRIOS — não
   redeclarar aqui: a versão antiga desta seção duplicava a classe com fundo
   e raio diferentes, e a ordem no arquivo faz esta sobrescrever aquela por
   inteiro, arriscando as duas divergirem a cada edição futura. */
