/* Shell responsivo do Admin Web — mobile-first, sem rolagem horizontal da página. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  height: 100%;
}

body {
  margin: 0;
  min-height: 100%;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-bg);
  overflow-wrap: break-word;
}

img {
  max-width: 100%;
  height: auto;
}

/* Controle nativo (caixa de seleção, botão de opção, barra de progresso) seguia o AZUL
   padrão do navegador — a única cor da tela que não era da marca. `accent-color` aceita
   a tinta em vez do acento sólido de propósito: no escuro o preenchimento em #4223d1 fica
   a 2,3:1 do fundo e o quadrado marcado some; o navegador escolhe sozinho a cor do
   "certo" pelo brilho do preenchimento. */
:root {
  accent-color: var(--color-accent-ink);
}

/* Sem regra própria, o texto de exemplo herda o cinza do navegador — mais apagado que o
   `--color-text-muted` e sem relação com o tema. */
::placeholder {
  color: var(--color-text-muted);
  opacity: 1;
}

/* A seleção nascia com o azul do sistema por cima do roxo da marca. */
::selection {
  background: var(--brand-soft);
  color: var(--color-text);
}

/* Estado de carregamento do runtime WASM (substituído quando o app monta). */
.boot-splash {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  color: var(--color-text-muted);
}

.skip-link {
  position: absolute;
  left: var(--space-2);
  top: -100%;
  z-index: 30;
  padding: var(--space-2) var(--space-3);
  background: var(--color-surface);
  color: var(--color-text);
  border-radius: var(--radius);
}

.skip-link:focus {
  top: var(--space-2);
}

:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* ——— Links (DESIGN_SYSTEM.md) ———
   O portal não estilizava <a> nenhum: caía no padrão do navegador — azul sublinhado e
   ROXO depois de visitado. Duas cores na mesma lista, sem significado para quem lê: o
   roxo só conta que alguém já clicou ali. É o que dava a cara antiga.

   Declaração de autor vence a folha do navegador em qualquer especificidade, então
   definir `color` aqui já mata `:visited` — não existe (nem deve existir) regra de
   `:visited` no portal, porque a cor é justamente o que não pode mudar.

   O PADRÃO do <a> é o link DENTRO DE FRASE: é o único papel que nasce sublinhado,
   porque no meio de um parágrafo a cor sozinha não identifica o que é clicável
   (WCAG 1.4.1). Os outros dois papéis pedem classe — MqLink resolve isso por
   parâmetro tipado, para não depender de lembrar a classe certa. */
a {
  color: var(--color-accent-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--color-accent-ink) 40%, transparent);
  text-underline-offset: 0.18em;
  transition: color var(--motion), text-decoration-color var(--motion);
}

/* `:where()` não soma especificidade: sem ele, `a:hover` (0,1,1) venceria
   `.btn-primary` (0,1,0) e o rótulo do botão primário trocaria de cor ao passar o
   ponteiro — sobre o próprio acento, ficando ilegível. */
a:hover:where(:not(.btn, .app-nav-link, .skip-link)) {
  color: var(--color-accent-ink-hover);
  text-decoration-color: currentColor;
}

/* Nome do que a linha É, dentro de lista ou cartão. Cor de texto e peso 600: o cartão
   inteiro já é a afordância, e pintar todo título de acento faria a lista virar um
   bloco colorido. O sublinhado é a resposta ao ponteiro, não decoração permanente. */
.link-title,
.journey-name {
  color: var(--color-text);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.link-title:hover,
.journey-name:hover {
  color: var(--color-accent-ink);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 4px;
}

/* Travessia entre telas. A seta é ícone traçado, não o caractere ← digitado no meio do
   texto: em leitor de tela o caractere é lido como palavra, e no zoom ele não acompanha
   a espessura do resto. */
.link-nav {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--touch-target);
  color: var(--color-accent-ink);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
}

.link-nav:hover {
  color: var(--color-accent-ink-hover);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 4px;
}

.link-nav .link-arrow {
  width: 16px;
  height: 16px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* O Router usa FocusOnNavigate no h1 (App.razor): a cada navegação o Blazor põe
   tabindex="-1" no título e o foca, para quem usa teclado/leitor de tela cair no conteúdo
   em vez de recomeçar pelo menu. O efeito colateral é o anel de foco desenhado em volta do
   título — no "Entrar" da tela de login ele parecia um campo de texto vazio.
   O foco CONTINUA indo para o título (o leitor de tela anuncia a página); só o anel some, e
   só em título com tabindex="-1": elemento que se opera pelo teclado nunca entra aqui, e um
   título não é operável — está fora do tab order por construção. */
h1[tabindex="-1"]:focus,
h1[tabindex="-1"]:focus-visible {
  outline: none;
}

/* Cabeçalho escuro: exigência da marca para o wordmark branco. */
.app-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: var(--header-height);
  padding: 0 var(--space-4);
  padding-left: max(var(--space-4), env(safe-area-inset-left));
  padding-right: max(var(--space-4), env(safe-area-inset-right));
  background: var(--brand-dark-surface);
  color: var(--brand-on-primary);
}

.app-logo {
  display: block;
  width: auto;
  height: 28px;
  /* Em 320px o header disputa cada pixel: o logotipo cede antes de empurrar o "Sair"
     para fora da tela. */
  max-width: 32vw;
  object-fit: contain;
  object-position: left center;
}

.app-header-context {
  font-size: var(--text-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #b9b9c6;
}

.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  cursor: pointer;
}

.nav-toggle-bar {
  display: block;
  width: 22px;
  height: 2px;
  margin: 0 auto;
  background: var(--brand-on-primary);
  border-radius: 1px;
}

.app-layout {
  position: relative;
  display: flex;
  max-width: 100%;
}

/* Navegação: drawer no mobile, coluna fixa em telas largas. */
.app-nav {
  position: fixed;
  inset: var(--header-height) auto 0 0;
  z-index: 15;
  width: min(var(--nav-width), 85vw);
  padding: var(--space-4) var(--space-3);
  background: var(--color-sunken);
  border-right: 1px solid var(--color-border);
  transform: translateX(-100%);
  transition: transform 160ms ease-out;
  overflow-y: auto;
}

.app-nav[data-open="true"] {
  transform: translateX(0);
}

.nav-overlay {
  position: fixed;
  inset: var(--header-height) 0 0 0;
  z-index: 10;
  background: rgb(9 9 11 / 45%);
}

/* Retrator no topo do painel: só existe onde a navegação é coluna fixa (desktop). */
.app-nav-collapse {
  display: none;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--touch-target);
  margin-bottom: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--motion), color var(--motion);
}

.app-nav-collapse:hover {
  background: var(--color-sunken);
  color: var(--color-text);
}

.app-nav-collapse svg {
  width: 16px;
  height: 16px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.app-nav-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-1);
}

.app-nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  color: var(--color-text-muted);
  text-decoration: none;
  transition: background var(--motion), color var(--motion);
}

.app-nav-link .nav-icon {
  width: 18px;
  height: 18px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.app-nav-link[aria-current="page"] {
  background: var(--brand-soft);
  color: var(--color-accent-ink);
  font-weight: var(--weight-semibold);
  box-shadow: inset 3px 0 var(--color-accent-ink);
}

.app-nav-link:hover:not([aria-current="page"]):not(.app-nav-link-disabled) {
  background: var(--brand-soft);
  color: var(--color-accent-ink);
}

.app-nav-link-disabled {
  color: var(--color-text-muted);
  pointer-events: none;
}

.app-main {
  flex: 1;
  width: 100%;
  /* Item de flex nasce com `min-width: auto` e se recusa a encolher abaixo do conteúdo:
     bastava um elemento largo lá dentro para o CONTEÚDO empurrar o shell e a página inteira
     ganhar rolagem horizontal. O transbordo fica contido no componente, nunca no documento. */
  min-width: 0;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) var(--space-6);
}

