/* fontes auto-hospedadas (fonts/) — sem dependência de rede externa, ver fonts/SOURCE.txt */
@font-face {
  font-family: "Manrope"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/manrope-600.woff2") format("woff2");
}
@font-face {
  font-family: "Manrope"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("fonts/manrope-700.woff2") format("woff2");
}
@font-face {
  font-family: "Manrope"; font-style: normal; font-weight: 800; font-display: swap;
  src: url("fonts/manrope-800.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/inter-400.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/inter-500.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/inter-600.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("fonts/inter-700.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/plexmono-500.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/plexmono-600.woff2") format("woff2");
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* Sistema "Pinheiro & Barro" — pinheiro profundo (não o mint-SaaS genérico) como cor de
   identidade, barro/terracota como acento raro de calor humano (ticket, prioridade), sobre
   neutro claro (não branco puro, não creme). Ver server/public/paciente.html #waiting-room
   .roofline pro elemento de assinatura (o gable da própria marca, abstraído em CSS puro). */
:root {
  --bg: #F5F6F4;
  --surface: #FFFFFF;
  --surface-sunken: #ECEEEB;
  --border: #DFE3DE;
  --ink: #1B2620;
  --ink-soft: #57635A;
  /* ink-faint precisa passar 4.5:1 (WCAG AA) sobre --surface E sobre --surface-sunken: é o tom
     de metadado do sistema inteiro (título de painel, hint, ::placeholder, th de tabela). O
     valor antigo (#8B9389) dava 3.17:1 / 2.71:1 e reprovava nos quatro pares dos dois temas. */
  --ink-faint: #676D65;
  /* Verde institucional = a cor da MARCA (assets/logo). Trocado em 2026-08-17 junto com a logo
     nova: era #145C40 (H=157) e a marca passou a ser #0B6C60 (H=173) — o botão primário ficava
     visivelmente mais verde que o logo ao lado dele na tela de login.
     Os três tons derivados NÃO foram escolhidos a olho: mantêm o mesmo L e S que cada tom antigo
     tinha, só com o H novo, pra preservar a hierarquia que a paleta já provava em contraste.
     Medido (WCAG 2.1 AA), tema claro: ink/accent 6.31, soft-ink/soft 8.43, accent/surface 6.31,
     accent/bg 5.82. O par accent/surface caiu de 7.97 pra 6.31 — é consequência da marca ser
     mais clara e saturada que o verde antigo, e continua com folga sobre o mínimo de 4.5. */
  --accent: #0B6C60;
  --accent-ink: #FFFFFF;
  --accent-soft: #E1EDEC;
  --accent-soft-ink: #0E4A43;
  --queue: #A8481B;
  --queue-soft: #F5E2D2;
  /* tinta de contraste do barro: --queue muda de escuro (claro) pra claro (escuro) entre os
     temas, então texto branco fixo reprovava (2.65:1) no tema escuro. */
  --queue-ink: #FFFFFF;
  --signature: #35578C;
  --signature-soft: #E6EBF3;
  --danger: #B8352A;
  --danger-soft: #F6E1DD;
  --ok: #1E7A4C;
  --ok-soft: #E1F0E6;
  --warn: #92400E;
  --warn-soft: #FEF3C7;
  /* Véu (scrim): escurece o que está ATRÁS pra destacar o que está na frente. Dois degraus,
     porque os dois trabalhos são diferentes:
       --scrim       veda a interface (fundo de modal, gaveta de navegação no celular). Leva a
                     tinta da paleta, não preto puro — é a mesma família de cor do app.
       --scrim-media veda VÍDEO e foto (rótulo "Você"/"Médico" sobre a câmera). Preto neutro e
                     mais opaco de propósito: o fundo é imagem arbitrária, que muda a cada quadro,
                     e um véu tingido some sobre cena clara.
     Os dois valem IGUAL nos dois temas, e por isso não são redefinidos nos blocos de tema: véu
     existe pra criar contraste contra conteúdo, não contra o fundo da aplicação. */
  --scrim: rgba(15,20,17,0.5);
  --scrim-media: rgba(0,0,0,0.5);
  /* Painel de marca: a superfície escura de assinatura, usada no painel da tela de login e na
     faixa do topo da tela Início. É uma rampa do verde da marca escurecido — não um cinza
     neutro — e vale IGUAL nos dois temas, por isso mora aqui e não nos blocos de tema: é a
     marca. Marca que troca de cor conforme o tema do sistema para de ser reconhecível.
     Os três tons são o mesmo H/S de --accent com L descendo, para o gradiente ter profundidade
     sem virar outra cor. Contraste medido (WCAG 2.1 AA) contra --brand-panel — o MAIS CLARO dos
     três, ou seja o pior caso: sobre --brand-panel-mid e -deep todos os pares sobem.
       --brand-panel-ink ....... 13.0:1  título e corpo
       --brand-panel-ink-soft ... 8.2:1  texto de apoio (mínimo de corpo é 4.5)
       --brand-panel-glow ....... 8.3:1  palavra destacada no título */
  --brand-panel: #06382F;
  --brand-panel-mid: #052E29;
  --brand-panel-deep: #04231F;
  --brand-panel-ink: #FFFFFF;
  --brand-panel-ink-soft: rgba(255,255,255,0.76);
  --brand-panel-glow: #74E0D3;
  --shadow: 0 1px 2px rgba(27,38,32,0.05), 0 10px 28px -10px rgba(27,38,32,0.16);
  --font-display: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;

  /* Escala tipográfica e de raio — antes destas duas escalas existirem, cada tela declarava o
     tamanho na mão e o projeto acumulou 20 tamanhos de fonte e 13 raios distintos, com passos
     de 0,5px (12px e 12.5px conviviam em 116 declarações) que não criam hierarquia nenhuma:
     só divergem em manutenção. Consolidado em 2026-08-13 fundindo cada par imperceptível no
     valor DOMINANTE do próprio CSS (não num ideal externo), então nenhum elemento mudou mais
     de 1px de tamanho. `padding`/`gap` seguem literais de propósito — espaçamento aqui é
     decisão de composição por componente, não escala compartilhada.

     Ao criar tela nova: use estes tokens. Um tamanho fora da escala é uma decisão, não um
     acidente — se precisar de um, adicione aqui com o motivo em vez de declarar solto. */
  --fs-micro: 10.5px;   /* micro-label: eyebrow, badge de status */
  --fs-xs: 11px;        /* metadado, hint, legenda de tabela */
  --fs-sm: 12.5px;      /* corpo de UI densa — o tamanho mais usado do sistema */
  --fs-md: 13px;        /* label de campo, título de item de lista */
  --fs-lg: 14px;        /* ênfase dentro de bloco denso */
  --fs-body: 15px;      /* leitura corrida (texto do paciente, termo LGPD) */
  --fs-xl: 18px;        /* headline de painel */
  --fs-2xl: 22px;       /* display de seção */
  --fs-numeric: 46px;   /* senha da fila — o número que o paciente procura na tela */
  /* A senha aparece em três tamanhos, não um: hero (46), hero no celular (34) e a caixa
     compacta "senha atual" do médico (30). Eram literais soltos; entram na escala com o
     motivo, como o comentário acima manda. */
  --fs-numeric-md: 34px;
  --fs-numeric-sm: 30px;
  --fs-numeric-xs: 24px;  /* senha no aro compacto durante a chamada (body.in-call) */
  --fs-glyph: 16px;     /* caractere usado como ícone, não como texto (o "×" de fechar) */

  --r-xs: 2px;          /* barra/indicador fino */
  --r-sm: 4px;
  --r-md: 6px;          /* chip, pill pequena */
  --r-lg: 8px;          /* botão, input — raio padrão do sistema */
  --r-xl: 10px;
  --r-2xl: 12px;
  --r-3xl: 14px;
  --r-4xl: 16px;        /* card, painel */
  --r-5xl: 18px;
  --r-6xl: 20px;
  --r-pill: 999px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101A15; --surface: #182720; --surface-sunken: #12201A; --border: #2A3B31;
    --ink: #EDEEE4; --ink-soft: #ABB6A8; --ink-faint: #839480;
    /* accent do tema escuro NÃO é a cor da marca crua: a marca (#0B6C60) sobre fundo escuro dá
       1.9:1 e some. É a marca clareada/dessaturada na mesma proporção que o verde antigo usava
       (mesmo L e S de #3FAE7F, H da marca). Medido: ink/accent 5.69, soft-ink/soft 7.81,
       accent/surface 5.76, accent/bg 6.58. */
    --accent: #3FAEA0; --accent-ink: #062A26; --accent-soft: #1C3A36; --accent-soft-ink: #74E0D3;
    --queue: #E2894C; --queue-soft: #3A2617; --queue-ink: #2B1305;
    --signature: #86A6DD; --signature-soft: #1E2C42;
    --danger: #E2776A; --danger-soft: #3A211E; --ok: #4BC98A; --ok-soft: #173226;
    --warn: #E2A83F; --warn-soft: #3A2C12;
    --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 10px 28px -10px rgba(0,0,0,0.5);
  }
}
:root[data-theme="dark"] {
  --bg: #101A15; --surface: #182720; --surface-sunken: #12201A; --border: #2A3B31;
  --ink: #EDEEE4; --ink-soft: #ABB6A8; --ink-faint: #839480;
  --accent: #3FAEA0; --accent-ink: #062A26; --accent-soft: #1C3A36; --accent-soft-ink: #74E0D3;
  --queue: #E2894C; --queue-soft: #3A2617; --queue-ink: #2B1305;
  --signature: #86A6DD; --signature-soft: #1E2C42;
  --danger: #E2776A; --danger-soft: #3A211E; --ok: #4BC98A; --ok-soft: #173226;
  --warn: #E2A83F; --warn-soft: #3A2C12;
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 10px 28px -10px rgba(0,0,0,0.5);
}
:root[data-theme="light"] {
  --bg: #F5F6F4; --surface: #FFFFFF; --surface-sunken: #ECEEEB; --border: #DFE3DE;
  --ink: #1B2620; --ink-soft: #57635A; --ink-faint: #676D65;
  --accent: #0B6C60; --accent-ink: #FFFFFF; --accent-soft: #E1EDEC; --accent-soft-ink: #0E4A43;
  --queue: #A8481B; --queue-soft: #F5E2D2; --queue-ink: #FFFFFF;
  --signature: #35578C; --signature-soft: #E6EBF3;
  --danger: #B8352A; --danger-soft: #F6E1DD; --ok: #1E7A4C; --ok-soft: #E1F0E6;
  --warn: #92400E; --warn-soft: #FEF3C7;
  --shadow: 0 1px 2px rgba(27,38,32,0.05), 0 10px 28px -10px rgba(27,38,32,0.16);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; }
table { border-collapse: collapse; width: 100%; }
.tabular { font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
[hidden] { display: none !important; }

.app { max-width: 1240px; margin: 0 auto; padding: 20px 24px 64px; }
.app.narrow { max-width: 480px; }

/* ---------------- shell: sidebar + main (telas internas) ---------------- */
.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: 240px; flex: none; background: var(--surface); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; padding: 20px 14px; gap: 2px;
}
.sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 6px 8px 22px; }
.sidebar-brand .mark {
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center; flex: none;
}
.sidebar-brand .mark img { width: 100%; height: 100%; object-fit: contain; }
.sidebar-brand .word { font-family: var(--font-display); font-weight: 600; font-size: 15px; line-height: 1.28; letter-spacing: -0.005em; }
.sidebar-brand .word .lar { color: var(--accent); }
.side-link {
  display: flex; align-items: center; gap: 11px; padding: 9px 11px; border-radius: 8px;
  font-size: 13px; font-weight: 560; color: var(--ink-soft); text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}
