/* Portal do Paciente — Fase 1A.
   Mobile-first e independente do CSS da SPA administrativa: nada aqui é
   importado de `componentes.css`, para o portal não herdar regras pensadas
   para um ecrã de trabalho com rato.
   Critérios de §9.4 tratados como requisito, não como acabamento:
   funcional a partir de 320 px, alvos de toque de 44 px, foco sempre
   visível, contraste AA, zoom até 200% sem perda de conteúdo e
   `prefers-reduced-motion` respeitado. */

/* Playfair Display auto-hospedada (spec 2026-08-31, revisto na auditoria).
   NÃO vem do Google Fonts: a CSP do host do portal é `default-src 'self';
   style-src 'self'` (sem `font-src` próprio, portanto também `'self'`), e o
   `<link>` para `fonts.googleapis.com` era silenciosamente bloqueado em
   PRODUÇÃO — a tipografia da marca caía para Georgia e ninguém dava por isso,
   porque em DEV não há CSP e lá funcionava. Verificado na auditoria.

   Auto-hospedar resolve os dois lados: não exige relaxar a CSP (relaxá-la
   para servir uma fonte seria pagar em segurança o que se ganha em estética)
   e elimina o pedido a terceiros, coerente com o isolamento que esta folha
   já tem. Subconjunto `latin` apenas — 38 KB, ficheiro variável que cobre
   600 e 700; cirílico e vietnamita seriam peso morto num portal pt-BR. */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/assets/fonts/playfair-display-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

/* `input[type="text"]{display:block}` (mais abaixo) tem especificidade
   maior que a regra UA `[hidden]{display:none}` e vencia-a — o input
   `hidden` do password-manager em `acesso.js::vistaSenha` ficava visível em
   produção. `!important` garante que qualquer atributo `hidden` continua
   escondido, seja qual for a especificidade de quem vier depois — o portal
   já depende disso (`.hidden = true/false` em agenda.js/conta.js/diario.js/
   mensagens.js, e o `[hidden]{display:none}` explícito só existia para
   `.portal-pedido`/`.portal-grelha-*` mais abaixo). Nenhum uso actual de
   `hidden` depende de ficar visível, portanto esta regra não parte nada. */
[hidden] { display: none !important; }

:root {
  --navy: #091026;
  --cream: #f5f4ee;
  --gold: #8a7434;        /* escurecido face ao #bfa45f da marca: 4.6:1 sobre cream */
  /* Alias do nome usado no resto do sistema (`--gold-texto`, admin). O
     `--gold` do portal já nasceu escurecido para 4.6:1 — não precisa de um
     valor próprio, só do nome, para o anel de foco global e outros usos de
     texto/contorno poderem seguir a mesma convenção sem repetir o hex.
     Antes desta linha, `var(--gold-texto)` era uma referência a uma
     variável nunca definida aqui (achado na auditoria de 08/09/2026, ex.:
     `.portal-conta-link[aria-current="page"]`) — a declaração ficava
     inválida em silêncio. */
  --gold-texto: var(--gold);
  /* Dourado claro (mesmo valor do --gold-2 do admin, já validado a >=4.5:1
     sobre navy) — só para texto/rótulo sobre --navy; nunca usar --gold aqui
     em cima de escuro (fica sem contraste, --gold nasceu para cream). */
  --gold-claro: #d4b86a;
  --texto: #1f2430;
  --texto-suave: #4a5060;
  --erro: #a3261e;
  --borda: #d8d5cb;
  --raio: 4px;
  /* Playfair Display SÓ em títulos (DESIGN.md §6). O corpo fica em tipos de
     sistema: uma família a carregar, não duas, e `display=swap` no `<link>`
     garante que o primeiro texto legível nunca espera pela rede. A serif é o
     que liga o portal à identidade da clínica — sem ela, a superfície que o
     paciente vê é indistinguível de qualquer aplicação genérica. */
  --fonte-titulo: "Playfair Display", Georgia, "Times New Roman", serif;
}

* { box-sizing: border-box; }

/* A barra de navegação é fixa em baixo (~60px + safe-area): foco por teclado e
   `scrollIntoView` param acima dela em vez de deixarem o controle escondido por baixo. */
html { scroll-padding-bottom: calc(76px + env(safe-area-inset-bottom)); }

body {
  margin: 0;
  background: var(--cream);
  color: var(--texto);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  font-size: 16px;               /* nunca abaixo de 16px: evita zoom automático no iOS */
  line-height: 1.6;
}

/* Esconde visualmente mantendo acessível a leitores de ecrã (nunca
   `display:none`, que remove do leitor) — padrão "visually-hidden" standard.
   Usado pelo rótulo do composer de Mensagens e pela região `aria-live` das
   reacções (`portal/mensagens.js`), que precisam de ser lidos por
   tecnologia assistiva sem ocupar espaço visual (revisão final, achado 5).
   `assets/css/portal.css` é a única folha carregada por `portal/index.html`
   — não existe `.portal-oculto`/`sr-only`/`visually-hidden` em mais
   nenhuma folha para esta vista. */
.portal-oculto {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.salto-conteudo {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--navy);
  color: var(--cream);
  padding: 12px 16px;
  z-index: 10;
}
.salto-conteudo:focus { left: 0; }

#portal-app {
  max-width: 640px;
  margin: 0 auto;
  padding: 16px 16px calc(80px + env(safe-area-inset-bottom));
  min-height: 100vh;
}

.portal-cabecalho {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0 20px;
  border-bottom: 1px solid var(--borda);
  margin-bottom: 24px;
}
.portal-cabecalho img { max-height: 40px; width: auto; }
.portal-cabecalho h1 {
  font-family: var(--fonte-titulo);
  font-size: 1.3125rem;
  line-height: 1.2;
  margin: 0;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--navy);
}

/* "Minha conta" (Lote D): saiu da `.portal-nav-fixa` e passou a viver no
   cabeçalho, como um segundo alvo de toque ao lado do logo/nome. Nenhuma
   cor nova: `var(--texto-suave)`/`var(--gold)` já existem
   (`--gold` já marca o item activo em `.portal-nav-fixa a[aria-current]`,
   ver acima) — o mesmo vocabulário de "activo = dourado" aplica-se aqui. */
.portal-conta-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-left: auto;
  flex-shrink: 0;
  color: var(--texto-suave);
  text-decoration: none;
  border-radius: var(--raio);
}
.portal-conta-link[aria-current="page"] { color: var(--gold-texto); }

/* Qualquer `h1` de vista, não só o do cabeçalho: era o maior texto do ecrã e
   o único fora do sistema (system-ui 32px, entrelinha 51px). Apanhado na
   auditoria de 2026-08-31 no ecrã de Conta. */
#portal-vista h1,
.portal-conta h1 {
  font-family: var(--fonte-titulo);
  font-size: 1.5rem;
  line-height: 1.2;
  font-weight: 600;
  color: var(--navy);
  margin: 0 0 8px;
}

h2 {
  font-family: var(--fonte-titulo);
  font-size: 1.375rem;
  line-height: 1.2;
  font-weight: 600;
  color: var(--navy);
  margin: 28px 0 10px;
}

