/* =====================================================================================================
   APP.CSS · a CASCA da area logada do BOOOT (v2 · 07/09/2026 · tarefa 205 · AREA 2 · chip S)
   Servida como /ds/app.css?v=<hash> pelo build-painel.mjs. Consumidores: /app (o Painel) · /app/videos ·
   /app/conta · /catalogo · /entrar.

   O QUE ESTA FOLHA E: a anatomia do STChat (crm.booot.com.br) escrita com os valores da casa. Menu
   lateral grafite de 15rem com o trocador de conta no topo, barra superior FIXA de 3.5rem da MESMA cor do
   menu, conteudo claro com cartoes brancos. Tema claro por padrao (html.tema-claro) e escuro pelo botao da
   barra; menu e barra ficam grafite nos DOIS temas, como no STChat.

   PRONTO (anti-tijolo): adotamos a ANATOMIA shadcn/ui que o STChat usa (sidebar + topbar + card + pill +
   dialog + empty state + sticky bar), o <dialog> NATIVO (showModal / ::backdrop / Esc / foco) no lugar de
   sheet propria, os icones Lucide (ISC) como <symbol> inline no partial, e prefers-reduced-motion. NAO
   adotamos Tailwind (a casa nao tem build de CSS) nem framework de JS: o que se CONSTROI aqui e so o glue.

   LEI DA MARCA: so COMPOE por var(--token) de _MARCA/tokens/tokens.css (importado na abertura). Zero hex,
   zero rgb()/hsl(), zero nome de letra, px so 1px (borda) e 44px (alvo de toque); o resto em rem, % ou
   token. As custom properties PROPRIAS (--sh-*) estao na lista PROPRIOS de app/auditar-app.mjs, com o
   motivo. Fonte no app: Inter em TUDO (--fonte-texto); o Archivo (display) NAO entra aqui, porque a
   manchete de display dentro do produto foi o que o dono chamou de Word.

   Divisor de painel em propriedade LOGICA (border-inline-end), nunca border-right: mesmo pixel, e nao se
   confunde com a listra decorativa que o gate anti-slop-visual barra.

   FIDELIDADE FINA (07/09 · D-PLATAFORMA-COPIA-O-STCHAT-07SET): as receitas de movimento, foco, menu,
   botao e popup daqui NAO sao gosto. Sao a transcricao, valor por valor, da marcacao e da folha que o
   PROPRIO fornecedor serve (`_MARCA/whitelabel/refs-stchat/estilo-do-fornecedor.css` + as 2 paginas
   salvas `pagina-painel.html` e `pagina-sla.html`, onde a classe de cada elemento E a especificacao).
   A transcricao completa (classe do fornecedor -> regra daqui), as 2 formas de botao dele e as 4
   divergencias declaradas vivem em `_work/produto-area-logada/app-v2/HANDOFF-F.md` §2-3; a leitura de
   cor, forma e fluxo esta em `_MARCA/whitelabel/refs-stchat/ANATOMIA-MEDIDA.md`.

   Travas: _MOTOR/_tests/app-shell.test.mjs (o partial, os 2 temas, o teto de 40 KB, a secao "fidelidade
   ao STChat") · _MOTOR/_tests/app-catalogo.test.mjs (folha so token, sabotagem, menu escuro nos 2 temas) ·
   2_CLIENTES/ongoing/painel/app/auditar-app.mjs (a bancada com navegador).
   ===================================================================================================== */
/* inline pelo build: ../tokens/tokens.css */
/* =====================================================================
   BOOOT · DESIGN TOKENS · v2.0.0 · sistema OURO
   Fonte única da verdade do sistema visual BOOOT.

   DECISÃO: D-MARCA-OURO-LARANJA-E-CREME-SAEM-16AGO (dono, 16/ago/2026 ·
   ledger _ESTADO/decisoes-copy.jsonl · contrato
   0_CENTRAL/PEDIDO-FABLE-DESIGN-SYSTEM-BOOOT.md). O acento ÚNICO é o
   OURO #D4921B no degrau 600. O laranja, o creme e a letra antiga
   MORRERAM: peça nova não os usa (os valores mortos estão listados na
   checagem de pureza do verify-tokens.mjs). As peças já aprovadas seguem
   rendendo pelo @import de legado abaixo até cada repintura receber a
   palavra do dono (§8.3 do contrato) · a ponte morre com o §8.3.

   Deploy do Portal segue seguro DURANTE a transição: as páginas do site
   consomem só nomes legados, a ponte os congela nos valores antigos, e o
   build (copyMarca) segue o @import e as fontes por recursão · o site
   renderiza idêntico ao aprovado até cada repintura do §8.3.

   Regra-mãe: o BOOOT é grafite frio e ouro. Ouro é valor conquistado:
   assinatura, número de resultado, UM botão por tela no escuro. Em
   página clara, ouro de preenchimento é PROIBIDO (dono, 16/ago: "em
   páginas brancas ou claras o certo é não ter botão ouro. Ponto final.");
   no claro o ouro vira texto/borda no degrau 800 couro.

   Todo contraste comentado abaixo foi medido (WCAG 2.x) em 16/ago/2026
   com a base declarada ao lado. Número sem base é número sem sentido.

   NÃO editar valores soltos. Mude aqui e o sistema inteiro herda.
   Paridade com tokens.json + tailwind.tokens.js: node verify-tokens.mjs
   ===================================================================== */

/* inline pelo build: legado-repintura.css */
/* =====================================================================
   BOOOT · LEGADO EM REPINTURA · a ponte que morre
   D-MARCA-OURO-LARANJA-E-CREME-SAEM-16AGO (ledger _ESTADO/decisoes-copy.jsonl)

   O QUE ISTO E: os nomes da marca ANTIGA (carvao, creme, laranja, Poppins),
   congelados nos VALORES antigos, pra que as pecas JA APROVADAS pelo dono
   continuem rendendo exatamente como ele as aprovou ate cada repintura
   receber a palavra dele (contrato 0_CENTRAL/PEDIDO-FABLE-DESIGN-SYSTEM-BOOOT.md
   §8.3: patterns/site, cards de prova, carrossel, kit social, juiz, Painel).

   O QUE ISTO NAO E: paleta permitida. O brand-check-gate le SO o tokens.css
   (a fonte nova) e este arquivo fica FORA da allowlist de proposito: peca
   NOVA com creme/laranja/Poppins reprova. Usar estes nomes em peca nova
   e proibido (manual da marca).

   MORTE: cada bloco daqui morre no mesmo movimento da repintura da peca que
   o consome (zero-residuo). Quando o §8.3 fechar inteiro, este arquivo e
   deletado e o @import sai do tokens.css.
   ===================================================================== */

