/* ══════════════════════════════════════════════════════════════════════════
   Base
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   Constantes de sistema (P3, GAP-10) — lugar ÚNICO dos literais de movimento,
   borda, foco, translucência e mistura de estado. Não são tokens: não vêm de
   tokens.json (D-04: compostos e curvas ficam em CSS, com guarda — ver
   scripts/audit-constants.py, que falha se o literal reaparecer fora deste bloco).
   Nomes por VALOR, como sp-N: não inventam papel que o sistema não tem.
   Fora de propósito (revisados, com motivo, na allowlist do audit): 200ms (largura
   do .progress-fill) e 700ms (spinners), a borda de 5px, linear/ease-in-out.
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
  --dur-40: 40ms;
  --dur-80: 80ms;
  --dur-120: 120ms;
  --dur-160: 160ms;
  --dur-240: 240ms;
  --dur-420: 420ms;
  --dur-1400: 1400ms;
  --border-w-1: 1px;
  --border-w-1-5: 1.5px;
  --border-w-2: 2px;
  --outline-width: 2px;
  --outline-offset: 3px;
  --outline-offset-tight: 2px;
  --outline-offset-inset: -2px;
  --glass-filter: blur(24px) saturate(180%);
  --glass-alpha: 72%;
  --state-mix: 92%;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--color-bg); color: var(--color-text);
  font: 400 1.125rem/1.7 var(--font-body); letter-spacing: 0;
  color-scheme: dark; text-wrap: pretty;
}
[data-theme="light"] { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }

/* Display and h1 are the only League Spartan text in a page. h2 down is
   Poppins: hierarchy by size and weight together, never by colour. */
.display, h1 {
  font: 700 6rem/0.88 var(--font-display); letter-spacing: -0.045em;
  color: var(--color-text-strong); margin: 0 0 var(--sp-24);
}
h1 { font: 600 3rem/1.0 var(--font-display); letter-spacing: -0.04em; }
h2 { font: 600 1.625rem/1.25 var(--font-body); letter-spacing: -0.01em; color: var(--color-text-strong); margin: 0 0 var(--sp-16); }
h3 { font: 600 1.25rem/1.3 var(--font-body); letter-spacing: -0.005em; color: var(--color-text-strong); margin: 0 0 var(--sp-16); }
h4 { font: 600 1.0625rem/1.35 var(--font-body); color: var(--color-text-strong); margin: 0 0 var(--sp-8); }
h5 { font: 600 0.9375rem/1.4 var(--font-body); color: var(--color-text-strong); margin: 0 0 var(--sp-8); }
h6, .label {
  font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--color-text-muted);
  margin: 0 0 var(--sp-8);
}
p { margin: 0 0 var(--sp-16); }
a { color: var(--color-accent); text-underline-offset: 3px; transition: color var(--dur-80) var(--ease-standard); }
a:hover { color: var(--color-text-strong); }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption { font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0; color: var(--color-text-muted); margin-top: var(--sp-8); }
small, .text-small { font-size: 0.8125rem; }
.text-muted { color: var(--color-text-muted); }
.text-secondary { color: var(--color-text-secondary); }
.text-strong { color: var(--color-text-strong); }
:focus { outline: none; }
:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
/* Alguns elementos pequenos e bem próximos uns dos outros (Slider thumb, Tabs,
   Toast close, links de Breadcrumb, Table pagination) usam outline-offset:2px
   em vez do 3px acima — proposital, não esquecimento: com 3px, o anel de foco
   de um item colado no vizinho (abas lado a lado, botões de paginação de
   32px) passaria a se sobrepor ou vazar pro elemento ao lado. */
::selection { background: var(--color-selection-bg); color: var(--color-selection-text); }

/* Movimento: respeitar prefers-reduced-motion — troca por opacidade em 120ms. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: var(--dur-120) !important; animation-iteration-count: 1 !important;
    transition-duration: var(--dur-120) !important; transition-property: opacity !important;
  }
}

/* Transparência: respeitar prefers-reduced-transparency — ver as duas regras
   de material (.translucent, .seg), mais abaixo, que ficam sob esse media
   query. Nota de posição, não de regra: cada uma precisa vir DEPOIS da
   própria classe base no arquivo (mesma especificidade de seletor — a
   cascata desempata por ordem de origem, não por media query casar ou não;
   colocar aqui em cima, antes da base, faria a base sempre vencer e a regra
   de acessibilidade nunca se aplicar — foi o primeiro jeito que escrevi
   isto, e o Playwright de verificação pegou o erro). */

/* ══════════════════════════════════════════════════════════════════════════
   Marca
   ══════════════════════════════════════════════════════════════════════════ */

/* Wordmark — League Spartan 600, tracking −0.05em, always lowercase, final
   period mandatory. Symbol and wordmark are independent pieces and never
   appear in the same piece: pick the one that fits the surface (symbol for
   avatar, favicon, app and seal; wordmark for signature, header and
   document) and use it alone. */
.wordmark {
  display: inline-block; font-family: var(--font-display); font-weight: 600;
  letter-spacing: -0.05em; text-transform: lowercase;
  color: var(--color-text-strong); text-decoration: none; line-height: 1;
}
/* The symbol is white by default — on ink and over brand alike. It becomes
   ink only on paper, and only in print. Minimum digital size 16px tall. */
.symbol { display: block; height: 40px; width: auto; color: var(--color-white); }
[data-theme="light"] .symbol { color: var(--color-ink); }
.symbol-clear { padding: 1em; } /* respiro: uma altura de símbolo em volta */
/* Toque no símbolo: escala 0.9 — mais profunda que a dos controles, porque a
   marca é a única peça que responde assim. */
.symbol-press { cursor: pointer; transition: transform var(--dur-240) var(--ease-emphasized); }
.symbol-press:active { transform: scale(0.9); }
@keyframes s1-wipe { 0% { clip-path:polygon(0 0,0 0,0 100%,0 100%); } 45%,55% { clip-path:polygon(0 0,100% 0,100% 100%,0 100%); } 100% { clip-path:polygon(100% 0,100% 0,100% 100%,100% 100%); } }

/* Régua de topo de seção — quase branca, o divisor mais forte do sistema. */
.section-rule { border-top: var(--border-w-1) solid var(--color-rule-section); }

/* ══════════════════════════════════════════════════════════════════════════
   Componentes
   ══════════════════════════════════════════════════════════════════════════ */

.hr { height: 1px; border: 0; margin: var(--sp-48) 0; background: var(--color-divider); }

/* — buttons — One brand button per screen: the next action. Its fill uses
     #4A57E8, because white at 15px over #6774FC is 3.8:1 — below the AA
     minimum. Everything else is ink, outline or text. Minimum target 44px. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-8);
  min-height: var(--target-min); padding: 0 var(--sp-24);
  font: 500 0.9375rem/1.4 var(--font-body); letter-spacing: 0; text-decoration: none; cursor: pointer;
  color: var(--color-text-strong); background: transparent;
  border: var(--border-w-1) solid transparent; border-radius: var(--radius-button);
  transition: background var(--dur-80) var(--ease-standard),
              border-color var(--dur-80) var(--ease-standard),
              color var(--dur-80) var(--ease-standard),
              transform var(--dur-160) var(--ease-standard);
}
.btn svg { display: block; }
/* Response on pointer-down, not on release — critically damped, no oscillation. */
.btn:active { transform: scale(0.97); }
/* Sem regra própria de :focus-visible aqui — o padrão global (2px/3px, topo do arquivo) já cobre .btn identicamente; restatá-la era redundante. */
.btn:disabled, .btn[aria-disabled="true"] { color: var(--color-text-muted); cursor: not-allowed; transform: none; }
.btn-primary { background: var(--color-accent-fill); color: var(--color-accent-on-fill); }
/* Hover lifts the fill 8%, press drops it 8% — a light step, not a hue change. */
.btn-primary:hover { background: color-mix(in srgb, var(--color-accent-fill) var(--state-mix), white); }
.btn-primary:active { background: color-mix(in srgb, var(--color-accent-fill) var(--state-mix), black); }
[data-theme="light"] .btn-primary:hover { background: var(--color-accent-fill-hover); }
/* Disabled NEVER uses opacity on the whole element — the background and text
   colours are swapped instead, so contrast stays predictable and the label
   never dims below legibility. */
.btn-primary:disabled { background: var(--color-surface-2); color: var(--color-text-muted); }
.btn-secondary { background: var(--color-surface-2); color: var(--color-text-strong); }
.btn-secondary:hover { background: var(--color-surface-3); }
.btn-outline { border-color: var(--color-border-strong); color: var(--color-text-strong); }
.btn-outline:hover { background: rgba(255, 255, 255, 0.07); }
[data-theme="light"] .btn-outline:hover { background: rgba(11, 11, 15, 0.05); }
.btn-ghost { color: var(--color-text-muted); padding-inline: var(--sp-16); }
.btn-ghost:hover { color: var(--color-text-strong); }
/* P1/QW-9: o ghost desabilitado era idêntico ao repouso (mesma cor, sem fundo). Recolore o fundo, a técnica do .btn-primary:disabled — nunca opacity. O hover não reacende o texto. Em loading (que também marca disabled) o ghost continua como estava. */
.btn-ghost:disabled:not(.btn-loading), .btn-ghost[aria-disabled="true"]:not(.btn-loading) { background: var(--color-surface-2); color: var(--color-text-muted); }
.btn-icon { width: var(--target-min); padding: 0; }
.btn-block { width: 100%; }
.btn-loading { position: relative; }
.btn-spinner { width: 16px; height: 16px; flex: none; border-radius: 50%; border: var(--border-w-2) solid currentColor; border-top-color: transparent; animation: btn-spin 700ms linear infinite; }
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* — forms — Field radius 12, same 44px target as the buttons. Focus lifts the
     field onto the next surface and adds the brand ring. */
.field { display: block; margin-bottom: var(--sp-16); }
.field > label, .field > span { display: block; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); margin-bottom: var(--sp-8); }
.input {
  width: 100%; min-height: var(--target-min); padding: 0 var(--sp-16);
  font: 400 1rem/1.5 var(--font-body); color: var(--color-text-strong); caret-color: var(--color-accent);
  background: var(--color-bg); border: var(--border-w-1) solid var(--color-border);
  border-radius: var(--radius-field);
  transition: border-color var(--dur-80) var(--ease-standard), background var(--dur-80) var(--ease-standard), box-shadow var(--dur-80) var(--ease-standard);
}
.input::placeholder { color: var(--color-text-muted); }
.input:hover { border-color: var(--color-border-strong); }
.input:focus-visible { border-color: var(--color-focus); background: var(--color-surface); box-shadow: var(--focus-ring); outline: none; }
/* Error and success always carry TEXT alongside the colour — colour alone does
   not communicate state. Pair either with a .field-msg. */
