/* GERADO a partir do repositorio medguide-design-system (components.css) — NÃO EDITE AQUI. Edite src/, rode build.py la, e ferramentas/sincroniza_ds.py aqui · versao 8bb5db7e */
/* MedGuide Design System
   components.css — versao 0.2.2 — gerado em 2026-09-12
   ARQUIVO GERADO. Nao edite: mexa em src/ e rode build.py.
   Origem: 20 arquivos em src/componentes/
*/
/* ==========================================================================
   MedGuide Design System — componentes (prefixo mg-) · v0.2
   --------------------------------------------------------------------------
   Depende de tokens.css. Convive com o Tailwind e com o CSS do painel: todo
   seletor de componente começa por .mg- (a única exceção é a regra [hidden],
   que reforça o comportamento padrão do HTML). Só usa tokens SEMÂNTICOS:
   nenhum hex e nenhuma cor crua da paleta (teal-N, navy-N) aqui.
   ATENÇÃO: nunca escreva asterisco seguido de barra dentro de um comentário.
   Isso FECHA o comentário, e o navegador descarta calado a regra seguinte.
   Aconteceu na v0.2 com a regra [hidden]: o modal da vitrine abria sozinho (R30).
   Regra de ouro: o COMPONENTE é do DS, o ARRANJO é da tela.
   Estados por atributo sempre que existir um ARIA equivalente (aria-invalid,
   aria-busy, aria-selected, aria-pressed, aria-checked, aria-current).
   Cascata: o <style> do Tailwind Play CDN entra DEPOIS destes arquivos, então
   uma utilitária na mesma tag (ex.: px-8) vence o componente. É intencional
   para ajuste pontual — não use isso para redesenhar o componente.
   Caracteres não-ASCII em `content:` vão escapados (\203A), para não depender
   da codificação em que o CSS for servido.
   ========================================================================== */

/* ---- Modelo de caixa --------------------------------------------------------
   `box-sizing` não aparecia UMA vez no design system inteiro (achado em 12/09, na
   vitrine). O <select> parecia certo só porque o navegador já o entrega em border-box
   por padrão; todo .mg-input, .mg-textarea e afins tinha `width: 100%` somado a 12px+12px
   de padding e 1px+1px de borda, e transbordava a célula da grade em 26px. Num formulário
   de duas colunas isso põe o campo da esquerda por cima da calha.

   Por que NÃO é `* { box-sizing: border-box }`: o design system entra por cima de telas
   que já existem, e trocar o modelo de caixa da página inteira mudaria o layout do
   anfitrião. Ele tem de ser inerte fora do que é dele (A20, F-40). O par de seletores
   abaixo é o jeito exato de dizer "elemento que tem alguma classe mg-": o primeiro pega
   quando ela é a primeira do atributo, o segundo quando vem depois de um espaço. */
[class^="mg-"], [class*=" mg-"],
[class^="mg-"]::before, [class*=" mg-"]::before,
[class^="mg-"]::after,  [class*=" mg-"]::after { box-sizing: border-box; }

/* O atributo hidden sempre esconde. Sem isto, qualquer .mg-* com display próprio
   (flex, grid) ignorava hidden fora do Tailwind (no site institucional, por exemplo). */
[hidden] { display: none !important; }

/* ---- Base opcional: aplique .mg-root no <body> de tela nova --------------- */
.mg-root {
  font-family: var(--mg-font-ui);
  font-size: var(--mg-text-sm);
  line-height: var(--mg-leading-normal);
  color: var(--mg-text);
  background: var(--mg-bg);
}

.mg-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---- Pular para o conteúdo -------------------------------------------------------
   Primeiro focável da página: quem navega por teclado não precisa tabular por 30 itens
   de menu em cada tela. O painel já tinha (main.css:1650); aqui o nome estava RESERVADO
   na ferramenta de cobertura e o componente nunca foi escrito — a isenção existia para
   esconder a falta (12/09). Uso:
   <a class="mg-pular" href="#conteudo">Pular para o conteúdo</a> … <main id="conteudo"> */
.mg-pular {
  position: absolute; left: var(--mg-space-3); top: -100%;
  z-index: var(--mg-z-toast);
  padding: var(--mg-space-2) var(--mg-space-4);
  background: var(--mg-surface); color: var(--mg-action-text);
  border: 1px solid var(--mg-action); border-radius: var(--mg-radius-md);
  font-weight: var(--mg-weight-semibold); text-decoration: none;
}
.mg-pular:focus { top: var(--mg-space-3); }

/* ---- Foco: contorno sólido em TODO controle do DS, sem depender de .mg-root */
.mg-btn:focus-visible, .mg-input:focus-visible, .mg-select:focus-visible, .mg-textarea:focus-visible,
.mg-switch:focus-visible, .mg-tab:focus-visible, .mg-segmented__item:focus-visible, .mg-page:focus-visible,
.mg-menu__item:focus-visible, .mg-chip__remove:focus-visible, .mg-modal__close:focus-visible,
.mg-pular:focus-visible,
.mg-toast__close:focus-visible, .mg-accordion__summary:focus-visible, .mg-link:focus-visible,
.mg-breadcrumb a:focus-visible, .mg-check input:focus-visible, .mg-dropzone:focus-within,
.mg-modal__dialog:focus-visible {
  outline: var(--mg-focus-width) solid var(--mg-focus-color);
  outline-offset: var(--mg-focus-offset);
}
.mg-sidebar a:focus-visible, .mg-sidebar button:focus-visible {
  outline: var(--mg-focus-width) solid var(--mg-on-chrome);
  outline-offset: calc(-1 * var(--mg-focus-width));
}

.mg-link { color: var(--mg-action-text); text-decoration: underline; text-underline-offset: 2px; }
.mg-link:hover { color: var(--mg-action-active); }

/* ==========================================================================
   Botão — .mg-btn + variante. Sempre <button type="button"> (ou "submit").
   Só-ícone exige aria-label.
   ========================================================================== */
.mg-btn {
  appearance: none;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--mg-space-2);
  height: var(--mg-control-h-md);
  padding: 0 var(--mg-space-4);
  border: 1px solid transparent;
  border-radius: var(--mg-radius-md);
  font: var(--mg-weight-semibold) var(--mg-text-sm)/1 var(--mg-font-ui);
  /* Um .mg-btn SEM variação não pode cair no visual padrão do navegador (fundo cinza,
     texto preto): medido em 12/09, era o que acontecia fora de uma página com reset. */
  background: transparent;
  color: var(--mg-text);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--mg-duration-fast) var(--mg-ease-out),
              border-color var(--mg-duration-fast) var(--mg-ease-out),
              color var(--mg-duration-fast) var(--mg-ease-out);
}
.mg-btn svg, .mg-btn [data-lucide] { width: 16px; height: 16px; flex: none; }

.mg-btn--primary   { background: var(--mg-action); color: var(--mg-on-action); }
.mg-btn--primary:hover   { background: var(--mg-action-hover); }
.mg-btn--primary:active  { background: var(--mg-action-active); }