/* Poppins self-host (5 pesos · OFL) · SO pras pecas legadas. Peca nova usa
   Archivo + Inter (assets/fonts/fonts.css). Os woff2 morrem junto daqui. */
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 400; font-display: swap; src: url('../assets/fonts/poppins-400.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap; src: url('../assets/fonts/poppins-500.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap; src: url('../assets/fonts/poppins-600.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap; src: url('../assets/fonts/poppins-700.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 900; font-display: swap; src: url('../assets/fonts/poppins-900.woff2') format('woff2'); }

:root {
  /* ---- as 5 cores antigas (mortas pra peca nova · vivas pro legado) ---- */
  --booot-carvao: #1D1D1F;
  --booot-creme: #E9DCC9;
  --booot-laranja: #FF3F02;
  --booot-cinza-claro: #E6E2DA;
  --booot-cinza-medio: #B8B4AC;
  --booot-laranja-press: color-mix(in srgb, var(--booot-laranja) 88%, var(--booot-carvao));
  --booot-laranja-tint: color-mix(in srgb, var(--booot-laranja) 10%, transparent);

  /* ---- tripletos HSL antigos ---- */
  --booot-carvao-hsl: 240 3% 12%;
  --booot-creme-hsl: 36 42% 85%;
  --booot-laranja-hsl: 15 100% 50%;
  --booot-cinza-claro-hsl: 40 19% 88%;
  --booot-cinza-medio-hsl: 40 8% 70%;
  --booot-erro-hsl: 0 79% 65%;

  /* ---- semanticos antigos ---- */
  --bg-dark: var(--booot-carvao);
  --bg-light: var(--booot-creme);
  --fg-dark: var(--booot-creme);
  --fg-light: var(--booot-carvao);
  --accent: var(--booot-laranja);
  --muted: var(--booot-cinza-medio);
  --line: color-mix(in srgb, var(--booot-carvao) 16%, transparent);

  /* ---- ladder de texto sobre carvao ---- */
  --fg-on-dark: var(--booot-creme);
  --fg-on-dark-strong: hsl(var(--booot-creme-hsl) / .92);
  --fg-on-dark-body: hsl(var(--booot-creme-hsl) / .72);
  --fg-on-dark-muted: hsl(var(--booot-creme-hsl) / .55);
  --fg-on-dark-faint: hsl(var(--booot-creme-hsl) / .42);
  --fg-on-dark-dim: hsl(var(--booot-creme-hsl) / .28);
  --surface-on-dark: hsl(var(--booot-creme-hsl) / .05);
  --hairline-on-dark: 1px solid hsl(var(--booot-creme-hsl) / .08);
  --fg-on-laranja: hsl(29 100% 96%);

  /* ---- tipografia antiga ---- */
  --font-sans: 'Poppins', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  --fw-black: 900;
  --tracking-display: -0.038em;
  --tracking-tight: -0.025em;
  --tracking-caps: 0.18em;
  --cta-min-size: 1.0625rem;

  /* ---- raio antigo (o novo e --raio-*) ---- */
  --radius-md: 1rem;
  --radius-lg: 1.5rem;
  --radius-pill: 999px;

  /* ---- superficies, linhas, sombras antigas ---- */
  --surface-dark-lift: color-mix(in srgb, var(--booot-creme) 8%, transparent);
  --surface-light-lift: color-mix(in srgb, var(--booot-carvao) 4%, transparent);
  --hairline-dark: 1px solid color-mix(in srgb, var(--booot-creme) 8%, transparent);
  --hairline-light: 1px solid color-mix(in srgb, var(--booot-carvao) 12%, transparent);
  --glow-accent-soft: 0 14px 30px -16px hsl(0 0% 0% / .5);
  --shadow-overlay: 0 16px 48px color-mix(in srgb, var(--booot-carvao) 22%, transparent);
  --focus-ring: 2px solid var(--booot-laranja);

  /* ---- app-ui v1.1 antigo (Painel, form, tabela) ---- */
  --line-on-light: color-mix(in srgb, var(--booot-carvao) 12%, transparent);
  --line-on-dark: color-mix(in srgb, var(--booot-creme) 8%, transparent);
  --text-secondary-on-light: color-mix(in srgb, var(--booot-carvao) 72%, transparent);
  --text-secondary-on-dark: var(--booot-cinza-medio);
  --state-positive: var(--booot-laranja);
  --state-attention: var(--booot-laranja);
  --state-negative: var(--booot-carvao);
  --field-bg: var(--surface-light-lift);
  --field-border: color-mix(in srgb, var(--booot-carvao) 12%, transparent);
  --field-border-focus: var(--booot-laranja);
  --field-disabled: color-mix(in srgb, var(--booot-carvao) 38%, transparent);
  --placeholder-color: color-mix(in srgb, var(--booot-carvao) 50%, transparent);
  --table-header-bg: var(--booot-carvao);
  --table-header-fg: var(--booot-creme);
  --row-stripe: var(--surface-light-lift);
  --row-hover: color-mix(in srgb, var(--booot-carvao) 6%, transparent);
}


:root {
  /* ---- OURO · a escala do acento (degrau 600 = a cor da marca) ------ */
  --booot-ouro-100: #F4EAD7;   /* areia · wash */
  --booot-ouro-200: #F3D7A5;   /* trigo · wash */
  --booot-ouro-300: #EEC377;   /* mel */
  --booot-ouro-400: #E9B353;   /* sol */
  --booot-ouro-500: #E6A93C;   /* âmbar · HOVER do ouro */
  --booot-ouro-600: #D4921B;   /* OURO · a cor da marca (7,10 s/ cinza-000 · 6,57 s/ cinza-010) */
  --booot-ouro-700: #AC7616;   /* cobre · PRESSIONADO */
  --booot-ouro-800: #835A11;   /* couro · texto e borda no tema claro (5,70 s/ cinza-900 · 6,11 s/ branco) */
  --booot-ouro-900: #5A3E0C;   /* terra */

  /* ---- NEUTROS · a fundação fria (12 degraus, todos · palavra do dono) */
  --booot-cinza-000: #0E1216;  /* a página escura */
  --booot-cinza-010: #141B1F;  /* o cartão escuro */
  --booot-cinza-100: #1E2429;  /* elevado */
  --booot-cinza-200: #232A2F;  /* flutuante escuro */
  --booot-cinza-300: #2F363C;
  --booot-cinza-400: #40484F;
  --booot-cinza-500: #5C6B7A;  /* texto 2º no claro (5,10 s/ cinza-900) · primária do whitelabel */
  --booot-cinza-550: #7A8087;  /* o cinza do ícone · como TEXTO só >=16px s/ cartão escuro (4,36 s/ 010 · 4,71 s/ 000) */
  --booot-cinza-600: #96A0A6;  /* texto 2º no escuro (6,53 s/ 010) */
  --booot-cinza-700: #BCC2C8;
  --booot-cinza-800: #E2E6E9;
  --booot-cinza-900: #F6F7F8;  /* o claro do sistema (decisão do dono) · texto 1º no escuro (16,23 s/ 010) */

  /* ---- SEMÂNTICAS · 3, não 4 (a 4ª morreu por medição: âmbar = ouro) - */
  /* sobre o cartão escuro 010: erro 5,22 · sucesso 5,24 · info 5,18 (deliberado: mesma leitura) */
  --booot-erro: #EC5D5E;       /* Radix red-10 adotado (aberto, acessível em escuro) */
  --booot-sucesso: #3C9E70;    /* derivado do vermelho */
  --booot-info: #4990D6;       /* derivado do vermelho */

  /* ---- TIPOGRAFIA · Archivo (título) + Inter (texto) ---------------- */
  --fonte-titulo: 'Archivo', 'Inter', system-ui, sans-serif;
  --fonte-texto: 'Inter', system-ui, -apple-system, sans-serif;
  /* largura do Archivo (font-stretch · eixo wdth da variável):
     62% = manchete grande (>=28px: herói, post, número de resultado · cravado pelo dono)
     92% = título de seção e componente (a condensada fecha demais no tamanho pequeno) */
  --largura-display: 62%;
  --largura-titulo: 92%;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-extra: 800;             /* o peso de display do Archivo (o 900 morreu com a letra antiga) */

  --lh-display: 1.05;
  --lh-heading: 1.18;
  --lh-body: 1.6;

  /* tracking: a condensada já é compacta; o aperto forte da letra antiga esmagaria */
  --letra-display: -0.01em;    /* Archivo 62% grande */
  --letra-titulo: -0.02em;     /* Archivo 92% */
  --letra-caps: 0.14em;        /* Inter caps (eyebrow, rótulo) */

  --fs-micro: .75rem;          /* 12px fixo · legenda/rótulo de UI densa */
  --fs-eyebrow: clamp(.75rem, 1vw, .875rem);
  --fs-body: clamp(.9375rem, 1.3vw, 1.0625rem);
  --fs-body-lg: clamp(1.0625rem, 1.5vw, 1.1875rem);
  --fs-card-title: clamp(1.0625rem, 1.45vw, 1.1875rem);  /* título de card (promoção da ANATOMIA-ADOTADA) */
  --fs-h3: clamp(1.25rem, 2.2vw, 1.55rem);
  --fs-h2: clamp(1.6rem, 3.4vw, 2.4rem);
  --fs-display: clamp(2.25rem, 6vw, 3.5rem);
  --fs-hero: clamp(3rem, 8vw, 4.5rem);                   /* manchete do Portal (Archivo 62%) */

  /* ---- A ESCALA DO APP (04/10 · obra/rev-d-design) · UMA escala para tipo, espaço, peso e papel de texto ---------------------------------------
     PADRÃO ADOTADO (não construído): a escala de tipo e de espaço do Tailwind (MIT · tailwindcss.com/docs/font-size · /docs/padding) em grade de 4/8; a hierarquia
     de texto em 2 papéis (principal e secundário) do Radix Themes (MIT · radix-ui.com/themes/docs/theme/typography); contraste por TAMANHO e PESO, nunca por cinza
     (Vercel Geist · Linear). Aqui mora só a cola nos tokens da casa. A régua `stylelint.config.mjs` e o teste `design-escala.test.mjs` impõem.
     TIPO · 6 passos (o 12 é o --fs-micro de cima) e 2 pesos (--fw-regular e --fw-semibold):
       12 micro · legenda, pílula, ponta do trilho         14 sm · apoio, rótulo, controle         16 md · corpo
       20 xl · título de cartão                              24 2xl · número de cartão, título de tela         32 3xl · o número herói (um por tela)
     Piso de leitura: 14 px no texto de apoio, 16 px no corpo. O passo de 18 px MORREU (o título de cartão subiu para 20): cada passo tem UM papel.
     TEXTO · 2 papéis: --texto (principal) e --texto-2 (secundário, AA nos 2 temas). O secundário é APOIO de UMA linha, nunca o corpo de um parágrafo.
     ESPAÇO · grade de 4/8: 4 · 8 · 12 · 16 · 24 · 32 · 48 = --space-1, --space-2, --sh-12 (o degrau 12, declarado no kit), --space-3, --space-4, --space-5, --space-6.
     CARTÃO · 1 raio (--raio-cartao) e 1 sombra (--sombra-cartao). Só CSS (verify-tokens: lista CSS_ONLY, sem espelho no Tailwind). */
  --fs-sm: .875rem;            /* 14px · apoio, rótulo, controle */
  --fs-md: 1rem;               /* 16px · corpo da tela */
  --fs-xl: 1.25rem;            /* 20px · título de cartão */
  --fs-2xl: 1.5rem;            /* 24px · número de cartão, título de tela */
  --fs-3xl: 2rem;              /* 32px · o número herói (um por tela) */
  --fs-tela: var(--fs-2xl);    /* o título da pergunta nas telas de formulário (moldura): 24 no celular, 32 do tablet em diante (bloco abaixo) */
  --lh-snug: 1.3;              /* título de cartão e número */
  --lh-ui: 1.5;                /* texto de apoio e linha de lista */

  /* ---- SPACING (base 8 · sobrevive da v1 · +1 degrau pra UI densa) -- */
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2rem;
  --space-6: 3rem;
  --space-7: 4rem;
  --space-8: 5rem;
  --space-9: 7rem;

  /* ---- MEDIDAS DE LEITURA ------------------------------------------- */
  --medida-texto: 68ch;        /* coluna de leitura confortável */
  --medida-form: 560px;        /* form / diálogo */

  /* ---- RAIO · 3 papéis + pílula · aninhado desce um degrau ---------- */
  --raio-controle: .625rem;    /* 10px · botão, campo, chip retangular */
  --raio-cartao: .875rem;      /* 14px · card, painel */
  --raio-flutuante: 1.25rem;   /* 20px · modal, popover, hero container */
  --raio-pill: 999px;

  /* ---- Z-INDEX ------------------------------------------------------ */
  --z-base: 0;
  --z-sticky: 50;
  --z-dropdown: 100;
  --z-modal: 1000;
  --z-toast: 1100;

  /* ---- MOTION · anima só transform e opacity ------------------------ */
  --motion-fast: 180ms;
  --motion-base: 250ms;
  --motion-slow: 400ms;
  --ease-standard: cubic-bezier(.2, .6, .2, 1);

  /* ---- FORMA & A11Y ------------------------------------------------- */
  --cut-angle: 62deg;          /* corte diagonal canônico (crescimento) · a assinatura geométrica */
  --focus-offset: 2px;

  /* =====================================================================
     TOKENS SEMÂNTICOS DE TEMA · o default é o ESCURO (a casa da marca).
     O tema claro re-mapeia os MESMOS nomes no bloco .tema-claro abaixo.
     Consuma SEMPRE estes nomes em peça; primitivos são detalhe interno.
     ===================================================================== */

  /* superfícies · elevação por COR no escuro (sombra quase não lê aqui) */
  --pagina: var(--booot-cinza-000);
  --superficie: var(--booot-cinza-010);
  --superficie-2: var(--booot-cinza-100);
  --flutuante: var(--booot-cinza-200);

  /* texto · 1º 16,23 s/ superfície · 2º 6,53 · 3º 4,36 (só >=16px s/ cartão) */
  --texto: var(--booot-cinza-900);
  --texto-2: var(--booot-cinza-600);
  --texto-3: var(--booot-cinza-550);
  /* lead: o parágrafo de abertura ao lado de display. Um degrau abaixo do 1º
     (o quase-branco em massa de texto ficou duro na tela do dono, 16/ago):
     10,47 s/ página 000 · 9,69 s/ cartão 010 (medido 16/ago) */
  --texto-lead: var(--booot-cinza-700);

  --borda: color-mix(in srgb, var(--booot-cinza-900) 8%, transparent);
  --borda-forte: color-mix(in srgb, var(--booot-cinza-900) 16%, transparent);

  /* acento · estados são degraus vizinhos (500 hover · 700 press) */
  --acento: var(--booot-ouro-600);
  --acento-hover: var(--booot-ouro-500);
  --acento-press: var(--booot-ouro-700);
  --acento-texto: var(--booot-ouro-600);      /* 6,57 s/ superfície · 7,10 s/ página */
  --sobre-acento: var(--booot-cinza-000);     /* grafite s/ ouro 7,10 · o CTA branco do escuro é exceção do dono (manual) */

  /* CTA primário · escuro: ouro · claro: grafite (zero ouro de preenchimento no claro) */
  --cta-fundo: var(--booot-ouro-600);
  --cta-texto: var(--booot-cinza-000);
  --cta-hover: var(--booot-ouro-500);
  --cta-press: var(--booot-ouro-700);

  --anel-foco: 2px solid var(--booot-ouro-600);   /* 7,10 s/ página · 6,57 s/ cartão (piso 3,0 UI) */

  /* semânticas como TEXTO (no escuro as cruas passam: 5,22 · 5,24 · 5,18 s/ 010) */
  --erro-texto: var(--booot-erro);
  --sucesso-texto: var(--booot-sucesso);
  --info-texto: var(--booot-info);

  /* formulário */
  --campo-fundo: color-mix(in srgb, var(--booot-cinza-900) 4%, transparent);
  --campo-borda: color-mix(in srgb, var(--booot-cinza-900) 20%, transparent);
  --campo-borda-foco: var(--booot-ouro-600);

  --desabilitado: .45;         /* opacidade de estado desabilitado · sem trocar cor */
  --veu-foto: color-mix(in srgb, var(--booot-cinza-000) 65%, transparent);  /* texto sobre foto · janela 55-75% */

  /* sombra · escuro: só o que flutua tem sombra (elevação é por cor) */
  --sombra-cartao: none;
  --sombra-flutuante: 0 16px 48px hsl(0 0% 0% / .5);

  /* medalhas da escada (bronze · prata · ouro) · 04/10: o degrau conquistado leva a cor do SEU metal, nunca o verde do sucesso. Só reusa a paleta (cobre, cinza, ouro): nenhum hex novo. */
  --medalha-bronze: color-mix(in srgb, var(--booot-ouro-700) 70%, var(--booot-erro));   /* cobre-avermelhado #BF6E2C · se distingue do ouro e do verde */
  --medalha-prata: var(--booot-cinza-600);    /* 6,53 s/ cartão 010 */
  --medalha-ouro: var(--booot-ouro-600);      /* a cor da marca · 6,57 s/ cartão 010 */

  /* gráfico · a métrica-herói é a ÚNICA série ouro (9,69 e 3,18 s/ cartão nas neutras) */
  --serie-1: var(--booot-ouro-600);
  --serie-2: var(--booot-cinza-600);
  --serie-3: var(--booot-cinza-500);
}

@media (min-width: 640px) { :root { --fs-tela: var(--fs-3xl); } }

/* =====================================================================
   TEMA CLARO · a página é o #F6F7F8 do dono, o cartão é branco puro.
   Ouro de preenchimento NÃO existe aqui (ouro cru mede 2,47 s/ cinza-900
   e reprova até como indicador); o acento vira couro 800 em texto/borda
   e o CTA vira grafite.
   ===================================================================== */
.tema-claro {
  --pagina: var(--booot-cinza-900);
  --superficie: #FFFFFF;
  --superficie-2: #FFFFFF;
  --flutuante: #FFFFFF;

  /* texto · 1º 17,53 s/ página (18,80 s/ branco) · 2º 5,10 · 3º 8,67 */
  --texto: var(--booot-cinza-000);
  --texto-2: var(--booot-cinza-500);
  --texto-3: var(--booot-cinza-400);
  --texto-lead: var(--booot-cinza-300);   /* 11,42 s/ página 900 · 12,25 s/ branco (medido 16/ago) */

  --borda: color-mix(in srgb, var(--booot-cinza-000) 12%, transparent);
  --borda-forte: color-mix(in srgb, var(--booot-cinza-000) 20%, transparent);

  /* ⚠️ O `--acento` TAMBÉM desce pro couro aqui, e este bloco vivia sem ele.
     O cabeçalho deste arquivo já mandava ("no claro o ouro vira texto/borda no degrau
     800 couro"), mas só `--acento-texto` tinha sido remapeado: `--acento` continuava
     valendo o ouro 600 do :root e vazava ouro CRU pro tema claro por toda porta que
     usa o token de PREENCHIMENTO -- o selo "✓ SELECIONADO" do /checkout, a borda da
     aba Pix do /reserva, o disco de confirmação do /obrigado, o ponto "agora" da
     linha do tempo do /panorama, o anel de progresso do /cadastro. Um token que não
     muda com o tema é a família inteira de defeito da repintura numa linha só.
     Preenchimento de ouro segue PROIBIDO no claro (palavra do dono): quem preenche
     com `--acento` e leva TEXTO em cima (selo, badge) perde o fundo e vira
     texto+borda na sua própria regra `.tema-claro`; couro como texto/borda/ícone e
     como fundo de wash (14%) é o que este degrau autoriza. */
  --medalha-bronze: color-mix(in srgb, var(--booot-ouro-800) 70%, var(--booot-erro));   /* cobre escuro #A35B28 */
  --medalha-prata: var(--booot-cinza-500);    /* 5,10 s/ página 900 */
  --medalha-ouro: var(--booot-ouro-800);      /* couro: no claro o ouro vira couro (ouro cru não passa) */
  --acento: var(--booot-ouro-800);            /* couro · 5,70 s/ página · 6,11 s/ branco */
  --acento-texto: var(--booot-ouro-800);      /* couro · 5,70 s/ página · 6,11 s/ branco */

  /* CTA claro = grafite (hover/press sobem degraus da escada de cinza) */
  --cta-fundo: var(--booot-cinza-000);
  --cta-texto: #FFFFFF;                       /* 18,80 s/ o fundo grafite do botão */
  --cta-hover: var(--booot-cinza-100);
  --cta-press: var(--booot-cinza-200);

  --anel-foco: 2px solid var(--booot-ouro-800);   /* 5,70 s/ página (piso 3,0 UI) */

  /* semânticas como texto corrido: mistura 70% cor + 30% grafite (medido: 5,32 · 5,23 · 5,29 s/ página) */
  --erro-texto: color-mix(in srgb, var(--booot-erro) 70%, var(--booot-cinza-000));
  --sucesso-texto: color-mix(in srgb, var(--booot-sucesso) 70%, var(--booot-cinza-000));
  --info-texto: color-mix(in srgb, var(--booot-info) 70%, var(--booot-cinza-000));

  --campo-fundo: #FFFFFF;
  --campo-borda: color-mix(in srgb, var(--booot-cinza-000) 45%, transparent);  /* 3,04 s/ branco (piso 3,0) */
  --campo-borda-foco: var(--booot-ouro-800);

  /* claro: elevação é por sombra discreta + borda (cartão branco s/ página quase-branca) */
  --sombra-cartao: 0 1px 2px hsl(210 20% 10% / .06), 0 4px 16px hsl(210 20% 10% / .06);
  --sombra-flutuante: 0 16px 48px hsl(210 20% 10% / .18);

  /* a métrica-herói também desce um degrau: `--serie-1` ficava no ouro 600 e as barras
     do /panorama e do /reuniao saíam em ouro cru sobre branco (2,47) */
  --serie-1: var(--booot-ouro-800);           /* 6,11 s/ branco */
  --serie-2: var(--booot-cinza-500);          /* 5,47 s/ branco */
  --serie-3: var(--booot-cinza-300);
}

/* ============================================================================
   PLATAFORMA · os tokens do app logado (go.booot.com.br/app) · D-PLATAFORMA-COPIA-O-STCHAT-07SET
   O dono (07/09/2026): "o objetivo é ficar mais próximo ao STChat possível, para garantir consistência
   nas 2 plataformas". Valores MEDIDOS ao vivo em crm.booot.com.br (getComputedStyle, claro e escuro) e
   registrados em _MARCA/whitelabel/refs-stchat/ANATOMIA-MEDIDA.md. O escopo é o documento que carrega a
   casca (.sh-app · app/shell.html) ou a tela de entrar (.en-caixa · entrar.html): o Portal e o resto da casa NÃO mudam. Só os SEMÂNTICOS (CSS-only)
   são revalorados aqui; os primitivos (cinza-*, ouro-*) seguem os mesmos: o verify-tokens exige paridade
   css/json/tw dos valores do `:root` base (ele LÊ O BASE e ignora este bloco), então o que o app revalora abaixo
   (raio, passo de espaço, texto de 11 px, número de KPI, transição de 150 ms) é o valor MEDIDO no CRM e vale só
   onde há `.sh-app`/`.en-caixa` (fatia 1 de D-APP-COPIA-O-DESIGN-SYSTEM-DO-CRM-CLARO-E-ESCURO-PARAMETRIZADO-E-TESTADO-CLICANDO-07OUT,
   valores em _work/design-crm/INVENTARIO.md §3 e §5). A primária do whitelabel é o
   cinza-500 (D-WHITELABEL-CORES-OURO-16AGO); o ouro fica só no símbolo e na pill do plano.
   ============================================================================ */
:root:has(.sh-app, .en-caixa) {
  /* escuro do STChat (204 26% 7% · 204 24% 10% · 204 20% 15% · 200 18% 93% · 204 12% 64% · 204 18% 17%) */
  --pagina: #0D1316;
  --superficie: #131B20;
  --superficie-2: #1F282E;
  --texto: #EAEEF0;
  --texto-2: #98A5AE;
  --texto-3: #84929D;   /* 5,46 s/ a superfície · 5,86 s/ a página · 4,70 s/ a superfície-2 (WCAG 1.4.3, piso 4,5): o #6F7E89 do STChat dava 4,17 s/ a superfície e 3,58 s/ a superfície-2 (medido em 07/10, AUDITORIA B1) */
  --texto-lead: #C4CCD2;
  --borda: color-mix(in srgb, #242D33 70%, transparent);
  --borda-forte: #2E3940;
  --campo-fundo: color-mix(in srgb, #1F282E 40%, transparent);
  --campo-borda: #5C6B75;   /* 3,17 s/ a superfície · 3,40 s/ a página: a borda do campo é o contorno do controle (WCAG 1.4.11, piso 3:1); a do STChat dava 1,2 e o campo sumia (03/10) */
  --campo-borda-foco: var(--booot-cinza-500);
  /* GRAMÁTICA v1 (06/10 · revisão 3 · dono, L068 e L087: "São muitas fontes concorrendo" · "as caixas não estão padronizadas"). O APP tem 4 tamanhos de texto, não 6 (G1): rótulo 14 · corpo 16 · título 20 · número herói 32.
     O 12 (--fs-micro) cai para o 14 e o 24 (--fs-2xl) cai para o 20, o mais perto; o Portal segue com a escala dele (estas linhas só valem onde há `.sh-app`/`.en-caixa`).
     A CAIXA é uma só (G3, a regra mora em app.css); a página é uma coluna centrada de 1120 px (G6): `--pagina-max`. */
  --fs-micro: var(--fs-sm);
  --fs-2xl: var(--fs-xl);
  --pagina-max: 70rem;
  /* CTA = GRAFITE (D-BOTAO-PRINCIPAL-GRAFITE-NO-APP-04OUT · o cinza-500 parecia desabilitado): no escuro o grafite some no fundo, então o mesmo sistema invertido */
  --cta-fundo: var(--booot-cinza-900);
  --cta-texto: var(--booot-cinza-000);
  --cta-hover: var(--booot-cinza-800);
  --cta-press: var(--booot-cinza-700);
  --anel-foco: 2px solid var(--booot-cinza-500);
  --sombra-cartao: none;   /* T17 (revisão 3, 06/10 · dono: "Essas caixas com profundidade... só poluiu mais"): o app é plano, a borda separa o cartão */
  --sombra-flutuante: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);
  /* A FORMA DO CRM (medida em crm.booot.com.br, 07/10, claro e escuro: os mesmos valores nos dois temas). Fonte: INVENTARIO.md §3 (raio, espaço, movimento) e §2 (texto).
     Formato DTCG (W3C DTCG, designtokens.org/tr/drafts/format, `$type: dimension`): cada linha abaixo é um token de dimensão; nome e valor são o do CRM, o `--raio-*` e o `--motion-*` só trocam o valor do nome que a casa já tinha. */
  --raio-controle: .375rem;      /* 6 px · input, botão retangular, badge (CRM `rounded-md`) */
  --raio-cartao: .75rem;         /* 12 px · card, KPI, painel (CRM `rounded-xl`) */
  --raio-flutuante: .5rem;       /* 8 px · modal e popover: o diálogo do CRM é MENOR que o card */
  --space-xs: .375rem;           /* 6 px · o gap de meta de card e o rótulo colado ao número */
  --space-md: .75rem;            /* 12 px · O PASSO DOMINANTE do CRM entre blocos (15 a 222 usos por tela); é o mesmo degrau do `--sh-12` do kit */
  --fs-meta: .6875rem;           /* 11 px · o metadado padrão do CRM (eixo de gráfico, "vs" do período); só texto de apoio e só com --texto-2 ou mais forte */
  --fs-kpi: 1.5rem;              /* 24 px · o número do KPI (CRM: 24/700); o peso é o --fw-bold */
  --motion-fast: 150ms;          /* a transição única do CRM */
  --motion-base: 150ms;
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
}
:root:has(.sh-app, .en-caixa).tema-claro {
  /* claro do STChat (210 20% 98% · branco · 210 20% 96% · 222 47% 11% · 215 16% 47% · 214 32% 91%) */
  --pagina: #F9FAFB;
  --superficie: #FFFFFF;
  --superficie-2: #F1F5F9;
  --texto: #0F172A;
  --texto-2: #526074;   /* 6,39 s/ branco · 6,12 s/ a página · 5,84 s/ a superfície-2 (WCAG 1.4.3). O #64748B do STChat dava 4,76 · 4,55 · 4,34: reprovava s/ a superfície-2 e não deixava espaço para um 3º degrau MAIS CLARO que ainda passe 4,5:1; o 2º degrau desce 1 tom para a ordem texto > texto-2 > texto-3 valer nos 2 temas (07/10) */
  --texto-3: #5F6E83;   /* 5,19 s/ branco · 4,97 s/ a página · 4,74 s/ a superfície-2 (WCAG 1.4.3, piso 4,5): o #94A3B8 do STChat dava 2,56 s/ branco e 2,45 s/ a página (medido em 07/10, AUDITORIA B1). Mais claro que o --texto-2 (#526074, 6,39) e ainda ≥ 4,5:1 */
  --texto-lead: #334155;
  --borda: color-mix(in srgb, #E1E7EF 70%, transparent);
  --borda-forte: #CBD5E1;
  --campo-fundo: color-mix(in srgb, #F1F5F9 40%, transparent);
  --campo-borda: #8492A6;   /* 3,16 s/ branco · 3,02 s/ a página: o contorno do campo passa o piso 3:1 (WCAG 1.4.11); a do STChat dava 1,4 (03/10) */
  --campo-borda-foco: var(--booot-cinza-500);
  /* CTA = GRAFITE AZULADO (D-BOTAO-PRINCIPAL-GRAFITE-NO-APP-04OUT revista pelo T14 de 05/10): texto branco 17,85:1; hover e press sobem a escada do PRÓPRIO azulado (--texto-lead e a mistura dele), sem hex novo */
  --cta-fundo: var(--texto);     /* T14 (revisão 3, 06/10 · dono: "no tema claro, parece que você usou preto... Não usou o azul, o azulado"): o grafite AZULADO do claro, o mesmo do texto (#0F172A), nunca o quase-preto 000 */
  --cta-texto: #FFFFFF;
  --cta-hover: var(--texto-lead);   /* T14: #334155 · 10,35:1 com o branco */
  --cta-press: color-mix(in srgb, var(--texto-lead) 50%, var(--texto));   /* T14: entre o hover e o fundo, ainda azulado */
  --anel-foco: 2px solid var(--booot-cinza-500);
  --sombra-cartao: none;   /* T17 (revisão 3, 06/10 · dono: "Essas caixas com profundidade... só poluiu mais"): o app é plano, a borda separa o cartão */
  --sombra-flutuante: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);
}


/* ═══ 0 · A RECEITA UNICA (uma definicao, reusada em tudo que reage ao ponteiro) ════════════════════ */

:root {
  /* o `.transition` do fornecedor, letra por letra (estilo-do-fornecedor.css) */
  --sh-dur: 150ms;
  --sh-ease: cubic-bezier(.4, 0, .2, 1);
  --sh-ease-saida: cubic-bezier(0, 0, .2, 1);   /* o `.ease-out`, so na ABERTURA de popup */
  --sh-transicao: color var(--sh-dur) var(--sh-ease), background-color var(--sh-dur) var(--sh-ease),
    border-color var(--sh-dur) var(--sh-ease), opacity var(--sh-dur) var(--sh-ease),
    box-shadow var(--sh-dur) var(--sh-ease), transform var(--sh-dur) var(--sh-ease);
  /* o `shadow-lg` (so o modal usa) em rem: o tokens.css nao o define e a folha nao escreve px */
  --sh-sombra-modal: 0 .625rem .9375rem -.1875rem color-mix(in srgb, var(--booot-cinza-000) 10%, transparent),
    0 .25rem .375rem -.25rem color-mix(in srgb, var(--booot-cinza-000) 10%, transparent);
  /* anel de foco DENTRO do grafite · 55% e nao os 30% do fornecedor, que medem 2,45:1 (piso 3:1) */
  --sh-anel-grafite: color-mix(in srgb, var(--booot-cinza-900) 55%, transparent);
  --sh-12: var(--space-md, calc(var(--space-1) * 3));   /* o `px-3` dele: 12px · no app o degrau nasce no tokens.css (`--space-md`, o passo dominante do CRM); fora do escopo do app (404, index) segue o calc */
}

/* ═══ 1 · BASE ══════════════════════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }

/* [hidden] TEM que vencer o display do componente: o `display: grid` de `.sh-menu` (autor) ganha do
   `[hidden]{display:none}` do navegador, e o menu da conta ficava ABERTO por cima do conteudo em toda
   pagina, com a suite verde (achado da bancada, 07/09). Os resets de mercado carregam a mesma linha. */
[hidden] { display: none !important; }

/* NUNCA UMA PALAVRA ÓRFÃ (o dono, revisão de 03/10 [11:24:56]: "nunca deveria existir uma palavra órfão numa linha. Isso é o básico do design"):
   o navegador equilibra as linhas de TODO texto (`balance`; o texto longo em `pretty`), em toda tela, num ponto só. O teto de órfãs medidas no navegador só desce (`design-escala-orfas.json`). */
html { text-wrap: balance; }   /* `text-wrap` HERDA: um ponto só cobre p, li, span, b, célula, rótulo e o texto de todo componente. `balance` (até 6 linhas) equilibra as linhas do texto curto de UI: `pretty` deixava a órfã em frases de 2 linhas ("Libere a sua Página do Facebook") */
:where(.sh-doc-secao, .sh-doc-lista, .sh-texto-pronto, .sh-detalhes-corpo > p) { text-wrap: pretty; }   /* o texto LONGO (documento, explicação aberta) fica em `pretty`: o equilíbrio só vale até 6 linhas */
b, strong { font-weight: var(--fw-semibold); }   /* o negrito solto é o semibold: 2 pesos no app inteiro (era o 700 do navegador) */
:where(input, textarea, select, code, pre, .sh-codigo) { text-wrap: wrap; }

body {
  margin: 0;
  background: var(--pagina);
  color: var(--texto);
  font-family: var(--fonte-texto);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);                 /* 14/20 · o `text-sm` do fornecedor (.875rem / 1.25rem) */
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; }
img { height: auto; }

:where(h1, h2, h3, h4, p, ul, ol, figure, dl) { margin: 0; }
:where(ul, ol) { padding: 0; list-style: none; }

a { color: inherit; }

:where(button, input, select, textarea) { font: inherit; color: inherit; }

:focus-visible { outline: var(--anel-foco); outline-offset: var(--focus-offset); border-radius: var(--raio-controle); }

/* so LEITOR DE TELA (o rotulo que a tela nao mostra) */
.sh-vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* pular pro conteudo: o 1o Tab de toda pagina */
.sh-pular {
  position: fixed; z-index: var(--z-toast); top: var(--space-2); left: var(--space-2);
  padding: var(--space-2) var(--space-3); border-radius: var(--raio-controle);
  display: inline-flex; align-items: center; min-height: 44px;
  background: var(--booot-cinza-900); color: var(--booot-cinza-000);
  font-weight: var(--fw-semibold); text-decoration: none;
  transform: translateY(-200%);
}
.sh-pular:focus { transform: none; }

.sh-icone {
  flex: 0 0 auto; width: 1rem; height: 1rem;
  fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}

/* O ICONE DO TEMA MOSTRA O DESTINO, NAO O ESTADO (a receita do STChat, e o defeito que o verificador
   fresco de 07/09 pegou: "Ver no escuro" com um SOL do lado). Sol = vou pro claro (estou no escuro) ·
   lua = vou pro escuro (estou no claro). A troca e SO CSS, de proposito: com JS ela dependeria do
   hidratador e piscaria o icone errado no primeiro quadro. `:root` sem classe = tema escuro. */
.sh-icone--lua { display: none; }
html.tema-claro .sh-icone--sol { display: none; }
html.tema-claro .sh-icone--lua { display: inline-block; }

/* ═══ 2 · O ESQUELETO (menu fixo + barra fixa + conteudo) ═══════════════════════════════════════════ */

.sh-app {
  --sh-menu: 15rem;
  --sh-topo: 3.5rem;
  min-height: 100vh;
}
.sh-app[data-menu="recolhido"] { --sh-menu: 4.25rem; }

/* ── 2.1 · o painel lateral. Grafite nos DOIS temas (so primitivo: nada aqui muda com .tema-claro) ── */
.sh-side {
  position: fixed; inset: 0 auto 0 0; z-index: var(--z-sticky);
  display: flex; flex-direction: column;
  width: var(--sh-menu); padding: var(--space-2);
  background: var(--booot-cinza-000);
  color: var(--booot-cinza-900);
  border-inline-end: 1px solid var(--booot-cinza-300);
  overflow: hidden auto;
  transition: width var(--motion-fast) var(--ease-standard), transform var(--motion-base) var(--ease-standard);
}

/* o trocador de conta · `h-12 rounded-xl bg-sidebar-foreground/[0.08] ring-1 ring-sidebar-border
   hover:bg-sidebar-foreground/[0.14] gap-3 px-3`. O anel e box-shadow, nao borda: nao muda a caixa. */
.sh-org {
  display: flex; align-items: center; gap: var(--sh-12);
  width: 100%; min-height: 3rem; margin-bottom: var(--space-2); padding: var(--space-1) var(--sh-12);
  border: 0; border-radius: var(--raio-cartao);
  background: color-mix(in srgb, var(--booot-cinza-900) 8%, transparent); color: inherit;
  box-shadow: 0 0 0 1px var(--booot-cinza-300);
  text-align: left; cursor: pointer;
  transition: var(--sh-transicao);
}
.sh-org:hover:not(:disabled) { background: color-mix(in srgb, var(--booot-cinza-900) 14%, transparent); }
.sh-org:active:not(:disabled) { transform: scale(.97); }
.sh-org:disabled { cursor: default; }
.sh-org-logo { flex: 0 0 auto; width: 1.25rem; height: auto; }
.sh-org-nome {
  /* I (30/09 · juiz do ar): "Studio Zion Funcio…" nas 5 telas. O nome da academia é o herói da casca e é TEXTO DO CLIENTE:
     quebra em quantas linhas precisar, nunca corta (04/10 · G2: era `line-clamp: 2`; nome de academia grande perdia o fim). */
  flex: 1; min-width: 0;
  overflow-wrap: anywhere; line-height: var(--lh-snug);
  font-weight: var(--fw-semibold); font-size: var(--fs-sm);
}
.sh-org-chevron { color: var(--booot-cinza-600); }

.sh-nav { display: grid; gap: var(--space-1); align-content: start; }
.sh-nav-sep {
  display: block; height: 1px; margin: var(--space-2);
  background: var(--booot-cinza-300);
}

/* item do menu · a classe do fornecedor, transcrita: `h-12 rounded-xl text-sidebar-foreground/70
   transition-colors duration-150 hover:bg-sidebar-foreground/10 active:scale-[0.97] gap-3 px-3` · ativo
   `bg-sidebar-foreground/[0.16]`. O icone e `currentColor`: no STChat o ATIVO se marca pelo FUNDO, e o
   ouro que a casca de 07/09 pintava nele e o unico ouro que NAO existe no CRM. */
.sh-nav-item {
  display: flex; align-items: center; gap: var(--sh-12);
  width: 100%; min-height: 3rem; padding: 0 var(--sh-12);
  border: 0; border-radius: var(--raio-cartao);
  background: transparent; color: color-mix(in srgb, var(--booot-cinza-900) 70%, transparent);
  font-size: var(--fs-sm); font-weight: var(--fw-regular); text-align: left; text-decoration: none;
  cursor: pointer; white-space: nowrap;
  transition: var(--sh-transicao);
}
.sh-nav-item > span:not([class]) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sh-nav-item:hover { background: color-mix(in srgb, var(--booot-cinza-900) 10%, transparent); color: var(--booot-cinza-900); }
.sh-nav-item:active { transform: scale(.97); }
.sh-nav-item[aria-current="page"] {
  background: color-mix(in srgb, var(--booot-cinza-900) 16%, transparent);
  color: var(--booot-cinza-900); font-weight: var(--fw-semibold);
}
.sh-nav-item[aria-current="page"]:hover { background: color-mix(in srgb, var(--booot-cinza-900) 22%, transparent); }
.sh-nav-item .sh-icone { width: 1.25rem; height: 1.25rem; color: currentColor; }
/* o item FECHADO no modo 'em-breve' (`_MOTOR/lib/modo-do-app.mjs`): sem destino (o nav.js tira o href), apagado e com o selo "Em breve" ao lado */
.sh-nav-item[aria-disabled="true"], .sh-menu-item[aria-disabled="true"] { opacity: var(--desabilitado); cursor: not-allowed; }
.sh-nav-item[aria-disabled="true"]:hover, .sh-menu-item[aria-disabled="true"]:hover { background: transparent; color: inherit; }
.sh-nav-item[aria-disabled="true"]:active { transform: none; }
.sh-selo { margin-left: auto; flex: none; }


/* O rodape do menu mora num contexto que ROLA (`.sh-side` e `overflow: hidden auto`), e ali `margin-top:
   auto` so empurra pro fim enquanto o conteudo CABE: passando da altura da tela ele vale 0 e o rodape sai
   do campo de visao (o verificador fresco de 07/09 fotografou "Recolher o menu" cortado em 390). O padrao
   do `SidebarFooter` do shadcn e GRUDAR: `sticky bottom: 0` com o fundo do painel (primitivo grafite, o
   mesmo de `.sh-side`: nada aqui muda com o tema). */
.sh-side-rodape {
  position: sticky; bottom: 0; z-index: 1;
  display: grid; gap: var(--space-1); align-content: end;
  margin-top: auto; padding-top: var(--space-2);
  border-top: 1px solid var(--booot-cinza-300);
  background: var(--booot-cinza-000);
}

/* recolhido: so o icone (o rotulo some, o title do HTML fala) */
.sh-app[data-menu="recolhido"] .sh-org-nome,
.sh-app[data-menu="recolhido"] .sh-org-chevron,
.sh-app[data-menu="recolhido"] .sh-nav-item > span,
.sh-app[data-menu="recolhido"] .sh-nav-item > small { display: none; }
.sh-app[data-menu="recolhido"] .sh-nav-item,
.sh-app[data-menu="recolhido"] .sh-org { justify-content: center; padding-inline: 0; }
.sh-app[data-menu="recolhido"] .sh-recolher .sh-icone { transform: scaleX(-1); }

/* ── 2.2 · a barra superior FIXA, da MESMA cor do painel lateral (ordem do dono, 07/09) ── */
.sh-top {
  position: fixed; z-index: var(--z-sticky); top: 0; right: 0; left: var(--sh-menu);
  display: flex; align-items: center; gap: var(--space-3);
  height: var(--sh-topo); padding: 0 var(--space-3);
  background: var(--booot-cinza-000);
  color: var(--booot-cinza-900);
  border-bottom: 1px solid var(--booot-cinza-300);
  transition: left var(--motion-fast) var(--ease-standard);
}
.sh-top-titulo {
  flex: 0 0 auto;
  font-size: var(--fs-md); font-weight: var(--fw-semibold); letter-spacing: normal;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sh-top-acoes { display: flex; align-items: center; gap: var(--space-1); margin-left: auto; position: relative; }

/* icone da direita: `h-8 w-8 rounded-full ... hover:bg-white/15` no fornecedor (o botao REDONDO de 2rem
   com o icone de 1.25rem dentro), nunca um quadrado de raio 10. */
.sh-top-botao {
  display: inline-grid; place-items: center;
  width: 2.25rem; height: 2.25rem;
  border: 0; border-radius: var(--raio-pill);
  background: transparent; color: var(--booot-cinza-700);
  cursor: pointer;
  transition: var(--sh-transicao);
}
.sh-top-botao:hover { background: color-mix(in srgb, var(--booot-cinza-900) 15%, transparent); color: var(--booot-cinza-900); }
.sh-top-botao:active { transform: scale(.97); }
.sh-top-botao .sh-icone { width: 1.25rem; height: 1.25rem; }
/* o botao do topo COM palavra (30/09 · Lei da Adesao R5: icone nunca sem rotulo) · a mesma pilula, larga o bastante */
.sh-top-botao--rotulo { display: inline-flex; gap: var(--space-1); width: auto; padding: 0 var(--space-2); font-size: var(--fs-sm); }
/* o botao da gaveta so existe no celular. Ele carrega as DUAS classes e a especificidade e a mesma, entao
   quem vem depois no arquivo ganha: esta linha PRECISA ficar abaixo de `.sh-top-botao` (antes dela, o
   hamburguer aparecia em 1280 · visto na foto da bancada em 07/09). */
.sh-top-menu { display: none; }

.sh-avatar {
  display: inline-grid; place-items: center;
  width: 2rem; height: 2rem; margin-left: var(--space-1);
  border: 0; border-radius: var(--raio-pill);
  background: var(--booot-cinza-400); color: var(--booot-cinza-900);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: var(--sh-transicao);
}
/* o fornecedor faz `hover:opacity-90`; aqui o hover troca o FUNDO, porque a regua de hover da bancada le
   cor/fundo/borda/sombra e NAO le opacity: mesma leitura na tela, e medivel. */
.sh-avatar:hover { background: var(--booot-cinza-500); }
.sh-avatar:active { transform: scale(.97); }

/* abas em pilula, dentro da barra (Tutoriais · Treinamentos · Gravacoes) */
.sh-abas { display: flex; align-items: center; gap: var(--space-1); min-width: 0; overflow: auto hidden; scrollbar-width: none; overscroll-behavior-x: contain; }
.sh-abas::-webkit-scrollbar { display: none; }
.sh-abas:empty { display: none; }
/* a pagina entrega as abas dentro de um [role=tablist] (o padrao WAI-ARIA); a caixa e a mesma */
.sh-abas > [role="tablist"] { display: flex; align-items: center; gap: var(--space-1); }
/* A PISTA DE ROLAGEM (04/10 · o juiz visual do AR, C4: "WA API Ofi" e "Mentorias e In…" cortados no iPhone, sem nenhum sinal de que havia mais aba · o padrao "Tabs · scrollable" do Material Design 3).
   `App.abas` (app.js §q) liga `data-rola-esq`/`data-rola-dir` na barra conforme ha aba escondida de cada lado; aqui a borda DESVANECE (mascara, nao cor: serve em qualquer fundo de barra).
   A aba nunca encolhe nem ganha reticencias: o rotulo inteiro ou a pista de que ha mais. */
/* A LARGURA DA PISTA (04/10 · o juiz do AR, Atrair a 390 px: "Prompt IA" escondida sem indício). Com 32 px a borda só desvanecia o fim do último rótulo quando o corte caía no vão entre duas abas
   (Posts termina, a próxima começa 4 px depois e fica toda fora da barra): a pista existia e ninguém a via. 48 px desbotam o último rótulo à vista, em qualquer largura de celular. */
:root { --sh-pista: var(--space-6); }
.sh-abas[data-rola-dir] { -webkit-mask-image: linear-gradient(to right, currentcolor calc(100% - var(--sh-pista)), transparent); mask-image: linear-gradient(to right, currentcolor calc(100% - var(--sh-pista)), transparent); }
.sh-abas[data-rola-esq] { -webkit-mask-image: linear-gradient(to left, currentcolor calc(100% - var(--sh-pista)), transparent); mask-image: linear-gradient(to left, currentcolor calc(100% - var(--sh-pista)), transparent); }
.sh-abas[data-rola-esq][data-rola-dir] { -webkit-mask-image: linear-gradient(to right, transparent, currentcolor var(--sh-pista), currentcolor calc(100% - var(--sh-pista)), transparent); mask-image: linear-gradient(to right, transparent, currentcolor var(--sh-pista), currentcolor calc(100% - var(--sh-pista)), transparent); }
/* a aba: `rounded-full px-3 py-1 text-xs font-medium ... opacity-70 hover:bg-white/10` · ativa
   `bg-white/20 opacity-100 shadow-sm` (a classe do fornecedor, verbatim) */
.sh-aba {
  display: inline-flex; align-items: center; flex: none; text-overflow: clip;
  min-height: 2.25rem; padding: 0 var(--sh-12);
  border: 0; border-radius: var(--raio-pill);
  background: transparent; color: color-mix(in srgb, var(--booot-cinza-900) 70%, transparent);
  font-size: var(--fs-sm); font-weight: var(--fw-regular); white-space: nowrap; text-decoration: none;
  cursor: pointer;
  transition: var(--sh-transicao);
}
.sh-aba:hover { background: color-mix(in srgb, var(--booot-cinza-900) 10%, transparent); color: var(--booot-cinza-900); }
.sh-aba:active { transform: scale(.97); }
.sh-aba[aria-selected="true"], .sh-aba[aria-current="page"] {
  background: color-mix(in srgb, var(--booot-cinza-900) 20%, transparent);
  color: var(--booot-cinza-900); font-weight: var(--fw-semibold);
  box-shadow: var(--sombra-cartao);
}
.sh-aba[aria-selected="true"]:hover, .sh-aba[aria-current="page"]:hover {
  background: color-mix(in srgb, var(--booot-cinza-900) 26%, transparent);
}

/* foco dentro do grafite: `focus-visible:ring-2 ring-sidebar-foreground/30` no fornecedor. Aqui o mesmo
   branco em 55%: os 30% dele medem 2,45:1 e reprovam o piso 3:1 de nao-texto (DESIGN.md §11). */
.sh-side :focus-visible, .sh-top :focus-visible {
  outline: medium solid var(--sh-anel-grafite); outline-offset: var(--focus-offset);
}

/* ── 2.3 · o conteudo ── */
.sh-main {
  margin-left: var(--sh-menu);
  padding-top: var(--sh-topo);
  min-height: 100vh;
  background: var(--pagina);
  transition: margin-left var(--motion-fast) var(--ease-standard);
}
.sh-pagina {
  max-width: var(--pagina-max, 70rem); margin-inline: auto;   /* G6 · coluna centrada de 1120 px */
  padding: var(--space-5) var(--space-5) var(--space-7);   /* o computador (1366 e 1440) manda: 32 px de margem, e o conteúdo respira */
  display: grid; gap: var(--space-4); align-content: start;
}
/* a medida de leitura: texto corrido nunca estica de borda a borda (68ch, --medida-texto); número, rótulo e botão não são afetados */
.sh-pagina :where(p, .sh-texto, .sh-apoio) { max-width: var(--medida-texto); }

/* o veu da gaveta. O z-index e o do MENU ABERTO menos 1, nunca o da barra menos 1: com `--z-sticky - 1`
   ele ficava ABAIXO da barra (49 contra 50) e a barra seguia acesa e CLICAVEL por cima dele com a gaveta
   aberta (medido: `elementFromPoint` no canto direito devolvia o avatar). Veu que nao cobre e sombra. */
.sh-veu {
  position: fixed; inset: 0; z-index: calc(var(--z-dropdown) - 1);
  background: var(--veu-foto);
  border: 0;
}

/* ═══ 2b · A BARRA DE CARREGAMENTO DA CASCA (#1174 · 17/09/2026) ═══════════════════════════════════
   O DEFEITO (dono, revisão 17/09, 4 vezes): "demora bastante pra carregar e não existe nenhuma barra de
   loading". Medido no ar: o documento chega em 0,2 s e a Início espera 4-5,5 s por três leituras do
   fornecedor; o esqueleto parado não lê como "está vindo".
   PRONTO (adotado): o padrão YouTube / GitHub / nprogress: 3 px no topo da tela, anda rápido no começo e
   devagar depois (a pessoa vê movimento enquanto a rede segura), fecha em 100% e some. Ouro (a cor da marca),
   nunca semáforo. Quem liga é o kernel (App.ocupado); reduced-motion vira uma barra parada (a regra global). */
.sh-carregando { position: absolute; top: 0; left: 0; right: 0; height: .1875rem; overflow: hidden; pointer-events: none; }
.sh-carregando > i {
  display: block; height: 100%; background: var(--booot-ouro-600);
  transform-origin: left; transform: scaleX(0);
}
.sh-carregando.is-ativo > i { animation: sh-carregar 8s cubic-bezier(.1, .7, .3, 1) forwards; }
.sh-carregando.is-fim > i {
  animation: none; transform: scaleX(1); opacity: 0;
  transition: transform var(--motion-fast) var(--ease-standard), opacity var(--motion-fast) var(--ease-standard) var(--motion-fast);
}
@keyframes sh-carregar { from { transform: scaleX(0); } to { transform: scaleX(.92); } }

/* ═══ 3 · MENU FLUTUANTE (conta · unidades) ═════════════════════════════════════════════════════════ */

/* `rounded-xl p-2 border bg-popover shadow-md`, e a ABERTURA e `animate-in fade-in-0 zoom-in-95
   slide-in-from-top-2` em 150 ms `ease-out`: nunca aparece seco. */
.sh-menu {
  position: absolute; z-index: var(--z-dropdown); top: calc(100% + var(--space-1)); right: 0;
  min-width: 13rem; padding: var(--space-2);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-controle);
  background: var(--flutuante); color: var(--texto);
  box-shadow: var(--sombra-flutuante);
  display: grid; gap: var(--space-1);
  transform-origin: top right;
  animation: sh-entrar var(--sh-dur) var(--sh-ease-saida);
}
.sh-side > .sh-menu { top: 3.25rem; right: var(--space-2); left: var(--space-2); transform-origin: top center; }
.sh-menu-item {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; min-height: 2.25rem; padding: 0 var(--space-2);
  border: 0; border-radius: var(--raio-controle);
  background: transparent; color: inherit;
  font-size: var(--fs-sm); text-align: left; text-decoration: none; white-space: nowrap;
  cursor: pointer;
  transition: var(--sh-transicao);
}
/* `hover:bg-accent`, aqui como lavagem do proprio texto e nao `--superficie-2`: o flutuante do tema
   ESCURO e mais claro que a superficie-2 da Plataforma e o hover iria pro lado errado (medido). */
.sh-menu-item:hover { background: color-mix(in srgb, var(--texto) 7%, transparent); }
.sh-menu-item:active { transform: scale(.97); }
.sh-menu-item .sh-icone { color: var(--texto-2); }

/* ═══ 4 · CARTAO ════════════════════════════════════════════════════════════════════════════════════ */

.sh-card { display: grid; gap: var(--space-3); align-content: start; }
/* G3 · A CAIXA É UMA SÓ (gramática v1, 06/10/2026 · o dono: "as caixas não estão padronizadas"). TODA raiz de caixa de conteúdo do app devolve a MESMA assinatura: raio do cartão, borda de 1 px,
   respiro de 24 (16 no celular), fundo `--superficie`, sombra do token (none no app: o app é plano, a borda separa). Aqui, UMA vez; nenhuma raiz repete borda, raio, fundo nem sombra.
   As 8 raízes: `.sh-card` · `.sh-secao` (a seção-caixa, §19.1) · `.sh-stat` · `.sh-oferta` · `.sh-vitrine` · `.sh-midia` · `.sh-degrau` · `.sh-vazio` solto.
   As faixas e embutidos (`.sh-aviso`, `.sh-video`, `.sh-quadro`, `.sh-qr`, `.sh-org`) são PEÇAS, não caixas de conteúdo: não entram na conta de caixas (`olhos/deriva.mjs`: PECAS).
   Padrão adotado: um só "card" do Stripe Dashboard e do Linear (https://linear.app/blog/how-we-redesigned-the-linear-ui: poucas elevações), sem variantes de moldura. */
.sh-card, .sh-stat, .sh-oferta, .sh-vitrine, .sh-midia, .sh-degrau,
.sh-secao:not([role="tabpanel"], .sh-secao--solta, :has(> :is(.sh-oferta, .sh-aviso):only-child)),
.sh-secao[role="tabpanel"]:not(.sh-secao--solta):has(> .sh-secao-cabeca),
.sh-vazio:not(:is(.sh-card, .sh-stat, dialog, .sh-secao:not([role="tabpanel"], .sh-secao--solta), .sh-secao:has(> .sh-secao-cabeca)) .sh-vazio) {
  padding: var(--space-4);
  border: 1px solid var(--borda); border-radius: var(--raio-cartao);
  background: var(--superficie);
  box-shadow: var(--sombra-cartao);
}
@media (max-width: 40rem) {   /* 640 px */
  .sh-card, .sh-stat, .sh-oferta, .sh-vitrine, .sh-midia, .sh-degrau,
  .sh-secao:not([role="tabpanel"], .sh-secao--solta, :has(> :is(.sh-oferta, .sh-aviso):only-child)),
  .sh-secao[role="tabpanel"]:not(.sh-secao--solta):has(> .sh-secao-cabeca),
  .sh-vazio:not(:is(.sh-card, .sh-stat, dialog, .sh-secao:not([role="tabpanel"], .sh-secao--solta), .sh-secao:has(> .sh-secao-cabeca)) .sh-vazio) { padding: var(--space-3); }
}
/* G4 · ZERO CAIXA DENTRO DE CAIXA. O filho de uma caixa é LINHA ou SUBGRUPO, nunca outra moldura: a raiz aninhada perde borda, raio, fundo, sombra e respiro (só o espaço da grade da caixa de fora
   separa os irmãos). O estado "atual" de um degrau se vê pelo fundo e pelo peso, não por uma borda. */
:is(.sh-card, .sh-stat, .sh-oferta, .sh-vitrine, .sh-midia, .sh-degrau,
  .sh-secao:not([role="tabpanel"], .sh-secao--solta, :has(> :is(.sh-oferta, .sh-aviso):only-child)),
  .sh-secao[role="tabpanel"]:not(.sh-secao--solta):has(> .sh-secao-cabeca)) :is(.sh-card, .sh-stat, .sh-oferta, .sh-midia, .sh-degrau, .sh-vazio, .sh-secao:not([role="tabpanel"])) {
  padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none;
}
.sh-card-cabeca {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3);
}
.sh-card-acoes { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.sh-stack { display: grid; gap: var(--space-2); }
/* G7 · WEB PRIMEIRO: a grade de blocos tem 1 coluna até 1000 px e 2 colunas dali em diante (nunca 3 ou 4 por sobra de espaço: `auto-fit` era isso). A fileira de números é outra grade (até 4). */
.sh-grade { display: grid; gap: var(--space-4); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1000px) { .sh-grade { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.sh-titulo {
  font-family: var(--fonte-texto);
  font-size: var(--fs-xl); font-weight: var(--fw-semibold); line-height: var(--lh-snug); letter-spacing: normal;
}
.sh-titulo--tela { font-size: var(--fs-tela); }   /* o título da tela: 20 no celular, 32 do tablet em diante (o --fs-tela do token) */
/* o rótulo é FRASE NORMAL (sem caixa alta, sem espaçamento de letra): a hierarquia vem do tamanho e do peso (Nubank / Material 3) */
.sh-rotulo {
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: var(--lh-ui);
  letter-spacing: normal; text-transform: none; color: var(--texto-2);
}
.sh-texto { font-size: var(--fs-md); line-height: var(--lh-ui); color: var(--texto); }
.sh-texto--forte { font-weight: var(--fw-semibold); }
.sh-apoio { font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--texto-2); }
/* o 3o degrau de texto so le a partir de 16px (o tokens.css declara a medida ao lado do token); em 12px
   o micro usa o 2o degrau, senao a linha de rodape sai em 4,48:1 (medido na bancada em 07/09) */
.sh-micro { font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--texto-2); }
/* o METADADO de 11 px do CRM (07/10 · INVENTARIO §2: o `meta-11`, dominante em Tarefas e Contatos): só para a linha que explica o que está ao lado (contra quê o cartão compara, o eixo de um gráfico), sempre em --texto-2 (4,5:1 nos 2 temas, travado no verify-tokens). Nunca para texto que o dono precisa ler para decidir. */
.sh-meta { font-size: var(--fs-meta); line-height: var(--lh-ui); color: var(--texto-2); }

/* ═══ 5 · KPI (o numero que o dono le de relance) ═══════════════════════════════════════════════════ */

.sh-kpi { display: grid; gap: var(--space-xs); align-content: start; }
.sh-kpi-cabeca { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.sh-kpi-cabeca .sh-icone { color: var(--texto-2); }
/* `text-2xl font-bold tabular-nums leading-none` = 1.5rem/700/1. Numero de produto NAO e manchete: a aba
   Acelerar abria com "500" em 52px, e foi isso que o dono chamou de Word. O HEROI (um por tela) vai a 2rem. */
.sh-kpi-numero {
  font-size: var(--fs-kpi); font-weight: var(--fw-bold); line-height: 1;   /* 07/10: 24/700, o número do KPI do CRM (INVENTARIO §2); o herói abaixo segue 32 */
  font-variant-numeric: tabular-nums; letter-spacing: var(--letra-titulo);
}
.sh-kpi-numero--heroi { font-size: var(--fs-3xl); }
/* o 2º valor de um cartão (o foco abaixo do número que falta): um degrau de título, para os dois não competirem */
.sh-kpi-numero--medio { font-size: var(--fs-xl); line-height: var(--lh-snug); }
/* a FRASE EM DESTAQUE de um cartão (a resposta de uma simulação): o mesmo degrau do número médio, em texto corrido */
.sh-destaque { font-size: var(--fs-xl); font-weight: var(--fw-semibold); line-height: var(--lh-snug); letter-spacing: normal; color: var(--texto); }
.sh-kpi-numero b { font-weight: inherit; }
.sh-kpi-apoio { font-size: var(--fs-sm); color: var(--texto-2); }
.sh-kpi-numero[data-valencia="bom"] { color: var(--sucesso-texto); }
.sh-kpi-numero[data-valencia="ruim"] { color: var(--erro-texto); }
/* A VARIAÇÃO do KPI (CRM Relatórios: pílula ▲/▼ sob o número). A COR É O VEREDITO, não o sinal (o CRM pinta de vermelho o que subiu 1264%: ambíguo, AUDITORIA UX-5): `data-valencia` "bom" | "ruim" | "neutro" vem de quem conhece o indicador
   (mais aluno é bom, mais custo é ruim). Estado nunca só cor: o glifo ▲/▼ e o número vão no texto. 11 px (--fs-meta), cor de texto que passa 4,5:1 nos 2 temas. A linha existe SEMPRE (min-height): trocar o período não muda a altura do cartão. */
.sh-kpi-delta {
  display: inline-flex; align-items: center; gap: var(--space-xs); min-height: 1.25rem;
  font-size: var(--fs-meta); font-weight: var(--fw-semibold); line-height: var(--lh-ui); font-variant-numeric: tabular-nums; color: var(--texto-2);
}
.sh-kpi-delta[data-valencia="bom"] { color: var(--sucesso-texto); }
.sh-kpi-delta[data-valencia="ruim"] { color: var(--erro-texto); }
.sh-kpi-delta-ref { font-weight: var(--fw-regular); color: var(--texto-2); }

/* ═══ 6 · PILL (estado sempre com ponto, nunca so cor) ══════════════════════════════════════════════ */

/* 11px/500, sem CAIXA ALTA (DESIGN.md §7). O PONTO nao e decoracao: so aparece em ESTADO VIVO (No ar ·
   Conectado · Desativada). Pill sem estado nasce sem ponto: era o anti-padrao que a §7 lista. */
.sh-pill {
  display: inline-flex; align-items: center; gap: var(--space-1);
  min-height: 1.5rem; padding: 0 var(--sh-12);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-pill);
  background: var(--pagina); color: var(--texto-2);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); white-space: nowrap;
}
.sh-pill--sucesso::before, .sh-pill--atencao::before, .sh-pill--erro::before, .sh-pill--vivo::before {
  content: ""; width: .375rem; height: .375rem; border-radius: var(--raio-pill);
  background: currentColor; flex: 0 0 auto;
}
.sh-pill--sucesso { color: var(--sucesso-texto); border-color: color-mix(in srgb, var(--booot-sucesso) 40%, transparent); }
.sh-pill--atencao { color: var(--acento-texto); border-color: color-mix(in srgb, var(--booot-ouro-600) 40%, transparent); }
.sh-pill--erro { color: var(--erro-texto); border-color: color-mix(in srgb, var(--booot-erro) 40%, transparent); }
/* o selo do plano: o UNICO ouro do painel lateral junto com o simbolo (nunca em botao). No CONTEUDO ele
   segue o acento do tema (couro no claro: ouro cru sobre branco mede 2,47:1 e reprova); dentro do painel
   lateral e da barra, que sao sempre grafite, ele volta pro ouro-600 em primitivo. */
.sh-pill--plano {
  border-color: color-mix(in srgb, var(--acento) 45%, transparent);
  background: transparent; color: var(--acento-texto);
  min-height: 1.25rem; padding: 0 var(--space-1); font-size: var(--fs-sm);
}
.sh-side .sh-pill--plano { border-color: color-mix(in srgb, var(--booot-ouro-600) 45%, transparent); color: var(--booot-ouro-600); }

/* a pílula que se CLICA (filtro, período, tema: `button.sh-pill`, `a.sh-pill`) tem altura de controle (36 px; 44 no dedo, §16); a que só informa segue em 24 px */
button.sh-pill, a.sh-pill { min-height: 2.25rem; }
/* todo resumo que abre (<details>) é um controle: a linha toda clica, com a altura de um botão (36 px; 44 no dedo, §16) */
details > summary { min-height: 2.25rem; padding-block: var(--space-2); cursor: pointer; }   /* sem `display`: o triângulo nativo do resumo fica */

/* ═══ 7 · BOTAO (as DUAS formas do fornecedor, medidas na marcacao dele) ════════════════════════════ */

/* ⚠️ ACHADO (HANDOFF-F §3.1): o STChat tem DUAS formas de botao, e so UMA e pilula.
     primario   -> `bg-primary hover:bg-primary/90 h-9 rounded-md px-3 text-sm font-medium` · NAO e pilula
     secundario -> `border border-input h-8 rounded-full px-3 text-xs font-medium`          · E pilula
   Fonte: a marcacao salva do fornecedor + `.rounded-md{calc(var(--radius) - 2px)}` com `--radius:.5rem`.
   As 2 fotos do dono confirmam. Pilular o primario AFASTARIA o app do CRM no botao mais visivel da tela. */
.sh-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 2.25rem; padding: 0 var(--sh-12);   /* o PISO DE CLIQUE do computador: 36 px (2x o 24 do WCAG 2.5.8); no dedo sobe a 44 (§16) */
  border: 1px solid transparent; border-radius: var(--raio-pill);
  background: transparent; color: var(--texto);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); text-decoration: none; white-space: nowrap;
  cursor: pointer;
  transition: var(--sh-transicao);
}
/* `disabled:opacity-50 disabled:pointer-events-none` · nunca troca de cor (DESIGN.md §7) */
.sh-btn:disabled, .sh-btn[aria-disabled="true"] { opacity: var(--desabilitado); cursor: not-allowed; pointer-events: none; }
.sh-btn:active:not(:disabled) { transform: scale(.97); }
.sh-btn .sh-icone { width: .9375rem; height: .9375rem; }