.input-error { border-color: var(--color-risk-mark); }
.input-valid { border-color: var(--color-done-mark); }
.field-msg { display: block; margin-top: var(--sp-8); font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-muted); }
.field-msg-error { color: var(--color-risk-mark); }
.field-msg-valid { color: var(--color-done-mark); }
textarea.input { min-height: 112px; padding: var(--sp-16); resize: vertical; line-height: 1.6; }
.radio { display: inline-flex; align-items: center; gap: var(--sp-8); min-height: var(--target-min); cursor: pointer; font: 500 0.9375rem/1.4 var(--font-body); }
.radio input, .seg-opt input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; padding: 0; border: 0; appearance: none; -webkit-appearance: none; pointer-events: none; }
.radio .dot { width: 20px; height: 20px; flex: none; border-radius: 50%; border: var(--border-w-1-5) solid var(--color-text-muted); transition: border-color var(--dur-80) var(--ease-standard), background var(--dur-80) var(--ease-standard); }
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot { border-color: var(--color-accent-fill); background: var(--color-accent-fill); box-shadow: inset 0 0 0 4px var(--color-bg); }
.radio input:focus-visible + .dot { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
/* Segmented — sits on the translucent material, the selected option on a card. */
.seg { display: inline-flex; align-items: center; gap: var(--sp-6); padding: var(--sp-6); background: rgba(255, 255, 255, 0.1); backdrop-filter: var(--glass-filter); -webkit-backdrop-filter: var(--glass-filter); border: var(--border-w-1) solid rgba(255, 255, 255, 0.16); border-radius: 16px; }
[data-theme="light"] .seg { background: rgba(11, 11, 15, 0.05); border-color: rgba(11, 11, 15, 0.1); }
/* Sem transparência (prefers-reduced-transparency: reduce): mesma troca do
   .translucent (ver Superfícies, abaixo) — material vira superfície sólida
   opaca, blur desligado. --color-surface-2 e não --color-surface de
   propósito: a opção marcada usa --color-surface (.seg-opt:has(input:checked))
   — um fundo igual faria a marcação sumir. Repete o seletor com
   [data-theme="light"] só pra igualar a especificidade da regra de tema
   logo acima — sem isso, ela venceria mesmo com o media query casando (a
   cascata compara especificidade antes de origem, media query ou não). Cor
   de borda/texto inalteradas. */
@media (prefers-reduced-transparency: reduce) {
  .seg, [data-theme="light"] .seg {
    background: var(--color-surface-2);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}
.seg-opt { display: inline-flex; align-items: center; gap: var(--sp-8); min-height: 40px; padding: 0 var(--sp-16); font: 500 0.9375rem/1.4 var(--font-body); color: var(--color-text-secondary); cursor: pointer; border-radius: var(--radius-button); transition: background var(--dur-80) var(--ease-standard), color var(--dur-80) var(--ease-standard); }
.seg-opt:has(input:checked) { background: var(--color-surface); color: var(--color-text-strong); }
.seg-opt:not(:has(input:checked)):hover { color: var(--color-text-strong); }
.seg-opt:has(input:focus-visible) { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
/* — checkbox — Square at the field radius' inner step, 44px target on the label. */
.check { display: inline-flex; align-items: center; gap: var(--sp-8); min-height: var(--target-min); cursor: pointer; font: 500 0.9375rem/1.4 var(--font-body); }
.check input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; padding: 0; border: 0; appearance: none; -webkit-appearance: none; pointer-events: none; }
.check .box { position: relative; width: 20px; height: 20px; flex: none; border-radius: var(--radius-6); border: var(--border-w-1-5) solid var(--color-text-muted); transition: border-color var(--dur-160) var(--ease-standard), background var(--dur-160) var(--ease-standard); }
.check .box::after { content: ""; position: absolute; inset: 0; opacity: 0; background: no-repeat center / 12px 12px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E"); transition: opacity var(--dur-160) var(--ease-standard); }
.check:hover .box { border-color: var(--color-accent); }
.check input:checked + .box { border-color: var(--color-accent-fill); background: var(--color-accent-fill); }
.check input:checked + .box::after { opacity: 1; }
.check input:indeterminate + .box { border-color: var(--color-accent-fill); background: var(--color-accent-fill); }
.check input:indeterminate + .box::after { opacity: 1; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke='white' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 12h12'/%3E%3C/svg%3E"); }
.check input:focus-visible + .box { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
.check input:disabled + .box { border-color: var(--color-surface-3); background: var(--color-surface-2); }
.check:has(input:disabled) { color: var(--color-text-muted); cursor: not-allowed; }
/* — switch — For an immediate on/off; a checkbox is for a value in a form. */
.switch { display: inline-flex; align-items: center; gap: var(--sp-16); min-height: var(--target-min); cursor: pointer; font: 500 0.9375rem/1.4 var(--font-body); }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; padding: 0; border: 0; appearance: none; -webkit-appearance: none; pointer-events: none; }
.switch .track { position: relative; width: 44px; height: 26px; flex: none; border-radius: var(--radius-pill); background: var(--color-track); transition: background var(--dur-160) var(--ease-standard); }
.switch .track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: var(--color-text-muted); transition: transform var(--dur-160) var(--ease-standard), background var(--dur-160) var(--ease-standard); }
.switch input:checked + .track { background: var(--color-accent-fill); }
.switch input:checked + .track::after { transform: translateX(18px); background: var(--color-white); }
.switch input:focus-visible + .track { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
.switch input:disabled + .track { background: var(--color-surface-2); }
.switch input:disabled + .track::after { background: var(--color-surface-3); }
.switch:has(input:disabled) { color: var(--color-text-muted); cursor: not-allowed; }

/* Rótulo sobre superfície elevada, abaixo do mínimo de 4.5:1 pra texto nos
   dois temas (números reconferidos — a versão anterior deste comentário citava
   o hex do escuro com os números do claro): no claro, Ardósia/slate (#6B6E7C)
   mede 4.25:1 na superfície 2 e 3.91:1 na superfície 3; no escuro, Névoa
   (#8A8D9B) mede 4.86:1 na superfície 2 (passa) mas 4.21:1 na superfície 3
   (não passa). Nessas bases o tom de rótulo sobe um degrau, para Corpo em card
   (5.95:1 na superfície 2 — não 7.1:1 como este comentário dizia antes). A cor
   de marca também não serve como TEXTO na superfície 3 (4.24:1): ali ela
   entra só como área ou preenchimento. */
:is(.panel-raised, .dialog, .toast, .elev-md, .elev-lg, .drawer, .palette, .select-menu, .datepicker-menu, .alert) :is(h6, .label, .field > label, .field > span, .card-meta, .text-muted, .field-msg) {
  color: var(--color-text-secondary);
}

/* — cards — Card radius 20, inner padding 24; the inner radius is the outer
     minus the padding, which is why nested content sits at 12. No shadow:
     a card is a surface step, and that is the whole of its elevation. */
.card {
  display: flex; flex-direction: column; gap: var(--sp-8);
  padding: var(--sp-24); border-radius: var(--radius-card);
  background: var(--color-surface);
}
.card-kicker { font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-accent); }
.card-title { font: 600 1.625rem/1.25 var(--font-body); letter-spacing: -0.01em; color: var(--color-text-strong); }
.card-body { margin: 0; font-size: 0.9375rem; line-height: 1.6; color: var(--color-text-secondary); flex: 1; }
.card-meta { display: flex; align-items: center; gap: var(--sp-8); font-size: 0.8125rem; color: var(--color-text-muted); }
/* Footer inside a card sits behind a hairline, flush to the card's edges. */
.card-foot { display: flex; align-items: center; gap: var(--sp-16); border-top: var(--border-w-1) solid var(--color-divider); margin: var(--sp-8) calc(-1 * var(--sp-24)) calc(-1 * var(--sp-24)); padding: var(--sp-16) var(--sp-24); }
.panel { padding: var(--sp-24); border-radius: var(--radius-panel); background: var(--color-surface); }
.panel-raised { background: var(--color-surface-2); }
.surface { padding: var(--sp-32); border-radius: var(--radius-surface); background: var(--color-surface); }
.elev-sm { background: var(--color-surface-1); }
.elev-md { background: var(--color-surface-2); }
.elev-lg { background: var(--color-surface-2); box-shadow: var(--shadow-lg); }
/* Translucent surface — the content passes under the bar; the separation comes
   from the material, not from a 1px line. */
.translucent {
  background: color-mix(in srgb, var(--color-bg) var(--glass-alpha), transparent);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
}
/* Sem transparência (prefers-reduced-transparency: reduce): troca o material
   por uma superfície sólida opaca e desliga o blur, que deixa de ter função
   sem transparência por trás. --color-surface (nível 1) e não
   --color-surface-2 de propósito: dentro da TabBar, o item ativo já usa
   --color-surface-2 como destaque (.tabbar-item[aria-current="page"]) — um
   fundo igual faria esse destaque sumir. Cor de texto/borda inalteradas. */
@media (prefers-reduced-transparency: reduce) {
  .translucent {
    background: var(--color-surface);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* — tags — Pill shaped, label type at +0.06em. */
.tag { display: inline-flex; align-items: center; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.06em; text-transform: uppercase; padding: 9px 14px; border-radius: var(--radius-pill); }
.tag-accent { background: var(--color-accent-fill); color: var(--color-white); }
.tag-neutral { background: var(--color-surface-2); color: var(--color-text-secondary); }
.tag-outline { border: var(--border-w-1) solid rgba(255, 255, 255, 0.22); color: var(--color-text-secondary); }
[data-theme="light"] .tag-outline { border-color: rgba(11, 11, 15, 0.18); }
/* Estado — semantic colour, never the brand's. */
.status { display: inline-flex; align-items: center; gap: var(--sp-8); font-size: 0.8125rem; color: var(--color-text-secondary); }
.status::before { content: ""; width: 8px; height: 8px; flex: none; border-radius: 50%; background: currentColor; }
.status-done::before { background: var(--color-done-mark); }
.status-pending::before { background: var(--color-pending-mark); }
.status-risk::before { background: var(--color-risk-mark); }
/* Marca de proibição nas listas "não faça". */
.dont-mark { color: var(--color-risk-mark); }

/* — navigation — */
.nav { display: flex; align-items: center; gap: var(--sp-24); min-height: 64px; padding: 0 var(--sp-24); border-bottom: var(--border-w-1) solid var(--color-divider); }
/* The header carries the WORDMARK alone — never the symbol beside it. */
.nav-brand { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.03em; text-transform: lowercase; font-size: 1.25rem; color: var(--color-text-strong); margin-inline-end: auto; }
.nav a { color: var(--color-text-muted); text-decoration: none; font: 500 0.9375rem/1.4 var(--font-body); }
.nav a:hover { color: var(--color-text-strong); }
.nav a[aria-current="page"] { color: var(--color-accent); font-weight: 600; } /* P1/QW-8: peso além da cor (WCAG 1.4.1); Poppins SemiBold já é carregada */

/* — tables — Horizontal rules only. No frame, no grey fill, no shadow. */
.table { width: 100%; border-collapse: collapse; font: 500 0.9375rem/1.4 var(--font-body); }
.table th { text-align: start; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); padding: var(--sp-16); border-bottom: var(--border-w-1) solid var(--color-divider); }
.table td { padding: var(--sp-16); color: var(--color-text-strong); border-bottom: var(--border-w-1) solid var(--color-grid-line); }
.table tbody tr { transition: background var(--dur-80) var(--ease-standard); }
.table tbody tr:hover { background: var(--color-surface-2); }
/* — fnd-table — tabela de referência compacta para páginas estáticas de Fundamentos
   (Movimento, Símbolos, Cor, Assinaturas). `.table` é pesada demais pra essas
   páginas (fonte 0.9375rem, pensada pra dado de produto); consolidação de 5
   variantes locais quase idênticas (.mo-table, .mtable, .sym-table, .col-mtable,
   .sig-mtable) em duas — ver CONTRIBUTING.md. */
.fnd-table, .fnd-table-labeled { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
.fnd-table th { text-align: left; color: var(--color-text-muted); padding: 0 var(--sp-16) var(--sp-8) 0; border-bottom: var(--border-w-1) solid var(--color-divider); }
.fnd-table td { padding: 14px var(--sp-16) 14px 0; color: var(--color-text-secondary); border-bottom: var(--border-w-1) solid var(--color-grid-line); vertical-align: top; }
.fnd-table td:first-child { color: var(--color-text-strong); font-family: ui-monospace, 'SF Mono', Menlo, monospace; white-space: nowrap; }
.fnd-table-num td:nth-child(2) { color: var(--color-text-strong); font-variant-numeric: tabular-nums; white-space: nowrap; }
.fnd-table-labeled { margin-top: var(--sp-16); }
.fnd-table-labeled th { text-align: left; font-size: 0.6875rem; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 500; color: var(--color-text-muted); padding: 10px var(--sp-16); border-bottom: var(--border-w-1) solid var(--color-divider); }
.fnd-table-labeled td { padding: 10px var(--sp-16); color: var(--color-text); border-bottom: var(--border-w-1) solid var(--color-grid-line); }
/* Numerals in a highlighted value take League Spartan 600; the label stays
   Poppins 400. Never the value in blue and green at once. */
.value { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.02em; color: var(--color-text-strong); }

/* — select — Trigger reads like a field, menu reads like a dropped panel;
   z-dropdown sits below tooltip and toast, above raised nav. */
.select { position: relative; display: inline-block; }
.select-trigger { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8); min-height: var(--target-min); min-width: 220px; padding: 0 var(--sp-16); border-radius: var(--radius-field); border: var(--border-w-1) solid var(--color-border); background: var(--color-surface); color: var(--color-text-strong); font: 500 0.9375rem/1.4 var(--font-body); cursor: pointer; }
.select-trigger:hover { border-color: var(--color-border-strong); }
.select-trigger:has(.select-chips) { min-height: var(--target-min); height: auto; padding: var(--sp-4) var(--sp-16); }
.select-trigger:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
/* MultiSelect (P2/C-A11Y-05): a caixa .select-trigger é só visual; o foco real fica no <button> .select-trigger-toggle (irmão dos chips), e o anel é o mesmo conjunto de foco, desenhado na caixa. */
.select-trigger-toggle { flex: 1; align-self: stretch; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8); min-width: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; cursor: pointer; outline: none; }
.select-chips + .select-trigger-toggle { flex: none; justify-content: flex-end; }
.select-trigger:has(.select-trigger-toggle:focus-visible) { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
.select-trigger .chev { flex: none; color: var(--color-text-muted); transition: transform var(--dur-160) var(--ease-standard); }
.select[data-open="true"] .select-trigger .chev { transform: rotate(180deg); }
/* P2/GAP-02: Select, Combobox, MultiSelect e DatePicker vivem na camada flutuante (.floating, portal): a posição vem de lá e a lista/calendário só existe enquanto aberto. As regras antigas (dropdown absoluto invisível quando fechado — .select > .select-menu e .datepicker-menu — e o [data-open] que as reabria) foram removidas: nada mais as casa. */
.select-menu { padding: var(--sp-6); display: grid; gap: var(--sp-2); }
.select-opt { display: flex; align-items: center; justify-content: space-between; min-height: 40px; padding: 0 var(--sp-16); border-radius: var(--radius-sm); font: 500 0.9375rem/1.4 var(--font-body); color: var(--color-text-secondary); cursor: pointer; }
.select-opt:hover, .select-opt.is-active { background: var(--color-surface-3); color: var(--color-text-strong); }
.select-opt.is-selected { color: var(--color-accent); }
.select-opt.is-selected:not(:has(.select-opt-check)) { font-weight: 600; } /* P1/QW-8: peso além da cor; as opções com .select-opt-check já têm o check como canal */
.select-opt:has(.select-opt-check).is-selected { color: var(--color-text-strong); }
.select-label { display: block; margin-bottom: var(--sp-8); font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); }

/* — stepper — Same segmented bar Onboarding already drew by hand; formalized so
   every multi-step flow shares one component instead of redrawing it. */
.stepper { display: grid; gap: var(--sp-8); }
.stepper-track { display: flex; gap: var(--sp-8); }
.stepper-seg { height: 4px; border-radius: var(--radius-2); flex: 1; background: var(--color-divider); transition: background var(--dur-240) var(--ease-emphasized); }
.stepper-seg.is-done, .stepper-seg.is-current { background: var(--color-accent); }
.stepper-labels { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--sp-8); font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); }
.stepper-labels .is-current { color: var(--color-text-strong); }

/* — tab bar (mobile) — Bottom bar over translucent material; the active item
   takes a surface pill, never an underline (that is .tabs, a different
   component). 44px targets, icon over label. */
.tabbar { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-6); border-radius: 18px; border: var(--border-w-1) solid var(--color-divider); }
.tabbar-item { flex: 1; display: grid; justify-items: center; gap: var(--sp-4); min-height: var(--target-min); padding: var(--sp-8) 0; border-radius: 14px; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); text-decoration: none; transform-origin: center; transition: color var(--dur-80) var(--ease-standard), background var(--dur-80) var(--ease-standard), transform var(--dur-80) var(--ease-standard); }
.tabbar-item:hover { color: var(--color-text-strong); }
.tabbar-item[aria-current="page"] { background: var(--color-surface-2); color: var(--color-accent); }
.tabbar-item .icon { width: var(--icon-md); height: var(--icon-md); }