/* A página do flow designer respeita o MESMO teto das demais (01/09): a exceção de largura
   fazia a tela da jornada destoar de todo o portal. Quem precisa de área de diagrama abre o
   designer em tela cheia (`.flow-studio-fullscreen`), que aí sim sai do fluxo da página. */

h1 {
  margin: 0 0 var(--space-3);
  font-size: var(--text-2xl);
  line-height: 1.2;
}

.lead {
  margin: 0 0 var(--space-5);
  max-width: 65ch;
  color: var(--color-text-muted);
}

.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

.card {
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  transition: border-color var(--motion);
}

a.card:hover,
.card:has(a):hover {
  border-color: var(--color-border-strong);
}

.card h2 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
}

.card p {
  margin: 0;
  color: var(--color-text-muted);
}

/* Erro fatal do Blazor: manter discreto e sem stack trace na UI. */
#blazor-error-ui {
  display: none;
}

/* ——— Componentes do portal (mínimos, sobre os tokens) ——— */

.app-header-tenant {
  margin-left: auto;
  max-width: 40vw;
  min-width: 0;
  flex-shrink: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-sm);
  color: #d9d9e2;
}

/* O cabeçalho é a superfície de contraste FIXO do portal — escura nos dois temas, por
   exigência da marca —, então o que vive dentro dele não pode seguir a tinta do tema.
   O seletor precisa do `.app-header` na frente: `.btn-ghost` vem depois na folha e, com a
   mesma especificidade, vencia — no tema claro isso levava o "Sair" para o cinza escuro do
   texto esmaecido, 2,97:1 sobre o preto do cabeçalho. */
.app-header .app-header-exit {
  color: #b9b9c6;
  flex-shrink: 0;
}

.app-header .app-header-exit:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
  color: var(--brand-on-primary);
}

/* 320–400px: sem o rótulo decorativo "HR", gaps menores e alvos de 44px (mínimo tocável)
   o header fecha a conta sem esconder nenhuma ação. */
@media (max-width: 480px) {
  .app-header {
    gap: var(--space-2);
  }

  .app-header-context {
    display: none;
  }

  .nav-toggle,
  .theme-toggle {
    min-width: 44px;
    min-height: 44px;
  }
}

.auth-card {
  max-width: 26rem;
  margin: 10vh auto 0;
  padding: var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.panel {
  margin: 0 0 var(--space-5);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.panel h2 {
  margin: 0 0 var(--space-3);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

.panel-success {
  border-color: var(--ok-ink);
}

/* Grade de três faixas — rótulo · controle · apoio. A causa dos desalinhamentos era o
   campo ser uma pilha de altura livre: um com dica ficava mais alto que o vizinho sem
   dica, e a linha inteira desencontrava. Com as faixas, cada uma alinha com a mesma faixa
   do campo ao lado.
   `minmax(var(--touch-target), auto)` porque textarea cresce — faixa fixa a esmagaria. */
.form-field {
  display: grid;
  grid-template-rows: auto minmax(var(--touch-target), auto) auto;
  align-content: start;
  gap: var(--space-1);
  margin-bottom: var(--space-4);
  min-width: 0;
}

.form-field > label {
  align-self: end;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text-muted);
}

/* Campo com MAIS de um controle — grupo de caixas de seleção, lista de opções. As três
   faixas deixam de valer: não existe um controle único com que alinhar, e sem esta saída
   o segundo controle cai na faixa de apoio e o terceiro numa faixa inventada. Era essa a
   origem silenciosa de metade dos desalinhamentos do portal. */
.form-field-group {
  grid-template-rows: none;
  grid-auto-rows: min-content;
}

input[type="text"],
input[type="password"],
input[type="email"],
input[type="datetime-local"],
input[type="date"],
input[type="url"],
textarea,
select {
  width: 100%;
  /* `select` tem largura MÍNIMA igual à da opção mais longa, e `width: 100%` não vence isso:
     uma opção comprida empurra a coluna, depois o painel, depois a página inteira. Com
     `min-width: 0` ele encolhe com o container e o valor fechado trunca — que é o
     comportamento certo, e o único que sobrevive a 320px. */
  min-width: 0;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  font: inherit;
  color: var(--color-text);
  background: var(--color-raised);
  border: 1.5px solid var(--color-border-strong);
  border-radius: var(--radius);
  transition: border-color var(--motion), box-shadow var(--motion);
}

input[type="text"]:focus,
input[type="password"]:focus,
input[type="email"]:focus,
input[type="datetime-local"]:focus,
input[type="date"]:focus,
input[type="url"]:focus,
input[type="number"]:focus,
textarea:focus,
select:focus {
  /* Transparente, não `none`: o glow abaixo é quem mostra o foco no uso normal, mas
     `box-shadow` é DESCARTADO no modo de alto contraste do Windows (forced-colors) e o
     campo ficaria sem indicação nenhuma. Contorno transparente é invisível aqui e ganha
     cor do sistema lá — o desenho aprovado não muda e o foco nunca some. */
  outline: 2px solid transparent;
  outline-offset: 0;
  border-color: var(--color-accent-ink);
  box-shadow: 0 0 0 4px var(--brand-glow);
}

textarea {
  min-height: 8rem;
  resize: vertical;
}

.inline-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  /* Empilhado (celular) a base basta. Em linha, quem alinha de verdade é a subgrid do
     bloco de 56rem — `end` sozinho alinhava a ação pela base da LINHA, que é a base da
     faixa de apoio, e o botão nascia um degrau abaixo do input. */
  align-items: end;
}

/* Na forma em linha a faixa de apoio existe mesmo vazia: sem isso, o campo com dica
   empurra o vizinho sem dica para cima e a linha desencontra. Em formulário empilhado a
   faixa some, porque ali não há nada com que alinhar. */
.inline-form .form-field-hint:empty {
  min-height: 1.05em;
}

/* Abaixo de 30rem a ação PRIMÁRIA do formulário toma a linha inteira: no polegar, alvo
   largo é mais fácil de acertar, não mais pesado. As de apoio continuam do tamanho do
   rótulo — é largura de ação primária, não licença geral para barra. */
@media (max-width: 30rem) {
  .inline-form > .btn-primary {
    justify-self: stretch;
  }
}

/* Rótulo em --text-sm e recuo lateral de --space-3: o botão estava grande porque o
   rótulo tinha o tamanho do corpo de texto e 8rem de largura mínima em toda barra de
   ações. A ALTURA continua no piso tocável de 44px — isso é acessibilidade
   (RESPONSIVE_WEB_UX.md), não estética, e não entra na conta do enxugamento. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--motion), transform var(--motion), box-shadow var(--motion), border-color var(--motion);
}

/* Botão tem a largura do RÓTULO, nunca a da coluna. Onde o pai é flex ou grid em
   COLUNA, `stretch` é o padrão — e é ele que transformava "Excluir esta organização…"
   numa barra da largura da tela. Cada dono de layout em coluna declara o contrário aqui,
   num lugar só.
   Fora desta lista: pai em LINHA (`btn-row`, `action-row`, `card-row`) estica só a
   altura, e ali `stretch` é o que queremos — e `form-field` fica de fora de propósito,
   porque campo tem UM controle: botão dentro dele é o defeito, não um caso a acomodar
   (as duas exceções, `option-field` e `variable-row`, têm grade própria). */
.collapse-body > .btn,
.stacked-form > .btn {
  align-self: start;
  justify-self: start;
}

/* Botão SOLTO nunca encosta no irmão de cima (01/09, por print de Helber). `.panel` e
   `.collapse-body` são fluxo de bloco: quem tem `gap` é o `.stacked-form` DENTRO deles, e
   um botão logo abaixo do formulário nascia grudado nele. Regra do CONTÊINER, num lugar
   só, como a de `align-self` acima — `.btn-row` já traz a própria margem, e a margem aqui
   COLAPSA com a do irmão anterior quando ele já tem uma, então onde o espaçamento já
   estava certo nada muda. */
.panel > * + .btn,
.collapse-body > * + .btn {
  margin-top: var(--space-3);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--color-primary);
  color: var(--brand-on-primary);
  box-shadow: 0 4px 14px var(--brand-glow);
}