.sh-btn--primario {
  min-height: 2.25rem; padding: 0 var(--space-3);
  border-radius: var(--raio-controle);
  background: var(--cta-fundo); color: var(--cta-texto);
  font-size: var(--fs-sm);
  box-shadow: var(--sombra-cartao);
}
/* o hover e o degrau do TEMA (`--cta-hover`, tokens.css): com o CTA grafite (D-BOTAO-PRINCIPAL-GRAFITE-NO-APP-04OUT) escurecer com o
   cinza-000 nao mudava nada; o token sobe a escada do cinza (claro: 000 → 100) e desce no escuro invertido (900 → 800). Nunca alfa: o `/90`
   do fornecedor cai abaixo do piso 4,5 sobre cartao branco (medido). */
.sh-btn--primario:hover:not(:disabled) { background: var(--cta-hover); }
.sh-btn--primario:active:not(:disabled) { background: var(--cta-press); }
.sh-btn--secundario { background: var(--superficie); border-color: var(--borda-forte); color: var(--texto); }
/* ⚠️ o hover NAO pode ser `--superficie-2`: no claro ele e branco puro, igual a `--superficie`, e o botao
   ficava sem NENHUMA mudanca sobre um cartao (medido). A lavagem do texto muda nos dois temas. */
.sh-btn--secundario:hover:not(:disabled) { background: color-mix(in srgb, var(--texto) 6%, transparent); border-color: var(--texto-2); }
.sh-btn--fantasma { color: var(--texto-2); }
.sh-btn--fantasma:hover:not(:disabled) { background: color-mix(in srgb, var(--texto) 7%, transparent); color: var(--texto); }
.sh-btn--perigo { color: var(--erro-texto); border-color: color-mix(in srgb, var(--booot-erro) 35%, transparent); }
.sh-btn--largo { width: 100%; }
/* a variante GRANDE (03/10 · regra 31 do dono: "esses botões de ver o plano poderiam ser maiores"): a ação principal da tela, 48 px, sem mudar a cor do botão. No celular ocupa a linha. */
.sh-btn.sh-btn--grande { min-height: 3rem; padding: 0 var(--space-4); font-size: var(--fs-md); }   /* dois seletores: vence o piso de 44 px do celular, que vem depois no arquivo */

/* o botao SO-ICONE do CONTEUDO (o "X" do popup): 2rem redondo, sem caixa nem borda. Irmao de
   `.sh-top-botao`, que so serve DENTRO do grafite (o hover dele e branco a 15%, invisivel num modal). */
.sh-icone-btn {
  display: inline-grid; place-items: center; flex: 0 0 auto;
  width: 2.25rem; height: 2.25rem;
  border: 0; border-radius: var(--raio-pill);
  background: transparent; color: var(--texto-2);
  cursor: pointer;
  transition: var(--sh-transicao);
}
.sh-icone-btn:hover { background: color-mix(in srgb, var(--texto) 8%, transparent); color: var(--texto); }
.sh-icone-btn:active { transform: scale(.97); }
.sh-icone-btn .sh-icone { width: 1.125rem; height: 1.125rem; }

/* ═══ 8 · CAMPO ═════════════════════════════════════════════════════════════════════════════════════ */

/* `h-10 rounded-md border border-input bg-background px-3 text-sm` no fornecedor: campo e RETANGULO. A
   PILULA e da BUSCA, o unico campo redondo do CRM. Foco = `border-primary` + `ring-1` por box-shadow. */
.sh-campo {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: 2.25rem; padding: 0 var(--sh-12);
  border: 1px solid var(--campo-borda); border-radius: var(--raio-controle);
  background: var(--campo-fundo); color: var(--texto);
  font-size: var(--fs-sm);
  transition: var(--sh-transicao);
}
.sh-campo:hover { border-color: var(--texto-2); }   /* o hover ESCURECE o contorno (a borda em repouso já passa 3:1; `--borda-forte` ficaria mais fraca que ela) */
.sh-campo:focus-within { border-color: var(--campo-borda-foco); box-shadow: 0 0 0 1px var(--campo-borda-foco); }
.sh-campo--busca { border-radius: var(--raio-pill); }
.sh-campo[data-erro="sim"] { border-color: var(--booot-erro); }
.sh-campo[data-erro="sim"]:focus-within { box-shadow: 0 0 0 1px var(--booot-erro); }
.sh-campo .sh-icone { color: var(--texto-2); }
/* o campo inteiro e o alvo: sem o `align-self: stretch` o <input> fica com a altura NATURAL do texto (21px
   medidos) dentro de uma caixa de 36, e so a faixa do meio recebe o clique. */
.sh-campo input, .sh-campo select {
  flex: 1; min-width: 0; align-self: stretch; border: 0; background: transparent; color: inherit; font: inherit;
}
.sh-campo input:focus-visible { outline: none; }
.sh-campo input::placeholder { color: var(--texto-2); }

/* ═══ 9 · LISTA (linha de 3rem com divisor) ═════════════════════════════════════════════════════════ */

.sh-lista { display: grid; }
.sh-linha {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: 3rem; padding: var(--space-2) 0;
  border-bottom: 1px solid var(--borda);
  font-size: var(--fs-md);
}
.sh-lista > :last-child.sh-linha, .sh-lista > :last-child > .sh-linha { border-bottom: 0; }
/* so a linha CLICAVEL reage (cartao estatico nao levanta · DESIGN.md §7 e a regra do CRM) */
a.sh-linha, button.sh-linha { transition: var(--sh-transicao); cursor: pointer; }
a.sh-linha:hover, button.sh-linha:hover { background: color-mix(in srgb, var(--texto) 5%, transparent); }
.sh-linha-corpo { flex: 1; min-width: 0; display: grid; gap: 1px; }
.sh-linha-corpo b { font-weight: var(--fw-semibold); }
/* `>` e nao descendente (30/09 · juiz #6 · P1-7): o `span.txt-longo` (o titulo do pedido cortado em 72 caracteres, com o botao "ver mais")
   mora DENTRO do `<b>` do corpo, e a regra de descendente o pintava tambem como apoio (bloco, sem quebra): a linha estourava a largura e o
   "ver mais" sobrepunha o selo. O apoio e SEMPRE filho direto do corpo. */
.sh-linha-corpo > span {
  display: block; color: var(--texto-2); font-size: var(--fs-sm);
  overflow-wrap: anywhere;   /* o apoio da linha QUEBRA e mostra tudo (04/10 · G2, "nenhum texto cortado"): era nowrap + reticências e cortava "Não conseguimos ler agora…" no celular */
}
/* o SELO de estado no corpo (`.sh-pill`) não é apoio (12/10 · #2310, juiz visual: "Falta completar" virava caixa branca larga sobre o texto, porque a regra acima o fazia `block` na cor do apoio):
   volta a ser chip em linha, do tamanho do texto, encostado à esquerda e com a cor do tom dele (o "label/badge" do Primer e do Shoelace: inline-flex, altura fixa, nunca largura total). */
.sh-linha-corpo > .sh-pill { display: inline-flex; justify-self: start; margin-bottom: var(--space-1); color: var(--texto-2); }
.sh-linha-corpo > .sh-pill--sucesso { color: var(--sucesso-texto); }
.sh-linha-corpo > .sh-pill--atencao { color: var(--acento-texto); }
.sh-linha-corpo > .sh-pill--erro { color: var(--erro-texto); }

/* ═══ 10 · VAZIO · ERRO · ESQUELETO (os estados que nao sao "pronto") ═══════════════════════════════ */

/* o vazio ENSINA (regra 4 do fluxo do CRM: icone em circulo de 4rem + titulo + frase + acao). Com
   `.sh-vazio-ico` entra o icone de verdade; sem ele, o ::before desenha o circulo, nunca um vazio pelado. */
.sh-vazio {
  display: grid; justify-items: center; gap: var(--space-2);
  padding: var(--space-5) var(--space-3); text-align: center;
}
.sh-vazio:not(:has(.sh-vazio-ico, .sh-marca))::before {
  content: ""; width: 4rem; height: 4rem; border-radius: var(--raio-pill);
  background: var(--superficie-2); border: 1px solid var(--borda);
}
.sh-vazio-ico {
  display: grid; place-items: center; width: 4rem; height: 4rem;
  border-radius: var(--raio-pill); border: 1px solid var(--borda);
  background: var(--superficie-2); color: var(--texto-2);
}
.sh-vazio-ico .sh-icone { width: 1.5rem; height: 1.5rem; }
.sh-vazio > :where(p, h2, h3):first-of-type { font-size: var(--fs-xl); font-weight: var(--fw-semibold); color: var(--texto); }
.sh-vazio > p { font-size: var(--fs-sm); color: var(--texto-2); max-width: 34ch; }

.sh-erro {
  display: grid; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--raio-controle);
  border: 1px solid color-mix(in srgb, var(--booot-erro) 35%, transparent);
  background: color-mix(in srgb, var(--booot-erro) 8%, transparent);
}
.sh-erro-cabeca { display: flex; align-items: center; gap: var(--space-2); color: var(--erro-texto); }

/* `animate-pulse` do fornecedor, exato. Saiu o brilho que corria de lado: era invencao da casa, e o fundo
   em gradiente ainda cegava a regua de contraste da bancada. */