.side-link svg { width: 17px; height: 17px; flex: none; }
.side-link:hover { background: var(--surface-sunken); color: var(--ink); }
.side-link.active { background: var(--accent-soft); color: var(--accent-soft-ink); font-weight: 650; }
.side-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.side-divider { height: 1px; background: var(--border); margin: 10px 6px; }
.side-label { padding: 0 11px 4px; font-size: 10.5px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); }

/* submenu colapsável (hoje só "Home Care > Escala") */
.side-group { display: flex; flex-direction: column; gap: 2px; }
.side-link-row { display: flex; align-items: center; gap: 2px; }
.side-link-row .side-link { flex: 1; min-width: 0; }
.side-group-toggle {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; border: none; background: none; color: var(--ink-faint);
  border-radius: 6px; cursor: pointer; transition: background 0.12s ease, color 0.12s ease;
}
.side-group-toggle:hover { background: var(--surface-sunken); color: var(--ink-soft); }
.side-group-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.side-group-toggle .chevron { width: 15px; height: 15px; transition: transform 0.15s ease; }
.side-group-toggle[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.side-submenu {
  display: none; flex-direction: column; gap: 2px;
  margin: 0 0 0 20px; padding-left: 9px; border-left: 1px solid var(--border);
}
.side-submenu.open { display: flex; }
.side-sublink { font-size: 12.5px; padding: 8px 11px; }

.sidebar-foot { margin-top: auto; padding-top: 14px; display: flex; flex-direction: column; gap: 3px; }
.sidebar-foot .who {
  display: grid; grid-template-columns: 30px 1fr; align-items: center; column-gap: 10px;
  margin: 0 2px 10px; padding: 8px 10px;
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: 12px;
}
.sidebar-foot .who .avatar {
  grid-row: 1 / 3; width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--accent-ink); text-decoration: none;
  font-family: var(--font-display); font-weight: 700; font-size: 12.5px;
  transition: filter 0.12s ease, transform 0.08s ease;
}
.sidebar-foot .who .avatar:hover { filter: brightness(1.12); transform: scale(1.05); }
.sidebar-foot .who .avatar:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sidebar-foot .who .name { display: block; font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.3; }
.sidebar-foot .who .role { display: block; font-size: 10.5px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 1px; }
button.side-link { border: none; background: none; width: 100%; text-align: left; font: inherit; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* O cabeçalho da tela É a superfície de marca. Antes era uma faixa clara com o título em tinta
   escura e uma tarja verde separada logo abaixo, dentro do scroll: duas faixas empilhadas, dois
   cabeçalhos, e a marca aparecendo depois do título em vez de junto com ele. Agora é uma peça só.
   A superfície, o gradiente e o grão vêm de `.brand-surface` (a mesma do painel de login e da faixa
   do Início) — aqui mora só a geometria do cabeçalho. */
.main-top {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 32px; flex-wrap: wrap;
}
.main-top h1 {
  font-family: var(--font-display); font-weight: 700; font-size: 22px; margin: 0;
  letter-spacing: -0.015em; color: var(--brand-panel-ink); text-wrap: balance;
  display: inline-flex; align-items: center; gap: 11px;
}
/* A barra de 4px continua sendo a marca de cabeçalho do sistema, mas trocou o degrau claro: o
   `--accent` (#0B6C60) sobre `--brand-panel` (#06382F) dá 1.4:1 e a barra desaparecia no fundo.
   O glow no topo e o barro embaixo mantêm o gradiente pinheiro→barro legível sobre o escuro. */
/* Branca, e não o gradiente pinheiro→barro que ela tinha sobre o cabeçalho claro: sobre o teal
   profundo o degrau verde do gradiente dá 1.4:1 e a metade de cima da barra desaparecia no fundo. */
.main-top h1::before {
  content: ""; width: 4px; height: 22px; border-radius: 2px; flex: none;
  background: var(--brand-panel-ink);
}
/* Linha de escrever mensagem da sala de atendimento (paciente, convidado, médico e triagem de
   enfermagem). A regra mora AQUI, e não nas páginas, porque o bloco está duplicado nas quatro e
   o defeito era idêntico nas quatro.
   O defeito: o campo é item flex com `flex: 1`, e item flex tem `min-width: auto` por padrão —
   ele se recusa a encolher abaixo do próprio tamanho intrínseco. Num celular estreito, campo
   (170px) + clipe (44px) + Enviar (70px) + espaçamentos não cabiam na largura do cartão, e quem
   sobrava pra fora era o botão Enviar, que ainda levava a página inteira a rolar na horizontal.
   Relatado numa sala real de atendimento em 2026-08-19.
   `min-width: 0` devolve ao campo a permissão de encolher, que é o que o `flex: 1` já prometia.
   O `flex-wrap` é a segunda linha de defesa: em largura absurda (ou com fonte muito ampliada por
   acessibilidade), a linha quebra em duas em vez de vazar. */
.chat-input-row { flex-wrap: wrap; }
.chat-input-row input[type="text"] { min-width: 0; }

.main-top .right { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* Data de hoje no canto direito do cabeçalho (Shared.renderHeaderDate). Mesma tipografia do
   `.brand-eyebrow` — é a mesma classe de informação, contexto e não título —, e a mesma tinta
   suave da superfície de marca, pra não competir com o h1 branco ao lado.
   `margin-left: auto` cobre o caso de a data ser o único elemento além do h1: o space-between já
   resolveria, mas com um terceiro filho (botão) a data ficaria no meio sem isto. */
.main-top-date {
  font-family: var(--font-mono); font-size: var(--fs-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--brand-panel-ink-soft); margin-left: auto; white-space: nowrap;
}
/* No celular o cabeçalho quebra em duas linhas (flex-wrap): a data desce sozinha e o
   `margin-left: auto` a empurraria pra quina de uma linha só dela. Alinhada à esquerda ali,
   ela lê como legenda do título em vez de sobra. */
@media (max-width: 560px) {
  .main-top-date { margin-left: 0; }
}
/* Controle sobre o cabeçalho escuro: os botões do sistema usam --surface/--border/--ink-soft, que
   sobre o teal profundo somem. Estes derivam da tinta do painel. */
.main-top .btn-ghost {
  border-color: rgba(255,255,255,0.22); background: rgba(255,255,255,0.06);
  color: var(--brand-panel-ink-soft);
}
.main-top .btn-ghost:hover {
  color: var(--brand-panel-ink); border-color: rgba(255,255,255,0.42); background: rgba(255,255,255,0.12);
}
.main-top .btn-ghost:focus-visible, .main-top .btn-primary:focus-visible {
  outline: 2px solid var(--brand-panel-glow); outline-offset: 2px;
}
.main-top .conn { color: var(--brand-panel-ink-soft); }

.main-scroll { flex: 1; padding: 32px; max-width: 1180px; width: 100%; margin: 0 auto; }

/* ---------------- navegação mobile: drawer ----------------
   Havia uma barra fixa no rodapé tentando caber a navegação inteira. Gestão vê 10 destinos:
   os rótulos quebravam e se sobrepunham ("PA Virtual" colidia com "Home Care" de baixo), a
   Escala escapava pra cima da barra (o `display: contents` no .side-group tirava o submenu
   do fluxo da linha) e os últimos itens saíam cortados fora da tela.

   Nenhuma barra de rodapé resolve 10 itens. O drawer resolve qualquer quantidade — e como
   cada papel vê um conjunto diferente (applyRoleNav esconde o que não é do papel), a
   navegação não pode depender de caber num número fixo de colunas. De quebra, o submenu
   Home Care > Escala/Roteirização volta a ser hierarquia de verdade, com chevron. */
@media (max-width: 860px) {
  /* z-index acima de 1000: o Leaflet põe os próprios controles em 1000 (.leaflet-top/.leaflet-bottom)
     e as camadas em 400, então com o drawer em 60 o mapa do Home Care era desenhado por cima dele.
     Fica abaixo de .modal-overlay (2000) e do .skip-link (3000), acima do Assistente (1200) — o
     drawer cobre a tela, então tem que cobrir o FAB também. */
  .sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 1410;
    width: min(300px, 84vw); padding: 18px 14px;
    border-right: 1px solid var(--border);
    transform: translateX(-100%);
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
    overflow-y: auto; overscroll-behavior: contain;
    box-shadow: none;
  }
  body.nav-open .sidebar { transform: translateX(0); box-shadow: 0 0 40px -8px rgba(16,30,25,0.35); }

  .nav-scrim {
    position: fixed; inset: 0; z-index: 1400; background: var(--scrim);
    opacity: 0; pointer-events: none; transition: opacity 0.22s ease;
  }
  body.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

  /* O gatilho é injetado por shared.js no .main-top de toda tela com shell. */
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    width: 44px; height: 44px; margin-left: -8px; border-radius: 10px;
    /* Vive DENTRO do cabeçalho, que é a superfície de marca escura — daí a borda e a tinta
       derivarem do painel, e não de --surface/--ink como o resto dos controles do sistema. */
    border: 1px solid rgba(255,255,255,0.22); background: rgba(255,255,255,0.06); color: var(--brand-panel-ink);
    transition: background 0.12s ease, border-color 0.12s ease;
  }
  .nav-toggle svg { width: 20px; height: 20px; }
  .nav-toggle:hover { background: rgba(255,255,255,0.14); border-color: rgba(255,255,255,0.42); }
  .nav-toggle:focus-visible { outline: 2px solid var(--brand-panel-glow); outline-offset: 2px; }

  /* Alvos generosos: o drawer é tocado com o polegar, não clicado com mouse. */
  .side-link { padding: 12px 12px; min-height: 46px; font-size: 14px; }
  .side-sublink { min-height: 44px; font-size: 13px; }
  .side-link svg { width: 19px; height: 19px; }
  .sidebar-brand { padding: 2px 6px 20px; }
  /* Sem `background` aqui: o cabeçalho já é a superfície de marca, e repintar com --bg apagaria o
     gradiente justamente no celular.
     O seletor precisa das DUAS classes: `.brand-surface` declara `position: relative` e está
     definida depois deste bloco no arquivo, então com a mesma especificidade (0,1,0) ela ganhava
     por ordem e o cabeçalho parava de grudar no topo ao rolar. Medido: `position` computado vinha
     `relative`. `.main-top.brand-surface` é (0,2,0) e resolve sem depender da ordem. */
  .main-top.brand-surface { position: sticky; top: 0; z-index: 30; }
  /* Com o botão de menu injetado no cabeçalho, o `justify-content: space-between` do desktop jogava
     o título pro canto direito, longe do botão que o acompanha. `margin-right: auto` devolve o
     título pro lado do menu e mantém o espaço livre à direita pros controles da tela. */
  .main-top h1 { margin-right: auto; }
}
@media (min-width: 861px) {
  /* fora do mobile o drawer não existe: sidebar é coluna fixa e o gatilho some */
  .nav-toggle, .nav-scrim { display: none; }
}