.mg-btn--secondary { background: var(--mg-surface); color: var(--mg-text); border-color: var(--mg-control-border); }
.mg-btn--secondary:hover { background: var(--mg-surface-2); border-color: var(--mg-control-border-hover); }

.mg-btn--ghost     { background: transparent; color: var(--mg-action-text); }
.mg-btn--ghost:hover     { background: var(--mg-action-subtle); }

.mg-btn--danger    { background: var(--mg-danger); color: var(--mg-on-action); }
.mg-btn--danger:hover    { background: var(--mg-danger-hover); }

/* `:active` nas QUATRO variantes: só o primário tinha. Sem ele, o botão não responde ao
   toque — em celular, onde não há `:hover`, é o único retorno que a pessoa recebe de que
   o toque pegou (o painel já tinha em primary e secondary). */
.mg-btn--secondary:active { background: var(--mg-surface-3); }
.mg-btn--ghost:active     { background: var(--mg-surface-3); }
.mg-btn--danger:active    { background: var(--mg-danger-hover); }

/* Duas variantes que o painel tem e o DS não tinha. Sem elas, migrar as telas que as usam
   obrigaria a escrever `<style>` na página — o que o princípio 6 proíbe. */
.mg-btn--outline {
  background: transparent; color: var(--mg-action-text);
  /* `--mg-action-border` é tom de fundo suave: sobre branco dá 1,36:1 e a borda some.
     A borda de um controle precisa de 3:1 — é a mesma lição que a borda de campo já
     tinha aprendido na v0.2 (`--mg-control-border`, 3,5:1). */
  border-color: var(--mg-action);
}
.mg-btn--outline:hover  { background: var(--mg-action-subtle); }
.mg-btn--outline:active { background: var(--mg-action-subtle); border-color: var(--mg-action); }
.mg-btn--success        { background: var(--mg-success); color: var(--mg-on-strong); }
.mg-btn--success:hover  { background: var(--mg-success-hover); }
.mg-btn--success:active { background: var(--mg-success-hover); }

.mg-btn--sm   { height: var(--mg-control-h-sm); padding: 0 var(--mg-space-3); font-size: var(--mg-text-xs); }
.mg-btn--lg   { height: var(--mg-control-h-lg); padding: 0 var(--mg-space-6); font-size: var(--mg-text-md); }
.mg-btn--icon { width: var(--mg-control-h-md); padding: 0; }
.mg-btn--icon.mg-btn--sm { width: var(--mg-control-h-sm); }
.mg-btn--block { width: 100%; }

.mg-btn:disabled,
.mg-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; pointer-events: none; }

/* Carregando: o texto some, o tamanho fica (evita o botão "pular") */
.mg-btn[aria-busy="true"] { position: relative; color: transparent !important; pointer-events: none; }
.mg-btn[aria-busy="true"]::after {
  content: ""; position: absolute; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--mg-on-action); border-right-color: transparent;
  animation: mg-spin .8s linear infinite;
}
.mg-btn--secondary[aria-busy="true"]::after,
.mg-btn--ghost[aria-busy="true"]::after { border-color: var(--mg-action); border-right-color: transparent; }

/* ==========================================================================
   Campos — .mg-field agrupa rótulo + controle + ajuda/erro
   ========================================================================== */
.mg-field { display: flex; flex-direction: column; gap: var(--mg-space-1); min-width: 0; }
.mg-label { font-size: var(--mg-text-sm); font-weight: var(--mg-weight-medium); color: var(--mg-text-2); }
.mg-label .mg-required { color: var(--mg-danger-text); margin-left: 2px; }
.mg-hint  { line-height: var(--mg-leading-normal); margin: 0; font-size: var(--mg-text-xs); color: var(--mg-text-muted); }
/* `min-height` reserva o espaço da mensagem ANTES de ela existir: sem isso o formulário
   inteiro salta quando o primeiro erro aparece, e o campo que a pessoa ia clicar muda de
   lugar debaixo do dedo. O painel já reservava (components.css:334). */
.mg-field-error {
  /* exatamente UMA linha: 1em × a altura de linha. Chutei 1.15em na primeira versão
     e o teste mediu 13,8px reservados contra 18px ocupados — a tela ainda saltava. */
  min-height: calc(1em * var(--mg-leading-normal));
  line-height: var(--mg-leading-normal); margin: 0;
  font-size: var(--mg-text-xs); color: var(--mg-danger-text);
}

.mg-input, .mg-select, .mg-textarea {
  width: 100%;
  min-height: var(--mg-control-h-md);
  padding: var(--mg-space-2) var(--mg-space-3);
  border: 1px solid var(--mg-control-border);
  border-radius: var(--mg-radius-md);
  background: var(--mg-surface);
  color: var(--mg-text);
  font: var(--mg-weight-regular) var(--mg-text-sm)/var(--mg-leading-normal) var(--mg-font-ui);
  transition: border-color var(--mg-duration-fast);
}
.mg-textarea { min-height: 96px; resize: vertical; }
.mg-input::placeholder, .mg-textarea::placeholder { color: var(--mg-text-muted); }
.mg-input:hover, .mg-select:hover, .mg-textarea:hover { border-color: var(--mg-control-border-hover); }
.mg-input:focus, .mg-select:focus, .mg-textarea:focus { border-color: var(--mg-action); }
.mg-input[aria-invalid="true"], .mg-select[aria-invalid="true"], .mg-textarea[aria-invalid="true"] {
  border-color: var(--mg-danger);
}
/* opacity: 1 anula o `input:disabled { opacity: .7 }` global do main.css do painel */
.mg-input:disabled, .mg-select:disabled, .mg-textarea:disabled {
  opacity: 1; background: var(--mg-surface-3); color: var(--mg-text-muted); cursor: not-allowed;
}
/* iOS dá zoom em campo com fonte < 16px */
@media (max-width: 640px) {
  .mg-input, .mg-select, .mg-textarea { font-size: var(--mg-text-md); }
}

/* Campo com prefixo/sufixo (R$, %, kg) ou ícone (busca) */
.mg-input-group { display: flex; align-items: stretch; position: relative; }
.mg-input-group > .mg-input { flex: 1; min-width: 0; }
.mg-input-group__addon {
  display: inline-flex; align-items: center; padding: 0 var(--mg-space-3);
  background: var(--mg-surface-2); color: var(--mg-text-muted); font-weight: var(--mg-weight-medium);
  border: 1px solid var(--mg-control-border);
}
.mg-input-group__addon:first-child { border-right: 0; border-radius: var(--mg-radius-md) 0 0 var(--mg-radius-md); }
.mg-input-group__addon:last-child  { border-left: 0;  border-radius: 0 var(--mg-radius-md) var(--mg-radius-md) 0; }
.mg-input-group__addon:first-child + .mg-input { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.mg-input-group > .mg-input:has(+ .mg-input-group__addon) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.mg-input-group__icon {
  position: absolute; left: var(--mg-space-3); top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--mg-text-muted); pointer-events: none;
}
.mg-input-group__icon + .mg-input { padding-left: calc(var(--mg-space-3) * 2 + 16px); }