.sh-esqueleto-grupo { display: grid; gap: var(--space-2); }
.sh-esqueleto {
  display: block; height: .75rem; border-radius: var(--raio-controle);
  background: color-mix(in srgb, var(--texto) 10%, transparent);
  animation: sh-pulsar 2s cubic-bezier(.4, 0, .6, 1) infinite;
}
.sh-esqueleto--titulo { height: 1.125rem; width: 40%; }
.sh-esqueleto--linha { width: 100%; }
.sh-esqueleto--linha-curta { width: 60%; }
.sh-esqueleto--cartao { height: 4rem; width: 100%; }

/* ═══ 11 · BARRA DE PROGRESSO · VIDEO ══════════════════════════════════════════════════════════════ */

.sh-barra {
  position: relative; height: .375rem; border-radius: var(--raio-pill);
  background: color-mix(in srgb, var(--texto) 10%, transparent); overflow: hidden;
}
/* PROGRESSO E NEUTRO, nunca semaforo (DESIGN.md §4; no CRM a barra usa a primaria): uma barra verde diz
   "deu certo" onde o dado so diz "3 de 6". */
.sh-barra > i {
  position: absolute; inset: 0 auto 0 0; display: block;
  width: calc(var(--pct, 0) * 1%); border-radius: inherit;
  background: var(--cta-fundo);
}
/* a CAIXA (`position` + largura) mora na receita compartilhada de §19.15, junto com `.sh-grafico`:
   duas caixas de proporcao na mesma folha eram a 2a receita que este kit existe pra matar. Aqui fica
   so o que e do VIDEO: a razao 16/9 e a moldura. */
.sh-video {
  aspect-ratio: 16 / 9;
  border: 1px solid var(--borda); border-radius: var(--raio-cartao);
  background: var(--superficie-2); overflow: hidden;
}
.sh-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ═══ 12 · BARRA FIXA DE SALVAR ("Alteracoes nao salvas · Salvar", como no STChat) ══════════════════ */

.sh-barra-fixa {
  position: sticky; bottom: 0; z-index: var(--z-sticky);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  margin-top: var(--space-3); padding: var(--space-2) var(--space-3);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-cartao);
  background: var(--flutuante); color: var(--texto);
  box-shadow: var(--sombra-flutuante);
  font-size: var(--fs-sm);
}

/* ═══ 13 · DIALOG NATIVO (a ajuda e todo tutorial · NUNCA outra pagina · ordem do dono 07/09) ═══════ */

/* o modal do CRM: raio 16 (aqui `--raio-cartao`; DESIGN.md §5 pedia o flutuante de 20 e a fidelidade
   vence, declarada), `shadow-lg`, veu a 60%, abertura em 150 ms `ease-out` (veu `fade-in-0`, painel
   `fade-in-0 zoom-in-95 slide-in-from-top-2`). */
dialog.sh-modal {
  width: min(40rem, 100% - var(--space-4));
  max-height: min(85vh, 48rem);
  padding: 0; margin: auto;
  border: 1px solid var(--borda-forte); border-radius: var(--raio-cartao);
  background: var(--flutuante); color: var(--texto);
  box-shadow: var(--sh-sombra-modal);
  overflow: hidden;
}
dialog.sh-modal::backdrop { background: color-mix(in srgb, var(--booot-cinza-000) 60%, transparent); }
dialog.sh-modal[open]::backdrop { animation: sh-aparecer var(--sh-dur) var(--sh-ease-saida); }
dialog.sh-modal[open] {
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  animation: sh-entrar var(--sh-dur) var(--sh-ease-saida);
}
.sh-modal-cabeca {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3); border-bottom: 1px solid var(--borda);
  background: color-mix(in srgb, var(--texto) 4%, transparent);
}
.sh-modal-corpo { padding: var(--space-3); overflow: auto; display: grid; gap: var(--space-3); align-content: start; }
/* ⚪ o rodape do CRM ("Cancelar" fantasma + primario a direita) NAO foi construido: nenhum popup do app
   tem acao hoje (o `.sh-modal` so serve ajuda e tutorial; os modais COM acao do Painel sao os dele). Nasce
   quando o 1o consumidor existir; caixa vazia esperando uso e o que a 5-PASSOS manda deletar. */
.sh-modal-corpo p { font-size: var(--fs-md); color: var(--texto-2); }
/* `:not(.sh-marcos)`: a linha do tempo do kit (§19.22) mora dentro do popup (o caminho do checkout) e não é a lista numerada do tutorial */
.sh-modal-corpo ol:not(.sh-marcos) { display: grid; gap: var(--space-2); counter-reset: sh-passo; }
.sh-modal-corpo ol:not(.sh-marcos) > li {
  display: grid; grid-template-columns: auto 1fr; gap: var(--space-2); align-items: baseline;
  font-size: var(--fs-sm);
}
.sh-modal-corpo ol:not(.sh-marcos) > li::before {
  counter-increment: sh-passo; content: counter(sh-passo);
  display: inline-grid; place-items: center; width: 1.25rem; height: 1.25rem;
  border-radius: var(--raio-pill); background: var(--superficie-2); color: var(--texto-2);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold);
}

/* ═══ 14 · TOAST ════════════════════════════════════════════════════════════════════════════════════ */

.sh-toast {
  position: fixed; z-index: var(--z-toast); bottom: var(--space-4);
  inset-inline: 0; margin-inline: auto; width: fit-content;
  max-width: calc(100% - var(--space-4));
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-pill);
  background: var(--flutuante); color: var(--texto);
  box-shadow: var(--sombra-flutuante);
  font-size: var(--fs-sm);
}
.sh-toast > span { min-width: 0; }
.sh-toast[data-estado="erro"] { border-color: color-mix(in srgb, var(--booot-erro) 45%, transparent); }

/* ═══ 15 · MAQUINA DE ESTADOS (o kernel troca [data-estado]; a folha so esconde quem nao casa) ═════ */

/* SO ESCONDE quem nao casa, e nunca DECLARA display em quem casa: `display: revert` apagaria o `grid`/`flex`
   que a folha deu ao filho (uma `.sh-lista` viraria bloco). O kernel repete a regra por `hidden`, pro estado
   que esta folha nao enumera. */
[data-estado="pronto"] > [data-quando]:not([data-quando~="pronto"]),
[data-estado="vazio"] > [data-quando]:not([data-quando~="vazio"]),
[data-estado="carregando"] > [data-quando]:not([data-quando~="carregando"]),
[data-estado="erro"] > [data-quando]:not([data-quando~="erro"]),
[data-estado="sem_fonte"] > [data-quando]:not([data-quando~="sem_fonte"]),
[data-estado="sem_medida"] > [data-quando]:not([data-quando~="sem_medida"]),
[data-estado="sem_calculadora"] > [data-quando]:not([data-quando~="sem_calculadora"]),
[data-estado="sem_destino"] > [data-quando]:not([data-quando~="sem_destino"]),
[data-estado="sem_sessao"] > [data-quando]:not([data-quando~="sem_sessao"]),
[data-estado="sem_contrato"] > [data-quando]:not([data-quando~="sem_contrato"]),
[data-estado="ativo"] > [data-quando]:not([data-quando~="ativo"]) { display: none; }

/* ═══ 16 · CELULAR E TABLET ════════════════════════════════════════════════════════════════════════ */

@media (max-width: 900px) {
  .sh-side { transform: translateX(-100%); box-shadow: var(--sombra-flutuante); }
  /* a gaveta cobre a barra: com o mesmo z-index, a barra (que vem depois no documento) pintava por cima e
     comia o trocador de conta do topo do menu (visto na foto da bancada em 07/09). */
  .sh-app[data-menu="gaveta"] .sh-side { transform: none; z-index: var(--z-dropdown); }
  .sh-recolher { display: none; }
  .sh-app[data-menu="recolhido"] { --sh-menu: 15rem; }
  .sh-top { left: 0; }
  .sh-top-menu { display: inline-grid; }
  .sh-main { margin-left: 0; }
  .sh-pagina { padding: var(--space-3) var(--space-3) var(--space-6); }
}
@media (min-width: 901px) {
  .sh-veu { display: none; }
}

@media (max-width: 640px) {
  /* as abas ganham a PROPRIA faixa embaixo do titulo: espremidas na mesma linha das 3 acoes, so a primeira
     aparecia e as outras duas rolavam pra fora sem nenhuma pista (visto na foto da bancada em 07/09).
     A altura da barra e um token proprio, entao o `padding-top` do conteudo acompanha sozinho.

     ⚠️ SO QUANDO A PAGINA TEM ABA. Ate 07/09 a faixa era reservada em TODA pagina, e o `/app` (o Painel,
     que nao tem aba) servia barra de 96 px no celular contra os 56 da ANATOMIA §2 (medido pelo verificador
     fresco). `.sh-abas:empty` nao resolve: a pagina entrega as abas dentro de um `[role=tablist]`, que
     nunca fica vazio depois da hidratacao. Quem sabe desde o PRIMEIRO quadro (sem pulo de layout) e o
     contrato da casca: pagina COM aba carrega `<template data-para="[data-abas]">`. O 2o selecionador
     cobre quem injete `.sh-aba` por JS sem passar pelo template. */
  body:has(template[data-para="[data-abas]"]) .sh-app,
  .sh-app:has(.sh-top .sh-aba) { --sh-topo: 6rem; }
  body:has(template[data-para="[data-abas]"]) .sh-top,
  .sh-app:has(.sh-top .sh-aba) .sh-top { flex-wrap: wrap; align-content: center; row-gap: var(--space-1); }
  /* O TÍTULO DO TOPO NUNCA CORTA A PALAVRA (03/10 · o dono, no celular: "Fazer um pedi…"): no celular ele QUEBRA em até 2 linhas (a barra de 56 px comporta, e a de 96 px com abas
     tem folga) em vez de truncar no meio da palavra. As reticências só chegam depois da 2ª linha. Vale para o topo de TODA tela, porque é a peça do kit. */
  .sh-top-titulo {
    flex: 1; min-width: 0; font-size: var(--fs-sm); line-height: var(--lh-snug);
    white-space: normal;
    text-wrap: balance; text-overflow: clip; overflow-wrap: normal; word-break: normal;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  }
  .sh-abas { order: 3; flex-basis: 100%; }
  .sh-btn, .sh-btn--primario, .sh-icone-btn, button.sh-pill, a.sh-pill, details > summary { min-height: 44px; }
  details > summary { padding-block: var(--sh-12); }
  /* A BARRA DO TOPO NO CELULAR (30/09 · juiz #6 · P1-1): esta linha era `.sh-top-botao, .sh-avatar { width: 44px }` e, vindo
     DEPOIS de `.sh-top-botao--rotulo { width: auto }` (§2.2), vencia pela ordem: o botão com PALAVRA ficava preso em 44 px e
     "Ajuda / Avisos / Tema" se atropelavam (o "Tema" cortado pelo avatar). Agora só o botão SEM palavra e o avatar têm 44 px fixos;
     o botão com palavra tem o alvo de 44 px como MÍNIMO e cresce até a palavra caber, e as ações nunca encolhem: quem trunca é o
     TÍTULO da página (reticências). Abaixo de 360 px a palavra sai (o `aria-label` segue dizendo a ação) em vez de sobrepor. */
  .sh-top { gap: var(--space-2); }
  .sh-top-botao:not(.sh-top-botao--rotulo), .sh-avatar { width: 44px; height: 44px; }
  .sh-top-botao--rotulo { width: auto; min-width: 44px; height: 44px; padding-inline: var(--space-1); flex: none; }
  .sh-top-acoes { flex: none; }
  .sh-icone-btn { width: 44px; }
  .sh-aba { min-height: 44px; padding-inline: var(--space-3); }
  .sh-campo, .sh-campo input, .sh-campo select, .sh-menu-item, .sh-escolha { min-height: 44px; }   /* o <select> dentro do campo também: o alvo de toque é ele (medido: 332×42 no "Quanto tempo vale cada voucher?", 44 só da caixa com a borda) */
  .sh-card { padding: var(--space-3) var(--space-2); }
  /* lista com pilula + acoes (Conta › Equipe): o que nao couber ao lado do corpo desce · foto 18/09 */
  .sh-linha { flex-wrap: wrap; row-gap: var(--space-1); }
  .sh-linha-corpo { flex: 1 1 60%; }
  /* o dialog vira folha de baixo (o padrao de bottom sheet do celular · `slide-in-from-bottom` no CRM) */
  dialog.sh-modal {
    width: 100%; max-width: 100%; max-height: 88vh;
    margin: auto auto 0;
    border-radius: var(--raio-cartao) var(--raio-cartao) 0 0;
    border-bottom: 0;
  }
  dialog.sh-modal[open] { animation: sh-subir var(--sh-dur) var(--sh-ease-saida); }
}
/* celular estreito (< 360 px): as 3 palavras do topo não cabem ao lado do menu e do avatar. A palavra sai e o ícone fica (o
   `aria-label` e o `title` seguem dizendo a ação): sobrepor foi o defeito que o juiz #6 achou no 390 (P1-1). */
@media (max-width: 359px) {
  .sh-top-botao--rotulo > span { display: none; }
}

/* o dedo tambem manda em tela SEM ponteiro fino (tablet, celular deitado): o alvo minimo de 44 nao pode
   depender so da largura (DESIGN.md §10) */
@media (hover: none) and (pointer: coarse) {
  .sh-btn, .sh-btn--primario, .sh-aba, .sh-icone-btn, .sh-top-botao, .sh-avatar, .sh-menu-item, .sh-nav-item, button.sh-pill, a.sh-pill, details > summary { min-height: 44px; }
  details > summary { padding-block: var(--sh-12); }
  .sh-icone-btn, .sh-top-botao, .sh-avatar { min-width: 44px; }
}

/* ═══ 17 · O CATALOGO (a prova visual · /catalogo · os 2 temas lado a lado) ════════════════════════ */

.sh-demo { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }
.sh-demo > div {
  display: grid; gap: var(--space-3); align-content: start;
  padding: var(--space-3);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-cartao);
  background: var(--pagina); color: var(--texto);
}
.sh-demo-rotulo {
  font-size: var(--fs-sm); font-weight: var(--fw-semibold);
  color: var(--texto-2);
}
.sh-demo-linha { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* O catalogo NAO roda o hidratador com dados (`data-pct` e uma CHAVE de copy, e o copy.js e de outro
   chip), entao a amostra de barra recebe a largura por aqui, e so aqui. Sem isto o funil apareceria
   zerado na foto e a prova visual seria falsa. */
.sh-demo [data-demo-pct="100"] { --pct: 100; }
.sh-demo [data-demo-pct="46"] { --pct: 46; }
.sh-demo [data-demo-pct="33"] { --pct: 33; }
.sh-demo [data-demo-pct="31"] { --pct: 31; }
.sh-demo [data-demo-pct="20"] { --pct: 20; }

/* o popup e a folha aparecem ABERTOS e no fluxo do catalogo: `dialog` nasce `position: absolute` no
   navegador, e sem isto os dois flutuariam por cima das colunas em vez de posarem pra foto. */
.sh-demo dialog[open] {
  position: static; margin: 0; max-width: 100%; height: auto; max-height: none; animation: none;
}

/* ═══ 18 · MOVIMENTO (os 4 quadros do fornecedor · nada aqui e invencao) ═══════════════════════════ */

/* `@keyframes enter` = opacidade 0 -> 1 + `scale3d(.95)` + `translateY(-.5rem)` · `slide-in-from-bottom`
   na folha do celular · `fade-in-0` no veu · `pulse` no carregando. */
@keyframes sh-entrar { from { opacity: 0; transform: translateY(-.5rem) scale(.95); } }
@keyframes sh-subir { from { opacity: 0; transform: translateY(100%); } }
@keyframes sh-aparecer { from { opacity: 0; } }
@keyframes sh-pulsar { 50% { opacity: .5; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms; animation-iteration-count: 1;
    transition-duration: .01ms; scroll-behavior: auto;
  }
  /* quem afunda no clique nao afunda: `transform` sem transicao continuaria pulando de uma vez */
  .sh-btn:active, .sh-icone-btn:active, .sh-nav-item:active, .sh-aba:active,
  .sh-menu-item:active, .sh-org:active, .sh-top-botao:active, .sh-avatar:active { transform: none; }
}

/* ═══ 19 · O KIT DA RODADA 4 (as classes que TODA tela compoe · contrato §8.3 · LEI DA ADESAO) ══════ */

/* POR QUE ESTA SECAO EXISTE (o diagnostico do dono, 08/09): "parece uma grande gambiarra de elementos".
   A causa medida foi CHASSI AUSENTE: cada pagina inventava o proprio cartao, o proprio botao secundario
   (4 receitas na mesma tela) e o proprio tamanho de letra. Aqui moram as 13 pecas que faltavam, cada uma
   com UMA receita, para que nenhuma pagina precise inventar de novo.

   TIPOGRAFIA TRANCADA EM 4 TAMANHOS E 2 PESOS (a escala atual do app, 06/10: 14 · 16 · 20 · 32; nasceu em 6 passos em 04/10/2026 · obra/rev-d-design · a escala mora em `_MARCA/tokens/tokens.css`, A ESCALA DO APP; aqui só se CONSOME).
   O dono (04/10): "regras muito ruim de design, hierarquia e espaçamento ... adotando os melhores padrões de saas minimalista". A causa medida: 16 tamanhos, 5 pesos e 3 papéis de cinza competindo
   na mesma tela, e a explicação em cinza dominando o número. Padrão adotado: escala de tipo e de espaço do Tailwind em grade de 4/8, 2 papéis de texto do Radix Themes, contraste por tamanho e peso (Geist, Linear).
     papel                 passo               peso   cor            classe
     título de tela        20 (--fs-2xl→xl)    600    texto          `.sh-titulo--tela`
     título de cartão      20 (--fs-xl)        600    texto          `.sh-titulo`
     número do cartão      20 (--fs-2xl→xl)    600    texto          `.sh-kpi-numero` · o herói (UM por tela) 32 (--fs-3xl) `.sh-kpi-numero--heroi`
     corpo                 16 (--fs-md)        400    texto          `.sh-texto`
     apoio                 14 (--fs-sm)        400    texto-2        `.sh-apoio` · `.sh-micro` · `.sh-kpi-apoio` · `.sh-rotulo` (600): UMA linha, nunca o corpo de um parágrafo
     legenda               14 (--fs-micro→sm)  400/600 texto-2      pílula, ponta do trilho
   O secundário (--texto-2) é só APOIO; a explicação longa é texto principal (`.sh-texto`) e mora recolhida em "Saiba mais" (`.sh-detalhes`, `App.cartaoModelo`).
   O ESQUELETO (menu, barra do topo, botão, item de menu) fica em 14 px, a altura de controle de 36 px; as iniciais do avatar em 12. (O 24 e o 12 desta tabela foram colapsados para 20 e 14 em `tokens.css`, bloco GRAMÁTICA v1.)
   A régua que impõe: `stylelint.config.mjs` (token) e `_MOTOR/_tests/design-escala.test.mjs` (catraca: o número de valor solto por arquivo só desce).
   Por que a escala NAO virou custom properties por papel (`--t-tela`...): `defeitosDeToken` (em `app/auditar-app.mjs`)
   reprova toda custom property fora da lista PROPRIOS, e a classe ja entrega o mesmo tranco. Declarado no HANDOFF-K-r4.
   A CAUSA DE RAIZ (03/10/2026): o kit existia, mas nada obrigava a tela a usa-lo. O GATE agora esta no
   `stylelint.config.mjs` (`overrides` para `app/*.css`): a tela COMPOE (posicao, grid, token de espaco), o kit DESENHA
   (borda, raio, sombra, largura de pagina, caixa alta, fundo). Pecas que faltavam: §19.21 a 19.23 (pagina com apoio,
   marcos, calendario).

   ⚠️ A LAVAGEM DO TEXTO NO LUGAR DE `--superficie-2`. Varias pecas daqui precisam de uma superficie
   TINTA (chip de icone, faixa de cabecalho de popup, cartao-radio selecionado). Elas NAO usam
   `--superficie-2` porque no tema claro BASE (`.tema-claro`, que e o que o catalogo usa nas colunas
   claras) ele vale branco puro, igual a `--superficie`: o estado seria invisivel. A folha ja tinha pago
   esse erro no hover do botao secundario (§7). A lavagem `color-mix(in srgb, var(--texto) N%, transparent)`
   le nos DOIS temas e nas DUAS pinturas do claro. */

/* ── 19.1 · SECAO · o bloco de pagina = UM CARTAO (titulo + apoio + acao + conteudo, tudo DENTRO) ──────────────────
   Anatomia: section header do shadcn. A ACAO fica na mesma linha do titulo, nunca embaixo do apoio.

   03/10/2026 · A REGRA DA CAIXA (o dono: "muito erro de padronização com texto dentro e fora das caixas ... colocar 100% dentro das caixas").
   A causa medida: a seção era só um agrupador sem superfície, então o título, o apoio e os botões ficavam SOLTOS no fundo da página e só o
   miolo morava num `.sh-card`. A cura é uma regra do kit, para todas as telas: A SEÇÃO É O CARTÃO.
     (1) `.sh-secao` tem a superfície do cartão (fundo, borda, raio, respiro) e o `.sh-secao-cabeca` (título, apoio, ação) mora DENTRO dela.
     (2) um `.sh-card` filho DIRETO e ÚNICO da seção perde a própria moldura: vira o conteúdo (nunca caixa dentro de caixa).
     (3) vários cartões na mesma seção (os `.sh-card` irmãos, a `.sh-grade` de cartões e de `.sh-stat`) viram LADRILHOS internos leves: a lavagem do
         texto a 5% (a mesma de `.sh-card-ico`; NÃO `--superficie-2`, que no claro é branco puro e o ladrilho sumiria), sem borda e sem sombra.
     (4) fica SEM caixa, por declaração: o painel de uma aba (`[role="tabpanel"]`: é a página, os blocos dele é que são caixas, SALVO quando o
         painel tem o `.sh-secao-cabeca` como filho direto, aí ele mesmo é a seção), a seção que só guarda um `.sh-oferta` ou um `.sh-aviso` (já são um cartão e uma faixa),
         a seção sem filho visível (some em vez de desenhar uma caixa vazia) e o que levar `.sh-secao--solta` (o respiro de página sem caixa, ex.: o
         topo da página). Uma seção dentro de uma seção não leva caixa de novo.
   Padrão adotado: o "card with header" (Material 3 cards https://m3.material.io/components/cards/guidelines · Stripe Dashboard). Zero HTML de tela muda. */
.sh-secao { display: grid; gap: var(--space-3); align-content: start; }
.sh-secao:not([role="tabpanel"], .sh-secao--solta):not(:has(> :not([hidden]))) { display: none; }
/* (5) o estado vazio SOLTO (sem cartão, estatística, diálogo ou seção-caixa em volta) leva a caixa do cartão: "100% dentro das caixas" vale também para o vazio que ensina.
   Dentro de uma caixa ele continua sem moldura (o ícone e a frase são o conteúdo dela). */
/* o painel de uma aba (a página inteira): os blocos dele respiram 24 px entre si, no computador e no celular (04/10 · UM espaço entre cartões: a coluna da página, o painel da aba e a grade usam o mesmo degrau);
   título e corpo de UM bloco seguem a 16 px (o grupo se lê junto) */
.sh-secao[role="tabpanel"] { gap: var(--space-4); }
.sh-secao-cabeca {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: var(--space-3);
}
.sh-secao-cabeca > .sh-stack { min-width: 0; }
/* ⚠️ A ACAO DA SECAO QUEBRA LINHA (08/09 · achado M2 do verificador no ar). Com `flex: 0 0 auto` e
   `.sh-btn { white-space: nowrap }`, o cabecalho de "Sua meta" (o "?" + 2 botoes) media 409px de
   min-content e ESTICAVA a pagina inteira: a aba Acelerar abria com 433px num aparelho de 390, com
   tudo encolhido e uma borda vazia a direita. A cura e do KIT, por classe (nunca no cartao): a acao
   pode encolher (`min-width: 0`) e envolver (`flex-wrap: wrap`) em vez de empurrar o documento. */
.sh-secao-acao {
  flex: 0 1 auto; min-width: 0;
  display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end;
  gap: var(--space-2);
}

/* 19.1b · SEÇÃO RECOLHÍVEL · "menos na tela por padrão" (o dono, 03/10/2026: "em todo app tem que aparecer menos coisas na tela do cliente ... sessões recolhíveis").
   A MESMA seção-caixa do §19.1, só que é um `<details class="sh-secao sh-secao--recolhivel">` e o `<summary class="sh-secao-cabeca">` é o cabeçalho (título, apoio e ações) com a seta
   que gira ao abrir. O conteúdo mora no `.sh-secao-corpo`. Quem desenha é `App.secao` (app.js (k)); regra de uso: o PRINCIPAL da tela nasce aberto, o secundário recolhido.
   Padrão adotado: divulgação progressiva (disclosure) do Material 3 e do GOV.UK "Details". `<details>` não aceita `display: grid` com segurança em todos os navegadores: o espaçamento
   vai no corpo, nunca na raiz. Uma recolhível dentro de uma seção não ganha caixa de novo (a regra do §19.1), só a linha que a separa do que vem antes. */
.sh-secao--recolhivel { display: block; }
.sh-secao--recolhivel > summary.sh-secao-cabeca { flex-wrap: nowrap; list-style: none; cursor: pointer; }
.sh-secao--recolhivel > summary.sh-secao-cabeca::-webkit-details-marker { display: none; }
.sh-secao-seta { flex: 0 0 auto; color: var(--texto-2); transition: transform var(--sh-dur) var(--sh-ease); }
.sh-secao--recolhivel[open] > summary .sh-secao-seta { transform: rotate(180deg); }
.sh-secao--recolhivel > .sh-secao-corpo { display: grid; gap: var(--space-3); padding-top: var(--space-3); }
.sh-secao--recolhivel > .sh-secao-corpo > .sh-card:only-child { padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
.sh-secao:not([role="tabpanel"], .sh-secao--solta) .sh-secao.sh-secao--recolhivel { border-top: 1px solid var(--borda); padding-top: var(--space-3); }
.sh-secao:not([role="tabpanel"], .sh-secao--solta) .sh-secao.sh-secao--recolhivel:first-child { border-top: 0; padding-top: 0; }

/* ── 19.2 · CARTAO COM ICONE · o cartao de entrega (icone | texto | estado + acao) ─────────────────
   `.sh-card-lado` guarda a pill e o botao a DIREITA, na mesma linha: o dono chamou de gambiarra o
   "conta conectada / gestao BOOOT em tamanhos de letra diferentes" espalhado pelo cartao ([23:02]). */
/* A CLASSE "QUEBRA PELO ESPAÇO DA PEÇA, NUNCA PELA LARGURA DA TELA" (03/10 · o dono na conta real: "esse crime de UX"; varredura do kit provou em foto
   a 860/412/352/300 px): o cartão com ícone é flex com quebra; o corpo pede 12rem e o lado desce quando a coluna não tem o espaço. */
.sh-card--icone {
  display: flex; flex-wrap: wrap; align-items: center;
  column-gap: var(--space-3); row-gap: var(--space-2);
}
.sh-card--icone > :not(.sh-card-ico):not(.sh-card-lado) { flex: 1 1 12rem; min-width: 0; }
.sh-card--icone > .sh-card-lado { flex: 0 0 auto; margin-inline-start: auto; }
/* G5 · O ÍCONE DO BLOCO É UM SÓ: 24 px, sem disco, à ESQUERDA do título, cor secundária (`.sh-oferta-ico`, `.sh-card-ico` e o ícone do cabeçalho da seção/linha/número são este mesmo encaixe).
   Em blocos irmãos o ícone aparece em TODOS ou em NENHUM (`App.uniformaIcones`); nunca emoji (G11). */
.sh-card-ico, .sh-oferta-ico {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 1.5rem; height: 1.5rem;
  color: var(--texto-2);
}
.sh-card-ico .sh-icone, .sh-oferta-ico .sh-icone { width: 1.5rem; height: 1.5rem; }
.sh-oferta-ico { color: var(--acento-texto); }
.sh-card-lado {
  display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2);
}
/* apoio de cartao em ATE 2 linhas (regra R4 da LEI DA ADESAO: descricao <= 2 linhas) */
.sh-card--icone .sh-apoio {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ── 19.3 · STAT · o numero que o dono le de relance (STChat Relatorios, medido na foto) ───────────
   O cartao e daqui; o MIOLO reusa `.sh-rotulo` + `.sh-kpi-numero` + `.sh-kpi-apoio` (§5): uma receita
   de numero na casa, nunca duas. */
.sh-stat { display: grid; gap: var(--space-2); align-content: start; }
.sh-stat-cabeca {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2);
  min-height: 2rem;
}
.sh-stat-cabeca .sh-rotulo { min-width: 0; }
.sh-stat-cabeca .sh-icone { color: var(--texto-2); }
/* o numero do STAT e o assunto do cartao: 28, o topo da faixa 24-28 da ANATOMIA (Relatorios do CRM mede
   28-30). O `.sh-kpi-numero` solto continua em 24, que e o tamanho dele DENTRO de um cartao com mais coisa. */
/* a unidade do número (App.numeros · `unidade`): menor, no peso normal, colada no número e sem quebra (04/10) */
.sh-kpi-unidade { font-size: var(--fs-md); font-weight: var(--fw-regular); white-space: nowrap; }

/* ── 19.4 · ESCOLHA · o cartao-radio (nunca checkbox · GOV.UK radios + foto form-claro.jpg) ────────
   R2 da LEI DA ADESAO: escolha e cartao, no maximo 3 por decisao. O `input` fica escondido mas
   FOCAVEL (nunca `display: none`, que o tira do Tab), e o anel de foco vai no cartao inteiro.
   A marca alinha pela PRIMEIRA linha (`flex-start` + meio degrau), como no CRM: com descricao de 3
   linhas, um radio centrado no bloco fica boiando longe do titulo que ele responde. */
.sh-escolhas { display: grid; gap: var(--space-2); }
.sh-escolha {
  position: relative;
  display: flex; align-items: flex-start; gap: var(--sh-12);
  min-height: 2.5rem; padding: var(--space-3) var(--sh-12);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-controle);
  background: var(--superficie); color: var(--texto);
  cursor: pointer;
  transition: var(--sh-transicao);
}
.sh-escolha > input {
  position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0;
}
.sh-escolha > .sh-stack { flex: 1; min-width: 0; gap: var(--space-1); }
.sh-escolha-marca {
  flex: 0 0 auto; margin-top: calc(var(--space-1) / 2);
  display: grid; grid-template-areas: "marca"; place-items: center;
  width: 1.125rem; height: 1.125rem;
  /* o círculo/quadrado vazio é controle: contraste mínimo 3:1 com o fundo (WCAG 1.4.11). `--campo-borda` mede hoje 3,17:1 no escuro e 3,16:1 no
     claro (passa o piso; a borda antiga, quase invisível, fazia a opção não marcada sumir, catálogo renderizado, 03/10); a marca usa `--texto-2`, o mesmo da moldura do formulário (§19.24), que passa nos dois temas com folga */
  border: 1px solid var(--texto-2); border-radius: var(--raio-pill);
  background: var(--superficie);
  transition: var(--sh-transicao);
}
.sh-escolha-marca::after {
  content: ""; grid-area: marca; width: .5rem; height: .5rem; border-radius: var(--raio-pill);
  background: var(--texto); transform: scale(0);
  transition: transform var(--sh-dur) var(--sh-ease);
}
.sh-escolha-marca .sh-icone { grid-area: marca; width: .875rem; height: .875rem; opacity: 0; }
.sh-escolha:hover {
  background: color-mix(in srgb, var(--texto) 4%, transparent); border-color: var(--texto-2);
}
.sh-escolha:has(> input:checked) {
  border-color: var(--texto);
  background: color-mix(in srgb, var(--texto) 6%, transparent);
}
.sh-escolha:has(> input:checked) .sh-escolha-marca { border-color: var(--texto); }
.sh-escolha:has(> input:checked) .sh-escolha-marca::after { transform: scale(1); }
.sh-escolha:has(> input:focus-visible) {
  outline: var(--anel-foco); outline-offset: var(--focus-offset);
}
.sh-escolha:has(> input:disabled) {
  opacity: var(--desabilitado); cursor: not-allowed;
}
.sh-escolhas[data-erro="sim"] > .sh-escolha { border-color: var(--booot-erro); }
/* multipla escolha: a marca vira QUADRADO com check (o `i-ok` que a casca ja tem). O raio e o
   `--space-1` (4) e nao o `--raio-controle` (10): num quadrado de 18 o raio de controle vira circulo,
   e a diferenca entre "escolha uma" e "escolha quantas quiser" some. */