.btn-primary:hover:not(:disabled) {
  background: var(--color-primary-hover);
  transform: translateY(-1px);
}

.btn-secondary {
  background: transparent;
  color: var(--color-accent-ink);
  border-color: color-mix(in srgb, var(--color-accent-ink) 55%, var(--color-border-strong));
}

.btn-secondary:hover:not(:disabled) {
  background: var(--brand-soft);
}

/* Fantasma agora É apagado de verdade: cor esmaecida e superfície só no hover. Enquanto
   herdava a cor do texto, tinha o mesmo peso visual de uma ação de apoio sólida — que é o
   que fazia ele parecer link solto e o que motivou o terciário. */
.btn-ghost {
  background: transparent;
  color: var(--color-text-muted);
  border-color: transparent;
}

.btn-ghost:hover:not(:disabled) {
  background: var(--color-sunken);
  color: var(--color-text);
}

/* Segundo toque do padrão de dois toques: o botão sai do contorno e vira sólido, para a
   confirmação não parecer a mesma coisa que a proposta. */
.btn-danger-armed {
  background: var(--danger);
  color: var(--brand-on-primary);
  border-color: var(--danger);
}

.btn-danger-armed:hover:not(:disabled) {
  background: color-mix(in srgb, var(--danger) 85%, black);
}

.alert {
  padding: var(--space-3);
  border-radius: var(--radius);
  margin: 0 0 var(--space-3);
}

.alert-error {
  background: color-mix(in srgb, var(--danger) 12%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--danger-ink) 55%, var(--color-border));
  color: color-mix(in srgb, var(--danger-ink) 80%, var(--color-text));
}

.muted {
  color: var(--color-text-muted);
}

.card-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-3);
}

.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
}

.card-row .muted {
  display: block;
  font-size: var(--text-sm);
}

.card-list > .card-row:not(.card) {
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.card-list > .card-row:focus-within {
  border-color: var(--color-focus-ring);
}

/* Barra de ações DENTRO de uma linha de cartão não empurra: a linha já alinha pelo
   centro, e o respiro de topo — que existe para barra ABAIXO de um bloco — virava um
   degrau de 12px entre o texto do item e os botões dele. */
.card-row > .btn-row,
.member-card > .btn-row {
  margin-top: 0;
}

.table-scroll {
  /* Contêiner de rolagem precisa ser BLOCO DE CONTENÇÃO, não só rolar: sem `position`, um
     descendente `position: absolute` (o `.sr-only` do cabeçalho de ações, por exemplo) escapa
     do scroller, ancora no viewport e volta a alargar a PÁGINA — 98px de rolagem horizontal
     em 390px, que foi exatamente o que o smoke pegou. Vale para qualquer absoluto futuro
     dentro de tabela. */
  position: relative;
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  margin-bottom: var(--space-4);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  /* Dígito de largura fixa na tabela inteira: sem isto a coluna dança a cada valor novo,
     que é o desalinhamento mais visível do portal. */
  font-variant-numeric: tabular-nums;
}

.data-table thead th {
  padding: var(--space-3);
  text-align: left;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-sunken);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}

.data-table td {
  padding: var(--space-3);
  text-align: left;
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}

/* Texto à esquerda, número à direita. A coluna precisa marcar `num` — não dá para
   adivinhar o que é número olhando o markup. */
.data-table th.num,
.data-table td.num {
  text-align: right;
}

.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.data-table tbody tr:hover,
.data-table tbody tr:focus-within {
  background: var(--color-sunken);
}

.stat-row {
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-5);
}

/* Eram #1d7a4f e #b02a2a cravados: uma segunda definição de "ok" e "perigo", quase igual
   à dos tokens e sem tema escuro. Semântica tem um dono só. */
.stat-ok strong {
  color: var(--ok-ink);
}

.stat-bad strong {
  color: var(--danger-ink);
}

.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

@media (min-width: 56rem) {
  .inline-form {
    grid-template-columns: 1fr 1fr auto;
  }

  /* A ação nunca herda a largura da faixa: com `1fr 1fr auto` e só dois filhos, o botão
     cai na SEGUNDA faixa de 1fr (não na de `auto`) e virava a barra de meia tela da
     queixa. `start` resolve nos dois casos — um campo ou dois. */
  .inline-form > .btn {
    justify-self: start;
  }

  /* Campo e ação passam a dividir as MESMAS três faixas — rótulo, controle, apoio.
     A ação vive na faixa do controle e nasce alinhada com o input por construção, não
     por margem calibrada à mão. Sem isto ela alinha pela base da faixa de apoio e fica
     um degrau abaixo, que é o desalinhamento visível em "Novo tenant" e "Renomear". */
  @supports (grid-template-rows: subgrid) {
    .inline-form {
      grid-template-rows: auto minmax(var(--touch-target), auto) auto;
      row-gap: var(--space-1);
      column-gap: var(--space-3);
    }

    .inline-form > * {
      grid-row: 1 / -1;
    }

    .inline-form > .form-field {
      display: grid;
      grid-template-rows: subgrid;
      row-gap: var(--space-1);
      margin-bottom: 0;
    }

    .inline-form > .btn {
      grid-row: 2;
    }
  }
}

/* Breakpoint por conteúdo: navegação vira coluna fixa quando há espaço. O botão de menu
   CONTINUA visível — no desktop ele retrai/expande a coluna (28/08); o estado persiste em
   localStorage e todas as páginas se reacomodam (o canvas do Studio é quem mais lucra). */
@media (min-width: 56rem) {
  .nav-overlay {
    display: none;
  }

  .app-nav {
    position: sticky;
    top: var(--header-height);
    height: calc(100vh - var(--header-height));
    transform: none;
    flex: 0 0 var(--nav-width);
  }

  .app-layout[data-nav-collapsed="true"] .app-nav {
    display: none;
  }

  .app-nav-collapse {
    display: flex;
  }

  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 75rem) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Journey Studio */

/* Campo de número tem a largura do NÚMERO. Um input de parágrafo inteiro para conter "25"
   é a mesma queixa dos botões largos: a forma promete um conteúdo que não existe. */
input[type="number"] {
  width: 100%;
  max-width: 10rem;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border-strong);
  border-radius: var(--radius);
}

.alert-info {
  background: var(--brand-soft);
  border: 1px solid color-mix(in srgb, var(--color-accent-ink) 45%, var(--color-border));
  color: color-mix(in srgb, var(--color-accent-ink) 55%, var(--color-text));
}

.alert-success {
  background: color-mix(in srgb, var(--ok) 12%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--ok-ink) 55%, var(--color-border));
  color: color-mix(in srgb, var(--ok-ink) 75%, var(--color-text));
}

.stacked-form {
  display: grid;
  gap: var(--space-3);
}