/* Checkbox e radio — o controle é o nativo (acessível de graça), só tingido */
.mg-check { display: inline-flex; align-items: flex-start; gap: var(--mg-space-2); cursor: pointer; color: var(--mg-text); }
.mg-check input { width: 18px; height: 18px; margin: 1px 0 0; accent-color: var(--mg-action); flex: none; cursor: pointer; }
.mg-check input:disabled, .mg-check input:disabled + span { cursor: not-allowed; color: var(--mg-text-muted); }
.mg-check-group { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--mg-space-2); }
.mg-check-group--inline { flex-direction: row; flex-wrap: wrap; gap: var(--mg-space-4); }
.mg-legend { padding: 0; margin-bottom: var(--mg-space-2); font-size: var(--mg-text-sm); font-weight: var(--mg-weight-medium); color: var(--mg-text-2); }

/* Interruptor (liga/desliga) — <button type="button" role="switch" aria-checked> */
.mg-switch {
  appearance: none; position: relative; flex: none;
  width: 40px; height: 24px; border-radius: var(--mg-radius-full);
  border: none; background: var(--mg-control-off); cursor: pointer;
  transition: background-color var(--mg-duration-base) var(--mg-ease-out);
}
.mg-switch::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%; background: var(--mg-surface);
  box-shadow: var(--mg-shadow-sm);
  transition: transform var(--mg-duration-base) var(--mg-ease-out);
}
.mg-switch[aria-checked="true"] { background: var(--mg-action); }
.mg-switch[aria-checked="true"]::after { transform: translateX(16px); }
.mg-switch:disabled { opacity: .5; cursor: not-allowed; }

/* Segmentado — filtro de escolha única (Hoje / Amanhã / Semana). NÃO é aba:
   não troca painel, só filtra. Botões com aria-pressed. */
.mg-segmented {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--mg-surface-3); border-radius: var(--mg-radius-md);
}
.mg-segmented__item {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  height: calc(var(--mg-control-h-md) - 6px); padding: 0 var(--mg-space-4);
  border-radius: calc(var(--mg-radius-md) - 2px);
  font: var(--mg-weight-medium) var(--mg-text-sm)/1 var(--mg-font-ui); color: var(--mg-text-2);
}
.mg-segmented__item[aria-pressed="true"] { background: var(--mg-surface); color: var(--mg-text); box-shadow: var(--mg-shadow-sm); font-weight: var(--mg-weight-semibold); }

/* ==========================================================================
   Estrutura de página
   ========================================================================== */
.mg-page-header {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: var(--mg-space-4); margin-bottom: var(--mg-space-6);
}
.mg-page-header__title { font-family: var(--mg-font-ui); line-height: var(--mg-leading-tight);
  margin: 0; font-size: var(--mg-text-2xl); font-weight: var(--mg-weight-bold);
  line-height: var(--mg-leading-tight); color: var(--mg-text);
}
.mg-page-header__subtitle { line-height: var(--mg-leading-normal); margin: var(--mg-space-1) 0 0; color: var(--mg-text-muted); }
.mg-page-header__actions { display: flex; flex-wrap: wrap; gap: var(--mg-space-2); }

/* Breadcrumb — <nav aria-label="Você está em"><ol class="mg-breadcrumb">… <a aria-current="page"> */
.mg-breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--mg-space-2); list-style: none; margin: 0 0 var(--mg-space-3); padding: 0; font-size: var(--mg-text-sm); }
.mg-breadcrumb li { display: inline-flex; align-items: center; gap: var(--mg-space-2); color: var(--mg-text-muted); }
.mg-breadcrumb li + li::before { content: "\203A"; color: var(--mg-text-muted); }
.mg-breadcrumb a { color: var(--mg-action-text); text-decoration: none; }
.mg-breadcrumb a:hover { text-decoration: underline; }
.mg-breadcrumb [aria-current="page"] { color: var(--mg-text); font-weight: var(--mg-weight-medium); }

/* Casca do app: sidebar navy + topbar + conteúdo. O painel de hoje desenha a casca em
   components/menu.js; migrar é um PR próprio (não misture com conserto de tela). */
.mg-shell { display: grid; grid-template-columns: var(--mg-sidebar-w) minmax(0, 1fr); min-height: 100vh; background: var(--mg-bg); }
.mg-sidebar {
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--mg-space-1);
  padding: var(--mg-space-5) var(--mg-space-3);
  background: var(--mg-chrome); color: var(--mg-on-chrome);
}
.mg-sidebar__brand { padding: 0 var(--mg-space-2) var(--mg-space-4); }
.mg-sidebar__section { margin: var(--mg-space-4) var(--mg-space-2) var(--mg-space-1); font-size: var(--mg-text-xs); font-weight: var(--mg-weight-semibold); letter-spacing: .06em; text-transform: uppercase; color: var(--mg-on-chrome-muted); }
.mg-sidebar__item {
  display: flex; align-items: center; gap: var(--mg-space-3);
  padding: var(--mg-space-2) var(--mg-space-3); border-radius: var(--mg-radius-md);
  color: var(--mg-on-chrome); text-decoration: none; font-weight: var(--mg-weight-medium);
}
.mg-sidebar__item:hover { background: var(--mg-chrome-hover); }
.mg-sidebar__item[aria-current="page"] { background: var(--mg-chrome-active); box-shadow: inset 3px 0 0 var(--mg-brand); }
.mg-sidebar__item svg, .mg-sidebar__item [data-lucide] { width: 18px; height: 18px; flex: none; }
.mg-topbar {
  position: sticky; top: 0; z-index: var(--mg-z-sticky);
  display: flex; align-items: center; justify-content: space-between; gap: var(--mg-space-4);
  height: var(--mg-topbar-h); padding: 0 var(--mg-space-6);
  background: var(--mg-surface); border-bottom: 1px solid var(--mg-border);
}
.mg-main { padding: var(--mg-space-6); max-width: var(--mg-content-max); }
/* Botão de abrir a gaveta: só aparece no celular. Fica na topbar, antes de tudo. */
.mg-shell__abrir { display: none; }
/* Véu escuro atrás da gaveta aberta. Fecha ao clique (o mg.js cuida). */
.mg-shell__veu { display: none; }

@media (max-width: 1023px) {
  /* Até 12/09 aqui havia só `position: static; height: auto` — a sidebar inteira
     empilhava ACIMA do conteúdo, e no celular o usuário rolava o menu todo antes de ver
     a tela. O painel já tinha gaveta com véu (components.css:32-38); adotar a casca do
     design system sem isto seria regressão (revisão independente, 12/09). */
  .mg-shell { grid-template-columns: minmax(0, 1fr); }
  .mg-shell__abrir { display: inline-flex; }

  .mg-sidebar {
    position: fixed; top: 0; bottom: 0; left: 0;
    width: min(var(--mg-sidebar-w), 86vw); height: 100dvh;
    z-index: var(--mg-z-overlay);
    transform: translateX(-100%);
    transition: transform var(--mg-duration-base) var(--mg-ease-out);
    box-shadow: var(--mg-shadow-lg);
  }
  .mg-shell[data-menu="aberto"] .mg-sidebar { transform: translateX(0); }

  .mg-shell[data-menu="aberto"] .mg-shell__veu {
    display: block; position: fixed; inset: 0;
    z-index: calc(var(--mg-z-overlay) - 1);
    background: var(--mg-overlay);
  }
  /* Quem prefere menos movimento não leva a gaveta deslizando na cara. */
  @media (prefers-reduced-motion: reduce) {
    .mg-sidebar { transition: none; }
  }
}

