/* ============================================================
   PEÇAS DO SISTEMA VISUAL ("peça de inventário")
   ============================================================
   NA LOJA desde 12/10/2026: cópia do app/pecas.css do formulario-spot
   (que é a cópia sem mudança do Guia da Staff, ../guiadastaff-spot), SEM o
   bloco final da NUVEM DE PIXEL: a loja não tem o céu do topo (pedido do
   dono). Pra trazer uma correção de lá, copie o arquivo de novo, tire a
   nuvem e refaça só este parágrafo. Ajuste de uma peça pra loja vai no
   styles/loja.css, que carrega depois e ganha no empate.
   Ordem na loja (layouts/layout.html):
       tokens.css → pecas.css → core.css → loja.css → Tailwind (CDN)
   O Tailwind do CDN injeta o CSS dele DEPOIS de tudo: um utilitário no HTML
   (rounded-full, bg-primary...) ganha da peça. Por isso o HTML convertido
   não mistura peça com utilitário de cor, borda ou raio.
   A fonte pixel (Silkscreen) NÃO é usada na loja (pedido do dono): o
   .ln-eyebrow e o .ln-pixel-text são redefinidos no loja.css com a fonte
   normal.

   (O texto abaixo é o do formulário, como veio.)
   NO FORMULÁRIO desde 11/10/2026: cópia SEM MUDANÇA do app/pecas.css do
   Guia da Staff (../guiadastaff-spot).
   Diferença de uso: aqui não existem os componentes de components/ui do
   guia (<Button>, <Badge>...). As telas são HTML fixo com a lógica em JS
   puro, então o HTML leva direto as MESMAS classes que o <Button> do guia
   desenharia (ex.: "ui-btn-reset ui-btn ln-btn ui-btn-lg").

   Trazidas do gestaostaff-spot em 24/09/2026 (lá elas moram no globals.css,
   dentro de `@layer components` do Tailwind). Todas leem só de
   app/tokens.css. A receita das 4 camadas está explicada no topo dele.

   AQUI É CSS PURO, SEM TAILWIND E SEM `@layer` — de propósito:
   - Medido em 24/09/2026: o Tailwind 3 do gestaostaff não gera `@layer`
     nativo nenhum; ele só coloca as peças mais cedo no arquivo, e quem
     ajusta uma peça ganha por vir DEPOIS. Aqui a ordem é a mesma, pelos
     imports do app/layout.js:
         tokens.css → pecas.css → globals.css → CSS da tela
     Pra ajustar uma peça numa tela, escreva no CSS da tela com a mesma
     especificidade: ele carrega depois e ganha.
   - NÃO embrulhe estas peças em `@layer`. Com camada nativa, TODA regra
     solta das folhas antigas (são ~13 mil linhas) ganharia de TODAS as
     peças, até com especificidade menor — e parece bug de especificidade.
   - Sem Tailwind não existe poda: toda peça daqui vai pro site. Mesmo
     assim, escreva o nome INTEIRO da peça no .js (nada de `ln-${x}`): é o
     que deixa achar quem usa o quê com uma busca.

   REGRAS DE USO que seguram o sistema:
   - "ligado" (aba ativa, chip marcado, switch ligado) = fundo da marca + o
     relevo INVERTIDO (--ln-brand-bevel-*). A mesma assinatura em tudo.
   - hover de recipiente = a borda clareia (--ln-selection). Nada se mexe.
   - botão pressionado = o degrau de baixo cai de 3px pra 1px. Ele afunda.
   - a marca nunca é cor de texto sobre o escuro: texto na cor dela usa
     --ln-brand-text.
   - CSS novo usa token `--ln-*`, nunca hex escrito na mão.
   - fonte pixel (Silkscreen) só em rótulo curto e maiúsculo, SEMPRE em px
     inteiro (em rem fracionário ela borra) e `letter-spacing: 0`. A tinta
     dela fica meio pixel ABAIXO do centro da linha e a do ícone do Font
     Awesome meio pixel ACIMA: alinhar os dois pede `position: relative;
     top: 1px` no ícone. Rótulo = 13px.
   - raio CONCÊNTRICO: peça dentro de um poço/trilho usa
     `raio do poço − o quanto ela está pra dentro`. Com o raio cheio o canto
     dela corta mais que o do poço e sobra uma cunha escura em cada quina
     (ver .ln-pill-bar > *).
   - recipiente com área de ROLAGEM dentro: a moldura não pode ser
     `outline` — use .ln-moldura-cima (no fim deste arquivo).
   - `transform: translateZ(0)` só em quem anima: num elemento encostado na
     borda, com largura fracionária, ele desenha 1px diferente em escala
     125% do Windows.
   ============================================================ */

/* ── BASE DOS COMPONENTES ──
   Devolve o que um reset faria nos <button>: sem aparência nativa do
   sistema, fonte do guia em vez da fonte do navegador, sem margem, cursor
   de clique. Usada por components/ui/button.js e badge.js.

   As três linhas de `border` são as mais importantes: a borda nativa de um
   <button> é `2px outset ButtonBorder` — grossa, clara e com relevo 3D.
   Zerando a espessura e fixando `solid`, a borda só aparece onde a peça
   pede.

   Fundo transparente e cor herdada: no gestaostaff quem faz isso é o
   preflight do Tailwind, e aqui não tem Tailwind — um <button> só com esta
   classe (sem peça) nascia com o cinza-claro nativo. As peças definem fundo
   e cor DEPOIS, então não mudam. */
