/* ─────────────────────────────────────────────────────────────────────────
   Catalogador 3D — o sistema de design

   **A fonte é o DOC_DESIGN**, `fontes/P2_Catalogo3D_Prompt_ClaudeDesign.md`
   §3, que o `CLAUDE.md` §5 põe acima de tudo o resto no que toca a interface.
   Os valores de cor são os de lá, à letra: "usa exatamente estes valores".

   ## Três notas, porque não é uma cópia cega

   1. **Onde os dois documentos discordam, ganha o Prompt.** O `UI_Spec` §6 dá
      `#1A1F2E` à sidebar; o Prompt dá `#1A1A1A`. É o Prompt que o `CLAUDE.md`
      nomeia como DOC_DESIGN, por isso é `#1A1A1A`.

   2. **O indicador de confiança da extração (UI_Spec §5.4) não existe aqui, e
      é de propósito.** A D-16 mediu que a confiança que o modelo declara sobre
      si próprio **não prevê o acerto**, e tirou-a do sistema. O que a
      substitui é a *etiqueta de origem* — `2D cliente`, `3D`, `manual` —, que
      é um facto e não um palpite. Construir os `✓ ⚠ ✗` seria pôr no ecrã um
      número que já sabemos que engana.

   3. **Os ícones são desenhados aqui, não vêm de um CDN.** O DOC_DESIGN pede
      Lucide por CDN; a aplicação corre na máquina do Igor e há-de correr na
      fábrica. Uma folha que fica sem ícones quando a rede falha não serve.
      As formas são as do Lucide, em SVG dentro do `base.html`.

   As classes têm os nomes que os ecrãs já usavam (`.cartao`, `.selo`,
   `.botao`). Mudou a pele, não o vocabulário — por isso nenhum ecrã teve de
   ser reescrito para receber isto.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  /* ── Cores: DOC_DESIGN §3.1, à letra ─────────────────────────────────── */
  --bg: #FFFFFF;
  --bg-secondary: #F7F7F7;
  --sidebar-bg: #1A1A1A;
  --text-primary: #333333;
  --text-secondary: #616161;
  --accent-primary: #FF7B2B;
  --accent-brand-highlight: #FFDE00;
  --success: #16A34A;
  --warning: #D97706;
  --danger: #DC2626;
  --border: #E5E7EB;

  /* Derivadas. Não inventam cor nenhuma — são a de marca a baixa opacidade,
     para fundos de estado que não podem competir com o texto. */
  --accent-fraco: #FFF3EA;
  --success-fraco: #E9F7EE;
  --warning-fraco: #FDF3E3;
  --danger-fraco: #FDEAEA;

  /* Chips por categoria — UI_Spec §5.3 */
  --chip-material: #1E4A8C;
  --chip-processo: #374151;
  --chip-certificacao: #B91C1C;

  --raio: 8px;
  --raio-pequeno: 6px;
  --sombra: 0 1px 2px rgba(26, 26, 26, .05);
  --sombra-media: 0 2px 8px rgba(26, 26, 26, .07);

  --sidebar-largura: 232px;
  --topo: 0px;                 /* altura da barra fixa; a sidebar é lateral */

  /* ── Movimento ─────────────────────────────────────────────────────────
     Um vocabulário só, para a plataforma inteira mexer da mesma maneira:
     `--dur-1` para micro-reações (hover, foco), `--dur-2` para painéis e
     desdobramentos. A curva é a mesma em todo o lado — mudá-la num sítio só
     muda o carácter da aplicação toda, que é o objetivo. Tudo isto desliga
     em bloco no `prefers-reduced-motion`, no fim desta folha. */
  --dur-1: 140ms;
  --dur-2: 260ms;
  --ease-suave: cubic-bezier(.16, 1, .3, 1);
}

/* ── Tipografia: DOC_DESIGN §3.2 ─────────────────────────────────────────
   Fira Sans no corpo, IBM Plex Mono nas referências e nos números. As pilhas
   de recurso são longas de propósito: se o Google Fonts não carregar — a
   fábrica pode não ter saída para a Internet —, a página continua legível e
   com a mesma métrica aproximada. */
* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg-secondary);
  color: var(--text-primary);
  font-family: "Fira Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 15px;
  line-height: 1.55;
}

.mono, .mono * {
  font-family: "IBM Plex Mono", ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .92em;
  letter-spacing: -.01em;
}

h1, h2, h3 { font-weight: 600; letter-spacing: -.01em; }

/* ── A moldura: sidebar à esquerda, conteúdo à direita ───────────────────
   UI_Spec §3 e §5.1. A navegação era uma barra no topo; a barra no topo
   comia altura, e este produto é de tabelas e desenhos — a altura é o que
   escasseia. Lateral também deixa a lista de secções crescer. */
.aplicacao { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-largura);
  flex: 0 0 var(--sidebar-largura);
  background: var(--sidebar-bg);
  color: #FFFFFF;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

.sidebar-marca {
  padding: 18px 18px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, .09);
  display: flex;
  align-items: center;
  gap: 11px;
}
.sidebar-marca svg { color: var(--accent-primary); flex: 0 0 auto; }
.sidebar-marca .empresa { font-size: 14px; font-weight: 600; line-height: 1.25; }
.sidebar-marca .aplicacao-nome {
  font-size: 12px; color: rgba(255, 255, 255, .55); line-height: 1.25;
}

.sidebar nav { padding: 12px 10px; display: flex; flex-direction: column; gap: 2px; }
.sidebar nav a, .sidebar nav span.por-construir {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 11px; border-radius: var(--raio-pequeno);
  color: rgba(255, 255, 255, .78); text-decoration: none;
  font-size: 14px; font-weight: 500; white-space: nowrap;
}

/* O preenchimento que sobe. Adaptado do "PillNav" (reactbits) que o Igor
   trouxe a 2026-08-17: lá é um círculo GSAP que nasce debaixo da pílula e
   cresce até a encher; aqui é o mesmo gesto em CSS puro — um círculo no fundo
   do item que sobe e cobre no hover. Da referência ficou a geometria e a
   curva; a cor é a da casa e o texto não salta (o duplo-rótulo da referência
   é ginástica a mais para uma ferramenta de trabalho). */
.sidebar nav a { position: relative; overflow: hidden; isolation: isolate;
                 transition: color var(--dur-2) var(--ease-suave); }
.sidebar nav a::before {
  content: ""; position: absolute; left: 50%; bottom: 0; z-index: 0;
  width: 140%; aspect-ratio: 1; border-radius: 50%;
  background: rgba(255, 255, 255, .09);
  transform: translate(-50%, 104%) scale(.4);
  transition: transform var(--dur-2) var(--ease-suave);
}
.sidebar nav a:hover::before { transform: translate(-50%, 12%) scale(1.05); }
.sidebar nav a > * { position: relative; z-index: 1; }
.sidebar nav a span:not(.marcador) {
  transition: transform var(--dur-2) var(--ease-suave); }