/* ==========================================================================
   Card e métrica
   ========================================================================== */
.mg-card {
  background: var(--mg-surface);
  border: 1px solid var(--mg-border);
  border-radius: var(--mg-radius-lg);
  box-shadow: var(--mg-shadow-sm);
}
.mg-card__header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--mg-space-3);
  padding: var(--mg-space-4) var(--mg-space-5);
  border-bottom: 1px solid var(--mg-border);
}
.mg-card__title { margin: 0; font-size: var(--mg-text-md); font-weight: var(--mg-weight-semibold); }
.mg-card__body   { padding: var(--mg-space-5); }
.mg-card__footer {
  display: flex; justify-content: flex-end; gap: var(--mg-space-2);
  padding: var(--mg-space-3) var(--mg-space-5);
  border-top: 1px solid var(--mg-border); background: var(--mg-surface-2);
  border-radius: 0 0 var(--mg-radius-lg) var(--mg-radius-lg);
}

/* Métrica — substitui stat-card, -v2 e -v3 */
.mg-stat { display: flex; flex-direction: column; gap: var(--mg-space-1); padding: var(--mg-space-5); }
.mg-stat__label { line-height: var(--mg-leading-tight); margin: 0; font-size: var(--mg-text-xs); font-weight: var(--mg-weight-semibold); color: var(--mg-text-muted); text-transform: uppercase; letter-spacing: .04em; }
.mg-stat__value { line-height: var(--mg-leading-tight); margin: 0; font-size: var(--mg-text-2xl); font-weight: var(--mg-weight-bold); color: var(--mg-text); font-variant-numeric: tabular-nums; }
.mg-stat__detail { line-height: var(--mg-leading-normal); margin: 0; font-size: var(--mg-text-xs); color: var(--mg-text-muted); }
/* Valor que não carregou NUNCA vira 0: mostra traço e o motivo no detalhe */
.mg-stat__value[data-state="error"] { color: var(--mg-text-muted); }

/* ==========================================================================
   Badge, chip e avatar
   ========================================================================== */
.mg-badge {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 var(--mg-space-2);
  border: 1px solid transparent; border-radius: var(--mg-radius-sm);
  font-size: var(--mg-text-xs); font-weight: var(--mg-weight-semibold); white-space: nowrap;
}
.mg-badge--dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.mg-badge--neutral, .mg-chip--neutral { background: var(--mg-surface-3);     color: var(--mg-text-2);        border-color: var(--mg-border-strong); }
.mg-badge--action,  .mg-chip--action  { background: var(--mg-action-subtle); color: var(--mg-action-text);   border-color: var(--mg-action-border); }
.mg-badge--success, .mg-chip--success { background: var(--mg-success-subtle); color: var(--mg-success-text); border-color: var(--mg-success-border); }
.mg-badge--warning, .mg-chip--warning { background: var(--mg-warning-subtle); color: var(--mg-warning-text); border-color: var(--mg-warning-border); }
.mg-badge--danger,  .mg-chip--danger  { background: var(--mg-danger-subtle);  color: var(--mg-danger-text);  border-color: var(--mg-danger-border); }
.mg-badge--info,    .mg-chip--info    { background: var(--mg-info-subtle);    color: var(--mg-info-text);    border-color: var(--mg-info-border); }

/* Situação da consulta — UM mapa para o produto inteiro. Valores do enum AppointmentStatus
   (clinic-manager/src/modules/appointment/domain/enums/appointment-status.ts).
   <span class="mg-badge mg-badge--dot" data-appointment-status="confirmed">Confirmado</span> */
/* PADRÃO para situação que o design system ainda não conhece. Sem isto, um status novo
   (ou um que só existe no painel, como `blocked`) casava apenas com `.mg-badge`, que
   declara `border-color: transparent` e NENHUM fundo: o selo saía invisível na tela e
   nada avisava. Medido em 12/09.
   O `:not()` é de propósito, para esta regra NÃO competir com as específicas abaixo —
   se fosse só uma questão de ordem, quem mexer no arquivo amanhã reintroduz o defeito
   sem perceber. Mesma lição do chip (R41). */
.mg-badge[data-appointment-status]:not([data-appointment-status="scheduled"]):not([data-appointment-status="pending_patient_confirmation"]):not([data-appointment-status="confirmed"]):not([data-appointment-status="waiting"]):not([data-appointment-status="in_progress"]):not([data-appointment-status="done"]):not([data-appointment-status="cancelled"]):not([data-appointment-status="no_show"]) {
  background: var(--mg-surface-3); color: var(--mg-text-2); border-color: var(--mg-border-strong);
}
.mg-badge[data-appointment-status="scheduled"]                    { background: var(--mg-action-subtle);  color: var(--mg-action-text);  border-color: var(--mg-action-border); }
.mg-badge[data-appointment-status="pending_patient_confirmation"] { background: var(--mg-warning-subtle); color: var(--mg-warning-text); border-color: var(--mg-warning-border); }
.mg-badge[data-appointment-status="confirmed"]                    { background: var(--mg-success-subtle); color: var(--mg-success-text); border-color: var(--mg-success-border); }
.mg-badge[data-appointment-status="waiting"]                      { background: var(--mg-info-subtle);    color: var(--mg-info-text);    border-color: var(--mg-info-border); }
.mg-badge[data-appointment-status="in_progress"]                  { background: var(--mg-chrome);         color: var(--mg-on-strong);    border-color: var(--mg-chrome); }
.mg-badge[data-appointment-status="done"]                         { background: var(--mg-surface-3);      color: var(--mg-text-2);       border-color: var(--mg-border-strong); }
.mg-badge[data-appointment-status="cancelled"]                    { background: var(--mg-danger-subtle);  color: var(--mg-danger-text);  border-color: var(--mg-danger-border); }
.mg-badge[data-appointment-status="no_show"]                      { background: var(--mg-danger);         color: var(--mg-on-strong);    border-color: var(--mg-danger); }

/* Chip — etiqueta de paciente, filtro aplicado. Removível com .mg-chip__remove */
.mg-chip {
  display: inline-flex; align-items: center; gap: var(--mg-space-1);
  min-height: 26px; padding: 0 var(--mg-space-2) 0 var(--mg-space-3);
  border: 1px solid var(--mg-border-strong); border-radius: var(--mg-radius-full);
  font-size: var(--mg-text-xs); font-weight: var(--mg-weight-medium);
}
/* A cor do chip sai da variação. Esta regra pinta só o chip SEM variação — e usa :not()
   de propósito, para não competir com .mg-chip--danger e companhia.
   Por que assim: a base ficava DEPOIS das variações no arquivo e, com a mesma
   especificidade, apagava as seis calada (12/09). Dava para consertar mudando a ordem,
   mas ordem é frágil — quem mexer no arquivo amanhã reintroduz o defeito sem perceber.
   Assim o acerto não depende de ninguém lembrar de nada. */
