/* Design system do Portal FertMinas — tokens extraídos de c:\Portal\modelo.html
   (CLAUDE.md §7). Fidelidade estrita: hierarquia por tipografia e hairlines,
   nunca blocos de cor preenchidos; verde da marca só como traço/ação. */

:root {
  --fm-bg: #f3f2f2;
  --fm-panel: #eae9e9;
  --fm-card: transparent;
  --fm-line: rgba(29, 33, 31, .16);
  --fm-fg: #1d211f;
  --fm-muted: #6b6f6c;
  --fm-accent: #446A5F;
  --fm-accent-fg: #f4f6f4;
  --fm-accent-soft: rgba(68, 106, 95, .08);
  --fm-rail: #2C463E;
  --fm-rail-fg: rgba(244, 246, 244, .6);
  --fm-rail-active: #a9cc74;
  --fm-input: #ffffff;
  --fm-ok: #628132;
  --fm-warn: #B07A22;
  --fm-warn-fg: #8a5d15;
  --fm-alarm: #A4463A;
  --fm-idle: #899B94;
  --fm-grid: rgba(29, 33, 31, .1);

  /* Papel/tinta da assinatura desenhada (.fm-signature, seção 12) — NÃO é
     superfície de interface, é artefato documental: o PNG vira anexo cifrado
     em `documents` e ganha marca d'água por cima. Por isso é INVARIANTE ao
     tema, exatamente como o trilho e o painel do login (CLAUDE.md §7.4) — uma
     assinatura clara sobre papel preto seria ilegível no PDF impresso. */
  --fm-signature-paper: #ffffff;
  --fm-signature-ink: #1d211f;

  /* ATENÇÃO (2026-08-17, Agente Visual): a Montserrat NÃO está vendorizada em
     static/fonts/ nem carregada por @font-face — hoje o Portal cai no
     system-ui em qualquer máquina que não tenha a fonte instalada, o que
     contraria "Montserrat exclusivamente" (CLAUDE.md §7). Correção pendente:
     baixar os pesos 300/400/500/600 (woff2, subset latin+latin-ext) para
     static/fonts/ e declarar @font-face aqui — mesmo padrão "vendorizado
     localmente, sem CDN" já usado para htmx/Alpine/Chart.js/Lucide. */
  --fm-font: Montserrat, system-ui, sans-serif;
  --fm-radius: 4px;
  --fm-rail-width: 64px;
  --fm-menu-width: 230px;
}

/* ===========================================================================
   DARK MODE (2026-08-18) — dinâmico: segue o SO por padrão, com escolha
   explícita do usuário (fm-theme-toggle no rodapé do trilho) sobrepondo e
   persistindo em localStorage (chave "fm-theme"). Padrão de 3 camadas —
   mesmo contrato usado em qualquer página com tema client-side:
     1. :root (acima) = tema claro, sempre o default sem JS/preferência algum.
     2. @media (prefers-color-scheme: dark), guardado por :not([data-theme="light"])
        = aplica escuro quando o SO pede E o usuário não fixou claro.
     3. :root[data-theme="dark"] = escolha explícita do usuário, vence sempre.
   `--fm-rail`/`--fm-rail-fg`/`--fm-rail-active` (trilho) e o painel visual do
   login (.fm-auth-visual, sempre escuro com imagem+scrim) são chrome de marca
   e NUNCA mudam entre temas — só a superfície de conteúdo (bg/panel/fg/...)
   inverte. Ver templates/base.html para o script de FOUC (aplica o atributo
   ANTES do primeiro paint) e fm-components.js::FmThemeToggle para o botão. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fm-bg: #15181a;
    --fm-panel: #1d2224;
    --fm-line: rgba(244, 246, 244, .14);
    --fm-fg: #eef0ee;
    --fm-muted: #999d97;
    --fm-accent: #7bab98;
    --fm-accent-fg: #0e1512;
    --fm-accent-soft: rgba(123, 171, 152, .14);
    --fm-input: #1b1f21;
    --fm-ok: #8bc34f;
    --fm-warn: #e0a542;
    --fm-warn-fg: #f0be6c;
    --fm-alarm: #e2685c;
    --fm-idle: #9a9d97;
    --fm-grid: rgba(244, 246, 244, .1);
  }
}
:root[data-theme="dark"] {
  --fm-bg: #15181a;
  --fm-panel: #1d2224;
  --fm-line: rgba(244, 246, 244, .14);
  --fm-fg: #eef0ee;
  --fm-muted: #999d97;
  --fm-accent: #7bab98;
  --fm-accent-fg: #0e1512;
  --fm-accent-soft: rgba(123, 171, 152, .14);
  --fm-input: #1b1f21;
  --fm-ok: #8bc34f;
  --fm-warn: #e0a542;
  --fm-warn-fg: #f0be6c;
  --fm-alarm: #e2685c;
  --fm-idle: #9a9d97;
  --fm-grid: rgba(244, 246, 244, .1);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fm-bg);
  color: var(--fm-fg);
  font-family: var(--fm-font);
  font-size: 14px;
  line-height: 1.6;
  overflow-x: hidden;
  transition: background-color .15s ease, color .15s ease;
}

/* Defesa contra rolagem horizontal: grid/flex item sem min-width:0 usa o
   tamanho intrínseco do conteúdo (texto longo, JSON solto etc.) e pode
   estourar a coluna reservada — bug real visto ao vivo em 2026-08-14. */
.fm-shell__main > *, .fm-shell__main { min-width: 0; }
.fm-card { overflow-wrap: break-word; min-width: 0; }

a { color: var(--fm-accent); }

/* --- Layout de 3 camadas: trilho + menu + conteúdo (CLAUDE.md §7) ---
   Trilho é position:fixed e expande no hover (regra do usuário, 2026-08-14) —
   por isso fica FORA do grid; .fm-shell só reserva o espaço com margin-left. */
.fm-shell {
  min-height: 100vh;
}

.fm-shell__main {
  display: grid;
  grid-template-columns: var(--fm-menu-width) 1fr;
  margin-left: var(--fm-rail-width);
  min-height: 100vh;
}

.fm-rail {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--fm-rail-width);
  background: var(--fm-rail);
  color: var(--fm-rail-fg);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 16px 0;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 50;
  transition: width .15s ease;
  /* Barra de rolagem escondida de propósito (decisão de 2026-08-14) — com 24
     itens ela ficava sobrepondo os ícones (scrollbar do Windows/Edge é
     overlay, desenha por cima do conteúdo em vez de reservar espaço). Rolar
     com o mouse/trackpad continua funcionando normalmente, só o indicador
     visual some — mesmo padrão de trilhos compactos tipo VS Code. */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* Edge legado */
}
.fm-rail:hover { width: 240px; }
.fm-rail::-webkit-scrollbar { display: none; /* Chrome/Edge/Safari */ }
.fm-rail__top, .fm-rail__bottom { display: flex; flex-direction: column; gap: 2px; }
.fm-rail__bottom { padding-top: 10px; border-top: 1px solid rgba(244, 246, 244, .12); margin-top: 10px; }
.fm-rail__bottom form { display: contents; }

.fm-menu {
  background: var(--fm-panel);
  border-right: 1px solid var(--fm-line);
  padding: 24px 16px;
  /* Coluna: o rodapé de usuário usa margin-top:auto para colar embaixo.
     Estava como style inline em templates/_shell.html até 2026-08-17 —
     regra do projeto é CSS em arquivo, nunca inline (CLAUDE.md §11d). */
  display: flex;
  flex-direction: column;
}
.fm-menu__area-name { font-weight: 600; font-size: 16px; margin-top: 3px; }

.fm-content {
  padding: 32px 40px;
}

.fm-page-title {
  font-weight: 300;
  font-size: 32px;
  letter-spacing: -.025em;
  margin: 0 0 24px;
  border-bottom: 1px solid var(--fm-line);
  padding-bottom: 16px;
}

.fm-block-title {
  font-size: 18px;
  font-weight: 600;
  margin: 0 0 12px;
}

.fm-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--fm-muted);
}

.tnum { font-variant-numeric: tabular-nums; }

/* --- Formulário --- */
.fm-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.fm-field label { font-size: 12px; color: var(--fm-muted); }
.fm-field input, .fm-field select, .fm-field textarea {
  font-family: var(--fm-font);
  font-size: 14px;
  padding: 10px 12px;
  border: 1px solid var(--fm-line);
  border-radius: var(--fm-radius);
  background: var(--fm-input);
  color: var(--fm-fg);
}
.fm-field input:focus, .fm-field select:focus, .fm-field textarea:focus {
  outline: 2px solid var(--fm-accent-soft);
  border-color: var(--fm-accent);
}

.fm-btn {
  font-family: var(--fm-font);
  font-size: 14px;
  padding: 10px 20px;
  border-radius: var(--fm-radius);
  border: 1px solid var(--fm-accent);
  background: var(--fm-accent);
  color: var(--fm-accent-fg);
  cursor: pointer;
}
.fm-btn:hover { opacity: .92; }
.fm-btn--secondary {
  background: transparent;
  color: var(--fm-fg);
  border-color: var(--fm-line);
}