.badge {
  display: inline-block;
  padding: 0.15rem var(--space-2);
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.badge-draft {
  background: color-mix(in srgb, var(--color-border) 55%, transparent);
  color: var(--color-text-muted);
}

.badge-review {
  background: color-mix(in srgb, var(--warn) 14%, var(--color-surface));
  color: color-mix(in srgb, var(--warn-ink) 80%, var(--color-text));
}

.badge-approved {
  background: var(--brand-soft);
  color: color-mix(in srgb, var(--color-accent-ink) 65%, var(--color-text));
}

.badge-published {
  background: color-mix(in srgb, var(--ok) 14%, var(--color-surface));
  color: color-mix(in srgb, var(--ok-ink) 78%, var(--color-text));
}

.badge-step {
  background: var(--brand-soft);
  color: color-mix(in srgb, var(--color-accent-ink) 60%, var(--color-text));
}

/* Saúde operacional (/p/health, D-060): o estado vem CALCULADO da API no data-state; aqui
   só a pintura. "unknown" usa o cinza de rascunho de propósito — sem coleta nunca é verde. */
.health-badge[data-state='ok'] {
  background: color-mix(in srgb, var(--ok) 14%, var(--color-surface));
  color: color-mix(in srgb, var(--ok-ink) 78%, var(--color-text));
}

.health-badge[data-state='degraded'] {
  background: color-mix(in srgb, var(--warn) 14%, var(--color-surface));
  color: color-mix(in srgb, var(--warn-ink) 80%, var(--color-text));
}

.health-badge[data-state='down'] {
  background: color-mix(in srgb, var(--danger) 13%, var(--color-surface));
  color: var(--danger-ink);
}

.health-badge[data-state='unknown'] {
  background: color-mix(in srgb, var(--color-border) 55%, transparent);
  color: var(--color-text-muted);
}

.health-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}

/* Linha secundária dentro do cartão sem virar célula própria da grade. */
.card-row .block {
  display: block;
}

.health-trend {
  display: inline-flex;
  align-items: center;
  min-height: 20px;
}

.sparkline {
  max-width: 100%;
  height: 20px;
}

.sparkline rect {
  fill: color-mix(in srgb, var(--color-accent-ink) 70%, var(--color-text-muted));
}

.journey-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}

.journey-list .card-row {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
}

/* .journey-name é o papel "título de item": estilo junto de .link-title, lá em cima. */

.panel-issues {
  border-color: var(--danger-ink);
}

.issue-list {
  margin: 0;
  padding-left: var(--space-4);
  display: grid;
  gap: var(--space-1);
}

.review-box h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-base);
}

.statement {
  margin: 0 0 var(--space-3);
  padding: var(--space-3);
  background: var(--color-bg);
  border-left: 4px solid var(--color-accent-ink);
  border-radius: var(--radius);
  font-style: normal;
}

.check-field {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  cursor: pointer;
}

.check-field input[type="checkbox"] {
  width: 1.4rem;
  height: 1.4rem;
  margin-top: 0.1rem;
  flex-shrink: 0;
}

.panel textarea {
  min-height: 4.5rem;
}

.step-flow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--text-sm);
}

.option-list {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.option-field {
  margin-bottom: 0;
}

/* Verificação da etapa: regra em leitura, texto de reforço editável. */
.step-check {
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--color-accent-ink);
  background: var(--color-surface);
  border-radius: var(--radius);
}

.step-check .form-field {
  margin-bottom: 0;
}

.step-check p {
  margin: 0 0 var(--space-2);
}

/* O select de tipo não pode esticar o painel além da coluna. */
.step-type {
  max-width: 100%;
  min-height: var(--touch-target);
}

.step-flow-edit {
  margin-top: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.step-flow-edit > .btn {
  align-self: flex-start;
}

/* Condição numerada: a ORDEM é comportamento (a primeira que casar vence), então cada
   cartão carrega o número — o mesmo que aparece no rótulo da aresta do canvas. */
.transition-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  padding-left: var(--space-6);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-sunken);
}

.transition-order {
  position: absolute;
  top: var(--space-3);
  left: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--color-text-muted);
}

.transition-actions {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.transition-row fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.transition-row legend {
  padding: 0;
  font-size: var(--text-sm);
}

.btn-danger {
  background: var(--color-surface);
  color: var(--danger-ink);
  border-color: var(--danger-ink);
}

/* Rótulo da opção: valor e pontuação lado a lado sem forçar rolagem no celular. */
.option-field label {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}

.scoring-block {
  margin-bottom: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.scoring-block h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
}

.scoring-block label {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}

@media (min-width: 56rem) {
  .journey-list .card-row {
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
  }

  .option-list {
    grid-template-columns: 1fr 1fr;
  }
}

/* ——— Linha de lista em COLUNAS ———
   A LISTA é a grade e cada linha herda as trilhas dela (`subgrid`). Sem isso cada linha
   media a própria largura e, com `justify-content: space-between`, o item do MEIO parava
   numa vertical diferente a cada linha: o selo da campanha 1 não batia com o da campanha 3,
   e o mesmo valia para os papéis em Usuários da empresa. Agora a trilha 1 cresce
   (identidade) e as demais têm a largura do maior conteúdo DA COLUNA — selo, papéis, meta
   e ações nascem alinhados entre linhas, como numa tabela.
   As gutters da linha precisam ser as da LISTA: gap diferente do pai desloca as trilhas e
   o alinhamento se perde de novo.
   Breakpoint por conteúdo: a partir de 64rem sobram ~46rem depois da coluna de navegação,
   que é onde três faixas cabem sem espremer o nome. Abaixo disso a linha continua
   empilhando (flex + wrap), que é o layout já validado em 320/390/768. */
@media (min-width: 64rem) {
  @supports (grid-template-columns: subgrid) {
    .card-list {
      grid-template-columns: minmax(0, 1fr) auto;
    }

    /* Três faixas: identidade | atributo (selo, papéis, templates) | fim da linha. */
    .card-list--3col {
      grid-template-columns: minmax(0, 1fr) auto auto;
    }

    /* Item que não é linha tabular (sinal crítico, cartão com formulário dentro) ocupa a
       largura toda em vez de caber só na primeira trilha. */
    .card-list > * {
      grid-column: 1 / -1;
    }

    .card-list > li.card-row {
      display: grid;
      grid-template-columns: subgrid;
      align-items: center;
      /* Selo é pílula e botão tem a largura do rótulo: sem `start` a trilha estica os dois
         até a largura da coluna. */
      justify-items: start;
    }

    /* `member-card` mora DENTRO do cartão, então o cartão precisa herdar as trilhas também
       — senão a faixa do meio volta a flutuar. Vale só para o cartão que tem um. */
    .card-list > li.card:has(> .member-card) {
      display: grid;
      grid-template-columns: subgrid;
    }

    .card-list > li.card:has(> .member-card) > * {
      grid-column: 1 / -1;
    }

    .card-list > li.card > .member-card {
      display: grid;
      grid-template-columns: subgrid;
      align-items: center;
      justify-items: start;
      gap: var(--space-2) var(--space-3);
    }
  }
}

.auth-dev-fallback {
  margin-top: 1.5rem;
}

.auth-dev-fallback summary {
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.auth-dev-fallback form {
  margin-top: 0.75rem;
}

.variable-row {
  display: grid;
  grid-template-columns: 1fr 1.5fr auto;
  gap: 0.5rem;
  align-items: center;
}

/* A dica da linha é do que a CHAVE significa: ocupa a linha inteira, embaixo dos três
   controles, e não uma quarta coluna. */
.variable-row > .form-field-hint,
.variable-row > .form-field-error {
  grid-column: 1 / -1;
}

@media (max-width: 30rem) {
  .variable-row {
    grid-template-columns: 1fr;
  }
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

/* Sem largura mínima: 8rem em toda barra de ações fazia "Fechar" e "Buscar" medirem o
   mesmo que "Confirmar reatribuição". Largura de botão é a do rótulo. */
.btn-row .btn {
  width: auto;
}

.options-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.check-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
  min-height: 44px;
  cursor: pointer;
}

/* --- Relatório da campanha (Fase 8) ---
   As cores das faixas seguem a linguagem permitida de SCORING_AND_INDICATORS.md §5: são
   INTENSIDADE DE SINAL, não semáforo de risco. Por isso nenhuma faixa usa vermelho de erro
   nem verde de "conforme" — chamar isto de risco alto/baixo é proibido pelo documento.
   A cor nunca é o único indicador: o percentual e o texto da faixa acompanham sempre. */

.report-domains {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.report-domain {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-3);
  /* Item de grid nasce com min-width: auto — sem isto a tabela de itens estica o cartão e a
     PÁGINA passa a rolar na horizontal, em vez de a tabela rolar dentro do próprio componente. */
  min-width: 0;
}

.report-domain-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.report-domain-name {
  font-weight: var(--weight-semibold);
}

.report-domain-band {
  margin-top: var(--space-1);
}

.report-bar {
  margin-top: var(--space-2);
  height: 0.6rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-border) 60%, transparent);
  overflow: hidden;
}