.mg-chip:not([class*="mg-chip--"]) { background: var(--mg-surface-3); color: var(--mg-text-2); }
.mg-chip:not(:has(.mg-chip__remove)) { padding-right: var(--mg-space-3); }
.mg-chip__remove {
  appearance: none; border: 0; background: transparent; cursor: pointer; color: inherit;
  display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%;
  font-size: 14px; line-height: 1;
}
.mg-chip__remove:hover { background: rgba(15, 27, 41, .08); }
.mg-chip-list { display: flex; flex-wrap: wrap; gap: var(--mg-space-2); }

/* Avatar com iniciais — MG.avatar(nome) gera o HTML com as iniciais e o tom */
.mg-avatar {
  display: inline-grid; place-items: center; flex: none;
  width: 36px; height: 36px; border-radius: 50%;
  font-size: var(--mg-text-xs); font-weight: var(--mg-weight-bold); letter-spacing: .02em;
  background: var(--mg-surface-3); color: var(--mg-text-2);
  user-select: none; overflow: hidden;
}
.mg-avatar img { width: 100%; height: 100%; object-fit: cover; }
.mg-avatar--sm { width: 28px; height: 28px; font-size: 11px; }
.mg-avatar--lg { width: 48px; height: 48px; font-size: var(--mg-text-sm); }
.mg-avatar[data-tone="1"] { background: var(--mg-action-subtle);  color: var(--mg-action-text); }
.mg-avatar[data-tone="2"] { background: var(--mg-info-subtle);    color: var(--mg-info-text); }
.mg-avatar[data-tone="3"] { background: var(--mg-success-subtle); color: var(--mg-success-text); }
.mg-avatar[data-tone="4"] { background: var(--mg-warning-subtle); color: var(--mg-warning-text); }
.mg-avatar[data-tone="5"] { background: var(--mg-danger-subtle);  color: var(--mg-danger-text); }
.mg-avatar[data-tone="6"] { background: var(--mg-surface-3);      color: var(--mg-text-2); }

/* ==========================================================================
   Campo de leitura — rótulo em cima, valor embaixo. NÃO é formulário.
   Usado em ficha do paciente, dados da clínica, detalhe da consulta.
   Valor que não veio usa .mg-data__value--vazio com um traço, nunca em branco:
   campo vazio e campo que falhou de carregar parecem a mesma coisa, e não são.
   <div class="mg-data"><p class="mg-data__label">E-mail</p>
                        <p class="mg-data__value">ana@clinica.com</p></div>
   ========================================================================== */
.mg-data + .mg-data { margin-top: var(--mg-space-3); }
.mg-data__label { line-height: var(--mg-leading-normal);
  margin: 0 0 2px;
  font-size: var(--mg-text-xs); font-weight: var(--mg-weight-medium);
  text-transform: uppercase; letter-spacing: .04em;
  color: var(--mg-text-muted);
}
.mg-data__value {
  margin: 0;
  font-size: var(--mg-text-sm); font-weight: var(--mg-weight-medium);
  color: var(--mg-text); line-height: 1.4;
}
.mg-data__value--vazio { font-weight: var(--mg-weight-regular); font-style: italic; color: var(--mg-text-muted); }
/* Em grade: duas colunas a partir de 640px, uma abaixo disso. */
.mg-data-grid { display: grid; gap: var(--mg-space-3) var(--mg-space-5); }
@media (min-width: 640px) { .mg-data-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.mg-data-grid > .mg-data + .mg-data { margin-top: 0; }

/* ==========================================================================
   Tela de acesso — casca centrada de login, cadastro e recuperação de senha.
   Existe no sistema (acesso.html) e no site; sem componente, as duas telas
   divergem e a marca muda de uma para a outra.
   ========================================================================== */
.mg-auth {
  min-height: 100vh; min-height: 100dvh;
  display: grid; place-items: center;
  padding: var(--mg-space-5);
  background: var(--mg-bg);
}
.mg-auth__card {
  width: 100%; max-width: 400px;
  background: var(--mg-surface);
  border: 1px solid var(--mg-border);
  border-radius: var(--mg-radius-xl);
  box-shadow: var(--mg-shadow-md);
  padding: var(--mg-space-6);
}
.mg-auth__header { text-align: center; margin-bottom: var(--mg-space-5); }
.mg-auth__logo { height: 32px; width: auto; margin-bottom: var(--mg-space-4); }
.mg-auth__title { line-height: var(--mg-leading-tight); font-family: var(--mg-font-ui); margin: 0 0 var(--mg-space-1); font-size: var(--mg-text-xl); font-weight: var(--mg-weight-semibold); color: var(--mg-text); }
.mg-auth__subtitle { line-height: var(--mg-leading-normal); margin: 0; font-size: var(--mg-text-sm); color: var(--mg-text-2); }
.mg-auth__form { display: flex; flex-direction: column; gap: var(--mg-space-4); }
.mg-auth__footer {
  margin-top: var(--mg-space-5); padding-top: var(--mg-space-4);
  border-top: 1px solid var(--mg-border);
  text-align: center; font-size: var(--mg-text-sm); color: var(--mg-text-2);
}

/* ==========================================================================
   Alerta inline (callout) — mensagem que fica na tela
   ========================================================================== */
.mg-alert {
  display: flex; gap: var(--mg-space-3); align-items: flex-start;
  padding: var(--mg-space-3) var(--mg-space-4);
  border: 1px solid; border-radius: var(--mg-radius-md);
}
.mg-alert__title { margin: 0 0 2px; font-weight: var(--mg-weight-semibold); }
.mg-alert p { margin: 0; }
/* `color: inherit` não é enfeite: a variação pinta o CONTAINER e o texto herda. Herança
   perde para qualquer regra direta, e o site institucional tem `p { color: slate }` —
   medido em 12/09: o alerta de PERIGO saía CINZA dentro do site, perdendo o significado
   da cor. Declarar inherit devolve a cor ao texto sem competir com a variação. */
.mg-alert__title, .mg-alert p, .mg-alert li, .mg-alert a, .mg-alert strong,
.mg-alert h1, .mg-alert h2, .mg-alert h3, .mg-alert h4, .mg-alert h5, .mg-alert h6 {
  color: inherit;
  line-height: var(--mg-leading-normal);
}
.mg-alert--info    { background: var(--mg-info-subtle);    color: var(--mg-info-text);    border-color: var(--mg-info-border); }
.mg-alert--success { background: var(--mg-success-subtle); color: var(--mg-success-text); border-color: var(--mg-success-border); }
.mg-alert--warning { background: var(--mg-warning-subtle); color: var(--mg-warning-text); border-color: var(--mg-warning-border); }
.mg-alert--danger  { background: var(--mg-danger-subtle);  color: var(--mg-danger-text);  border-color: var(--mg-danger-border); }

/* ==========================================================================
   Barra de filtros — busca que cresce + filtros + ações
   ========================================================================== */
.mg-filterbar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--mg-space-3);
  padding: var(--mg-space-4); margin-bottom: var(--mg-space-4);
  background: var(--mg-surface); border: 1px solid var(--mg-border); border-radius: var(--mg-radius-lg);
}
.mg-filterbar__search { flex: 1 1 260px; }
.mg-filterbar > .mg-field { flex: 0 1 200px; }
.mg-filterbar__actions { display: flex; gap: var(--mg-space-2); margin-left: auto; }

