/*
 * TermoVision v3 — componentes do design system.
 *
 * O HTML e os nomes de classe de cada componente estão em
 * docs/v3/DESIGN_SYSTEM.md §3; o JS que gera esse HTML mora em js/ui/.
 *
 * ESPECIFICIDADE — a escolha é a camada de cascata, não um prefixo `.v3`:
 *   @layer tokens, componentes, shell, secoes;
 * Entre camadas vence a declarada DEPOIS, qualquer que seja a especificidade:
 * uma regra de seção ganha de um componente daqui sem precisar de seletor
 * mais pesado. Um prefixo `.v3` só somaria especificidade.
 * Consequência que vale para toda página da v3: CSS FORA de camada vence
 * qualquer camada. Folha de página entra em `@layer secoes` (ou `shell`).
 *
 * Só classes de componente, mais o mínimo de base (box-sizing, corpo da
 * página, foco, [hidden], kbd, barras de rolagem e a faixa `input[type=range]`).
 *
 * Sem cor solta, sem espaço/fonte/raio/z literal: tudo via tokens.css.
 * `!important` só em [hidden] e no bloco prefers-reduced-motion.
 */
@layer componentes {

  /* ------------------------------------------------------------------ base */

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

  /* Sem margem nem recuo de fábrica (p, ul, button, fieldset…): cada componente
     declara os seus, e `:where` (especificidade 0) deixa qualquer regra ganhar.
     Fica de fora o que o Leaflet estiliza — classes leaflet-* e o <p> do balão —,
     porque a folha dele mora numa camada de baixo e perderia para esta. */
  :where(*:not([class*="leaflet-"], .leaflet-popup-content p)) { margin: 0; padding: 0; }

  [hidden] { display: none !important; }

  body {
    margin: 0;
    background: var(--sup-0);
    color: var(--texto-1);
    font-family: var(--fonte);
    font-size: var(--t-md);
    line-height: var(--lh-md);
    font-weight: var(--peso-normal);
    -webkit-font-smoothing: antialiased;
  }

  :focus-visible {
    outline: 2px solid var(--foco);
    outline-offset: 2px;
  }

  kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--e-5);
    padding: 0 var(--e-1);
    font-family: var(--fonte-mono);
    font-size: var(--t-xs);
    line-height: var(--lh-xs);
    font-weight: var(--peso-medio);
    color: var(--texto-2);
    background: var(--sup-2);
    border: 1px solid var(--borda-2);
    border-radius: var(--r-sm);
    white-space: nowrap;
  }

  /* Barras de rolagem discretas, no tom do tema (Chromium). O polegar é uma
     pílula de 6 px dentro da faixa de 10 (borda de 2 px na cor do painel). */
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: var(--borda-1);
    border: 2px solid var(--sup-1);
    border-radius: var(--r-pill);
  }
  ::-webkit-scrollbar-thumb:hover { background: var(--borda-2); }
  /* Sem esta regra o Chromium pinta de BRANCO o canto entre as duas barras
     (Usinas › Lista a 1229×584: 10×10 px rgb(255,255,255), L4, Lote 4). */
  ::-webkit-scrollbar-corner { background: transparent; }

  /* Faixa (input range): trilho fino e polegar de acento. A altura vem do
     min-height que cada seção dá ao controle (L10: alvo de 28 px); o trilho é
     uma linha de 4 px no meio dessa caixa, em --borda-controle (§1.3: só ela
     delimita controle). Em --borda-1 sobre o modal (--sup-3) ele media
     1,04:1, e as seções o apagavam com `background: transparent`: Velocidade
     e Núcleos eram só o polegar solto (Lote 4). */
  input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    color: inherit;                     /* o cinza do navegador não é token (L4) */
    width: 100%;
    border-radius: var(--r-sm);
    background: linear-gradient(var(--borda-controle), var(--borda-controle)) center / 100% 4px no-repeat;
    cursor: pointer;
  }
  input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 13px;
    height: 13px;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--acento);
    transition: transform var(--dur-rapido) var(--ease-padrao);
  }
  input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.2); }
  input[type="range"]::-moz-range-thumb {
    width: 13px;
    height: 13px;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--acento);
  }

  /* ----------------------------------------------------- 3.1 Botão .bt */

  .bt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    flex: none;
    min-width: 0;
    margin: 0;
    border: 1px solid transparent;
    border-radius: var(--r-md);
    font-family: inherit;
    font-weight: var(--peso-medio);
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    transition:
      background-color var(--dur-rapido) var(--ease-padrao),
      color var(--dur-rapido) var(--ease-padrao),
      border-color var(--dur-rapido) var(--ease-padrao);
  }
  .bt-sm {
    min-height: var(--alt-sm);
    padding: var(--e-1) var(--e-3);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
  }
  .bt-md {
    min-height: var(--alt-md);
    padding: var(--e-1) var(--e-4);
    font-size: var(--t-md);
    line-height: var(--lh-md);
  }
  /* Sem tamanho declarado, o botão é md: nunca cai na fonte de 13,33 px do navegador. */
  .bt:not(.bt-sm):not(.bt-md) {
    min-height: var(--alt-md);
    padding: var(--e-1) var(--e-4);
    font-size: var(--t-md);
    line-height: var(--lh-md);
  }

  .bt-primario { background: var(--acento); color: var(--texto-sobre-acento); }
  .bt-primario:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--acento-hover); }

  .bt-secundario { background: var(--sup-2); color: var(--texto-1); border-color: var(--borda-controle); }
  .bt-secundario:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--sup-3); }

  .bt-fantasma { background: transparent; color: var(--texto-2); }
  .bt-fantasma:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--sup-2); color: var(--texto-1); }

  .bt-perigo { background: var(--perigo-fundo); color: var(--texto-sobre-perigo); }
  .bt-perigo:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--perigo-fundo-hover); }

  .bt:disabled, .bt[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

  /* Ocupado: spinner ANTES do texto, e o texto não muda (M33). */
  .bt[aria-busy="true"] { cursor: progress; }
  .bt[aria-busy="true"]::before {
    content: "";
    flex: none;
    width: 12px;
    height: 12px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: var(--r-pill);
    animation: tv-girar calc(var(--dur-lento) * 2) linear infinite;
  }

  .bt-ic { display: inline-flex; flex: none; }
  .bt-ic svg { width: 16px; height: 16px; }
  .bt-md .bt-ic svg, .bt:not(.bt-sm) .bt-ic svg { width: 20px; height: 20px; }

  /* --------------------------------------- 3.2 Botão-ícone .bt-icone */

  .bt-icone {
    display: inline-flex;          /* a L2 exige flex + center/center */
    align-items: center;
    justify-content: center;
    flex: none;
    margin: 0;
    padding: 0;
    line-height: 1;
    min-width: var(--alt-md);
    min-height: var(--alt-md);
    border: 1px solid transparent;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--texto-2);
    font-family: inherit;
    font-size: var(--t-md);
    cursor: pointer;
    transition:
      background-color var(--dur-rapido) var(--ease-padrao),
      color var(--dur-rapido) var(--ease-padrao),
      box-shadow var(--dur-rapido) var(--ease-padrao);
  }
  .bt-icone-sm { min-width: var(--alt-sm); min-height: var(--alt-sm); }
  .bt-icone-md { min-width: var(--alt-md); min-height: var(--alt-md); }
  .bt-icone-lg { min-width: var(--alt-lg); min-height: var(--alt-lg); }
  .bt-icone svg { width: 20px; height: 20px; flex: none; pointer-events: none; }
  .bt-icone-sm svg { width: 16px; height: 16px; }

  .bt-icone:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--sup-2); color: var(--texto-1); }
  .bt-icone:disabled, .bt-icone[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

  /* Toggle genérico (olho, cadeado…): ligado = acento sobre fundo fraco. */
  .bt-icone[aria-pressed="true"] { background: var(--acento-fraco); color: var(--acento); }

  /* D2 — ferramenta ativa: fundo preenchido. */
  .bt-icone[data-ferramenta][aria-pressed="true"],
  .bt-icone[data-ferramenta][aria-pressed="true"]:hover {
    background: var(--acento);
    color: var(--texto-sobre-acento);
    box-shadow: none;
  }
  /* D2 — painel aberto: faixa de 3 px à esquerda + fundo sutil. */
  .bt-icone[data-painel][aria-pressed="true"],
  .bt-icone[data-painel][aria-pressed="true"]:hover {
    background: var(--sup-3);
    color: var(--texto-1);
    box-shadow: inset 3px 0 0 var(--acento);
  }

  /* ------------------------------------------------------- 3.3 Modal */

  .modal-fundo {
    position: fixed;
    inset: 0;
    background: var(--fundo-modal);
    backdrop-filter: blur(2px);
    z-index: calc(var(--z-fundo-modal) + 2 * var(--n, 0));
    animation: tv-surgir var(--dur-medio) var(--ease-entrada);
  }

  .modal {
    position: fixed;
    inset: 0;
    margin: auto;                       /* centra sem transform: texto nítido */
    width: min(var(--modal-w, var(--modal-md)), calc(100vw - 2 * var(--e-5)));
    height: fit-content;
    max-height: calc(100vh - 2 * var(--e-5));
    overflow: auto;
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--sup-3);
    color: var(--texto-1);
    border: 1px solid var(--borda-2);
    border-radius: var(--r-lg);
    box-shadow: var(--sombra-2);
    z-index: calc(var(--z-modal) + 2 * var(--n, 0));
    animation: tv-modal-entrar var(--dur-medio) var(--ease-entrada);
  }
  .modal:focus { outline: none; }
  .modal-sm { --modal-w: var(--modal-sm); }
  .modal-md { --modal-w: var(--modal-md); }
  .modal-lg { --modal-w: var(--modal-lg); }
  .modal-full { width: 96vw; height: 94vh; max-height: 94vh; }

  .modal-cab {
    display: flex;
    align-items: center;
    gap: var(--e-3);
    min-height: 56px;
    padding: var(--e-3) var(--e-3) var(--e-3) var(--e-5);
    border-bottom: 1px solid var(--borda-1);
    flex: none;
  }
  .modal-titulo {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: var(--t-lg);
    line-height: var(--lh-lg);
    font-weight: var(--peso-forte);
    overflow-wrap: anywhere;
  }
  .modal-corpo {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: var(--e-3);
    min-height: 0;
    min-width: 0;
    max-height: calc(100vh - 160px);
    overflow: auto;
    padding: var(--e-5);
    color: var(--texto-1);
  }
  .modal-full .modal-corpo { max-height: none; }
  .modal-corpo > p { margin: 0 0 var(--e-3); color: var(--texto-2); }
  .modal-corpo > p:last-child { margin-bottom: 0; }
  .modal-rodape {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--e-2);
    padding: var(--e-3) var(--e-5);
    border-top: 1px solid var(--borda-1);
    flex: none;
  }

  /* Confirmação (alertdialog sm): o texto e os detalhes. */
  .modal-corpo details { margin-top: var(--e-3); color: var(--texto-2); }
  .modal-corpo summary {
    display: flex;
    align-items: center;
    min-height: var(--alt-sm);
    cursor: pointer;
    color: var(--texto-2);
    font-size: var(--t-sm);
  }
  .modal-corpo pre {
    margin: var(--e-2) 0 0;
    padding: var(--e-2) var(--e-3);
    max-height: 200px;
    overflow: auto;
    background: var(--sup-1);
    border-radius: var(--r-md);
    font-family: var(--fonte-mono);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }

  /* -------------------------------------------------------- 3.5 Toast */

  .toasts {
    position: fixed;
    right: var(--e-4);
    /* --toast-base: toast.js sobe a pilha acima do rodapé do modal do topo. */
    bottom: calc(var(--toast-base, var(--status-h)) + var(--e-4));
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--e-2);
    width: min(var(--toast-w), calc(100vw - 2 * var(--e-4)));
    pointer-events: none;               /* só o toast recebe clique, nunca o vão */
  }
  .toasts:empty { display: none; }
  .toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: var(--e-3);
    min-width: 0;
    padding: var(--e-3);
    color: var(--texto-1);
    background: var(--info-fundo);
    border: 1px solid var(--borda-2);
    border-radius: var(--r-lg);
    box-shadow: var(--sombra-2);
    animation: tv-toast-entrar var(--dur-medio) var(--ease-entrada);
  }
  .toast-ic { display: inline-flex; flex: none; padding: var(--e-1) 0; color: var(--info); }
  .toast-ic svg { width: 20px; height: 20px; }
  .toast-txt { flex: 1 1 auto; min-width: 0; padding: var(--e-1) 0; overflow-wrap: anywhere; }
  .toast-txt strong { display: block; font-weight: var(--peso-forte); }
  .toast-txt p { margin: 0; color: var(--texto-2); }
  .toast .bt, .toast .bt-icone { flex: none; }
  .toast-info    { background: var(--info-fundo); }
  .toast-ok      { background: var(--ok-fundo); }
  .toast-atencao { background: var(--aviso-fundo); }
  .toast-erro    { background: var(--erro-fundo); }
  .toast-ok .toast-ic      { color: var(--ok); }
  .toast-atencao .toast-ic { color: var(--aviso); }
  .toast-erro .toast-ic    { color: var(--erro); }
  .toast.saindo { animation: tv-sumir var(--dur-medio) var(--ease-saida) forwards; }

  /* ------------------------------------ 3.6 Popover, Menu, Menu de contexto */

  .popover {
    position: fixed;
    z-index: var(--z-popover);
    min-width: 160px;
    max-width: min(360px, calc(100vw - 2 * var(--e-2)));
    max-height: calc(100vh - 2 * var(--e-2));
    overflow: auto;
    padding: var(--e-3);
    color: var(--texto-1);
    background: var(--sup-3);
    border: 1px solid var(--borda-2);
    border-radius: var(--r-lg);
    box-shadow: var(--sombra-1);
    animation: tv-surgir var(--dur-rapido) var(--ease-entrada);
  }
  .popover:focus { outline: none; }
  .popover-titulo {
    margin: 0 0 var(--e-1);
    font-size: var(--t-md);
    line-height: var(--lh-md);
    font-weight: var(--peso-forte);
  }
  .popover p { margin: 0 0 var(--e-2); color: var(--texto-2); }
  .popover p:last-child { margin-bottom: 0; }

  .menu { padding: var(--e-1); min-width: 200px; }
  .menu-item {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    width: 100%;
    min-height: var(--alt-md);
    margin: 0;
    padding: var(--e-1) var(--e-2);
    border: 0;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--texto-1);
    font-family: inherit;
    font-size: var(--t-md);
    line-height: var(--lh-md);
    text-align: left;
    text-decoration: none;            /* <a class="menu-item"> (conta, menu ⚙) */
    cursor: pointer;
  }
  .menu-item:hover, .menu-item:focus-visible { background: var(--sup-2); }
  .menu-item:focus-visible { outline-offset: -2px; }
  .menu-item[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
  .menu-item.perigo { color: var(--erro); }
  .menu-ic { display: inline-flex; flex: none; width: 16px; color: var(--texto-2); }
  .menu-ic svg { width: 16px; height: 16px; }
  .menu-item.perigo .menu-ic { color: var(--erro); }
  .menu-rotulo { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .menu-item kbd { margin-left: auto; }
  .menu-sep { height: 1px; margin: var(--e-1) 0; background: var(--borda-1); border: 0; }

  /* --------------------------------------------------------- 3.7 Tooltip */

  .tooltip {
    position: fixed;
    z-index: var(--z-tooltip);
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    max-width: 320px;
    padding: var(--e-1) var(--e-2);
    color: var(--texto-1);
    background: var(--sup-3);
    border: 1px solid var(--borda-2);
    border-radius: var(--r-md);
    box-shadow: var(--sombra-1);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
    pointer-events: none;
    overflow-wrap: anywhere;
    animation: tv-surgir var(--dur-rapido) var(--ease-entrada);
  }

  /* ----------------------------------------------------------- 3.8 Ícones */

  .ic { flex: none; display: inline-block; vertical-align: middle; }

  /* ----------------------------------------------------------- 3.9 Abas */

  .abas {
    display: flex;
    align-items: stretch;
    gap: var(--e-1);
    min-width: 0;
    overflow-x: auto;
    border-bottom: 1px solid var(--borda-1);
  }
  .abas [role="tab"] {
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    flex: none;
    min-height: 36px;
    margin: 0;
    padding: var(--e-2) var(--e-3);
    border: 0;
    border-radius: var(--r-md) var(--r-md) 0 0;
    background: transparent;
    color: var(--texto-2);
    font-family: inherit;
    font-size: var(--t-md);
    line-height: var(--lh-md);
    font-weight: var(--peso-medio);
    cursor: pointer;
    transition: color var(--dur-rapido) var(--ease-padrao), box-shadow var(--dur-rapido) var(--ease-padrao);
  }
  .abas [role="tab"]:hover { color: var(--texto-1); background: var(--sup-2); }
  .abas [role="tab"][aria-selected="true"] {
    color: var(--texto-1);
    box-shadow: inset 0 -2px 0 var(--acento);
  }
  .abas [role="tab"]:focus-visible { outline-offset: -2px; }

  /* ------------------------------------------------------ 3.10 Segmentado */

  .seg {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    min-width: 0;
    padding: 0;
    border: 1px solid var(--borda-controle);
    border-radius: var(--r-md);
    background: var(--sup-1);
  }
  .seg-op {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    flex: 0 1 auto;
    min-width: 0;
    min-height: var(--alt-md);
    margin: 0;
    padding: var(--e-1) var(--e-3);
    border: 1px solid transparent;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--texto-2);
    font-family: inherit;
    font-size: var(--t-md);
    line-height: var(--lh-md);
    font-weight: var(--peso-medio);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--dur-rapido) var(--ease-padrao), color var(--dur-rapido) var(--ease-padrao);
  }
  .seg-op:hover { color: var(--texto-1); }
  .seg-op[aria-checked="true"], .seg-op[aria-pressed="true"] {
    background: var(--sup-3);
    color: var(--texto-1);
    border-color: var(--borda-controle);
  }
  .seg-op:disabled, .seg-op[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
  .seg-op kbd { min-width: var(--e-4); }
  .seg-op:focus-visible { outline-offset: -2px; }

  /* ---------------------------------------------------- 3.11 Chip e Selo */

  .chip {
    display: inline-flex;
    align-items: center;
    gap: var(--e-1);
    flex: none;
    min-width: 0;
    max-width: 100%;
    min-height: 22px;
    margin: 0;
    padding: 0 var(--e-2);
    border: 1px solid var(--borda-2);
    border-radius: var(--r-pill);
    background: var(--sup-2);
    color: var(--texto-1);
    font-family: inherit;
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
    font-weight: var(--peso-medio);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    user-select: none;
  }
  button.chip {
    min-height: var(--alt-sm);
    padding: var(--e-1) var(--e-3);
    border-color: var(--borda-controle);
    cursor: pointer;
  }
  button.chip:hover { background: var(--sup-3); }
  button.chip[aria-pressed="true"] { background: var(--acento-fraco); border-color: var(--acento); }

  .chip-ponto {
    display: inline-block;
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: var(--r-pill);
    background: var(--texto-3);
  }
  .chip-ok .chip-ponto      { background: var(--ok); }
  .chip-info .chip-ponto    { background: var(--info); }
  .chip-atencao .chip-ponto { background: var(--aviso); }
  .chip-erro .chip-ponto    { background: var(--erro); }
  .chip-neutro .chip-ponto  { background: var(--texto-3); }

  .chip-modalidade[data-mod="rgb"]     { border-color: var(--mod-rgb); }
  .chip-modalidade[data-mod="termico"] { border-color: var(--mod-termico); }

  /* Origem: o ponto tem a MESMA cor do traço no mapa (matriz_mapa.js:20-26). */
  .chip-origem::before, .chip[data-coa]::before {
    content: "";
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: var(--r-pill);
    background: var(--texto-3);
  }
  .chip-origem[data-origem="manual"]::before { background: var(--mapa-grade-manual); }
  .chip-origem[data-origem="rede"]::before   { background: var(--mapa-grade-ia); }
  .chip-origem[data-origem="regra"]::before  { background: var(--mapa-grade-regra); }
  .chip-origem[data-origem="rejeitada"]::before { background: var(--mapa-rejeitada); }
  .chip-origem[data-origem="correcao"]::before { background: var(--mapa-correcao); }
  .chip-origem[data-origem="projeto"]::before { background: var(--mapa-mesa-projeto); }
  .chip[data-coa="1"]::before { background: var(--coa-1); }
  .chip[data-coa="2"]::before { background: var(--coa-2); }
  .chip[data-coa="3"]::before { background: var(--coa-3); }

  .selo {
    display: inline-flex;
    align-items: center;
    flex: none;
    padding: 0 var(--e-1);
    border: 1px solid var(--borda-controle);
    border-radius: var(--r-sm);
    color: var(--texto-2);
    font-size: var(--t-xs);
    line-height: var(--lh-xs);
    font-weight: var(--peso-forte);
    white-space: nowrap;
  }

  /* ------------------------------------------------- 3.12 Campo e Select */

  .campo { display: flex; flex-direction: column; gap: var(--e-1); min-width: 0; }
  .campo-rotulo {
    color: var(--texto-2);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
    font-weight: var(--peso-medio);
  }
  .campo-ctrl {
    display: block;
    width: 100%;
    min-width: 0;
    min-height: var(--alt-md);       /* nunca height (F2) */
    margin: 0;
    padding: var(--e-1) var(--e-3);
    color: var(--texto-1);
    background: var(--sup-2);
    border: 1px solid var(--borda-controle);
    border-radius: var(--r-md);
    font-family: inherit;
    font-size: var(--t-md);
    line-height: var(--lh-md);
    transition: border-color var(--dur-rapido) var(--ease-padrao);
  }
  .campo-ctrl::placeholder { color: var(--texto-3); }
  .campo-ctrl:hover:not(:disabled) { border-color: var(--texto-3); }
  .campo-ctrl:focus-visible { outline-offset: 0; border-color: var(--acento); }
  .campo-ctrl:disabled { opacity: .45; cursor: not-allowed; }
  .campo-ctrl[aria-invalid="true"] { border-color: var(--erro); }
  textarea.campo-ctrl { min-height: 80px; resize: vertical; }
  .campo-ajuda {
    margin: 0;
    color: var(--texto-3);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
  }
  .campo-erro {
    display: flex;
    align-items: center;
    gap: var(--e-1);
    margin: 0;
    color: var(--erro);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
  }
  .campo-erro svg { width: 16px; height: 16px; flex: none; }

  /* Checkbox e rádio: quem tem o alvo de 28 px é o <label> que os envolve (L10). */
  .campo-check {
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    min-height: var(--alt-sm);
    min-width: var(--alt-sm);        /* checkbox sem texto (seleção em tabela) */
    justify-content: flex-start;
    color: var(--texto-1);
    font-size: var(--t-md);
    line-height: var(--lh-md);
    cursor: pointer;
  }
  .campo-check input { margin: 0; accent-color: var(--acento); width: 16px; height: 16px; flex: none; }

  /* --------------------------------------------------------- 3.13 Tabela */

  .tabela-rolagem {
    min-width: 0;
    overflow: auto;
    border: 1px solid var(--borda-1);
    border-radius: var(--r-md);
    background: var(--sup-1);
  }
  .tabela {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
    font-variant-numeric: tabular-nums;
  }
  .tabela th {
    position: sticky;
    top: 0;
    z-index: var(--z-local);
    padding: var(--e-2) var(--e-3);
    background: var(--sup-1);
    color: var(--texto-2);
    font-weight: var(--peso-forte);
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid var(--borda-2);
  }
  .tabela td {
    height: 36px;                     /* em célula de tabela, height age como mínimo */
    padding: var(--e-2) var(--e-3);
    color: var(--texto-1);
    vertical-align: middle;
    border-bottom: 1px solid var(--borda-1);
  }
  .tabela tbody tr:last-child td { border-bottom-color: transparent; }
  .tabela .num { text-align: right; white-space: nowrap; }
  .tabela tbody tr:hover td { background: var(--sup-2); }
  .tabela tbody tr[tabindex] { cursor: pointer; }
  .tabela tbody tr[tabindex]:focus-visible { outline-offset: -2px; }
  .tabela tbody tr[aria-selected="true"] td { background: var(--acento-fraco); }
  .tabela .campo-check { min-height: var(--alt-sm); justify-content: center; }
  .cel-titulo, .cel-sub {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
  }
  .cel-titulo { color: var(--texto-1); font-weight: var(--peso-medio); }
  .cel-sub { color: var(--texto-3); -webkit-line-clamp: 1; }

  /* ---------------------------------------------------- 3.14 Estado vazio */

  .vazio {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--e-3);
    padding: var(--e-6) var(--e-5);
    text-align: center;
    color: var(--texto-2);
    font-size: var(--t-sm);           /* texto solto no .vazio (sem <p>) */
  }
  .vazio-ic { display: inline-flex; color: var(--texto-3); }
  .vazio-ic svg { width: 32px; height: 32px; }
  .vazio p { margin: 0; max-width: 40ch; font-size: var(--t-md); line-height: var(--lh-md); }

  /* -------------------------------------------------------- 3.15 Skeleton */

  /* Os primeiros 300 ms ficam invisíveis: espera curta não pisca esqueleto (NN/g). */
  .esqueleto {
    display: flex;
    flex-direction: column;
    gap: var(--e-2);
    animation: tv-aparecer-atrasado 1ms linear 300ms both;
  }
  .esq-linha {
    height: var(--e-4);
    width: 100%;
    border-radius: var(--r-sm);
    background: var(--sup-2);
    animation: tv-pulsar calc(var(--dur-lento) * 3) var(--ease-padrao) infinite alternate;
  }
  .esq-linha.curta { width: 60%; }

  /* ------------------------------------------------------- 3.16 Progresso */

  .progresso {
    position: relative;
    height: 6px;
    min-width: 0;
    overflow: hidden;
    border-radius: var(--r-pill);
    background: var(--sup-3);
  }
  .progresso-barra {
    height: 100%;
    width: var(--p, 0%);
    border-radius: inherit;
    background: var(--acento);
    transition: width var(--dur-medio) var(--ease-padrao);
  }
  .progresso[data-estado="concluido"] .progresso-barra { background: var(--ok); }
  .progresso[data-estado="erro"] .progresso-barra { background: var(--erro); }
  .progresso:not([aria-valuenow]) .progresso-barra {
    width: 40%;
    animation: tv-deslizar calc(var(--dur-lento) * 4) var(--ease-padrao) infinite;
  }
  .progresso-txt {
    margin: var(--e-1) 0 0;
    color: var(--texto-2);
    font-size: var(--t-sm);
    line-height: var(--lh-sm);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
  }

  /* ------------------------------------------------------------ animações */

  @keyframes tv-girar { to { transform: rotate(360deg); } }
  @keyframes tv-surgir { from { opacity: 0; } }
  @keyframes tv-sumir { to { opacity: 0; transform: translateY(4px); } }
  /* Entrada de modal e toast SEM opacidade: um elemento com opacity 0 conta como
     invisível para checkVisibility(), e a régua (L6/L7) pularia o modal recém-aberto
     — numa aba em segundo plano a animação nem anda e ele ficaria "invisível".
     Sem scale também: a 98 % o botão de 28 px mede 27,4 e reprova a L10. */
  @keyframes tv-modal-entrar { from { transform: translateY(8px); } }
  @keyframes tv-toast-entrar { from { transform: translateY(8px); } }
  @keyframes tv-pulsar { to { opacity: .5; } }
  @keyframes tv-aparecer-atrasado { from { opacity: 0; } to { opacity: 1; } }
  @keyframes tv-deslizar {
    from { transform: translateX(-100%); }
    to { transform: translateX(250%); }
  }

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