.report-bar-fill {
  height: 100%;
  border-radius: 999px;
  animation: report-bar-grow 700ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

@keyframes report-bar-grow {
  from {
    width: 0;
  }
}

/* Badge usa a versão suave; a BARRA usa a cor sólida da faixa — estado legível de longe. */
.badge-band-limited {
  background: color-mix(in srgb, var(--band-limited) 16%, var(--color-surface));
  color: color-mix(in srgb, var(--band-limited-ink) 85%, var(--color-text));
}

.badge-band-attention {
  background: color-mix(in srgb, var(--band-attention) 15%, var(--color-surface));
  color: color-mix(in srgb, var(--band-attention-ink) 82%, var(--color-text));
}

.badge-band-relevant {
  background: color-mix(in srgb, var(--band-relevant) 15%, var(--color-surface));
  color: color-mix(in srgb, var(--band-relevant-ink) 82%, var(--color-text));
}

.badge-band-widespread {
  background: color-mix(in srgb, var(--band-widespread) 15%, var(--color-surface));
  color: color-mix(in srgb, var(--band-widespread-ink) 85%, var(--color-text));
}

.report-bar-fill.badge-band-limited {
  background: var(--band-limited);
}

.report-bar-fill.badge-band-attention {
  background: var(--band-attention);
}

.report-bar-fill.badge-band-relevant {
  background: var(--band-relevant);
}

.report-bar-fill.badge-band-widespread {
  background: var(--band-widespread);
}

.badge-suppressed {
  background: color-mix(in srgb, var(--color-border) 55%, transparent);
  color: var(--color-text-muted);
}

.report-domain details {
  margin-top: var(--space-2);
}

.report-domain summary {
  cursor: pointer;
  font-size: var(--text-sm);
}

/* Matriz de permissions: rolagem interna no celular, sem rolar a página inteira.
   Dentro do painel de Configurações (D-057) ela é uma lista de tabelas, uma por papel, com
   o papel em `h3` — não outro painel, que seria moldura dentro de moldura. O espaçamento
   mora aqui porque o `collapse-body` só distribui gap entre os filhos DIRETOS dele. */
.permission-matrix {
  display: grid;
  gap: var(--space-3);
}

.permission-matrix h3 {
  margin: var(--space-3) 0 0;
  font-size: var(--text-base);
}

.permission-matrix > h3:first-child {
  margin-top: 0;
}

.permission-matrix .data-table th[scope="row"] {
  text-align: left;
  font-weight: var(--weight-semibold);
}

.permission-cell {
  text-align: center;
  white-space: nowrap;
}

.permission-default {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* --- Impressão: o relatório precisa sair em papel/PDF sem depender de biblioteca ---
   O navegador já gera PDF; o que faltava era a folha de estilo. Some o que é navegação e
   interação, abre os <details> (senão o PDF sai sem os itens) e força fundo branco. */
.collapse-body[hidden] {
  display: none !important;
}

@media print {
  .collapse-body.print-visible[hidden] {
    display: block !important;
  }
  .app-header,
  .app-nav,
  .nav-overlay,
  .skip-link,
  .btn,
  .btn-row,
  .no-print {
    display: none !important;
  }

  .app-layout,
  .app-main {
    display: block;
    padding: 0;
    margin: 0;
  }

  body {
    /* O papel usa tinta escura mesmo quando a preferência da tela é escura.
       Os componentes continuam consumindo os mesmos tokens, sem fundos densos. */
    color-scheme: light;
    --color-bg: #fff;
    --color-surface: #fff;
    --color-raised: #fff;
    --color-sunken: #fff;
    --color-text: #000;
    --color-text-muted: #333;
    --color-accent-ink: #000;
    --color-accent-ink-hover: #000;
    --brand-soft: #fff;
    --ok-ink: #000;
    --warn-ink: #000;
    --danger-ink: #000;
    --band-limited-ink: #000;
    --band-attention-ink: #000;
    --band-relevant-ink: #000;
    --band-widespread-ink: #000;
    --shadow-1: none;
    --shadow-2: none;
    color: var(--color-text);
    background: #fff;
  }

  body .ai-tag {
    color: #000;
    background: #fff;
    border: 1px solid currentColor;
  }

  .panel,
  .report-domain {
    break-inside: avoid;
    box-shadow: none;
    border: 1px solid #d9d9e3;
  }

  /* Sem isto, o PDF sai sem os itens de cada domínio — o leitor veria só as médias. */
  details {
    display: block;
  }

  details > summary {
    display: none;
  }

  details > *:not(summary) {
    display: block !important;
  }

  .table-scroll {
    overflow: visible;
  }

  .data-table {
    width: 100%;
    table-layout: fixed;
  }

  .data-table thead th,
  .data-table tbody td {
    white-space: normal;
    overflow-wrap: anywhere;
  }

  a[href]::after {
    content: "";
  }
}

/* Botão que se comporta como link: usado quando a ação precisa de JS (download autenticado)
   mas visualmente pertence ao texto corrido. */
.btn-link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-accent-ink);
  /* Mesmo sublinhado do link dentro de frase: fino, esmaecido em repouso, cheio no
     hover. É o papel que ele ocupa — o que muda é só ser <button>, porque a ação
     precisa de JS e não de navegação. */
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--color-accent-ink) 40%, transparent);
  text-underline-offset: 0.18em;
  cursor: pointer;
  transition: color var(--motion), text-decoration-color var(--motion);
}

.btn-link:hover {
  color: var(--color-accent-ink-hover);
  text-decoration-color: currentColor;
}

/* ——— Design v2 (mockup aprovado em 03/08): KPIs, IA, sinais, login e tema ——— */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  background: transparent;
  color: var(--brand-on-primary);
  cursor: pointer;
  font-size: var(--text-lg);
  transition: background var(--motion);
}

.theme-toggle:hover {
  background: rgba(255, 255, 255, 0.12);
}

.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
}

.kpi {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-1);
  min-width: 0;
}

.kpi .kpi-label {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
}