/* ==========================================================================
   Tabela — sempre dentro de .mg-table-wrap (rola sozinha no celular)
   ========================================================================== */
.mg-table-wrap {
  overflow-x: auto;
  background: var(--mg-surface);
  border: 1px solid var(--mg-border);
  border-radius: var(--mg-radius-lg);
}
/* Cabeçalho que gruda: só com altura máxima, porque o wrap vira o contêiner de rolagem */
.mg-table-wrap--scroll { max-height: 70vh; overflow-y: auto; }
.mg-table-wrap--scroll .mg-table th { position: sticky; top: 0; z-index: var(--mg-z-base); }
/* `separate`, não `collapse`: com bordas colapsadas a borda pertence à TABELA, não à
   célula, e não acompanha o `position: sticky` — ao rolar, o cabeçalho gruda SEM a linha
   embaixo e as linhas passam coladas por baixo dele. O painel usa separate exatamente
   por isso (components.css:498). O changelog da v0.2 dizia que o sticky estava
   corrigido: grudou, mas tinha perdido a borda (revisão independente, 12/09). */
.mg-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--mg-text-sm); }
.mg-table th {
  padding: var(--mg-space-3) var(--mg-space-4);
  background: var(--mg-surface-2);
  border-bottom: 1px solid var(--mg-border);
  color: var(--mg-text-muted);
  font-size: var(--mg-text-xs); font-weight: var(--mg-weight-semibold);
  text-align: left; text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}
.mg-table td { padding: var(--mg-space-3) var(--mg-space-4); border-bottom: 1px solid var(--mg-border); color: var(--mg-text-2); vertical-align: middle; }
.mg-table tbody tr:last-child td { border-bottom: none; }
.mg-table tbody tr:hover td { background: var(--mg-surface-2); }
.mg-table td.mg-num, .mg-table th.mg-num { text-align: right; font-variant-numeric: tabular-nums; }
.mg-table__actions { width: 1%; white-space: nowrap; text-align: right; }
.mg-table tr.mg-state-row td, .mg-table tr.mg-state-row:hover td { padding: 0; background: var(--mg-surface); }
.mg-cell-person { display: flex; align-items: center; gap: var(--mg-space-3); min-width: 0; }
.mg-cell-person__name { font-weight: var(--mg-weight-medium); color: var(--mg-text); }
.mg-cell-person__meta { font-size: var(--mg-text-xs); color: var(--mg-text-muted); }

/* Paginação — <nav class="mg-pagination" aria-label="Paginação"> */
.mg-pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--mg-space-3); padding: var(--mg-space-3) var(--mg-space-4); font-size: var(--mg-text-sm); color: var(--mg-text-muted); }
.mg-pagination__pages { display: flex; gap: var(--mg-space-1); }
.mg-page {
  appearance: none; min-width: var(--mg-control-h-sm); height: var(--mg-control-h-sm); padding: 0 var(--mg-space-2);
  border: 1px solid var(--mg-border-strong); border-radius: var(--mg-radius-md); background: var(--mg-surface);
  color: var(--mg-text-2); font: var(--mg-weight-medium) var(--mg-text-sm)/1 var(--mg-font-ui); cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.mg-page:hover { background: var(--mg-surface-2); }
.mg-page[aria-current="page"] { background: var(--mg-action); border-color: var(--mg-action); color: var(--mg-on-action); }
.mg-page:disabled { opacity: .5; cursor: not-allowed; }

/* ==========================================================================
   Abas — padrão APG: MG.tabs(lista) cuida de setas, Home/End e painéis.
   <div class="mg-tabs" role="tablist"> <button class="mg-tab" role="tab" aria-controls="p1">
   <div class="mg-tab-panel" role="tabpanel" id="p1">
   Para FILTRO (não troca painel), use .mg-segmented.
   ========================================================================== */
.mg-tabs { display: flex; gap: var(--mg-space-1); border-bottom: 1px solid var(--mg-border); overflow-x: auto; padding: 4px 4px 0; }
.mg-tab {
  appearance: none; background: none; border: none; cursor: pointer;
  padding: var(--mg-space-3) var(--mg-space-4); margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--mg-text-muted); font: var(--mg-weight-medium) var(--mg-text-sm)/1 var(--mg-font-ui);
  white-space: nowrap;
}
.mg-tab:hover { color: var(--mg-text); }
.mg-tab:focus-visible { outline-offset: -2px; }
.mg-tab[aria-selected="true"] { color: var(--mg-action-text); border-bottom-color: var(--mg-action); font-weight: var(--mg-weight-semibold); }
.mg-tab-panel { padding-top: var(--mg-space-5); }

/* ==========================================================================
   Menu de ações (dropdown) — MG.menu cuida de abrir, setas, Esc e clique fora.
   <div class="mg-menu-wrap"><button aria-haspopup="menu" aria-expanded="false" aria-controls="m1" data-mg-menu>
   <div class="mg-menu" id="m1" role="menu" hidden><button class="mg-menu__item" role="menuitem">
   ========================================================================== */
.mg-menu-wrap { display: inline-block; }
/* `fixed`, não `absoluto`, e com as coordenadas postas pelo MG.menu ao abrir.
   Por quê: um elemento absoluto é RECORTADO por qualquer ancestral com rolagem, e
   `.mg-table-wrap` tem `overflow-x: auto` — que, por especificação, força `overflow-y`
   a `auto` também. O padrão mais comum de painel de clínica (três pontinhos na última
   coluna da tabela) abria cortado ou invisível. E `left: 0` fixo jogava o menu para fora
   da tela nas linhas do lado direito, com `--end` dependendo de alguém lembrar de pôr à
   mão (revisão independente, 12/09).
   O JS mede a tela e decide: abaixo ou acima, alinhado ao início ou ao fim. */
.mg-menu {
  position: fixed; top: 0; left: 0; z-index: var(--mg-z-dropdown);
  min-width: 200px; max-width: min(320px, calc(100vw - 16px));
  max-height: calc(100vh - 16px); overflow-y: auto; overscroll-behavior: contain;
  padding: var(--mg-space-1);
  background: var(--mg-surface); border: 1px solid var(--mg-border);
  border-radius: var(--mg-radius-md); box-shadow: var(--mg-shadow-md);
}
.mg-menu__item {
  appearance: none; display: flex; align-items: center; gap: var(--mg-space-2); width: 100%;
  padding: var(--mg-space-2) var(--mg-space-3); border: 0; border-radius: var(--mg-radius-sm);
  background: transparent; color: var(--mg-text); text-align: left; text-decoration: none;
  font: var(--mg-weight-regular) var(--mg-text-sm)/1.3 var(--mg-font-ui); cursor: pointer;
}
.mg-menu__item:hover, .mg-menu__item:focus-visible { background: var(--mg-surface-2); }
.mg-menu__item--danger { color: var(--mg-danger-text); }
.mg-menu__sep { height: 1px; margin: var(--mg-space-1) 0; background: var(--mg-border); border: 0; }