.ui-btn-reset {
  appearance: none;
  -webkit-appearance: none;
  font-family: inherit;
  margin: 0;
  cursor: pointer;
  background-color: transparent;
  color: inherit;
  background-image: none;
  text-decoration: none;
  border-width: 0;
  border-style: solid;
  border-color: var(--ln-edge-1);
}
.ui-btn-reset:disabled { cursor: default; }

/* ── DIÁLOGO (components/ui/dialog.js e confirm-dialog.js) ── */
.ui-dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 10050;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  /* Escurece, não desfoca: o sistema visual não usa backdrop-filter. */
  background: var(--ln-overlay);
  opacity: 0;
  /* O fundo sai rápido: ele escurece logo, pra o clique parecer atendido
     na hora. Quem faz o movimento "leve" é o cartão, abaixo. */
  transition: opacity 240ms cubic-bezier(0.33, 1, 0.68, 1);
}
/* ENTRADA por @keyframes, e não por transição: uma transição só roda se o
   navegador tiver PINTADO o estado inicial antes da classe mudar, e isso
   depende de quando o React solta o efeito (às vezes animava, às vezes
   não). Uma animação roda mesmo num elemento que acabou de entrar no DOM.
   A SAÍDA continua transição — lá o elemento já está na tela há tempo. */
.ui-dialog-overlay.is-open {
  opacity: 1;
  animation: uiDialogFundoEntra 240ms cubic-bezier(0.33, 1, 0.68, 1);
}
/* Só `from`: o `to` implícito é o próprio estilo do elemento, então o fim
   da animação e o estado parado coincidem — sem solavanco no final. */
@keyframes uiDialogFundoEntra { from { opacity: 0; } }
/* SAÍDA mais curta que a entrada (sair devagar dá sensação de travado), e
   `pointer-events: none` impede clicar num diálogo que já está sumindo. */
.ui-dialog-overlay.is-closing {
  opacity: 0;
  pointer-events: none;
  transition: opacity 160ms cubic-bezier(0.4, 0, 1, 1);
}

/* O cartão é o PAINEL do sistema visual: borda de 2px, moldura interna a
   35% e a sombra chapada de 4px embaixo (sem desfoque — a peça parece
   empilhada sobre a tela, não flutuando). Se um dia o corpo do diálogo
   ganhar área de rolagem, acrescente .ln-moldura-cima na caixa. */
.ui-dialog {
  width: 100%;
  max-width: 380px;
  overflow: hidden;
  border-radius: var(--ln-radius-card);
  background: var(--ln-surface-1);
  border: 2px solid var(--ln-outline);
  outline: 2px solid var(--ln-frame-panel);
  outline-offset: -4px;
  box-shadow: 0 4px 0 0 var(--ln-shadow-flat);
  transform: translateY(8px) scale(0.99);
  opacity: 0;
  /* A curva espalha o movimento pelo percurso todo (17% / 50% / 85% nos
     marcos de 25/50/75% do tempo) — um ease-out expo dá um pulo e depois
     "rasteja" invisível. A opacidade aparece logo (ease-out) e o deslize
     continua por baixo. */
  transition: transform 320ms cubic-bezier(0.4, 0, 0.2, 1),
              opacity 240ms cubic-bezier(0.33, 1, 0.68, 1);
}
/* `none`, e não `translateY(0) scale(1)`: mesma posição, mas sem manter o
   cartão numa camada de composição própria enquanto ele fica aberto (o
   que fazia o hover de um botão "piscar" o cartão inteiro com GPU). */
.ui-dialog-overlay.is-open .ui-dialog {
  transform: none;
  opacity: 1;
  animation: uiDialogEntra 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes uiDialogEntra {
  from { transform: translateY(8px) scale(0.99); opacity: 0; }
}
.ui-dialog-overlay.is-closing .ui-dialog {
  transform: translateY(6px) scale(0.99);
  opacity: 0;
  transition: transform 180ms cubic-bezier(0.4, 0, 1, 1),
              opacity 150ms cubic-bezier(0.4, 0, 1, 1);
}
/* Quem pediu menos movimento no sistema recebe só o fade. */
@media (prefers-reduced-motion: reduce) {
  .ui-dialog-overlay,
  .ui-dialog,
  .ui-dialog-overlay.is-closing,
  .ui-dialog-overlay.is-closing .ui-dialog {
    transition-duration: 120ms;
  }
  .ui-dialog,
  .ui-dialog-overlay.is-closing .ui-dialog { transform: none; }
  .ui-dialog-overlay.is-open,
  .ui-dialog-overlay.is-open .ui-dialog { animation: none; }
}

/* Cabeçalho centrado (ícone no slot + título + descrição), o mesmo nos
   dois formatos de diálogo. */
.ui-dialog-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 2rem 1.75rem;
  text-align: center;
}
/* O ícone vai num SLOT (a casinha de inventário): quadrado, borda de 2px e
   moldura interna, tingido com a cor do tom. */