/* — timeline — Vertical progress through named steps: a dot per step on a
   connecting rule, semantic colour on the dot, never on the text. */
.timeline { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-24); }
.timeline-item { position: relative; padding-inline-start: 40px; }
.timeline-item::before { content: ""; position: absolute; inset-inline-start: 11px; top: 26px; bottom: calc(-1 * var(--sp-24)); width: 2px; background: var(--color-divider); }
.timeline-item:last-child::before { display: none; }
.timeline-dot { position: absolute; left: 4px; top: 4px; width: 16px; height: 16px; border-radius: 50%; border: var(--border-w-2) solid var(--color-border-strong); background: var(--color-bg); }
/* Numbered node — same rail, but the step carries its number (the Trilha case).
   The digit is the label type in 700; 24px keeps the rail centred at left 11px. */
.timeline-num { position: absolute; left: 0; top: 2px; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font: 500 0.75rem/1.5 var(--font-body); font-weight: 700; background: var(--color-surface-2); color: var(--color-text-muted); }
.timeline-done .timeline-num { background: var(--color-accent); color: var(--color-bg); }
.timeline-current .timeline-num { background: var(--color-surface-2); color: var(--color-text); border: var(--border-w-2) solid var(--color-accent); }
.timeline-risk .timeline-num { background: var(--color-risk-mark); color: var(--color-bg); }
.timeline-done .timeline-dot { border-color: var(--color-done-mark); background: var(--color-done-mark); }
.timeline-current .timeline-dot { border-color: var(--color-accent); box-shadow: var(--focus-ring); }
.timeline-risk .timeline-dot { border-color: var(--color-risk-mark); background: var(--color-risk-mark); }
/* P1/QW-8 — canal secundário além do tom (WCAG 1.4.1): ✓ em concluído, ! em risco. Máscara + token, então a marca segue o tema.
   Ponto de 16px: a marca vai dentro, na cor do fundo (como o número dos nós numerados). Nó numerado: o número fica e a marca é uma insígnia no canto. */
.timeline-done .timeline-dot::after, .timeline-risk .timeline-dot::after { content: ""; position: absolute; inset: 0; background: var(--color-bg); -webkit-mask: var(--timeline-mark) center / 75% no-repeat; mask: var(--timeline-mark) center / 75% no-repeat; }
.timeline-done { --timeline-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.5l2.5 2.5 4.5-5.5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.timeline-risk { --timeline-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M6 2.2v4.4' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3Ccircle cx='6' cy='9.3' r='1.1' fill='black'/%3E%3C/svg%3E"); }
.timeline-done .timeline-num::before, .timeline-risk .timeline-num::before { content: ""; position: absolute; right: -6px; bottom: -6px; width: 16px; height: 16px; border-radius: 50%; background: var(--color-bg); }
.timeline-done .timeline-num::after, .timeline-risk .timeline-num::after { content: ""; position: absolute; right: -4px; bottom: -4px; width: 12px; height: 12px; -webkit-mask: var(--timeline-mark) center / contain no-repeat; mask: var(--timeline-mark) center / contain no-repeat; }
.timeline-done .timeline-num::after { background: var(--color-done-mark); }
.timeline-risk .timeline-num::after { background: var(--color-risk-mark); }
/* Em forced-colors o navegador força background-color pro fundo da página e a marca (que é máscara pintada com background) sumiria — concluído e risco voltariam a ser idênticos. Aqui a marca assume a cor de texto do sistema. */
@media (forced-colors: active) {
  .timeline-done .timeline-dot::after, .timeline-risk .timeline-dot::after,
  .timeline-done .timeline-num::after, .timeline-risk .timeline-num::after { forced-color-adjust: none; background: CanvasText; }
}
.timeline-title { font: 500 0.9375rem/1.4 var(--font-body); font-weight: 500; color: var(--color-text-strong); margin: 0; }
.timeline-body { font-size: 0.875rem; line-height: 1.6; color: var(--color-text-secondary); margin: var(--sp-8) 0 0; }
.timeline-meta { font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); }

/* — journey-map — Linha de metrô horizontal: o "mapa" que Timeline não
   cobre. Terceira versão (ver o comentário do componente em bundle.js e
   JourneyMap/README.md pro porquê de cada decisão). Estrutura:
   - `.journey-map` é um grid de 3 linhas (rótulo | trilho 40px | faixas do
     fork) e cada passo usa subgrid — por isso todo rótulo encosta na mesma
     base e todo marcador fica na mesma linha de trilho, com ou sem marco,
     com rótulo de 1 ou 2 linhas.
   - O trilho é feito de metades: `::before` (chegada) e `::after` (saída)
     de `.journey-track`, sempre na cor neutra do divisor — a mesma
     convenção de `Timeline` (o `::before` de `.timeline-item` nunca muda
     de cor por state, só o dot em cima dele). Refinamento desta leva:
     a primeira versão pintava o trecho percorrido em verde — inventava
     um segundo canal de estado (cor no trilho) que não existe em nenhum
     outro componente do sistema e brigava com a cor do próprio marcador;
     revertido pra deixar só o marcador falar.
   - 40px (linha do trilho e distância entre faixas) e os 3px do trilho são
     geometria de desenho, espelhados nas constantes JM_* de bundle.js —
     mesma categoria de exceção do audit de espaçamento que o conector já
     tinha, não espaço "entre" elementos.
   min-width:0 no wrap é defensivo (bug de overflow de item flex/grid —
   achado real na leva anterior). */
.journey-map-wrap { position: relative; min-width: 0; }
/* --journey-pending = --color-divider, a mesma cor neutra do trilho de
   Timeline (nunca --color-track, que é a cor do INTERIOR de um controle
   como Switch/Slider — famílias diferentes: trilho de navegação vs.
   trilho de input). */
.journey-map { --journey-pending: var(--color-divider); }
.journey-map { list-style: none; margin: 0; padding: var(--sp-8) 0 var(--sp-8); display: grid; grid-auto-flow: column; grid-auto-columns: max-content; grid-template-rows: auto 40px auto; overflow-x: auto; scrollbar-width: thin; }
.journey-step { grid-row: 1 / span 3; display: grid; grid-template-rows: subgrid; width: 152px; justify-items: center; text-align: center; }
.journey-text { grid-row: 1; align-self: end; display: grid; gap: var(--sp-2); padding: 0 var(--sp-8) var(--sp-8); }
.journey-label { font: 500 0.875rem/1.35 var(--font-body); color: var(--color-text-strong); margin: 0; text-wrap: balance; }

/* nowrap: "SEMANAS 10–12" quebrava no meio do en-dash (bug real, leva anterior). */
.journey-meta { font: 500 0.6875rem/1.4 var(--font-body); letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); margin: 0; white-space: nowrap; }
/* Utilitário único de texto só pra leitor de tela (visually-hidden). Substitui as 4 cópias locais (.journey-sr, .link-sr, .spinner-sr, .line-chart-sr). Em vez de margin:-1px (que o audit-spacing-tiers.py lê como 1px sem token — RI-M04), o recuo de 1px que impede o elemento de estender a área rolável do contêiner vem do transform. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; transform: translate(-1px, -1px); }

/* Trilho */
.journey-track { grid-row: 2; justify-self: stretch; position: relative; display: grid; place-items: center; }
.journey-track::before, .journey-track::after { content: ""; position: absolute; top: calc(50% - 1.5px); height: 3px; background: var(--journey-pending); }
.journey-track::before { left: 0; right: 50%; }
.journey-track::after { left: 50%; right: 0; }
.journey-step:first-child .journey-track::before, .journey-step:last-child .journey-track::after { display: none; }