.kpi .kpi-value {
  display: block;
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.kpi .kpi-note {
  display: block;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.kpi-ring {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.kpi-ring svg {
  width: 58px;
  height: 58px;
  flex: none;
  transform: rotate(-90deg);
}

.kpi-ring circle {
  fill: none;
  stroke-width: 7;
}

.kpi-ring .ring-track {
  stroke: var(--color-border);
}

.kpi-ring .ring-arc {
  stroke: var(--color-accent-ink);
  stroke-linecap: round;
  animation: ring-draw 900ms ease-out;
}

@keyframes ring-draw {
  from {
    stroke-dashoffset: 163.4;
  }
}

.ai-card {
  margin: 0 0 var(--space-5);
  padding: var(--space-4);
  border: 1px solid color-mix(in srgb, var(--color-primary) 28%, var(--color-border));
  background: linear-gradient(135deg, color-mix(in srgb, var(--color-primary) 7%, var(--color-surface)), var(--color-surface) 55%);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.ai-card h2 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.ai-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: var(--color-primary);
  color: var(--brand-on-primary);
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.2rem 0.65rem;
  white-space: nowrap;
}

.ai-summary {
  margin: var(--space-2) 0;
  padding: var(--space-3);
  background: color-mix(in srgb, var(--color-border) 30%, transparent);
  border-radius: var(--radius);
}

.ai-summary p {
  margin: 0 0 var(--space-1);
}

.theme-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.theme-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  border: 1px solid var(--color-border);
  background: var(--color-raised);
  padding: 0.3rem var(--space-3);
  border-radius: 999px;
  font-size: var(--text-sm);
}

.theme-chip b {
  font-variant-numeric: tabular-nums;
  color: var(--color-accent-ink);
}

/* Sinais críticos: urgência calma — borda âmbar, nunca vermelho berrante. */
.signal-card {
  margin: 0 0 var(--space-3);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--warn-ink);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
}

.signal-card.signal-calm {
  border-left-color: var(--band-limited-ink);
}

.signal-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.signal-when {
  margin-left: auto;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

.signal-card blockquote {
  margin: var(--space-1) 0 var(--space-3);
  padding: var(--space-3);
  background: color-mix(in srgb, var(--color-border) 35%, transparent);
  border-radius: var(--radius);
}

.cat-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  border-radius: 999px;
  padding: 0.16rem 0.62rem;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  white-space: nowrap;
}

.cat-danger {
  background: color-mix(in srgb, var(--danger) 13%, var(--color-surface));
  color: var(--danger-ink);
}

.cat-warn {
  background: color-mix(in srgb, var(--warn) 14%, var(--color-surface));
  color: var(--warn-ink);
}

.cat-calm {
  background: var(--brand-soft);
  color: var(--band-limited-ink);
}

/* Login em dois painéis: marca respirando no escuro, formulário limpo no claro.
   Vive dentro do app-main, então é um cartão split — não uma página inteira. */
.login-split {
  display: grid;
  grid-template-columns: 1fr;
  min-height: 32rem;
  max-width: 64rem;
  margin: 4vh auto 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-2);
  border: 1px solid var(--color-border);
}

.login-brand {
  position: relative;
  overflow: hidden;
  background: var(--brand-dark-surface);
  color: var(--brand-on-primary);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-6);
  min-height: 220px;
}

.login-brand::before {
  content: "";
  position: absolute;
  inset: -40%;
  background:
    radial-gradient(circle at 30% 70%, rgba(66, 35, 209, 0.55), transparent 55%),
    radial-gradient(circle at 75% 20%, rgba(122, 92, 255, 0.35), transparent 50%);
  animation: login-breathe 9s ease-in-out infinite alternate;
}

@keyframes login-breathe {
  from {
    transform: translate3d(-2%, 1%, 0) scale(1);
  }

  to {
    transform: translate3d(2%, -2%, 0) scale(1.06);
  }
}

.login-brand > * {
  position: relative;
}

.login-brand h2 {
  margin: 0 0 var(--space-2);
  font-size: clamp(1.4rem, 3vw, 2rem);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  line-height: 1.2;
  max-width: 22ch;
  text-wrap: balance;
}

.login-brand p {
  margin: 0;
  color: #b9b5d4;
  max-width: 44ch;
}

.login-brand .login-foot {
  color: #8f8baa;
  font-size: var(--text-xs);
}

.login-pane {
  display: grid;
  place-items: center;
  background: var(--color-bg);
  padding: var(--space-5) var(--space-4);
}

.login-pane .auth-card {
  margin: 0;
  width: min(26rem, 100%);
  box-shadow: none;
  border: 0;
  background: transparent;
}

@media (min-width: 56rem) {
  .login-split {
    grid-template-columns: 1fr 1fr;
  }
}

/* Motion é cortesia, nunca exigência. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* Área Plataforma (gestão Maquinize) */

.app-nav-heading {
  margin-top: var(--space-4);
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.role-chip {
  display: inline-block;
  padding: 0.1rem 0.55rem;
  margin: 0.1rem 0.25rem 0.1rem 0;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--color-accent-ink);
  font-size: var(--text-sm);
  white-space: nowrap;
}

.member-card {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  /* Era `baseline`: a linha de base do texto contra a de um botão de 44px deixava as
     ações penduradas acima do centro do cartão. */
  align-items: center;
  justify-content: space-between;
}

.member-card .member-id {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* O conteúdo que ABRE abaixo da linha do item (reatribuir número, templates da Meta)
   precisa de ar: sem isto o primeiro rótulo do formulário encosta na barra de ações.
   Antes o respiro vinha por acidente, da margem de topo do próprio `btn-row`. */
.member-card + * {
  margin-top: var(--space-4);
}

/* --- Contrato do template (conexões WhatsApp) ---
   O que era campo virou contrato EXIBIDO. Idioma e ordem das variáveis pertencem ao tipo
   de mensagem: em toda WABA os templates do produto têm o mesmo texto e as mesmas
   variáveis (D-042) e só o nome varia por número. Campo editável ali pedia ao operador
   uma decisão que não é dele — e a ordem trocada registrava o convite com o nome da
   empresa no lugar do nome da pessoa. */
.template-contract {
  display: grid;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--color-sunken);
  border-radius: var(--radius);
}

.template-contract p {
  margin: 0;
  font-size: var(--text-sm);
}

/* A ressalva é rodapé do contrato, não uma segunda afirmação de mesmo peso. */
.template-contract p.muted {
  font-size: var(--text-xs);
}

.template-contract-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.template-contract-icon {
  width: 16px;
  height: 16px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.template-variables {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* O selo já tem margem própria (herança de quando ficava em linha corrida); dentro de um
   flex com gap ela vira espaçamento duplo e desigual. */
.template-variables .role-chip {
  margin: 0;
}

.template-variables .role-chip strong {
  margin-right: var(--space-1);
  font-weight: var(--weight-bold);
}

.temp-password {
  display: inline-block;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-lg);
  letter-spacing: 0.06em;
  user-select: all;
  overflow-wrap: anywhere;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Biblioteca de componentes (Components/Mq*.razor)

   Daqui para baixo, TUDO tem um componente Razor como dono único. Mudar a
   aparência de um botão, de um painel colapsável ou de um grupo de menu é
   mudar aqui e no .razor correspondente — não caçar ocorrência por página.
   Regras de uso: docs/02-engineering/DESIGN_SYSTEM.md
   ═══════════════════════════════════════════════════════════════════════════ */

/* --- Botão terciário: o nível que faltava ---
   O portal usava primário e fantasma na MESMA quantidade (38 cada) e nada no
   meio, o que fazia ação de apoio parecer link solto. Forma de botão, peso
   baixo, superfície própria. */
.btn-tertiary {
  background: var(--color-sunken);
  color: var(--color-text);
  border-color: var(--color-border);
}

.btn-tertiary:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--color-text) 24%, var(--color-border));
}

/* --- Painel colapsável ---
   O cabeçalho FECHADO carrega o estado do que está dentro. Sem esse resumo,
   colapsar apenas esconde e a pessoa reabre tudo procurando. */
.collapse-panel {
  margin: 0 0 var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.collapse-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  /* Cabeçalho INTEIRO é o alvo, do chevron ao selo — não uma área do tamanho
     de um ícone. É o que faz funcionar no polegar. */
  min-height: 60px;
  padding: var(--space-3) var(--space-4);
  font: inherit;
  color: inherit;
  text-align: left;
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: background var(--motion);
}

.collapse-head:hover {
  background: var(--color-sunken);
}

.collapse-chevron {
  width: 20px;
  height: 20px;
  flex: none;
  stroke: var(--color-text-muted);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 180ms ease;
}

.collapse-panel[data-open="true"] .collapse-chevron {
  transform: rotate(90deg);
}

.collapse-panel[data-open="true"] .collapse-head {
  border-bottom: 1px solid var(--color-border);
}

.collapse-title {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.collapse-name {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
}

.collapse-summary {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

/* Recuo alinhado ao título: chevron (20px) + gap. */
.collapse-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-4) var(--space-5)
    calc(var(--space-4) + 20px + var(--space-3));
}

/* No celular o resumo some e sobra o selo — é o que resta quando tudo mais é
   cortado. O corpo perde o recuo decorativo para não espremer o conteúdo. */
@media (max-width: 30rem) {
  .collapse-summary {
    font-size: var(--text-xs);
  }

  .collapse-body {
    padding-left: var(--space-4);
  }
}