.ui-dialog-media {
  --ui-media-c: var(--ln-text-fg);
  width: 48px;
  height: 48px;
  border-radius: var(--ln-radius-slot);
  border: 2px solid var(--ln-outline-slot);
  outline: 2px solid var(--ln-frame-slot);
  outline-offset: -4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05rem;
  margin-bottom: 4px;
  color: var(--ui-media-c);
  background: color-mix(in srgb, var(--ui-media-c) 14%, var(--ln-slot-fill));
}
.ui-dialog-media--danger  { --ui-media-c: var(--ln-danger); }
.ui-dialog-media--warning { --ui-media-c: var(--ln-warning); }
.ui-dialog-media--success { --ui-media-c: var(--ln-success); }
.ui-dialog-media--violet  { --ui-media-c: var(--ln-cat-amethyst); }
.ui-dialog-media--info    { --ui-media-c: var(--ln-brand-text); }
.ui-dialog-titulo {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ln-text-fg);
}
.ui-dialog-desc {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ln-text-muted);
}
/* Rodapé do ALERTA (ConfirmDialog): os dois botões lado a lado, meia
   largura cada, DENTRO do cartão e com respiro. O botão é uma peça com
   relevo — colado na borda ele perdia o degrau de baixo e virava faixa. */
.ui-dialog-footer {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  padding: 0 16px 16px;
}
.ui-dialog-footer > .ui-btn { height: 2.5rem; }
/* O segundo formato, diálogo de FORMULÁRIO: quando tem corpo (um campo, uma
   grade), os botões voltam pra direita, que é onde a ação de um formulário
   mora. Meia largura cada num cartão largo viraria parede de botão. */
.ui-dialog-body {
  padding: 0 24px 20px;
}
.ui-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--ln-edge-1);
}

/* ── RECIPIENTES ── */
.ln-card {
  background: var(--ln-surface-1);
  border: 2px solid var(--ln-outline);
  outline: 2px solid var(--ln-frame-card);
  outline-offset: -4px;
  border-radius: var(--ln-radius-card);
}
.ln-card-raised {
  background: var(--ln-surface-2);
  border: 2px solid var(--ln-outline);
  outline: 2px solid var(--ln-frame-panel);
  outline-offset: -4px;
  border-radius: var(--ln-radius-card);
  box-shadow: 0 3px 0 0 var(--ln-shadow-flat);
}
.ln-card-hover { transition: border-color 0.12s; }
.ln-card-hover:hover { border-color: var(--ln-selection); }
.ln-panel {
  background: var(--ln-surface-1);
  border: 2px solid var(--ln-outline);
  outline: 2px solid var(--ln-frame-panel);
  outline-offset: -4px;
  border-radius: var(--ln-radius-card);
}
.ln-raised { box-shadow: 0 4px 0 0 var(--ln-shadow-flat); }
/* O poço é o inverso do cartão: o conteúdo AFUNDA. */
.ln-well {
  background: var(--ln-well-floor);
  border: 2px solid var(--ln-outline);
  outline: 2px solid var(--ln-frame-well);
  outline-offset: -4px;
  border-radius: var(--ln-radius-slot);
  box-shadow: inset 0 4px 0 0 var(--ln-well-depth), inset 0 -1px 0 0 var(--ln-well-lip);
}
.ln-slot {
  background: var(--ln-slot-fill);
  border: 2px solid var(--ln-outline-slot);
  outline: 2px solid var(--ln-frame-slot);
  outline-offset: -4px;
  border-radius: var(--ln-radius-slot);
  transition: border-color 0.12s;
}
.ln-slot-raised {
  background: var(--ln-surface-2);
  border: 2px solid var(--ln-outline-slot);
  outline: 2px solid var(--ln-frame-slot);
  outline-offset: -4px;
  border-radius: var(--ln-radius-slot);
}
.ln-slot-muted {
  background: var(--ln-surface-3);
  border: 2px solid var(--ln-outline);
  border-radius: var(--ln-radius-slot);
}
/* Hover de slot: a borda clareia e um véu cobre o miolo. */
.ln-slot-hover { position: relative; }
.ln-slot-hover::after {
  content: '';
  position: absolute;
  inset: 2px;
  border-radius: 3px;
  pointer-events: none;
  background: transparent;
  transition: background-color 0.1s;
}
.ln-slot-hover:hover { border-color: var(--ln-selection); }
.ln-slot-hover:hover::after { background: var(--ln-hover-veil); }

/* ── BOTÕES ──
   Duas famílias com o mesmo corpo: .ln-btn (cheio, ação) e .ln-slot-btn
   (peça de inventário: navegação, filtro, ação secundária). A cor de cada
   variante são só três valores — face, luz de cima, sombra de baixo. */