.fm-error {
  color: var(--fm-alarm);
  font-size: 13px;
  margin-top: 8px;
}

/* --- Card (nunca preenchido de cor — só hairline) --- */
.fm-card {
  border: 1px solid var(--fm-line);
  border-radius: var(--fm-radius);
  padding: 20px;
}

/* --- Web Components (static/js/components/fm-components.js) ---
   Estrutura fiel ao W1/W2 de modelo.html (extraído em 2026-08-14): rail
   ícone-only (Lucide), menu 230px texto puro em grupos, avatar no rodapé do
   menu (não no header). */
.fm-rail__logo { width: 30px; margin: 6px auto 20px; display: block; flex-shrink: 0; }

.fm-rail-item {
  display: flex;
  align-items: center;
  height: 40px;
  margin: 1px 8px;
  border-radius: 8px;
  color: var(--fm-rail-fg);
  text-decoration: none;
  white-space: nowrap;
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--fm-font);
  font-size: 13px;
  text-align: left;
  overflow: hidden;
  opacity: .82;
}
.fm-rail-item:hover { opacity: 1; background: rgba(244, 246, 244, .06); }
/* Slot de ícone com largura FIXA — o ícone sempre centraliza aqui, não importa
   se o trilho está colapsado (64px) ou expandido no hover (240px). Antes o
   ícone era posicionado por padding calculado à mão, o que cortava/descentralizava
   (bug real visto ao vivo em 2026-08-14) — slot fixo é robusto por construção. */
.fm-rail-item__icon-slot {
  flex: 0 0 48px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fm-rail-item svg { width: 17px; height: 17px; flex-shrink: 0; }
/* fundo do item ativo usa o verde-folha (#7BA33D) translúcido; o ÍCONE em si
   usa --fm-rail-active (#a9cc74) — são tokens diferentes, replicando o mockup. */
.fm-rail-item--active { background: rgba(123, 163, 61, .22); color: var(--fm-rail-active); opacity: 1; }
.fm-rail-item--active:hover { background: rgba(123, 163, 61, .28); }
.fm-rail-item__label {
  opacity: 0;
  max-width: 0;
  overflow: hidden;
  transition: opacity .1s ease, max-width .15s ease;
}
.fm-rail:hover .fm-rail-item__label { opacity: 1; max-width: 160px; }
.fm-rail__top { gap: 1px; padding-top: 2px; }

/* Toggle de tema (fm-components.js::FmThemeToggle) — mesma marcação de
   fm-rail-item, só troca qual dos dois ícones (lua/sol) fica visível via CSS
   puro em cima do atributo data-theme já usado pela cascata de cores acima,
   sem precisar chamar lucide.createIcons() de novo a cada clique. */
.fm-theme-toggle__icon--light { display: none; }
:root[data-theme="dark"] .fm-theme-toggle__icon--dark { display: none; }
:root[data-theme="dark"] .fm-theme-toggle__icon--light { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .fm-theme-toggle__icon--dark { display: none; }
  :root:not([data-theme="light"]) .fm-theme-toggle__icon--light { display: block; }
}

.fm-menu__section-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--fm-muted);
  margin: 0 0 8px;
}
.fm-menu__group { display: flex; flex-direction: column; gap: 1px; margin-bottom: 14px; }
.fm-menu__rule { height: 1px; background: var(--fm-line); margin: 14px 0; }

.fm-menu-item {
  display: block;
  padding: 9px 10px;
  border-left: 2px solid transparent;
  color: var(--fm-fg);
  text-decoration: none;
  font-size: 13px;
}
.fm-menu-item:hover { background: var(--fm-accent-soft); }
.fm-menu-item--active { background: var(--fm-accent-soft); color: var(--fm-fg); border-left-color: var(--fm-accent); font-weight: 600; }

.fm-menu__user {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  text-decoration: none;
  color: var(--fm-fg);
  padding-top: 14px;
}
.fm-avatar {
  width: 32px;
  height: 32px;
  min-width: 32px;
  border-radius: 50%;
  border: 1px solid var(--fm-line);
  display: grid;
  place-items: center;
  font-weight: 600;
  font-size: 12px;
  background: var(--fm-bg);
}
.fm-menu__user-name { line-height: 1.35; }
.fm-menu__user-role { font-size: 10px; color: var(--fm-muted); display: block; }

/* --- Header do conteúdo (busca + sino + ação primária, sem avatar) --- */
.fm-content-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--fm-line);
  padding-bottom: 18px;
  margin-bottom: 24px;
}
/* Sem `min-width: 0`, o bloco do título não encolhe abaixo do próprio conteúdo
   e empurra as ações para fora da linha — visível assim que um título real de
   licença entra no lugar do texto curto de exemplo. */
.fm-content-header > :first-child { min-width: 0; }
.fm-content-header__eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--fm-accent);
}
/* Medida de linha limitada: título de 32px/300 atravessando 1400px não se lê.
   Nome real de documento regulatório tem 60–90 caracteres e quebra em duas
   linhas — daí a line-height apertada (1.15), que a 32px continua confortável
   e evita o buraco vertical do valor herdado do corpo de texto.
   `anywhere` cobre número de protocolo comprido sem espaço. */
.fm-content-header__title {
  font-weight: 300; font-size: 32px; margin-top: 8px;
  line-height: 1.15; max-width: 40ch; overflow-wrap: anywhere;
}
.fm-content-header__actions { display: flex; gap: 10px; align-items: center; }
.fm-icon-btn {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  background: transparent;
  border: 1px solid var(--fm-line);
  border-radius: var(--fm-radius);
  cursor: pointer;
  color: var(--fm-fg);
}
.fm-icon-btn svg { width: 16px; height: 16px; }

/* --- KPI cards --- */
.fm-kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 24px; }
.fm-kpi-card { border: 1px solid var(--fm-line); border-top: 2px solid var(--fm-accent); border-radius: var(--fm-radius); padding: 14px 16px; }
.fm-kpi-card--ok { border-top-color: var(--fm-ok); }
.fm-kpi-card--warn { border-top-color: var(--fm-warn); }
.fm-kpi-card--alarm { border-top-color: var(--fm-alarm); }
.fm-kpi-card__label { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
/* overflow-wrap: anywhere — achado em 2026-08-18 (PCP, dado histórico real):
   número grande sem espaço (ex. "R$ 11.059.897,00") não tem ponto de quebra
   natural e transbordava o card. Quebra em 2 linhas em vez de estourar o
   layout ou truncar um valor financeiro/quantidade real. */
.fm-kpi-card__value { font-weight: 500; font-size: 32px; line-height: 1.3; overflow-wrap: anywhere; }

/* --- Módulos / cards de ferramenta --- */
.fm-module-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 14px; }
.fm-module-card { border: 1px solid var(--fm-line); border-radius: var(--fm-radius); padding: 16px; text-decoration: none; color: var(--fm-fg); display: block; }
.fm-module-card svg { color: var(--fm-accent); width: 20px; height: 20px; }
.fm-module-card__title { font-weight: 600; font-size: 14px; margin-top: 10px; }
.fm-module-card__subtitle { font-size: 11px; color: var(--fm-muted); margin-top: 2px; }

/* --- Timeline de avisos --- */
.fm-timeline-item { border-left: 2px solid var(--fm-line); padding-left: 12px; margin-bottom: 16px; }
.fm-timeline-item--alarm { border-left-color: var(--fm-alarm); }
.fm-timeline-item--warn { border-left-color: var(--fm-warn); }
.fm-timeline-item--ok { border-left-color: var(--fm-ok); }
.fm-timeline-item__meta { font-size: 10px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }
.fm-timeline-item--alarm .fm-timeline-item__meta { color: var(--fm-alarm); }
.fm-timeline-item--warn .fm-timeline-item__meta { color: var(--fm-warn); }
.fm-timeline-item--ok .fm-timeline-item__meta { color: var(--fm-ok); }
.fm-timeline-item__body { font-size: 12px; line-height: 1.55; margin-top: 4px; }
.fm-empty-state { font-size: 12px; color: var(--fm-muted); }

/* --- Campos soltos fora de .fm-field (ex.: linhas de participante externo)
   precisam do mesmo tratamento visual — sem isso ficam com o estilo padrão
   do navegador, quebrando o alinhamento com o resto do formulário. --- */
.fm-inline-fields input, .fm-inline-fields select {
  width: 100%;
  font-family: var(--fm-font);
  font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--fm-line);
  border-radius: var(--fm-radius);
  background: var(--fm-input);
  color: var(--fm-fg);
}

/* --- Participante pesquisável (Alpine.js) --- */
.fm-search-results {
  max-height: 160px;
  overflow-y: auto;
  border: 1px solid var(--fm-line);
  border-radius: var(--fm-radius);
  margin-top: 4px;
}
.fm-search-results__item { padding: 8px 10px; font-size: 12px; cursor: pointer; }
.fm-search-results__item:hover { background: var(--fm-accent-soft); }
.fm-chip-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.fm-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border: 1px solid var(--fm-line); border-radius: 12px;
  font-size: 11px; background: var(--fm-panel);
}
.fm-chip button { border: none; background: none; cursor: pointer; color: var(--fm-muted); font-size: 13px; line-height: 1; padding: 0; }