/* Estação */
.journey-marker { position: relative; z-index: 1; display: block; width: 16px; height: 16px; box-sizing: border-box; border-radius: 50%; border: var(--border-w-2) solid var(--color-border-strong); background: var(--color-bg); }
.journey-done .journey-marker { border-color: var(--color-done-mark); background: var(--color-done-mark); }
.journey-risk .journey-marker { border-color: var(--color-risk-mark); background: var(--color-risk-mark); }
.journey-current .journey-marker { border-color: var(--color-accent); box-shadow: var(--focus-ring); }
/* Marco — losango (quadrado girado) com o ícone `marcador` de Icon,
   contra-girado. Nunca preenche o fundo nem inverte a cor do ícone por
   state (a versão anterior fazia isso — quebrava a própria regra de
   Icons/preview.html: "nunca dentro de círculo colorido, nunca
   preenchido"). O estado fala só pela borda, igual ao marcador redondo;
   o ícone fica neutro o tempo todo, exceto no item ativo (mesma regra:
   "azul apenas no item ativo"). */
.journey-milestone .journey-marker { width: 26px; height: 26px; border-radius: var(--radius-6); transform: rotate(45deg); display: grid; place-items: center; background: var(--color-bg); color: var(--color-text-muted); }
.journey-milestone .journey-marker-icon { transform: rotate(-45deg); }
.journey-milestone.journey-done .journey-marker { border-color: var(--color-done-mark); }
.journey-milestone.journey-risk .journey-marker { border-color: var(--color-risk-mark); }
.journey-milestone.journey-current .journey-marker { border-color: var(--color-accent); color: var(--color-accent); box-shadow: var(--focus-ring); }

/* Ponto vivo na ponta — mesmo comportamento e mesmos tempos do card
   Motion ("o marcador respira e solta um halo que se dissipa"): só a
   estação atual se move. `scale` (propriedade individual) em vez de
   `transform`, pra compor com o rotate(45deg) do losango do marco. */


/* Fork — faixas octilineares. Colunas: diagonal de saída do trilho |
   faixas (estação + nome inline) | diagonal de volta. A largura das
   diagonais vem do componente (--journey-fork-w, = JM_LEAD + (n-1)·40 +
   JM_TAIL) porque depende do número de faixas. */
.journey-fork { width: auto; min-width: 152px; grid-template-columns: var(--journey-fork-w, 56px) minmax(max-content, 1fr) var(--journey-fork-w, 56px); }
.journey-fork .journey-text { grid-column: 1 / -1; }
.journey-fork-svg { grid-row: 2 / span 2; align-self: start; display: block; overflow: visible; }
.journey-fork-in { grid-column: 1; }
.journey-fork-out { grid-column: 3; }
.journey-lane-path { stroke-width: 3; stroke-linejoin: round; }
.journey-lanes { grid-column: 2; grid-row: 2 / span 2; align-self: start; list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: 40px; }
.journey-lane { display: flex; align-items: center; }
.journey-lane-rail { height: 3px; flex: none; width: 10px; }
.journey-lane-rail-out { flex: 1 0 12px; }
.journey-tone-pending { background: var(--journey-pending); stroke: var(--journey-pending); }
.journey-tone-done { background: var(--color-done-mark); stroke: var(--color-done-mark); }
.journey-tone-current { background: var(--color-accent); stroke: var(--color-accent); }
.journey-tone-risk { background: var(--color-risk-mark); stroke: var(--color-risk-mark); }
.journey-lane-dot { position: relative; flex: none; width: 14px; height: 14px; box-sizing: border-box; border-radius: 50%; border: var(--border-w-2) solid var(--color-border-strong); background: var(--color-bg); }
.journey-lane-done .journey-lane-dot { border-color: var(--color-done-mark); background: var(--color-done-mark); }
.journey-lane-risk .journey-lane-dot { border-color: var(--color-risk-mark); background: var(--color-risk-mark); }
.journey-lane-current .journey-lane-dot { border-color: var(--color-accent); box-shadow: var(--focus-ring); }
/* Peso e cor fixos, qualquer que seja o state — a mesma regra de
   `.timeline-title` (nunca muda por done/current/risk): quem fala o
   estado é o dot e a faixa, o texto fica só mais quieto que o rótulo
   principal do passo (é secundário por natureza, não por state). */
.journey-lane-label { padding-inline: var(--sp-8); font: 400 0.8125rem/1.3 var(--font-body); color: var(--color-text-secondary); white-space: nowrap; }

/* — alert — The message that STAYS (Toast is transitory, EmptyState replaces
   content). Semantic dot plus text, on a surface — no colour-only signal and
   no coloured border rail. */
.alert { display: flex; align-items: flex-start; gap: var(--sp-16); padding: var(--sp-16); border-radius: var(--radius-card); background: var(--color-surface-2); }
.alert .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; margin-top: var(--sp-6); background: currentColor; }
.alert-done { color: var(--color-done-mark); }
.alert-pending { color: var(--color-pending-mark); }
.alert-risk { color: var(--color-risk-mark); }
.alert-info { color: var(--color-accent); }
.alert-body { flex: 1; display: grid; gap: var(--sp-4); }
.alert-body b { font: 500 0.9375rem/1.4 var(--font-body); font-weight: 500; color: var(--color-text-strong); }
.alert-body span { font-size: 0.875rem; line-height: 1.6; color: var(--color-text-secondary); }
.alert-close { flex: none; background: none; border: 0; padding: var(--sp-4); color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); }
.alert-close:hover { color: var(--color-text-strong); }

/* — accordion — Hairline rules, chevron rotates; no card per row. */
.accordion { display: grid; }
.accordion-item { border-bottom: var(--border-w-1) solid var(--color-divider); }
.accordion-trigger { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16); width: 100%; min-height: var(--target-min); padding: var(--sp-16) 0; background: none; border: 0; font: 500 0.9375rem/1.4 var(--font-body); color: var(--color-text-strong); text-align: start; cursor: pointer; }
.accordion-trigger:hover { color: var(--color-accent); }
.accordion-trigger .chev { flex: none; color: var(--color-text-muted); transition: transform var(--dur-160) var(--ease-standard); }
.accordion-trigger[aria-expanded="true"] .chev { transform: rotate(180deg); }
.accordion-panel { padding: 0 0 var(--sp-24); font-size: 0.9375rem; line-height: 1.7; color: var(--color-text-secondary); }

/* — drawer — Side sheet at dialog elevation; surface radius on the entering
   edges only, so it reads as attached to the screen edge. */
/* Base compartilhada dos três backdrops de overlay modal (Drawer/CommandPalette/Dialog) — mesma posição, z-index e cor de scrim; só o layout interno varia por componente. */
.drawer-backdrop, .palette-backdrop, .dialog-backdrop { position: fixed; inset: 0; z-index: var(--z-dialog); background: var(--color-scrim); }
.drawer-backdrop { display: flex; }
.drawer { position: relative; display: flex; flex-direction: column; gap: var(--sp-16); padding: var(--sp-32); background: var(--color-surface-2); box-shadow: var(--shadow-lg); }
.drawer-right { margin-inline-start: auto; width: min(420px, 100%); height: 100%; border-start-start-radius: var(--radius-panel); border-end-start-radius: var(--radius-panel); animation: drawer-in-right var(--dur-420) var(--ease-emphasized) both; }
.drawer-bottom { margin-top: auto; width: 100%; max-height: 80%; border-radius: var(--radius-panel) var(--radius-panel) 0 0; animation: drawer-in-bottom var(--dur-420) var(--ease-emphasized) both; }
@keyframes drawer-in-right { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes drawer-in-bottom { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer-title { font: 600 1.625rem/1.25 var(--font-body); letter-spacing: -0.01em; color: var(--color-text-strong); margin: 0; }
.drawer-body { flex: 1; overflow: auto; font-size: 0.9375rem; line-height: 1.7; color: var(--color-text-secondary); }
.drawer-actions { display: flex; justify-content: flex-end; gap: var(--sp-16); }
.drawer-handle { width: 36px; height: 4px; border-radius: var(--radius-2); background: var(--color-text-muted); margin: 0 auto var(--sp-8); }

/* — combobox — Same shape as select-menu/select-opt; the trigger is a real
   text input instead of a button, filtering client-side as you type. */
.combobox { position: relative; }
.combobox-input { padding-inline-end: 40px; }
.combobox-clear { position: absolute; inset-inline-end: 12px; top: 50%; transform: translateY(-50%); background: none; border: 0; color: var(--color-text-muted); cursor: pointer; padding: var(--sp-4); display: grid; }
.combobox-clear:hover { color: var(--color-text-strong); }
.combobox-empty { padding: var(--sp-16); font-size: 0.8125rem; color: var(--color-text-muted); text-align: center; }

/* — multiselect — Select's trigger/menu, chips instead of plain text, options
   stay open and toggle instead of closing on pick. */
.select-chips { display: flex; flex-wrap: wrap; gap: var(--sp-6); padding: var(--sp-8) 0; }
.select-chip { display: inline-flex; align-items: center; gap: var(--sp-4); padding: var(--sp-2) var(--sp-8); border-radius: var(--radius-pill); background: var(--color-surface-3); font-size: 0.75rem; color: var(--color-text-strong); }
.select-chip button { background: none; border: 0; padding: 0; color: var(--color-text-muted); cursor: pointer; display: inline-flex; }
.select-chip button:hover { color: var(--color-risk-mark); }
.select-opt-check { flex: none; width: 20px; height: 20px; border-radius: var(--radius-6); border: var(--border-w-1-5) solid var(--color-text-muted); background: no-repeat center / 12px 12px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Cpath d='M4 12l6 6L20 6'/%3E%3C/svg%3E"); background-size: 0; transition: border-color var(--dur-160) var(--ease-standard), background-color var(--dur-160) var(--ease-standard); }
.select-opt.is-selected .select-opt-check { background-color: var(--color-accent-fill); border-color: var(--color-accent-fill); background-size: 12px 12px; }

/* — date picker — Popover calendar; same trigger/menu contract as select. */
.datepicker { position: relative; display: inline-block; }
.datepicker-menu { width: 280px; padding: var(--sp-6); }
.datepicker .select-trigger:has(.datepicker-input:focus-visible) { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
.datepicker-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-16); }
.datepicker-head button { background: none; border: 0; color: var(--color-text-muted); cursor: pointer; padding: var(--sp-4); border-radius: var(--radius-sm); display: grid; }
.datepicker-head button:hover { color: var(--color-text-strong); background: var(--color-surface-3); }
.datepicker-month { font: 500 0.9375rem/1.4 var(--font-body); font-weight: 500; color: var(--color-text-strong); text-transform: capitalize; }
.datepicker-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--sp-2); padding: var(--sp-8); }
.datepicker-dow { font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); text-align: center; padding-bottom: var(--sp-6); }
.datepicker-day { aspect-ratio: 1; display: grid; place-items: center; border-radius: 50%; font-size: 0.8125rem; color: var(--color-text-secondary); background: none; border: 0; cursor: pointer; }
.datepicker-day:hover { background: var(--color-surface-3); color: var(--color-text-strong); }
.datepicker-day.is-muted { color: var(--color-text-muted); opacity: 0.4; }
.datepicker-day.is-today { box-shadow: inset 0 0 0 1px var(--color-border-strong); }
.datepicker-day.is-selected { background: var(--color-accent-fill); color: var(--color-white); }
.datepicker-day:disabled { color: var(--color-text-muted); cursor: not-allowed; }

/* — upload — Dashed dropzone; the accent border only on drag-over or focus,
   never a filled background (the empty state is a border, not a fill). */