/* Tooltip — texto curto de apoio, nunca informação essencial.
   <span class="mg-tooltip-wrap"><button aria-describedby="t1">…</button><span class="mg-tooltip" role="tooltip" id="t1">…</span></span> */
.mg-tooltip-wrap { position: relative; display: inline-flex; }
.mg-tooltip {
  position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  z-index: var(--mg-z-dropdown); width: max-content; max-width: 240px;
  padding: 6px var(--mg-space-2); border-radius: var(--mg-radius-sm);
  background: var(--mg-chrome); color: var(--mg-on-chrome);
  font-size: var(--mg-text-xs); line-height: 1.4; pointer-events: none;
  opacity: 0; visibility: hidden; transition: opacity var(--mg-duration-fast);
}
/* O `[data-mg-oculto]` é posto pelo mg.js quando a pessoa aperta Esc: a WCAG 1.4.13
   (Content on Hover or Focus) exige que conteúdo que aparece no hover seja DISPENSÁVEL
   sem tirar o ponteiro dali — sem isso, uma dica grande pode cobrir o que a pessoa
   estava lendo e não há como fechá-la. Achado por revisão independente em 12/09. */
.mg-tooltip-wrap:hover .mg-tooltip:not([data-mg-oculto]),
.mg-tooltip-wrap:focus-within .mg-tooltip:not([data-mg-oculto]) { opacity: 1; visibility: visible; }

/* ==========================================================================
   Formulário longo — seções com título à esquerda, campos em grade à direita
   ========================================================================== */
.mg-form-section {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--mg-space-6);
  padding: var(--mg-space-6) 0; border-bottom: 1px solid var(--mg-border);
}
.mg-form-section:last-of-type { border-bottom: 0; }
.mg-form-section__title { font-family: var(--mg-font-ui); line-height: var(--mg-leading-tight); margin: 0 0 var(--mg-space-1); font-size: var(--mg-text-md); font-weight: var(--mg-weight-semibold); color: var(--mg-text); }
.mg-form-section__text { line-height: var(--mg-leading-normal); margin: 0; color: var(--mg-text-muted); max-width: 36ch; }
.mg-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--mg-space-4); }
.mg-form-grid__full { grid-column: 1 / -1; }
@media (max-width: 768px) {
  .mg-form-section, .mg-form-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Acordeão — <details class="mg-accordion"><summary class="mg-accordion__summary"> (teclado de graça) */
.mg-accordion { border: 1px solid var(--mg-border); border-radius: var(--mg-radius-lg); background: var(--mg-surface); }
.mg-accordion + .mg-accordion { margin-top: var(--mg-space-2); }
.mg-accordion__summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--mg-space-3);
  padding: var(--mg-space-4) var(--mg-space-5); cursor: pointer; list-style: none;
  font-weight: var(--mg-weight-semibold); color: var(--mg-text); border-radius: var(--mg-radius-lg);
}
.mg-accordion__summary::-webkit-details-marker { display: none; }
.mg-accordion__summary::after { content: "\25BE"; color: var(--mg-text-muted); transition: transform var(--mg-duration-fast); }
.mg-accordion[open] > .mg-accordion__summary::after { transform: rotate(180deg); }
.mg-accordion__body { padding: 0 var(--mg-space-5) var(--mg-space-5); color: var(--mg-text-2); }

/* ==========================================================================
   Progresso e passos (onboarding)
   ========================================================================== */
.mg-progress { height: 8px; border-radius: var(--mg-radius-full); background: var(--mg-surface-3); overflow: hidden; }
.mg-progress__bar { height: 100%; width: var(--mg-progress, 0%); background: var(--mg-action); border-radius: inherit; transition: width var(--mg-duration-slow) var(--mg-ease-out); }

.mg-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--mg-space-3); }
.mg-step { display: flex; align-items: center; gap: var(--mg-space-3); color: var(--mg-text-2); }
.mg-step__marker {
  display: inline-grid; place-items: center; flex: none; width: 24px; height: 24px; border-radius: 50%;
  border: 2px solid var(--mg-control-border); background: var(--mg-surface);
  font-size: 12px; font-weight: var(--mg-weight-bold); color: var(--mg-text-muted);
}
.mg-step[data-state="done"] .mg-step__marker { background: var(--mg-action); border-color: var(--mg-action); color: var(--mg-on-action); }
.mg-step[data-state="current"] .mg-step__marker { border-color: var(--mg-action); color: var(--mg-action-text); }
.mg-step[data-state="current"] { color: var(--mg-text); font-weight: var(--mg-weight-semibold); }
.mg-step[data-state="done"] .mg-step__label { color: var(--mg-text-muted); }

/* ==========================================================================
   Upload — <label class="mg-dropzone" data-mg-upload><input type="file" class="mg-sr-only">
   ========================================================================== */
.mg-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--mg-space-1);
  padding: var(--mg-space-6); border: 2px dashed var(--mg-control-border); border-radius: var(--mg-radius-lg);
  background: var(--mg-surface-2); color: var(--mg-text-2); text-align: center; cursor: pointer;
  transition: border-color var(--mg-duration-fast), background-color var(--mg-duration-fast);
}
.mg-dropzone:hover, .mg-dropzone.is-dragover { border-color: var(--mg-action); background: var(--mg-action-subtle); }
.mg-dropzone__title { font-weight: var(--mg-weight-semibold); color: var(--mg-text); }
.mg-dropzone__hint { font-size: var(--mg-text-xs); color: var(--mg-text-muted); }
.mg-dropzone__files { list-style: none; margin: var(--mg-space-2) 0 0; padding: 0; font-size: var(--mg-text-sm); color: var(--mg-text); }

/* ==========================================================================
   Modal — UMA casca. Abrir/fechar só por MG.modal (mg.js).
   <div class="mg-modal" id="x" hidden> <div class="mg-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="x-title" tabindex="-1">…
   ========================================================================== */
.mg-modal {
  position: fixed; inset: 0; z-index: var(--mg-z-modal);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 6vh var(--mg-space-4) var(--mg-space-4);
  background: var(--mg-overlay);
  overflow-y: auto;
}
/* Quem rola é o CORPO, não a página inteira. Sem `max-height`, um formulário longo —
   cadastro de paciente, que é o modal mais usado do produto — empurrava o rodapé com
   "Salvar" para baixo da dobra, e o usuário tinha que rolar o fundo escuro inteiro até
   o fim para achar o botão. O cabeçalho sumia junto.
   O painel já resolvia isso desde sempre (components.css:159-170); adotar o modal do
   design system sem isto seria REGRESSÃO, não melhoria (revisão independente, 12/09). */