@media (max-width: 560px) {
  .main-scroll { padding: 18px; }
  .main-top { padding: 12px 16px; gap: 10px; }
  .main-top h1 { font-size: 18px; }
  .main-top h1::before { height: 18px; }
}

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 4px 0 20px; border-bottom: 1px solid var(--border); margin-bottom: 22px;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 11px; }
.brand .mark {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.brand .mark img { width: 100%; height: 100%; object-fit: contain; }
.brand h1 {
  font-family: var(--font-display); font-size: 22px; font-weight: 700; margin: 0;
  letter-spacing: -0.015em; text-wrap: balance; color: var(--ink);
  display: inline-flex; align-items: center; gap: 10px;
}
.brand h1::before {
  content: ""; width: 4px; height: 21px; border-radius: 2px; flex: none;
  background: linear-gradient(180deg, var(--accent), var(--queue));
}
.brand .sub { font-size: 12.5px; color: var(--ink-faint); margin-left: 2px; }

.nav-links { display: flex; gap: 6px; flex-wrap: wrap; }
.nav-link {
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-soft);
  padding: 7px 12px; border-radius: 8px; font-size: 12.5px; font-weight: 550;
  text-decoration: none; display: inline-flex; align-items: center; gap: 5px;
}
.nav-link:hover { color: var(--accent); border-color: var(--accent-soft); background: var(--accent-soft); }
.nav-link.active { color: var(--accent-soft-ink); background: var(--accent-soft); border-color: var(--accent-soft); }

.conn { font-size: 11px; color: var(--ink-faint); display: flex; align-items: center; gap: 5px; }
.conn .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); flex: none; }
.conn.down .dot { background: var(--danger); }

h2.section-title { font-size: 13px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); margin: 0 0 12px; }

.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), var(--shadow);
}
.card { transition: box-shadow 0.16s ease, border-color 0.16s ease, transform 0.16s ease; }

/* ---------------- superfície de marca (faixa / painel / tarja) ----------------
   O material de marca do produto: rampa de três tons do verde institucional (os tokens
   `--brand-panel*`), quatro camadas de luz e um grão que dá material ao gradiente.

   Nasceu duplicado LITERAL em login.html e landing.html — mesmo gradiente, mesmo data-URI de
   ruído, escritos duas vezes. Ao propagar a linguagem pras telas de entrada do beneficiário a
   duplicação ia pra cinco cópias, que é exatamente o caso que a Regra do Padrão Repetido
   (DESIGN.md) proíbe: as três telas cruas que o projeto já registra vieram daí. Uma superfície
   de marca, um valor, e o modificador decide a proporção.

   Três modificadores, porque são três geometrias com problemas diferentes:
     --panel  painel alto e estreito (metade esquerda do login). Vertical, aceita a marca
              d'água sangrando pelo canto, porque tem altura pra mostrar o símbolo inteiro.
     --band   faixa horizontal larga (topo do Início, cabeçalho das telas de entrada). Sem
              marca d'água: o símbolo é quase quadrado (720×670) e numa faixa de ~180px
              qualquer posição corta uma fatia do meio da casa, que lê como borrão.
     --strip  tarja baixa (~64px) das telas de trabalho. Carrega só papel + data em mono; sem
              headline, porque numa tela cuja informação é a fila ou a tabela, altura gasta em
              marca é altura roubada do conteúdo.

   Contraste medido (WCAG 2.1 AA) contra --brand-panel, o mais claro dos três tons e portanto o
   pior caso: --brand-panel-ink 13.0:1, --brand-panel-ink-soft 8.2:1, --brand-panel-glow 8.3:1. */
.brand-surface {
  position: relative; overflow: hidden; isolation: isolate;
  color: var(--brand-panel-ink);
  /* Três camadas, e cada uma faz uma coisa: brilho quente no topo-esquerda (de onde a luz
     vem), halo do verde da marca no canto oposto, e a rampa diagonal que segura as duas.
     Gradiente sozinho fica plano; é a sobreposição que dá profundidade. */
  background:
    radial-gradient(88% 70% at 11% 0%, rgba(255,255,255,0.13) 0%, transparent 55%),
    radial-gradient(68% 65% at 90% 96%, color-mix(in srgb, var(--accent) 52%, transparent) 0%, transparent 61%),
    linear-gradient(155deg, var(--brand-panel) 0%, var(--brand-panel-mid) 53%, var(--brand-panel-deep) 100%);
}
/* Grão: sem ele, superfície grande de gradiente lê como plástico. Em pseudo-elemento com
   pointer-events:none e sem repaint — a superfície não anima, então não custa FPS. */
.brand-surface::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.16'/%3E%3C/svg%3E");
}
/* Conteúdo acima do grão e da marca d'água, que vivem em z-index -1. */
.brand-surface > * { position: relative; }

.brand-surface--panel {
  padding: clamp(36px, 4.2vw, 72px) clamp(32px, 4.5vw, 76px);
  display: flex; flex-direction: column; gap: clamp(28px, 3.4vh, 44px);
  /* Fio de luz na aresta em vez de border sólido: a emenda entre painel e formulário deixa de
     ser corte seco e passa a ler como quina iluminada. */
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.09);
}

/* Raio 20px e sombra tingida no próprio verde da marca, em duas camadas: contato curto que
   assenta na superfície, queda longa que dá elevação. Sombra preta pura sobre o papel
   esverdeado do sistema suja — a Regra da Sombra Tingida vale aqui também. */
.brand-surface--band {
  border-radius: 20px; padding: clamp(30px, 3.4vw, 46px) clamp(26px, 3.6vw, 52px);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--brand-panel) 10%, transparent),
    0 22px 50px -28px color-mix(in srgb, var(--brand-panel) 42%, transparent);
}

/* Raio 14px e não 20: a Regra do Raio Proporcional manda o raio crescer com a área, e a tarja tem
   um terço da altura da faixa. Grão a 0.32 pelo mesmo motivo — em superfície baixa o ruído a 0.5 lê
   como sujeira, não como material.
   A tarja fica DENTRO do scroll, abaixo do cabeçalho: o cabeçalho carrega só a marca e o título da
   tela, e o contexto de turno (escopo · papel · data) pertence ao conteúdo, não ao título. */
.brand-surface--strip {
  border-radius: 14px; padding: 15px 20px;
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--brand-panel) 10%, transparent),
    0 14px 30px -22px color-mix(in srgb, var(--brand-panel) 38%, transparent);
}
.brand-surface--strip::after { opacity: 0.32; }
.brand-surface--strip .brand-eyebrow { margin: 0; }
/* Espaço entre a tarja e o conteúdo. Mora aqui e não na página porque a tarja é inserida por JS
   (Shared.renderBrandStrip) como primeiro filho de `.main-scroll`. */
.main-scroll > .brand-surface--strip { margin-bottom: 22px; }
@media (max-width: 560px) {
  .brand-surface--strip { padding: 13px 16px; gap: 8px; }
}
/* Número vivo da direita da tarja. Mono porque é contagem — a Regra do Mono de Identidade. `glow` e
   não a tinta branca pra separar o dado do rótulo sem precisar de outro peso de fonte. */
/* Valor ausente num slot de NÚMERO (quadro de indicador, total de período). Diferente da célula
   de tabela, onde um hífen basta porque a coluna já diz do que se trata: aqui o slot é o assunto do
   quadro, e um traço solto em 22px de mono lê como defeito de renderização. Diz a ausência em
   palavra, no tamanho de metadado, pra não competir com os quadros que TÊM número. */
.is-empty {
  font-family: var(--font-ui) !important; font-size: var(--fs-sm) !important;
  font-weight: 500 !important; color: var(--ink-faint) !important; letter-spacing: 0 !important;
}

.brand-strip-note {
  font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 600;
  color: var(--brand-panel-glow); white-space: nowrap;
}

/* Marca d'água: o símbolo da marca ampliado, sangrando pelo canto. Textura, não conteúdo —
   quem usa leitor de tela já recebeu o nome da marca no logo, e repetir seria ruído. Só no
   modificador --panel (ver o comentário de geometria acima). */
.brand-surface .brand-watermark {
  position: absolute; right: -12%; bottom: -14%; width: min(88%, 720px); height: auto;
  opacity: 0.16; z-index: -1; pointer-events: none; user-select: none;
}

/* Eyebrow da superfície de marca: papel Micro-label da escala, em mono. Diz o que a pessoa
   precisa saber antes do título — em que turno está, ou em que etapa da jornada. */
.brand-surface .brand-eyebrow {
  font-family: var(--font-mono); font-size: var(--fs-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--brand-panel-ink-soft); margin: 0 0 14px;
}
.brand-surface .brand-eyebrow .sep { opacity: 0.45; margin: 0 0.5em; }
.brand-surface--strip .brand-eyebrow { margin: 0; }

/* Texto de apoio sob o título, dentro da superfície. */
.brand-surface .brand-support {
  font-size: clamp(14.5px, 1.2vw, 16.5px); color: var(--brand-panel-ink-soft); line-height: 1.68;
  margin: 12px 0 0; max-width: 46ch;
}
/* Rodapé do painel de login ("Acesso restrito à equipe assistencial"): empurrado pro fim pelo
   `auto` no topo da margem, dentro do flex-column do --panel. */
.brand-surface .brand-tagline {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.5); margin: auto 0 0;
}

/* Botão fantasma SOBRE a superfície escura. O .btn-ghost normal usa --surface/--border/
   --ink-soft, que sobre o teal profundo dá 1.3:1 de borda e texto quase invisível. Aqui a
   borda e o texto vêm da tinta do painel: 8.2:1 no texto, e o hover sobe pra tinta cheia. */
.brand-surface .btn-ghost-onbrand {
  border: 1px solid rgba(255,255,255,0.22); background: rgba(255,255,255,0.06);
  padding: 9px 15px; border-radius: 8px; font-size: 13px; font-weight: 560;
  color: var(--brand-panel-ink-soft); text-decoration: none; display: inline-flex;
  align-items: center; gap: 6px; white-space: nowrap;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease, transform 0.08s ease;
}
.brand-surface .btn-ghost-onbrand:hover {
  color: var(--brand-panel-ink); border-color: rgba(255,255,255,0.42); background: rgba(255,255,255,0.12);
}
.brand-surface .btn-ghost-onbrand:active { transform: translateY(1px); }
.brand-surface .btn-ghost-onbrand:focus-visible { outline: 2px solid var(--brand-panel-glow); outline-offset: 2px; }

/* ---------------- Display Hero: o degrau fluido da escala tipográfica ----------------
   Só dentro da superfície de marca (DESIGN.md nomeia o papel; até agora cada tela declarava o
   clamp na mão). Peso 600 e não 700 porque em corpo grande o 700 do Manrope fecha o contraforma
   — o tamanho já é a ênfase. line-height 1.11 é o mínimo seguro: o título tem descendente e a
   ênfase pode ser itálica, e o padding-bottom é a reserva pra essa descendente não ser cortada.
   É o único degrau fluido do sistema porque a faixa ocupa a largura toda: valor fixo ou quebra
   em três linhas no notebook, ou fica tímido no monitor grande. */