.sidebar nav a:hover span:not(.marcador) { transform: translateX(2px); }
.sidebar nav .grupo {
  margin: 14px 11px 4px; padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, .09);
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em;
  color: rgba(255, 255, 255, .3); font-weight: 600;
}
.sidebar nav a:hover { color: #FFFFFF; }
.sidebar nav a.ativo { background: rgba(255, 123, 43, .14); color: var(--accent-primary); }
.sidebar nav a.ativo::before { background: rgba(255, 123, 43, .10); }
.sidebar nav a.ativo svg { color: var(--accent-primary); }
.sidebar nav svg { flex: 0 0 auto; color: rgba(255, 255, 255, .5);
                   transition: color var(--dur-2) var(--ease-suave); }
.sidebar nav a:hover svg { color: rgba(255, 255, 255, .85); }

/* O que ainda não existe diz que não existe. Um item que parece navegável e
   dá 404 custa mais confiança do que um item apagado que se explica. */
.sidebar nav span.por-construir { color: rgba(255, 255, 255, .3); cursor: default; }
.sidebar nav span.por-construir svg { color: rgba(255, 255, 255, .22); }
.sidebar .marcador {
  margin-left: auto; font-size: 11px; font-weight: 500;
  background: rgba(255, 255, 255, .12); color: rgba(255, 255, 255, .75);
  padding: 1px 7px; border-radius: 999px;
}
.sidebar nav a.ativo .marcador { background: rgba(255, 123, 43, .22); color: var(--accent-primary); }
.sidebar nav span.por-construir .marcador {
  background: rgba(255, 255, 255, .08); color: rgba(255, 255, 255, .45);
}

.sidebar-rodape {
  margin-top: auto; padding: 14px 18px;
  border-top: 1px solid rgba(255, 255, 255, .09);
  font-size: 12px; color: rgba(255, 255, 255, .45); line-height: 1.5;
}
.sidebar-rodape a { color: rgba(255, 255, 255, .6); }

.conteudo { flex: 1 1 auto; min-width: 0; }
main { max-width: 1180px; margin: 0 auto; padding: 26px 28px 60px; }
main.largo { max-width: 1780px; }

/* ── Cabeçalho de ecrã ───────────────────────────────────────────────────
   Cada ecrã abre com o mesmo bloco: o que é, e o que se pode fazer. */
.cabecalho { display: flex; align-items: baseline; gap: 14px;
             flex-wrap: wrap; margin: 0 0 20px; }
.cabecalho h1 { font-size: 20px; margin: 0; }
.cabecalho .subtitulo { color: var(--text-secondary); font-size: 14px; }
.cabecalho .accoes { margin-left: auto; display: flex; gap: 10px; align-items: center; }

/* ── Cartões e secções ───────────────────────────────────────────────────
   Densidade média-alta e sombras subtis, DOC_DESIGN §3.3. */
.cartao {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--raio); padding: 18px 20px; margin-bottom: 16px;
  box-shadow: var(--sombra);
  /* Uma tabela de sete colunas não cabe em toda a janela, e quando não cabe é
     **o cartão** que ganha barra — nunca a página. Uma página que rola na
     horizontal esconde a coluna do Estado sem dizer que a escondeu. */
  overflow-x: auto;
}
/* O cabeçalho de secção — `.cartao h2` e `.secao` — vive todo no bloco do
   registo técnico, no fim desta folha. Estava aqui, e era **outro**: a §8.1
   das tarefas mediu 27 `h2` cinzentos contra 5 `.secao` numeradas a fazer o
   mesmo trabalho, e era isso que fazia a plataforma ler-se como dois
   produtos colados. */

/* ── Tabelas ─────────────────────────────────────────────────────────────
   Cabeçalho em `--bg-secondary`, linhas alternadas, hover em laranja muito
   fraco. DOC_DESIGN §3.4. */