/* --- Grade de calendário mensal --- */
.fm-calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 10px; }
.fm-calendar-header__month { margin: 0; min-width: 180px; }
.fm-calendar-header__actions { display: flex; gap: 10px; }
.fm-calendar-nav { display: flex; align-items: center; gap: 10px; }
.fm-calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); border: 1px solid var(--fm-line); border-radius: var(--fm-radius); overflow: hidden; }
.fm-calendar-grid__weekday {
  background: var(--fm-panel); padding: 8px; font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .08em; color: var(--fm-muted);
  text-align: center; border-bottom: 1px solid var(--fm-line);
}
.fm-calendar-day { min-height: 92px; padding: 6px; border-right: 1px solid var(--fm-line); border-bottom: 1px solid var(--fm-line); }
.fm-calendar-day:nth-child(7n) { border-right: none; }
.fm-calendar-day--muted { background: var(--fm-panel); }
.fm-calendar-day--muted .fm-calendar-day__number { color: var(--fm-muted); }
.fm-calendar-day__number { font-size: 12px; margin-bottom: 4px; }
.fm-calendar-day--today .fm-calendar-day__number {
  color: var(--fm-accent-fg); background: var(--fm-accent); border-radius: 50%;
  width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;
}
.fm-calendar-event {
  display: block; color: var(--fm-fg); text-decoration: none;
  font-size: 10px; padding: 2px 4px; margin-bottom: 2px; border-left: 2px solid var(--fm-line);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fm-calendar-event:hover { background: var(--fm-accent-soft); }
.fm-calendar-event--ok { border-left-color: var(--fm-ok); }
.fm-calendar-event--warn { border-left-color: var(--fm-warn); }
.fm-calendar-event--alarm { border-left-color: var(--fm-alarm); }
.fm-calendar-day { cursor: pointer; }

/* M-series (CLAUDE.md §7.2) — achado real, 2026-09-03: sem isto, nav (setas +
   mês) e ações (Hoje + Novo compromisso) disputavam a mesma linha sem quebrar,
   e "Novo compromisso" saía da tela num frame de 390px. Empilha as duas
   metades e estica as ações pra alvo de toque de largura confortável. */
@media (max-width: 860px) {
  .fm-calendar-header__month { min-width: 0; }
  .fm-calendar-header__actions { width: 100%; }
  .fm-calendar-header__actions .fm-btn,
  .fm-calendar-header__actions .fm-btn--secondary { flex: 1; justify-content: center; }
}

[x-cloak] { display: none !important; }

/* --- Gaveta lateral direita (formulário de novo compromisso) --- */
.fm-drawer-backdrop {
  position: fixed; inset: 0; background: rgba(0, 0, 0, .35); z-index: 200;
}
.fm-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 420px; max-width: 92vw;
  background: var(--fm-bg); border-left: 1px solid var(--fm-line);
  box-shadow: -8px 0 24px rgba(0, 0, 0, .12); z-index: 201;
  padding: 20px; overflow-y: auto;
  transform: translateX(100%); transition: transform .2s ease;
}
.fm-drawer--open { transform: translateX(0); }
.fm-drawer__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.fm-drawer__head .fm-block-title { margin: 0; }
.fm-btn--block { width: 100%; }

/* --- Modal de detalhe do dia (clique em um dia da grade) --- */
.fm-day-modal {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 380px; max-width: 92vw; max-height: 80vh; overflow-y: auto;
  background: var(--fm-bg); border: 1px solid var(--fm-line); border-radius: var(--fm-radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .18); z-index: 201; padding: 18px;
}
.fm-day-modal__event {
  display: flex; gap: 10px; align-items: baseline; padding: 8px 6px;
  border-radius: 6px; text-decoration: none; color: var(--fm-fg); font-size: 13px;
}
.fm-day-modal__event:hover { background: var(--fm-accent-soft); }

/* --- Tabs (login; extensão 2026-08-19 para abas de tela de módulo, ver
   Indicadores de Produção — mesma classe, elemento passa a poder ser
   <button> além de <span>/<a>, precisa de reset dos estilos nativos de
   botão para herdar a aparência do componente) --- */
.fm-tabs { display: flex; border: 1px solid var(--fm-line); border-radius: 6px; overflow: hidden; font-size: 13px; }
.fm-tab {
  flex: 1; text-align: center; padding: 12px 0; color: var(--fm-muted); text-decoration: none;
  background: none; border: none; font: inherit; cursor: pointer;
}
.fm-tab--active { background: var(--fm-accent); color: var(--fm-accent-fg); font-weight: 600; }

.fm-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
}
.fm-status-pill i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.fm-status-pill--ok i { background: var(--fm-ok); }
.fm-status-pill--warn i { background: var(--fm-warn); }
.fm-status-pill--alarm i { background: var(--fm-alarm); }
.fm-status-pill--idle i { background: var(--fm-idle); }

/* --- Auth: split screen fiel ao W1 de modelo.html (imagem sangrada + formulário) --- */
.fm-auth-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 500px;
  background: var(--fm-bg);
  color: var(--fm-fg);
}
@media (max-width: 900px) {
  .fm-auth-shell { grid-template-columns: 1fr; }
  .fm-auth-visual { display: none; }
}

.fm-auth-visual {
  position: relative;
  background: var(--fm-rail);
  overflow: hidden;
}
.fm-auth-visual img.fm-auth-visual__bg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 20% 50%;
}
.fm-auth-visual__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(16, 26, 22, .45), rgba(16, 26, 22, .9));
}
.fm-auth-visual__content {
  position: absolute; inset: 0; padding: 52px;
  display: flex; flex-direction: column; justify-content: space-between;
  color: #f4f6f4;
}
.fm-auth-visual__top { display: flex; justify-content: space-between; align-items: flex-start; }
.fm-auth-visual__logo { width: 200px; }
.fm-auth-visual__badge {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px; border-radius: 8px;
  background: rgba(244, 246, 244, .12); border: 1px solid rgba(244, 246, 244, .28);
  backdrop-filter: blur(14px) saturate(1.2);
  font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
}
.fm-auth-visual__badge i { width: 8px; height: 8px; border-radius: 50%; background: #8CBF4D; display: inline-block; }
.fm-auth-visual__rule { width: 72px; height: 2px; background: #7BA33D; margin-bottom: 24px; }
.fm-auth-visual__headline { font-weight: 300; font-size: 34px; line-height: 1.25; }
.fm-auth-visual__headline strong { font-weight: 600; }

.fm-auth-form {
  padding: 64px 52px;
  display: flex; flex-direction: column; justify-content: center; gap: 20px;
}
.fm-auth-form__eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--fm-accent); }
.fm-auth-form__title { font-weight: 300; font-size: 32px; margin-top: 8px; }
.fm-auth-form__footer { font-size: 11px; color: var(--fm-muted); line-height: 1.7; }
.fm-auth-form__links { display: flex; justify-content: space-between; align-items: center; font-size: 12px; }
.fm-auth-form__links a { color: var(--fm-accent); font-weight: 500; text-decoration: none; }

/* ===========================================================================
   EXTENSÕES DO DESIGN SYSTEM — 2026-08-17 (Agente Visual)
   Criadas para o módulo Produção, mas TODAS genéricas de propósito: qualquer
   módulo futuro reusa daqui em vez de reinventar. Documentadas em CLAUDE.md §7.
   Princípios mantidos: hierarquia por tipografia + hairline, nunca bloco de
   cor preenchido; cor de marca só como traço/ação; estado sempre cor+palavra.
   =========================================================================== */

/* --- 1. Sub-navegação de módulo (dentro do menu de 230px) -------------------
   O menu é data-driven por FERRAMENTA (web/nav.py), e uma ferramenta pode ter
   mais de uma tela (Produção: painel + apontamentos). As sub-telas entram como
   sub-itens do item ativo — nunca como linha nova na tabela `tools`, que é
   catálogo de PERMISSÃO, não de navegação. */
.fm-menu__subgroup {
  display: flex;
  flex-direction: column;
  margin: 2px 0 6px 11px;
  border-left: 1px solid var(--fm-line);
}
.fm-menu-subitem {
  display: block;
  padding: 7px 10px;
  margin-left: -1px;
  border-left: 2px solid transparent;
  font-size: 12px;
  color: var(--fm-muted);
  text-decoration: none;
}
.fm-menu-subitem:hover { color: var(--fm-fg); background: var(--fm-accent-soft); }
.fm-menu-subitem--active { color: var(--fm-fg); font-weight: 600; border-left-color: var(--fm-accent); }

/* --- 2. Aviso de sistema (fm-notice) ---------------------------------------
   Generalização do padrão .fm-timeline-item para mensagens de estado da tela
   (fonte de dado fora do ar, dado parcial, ação enfileirada, erro de
   permissão). Filete de 2px na cor do estado + PALAVRA no rótulo — nunca um
   retângulo preenchido de vermelho, que roubaria a hierarquia da tela inteira
   para algo que quase nunca é erro do usuário. */