/* Filete dourado curto acima de cada secção: a assinatura editorial do
   sistema, traduzida para uma superfície de toque.

   Só em `h2` de SECÇÃO, nunca dentro de um cartão. Aplicá-lo a todos os `h2`
   punha seis filetes num ecrã de Conta (um por documento legal) — uma
   assinatura repetida seis vezes deixa de ser assinatura e vira decoração,
   que é o tell que este sistema evita. Auditoria de 2026-08-31. */
#portal-vista > h2::before,
.portal-conta > h2::before {
  content: '';
  display: block;
  width: 28px;
  height: 2px;
  background: var(--gold);
  margin-bottom: 10px;
}

#portal-vista > h2:first-child { margin-top: 8px; }

.portal-cartao h3 {
  font-family: var(--fonte-titulo);
  font-size: 1.0625rem;
  line-height: 1.25;
  font-weight: 600;
  color: var(--navy);
  margin: 0 0 6px;
}
p { margin: 0 0 16px; }

.portal-ajuda { color: var(--texto-suave); font-size: .875rem; }

label {
  display: block;
  margin-bottom: 16px;
  font-size: .875rem;
  font-weight: 600;
}

input[type="email"],
input[type="text"],
input[type="tel"],
input[type="password"],
input[type="datetime-local"],
input[type="file"] {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-top: 6px;
  padding: 10px 12px;
  font-size: 1rem;
  font-family: inherit;
  color: var(--texto);
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
/* `input[type="text"]` (0,1,1) ganhava a `.portal-oculto` (0,1,0) e devolvia
   width 100% + padding ao campo `username` escondido do login: 28 px de
   rolagem horizontal a 390 px (QA F23). Mesma especificidade, vem depois. */
input.portal-oculto {
  width: 1px;
  min-height: 0;
  margin: -1px;
  padding: 0;
  border: 0;
}

button {
  min-height: 44px;
  min-width: 44px;
  padding: 12px 20px;
  font-size: 1rem;
  font-family: inherit;
  font-weight: 600;
  color: var(--cream);
  background: var(--navy);
  border: 1px solid var(--navy);
  border-radius: var(--raio);
  cursor: pointer;
}
button.secundario { background: transparent; color: var(--navy); }
button[disabled] { opacity: .6; cursor: not-allowed; }

/* Foco sempre visível, e não só no teclado: um anel de foco removido é a
   forma mais comum de tornar um formulário inutilizável sem rato. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--gold-texto);
  outline-offset: 2px;
}

.portal-cartao {
  background: #fff;
  border: 1px solid var(--borda);
  /* 2px, não 3px: com o dourado escurecido do portal (#8a7434) uma tarja de
     3px à largura toda lia-se como barra de aviso, não como assinatura. */
  border-top: 2px solid var(--gold);
  border-radius: var(--raio);
  padding: 20px 16px;
  margin-bottom: 16px;
}

/* Estados de erro nunca dependem só da cor (§9.4): o ícone (alert-circle do Tabler,
   desenhado por máscara na cor do texto, preso ao canto) e o `role="alert"` acompanham
   sempre. Era o glifo "! " inline, que ficava sozinho numa linha antes de um <p>. */
.portal-erro {
  position: relative;
  border-left: 4px solid var(--erro);
  background: #fdf3f2;
  color: var(--erro);
  padding: 12px 16px 12px 40px;
  border-radius: var(--raio);
  font-size: .875rem;
  margin-bottom: 16px;
}
.portal-erro::before {
  content: ""; position: absolute; left: 14px; top: 12px; width: 18px; height: 18px;
  background: currentColor;
  -webkit-mask: var(--icone-alerta) center / contain no-repeat;
  mask: var(--icone-alerta) center / contain no-repeat;
}
:root {
  --icone-alerta: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0'/%3E%3Cpath d='M12 8v4'/%3E%3Cpath d='M12 16h.01'/%3E%3C/svg%3E");
}

.portal-consentimento {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 16px;
  margin-bottom: 16px;
  background: #fff;
}
.portal-consentimento h3 { font-size: 1rem; margin: 0 0 8px; }
.portal-consentimento .texto-legal {
  max-height: 240px;
  overflow-y: auto;
  font-size: .875rem;
  color: var(--texto-suave);
  margin-bottom: 12px;
}
.portal-consentimento .aceite {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-weight: 400;
}
.portal-consentimento input[type="checkbox"] {
  width: 24px;
  height: 24px;
  margin: 0;
  flex-shrink: 0;
}

.portal-construcao {
  text-align: center;
  padding: 32px 16px;
}
.portal-construcao h2 { margin-bottom: 12px; }

.portal-rodape {
  margin-top: 32px;
  padding-top: 16px;
  border-top: 1px solid var(--borda);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.portal-carregando { color: var(--texto-suave); }

/* Barra de navegação fixa em baixo (Task 3, decisão A do companion visual).
   Substitui as abas de topo de 1B: cinco itens (Início/Cuidados/Agenda/
   Agendar/Conta), sempre visível, alvo de toque de 44 px, foco visível
   herdado de `:focus-visible`, destino corrente marcado com `aria-current`
   — não só com cor. `#portal-app` já reserva `padding-bottom` para não
   ficar por baixo dela. */
.portal-nav-fixa {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: 0;
  width: 100%;
  max-width: 640px;
  display: flex;
  background: #fff;
  border-top: 1px solid var(--borda);
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 5;
}
.portal-nav-fixa a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  text-align: center;
  padding: 8px 4px;
  font-size: .6875rem;
  color: var(--texto-suave);
  text-decoration: none;
  min-height: 44px;
}
/* SVG inline em vez de emoji (ver `portal/app.js::ICONES_NAV`): herda
   `currentColor`, por isso o item activo colore o traço sozinho, sem uma
   segunda regra de cor. 22px de traço fino a par de um rótulo de 11px. */
.portal-nav-icone {
  width: 22px;
  height: 22px;
  display: block;
  color: inherit;
}
.portal-nav-fixa a[aria-current="page"] {
  color: var(--gold);
  font-weight: 700;
  border-top: 2px solid var(--gold);
}

/* Passo de login em ecrã inteiro (Task 3, decisão B do companion visual):
   um cartão por passo, centrado verticalmente. Só para os ecrãs de login
   fora do shell (CPF, clínicas, ligação) — aí `#portal-app` é o único
   conteúdo do ecrã. `calc(100vh - 112px)` reflecte o `padding` real de
   `#portal-app` (16px no topo + 80px + safe-area no fundo, ~112px no
   total): `- 32px` deixava o cartão maior que o espaço disponível dentro do
   shell, onde há também cabeçalho/saudação por cima e a barra de navegação
   fixa por baixo — achado de revisão. Dentro do shell (estado vazio e
   confirmação de `agendar.js`) usa-se `.portal-cartao` simples. */