.ln-btn,
.ln-slot-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--ln-outline);
  border-radius: var(--ln-radius-slot);
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  font-family: inherit;
  box-shadow:
    inset 0 var(--ln-btn-top) 0 0 var(--ln-b-top),
    inset 0 calc(-1 * var(--ln-btn-bottom)) 0 0 var(--ln-b-bottom);
  transition: filter 0.15s;
}
.ln-btn {
  background: var(--ln-btn-primary-face);
  color: #ffffff;
  font-weight: 600;
  --ln-b-top: var(--ln-btn-primary-top);
  --ln-b-bottom: var(--ln-btn-primary-bottom);
}
.ln-slot-btn {
  background: var(--ln-btn-slot-face);
  color: var(--ln-btn-slot-ink);
  font-weight: 500;
  --ln-b-top: var(--ln-btn-slot-top);
  --ln-b-bottom: var(--ln-btn-slot-bottom);
}
.ln-btn:hover,
.ln-slot-btn:hover { filter: brightness(1.07); }
/* Pressionado (ou com o menu que ele abriu aberto): o degrau some e a peça
   afunda. */
.ln-btn:active,
.ln-slot-btn:active,
.ln-btn[aria-expanded='true'],
.ln-slot-btn[aria-expanded='true'] {
  box-shadow: inset 0 calc(-1 * var(--ln-btn-pressed-bottom)) 0 0 var(--ln-b-bottom);
}
.ln-btn:focus-visible,
.ln-slot-btn:focus-visible {
  outline: 2px solid var(--ln-ring);
  outline-offset: 2px;
}
.ln-btn:disabled,
.ln-slot-btn:disabled {
  filter: saturate(0.4) brightness(0.75);
  cursor: not-allowed;
}
.ln-btn-secondary {
  background: var(--ln-btn-secondary-face);
  color: var(--ln-btn-slot-ink);
  --ln-b-top: var(--ln-btn-secondary-top);
  --ln-b-bottom: var(--ln-btn-secondary-bottom);
}
.ln-btn-danger {
  background: var(--ln-btn-danger-face);
  color: #ffffff;
  --ln-b-top: var(--ln-btn-danger-top);
  --ln-b-bottom: var(--ln-btn-danger-bottom);
}
/* O botão claro é o CTA mais forte da tela: no máximo um por página. No
   hover ele escurece, não clareia. */