.fm-notice { border-left: 2px solid var(--fm-line); padding: 1px 0 1px 12px; margin: 0 0 18px; }
.fm-notice__title { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-notice__body { font-size: 12px; line-height: 1.55; margin-top: 3px; }
.fm-notice--ok { border-left-color: var(--fm-ok); }
.fm-notice--ok .fm-notice__title { color: var(--fm-ok); }
.fm-notice--warn { border-left-color: var(--fm-warn); }
.fm-notice--warn .fm-notice__title { color: var(--fm-warn-fg); }
.fm-notice--alarm { border-left-color: var(--fm-alarm); }
.fm-notice--alarm .fm-notice__title { color: var(--fm-alarm); }
.fm-notice--idle { border-left-color: var(--fm-idle); }
.fm-notice--idle .fm-notice__title { color: var(--fm-idle); }

/* --- 3. Card de métrica composta (fm-metric-card) --------------------------
   Um indicador principal grande + as sub-métricas que o compõem, separadas por
   hairline vertical. Mesma gramática do .fm-kpi-card do modelo (filete de 2px
   no topo indicando o estado), escalada para o indicador-chefe da tela.
   Hierarquia: valor-chefe 44px/300 (mesmo peso dos títulos de página) vs.
   sub-métrica 26px/500 (peso dos KPIs do modelo) — hierarquia por TAMANHO e
   PESO, não por cor de fundo. */
.fm-metric-card {
  border: 1px solid var(--fm-line);
  border-top: 2px solid var(--fm-accent);
  border-radius: var(--fm-radius);
  padding: 20px 22px 6px;
  margin-bottom: 24px;
}
.fm-metric-card--ok { border-top-color: var(--fm-ok); }
.fm-metric-card--warn { border-top-color: var(--fm-warn); }
.fm-metric-card--alarm { border-top-color: var(--fm-alarm); }
.fm-metric-card--idle { border-top-color: var(--fm-idle); }
.fm-metric-card__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; flex-wrap: wrap; }
/* overflow-wrap: anywhere — mesmo achado do .fm-kpi-card__value acima. */
.fm-metric-card__value { font-weight: 300; font-size: 44px; line-height: 1.15; letter-spacing: -.02em; margin-top: 4px; overflow-wrap: anywhere; }
.fm-metric-card__unit { font-size: 17px; font-weight: 400; color: var(--fm-muted); margin-left: 3px; }
.fm-metric-card__note { font-size: 11px; color: var(--fm-muted); margin-top: 6px; }
.fm-metric-card__parts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 20px;
  border-top: 1px solid var(--fm-line);
}
.fm-metric { padding: 16px 0 14px 22px; border-left: 1px solid var(--fm-line); }
.fm-metric:first-child { border-left: none; padding-left: 0; }
.fm-metric__label { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-metric__value { font-weight: 500; font-size: 26px; line-height: 1.3; }
.fm-metric__value-unit { font-size: 12px; font-weight: 400; color: var(--fm-muted); margin-left: 2px; }
.fm-metric__foot { margin-top: 4px; }
.fm-kpi-card__delta { font-size: 11px; color: var(--fm-muted); margin-top: 4px; }
.fm-kpi-card__delta--ok { color: var(--fm-ok); }
.fm-kpi-card__delta--warn { color: var(--fm-warn-fg); }
.fm-kpi-card__delta--alarm { color: var(--fm-alarm); }

/* --- 4. Frescor do dado (fm-freshness) -------------------------------------
   Bloco compacto de cabeçalho: quando o dado foi calculado + o estado da fonte
   em palavra. Regra de negócio do usuário ("aviso na tela quando a fonte
   cair") resolvida com peso visual proporcional: informação permanente e
   discreta no header, e só quando há problema é que sobe um .fm-notice. */
.fm-freshness { text-align: right; line-height: 1.4; }
.fm-freshness__label { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-freshness__value { font-size: 13px; }
.fm-freshness__age { font-size: 11px; color: var(--fm-muted); }
.fm-freshness fm-status-pill { display: block; margin-top: 4px; }
.fm-freshness .fm-status-pill { justify-content: flex-end; }

/* --- 5. Gráfico (fm-chart) -------------------------------------------------
   Moldura do gráfico + legenda por TRAÇO (não por bloco de cor). O desenho em
   si é Chart.js configurado para reproduzir o gráfico do modelo.html: linha
   fina sem preenchimento, grade em --fm-grid, rótulos 10px em --fm-muted. */
.fm-chart { border: 1px solid var(--fm-line); border-radius: var(--fm-radius); padding: 18px 20px 14px; }
.fm-chart__head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.fm-chart__canvas-wrap { position: relative; height: 220px; }
/* Variante compacta — grade de cards em miniatura (ex.: um card por mês no
   bloco "Acuracidade por Mês" do S&OP, CLAUDE.md §11f/§11, 2026-08-21). */
.fm-chart__canvas-wrap--sm { height: 150px; }
.fm-chart__legend { display: flex; gap: 16px; flex-wrap: wrap; }
.fm-chart-legend-item { display: inline-flex; align-items: center; gap: 7px; font-size: 11px; color: var(--fm-muted); }
.fm-chart-legend-item__line { width: 16px; height: 0; border-top: 2px solid var(--fm-accent); display: inline-block; }
.fm-chart-legend-item--thin .fm-chart-legend-item__line { border-top-width: 1px; border-top-color: var(--fm-muted); }
.fm-chart-legend-item--dash .fm-chart-legend-item__line { border-top-style: dashed; }
.fm-chart-legend-item--dot .fm-chart-legend-item__line { border-top-style: dotted; }
/* Tabela de detalhe ANINHADA dentro de um .fm-chart (ex.: card de mês do
   bloco "Acuracidade por Mês" do S&OP — combo chart + tabela por família no
   mesmo cartão) — mesma tabela (.fm-table), só compacta o bastante para caber
   em grade de 3 colunas. CLAUDE.md §11f/§11, 2026-08-21. */
.fm-chart__table { margin-top: 14px; font-size: 11px; }
.fm-chart__table thead th { padding-bottom: 6px; }
.fm-chart__table tbody td { height: 32px; }

/* --- 6. Tabela (fm-table) --------------------------------------------------
   Primeira tabela real do Portal. O modelo.html não usa <table> (usa grids
   com hairline), mas a semântica de dado tabular pede <table> por
   acessibilidade — o VISUAL é o mesmo do modelo: sem zebra, sem borda externa,
   só hairline entre linhas; cabeçalho em maiúsculas 10px; linha de 44px. */
.fm-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.fm-table thead th {
  font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--fm-muted); text-align: left; padding: 0 12px 10px;
  border-bottom: 1px solid var(--fm-line); white-space: nowrap;
}
.fm-table tbody td { height: 44px; padding: 0 12px; border-bottom: 1px solid var(--fm-line); vertical-align: middle; }
.fm-table tbody tr:hover { background: var(--fm-accent-soft); }
.fm-table th:first-child, .fm-table td:first-child { padding-left: 0; }
.fm-table th:last-child, .fm-table td:last-child { padding-right: 0; }
.fm-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.fm-table .fm-empty-state { padding: 14px 0; display: block; }
.fm-table__muted { color: var(--fm-muted); }

/* Célula de texto longo: título de licença, nome de órgão, nome de arquivo
   anexado. Dado real tem nome comprido ("Licença de Operação para Atividades
   Poluidoras/Degradadoras do Meio Ambiente") — a regra do Portal é QUEBRAR EM
   LINHA, nunca truncar com reticências: identificação de documento cortada
   obriga a abrir cada linha para saber qual é qual. `anywhere` (e não
   `break-word`) porque nome de arquivo pode não ter espaço nenhum. A altura de
   44px da linha vira piso, não teto — a célula cresce quando precisa. */
.fm-table__wrap { overflow-wrap: anywhere; }
.fm-table tbody td { overflow-wrap: break-word; }

/* Lista de anexos dentro de uma célula (N documentos numa mesma linha de
   tabela). Nasceu nas competências de Documentos Recorrentes; é genérica para
   qualquer módulo documental. Sem marcador de lista: a hierarquia é o ícone de
   clipe do próprio link. */
.fm-filelist { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.fm-filelist li { display: flex; flex-direction: column; gap: 1px; }
/* .fm-link-action é `nowrap` por padrão (ação curta em linha); nome de arquivo
   precisa do oposto. */
.fm-filelist .fm-link-action { white-space: normal; overflow-wrap: anywhere; align-items: flex-start; }
.fm-filelist .fm-link-action svg { flex: none; margin-top: 2px; }
.fm-filelist__origin { font-size: 10px; color: var(--fm-muted); padding-left: 19px; }

/* Paginação client-side de tabela grande dentro de um snapshot já pré-
   computado (não uma query viva — a lista inteira já chegou no payload da
   página; isso só governa quantas linhas ficam visíveis por vez, evitando
   rolagem excessiva sem round-trip novo ao servidor). */
.fm-table-pager {
  display: flex; align-items: center; justify-content: center; gap: 16px;
  margin-top: 14px; font-size: 12px; color: var(--fm-muted);
}
.fm-table-pager .fm-btn--secondary:disabled { opacity: .4; cursor: default; }

/* Severidade de desvio na tabela de Paradas de Produção (fm-text--*, não
   fm-notice: é uma célula dentro de uma linha, não um aviso de sistema
   inteiro — CLAUDE.md §11e, "Indicadores"). Cor sempre com o número já
   formatado ao lado, nunca a única pista. */
.fm-text--alarm { color: var(--fm-alarm); font-weight: 600; }
.fm-text--warn { color: var(--fm-warn-fg); }
.fm-text--ok { color: var(--fm-ok); }
.fm-text--idle { color: var(--fm-idle); }

/* Linha "Total" de tabela (soma agregada) — destaque por TIPOGRAFIA/HAIRLINE
   mais grossa, nunca bloco de cor preenchido (mesma gramática de todo o
   design system). Nasceu no bloco "YTD por família" do S&OP (CLAUDE.md
   §11f/§11, 2026-08-21), reutilizável por qualquer tabela com linha de soma. */
.fm-table__total-row td { font-weight: 600; border-top: 2px solid var(--fm-line); }

/* --- 7. Seção de conteúdo (fm-section) ------------------------------------- */
.fm-section { margin-bottom: 28px; }
.fm-section__head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  border-bottom: 1px solid var(--fm-line); padding-bottom: 10px; margin-bottom: 14px;
}
.fm-section__title { font-size: 15px; font-weight: 600; }
.fm-section__hint { font-size: 11px; color: var(--fm-muted); text-align: right; }
.fm-section__hint--left { text-align: left; }
.fm-section__foot { font-size: 11px; color: var(--fm-muted); margin-top: 10px; }
/* Bloco secundário/piloto: mesma gramática, peso visual deliberadamente menor
   (título 12px, sem filete de destaque) — usado quando um assunto precisa
   estar na tela sem competir com o indicador principal (ex.: Kronos). */
.fm-section--aside .fm-section__title { font-size: 12px; font-weight: 600; letter-spacing: .04em; color: var(--fm-muted); }

/* --- 8. Grid de 12 colunas (gap 24px) -------------------------------------- */
.fm-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 24px; }
.fm-col-3 { grid-column: span 3; }
.fm-col-4 { grid-column: span 4; }
.fm-col-6 { grid-column: span 6; }
.fm-col-8 { grid-column: span 8; }
.fm-col-9 { grid-column: span 9; }
.fm-col-12 { grid-column: span 12; }