.display-hero {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(30px, 3.4vw, 46px); line-height: 1.11; letter-spacing: -0.025em;
  margin: 0; padding-bottom: 3px; text-wrap: balance; color: var(--brand-panel-ink);
}
/* A palavra destacada. Sobre o painel escuro o verde da marca some (4.0:1), por isso usa
   --brand-panel-glow, o teal claro da paleta, que dá 8.3:1 no mesmo fundo. Itálico é opção do
   uso, não do papel: em nome próprio o itálico lê como citação ou estrangeirismo, e não é
   nenhum dos dois — por isso `.glow` existe separado de `em`. */
.display-hero em { font-style: italic; color: var(--brand-panel-glow); }
.display-hero .glow { color: var(--brand-panel-glow); }
/* Coluna estreita (jornada do beneficiário, ~460px): o clamp acima é calculado sobre a JANELA,
   não sobre o container, então num container de 412px o passo de 46px quebra em quatro linhas.
   Este degrau fecha a escala no que caber na coluna. */
.display-hero--narrow { font-size: clamp(23px, 5.4vw, 31px); line-height: 1.18; letter-spacing: -0.018em; }

/* ---------------- entrada em cascata ----------------
   Uma entrada, uma vez, e só: nada em loop, nada preso a scroll. Serve a hierarquia — a ordem
   em que a tela se explica — e morre depois de ~700ms.

   Fora do @media a página nasce com opacidade 1: quem pediu menos movimento não vê nada
   aparecer, e nada fica invisível se a animação não rodar. Nasceu duplicada em login.html e
   landing.html com easing e duração DIFERENTES (0.62s vs 0.5s, curvas distintas), o que fazia
   a mesma cascata ter dois ritmos entre duas telas vizinhas. Unificado aqui na curva mais
   curta, que é a que lê melhor em tela com conteúdo. */
@media (prefers-reduced-motion: no-preference) {
  .rise { animation: rise 0.52s cubic-bezier(0.22, 1, 0.36, 1) both; }
  .rise-1 { animation-delay: 0.04s; }
  .rise-2 { animation-delay: 0.12s; }
  .rise-3 { animation-delay: 0.18s; }
  .rise-4 { animation-delay: 0.24s; }
  .rise-5 { animation-delay: 0.30s; }
  @keyframes rise {
    from { opacity: 0; transform: translateY(11px); }
    to   { opacity: 1; transform: none; }
  }
}

/* ---------------- cabeçalho de seção em display ----------------
   O degrau Display da escala, alinhado à esquerda na mesma margem do conteúdo abaixo. Existe
   porque o sistema só tinha o papel Label pra título de seção (13px, uppercase, ink-faint,
   ver .panel h2 e h2.section-title) — que é certo pra título DENTRO de um card, e fraco demais
   pra separar grupos de cards numa tela. Título centralizado no meio de uma coluna alinhada à
   esquerda cria um eixo que nada mais na página usa, por isso não é centralizado. */
.section-head { margin: 0 0 18px; }
.section-head > h2, .section-head > h3 {
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-2xl);
  margin: 0; letter-spacing: -0.005em; color: var(--ink); text-transform: none;
}
.section-head > p { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--ink-soft); line-height: 1.55; max-width: 62ch; }

/* ---------------- card de destino (com cor própria) ----------------
   O card dos módulos do Início: cada um declara seu `--tint` e a superfície, a sombra e a seta
   derivam dele. Sombra tingida na cor do próprio card, em duas camadas — sombra preta neutra
   sobre o papel esverdeado do sistema acinzenta a cor do card por baixo. */
.tint-card {
  position: relative; border-radius: 16px; padding: 24px;
  display: flex; flex-direction: column; gap: 10px;
  text-decoration: none; color: inherit; border: 1px solid var(--border);
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
  background: linear-gradient(160deg, var(--tint-soft) 0%, var(--surface) 65%);
}
.tint-card:hover {
  transform: translateY(-3px);
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--tint) 14%, transparent),
    0 16px 32px -18px color-mix(in srgb, var(--tint) 55%, transparent);
  border-color: color-mix(in srgb, var(--tint) 30%, var(--border));
}
.tint-card:active { transform: translateY(-1px); }
.tint-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Os quatro pares de tinta do sistema. Barro (`queue`) aparece aqui só no card do Home Care —
   a Regra do Barro Raro continua valendo: não é cor de card qualquer. */
.tint-card.tint-accent { --tint: var(--accent); --tint-soft: var(--accent-soft); }
.tint-card.tint-queue { --tint: var(--queue); --tint-soft: var(--queue-soft); }
.tint-card.tint-signature { --tint: var(--signature); --tint-soft: var(--signature-soft); }
.tint-card.tint-plain { --tint: var(--ink-faint); --tint-soft: var(--surface-sunken); }
.tint-card .icon-wrap {
  width: 44px; height: 44px; border-radius: 12px; background: var(--surface);
  box-shadow: var(--shadow); display: flex; align-items: center; justify-content: center;
  transition: transform 0.16s ease;
}
.tint-card:hover .icon-wrap { transform: scale(1.06); }
.tint-card .icon-wrap svg { width: 21px; height: 21px; color: var(--tint); }
.tint-card h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-xl); margin: 4px 0 0; }
.tint-card p { font-size: var(--fs-sm); color: var(--ink-soft); line-height: 1.55; margin: 0; }
.tint-card .go { margin-top: auto; padding-top: 6px; font-size: var(--fs-sm); font-weight: 630; color: var(--tint); display: flex; align-items: center; gap: 4px; }
.tint-card .go .arrow { transition: transform 0.16s ease; }
.tint-card:hover .go .arrow { transform: translateX(3px); }

/* ---------------- estado vazio ----------------
   Fonte única do "aqui existe um lugar, e ele está vazio". Cada tela tinha inventado o seu:
   `.record-empty` (texto solto, 40px de padding), `.rot-empty` (texto solto, 30px), `.empty-note`
   em duas versões conflitantes na mesma base, mais uma dúzia de frases centralizadas sem classe
   nenhuma. Numa tela de plantão calmo o estado vazio é o que a pessoa olha o dia inteiro, e texto
   solto no meio de um card alto lê como "faltou carregar", não como "está vazio".

   A superfície afundada é o que resolve: é a única ferramenta de hierarquia sem sombra do sistema,
   e ela desenha o limite do lugar vazio. Os nomes antigos entram no mesmo seletor em vez de serem
   trocados em ~60 pontos de markup — mesma decisão que `users-head`/`toggle-switch`/`editable-table`
   registram em DESIGN.md.

   Ficam FORA de propósito `.video-placeholder` e `.guest-empty`: são placeholders de mídia dentro
   de container de vídeo (fundo --ink), onde superfície afundada clara não tem contraste. */
.empty-state,
.record-empty, .rot-empty, .empty-note {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  text-align: center; padding: 26px 20px; border-radius: 12px;
  background: var(--surface-sunken); color: var(--ink-soft);
  font-size: var(--fs-md); line-height: 1.55;
}
/* Título do estado vazio, quando ele tem duas linhas: o que está vazio, e o que fazer a respeito.
   Uma linha só continua sendo o padrão — não force uma segunda pra preencher espaço. */
.empty-state strong, .empty-state .es-title { font-weight: 650; color: var(--ink); }
.empty-state .es-hint { font-size: var(--fs-xs); color: var(--ink-faint); }
/* Ícone opcional, pra estado vazio que ocupa card inteiro. Em bloco pequeno é ruído. */
.empty-state .es-icon {
  width: 34px; height: 34px; border-radius: 10px; background: var(--surface);
  display: flex; align-items: center; justify-content: center; margin-bottom: 3px;
  box-shadow: var(--shadow);
}
.empty-state .es-icon svg { width: 17px; height: 17px; color: var(--ink-faint); }
/* Vaga à espera de conteúdo que o usuário vai criar (fila, escala, rota), em oposição a lista que
   simplesmente não tem nada hoje. O tracejado é o convite. */
.empty-state--slot { background: transparent; border: 1px dashed var(--border); }
/* Dentro de linha de tabela ou sub-bloco, onde 26px de padding empurra o resto da tela. */
.empty-state--compact, .rot-empty.small { padding: 13px 12px; font-size: var(--fs-sm); gap: 3px; }
/* Ocupa o card todo, pra não deixar um bloco de 20px de altura no meio de um card de 300px. */
.empty-state--tall { min-height: 180px; }

/* Base comum aos dois botões. Existe porque o sistema usa `<a class="btn-ghost">` em 29 lugares
   (exportação em Manutenção, atalhos no Dashboard e na Roteirização) e nenhuma das duas classes
   zerava o `text-decoration` da âncora: o MESMO botão saía sólido quando era <button> e sublinhado
   quando era <a>, lado a lado na mesma linha em manutencao.html.
   `inline-flex` + `min-height` pelo mesmo motivo de alinhamento: com `padding` sozinho, botão (35px)
   e campo de formulário (38px) fechavam alturas diferentes, e toda linha que mistura os dois com
   `align-items: flex-end` saía irregular. Um piso só resolve as duas coisas. */
.btn-primary, .btn-ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 38px; box-sizing: border-box; text-decoration: none; cursor: pointer;
  white-space: nowrap; font-family: inherit;
}
.btn-primary {
  border: none; background: var(--accent); color: var(--accent-ink); font-weight: 630;
  padding: 9px 15px; border-radius: 8px; font-size: 13px; letter-spacing: 0.005em;
  box-shadow: 0 1px 1px rgba(27,38,32,0.06);
  transition: filter 0.12s ease, transform 0.08s ease, box-shadow 0.12s ease;
}
.btn-primary:hover { filter: brightness(1.1); box-shadow: 0 3px 10px -3px color-mix(in srgb, var(--accent) 55%, transparent); transform: translateY(-1px); }
.btn-primary:active { transform: translateY(0); filter: brightness(1.02); }
.btn-primary[disabled], .take-btn[disabled] { opacity: 0.55; cursor: default; transform: none; box-shadow: none; }
.btn-primary:focus-visible, .btn-ghost:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-ghost {
  border: 1px solid var(--border); background: var(--surface); padding: 9px 15px; border-radius: 8px;
  font-size: 13px; font-weight: 560; color: var(--ink-soft);
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease, transform 0.08s ease;
}
.btn-ghost:hover { color: var(--ink); border-color: var(--ink-faint); background: var(--surface-sunken); }
.btn-ghost:active { transform: translateY(1px); }
.btn-ghost[disabled] { opacity: 0.55; cursor: default; transform: none; }

/* ---------------- grupo segmentado ----------------
   Três formatos do MESMO dado (CSV / XLSX / JSON) eram três botões soltos com 4px de vão entre eles,
   o que lê como três ações independentes. Encostados e com uma borda só, leem como o que são: uma
   escolha entre variações da mesma ação. Também acaba com o efeito de "borda dupla" no vão. */