.sh-escolha--multi > .sh-escolha-marca { border-radius: var(--space-1); }
.sh-escolha--multi > .sh-escolha-marca::after { display: none; }
.sh-escolha--multi:has(> input:checked) > .sh-escolha-marca {
  background: var(--texto); color: var(--superficie);
}
.sh-escolha--multi:has(> input:checked) > .sh-escolha-marca .sh-icone { opacity: 1; }

/* ── 19.5 · PASSOS · o assistente (GOV.UK "one thing per page") ────────────────────────────────────
   R3 da LEI DA ADESAO: form longo NAO existe. Vira 1 pergunta por passo, com "Passo 3 de 9",
   progresso, voltar e "Salvo" que so aparece depois de salvar de verdade. */
.sh-passos { display: grid; gap: var(--space-3); align-content: start; }
.sh-passos-cabeca {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.sh-passos [data-passo] { display: grid; gap: var(--space-3); align-content: start; }
.sh-passos-rodape {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding-top: var(--space-3); border-top: 1px solid var(--borda);
}
.sh-passos-rodape > .sh-btn--primario { margin-left: auto; }
/* `.sh-progresso` e o NOME que o assistente da a barra de §11: a marcacao e
   `<div class="sh-barra sh-progresso"><i></i></div>`, uma engine e dois nomes (o mesmo padrao de
   `.sh-btn sh-btn--primario`). Aqui so mora o que muda no assistente: a barra ocupa a linha inteira e
   fica mais fina, porque no cabecalho ela e apoio ao lado de "Passo 3 de 9", nunca o assunto. */
.sh-progresso { width: 100%; height: .25rem; }

/* "Salvo" com o check: cor de sucesso e a PALAVRA junto (R6: estado nunca e so cor) */
.sh-salvo {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-size: var(--fs-sm); color: var(--sucesso-texto);
}
.sh-salvo .sh-icone { width: .875rem; height: .875rem; }

/* ── 19.6 · FOLHA · o <dialog> lateral (shadcn Sheet) ──────────────────────────────────────────────
   Fluxo com passos que nao merece trocar de pagina (upgrade, fotos, ajustar anuncio) desliza da
   direita e ocupa a altura toda; no celular vira folha de baixo, como o `.sh-modal`.
   O cabecalho, o corpo e o rodape sao os MESMOS de `.sh-modal` (§13 e 19.7): uma receita, dois casulos. */
dialog.sh-folha {
  width: min(30rem, 100%); max-width: 100%;
  height: 100%; max-height: 100%;
  padding: 0; margin: 0 0 0 auto;
  border: 0; border-inline-start: 1px solid var(--borda-forte); border-radius: 0;
  background: var(--flutuante); color: var(--texto);
  box-shadow: var(--sombra-flutuante);
  overflow: hidden;
}
dialog.sh-folha::backdrop { background: color-mix(in srgb, var(--booot-cinza-000) 60%, transparent); }
dialog.sh-folha[open] {
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  animation: sh-deslizar var(--sh-dur) var(--sh-ease-saida);
}
dialog.sh-folha[open]::backdrop { animation: sh-aparecer var(--sh-dur) var(--sh-ease-saida); }

/* ── 19.7 · MODAL · as 3 larguras e o RODAPE (o popup que o dono chamou de "muito feio" no escuro) ──
   O que estava feio, medido na foto 03.08.06: painel sem borda visivel sobre a pagina escura e sem
   nenhuma faixa separando cabecalho de corpo. Aqui o painel ganha `--borda-forte`, e cabecalho e
   rodape ganham a lavagem (ver o aviso do topo da §19: `--superficie-2` e branco puro no claro base).
   As larguras seguem a anatomia do Dialog do shadcn: sm 26rem · md 38.75rem · lg 55rem. */
.sh-modal-rodape {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2);
  padding: var(--space-3);
  border-top: 1px solid var(--borda);
  background: color-mix(in srgb, var(--texto) 4%, transparent);
}
.sh-modal-rodape > .sh-btn--fantasma:first-child { margin-right: auto; }

/* ── 19.8 · FUNIL · a etapa com numero, barra e a FRASE que traduz a taxa ──────────────────────────
   Dono [05:48] e [06:16]: percentual E "a cada 10, 2 viram alunos", com desenho. R6 da LEI DA ADESAO:
   taxa sem frase e numero que ninguem le. As 4 etapas usam a MESMA barra de §11, com o `--pct`. */
.sh-funil { display: grid; gap: var(--space-2); }
.sh-funil-etapa {
  display: grid; grid-template-columns: minmax(6rem, 9rem) minmax(0, 1fr) auto;
  align-items: center; gap: var(--space-3);
}
.sh-funil-etapa > .sh-barra { height: 1.25rem; border-radius: var(--raio-controle); }
.sh-funil-numero {
  font-size: var(--fs-md); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums;
  text-align: right; min-width: 3ch;
}
.sh-funil-frase {
  padding-top: var(--space-2); border-top: 1px solid var(--borda);
  font-size: var(--fs-sm); color: var(--texto-2);
}
.sh-funil-frase b { color: var(--texto); font-weight: var(--fw-semibold); }

/* ── 19.9 · AVISO e SINO · a novidade que nao interrompe (dono [04:24]) ────────────────────────────
   Faixa dispensavel no topo do conteudo (GitHub/Slack banner) e o ponto no botao do sino. O ponto
   NUNCA vai sozinho: a faixa carrega a frase, porque cor sem palavra falha a R6. */
.sh-aviso {
  display: flex; align-items: center; gap: var(--sh-12);
  padding: var(--space-2) var(--sh-12);
  border: 1px solid var(--borda-forte); border-radius: var(--raio-controle);
  background: color-mix(in srgb, var(--texto) 4%, transparent);
  font-size: var(--fs-md); color: var(--texto);
}
.sh-aviso > .sh-icone { color: var(--texto-2); }
/* 18/09 (revisão 3 do dono: "aqui ele tá colado... em conversas ele tá com espaçamento... que seja definido na raiz"):
   quando a página não tem `.sh-pagina` (o legado Atrair · Atender · Acelerar), o nav.js pendura a faixa direto em
   `.sh-main`, e ela nascia colada nas bordas. O respiro é o mesmo da `.sh-pagina`, definido AQUI, uma vez. */
.sh-main > .sh-aviso { margin: var(--space-4) var(--space-4) 0; }
.sh-aviso-texto { flex: 1; min-width: 0; }
.sh-aviso[data-tom="atencao"] {
  border-color: color-mix(in srgb, var(--booot-ouro-600) 40%, transparent);
  background: color-mix(in srgb, var(--booot-ouro-600) 10%, transparent);
}
.sh-aviso[data-tom="atencao"] > .sh-icone { color: var(--acento-texto); }
/* os outros dois tons da porta `App.aviso` (revisão 3 · D1a): erro e ok, sempre com ícone + palavra (R6), nunca só a cor */
.sh-aviso[data-tom="erro"] { border-color: color-mix(in srgb, var(--booot-erro) 35%, transparent); }
.sh-aviso[data-tom="erro"] > .sh-icone { color: var(--erro-texto); }
.sh-aviso[data-tom="ok"] { border-color: color-mix(in srgb, var(--booot-sucesso) 40%, transparent); }
.sh-aviso[data-tom="ok"] > .sh-icone { color: var(--sucesso-texto); }
/* o ponto do sino mora DENTRO do grafite da barra, entao o anel dele e primitivo (nao muda com o tema) */
.sh-sino { position: relative; }
.sh-sino[data-novo="sim"]::after {
  content: ""; position: absolute; top: .375rem; right: .375rem;
  width: .5rem; height: .5rem; border-radius: var(--raio-pill);
  background: var(--booot-erro); border: 1px solid var(--booot-cinza-000);
}

/* ── 19.10 · DEGRAUS · a escada 3 + 1 (ordem do dono [15:19]) ──────────────────────────────────────
   "deixar o trofeu grande embaixo, com essa perspectiva de que o trofeu e so a base pra voce conseguir
   chegar na sua meta": 3 degraus em linha e o trofeu ocupando a largura embaixo, nunca solto no canto. */
.sh-degraus { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
.sh-degrau {
  display: grid; justify-items: center; align-content: start; gap: var(--space-1);
  text-align: center;
}
.sh-degrau .sh-icone { width: 1.5rem; height: 1.5rem; color: var(--texto-2); }
.sh-degrau[data-atual="sim"] { background: color-mix(in srgb, var(--texto) 6%, transparent); font-weight: var(--fw-semibold); }
.sh-degrau[data-atual="sim"] .sh-icone { color: var(--acento-texto); }
/* o degrau CONQUISTADO leva a cor do SEU metal (o dono, 04/10: "o bronze aparecer verde não tem sentido"): bronze, prata, ouro; o troféu é ouro. Verde é estado de sucesso, nunca medalha. */
.sh-degrau[data-feito="sim"] .sh-icone { color: var(--medalha-ouro); }
.sh-degrau[data-feito="sim"][data-metal="bronze"] .sh-icone { color: var(--medalha-bronze); }
.sh-degrau[data-feito="sim"][data-metal="prata"] .sh-icone { color: var(--medalha-prata); }
.sh-degrau[data-feito="sim"][data-metal="ouro"] .sh-icone { color: var(--medalha-ouro); }
.sh-degrau--base {
  grid-column: 1 / -1;
  border-color: var(--borda-forte);
  background: color-mix(in srgb, var(--texto) 4%, transparent);
}
/* o OURO do trofeu mora no ICONE (o selo da dosagem NEUTRA), nunca preenchendo a caixa: em pagina clara
   ouro nao preenche (`_MARCA/_PARA-AGENTE.md`, palavra do dono). */
.sh-degrau--base .sh-icone { width: 2.5rem; height: 2.5rem; color: var(--acento-texto); }

/* ── 19.11 · TOUR · o guia de 1a visita (anatomia do Shepherd.js) ──────────────────────────────────
   Vive dentro de `dialog.sh-modal.sh-modal--sm`. O dono [03:08] fotografou o tour AZUL: azul nao e cor
   da casa e nao existe no CRM. Aqui o Proximo e o primario do kit, o Anterior e secundario e o Pular e
   fantasma, sempre nessa ordem de peso. */
.sh-tour { display: grid; gap: var(--space-2); }
.sh-tour-passo {
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: var(--lh-ui);
  color: var(--texto-2);
}
.sh-tour-acoes { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.sh-tour-acoes > .sh-btn--fantasma:first-child { margin-right: auto; }

/* ── 19.12 · TOOLBAR · a 1a linha do conteudo (busca em pilula + chips + "+") ──────────────────────
   O chip de filtro NAO ganhou classe nova: e o `.sh-pill` de §6 como BOTAO, com o ativo INVERTIDO
   (`bg-foreground text-background`), que e exatamente a receita do CRM. */
.sh-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.sh-toolbar > .sh-campo--busca { flex: 1 1 12rem; min-width: 0; max-width: 22rem; }
.sh-toolbar > .sh-icone-btn--primario { margin-left: auto; }
button.sh-pill { cursor: pointer; transition: var(--sh-transicao); }
button.sh-pill:hover { color: var(--texto); border-color: var(--texto-2); }
button.sh-pill[aria-pressed="true"] {
  background: var(--texto); border-color: var(--texto); color: var(--pagina);
}
/* o "+" do CRM: 36 redondo, na cor da acao */
.sh-icone-btn--primario {
  width: 2.25rem; height: 2.25rem;
  background: var(--cta-fundo); color: var(--cta-texto);
  box-shadow: var(--sombra-cartao);
}
.sh-icone-btn--primario:hover {
  background: color-mix(in srgb, var(--cta-fundo) 88%, var(--booot-cinza-000)); color: var(--cta-texto);
}

/* ── 19.13 · SLIDER · o controle deslizante ALINHADO (dono [06:22]) ────────────────────────────────
   "tem um slider aqui abaixo, outro acima": o defeito era o rotulo e o valor flutuando em alturas
   diferentes. Aqui a peca tem 2 linhas de altura FIXA (rotulo + valor, depois o trilho), entao dois
   sliders lado a lado nascem na mesma linha de base sem ninguem alinhar na mao.
   Anatomia: Radix Slider. O trilho tem 40 de alvo de toque, mesmo desenhando 6. */
.sh-slider { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-1) var(--space-3); }
.sh-slider-rotulo, .sh-slider-valor { display: flex; align-items: center; min-height: 1.25rem; }
.sh-slider-rotulo { font-size: var(--fs-sm); color: var(--texto-2); }
.sh-slider-valor {
  justify-content: flex-end;
  font-size: var(--fs-md); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums;
}
.sh-slider > input[type="range"] {
  grid-column: 1 / -1;
  appearance: none; -webkit-appearance: none;
  width: 100%; height: 2.5rem; margin: 0;
  background: transparent; cursor: pointer;
}
.sh-slider > input[type="range"]::-webkit-slider-runnable-track {
  height: .375rem; border-radius: var(--raio-pill);
  background: color-mix(in srgb, var(--texto) 12%, transparent);
}
.sh-slider > input[type="range"]::-moz-range-track {
  height: .375rem; border-radius: var(--raio-pill);
  background: color-mix(in srgb, var(--texto) 12%, transparent);
}
.sh-slider > input[type="range"]::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none;
  width: 1.125rem; height: 1.125rem; margin-top: calc(var(--space-1) * -1.5);
  border: 1px solid var(--superficie); border-radius: var(--raio-pill);
  background: var(--cta-fundo); box-shadow: var(--sombra-flutuante);
}
.sh-slider > input[type="range"]::-moz-range-thumb {
  width: 1.125rem; height: 1.125rem;
  border: 1px solid var(--superficie); border-radius: var(--raio-pill);
  background: var(--cta-fundo); box-shadow: var(--sombra-flutuante);
}
.sh-slider > input[type="range"]:disabled { opacity: var(--desabilitado); cursor: not-allowed; }

/* ── 19.14 · MARCA · o logo ESCRITO (dono [00:18]) ─────────────────────────────────────────────────
   Wordmark como ASSET, nunca a palavra BOOOT em texto (lei da marca, `_MARCA/_PARA-AGENTE.md`). A peca
   carrega os DOIS arquivos e a folha mostra o que casa com o fundo: `-claro` sobre grafite, `-grafite`
   sobre claro. O selecionador e `.tema-claro` NU (nao `html.tema-claro`) porque o catalogo pinta o tema
   claro num CONTEINER, e um wordmark preto sobre grafite ali seria uma prova falsa. */
.sh-marca { display: inline-flex; align-items: center; }
.sh-marca img { display: block; width: auto; height: 1.5rem; }
.sh-marca--grande img { height: 2.25rem; }
.sh-marca [data-marca="claro"] { display: none; }
.tema-claro .sh-marca [data-marca="claro"] { display: block; }
.tema-claro .sh-marca [data-marca="escuro"] { display: none; }

/* ── 19.15 · AS 3 VARIANTES QUE A ACELERAR PEDIU (chip P3, HANDOFF-P3-r4 §11.3-5) ───────────────
   Nenhuma peca nova aqui: sao VARIANTES das classes que a folha ja tem (a anatomia do shadcn/21st,
   onde a variante muda UMA dimensao da peca base e nunca clona a peca). Cada uma nasceu de uma
   medida na tela, nunca de gosto.

   (1) `.sh-grade--stats` · a linha de KPIs. `.sh-grade` e `minmax(15rem, 1fr)`, feita pro CARTAO;
       com 5 `.sh-stat` na coluna de conteudo do 1280 ela computava `304px 304px 304px` e quebrava a
       leitura do funil em 3 + 2 (medido na bancada U1, 08/09). O piso cai pra 11rem, que e a largura
       real de um stat de 4 digitos com o rotulo em caixa alta; o resto da receita e a mesma, entao a
       quebra no celular continua acontecendo sozinha, sem media query.
   (2) `.sh-lista--rolavel` · a mascara de fade no rodape da lista que rola. A affordance existia,
       mas morava em `app/inicio-plano.css` como classe NUA (`.is-rolavel`), pintando uma lista da
       Acelerar a partir da folha da Inicio: uma receita fora do chassi e do dono errado. Ela vem pro
       kit inteira. A mascara so precisa de uma cor OPACA (o alfa e que desenha o fade), e por isso
       usa `--texto`, que le nos 2 temas. Quem MARCA a classe e o JS, e so quando a lista rola de
       verdade (`#ranking :: snap`): fade permanente mentiria que ha mais coisa embaixo.
   (3) `.sh-grafico` · o conteiner de proporcao do canvas, que era `.tendencia-chart` do `painel.css`
       (altura fixa de 148px). Proporcao no lugar de altura fixa: o mesmo desenho respira no 1280 e
       nao vira um risco de 148px no celular. O `!important` do canvas nao e enfeite: o Chart.js roda
       com `maintainAspectRatio: false` e escreve `width`/`height` em px no proprio canvas por CSSOM
       a cada `resize`: e a receita transcrita do `painel.css`, que ja pagou esse erro. */
.sh-grade--stats { grid-template-columns: repeat(auto-fit, minmax(max(11rem, calc((100% - 3 * var(--space-4)) / 4)), 1fr)); }   /* no máximo 4 por fileira */
/* a fileira de NÚMEROS de uma ação (`App.numeros`, app.js (k)): 5 números cabem em duas colunas no celular */
.sh-grade--numeros { grid-template-columns: repeat(auto-fit, minmax(max(8.5rem, calc((100% - 3 * var(--space-4)) / 4)), 1fr)); }
.sh-grade--numeros .sh-progresso { margin-top: var(--space-1); }

/* o CORTE de uma lista que mostra o topo e a linha de quem lê (leaderboard): três pontos na vertical, desenhados pelo CSS (nunca texto de reticências) */
.sh-lista-corte { display: flex; justify-content: center; align-items: center; min-height: var(--space-4); color: var(--texto-2); }
.sh-lista-corte::before { content: "\22EE"; }

.sh-lista--rolavel {
  -webkit-mask-image: linear-gradient(to bottom, var(--texto) calc(100% - var(--space-4)), transparent 100%);
  mask-image: linear-gradient(to bottom, var(--texto) calc(100% - var(--space-4)), transparent 100%);
}

/* ⚠️ A CAIXA DE PROPORCAO JA EXISTIA NESTA FOLHA, e eu quase escrevi a segunda: `.sh-video` (§11) e
   ela com razao 16/9 e moldura. E o padrao AspectRatio (Radix/shadcn), e a casa ja o tinha 587 linhas
   acima do lugar onde eu estava editando. As duas passam a dividir a receita; o que difere e a RAZAO
   e a moldura. (Achado do verificador fresco de 08/09: a varredura do ANTI-TIJOLO nao pode parar na
   porta do arquivo que voce esta abrindo.)
   ⚠️ `min-width: 0` + `max-width: 100%` NAO sao enfeite, e a medida esta no HANDOFF-U1-r4 §3.1:
   `aspect-ratio` faz a LARGURA MINIMA do elemento nascer da altura (razao x altura), e num grid ela
   vira a contribuicao de min-content da coluna. Sem os dois, a aba inteira passou de 434 pra 762 px
   de largura num aparelho de 390 (o cartao empurrava a `.sh-secao`, e a pagina do cliente ganhava
   rolagem lateral). Medido no Chromium, 4 variantes, e so estas duas linhas zeram o estouro. Um
   `min-height` aqui reintroduz o mesmo defeito: quem da altura no celular e a razao, logo abaixo.
   O video ganha os dois de carona, e isso e cura: ele tinha o mesmo estouro latente. */
.sh-video, .sh-grafico { position: relative; width: 100%; min-width: 0; max-width: 100%; }
.sh-grafico { aspect-ratio: 5 / 1; }
.sh-grafico > canvas { display: block; width: 100% !important; height: 100% !important; }

/* ── 19.17 · OFERTA · o cartão de oferta no contexto (revisão do app de 02/10/2026 · regra 3 de tela) ──────────
   Onde a necessidade nasce, com o valor, o preço da fonte, o que acontece e UM botão. Anatomia (desenhada por `App.oferta`, app.js (i)):
   ícone | corpo (título · valor · o que acontece) | lado (preço + botão). Texto e número chegam do servidor (`subida` de /api/conta-status):
   esta folha só COMPÕE. O botão é secundário, salvo na página que é a própria oferta (R1: uma ação primária por tela). */
/* QUEBRA PELO ESPAÇO DO CARTÃO, NUNCA PELA LARGURA DA TELA (o dono, 03/10, conta real a 1366: na coluna da direita o "Peça o Adicional" ficou com
   uma palavra por linha e o preço por cima do texto: "esse crime de UX"). Flex com quebra: o corpo pede no mínimo 12rem; quando o cartão não tem
   esse espaço ao lado do preço, o lado (preço + botão) desce para a linha de baixo, em qualquer coluna, sem regra por tela. */
.sh-oferta {
  display: flex; flex-wrap: wrap; align-items: center;
  column-gap: var(--space-3); row-gap: var(--space-2);
}
.sh-oferta-corpo { display: grid; gap: var(--space-1); min-width: 0; flex: 1 1 12rem; }
.sh-oferta-lado { display: grid; justify-items: end; gap: var(--space-2); flex: 0 0 auto; margin-inline-start: auto; }
.sh-oferta-preco {
  font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  font-variant-numeric: tabular-nums; color: var(--texto);
}

/* ── 19.18 · TAREFA · a linha da agenda: um checklist compacto (revisão do app de 03/10/2026) ──────────────────────
   A agenda é uma lista VERTICAL de tarefas, no desenho do Things 3 · Todoist · Linear: uma linha curta, sem ruído. Anatomia:
     <ul class="sh-tarefas"><li class="sh-tarefa" data-situacao="aberta|feita|atrasada">
       <span class="sh-tarefa-marca"><svg class="sh-icone"><use href="#i-ok"/></svg></span>
       <div class="sh-tarefa-corpo"><b class="sh-tarefa-titulo"><a href="…">o que fazer</a></b><p class="sh-tarefa-data">Até 04/10 · BOOOT faz</p></div>
       <div class="sh-tarefa-ajuda"><button class="sh-icone-btn">?</button></div></li></ul>
   O TÍTULO É A AÇÃO (link ou botão, sem sublinhado até o hover, com o anel de foco do kit); o porquê mora atrás do "?" (`.sh-tarefa-ajuda`),
   nunca solto na linha. A meta é UMA linha de texto pequeno: o prazo, "Atrasada · era até …" e, só quando a casa faz, "BOOOT faz". Não há
   pílula na linha. O estado mora em `data-situacao` (e não em `data-estado`, que é da máquina do kernel: carregando · vazio · erro · pronto);
   a marca é ícone + cor e a meta diz a palavra: "atrasada" nunca é só vermelho (R6). A linha que traz botão no lado (`.sh-tarefa-acao`:
   ideia de ação, plano da Black) cai sob o corpo no celular. */