/* --- 9. Estados de botão / campo ------------------------------------------- */
.fm-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.fm-btn:disabled, .fm-btn[disabled] { opacity: .45; cursor: not-allowed; }
.fm-btn:disabled:hover, .fm-btn[disabled]:hover { opacity: .45; }
.fm-btn svg { width: 14px; height: 14px; }
.fm-field__hint { font-size: 11px; color: var(--fm-muted); }
.fm-field__error { font-size: 11px; color: var(--fm-alarm); }
.fm-field--invalid input, .fm-field--invalid select { border-color: var(--fm-alarm); }
/* Formulário em grid de 12 colunas — mesmo gap do grid de conteúdo. */
.fm-form-grid { display: grid; grid-template-columns: repeat(12, 1fr); column-gap: 24px; }
.fm-form-grid .fm-field { grid-column: span 12; }
.fm-form-grid .fm-field--6 { grid-column: span 6; }
.fm-form-grid .fm-field--4 { grid-column: span 4; }

/* --- 9a. Detalhe expansível (fm-details) — 2026-08-19 (PCP · Ordem do Dia) -
   `<details>`/`<summary>` nativo (sem componente equivalente no Portal até
   aqui — checado, nenhum outro módulo usa) para expandir os apontamentos de
   uma OP dentro da própria linha da tabela, sem precisar de Alpine/JS: mesma
   filosofia de "hierarquia por hairline, nunca bloco de cor preenchido" do
   resto do design system, só trocando o marcador nativo do navegador (▶) por
   um ícone Lucide que já é vendorizado. */
.fm-details { border-top: 1px solid var(--fm-line); padding: 10px 0 0; }
.fm-details__summary {
  display: flex; align-items: center; gap: 6px; cursor: pointer; list-style: none;
  font-size: 11px; color: var(--fm-muted); font-weight: 600; letter-spacing: .04em;
}
.fm-details__summary::-webkit-details-marker { display: none; }
.fm-details__summary svg { width: 14px; height: 14px; transition: transform .15s ease; }
.fm-details[open] > .fm-details__summary svg { transform: rotate(90deg); }
.fm-details__body { padding: 10px 0 4px; }

/* ===========================================================================
   10. RESPONSIVO / M-SERIES — 2026-08-17 (Agente Visual)
   O modelo.html especifica o app de campo como frame 390×844, cantos 28px,
   alvo de toque ≥48px, mas não formalizava breakpoints para o portal web em
   tela pequena. Formalizados aqui (mesma base de código, sem app separado):
     ≥1101px  desktop (trilho 64 + menu 230 + conteúdo)
     861–1100 menu comprimido para 190px, conteúdo com padding menor
     ≤860px   M-series: trilho vira barra INFERIOR (polegar), menu vira faixa
              horizontal rolável no topo, tabelas empilham em blocos
   =========================================================================== */
@media (max-width: 1100px) {
  .fm-shell__main { grid-template-columns: 190px 1fr; }
  .fm-content { padding: 24px 24px; }
  .fm-metric-card__value { font-size: 38px; }
  /* Esta faixa é, na prática, TABLET EM PAISAGEM (iPad 1024px) — não um
     desktop pequeno. Quem assina aqui assina com o dedo, então a área de
     assinatura e os botões que a acompanham já entram com métrica de toque,
     sem esperar o breakpoint de 860px (2026-08-19, Almoxarifado). */
  .fm-signature__pad { height: 210px; }
  .fm-signature__actions .fm-btn { min-height: 48px; }
}

@media (max-width: 860px) {
  /* Trilho de áreas: coluna esquerda -> barra inferior fixa (alvo de toque de
     48px, alcance de polegar). Continua sendo a MESMA marcação do desktop. */
  .fm-rail {
    top: auto; bottom: 0; left: 0; right: 0;
    width: auto; height: 56px;
    flex-direction: row; justify-content: flex-start;
    padding: 0 8px;
    border-top: 1px solid rgba(244, 246, 244, .12);
    overflow-x: auto; overflow-y: hidden;
  }
  .fm-rail:hover { width: auto; }
  .fm-rail__logo { display: none; }
  .fm-rail__top, .fm-rail__bottom { flex-direction: row; align-items: center; }
  .fm-rail__bottom {
    border-top: none; border-left: 1px solid rgba(244, 246, 244, .12);
    margin: 0 0 0 6px; padding: 0 0 0 6px;
  }
  .fm-rail-item { height: 48px; min-width: 48px; margin: 4px 1px; }
  .fm-rail-item__label { display: none; }

  .fm-shell__main { grid-template-columns: 1fr; margin-left: 0; padding-bottom: 56px; }

  /* Menu do módulo: coluna -> faixa horizontal rolável acima do conteúdo. */
  .fm-menu {
    flex-direction: row; align-items: center; gap: 4px;
    padding: 8px 16px; border-right: none; border-bottom: 1px solid var(--fm-line);
    overflow-x: auto; white-space: nowrap;
  }
  .fm-menu > * { flex: none; }
  .fm-menu__area .fm-menu__section-label { display: none; }
  .fm-menu__area-name { font-size: 13px; margin-top: 0; }
  .fm-menu__section-label { margin: 0 4px 0 0; }
  .fm-menu__group { flex-direction: row; margin-bottom: 0; gap: 2px; }
  .fm-menu__rule { width: 1px; height: 20px; margin: 0 8px; flex: none; }
  .fm-menu-item { padding: 10px 12px; border-left: none; border-bottom: 2px solid transparent; min-height: 44px; display: flex; align-items: center; }
  .fm-menu-item--active { border-left-color: transparent; border-bottom-color: var(--fm-accent); }
  .fm-menu__subgroup { flex-direction: row; border-left: none; margin: 0; }
  .fm-menu-subitem { border-left: none; border-bottom: 2px solid transparent; margin-left: 0; min-height: 44px; display: flex; align-items: center; }
  .fm-menu-subitem--active { border-bottom-color: var(--fm-accent); }
  .fm-menu__user { margin-top: 0; padding-top: 0; }

  .fm-content { padding: 18px 16px 28px; }
  .fm-content-header { flex-direction: column; align-items: stretch; gap: 14px; }
  .fm-content-header__title, .fm-page-title { font-size: 24px; }
  .fm-freshness { text-align: left; }
  .fm-freshness .fm-status-pill { justify-content: flex-start; }

  /* Alvo de toque e tipografia de entrada (16px evita zoom automático no iOS). */
  .fm-btn { min-height: 48px; padding: 12px 20px; }
  .fm-icon-btn { width: 44px; height: 44px; }
  .fm-field input, .fm-field select, .fm-field textarea { min-height: 48px; font-size: 16px; }
  .fm-field textarea { min-height: 72px; }

  .fm-grid { grid-template-columns: 1fr; gap: 20px; }
  .fm-col-3, .fm-col-4, .fm-col-6, .fm-col-8, .fm-col-9, .fm-col-12 { grid-column: span 1; }
  .fm-form-grid { grid-template-columns: 1fr; }
  .fm-form-grid .fm-field, .fm-form-grid .fm-field--6, .fm-form-grid .fm-field--4 { grid-column: span 1; }

  .fm-metric-card__parts { grid-template-columns: 1fr; }
  .fm-metric { border-left: none; border-top: 1px solid var(--fm-line); padding: 12px 0 10px; }
  .fm-metric:first-child { border-top: none; }
  .fm-chart__canvas-wrap { height: 180px; }
  .fm-drawer { width: 100%; max-width: 100%; }

  /* Tabela -> blocos empilhados. Cada <td> precisa de data-label no template;
     o rótulo da coluna passa a viver dentro da própria linha. */
  .fm-table--stack thead { display: none; }
  .fm-table--stack tbody tr { display: block; padding: 12px 0; border-bottom: 1px solid var(--fm-line); }
  .fm-table--stack tbody tr:hover { background: none; }
  .fm-table--stack tbody td {
    display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
    height: auto; min-height: 30px; padding: 3px 0; border-bottom: none;
  }
  .fm-table--stack tbody td::before {
    content: attr(data-label);
    font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
    color: var(--fm-muted); flex: none;
  }
  .fm-table--stack tbody td[data-label=""]::before { content: none; }
}