.btn-group { display: inline-flex; align-items: stretch; }
.btn-group > .btn-ghost {
  border-radius: 0; margin-left: -1px; padding: 9px 13px; font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.btn-group > .btn-ghost:first-child { border-radius: 8px 0 0 8px; margin-left: 0; }
.btn-group > .btn-ghost:last-child { border-radius: 0 8px 8px 0; }
.btn-group > .btn-ghost:only-child { border-radius: 8px; }
/* z-index no hover/foco pra a borda ativa aparecer inteira, e não cortada pelo vizinho de -1px. */
.btn-group > .btn-ghost:hover, .btn-group > .btn-ghost:focus-visible { position: relative; z-index: 1; }

/* ---------------- campo de arquivo ----------------
   O `<input type="file">` nativo desenha o botão do sistema operacional dentro do formulário: fonte,
   raio e altura diferentes de todo o resto, e largura esticada até o fim do container. Estilizado
   pelo pseudo-elemento `::file-selector-button`, o botão passa a ser o mesmo `.btn-ghost` do sistema
   e o nome do arquivo fica no tom de metadado. Sem JS e sem mudar markup: vale nos seis campos de
   arquivo que já existem (importação em Manutenção, anexo de chat em três telas). */
/* Os dois seletores: `.field input` (mais abaixo neste arquivo) declara `width: 100%`, `padding` e
   `border-radius` com especificidade (0,2,0) e ganharia de `input[type="file"]` (0,1,1) — o campo
   voltava pra largura total do container e perdia o desenho de área de soltura. */
input[type="file"], .field input[type="file"] {
  /* `width` explícito, e NÃO display:flex + min-width: o layout interno do campo de arquivo é shadow
     DOM do navegador, então flex no elemento não distribui nada — a área do nome do arquivo continua
     com a largura intrínseca dela e o texto vira "Nenhum ar...vo escolhido", com elipse no MEIO da
     frase. Só largura resolve. 24rem cabe o texto padrão do português mais o botão; `max-width`
     mantém o campo dentro do container em tela estreita. */
  width: 24rem; max-width: 100%;
  padding: 5px 10px 5px 5px; min-height: 38px; box-sizing: border-box;
  border: 1.5px dashed var(--border); border-radius: 9px; background: var(--surface);
  font-family: inherit; font-size: 12.5px; color: var(--ink-faint); cursor: pointer;
  transition: border-color 0.14s ease, background 0.14s ease;
}
input[type="file"]:hover, .field input[type="file"]:hover { border-color: var(--ink-faint); background: var(--surface-sunken); }
input[type="file"]:focus-visible, .field input[type="file"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
input[type="file"]::file-selector-button, .field input[type="file"]::file-selector-button {
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-soft);
  padding: 7px 13px; border-radius: 7px; font-family: inherit; font-size: 12.5px; font-weight: 560;
  margin-right: 10px; cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
input[type="file"]::file-selector-button:hover, .field input[type="file"]::file-selector-button:hover { color: var(--ink); border-color: var(--ink-faint); background: var(--surface-sunken); }

.panel { padding: 20px 22px; display: flex; flex-direction: column; gap: 14px; }
/* Título de seção do card. Era só `h3`, o que forçava as telas a pular de <h1> direto pra <h3>
   — navegação por cabeçalho em leitor de tela via um nível fantasma faltando. Agora o estilo é
   o mesmo em h2 (seção de primeiro nível) e h3 (subseção dentro de uma), e o nível vira decisão
   de estrutura, não de aparência. */
/* O `:not()` não é enfeite: sem ele esta regra tem especificidade (0,1,1) e ATROPELA
   `.display-hero` (0,1,0) e `.section-head > h2` sempre que um deles cai dentro de um `.panel` —
   o título de display sai em 13px, caixa alta e `ink-faint`, ou seja com a aparência de rótulo de
   metadado. Aconteceu de verdade na superfície de saída de convidado.html, onde a faixa de marca
   fica dentro do card da chamada. Com o `:not()` o padrão simplesmente não casa quando o
   cabeçalho declara um papel explícito, e aí quem manda é a classe do papel. */
.panel h2:not(.display-hero):not(.section-title),
.panel h3:not(.display-hero):not(.section-title) { margin: 0; font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); font-weight: 650; }

/* Cabeçalho de card com título + descrição — fonte única (antes só existia local em
   config.html, então ia.html/manutencao.html mostravam o <p> sem nenhum estilo, cru). */
.users-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
.users-head p { margin: 3px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-soft); max-width: 62ch; }
.users-head-row { display: flex; align-items: flex-start; gap: 12px; flex: 1; min-width: 0; }
.users-head .head-text { flex: 1; min-width: 0; }
/* flex:1 + min-width:0 deixa esta caixa encolher abaixo do conteúdo. Sem quebra forçada, um
   título em CAIXA ALTA com letter-spacing ("INDICADORES DE SLA · PA VIRTUAL") ultrapassa a
   própria caixa e é pintado POR CIMA do controle ao lado — não é sobreposição de layout, é
   texto vazando, então nenhuma checagem de bounding box pega. */
.users-head-row h1, .users-head-row h2, .users-head-row h3 { overflow-wrap: anywhere; min-width: 0; }

/* No celular o título e a ação ao lado dele disputam a mesma linha: como .users-head-row é
   flex:1 (base 0), ele encolhe em vez de quebrar, e o título vira três linhas espremidas ao
   lado de um botão. Empilhar é o certo — a ação ganha largura total e vira alvo de toque. */
@media (max-width: 640px) {
  .users-head { flex-direction: column; align-items: stretch; }
  .users-head > .btn-primary, .users-head > .btn-ghost { width: 100%; }
}

/* Ícone de identidade por seção — usado quando uma tela empilha vários cards/catálogos
   soltos (Configurações, telas de cadastro) e cada um precisa ser reconhecido de relance.
   Variantes de cor tomam emprestado o vocabulário já usado nos chips (.papel-chip etc):
   verde=PA Virtual, terracota=Home Care, azul=neutro/Geral. */
.section-icon {
  width: 34px; height: 34px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
  flex: none; background: var(--signature-soft); color: var(--signature);
}
.section-icon svg { width: 18px; height: 18px; }
.section-icon.accent { background: var(--accent-soft); color: var(--accent-soft-ink); }
.section-icon.queue { background: var(--queue-soft); color: var(--queue); }
.section-icon.signature { background: var(--signature-soft); color: var(--signature); }
.section-icon.danger { background: var(--danger-soft); color: var(--danger); }

/* Switch liga/desliga — fonte única (antes só existia local em ia.html). Marcação:
   <label class="toggle-switch"><input type="checkbox">.<span class="track"></span></label> */
.toggle-switch { position: relative; display: inline-block; width: 34px; height: 20px; flex: none; }
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-switch .track { position: absolute; inset: 0; background: var(--border); border-radius: 999px; transition: background .15s; cursor: pointer; }
.toggle-switch .track::before { content: ""; position: absolute; width: 14px; height: 14px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform .15s; }
.toggle-switch input:checked + .track { background: var(--accent); }
.toggle-switch input:checked + .track::before { transform: translateX(14px); }
.toggle-switch input:disabled + .track { opacity: .5; cursor: not-allowed; }
.toggle-switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Tabela de catálogo editável (perguntas/protocolos/turnos/usuários etc.) — fonte única,
   nasceu em config.html/escala.html. Campo "fantasma" em repouso (lê como dado limpo, contorno
   só aparece ao passar o mouse/focar) exceto na linha "adicionar" (classe .add-row), que é
   formulário mesmo e fica sempre com contorno visível. */
.editable-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.editable-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 620; padding: 9px 10px; border-bottom: 1px solid var(--border); }
.editable-table td { padding: 4px 6px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.editable-table tr:last-child td { border-bottom: none; }
.editable-table tbody tr:not(.add-row):hover td { background: var(--surface-sunken); }
.editable-table tbody tr:not(.add-row) input[type="text"],
.editable-table tbody tr:not(.add-row) input:not([type]),
.editable-table tbody tr:not(.add-row) input[type="time"],
.editable-table tbody tr:not(.add-row) input[type="number"],
.editable-table tbody tr:not(.add-row) select {
  border-color: transparent; background: transparent;
}
.editable-table tbody tr:not(.add-row) input[type="text"]:hover,
.editable-table tbody tr:not(.add-row) input:not([type]):hover,
.editable-table tbody tr:not(.add-row) input[type="time"]:hover,
.editable-table tbody tr:not(.add-row) input[type="number"]:hover,
.editable-table tbody tr:not(.add-row) select:hover {
  border-color: var(--border); background: var(--surface);
}
.editable-table input[type="text"], .editable-table input:not([type]), .editable-table select, .editable-table input[type="time"] {
  width: 100%; padding: 7px 9px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface); font-size: 13px;
  transition: border-color .12s ease, background .12s ease;
}
.editable-table input[type="text"]:focus-visible, .editable-table input:not([type]):focus-visible,
.editable-table select:focus-visible, .editable-table input[type="time"]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); background: var(--surface);
}
.editable-table input[type="number"] { width: 64px; padding: 7px 9px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface); }
.editable-table .add-row td { background: var(--surface-sunken); padding: 8px 6px; }
.editable-table .add-row .btn-primary { white-space: nowrap; }

/* Formulário de linha única (novo horário, nova campanha etc.) numa faixa própria — os
   campos deixam de parecer soltos/esquecidos embaixo de uma tabela. */
.inline-form-strip {
  display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; margin-top: 12px;
  padding: 14px; border-radius: 12px; background: var(--surface-sunken); border: 1px solid var(--border);
}