.sh-tarefas { display: grid; margin: 0; padding: 0; list-style: none; }
.sh-tarefa {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  column-gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--borda);
}
.sh-tarefas > .sh-tarefa:last-child { border-bottom: 0; }
.sh-tarefa-marca {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 1.5rem; height: 1.5rem;
  border: 1px solid var(--borda-forte); border-radius: var(--raio-pill);
  color: var(--texto-2);
}
.sh-tarefa-marca .sh-icone { width: .875rem; height: .875rem; }
.sh-tarefa[data-situacao="aberta"] .sh-tarefa-marca .sh-icone { visibility: hidden; }
.sh-tarefa[data-situacao="feita"] .sh-tarefa-marca { border-color: color-mix(in srgb, var(--booot-sucesso) 40%, transparent); color: var(--sucesso-texto); }
.sh-tarefa[data-situacao="atrasada"] .sh-tarefa-marca { border-color: color-mix(in srgb, var(--booot-erro) 40%, transparent); color: var(--erro-texto); }
/* a marca que É o "feito" (`marcaAcao` do modelo): o mesmo círculo, agora um botão; a área de toque passa de 44 px sem aumentar o círculo, e na linha aberta o ✓ aparece ao passar o mouse ou focar */
button.sh-tarefa-marca { position: relative; padding: 0; background: none; font: inherit; cursor: pointer; }
button.sh-tarefa-marca::after { content: ""; position: absolute; inset: -.625rem; }
.sh-tarefa[data-situacao="aberta"] button.sh-tarefa-marca:is(:hover, :focus-visible) { border-color: color-mix(in srgb, var(--booot-sucesso) 40%, transparent); color: var(--sucesso-texto); }
.sh-tarefa[data-situacao="aberta"] button.sh-tarefa-marca:is(:hover, :focus-visible) .sh-icone { visibility: visible; opacity: .55; }
.sh-tarefa-corpo { display: grid; gap: 0; min-width: 0; }
/* o título NUNCA é cortado (03/10 · o dono: "o título nunca cortado"): quebra em quantas linhas precisar; o respiro de .125rem dentro da caixa é para o anel de foco do link */
.sh-tarefa-titulo {
  display: block; overflow-wrap: break-word;
  margin: calc(var(--space-1) / -2); padding: calc(var(--space-1) / 2);
  font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-snug); letter-spacing: normal;
  color: var(--texto);
}
.sh-tarefa-titulo a, .sh-tarefa-titulo button {
  display: inline; margin: 0; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; text-align: left; text-decoration: none; cursor: pointer;
}
.sh-tarefa-titulo a:hover, .sh-tarefa-titulo button:hover { text-decoration: underline; text-underline-offset: .125rem; }
.sh-tarefa-titulo a:not([href]) { cursor: default; text-decoration: none; }
.sh-tarefa[data-situacao="feita"] .sh-tarefa-titulo, .sh-tarefa[data-situacao="feita"] .sh-titulo { color: var(--texto-2); }
.sh-tarefa-data {
  font-size: var(--fs-sm); line-height: var(--lh-snug);
  font-variant-numeric: tabular-nums; color: var(--texto-2);
}
.sh-tarefa[data-situacao="atrasada"] .sh-tarefa-data { color: var(--erro-texto); }
/* a linha de meta: QUEM faz (o selo) e as datas, lado a lado (regras 2, 13 e 33 do dono). A tarefa da academia ("Você") chama atenção; a da casa ("BOOOT") fica quieta: o dono
   bate o olho e vê o que é dele. O selo nunca é só cor (R6): a palavra está nele. */
.sh-tarefa-meta { display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--space-2); row-gap: 0; }
.sh-tarefa-meta .sh-tarefa-data { margin: 0; }
/* o MARCADOR de hoje: a palavra "Hoje" em ouro na linha de meta (o estado vai por palavra, nunca em pílula) */
.sh-tarefa-hoje { font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: var(--lh-ui); color: var(--acento-texto); }
.sh-tarefa-quem {
  display: inline-flex; align-items: center; flex: 0 0 auto;
  padding: 0 var(--space-2); min-height: 1.25rem;
  border: 1px solid var(--borda-forte); border-radius: var(--raio-pill);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: 1; letter-spacing: .01em;
  color: var(--texto-2); background: transparent;
}
.sh-tarefa-quem[data-quem="academia"] { border-color: var(--texto); background: var(--texto); color: var(--superficie); }
/* o COMO da tarefa de hoje, à vista sob a linha de meta (nas outras ele mora atrás do "?") */
/* T19 (06/10): o "como" corre até o fim da linha, como o título (o teto de 60ch fazia as linhas da lista quebrarem diferente) */
.sh-tarefa-como { margin: var(--space-1) 0 0; font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--texto-2); }
.sh-tarefa-acao, .sh-tarefa-ajuda { align-self: center; }

/* ── 19.19 · PEDIDO COM PRAZO · estado + prazo + quem está fazendo (regra 5 de tela, revisão de 02/10/2026) ──────
   Todo pedido mostra os TRÊS fatos juntos, na ordem em que o cliente os procura. O prazo é o SLA do catálogo (nunca digitado na tela) e o estado
   é a pílula com ponto do kit (§6). Anatomia:
     <dl class="sh-pedido-prazo" data-situacao="recebido|andamento|pronto|atencao">
       <div><dt>Estado</dt><dd><span class="sh-pill sh-pill--vivo">Em andamento</span></dd></div>
       <div><dt>Prazo</dt><dd>até 2 dias úteis</dd></div>
       <div><dt>Quem está fazendo</dt><dd>Equipe BOOOT</dd></div></dl> */
.sh-pedido-prazo {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));   /* 3 lado a lado quando cabem; quebra pelo espaço (a classe acima) */ gap: var(--space-2) var(--space-3);
  margin: 0; padding: var(--sh-12) var(--space-3);
  border: 1px solid var(--borda); border-radius: var(--raio-controle);
  background: color-mix(in srgb, var(--texto) 3%, transparent);
}
.sh-pedido-prazo > div { display: grid; gap: var(--space-1); align-content: start; min-width: 0; }
.sh-pedido-prazo dt {
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: var(--lh-ui);
  color: var(--texto-2);
}
.sh-pedido-prazo dd { margin: 0; font-size: var(--fs-md); line-height: var(--lh-ui); color: var(--texto); overflow-wrap: anywhere; }
.sh-pedido-prazo[data-situacao="atencao"] { border-color: color-mix(in srgb, var(--booot-ouro-600) 40%, transparent); }

/* A LINHA DE PEDIDO (03/10 · #1799 · classe `texto-ao-cliente-cortado-por-css`): a lista do kit corta o apoio da linha em UMA linha com reticências
   (`.sh-linha-corpo > span`, feito para o apoio curto), e o pedido NÃO é apoio curto: o título, o andamento ("A casa começa a sua parte em 05/10"), o prazo e
   quem faz são o conteúdo. `<div class="sh-linha sh-linha--pedido">` quebra e mostra tudo, em qualquer tela (Conta, Atender, Ações): nenhuma tela refaz isto. */
.sh-linha--pedido { align-items: flex-start; }
.sh-linha--pedido .sh-linha-corpo > * { margin: 0; white-space: normal; text-wrap: balance; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
.sh-linha--pedido .sh-pill { flex-shrink: 0; }

/* as 3 peças no celular: a oferta e a tarefa empilham o lado/ação sob o corpo; o pedido vira uma coluna (3 colunas em 390 espremem o prazo) */
@media (max-width: 640px) {
  .sh-oferta-lado { flex-basis: 100%; grid-auto-flow: column; justify-content: space-between; justify-items: start; align-items: center; }
  /* o "?" fica na 1ª linha, ao lado do título (no celular ele caía sozinho numa 2ª linha e dobrava a altura de cada passo · foto do ensaio
     a05a2567, 03/10); só o botão de ação desce para baixo do corpo */
  .sh-tarefa-ajuda { grid-column: 3; grid-row: 1; }
  .sh-tarefa-acao { grid-column: 2 / -1; justify-self: start; padding-top: var(--space-2); }
  .sh-pedido-prazo { grid-template-columns: minmax(0, 1fr); }
  .sh-btn--grande { width: 100%; }   /* a ação principal da tela ocupa a linha no celular */
}
@media (hover: none) and (pointer: coarse) {
  .sh-oferta .sh-btn, .sh-tarefa .sh-btn { min-height: 44px; }
}

/* ── 19.20 · O SELO DO MENU · "Black" ao lado de Ações enquanto a academia tem a Black em curso (revisão de 02/10/2026) ──
   Mora no painel lateral (grafite nos dois temas): o ouro é o ouro-600 primitivo, como o selo do plano. Nasce `hidden`; o `nav.js` o liga. */
.sh-nav-destaque {
  margin-left: auto; flex: none;
  border-color: color-mix(in srgb, var(--booot-ouro-600) 45%, transparent);
  background: transparent; color: var(--booot-ouro-600);
}
.sh-nav-destaque::before { content: "\2605"; font-size: var(--fs-sm); }
.sh-app[data-menu="recolhido"] .sh-nav-destaque { display: none; }

/* ── 19.16 · O KIT NO CELULAR E NO DEDO ────────────────────────────────────────────────────────────
   O `@media (max-width: 640px)` de §16 ja vira o `.sh-modal` em folha de baixo; aqui vao SO as pecas
   novas. As larguras do modal ficam num `min-width` de proposito: no celular quem manda e a folha. */
@media (min-width: 641px) {
  dialog.sh-modal--sm { width: min(26rem, 100% - var(--space-4)); }
  dialog.sh-modal--md { width: min(38.75rem, 100% - var(--space-4)); }
  dialog.sh-modal--lg { width: min(55rem, 100% - var(--space-4)); }
}
@media (max-width: 640px) {
  /* a folha lateral vira folha de BAIXO, como o modal (o padrao de bottom sheet do celular) */
  dialog.sh-folha {
    width: 100%; height: auto; max-height: 88vh;
    margin: auto auto 0;
    border-inline-start: 0; border-top: 1px solid var(--borda-forte);
    border-radius: var(--raio-cartao) var(--raio-cartao) 0 0;
  }
  dialog.sh-folha[open] { animation: sh-subir var(--sh-dur) var(--sh-ease-saida); }
  /* cartao com icone, funil e degraus empilham: 3 colunas em 390 espremem numero e rotulo */
  .sh-card--icone > .sh-card-lado { flex-basis: 100%; justify-content: flex-start; margin-inline-start: 0; }
  .sh-funil-etapa { grid-template-columns: minmax(0, 1fr) auto; }
  .sh-funil-etapa > .sh-barra { grid-column: 1 / -1; }
  .sh-degraus { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sh-escolha { padding: var(--sh-12); }
  .sh-passos-rodape { flex-wrap: wrap; }
  /* a linha de KPIs quebra sozinha (a grade e auto-fit) e o GRAFICO fica mais alto. A razao 5/1 num
     celular deixaria o grafico com menos de 90 px de altura, que e risco, nao grafico; com 5/2 a
     bancada mediu 157 px no 390, contra os 148 px fixos que o `.tendencia-chart` tinha. */
  .sh-grafico { aspect-ratio: 5 / 2; }
}
@media (hover: none) and (pointer: coarse) {
  .sh-escolha, .sh-aviso { min-height: 44px; }
}

/* o deslize da folha lateral: o `slide-in-from-right` do fornecedor */
@keyframes sh-deslizar { from { opacity: 0; transform: translateX(100%); } }

@media (prefers-reduced-motion: reduce) {
  dialog.sh-folha[open] { animation: none; }
  .sh-escolha-marca::after { transition: none; }
}

/* ── 19.21 · PÁGINA COM APOIO · duas colunas (o "supporting pane" do Material 3) ──────────────────────────────────
   O dono (03/10): "na tela inicial, uma agenda de verdade e, na lateral, a lista de tarefas". UMA receita de duas colunas, para a tela
   nunca declarar `grid-template-columns` de página. Anatomia:
     <div class="sh-pagina sh-pagina--apoio"><div class="sh-pagina-principal">…</div><aside class="sh-pagina-apoio">…</aside></div>
   Padrão adotado: https://m3.material.io/foundations/layout/canonical-layouts/supporting-pane
   A partir de 1100 px: principal 1fr, apoio de 22 a 24 rem. Abaixo disso empilha, o apoio depois do principal. */
.sh-pagina--apoio { display: grid; gap: var(--space-4); grid-template-columns: minmax(0, 1fr); }
.sh-pagina-principal, .sh-pagina-apoio { display: grid; gap: var(--space-4); align-content: start; min-width: 0; }
@media (min-width: 1100px) {
  .sh-pagina--apoio { grid-template-columns: minmax(0, 1fr) clamp(22rem, 24vw, 24rem); column-gap: var(--space-5); align-items: start; }
}

/* ── 19.22 · MARCOS · a linha do tempo e os checkpoints (Nubank "acompanhe seu pedido" · Material 3 stepper) ─────────
   Visual antes de texto: o passo é um PONTO numa linha, nunca um parágrafo. Anatomia:
     <ol class="sh-marcos [sh-marcos--horizontal]"><li class="sh-marco" data-estado="feito|atrasado|hoje|proximo">
       <span class="sh-marco-ponto"></span><span class="sh-marco-titulo">…</span><span class="sh-marco-data">05/10</span></li></ol>
   O estado NUNCA é só cor (R6): feito = ponto cheio com ✓; atrasado = ponto de atenção com "!" e a PALAVRA "Atrasado" antes da data;
   hoje = ponto maior com anel e título em negrito; próximo = ponto vazio e o texto apagado. A tela escreve só a data ("05/10"). */
.sh-marcos { display: grid; margin: 0; padding: 0; list-style: none; }
/* a linha do tempo VERTICAL numa coluna estreita: a data ("Atrasado · 05/10 a 08/10", que não quebra) desce para baixo do título, pelo espaço da
   própria lista (container query), nunca espremendo o título letra por letra (a classe "quebra pelo espaço da peça") */
.sh-marcos:not(.sh-marcos--horizontal):not(.sh-marcos--roteiro) { container-type: inline-size; }
@container (max-width: 24rem) {
  .sh-marcos:not(.sh-marcos--horizontal):not(.sh-marcos--roteiro) > .sh-marco { grid-template-columns: 1.5rem minmax(0, 1fr); }
  .sh-marcos:not(.sh-marcos--horizontal):not(.sh-marcos--roteiro) > .sh-marco > .sh-marco-data { grid-column: 2; }
}
.sh-marco {
  position: relative;
  display: grid; grid-template-columns: 1.5rem minmax(0, 1fr) auto; align-items: center;
  column-gap: var(--space-3);
  padding-bottom: var(--space-3);
}
.sh-marco:last-child { padding-bottom: 0; }
/* a linha que liga um ponto ao próximo */
.sh-marco:not(:last-child)::before {
  content: ""; position: absolute; left: .6875rem; top: 1.5rem; bottom: 0; width: 2px;
  background: var(--borda-forte);
}
.sh-marco[data-estado="feito"]:not(:last-child)::before { background: color-mix(in srgb, var(--booot-sucesso) 55%, transparent); }
.sh-marco-ponto {
  position: relative; z-index: 1;
  display: grid; place-items: center;
  width: 1.5rem; height: 1.5rem;
  border: 2px solid var(--borda-forte); border-radius: var(--raio-pill);
  background: var(--superficie); color: var(--texto-2);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: 1;
}
.sh-marco-titulo { min-width: 0; font-size: var(--fs-md); line-height: var(--lh-ui); color: var(--texto); overflow-wrap: break-word; hyphens: auto; }
.sh-marco-data { font-size: var(--fs-sm); font-variant-numeric: tabular-nums; color: var(--texto-2); white-space: nowrap; }
.sh-marco[data-estado="feito"] .sh-marco-ponto {
  border-color: var(--sucesso-texto); background: var(--sucesso-texto); color: var(--superficie);
}
.sh-marco[data-estado="feito"] .sh-marco-ponto::after { content: "\2713"; }
.sh-marco[data-estado="feito"] .sh-marco-titulo { color: var(--texto-2); }
.sh-marco[data-estado="atrasado"] .sh-marco-ponto {
  border-color: var(--acento-texto); background: color-mix(in srgb, var(--booot-ouro-600) 14%, var(--superficie)); color: var(--acento-texto);
}
.sh-marco[data-estado="atrasado"] .sh-marco-ponto::after { content: "!"; }
.sh-marco[data-estado="atrasado"] .sh-marco-data { color: var(--acento-texto); font-weight: var(--fw-semibold); }
.sh-marco[data-estado="atrasado"] .sh-marco-data::before { content: "Atrasado \00B7  "; }
.sh-marco[data-estado="hoje"] .sh-marco-ponto {
  border-color: var(--texto); background: var(--texto);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--texto) 18%, transparent);
}
.sh-marco[data-estado="hoje"] .sh-marco-titulo { font-weight: var(--fw-semibold); }
.sh-marco[data-estado="hoje"] .sh-marco-data { color: var(--texto); font-weight: var(--fw-semibold); }
.sh-marco[data-estado="proximo"] .sh-marco-titulo, .sh-marco[data-estado="proximo"] .sh-marco-data { color: var(--texto-2); }
/* horizontal: os marcos lado a lado, o ponto em cima e a linha correndo pela frente de cada um */
.sh-marcos--horizontal { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
.sh-marcos--horizontal .sh-marco {
  grid-template-columns: minmax(0, 1fr); row-gap: var(--space-2); justify-items: start; align-items: start;
  padding: 0 var(--space-3) 0 0;
}
.sh-marcos--horizontal .sh-marco:not(:last-child)::before { left: 2rem; right: var(--space-1); top: .6875rem; bottom: auto; width: auto; height: 2px; }
/* seis marcos ou mais nunca cabem lado a lado numa coluna de conteúdo (rótulo partido no meio da palavra, foto do ensaio 03/10):
   a linha do tempo é vertical em qualquer largura (Material 3 · steppers: horizontal só para poucos passos curtos) */
.sh-marcos--horizontal:has(> .sh-marco:nth-child(6)) { grid-auto-flow: row; grid-auto-columns: auto; }
.sh-marcos--horizontal:has(> .sh-marco:nth-child(6)) > .sh-marco { grid-template-columns: 1.5rem minmax(0, 1fr) auto; align-items: center; padding: 0 0 var(--space-3); row-gap: 0; }
.sh-marcos--horizontal:has(> .sh-marco:nth-child(6)) > .sh-marco:last-child { padding-bottom: 0; }
.sh-marcos--horizontal:has(> .sh-marco:nth-child(6)) > .sh-marco:not(:last-child)::before { left: .6875rem; right: auto; top: 1.5rem; bottom: 0; width: 2px; height: auto; }
.sh-marcos--horizontal:has(> .sh-marco:nth-child(6)) .sh-marco-data { white-space: nowrap; }
@media (max-width: 640px) {
  /* em 390 px cinco marcos lado a lado não cabem: a linha do tempo volta a ser vertical */
  .sh-marcos--horizontal { grid-auto-flow: row; grid-auto-columns: auto; }
  .sh-marcos--horizontal .sh-marco { grid-template-columns: 1.5rem minmax(0, 1fr) auto; align-items: center; padding: 0 0 var(--space-3); row-gap: 0; }
  .sh-marcos--horizontal .sh-marco:last-child { padding-bottom: 0; }
  .sh-marcos--horizontal .sh-marco:not(:last-child)::before { left: .6875rem; right: auto; top: 1.5rem; bottom: 0; width: 2px; height: auto; }
  .sh-marcos--horizontal .sh-marco-data { white-space: nowrap; }
}

/* AS FASES DA BLACK (`App.marcos`, 03/10 · P3 do dono): a MESMA linha do tempo, uma só por tela. A fase de hoje (ou a próxima, se a Black ainda não começou) em destaque; as futuras em cinza
   (o "próximo" do kit acima é apagado de propósito, no roteiro; aqui o próximo é o que se faz primeiro e fica forte). A fase que traz as tarefas dela é um `details` que abre ao tocar. */
.sh-marcos--fases > .sh-marco { display: block; padding-bottom: var(--space-3); }
.sh-marcos--fases > .sh-marco:last-child { padding-bottom: 0; }
/* a linha da fase: ponto | nome | as datas (| a seta, quando a fase abre) */
.sh-marcos--fases .sh-marco-resumo, .sh-marcos--fases > .sh-marco:not(:has(> .sh-marco-abre)) {
  display: grid; grid-template-columns: 1.5rem minmax(0, 1fr) auto; align-items: center; column-gap: var(--space-3); min-height: 1.5rem;
}
.sh-marcos--fases .sh-marco-resumo { grid-template-columns: 1.5rem minmax(0, 1fr) auto 1rem; list-style: none; cursor: pointer; }
.sh-marcos--fases .sh-marco-resumo::-webkit-details-marker { display: none; }
.sh-marcos--fases .sh-marco-resumo .sh-secao-seta { width: 1rem; height: 1rem; color: var(--texto-2); transition: transform var(--sh-dur) var(--sh-ease); }
.sh-marcos--fases .sh-marco-abre[open] > .sh-marco-resumo .sh-secao-seta { transform: rotate(180deg); }
.sh-marcos--fases .sh-marco-detalhe { margin: var(--space-2) 0 0 calc(var(--space-4) + var(--space-3)); }
.sh-marcos--fases .sh-marco-data { white-space: normal; text-wrap: balance; text-align: right; }
/* futuras em cinza; a de hoje (ou a primeira, se a Black ainda não começou) em destaque */
.sh-marcos--fases > .sh-marco:not([data-estado]) .sh-marco-titulo { color: var(--texto-2); }
.sh-marcos--fases > .sh-marco:not([data-estado]) .sh-marco-ponto { color: var(--texto-2); }
.sh-marcos--fases > .sh-marco[data-estado="proximo"] .sh-marco-titulo { color: var(--texto); font-weight: var(--fw-semibold); }
.sh-marcos--fases > .sh-marco[data-estado="proximo"] .sh-marco-data { color: var(--texto); }
.sh-marcos--fases > .sh-marco[data-estado="proximo"] .sh-marco-ponto { border-color: var(--texto); }
@media (max-width: 640px) {
  /* no celular a data desce para baixo do nome (nunca espreme o nome letra por letra) */
  .sh-marcos--fases .sh-marco-resumo, .sh-marcos--fases > .sh-marco:not(:has(> .sh-marco-abre)) { grid-template-columns: 1.5rem minmax(0, 1fr) 1rem; }
  .sh-marcos--fases > .sh-marco:not(:has(> .sh-marco-abre)) { grid-template-columns: 1.5rem minmax(0, 1fr); }
  .sh-marcos--fases .sh-marco-data { grid-column: 2; grid-row: 2; text-align: left; }
  .sh-marcos--fases .sh-marco-resumo .sh-secao-seta { grid-column: 3; grid-row: 1; }
}

/* ── 19.22b · PROVA · "academias como a sua tiveram resultado X aplicando Y" (`App.prova`, 03/10 · P5 do dono: prova antes do pedido) ───────────────────
   UMA linha curta ao lado da meta e da oferta: o que aconteceu com quem aplicou, e a fonte atrás do "?" (nunca um número sem base). Anatomia:
     <p class="sh-prova"><span class="sh-prova-texto">1 em cada 4 pessoas do grupo virou aluno.</span><button class="sh-icone-btn sh-prova-fonte">?</button></p>
   Sem caixa e sem cartão: é uma linha de apoio com o filete da marca à esquerda, para a prova ser vista sem competir com o número. */
.sh-prova { display: flex; align-items: center; gap: var(--space-2); margin: 0; padding: var(--space-1) 0 var(--space-1) var(--space-3); border-left: 3px solid var(--acento-texto); }
.sh-prova-texto { min-width: 0; font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--texto); }   /* frase curta: herda o `balance` do html (em `pretty` deixava a órfã) */
.sh-prova-fonte { flex: 0 0 auto; width: 1.75rem; height: 1.75rem; color: var(--texto-2); }
.sh-prova-fonte .sh-icone { width: 1rem; height: 1rem; }

/* ── 19.23 · CALENDÁRIO · a semana com os eventos e as ações (agenda de verdade · Google Agenda / Uber "Atividade") ──
   Anatomia:
     <div class="sh-calendario"><div class="sh-calendario-dia [sh-calendario-dia--hoje]"><span class="sh-calendario-data">seg 05</span>
       <button type="button" class="sh-calendario-evento [sh-calendario-evento--atrasado|--feito|--black|--evento]">…</button></div>…</div>
   O evento é UMA linha só (o sinal do tipo + o título curto; o que passa vira reticências e o título inteiro vai na dica `title`): o detalhe abre ao TOCAR, na ficha da tarefa (`App.fichaDaTarefa`).
   No computador: 7 colunas, uma por dia. No celular: lista, o dia na esquerda e os eventos à direita (dia vazio some, salvo hoje).
   O tipo do evento NUNCA é só cor (R6): atrasado leva "!", feito leva ✓ e o texto apagado, Black leva ★, evento leva ◆; a faixa colorida só reforça. */