.portal-cartao-central {
  min-height: calc(100vh - 112px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.portal-lista-clinica {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 44px;
  padding: 12px 16px;
  margin-bottom: 8px;
  background: #fff;
  color: var(--texto);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: 1rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.portal-lista-clinica:hover { border-color: var(--gold); }

.portal-trilha { display: block; color: inherit; text-decoration: none; }
.portal-trilha h3 { margin: 0 0 8px; font-size: 1.0625rem; }

.portal-etiqueta {
  display: inline-block;
  background: #f4efdf;
  color: #6b5a25;              /* 5.2:1 sobre #f4efdf */
  border-radius: var(--raio);
  padding: 2px 8px;
  font-size: .8125rem;
  font-weight: 600;
  margin: 0 0 8px;
}

.portal-progresso { color: var(--texto-suave); font-size: .875rem; margin: 8px 0 0; }

/* Declaração de leitura crítica fora do onboarding: `.portal-consentimento
   .aceite` não se aplica aqui (essa aula não vive dentro desse cartão), por
   isso `.aceite` ganha também uma regra de topo. */
.aceite {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-weight: 400;
  margin-bottom: 12px;
}
.aceite input[type="checkbox"] { width: 24px; height: 24px; margin: 0; flex-shrink: 0; }

.portal-modulo h3 { font-size: 1.0625rem; margin: 0 0 12px; }
.portal-aulas { list-style: none; margin: 0; padding: 0; }
.portal-aula-linha { border-top: 1px solid var(--borda); }
.portal-aula-linha:first-child { border-top: 0; }
.portal-aula-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  padding: 12px 0;
  background: transparent;
  color: var(--texto);
  border: 0;
  font-weight: 600;
  text-align: left;
}
.portal-aula-corpo { margin-bottom: 16px; }
.portal-aula-corpo :last-child { margin-bottom: 0; }
/* Conteúdo vindo do editor da clínica não pode rebentar o layout a 320 px. */
.portal-aula-corpo img { max-width: 100%; height: auto; }
.portal-aula-corpo table { display: block; overflow-x: auto; max-width: 100%; }

/* Abas de categoria da lista de trilhas (Task 5, Fase 1C). */
.portal-abas {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  margin-bottom: 16px;
}
.portal-aba {
  flex-shrink: 0;
  min-height: 44px;
  padding: 8px 16px;
  font-size: .875rem;
  font-weight: 600;
  color: var(--texto-suave);
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
.portal-aba[aria-selected="true"] {
  color: var(--cream);
  background: var(--navy);
  border-color: var(--navy);
}

/* Leitor da aula (Task 5, Fase 1C): `<dialog>` nativo — é o único padrão de
   modal no portal, não havia nenhum estabelecido antes desta task. */
.portal-dialogo-aula {
  width: min(560px, calc(100% - 32px));
  max-height: calc(100vh - 64px);
  margin: auto;
  padding: 20px 16px;
  color: var(--texto);
  background: #fff;
  border: 1px solid var(--borda);
  border-top: 3px solid var(--gold);
  border-radius: var(--raio);
  overflow-y: auto;
}
.portal-dialogo-aula::backdrop { background: rgba(9, 16, 38, .6); }
.portal-dialogo-cabecalho {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.portal-dialogo-cabecalho h3 { font-size: 1.0625rem; margin: 0; }

.portal-leitor-media {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin-bottom: 16px;
  background: var(--navy);
  border: 0;
  border-radius: var(--raio);
}

.portal-consulta h3 { font-size: 1.0625rem; margin: 0 0 8px; }
.portal-accoes { display: flex; flex-wrap: wrap; gap: 8px; }
.portal-pedido { margin-top: 16px; }
.portal-pedido[hidden] { display: none; }

/* Grelha de dias/horários da remarcação (Task 3) — só botões simples do
   próprio CSS do Portal, sem reaproveitar o componente do assistente de
   agendamento do SPA (`assets/js/paginas/agendamento.js`). */
.portal-grelha-dias,
.portal-grelha-horarios {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0 16px;
}
.portal-grelha-dias[hidden],
.portal-grelha-horarios[hidden] { display: none; }
.portal-dia,
.portal-horario {
  min-height: 44px;
  min-width: 44px;
  padding: 8px 14px;
  font-weight: 600;
  color: var(--navy);
  background: transparent;
  border: 1px solid var(--borda);
}
.portal-dia.selecionado,
.portal-horario.selecionado {
  color: var(--cream);
  background: var(--navy);
  border-color: var(--navy);
}

/* `agendar` saiu da barra inferior (Task 13, Decisão 8) — este é o caminho
   visível para marcar consulta, na própria vista Agenda. Mesma aparência de
   `button` (alvo de 44px, cantos), como âncora — sem handler próprio, o
   `hashchange` já resolve `#/agendar`. */
.portal-marcar-consulta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 12px 20px;
  margin-bottom: 16px;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--cream);
  background: var(--navy);
  border-radius: var(--raio);
}

.portal-solicitacoes { list-style: none; padding: 0; margin: 0; }
.portal-solicitacoes li {
  /* Tarja no topo, não acento lateral — mesma assinatura de `.portal-cartao`
     (achado da auditoria de 08/09/2026: acento à esquerda é o padrão que o
     DESIGN.md não usa em nenhum outro cartão do sistema). */
  border-top: 2px solid var(--gold);
  background: #fff;
  padding: 12px 16px;
  margin-bottom: 8px;
  border-radius: var(--raio);
  font-size: .875rem;
}

/* Vista "Documentos" (Fase 1C, Task 7): lista de publicados + envio de
   exames. `.portal-documento`/`.portal-upload` reaproveitam `.portal-cartao`
   (tarja dourada já herdada) só acrescentando o layout interno. */
[data-documentos-lista],
[data-uploads-lista] { list-style: none; padding: 0; margin: 0; }
.portal-documento,
.portal-upload {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.portal-documento h3,
.portal-upload h3 { margin: 0 0 4px; font-size: 1rem; }
.portal-upload[data-upload-estado="rejeitado"] .portal-ajuda { color: var(--erro); }
/* Linha "Consulta de … · publicado em … · 46 KB": o "·" vive no início de
   cada item e, quando o item abre linha, cai na margem cortada — nunca fica
   pendurado (QA N3). */
.portal-documento-meta { overflow: hidden; }
.portal-documento-meta-lista { display: flex; flex-wrap: wrap; margin-left: -1em; }
.portal-documento-meta-item { position: relative; min-width: 0; padding-left: 1em; }
.portal-documento-meta-sep { position: absolute; left: .35em; }
[data-progresso-upload] progress {
  width: 100%;
  height: 12px;
  margin: 12px 0;
  accent-color: var(--gold);
}
#portal-doc-arquivo { display: block; margin: 8px 0 16px; }

/* Mensagens — fio unico paciente<->clinica.
   Balao da clinica a esquerda, do paciente a direita. A cor NUNCA e o unico
   diferenciador: cada balao leva rotulo textual ("Clinica"/"Voce"), por isso
   isto continua legivel em monocromatico e para daltonicos. */
.portal-conversa {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 8px 0 16px;
}

.portal-balao {
  max-width: 85%;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: #fff;
}

.portal-balao-texto { line-height: 1.5; }

.portal-balao-clinica { align-self: flex-start; }

.portal-balao-eu {
  align-self: flex-end;
  background: #f3f1e8;
}

.portal-balao-rotulo {
  display: block;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--texto-suave);
  margin-bottom: 6px;
}

.portal-balao p { margin: 0; }

.portal-envio-mensagem {
  position: sticky;
  bottom: calc(72px + env(safe-area-inset-bottom));
  display: flex;
  gap: 8px;
  padding: 12px 0;
  background: var(--cream);
  border-top: 1px solid var(--borda);
}

.portal-envio-mensagem textarea {
  flex: 1;
  min-height: 44px;
  font-size: 1rem;              /* 1rem = 16px por omissão: evita zoom no iOS */
  padding: 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
}

.portal-envio-mensagem button {
  min-width: 44px;
  min-height: 44px;
}

/* Botão de reagir. Herdava `min-height/min-width: 44px` da regra global de
   `button` com uma moldura visível — o resultado era uma caixa vazia grande
   com um ícone perdido lá dentro, que se lia como imagem partida (visto no
   harness). O alvo de toque continua a ser 44px, mas por área invisível: o
   `::after` estende a zona clicável para além do desenho, em vez de a
   desenhar. Sem moldura em repouso; o ícone é o botão. */
.portal-reagir {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  min-width: 0;
  width: 30px;
  height: 30px;
  margin-top: 6px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 999px;
  color: var(--texto-suave);
  cursor: pointer;
}

/* Alvo de toque de 44px sem desenhar 44px (§9.4 continua cumprido). */
.portal-reagir::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.portal-reagir:hover { color: var(--navy); }

/* Estado registado: traço dourado E preenchimento do ícone (`fill` no SVG,
   ver `portal/mensagens.js`) — nunca só a cor. */
.portal-reagir[aria-pressed="true"] {
  color: var(--gold);
  background: #f3f1e8;
}

/* Hora da mensagem: metadado, nunca com o peso do texto que foi escrito. */
.portal-balao-hora {
  font-size: .75rem;
  color: var(--texto-suave);
  margin-top: 6px;
}

/* D1 (spec 2026-09-04 §2) — cor semântica de estado, confinada ao portal.
   Regra do Acento Único: fora daqui é --navy/--gold, nunca estas três.
   13 estados crus (`consentimentos_vocabulario.js::ESTADOS_CONHECIDOS`)
   mapeiam para só 3 GRUPOS (`grupoSemantico`) — por família, nunca por
   estado individual. Excepções fixas do spec: alta/realizada/concluído é
   sempre --neutro (cinzento), nunca --ok (verde é só "dinheiro entrou",
   financeiro); nada aqui é urgência médica, por isso recusado/revogado
   também é --neutro, nunca vermelho.
   Contraste sobre o cream do portal (--cor-fundo, #f5f4ee), AA texto
   pequeno = 4.5:1: --ok 5.6:1, --pendente 6.12:1, --neutro 7.31:1. */
:root {
  --ok: #3d6b4a;
  --pendente: #6b5a25;
  --neutro: #4a5060;
  --ok-tint: #f3f1e8;
  --pendente-tint: #f4efdf;
  --neutro-tint: #d8d5cb;
}

/* Selo de estado (`portal/conta.js::_selo`, `portal/agenda.js::seloConsulta`)
   — única regra: havia duas declarações da mesma classe (achado do Lote F,
   linha ~721 apagava font-size/weight/letter-spacing/color desta por vir
   depois na cascata com a mesma especificidade). A cor nunca vai sozinha:
   o ponto (`.portal-consent-selo`) e o rótulo em texto continuam a fazer o
   trabalho principal — a cor é reforço. */
.portal-consent-estado {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--texto-suave);
}
.portal-consent-selo { width: 8px; height: 8px; border-radius: 50%; background: var(--texto-suave); }

.portal-consent-estado--ok { color: var(--ok); background: var(--ok-tint); }
.portal-consent-estado--ok .portal-consent-selo { background: var(--ok); }

.portal-consent-estado--pendente { color: var(--pendente); background: var(--pendente-tint); }
.portal-consent-estado--pendente .portal-consent-selo { background: var(--pendente); }

.portal-consent-estado--neutro { color: var(--neutro); background: var(--neutro-tint); }
.portal-consent-estado--neutro .portal-consent-selo { background: var(--neutro); }

.portal-consent-resumo { margin: 12px 0; font-size: .875rem; color: var(--texto-suave); }
.portal-consent-direitos { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--borda); }
.portal-consent-paginacao { display: flex; gap: 8px; justify-content: center; margin-top: 12px; }