table { width: 100%; border-collapse: collapse; font-size: 14px; }
thead th {
  text-align: left; font-weight: 600; color: var(--text-secondary);
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em;
  padding: 9px 12px; background: var(--bg-secondary);
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
thead th:first-child { border-top-left-radius: var(--raio-pequeno); }
thead th:last-child { border-top-right-radius: var(--raio-pequeno); }
td { padding: 10px 12px; border-bottom: 1px solid var(--border); }
tbody tr { transition: background-color var(--dur-1) ease; }
tbody tr:nth-child(even) { background: #FBFBFB; }
tbody tr:hover { background: var(--accent-fraco); }
tbody tr:last-child td { border-bottom: 0; }
/* Tabelas de duas colunas (rótulo · valor) não são listas: não alternam. */
table.propriedades tbody tr:nth-child(even) { background: none; }
table.propriedades tbody tr:hover { background: var(--bg-secondary); }
table.propriedades td:first-child { width: 250px; color: var(--text-secondary); }

/* ── Texto de apoio ──────────────────────────────────────────────────────*/
a { color: var(--accent-primary); text-decoration-color: rgba(255, 123, 43, .35);
    transition: text-decoration-color var(--dur-1) ease, color var(--dur-1) ease; }
a:hover { text-decoration-color: currentColor; }
.fraco { color: var(--text-secondary); }
.vazio { color: #B6BCC6; }
code {
  background: var(--bg-secondary); padding: 1px 6px; border-radius: 4px;
  border: 1px solid var(--border);
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace; font-size: 12.5px;
}
pre code { display: block; padding: 12px 14px; overflow-x: auto; border-radius: var(--raio-pequeno); }

/* ── Selos de estado e chips de atributo ─────────────────────────────────
   Duas coisas diferentes, e o DOC_DESIGN §3.1 insiste na diferença: o laranja
   e o amarelo são **marca**, não semântica. Sucesso, aviso e erro ficam em
   verde, âmbar e vermelho, que é convenção universal. */
.selo, .chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 500; white-space: nowrap;
}
.selo.ok     { background: var(--success-fraco); color: var(--success); }
.selo.aviso  { background: var(--warning-fraco); color: var(--warning); }
.selo.mau    { background: var(--danger-fraco);  color: var(--danger); }
.selo.neutro { background: var(--bg-secondary); color: var(--text-secondary);
               border: 1px solid var(--border); }
.selo.marca  { background: var(--accent-fraco); color: #C2571A; }
/* A etiqueta de origem de um campo. **Não é um estado** — é um facto sobre a
   proveniência, e por isso não pode vestir-se de aviso. Andava em âmbar, o que
   dizia "cuidado com este valor" sobre campos que estavam certos. Azul da
   família dos chips técnicos: informa, não alarma. */
.selo.fonte  { background: #EEF2F8; color: var(--chip-material);
               border: 1px solid #DCE4EF; }

.chip { color: #FFFFFF; font-weight: 500; }
.chip.material     { background: var(--chip-material); }
.chip.processo     { background: var(--chip-processo); }
.chip.setor        { background: var(--accent-primary); }
.chip.setor.geral  { background: var(--chip-processo); }
.chip.certificacao { background: var(--chip-certificacao); }

/* ── Botões ──────────────────────────────────────────────────────────────*/
.botao {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--accent-primary); color: #FFFFFF;
  padding: 9px 16px; border-radius: var(--raio-pequeno);
  text-decoration: none; font-size: 14px; font-weight: 500;
  border: 1px solid var(--accent-primary); cursor: pointer;
  font-family: inherit; line-height: 1.3;
  transition: background-color var(--dur-1) ease, border-color var(--dur-1) ease,
              box-shadow var(--dur-1) ease, transform var(--dur-1) ease;
}
.botao:hover { background: #E96A1B; border-color: #E96A1B;
               box-shadow: var(--sombra-media); }
/* O carregar sente-se: um milímetro para baixo enquanto o botão está premido.
   É a reação mais barata que existe e a que mais falta faz quando não está. */
.botao:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }
.botao.claro {
  background: var(--bg); color: var(--text-primary); border-color: var(--border);
}
.botao.claro:hover { background: var(--bg-secondary); border-color: #D3D8E0; }
.botao:disabled { opacity: .5; cursor: default; }

/* Um botão a trabalhar diz que trabalha. O JS (`interacoes.js`) troca o
   conteúdo por isto e repõe-no se o pedido falhar. */
.botao .roda-pontos { --tam: 1.05em; }

/* ── O botão que dispara a ação do ecrã ─────────────────────────────────
   Estilo de referência dado pelo Igor (2026-08-21): pílula, maiúsculas
   espaçadas, ícone à esquerda, sombra dupla suave que se recolhe no hover e
   desaparece no premir. As cores da referência não entraram — mantém-se o
   laranja da marca (DOC_DESIGN §3.1). */
.botao.botao-principal {
  gap: 10px;
  font-size: 13px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.4px;
  border-radius: 999px;
  padding: 15px 28px 15px 24px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  box-shadow: -4px -2px 16px 0 rgba(255, 255, 255, 0.9),
              4px 2px 16px 0 rgba(255, 123, 43, 0.45);
}
.botao.botao-principal:hover {
  box-shadow: -2px -1px 8px 0 rgba(255, 255, 255, 0.9),
              2px 1px 8px 0 rgba(255, 123, 43, 0.45);
}
.botao.botao-principal:active:not(:disabled) { box-shadow: none; }
.botao.botao-principal svg { flex: none; }

/* ── Campos de formulário ────────────────────────────────────────────────*/
label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 5px;
        color: var(--text-primary); }
input, select, textarea {
  width: 100%; padding: 8px 11px; border: 1px solid var(--border);
  border-radius: var(--raio-pequeno); font: inherit; font-size: 14px;
  background: var(--bg); color: var(--text-primary);
  transition: border-color var(--dur-1) ease, background-color var(--dur-1) ease;
}
input:hover, select:hover, textarea:hover { border-color: #D3D8E0; }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent-primary); outline-offset: -1px; border-color: transparent;
}
input::placeholder, textarea::placeholder { color: #AFB5BF; }
.campos { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 15px; }

/* ── Caixas de estado ────────────────────────────────────────────────────*/
.aviso-caixa, .erro-caixa {
  border-radius: var(--raio); padding: 14px 18px; margin-bottom: 16px;
  border: 1px solid; font-size: 14px;
}
.aviso-caixa { background: var(--warning-fraco); border-color: #F0D9AE; }
.erro-caixa  { background: var(--danger-fraco);  border-color: #F2C4C4; }
.aviso-caixa h3, .erro-caixa h3 { margin: 0 0 6px; font-size: 15px; }

/* ── Cartões de indicador (Dashboard, topo do catálogo) ──────────────────*/
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; }
.kpi {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--raio); padding: 15px 17px; box-shadow: var(--sombra);
}
.kpi .n { font-size: 27px; font-weight: 600; letter-spacing: -.03em; line-height: 1.15;
          font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace; }
.kpi .r { font-size: 11.5px; color: var(--text-secondary); text-transform: uppercase;
          letter-spacing: .05em; margin-top: 2px; }
/* Cantoneiras — §8.6. Os KPI são o que a Direção vê primeiro, e eram caixas
   lisas. **Duas e não quatro**, e sem markup nenhum: quatro cantoneiras dentro
   de uma moldura que já existe leem-se como moldura a dobrar, e são nove
   cartões no mesmo ecrã. Duas em diagonal bastam para dizer "isto é um
   instrumento de medida" e passam despercebidas quando não se olha para elas. */
.kpi { position: relative; }
.kpi::before, .kpi::after {
  content: ""; position: absolute; width: 9px; height: 9px;
  border: 1.5px solid var(--border); pointer-events: none;
}
.kpi::before { top: 6px; left: 6px; border-right: 0; border-bottom: 0; }
.kpi::after { bottom: 6px; right: 6px; border-left: 0; border-top: 0; }

/* ── Score de semelhança ─────────────────────────────────────────────────
   O amarelo de marca, com texto escuro por cima. O DOC_DESIGN é explícito:
   `#FFDE00` nunca leva texto branco. */
.score {
  background: var(--accent-brand-highlight); color: var(--sidebar-bg);
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 22px; font-weight: 600; letter-spacing: -.03em;
  padding: 4px 12px; border-radius: var(--raio-pequeno); line-height: 1.25;
}
.score .de { font-size: 12px; font-weight: 400; opacity: .6; }

/* ── Dois lados: o desenho e os dados ────────────────────────────────────
   Ecrã 5 do DOC_DESIGN — "documento original à esquerda, formulário à
   direita". A coluna do desenho fica colada ao topo: descer até às dimensões
   não pode deixar a folha para trás. */
.lado-a-lado { display: grid; align-items: start; gap: 18px;
               grid-template-columns: minmax(460px, 5fr) minmax(520px, 6fr); }
/* Sem isto, uma tabela larga empurra a coluna para fora do ecrã: por omissão
   um item de grelha nunca encolhe abaixo do seu conteúdo. É a tabela que
   passa a ter barra, não a página. */
.lado-a-lado > * { min-width: 0; }
.coluna-visor { position: sticky; top: 26px; }
/* Peças semelhantes (Etapa 1.3 do DOC_DESIGN): "à esquerda, resumo do
   pedido; à direita, as peças". O resumo não precisa da largura de um visor. */
.lado-a-lado.resumo-estreito { grid-template-columns: minmax(260px, 3fr) minmax(520px, 9fr); }
.coluna-resumo { position: sticky; top: 26px; }

/* ── Assistente de Novo Pedido: os três passos ────────────────────────────
   DOC_DESIGN Etapa 1: "wizard de 3 etapas com barra de progresso no topo". */
.wizard-progresso { display: flex; gap: 0; margin-bottom: 22px; }
.wizard-passo {
  display: flex; align-items: center; gap: 8px; flex: 1;
  font-size: 13px; color: var(--text-secondary);
  padding-bottom: 10px; border-bottom: 3px solid var(--border);
}
.wizard-passo .wizard-numero {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-secondary); color: var(--text-secondary);
  font-size: 12px; font-weight: 600;
}
.wizard-passo.feito { border-color: var(--success); color: var(--text-primary); }
.wizard-passo.feito .wizard-numero { background: var(--success-fraco); color: var(--success); }
.wizard-passo.atual { border-color: var(--accent-primary); color: var(--text-primary); font-weight: 600; }
.wizard-passo.atual .wizard-numero { background: var(--accent-primary); color: #FFF; }

/* A etiqueta de origem é o gesto: diz de onde veio o valor, e carregar nela
   põe essa folha no visor. */
.origem-ligada { border: 0; background: none; padding: 0; cursor: pointer;
                 font: inherit; text-align: left; }
.origem-ligada .selo { text-decoration: underline dotted; text-underline-offset: 2px; }
.origem-ligada:hover .selo { filter: brightness(.95); }
.linha-ligada { cursor: pointer; }

@media (max-width: 1180px) {
  .lado-a-lado { grid-template-columns: 1fr; }
  .coluna-visor, .coluna-resumo { position: static; }
}

/* Abaixo de 1280 px a aplicação sai do âmbito (DOC_DESIGN §2: desktop, mínimo
   1280). A sidebar encolhe para os ícones em vez de partir o ecrã. */
@media (max-width: 980px) {
  :root { --sidebar-largura: 60px; }
  .sidebar-marca .textos, .sidebar nav span:not(.marcador):not(.por-construir),
  .sidebar nav .grupo, .sidebar-rodape { display: none; }
  .sidebar nav a, .sidebar nav span.por-construir { justify-content: center; }
  main { padding: 18px 16px 50px; }
}

/* ── Painel lateral de detalhe rápido ────────────────────────────────────
   `UI_Spec` §4.2 / DOC_DESIGN Etapa 2: "ao clicar num cartão, abre um painel
   lateral de detalhe rápido à direita **sem sair da lista**". O ponto é esse:
   espreitar uma peça não pode custar perder os filtros e a posição na lista. */
.painel-rapido {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(420px, 92vw);
  background: var(--bg); border-left: 1px solid var(--border);
  box-shadow: -4px 0 16px rgba(26, 26, 26, .10);
  padding: 22px 24px; overflow-y: auto; z-index: 40;
  transform: translateX(100%); transition: transform .18s ease-out;
}
.painel-rapido[aberto] { transform: translateX(0); }
.painel-rapido .fechar {
  position: absolute; top: 14px; right: 16px; border: 0; background: none;
  font-size: 22px; line-height: 1; color: var(--text-secondary);
  cursor: pointer; padding: 4px 8px; width: auto;
}
.painel-rapido h2 { margin-top: 0; }
.painel-rapido .miniatura {
  width: 100%; max-height: 200px; object-fit: contain;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: var(--raio-pequeno); margin-bottom: 14px;
}
/* Quem prefere o teclado ou o rato do meio continua a abrir a ficha inteira:
   o cartão é um link a sério, e o painel é só o clique normal interceptado. */
.peca[data-peca], td [data-peca] { cursor: pointer; }

/* ── Foco por teclado ────────────────────────────────────────────────────
   `:focus-visible` e não `:focus`: o anel aparece a quem navega com Tab e
   não a quem clica. Os campos de formulário já têm o seu. */
a:focus-visible, button:focus-visible, summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-primary); outline-offset: 2px;
  border-radius: var(--raio-pequeno);
}

/* ── A roda de pontos: o botão que diz que está a trabalhar ─────────────
   Adaptado do dot-spinner de Uiverse.io (abrahamcalsin), trazido pelo Igor a
   2026-08-17. Da referência ficou a mecânica — oito pontos a pulsar em roda,
   desfasados um oitavo cada —; saíram o tamanho fixo, a cor própria e o
   brilho. `currentColor` para herdar branco no botão cheio e cinza no claro. */
.roda-pontos { --tam: 1em;
  position: relative; display: inline-block; flex: none;
  height: var(--tam); width: var(--tam); }
.roda-pontos i { position: absolute; inset: 0; display: block; }
.roda-pontos i::before {
  content: ""; position: absolute; left: 0; top: 50%; margin-top: -10%;
  height: 20%; width: 20%; border-radius: 50%;
  background: currentColor; opacity: .5; transform: scale(0);
  animation: roda-pulso 1s ease-in-out infinite;
}
.roda-pontos i:nth-child(2) { transform: rotate(45deg); }
.roda-pontos i:nth-child(3) { transform: rotate(90deg); }
.roda-pontos i:nth-child(4) { transform: rotate(135deg); }
.roda-pontos i:nth-child(5) { transform: rotate(180deg); }
.roda-pontos i:nth-child(6) { transform: rotate(225deg); }
.roda-pontos i:nth-child(7) { transform: rotate(270deg); }
.roda-pontos i:nth-child(8) { transform: rotate(315deg); }
.roda-pontos i:nth-child(2)::before { animation-delay: -.875s; }
.roda-pontos i:nth-child(3)::before { animation-delay: -.75s; }
.roda-pontos i:nth-child(4)::before { animation-delay: -.625s; }
.roda-pontos i:nth-child(5)::before { animation-delay: -.5s; }
.roda-pontos i:nth-child(6)::before { animation-delay: -.375s; }
.roda-pontos i:nth-child(7)::before { animation-delay: -.25s; }
.roda-pontos i:nth-child(8)::before { animation-delay: -.125s; }
@keyframes roda-pulso {
  0%, 100% { transform: scale(0); opacity: .5; }
  50% { transform: scale(1); opacity: 1; }
}

/* ── A torre: a espera da leitura em /pedido ────────────────────────────
   Adaptada do "3D tower loader" de Uiverse.io (csozidev), trazido pelo Igor a
   2026-08-17. Da referência ficou tudo o que interessa — os tijolos
   isométricos que chegam alternadamente da esquerda e da direita e assentam
   uns sobre os outros —; a cor passou a ser a família do laranja da marca e a
   escala desceu para caber num cartão sem gritar. É a imagem certa para este
   painel: a ficha está literalmente a ser construída camada a camada. */
.torre { position: relative; height: 50px; width: 40px;
         transform: scale(1.5); transform-origin: top left; }
.torre .caixa { position: relative; opacity: 0; left: 10px; }
.torre .lado-esq {
  position: absolute; background: #C25712; width: 19px; height: 5px;
  transform: skew(0deg, -25deg); top: 14px; left: 10px; }
.torre .lado-dir {
  position: absolute; background: #E96A1B; width: 19px; height: 5px;
  transform: skew(0deg, 25deg); top: 14px; left: -9px; }
.torre .lado-topo {
  position: absolute; background: var(--accent-primary); width: 20px;
  height: 20px; rotate: 45deg; transform: skew(-20deg, -20deg); }
.torre .caixa:nth-child(1) { animation: torre-esq 4s infinite; }
.torre .caixa:nth-child(2) { animation: torre-dir 4s infinite; animation-delay: 1s; }
.torre .caixa:nth-child(3) { animation: torre-esq 4s infinite; animation-delay: 2s; }
.torre .caixa:nth-child(4) { animation: torre-dir 4s infinite; animation-delay: 3s; }
@keyframes torre-esq {
  0%   { z-index: 20; opacity: 0; translate: -20px -6px; }
  20%  { z-index: 10; opacity: 1; translate: 0 0; }
  40%  { z-index: 9; translate: 0 4px; }
  60%  { z-index: 8; translate: 0 8px; }
  80%  { z-index: 7; opacity: 1; translate: 0 12px; }
  100% { z-index: 5; opacity: 0; translate: 0 30px; }
}
@keyframes torre-dir {
  0%   { z-index: 20; opacity: 0; translate: 20px -6px; }
  20%  { z-index: 10; opacity: 1; translate: 0 0; }
  40%  { z-index: 9; translate: 0 4px; }
  60%  { z-index: 8; translate: 0 8px; }
  80%  { z-index: 7; opacity: 1; translate: 0 12px; }
  100% { z-index: 5; opacity: 0; translate: 0 30px; }
}

/* ── A barra por critério, na decomposição do score ─────────────────────
   Pedida à letra pelo DOC_DESIGN (Etapa 1.3): "barras de progresso por
   critério". A barra mostra o `score` do critério — quão parecido é naquele
   eixo —; o número ao lado continua a ser o contributo em pontos. */
.criterio-barra { flex: 1 1 auto; height: 5px; border-radius: 3px;
                  background: var(--bg-secondary); overflow: hidden;
                  min-width: 60px; }
.criterio-barra > span { display: block; height: 100%; width: 0;
                         background: var(--accent-primary); border-radius: 3px;
                         transition: width var(--dur-2) var(--ease-suave); }

/* ── A zona de largar ficheiros ─────────────────────────────────────────
   DOC_DESIGN Etapa 1.1: a zona é "grande" e tem de dizer que é um destino.
   O estado `.sobre` põe-no em evidência enquanto um ficheiro paira. */
.zona-largar {
  border: 2px dashed var(--border); border-radius: var(--raio);
  padding: 34px 20px; text-align: center; background: var(--bg-secondary);
  cursor: pointer;
  transition: border-color var(--dur-1) ease, background-color var(--dur-1) ease,
              box-shadow var(--dur-1) ease;
}
.zona-largar:hover { border-color: #D3D8E0; }
.zona-largar.sobre {
  border-color: var(--accent-primary); border-style: solid;
  background: var(--accent-fraco); box-shadow: var(--sombra-media);
}

/* ── Grupos de campos num formulário ────────────────────────────────────
   Os títulos da Etapa 3.1 do DOC_DESIGN (Identificação · Material e processo
   · Geometria · Normas), no formulário de rever — a mesma arrumação da
   Ficha de Projeto, para as coisas estarem no mesmo sítio nos dois ecrãs. */
.grupo-campos {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-secondary); font-weight: 600;
  margin: 20px 0 12px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

/* ── O campo que foi mexido ─────────────────────────────────────────────
   No ecrã de rever, editar um campo é o momento em que a etiqueta passa a
   `manual` — e o tom de fundo diz isso no próprio campo, sem esperar pelo
   gravar. Se o valor voltar ao que era, o tom sai. */
.campo-editado input, .campo-editado select, .campo-editado textarea {
  background: var(--accent-fraco); border-color: #F0C9A8;
}

/* ── A barra de gravar, sempre à mão ────────────────────────────────────
   O formulário de rever é comprido; o botão de gravar não pode viver só no
   fundo da página. `sticky` e não `fixed`: cola-se ao fundo enquanto o
   formulário passa, e arruma-se quando o formulário acaba. */
.barra-gravar {
  position: sticky; bottom: 0; z-index: 30;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--raio); box-shadow: 0 -2px 10px rgba(26, 26, 26, .07);
  padding: 12px 20px; margin-bottom: 16px;
  display: flex; gap: 10px; align-items: center;
}

/* ── Ampliar uma miniatura ──────────────────────────────────────────────
   A lupa aparece no hover; carregar nela abre a folha em grande sem sair da
   lista. A miniatura serve para reconhecer; a lupa serve para confirmar. */
.moldura-ampliavel { position: relative; display: inline-block; }
.moldura-ampliavel .ampliar {
  position: absolute; right: 4px; bottom: 4px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border: 0; border-radius: var(--raio-pequeno);
  background: rgba(26, 26, 26, .72); color: #FFF; cursor: zoom-in; padding: 0;
  opacity: 0; transition: opacity var(--dur-1) ease,
                          background-color var(--dur-1) ease;
}
.moldura-ampliavel:hover .ampliar, .moldura-ampliavel .ampliar:focus-visible {
  opacity: 1; }
.moldura-ampliavel .ampliar:hover { background: rgba(26, 26, 26, .9); }
/* Na miniatura pequena da lista, a lupa encolhe com ela. */
td .moldura-ampliavel .ampliar { width: 20px; height: 20px; right: 2px; bottom: 2px; }

.luz-caixa {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(26, 26, 26, .78);
  display: flex; align-items: center; justify-content: center; padding: 28px;
  opacity: 0; transition: opacity var(--dur-2) ease;
}
/* Sem isto, o `display: flex` de cima anula o atributo `hidden` (os estilos
   de autor ganham aos do browser) e a caixa fica um vidro invisível por cima
   da página inteira, a engolir todos os cliques — aconteceu a 2026-08-17,
   e foi "não consigo clicar em nada" no ecrã do Igor. */
.luz-caixa[hidden] { display: none; }
.luz-caixa.a-ver { opacity: 1; }
.luz-caixa img {
  max-width: 100%; max-height: 100%; background: #FFF;
  border-radius: var(--raio-pequeno); box-shadow: 0 8px 40px rgba(0, 0, 0, .4);
  transform: scale(.97); transition: transform var(--dur-2) var(--ease-suave);
}
.luz-caixa.a-ver img { transform: scale(1); }
.luz-caixa .fechar-luz {
  position: absolute; top: 14px; right: 18px; border: 0; background: none;
  color: rgba(255, 255, 255, .85); font-size: 30px; line-height: 1;
  cursor: pointer; padding: 6px 10px; width: auto;
}
.luz-caixa .nota-luz { position: absolute; color: rgba(255, 255, 255, .8);
                       font-size: 14px; }

/* ── O percurso da cotação ──────────────────────────────────────────────
   Adaptado do "process tracker" (shadcn) que o Igor trouxe a 2026-08-17: cada
   linha desenha o seu conector, o feito leva visto e conector verde, o ativo
   pulsa, o pendente fica apagado. Da referência saíram o índigo e a Inter —
   as cores e a letra são as da casa — e o pulso do ativo é o laranja de
   marca, porque "por decidir" é chamada à ação, não um estado de erro. */
.percurso { list-style: none; margin: 0 0 18px; padding: 0; }
.percurso li { position: relative; padding: 0 0 18px 30px; }
.percurso li:last-child { padding-bottom: 2px; }
.percurso .marca {
  position: absolute; left: 0; top: 1px; width: 18px; height: 18px;
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--bg-secondary); border: 1.5px solid var(--border);
  color: #FFF; z-index: 1;
}
.percurso li::before {
  content: ""; position: absolute; left: 8.5px; top: 21px; bottom: 1px;
  width: 1.5px; background: var(--border);
}
.percurso li:last-child::before { display: none; }
.percurso li.feito .marca { background: var(--success); border-color: var(--success); }
.percurso li.feito::before { background: #BFE3CB; }
.percurso li.perdida .marca { background: var(--text-secondary);
                              border-color: var(--text-secondary); }
.percurso li.ativo .marca { background: var(--accent-primary);
                            border-color: var(--accent-primary); }
.percurso li.ativo .marca::after {
  content: ""; position: absolute; inset: -5px; border-radius: 50%;
  border: 2px solid rgba(255, 123, 43, .5);
  animation: percurso-pulso 1.8s ease-out infinite;
}
@keyframes percurso-pulso {
  0% { transform: scale(.6); opacity: 1; }
  70%, 100% { transform: scale(1.15); opacity: 0; }
}
.percurso .titulo { font-size: 14px; font-weight: 500; }
.percurso li.pendente .titulo { color: var(--text-secondary); font-weight: 400; }
.percurso .detalhe { font-size: 12.5px; color: var(--text-secondary); }

/* ═══════════════════════════════════════════════════════════════════════
   O REGISTO TÉCNICO — 2026-08-17

   O Igor pediu mais "wow" sem perder o profissionalismo. A resposta não é
   acrescentar efeito: é **ir buscar a linguagem ao próprio objeto**. Este
   produto vive de desenhos técnicos, e uma folha de desenho já tem um
   vocabulário visual próprio, sério e reconhecível — papel milimétrico,
   marcas de canto, campos numerados, cotas em monoespaçado.

   Nada disto contraria o DOC_DESIGN §3.3 (*"sem elementos decorativos
   desnecessários"*): não há gradientes de enfeite, brilhos nem sombras
   grandes. As cores continuam a ser as sete do documento. O que muda é a
   **composição** — que o documento não fixa (fixa os tokens e o conteúdo de
   cada ecrã).
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Papel milimétrico ───────────────────────────────────────────────────
   O fundo de uma folha de desenho. Tem de ser quase invisível: se se ler a
   grelha antes do conteúdo, está errada. Medida a 4% de preto sobre branco. */
.grelha-tecnica {
  background-image:
    linear-gradient(rgba(26, 26, 26, .038) 1px, transparent 1px),
    linear-gradient(90deg, rgba(26, 26, 26, .038) 1px, transparent 1px),
    linear-gradient(rgba(26, 26, 26, .022) 1px, transparent 1px),
    linear-gradient(90deg, rgba(26, 26, 26, .022) 1px, transparent 1px);
  background-size: 64px 64px, 64px 64px, 8px 8px, 8px 8px;
  background-position: -1px -1px;
}

/* ── Marcas de canto ─────────────────────────────────────────────────────
   Os cantos de registo de uma folha de desenho. São quatro cantoneiras em
   `::before`/`::after` de dois elementos — sem markup extra, sem imagens. */
.cantos { position: relative; }
.cantos::before, .cantos::after,
.cantos > .canto-b::before, .cantos > .canto-b::after {
  content: ""; position: absolute; width: 13px; height: 13px;
  border: 1.5px solid var(--border); pointer-events: none;
  transition: border-color var(--dur-2) var(--ease-suave);
}
.cantos::before { top: 9px; left: 9px; border-right: 0; border-bottom: 0; }
.cantos::after { top: 9px; right: 9px; border-left: 0; border-bottom: 0; }
.cantos > .canto-b::before { bottom: 9px; left: 9px; border-right: 0; border-top: 0; }
.cantos > .canto-b::after { bottom: 9px; right: 9px; border-left: 0; border-top: 0; }
/* Quando a zona está a receber alguma coisa, os cantos acendem — é o mesmo
   sinal do contorno, mas nas quatro esquinas, e lê-se antes do texto. */
.cantos.aceso::before, .cantos.aceso::after,
.cantos.aceso > .canto-b::before, .cantos.aceso > .canto-b::after {
  border-color: var(--accent-primary);
}

/* ── Cabeçalho de secção ─────────────────────────────────────────────────
   **Um só, para a plataforma inteira** — D-33, §8.1 das tarefas.

   Havia dois a fazer o mesmo trabalho: `.cartao h2` (27, cinzento e mudo) e
   `.secao` (5, numerada, só no assistente). O Igor leu isso como dois
   produtos colados, e tinha razão: a mesma pergunta — *"começa aqui uma
   secção"* — não pode ter duas respostas.

   O objeto é um só: **rótulo em maiúsculas · risca até à margem · nota à
   direita**. O que varia é uma coisa e só uma:

   - **O número `01` aparece onde há sequência** — um formulário que se
     preenche de cima para baixo (`/pedido`, o Passo 2, `/novo`, `/admin`, o
     registo de cotação). Ali o número é informação: diz quantos passos
     faltam.
   - **Não aparece em ecrã de consulta** — Ficha, Dashboard, Catálogo,
     Semelhantes, Revisão. Os blocos não se leem por ordem, e numerá-los
     prometia uma sequência que não existe (§8.7).

   A risca vem de um pseudo-elemento e não de markup: são 27 `<h2>` em nove
   ecrãs, e assim **nenhum precisou de ser tocado nem perdeu o `<h2>`** — que
   é o que um leitor de ecrã usa para saltar de secção em secção. O `order`
   põe a risca antes da nota da direita, mesmo estando depois dela na folha. */
/* **Revisto a 2026-08-24, por observação do Igor:** era 12.5px em maiúsculas
   espaçadas — mais *pequeno* do que o corpo de texto de 15px. Um título que é
   menor do que o texto que titula não se lê como título, e o ecrã fica uma
   folha plana. Agora é 16px, caixa normal, e a escala do produto é
   20 (h1) · 16 (secção) · 15 (corpo) · 13 (apoio) — razão ~1,2 entre degraus.
   A risca continua a fechar a linha; é ela que dá a banda de secção. */
.secao,
.cartao h2 {
  display: flex; align-items: center; gap: 12px;
  font-size: 16px; font-weight: 600; text-transform: none;
  letter-spacing: -.01em; color: var(--text-primary);
  margin: 0 0 14px;
}
/* `:not(:first-child)` e não `> :first-child`: apanha o cabeçalho esteja ele
   à profundidade que estiver. Era o que faltava aos três `style="margin-top"`
   escritos à mão que isto veio substituir. */
.secao:not(:first-child),
.cartao h2:not(:first-child) { margin-top: 26px; }

.secao::after,
.cartao h2::after {
  content: ""; order: 2; flex: 1 1 auto; height: 1px; background: var(--border);
}
/* O número. Só onde há sequência — ver o cabeçalho deste bloco. */
.secao .n {
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 12px; font-weight: 500; color: var(--accent-primary);
  background: var(--accent-fraco); border: 1px solid #F6DCC6;
  border-radius: 4px; padding: 1px 7px; flex: none;
  letter-spacing: 0; text-transform: none;
}
.secao .t { flex: none; }
/* A frase que explica a secção, debaixo do cabeçalho. Existe porque nove
   ecrãs a escreviam à mão com `style="margin-top:-6px; font-size:13px"` — e
   uma margem negativa repetida nove vezes é uma classe que falta. */
.secao-nota {
  margin: -8px 0 14px; font-size: 13px; color: var(--text-secondary);
  max-width: 78ch;
}
.secao-nota:last-child { margin-bottom: 0; }

.secao .nota,
.cartao h2 .nota {
  order: 3; flex: none; font-size: 12.5px; font-weight: 400;
  text-transform: none; letter-spacing: 0; color: var(--text-secondary);
}

/* ── Filtros ─────────────────────────────────────────────────────────────
   Duas formas, e uma só gramática: `.filtros` é a grelha de campos do catálogo
   (sete filtros, UI_Spec §4.2) e `.linha-filtro` é a variante de uma linha,
   para ecrãs com um ou dois. Vivem aqui e não dentro de um ecrã porque estavam
   dentro de um: o catálogo tinha rótulos de 11.5px em maiúsculas e a revisão
   tinha rótulos de 13px em caixa normal, a fazer o mesmo trabalho. */
.filtros { display: grid; gap: 12px;
           grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.filtros label,
.linha-filtro label { font-size: 11.5px; text-transform: uppercase;
                      letter-spacing: .05em; color: var(--text-secondary); }
.linha-filtro { display: flex; gap: 10px; align-items: end; flex-wrap: wrap;
                margin-bottom: 16px; }
.linha-filtro a { font-size: 13px; }

/* ── Miniatura de lista ──────────────────────────────────────────────────
   O `<img class="mini">` andava em três ecrãs **sem uma regra que o
   apanhasse**: a folha entrava na célula ao tamanho natural. Uma peça
   reconhece-se pela figura — uma referência `AC2026425` não diz nada a
   ninguém —, por isso a figura tem de ter medida fixa e caber inteira. */
img.mini {
  width: 62px; height: 44px; object-fit: contain;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 4px; display: block;
}
/* Lugar da figura quando ela não existe. Mantém a linha do mesmo tamanho:
   sem isto, uma lista com e sem figura salta de altura linha a linha. */
.mini-vazia {
  width: 62px; height: 44px; border: 1px dashed var(--border);
  border-radius: 4px; display: grid; place-items: center;
  color: #B6BCC6; font-size: 10.5px; letter-spacing: .02em;
}

/* ── Faixa de ação ───────────────────────────────────────────────────────
   Um estado que pede uma decisão, e o botão que a toma, na mesma faixa e no
   topo do ecrã. Nasceu do botão *Confirmar revisão*: era um `.botao.claro` de
   13px encolhido no meio dos chips do cabeçalho — a ação mais importante da
   ficha vestida de ação secundária. Aqui não se perde. */
.faixa-accao {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  background: var(--warning-fraco); border: 1px solid #F0DCBA;
  border-left: 1px solid #F0DCBA;
  border-radius: var(--raio); padding: 14px 18px; margin-bottom: 16px;
}
.faixa-accao .texto { flex: 1 1 320px; min-width: 0; }
.faixa-accao .texto strong { display: block; font-size: 15px; }
.faixa-accao .texto span { font-size: 13px; color: var(--text-secondary); }
.faixa-accao form { width: auto; margin: 0; flex: none; }
/* Confirmada, a mesma faixa fica verde e sem botão — o estado vê-se, e o
   sítio onde ele se vê não muda. */
.faixa-accao.feita { background: var(--success-fraco); border-color: #C6E7D2; }

/* ── Zona de largar, versão grande ───────────────────────────────────────
   O DOC_DESIGN Etapa 1.1 pede-a **grande**, e a versão anterior era uma
   caixa tracejada modesta debaixo de dois parágrafos: a hierarquia estava
   invertida, porque a tarefa deste ecrã é largar um ficheiro. */
.zona-largar.grande {
  padding: 44px 24px 40px;
  /* `background-color` e **não** o atalho `background`: o atalho apagaria o
     `background-image` do papel milimétrico que vem da `.grelha-tecnica`.
     Aconteceu ao construir isto, e a grelha desapareceu em silêncio. */
  background-color: var(--bg);
  border-color: #D8DDE5;
}
.zona-largar.grande.sobre { background-color: var(--accent-fraco); }
.zona-largar.grande .icone-largar {
  color: var(--text-secondary); margin-bottom: 12px;
  transition: color var(--dur-2) var(--ease-suave),
              transform var(--dur-2) var(--ease-suave);
}
.zona-largar.grande.sobre .icone-largar {
  color: var(--accent-primary); transform: translateY(-3px);
}
.zona-largar.grande .frase {
  font-size: 18px; font-weight: 600; letter-spacing: -.01em;
  color: var(--text-primary);
}
.zona-largar.grande .sub { font-size: 13.5px; color: var(--text-secondary);
                           margin-top: 5px; }
/* Os formatos como etiquetas de ficheiro, em monoespaçado — não como uma
   frase corrida. Um formato é um facto, e lê-se de relance. */
.formatos { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
            margin-top: 16px; }
.formatos span {
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 11.5px; color: var(--text-secondary);
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 4px; padding: 2px 8px;
}
.zona-largar.grande.sobre .formatos span { border-color: #F0C9A8; }

/* Com ficheiros na fila, a caixa muda de estado: contorno firme da cor da
   marca, fundo tingido, e a frase passa a dizer a contagem (o JS troca-a).
   O tracejado é a promessa "podes largar aqui"; cumprida, deixa de o ser. */
.zona-largar.grande.com-ficheiros {
  border-style: solid; border-color: var(--accent-primary);
  background-color: var(--accent-fraco);
}
.zona-largar.grande.com-ficheiros .icone-largar { color: var(--accent-primary); }
.zona-largar.grande.com-ficheiros .formatos span { border-color: #F0C9A8; }

/* A lista do que já entrou: uma linha por ficheiro, com a marca verde a
   dizer "está cá dentro". A tabela anónima de antes lia-se como decoração. */
.lista-ficheiros { border: 1px solid var(--border); border-radius: var(--raio-pequeno);
                   overflow: hidden; }
.lista-ficheiros td { padding: 10px 12px; }
.lista-ficheiros tr + tr td { border-top: 1px solid var(--border); }
.lista-ficheiros .ok-marca { width: 1%; padding-right: 0; color: var(--success); }
.lista-ficheiros .ok-marca svg { display: block; }
.lista-ficheiros .nome { font-weight: 600; }

/* ── Estado vazio, com registo técnico ───────────────────────────────────
   §8.5 das tarefas. Um cartão vazio era uma linha de texto cinzento a boiar
   no branco — e um estado vazio é **a primeira coisa que se vê num sistema
   novo**: é ele que diz se falta trabalho ou se falta o sistema.

   É a superfície mais parecida com a zona de largar — espaço em branco à
   espera de uma ação —, por isso leva a mesma grelha e as mesmas cantoneiras.
   **O que não leva é o tracejado:** esse fica reservado ao que se pode
   largar. Um estado vazio tracejado prometia um alvo que não existe.

   Contaram-se 24 sítios com `.vazio`, e a maioria **não** é isto: um traço
   dentro de uma célula de tabela é um valor em falta, não um ecrã vazio. Isto
   é só para o bloco que ocupa o cartão inteiro. */
.vazio-tecnico {
  padding: 34px 26px 30px; text-align: center;
  border: 1px solid var(--border); border-radius: var(--raio-pequeno);
  /* `background-color` e não o atalho — ver a nota da `.zona-largar.grande`:
     `background` apaga o `background-image` da grelha em silêncio. */
  background-color: var(--bg-secondary);
}
.vazio-tecnico .frase {
  font-size: 15px; font-weight: 600; color: var(--text-primary);
}
.vazio-tecnico .sub {
  font-size: 13.5px; color: var(--text-secondary); margin: 7px auto 0;
  max-width: 56ch; line-height: 1.55;
}
.vazio-tecnico .accao { margin-top: 17px; }
.vazio-tecnico pre { text-align: left; margin: 14px auto 0; max-width: 60ch; }

/* ── Interruptor ─────────────────────────────────────────────────────────
   Substitui a caixa de verificação dentro de um bloco âmbar. O bloco âmbar
   era o elemento mais berrante do ecrã e é uma **definição**, não a ação —
   a cor de aviso passa a viver só na linha que descreve a consequência. */
.interruptor { display: inline-flex; align-items: center; gap: 11px;
               cursor: pointer; user-select: none; }
.interruptor input { position: absolute; opacity: 0; width: 0; height: 0; }
.interruptor .calha {
  width: 38px; height: 21px; border-radius: 999px; flex: none;
  background: #D3D8E0; position: relative;
  transition: background-color var(--dur-2) var(--ease-suave);
}
.interruptor .calha::after {
  content: ""; position: absolute; top: 2.5px; left: 2.5px;
  width: 16px; height: 16px; border-radius: 50%; background: #FFF;
  box-shadow: 0 1px 2px rgba(26, 26, 26, .25);
  transition: transform var(--dur-2) var(--ease-suave);
}
.interruptor input:checked + .calha { background: var(--accent-primary); }
.interruptor input:checked + .calha::after { transform: translateX(17px); }
.interruptor input:focus-visible + .calha {
  outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.interruptor input:disabled + .calha { opacity: .45; }
.interruptor .rotulo { font-size: 14px; font-weight: 500; }

/* ── Cabeçalho de ecrã, com sobrancelha ──────────────────────────────────
   Uma linha em maiúsculas monoespaçadas por cima do título: diz em que
   parte do sistema se está, sem gastar uma linha de prosa. */
.cabecalho .sobrancelha {
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 11px; text-transform: uppercase; letter-spacing: .14em;
  color: var(--text-secondary); display: block; margin-bottom: 3px;
}
.cabecalho .titulo-bloco { flex: none; }
.cabecalho .titulo-bloco h1 { margin: 0; }

/* ── Nota dobrável ───────────────────────────────────────────────────────
   A prosa que explicava o ecrã antes de se poder agir. Continua toda lá —
   passa a estar debaixo de um resumo de uma linha, que se abre a quem for
   novo e não estorva quem já sabe. */
.nota-dobravel { border: 1px solid var(--border); border-radius: var(--raio-pequeno);
                 background: var(--bg-secondary); margin-bottom: 18px; }
.nota-dobravel > summary {
  cursor: pointer; padding: 9px 14px; font-size: 13.5px;
  color: var(--text-secondary); list-style: none; display: flex;
  align-items: center; gap: 8px;
}
.nota-dobravel > summary::-webkit-details-marker { display: none; }
.nota-dobravel > summary::before {
  content: "?"; font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 11px; font-weight: 600; color: var(--text-secondary);
  border: 1px solid var(--border); border-radius: 50%; background: var(--bg);
  width: 17px; height: 17px; display: inline-flex; align-items: center;
  justify-content: center; flex: none;
}
.nota-dobravel[open] > summary { color: var(--text-primary);
                                 border-bottom: 1px solid var(--border); }
.nota-dobravel .corpo { padding: 12px 14px 14px; font-size: 14px;
                        color: var(--text-secondary); }
.nota-dobravel .corpo p { margin: 0 0 8px; }
.nota-dobravel .corpo p:last-child { margin-bottom: 0; }

/* ── Voltar atrás ───────────────────────────────────────────────────────
   Um só, na moldura, em todos os ecrãs. Discreto: é uma saída de emergência,
   não um elemento de navegação principal — a sidebar é que navega. */
.voltar-atras {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1.5px solid var(--border); background: var(--bg);
  color: var(--text-primary); border-radius: 999px;
  font: inherit; font-size: 14px; font-weight: 600;
  padding: 8px 18px; cursor: pointer;
  margin: 16px 0 0 26px; align-self: flex-start;
  box-shadow: 0 1px 4px rgba(26, 26, 26, .06);
  transition: color var(--dur-1) var(--ease-suave),
              border-color var(--dur-1) var(--ease-suave),
              box-shadow var(--dur-1) var(--ease-suave);
}
.voltar-atras:hover { color: var(--accent-primary);
                      border-color: var(--accent-primary);
                      box-shadow: var(--sombra-media); }
@media print { .voltar-atras { display: none !important; } }

/* ── Tabelas com campos editáveis ───────────────────────────────────────
   Materiais e dimensões do ecrã de rever: os inputs encolhem para a linha
   da tabela não rebentar, e a coluna "tirar" fica discreta. */
.tabela-editavel input, .tabela-editavel select {
  padding: 5px 7px; font-size: 13px; min-width: 56px; width: 100%; }
.tabela-editavel td { vertical-align: middle; }

/* ── Tosta: o aviso que não rouba a página ──────────────────────────────
   Os erros de gravação apareciam como uma página preta de JSON (visto pelo
   Igor a 2026-08-18). Um aviso é uma frase, não um destino: fica por cima do
   ecrã, com o trabalho intacto por baixo. */
.tosta {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 12px);
  z-index: 60; display: flex; align-items: center; gap: 12px;
  max-width: min(560px, calc(100vw - 32px));
  background: var(--warning-fraco); border: 1px solid var(--warning);
  border-radius: var(--raio); padding: 12px 14px; font-size: 14px;
  color: var(--text-primary); box-shadow: 0 6px 24px rgba(26, 26, 26, .18);
  opacity: 0; transition: opacity var(--dur-2) var(--ease-suave),
                          transform var(--dur-2) var(--ease-suave);
}
.tosta.a-ver { opacity: 1; transform: translate(-50%, 0); }
.tosta-fechar {
  border: 0; background: none; font: inherit; font-size: 18px; line-height: 1;
  color: var(--text-secondary); cursor: pointer; padding: 0 2px; flex: none;
}
.tosta-fechar:hover { color: var(--text-primary); }

/* ── Chips: uma lista que se lê e se apaga um a um ──────────────────────
   As normas de um desenho chegam às vinte; numa caixa de texto corrida
   ninguém as confere. Cada valor é uma etiqueta: a cruz tira-a, o duplo
   clique edita-a, o campo do fim acrescenta. O input verdadeiro fica
   escondido e é ele que o formulário submete. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
         border: 1px solid var(--border); border-radius: var(--raio-pequeno);
         background: var(--bg); padding: 7px 8px; }
/* Cor explícita: os chips vivem dentro de zonas de formulário com heranças
   próprias, e a primeira versão saía com o texto quase invisível (screenshot
   do Igor, 2026-08-18). Aqui nada se herda.
   E `.chips .chip`, não `.chip`: sem o prefixo, esta regra — que vem mais
   abaixo no ficheiro — reescrevia a cor dos chips de atributo da tabela
   (texto escuro sobre azul escuro; screenshot do Igor, 2026-08-21). Os chips
   editáveis vivem sempre dentro de `.chips`; os de atributo, nunca. */
.chips .chip { display: inline-flex; align-items: center; gap: 5px;
        border: 1px solid var(--border); border-radius: 999px;
        background: var(--bg-secondary); color: var(--text-primary);
        padding: 2px 4px 2px 10px;
        font-size: 13px; line-height: 1.6; cursor: default;
        transition: border-color var(--dur-1) var(--ease-suave); }
.chips .chip:hover { border-color: var(--accent-primary); }
.chip-tirar { border: 0; background: none; font: inherit; font-size: 14px;
              line-height: 1; color: var(--text-secondary); cursor: pointer;
              padding: 2px 5px; border-radius: 50%; }
.chip-tirar:hover { color: var(--danger, #b3261e); }
.chips-novo { border: 0 !important; outline: none; background: none;
              font: inherit; font-size: 13px; color: var(--text-primary);
              flex: 1 1 90px; min-width: 90px;
              padding: 2px 4px !important; box-shadow: none !important; }
.chip-editar { font-size: 12.5px; padding: 2px 8px !important;
               border-radius: 999px !important; width: auto; }

/* ── Dicas: a explicação ao pé do termo ─────────────────────────────────
   O termo fica com pontilhado por baixo e a frase em `data-dica`. O `title`
   nativo levava ~1 s a aparecer e não se estiliza (pedido do Igor,
   2026-08-21). Referência visual dele, adaptada às cores da plataforma:
   painel escuro, canto largo, seta, sombra suave com um resto de laranja.
   Só CSS: aparece rápido, sai rápido, e funciona com teclado (focus). */
.dica {
  position: relative;
  text-decoration: underline dotted; text-underline-offset: 3px;
  cursor: help;
}
.dica::after {
  content: attr(data-dica);
  position: absolute; bottom: calc(100% + 10px); left: 50%;
  transform: translate(-50%, 5px);
  width: 264px; padding: 10px 13px;
  background: linear-gradient(135deg, rgba(33, 33, 38, .97), rgba(24, 24, 28, .97));
  color: #E7E8EB; border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 12px;
  font-size: 12.5px; font-weight: 400; line-height: 1.55;
  font-family: "Fira Sans", system-ui, sans-serif;
  text-align: left; text-transform: none; letter-spacing: normal;
  white-space: normal; text-decoration: none;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .32), 0 0 22px rgba(255, 123, 43, .10);
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 70;
  transition: opacity var(--dur-1) ease-out, transform var(--dur-1) ease-out,
              visibility 0s linear var(--dur-1);
}
/* A seta: um quadrado rodado com o mesmo fundo e a mesma borda. */
.dica::before {
  content: ""; position: absolute; bottom: calc(100% + 6px); left: 50%;
  width: 9px; height: 9px;
  transform: translate(-50%, 5px) rotate(45deg);
  background: rgba(24, 24, 28, .97);
  border-right: 1px solid rgba(255, 255, 255, .13);
  border-bottom: 1px solid rgba(255, 255, 255, .13);
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 71;
  transition: opacity var(--dur-1) ease-out, transform var(--dur-1) ease-out,
              visibility 0s linear var(--dur-1);
}
.dica:hover::after, .dica:focus-visible::after {
  opacity: 1; visibility: visible; transform: translate(-50%, 0);
  transition-delay: .06s;
}
.dica:hover::before, .dica:focus-visible::before {
  opacity: 1; visibility: visible; transform: translate(-50%, 0) rotate(45deg);
  transition-delay: .06s;
}

/* ── Movimento: o interruptor geral ─────────────────────────────────────
   Quem pediu menos movimento ao sistema operativo recebe a plataforma
   quieta: os estados continuam todos lá, só que instantâneos. É um bloco só
   para não haver animação que se esqueça dele. O visor 3D lê a mesma
   preferência no JS (roda automática desligada). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