.sh-calendario { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-1); }   /* a semana divide a largura com a lista lateral (~95 px por dia a 1440): folga curta */
.sh-calendario-dia {
  display: grid; gap: var(--space-1); align-content: start; min-width: 0;
  min-height: 7.5rem; padding: var(--space-1);
  border: 1px solid var(--borda); border-radius: var(--raio-controle);
  background: var(--superficie);
}
.sh-calendario-data { font-size: var(--fs-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; color: var(--texto-2); }
.sh-calendario-dia--hoje { border-color: var(--texto); background: color-mix(in srgb, var(--texto) 5%, var(--superficie)); }
.sh-calendario-dia--hoje .sh-calendario-data { color: var(--texto); }
.sh-calendario-dia--hoje .sh-calendario-data::after { content: " \00B7  hoje"; font-weight: var(--fw-regular); }
.sh-calendario-evento {
  /* O título QUEBRA dentro do compromisso e aparece inteiro (04/10 · G2, "nenhum texto cortado": era UMA linha com reticências e cortava
     "Conecte o WhatsApp da rec…" no celular). Nunca `nowrap` + `text-overflow` nem `line-clamp` (o clamp deixava a 2ª linha pintada como uma lasca
     embaixo, ensaio a05a2567). O que dá a altura é o texto; a mínima (alvo de toque) vem do respiro em cima e embaixo, que centra a linha única. */
  --evento-alto: 2.25rem;
  display: block; width: 100%; min-width: 0; min-height: var(--evento-alto);
  padding: max(var(--space-1), calc((var(--evento-alto) - 1.35em) / 2)) var(--space-1);
  border: 0; border-left: 3px solid var(--borda-forte); border-radius: var(--space-1);
  background: color-mix(in srgb, var(--texto) 6%, transparent); color: var(--texto);
  font: inherit; font-size: var(--fs-sm); line-height: var(--lh-snug); text-align: left; text-decoration: none;
  white-space: normal;
  text-wrap: balance; overflow-wrap: anywhere;
  cursor: pointer;
  transition: var(--sh-transicao);
}
.sh-calendario-evento:hover { background: color-mix(in srgb, var(--texto) 11%, transparent); }
.sh-calendario-evento--atrasado { border-left-color: var(--acento-texto); background: color-mix(in srgb, var(--booot-ouro-600) 12%, transparent); }
.sh-calendario-evento--atrasado::before { content: "! "; font-weight: var(--fw-semibold); color: var(--acento-texto); }
.sh-calendario-evento--feito { border-left-color: var(--sucesso-texto); color: var(--texto-2); }
.sh-calendario-evento--feito::before { content: "\2713  "; color: var(--sucesso-texto); }
.sh-calendario-evento--black { border-left-color: var(--booot-ouro-600); }
.sh-calendario-evento--black::before { content: "\2605  "; color: var(--acento-texto); }
.sh-calendario-evento--evento { border-left-color: var(--info-texto); }
.sh-calendario-evento--evento::before { content: "\25C6  "; color: var(--info-texto); }
/* A SEMANA VIRA LISTA PELO ESPAÇO DA COLUNA, NUNCA PELA LARGURA DA TELA (o dono, 03/10 13h50, Início publicada a ~1000 px: cada compromisso
   virava "Check-i…", "Trazer…": "Tá horrível"). 7 dias legíveis pedem ~48rem; abaixo disso, o dia à esquerda e os eventos à direita (dia vazio
   some, salvo hoje). A grade do calendário é o container (o cartão que o envolve), e o mês/ano seguem com a regra deles. */
:where(*):has(> .sh-calendario) { container-type: inline-size; }
@container (max-width: 48rem) {
  .sh-calendario:not(.sh-calendario--mes):not(.sh-calendario--ano) { grid-template-columns: minmax(0, 1fr); }
  .sh-calendario:not(.sh-calendario--mes):not(.sh-calendario--ano) > .sh-calendario-dia { grid-template-columns: 5.5rem minmax(0, 1fr); column-gap: var(--space-3); min-height: 0; align-items: start; }
  .sh-calendario:not(.sh-calendario--mes):not(.sh-calendario--ano) > .sh-calendario-dia > .sh-calendario-data { grid-column: 1; }
  .sh-calendario:not(.sh-calendario--mes):not(.sh-calendario--ano) > .sh-calendario-dia > .sh-calendario-evento { grid-column: 2; }
  .sh-calendario:not(.sh-calendario--mes):not(.sh-calendario--ano) > .sh-calendario-dia:not(.sh-calendario-dia--hoje):not(:has(.sh-calendario-evento)) { display: none; }
}
@media (max-width: 900px) {
  .sh-calendario { grid-template-columns: minmax(0, 1fr); }
  .sh-calendario-dia { grid-template-columns: 5.5rem minmax(0, 1fr); column-gap: var(--space-3); min-height: 0; align-items: start; }
  .sh-calendario-dia > .sh-calendario-data { grid-column: 1; }
  .sh-calendario-dia > .sh-calendario-evento { grid-column: 2; }
  .sh-calendario-dia:not(.sh-calendario-dia--hoje):not(:has(.sh-calendario-evento)) { display: none; }
}
@media (hover: none) and (pointer: coarse) {
  .sh-calendario-evento { --evento-alto: 44px; }
}

/* ── 19.24 · FORMULÁRIO · o desenho da moldura de tela cheia (GOV.UK "Question pages" · Material 3 text fields e selection controls) ──────────
   O dono (03/10): "tem coisas que não seguem o mesmo chassi (parece gambiarra)". A moldura (`app/moldura.css`) só POSICIONA (topo e rodapé fixos, a
   coluna de leitura, a grade do topo); TODO o desenho do formulário mora aqui, em `sh-form-*` (e em `.sh-form .sh-escolha`, a opção do kit na
   forma de formulário). A marcação carrega as DUAS classes: `fx-topo sh-form-topo` (o `fx-` diz ONDE, o `sh-form-` diz COMO). Anatomia:
     <section class="fx-moldura sh-form">
       topo   .sh-form-topo      voltar · .sh-form-contador ("Passo 2 de 5") · .sh-salvo · fechar · .sh-progresso OU a trilha .sh-form-trilha
       corpo  .sh-form-corpo     a pergunta (.sh-titulo), a ajuda curta ([data-parte="apoio"]) + .sh-form-mais ("Por que sugerimos"), as opções
                                 (.sh-escolhas > .sh-escolha), "Outro valor" (.sh-form-outro), a consequência (.sh-form-consequencia), copiar (.sh-form-copiar)
       rodapé .sh-form-rodape    Voltar · Continuar (um primário por tela, sempre clicável)
   A página que a hospeda leva `.sh-form-pagina` (a moldura ocupa a área principal inteira, sem a coluna de 75rem do `.sh-pagina`). A coluna de LEITURA
   (44rem) e o gutter são da posição (moldura.css); o texto corrido segue a medida do kit (`--medida-texto`, §2.3).
   Padrões adotados: GOV.UK "Question pages / one thing per page" https://design-system.service.gov.uk/patterns/question-pages/ ·
   Material 3 text fields https://m3.material.io/components/text-fields e radio/checkbox https://m3.material.io/components/radio-button */
.sh-form-pagina, .sh-pagina.sh-form-pagina { max-width: none; padding: 0; gap: 0; }

/* topo e rodapé: faixas de ponta a ponta com o fundo da página (a rolagem passa por baixo), o rodapé separado por UMA linha */
.sh-form-topo { background: var(--pagina); }
.sh-form-rodape { background: var(--pagina); border-top: 1px solid var(--borda); }
.sh-form-rodape .sh-btn--primario[data-apagado="sim"] { opacity: var(--desabilitado); }
/* "Passo 2 de 5": 14 px de peso médio, não 13 de legenda (o dono: "sem escrever tudo pequeno demais"); o "Salvo" ao lado na mesma altura */
.sh-form-contador { font-size: var(--fs-sm); line-height: var(--lh-ui); font-weight: var(--fw-regular); color: var(--texto-2); }
.sh-form .sh-salvo { font-size: var(--fs-sm); }

/* a trilha das etapas: UM trecho fino por etapa, que nunca quebra; feita = cheia, a atual enche pela fração (`--pct`, 0 a 100, passo k de m) */
.sh-form-trilha { display: flex; flex-wrap: nowrap; gap: var(--space-1); margin: 0; padding: 0; min-width: 0; list-style: none; }
.sh-form-trilha > li {
  flex: 1 1 0; min-width: 0; height: .25rem; border-radius: var(--raio-pill);
  background: color-mix(in srgb, var(--texto) 12%, transparent); font-size: 0; overflow: hidden;
}
.sh-form-trilha > li[data-estado="feita"] { background: var(--texto-2); }
.sh-form-trilha > li[aria-current="step"] { position: relative; }
.sh-form-trilha > li[aria-current="step"]::after { content: ""; position: absolute; inset: 0 auto 0 0; width: calc(var(--pct, 100) * 1%); background: var(--texto); }   /* G11: o avanço é uma barra chapada, sem degradê */

/* o corpo: a PERGUNTA é o protagonista (o maior texto da tela), a ajuda curta embaixo, o resto da ajuda recolhido */
.sh-form-corpo > .sh-titulo { font-size: var(--fs-tela); line-height: var(--lh-heading); letter-spacing: -.01em; text-wrap: balance; }
.sh-form-corpo > .sh-titulo:focus { outline: none; }
.sh-form-corpo > [data-parte="apoio"] { font-size: var(--fs-md); line-height: var(--lh-ui); }
.sh-form-mais > summary {
  display: flex; align-items: center; min-height: 44px;
  font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--texto);
}
.sh-form-mais > p { margin-top: var(--space-1); font-size: var(--fs-md); line-height: var(--lh-ui); color: var(--texto-2); white-space: pre-line; text-wrap: pretty; }

/* o campo de texto: a caixa do `.sh-campo` desenha, o <textarea> dentro dele não tem borda nem fundo próprios */
.sh-form .sh-campo textarea { border: 0; background: transparent; color: var(--texto); font: inherit; }
.sh-form .sh-campo textarea:focus-visible { outline: none; }   /* o anel de foco é o do campo inteiro (`.sh-campo:focus-within`), nunca dois */

/* AS OPÇÕES (a escolha do kit na forma de formulário): alvo >= 56 px, a MARCA do rádio/caixa visível nos dois temas (>= 3:1, WCAG 1.4.11:
   o 2º degrau de texto mede 7,3:1 no escuro e 4,8:1 no claro sobre o cartão; o `--campo-borda` mede hoje 3,17:1 no escuro e 3,16:1 no claro, mas a marca do rádio usa o 2º degrau, com folga),
   o marcado inconfundível (borda e anel na cor do texto). Escopo `.sh-form`: a escolha das outras telas segue a do §19.4. */
.sh-form .sh-escolhas { gap: var(--space-3); }
.sh-form fieldset.sh-escolhas { border: 0; margin: 0; padding: 0; min-width: 0; }
.sh-form .sh-escolha {
  min-height: 3.5rem; padding: var(--space-3) var(--space-4); gap: var(--space-3); align-items: flex-start;
  border: 1px solid var(--borda-forte); border-radius: var(--raio-cartao); background: var(--superficie);
}
.sh-form .sh-escolha:hover { border-color: var(--texto-2); background: color-mix(in srgb, var(--texto) 4%, transparent); }
.sh-form .sh-escolha > .sh-stack { gap: var(--space-1); align-content: center; min-height: 1.5rem; }
.sh-form .sh-escolha .sh-texto, .sh-form .sh-escolha .sh-apoio { font-size: var(--fs-md); line-height: var(--lh-ui); }
.sh-form .sh-escolha-marca { width: 1.5rem; height: 1.5rem; margin-top: 0; border: .125rem solid var(--texto-2); background: var(--superficie); }
.sh-form .sh-escolha-marca::after { width: .75rem; height: .75rem; }
.sh-form .sh-escolha-marca .sh-icone { width: 1rem; height: 1rem; }
.sh-form .sh-escolha:has(> input:checked), .sh-form .sh-escolha[aria-checked="true"] {
  border-color: var(--texto); box-shadow: 0 0 0 1px var(--texto); background: color-mix(in srgb, var(--texto) 6%, transparent);
}
.sh-form .sh-escolha:has(> input:checked) > .sh-escolha-marca, .sh-form .sh-escolha[aria-checked="true"] > .sh-escolha-marca { border-color: var(--texto); }
/* a pílula "Recomendado": a largura do PRÓPRIO texto (na pilha de grade ela esticava na largura toda do cartão) e colada ao título, logo acima dele */
.sh-form .sh-escolha .sh-pill { justify-self: start; order: -1; width: fit-content; min-height: 1.5rem; font-size: var(--fs-sm); color: var(--texto-2); background: var(--pagina); }
/* com a pílula acima do título, a marca desce até a linha do TÍTULO (a pílula tem 1,5rem + o respiro da pilha) */
.sh-form .sh-escolha:has(.sh-pill) > .sh-escolha-marca { margin-top: calc(var(--space-4) + var(--space-1)); }

/* "OUTRO VALOR" é uma OPÇÃO como as outras: o mesmo cartão, o mesmo alvo, a mesma marca (círculo vazio) e, aberto, o campo no cartão já marcado */
.sh-form .sh-form-outro {
  position: relative; width: 100%; min-height: 3.5rem; padding: var(--space-3) var(--space-4); gap: var(--space-3);
  display: flex; align-items: center; justify-content: flex-start;
  border: 1px solid var(--borda-forte); border-radius: var(--raio-cartao); background: var(--superficie);
  color: var(--texto); font-size: var(--fs-md); font-weight: var(--fw-semibold); text-align: left;
}
.sh-form .sh-form-outro::before {
  content: ""; flex: none; box-sizing: border-box; width: 1.5rem; height: 1.5rem;
  border: .125rem solid var(--texto-2); border-radius: var(--raio-pill); background: var(--superficie);
}
.sh-form button.sh-form-outro:hover:not(:disabled) { background: color-mix(in srgb, var(--texto) 4%, transparent); border-color: var(--texto-2); color: var(--texto); }
.sh-form label.sh-form-outro { border-color: var(--texto); box-shadow: 0 0 0 1px var(--texto); font-weight: var(--fw-regular); }
.sh-form label.sh-form-outro::before { border-color: var(--texto); background: var(--texto); box-shadow: inset 0 0 0 .125rem var(--superficie); }   /* G11: o ponto do radio é chapado (anel de superfície), sem degradê */
.sh-form label.sh-form-outro input { font-size: var(--fs-md); min-height: 44px; }

/* a consequência na hora (LEGO §2): um cartão baixo logo abaixo das opções; vazia some do olho e fica no DOM (live region) */
.sh-form-consequencia { padding: var(--space-3); border: 1px solid var(--borda); border-radius: var(--raio-controle); background: var(--superficie-2); }
.sh-form-consequencia:empty { padding: 0; border: 0; }

/* o número ou o texto que a pessoa copia (a linha da API, o link): cartão baixo com o valor e o botão de copiar */
.sh-form-copiar {
  display: grid; gap: var(--space-2); justify-items: start; width: 100%;
  padding: var(--space-3); border: 1px solid var(--borda); border-radius: var(--raio-controle); background: var(--superficie-2);
}
.sh-form-copiar-valor { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--texto); overflow-wrap: anywhere; }
.sh-form-copiar--longo .sh-form-copiar-valor { font-size: var(--fs-sm); font-weight: var(--fw-regular); white-space: pre-wrap; text-wrap: pretty; margin: 0; }


/* ═══ 20-VIDEOS · a vitrine de mídia, a série, a leitura e o quadro embutido (onda 2 · 03/10/2026 · "a tela compõe, o kit desenha") ═══════════
   Vídeos e Atender desenhavam à mão: o cartão de vídeo com capa e selo de duração, a lista da série com o item atual, os passos que abrem, a tabela, o documento, o PIN e
   o quadro do CRM. Agora o desenho mora aqui e a tela só posiciona. Padrões adotados: o Card de mídia e as Lists do Material 3 (https://m3.material.io/components/cards),
   a grade de vídeo do YouTube / Netflix web, a playlist (player + lista da série com o atual destacado) e a divulgação progressiva do NN/g. Tudo com token, nada de valor cru
   de cor da tela. */

/* 20.1 · VITRINE · UMA grade, UM cartão por item. `auto-fill`, NUNCA `auto-fit` (medido em 07/09): com UM item o `auto-fit` colapsa as colunas vazias e estica o único
   cartão pro tamanho da tela. Anatomia (a lista é <ul>, o item é <li>, o cartão é <button> ou <a>):
     <ul class="sh-grade sh-grade--vitrine"><li><button class="sh-midia" [data-visto="sim"]>
       <span class="sh-midia-capa"><svg class="sh-icone sh-midia-ico"/><span class="sh-selo-foto">12:30</span></span>
       <span class="sh-midia-corpo"><b>Título</b><span class="sh-pill sh-pill--ok">Aberto</span></span></button></li></ul> */
.sh-grade--vitrine { margin: 0; padding: 0; list-style: none; gap: var(--space-4); grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }
/* a fileira reta: o item do grid é o <li> e ele esticava sozinho enquanto o cartão ficava na altura do conteúdo */
.sh-grade--vitrine > li { display: grid; }
.sh-midia {
  display: grid; gap: var(--space-3); align-content: start; width: 100%;
  color: inherit; text-align: left; text-decoration: none; cursor: pointer; font: inherit; overflow: hidden;
  transition: var(--sh-transicao);
}
.sh-midia:hover { border-color: var(--borda-forte); }
.sh-midia:active { transform: scale(.99); }
/* A CAPA (04/10 · C7 do juiz visual do AR: "todas as miniaturas são um cinza com ▷"): a imagem do vídeo cobre a caixa 16:9 (`.sh-midia-img`, preguiçosa, gravada na publicação); sem ela, a capa de RESERVA
   da marca (um degradê de token) com o botão de tocar num disco, como as plataformas de vídeo desenham o que ainda não tem foto. O disco fica por cima da imagem também: é o sinal de "toque para assistir". */
.sh-midia-capa {
  position: relative; display: grid; place-items: center; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: var(--raio-controle); background: color-mix(in srgb, var(--texto) 8%, transparent);   /* G11: capa de reserva CHAPADA (sem degradê) */
}
.sh-midia-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.sh-midia-ico { position: relative; box-sizing: content-box; width: 1.25rem; height: 1.25rem; padding: var(--space-2); border-radius: var(--raio-pill); background: var(--superficie); color: var(--texto); box-shadow: var(--sombra-cartao); }
.sh-midia:hover .sh-midia-ico { background: var(--superficie-2); }
.sh-midia[data-visto="sim"] .sh-midia-capa { opacity: var(--desabilitado); }
.sh-midia-corpo { display: grid; gap: var(--space-2); justify-items: start; min-width: 0; }
/* 2 linhas e para: título de 10 palavras não empurra a grade */
.sh-midia-corpo > b {
  font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
/* o selo SOBRE a capa (a duração, ou a palavra "Leitura"), como no YouTube e no Loom: fundo escuro e texto claro FIXOS nos dois temas (o semântico inverte no claro e o selo
   ficaria ilegível sobre a capa), algarismo tabular. Vale para qualquer selo que fique sobre foto ou vídeo. */
.sh-selo-foto {
  position: absolute; right: var(--space-2); bottom: var(--space-2);
  padding: 0 var(--space-2); border-radius: var(--raio-pill);
  background: color-mix(in srgb, var(--booot-cinza-000) 78%, transparent); color: var(--booot-cinza-900);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums;
}

/* 20.2 · LINHA DE SÉRIE · a lista de uma playlist: número (ou ✓ no que já foi aberto), título, duração; o ATUAL com a barra à esquerda. Estado é forma MAIS cor (R6).
     <ul class="sh-lista"><li><button class="sh-linha" aria-current="true"><span class="sh-linha-n">3</span><span class="sh-linha-corpo"><b>…</b></span><span class="sh-linha-fim">4:10</span></button></li></ul> */
button.sh-linha { width: 100%; background: transparent; border: 0; border-bottom: 1px solid var(--borda); color: inherit; text-align: left; font: inherit; font-size: var(--fs-md); }
.sh-linha-n {
  flex: 0 0 auto; display: grid; place-items: center; width: 1.75rem; height: 1.75rem; border-radius: var(--raio-pill);
  background: color-mix(in srgb, var(--texto) 8%, transparent); color: var(--texto-2);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums;
}
.sh-linha-n .sh-icone { width: .875rem; height: .875rem; color: var(--sucesso-texto); }
.sh-linha-fim { flex: 0 0 auto; color: var(--texto-2); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.sh-linha[aria-current="true"] { position: relative; padding-left: var(--space-2); border-radius: var(--raio-controle); background: var(--superficie-2); }
.sh-linha[aria-current="true"]::before {
  content: ""; position: absolute; left: 0; top: var(--space-1); bottom: var(--space-1); width: 2px; border-radius: var(--raio-pill); background: var(--texto);
}
.sh-linha[aria-current="true"] .sh-linha-n { background: var(--texto); color: var(--pagina); }

/* 20.3 · PÍLULA · a contagem dentro do chip de filtro e as duas variantes SEM ponto (o ponto é de ESTADO VIVO, §6): `--ok` = feito/aberto, `--destaque` = o que pede a ação agora */
.sh-pill-n { font-variant-numeric: tabular-nums; color: var(--texto-2); }
button.sh-pill[aria-pressed="true"] .sh-pill-n { color: inherit; opacity: .75; }
.sh-pill--ok { color: var(--sucesso-texto); border-color: color-mix(in srgb, var(--booot-sucesso) 40%, transparent); }
.sh-pill--ok .sh-icone { width: .75rem; height: .75rem; }
.sh-pill--destaque { color: var(--acento-texto); border-color: color-mix(in srgb, var(--booot-ouro-600) 40%, transparent); }

/* 20.4 · LEITURA · a coluna de texto corrido (a medida confortável do token) e a NOTA (o recado numa lavagem do texto, sem borda) */
.sh-leitura { max-width: var(--medida-texto); }
.sh-nota {
  margin: 0; padding: var(--space-3) var(--space-4); border-radius: var(--raio-controle);
  background: color-mix(in srgb, var(--texto) 5%, transparent);
}

/* 20.5 · DETALHES · "ver mais" que abre no lugar (divulgação progressiva do NN/g, o <details> nativo faz teclado, foco e leitor de tela). Nasce FECHADO.
   O resumo é o MESMO da 20-ATRAIR (uma peça só); `--linha` leva o fio de cima e o corpo respira com a medida de leitura. */

/* ═══ 20-ATRAIR · as peças que o Atrair e o Acelerar pediram à onda 2 (03/10/2026 · "a tela compõe, o kit desenha") ═══════════
   Antes cada tela desenhava à mão: a bolinha numerada (.atr-num), o código copiável, o texto pronto, a imagem do passo, o cabeçalho do relatório em CAIXA ALTA.
   Agora o desenho mora aqui e a tela só compõe. Padrões adotados: o stepper e a linha do tempo do Material 3 / "acompanhe seu pedido" do Nubank (marcos, §19.22),
   o funil em barras do Amplitude https://amplitude.com/docs/analytics/charts/funnel-analysis (proporcional à 1ª etapa), a divulgação progressiva (details). */

/* 20.1 · ROTEIRO · os marcos com CORPO (o passo a passo numerado): o ponto fica no alto, o corpo respira ao lado.
   O ponto leva o NÚMERO do passo (texto dentro dele) enquanto não foi feito, e o ✓ quando foi (o estado nunca é só cor). Anatomia:
     <ol class="sh-marcos sh-marcos--roteiro"><li class="sh-marco" data-estado="feito|hoje|proximo"><span class="sh-marco-ponto">1</span>
       <div class="sh-marco-corpo">…</div><span class="sh-marco-data"><span class="sh-pill">Liberado</span></span></li></ol> */
.sh-marcos--roteiro .sh-marco { align-items: start; padding-bottom: var(--space-4); }
.sh-marcos--roteiro .sh-marco:last-child { padding-bottom: 0; }
.sh-marcos--roteiro .sh-marco-ponto { font-size: var(--fs-sm); }
.sh-marcos--roteiro .sh-marco[data-estado="proximo"] .sh-marco-ponto { color: var(--texto-2); }
.sh-marcos--roteiro .sh-marco[data-estado="hoje"] .sh-marco-ponto { color: var(--superficie); }
.sh-marcos--roteiro .sh-marco-data { white-space: normal; text-wrap: balance; }
.sh-marco-corpo { display: grid; gap: var(--space-2); align-content: start; min-width: 0; }
/* o título do corpo vira o assunto do passo; o apoio é o texto de ajuda, e vale também pro marco horizontal (a frase curta sob o título) */
.sh-marco-apoio { min-width: 0; font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--texto-2); overflow-wrap: anywhere; }
.sh-marcos--horizontal .sh-marco-titulo { font-weight: var(--fw-semibold); }
/* lado a lado a data quebra no espaço ("01/10 a" / "16/10") em vez de invadir o vizinho; vertical (6+ marcos, celular) ela volta a uma linha */
.sh-marcos--horizontal .sh-marco-data { font-size: var(--fs-sm); white-space: normal; text-wrap: balance; }

/* 20.2 · COPIÁVEL · o código (ou o texto curto) que a pessoa copia, com o botão ao lado · e o TEXTO PRONTO (o bloco que se cola em outro lugar) */
.sh-copiavel {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--borda); border-radius: var(--raio-controle); background: var(--superficie-2);
}
.sh-copiavel code { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--texto); overflow-wrap: anywhere; }
.sh-texto-pronto {
  margin: 0; padding: var(--space-3); white-space: pre-wrap; text-wrap: pretty; overflow-wrap: anywhere;
  font: inherit; font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--texto);
  border: 1px solid var(--borda); border-radius: var(--raio-controle); background: var(--superficie-2);
}

/* 20.3 · IMAGEM · a figura do conteúdo (print de um passo, post da academia): cantos do controle, fundo de espera; `--moldura` leva a borda, `--retrato` a proporção 4:5 do feed */
.sh-imagem { display: block; width: 100%; border-radius: var(--raio-controle); background: var(--superficie-2); }
.sh-imagem--moldura { border: 1px solid var(--borda); }
.sh-imagem--retrato { aspect-ratio: 4 / 5; object-fit: cover; }

/* 20.4 · DETALHES · "ver mais" que abre no lugar (divulgação progressiva): a linha toda clica, o chevron gira ao abrir */
.sh-detalhes > summary {
  display: inline-flex; align-items: center; gap: var(--space-2);
  list-style: none; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--texto);
}
.sh-detalhes > summary::-webkit-details-marker { display: none; }
.sh-detalhes > summary .sh-icone { transition: transform var(--sh-dur) var(--sh-ease); }
.sh-detalhes[open] > summary .sh-icone { transform: rotate(180deg); }
.sh-detalhes[open] > summary { margin-block-end: var(--space-2); }
.sh-detalhes--linha { border-top: 1px solid var(--borda); padding-top: var(--space-3); }
.sh-detalhes-corpo { display: grid; gap: var(--space-3); max-width: var(--medida-texto); }
.sh-detalhes-corpo > * { margin: 0; }

/* 20.6 · DOCUMENTO · o texto longo em leitura: título de seção, lista com marcador (o `:where(ul, ol)` do kit zera o marcador, e no documento ele É informação) */
.sh-doc-secao { font-size: var(--fs-xl); font-weight: var(--fw-semibold); line-height: var(--lh-snug); color: var(--texto); }
h4.sh-doc-secao { font-size: var(--fs-md); }
.sh-doc-lista { padding-left: var(--space-5); }
ul.sh-doc-lista { list-style: disc; }
ol.sh-doc-lista { list-style: decimal; }
.sh-doc-lista > li + li { margin-top: var(--space-2); }

/* 20.7 · TABELA · a tabela de leitura (cabeçalho em peso, fio entre linhas). No celular ela EMPILHA: cada linha vira um bloco e cada célula depois da 1ª diz o nome da
   coluna (o `data-rotulo` que a tela copia do cabeçalho), porque tabela que rola de lado esconde a coluna do prazo sem aviso. Envolva em `.sh-tabela-rola`. */
.sh-tabela-rola { overflow-x: auto; }
.sh-tabela { width: 100%; border-collapse: collapse; font-size: var(--fs-md); line-height: var(--lh-ui); }
.sh-tabela th, .sh-tabela td { padding: var(--space-2) var(--space-3) var(--space-2) 0; border-bottom: 1px solid var(--borda); text-align: left; vertical-align: top; }
.sh-tabela th { color: var(--texto-2); font-weight: var(--fw-semibold); white-space: nowrap; }
@media (max-width: 640px) {
  .sh-tabela thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .sh-tabela, .sh-tabela tbody, .sh-tabela tr, .sh-tabela td { display: block; }
  .sh-tabela tr { padding: var(--space-2) 0; border-bottom: 1px solid var(--borda); }
  .sh-tabela td { padding: 0; border: 0; }
  .sh-tabela td:first-child { font-weight: var(--fw-semibold); }
  .sh-tabela td + td::before { content: attr(data-rotulo) ": "; color: var(--texto-2); }
}

/* 20.8 · PLAYER · o iframe de verdade dentro da caixa 16:9 (`data-com-video`) e a FACHADA (o botão no centro da caixa; o iframe só nasce no toque) */
.sh-video[data-com-video] { padding: 0; overflow: hidden; }
.sh-video[data-com-video] iframe { border-radius: inherit; }
.sh-video--fachada { display: grid; place-items: center; }

/* 20.9 · QUADRO · a página de outro sistema embutida (o CRM), que ocupa a altura útil da janela: a casca (topo + faixa) fica fora; no celular nunca menor que 28rem */
.sh-quadro {
  display: block; width: 100%; height: calc(100dvh - 11rem); min-height: 28rem;
  border: 0; border-radius: var(--raio-cartao); background: var(--superficie);
}