/* A partir de 320 px o layout tem de continuar utilizável: sem colunas,
   sem overflow horizontal, botões a ocupar a largura disponível.

   480 px e não 360 px: a 360 px ficavam de fora exactamente os telemóveis
   reais (iPhone 375-430 px), e nessa faixa o botão PRINCIPAL ficava com menos
   área de toque (202 px, `inline-block`) do que o secundário (309 px, `block`)
   — o contrário do que deve ser. Medido em DEV a 375 px, 2026-09-01. */
@media (max-width: 480px) {
  #portal-app { padding-left: 12px; padding-right: 12px; }
  button { width: 100%; }
  .portal-rodape { flex-direction: column; align-items: stretch; }
}

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


/* Cartão de consentimento. A classe existia no HTML desde a Fase 1A e a folha
   nunca teve uma regra para ela: medido na auditoria de 2026-08-31, dava
   `background: transparent; border: none; padding: 0` — os cartões eram texto
   solto. É a TERCEIRA ocorrência do mesmo padrão nesta base (depois de
   `.portal-oculto` e `.mens-nova`): marcação escrita, folha esquecida. */
.portal-consent-card {
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 16px;
  margin-bottom: 12px;
}

.portal-consent-card h2 {
  font-size: 1.0625rem;
  margin: 0 0 10px;
}

/* O estado é o que o paciente vem cá ver; o botão é secundário. Antes o botão
   navy cheio dominava e o estado era texto solto ao lado. Regra de
   `.portal-consent-estado` fundida na única definição, junto aos tokens D1
   (achado do Lote F: havia duas, esta apagava a primeira na cascata). */

.portal-consent-card button {
  min-height: 44px;
  padding: 10px 16px;
  font-size: .875rem;
  color: var(--navy);
  background: transparent;
  border: 1px solid var(--borda);
}

.portal-consent-card button:hover {
  border-color: var(--gold);
}

/* Margem à direita (não à esquerda do 2.º): ao quebrar em duas linhas os botões
   continuam alinhados à esquerda. */
.portal-consent-card button {
  margin: 0 8px 8px 0;
}

/* Diário pós-consulta (Fase 3, Bloco B, Lote E, Task 9) — escolha guiada,
   não texto livre. `fieldset`/`legend` reais dão o contexto ao leitor de
   ecrã (nenhum `role` por cima: é o comportamento nativo de um grupo de
   rádios). `.portal-escolha` é o alvo de toque de 44px de cada opção;
   `input:checked + span` marca a escolha em navy — cor nunca é o único
   diferenciador, o próprio estado `:checked` do rádio já o é. */
fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 20px;
}

legend {
  padding: 0;
  margin: 0 0 8px;
  font-size: .875rem;
  font-weight: 600;
  color: var(--navy);
}