/* Pill-tabs — fonte única (nasceu em config.html). */
.tabs { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.tabs button {
  padding: 7px 16px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
  font-size: 12.5px; font-weight: 620; color: var(--ink-soft); cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.tabs button:hover:not(.active) { border-color: var(--ink-faint); color: var(--ink); }
.tabs button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tabs button.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* ---------------- campos de formulário (fonte única — antes cada tela reinventava) ---------------- */
.field { display: flex; flex-direction: column; gap: 6px; }
/* `line-height` explícito: o padrão do navegador pra 12.5px sobra espaço fantasma acima e abaixo do
   texto, e numa linha de formulário que alterna campo e grupo de botões (a exportação em Manutenção)
   cada rótulo assentava numa altura diferente, deixando a fileira irregular. */
.field label { font-size: 12.5px; font-weight: 630; color: var(--ink-soft); line-height: 1.35; }
/* Linha de formulário que mistura campo, grupo de botões e ação. `flex-end` alinha pela base dos
   controles, que é o que o olho lê como "uma linha", e não pelo topo dos rótulos de alturas
   diferentes. Fonte única: estava escrito à mão, com valores divergentes, em cada <form>. */
.form-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
/* Sem `min-width: 0` aqui: como item de flex o campo encolhe abaixo do próprio conteúdo, e o campo
   de arquivo — que tem largura declarada justamente pra caber o nome do arquivo — era comprimido de
   volta pra 20rem, desfazendo a correção da elipse. Cada campo ocupa o que precisa e a linha quebra
   quando não couber, que é pra isso que existe o `flex-wrap`. */
.form-row > .field { flex: 0 0 auto; }
.field input, .field select, .field textarea,
input.field-input, select.field-input, textarea.field-input {
  width: 100%; padding: 9px 12px; font-size: 13px; font-family: inherit; color: var(--ink);
  border-radius: 8px; border: 1.5px solid var(--border); background: var(--surface);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.field textarea { resize: vertical; min-height: 60px; line-height: 1.5; }
.field input::placeholder, .field textarea::placeholder { color: var(--ink-faint); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-faint); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible,
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.field input:disabled, .field select:disabled, .field textarea:disabled { opacity: 0.6; background: var(--surface-sunken); cursor: not-allowed; }
.field input.invalid, .field select.invalid, .field textarea.invalid { border-color: var(--danger); }
.field input.invalid:focus-visible, .field input.invalid:focus { box-shadow: 0 0 0 3px var(--danger-soft); }
/* `.hint` era declarado só como `.field .hint`, mas 9 telas o usam SOLTO (fora de um `.field`):
   corpo de modal enquanto carrega, nota abaixo de um bloco, legenda de tabela. Nesses 19 usos o
   elemento saía sem estilo nenhum — texto de metadado no tamanho e na cor de corpo. Vira classe
   de primeiro nível, com o descendente mantido só pela ordem (mesma declaração, então quem já
   estava dentro de `.field` não muda em nada). */
.hint, .field .hint { font-size: 11px; color: var(--ink-faint); line-height: 1.5; }
.field .error-msg { font-size: 11px; color: var(--danger); font-weight: 560; }

/* Olho de exibir/ocultar senha. O botão é injetado em TODO input[type=password] por shared.js
   (enhancePasswordFields), então o estilo mora aqui e não copiado nas 6 telas que têm campo de
   senha. O embrulho não declara largura: em bloco ele já ocupa a linha inteira, e o input dentro
   continua com o width que a própria tela declarou pra ele. O recuo à direita que abre espaço pro
   botão vai inline pelo JS — cada tela estiliza o próprio padding (login, redefinir-senha e .field
   usam valores diferentes), e uma regra aqui perderia a disputa de ordem pro <style> da página. */
.pw-wrap { position: relative; }
/* Só o embrulho criado pelo JS é <span> — quando o campo já vive num container posicionado da
   própria tela (o .input-icon do login, que é flex), o container recebe .pw-wrap mas não pode ter
   o display trocado, senão o ícone à esquerda e o campo saem de lugar. */
span.pw-wrap { display: block; }
/* Dois níveis de classe no seletor de propósito: as telas estilizam `button` genérico dentro do
   próprio cartão (`.reset-card button` deixa o botão verde, 100% de largura), e esse seletor tem
   especificidade maior que `.pw-toggle` sozinho — o olho saía como botão de ação. Daí também os
   resets explícitos de margin/min-height/box-shadow/font: é o que essas regras de página mandam
   e que precisa ser desfeito aqui. */
.pw-wrap .pw-toggle {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; min-height: 0; margin: 0; padding: 0;
  border: none; border-radius: 6px; box-shadow: none; font-size: inherit;
  background: none; color: var(--ink-faint); cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease;
}
.pw-wrap .pw-toggle:hover { color: var(--ink-soft); background: var(--surface-sunken); box-shadow: none; transform: translateY(-50%); }
.pw-wrap .pw-toggle:active { transform: translateY(-50%); }
.pw-wrap .pw-toggle:focus-visible { outline: none; color: var(--ink-soft); box-shadow: 0 0 0 2px var(--accent-soft); }
.pw-wrap .pw-toggle svg { width: 17px; height: 17px; }

/* Combobox digitável de código clínico: CID-10 e CIAP2 (injetado por shared.js:
   enhanceCodeSearchFields, um catálogo por fonte em CODE_SEARCH_SOURCES). Sem `flex-grow` aqui:
   `.field` é flex-column, então crescer no eixo principal (`flex:1`) faz o wrap esticar na
   VERTICAL até a altura do `.field` (que o grid do `.vitals-row` estica pro tamanho do vizinho
   mais alto, ex.: CID-10 com a lista de sugestão de IA aberta) — a seta, posicionada em
   `top: 50%` do wrap, ia flutuar no meio desse vazio em vez de ficar dentro do input. Onde a
   busca fica ao lado de um botão (f-cid em medico.html), `.field-input-row` reaplica o
   `flex: 1` — ali o eixo principal é horizontal, e crescer é o que reserva o espaço certo. */
.code-combo { position: relative; flex: 0 1 auto; display: block; min-width: 0; }
.field-input-row { display: flex; gap: 6px; }
.field-input-row .code-combo, .field-input-row select { flex: 1; }
.code-search-toggle {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; min-height: 0; margin: 0; padding: 0;
  border: none; border-radius: 6px; box-shadow: none;
  background: none; color: var(--ink-faint); cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease, transform 0.12s ease;
}
.code-search-toggle:hover { color: var(--ink-soft); background: var(--surface-sunken); }
.code-search-toggle:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--accent-soft); }
.code-search-toggle svg { width: 15px; height: 15px; }
.code-search-toggle.open svg { transform: rotate(180deg); }
.code-search-toggle:disabled { opacity: 0.6; cursor: not-allowed; }
.code-search-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
  max-height: 260px; overflow: auto; margin: 0; padding: 4px; list-style: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow);
}
.code-search-list li {
  padding: 8px 10px; border-radius: 6px; font-size: 12.5px; line-height: 1.4;
  color: var(--ink); cursor: pointer; display: flex; gap: 6px; align-items: baseline;
}
.code-search-list li strong { flex: none; color: var(--accent-soft-ink); }
.code-search-list li.active, .code-search-list li:hover { background: var(--accent-soft); }
.code-search-list li[aria-disabled="true"] { color: var(--ink-faint); cursor: default; }
.code-search-list li[aria-disabled="true"]:hover { background: none; }

/* Piso pra <textarea> solta. Vários lugares estilizavam `input, select` e esqueciam textarea
   (era o caso de medico.html com 5 delas, pa-virtual-enfermagem com 2, e da nota de cuidado
   coordenado no Home Care): sem regra alguma, o campo cai na borda padrão do navegador —
   escura, grossa e sem relação com o resto do formulário. Seletor de elemento puro (0-0-1),
   então qualquer regra local com classe continua vencendo; isto é rede de segurança, não
   imposição. */
textarea {
  padding: 9px 12px; font-size: 13px; line-height: 1.5; color: var(--ink);
  border-radius: 8px; border: 1.5px solid var(--border); background: var(--surface);
  resize: vertical; min-height: 62px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
textarea::placeholder { color: var(--ink-faint); }
textarea:hover { border-color: var(--ink-faint); }
textarea:focus, textarea:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
textarea:disabled { opacity: 0.6; background: var(--surface-sunken); cursor: not-allowed; }

.doctor-actions { display: flex; gap: 8px; }
.doctor-actions button { flex: 1; }

.ticket-hero {
  position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: center;
  gap: 4px; padding: 24px 20px 18px; border-radius: 14px; margin: 2px 0 4px;
  background: linear-gradient(180deg, var(--surface-sunken) 0%, var(--surface) 60%);
  border: 1px solid var(--border);
}
.ticket-hero::before, .ticket-hero::after {
  content: ""; position: absolute; top: 50%; width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--border); transform: translateY(-50%);
}
.ticket-hero::before { left: -10px; }
.ticket-hero::after { right: -10px; }
.ticket-hero .eyebrow {
  font-size: 10.5px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--signature); background: var(--signature-soft); padding: 3px 10px; border-radius: 20px; margin-bottom: 4px;
}
.ticket-hero .big { font-family: var(--font-mono); font-size: 46px; font-weight: 700; color: var(--accent); line-height: 1; letter-spacing: -0.01em; }
.ticket-hero .label { font-size: 11px; color: var(--ink-faint); text-align: center; max-width: 26ch; }
.ticket-hero .ahead { font-size: 13px; font-weight: 550; color: var(--ink-soft); margin-top: 2px; }

.take-btn {
  border: none; background: var(--queue); color: var(--queue-ink); font-weight: 650; font-size: 14px;
  padding: 13px 16px; border-radius: 10px; width: 100%; min-height: 44px;
  transition: filter 0.12s ease, transform 0.08s ease;
}
.take-btn:hover { filter: brightness(1.06); }
.take-btn:active { transform: translateY(1px); }
.take-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.queue-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; max-height: 360px; overflow-y: auto; }
.queue-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px; border-radius: 8px; background: var(--surface-sunken); font-size: 13px;
}
.queue-list .num { font-family: var(--font-mono); font-weight: 700; color: var(--queue); }
.queue-list .wait { font-size: 11px; color: var(--ink-faint); }

.current-box { background: var(--accent-soft); border-radius: 10px; padding: 16px; text-align: center; display: flex; flex-direction: column; gap: 4px; }
.current-box .num { font-family: var(--font-mono); font-size: 30px; font-weight: 700; color: var(--accent-soft-ink); }
/* accent-soft-ink, não ink-faint: dentro da .current-box o fundo é --accent-soft, e ink-faint
   ali dá 4.42:1 (reprova AA). O par -soft/-soft-ink existe exatamente pra isso. */
.current-box .none { font-size: 13px; color: var(--accent-soft-ink); padding: 14px 0; }

.call-box { display: flex; flex-direction: column; gap: 10px; padding-top: 4px; }
/* `width: 100%` + `min-width: 0` + `max-width: 100%` não são redundância: `.call-videos` é item
   flex dentro de `.call-box` (coluna) e tem `aspect-ratio` com `min-height`. Item flex nasce com
   `min-width: auto`, e o WebKit resolve a largura A PARTIR da altura quando existe aspect-ratio —
   num iPhone de 320px o bloco de vídeo calculava 498px dentro de um pai de 258px, a sala ganhava
   rolagem horizontal e o vídeo remoto vazava pela direita. Chromium e Firefox limitam ao pai
   sozinhos, então o defeito só aparecia no navegador que o beneficiário usa de verdade (Safari
   no iPhone, que é por onde o link da sala chega pelo WhatsApp). Achado em 2026-08-21 pela
   matriz de navegadores, com guarda em tests/browser-matrix/chat-sala-layout.spec.ts. */
.call-videos {
  position: relative; background: var(--ink); border-radius: 10px; overflow: hidden;
  aspect-ratio: 16 / 9; min-height: 220px;
  width: 100%; max-width: 100%; min-width: 0;
}
.call-video { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--ink); }
.call-video.remote { position: absolute; inset: 0; }
.call-video.local {
  position: absolute; width: 26%; height: auto; bottom: 10px; right: 10px; border-radius: 6px;
  border: 2px solid var(--surface); aspect-ratio: 4 / 3; box-shadow: var(--shadow); z-index: 1;
}
.call-status { font-size: 12.5px; color: var(--ink-faint); text-align: center; }

.call-controls {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 2;
  display: flex; align-items: center; gap: 8px; padding: 7px; border-radius: 999px;
  background: rgba(255,255,255,0.94); box-shadow: var(--shadow);
}
/* 44px: são os controles que o paciente usa sob estresse (mudo, câmera, desligar), muitas
   vezes idoso e no celular. Errar o "desligar" no meio da consulta é falha de tarefa. */