.upload { position: relative; border: var(--border-w-1-5) dashed var(--color-border-strong); border-radius: var(--radius-card); padding: var(--sp-32); display: grid; justify-items: center; gap: var(--sp-8); text-align: center; cursor: pointer; transition: border-color var(--dur-80) var(--ease-standard), background var(--dur-80) var(--ease-standard); }
.upload:hover, .upload.is-dragging { border-color: var(--color-accent); background: var(--color-surface-1); }
.upload:has(input[type="file"]:focus-visible) { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset); }
.upload input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.upload .glyph { width: 32px; height: 32px; color: var(--color-text-muted); }
.upload-hint { font-size: 0.8125rem; color: var(--color-text-muted); }
.upload-list { display: grid; gap: var(--sp-8); margin-top: var(--sp-16); }
.upload-item { display: flex; align-items: center; gap: var(--sp-16); padding: var(--sp-8) var(--sp-16); border-radius: var(--radius-sm); background: var(--color-surface-1); font-size: 0.875rem; }
.upload-item .name { flex: 1; color: var(--color-text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-item .size { color: var(--color-text-muted); font-size: 0.75rem; }
.upload-item button { flex: none; background: none; border: 0; color: var(--color-text-muted); cursor: pointer; padding: var(--sp-4); display: grid; }
.upload-item button:hover { color: var(--color-risk-mark); }

/* — slider — Filled track via --_fill (set inline per value), critically
   damped thumb scale on hover like every other control's press response. */
.slider-field { display: grid; gap: var(--sp-8); }
.slider-head { display: flex; justify-content: space-between; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); }
.slider-head .value { color: var(--color-text-strong); font-variant-numeric: tabular-nums; }
.slider { -webkit-appearance: none; appearance: none; width: 100%; height: 4px; border-radius: var(--radius-2); background: linear-gradient(to right, var(--color-accent-fill) var(--_fill, 50%), var(--color-divider) var(--_fill, 50%)); outline: none; }
.slider::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: var(--color-accent-fill); cursor: pointer; box-shadow: 0 0 0 1px var(--color-bg); transition: transform var(--dur-80) var(--ease-standard); }
.slider::-webkit-slider-thumb:hover { transform: scale(1.1); }
.slider::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: var(--color-accent-fill); border: 0; cursor: pointer; }
.slider:focus-visible { outline: none; }
.slider:focus-visible::-webkit-slider-thumb { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-tight); }
.slider:focus-visible::-moz-range-thumb { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-tight); }
.slider:disabled { cursor: not-allowed; background: linear-gradient(to right, var(--color-text-muted) var(--_fill, 50%), var(--color-divider) var(--_fill, 50%)); }
.slider:disabled::-webkit-slider-thumb { background: var(--color-text-muted); cursor: not-allowed; }
.slider:disabled::-moz-range-thumb { background: var(--color-text-muted); cursor: not-allowed; }

/* — skeleton — Standalone loading primitives; Table/Card/Form build their own
   skeletons inline (matches their exact layout) but share this animation. */
.skeleton { background: var(--color-surface-2); animation: skel-pulse var(--dur-1400) ease-in-out infinite; }
.skeleton-text { height: 14px; border-radius: var(--radius-4); }
.skeleton-circle { border-radius: 50%; }
.skeleton-block { border-radius: var(--radius-sm); }

.dtable-loading { opacity: 0.5; pointer-events: none; }

/* — command palette — Global search, Cmd/Ctrl+K overlay. Same dialog elevation
   and backdrop as Dialog, list follows the select-opt visual language. */
.palette-backdrop { display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
.palette { width: min(560px, calc(100vw - 32px)); max-height: 60vh; display: flex; flex-direction: column; background: var(--color-surface-2); border-radius: var(--radius-panel); box-shadow: var(--shadow-lg); overflow: hidden; }
.palette-input-row { display: flex; align-items: center; gap: var(--sp-16); padding: var(--sp-16); border-bottom: var(--border-w-1) solid var(--color-divider); }
.palette-input-row svg { flex: none; color: var(--color-text-muted); }
.palette-input { flex: 1; background: none; border: 0; outline: none; font: 500 0.9375rem/1.4 var(--font-body); color: var(--color-text-strong); }
/* .palette-input's outline:none has a substitute (CONTRIBUTING.md, "Teclado
   e foco"): this ring on the panel, not the input itself. Verified (item 11,
   BACKLOG.md): the search field autofocuses in the same effect that opens
   the component, so this ring is present from the first visible frame —
   the box-shadow:shadow-lg above never actually renders in normal use.
   Intentional, not dead code: see CommandPalette/README.md. */
.palette:focus-within { box-shadow: 0 0 0 2px var(--color-accent); }
.palette-input::placeholder { color: var(--color-text-muted); }
.palette-kbd { flex: none; font-size: 0.6875rem; letter-spacing: 0.14em; color: var(--color-text-muted); border: var(--border-w-1) solid var(--color-border); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-6); }
.palette-list { overflow-y: auto; padding: var(--sp-6); }
.palette-group-label { padding: var(--sp-8) var(--sp-16) var(--sp-4); font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); }
.palette-item { display: flex; align-items: center; gap: var(--sp-16); min-height: 44px; padding: 0 var(--sp-16); border-radius: var(--radius-sm); color: var(--color-text-secondary); cursor: pointer; }
.palette-item svg { flex: none; color: var(--color-text-muted); }
.palette-item.is-active { background: var(--color-surface-3); color: var(--color-text-strong); }
.palette-item.is-active svg { color: var(--color-text-strong); }
.palette-empty { padding: var(--sp-32) var(--sp-16); text-align: center; color: var(--color-text-muted); font-size: 0.875rem; }

/* — dialog — Panel radius 24 at the top elevation. */
.dialog-backdrop { display: grid; grid-template: minmax(0, 1fr) / minmax(0, 1fr); place-items: center; padding: var(--sp-24); }
.dialog { width: min(440px, 100%); max-height: 100%; display: flex; flex-direction: column; gap: var(--sp-16); padding: var(--sp-24); border-radius: var(--radius-panel); background: var(--color-surface-2); box-shadow: var(--shadow-lg); }
.dialog-title { font: 600 1.625rem/1.25 var(--font-body); letter-spacing: -0.01em; color: var(--color-text-strong); }
.dialog-body { font-size: 0.9375rem; line-height: 1.6; color: var(--color-text-secondary); overflow-y: auto; overscroll-behavior: contain; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--sp-8); margin-top: var(--sp-8); }

/* — imagery — Never a coloured filter, a blue duotone or the symbol over the
     photograph. Text on a photograph always gets the protective ink gradient,
     0% to 82% (see .photo-scrim::after below — cited in full here so a future
     edit to the real stops doesn't leave this comment wrong again). */
.photo { position: relative; overflow: hidden; border-radius: var(--radius-panel); background: var(--color-ink); }
.photo img { width: 100%; height: 100%; object-fit: cover; }
.photo-scrim::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(11, 11, 15, 0.82) 100%);
}
.photo-scrim > .photo-copy { position: absolute; inset: auto var(--sp-24) var(--sp-24); z-index: 1; display: grid; gap: var(--sp-8); color: var(--color-white); }
.photo-copy .kick { font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: rgba(255, 255, 255, 0.72); }
/* Desaturate the environment so the brand blue is the only saturated point. */
.photo-quiet img { filter: saturate(0.72); }
.avatar { border-radius: 50%; overflow: hidden; aspect-ratio: 1; } /* circle only here */

/* — ícones — Grade de 24, área ativa de 20, traço 2 em qualquer tamanho;
     terminais e junções redondos. Herdam a cor do texto ao lado. */
.icon { width: var(--icon-md); height: var(--icon-md); flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.icon-20 { width: var(--icon-sm); height: var(--icon-sm); }
.icon-28 { width: var(--icon-lg); height: var(--icon-lg); }

/* — stagger — 40ms between items, at most 6 animated; from the seventh
     everything enters together. Reduced motion turns it into the 120ms fade. */
.stagger > * { animation: stack1-enter var(--dur-240) var(--ease-emphasized) both; }
.stagger > :nth-child(1) { animation-delay: 0ms; }
.stagger > :nth-child(2) { animation-delay: var(--dur-40); }
.stagger > :nth-child(3) { animation-delay: calc(2 * var(--dur-40)); }
.stagger > :nth-child(4) { animation-delay: calc(3 * var(--dur-40)); }
.stagger > :nth-child(5) { animation-delay: calc(4 * var(--dur-40)); }
.stagger > :nth-child(6) { animation-delay: calc(5 * var(--dur-40)); }
.stagger > :nth-child(n+7) { animation-delay: calc(5 * var(--dur-40)); }
@keyframes stack1-enter { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* — data — Bar chart on the brand's sequential scale, five steps at most.
     Tracks are pills; the grid is horizontal lines only. */
.bar-row { display: grid; gap: var(--sp-6); margin-bottom: 14px; }
.bar-head { display: flex; justify-content: space-between; gap: var(--sp-16); font-size: 0.75rem; color: var(--color-text-secondary); }
.bar-track { height: 10px; border-radius: var(--radius-pill); background: var(--color-track); overflow: hidden; }
.bar-fill { height: 100%; border-radius: var(--radius-pill); background: var(--color-brand-500); transition: width var(--dur-240) var(--ease-emphasized); }
.donut { display: flex; align-items: center; gap: var(--sp-24); }
.donut .ring { width: 120px; height: 120px; flex: none; border-radius: var(--radius-pill); display: grid; place-items: center; }
.donut .ring i { width: 76px; height: 76px; border-radius: var(--radius-pill); background: var(--color-surface-1); display: grid; place-items: center; font-family: var(--font-display); font-weight: 600; font-size: 1.625rem; letter-spacing: -0.03em; color: var(--color-text-strong); font-style: normal; }
.legend { display: grid; gap: var(--sp-8); font-size: 0.75rem; color: var(--color-text-secondary); }
.legend span { display: flex; align-items: center; gap: var(--sp-8); }
.legend i { width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* Badge — contador sobre um ícone/avatar. Âncora no canto superior direito,
   crescendo pra FORA do ícone (left fixo, largura livre) — "99+" não cobre o
   ícone. overlap circular: âncora no ponto de 45° da circunferência
   (14,6% = 1 − 1/√2 do raio, a partir da borda), onde um círculo realmente
   tem "canto". Anel de corte em box-shadow (não border: border somaria à
   caixa; e border-color reativo junto de background fixo é o par que o
   audit-contrast.py sinaliza). Cor do anel = --badge-ring, default
   --color-bg: sobre um card, defina --badge-ring: var(--color-surface) no
   contêiner pra o recorte bater com o fundo real. */
.badge-wrap { position: relative; display: inline-flex; vertical-align: middle; }
.badge { position: absolute; top: -7px; left: calc(100% - 11px); min-width: 18px; height: 18px; padding: 0 var(--sp-4); box-sizing: border-box; border-radius: var(--radius-pill); background: var(--color-risk-solid); color: var(--color-on-risk-solid); font: 600 0.6875rem/18px var(--font-body); font-variant-numeric: tabular-nums; letter-spacing: 0; text-align: center; white-space: nowrap; box-shadow: 0 0 0 2px var(--badge-ring, var(--color-bg)); pointer-events: none; }
.badge-dot { top: -3px; left: calc(100% - 7px); min-width: 0; width: 10px; height: 10px; padding: 0; }
.badge-wrap-circular .badge { top: 14.6%; left: 85.4%; transform: translate(-35%, -50%); }
.badge-wrap-circular .badge-dot { transform: translate(-50%, -50%); }

/* Rating — só leitura (ver comentário em bundle.js). Duas fileiras de estrela
   idênticas sobrepostas: trilha neutra embaixo (preenchida, não contorno — lê
   como a trilha de um medidor, mesma lógica do .slider/.bar-track), fileira
   colorida em cima cortada por largura calculada estrela a estrela. As duas
   custom properties são a fonte única da geometria: o JS as usa no cálculo da
   fração, então tamanho e vão nunca divergem entre CSS e JS. */
.rating { --rating-star: 18px; --rating-gap: var(--sp-2); display: inline-flex; align-items: center; gap: var(--sp-8); vertical-align: middle; }
.rating-stars { position: relative; display: inline-flex; }
.rating-track, .rating-fill-row { display: flex; gap: var(--rating-gap); }
.rating-fill { position: absolute; top: 0; left: 0; height: 100%; overflow: hidden; }
.rating-star { width: var(--rating-star); height: var(--rating-star); flex: none; fill: var(--color-track); stroke: var(--color-track); stroke-width: 1.5; stroke-linejoin: round; }
.rating-fill-row .rating-star { fill: var(--color-accent); stroke: var(--color-accent); }
.rating-value { font: 600 0.875rem/1 var(--font-body); color: var(--color-text-strong); }

/* LineChart — o par sequencial do Donut (ver comentário em bundle.js).
   Traço/área num SVG esticado; ponto, leitura e valor final em HTML
   posicionado em % (redondos e nítidos em qualquer largura). Valor final numa
   coluna própria ao lado da ponta. Anel do ponto = --line-chart-ring
   (default --color-bg), mesma convenção do --badge-ring. */
.line-chart { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--sp-12); row-gap: var(--sp-8); }
.line-chart-plot { position: relative; height: 64px; border-radius: var(--radius-6); cursor: crosshair; touch-action: pan-y; }
.line-chart-plot svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: visible; }
.line-chart-base { stroke: var(--color-divider); stroke-width: 1; }
.line-chart-cross { stroke: var(--color-text-muted); stroke-width: 1; }
.line-chart-line { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.line-chart-dot { position: absolute; width: 8px; height: 8px; border-radius: var(--radius-pill); transform: translate(-50%, -50%); box-shadow: 0 0 0 2px var(--line-chart-ring, var(--color-bg)); pointer-events: none; }
/* Leitura: Tinta em qualquer tema, mesma regra do .tooltip — mais um fio de
   --color-divider, porque aqui ela flutua sobre dado e, no tema escuro, Tinta
   sobre Tinta perderia a borda. */
.line-chart-tip { position: absolute; top: 0; z-index: var(--z-tooltip); display: grid; gap: var(--sp-2); padding: var(--sp-6) var(--sp-8); border-radius: var(--radius-6); background: var(--color-ink); color: var(--color-white); box-shadow: 0 0 0 1px var(--color-divider); font-size: 0.75rem; line-height: 1.3; white-space: nowrap; pointer-events: none; }
.line-chart-tip strong { font-weight: 600; font-size: 0.8125rem; }
.line-chart-tip span { color: color-mix(in srgb, var(--color-white) var(--glass-alpha), transparent); }
.line-chart-end { position: relative; height: 64px; }
.line-chart-end span { position: relative; display: block; transform: translateY(-50%); font: 600 0.8125rem/1 var(--font-display); letter-spacing: -.02em; color: var(--color-text-strong); white-space: nowrap; }
.line-chart-foot { grid-column: 1; display: flex; justify-content: space-between; font-size: 0.75rem; color: var(--color-text-muted); }

/* — tabs — Underline indicator in accent-fill, never a pill or a filled tab. */
.tabs { display: flex; gap: var(--sp-24); border-bottom: var(--border-w-1) solid var(--color-divider); }
.tabs { overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab { position: relative; flex: none; padding: 0 0 var(--sp-16); background: transparent; border: 0; font: 500 0.9375rem/1.4 var(--font-body); color: var(--color-text-muted); cursor: pointer; transform-origin: bottom center; transition: color var(--dur-80) var(--ease-standard), transform var(--dur-80) var(--ease-standard); }
.tab:hover { color: var(--color-text-strong); }
.tab[aria-selected="true"] { color: var(--color-text-strong); }
/* O indicador existe sempre, recolhido em scaleX(0): assim ele cresce do centro
   na seleção em vez de aparecer de uma vez, e recolhe ao sair. */
.tab::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--color-accent-fill); transform: scaleX(0); transition: transform var(--dur-240) var(--ease-emphasized); }
.tab[aria-selected="true"]::after { transform: scaleX(1); }
/* Resposta no pressionar, nunca no soltar. */
.tab:active { transform: scale(0.97); }
.tabbar-item:active { transform: scale(0.97); }
.tab:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-tight); }