/* --- Grupo de navegação com sub-menu ---
   Agrupa DENTRO de cada ambiente; a fronteira da D-048 não é atravessada. */
.nav-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nav-group-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: left;
  color: var(--color-text-muted);
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--motion);
}

.nav-group-head:hover {
  background: var(--color-sunken);
}

.nav-group-chevron {
  width: 14px;
  height: 14px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 180ms ease;
}

.nav-group[data-open="true"] .nav-group-chevron {
  transform: rotate(90deg);
}

.nav-group-label {
  flex: 1;
  min-width: 0;
}

.nav-group-items {
  display: grid;
  gap: 2px;
  margin: 0 0 0 11px;
  padding: 0 0 0 var(--space-3);
  list-style: none;
  border-left: 1px solid var(--color-border);
}

/* --- Apoio do campo de formulário ---
   A faixa existe mesmo vazia: campo com dica ficava mais alto que o vizinho sem
   dica, e a linha inteira desencontrava. */
.form-field-hint {
  max-width: 68ch;
  font-size: var(--text-xs);
  line-height: 1.4;
  color: var(--color-text-muted);
}

.form-field-error {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--danger-ink);
}

.form-field-invalid input,
.form-field-invalid select,
.form-field-invalid textarea {
  border-color: var(--danger-ink);
}

/* --- <details> nativo alinhado ao painel colapsável ---
   O portal tinha DUAS linguagens de expansão na mesma tela: o chevron do
   MqCollapsePanel e o triângulo padrão do browser. Aqui o <details> passa a usar o
   mesmo chevron, o mesmo alvo de toque e a mesma superfície de hover.
   Segue sendo <details> nativo: funciona sem JavaScript e o teclado já o opera. */
details > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-2) var(--space-2) 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text-muted);
  cursor: pointer;
  border-radius: var(--radius);
  transition: background var(--motion), color var(--motion);
  /* Remove o triângulo do browser nos dois motores. */
  list-style: none;
}

details > summary::-webkit-details-marker {
  display: none;
}

details > summary::before {
  content: "";
  width: 16px;
  height: 16px;
  flex: 0 1 auto;
  min-width: 0;
  background: currentColor;
  transition: transform 180ms ease;
  /* Chevron desenhado em máscara: acompanha a cor do texto sem um SVG por ocorrência. */
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
}

details[open] > summary::before {
  transform: rotate(90deg);
}

details > summary:hover {
  color: var(--color-text);
}

/* O cabeçalho existe para a semântica e para a navegação por títulos; quem desenha a
   linha é o botão dentro dele. Por isso o h2 não traz estilo próprio nenhum. */
.collapse-heading {
  margin: 0;
  padding: 0;
  font: inherit;
  flex: 1;
  min-width: 0;
}

/* --- Botão de ícone ---
   O caso legítimo do fantasma: ação repetida uma vez por linha (remover ESTA opção,
   remover ESTA condição). Fantasma com TEXTO pelado era a queixa original de volta —
   parecia rótulo, não ação. Ícone num alvo quadrado de 44px tem afordância sem o peso
   de um botão cheio multiplicado por N linhas. O nome acessível vem do aria-label. */
.btn-icon {
  width: var(--touch-target);
  min-width: var(--touch-target);
  padding: 0;
  flex: none;
  align-self: end;
}

.btn-icon .btn-glyph {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* A opção é uma LINHA: rótulo e campo à esquerda, remoção na ponta. Empilhados, o
   botão caía na faixa de apoio da grade do campo e virava uma barra de largura inteira. */
.option-field,
.transition-row {
  min-width: 0;
}

.option-list > .option-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(var(--touch-target), auto) auto;
  align-items: end;
  column-gap: var(--space-2);
}

.option-list > .option-field > label {
  grid-column: 1;
}

.option-list > .option-field > input {
  grid-column: 1;
}

.option-list > .option-field > .btn-icon {
  grid-column: 2;
  grid-row: 2;
}

.option-list > .option-field > .form-field-hint,
.option-list > .option-field > .form-field-error {
  grid-column: 1 / -1;
}

/* Ação de acrescentar não estica: ela é um botão, não uma barra. */
.option-list > .btn,
.step-flow-edit > .btn,
.transition-row > .btn {
  justify-self: start;
}

/* ==========================================================================
   Flow designer do Journey Studio (D-051)
   O canvas do Blazor.Diagrams é estrutural (_content/…/style.min.css); a pele
   é toda daqui, por token. Nenhum hex fora dos tokens.
   ========================================================================== */

/* Tela desktop-only por decisão registrada (D-051): abaixo de 768px a página inteira
   dá lugar à orientação de abrir no computador — inclusive o ciclo de aprovação.
   Exceção ÚNICA à regra de responsividade; documentada em RESPONSIVE_WEB_UX.md.
   Consequência aceita: zoom de navegador a 200% num notebook 1280px cai no gate. */
.studio-mobile-gate {
  display: none;
}

@media (max-width: 47.9375rem) {
  .journey-studio {
    display: none;
  }

  .studio-mobile-gate {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-top: var(--space-5);
    padding: var(--space-6);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
  }

  .studio-mobile-gate h2 {
    font-size: var(--text-lg);
    margin: 0;
  }

  .studio-mobile-gate p {
    margin: 0;
  }
}

.flow-studio {
  margin-top: var(--space-6);
}

/* Tela cheia do DESIGNER, não da página (01/09): a jornada segue o teto de largura do
   portal e só o fluxo sai do documento quando pedido. Fica ACIMA do cabeçalho (30) e
   ABAIXO do MqDialog (40) — o editor de etapa continua abrindo por cima. */
.flow-studio-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 35;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: var(--space-4);
  background: var(--color-bg);
  outline: none;
}

/* Em tela cheia o canvas é quem estica; a barra e o rodapé de texto ficam no tamanho. */
.flow-studio-fullscreen .flow-canvas {
  flex: 1;
  height: auto;
  min-height: 0;
}

.flow-studio-fullscreen .flow-toolbar {
  flex: none;
}

/* O parágrafo de regra de versionamento não cabe no modo diagrama: ele é leitura da
   página, e ali só rouba altura do canvas. */
.flow-studio-fullscreen .flow-studio-note {
  display: none;
}

.flow-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.flow-toolbar-title {
  margin: 0;
}

.flow-toolbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* Canvas em LARGURA TOTAL (28/08): o painel lateral virou o MqDialog — cada pixel da
   página, inclusive o do menu retraído, é área de diagrama. */
.flow-canvas {
  position: relative;
  min-width: 0;
  height: min(72vh, 60rem);
  min-height: 26rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-sunken);
  overflow: hidden;
}

.flow-canvas .diagram-canvas {
  width: 100%;
  height: 100%;
  /* Pan com dedo/caneta fica por conta do diagrama; sem isto o navegador rola a página. */
  touch-action: none;
}

.flow-canvas-tools {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  display: flex;
  gap: var(--space-1);
  padding: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  box-shadow: var(--shadow-1);
}