.call-ctl-btn {
  width: 44px; height: 44px; border-radius: 50%; border: none; flex: none; position: relative;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-sunken); color: var(--ink); transition: background 0.12s ease, color 0.12s ease;
}
.call-ctl-btn svg { width: 19px; height: 19px; }
.call-ctl-btn:hover { filter: brightness(0.96); }
.call-ctl-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.call-ctl-btn.off { background: var(--danger-soft); color: var(--danger); }
.call-ctl-btn.off::after {
  content: ""; position: absolute; width: 140%; height: 2px; background: currentColor; border-radius: 2px;
  transform: rotate(-45deg);
}
.call-ctl-btn.hangup { width: 50px; height: 50px; background: var(--danger); color: #fff; }
.call-ctl-btn.hangup svg { width: 21px; height: 21px; }
.call-ctl-btn.hangup:hover { filter: brightness(1.08); }
.call-ctl-btn.rec { background: var(--danger); color: #fff; animation: rec-pulse 1.4s ease-in-out infinite; }
.call-ctl-btn.pending { background: var(--queue-soft); color: var(--queue); }
.call-ctl-btn.active-share { background: var(--signature); color: #fff; }
@keyframes rec-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 50%, transparent); } 50% { box-shadow: 0 0 0 6px transparent; } }
/* "Você está sendo gravado" é estado com peso legal, não decoração: sem o pulso, o botão
   gravando fica idêntico a qualquer botão vermelho. Anel sólido substitui a animação. */
@media (prefers-reduced-motion: reduce) {
  .call-ctl-btn.rec { box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 45%, transparent); }
}

/* ---------------- modo de entrada (vídeo / só áudio) ---------------- */
.call-mode-toggle { display: flex; gap: 6px; justify-content: center; margin-bottom: 4px; }
.call-mode-btn {
  border: 1.5px solid var(--border); background: var(--surface); border-radius: 999px;
  padding: 5px 13px; font-size: 12.5px; color: var(--ink-soft); font-weight: 600;
}
.call-mode-btn.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* ---------------- convidados (acompanhante / intérprete / 2º médico) ---------------- */
.call-guests { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.call-guest-tile { width: 120px; flex: none; }
.call-guest-tile video {
  width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 8px; background: #111; display: block;
}
.call-guest-tile .who { font-size: 10.5px; color: var(--ink-faint); text-align: center; margin-top: 2px; }

/* .audio-only-placeholder foi removida: a feature de "só áudio" existe (opts.audioOnly em
   makeCallSession, usado por convidado.html), mas nenhum elemento nunca recebeu essa classe —
   o placeholder visual não foi construído. Regra morta desde então, e a única fonte de 28px do
   arquivo. Se o placeholder for feito algum dia, ele nasce com token de escala. */

.invite-link-row { display: flex; gap: 6px; margin-top: 10px; }
.invite-link-row input { flex: 1; padding: 8px 10px; border-radius: 8px; border: 1.5px solid var(--border); background: var(--surface-sunken); font-size: 12.5px; font-family: var(--font-mono); }

/* ---------------- classificação de risco pré-atendimento (protocolo Manchester) ---------------- */
.priority-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; flex: none;
}
.priority-chip.unset { background: var(--surface-sunken); color: var(--ink-faint); text-transform: none; font-weight: 600; }
.priority-select { border: 1.5px solid var(--border); border-radius: 6px; padding: 3px 6px; font-size: 11px; background: var(--surface); color: var(--ink); flex: none; }

.history-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.history-list li { display: flex; justify-content: space-between; font-size: 12.5px; padding: 6px 8px; border-bottom: 1px solid var(--border); color: var(--ink-soft); }
.history-list li:last-child { border-bottom: none; }
.history-list .num { font-family: var(--font-mono); color: var(--ink); font-weight: 600; }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* Piso de alvo de toque nas superfícies do beneficiário (.patient-shell — paciente.html e
   paciente-login.html). Idoso no celular é o caso base aqui, não a exceção, então 44px é o
   mínimo pra qualquer coisa clicável. As telas internas de equipe seguem densas de propósito:
   turno de alto volume no desktop lê melhor compacto.
   Exceção deliberada: .lgpd-link fica de fora — é link dentro de uma frase, e esticar pra 44px
   quebraria o texto corrido (WCAG 2.5.8 isenta alvos inline). */
.patient-shell button:not(.lgpd-link),
.patient-shell a.btn-ghost,
.patient-shell a.btn-primary {
  min-height: 44px;
}
/* Checkbox de consentimento: 13px nativo é alvo pequeno demais pra uma decisão de LGPD.
   O <label> em volta já amplia a área de clique; isto aumenta o desenho junto. */
.patient-shell .lgpd-check input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent); }

/* Pular para o conteúdo — WCAG 2.4.1. Invisível até receber foco por teclado. */
.skip-link {
  position: absolute; left: 8px; top: -100px; z-index: 3000;
  background: var(--accent); color: var(--accent-ink); text-decoration: none;
  padding: 10px 16px; border-radius: 8px; font-size: 13px; font-weight: 630;
  box-shadow: var(--shadow); transition: top 0.12s ease;
}
.skip-link:focus { top: 8px; }

.foot-note { text-align: center; font-size: 11px; color: var(--ink-faint); padding: 24px 0 8px; }


.lgpd-check { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; color: var(--ink-soft); cursor: pointer; }
.lgpd-check input { margin-top: 2px; flex: none; }
.lgpd-check span { flex: 1; min-width: 0; }
.lgpd-link {
  display: inline; appearance: none; background: none; border: none; padding: 0; margin: 0; font: inherit; font-weight: 700;
  color: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
  /* <button> centraliza o próprio conteúdo por padrão: ao quebrar linha no celular, o link
     ficava centrado no meio de um parágrafo alinhado à esquerda. */
  text-align: inherit;
}
.lgpd-link:hover { color: var(--accent); }
.lgpd-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------------- modal genérico ---------------- */
.modal-overlay {
  position: fixed; inset: 0; background: var(--scrim); display: flex;
  align-items: center; justify-content: center; padding: 20px; z-index: 2000;
}
.modal-card {
  background: var(--surface); border-radius: 14px; box-shadow: var(--shadow);
  max-width: 640px; width: 100%; max-height: 86vh; overflow-y: auto; padding: 22px 24px;
}
.modal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
.modal-head h2 { font-family: var(--font-display); font-weight: 600; margin: 0 0 3px; font-size: 18px; }
.modal-head .meta { font-size: 12.5px; color: var(--ink-faint); }
/* O círculo continua com 28px de desenho, mas a área de toque vai a 44px via ::after — alvo
   grande sem engordar o cabeçalho do modal (paciente idoso no celular fecha modal errando). */
.modal-close {
  position: relative; border: none; background: var(--surface-sunken);
  width: 28px; height: 28px; border-radius: 50%; font-size: 14px; flex: none;
}
.modal-close::after { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }
.modal-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.modal-body { font-size: 13px; line-height: 1.65; color: var(--ink-soft); }
.modal-body h3 { font-size: 13px; font-weight: 650; color: var(--ink); margin: 18px 0 6px; }
.modal-body h3:first-child { margin-top: 0; }
.modal-body p { margin: 0 0 10px; }
.modal-body ul { margin: 0 0 10px; padding-left: 18px; }
.modal-body li { margin-bottom: 4px; }
@media (max-width: 640px) {
  .modal-card { padding: 16px 16px; max-height: 92vh; }
}

@media (max-width: 640px) {
  .app { padding: 14px 14px 48px; }
  .topbar { padding-bottom: 14px; margin-bottom: 16px; gap: 10px; }
  .brand h1 { font-size: 15px; }
  .brand .sub { display: none; }
  .doctor-actions { flex-wrap: wrap; }
  .doctor-actions button { flex: 1 1 45%; }
  .ticket-hero .big { font-size: 34px; }
  .panel { padding: 14px 16px; }
  /* PiP sobe pro topo no celular: os controles são centralizados em bottom:12px e crescem com
     4 alvos de 44px, então em tela estreita eles alcançavam o vídeo local que ficava em
     bottom/right — o botão de desligar cobria a própria imagem do paciente (visto no Android,
     390px). Embaixo ficam só os controles, que é onde o dedo alcança; a auto-imagem não disputa
     esse espaço porque ninguém precisa tocar nela. */
  .call-video.local { width: 34%; height: auto; top: 10px; bottom: auto; right: 10px; }
}

/* ---------------- toast: retorno de ação ----------------
   Nasceu só pro alerta de telemonitoramento, então era danger-only: borda vermelha e ⚠ fixos,
   e `cursor: pointer` mesmo quando não havia clique. Agora é o canal de retorno de QUALQUER
   ação do produto, com quatro variantes. A cor vem da faixa lateral, não da borda inteira —
   um card com borda vermelha lê como erro mesmo quando diz "salvo". */
.toast-container {
  position: fixed; top: 78px; right: 16px; z-index: 1000;
  display: flex; flex-direction: column; gap: 8px; width: min(340px, calc(100vw - 32px));
  pointer-events: none;   /* o container não intercepta clique; cada toast reativa */
}
.toast-container > * { pointer-events: auto; }
@media (max-width: 640px) {
  /* No celular vem de baixo: fica no alcance do polegar e longe do topo, onde a .main-top
     sticky e o gatilho do drawer moram. */
  .toast-container {
    top: auto; bottom: 16px; left: 16px; right: 16px; width: auto;
    flex-direction: column-reverse;
  }
}
.toast {
  position: relative; overflow: hidden;
  display: flex; align-items: flex-start; gap: 10px; padding: 12px 12px 12px 16px;
  border-radius: 10px; background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow); animation: toast-in 0.18s ease-out;
}
/* Faixa de 4px na borda esquerda é padrão banido em card e alerta de conteúdo — aqui é
   deliberado e diferente: o toast É a notificação, a faixa é o próprio identificador de
   severidade num elemento efêmero de 340px, não decoração de conteúdo. */
.toast::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--ink-faint); }
.toast[role="button"] { cursor: pointer; }
.toast:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.toast.out { opacity: 0; transform: translateX(8px); transition: opacity 0.2s, transform 0.2s; }
.toast-icon { flex: none; line-height: 0; color: var(--ink-faint); }
.toast-icon svg { width: 17px; height: 17px; }
.toast-body { flex: 1; min-width: 0; }
.toast-title { font-size: 13px; font-weight: 650; color: var(--ink); }
.toast-subtitle { font-size: 11px; color: var(--ink-soft); margin-top: 2px; line-height: 1.45; }
.toast-close {
  border: none; background: transparent; color: var(--ink-faint); flex: none;
  width: 24px; height: 24px; border-radius: 6px; display: flex; align-items: center; justify-content: center;
}
.toast-close svg { width: 14px; height: 14px; }
.toast-close:hover { color: var(--ink); background: var(--surface-sunken); }
.toast-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.toast.ok::before { background: var(--ok); }
.toast.ok .toast-icon { color: var(--ok); }
.toast.err::before { background: var(--danger); }
.toast.err .toast-icon { color: var(--danger); }
.toast.warn::before { background: var(--warn); }
.toast.warn .toast-icon { color: var(--warn); }
.toast.info::before { background: var(--signature); }
.toast.info .toast-icon { color: var(--signature); }