/* — toast — Surface step 2, semantic dot instead of a colour border. Enters
     by rising 8px and fading in, critically damped like the rest of motion. */
.toast-stack { position: fixed; display: grid; gap: var(--sp-8); z-index: var(--z-toast); }
.toast-stack-br { bottom: var(--sp-24); right: var(--sp-24); }
.toast { display: flex; align-items: flex-start; gap: var(--sp-16); min-width: 280px; max-width: 420px; padding: var(--sp-16); border-radius: var(--radius-card); background: var(--color-surface-2); box-shadow: var(--shadow-lg); animation: toast-in var(--dur-420) var(--ease-emphasized) both; }
.toast-leaving { animation: toast-out var(--dur-240) var(--ease-standard) both; }
/* Descartar arrastando: o gesto tem velocidade, ent\u00e3o a mola pode ultrapassar. */
.toast-draggable { cursor: grab; touch-action: pan-y; }
.toast-draggable:active { cursor: grabbing; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-4px); } }
.toast .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; margin-top: var(--sp-6); background: currentColor; }
.toast-done { color: var(--color-done-mark); }
.toast-pending { color: var(--color-pending-mark); }
.toast-risk { color: var(--color-risk-mark); }
.toast-body { flex: 1; display: grid; gap: var(--sp-2); }
.toast-body b { font: 600 0.9375rem/1.4 var(--font-body); color: var(--color-text-strong); }
.toast-body span { font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary); }
.toast-close { flex: none; color: var(--color-text-muted); background: transparent; border: 0; cursor: pointer; padding: var(--sp-2); font-size: 0.75rem; transition: color var(--dur-80) var(--ease-standard); }
.toast-close:hover { color: var(--color-text-strong); }
.toast-close:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-tight); }

/* — breadcrumb — Slash separators at half opacity, current page in text-strong. */
.breadcrumb { display: flex; align-items: center; gap: var(--sp-8); font: 500 0.9375rem/1.4 var(--font-body); color: var(--color-text-muted); flex-wrap: wrap; }
.breadcrumb a { color: var(--color-text-muted); text-decoration: none; transition: color var(--dur-80) var(--ease-standard); }
.breadcrumb a:hover { color: var(--color-text-strong); }
.breadcrumb a:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-tight); border-radius: var(--radius-4); }
.breadcrumb .sep { color: var(--color-text-muted); opacity: 0.5; }
.breadcrumb .current { color: var(--color-text-strong); }

/* — table — Header muted uppercase like a label; rows separated by hairline,
     never a full grid. Row hover lifts onto the next surface. */
.table-wrap { border-radius: var(--radius-card); background: var(--color-surface-1); overflow: hidden; }
.table-scroll { overflow-x: auto; }
.dtable { width: 100%; border-collapse: collapse; }
.dtable th { text-align: start; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); padding: var(--sp-16); border-bottom: var(--border-w-1) solid var(--color-divider); }
.dtable td { padding: var(--sp-16); font-size: 0.9375rem; color: var(--color-text-strong); border-bottom: var(--border-w-1) solid var(--color-divider); }
.dtable tr:last-child td { border-bottom: 0; }
.dtable tbody tr { transition: background var(--dur-80) var(--ease-standard); }
.dtable tbody tr:hover { background: var(--color-surface-2); }
.dtable td.num, .dtable th.num { text-align: end; font-family: var(--font-display); font-variant-numeric: tabular-nums; }
.dtable th.sortable { cursor: pointer; user-select: none; }
.dtable th.sortable:hover { color: var(--color-text-strong); }
/* Sem regra própria de :focus-visible aqui — o padrão global (2px/3px, topo do arquivo) já cobre este elemento identicamente; restatá-la era redundante. */
.dtable th .sort-arrow { display: inline-block; margin-inline-start: 4px; opacity: .6; }
.table-search { padding: var(--sp-16); border-bottom: var(--border-w-1) solid var(--color-divider); }
.table-search .input { max-width: 320px; }
.table-nomatch { padding: var(--sp-32) var(--sp-16); text-align: center; color: var(--color-text-muted); font-size: 0.875rem; }
.table-pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16); padding: var(--sp-16); border-top: var(--border-w-1) solid var(--color-divider); }
.table-pagination .count { font-size: 0.8125rem; color: var(--color-text-muted); }
.table-pagination .pages { display: flex; align-items: center; gap: var(--sp-8); }
.page-btn { min-width: 32px; height: 32px; border-radius: 8px; border: 0; background: transparent; color: var(--color-text-secondary); font: 500 0.9375rem/1.4 var(--font-body); cursor: pointer; transition: background var(--dur-80) var(--ease-standard); }
.page-btn:hover:not(:disabled) { background: var(--color-surface-2); }
.page-btn:disabled { color: var(--color-text-muted); cursor: not-allowed; }
.page-btn:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-tight); }
.page-btn.active { background: var(--color-accent-fill); color: var(--color-accent-on-fill); }

/* — tooltip — Ink surface regardless of theme (always the darkest ground),
     appears on hover/focus after a short delay, never traps focus. */
/* Leva 64: posição/portal agora vêm de .floating (base da leva 61) — .tooltip
   só é mais a caixa visual + a seta; sem :hover/:focus-within, o React decide
   quando existe. z-tooltip (100) fica mais alto que z-dropdown (50, o padrão
   de .floating) pra não ficar atrás de um Popover/Menu aberto ao mesmo tempo. */
.floating:has(> .tooltip) { z-index: var(--z-tooltip); }
.tooltip-wrap { position: relative; display: inline-flex; }
.tooltip { display: inline-block; position: relative; background: var(--color-ink); color: var(--color-white); font-size: 0.75rem; line-height: 1.4; padding: var(--sp-6) 10px; border-radius: var(--radius-6); white-space: nowrap; animation: tooltip-in var(--dur-80) var(--ease-standard); }
.tooltip::after { content: ""; position: absolute; left: 50%; transform: translateX(-50%); border: 5px solid transparent; }
.floating[data-side="top"] .tooltip::after { top: 100%; border-top-color: var(--color-ink); }
.floating[data-side="bottom"] .tooltip::after { bottom: 100%; border-bottom-color: var(--color-ink); }
@keyframes tooltip-in { from { opacity: 0; } to { opacity: 1; } }

/* — floating (base de Popover e Menu) — Painel fora do fluxo, num portal com
     position:fixed: nenhum overflow de ancestral corta, e o JS mede o gatilho e
     vira de lado quando não cabe (data-side). O wrapper .floating só posiciona;
     quem anima e tem a superfície é o filho (.popover / .menu). */
.floating-anchor { display: inline-flex; }
.floating { position: fixed; top: 0; left: 0; z-index: var(--z-dropdown); width: max-content; max-width: calc(100vw - 2 * var(--sp-8)); --floating-shift: -4px; }
.floating[data-side="top"] { --floating-shift: 4px; }
.floating[data-side="left"], .floating[data-side="right"] { --floating-shift: 0px; }
.popover, .menu, .select-menu, .datepicker-menu { box-sizing: border-box; max-height: var(--floating-max-h, none); overflow-y: auto; overscroll-behavior: contain; background: var(--color-surface-2); color: var(--color-text); border-radius: var(--radius-card); box-shadow: var(--shadow-lg); transform-origin: top; animation: floating-in var(--dur-160) var(--ease-standard); }
.floating[data-side="top"] > .popover, .floating[data-side="top"] > .menu, .floating[data-side="top"] > .select-menu, .floating[data-side="top"] > .datepicker-menu { transform-origin: bottom; }
@keyframes floating-in { from { opacity: 0; transform: translateY(var(--floating-shift)) scale(0.98); } to { opacity: 1; transform: none; } }
.popover { min-width: 200px; max-width: 360px; padding: var(--sp-16); font-size: 0.9375rem; line-height: 1.5; }
.menu { display: grid; gap: var(--sp-2); min-width: 200px; padding: var(--sp-6); }
.menu-item { display: flex; align-items: center; gap: var(--sp-12); width: 100%; min-height: var(--target-min); padding: 0 var(--sp-16); border: 0; border-radius: var(--radius-sm); background: none; color: var(--color-text-secondary); font: 500 0.9375rem/1.4 var(--font-body); text-align: start; cursor: pointer; }
.menu-item:hover, .menu-item:focus { background: var(--color-surface-3); color: var(--color-text-strong); }
.menu-item:focus-visible { outline: var(--outline-width) solid var(--color-accent); outline-offset: var(--outline-offset-inset); }
.menu-item.is-danger, .menu-item.is-danger:hover, .menu-item.is-danger:focus { color: var(--color-risk-mark); }
/* Destrutivo: o realce de hover/foco usa --color-surface (não --color-surface-3) — risk-mark sobre surface-3 mede 4,45:1 no escuro e 4,16:1 no claro (< 4,5); sobre surface, 5,78 e 5,39. */
.menu-item.is-danger:hover, .menu-item.is-danger:focus { background: var(--color-surface); }
.menu-item.is-disabled, .menu-item.is-disabled:hover, .menu-item.is-disabled:focus { background: none; color: var(--color-text-muted); cursor: not-allowed; }
.menu-item-icon { flex: none; display: inline-flex; color: var(--color-text-muted); }
.menu-item:hover .menu-item-icon, .menu-item:focus .menu-item-icon, .menu-item.is-danger .menu-item-icon { color: currentColor; }
.menu-item-label { flex: 1 1 auto; min-width: 0; }
.menu-item-shortcut { flex: none; margin-inline-start: var(--sp-16); color: var(--color-text-secondary); font: 500 0.75rem/1.5 var(--font-body); font-variant-numeric: tabular-nums; }
.menu-sep { height: 1px; margin: var(--sp-4) var(--sp-8); background: var(--color-divider); }
.menu-heading { padding: var(--sp-8) var(--sp-16) var(--sp-4); font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-secondary); }