/* ===========================================================================
   11. CONFIRMAÇÃO, FICHA E VISUALIZADOR DE DOCUMENTO — 2026-08-19 (Agente Visual)
   Nasceu no módulo Excelência Operacional (CLAUDE.md §11g), mas TUDO aqui é
   core/reutilizável: SGI e Assinaturas usam os mesmos componentes sem
   reimplementar. Registrado em CLAUDE.md §7.1.
   =========================================================================== */

/* --- 11.1 Botão de ação irreversível/pesada (arquivar, baixar original) -----
   Contorno + texto na cor de alarme, NUNCA preenchido: bloco de cor é
   proibido pelo design system (CLAUDE.md §7) e um botão vermelho sólido
   roubaria a hierarquia da tela inteira. A palavra continua sendo o que
   comunica a ação; a cor só reforça. */
.fm-btn--danger {
  background: transparent;
  color: var(--fm-alarm);
  border-color: var(--fm-alarm);
  font-weight: 500;
}
.fm-btn--danger:hover { background: rgba(164, 70, 58, .06); opacity: 1; }

/* --- 11.2 Modal de confirmação --------------------------------------------
   Substitui `confirm()`/`prompt()`/`alert()` nativos, proibidos por decisão
   do usuário (CLAUDE.md §11g). Mesma elevação do .fm-day-modal (modal é uma
   das DUAS únicas superfícies com sombra no design system, junto de dropdown);
   reaproveita .fm-drawer-backdrop como fundo. */
.fm-modal {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 420px; max-width: 92vw; max-height: 86vh; overflow-y: auto;
  background: var(--fm-bg); border: 1px solid var(--fm-line); border-radius: var(--fm-radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .18); z-index: 202; padding: 20px;
}
.fm-modal__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.fm-modal__eyebrow { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-modal__title { font-size: 17px; font-weight: 600; margin-top: 4px; line-height: 1.35; }
.fm-modal__body { font-size: 13px; line-height: 1.6; color: var(--fm-muted); margin-top: 12px; }
.fm-modal__body strong { color: var(--fm-fg); font-weight: 600; }
.fm-modal__actions {
  display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap;
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--fm-line);
}

/* --- 11.1b Rótulo de caixa de seleção --------------------------------------
   O `.fm-field label` padrão é o rótulo ACIMA do campo (12px, muted); num
   checkbox o texto é o próprio campo e precisa do peso de conteúdo, não de
   rótulo. Sem isto cada tela improvisava (havia até `style=` inline em
   pcp_reprocesso.html). Alvo de toque de 44px garantido no M-series. */
.fm-check {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 13px; color: var(--fm-fg); cursor: pointer; min-height: 28px;
}
.fm-field .fm-check { font-size: 13px; color: var(--fm-fg); }
.fm-check input[type="checkbox"] {
  width: 16px; height: 16px; flex: none; margin: 0;
  accent-color: var(--fm-accent); cursor: pointer;
}

/* --- 11.2b Ação em linha de tabela (link com ícone) -------------------------
   Ação dentro de célula não vira botão preenchido (competiria com a ação
   principal da tela): é texto na cor de marca com ícone de 13px. A variante
   --danger marca a saída de dado do sistema (baixar original). */
.fm-inline-actions { display: inline-flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.fm-link-action {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--fm-accent); text-decoration: none; white-space: nowrap;
}
.fm-link-action:hover { text-decoration: underline; }
.fm-link-action svg { width: 13px; height: 13px; }
.fm-link-action--danger { color: var(--fm-alarm); }
/* Mesma ação, ora como link (GET), ora como botão de um POST — a aparência é
   a mesma; só o mecanismo muda. O <form> vira `display: contents` para que o
   botão seja item direto do flex e não quebre o alinhamento da linha. */
button.fm-link-action {
  font-family: var(--fm-font); background: none; border: none; padding: 0; cursor: pointer;
}
.fm-inline-actions form { display: contents; }

/* Valor fixo dentro de formulário (contexto da ação, não campo editável):
   mesma métrica do input, sem moldura — o usuário precisa ver que não digita. */
.fm-readonly { font-size: 14px; padding: 10px 0; color: var(--fm-fg); }

/* Rodapé de sub-métrica quando o que qualifica o número é uma explicação, não
   um estado (não existe "no alvo/crítico" para "aguardando o órgão"). Ocupa o
   mesmo lugar do fm-status-pill para os cards não ficarem desalinhados. */
.fm-metric__note { font-size: 11px; color: var(--fm-muted); }

/* --- 11.3 Ficha de identificação (lista rótulo/valor) ----------------------
   Dado de cabeçalho que NÃO é número de indicador (unidade, órgão, titular,
   periodicidade). Não cabe em .fm-kpi-card (não é métrica) nem em .fm-table
   (não é tabular): rótulo 10px maiúsculo + valor 13px, separados por hairline,
   mesma gramática do .fm-metric sem o peso de indicador. */
/* minmax de 220px (era 180): com dado real a ficha ganhou Unidade/Órgão, e nome
   de órgão por extenso ("Secretaria de Estado de Meio Ambiente e Desenvolvimento
   Sustentável") em coluna de 180px vira uma pilha de 5 linhas.

   ⚠️ A hairline vertical é `border-left` do item, e só o PRIMEIRO item perde a
   borda — se a grade quebrar em duas fileiras, o primeiro item da segunda
   fileira fica com um filete solto na margem esquerda. Não há como saber em CSS
   onde a fileira quebra, então a regra de uso é: **no máximo 4 itens por
   `.fm-deflist`** (dois blocos empilhados quando a ficha for maior, como no
   detalhe de registro/plano de Excelência Operacional). Entre 861px e 1100px
   uma ficha de 4 itens ainda pode quebrar em 2+2 — cosmético, aceito por ora. */
.fm-deflist {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  border-top: 1px solid var(--fm-line); margin-bottom: 24px;
}
/* Dois blocos seguidos são a MESMA ficha em duas fileiras — encostam, sem o
   respiro de 24px que separaria seções diferentes. */
.fm-deflist + .fm-deflist { margin-top: -24px; }
.fm-deflist__item { padding: 12px 0 12px 22px; border-left: 1px solid var(--fm-line); }
.fm-deflist__item:first-child { border-left: none; padding-left: 0; }
.fm-deflist__label { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-deflist__value { font-size: 13px; margin-top: 3px; overflow-wrap: anywhere; }

/* --- 11.3b Texto corrido e linha de upload ---------------------------------
   `.fm-prose`: observação/descrição livre. Medida de linha limitada (~70
   caracteres) porque leitura confortável é parte da hierarquia tipográfica —
   texto atravessando 1400px de conteúdo não se lê.
   `.fm-upload-row`: campo de arquivo + botão na mesma linha, separado do que
   vem acima por hairline (nunca por bloco de fundo). */
.fm-prose { font-size: 13px; line-height: 1.7; max-width: 70ch; margin: 0; white-space: pre-line; }
.fm-upload-row {
  display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--fm-line);
}
.fm-upload-row .fm-field { margin-bottom: 0; flex: 1 1 320px; }
.fm-upload-row input[type="file"] { font-family: var(--fm-font); font-size: 13px; }

/* --- 11.4 Visualizador de documento (docs/security.md §10) ------------------
   Superfície de leitura em "modo foco": sem trilho/menu, só a barra de
   identificação + o palco do documento. O conteúdo é renderizado por PDF.js
   VENDORIZADO em canvas (static/js/document_viewer.js) — nunca <embed>/<iframe>
   do leitor nativo, que traz botão de imprimir/salvar embutido e anularia o
   resto da proteção (§10.6). O documento já chega com marca d'água aplicada
   pelo backend; nada aqui desenha marca. */