.mg-modal__dialog {
  width: 100%; max-width: 520px;
  max-height: 88vh;
  display: flex; flex-direction: column;
  background: var(--mg-surface);
  border-radius: var(--mg-radius-xl);
  box-shadow: var(--mg-shadow-lg);
  animation: mg-modal-in var(--mg-duration-base) var(--mg-ease-out);
}
.mg-modal--sm .mg-modal__dialog { max-width: 400px; }
.mg-modal--lg .mg-modal__dialog { max-width: 760px; }
/* O painel tem um tamanho a mais (900px, `.modal-xl`), usado em tela com tabela dentro
   do modal. Sem ele, migrar essas telas obrigaria a escrever CSS na página — o que o
   princípio 6 do DESIGN-SYSTEM.md proíbe. */
.mg-modal--xl .mg-modal__dialog { max-width: 900px; }
.mg-modal__header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--mg-space-3);
  padding: var(--mg-space-5) var(--mg-space-6) 0;
  flex-shrink: 0;                      /* fica visível enquanto o corpo rola */
}
.mg-modal__title { font-family: var(--mg-font-ui); line-height: var(--mg-leading-tight); margin: 0; font-size: var(--mg-text-xl); font-weight: var(--mg-weight-bold); color: var(--mg-text); }
.mg-modal__close {
  appearance: none; border: none; background: none; cursor: pointer;
  width: 32px; height: 32px; padding: 0; border-radius: var(--mg-radius-md);
  color: var(--mg-text-muted); font-size: 20px; line-height: 1;
}
.mg-modal__close:hover { background: var(--mg-surface-2); color: var(--mg-text); }
.mg-modal__body {
  padding: var(--mg-space-4) var(--mg-space-6);
  color: var(--mg-text-2);
  overflow-y: auto;                    /* é AQUI que a rolagem acontece */
  flex: 1 1 auto;
  min-height: 0;                       /* sem isto, o flex recusa encolher e o corpo estoura */
  overscroll-behavior: contain;        /* chegar ao fim não rola a página atrás */
}
.mg-modal__footer {
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--mg-space-2);
  padding: var(--mg-space-4) var(--mg-space-6) var(--mg-space-5);
  flex-shrink: 0;                      /* o botão de salvar nunca sai da tela */
  border-top: 1px solid var(--mg-border);
  background: var(--mg-surface-2);
  border-radius: 0 0 var(--mg-radius-xl) var(--mg-radius-xl);
}
body.mg-modal-open { overflow: hidden; }

/* ==========================================================================
   Aviso (toast) — criado só por MG.toast(). Tipo = cor + ícone + texto para leitor.
   ========================================================================== */
.mg-toast-region {
  position: fixed; right: var(--mg-space-4); bottom: var(--mg-space-4); z-index: var(--mg-z-toast);
  display: flex; flex-direction: column; gap: var(--mg-space-2);
  max-width: min(420px, calc(100vw - 2 * var(--mg-space-4)));
}
.mg-toast {
  display: flex; align-items: flex-start; gap: var(--mg-space-3);
  padding: var(--mg-space-3) var(--mg-space-3) var(--mg-space-3) var(--mg-space-4);
  background: var(--mg-surface); color: var(--mg-text);
  border: 1px solid var(--mg-border); border-left-width: 4px;
  border-radius: var(--mg-radius-md); box-shadow: var(--mg-shadow-lg);
  animation: mg-toast-in var(--mg-duration-base) var(--mg-ease-out);
}
.mg-toast__icon {
  display: inline-grid; place-items: center; flex: none; width: 20px; height: 20px; border-radius: 50%;
  font-size: 12px; font-weight: var(--mg-weight-bold); color: var(--mg-on-strong); margin-top: 1px;
}
.mg-toast__message { flex: 1; padding-top: 1px; }
.mg-toast__close {
  appearance: none; border: none; background: none; cursor: pointer; flex: none;
  width: 28px; height: 28px; padding: 0; border-radius: var(--mg-radius-sm);
  color: var(--mg-text-muted); font-size: 18px; line-height: 1;
}
.mg-toast__close:hover { background: var(--mg-surface-2); color: var(--mg-text); }
.mg-toast--success { border-left-color: var(--mg-success); } .mg-toast--success .mg-toast__icon { background: var(--mg-success); }
.mg-toast--error   { border-left-color: var(--mg-danger); }  .mg-toast--error .mg-toast__icon   { background: var(--mg-danger); }
.mg-toast--warning { border-left-color: var(--mg-warning); } .mg-toast--warning .mg-toast__icon { background: var(--mg-warning); }
.mg-toast--info    { border-left-color: var(--mg-info); }    .mg-toast--info .mg-toast__icon    { background: var(--mg-info); }

/* ==========================================================================
   Estados de carga — carregando / vazio / erro são TRÊS coisas diferentes.
   Falha nunca é desenhada como vazio (REGRAS-APRENDIDAS R1).
   ========================================================================== */
.mg-skeleton {
  display: block; border-radius: var(--mg-radius-sm);
  background: linear-gradient(90deg, var(--mg-surface-3) 0%, var(--mg-surface-2) 50%, var(--mg-surface-3) 100%);
  background-size: 200% 100%;
  animation: mg-shimmer 1.4s ease-in-out infinite;
}
.mg-skeleton--text   { height: 12px; }
.mg-skeleton--title  { height: 20px; width: 40%; }
.mg-skeleton--block  { height: 80px; }
.mg-skeleton--circle { width: 40px; height: 40px; border-radius: 50%; }
.mg-skeleton-stack   { display: flex; flex-direction: column; gap: var(--mg-space-3); padding: var(--mg-space-4); }

.mg-spinner {
  display: inline-block; width: 20px; height: 20px;
  border: 2px solid var(--mg-action-border); border-top-color: var(--mg-action);
  border-radius: 50%; animation: mg-spin .8s linear infinite;
}

.mg-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--mg-space-2); padding: var(--mg-space-10) var(--mg-space-6);
}
.mg-state__icon {
  display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%;
  background: var(--mg-surface-3); color: var(--mg-text-muted); font-size: 22px;
}
.mg-state__title { font-family: var(--mg-font-ui); line-height: var(--mg-leading-tight); margin: var(--mg-space-2) 0 0; font-size: var(--mg-text-md); font-weight: var(--mg-weight-semibold); color: var(--mg-text); }
.mg-state__text  { line-height: var(--mg-leading-normal); margin: 0; max-width: 42ch; color: var(--mg-text-muted); }
.mg-state__action { margin-top: var(--mg-space-3); }
.mg-state--error .mg-state__icon { background: var(--mg-danger-subtle); color: var(--mg-danger-text); }

/* ---- Animações ----------------------------------------------------------- */
@keyframes mg-spin { to { transform: rotate(360deg); } }
@keyframes mg-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@keyframes mg-modal-in { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes mg-toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .mg-skeleton, .mg-spinner, .mg-btn[aria-busy="true"]::after { animation-duration: 0s; animation-iteration-count: 1; }
  .mg-modal__dialog, .mg-toast { animation: none; }
  .mg-progress__bar, .mg-switch, .mg-switch::after { transition: none; }
}