/* ---------------- widget do assistente (chat de suporte interno) ---------------- */
.assistant-fab {
  position: fixed; bottom: 22px; right: 22px; z-index: 1200;
  width: 56px; height: 56px; border-radius: 50%; border: none;
  background: linear-gradient(155deg, var(--accent), var(--accent-soft-ink));
  /* font-size/line-height saíram: o FAB passou a renderizar SVG (ver .assistant-fab svg,
     28x28) quando o ícone de robô substituiu o caractere. Não havia mais texto pra
     dimensionar — era declaração morta, e a única fonte de 26px do arquivo. */
  color: var(--accent-ink);
  box-shadow: 0 4px 14px -2px color-mix(in srgb, var(--accent) 45%, transparent), var(--shadow);
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.assistant-fab:hover { transform: translateY(-2px) scale(1.04); box-shadow: 0 8px 20px -4px color-mix(in srgb, var(--accent) 50%, transparent), var(--shadow); }
.assistant-fab svg { width: 28px; height: 28px; }
.assistant-fab:active { transform: translateY(0) scale(0.97); }
.assistant-panel {
  position: fixed; bottom: 90px; right: 22px; z-index: 1200;
  width: min(360px, calc(100vw - 32px)); height: min(500px, calc(100vh - 150px));
  background: var(--surface); border: 1px solid var(--border); border-radius: 18px;
  box-shadow: 0 20px 48px -12px rgba(16,30,25,0.28), var(--shadow);
  display: none; flex-direction: column; overflow: hidden;
  opacity: 0; transform: translateY(10px) scale(0.98);
  transition: opacity 0.16s ease, transform 0.16s ease;
}
.assistant-panel.open { display: flex; }
.assistant-panel.open.in { opacity: 1; transform: translateY(0) scale(1); }
.assistant-header {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 14px; border-bottom: 1px solid var(--border);
  background: linear-gradient(135deg, var(--accent-soft), var(--surface));
  flex: none;
}
.assistant-header .avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: linear-gradient(155deg, var(--accent), var(--accent-soft-ink));
  display: flex; align-items: center; justify-content: center; color: var(--accent-ink);
  box-shadow: 0 2px 6px -1px color-mix(in srgb, var(--accent) 40%, transparent);
}
.assistant-header .avatar svg { width: 19px; height: 19px; }
.assistant-header .titles { flex: 1; min-width: 0; }
.assistant-header .title { font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.25; }
.assistant-header .subtitle { font-size: 10.5px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .04em; margin-top: 1px; }
.assistant-header .actions { display: flex; align-items: center; gap: 8px; flex: none; }
.assistant-header .actions button {
  border: none; background: transparent; color: var(--ink-faint); font-size: 11px; cursor: pointer;
  padding: 3px 4px; border-radius: 6px;
}
.assistant-header .actions button:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.assistant-header .actions .close-btn { font-size: 16px; line-height: 1; padding: 2px 5px; }
.assistant-messages { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 9px; }
.assistant-empty {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 16px; color: var(--ink-faint); gap: 10px;
}
.assistant-empty .avatar {
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--accent-soft); display: flex; align-items: center; justify-content: center; color: var(--accent);
}
.assistant-empty .avatar svg { width: 26px; height: 26px; }
.assistant-empty .greeting { font-size: 13px; color: var(--ink-soft); line-height: 1.5; max-width: 240px; }
.assistant-msg {
  max-width: 84%; padding: 9px 12px; border-radius: 14px; font-size: 13px; line-height: 1.48;
  white-space: pre-wrap; box-shadow: 0 1px 1px rgba(16,30,25,0.03);
}
.assistant-msg.mine { align-self: flex-end; background: var(--accent); color: var(--accent-ink); border-bottom-right-radius: 4px; }
.assistant-msg.theirs { align-self: flex-start; background: var(--surface-sunken); color: var(--ink); border-bottom-left-radius: 4px; }
.assistant-msg.pending { opacity: 0.65; font-style: italic; }
.assistant-msg p { margin: 0; }
.assistant-msg p + p { margin-top: 8px; }
.assistant-msg .amd-h { font-weight: 700; font-size: 13px; margin: 2px 0 4px; }
.assistant-msg .amd-h:first-child { margin-top: 0; }
.assistant-msg ul, .assistant-msg ol { margin: 6px 0; padding-left: 20px; }
.assistant-msg li { margin: 3px 0; }
.assistant-msg li + li { margin-top: 3px; }
.assistant-msg li > ul, .assistant-msg li > ol { margin: 4px 0 0; }
.assistant-msg strong { font-weight: 700; }
/* Duas coisas erradas aqui antes:
   - o fundo era um véu preto fixo de 8% de opacidade. No tema claro escurece a bolha cinza e
     funciona; no escuro a bolha JÁ é escura, então o preto some e o código inline perde a
     distinção. color-mix sobre --ink inverte com o tema (ink é escuro no claro, claro no
     escuro), que é o mesmo recurso já usado nas sombras tingidas do arquivo.
   - a pilha de mono era literal (ui-monospace, SFMono-Regular, Menlo), ignorando --font-mono.
     Resultado: o código inline do Assistente saía numa mono de sistema em vez da IBM Plex Mono
     autohospedada — justo no produto que não carrega fonte de fora. */
.assistant-msg code {
  background: color-mix(in srgb, var(--ink) 8%, transparent); padding: 1px 5px; border-radius: 4px;
  font-size: 12.5px; font-family: var(--font-mono);
}
/* Na bolha de acento o véu precisa ir na direção oposta: --accent-ink é branco no tema claro
   (sobre pinheiro escuro) e verde escuro no tema escuro (sobre pinheiro claro). */
.assistant-msg.mine code { background: color-mix(in srgb, var(--accent-ink) 22%, transparent); }
.assistant-msg .amd-table-wrap { overflow-x: auto; margin: 6px 0; max-width: 100%; }
.assistant-msg table { border-collapse: collapse; font-size: 12.5px; }
.assistant-msg th, .assistant-msg td { border: 1px solid var(--border); padding: 4px 7px; text-align: left; }
.assistant-msg th { font-weight: 700; background: color-mix(in srgb, var(--ink) 5%, transparent); }
.assistant-escalate-row { padding: 0 12px 8px; flex: none; }
.assistant-escalate-row button, .assistant-footer button {
  width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--surface); color: var(--ink-soft); font-size: 12.5px; cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.assistant-escalate-row button:hover, .assistant-footer button:hover { background: var(--surface-sunken); border-color: var(--ink-faint); }
.assistant-escalate-prompt { font-size: 12.5px; color: var(--ink-soft); margin-bottom: 6px; }
.assistant-escalate-actions { display: flex; gap: 7px; }
.assistant-escalate-actions button { width: auto; flex: 1; }
.assistant-escalate-file { display: none; }
.assistant-input-row { display: flex; gap: 7px; padding: 11px 12px; border-top: 1px solid var(--border); flex: none; }
.assistant-input-row input[type="text"] {
  flex: 1; padding: 9px 12px; border-radius: 999px; border: 1.5px solid var(--border);
  background: var(--surface); color: var(--ink); font-size: 13px;
  transition: border-color 0.12s ease;
}
.assistant-input-row input[type="text"]:focus-visible { outline: none; border-color: var(--accent); }
.assistant-input-row button {
  padding: 9px 16px; border-radius: 999px; border: none; background: var(--accent); color: var(--accent-ink);
  font-size: 13px; font-weight: 600; cursor: pointer; transition: filter 0.12s ease;
}
.assistant-input-row button:hover { filter: brightness(1.06); }
/* Rodapé do painel: UMA linha, não uma pilha. Empilhados e de largura total, os dois secundários
   pesavam igual à ação principal e o painel virava uma escada de retângulos. Agora o de suporte é
   botão discreto e "Manuais" é link quieto — hierarquia visível sem cor nova. */
.assistant-footer {
  padding: 8px 12px 12px; flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.assistant-footer button {
  width: auto; flex: none; min-height: 32px; padding: 0 12px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-soft);
  font-size: 12.5px; cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease;
}
.assistant-footer button:hover { background: var(--surface-sunken); border-color: var(--ink-faint); }
/* "Manuais" é <a> porque abre página em aba nova e continua valendo se o painel fechar. Sem
   caixa: sublinhado no hover é sinal suficiente, e uma terceira caixa só somaria ruído. */
.assistant-footer a {
  flex: none; padding: 4px 2px; font-size: 12.5px; color: var(--ink-faint);
  text-decoration: none; border-radius: 4px; transition: color 0.12s ease;
}
.assistant-footer a:hover { color: var(--accent); text-decoration: underline; }
.assistant-footer a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Modo suporte: sobra só o link, que alinha com a borda direita do botão de abrir chamado. */
.assistant-footer--fim { justify-content: flex-end; }
/* Modo suporte (cliente sem IA): formulário de chamado no lugar do campo de pergunta.
   Textarea, não input: a pessoa descreve um problema, não faz uma pergunta curta pro agente.
   COLUNA, não linha: lado a lado, o campo ficava estreito (placeholder quebrando em três linhas)
   e o botão esticava na altura dele, virando uma pílula do tamanho de um cartão. O padrão certo
   já existe no produto e é o de modal: campo em cima, ação embaixo à direita (ver .modal-actions
   em cada tela de cadastro). */
.assistant-support-form { display: block; padding: 11px 12px; border-top: 1px solid var(--border); flex: none; }
.assistant-support-form textarea {
  display: block; width: 100%; box-sizing: border-box; padding: 9px 11px; border-radius: 10px;
  border: 1.5px solid var(--border); background: var(--surface); color: var(--ink);
  font-size: 13px; font-family: inherit; line-height: 1.45; resize: vertical; min-height: 58px;
  transition: border-color 0.12s ease;
}
.assistant-support-form textarea::placeholder { color: var(--ink-faint); }
.assistant-support-form textarea:focus-visible { outline: none; border-color: var(--accent); }
/* Ação alinhada à direita, no tamanho dos botões do resto do app: altura de 34px e raio de 8px,
   não a pílula do campo de chat. Largura pelo conteúdo — botão de largura total num painel de
   360px lê como banner, não como ação. */
.assistant-support-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.assistant-support-actions .assistant-support-hint { font-size: 11.5px; color: var(--ink-faint); }
.assistant-support-form button {
  flex: none; min-height: 34px; padding: 0 14px; border-radius: 8px; border: none;
  background: var(--accent); color: var(--accent-ink); font-size: 12.5px; font-weight: 630;
  letter-spacing: 0.005em; cursor: pointer;
  transition: filter 0.12s ease, transform 0.08s ease;
}
.assistant-support-form button:hover { filter: brightness(1.08); }
.assistant-support-form button:active { transform: translateY(1px); }
.assistant-support-form button[disabled] { opacity: 0.55; cursor: default; transform: none; }
@media (max-width: 640px) {
  /* Sem a barra fixa de rodapé, o FAB volta pra margem normal (antes ficava 76px acima do
     chão pra não ser encoberto por ela). */
  .assistant-panel { right: 14px; left: 14px; width: auto; bottom: 82px; height: min(72vh, 560px); }
  .assistant-fab { right: 16px; bottom: 18px; }
}
@keyframes toast-in { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: translateX(0); } }

/* ---------------- destaque de elemento apontado pelo assistente ---------------- */
.assistant-highlight {
  animation: assistant-pulse 1.1s ease-in-out 3;
  outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 8px;
}
@keyframes assistant-pulse {
  0%, 100% { outline-color: var(--accent); }
  50% { outline-color: transparent; }
}