.portal-escolha-grupo {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.portal-escolha {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 8px 14px;
  margin: 0;
  font-size: .875rem;
  font-weight: 600;
  color: var(--texto);
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  cursor: pointer;
}

.portal-escolha-dor {
  min-width: 44px;
  padding: 8px;
}

.portal-escolha input[type="radio"] {
  /* O alvo de toque é o `<label>` inteiro (44px); o rádio em si fica
     visualmente escondido mas continua no fluxo de foco/leitor de ecrã —
     nunca `display:none`, que o tiraria da árvore de acessibilidade. */
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.portal-escolha input:checked + span {
  color: var(--cream);
}

.portal-escolha:has(input:checked) {
  color: var(--cream);
  background: var(--navy);
  border-color: var(--navy);
}

.portal-escolha input:focus-visible + span {
  outline: 3px solid var(--gold-texto);
  outline-offset: 2px;
}

textarea {
  display: block;
  width: 100%;
  min-height: 88px;
  margin-top: 6px;
  padding: 10px 12px;
  font-size: 1rem;
  font-family: inherit;
  color: var(--texto);
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  resize: vertical;
}

.portal-diario-lista { list-style: none; padding: 0; margin: 0; }
.portal-diario-item {
  /* Mesmo acerto de `.portal-solicitacoes li` acima — tarja no topo. */
  border-top: 2px solid var(--gold);
  background: #fff;
  padding: 12px 16px;
  margin-bottom: 8px;
  border-radius: var(--raio);
  font-size: .875rem;
}
.portal-diario-data {
  display: block;
  color: var(--texto-suave);
  font-size: .75rem;
  margin-bottom: 4px;
}

/* Atalho do Início (Lote E, Task 9): mesma base de `.portal-cartao`, como
   âncora — `#/diario` resolve pelo `hashchange`, sem handler próprio. */
.portal-diario-atalho {
  display: block;
  text-decoration: none;
  color: var(--texto);
}
.portal-diario-atalho h3 { margin: 0 0 4px; color: var(--navy); }

/* Ícone-emoji dos estados de confirmação/erro do agendamento (Migração
   CSP, 09/09/2026) — era style="" inline em portal/agendar.js. */
.portal-agendar-emoji { font-size: 2.25rem; margin: 0 0 10px; }

/* Entrada por CPF + senha (spec 2026-09-28, mockups 1C, 2A, 3A, 4A). */
.portal-hero-clinica { background: var(--navy); color: var(--cream); margin: -16px -16px 16px; padding: 28px 18px 22px; }
.portal-hero-clinica h2 { color: var(--cream); margin: 0; }
.portal-hero-rotulo { margin: 0 0 4px; letter-spacing: .08em; text-transform: uppercase; font-size: .75rem; color: var(--gold-claro); }
.portal-passo { margin: 0 0 4px; letter-spacing: .08em; text-transform: uppercase; font-size: .75rem; font-weight: 700; color: var(--gold-texto); }
.portal-link { background: none; border: 0; color: var(--navy); text-decoration: underline; text-underline-offset: 3px; padding: 12px 0; display: block; margin: 4px auto 0; }
.portal-cpf-escolhido { display: flex; align-items: center; gap: 8px; background: var(--cream); border: 1px solid var(--borda); border-radius: var(--raio); padding: 4px 10px; }
.portal-cpf-escolhido .portal-link { margin: 0 0 0 auto; padding: 8px 0; }
.portal-campo-senha { display: flex; gap: 6px; align-items: stretch; margin-top: 6px; }
.portal-campo-senha input { margin-top: 0; flex: 1; }
.portal-mostrar-senha { background: transparent; color: var(--navy); padding: 0 12px; }
/* (0,2,0): sem isto o `button { width: 100% }` de ≤ 480px espremia o campo a 30px (QA Onda 4). */
.portal-campo-senha .portal-mostrar-senha { flex: none; width: auto; }
.portal-requisitos { list-style: none; padding: 0; margin: -6px 0 16px; font-size: .875rem; color: var(--texto-suave); }
.portal-requisitos li::before { content: "○ "; }
.portal-requisitos li[data-ok="true"] { color: var(--ok); }
.portal-requisitos li[data-ok="true"]::before { content: "✓ "; font-weight: 700; }
.portal-otp { position: relative; }
.portal-otp input { position: absolute; inset: auto 0 0 0; height: 52px; opacity: 0; }
.portal-otp-caixas { display: flex; gap: 6px; justify-content: space-between; margin-top: 6px; }
.portal-otp-caixa { width: 44px; height: 52px; display: grid; place-items: center; background: #fff; border: 1px solid var(--borda); border-radius: var(--raio); font-size: 1.375rem; font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
.portal-otp:focus-within .portal-otp-caixa { border-color: var(--gold); }
.portal-canais { border: 0; padding: 0; margin: 0 0 12px; }
.portal-canal { display: flex; align-items: center; gap: 12px; border: 1px solid var(--borda); border-radius: var(--raio); padding: 12px; margin-bottom: 10px; font-weight: 600; }
.portal-canal:has(input:checked) { border-color: var(--navy); box-shadow: inset 0 0 0 1px var(--navy); }
.portal-canal input { order: 3; margin-left: auto; width: 20px; height: 20px; }
.portal-canal-icone { width: 36px; height: 36px; border-radius: 50%; background: var(--cream); display: grid; place-items: center; color: var(--navy); font-weight: 700; }
.portal-canal-texto small { display: block; font-weight: 400; color: var(--texto-suave); }
.portal-lista-passos { padding-left: 20px; }

/* Minha conta → Segurança (Task 16, mockups 5A/5C). */
.portal-qr { display: block; margin: 8px auto 12px; background: #fff; border: 1px solid var(--borda); }
.portal-chave { font-family: ui-monospace, Menlo, monospace; letter-spacing: .06em; background: var(--cream); border: 1px dashed var(--borda); padding: 8px; text-align: center; word-break: break-all; }
.portal-codigos { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; list-style: none; padding: 10px; margin: 0 0 12px; background: var(--cream); border-radius: var(--raio); font-family: ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; }
.portal-detalhes { border: 1px solid var(--borda); border-radius: var(--raio); padding: 8px 12px; margin-bottom: 12px; }
.portal-detalhes summary { font-weight: 600; color: var(--navy); min-height: 44px; display: flex; align-items: center; }
.portal-link-cartao { display: flex; justify-content: space-between; align-items: center; color: var(--navy); font-weight: 600; text-decoration: none; min-height: 44px; }

/* Minha conta → Meus dados (spec 2026-09-28-portal-meus-dados, mockup B). */
.portal-dados-topo { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.portal-dados-topo h2 { margin: 0; }
.portal-dados-editar { flex: none; width: auto; background: none; border: 0; color: var(--navy); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; padding: 0 4px; min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; }
.portal-dados-editar:hover { background: none; text-decoration-thickness: 2px; }
.portal-dados-lista { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 12px 0 0; }
.portal-dados-lista dt { color: var(--texto-suave); }
.portal-dados-lista dd { margin: 0; overflow-wrap: anywhere; }
.portal-dados-item { display: flex; justify-content: space-between; align-items: center; gap: 12px; border-top: 1px solid var(--borda); padding: 8px 0; }
.portal-dados-item > div { flex: 1; min-width: 0; }
.portal-dados-topo + .portal-dados-item { border-top: 0; margin-top: 4px; }
.portal-dados-rotulo { margin: 0; font-size: .875rem; color: var(--texto-suave); }
.portal-dados-valor { margin: 2px 0 0; overflow-wrap: anywhere; }
.portal-dados-nota { margin: 12px 0 0; font-size: .875rem; color: var(--texto-suave); }
.portal-dados-grade { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.portal-dados-acoes { display: flex; gap: 8px; flex-wrap: wrap; }
.portal-meus-dados select, .portal-troca-contato select { display: block; width: 100%; min-height: 44px; margin-top: 6px; padding: 10px 12px; font-size: 1rem; font-family: inherit; color: var(--texto); background: #fff; border: 1px solid var(--borda); border-radius: var(--raio); }
.portal-meus-dados select:focus-visible,
a.portal-dados-editar:focus-visible { outline: 3px solid var(--gold-texto); outline-offset: 2px; }

/* Onda 1 (spec 2026-09-29): abas da Agenda. Estado lido de aria-selected,
   nunca de uma classe. width:auto vence o button{width:100%} do mobile. */
.portal-abas {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--borda);
}
.portal-abas button[role="tab"] {
  width: auto;
  flex: 0 0 auto;
  background: transparent;
  color: var(--texto-suave);
  border: 0;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  padding: 12px 16px;
}
.portal-abas button[role="tab"][aria-selected="true"] {
  color: var(--navy);
  border-bottom-color: var(--gold);
}

/* Caixa "ligue para a clínica" (C2/C3): instrução no lugar do botão. */
.portal-ligue,
.portal-pedido-aberto {
  margin: 12px 0 0;
  padding: 12px 16px;
  background: var(--cream);
  border-left: 3px solid var(--gold);
  color: var(--texto);
  font-size: .875rem;
}

/* "Agendar de novo": âncora com aparência de botão secundário (alvo 44px). */
.portal-link-botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 12px 20px;
  margin-top: 8px;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--navy);
  border: 1px solid var(--navy);
  border-radius: var(--raio);
}

.portal-ver-mais { width: 100%; margin-top: 8px; }

/* Onda 1 (spec 2026-09-29): catálogo em cartões (mockup 2A). O cartão é o
   próprio botão nativo (teclado, foco e alvo de 44px herdados de button);
   width:100% sempre, por isso o button{width:100%} do mobile não o muda.
   Tarja de 2px como .portal-cartao (ver o porquê lá). */
.portal-procedimento {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  width: 100%;
  margin-bottom: 12px;
  padding: 16px;
  background: #fff;
  color: var(--texto);
  border: 1px solid var(--borda);
  border-top: 2px solid var(--gold);
  text-align: left;
  font-weight: 400;
}
.portal-procedimento:hover { border-color: var(--gold); }
.portal-procedimento-nome { font-family: var(--fonte-titulo); font-size: 1.125rem; color: var(--navy); }
.portal-procedimento-resumo { color: var(--texto); }
.portal-procedimento-meta,
.portal-procedimento-medicos { color: var(--texto-suave); font-size: .875rem; }

/* Faixa "Agendar de novo: …" no passo do horário. */
.portal-agendar-de-novo {
  margin: 8px 0;
  padding: 12px 16px;
  background: var(--cream);
  border-left: 3px solid var(--gold);
  color: var(--texto);
  font-weight: 600;
}

/* Ficha do profissional (spec 2026-09-29, mockup A). O cartão do catálogo é
   um button e não pode conter âncora: o link da ficha vive por baixo dele. */
.portal-procedimento-bloco { margin-bottom: 12px; }
.portal-procedimento-bloco .portal-procedimento { margin-bottom: 4px; }
.portal-procedimento-fichas { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 0; }
.portal-ficha-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  color: var(--navy);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.portal-iniciais {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--navy);
  color: var(--cream);
  font-size: .75rem;
  letter-spacing: .04em;
}
.portal-medico-opcao { margin-bottom: 8px; }
.portal-medico-opcao .portal-lista-clinica { margin-bottom: 0; }
.portal-ficha-link-sec {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--navy);
  font-size: .875rem;
  font-weight: 600;
  text-underline-offset: 3px;
}
.portal-ficha-topo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;
  text-align: center;
}
.portal-ficha-foto,
.portal-ficha-iniciais {
  flex: none;
  width: 120px;
  height: 120px;
  margin-bottom: 8px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--navy);
}
.portal-ficha-iniciais {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--cream);
  font-family: var(--fonte-titulo);
  font-size: 2rem;
}
.portal-ficha-nome { margin: 0; font-family: var(--fonte-titulo); color: var(--navy); }
.portal-ficha-nome:focus:not(:focus-visible),
.portal-ficha-titulo-vazio:focus:not(:focus-visible) { outline: none; }
.portal-ficha-crm { margin: 0; color: var(--texto-suave); font-size: .875rem; }
.portal-ficha .portal-ficha-subtitulo {
  margin: 24px 0 8px;
  font-family: inherit;
  font-size: .75rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--gold);
}
.portal-ficha-lista,
.portal-ficha-atende { margin: 0; padding: 0; list-style: none; }
.portal-ficha-lista li { padding: 2px 0; }
.portal-ficha-atende li {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--borda);
}
.portal-ficha-apresentacao { margin: 16px 0 0; white-space: pre-line; }
.portal-ficha-marcar {
  width: 100%;
  margin-top: 16px;
  background: var(--navy);
  color: var(--cream);
}