.ln-btn-light {
  background: var(--ln-btn-light-face);
  color: var(--ln-btn-light-ink);
  font-weight: 700;
  --ln-b-top: var(--ln-btn-light-top);
  --ln-b-bottom: var(--ln-btn-light-bottom);
}
.ln-btn-light:hover { filter: brightness(0.96); }
.ln-btn-green  { background: #1f9a4d; color: #ffffff; --ln-b-bottom: #005725; }
.ln-btn-purple { background: #8b3fc4; color: #ffffff; --ln-b-bottom: #4d2472; }
.ln-btn-yellow { background: #e0a020; color: #251c05; --ln-b-bottom: #856300; }
/* Cor vinda de DADO (cor do cargo, do tipo de punição): a face chega por
   variável, sem gerar CSS novo. */
.ln-btn-color {
  background: var(--btn-face);
  color: var(--btn-ink, #ffffff);
  --ln-b-top: rgba(255, 255, 255, 0.22);
  --ln-b-bottom: var(--btn-face-bottom, rgba(0, 0, 0, 0.35));
}
/* Tamanhos pra quem monta o botão à mão (o <Button> usa os .ui-btn-* do
   fim do arquivo). Sempre combinados com uma variante. */
.ln-btn-sm  { height: 2rem;    padding: 0 0.75rem; font-size: 0.75rem;   gap: 0.375rem; }
.ln-btn-md  { height: 2.25rem; padding: 0 1.1rem;  font-size: 0.875rem;  gap: 0.5rem; }
.ln-btn-cta { height: 2.5rem;  padding: 0 1rem;    font-size: 0.8125rem; gap: 0.625rem; }
.ln-btn-lg  { height: 2.75rem; padding: 0 1.5rem;  font-size: 0.9375rem; gap: 0.625rem; }
.ln-btn-icon-sm { width: 2rem;    height: 2rem;    padding: 0; }
.ln-btn-icon-md { width: 2.25rem; height: 2.25rem; padding: 0; }

/* ── BOTÃO FANTASMA ──
   Pros ícones de barra (topo, cabeçalho, menus). Sem relevo nenhum até o
   hover — uma barra cheia de botões com degrau vira ruído. */
.ln-ghost {
  background: transparent;
  color: var(--ln-text-muted);
  border: 0;
  border-radius: var(--ln-radius-slot);
  cursor: pointer;
  font-family: inherit;
  transition: background-color 0.1s, color 0.1s;
}
.ln-ghost:hover,
.ln-ghost[aria-expanded='true'] {
  background: var(--ln-hover-veil);
  color: var(--ln-text-fg);
}
.ln-ghost:active { background: var(--ln-surface-3); }
.ln-ghost:focus-visible { outline: 2px solid var(--ln-ring); outline-offset: 1px; }
.ln-ghost:disabled { opacity: 0.45; cursor: not-allowed; }
/* O item ATUAL de uma lista (a opção escolhida num menu): a linha
   realçada, não um botão com relevo. Quem marca é a classe `is-current`. */
.ln-ghost.is-current {
  background: var(--ln-surface-3);
  color: var(--ln-text-fg);
  font-weight: 600;
}
/* Dentro de um trilho segmentado (.ln-pill-bar), o atual é a ABA LIGADA:
   fundo da marca com o relevo invertido. */
.ln-pill-bar .ln-ghost.is-current,
.ln-pill-bar .ln-ghost.is-current:hover {
  background: var(--ln-brand-500);
  color: #ffffff;
  box-shadow: inset 0 2px 0 0 var(--ln-brand-bevel-top), inset 0 -2px 0 0 var(--ln-brand-bevel-bottom);
}
.ln-pill-bar .ln-ghost.is-current:hover { filter: brightness(1.07); }
/* ── BOTÃO QUE ALTERNA ──
   A opção de um grupo (aba, filtro, escolha) que troca de peça quando é
   escolhida: .ln-ghost ou .ln-slot-btn desligada, .ln-btn ligada. Quem marca
   é o `aria-pressed` (true/false), que o leitor de tela também anuncia. As
   peças têm borda e peso de letra diferentes, e a troca fazia o botão e os
   vizinhos pularem alguns px (achado pelo dono no gestaostaff, 26/09/2026; o
   mesmo conserto de lá). Aqui os dois estados têm a mesma caixa e o mesmo
   peso: só a cor muda, como no .ln-selected. O fantasma ganha a borda de 2px
   das outras peças, transparente. Vale só pro <Button> (.ui-btn): as peças
   montadas à mão com aria-pressed (os tópicos do Registro, os cartões da
   Versão) não trocam de peça e têm o peso delas. No trilho segmentado todas
   são fantasmas: lá a borda não entra, e a aba ligada fica com o peso das
   outras (senão as abas do Painel andavam ao trocar). */
.ui-btn.ln-btn[aria-pressed],
.ui-btn.ln-slot-btn[aria-pressed],
.ui-btn.ln-ghost[aria-pressed],
.ln-pill-bar .ln-ghost.is-current { font-weight: 500; }
.ui-btn.ln-ghost[aria-pressed] { border: 2px solid transparent; }
.ln-pill-bar .ui-btn.ln-ghost[aria-pressed] { border: 0; }
.ln-link {
  background: transparent;
  border: 0;
  color: var(--ln-brand-text);
  cursor: pointer;
  font-family: inherit;
}
.ln-link:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ── SELEÇÃO: chip, pill-bar, aba ──
   O chip troca a borda no hover, e os três ganham a assinatura da marca
   quando ligados (o estado LIGADO fica no fim deste bloco). */
.ln-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: 2px solid var(--ln-outline-slot);
  background: var(--ln-btn-slot-face);
  outline: 2px solid var(--ln-frame-panel);
  outline-offset: -4px;
  border-radius: var(--ln-radius-slot);
  color: var(--ln-btn-slot-ink);
  padding: 0.4rem 0.9rem;
  font-size: 0.8125rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.12s;
}
.ln-chip:hover { border-color: var(--ln-selection); }
/* Trilho segmentado: vive dentro de um poço. */
.ln-pill-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  padding: 0.25rem;
  border: 2px solid var(--ln-outline);
  background: var(--ln-well-floor);
  outline: 2px solid var(--ln-frame-well);
  outline-offset: -4px;
  border-radius: var(--ln-radius-slot);
  box-shadow: inset 0 4px 0 0 var(--ln-well-depth), inset 0 -1px 0 0 var(--ln-well-lip);
}
/* CANTO CONCÊNTRICO das abas dentro do trilho. Elas moram 6px pra dentro
   (2px de borda + 4px de padding), e a curva do poço a essa altura já vale
   `slot - 6px` — com o raio cheio o canto da aba cortava mais que o do
   trilho e sobrava uma cunha escura em cada quina. */
.ln-pill-bar > * {
  border-radius: max(0px, calc(var(--ln-radius-slot) - 6px));
}
.ln-tab {
  border: 0;
  background: transparent;
  border-radius: var(--ln-radius-sm);
  padding: 0.375rem 0.75rem;
  color: var(--ln-text-muted);
  font-family: inherit;
  font-size: 0.875rem;
  cursor: pointer;
  transition: color 0.12s, background-color 0.12s;
}
.ln-tab:hover { color: var(--ln-text-fg); }

/* ── BADGE ── */
.ln-badge {
  --ln-badge-c: var(--ln-text-body);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  /* A fonte do guia, sempre: um selo dentro de um título em fonte pixel
     herdaria ela — número em pixel-font fica ilegível em 11px. */
  font-family: var(--font-jakarta), 'Plus Jakarta Sans', sans-serif;
  letter-spacing: 0;
  text-transform: none;
  border: 2px solid var(--ln-outline);
  background: var(--ln-surface-2);
  color: var(--ln-badge-c);
  border-radius: var(--ln-radius-slot);
  padding: 0.125rem 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  white-space: nowrap;
  position: relative;
  overflow: hidden;
}
.ln-badge-tint {
  background: color-mix(in srgb, var(--ln-badge-c) 14%, var(--ln-surface-1));
  border-color: color-mix(in srgb, var(--ln-badge-c) 28%, var(--ln-outline));
}
.ln-badge-brand   { --ln-badge-c: var(--ln-brand-text); }
.ln-badge-success { --ln-badge-c: var(--ln-success-text); }
.ln-badge-warning { --ln-badge-c: var(--ln-warning-text); }
.ln-badge-danger  { --ln-badge-c: var(--ln-danger-text); }
/* Brilho que atravessa a pílula a cada 6s. É o único elemento que chama
   atenção sozinho — reservado a NOVIDADE. */
.ln-badge-sheen::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: translateX(-120%);
  background: linear-gradient(110deg, transparent 38%, rgba(255, 255, 255, 0.22) 50%, transparent 62%);
  animation: lnBadgeSheen 6s ease-in-out infinite;
}

/* ── ENTRADA ──
   Todo controle de entrada é um poço. O foco troca a moldura translúcida
   pela sólida — não põe anel por fora. */
.ln-input {
  width: 100%;
  border: 2px solid var(--ln-outline);
  background: var(--ln-well-floor);
  color: var(--ln-text-fg);
  border-radius: var(--ln-radius-slot);
  font: inherit;
  padding: 0.6rem 0.8rem;
  box-shadow:
    inset 0 0 0 2px var(--ln-frame-panel),
    inset 0 4px 0 0 var(--ln-well-depth),
    inset 0 -1px 0 0 var(--ln-well-lip);
  transition: box-shadow 0.12s;
}
.ln-input::placeholder { color: var(--ln-text-placeholder); }
.ln-input:hover {
  box-shadow:
    inset 0 0 0 2px var(--ln-frame-slot),
    inset 0 4px 0 0 var(--ln-well-depth),
    inset 0 -1px 0 0 var(--ln-well-lip);
}
.ln-input:focus {
  outline: none;
  box-shadow:
    inset 0 0 0 2px var(--ln-frame),
    inset 0 4px 0 0 var(--ln-well-depth);
}
/* Caixa de marcar: um poço pequeno; marcada, vira a peça "ligada" da marca
   (relevo invertido) com o ✓ branco. Quem usa é o <Checkbox>
   (components/ui/checkbox.js), que também dá o pulo ao marcar. Vale pro
   <input type="checkbox"> de verdade (estado no :checked, e o
   :indeterminate vira um traço) e pro <span> só de enfeite (estado no
   .is-on). O ✓ é o glifo do Font Awesome no ::before — nada de <i> dentro.
   Sem opacidade no :disabled: a caixa travada (lista só-leitura) tem que
   continuar mostrando o que está feito. */
.ln-checkbox {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  display: inline-grid;
  place-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 2px solid var(--ln-outline);
  background: var(--ln-well-floor);
  border-radius: var(--ln-radius-sm);
  color: transparent;
  box-shadow:
    inset 0 0 0 2px var(--ln-frame-panel),
    inset 0 3px 0 0 var(--ln-well-depth);
  cursor: pointer;
  transition: box-shadow 0.12s;
}
.ln-checkbox::before {
  content: '\f00c';
  font: var(--fa-font-solid, normal 900 1em/1 'Font Awesome 6 Free');
  font-size: 9px;
}
.ln-checkbox:hover {
  box-shadow: inset 0 0 0 2px var(--ln-frame), inset 0 3px 0 0 var(--ln-well-depth);
}
.ln-checkbox:focus-visible { outline: 2px solid var(--ln-ring); outline-offset: 2px; }
/* Marcada = a peça "ligada". A cor é a da marca, mas dá pra trocar por
   contexto declarando --ln-check-on (e os dois relevos, --ln-check-luz e
   --ln-check-degrau) no ANCESTRAL — ex.: uma lista de "feito" em verde. */
.ln-checkbox:checked,
.ln-checkbox:indeterminate,
.ln-checkbox.is-on,
.ln-checkbox[data-state='checked'] {
  background: var(--ln-check-on, var(--ln-brand-500));
  box-shadow:
    inset 0 2px 0 0 var(--ln-check-luz, var(--ln-brand-bevel-top)),
    inset 0 -2px 0 0 var(--ln-check-degrau, var(--ln-brand-bevel-bottom));
  color: #ffffff;
}
.ln-checkbox:checked:hover { filter: brightness(1.1); }
.ln-checkbox:indeterminate::before { content: '\f068'; }
.ln-checkbox:disabled { cursor: default; }
.ln-checkbox:disabled:hover { box-shadow: inset 0 0 0 2px var(--ln-frame-panel), inset 0 3px 0 0 var(--ln-well-depth); }
.ln-checkbox:checked:disabled:hover {
  filter: none;
  box-shadow:
    inset 0 2px 0 0 var(--ln-check-luz, var(--ln-brand-bevel-top)),
    inset 0 -2px 0 0 var(--ln-check-degrau, var(--ln-brand-bevel-bottom));
}
/* Só o desenho: quem recebe o clique (e o cursor) é o pai. */
span.ln-checkbox { cursor: inherit; }
/* Switch: a mesma peça do botão claro, encaixada num trilho. (O interruptor
   antigo do guia, .toggle-switch, é outro controle e continua existindo.) */
.ln-switch {
  display: inline-flex;
  align-items: center;
  width: 44px;
  height: 24px;
  padding: 2px;
  border: 2px solid var(--ln-outline);
  background: var(--ln-btn-slot-face);
  border-radius: var(--ln-radius-sm);
  cursor: pointer;
  box-shadow: inset 0 2px 0 0 var(--ln-btn-slot-top), inset 0 -2px 0 0 var(--ln-btn-slot-bottom);
}
.ln-switch.is-on,
.ln-switch[data-state='checked'] {
  background: var(--ln-brand-500);
  box-shadow: inset 0 2px 0 0 rgba(255, 255, 255, 0.22);
}
.ln-switch-thumb {
  display: block;
  width: 16px;
  height: 16px;
  border: 2px solid var(--ln-outline);
  background: var(--ln-btn-light-face);
  border-radius: 3px;
  box-shadow: inset 0 2px 0 0 var(--ln-btn-light-top), inset 0 -3px 0 0 var(--ln-btn-light-bottom);
  transition: translate 0.12s ease-out;
}
.ln-switch.is-on .ln-switch-thumb,
.ln-switch[data-state='checked'] .ln-switch-thumb { translate: 20px; }
.ln-progress {
  position: relative;
  height: 12px;
  overflow: hidden;
  border: 2px solid var(--ln-outline);
  background: var(--ln-well-floor);
  border-radius: var(--ln-radius-sm);
  box-shadow:
    inset 0 0 0 2px var(--ln-frame-panel),
    inset 0 4px 0 0 var(--ln-well-depth),
    inset 0 -1px 0 0 var(--ln-well-lip);
}
/* `display: block` pra servir em <span> também: sem ele, um <span> é de
   linha, o navegador ignora largura e altura e a barra nunca aparecia (a do
   "O que é?" do Dashboard, 25/09/2026). */
.ln-progress-fill {
  display: block;
  height: 100%;
  background: var(--ln-brand-500);
  box-shadow: inset 0 2px 0 0 rgba(255, 255, 255, 0.22);
  transition: width 0.3s;
}

/* ── FEEDBACK ──
   Alerta = um cartão comum com uma faixa de 3px colada à esquerda. A mesma
   variável pinta a faixa e o ícone. */
.ln-alert {
  --ln-alert-c: var(--ln-info);
  position: relative;
  overflow: hidden;
}
.ln-alert::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--ln-alert-c);
}
.ln-alert .ln-alert-icon { color: var(--ln-alert-c); }
.ln-alert-danger  { --ln-alert-c: var(--ln-danger); }
.ln-alert-warning { --ln-alert-c: var(--ln-warning); }
.ln-alert-success { --ln-alert-c: var(--ln-success); }
.ln-alert-info    { --ln-alert-c: var(--ln-info); }
/* Skeleton: a cor do vazio segue a superfície de trás. */
.ln-skeleton {
  background: var(--ln-skeleton-fill, var(--ln-surface-2));
  animation: lnSkeletonPulse 1.6s ease-in-out infinite;
}
.ln-skeleton-on-card { --ln-skeleton-fill: var(--ln-surface-3); }
.ln-tooltip {
  border: 2px solid var(--ln-outline);
  background: var(--ln-surface-2);
  color: var(--ln-text-fg);
  border-radius: var(--ln-radius-slot);
}