/* — divider — Linha divisória; horizontal por <hr>, vertical e com rótulo
     por elementos próprios (ver Divider.jsx). */
.divider { border: 0; border-top: var(--border-w-1) solid var(--color-divider); margin: var(--sp-16) 0; }
.divider-vertical { display: inline-block; align-self: stretch; width: 1px; background: var(--color-divider); margin: 0 var(--sp-8); }
.divider-labeled { display: flex; align-items: center; gap: var(--sp-12); margin: var(--sp-16) 0; }
.divider-labeled .divider-line { flex: 1; height: 1px; background: var(--color-divider); }
.divider-label { font: 500 0.8125rem/1.4 var(--font-body); color: var(--color-text-muted); white-space: nowrap; }

/* — link — Cor/hover já vêm do `a` global; aqui só a variação de sublinhado
     e o ícone de link externo, em em (acompanha o tamanho do texto ao redor,
     ao contrário de .icon, que é em px fixo pelos tokens de sizing). */
.link { text-underline-offset: 3px; }
.link.underline-always { text-decoration: underline; }
.link.underline-hover { text-decoration: none; }
.link.underline-hover:hover { text-decoration: underline; }
.link.underline-none { text-decoration: none; }
.link.is-disabled { color: var(--color-text-muted); cursor: not-allowed; text-decoration: none; }
.link-external-icon { width: 0.72em; height: 0.72em; display: inline-block; position: relative; top: -0.05em; margin-inline-start: 2px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vertical-align: baseline; }

/* — progress — Barra linear; .is-indeterminate ignora `width` inline e faz
     um bloco de 40% viajar de um lado a outro (@keyframes progress-indeterminate). */
.progress { display: grid; gap: var(--sp-8); }
.progress-label { display: flex; justify-content: space-between; font-size: 0.8125rem; color: var(--color-text-secondary); }
.progress-value { color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.progress-track { height: 8px; border-radius: var(--radius-pill); background: var(--color-track); overflow: hidden; }
.progress-fill { height: 100%; border-radius: var(--radius-pill); background: var(--color-accent-fill); transition: width 200ms var(--ease-standard); }
.progress-fill.progress-done { background: var(--color-done-mark); }
.progress-fill.progress-pending { background: var(--color-pending-mark); }
.progress-fill.progress-risk { background: var(--color-risk-mark); }
.progress-fill.is-indeterminate { width: 40% !important; transition: none; animation: progress-indeterminate var(--dur-1400) ease-in-out infinite; }
@keyframes progress-indeterminate { 0% { transform: translateX(-100%); } 100% { transform: translateX(250%); } }

/* — spinner — Mesmo giro do .btn-spinner (@keyframes btn-spin, já definido
     pra Button), avulso, pra usar fora de um botão. */
.spinner { display: inline-block; border-radius: 50%; border: var(--border-w-2) solid currentColor; border-top-color: transparent; color: var(--color-text-muted); animation: btn-spin 700ms linear infinite; flex: none; }

/* — pagination — Reaproveita .page-btn/.active do Table (mesmo visual nos
     dois lugares). Conhecido: 32px de altura fica abaixo de --target-min
     (44px); herdado do Table, não corrigido aqui — ver CHANGELOG. */
.pagination { display: flex; align-items: center; gap: var(--sp-8); }
.page-ellipsis { min-width: 32px; height: 32px; display: grid; place-items: center; color: var(--color-text-muted); font: 500 0.9375rem/1.4 var(--font-body); }
.skel-row td { padding: var(--sp-16); }
.skel-bar { height: 14px; border-radius: var(--radius-4); background: var(--color-surface-2); animation: skel-pulse var(--dur-1400) ease-in-out infinite; }
@keyframes skel-pulse { 0%,100% { opacity: .5; } 50% { opacity: 1; } }

/* — empty state — Centered, symbol-first (never a big generic illustration),
     a single action if there is one. */
.empty { display: grid; justify-items: center; text-align: center; gap: var(--sp-16); padding: var(--sp-72) var(--sp-32); }
.empty .glyph { width: 44px; height: 44px; color: var(--color-text-muted); }
.empty h4 { font: 600 1.25rem/1.3 var(--font-body); letter-spacing: -0.005em; color: var(--color-text-strong); margin: 0; }
/* nota: --type-h3/--track-h3 agora têm entrada real em tokens.json — antes eram
   tokens fantasma (citados em prosa, sem token de fato). bundle.css define
   :root SÓ pro bloco de constantes de sistema do topo (P3) — os TOKENS continuam
   chegando via o mecanismo de tema da plataforma, não são definidos aqui. */
.empty p { max-width: 40ch; font-size: 0.9375rem; line-height: 1.6; color: var(--color-text-secondary); margin: 0; }
.empty-error .glyph { color: var(--color-risk-mark); }
.empty-success .glyph { color: var(--color-done-mark); }

/* — form — Vertical field stack with section legends; actions right-aligned
     on a hairline, mirroring .card-foot. */
.form { display: grid; gap: var(--sp-8); }
.form-section + .form-section { margin-top: var(--sp-24); padding-top: var(--sp-24); border-top: var(--border-w-1) solid var(--color-divider); }
.form-legend { font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-text-muted); margin-bottom: var(--sp-16); }
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--sp-16); }
.form-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-16); border-top: var(--border-w-1) solid var(--color-divider); margin-top: var(--sp-8); padding-top: var(--sp-24); }
.dialog-busy { opacity: 0.7; pointer-events: none; }

/* — tablet breakpoint — Between mobile (720) and desktop: columns compress
   from three to two, but nothing stacks to one yet (that's 720). */
@media (max-width: 1080px) {
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}

/* — responsive — Dois cortes de media query neste arquivo: 1080px (grades de
     cartões caem de 3 pra 2 colunas) e 720px (abaixo dele, formulários e
     grades empilham em uma coluna e o dialog ocupa toda a largura útil do
     backdrop). Os componentes reflowam o próprio miolo (abas e tabelas
     rolam) sem media query — este bloco só mexe em contêineres de layout. */
@media (max-width: 720px) {
  .form-row { grid-template-columns: 1fr; }
  .dialog { width: 100%; }
  .dtable { min-width: 480px; }
}

/* — cover — Capa estática pra publicação externa (LinkedIn, YouTube, Reels/
     TikTok/Shorts). Três formatos, três regras de layout diferentes — não é
     um único template com proporção trocada, cada plataforma corta/sobrepõe
     a peça de um jeito diferente (ver README do card pra fonte de cada
     regra). Texto sempre em branco fixo (nunca token reativo a tema — a
     capa em si tem fundo próprio, escuro nos três formatos, então não
     acompanha o tema da página que a exibe, igual ao Deck). */
.cover { position: relative; overflow: hidden; border-radius: var(--radius-panel); background: var(--color-ink); color: var(--color-white); width: 100%; container-type: inline-size; }
.cover-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cover-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(11, 11, 15, 0) 0%, rgba(11, 11, 15, 0.78) 100%); }
.cover-mark { height: 28px; width: auto; color: var(--color-white); flex: none; }
.cover-kicker { display: block; font: 500 0.75rem/1.5 var(--font-body); letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255, 255, 255, 0.72); }
.cover-title { margin: var(--sp-8) 0 0; font-family: var(--font-display); font-weight: 600; letter-spacing: -0.02em; color: var(--color-white); overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.cover-blocks { position: absolute; inset: 0; }
.cover-blk { position: absolute; display: block; }

/* LinkedIn — capa de artigo: painel de texto sólido à esquerda (nunca sobre
   foto), figura 60%+ à direita, lado a lado — regra real: o card de preview
   do LinkedIn corta a borda direita em tela estreita, então nada essencial
   pode depender daquele canto sobrevivendo ao corte. 1200 × 627. */
.cover-linkedin-article { display: flex; }
.cover-linkedin-article .cover-panel { width: 38%; flex: none; display: flex; flex-direction: column; justify-content: center; gap: var(--sp-16); padding: var(--sp-32); background: var(--color-ink); }
.cover-linkedin-article .cover-title { font-size: clamp(18px, 8.5cqw, 34px); line-height: 1.08; -webkit-line-clamp: 5; }
.cover-linkedin-article .cover-figure { position: relative; flex: 1; overflow: hidden; }
.cover-linkedin-article .cover-blk-a { left: 8%; top: 14%; width: 46%; height: 72%; border-radius: var(--radius-surface); background: var(--color-brand-500); }
.cover-linkedin-article .cover-blk-b { left: 58%; top: -6%; width: 40%; height: 46%; border-radius: var(--radius-panel); background: var(--color-brand-700); }
.cover-linkedin-article .cover-blk-c { left: 64%; top: 62%; width: 32%; height: 44%; border-radius: var(--radius-card); background: var(--color-brand-300); }

/* YouTube (thumbnail de vídeo) — texto confinado à metade esquerda, terço
   superior privilegiado (é onde o olho pousa primeiro, visto minúsculo no
   feed) — tipo bem maior que os outros dois formatos por causa disso.
   Blocos de marca confinados à direita, nunca sob o texto. 1280 × 720. */
.cover-youtube-thumbnail .cover-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; padding: var(--sp-32); box-sizing: border-box; }
.cover-youtube-thumbnail .cover-text { max-width: 46%; }
.cover-youtube-thumbnail .cover-title { font-size: clamp(26px, 8.5cqw, 56px); line-height: 1.05; -webkit-line-clamp: 3; }
.cover-youtube-thumbnail .cover-overlay > .cover-mark { align-self: flex-end; }
.cover-youtube-thumbnail .cover-blk-a { left: 56%; top: 0; width: 44%; height: 100%; background: var(--color-brand-700); }
.cover-youtube-thumbnail .cover-blk-b { left: 56%; top: -10%; width: 24%; height: 56%; border-radius: var(--radius-surface); background: var(--color-brand-500); }
.cover-youtube-thumbnail .cover-blk-c { left: 80%; top: 48%; width: 20%; height: 56%; border-radius: var(--radius-panel); background: var(--color-brand-300); }

/* Reels/TikTok/Shorts — vertical, tratada como primeiro-frame equivalente à
   thumbnail. 20% inferior sempre livre de texto (é onde a interface nativa
   da plataforma — like, comentário, legenda — sobrepõe); blocos de marca
   confinados a essa mesma faixa, nunca atrás do texto. 1080 × 1920. */