.fm-doc-view { display: flex; flex-direction: column; min-height: 100vh; background: var(--fm-panel); }
.fm-doc-view__bar {
  display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  padding: 14px 28px; background: var(--fm-bg); border-bottom: 1px solid var(--fm-line);
  position: sticky; top: 0; z-index: 5;
}
.fm-doc-view__ident { display: flex; align-items: center; gap: 14px; min-width: 0; }
.fm-doc-view__logo { width: 26px; flex: none; }
.fm-doc-view__eyebrow { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-doc-view__title { font-size: 16px; font-weight: 500; margin-top: 2px; overflow-wrap: anywhere; }
.fm-doc-view__actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.fm-doc-view__body { padding: 24px 28px 40px; }
.fm-doc-view__stage {
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  /* Seleção desabilitada: dissuasão de cópia de texto (§10.6) — não é
     controle, texto continua extraível por quem quiser de verdade. */
  user-select: none; -webkit-user-select: none;
  transition: filter .12s ease;
}
/* Aba perdeu o foco -> desfoca o documento. Dissuade screenshot por ferramenta
   de captura em segundo plano; volta ao normal assim que a aba volta. */
.fm-doc-view--blurred .fm-doc-view__stage { filter: blur(14px); }
.fm-doc-view__page {
  max-width: 100%; border: 1px solid var(--fm-line); border-radius: var(--fm-radius);
  background: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, .08);
}
.fm-doc-view__page-label { font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--fm-muted); }
.fm-doc-view__foot { max-width: 900px; margin: 28px auto 0; }
.fm-doc-view__panel {
  background: var(--fm-bg); border: 1px solid var(--fm-line); border-radius: var(--fm-radius);
  padding: 18px 20px; margin-top: 18px;
}

/* Aviso de tentativa bloqueada (print/DevTools) — filete, nunca bloco. */
.fm-doc-view__signal { max-width: 900px; margin: 0 auto 18px; }

/* --- 11.5 Guarda de impressão ----------------------------------------------
   @media print esconde o documento e imprime só a advertência. É dissuasão,
   não garantia: captura em nível de SO/foto de tela continua possível — a
   proteção que de fato vale é marca d'água + log de acesso
   (docs/security.md §10.6). */
.fm-print-guard { display: none; }
@media print {
  .fm-doc-view__bar, .fm-doc-view__body, .fm-doc-view__foot { display: none !important; }
  .fm-print-guard {
    display: block !important; padding: 40px; font-family: var(--fm-font);
    font-size: 14px; line-height: 1.7; color: #1d211f;
  }
  .fm-print-guard__title { font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; }
}

@media (max-width: 860px) {
  .fm-modal { width: 100%; max-width: 100%; max-height: 100vh; height: 100vh; top: 0; left: 0; transform: none; border-radius: 0; }
  .fm-modal__actions .fm-btn { flex: 1; }
  .fm-deflist { grid-template-columns: 1fr; }
  .fm-deflist__item { border-left: none; border-top: 1px solid var(--fm-line); padding: 10px 0; }
  .fm-deflist__item:first-child { border-top: none; }
  .fm-doc-view__bar { padding: 12px 16px; }
  .fm-doc-view__body { padding: 16px 12px 32px; }
  /* Alvo de toque: ação em linha de tabela também precisa dos 44–48px. */
  .fm-inline-actions { gap: 20px; }
  .fm-link-action { min-height: 44px; font-size: 13px; }
  .fm-check { min-height: 48px; font-size: 15px; }
  .fm-check input[type="checkbox"] { width: 22px; height: 22px; }
}

/* ===========================================================================
   12. FICHA ASSINADA EM CAMPO — 2026-08-19 (Agente Visual · Almoxarifado)
   Tudo aqui é CORE/reutilizável, não exclusivo do Almoxarifado: o CQ tem os
   mesmos 4 checklists com assinatura reservada (CLAUDE.md §11h) e Assinaturas
   /SGI vão precisar da mesma gramática. Registrado em CLAUDE.md §7.1.

   Contexto que governa as decisões desta seção: o dispositivo alvo é
   TABLET/CELULAR na mão do almoxarife, e quem assina NÃO é quem está logado
   (CLAUDE.md §11i — `created_by` != `signed_by`). Isso cria um problema que
   nenhuma tela anterior do Portal tinha: em algum ponto do formulário o
   aparelho troca de mão. Se a tela não disser isso com todas as letras, o
   almoxarife digita a própria senha e a prova documental perde o valor.
   =========================================================================== */

/* --- 12.1 Passagem de aparelho (fm-handoff) --------------------------------
   Marca o ponto exato em que a responsabilidade muda de pessoa dentro de um
   mesmo formulário. Filete de 2px na cor de marca (mesma gramática do
   .fm-notice/.fm-timeline-item) + a PALAVRA de quem é a vez agora, com o nome
   da pessoa em destaque tipográfico — nunca um bloco de cor, nunca um ícone
   sozinho. O nome grande existe para o COLABORADOR reconhecer que é ele
   mesmo antes de assinar, não como enfeite. */
.fm-handoff {
  border-left: 2px solid var(--fm-accent);
  padding: 2px 0 2px 16px;
  margin: 24px 0 0;
}
.fm-handoff__step {
  font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--fm-accent);
}
.fm-handoff__title { font-size: 17px; font-weight: 400; line-height: 1.35; margin-top: 5px; overflow-wrap: anywhere; }
.fm-handoff__title strong { font-weight: 600; }
.fm-handoff__body { font-size: 12px; line-height: 1.6; color: var(--fm-muted); max-width: 60ch; margin: 6px 0 0; }
/* Bloco pertencente ao handoff: recuado pelo mesmo filete, sem moldura
   própria (a hierarquia já foi estabelecida pelo traço vertical). */
.fm-handoff__field { margin-top: 16px; }

/* Rótulo de etapa dentro de um formulário longo (par do .fm-handoff: a etapa
   que ainda é do operador). Mesma métrica de rótulo de coluna de tabela —
   hierarquia por tipografia, sem numeração desenhada em círculo colorido. */
.fm-formstep {
  font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--fm-muted); margin-bottom: 12px;
}
/* Rodapé de ação de formulário em gaveta — separa o botão de confirmar do
   último campo sem inventar margem inline em cada template. */
.fm-form-actions { margin-top: 20px; }
.fm-form-actions--split { display: flex; gap: 10px; flex-wrap: wrap; }

/* --- 12.2 Assinatura desenhada (fm-signature) ------------------------------
   Moldura do <canvas> de static/js/signature_pad.js. O papel é BRANCO e a
   tinta é escura nos DOIS temas, de propósito: o PNG resultante é um artefato
   documental (vira anexo cifrado em `documents`, marca d'água por cima), não
   um pedaço de interface — mesma lógica que mantém o trilho e o painel do
   login invariantes ao tema (CLAUDE.md §7.4). Por isso o hex literal aqui é
   uma exceção declarada, não um valor mágico esquecido. */
.fm-signature { margin-top: 12px; }
.fm-signature__pad {
  display: block; width: 100%; height: 190px;
  background: var(--fm-signature-paper);
  border: 1px solid var(--fm-line); border-radius: var(--fm-radius);
  /* touch-action:none evita que o primeiro toque no tablet vire rolagem em
     vez de traço; o JS também seta isso, aqui é para valer antes do JS. */
  touch-action: none; cursor: crosshair;
}
.fm-signature__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-top: 8px;
}
.fm-signature__hint { font-size: 11px; color: var(--fm-muted); }
.fm-signature__actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* --- 12.3 Linhas de item de uma ficha (fm-item-rows) -----------------------
   Formulário que repete o MESMO conjunto de campos N vezes (itens de uma
   entrega/empréstimo/devolução). Sem isto as linhas viram um paredão de
   campos indistinguíveis: separação por hairline + ordinal em 10px maiúsculo,
   igual ao cabeçalho de tabela, para o operador saber em que linha está. */
.fm-item-rows { border-top: 1px solid var(--fm-line); }
.fm-item-row { border-bottom: 1px solid var(--fm-line); padding: 14px 0 0; }
.fm-item-row__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  margin-bottom: 8px;
}
.fm-item-row__ordinal {
  font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--fm-muted);
}

/* --- 12.3b Barra de filtro de listagem (fm-filterbar) ----------------------
   Recorte de lista (situação, período) acima da tabela. É um `<form>` GET —
   o estado do filtro mora na URL, então recarregar/compartilhar a página não
   perde o recorte, e a paginação por keyset consegue carregá-lo adiante.
   Sem moldura nem fundo: rótulo em 10px maiúsculo + campo, na mesma linha. */
.fm-filterbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.fm-filterbar select, .fm-filterbar input {
  font-family: var(--fm-font); font-size: 13px; padding: 8px 10px;
  border: 1px solid var(--fm-line); border-radius: var(--fm-radius);
  background: var(--fm-input); color: var(--fm-fg);
}

/* --- 12.4 Paginação por keyset (servidor) ----------------------------------
   O .fm-table-pager da seção 6 nasceu para paginação client-side sobre um
   snapshot já carregado. A mesma barra serve para keyset REAL (cada botão é
   um link com o cursor da última linha), com uma diferença honesta: keyset
   não sabe o total nem tem "página anterior" barata — por isso o rótulo é
   "mais antigas"/"início", nunca "página 3 de 12", que seria mentira.
   Macro: `core.keyset_pager()` em templates/_core_macros.html. */