/* ── TIPOGRAFIA ── */
/* Eyebrow: o rótulo em fonte pixel que abre um bloco. BRANCO, e não na cor
   da marca como no gestaostaff: lá a peça quase não é usada, e os títulos pixel de
   lista, seção e menu são da cor do texto normal. Aqui ela é o título dos
   blocos, então segue esse padrão (pedido do dono, 25/09/2026). O rótulo
   em cima do título da página (.cabecalho-pagina-rotulo e
   .dash-abertura-rotulo) também é branco desde 28/09/2026: ele fica em cima
   do céu colorido, e o roxo não combinava (pedido do dono). */
.ln-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--ln-font-pixel);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--ln-text-fg);
}
.ln-pixel-text {
  font-family: var(--ln-font-pixel);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
/* Sombra de texto chapada: sobre fundo escuro. */
.ln-heading-shadow { text-shadow: 0.05em 0.05em rgba(2, 3, 6, 0.85); }
/* Marcador de seção: um "pixel" com sombra chapada. */
.ln-section-marker {
  display: inline-block;
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  background: var(--ln-brand-400);
  box-shadow: 3px 3px 0 0 var(--ln-brand-glow);
}

/* ── LIGADO ──
   A assinatura única de "selecionado/ativo/marcado": fundo da marca com o
   relevo invertido. Fica POR ÚLTIMO entre as peças de propósito — combina
   com qualquer uma (`ln-badge ln-selected`, `ln-chip is-active`) e, com a
   mesma especificidade, quem vem depois vence o fundo da peça base. */
.ln-selected,
.ln-chip.is-active,
.ln-chip[aria-pressed='true'],
.ln-tab.is-active,
.ln-tab[aria-selected='true'],
.ln-tab[data-state='active'] {
  background: var(--ln-brand-500);
  color: #ffffff;
  /* O relevo é o da MARCA porque o fundo normalmente é o da marca. Quem troca
     o fundo por outra cor troca também estas duas variáveis, senão sobra
     um degrau roxo embaixo de um selo vermelho. */
  box-shadow:
    inset 0 2px 0 0 var(--ln-on-luz, var(--ln-brand-bevel-top)),
    inset 0 -2px 0 0 var(--ln-on-degrau, var(--ln-brand-bevel-bottom));
}

@keyframes lnSkeletonPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@keyframes lnBadgeSheen {
  0% { transform: translateX(-120%); }
  22% { transform: translateX(120%); }
  100% { transform: translateX(120%); }
}
@media (prefers-reduced-motion: reduce) {
  .ln-skeleton,
  .ln-badge-sheen::after { animation: none; }
}

/* ── TAMANHOS DOS COMPONENTES ──
   No gestaostaff o <Button> e o <Badge> dimensionam com utilitários do
   Tailwind (h-9, px-4, text-xs...). Aqui são estas classes, com os MESMOS
   valores, e no mesmo lugar da ordem: DEPOIS das peças, como os
   utilitários de lá — então a altura e o padding daqui ganham da peça. */
.ui-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  white-space: nowrap;
  font-size: 0.875rem;
  line-height: 1;
}
.ui-btn:disabled { pointer-events: none; }
.ui-btn svg { pointer-events: none; width: 1rem; height: 1rem; flex-shrink: 0; }
.ui-btn i { flex-shrink: 0; font-size: 0.9em; line-height: 1; }
.ui-btn-md { height: 2.25rem; padding-left: 1rem; padding-right: 1rem; }
.ui-btn-sm { height: 2rem; padding-left: 0.75rem; padding-right: 0.75rem; font-size: 0.75rem; }
.ui-btn-lg { height: 2.5rem; padding-left: 1.5rem; padding-right: 1.5rem; }
.ui-btn-icon { width: 2.25rem; height: 2.25rem; padding: 0; }
.ui-btn-icon-sm { width: 2rem; height: 2rem; padding: 0; }
/* O fantasma e o link não têm peso próprio; o <Button> dá 500 a eles. */
.ui-btn-medium { font-weight: 500; }