.flow-panel-step {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.flow-panel-step > .btn {
  align-self: flex-start;
}

/* --- Campo de arquivo (MqFileField) ---
   O portal usava o `input[type=file]` cru: botão do sistema operacional, texto em inglês e
   nenhuma relação com o resto da tela. Não havia UMA regra para `input[type=file]` nem para
   `::file-selector-button` nesta folha.

   O input nativo continua sendo o controle: fica TRANSPARENTE cobrindo a zona inteira, e o
   que se vê é desenhado atrás dele. `display: none` exigiria reemitir o clique por JS e
   tiraria o campo do teclado. */
.file-field {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

.file-field-drop {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* Envolve o input absoluto; o `flex-wrap` é o que salva 320px, onde botão + nome do
     arquivo não cabem lado a lado. */
  position: relative;
  flex-wrap: wrap;
  min-height: var(--touch-target);
  padding: var(--space-3);
  background: var(--color-raised);
  border: 1.5px dashed var(--color-border);
  border-radius: var(--radius);
  transition: border-color var(--motion), background var(--motion);
}

/* Arrastar-e-soltar é ACRÉSCIMO (`.claude/rules/frontend.md`): o realce existe para quem
   arrasta, e o botão faz a mesma coisa sozinho — em celular ele é o único caminho. */
.file-field-drop.is-dragging {
  border-color: var(--color-accent-ink);
  border-style: solid;
  background: var(--brand-soft);
}

.file-field-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.file-field-input:disabled {
  cursor: not-allowed;
}

/* O seletor nativo do navegador nunca aparece: quem o desenha é `.file-field-button`. Sem
   isto o botão do sistema apareceria DENTRO da zona, embaixo do input transparente. */
.file-field-input::file-selector-button {
  display: none;
}

/* Herda a forma do terciário — ação de apoio nomeada, que é o papel de "escolher arquivo":
   não é a ação que a tela existe para realizar (essa é validar/importar). */
.file-field-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  background: var(--color-sunken);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  white-space: nowrap;
  transition: border-color var(--motion), background var(--motion);
}

.file-field-drop:hover .file-field-button {
  border-color: color-mix(in srgb, var(--color-text) 24%, var(--color-border));
}

/* O foco vive no input transparente; o anel precisa aparecer na zona, que é o que se vê.
   Contorno transparente + glow pelo mesmo motivo dos demais campos: `box-shadow` some no
   modo de alto contraste do Windows e o contorno ganha cor do sistema lá. */
.file-field-input:focus-visible + .file-field-button {
  outline: 2px solid transparent;
  outline-offset: 2px;
  border-color: var(--color-accent-ink);
  box-shadow: 0 0 0 4px var(--brand-glow);
}

.file-field-state {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
  font-size: var(--text-sm);
}

/* Nome longo trunca em vez de empurrar a zona, o painel e a página — o mesmo defeito que o
   `select` da tela de Configurações causava (124px de rolagem horizontal em 1280px). */
.file-field-name {
  overflow: hidden;
  min-width: 0;
  font-weight: var(--weight-medium);
  color: var(--color-text);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-field-size,
.file-field-empty,
.file-field-accepts {
  color: var(--color-text-muted);
}

.file-field-size {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.file-field-accepts {
  font-size: var(--text-xs);
}

/* Texto só para leitor de tela. O cabeçalho da coluna de ações da tabela de trabalhadores
   precisa existir na estrutura — `<th>` vazio deixa a tabela sem rótulo para quem navega por
   ela — mas escrever "Ações" na tela seria ruído para quem enxerga. `clip-path` em vez de
   `display: none`, que remove o elemento também do leitor. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Mapeamento de colunas da importação ---
   Uma coluna do arquivo por item: cabeçalho, exemplos e o que ela representa. É lista e não
   tabela de propósito — em 320px a tabela precisaria rolar por dentro, e escolher o papel de
   cada coluna é a tarefa principal desta tela, não um detalhe dentro de uma grade. */
.column-map {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0 var(--space-4);
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
}

.column-map-item {
  min-width: 0;
}

/* O cabeçalho vindo do arquivo pode ser longo ("NOME COMPLETO DO COLABORADOR") e é conteúdo
   do cliente: trunca em vez de empurrar a coluna e, com ela, a página. */
.column-map-item > .form-field > label {
  overflow: hidden;
  color: var(--color-text);
  font-weight: var(--weight-semibold);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Os exemplos ocupam a faixa de apoio do campo. Duas linhas no máximo: são para reconhecer a
   coluna, não para conferir o conteúdo. */
.column-map-item .form-field-hint {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-variant-numeric: tabular-nums;
}

.flow-panel-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.flow-panel-title {
  margin: 0;
  font-size: var(--text-base);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.flow-panel-title code {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.flow-panel-badges,
.flow-panel-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* --- Nó (cartão de etapa) ------------------------------------------------ */

.flow-node {
  width: 15rem;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  box-shadow: var(--shadow-1);
  cursor: grab;
  user-select: none;
}

.diagram-node.selected .flow-node {
  border-color: var(--color-accent-ink);
  box-shadow: 0 0 0 2px var(--color-focus-ring);
}

.flow-node-entry {
  border-left: 4px solid var(--color-accent-ink);
}

.flow-node-issue {
  border-color: var(--danger-ink);
}

/* Abertura e encerramento (01/09): são a MOLDURA da conversa, não etapas dela. Borda
   tracejada e fundo rebaixado dizem isso sem precisar de rótulo extra; o cursor é de
   ponteiro porque eles não se arrastam — a posição é derivada das etapas. */
.flow-text-node {
  border-style: dashed;
  background: var(--color-sunken);
  cursor: pointer;
}

.flow-text-node .flow-node-type {
  color: var(--color-accent-ink);
}

.flow-node-head {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.flow-node-type {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.flow-node-open {
  width: 100%;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.flow-node-open:focus-visible {
  outline: 2px solid var(--color-accent-ink);
  outline-offset: 2px;
}

.flow-node-text {
  margin: 0;
  font-size: var(--text-sm);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.flow-node-meta {
  margin: 0;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  display: flex;
  gap: var(--space-1);
  flex-wrap: wrap;
}

/* Porta de saída: alvo tocável de verdade, não um pontinho de 8px. */
.flow-canvas .diagram-port.flow-port {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: var(--color-accent-ink);
  border: 2px solid var(--color-surface);
  bottom: -0.625rem;
  cursor: crosshair;
}

.flow-canvas .diagram-port.flow-port:hover,
.flow-canvas .diagram-port.flow-port.has-links {
  background: var(--color-accent-ink-hover);
}

/* --- Arestas ------------------------------------------------------------- */

/* Presentation attribute perde de CSS: dá para tematizar o traço sem widget custom. */
.flow-canvas .diagram-svg-layer path {
  stroke: var(--color-text-muted);
}

.flow-canvas .diagram-svg-layer path.selected {
  stroke: var(--color-accent-ink);
}

.flow-canvas .diagram-svg-layer marker path {
  fill: var(--color-text-muted);
  stroke: var(--color-text-muted);
}

.flow-canvas .default-link-label {
  padding: calc(var(--space-1) / 2) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--text-xs);
  box-shadow: var(--shadow-1);
}

.issue-step-link {
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  text-decoration: underline;
}

/* --- MqDialog ------------------------------------------------------------- */

.mq-dialog-backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgb(9 9 11 / 45%);
}

.mq-dialog {
  display: flex;
  flex-direction: column;
  width: min(34rem, 100%);
  max-height: min(85vh, 48rem);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  box-shadow: var(--shadow-2);
  outline: none;
}

.mq-dialog-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.mq-dialog-title {
  margin: 0;
  font-size: var(--text-base);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* O corpo rola sozinho: editar a etapa 12 não pode exigir rolar a página atrás do diálogo. */
.mq-dialog-body {
  overflow-y: auto;
  padding: var(--space-4);
}

.mq-dialog-body textarea {
  min-height: 4.5rem;
}

/* ——— Política de contato por destinatário (D-066): editor de escala, exceções e prévia ——— */

/* Rótulo de um grupo de controles que não é um <label> (grupo de rádios, lista de intervalos). */
.form-field-label {
  font-weight: 600;
}

.stacked-options {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Linha de intervalo: início – fim + interruptor + remover. Quebra em duas linhas no celular. */
.interval-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.interval-field input[type="time"] {
  min-width: 6.5rem;
}

.cycle-days {
  list-style: none;
  padding: 0;
  margin: 0 0 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.cycle-day {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md, 0.5rem);
  padding: 0.75rem;
}

.team-pane,
.contact-preview {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--color-border);
}

.team-pane h3 {
  margin-top: 0.5rem;
}