.cover-reels .cover-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-start; padding: var(--sp-32) 24% 0 var(--sp-24); box-sizing: border-box; }
.cover-reels .cover-title { font-size: clamp(28px, 8cqw, 52px); line-height: 1.08; -webkit-line-clamp: 3; }
.cover-reels .cover-mark { margin-bottom: var(--sp-16); }
.cover-reels .cover-blk-a { left: 0; top: 78%; width: 100%; height: 22%; background: var(--color-brand-700); }
.cover-reels .cover-blk-b { left: -8%; top: 80%; width: 54%; height: 34%; border-radius: var(--radius-surface); background: var(--color-brand-500); }
.cover-reels .cover-blk-c { left: 66%; top: 70%; width: 42%; height: 30%; border-radius: var(--radius-panel); background: var(--color-brand-300); }

/* — score matrix — Score Elevate como componente real (pilar × nível, faixa "antes"/contorno e faixa "ganho"/marca cheia) — ver components/ScoreMatrix/README.md. */
.score-matrix { display: grid; gap: var(--sp-16); background: var(--color-surface-1); border-radius: var(--radius-panel); padding: var(--sp-24); }
.score-head { display: grid; gap: var(--sp-2); }
.score-kicker { font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; color: var(--color-accent); }
.score-title { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 1.0625rem; letter-spacing: -.02em; color: var(--color-text-strong); }
.score-grid { display: grid; gap: var(--sp-8); }
.score-row { display: grid; grid-template-columns: 96px 1fr; align-items: center; gap: var(--sp-8); }
.score-row-label { font-size: .75rem; color: var(--color-text-secondary); }
.score-row-cells { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-4); }
.score-cell { height: 20px; border-radius: 5px; background: var(--color-surface-2); border: var(--border-w-1) solid var(--color-divider); }
.score-cell-before { background: var(--color-surface-2); border: var(--border-w-1) solid rgba(129, 137, 252, .45); }
.score-cell-gained { background: var(--color-brand); border: 0; }
.score-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8); font-size: .6875rem; color: var(--color-text-muted); }
.score-mark { width: 14px; height: 15px; color: var(--color-accent); }
.score-matrix-compact { container-type: inline-size; container-name: score-compact; }
.score-matrix-compact .score-plans { display: grid; gap: var(--sp-8); }
.score-plan-row { display: grid; grid-template-columns: 88px 1fr; align-items: center; gap: var(--sp-8); }
.score-plan-label { font-size: .6875rem; color: var(--color-text-muted); }
.score-plan-track { height: 9px; display: block; }
.score-plan-fill { display: block; height: 100%; background: var(--color-brand-light); clip-path: polygon(0 0, 100% 0, 90% 100%, 0 100%); }
/* Regra literal do material de origem: "Abaixo de 56 px de largura, tire o
   rótulo e mantenha só os quatro planos." É a largura do PRÓPRIO
   .score-matrix-compact (avatar/story/miniatura), não do viewport — daí a
   container query em vez de media query. Nesse ponto o grid de duas
   colunas também vira uma coluna só, senão a coluna de 88px do rótulo
   inexistente deixaria a faixa artificialmente estreita. */
@container score-compact (max-width: 56px) {
  .score-plan-row { grid-template-columns: 1fr; }
  .score-plan-label { display: none; }
}
.score-matrix-changes { gap: var(--sp-12); }
.score-changes-kicker { font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; color: var(--color-text-muted); }
.score-changes-list { display: grid; gap: var(--sp-12); }
.score-change-row { display: grid; gap: var(--sp-2); }
.score-change-label { font-size: .625rem; color: var(--color-text-muted); }
.score-change-value { display: flex; align-items: center; gap: var(--sp-4); font-family: var(--font-display); font-weight: 600; font-size: .875rem; line-height: 1.15; color: var(--color-text-strong); }
.score-change-arrow { color: var(--color-accent); }
.score-change-note { margin: 0; font-size: .6875rem; line-height: 1.45; color: var(--color-text-muted); }

/* — testimonial — depoimento; a variante quote-cover implementa o formato real "Citação" do material Stack1 Templates v1 (1080×1080, fundo sólido da marca, sem wordmark) — ver components/Testimonial/README.md. */
.testimonial { display: grid; gap: var(--sp-16); background: var(--color-surface-1); border-radius: var(--radius-panel); padding: var(--sp-24); }
.testimonial-quote { margin: 0; font-size: .9375rem; line-height: 1.6; color: var(--color-text); }
.testimonial-byline { display: flex; align-items: center; gap: var(--sp-8); }
.testimonial-who { display: grid; gap: var(--sp-2); }
.testimonial-name { font-weight: 600; font-size: .8125rem; color: var(--color-text-strong); }
.testimonial-role { font-size: .75rem; color: var(--color-text-muted); }
.testimonial-quote-cover { position: relative; overflow: hidden; border-radius: var(--radius-panel); background: var(--color-brand-solid); color: var(--color-on-brand-solid); display: flex; flex-direction: column; justify-content: space-between; padding: var(--sp-32); container-type: inline-size; }
.testimonial-quote-cover .testimonial-mark { font-family: var(--font-display); font-weight: 600; font-size: clamp(28px, 10cqw, 48px); line-height: 1; color: rgba(255, 255, 255, .5); }
.testimonial-quote-cover .testimonial-quote { font-family: var(--font-display); font-weight: 600; font-size: clamp(18px, 7cqw, 28px); line-height: 1.15; letter-spacing: -.02em; color: var(--color-on-brand-solid); overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6; overflow: hidden; }
.testimonial-quote-cover .testimonial-signature { font-size: .75rem; color: rgba(255, 255, 255, .92); }

/* — certificate — selo de conclusão (stack1 Elevate e afins), post estático 1080×1080; mesma família visual do testimonial-quote-cover/stat-post (fundo de marca, escala por cqw) — ver components/Certificate/README.md. `certificate-body` usa gap fixo (var(--sp-16)), não clamp(), de propósito: espaçamento maior entre blocos (selo/kicker/nome/curso), sem a mesma necessidade de encolher em telas pequenas que `stat-post-body` tinha. */
.certificate { position: relative; overflow: hidden; border-radius: var(--radius-panel); background: var(--color-brand-solid); color: var(--color-on-brand-solid); display: flex; flex-direction: column; align-items: center; justify-content: space-between; text-align: center; padding: var(--sp-32); container-type: inline-size; }
.certificate-seal { width: clamp(40px, 11cqw, 72px); height: clamp(40px, 11cqw, 72px); border-radius: 50%; border: var(--border-w-1) solid rgba(255, 255, 255, .35); display: grid; place-items: center; flex: none; }
.certificate-mark { height: clamp(16px, 4cqw, 28px); width: auto; color: rgba(255, 255, 255, .75); }
.certificate-body { display: grid; gap: var(--sp-16); justify-items: center; margin: auto 0; }
.certificate-kicker { font-size: clamp(10px, 1.8cqw, 13px); letter-spacing: .14em; text-transform: uppercase; color: rgba(255, 255, 255, .65); }
.certificate-recipient { font-family: var(--font-display); font-weight: 700; font-size: clamp(28px, 8.5cqw, 60px); line-height: 1.05; letter-spacing: -.02em; color: var(--color-on-brand-solid); }
.certificate-course { font-size: clamp(13px, 2.8cqw, 19px); color: rgba(255, 255, 255, .92); }
.certificate-credential { font-size: clamp(10px, 1.6cqw, 12px); color: rgba(255, 255, 255, .55); }
.certificate-foot { display: flex; align-items: baseline; justify-content: space-between; width: 100%; gap: var(--sp-16); }
.certificate-lockup { display: flex; align-items: baseline; gap: 5px; }
.certificate-lockup-mark { font-family: var(--font-display); font-weight: 600; font-size: clamp(13px, 2.6cqw, 18px); letter-spacing: -.03em; color: var(--color-on-brand-solid); }
.certificate-lockup-sub { font-family: var(--font-body); font-weight: 500; font-size: clamp(11px, 2.2cqw, 15px); color: rgba(255, 255, 255, .75); }
.certificate-signature { text-align: right; }
.certificate-signature-name { display: block; font-size: clamp(11px, 2cqw, 14px); color: var(--color-on-brand-solid); }
.certificate-signature-date { display: block; font-size: clamp(10px, 1.6cqw, 12px); color: rgba(255, 255, 255, .6); }

/* — stat post — prova social numérica isolada, post estático 1080×1080; mesma família visual do testimonial-quote-cover (fundo de marca, escala por cqw) — ver components/StatPost/README.md. */
.stat-post { position: relative; overflow: hidden; border-radius: var(--radius-panel); background: var(--color-brand-solid); color: var(--color-on-brand-solid); display: flex; flex-direction: column; justify-content: space-between; padding: var(--sp-32); container-type: inline-size; }
.stat-post-mark { height: clamp(20px, 4cqw, 32px); width: auto; color: rgba(255, 255, 255, .55); flex: none; }
.stat-post-body { display: grid; gap: clamp(var(--sp-4), 1.2cqw, var(--sp-12)); margin-top: auto; }
.stat-post-value { font-family: var(--font-display); font-weight: 600; font-size: clamp(48px, 22cqw, 160px); line-height: .95; letter-spacing: -.03em; color: var(--color-on-brand-solid); }
.stat-post-label { font-size: clamp(12px, 2.6cqw, 18px); color: rgba(255, 255, 255, .92); }
.stat-post-delta { font-size: clamp(10px, 2cqw, 14px); color: rgba(255, 255, 255, .75); }
.stat-post-context { font-size: clamp(10px, 1.8cqw, 13px); color: rgba(255, 255, 255, .55); }

/* — pricing — oferta com preço-âncora; recommended reusa o tratamento de marca cheia (color-brand-solid/color-on-brand-solid) já usado em .dt-c.rec/.voice-is/.certificate/.stat-post/.testimonial-quote-cover — ver components/Pricing/README.md. */
.pricing { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--sp-24); justify-content: center; }
.pricing-offer { position: relative; display: grid; gap: var(--sp-16); align-content: start; background: var(--color-surface-1); border-radius: var(--radius-panel); padding: var(--sp-32); max-width: 360px; }
.pricing-offer-recommended { background: var(--color-brand-solid); color: var(--color-on-brand-solid); }
.pricing-badge { position: absolute; top: var(--sp-16); right: var(--sp-16); font-size: .625rem; letter-spacing: .08em; text-transform: uppercase; background: rgba(255, 255, 255, .92); color: var(--color-brand-700); padding: var(--sp-4) 10px; border-radius: var(--radius-pill); }
.pricing-name { font-family: var(--font-display); font-weight: 600; font-size: 1.0625rem; letter-spacing: -.02em; color: var(--color-text-strong); }
.pricing-offer-recommended .pricing-name { color: var(--color-on-brand-solid); }
.pricing-offer-recommended .btn-outline { color: var(--color-on-brand-solid); }
.pricing-description { margin: 0; font-size: .8125rem; line-height: 1.55; color: var(--color-text-secondary); }
.pricing-offer-recommended .pricing-description { color: rgba(255, 255, 255, .92); }
.pricing-amount { display: flex; align-items: baseline; gap: var(--sp-6); }
.pricing-anchor { font-size: .875rem; color: var(--color-text-muted); text-decoration: line-through; }
.pricing-offer-recommended .pricing-anchor { color: rgba(255, 255, 255, .92); }
.pricing-price { font-family: var(--font-display); font-weight: 600; font-size: 2rem; letter-spacing: -.03em; color: var(--color-text-strong); }
.pricing-offer-recommended .pricing-price { color: var(--color-on-brand-solid); }
.pricing-period { font-size: .8125rem; color: var(--color-text-muted); }
.pricing-offer-recommended .pricing-period { color: rgba(255, 255, 255, .92); }
.pricing-features { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-8); font-size: .8125rem; color: var(--color-text-secondary); }
.pricing-offer-recommended .pricing-features { color: rgba(255, 255, 255, .92); }
.pricing-features li { padding-left: 18px; position: relative; }
.pricing-features li::before { content: ''; position: absolute; left: 0; top: .55em; width: 8px; height: 8px; border-radius: var(--radius-2); background: var(--color-accent); }
.pricing-offer-recommended .pricing-features li::before { background: rgba(255, 255, 255, .92); }
.pricing-cta { margin-top: var(--sp-8); }