.ui-badge { gap: 0.25rem; font-weight: 600; line-height: 1; }
.ui-badge-outline { background-color: transparent; }
.ui-badge-xs { height: 1rem;    min-width: 1rem;    padding-left: 0.25rem;  padding-right: 0.25rem;  font-size: 0.625rem; }
.ui-badge-sm { height: 1.25rem; min-width: 1.25rem; padding-left: 0.375rem; padding-right: 0.375rem; font-size: 0.6875rem; }
.ui-badge-md { height: 1.5rem;  min-width: 1.5rem;  padding-left: 0.5rem;   padding-right: 0.5rem;   font-size: 0.75rem; }

.ui-spinner {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
  animation: uiSpin 1s linear infinite;
}
@keyframes uiSpin { to { transform: rotate(360deg); } }

/* ── MOLDURA POR CIMA ──
   A moldura interna das peças é um `outline`. Outline é pintado pelo
   PRÓPRIO elemento, e todo descendente pinta depois dele — então, numa
   caixa com área de rolagem, o conteúdo passa POR CIMA da moldura ao rolar
   (no gestaostaff o dono viu isso na lista dos quadros e no modal do
   staff, 24/09/2026).

   Esta classe apaga o outline e redesenha a MESMA moldura num ::before
   absoluto, acima do conteúdo. `inset: 0` num filho absoluto é o limite do
   PADDING do pai, ou seja, logo depois da borda de 2px — os mesmos 2px..4px
   que o `outline-offset: -4px` ocupava. O raio acompanha, menos a borda.

   Uso: some a peça E tem rolagem dentro → `ln-card ln-moldura-cima`.
   Exige o ::before livre (a caixa não pode usar ::before pra outra coisa),
   e a moldura não pode vir de `outline` no CSS da tela (ele carrega depois
   e ganharia do `outline: none` daqui). Pra achar TODAS as caixas que
   precisam, varra o DOM no navegador (caixa com moldura + filho rolável);
   grep no CSS acha menos. */
.ln-moldura-cima {
  position: relative;
  outline: none;
}
.ln-moldura-cima::before {
  content: '';
  position: absolute;
  inset: 0;
  border: 2px solid var(--ln-moldura-cor, var(--ln-frame-panel));
  border-radius: calc(var(--ln-moldura-raio, var(--ln-radius-card)) - 2px);
  pointer-events: none;
  z-index: 3;
}
.ln-card.ln-moldura-cima { --ln-moldura-cor: var(--ln-frame-card); }
.ln-well.ln-moldura-cima { --ln-moldura-cor: var(--ln-frame-well); --ln-moldura-raio: var(--ln-radius-slot); }
.ln-slot.ln-moldura-cima,
.ln-slot-raised.ln-moldura-cima { --ln-moldura-cor: var(--ln-frame-slot); --ln-moldura-raio: var(--ln-radius-slot); }