.fm-table-pager__count { flex: 1; text-align: center; }
.fm-table-pager--keyset { justify-content: space-between; }

@media (max-width: 860px) {
  /* Assinatura em tablet: papel mais alto (o traço de uma assinatura real
     ocupa mais espaço com o dedo do que com o mouse) e alvo de toque de 48px
     nos botões de limpar/desfazer — herdado de .fm-btn, garantido aqui. */
  .fm-signature__pad { height: 220px; }
  .fm-signature__foot { align-items: stretch; flex-direction: column-reverse; }
  .fm-signature__actions .fm-btn { flex: 1; min-height: 48px; }
  .fm-handoff { padding-left: 12px; }
  .fm-filterbar select, .fm-filterbar input { min-height: 48px; font-size: 16px; flex: 1; }
  .fm-table-pager--keyset { flex-direction: column; align-items: stretch; }
  .fm-table-pager--keyset .fm-btn { width: 100%; }
}

/* ===========================================================================
   13. GRADE DE CRONOGRAMA (Painel de Cronograma, CLAUDE.md §11k)
   ---------------------------------------------------------------------------
   O design system não tinha nada para representar DURAÇÃO ao longo do tempo:
   .fm-table é ponto no tempo, .fm-chart é série de valores, .fm-timeline-item
   é evento. Uma frente de trabalho que ocupa de set/26 a nov/26 precisa de
   extensão horizontal — daí este componente.

   Fiel aos princípios de modelo.html, e por isso NÃO é um Gantt comum:
     • a barra é um FILETE de 3px com rótulo ao lado, não um bloco de cor
       preenchido de ponta a ponta — bloco de cor é justamente o que o guia
       proíbe, e 66 blocos coloridos empilhados viram um arco-íris ilegível;
     • a cor é sempre acompanhada da palavra (a situação aparece no rótulo da
       linha e na pill da tabela, nunca só no traço);
     • a grade é hairline, igual ao gráfico de linha do modelo.
   Sem biblioteca: CSS Grid com uma coluna por mês, e o service já entrega
   `offset`/`span` em número de colunas — o template só posiciona.
   =========================================================================== */
.fm-gantt { border: 1px solid var(--fm-line); border-radius: var(--fm-radius); overflow-x: auto; }
.fm-gantt__inner { min-width: 900px; }

/* Cabeçalho de meses. Grudado no topo ao rolar: numa grade de 66 linhas, sem
   isto o leitor perde a referência de qual coluna é qual mês. */
.fm-gantt__head {
  display: grid; position: sticky; top: 0; z-index: 2;
  background: var(--fm-panel); border-bottom: 1px solid var(--fm-line);
}
.fm-gantt__corner { padding: 10px 14px; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--fm-muted); }
.fm-gantt__month {
  padding: 10px 4px; text-align: center; font-size: 10px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--fm-muted); border-left: 1px solid var(--fm-grid);
}
.fm-gantt__month--current { color: var(--fm-accent); font-weight: 600; }

.fm-gantt__track {
  padding: 12px 14px 6px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--fm-muted); border-top: 1px solid var(--fm-line); background: var(--fm-panel);
}
.fm-gantt__row { display: grid; align-items: center; border-top: 1px solid var(--fm-grid); min-height: 40px; }
.fm-gantt__row:hover { background: var(--fm-accent-soft); }
.fm-gantt__label { padding: 8px 14px; font-size: 12px; display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.fm-gantt__code { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--fm-fg); text-decoration: none; }
.fm-gantt__code:hover { color: var(--fm-accent); }
.fm-gantt__name { color: var(--fm-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A célula do mês existe só para desenhar a linha vertical da grade — a barra
   é posicionada por grid-column por cima dela. */
.fm-gantt__cell { border-left: 1px solid var(--fm-grid); height: 100%; }
.fm-gantt__cell--current { background: var(--fm-accent-soft); }

.fm-gantt__bar { grid-row: 1; align-self: center; height: 3px; border-radius: 2px; position: relative; margin: 0 3px; }
.fm-gantt__bar--ok { background: var(--fm-ok); }
.fm-gantt__bar--warn { background: var(--fm-warn); }
.fm-gantt__bar--alarm { background: var(--fm-alarm); }
.fm-gantt__bar--idle { background: var(--fm-idle); }
/* Ponta chanfrada quando a frente continua fora da janela do programa: o
   leitor precisa saber que a barra foi aparada, não que ela termina ali. */
.fm-gantt__bar--clip-start { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: 0; }
.fm-gantt__bar--clip-end { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }

/* Marca do previsto ORIGINAL quando a frente foi repactuada — o traço fino
   tracejado mostra de onde ela saiu, que é a informação que a diretoria pediu
   para nunca se perder. */
.fm-gantt__baseline { grid-row: 1; align-self: center; height: 0; border-top: 1px dashed var(--fm-muted); opacity: .55; margin: 10px 3px 0; }

.fm-gantt__legend { display: flex; flex-wrap: wrap; gap: 18px; padding: 12px 14px; border-top: 1px solid var(--fm-line); font-size: 11px; color: var(--fm-muted); }
.fm-gantt__legend-item { display: flex; align-items: center; gap: 7px; }
.fm-gantt__legend-line { width: 18px; height: 3px; border-radius: 2px; display: inline-block; }
.fm-gantt__legend-line--dash { height: 0; border-top: 1px dashed var(--fm-muted); }

@media (max-width: 860px) {
  /* M-series: a grade de 12 meses não cabe na largura do polegar e não vale
     forçar — a visão "Mês a mês" responde a mesma pergunta melhor no celular.
     A grade continua acessível por rolagem horizontal (o container já é
     overflow-x: auto), com a coluna de rótulo mais estreita. */
  .fm-gantt__inner { min-width: 720px; }
  .fm-gantt__name { display: none; }
}

/* ===========================================================================
   14. CAPTURA DE BIOMETRIA FACIAL (fm-face-capture) — CLAUDE.md §6.1a/ADR-0007
   ---------------------------------------------------------------------------
   Componente para <fm-face-capture> (static/js/components/fm-face-capture.js),
   CORE — reutilizado por cadastro (Perfil), login e, no futuro, step-up/
   assinatura. Estilizado pelo próprio nome da tag (light DOM, sem Shadow
   DOM), como os demais Web Components do Portal.

   Mesma disciplina do resto do design system: hairline em vez de bloco de
   cor preenchido, estado sempre cor+palavra (a moldura da câmera nunca muda
   de cor sozinha para dizer "sucesso"/"erro" — quem diz isso é o
   .fm-notice, com a palavra). Nenhuma cor nova fora de token: tudo aqui lê
   de --fm-line/--fm-panel/--fm-accent/--fm-muted, então dark mode (§7.4) já
   funciona sem ajuste. */
fm-face-capture { display: block; width: 100%; max-width: 380px; }

.fm-face-capture__stage {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--fm-line);
  border-radius: var(--fm-radius);
  background: var(--fm-panel);
}
.fm-face-capture__video, .fm-face-capture__preview {
  display: block; width: 100%; height: 100%; object-fit: cover;
}
/* Espelha só a EXIBIÇÃO (vídeo ao vivo e prévia capturada) — o usuário se vê
   como no espelho, familiar. O frame de fato enviado ao backend NUNCA é
   espelhado (static/js/components/fm-face-capture.js::_capture() desenha o
   <video> cru no <canvas>) — o reconhecimento facial recebe a orientação
   real da câmera. */
.fm-face-capture__video--mirror { transform: scaleX(-1); }
/* Guia oval hairline para ajudar o enquadramento do rosto — nunca um bloco
   de cor, só um traço na cor de marca com opacidade reduzida. Puramente
   orientativo: quem valida enquadramento/liveness de verdade é o backend
   (FaceAuth), este traço não bloqueia nem valida nada no cliente. */
.fm-face-capture__guide {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 56%; height: 78%; border: 1px solid var(--fm-accent); opacity: .55;
  border-radius: 50%; pointer-events: none;
}
.fm-face-capture__hint { font-size: 11px; color: var(--fm-muted); margin: 10px 0 0; }
.fm-face-capture__actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
/* .fm-notice já tem margem própria (seção 2) — aqui ela nasce sozinha dentro
   do componente (sem conteúdo acima), então perde a margem inferior. */
.fm-face-capture__notice { margin-top: 12px; margin-bottom: 0; }

@media (max-width: 860px) {
  fm-face-capture { max-width: 100%; }
  /* Alvo de toque M-series (CLAUDE.md §7.2): 48px mínimo. */
  .fm-face-capture__actions .fm-btn { flex: 1; min-height: 48px; }
}

/* --- 14.1 Divisor de método de autenticação (fm-auth-divider) -------------
   "ou" entre login por biometria e login por senha na tela de Login — hairline
   nos dois lados, nunca um bloco/pill de cor. Reutilizável por qualquer tela
   futura com mais de um método de entrada (ex. SSO do Portal do Cliente). */
.fm-auth-divider {
  display: flex; align-items: center; gap: 12px; margin: 22px 0;
  font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--fm-muted);
}
.fm-auth-divider::before, .fm-auth-divider::after { content: ""; flex: 1; height: 1px; background: var(--fm-line); }