/* 20.10 · CÓDIGO · o PIN (ou qualquer código curto que a pessoa lê e digita): peso, algarismo tabular e o respiro de título */
.sh-codigo { font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; letter-spacing: var(--letra-titulo); color: var(--texto); }


/* 20.5 · FUNIL GRANDE · as etapas em barras PROPORCIONAIS à 1ª (Interessados = 100%), com o número grande e o "vs" do período anterior embaixo dele.
   Anatomia (a tela escreve só o `--pct` por variável, depois da pintura):
     <div class="sh-funil sh-funil--grande"><div class="sh-funil-etapa"><span class="sh-funil-rotulo">Interessados</span>
       <span class="sh-barra" role="img" aria-label="…"><i></i></span><span class="sh-funil-valor"><b class="sh-funil-numero">31</b><span class="sh-kpi-apoio">+3 vs …</span></span></div>…</div> */
.sh-funil--grande { gap: var(--space-4); }
.sh-funil--grande .sh-funil-etapa { grid-template-columns: minmax(7rem, 11rem) minmax(0, 1fr) minmax(7rem, 14rem); }
.sh-funil--grande .sh-funil-etapa > .sh-barra { height: 2rem; }
.sh-funil-rotulo { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--texto); }
.sh-funil-valor { display: grid; justify-items: end; gap: var(--space-1); text-align: right; }
.sh-funil--grande .sh-funil-numero { font-size: var(--fs-xl); font-weight: var(--fw-semibold); line-height: 1; }
@media (max-width: 640px) {
  .sh-funil--grande .sh-funil-etapa { grid-template-columns: minmax(0, 1fr) auto; row-gap: var(--space-2); }
  .sh-funil--grande .sh-funil-etapa > .sh-barra { grid-column: 1 / -1; grid-row: 2; }
  .sh-funil--grande .sh-funil-valor { grid-column: 2; grid-row: 1; }
}
@media (max-width: 640px) {
  /* o marco horizontal volta a ser vertical no celular (§19.22): o apoio desce para a coluna do texto, sob o título */
  .sh-marcos--horizontal .sh-marco-apoio { grid-column: 2 / -1; }
}

/* ═══ 20-VITRINE · o que não está no plano APARECE, apagado, com UM botão para liberar (D-APP-E-VITRINE-O-QUE-NAO-ESTA-NO-PLANO-APARECE-E-ABRE-PARA-ASSINAR-03OUT) ══════
   O app é uma vitrine: o recurso fora do plano nunca some e nunca afirma o que a pessoa não pode cumprir. Mostra o conteúdo real (ou o exemplo) apagado e,
   embaixo, a trava: o selo do cadeado e o botão "Liberar com o <PLANO>", que leva à subida que o servidor mandou (`/app/assinar?para=<plano>&porque=<item>`).
   Padrão de mercado adotado: "locked feature preview / paywall in context" do freemium (Spotify, Notion, Linear)
   https://www.appcues.com/blog/freemium-upgrade-prompts . Anatomia (desenhada por `App.vitrine(el, subida)`, app.js (j); a tela só compõe o conteúdo):
     <div class="sh-vitrine" role="group" aria-label="Exemplo, disponível no PLUS">
       <div class="sh-vitrine-conteudo" aria-disabled="true"> …o conteúdo real ou o exemplo, SEM ação clicável (o kernel tira do foco o que houver)… </div>
       <div class="sh-vitrine-trava"><span class="sh-vitrine-selo"><svg class="sh-icone">cadeado</svg>Disponível no PLUS</span><a class="sh-btn sh-btn--secundario">Liberar com o PLUS</a></div>
     </div>
   Acessível: o conteúdo continua legível para o leitor de tela (aria-disabled, não inert), nada nele recebe foco ou clique e o botão da trava é o ÚNICO foco da peça.
   Nunca só cor (R6): o apagado vem com o cadeado e a palavra "Disponível no …". O botão é secundário: a primária da página é uma só (R1). */
.sh-vitrine { display: grid; gap: var(--space-3); align-content: start; min-width: 0; overflow: hidden; }
.sh-vitrine-conteudo {
  display: grid; gap: var(--space-3); align-content: start; min-width: 0;
  opacity: .55; filter: grayscale(.5);
  pointer-events: none; user-select: none; -webkit-user-select: none;
}
.sh-vitrine-conteudo * { pointer-events: none; }
.sh-vitrine-trava {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--borda);
}
.sh-vitrine-selo {
  display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0;
  font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-ui); color: var(--texto);
}
.sh-vitrine-selo .sh-icone { width: 1.25rem; height: 1.25rem; color: var(--acento-texto); }
@media (max-width: 640px) {
  .sh-vitrine-trava { flex-direction: column; align-items: stretch; }
  .sh-vitrine-trava .sh-btn { width: 100%; min-height: 44px; }
}

/* ═══ 20-ONBOARDING · as peças das telas de começo (Ativar a IA · Migrar · Assinar · Começar) ═════════════════════════════
   O dono (03/10): "Precisa ser mais simples ... mais elementos visuais - checkpoints, linha do tempo, progresso" e "Tem coisas que não
   seguem o mesmo chassi (cada coisa feita à mão)". A causa das 4 folhas de tela (ativar, migrar, assinar, comecar): cada uma desenhava
   o PRÓPRIO campo, cartão de aviso, resumo, lista de inclusão e erro de campo (66 declarações de desenho). Aqui moram as peças, uma
   receita cada, e as folhas de tela ficam só com posição. Padrões adotados (nada inventado):
     · GOV.UK "Question pages" / "Check answers" (uma pergunta por tela; resposta + "Alterar") https://design-system.service.gov.uk/patterns/check-answers/
     · Stripe Checkout (resumo do pedido, valor à direita) https://docs.stripe.com/payments/checkout
     · Material 3 stepper (marcos em §19.22) https://m3.material.io/components/progress-indicators */

/* ── 20.1 · CAMPO DE TEXTO LIVRE · o corpo do formulário em 16 px, a caixa grande, o número grande e o erro colado no campo ─
   `.sh-campo` nasceu para controle de 14 px (barra de busca, filtro). Em formulário o campo é o ASSUNTO da tela: `--corpo` sobe a 16 px
   (e o iOS não dá zoom). `--area` é a caixa de várias linhas (a textarea); `--numero` é o campo de um número só (Typeform: o campo É a tela). */
.sh-campo--corpo { font-size: var(--fs-md); }
.sh-campo--area { align-items: flex-start; padding-block: var(--space-2); }
.sh-campo textarea {
  flex: 1; min-width: 0; min-height: 6.5rem;
  border: 0; background: transparent; color: inherit; font: inherit; resize: vertical;
}
.sh-campo textarea:focus-visible { outline: none; }   /* o cartão do campo acende no :focus-within */
.sh-campo textarea::placeholder { color: var(--texto-2); }
.sh-campo--numero { gap: var(--space-3); padding-block: var(--space-2); }
.sh-campo--numero input {
  font-size: var(--fs-xl); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; letter-spacing: var(--letra-titulo);
}
.sh-campo-sufixo { flex: 0 0 auto; font-size: var(--fs-sm); color: var(--texto-2); white-space: nowrap; }
/* A23 · O "R$" DO CAMPO DE DINHEIRO fica FORA do <input>, à esquerda e alinhado ao número: o dono digita só o valor (o input nunca leva "R$" dentro, que quebra a conta e o teclado numérico).
   Anatomia: <label class="sh-campo sh-campo--numero"><span class="sh-campo-prefixo">R$</span><input inputmode="decimal" …></label>. Fica no celular (o sufixo sai, o prefixo não: é ele que diz que é dinheiro). */
.sh-campo-prefixo { flex: 0 0 auto; align-self: center; font-size: inherit; line-height: 1; color: var(--texto-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sh-campo--numero .sh-campo-prefixo { font-size: var(--fs-xl); font-weight: var(--fw-semibold); letter-spacing: var(--letra-titulo); }
/* o erro fica COLADO no campo, com ponto de estado (nunca só cor · DESIGN.md §4) */
.sh-campo-erro {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: var(--fs-sm); line-height: var(--lh-ui); color: var(--erro-texto);
}
.sh-campo-erro::before {
  content: ""; flex: 0 0 auto; width: .375rem; height: .375rem;
  border-radius: var(--raio-pill); background: currentColor;
}
@media (max-width: 640px) {
  .sh-campo--numero input { font-size: var(--fs-xl); }
  .sh-campo--numero .sh-campo-prefixo { font-size: var(--fs-xl); }
  .sh-campo--numero .sh-campo-sufixo { display: none; }   /* no celular a pergunta já diz o que é: o sufixo só rouba largura */
}

/* ── 20.2 · ESCOLHA MARCADA POR `aria-checked` (a múltipla escolha de botão, zero `input[type=checkbox]` na tela) e a pílula dentro dela ─
   Mesma anatomia e mesma cor da escolha de §19.4 (que marca por `:has(> input:checked)`); aqui o gancho é o `role=checkbox` do botão. */
.sh-escolha[aria-checked] { width: 100%; text-align: left; font: inherit; }
.sh-escolha[aria-checked="true"] {
  border-color: var(--texto);
  background: color-mix(in srgb, var(--texto) 6%, transparent);
}
.sh-escolha[aria-checked="true"] > .sh-escolha-marca { border-color: var(--texto); }
.sh-escolha[aria-checked="true"] > .sh-escolha-marca::after { transform: scale(1); }
.sh-escolha--multi[aria-checked="true"] > .sh-escolha-marca { background: var(--texto); color: var(--superficie); }
.sh-escolha--multi[aria-checked="true"] > .sh-escolha-marca .sh-icone { opacity: 1; }
.sh-escolha:focus-visible { outline: var(--anel-foco); outline-offset: var(--focus-offset); }
/* a pílula "Recomendado" tem a largura do PRÓPRIO texto (não estica) e fica no topo do cartão, ao lado do título da opção */
.sh-escolha > .sh-pill, .sh-escolha .sh-stack > .sh-pill { align-self: flex-start; justify-self: start; }

/* ── 20.3 · CARTÃO DE ATENÇÃO e CARTÃO ATUAL · o mesmo `.sh-card` com um tom ──────────────────────────────────────────────────
   Atenção = a academia não errou: duas respostas que não fecham entre si, ou uma sugestão da casa a confirmar. Cor de acento (nunca de
   erro: erro pinta culpa, acento pinta atenção). Atual = o plano/estado em que o cliente já está (a borda forte marca, a pílula diz). */
.sh-card[data-tom="atencao"] {
  border-color: var(--acento);
  background: color-mix(in srgb, var(--acento) 8%, var(--superficie));
}
.sh-card[data-tom="atencao"] > .sh-titulo, .sh-card[data-tom="atencao"] > .sh-rotulo { color: var(--acento-texto); }
.sh-card[data-atual="sim"] { border-color: var(--borda-forte); }

/* a linha de lista que mostra um valor de mais de uma linha (pergunta + resposta + "Alterar": o "Check answers" do GOV.UK) */
.sh-linha--livre { align-items: flex-start; }
.sh-linha--livre .sh-linha-corpo { gap: var(--space-1); }
.sh-linha--livre .sh-linha-corpo > p { white-space: pre-line; text-wrap: pretty; overflow-wrap: anywhere; }

/* ── 20.4 · SELO DE CONSEGUIU · o círculo do vazio (§10) na cor de sucesso, para o fim de um gesto ───────────────────────────── */
.sh-vazio-ico--sucesso { color: var(--sucesso-texto); }

/* ── 20.5 · LISTA DE INCLUSÃO · uma linha por benefício, com marcador (a comparação de planos) ───────────────────────────────
   Não é `.sh-linha`: aquela é a linha de REGISTRO (3 rem e divisória), e quatro delas empurram o botão do plano para fora da 1ª tela. */
.sh-inclui { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.sh-inclui > li { display: flex; align-items: baseline; gap: var(--space-2); font-size: var(--fs-md); line-height: var(--lh-ui); color: var(--texto-2); }
.sh-inclui > li::before {
  content: "\2713"; flex: 0 0 auto; color: var(--sucesso-texto); font-weight: var(--fw-semibold);
}

/* ── 20.6 · RESUMO DO PEDIDO · o que foi contratado à esquerda, o valor grande à direita (Stripe Checkout) ───────────────────── */
.sh-resumo {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3);   /* o valor desce quando não cabe (a classe acima) */
  padding: var(--space-3);
  border: 1px solid var(--borda); border-radius: var(--raio-controle);
  background: var(--superficie); color: var(--texto-2);
}
.sh-resumo > * { min-width: 0; }
.sh-resumo > :first-child { flex: 1 1 12rem; }
.sh-resumo > :last-child { margin-inline-start: auto; white-space: nowrap; }

/* ── 20.7 · QR E CÓDIGO DO PIX ─────────────────────────────────────────────────────────────────────────────────────────────── */
.sh-qr { width: 13rem; height: 13rem; border-radius: var(--raio-cartao); background: var(--superficie-2); }
.sh-codigo-bloco {
  width: 100%; margin: 0; padding: var(--space-3);
  border-radius: var(--raio-controle); background: var(--superficie-2);
  font-size: var(--fs-sm); color: var(--texto-2); word-break: break-all;
}

/* ── 20.8 · A FOLHA NÃO ESTOURA (classe `grade-sem-minmax-zero`, medida em 08/09 com a folha a 480 px) ─────────────────────────
   Grade aninhada sem `minmax(0, 1fr)` estoura para MAX-CONTENT dentro de um container estreito (item de grid nasce com `min-width: auto`).
   Medido: `.sh-modal-corpo` (479 de caixa) com `scrollWidth` 572, e a linha do plano anual saindo pela direita. A cura é do kit, UMA vez,
   para toda folha da casa; saiu de assinar.css onde estava como contenção declarada. */
.sh-folha .sh-modal-corpo,
.sh-folha .sh-escolhas,
.sh-folha .sh-escolha > .sh-stack { grid-template-columns: minmax(0, 1fr); }

/* ═══ 20-INICIO · a herança do Painel antigo (index.html) que saiu da folha da Início, e o calendário em 3 níveis (Ano · Mês · Semana) ═══
   A folha da tela (`app/inicio-plano.css`) só POSICIONA (gate `chassi-a-tela-compoe`). O que o Painel antigo ainda pinta com classe própria e que
   DESENHA (largura de página, raio, sombra, fundo e borda de botão) mora aqui, no kit, sem mudar um pixel: o QR do WhatsApp, o esqueleto do boot,
   o "ver mais" de texto longo e a receita única de popup dos modais (`.wa-modal-card`: Ajustar meta · Atualizar alunos · Análise da semana · Ranking ·
   SolModal · a conexão do WhatsApp). O 2º seletor do modal existe porque `#rank-modal .wa-modal-card` carrega um id e ganharia na especificidade. */
.wa-modal-qr { max-width: 300px; width: 100%; margin: 0 auto; display: block; border-radius: var(--radius-card); }
.boot-esqueleto { max-width: 75rem; }
.txt-longo-mais { padding: 0; margin-left: var(--space-1); background: none; border: 0; color: var(--blue-primary); font: inherit; font-size: var(--fs-sm); cursor: pointer; text-decoration: underline; }
.wa-modal:not([hidden]) .wa-modal-card,
#rank-modal:not([hidden]) .wa-modal-card {
  border-radius: var(--raio-cartao);
  box-shadow: var(--sh-sombra-modal);
}
/* o movimento respeita quem pediu menos movimento */
@media (prefers-reduced-motion: no-preference) {
  .wa-modal:not([hidden]) .wa-modal-card,
  #rank-modal:not([hidden]) .wa-modal-card { animation: sh-entrar var(--sh-dur) var(--sh-ease-saida); }
}


/* ── 20-INICIO.1 · CALENDÁRIO EM TRÊS NÍVEIS (Google Agenda: Ano · Mês · Semana) ────────────────────────────────────────────────────────────
   A SEMANA é o `.sh-calendario` de §19.23 (o detalhe da tarefa e da ação). O MÊS é o MESMO componente com `.sh-calendario--mes` (cabeça com os dias da semana, uma linha curta
   por item, o dia é um botão que abre a semana). O ANO é `.sh-calendario--ano`: 12 mini-meses, cada dia com NO MÁXIMO UM ponto da cor do tipo, e o nome do mês é o botão que abre o mês:
     <div class="sh-calendario sh-calendario--ano">
       <section class="sh-calendario-mes"><button class="sh-calendario-mes-nome">Outubro</button>
         <div class="sh-calendario-mini"><span class="sh-calendario-mini-cab">S</span>… <span></span> (vazios) <span class="sh-calendario-mini-dia" data-ponto="atrasado|black|evento|tarefa" [data-hoje="sim"]>5</span>…</div></section>…</div>
     <ul class="sh-calendario-legenda"><li data-ponto="black">Black</li>…</ul>      (a legenda dos pontos; os marcos da campanha usam `.sh-marcos--horizontal` de §19.22)
   O tipo NUNCA é só cor: o ponto de cada dia leva a palavra para o leitor de tela (`.sh-vh`) e a dica `title`; a legenda escreve o nome de cada cor. */
.sh-calendario--mes .sh-calendario-dia { min-height: 6.5rem; }
.sh-calendario--mes .sh-calendario-evento { --evento-alto: 0px; font-size: var(--fs-sm); }
.sh-calendario-cab { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--texto-2); padding-inline: var(--space-1); }
button.sh-calendario-data { padding: 0; border: 0; background: none; font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; color: var(--texto-2); text-align: left; cursor: pointer; text-decoration: none; }
button.sh-calendario-data:hover { color: var(--texto); text-decoration: underline; }
.sh-calendario--ano { grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr)); gap: var(--space-4); }
.sh-calendario-mes { display: grid; gap: var(--space-1); align-content: start; min-width: 0; }
.sh-calendario-mes-nome {
  justify-self: start; padding: var(--space-1) var(--space-2); margin-inline-start: calc(-1 * var(--space-2)); border: 0; border-radius: var(--raio-controle); background: none;
  font: inherit; font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--texto); cursor: pointer; transition: var(--sh-transicao);
}
.sh-calendario-mes-nome:hover { background: color-mix(in srgb, var(--texto) 8%, transparent); }
.sh-calendario-mini { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); row-gap: var(--space-1); text-align: center; }
.sh-calendario-mini-cab { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--texto-2); }
.sh-calendario-mini-dia {
  position: relative; display: grid; justify-items: center; align-content: start; gap: 1px; min-height: 2rem; padding-top: var(--space-1);
  border-radius: var(--raio-controle); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; color: var(--texto-2);
}
.sh-calendario-mini-dia[data-hoje="sim"] { background: var(--texto); color: var(--pagina); font-weight: var(--fw-semibold); }
.sh-calendario-mini-dia[data-ponto]::after, .sh-calendario-legenda > li::before { content: ""; width: .375rem; height: .375rem; border-radius: 50%; background: var(--texto-2); }
.sh-calendario-mini-dia[data-ponto="atrasado"]::after, .sh-calendario-legenda > li[data-ponto="atrasado"]::before { background: var(--acento-texto); }
.sh-calendario-mini-dia[data-ponto="black"]::after, .sh-calendario-legenda > li[data-ponto="black"]::before { background: var(--booot-ouro-600); }
.sh-calendario-mini-dia[data-ponto="evento"]::after, .sh-calendario-legenda > li[data-ponto="evento"]::before { background: var(--info-texto); }
.sh-calendario-mini-dia[data-hoje="sim"][data-ponto]::after { background: var(--pagina); }
.sh-calendario-legenda { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-block-start: var(--space-3); font-size: var(--fs-sm); color: var(--texto-2); }
.sh-calendario-legenda > li { display: inline-flex; align-items: center; gap: var(--space-1); }
.sh-marcos + .sh-calendario--ano { margin-block-start: var(--space-4); }
@media (max-width: 900px) {
  .sh-calendario-cab, .sh-calendario-vazio { display: none; }
  .sh-calendario--ano { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
}

/* ═══ 20-KIT · o ⓘ que explica e o gráfico (revisão 3 · D1c · 05/10/2026) ═════════════════════════════════════════════════════════════════════════════════════════════════════
   O ⓘ é a POPOVER API do navegador (Baseline desde 27/01/2025, https://developer.mozilla.org/en-US/docs/Web/API/Popover_API): `button[popovertarget]` + `[popover]`; abrir e fechar (clique, Esc, clique fora) é dele.
   A posição de base NÃO depende de nada novo: o popover é um cartão centrado na janela (o desenho do próprio navegador, legível sozinho). CSS Anchor Positioning (web-features: NÃO é Baseline) só REFINA, dentro de `@supports`:
   o balão passa a ficar abaixo do ⓘ. Só classe, só `var(--token)`: a CSP do /app é `style-src 'self'` (nada de `style=""`). */
.sh-explica { position: relative; display: inline-flex; align-items: center; vertical-align: middle; }
.sh-explica-btn {
  display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; border: 0; border-radius: var(--raio-pill);
  background: none; color: var(--texto-2); cursor: pointer; transition: var(--sh-transicao);
}
.sh-explica-btn:hover { color: var(--texto); }
.sh-explica-btn .sh-icone { width: 1rem; height: 1rem; }
.sh-explica-balao {
  position: fixed; inset: 0; margin: auto; height: fit-content; z-index: var(--z-dropdown);
  width: max-content; max-width: min(18rem, 80vw); padding: var(--space-2) var(--space-3);
  border: 1px solid var(--borda); border-radius: var(--raio-controle); background: var(--superficie); box-shadow: var(--sombra-flutuante);
  font-size: var(--fs-sm); line-height: var(--lh-ui); font-weight: var(--fw-regular); color: var(--texto); text-align: start; white-space: normal; text-wrap: balance;
}
@supports (anchor-name: --sh-explica) {
  .sh-explica-btn { anchor-name: --sh-explica; }
  .sh-explica-balao { position-anchor: --sh-explica; position-area: block-end; inset: auto; margin: var(--space-1) 0 0; justify-self: anchor-center; position-try-fallbacks: flip-block, flip-inline; }
}
/* no catálogo o popover aberto pousa no fluxo (como o `dialog`), senão flutuaria por cima das colunas na foto */
.sh-demo .sh-explica-balao:popover-open { position: static; inset: auto; margin: var(--space-2) 0 0; }

/* o GRÁFICO é o Charts.css 1.2.0 (MIT, https://github.com/ChartsCSS/charts.css, vendorizado em `vendor/charts-css/`): o dado é uma `table.charts-css` e o CSS dele a pinta. Aqui só se LIGAM as variáveis dele aos tokens. */
.sh-grafico { display: grid; gap: var(--space-2); min-width: 0; margin: 0; }
.sh-grafico .charts-css {
  --color-1: var(--acento); --color-2: var(--info-texto); --color-3: var(--sucesso-texto);
  --labels-size: 5rem; --heading-size: var(--fs-md); --data-spacing-1: var(--space-1);
  font-size: var(--fs-sm); color: var(--texto); width: 100%;
}
.sh-grafico .charts-css.column { height: 10rem; }
.sh-grafico .charts-css.bar { --aspect-ratio: auto; min-height: 6rem; }
.sh-grafico .charts-css caption { font-weight: var(--fw-semibold); color: var(--texto-2); }
.sh-grafico .charts-css .data { font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold); }
/* G9 · O FUNIL É UMA FORMA (gramática v1, 06/10 · o dono: "nem parece um funil"): barras CENTRADAS que ESTREITAM para baixo, cada uma com a largura da etapa sobre a maior (`--size`, 0 a 1, posta por CSSOM: a CSP é `style-src 'self'`).
   Por baixo é uma `<table>` de verdade (caption · th scope · o valor em texto visível ao lado da barra), uma só cor (`--serie-1`), sem Charts.css e sem gradiente. */
.sh-grafico[data-tipo="funil"] { aspect-ratio: auto; }
.sh-funil-forma { display: grid; gap: var(--space-2); width: 100%; margin: 0; border-collapse: separate; border-spacing: 0; font-size: var(--fs-sm); color: var(--texto); }
.sh-funil-forma caption { display: block; margin-bottom: var(--space-2); text-align: left; font-weight: var(--fw-semibold); color: var(--texto-2); }
.sh-funil-forma tbody { display: grid; gap: var(--space-2); }
.sh-funil-forma tr { display: grid; grid-template-columns: minmax(5rem, 9rem) minmax(0, 1fr) auto; align-items: center; column-gap: var(--space-3); }
.sh-funil-forma th { text-align: left; font-weight: var(--fw-regular); color: var(--texto-2); }
.sh-funil-forma td { display: contents; }
/* O TRILHO (fundo da barra) existe em TODA etapa, também com 0, e o número mora sempre na 3ª coluna, fora da barra: a mesma receita do `.sh-barra` (§11). Atrair e Acelerar leem ESTE trilho (06/10, verificador). */
.sh-funil-forma tr::before { content: ""; grid-column: 2; grid-row: 1; height: var(--space-5); border-radius: var(--raio-controle); background: color-mix(in srgb, var(--texto) 10%, transparent); }
.sh-funil-forma th { grid-column: 1; grid-row: 1; }
.sh-funil-barra { grid-column: 2; grid-row: 1; justify-self: center; width: calc(var(--size, 0) * 100%); min-width: var(--space-2); height: var(--space-5); border-radius: var(--raio-controle); background: var(--serie-1); }
.sh-funil-forma .data { grid-column: 3; grid-row: 1; justify-self: end; font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold); text-align: right; }
/* A CURVA (`App.grafico` tipo "area" · 07/10 · o gráfico de área do Relatórios do CRM): é o tipo `area` do Charts.css 1.2.0 que a casa já vendorizou (a mesma folha das barras), ligado aos tokens aqui. Preenchimento de 30% da série, 3 eixos secundários, eixo X em HTML de 11 px.
   Sem a linha de 2 px do CRM (o Charts.css não a desenha no tipo `area`): declarado em app.js (`areaArv`). */
.sh-grafico[data-tipo="area"] { aspect-ratio: auto; }
.sh-grafico .charts-css.area {
  --color: color-mix(in srgb, var(--serie-1) 30%, transparent);
  --labels-size: 0; --primary-axis-width: 1px; --primary-axis-color: var(--borda-forte);
  --secondary-axes-width: 1px; --secondary-axes-color: var(--borda);
  height: 9rem; width: 100%;
}
.sh-grafico .charts-css.area tbody { aspect-ratio: auto; height: 100%; }   /* a altura é a da tabela (9rem), não a proporção 21/9 do Charts.css */
.sh-area-plano { position: relative; }
.sh-area-max { position: absolute; top: 0; left: 0; padding-inline: var(--space-xs); font-size: var(--fs-meta); font-variant-numeric: tabular-nums; color: var(--texto-2); background: var(--superficie); border-radius: var(--raio-controle); }
.sh-area-eixo { display: flex; justify-content: space-between; margin: 0; padding: 0; list-style: none; font-size: var(--fs-meta); font-variant-numeric: tabular-nums; color: var(--texto-2); }
.sh-esqueleto--grafico { height: 8rem; width: 100%; }
/* G5 · o ícone no cabeçalho da seção: a pilha vira 2 colunas (ícone | título e apoio) */
.sh-secao-cabeca > .sh-stack:has(> .sh-card-ico) { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-3); align-items: center; }
.sh-secao-cabeca > .sh-stack:has(> .sh-card-ico) > :not(.sh-card-ico) { grid-column: 2; }
.sh-secao-cabeca > .sh-stack > .sh-card-ico { grid-row: 1; grid-column: 1; }
/* o ícone da linha e do número: o mesmo encaixe, colado ao texto */
.sh-linha > .sh-card-ico { align-self: center; }
.sh-kpi-cabeca-ico { display: flex; align-items: center; gap: var(--space-2); }