/* Onda 3 — formulário da consulta em 3 passos (mockups Tela 1 A / Tela 2 A).
   `.portal-progresso` já existe com outro uso, por isso a barra é `.portal-passos`. */
.portal-passos { display: flex; gap: 6px; margin: 0 0 8px; }
.portal-passos span { flex: 1; height: 4px; border-radius: var(--raio); background: var(--borda); }
.portal-passos--1 span:nth-child(-n+1),
.portal-passos--2 span:nth-child(-n+2),
.portal-passos--3 span { background: var(--navy); }
.portal-formulario h2 { margin: 4px 0 8px; }
.portal-formulario-termo {
  max-height: 60vh;
  overflow-y: auto;
  margin-bottom: 16px;
  padding: 12px;
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
/* Telefone e tablet: o termo corre na própria página (QA F5). Rolagem dentro
   da rolagem é armadilha de toque e deixava o texto cortado a meio da frase
   logo acima do "Continuar". */
/* Desktop: caixa com rolagem interna, degradê no fundo e pista em texto até o
   fim ser visto — a cor nunca é o único sinal (QA N5). */
.portal-formulario-termo-caixa { margin-bottom: 16px; }
.portal-formulario-termo-caixa .portal-formulario-termo { margin-bottom: 0; }
.portal-formulario-termo-janela { position: relative; }
.portal-formulario-termo-janela::after {
  content: "";
  position: absolute;
  left: 1px;
  right: 1px;
  bottom: 1px;
  height: 56px;
  background: linear-gradient(to bottom, rgb(255 255 255 / 0), #fff);
  pointer-events: none;
}
.portal-formulario-termo-pista { margin: 6px 0 0; font-weight: 600; }
.portal-formulario-termo-caixa--fim .portal-formulario-termo-janela::after,
.portal-formulario-termo-caixa--fim .portal-formulario-termo-pista { display: none; }
@media (max-width: 900px) {
  .portal-formulario-termo { max-height: none; overflow-y: visible; }
  .portal-formulario-termo-janela::after,
  .portal-formulario-termo-pista { display: none; }
}
/* Erros do passo 2 (QA F2): resumo no topo, focado, e mensagem junto ao campo. */
.portal-formulario-resumo::before { content: none; }
.portal-formulario-resumo > p { margin: 0 0 4px; font-weight: 600; }
.portal-formulario-resumo > p::before { content: "! "; font-weight: 700; }
.portal-formulario-resumo ul { margin: 0; padding-left: 20px; }
.portal-formulario-ir {
  width: auto;
  min-height: 44px;
  padding: 8px 0;
  font-weight: 600;
  text-align: left;
  color: var(--erro);
  background: none;
  border: 0;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.portal-formulario-erro { margin: 4px 0 8px; }
.portal-formulario-q--erro input[type="number"],
.portal-formulario-q--erro input[type="date"],
.portal-formulario-q--erro textarea { border-color: var(--erro); }
.portal-formulario-q { margin: 0 0 20px; }
.portal-formulario-q > label { margin-bottom: 6px; font-size: 1rem; color: var(--navy); }
.portal-formulario-q legend { font-size: 1rem; }
.portal-formulario-opcao {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 44px;
  margin: 0;
  padding: 8px 0;
  font-size: 1rem;
  font-weight: 400;
}
.portal-formulario-opcao input { width: 22px; height: 22px; margin: 0; flex: none; }
.portal-formulario-numero { display: flex; align-items: center; gap: 8px; }
.portal-formulario-q input[type="number"],
.portal-formulario-q input[type="date"] {
  min-height: 44px;
  max-width: 12rem;
  padding: 10px 12px;
  font-size: 1rem;
  font-family: inherit;
  color: var(--texto);
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
.portal-formulario-chip { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 8px; }
.portal-formulario-chip .portal-link-botao { margin-top: 0; }
.portal-formulario-aviso { display: block; color: inherit; text-decoration: none; }
.portal-formulario-aviso .portal-link-botao { margin-top: 8px; }
.portal-link-botao--primario { color: var(--cream); background: var(--navy); }

/* Sucesso do formulário (QA F20): a ≤480 px os botões ocupam a largura toda —
   a mesma regra de `button { width: 100% }`, estendida às âncoras-botão. */
@media (max-width: 480px) {
  .portal-formulario .portal-accoes > .portal-link-botao { flex: 1 1 100%; }
  .portal-formulario-aviso .portal-link-botao { display: flex; }
}

/* Rádios e caixas no dourado do portal (4,6:1), nunca no azul do sistema (QA V2). */
input[type="radio"],
input[type="checkbox"] { accent-color: var(--gold); }

/* ===== Família (Onda 4, mockup Telas 1 A e 3 A) ===== */

/* Seletor de perfil: fichas no celular, menu no computador. As duas variantes existem no DOM e
   o CSS escolhe — sobrevive a girar o aparelho e a redimensionar a janela sem matchMedia. */
.perfis--computador { display: none; }
.perfis { margin: 0 0 12px; }
.perfis-rotulo { margin: 0 0 6px; font-size: .75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--texto-suave); }
.perfis-fichas { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 6px; scroll-padding-inline: 16px; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; }
/* Degradê na borda onde ainda há fichas escondidas: a fila rola, e isso fica à vista. */
.perfis-fichas--mais-direita { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent); }
.perfis-fichas--mais-esquerda { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 40px), transparent); }
.perfis-fichas--mais-esquerda.perfis-fichas--mais-direita { -webkit-mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent); }
.perfil-avatar { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 32px; border-radius: 50%;
  background: var(--navy); color: var(--gold-claro); font-size: .75rem; font-weight: 700; letter-spacing: .02em; }
.perfil-ficha { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 6px 14px 6px 6px; color: var(--navy);
  background: #fff; border: 1px solid var(--borda); border-radius: 22px; font-weight: 600; white-space: nowrap; }
/* (0,2,0): vence o `button { width: 100% }` de ≤ 480px, que esticaria cada ficha à largura da tela. */
.perfis-fichas .perfil-ficha { flex: 0 0 auto; width: auto; scroll-snap-align: start; }
.perfil-ficha--ativa { color: var(--cream); background: var(--navy); border-color: var(--navy); }
.perfil-ficha--ativa .perfil-avatar { background: var(--gold-claro); color: var(--navy); }
.perfis-erro { margin: 8px 0 0; }

.perfil-menu { position: relative; }
.perfil-menu-botao { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; width: auto; padding: 6px 14px 6px 6px;
  color: var(--navy); background: #fff; border: 1px solid var(--borda); border-radius: var(--raio); }
.perfil-menu-lista { position: absolute; left: 0; top: 100%; z-index: 20; min-width: 280px; margin: 4px 0 0; padding: 4px; list-style: none;
  background: #fff; border: 1px solid var(--borda); border-top: 2px solid var(--gold); border-radius: var(--raio); box-shadow: 0 8px 24px rgba(9, 16, 38, .12); }
.perfil-menu-item { display: flex; align-items: center; justify-content: flex-start; gap: 10px; width: 100%; min-height: 44px; padding: 6px 10px;
  color: var(--navy); background: transparent; border: 0; text-align: left; font-weight: 600; }
.perfil-menu-item:hover { background: var(--cream); }
.perfil-menu-item--ativo { color: var(--cream); background: var(--navy); }
.perfil-menu-item--ativo:hover { background: var(--navy); }
.perfil-menu-item--ativo .perfil-avatar { background: var(--gold-claro); color: var(--navy); }

/* Faixa "Agindo em nome de": texto e borda, nunca só cor. */
.agindo { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; margin: 0 0 12px; padding: 10px 14px;
  color: var(--navy); background: var(--pendente-tint); border-left: 4px solid var(--gold); border-radius: var(--raio); font-size: .9375rem; }
/* Depois de `.agindo` (mesma especificidade: a última vence) e antes do @media que a inverte. */
.agindo--computador { display: none; }
.agindo-voltar { width: auto; min-height: 44px; padding: 0 4px; color: var(--navy); background: none; border: 0; text-decoration: underline; text-underline-offset: 3px; }
@media (min-width: 900px) {
  .perfis--celular { display: none; }
  /* Tela 1 A do computador: o botão "Você está vendo" fica à direita, sob o cabeçalho. */
  .perfis--computador { display: flex; justify-content: flex-end; }
  .perfis--computador .perfil-menu-lista { left: auto; right: 0; }
  .agindo--celular { display: none; }
  .agindo--computador { display: flex; }
}
.inicio-dependente { margin: -8px 0 16px; }

.aviso-maioridade { margin: 0 0 16px; padding: 14px 16px; color: var(--texto); background: #fff; border: 1px solid var(--borda);
  border-left: 4px solid var(--gold); border-radius: var(--raio); font-size: .9375rem; }
.aviso-maioridade b { color: var(--navy); }
.aviso-encerrado h3 { margin-top: 0; }
/* Por que a pessoa voltou à entrada (ex.: deixou de acompanhar a única conta): texto e borda, nunca só cor. */
.portal-aviso-entrada { margin: 0 0 16px; padding: 12px 16px; color: var(--navy); background: #fff; border: 1px solid var(--borda);
  border-left: 4px solid var(--gold); border-radius: var(--raio); font-weight: 600; }

/* Conta → Pessoas com acesso / lado do familiar */
.pessoas-acesso, .acompanhando { margin: 24px 0; }
.pessoas-acesso > h2, .acompanhando > h2 { font-family: var(--fonte-titulo); color: var(--navy); }
.pa-aviso:empty { display: none; }
.pa-aviso { color: var(--ok); font-weight: 600; }
.quem-perfil { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.quem-perfil > div { min-width: 0; overflow-wrap: anywhere; }
.quem-perfil small { display: block; color: var(--texto-suave); font-size: .875rem; }
.quem-estado { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-bottom: 12px; }
.quem-selo { display: inline-flex; align-items: center; padding: 2px 8px; border: 1px solid var(--borda); border-radius: var(--raio);
  font-size: .6875rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.quem-selo--ativo { color: var(--ok); border-color: var(--ok); background: var(--ok-tint); }
.quem-selo--aguardando { color: var(--pendente); border-color: var(--pendente); background: var(--pendente-tint); }
.quem-selo--vencido { color: var(--neutro); border-color: var(--neutro); background: #fff; }
.pa-historico { margin-top: 16px; }
.pa-historico summary { min-height: 44px; display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--navy); cursor: pointer; list-style: none; }
.pa-historico summary::-webkit-details-marker { display: none; }
/* `display: flex` apaga o marcador nativo: sem a seta o título lia-se como órfão. */
.pa-historico summary::before { content: '›'; display: inline-block; width: 1em; text-align: center; font-size: 1.25rem; line-height: 1; transition: transform .15s ease; }
.pa-historico[open] summary::before { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .pa-historico summary::before { transition: none; } }
.pa-historico ul { margin: 4px 0 0; padding-left: 20px; color: var(--texto-suave); font-size: .875rem; }
.pa-convite { margin-top: 16px; }
.pa-convite h3 { font-family: var(--fonte-titulo); color: var(--navy); }
.pa-campo { margin-bottom: 14px; }
.pa-campo label { margin-bottom: 0; }
.pa-erro { margin: 6px 0 0; }
.pa-resumo:focus { outline: 3px solid var(--gold-texto); outline-offset: 2px; }
.pa-resumo p { margin: 0 0 4px; font-weight: 600; }
.pa-resumo ul { margin: 0; padding-left: 1.2em; list-style: disc outside; }
/* `block`, não `inline-block`: o marcador alinha pela 1.ª linha do link quando ele quebra. */
.pa-resumo a { color: var(--erro); font-weight: 600; display: block; min-height: 32px; padding: 4px 0; }
.pa-convite select { display: block; width: 100%; min-height: 44px; margin-top: 6px; padding: 10px 12px; font-size: 1rem; font-family: inherit;
  color: var(--texto); background: #fff; border: 1px solid var(--borda); border-radius: var(--raio); }
.pa-convite [aria-invalid="true"] { border-color: var(--erro); }
.pa-convite input::placeholder, .pa-convite textarea::placeholder { color: var(--texto-suave); }
.pa-poderes-cartao { background: var(--cream); }
.pa-poderes-cartao h4 { margin: 0 0 6px; color: var(--navy); }
.pa-poderes, .convite-poderes { margin: 6px 0 10px; padding-left: 20px; }
.pa-poderes li, .convite-poderes li { margin-bottom: 4px; }

/* Caixa de seleção com rótulo ligado: o alvo inteiro tem ≥ 44px (QA da Onda 3). */
.portal-opcao { display: flex; align-items: flex-start; gap: 10px; min-height: 44px; margin: 8px 0; padding: 6px 0; cursor: pointer; font-weight: 400; font-size: 1rem; }
.portal-opcao input { flex: none; width: 22px; height: 22px; margin: 2px 0 0; accent-color: var(--gold); cursor: pointer; }

button.perigo { color: #fff; background: var(--erro); border-color: var(--erro); }

/* Folha de confirmação: presa ao fundo no celular, centrada a partir de 767px. */
.portal-folha-fundo { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-end; justify-content: center; background: rgba(9, 16, 38, .6); }
.portal-folha { width: 100%; max-width: 480px; padding: 20px 16px calc(20px + env(safe-area-inset-bottom)); background: #fff;
  border-top: 2px solid var(--gold); border-radius: var(--raio) var(--raio) 0 0; }
.portal-folha h3 { margin: 0 0 8px; font-family: var(--fonte-titulo); color: var(--navy); font-size: 1.125rem; }
.portal-folha .portal-accoes { flex-direction: column; margin-top: 12px; }
.portal-folha .portal-accoes button { width: 100%; }
@media (min-width: 767px) {
  .portal-folha-fundo { align-items: center; padding: 16px; }
  .portal-folha { border-radius: var(--raio); padding-bottom: 20px; }
  .portal-folha .portal-accoes { flex-direction: row-reverse; justify-content: flex-start; }
  .portal-folha .portal-accoes button { width: auto; }
}

/* Página pública do convite */
.convite-pagina { max-width: 520px; margin: 0 auto; }
.convite-pagina h1 { font-family: var(--fonte-titulo); color: var(--navy); font-size: 1.5rem; line-height: 1.25; margin: 0 0 8px; }
/* Título focado por programa (tabindex=-1) para o leitor de tela; não é alvo interativo. */
.convite-pagina h1:focus { outline: none; }
.convite-pagina .portal-cartao > h2 { margin-top: 0; font-size: 1.125rem; }
.convite-clinica { margin: 0; font-family: var(--fonte-titulo); font-weight: 700; color: var(--navy); font-size: 1.125rem; }
.convite-rotulo { margin: 0 0 4px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; font-size: .75rem; }
.convite-pagina label { margin-bottom: 0; }
.convite-pagina input::placeholder, .convite-pagina textarea::placeholder { color: var(--texto-suave); }
.convite-pagina form .portal-erro { margin: 6px 0 0; }
.convite-pagina form button[type="submit"] { margin-top: 16px; }
.convite-aviso { padding: 10px 14px; border-left: 4px solid var(--gold); background: var(--pendente-tint); color: var(--navy); border-radius: var(--raio); }
.convite-documentos { margin: 16px 0 0; padding: 0; border: 0; }
.convite-documentos legend { font-weight: 700; color: var(--navy); margin-bottom: 8px; }
.convite-documento { padding: 12px 0; border-top: 1px solid var(--borda); }
.convite-documento h3 { font-size: 1rem; margin: 0 0 6px; color: var(--navy); }
.convite-documento-texto { max-height: 200px; overflow-y: auto; padding: 10px 12px; font-size: .875rem; color: var(--texto-suave);
  background: var(--cream); border-radius: var(--raio); white-space: pre-line; }

/* Formulário em nome de outra pessoa (M12/M21) */
.portal-formulario-rascunho { margin: 0 0 12px; padding: 10px 14px; color: var(--navy); background: var(--pendente-tint);
  border-left: 4px solid var(--gold); border-radius: var(--raio); font-size: .9375rem; }
.portal-formulario-sem-direito p { margin: 0; }

/* Modalidade e selo do estado lado a lado, sem "·" solto antes do selo (que já é um bloco). */
.portal-consulta-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
