    /* ── reset ─────────────────────────────────────────────────────────────── */
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    /* ── design tokens ─────────────────────────────────────────────────────── */
    :root {
      /* escala de espaçamento (base 4 px) */
      --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
      --s6: 24px; --s8: 32px;

      /* escala tipográfica */
      --text-xs:   .75rem;    /* 12 px */
      --text-sm:   .875rem;   /* 14 px */
      --text-base: 1rem;      /* 16 px */
      --text-lg:   1.125rem;  /* 18 px */
      --text-xl:   1.25rem;   /* 20 px */
      --text-2xl:  1.5rem;    /* 24 px */

      /* raios */
      --r-sm:   6px;
      --r:      10px;
      --r-lg:   14px;
      --r-full: 9999px;

      /* sombras */
      --shadow-sm: 0 1px 4px rgba(0,0,0,.5);
      --shadow:    0 4px 16px rgba(0,0,0,.5);
      --shadow-lg: 0 8px 32px rgba(0,0,0,.6);

      /* paleta — tema escuro ardósia / acento índigo */
      --bg:           #0f172a;   /* slate-900 */
      --surface:      #1e293b;   /* slate-800 */
      --surface-2:    #263347;   /* slate-800→700 */
      --border:       #334155;   /* slate-700 */
      --text:         #f1f5f9;   /* slate-100 */
      --text-muted:   #94a3b8;   /* slate-400 */
      --text-subtle:  #64748b;   /* slate-500 */
      --accent:       #6366f1;   /* indigo-500 */
      --accent-hover: #4f46e5;   /* indigo-600 */
      --accent-light: #818cf8;   /* indigo-400 */
      --accent-bg:    #1e1b4b;   /* indigo-950 */
      --danger:       #ef4444;   /* red-500 */
      --danger-bg:    #450a0a;
      --danger-text:  #fca5a5;
      --success:      #22c55e;   /* green-500 */
      --success-bg:   #052e16;
      --success-text: #86efac;
      --warn-bg:      #1a1505;
      --warn-border:  #854d0e;
      --warn-text:    #fde68a;
    }

    /* ── base ──────────────────────────────────────────────────────────────── */
    body {
      font-family: system-ui, -apple-system, sans-serif;
      background: var(--bg);
      color: var(--text);
      min-height: 100vh;
      font-size: var(--text-base);
      line-height: 1.5;
      -webkit-font-smoothing: antialiased;
    }
    #app { max-width: 480px; margin: 0 auto; padding: var(--s6); }

    /* ── layout ─────────────────────────────────────────────────────────────── */
    .page { display: none; flex-direction: column; gap: var(--s4); }
    .page.active { display: flex; }
    /* Boot anti-flash: antes de o app.js (módulo, deferido) assumir, já mostra a página certa
       conforme a sessão salva — sem piscar o login. O app.js remove .booting ao assumir o controle. */
    html.booting.auth-in #page-login     { display: none; }
    html.booting.auth-in #page-dashboard { display: flex; }

    /* ── card ───────────────────────────────────────────────────────────────── */
    .card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--r-lg);
      padding: var(--s6);
      box-shadow: var(--shadow-sm);
    }

    /* ── tipografia ──────────────────────────────────────────────────────────── */
    h1 {
      font-size: var(--text-2xl);
      font-weight: 700;
      color: var(--text);
      letter-spacing: -.025em;
    }
    h2 {
      font-size: var(--text-lg);
      font-weight: 600;
      color: var(--text);
      margin-bottom: var(--s2);
    }
    p  { color: var(--text-muted); font-size: var(--text-sm); line-height: 1.6; }
    small { color: var(--text-muted); font-size: var(--text-xs); }

    /* ── campos de formulário ────────────────────────────────────────────────── */
    .field { display: flex; flex-direction: column; gap: var(--s1); }
    label {
      display: block;
      font-size: var(--text-sm);
      font-weight: 500;
      color: var(--text-muted);
    }
    input, select, textarea {
      width: 100%;
      background: var(--bg);
      border: 1px solid var(--border);
      border-radius: var(--r-sm);
      color: var(--text);
      padding: .625rem .875rem;
      font-size: var(--text-sm);
      font-family: inherit;
      outline: none;
      transition: border-color .15s, box-shadow .15s;
    }
    input::placeholder, textarea::placeholder { color: var(--text-subtle); }
    input:focus, select:focus, textarea:focus {
      border-color: var(--accent);
      box-shadow: 0 0 0 3px rgba(99,102,241,.2);
    }
    textarea { resize: vertical; min-height: 80px; }

    /* ── botões ─────────────────────────────────────────────────────────────── */
    .btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: var(--s2);
      padding: .625rem 1.25rem;
      border-radius: var(--r-sm);
      font-size: var(--text-sm);
      font-weight: 600;
      font-family: inherit;
      cursor: pointer;
      border: none;
      transition: background .15s, opacity .15s, box-shadow .15s, border-color .15s, color .15s;
      white-space: nowrap;
      user-select: none;
    }
    .btn:disabled { opacity: .4; cursor: not-allowed; pointer-events: none; }
    .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

    .btn-primary  { background: var(--accent); color: #fff; }
    .btn-primary:not(:disabled):hover  { background: var(--accent-hover); }
    .btn-primary:not(:disabled):active { opacity: .9; }

    .btn-danger   { background: var(--danger); color: #fff; }
    .btn-danger:not(:disabled):hover   { opacity: .85; }

    .btn-ghost {
      background: transparent;
      border: 1px solid var(--border);
      color: var(--text-muted);
    }
    .btn-ghost:not(:disabled):hover {
      border-color: var(--accent-light);
      color: var(--text);
      background: rgba(99,102,241,.06);
    }

    /* ── alertas ─────────────────────────────────────────────────────────────── */
    .alert {
      padding: .75rem var(--s4);
      border-radius: var(--r-sm);
      font-size: var(--text-sm);
      line-height: 1.5;
    }
    .alert-error { background: var(--danger-bg); border: 1px solid var(--danger); color: var(--danger-text); }
    .alert-ok    { background: var(--success-bg); border: 1px solid var(--success); color: var(--success-text); }

    /* ── lista de itens ─────────────────────────────────────────────────────── */
    .list-item {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--r);
      padding: .875rem var(--s4);
      cursor: pointer;
      transition: border-color .15s, background .15s, box-shadow .15s;
    }
    .list-item:hover {
      border-color: var(--accent-light);
      background: var(--surface-2);
      box-shadow: var(--shadow-sm);
    }
    .list-item:active { opacity: .9; }
    .list-item h3 { font-size: var(--text-sm); font-weight: 600; color: var(--text); }

    /* ── item da lista do painel admin (nome + ações) ───────────────────────── */
    /* Base = CELULAR: os dados em cima, os botões numa linha própria embaixo,
       dividindo a largura. Com dois botões ("Redefinir senha" e "Excluir") não há
       espaço para eles ao lado do nome em 375px sem espremer os dois. */
    .adm-item-linha  { display: flex; flex-direction: column; gap: var(--s2); }
    .adm-item-dados  { min-width: 0; }
    .adm-item-dados h3 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .adm-item-acoes  { display: flex; gap: var(--s2); }
    .adm-item-acoes:empty { display: none; }
    .adm-item-acoes .btn { flex: 1; font-size: var(--text-xs); padding: .4rem .6rem; }

    /* ── badges ─────────────────────────────────────────────────────────────── */
    .badge {
      display: inline-flex;
      align-items: center;
      padding: .175rem .55rem;
      border-radius: var(--r-full);
      font-size: .6875rem;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: .04em;
      white-space: nowrap;
    }
    .badge-draft { background: #1e3a5f; color: #93c5fd; }
    .badge-done  { background: var(--success-bg); color: var(--success-text); }

    /* ── linhas de domínio ────────────────────────────────────────────────────── */
    .domain-row {
      display: flex;
      align-items: center;
      gap: var(--s2);
      padding: .625rem var(--s2);
      border-radius: var(--r-sm);
      transition: background .1s;
    }
    .domain-row:hover { background: var(--surface-2); }
    .domain-row + .domain-row { border-top: 1px solid var(--border); }
    .domain-label  { flex: 1; font-size: var(--text-sm); font-weight: 500; color: var(--text); }
    .domain-status { font-size: var(--text-xs); color: var(--text-subtle); min-width: 80px; text-align: right; }

    /* ── aviso de IA (disclaimer) ─────────────────────────────────────────────── */
    .disclaimer {
      background: var(--warn-bg);
      border: 1px solid var(--warn-border);
      border-radius: var(--r-sm);
      padding: .75rem var(--s4);
      font-size: var(--text-xs);
      color: var(--warn-text);
      line-height: 1.6;
    }

    /* ── abas de navegação ────────────────────────────────────────────────────── */
    nav { display: flex; gap: var(--s2); margin-bottom: var(--s2); }
    nav .btn { flex: 1; padding: .5rem var(--s2); font-size: var(--text-xs); }
    .nav-active {
      background: var(--accent-bg) !important;
      border-color: var(--accent) !important;
      color: var(--accent-light) !important;
    }

    /* ── histórico ────────────────────────────────────────────────────────────── */
    .hist-meta { font-size: var(--text-xs); color: var(--text-muted); margin-top: var(--s1); }
    .hist-pagination {
      display: flex;
      gap: var(--s2);
      justify-content: center;
      align-items: center;
      margin-top: var(--s2);
    }

    /* ── spinner de carregamento ──────────────────────────────────────────────── */
    @keyframes spin { to { transform: rotate(360deg); } }
    .spinner {
      display: inline-block;
      width: 17px; height: 17px;
      border: 2px solid rgba(255,255,255,.25);
      border-top-color: #fff;
      border-radius: 50%;
      animation: spin .65s linear infinite;
      vertical-align: middle;
      flex-shrink: 0;
    }
    .spinner-muted {
      border-color: var(--border);
      border-top-color: var(--accent-light);
    }

    /* ── estado vazio ─────────────────────────────────────────────────────────── */
    .empty-state {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--s3);
      padding: var(--s8) var(--s4);
      color: var(--text-subtle);
      text-align: center;
    }
    .empty-state svg { opacity: .35; }
    .empty-state strong { font-size: var(--text-sm); color: var(--text-muted); font-weight: 600; }
    .empty-state p { font-size: var(--text-xs); color: var(--text-subtle); max-width: 220px; }

    /* ── banner de instalação PWA ─────────────────────────────────────────────── */
    #install-banner {
      display: none;
      background: var(--surface);
      border: 1px solid var(--accent);
      border-radius: var(--r-sm);
      padding: .75rem var(--s4);
      font-size: var(--text-sm);
      align-items: center;
      gap: var(--s2);
    }
    #install-banner.visible { display: flex; }

    /* ── logomarca inline ─────────────────────────────────────────────────────── */
    .lucida-logo {
      display: flex;
      align-items: center;
      gap: .6rem;
    }
    .lucida-wordmark {
      font-size: var(--text-2xl);
      font-weight: 700;
      color: var(--text);
      letter-spacing: -.025em;
    }

    /* ── ficha educacional + coleta + bandeiras (companion do curso) ──────────── */
    .domain-head { display: flex; align-items: center; gap: var(--s2); width: 100%; }
    /* cores do seletor de status: verde (sem), lilás (com), azul (não avaliado) */
    .dom-select { font-weight: 600; }
    .dom-select.st-sem { background: #0e2a1f; color: #86efac; border-color: #1d4d36; }
    .dom-select.st-com { background: #2a2440; color: #c4b5fd; border-color: #4c3f7a; }
    .dom-select.st-nao { background: #0c2a3a; color: #7dd3fc; border-color: #1e4a63; }
    .dom-select option { background: var(--surface); color: var(--text); }

    .ficha { margin: .35rem 0 .1rem; border-top: 1px dashed var(--border); }
    .ficha > summary {
      list-style: none; cursor: pointer; font-size: var(--text-xs);
      color: var(--accent-light); padding: .4rem 0; user-select: none;
    }
    .ficha > summary::-webkit-details-marker { display: none; }
    .ficha > summary:hover { color: var(--text); }
    .ficha[open] > summary { color: var(--text); font-weight: 600; }
    .ficha-body {
      font-size: var(--text-xs); color: var(--text-muted); line-height: 1.6;
      padding: .1rem 0 .55rem; display: flex; flex-direction: column; gap: .55rem;
    }
    .ficha-body h5 {
      font-size: var(--text-xs); color: var(--text); text-transform: uppercase;
      letter-spacing: .04em; margin-bottom: .2rem;
    }
    .ficha-alt { display: flex; flex-direction: column; gap: .25rem; }
    .ficha-alt .termo { color: var(--text); font-weight: 600; }
    .ficha-distincao { background: var(--surface-2); border-radius: var(--r-sm); padding: .45rem .65rem; }
    .ficha-distincao .vs { color: var(--accent-light); font-weight: 700; }
    .aula-link {
      display: inline-flex; align-items: center; gap: .3rem; align-self: flex-start;
      font-size: var(--text-xs); font-weight: 600; color: var(--accent-light);
      text-decoration: none; border: 1px solid var(--border); border-radius: var(--r-sm); padding: .35rem .65rem;
    }
    .aula-link:hover { border-color: var(--accent-light); background: rgba(99,102,241,.08); color: var(--text); }

    .bandeiras-box:not(:empty) { display: flex; flex-direction: column; gap: var(--s2); margin: var(--s1) 0; }
    .bandeira { border-radius: var(--r-sm); padding: .6rem var(--s3); font-size: var(--text-xs); line-height: 1.55; border: 1px solid; }
    .bandeira-alta       { background: var(--warn-bg);   border-color: var(--warn-border); color: var(--warn-text); }
    .bandeira-urgencia   { background: #2a1505;          border-color: #b45309;            color: #fdba74; }
    .bandeira-emergencia { background: var(--danger-bg); border-color: var(--danger);      color: var(--danger-text); }
    .bandeira .b-nivel { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; margin-right: .35rem; }
    .bandeira .b-acao  { display: block; margin-top: .25rem; opacity: .85; }
    .psicoedu { font-size: var(--text-xs); color: var(--text-subtle); line-height: 1.6; font-style: italic; padding: .2rem var(--s2); }

/* ══════════════════════════════════════════════════════════════════════════════
   LÚCIDA · CAMADA DESKTOP
   Colar no FIM de public/app.css, ANTES do bloco @media print (hoje na linha 351).

   ─── A TRAVA ────────────────────────────────────────────────────────────────
   Toda regra daqui para baixo vive dentro de
       @media screen and (min-width: 1024px) and (min-height: 500px)
   Três cadeados independentes, e cada um sozinho já barra telefone:

   1. `screen` — sem isso, a media query TAMBÉM casaria na impressão, porque em
      print a feature `width` é a caixa da PÁGINA, não a janela: A4 deitado
      (~1123px) e Carta deitado (~1056px) passariam de 1024 e o Ctrl+P sairia
      com layout de grade. Com `screen`, este bloco e o @media print são
      mutuamente exclusivos.
   2. `min-width: 1024px` — o maior telefone em paisagem hoje é o iPhone Pro Max
      com 956px CSS (Galaxy S Ultra: 915). Folga de 68px. "Solicitar site para
      computador" no Chrome/Safari do celular FIXA o viewport em ~980px — também
      abaixo do corte. E o PWA instalado usa o mesmo viewport do navegador
      (standalone tira a barra de endereço: muda a ALTURA, não a largura).
   3. `min-height: 500px` — telefone deitado tem 390-440px de altura CSS.
      Notebook 1366x768 com barra do Windows e cromo do Chrome fica em ~590px.
      Redundância barata: telefone deitado é barrado duas vezes.

   No Android há ainda uma quarta trava, física: manifest.webmanifest declara
   "orientation": "portrait-primary" — o PWA instalado não gira.

   ─── SERVICE WORKER: NÃO BUMPAR o CACHE ─────────────────────────────────────
   sw.js é NETWORK-FIRST e a lista ASSETS não inclui /app.css. O CSS novo chega
   no primeiro carregamento online, sem bump. Subir 'lucida-v18' para v19 seria
   PIOR: o activate apaga todo cache de nome diferente, jogando fora o app.css e
   o /sumula que hoje estão lá por cache oportunista — o offline degrada e não
   se ganha nada. Deixe em v18.

   ─── ESCOPO POR ARQUIVO ─────────────────────────────────────────────────────
   Os três HTML compartilham #app, #page-login, #rec-status, #btn-exportar e
   #btn-finalizar. Por isso cada tela é ancorada num id exclusivo seu:
       #app:has(#page-dashboard)   → só index.html
       #app:has(#page-revisao)     → só sumula.html
       #app:has(#page-adm-painel)  → só admin.html
   Sem :has() no navegador, essas regras caem e sobra a fundação (container
   largo, texto legível, coluna única) — o layout de hoje esticado, nunca quebrado.

   ─── .page / .page.active É SAGRADO ─────────────────────────────────────────
   Só duas regras aqui trocam `display` de uma página, e ambas exigem `.active`.
   Nenhuma toca `#page-dashboard`, então a regra anti-flash de boot
   (html.booting.auth-in #page-dashboard, app.css:70) continua valendo intacta.
   ══════════════════════════════════════════════════════════════════════════════ */

@media screen and (min-width: 1024px) and (min-height: 500px) {

  /* ══════════════════════════════════════════════════════════════════════════
     0 · FUNDAÇÃO — vale para as três telas
     ══════════════════════════════════════════════════════════════════════════ */

  :root {
    /* Um px CSS no monitor é ~1,5x maior que no celular, mas a distância de
       leitura quase dobra (33cm no colo, 60cm na mesa). O saldo é negativo: o
       mesmo 14px chega ao olho ~16% MENOR no desktop. Como todos os --text-*
       são rem, subir a raiz 6,25% sobe a escala inteira mantendo as proporções.
       Se ficar grande demais, troque por 103% — é só esta linha. */
    font-size: 106.25%;

    /* #64748b sobre --surface dá 3,07:1 — reprova o mínimo de 4,5:1. No celular
       passa batido (texto pequeno e perto); num monitor a 60cm é o primeiro
       texto que some. #8595ab dá 4,80:1 sobre --surface e 5,97:1 sobre --bg. */
    --text-subtle: #8595ab;

    /* tokens desta camada (só os que são realmente usados abaixo) */
    --d-gutter-x:  32px;   /* respiro lateral do #app                        */
    --d-gutter-y:  40px;   /* respiro superior                               */
    --d-gutter-b:  72px;   /* rodapé: o último botão precisa de chão          */
    --d-col-gap:   32px;   /* distância mínima entre colunas irmãs            */
    --d-row-gap:   20px;   /* gap vertical dentro de uma .page                */
    --d-card-pad:  28px;   /* padding interno de .card                        */
    --d-measure:      66ch;  /* prosa corrida                                 */
    --d-measure-wide: 78ch;  /* descrição de item, ficha educacional          */
    --d-measure-box:  92ch;  /* caixa colorida (alerta, aviso, bandeira)      */
    --d-field:        28rem; /* campo curto: e-mail, nome, registro           */
    --d-btn-max:      26rem; /* teto de botão de largura total                */
    --d-panel:        420px; /* coluna isolada: login                         */
  }

  body {
    line-height: 1.6;
    /* 1400px de #0f172a chapado lê como tela apagada. Em vez de clarear o fundo
       (o que mudaria a identidade), um halo do próprio --bg clareado no topo.
       Sem cor nova. Se der arrasto na rolagem em monitor 4K, apague as 3 linhas. */
    background-image: radial-gradient(1100px 520px at 50% -10%, #16203a 0%, rgba(15,23,42,0) 62%);
    background-repeat: no-repeat;
    background-attachment: fixed;
  }

  /* ── Largura da moldura ────────────────────────────────────────────────────
     A linha 62 (#app { max-width: 480px }) é o que verticaliza tudo. Aqui ela é
     solta — com teto por tela, porque as três têm necessidades diferentes.
     Empilhamento por especificidade: #app (1,0,0) < #app:has(#id) (2,0,0),
     então a ordem de colagem não importa. */
  #app {
    max-width: 1080px;
    padding: var(--d-gutter-y) var(--d-gutter-x) var(--d-gutter-b);
  }
  #app:has(#page-revisao)    { max-width: 1160px; }   /* súmula: entrada em 2 colunas + relato alto */
  #app:has(#page-adm-painel) { max-width: 1320px; }   /* admin: tabela densa + trilho de ações      */

  /* Só respiro. NÃO redeclara display — o par .page/.page.active fica intacto. */
  .page { gap: var(--d-row-gap); }

  /* ── Comprimento de linha ──────────────────────────────────────────────────
     A armadilha do "wide": alargar a moldura e transformar prosa em linhas de
     180 caracteres, o que é PIOR de ler que os 480px de hoje. A janela fica
     larga; a linha continua curta. O teto vai em `ch` e não em px porque `ch`
     acompanha o font-size do próprio bloco: a ficha educacional (12,75px) e um
     parágrafo (14,9px) recebem a mesma contagem de caracteres. */
  p                                   { max-width: var(--d-measure); }
  .psicoedu, .ficha-body              { max-width: var(--d-measure-wide); }
  .alert, .disclaimer, .bandeira      { max-width: var(--d-measure-box); }
  /* .empty-state p já tem max-width:220px (app.css:277, especificidade 0,2,1)
     e continua vencendo o `p` puro (0,0,1) — comportamento correto. */

  /* Prosa centralizada por style inline precisa continuar centralizada: sem
     isto o texto centraliza dentro de uma caixa de 66ch encostada à esquerda.
     Alvos reais: index.html:34 e :54, admin.html:19, :32 e :43. As variantes
     com espaço depois dos dois-pontos vão junto, de graça, para o seletor não
     morrer em silêncio se alguém reformatar o HTML. */
  p[style*="text-align:center"],
  p[style*="text-align: center"],
  [style*="text-align:center"] > p,
  [style*="text-align: center"] > p   { margin-inline: auto; }

  /* Um campo de e-mail de 1000px é a coisa mais esquisita de um desktop: a
     largura do campo insinua o tamanho do dado esperado. Nas colunas desenhadas
     abaixo (346-420px) esta regra já é inerte — ela existe pelas telas que
     ninguém desenhou. .dom-select tem width:auto inline e é imune na prática. */
  input, select { max-width: var(--d-field); }

  .card { padding: var(--d-card-pad); }

  /* ── Rede de segurança dos botões ──────────────────────────────────────────
     Onze botões têm style="width:100%" inline (index.html 178, 185, 226, 230,
     374, 377, 380, 383 · sumula.html 51, 112, 113). A 1080px isso vira uma
     barra índigo de ponta a ponta — o mesmo "fica esquisito" do pedido, só que
     na horizontal. Funciona SEM !important porque `max-width` é propriedade
     diferente de `width`: no cálculo do valor usado ela corta o width, inclusive
     o inline. As abas ficam de fora: nav .btn usa flex:1 (app.css:231) e um teto
     quebraria a divisão da linha. Onde as seções 1-3 posicionam o botão com
     width:auto, este teto simplesmente fica inerte. */
  #app .btn[style*="width:100%"],
  #app .btn[style*="width: 100%"] { max-width: var(--d-btn-max); }
  #app nav .btn                   { max-width: none; }

  ::selection { background: rgba(99,102,241,.32); color: var(--text); }


  /* ══════════════════════════════════════════════════════════════════════════
     1 · PAINEL  (index.html — âncora #page-dashboard)
     ══════════════════════════════════════════════════════════════════════════ */

  /* ── 1.1 · LOGIN — estreito de propósito ───────────────────────────────────
     Formulário de login esticado é o erro clássico de "deixar wide": o campo
     vira um risco de 1000px para um dado de 25 caracteres e a distância entre
     rótulo, campo e botão cresce sem nada ganhar (Gmail, Notion, Stripe: todos
     entre 360 e 450px). O respiro vem na vertical, não na horizontal.
     Só max-width/margin/padding — nenhuma troca de display. */
  #app:has(#page-dashboard) #page-login {
    max-width: var(--d-panel);
    margin-inline: auto;
    gap: var(--s6);
    /* clamp em vez de centragem vertical: escala com a janela e nunca corta o
       topo de forma irrecuperável, que é o risco de justify-content:center. */
    padding-block-start: clamp(var(--s6), 6vh, 72px);
  }
  #app:has(#page-dashboard) #page-login .card     { padding: var(--s8); }
  /* !important: vence gap:var(--s4) inline em index.html:39 */
  #app:has(#page-dashboard) #page-login .card > div { gap: var(--s6) !important; }
  #app:has(#page-dashboard) #page-login input {
    /* o padding-right:2.4rem que o app.js:986 injeta no campo de senha é
       longhand inline e continua vencendo só naquela borda — o olhinho não
       colide com o texto. Comportamento desejado. */
    padding: .75rem 1rem;
    font-size: var(--text-base);
  }
  #app:has(#page-dashboard) #btn-login { padding: .8rem 1.25rem; font-size: var(--text-base); }
  #app:has(#page-dashboard) #page-login .disclaimer { max-width: var(--d-panel); }

  /* ── 1.2 · PERFIL / ONBOARDING — formulário em duas colunas ────────────────
     Seis campos empilhados mais separador e caixa de erro é um onboarding que
     rola. Pareado na ordem natural do DOM: (Nome | Profissão), (Registro |
     Telefone), separador atravessando, (Senha | Repita), erro atravessando.
     Altura cai de ~7 para ~4 linhas — cabe sem rolar. */
  #app:has(#page-dashboard) #page-perfil { max-width: 780px; margin-inline: auto; }
  #app:has(#page-dashboard) #page-perfil > h2,
  #app:has(#page-dashboard) #perfil-onboarding-hint { max-width: 62ch; }
  #app:has(#page-dashboard) #page-perfil .card { padding: var(--s8); }

  /* !important em display E gap: o wrapper (index.html:76) tem
     style="display:flex; flex-direction:column; gap:var(--s4)" — inline vence
     folha externa, e sem o segundo !important o column-gap fica preso em 16px.
     O olhinho de senha do app.js NÃO quebra esta grade: o wrapper que ele cria
     nasce DENTRO do .field (inp.parentNode é o .field), então os filhos diretos
     desta grade continuam os mesmos oito. */
     REVISTO (dono, 2026-08-10): coluna única aqui também. O formulário fica em
     uma coluna, com os campos numa largura confortável (não esticados por
     1300px, o que seria pior que o celular). */
  #app:has(#page-dashboard) #page-perfil .card > div > .field { max-width: var(--d-field); }

  /* Barra de ações: botões com largura natural, à direita — onde o olho procura
     confirmação em formulário de desktop.
     !important no gap: vence gap:var(--s2) inline em index.html:110.
     !important no flex: vence flex:1 / flex:2 inline em index.html:111-112. */
  #app:has(#page-dashboard) #page-perfil > div:has(> #btn-perfil-salvar) {
    justify-content: flex-end;
    gap: var(--s3) !important;
  }
  #app:has(#page-dashboard) #btn-perfil-cancel,
  #app:has(#page-dashboard) #btn-perfil-salvar {
    flex: 0 0 auto !important;
    min-width: 168px;
    padding-block: .7rem;
  }

  /* ── 1.3 · DASHBOARD ───────────────────────────────────────────────────────
     NÃO gridamos #page-dashboard: a regra anti-flash de boot
     (html.booting.auth-in #page-dashboard { display:flex }, especificidade
     1,2,1) venceria .page.active e o painel piscaria no layout antigo até o
     app.js remover .booting. As grades vão nos containers INTERNOS — que é
     justamente onde o JS injeta filhos e onde o pai pode virar grade sem que o
     JS saiba de nada. */

  /* cabeçalho vira barra de aplicativo */
  #app:has(#page-dashboard) #page-dashboard > div:has(> .lucida-logo) {
    border-bottom: 1px solid var(--border);
    padding-bottom: var(--s4);
  }
  /* !important: vence height:42px inline em index.html:129 */
  #app:has(#page-dashboard) #page-dashboard > div:has(> .lucida-logo) img { height: 48px !important; }
  #app:has(#page-dashboard) #page-dashboard > div:has(> #dash-nome) { margin-top: calc(var(--s2) * -1); }
  /* !important: vence font-size:var(--text-sm) inline em index.html:141 */
  #app:has(#page-dashboard) #dash-nome { font-size: var(--text-base) !important; }

  /* Card "Como funciona": os quatro parágrafos viram grade 2x2 e o card encolhe
     de ~5 rolagens para uma tela — o ganho real para quem abre o Lúcida pela
     primeira vez. O max-width por parágrafo é o que impede o wide de piorar a
     leitura: sem ele seriam linhas de 130 caracteres.

     ⚠ O `display` AQUI é deliberadamente SEM !important. O card tem
     style="display:none" inline e o app.js:303 alterna com
     `orient.style.display = '' | 'none'`. String vazia REMOVE o inline e a
     grade assume; 'none' inline continua vencendo e esconde. Pôr !important
     aqui deixaria o card de boas-vindas visível PARA SEMPRE. */
     REVISTO (dono, 2026-08-10): prosa em duas colunas sofre do mesmo problema
     que ele apontou na revisão — não se sabe se a leitura desce ou vai para o
     lado. Volta a ser um bloco único; o ganho vem da largura de linha maior. */
  #app:has(#page-dashboard) #dash-orientacao { padding: var(--s8); }
  #app:has(#page-dashboard) #dash-orientacao > h3 { font-size: var(--text-xl); }
  #app:has(#page-dashboard) #dash-orientacao > p { max-width: 90ch; }

  /* Abas: sem isto, o `nav .btn { flex: 1 }` global produziria dois botões de
     ~500px para escrever "Rascunhos" e "Finalizados". Vence por especificidade
     (1,1,1 contra 0,1,1) — não precisa de !important.
     ALTURA FIXA (dono, 2026-08-10): as abas e o "+ Nova Súmula" tinham que ficar
     "na mesma linha". Eles NÃO são irmãos no HTML (o botão vive dentro de
     #tab-rascunhos), então a única forma sem tocar no JS é subir o botão com
     margem negativa. Travar a altura do nav é o que torna essa conta
     determinística em vez de chute. */
  #app:has(#page-dashboard) #page-dashboard nav {
    justify-content: flex-start;
    gap: var(--s3);
    margin-bottom: 0;
    height: 42px;
    align-items: stretch;
  }
  #app:has(#page-dashboard) #page-dashboard nav .btn {
    flex: 0 0 auto;
    min-width: 168px;
    font-size: var(--text-sm);
    padding: .55rem var(--s4);
  }

  /* Containers das abas. SEM !important pelo mesmo motivo do card de orientação:
     o app.js:250-251 alterna a aba com style.display = '' | 'none'. */
  #app:has(#page-dashboard) #tab-rascunhos,
  #app:has(#page-dashboard) #tab-finalizados { display: grid; gap: var(--s4); }

  /* "+ Nova Súmula" sobe para a linha das abas, encostado à direita.
     A margem negativa = altura do nav (42px, travada acima) + o gap da página.
     Se por algum motivo isso falhar, o botão apenas volta a ficar acima da lista
     — o comportamento de antes, nunca uma tela quebrada.
     !important: vence width:100% inline em index.html:178 e 185. */
  #app:has(#page-dashboard) .btn-nova {
    width: auto !important;
    max-width: none;
    justify-self: end;
    min-width: 200px;
    padding: .55rem var(--s6);
    margin-top: calc(-42px - var(--d-row-gap));
  }

  /* LISTAS EM COLUNA ÚNICA, LARGURA INTEIRA — decisão do dono (2026-08-10).
     Em grade de cartões o título do rascunho ficava preso a ~320px e truncava
     ("não consigo ler todo o título, sendo que ele poderia estar horizontal
     gigante porque eu tenho espaço"). Em linha inteira o título cabe.
     !important é seguro: varri o app.js e estas duas listas SÓ recebem innerHTML
     (linhas 220, 281, 288-298) — nunca style.display.
     !important vence display:flex / gap / margin-top inline em index.html:180 e 187. */
  #app:has(#page-dashboard) #rascunhos-list,
  #app:has(#page-dashboard) #finalizados-list {
    display: flex !important;
    flex-direction: column;
    gap: var(--s2) !important;
    margin-top: 0 !important;
  }
  /* o título do caso deixa de truncar: usa a linha inteira disponível */
  #app:has(#page-dashboard) #rascunhos-list .list-item h3,
  #app:has(#page-dashboard) #finalizados-list .list-item h3 {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    font-size: var(--text-base);
  }
  /* O app.js injeta três tipos de filho nestas listas: .list-item (cartão),
     .empty-state (vazio) e as âncoras de arquivados (app.js:288-298). Os dois
     últimos precisam atravessar, senão parecem cartão torto numa coluna.
     !important: vence margin-top:var(--s3) inline gerado em app.js:290. */
  #app:has(#page-dashboard) #rascunhos-list  > .empty-state,
  #app:has(#page-dashboard) #finalizados-list > .empty-state,
  #app:has(#page-dashboard) #finalizados-list > a { grid-column: 1 / -1; }
  #app:has(#page-dashboard) #finalizados-list > a { margin-top: 0 !important; }

  #app:has(#page-dashboard) #rascunhos-list  > .empty-state,
  #app:has(#page-dashboard) #finalizados-list > .empty-state {
    border: 1px dashed var(--border);
    border-radius: var(--r-lg);
    padding-block: var(--s8);
  }
  #app:has(#page-dashboard) #rascunhos-list  .list-item,
  #app:has(#page-dashboard) #finalizados-list .list-item { padding: var(--s4); }

  /* ── 1.4 · TELAS DORMENTES do index.html ───────────────────────────────────
     #page-gravar, #page-nova, #page-transcricao, #page-completude, #page-sumula
     e #page-resumo são o fluxo v1 duplicado: hoje inalcançáveis, porque
     .btn-nova navega para /sumula (app.js:377-379) e o clique no cartão vai
     para /sumula?id= (app.js:309). Recebem só um teto de largura — investir
     desenho seria trabalho para código morto, e deixar sem teto seria deixar
     uma bomba armada caso alguém reative o fluxo. O teto também segura as
     barras de dois botões dessas telas, que ninguém desenhou. */
  #app:has(#page-dashboard) #page-gravar,
  #app:has(#page-dashboard) #page-nova,
  #app:has(#page-dashboard) #page-transcricao,
  #app:has(#page-dashboard) #page-completude { max-width: 760px; margin-inline: auto; }
  #app:has(#page-dashboard) #page-sumula,
  #app:has(#page-dashboard) #page-resumo     { max-width: 920px; margin-inline: auto; }
  /* !important: vence min-height:260px inline em index.html:267 */
  #app:has(#page-dashboard) #transcricao-texto { min-height: 380px !important; }
  /* #rec-status também existe em sumula.html (como <small>): daí o prefixo de página.
     !important: vence padding:var(--s6) inline em index.html:211 */
  #app:has(#page-dashboard) #page-gravar #rec-status { padding: var(--s8) !important; }


  /* ══════════════════════════════════════════════════════════════════════════
     2 · SÚMULA  (sumula.html — âncora #page-revisao)
     ══════════════════════════════════════════════════════════════════════════ */

  /* cabeçalho (logo + "← Painel") vira faixa do app, com régua */
  #app:has(#page-revisao) > div:not(.page) {
    padding-bottom: var(--s4);
    border-bottom: 1px solid var(--border);
  }

  /* ── 2.1 · ENTRADA — controles à esquerda, trabalho à direita ──────────────
     Hoje o profissional vê empilhados: identificação, parágrafo de instrução,
     bloco de áudio (~165px) e só então o textarea. Num monitor deitado ele rola
     para baixo para escrever e para cima para gravar — o campo de trabalho
     nasce debaixo da dobra.

     ⚠ O seletor exige `.page.active`. Escrito como `#page-entrada` sozinho, a
     regra ressuscitaria as 5 etapas de uma vez. Com `.active`, a regra
     simplesmente não casa nas páginas inativas e `.page { display:none }`
     (app.css:65) continua sendo quem manda. O pior resultado possível se algo
     falhar é a página voltar a display:flex em coluna — o layout de hoje. */
  #app:has(#page-revisao) #page-entrada.page.active {
    display: grid;
    grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
    grid-template-areas:
      "titulo  titulo"
      "ident   relato"
      "instr   relato"
      "audio   relato"
      ".       erro"
      ".       acao";
    align-items: start;
    column-gap: var(--d-col-gap);
    row-gap: var(--s4);
  }
  #app:has(#page-revisao) #page-entrada.page.active > h2                       { grid-area: titulo; }
  #app:has(#page-revisao) #page-entrada.page.active > .field:has(#titulo-caso) { grid-area: ident;  }
  #app:has(#page-revisao) #page-entrada.page.active > p                        { grid-area: instr;  }
  #app:has(#page-revisao) #page-entrada.page.active > #audio-bloco             { grid-area: audio;  }
  #app:has(#page-revisao) #page-entrada.page.active > #entrada-error           { grid-area: erro;   }

  /* O relato ocupa a altura da tela em vez de forçar rolagem. clamp: piso
     260px, alvo = viewport menos o cromo do app, teto 720px. Em notebook
     1366x768 (viewport útil ~648px) dá ~358px e a tela fecha sem rolar; em
     1080p bate o teto. Para afinar numa máquina específica, mexa só no 290px. */
  #app:has(#page-revisao) #page-entrada.page.active > .field:has(#exame) {
    grid-area: relato;
    align-self: stretch;
    min-height: clamp(260px, calc(100vh - 290px), 720px);
  }
  #app:has(#page-revisao) #exame {
    flex: 1 1 auto;               /* .field já é flex-column: o textarea preenche */
    height: auto;
    max-width: none;              /* superfície de trabalho: aqui largura é boa   */
    font-size: var(--text-base);  /* 14px é pouco para escrever/reler um relato   */
  }

  /* CTA com largura de conteúdo, ancorada na borda direita do relato — onde o
     cursor acaba de sair. Sem o grid-area, o botão cairia em posicionamento
     automático e aterrissaria na coluna estreita da esquerda, ao lado da
     mensagem de erro.
     !important: vence width:100% inline em sumula.html:51 */
  #app:has(#page-revisao) #page-entrada.page.active > #btn-gerar {
    grid-area: acao;
    width: auto !important;
    justify-self: end;
    padding: .75rem 2rem;
  }

  /* Os 3 botões de áudio numa coluna de ~350px: com flex:1 inline eles se
     espremeriam abaixo do próprio texto ("⤴ Transcrever" tem white-space:nowrap
     e estouraria). flex:1 1 auto devolve largura de conteúdo e deixa quebrar
     linha (o wrapper já tem flex-wrap:wrap inline).
     !important: vence flex:1 inline em sumula.html:40-42 */
  #app:has(#page-revisao) #audio-bloco .btn { flex: 1 1 auto !important; }

  /* ── 2.2 · REVISÃO — os 17 campos em duas colunas ──────────────────────────
     É aqui que o desktop paga sozinho. Hoje são 17 .domain-row empilhados: a
     página tem ~2.400px e o profissional revisa o caso por um visor de 600px,
     sem nunca ver o conjunto. Em duas colunas ele vê ~9 de cada lado e enxerga
     o PADRÃO do caso — que é o raciocínio clínico que o produto existe para
     apoiar. A grade é do PAI; o JS continua injetando o mesmo innerHTML e
     nenhuma linha de sumula.js muda.

     GRID e não `columns: 2`: multi-coluna FRAGMENTA o .domain-row entre colunas
     e rebalanceia a lista inteira quando alguém abre um <details class="ficha">,
     fazendo os itens saltarem debaixo do cursor. Grid trata cada linha como
     bloco indivisível e não rebalanceia nada. */

  /* !important: vence padding:var(--s2) var(--s3) inline em sumula.html:63 */
  #app:has(#page-revisao) #page-revisao > .card { padding: var(--s4) var(--s6) !important; }

  /* COLUNA ÚNICA, LARGA — decisão do dono (2026-08-10), depois de ver em duas
     colunas: "não quero um monte de coluna; a gente não sabe se tem que ir de
     cima para baixo ou da direita para a esquerda". A leitura de uma súmula é
     sequencial (item 1 ao 17); partir em colunas obriga o olho a decidir a cada
     linha. O ganho do desktop vem da LARGURA: cada descrição que no celular
     ocupava 5-6 linhas agora cabe em 1-2. Mantém-se o separador original
     (.domain-row + .domain-row { border-top }) do CSS base — em coluna única
     ele funciona como sempre funcionou, sem nenhuma regra extra. */
  #app:has(#page-revisao) #revisao-container > .domain-row,
  #app:has(#page-revisao) #tecnica-lista   > .domain-row {
    padding: var(--s3) var(--s2);
  }
  /* O texto de cada item usa a largura inteira: é o ponto do layout largo.
     Vence o max-width de 66ch do `p` da fundação (especificidade 3,1,0 x 0,0,1). */
  #app:has(#page-revisao) #revisao-container .domain-texto { max-width: none; }

  /* ── 2.3 · ALTERAÇÕES ENCONTRADAS ──────────────────────────────────────────
     Lista corrida, em coluna única (pedido do dono): são os achados do caso,
     lidos de cima para baixo. Cada achado ganha a largura inteira em vez de
     quebrar em várias linhas curtas. */
  #app:has(#page-revisao) #alteracoes-lista > li { max-width: none; }

  /* ── 2.4 · SÚMULA TÉCNICA ──────────────────────────────────────────────────
     Também coluna única. Cada linha é "13. Pensamento .......... taquipsiquismo":
     na largura inteira, o rótulo fica à esquerda e o termo à direita, alinhados
     numa régua — mais legível que três colunas de itens curtos.
     !important: vence padding:var(--s2) var(--s3) inline em sumula.html:92 */
  #app:has(#page-revisao) #page-tecnica > .card { padding: var(--s4) var(--s6) !important; }
  /* o termo técnico ganha espaço para não truncar em caso longo */
  #app:has(#page-revisao) #tecnica-lista .domain-status { min-width: 22ch; }

  /* ── 2.5 · HIPÓTESES + DIAGNÓSTICO lado a lado ─────────────────────────────
     Hoje o campo "Diagnóstico" (decisão exclusiva do profissional) fica ABAIXO
     do card de hipóteses. Em desktop isso significa escrever o diagnóstico com
     as hipóteses fora da tela — o contrário do que o desenho quer. Conserta um
     erro de fluxo, não de estética.
     Como não existe wrapper para os dois botões no HTML, a grade tem 3 trilhas
     e cada botão pega uma: Exportar alinhado à direita da sua, Finalizar à
     esquerda da seguinte — encostam formando um par sob o diagnóstico.
     De novo: `.page.active`, para não mexer no mostrar/esconder. */
     REVISTO (dono, 2026-08-10): SEM colunas. As hipóteses e o diagnóstico ficam
     empilhados, ocupando a largura inteira — o texto das hipóteses era o que mais
     sofria com coluna estreita ("que o texto não seja quebrado em tantas linhas").
     A página continua flex em coluna (herda de .page); só os dois botões saem da
     faixa de ponta a ponta e viram um par à direita. */
  #app:has(#page-revisao) #page-hipoteses.page.active > .card,
  #app:has(#page-revisao) #page-hipoteses.page.active > .field { max-width: none; }
  #app:has(#page-revisao) #hipoteses-conteudo,
  #app:has(#page-revisao) #hipoteses-conteudo p { max-width: none; }
  #app:has(#page-revisao) #diagnostico { min-height: 180px; max-width: none; font-size: var(--text-base); }

  /* Os botões deixam de ser faixas de ponta a ponta e ficam com largura natural,
     à direita — onde o olho termina a leitura da página.
     !important: vence width:100% inline em sumula.html:112-113 */
  #app:has(#page-revisao) #page-hipoteses.page.active > #btn-exportar,
  #app:has(#page-revisao) #page-hipoteses.page.active > #btn-finalizar {
    width: auto !important;
    align-self: flex-end;
    min-width: 15rem;
    padding: .75rem 1.5rem;
  }

  /* ── 2.6 · BARRAS DE NAVEGAÇÃO (voltar / continuar) ────────────────────────
     Hoje esticam por toda a largura (flex:1 / flex:2). Em 1160px viram duas
     faixas gigantes onde o "Voltar" fica com ~380px — alvo enorme para a ação
     secundária. Passam a ter largura de conteúdo, ancoradas à direita: ordem
     "← Voltar | Continuar →" no canto onde o olho termina a leitura.
     Os wrappers não têm classe; são identificados pelo botão que contêm — o
     cabeçalho de cada página (que também tem um [data-ir]) não casa.
     !important: vence flex:1 / flex:2 inline em sumula.html:65-66, 80-81, 94-95 */
  #app:has(#page-revisao) #page-revisao    > div:has(> #btn-confirmar),
  #app:has(#page-revisao) #page-alteracoes > div:has(> #btn-tecnica),
  #app:has(#page-revisao) #page-tecnica    > div:has(> #btn-hipoteses) {
    justify-content: flex-end;
  }
  #app:has(#page-revisao) #page-revisao    > div:has(> #btn-confirmar) > .btn,
  #app:has(#page-revisao) #page-alteracoes > div:has(> #btn-tecnica)   > .btn,
  #app:has(#page-revisao) #page-tecnica    > div:has(> #btn-hipoteses) > .btn {
    flex: 0 0 auto !important;
    padding: .75rem 1.5rem;
  }


  /* ══════════════════════════════════════════════════════════════════════════
     3 · ADMIN  (admin.html — âncora #page-adm-painel)
     ══════════════════════════════════════════════════════════════════════════ */

  /* ── 3.1 · Login e "definir senha" — estreitos e centrados ─────────────────
     Formulário de 2 campos não melhora ficando largo. O ganho no desktop é
     parar de ficar espremido no topo esquerdo de uma tela de 1080p.
     Sem troca de display: zero risco para o mostrar/esconder. */
  #app:has(#page-adm-painel) #page-admin-login,
  #app:has(#page-adm-painel) #page-adm-nova-senha {
    max-width: var(--d-panel);
    margin-inline: auto;
    padding-block-start: clamp(var(--s4), 5vh, 56px);
  }

  /* ── 3.2 · Painel: lista à esquerda, trilho de ações à direita ─────────────
     Hoje são três blocos empilhados: cadastrar, lista, trocar senha. No desktop
     isso significa rolar por cima do formulário de cadastro toda vez que se
     quer só olhar a lista — e a lista é o que se olha 90% das vezes. A grade
     separa por FREQUÊNCIA DE USO: lista na coluna principal, os dois
     formulários num trilho de 320-380px. "Cadastrar acesso" no topo do trilho
     porque é corriqueiro; "Trocar minha senha" embaixo porque é anual.
     De novo: `.page.active`. */
  #app:has(#page-adm-painel) #page-adm-painel.page.active {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(320px, 27vw, 380px);
    column-gap: var(--s6);
    row-gap: var(--s4);
    align-items: start;
  }
  /* Cabeçalho e "Conectado como…" atravessam.
     !important: vence margin-bottom:var(--s2) inline em admin.html:60 e
     margin-bottom:var(--s3) inline em admin.html:64 — o row-gap já separa. */
  #app:has(#page-adm-painel) #page-adm-painel > div:first-child {
    grid-column: 1 / -1; grid-row: 1; margin-bottom: 0 !important;
  }
  #app:has(#page-adm-painel) #page-adm-painel > div:first-child h2 { font-size: var(--text-xl); }
  #app:has(#page-adm-painel) #page-adm-painel > #adm-quem {
    grid-column: 1 / -1; grid-row: 2; margin-bottom: 0 !important;
  }
  /* Posições. Conferi os filhos diretos de #page-adm-painel: são exatamente 5
     (cabeçalho :60 · #adm-quem :64 · card Cadastrar :67 · card Usuários :87 ·
     card Trocar senha :97). Se alguém inserir um card novo no meio, as posições
     mudam e os cards trocam de coluna — nada quebra, mas embaralha. */
  #app:has(#page-adm-painel) #page-adm-painel > .card:nth-child(3) { grid-column: 2; grid-row: 3; }            /* Cadastrar acesso  */
  #app:has(#page-adm-painel) #page-adm-painel > .card:nth-child(4) { grid-column: 1; grid-row: 3 / span 2; }   /* Usuários          */
  #app:has(#page-adm-painel) #page-adm-painel > .card:nth-child(5) { grid-column: 2; grid-row: 4; }            /* Trocar minha senha */

  /* ── 3.3 · Lista de usuários: de cartões empilhados para tabela densa ──────
     Hoje cada conta é um cartão com borda, raio e respiro, nome numa linha e
     metadados na de baixo: ~78px por conta, ~2.800px para 36 contas. Vira linha
     de tabela (~41px), e a lista rola sozinha para o cabeçalho e o trilho de
     cadastro ficarem parados — comportamento canônico de painel administrativo,
     impossível no celular (por isso fica de fora).
     !important: vence gap:var(--s2) inline em admin.html:93 */
  #app:has(#page-adm-painel) #adm-lista {
    gap: 0 !important;
    border: 1px solid var(--border);
    border-radius: var(--r);
    overflow: auto;
    max-height: calc(100vh - 260px);   /* opinativo: apague as 3 linhas de */
    min-height: 200px;                 /* overflow/max-height/min-height e */
  }                                    /* a página volta a rolar inteira.  */
  #app:has(#page-adm-painel) #adm-lista .list-item {
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    padding: .45rem var(--s3);
  }
  #app:has(#page-adm-painel) #adm-lista .list-item:nth-child(even) { background: rgba(255,255,255,.022); }
  #app:has(#page-adm-painel) #adm-lista .list-item:last-child      { border-bottom: 0; }
  #app:has(#page-adm-painel) #adm-lista .list-item:hover {
    background: var(--surface-2); border-color: var(--border); box-shadow: none; transform: none;
  }
  /* lista vazia não herda a moldura de tabela (admin.js:130) */
  #app:has(#page-adm-painel) #adm-lista:has(> .empty-state) { border: 0; min-height: 0; }

  /* No computador a conta volta a ser UMA linha: dados à esquerda, ações à direita.
     No celular (fora desta media query) os botões ficam embaixo, lado a lado. */
  #app:has(#page-adm-painel) #adm-lista .adm-item-linha {
    flex-direction: row; align-items: center; gap: var(--s3);
  }
  #app:has(#page-adm-painel) #adm-lista .adm-item-dados { flex: 1 1 auto; }
  #app:has(#page-adm-painel) #adm-lista .adm-item-acoes { flex: 0 0 auto; }
  #app:has(#page-adm-painel) #adm-lista .adm-item-acoes .btn {
    flex: 0 0 auto;                    /* no celular é flex:1; aqui, largura natural */
    padding: .3rem .7rem;
  }

  /* Nome e metadados na MESMA linha: uma conta = uma linha. */
  #app:has(#page-adm-painel) #adm-lista .adm-item-dados {
    display: flex; align-items: baseline; gap: var(--s3);
  }
  #app:has(#page-adm-painel) #adm-lista .list-item h3 {
    flex: 0 1 auto; min-width: 7rem; max-width: 42%;   /* o ellipsis já vem inline no h3 gerado */
  }
  #app:has(#page-adm-painel) #adm-lista .list-item small {
    flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* ── 3.4 · Botão Excluir: presente, mas sem parede de vermelho ─────────────
     Com 36 contas, 36 botões vermelhos sólidos formam uma parede que puxa o
     olho para a ação mais perigosa da tela. Esconder até o hover seria pior
     (ação destrutiva escondida). Meio-termo: contorno em repouso, sólido só no
     hover do próprio botão. Continua visível, tabulável e com o confirm() do JS. */
  #app:has(#page-adm-painel) #adm-lista .btn-danger {
    background: transparent; color: var(--danger-text);
    border: 1px solid var(--danger); opacity: .7;
  }
  #app:has(#page-adm-painel) #adm-lista .btn-danger:focus-visible { opacity: 1; }
  #app:has(#page-adm-painel) #adm-lista .btn-danger:hover { background: var(--danger); color: #fff; opacity: 1; }
  /* Sem esta regra, a de cima (2 ids) venceria `.btn:disabled { opacity:.4 }`
     (app.css:141) e o botão deixaria de escurecer enquanto a exclusão roda
     (admin.js:133) — some o sinal de "processando". */
  #app:has(#page-adm-painel) #adm-lista .btn-danger:disabled { opacity: .4; background: transparent; }


  /* ══════════════════════════════════════════════════════════════════════════
     4 · FOCO DE TECLADO
     Hoje só .btn tem :focus-visible. Num desktop se navega por Tab.
     Limite honesto: <a> sem href não entra na ordem de tabulação, então os
     links "✎ Preencher item" e "↻ Atualizar hipóteses" continuam sem foco —
     resolver exige tabindex no HTML/JS. Fica registrado como dívida.
     ══════════════════════════════════════════════════════════════════════════ */
  #app a:focus-visible,
  #app summary:focus-visible,
  #app select:focus-visible,
  #app [role="button"]:focus-visible {
    outline: 2px solid var(--accent-light);
    outline-offset: 2px;
    border-radius: var(--r-sm);
  }
}


/* ══════════════════════════════════════════════════════════════════════════════
   5 · HOVER — só onde existe ponteiro fino
   `(hover:hover) and (pointer:fine)` aqui é seguro porque é ADITIVO: notebook
   com tela sensível ao toque que não casar perde só o hover, não o layout.
   (É por isso que essas features NÃO entram na trava principal: lá elas
   excluiriam esses mesmos notebooks do layout de desktop inteiro.)

   Os links "✎ Preencher item", "↻ Atualizar hipóteses" e "🗄 Ver arquivados"
   têm color inline (sumula.js:130, app.js:290 e :358), então `color:` no hover
   seria letra morta. `filter` e `text-decoration` passam por cima do inline sem
   !important.
   ══════════════════════════════════════════════════════════════════════════════ */
@media screen and (min-width: 1024px) and (min-height: 500px) and (hover: hover) and (pointer: fine) {

  /* o controle mais tocado do app não tinha nem cursor: pointer */
  #app .dom-select       { cursor: pointer; }
  #app .dom-select:hover { border-color: var(--accent-light); }

  /* elevação de cartão clicável — só nas listas do painel. NÃO nas linhas da
     tabela do admin, que não devem pular. */
  #app:has(#page-dashboard) #rascunhos-list  .list-item:hover,
  #app:has(#page-dashboard) #finalizados-list .list-item:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow);
  }
  /* `transform` não está na lista de transições de .list-item (app.css:179):
     sem redeclarar, a elevação pularia seca. */
  #app:has(#page-dashboard) #rascunhos-list  .list-item,
  #app:has(#page-dashboard) #finalizados-list .list-item {
    transition: border-color .15s, background .15s, box-shadow .15s, transform .15s;
  }

  /* <a> sem href: no celular funciona porque a pessoa toca no que lê; no
     desktop o cursor passa por cima e nada acontece — não dá para saber que é
     clicável. */
  #app .dom-edit-toggle:hover,
  #app #btn-hipoteses-atualizar:hover,
  #app #link-ver-arquivados:hover,
  #app #link-voltar-finalizados:hover { text-decoration: underline; filter: brightness(1.22); }
}

@media screen and (min-width: 1024px) and (min-height: 500px) and (prefers-reduced-motion: reduce) {
  #app .list-item:hover { transform: none; }
}


/* ══════════════════════════════════════════════════════════════════════════════
   6 · SEGUNDO DEGRAU — monitor grande (≥ 1440px)
   Só respiro e um pouco mais de largura. NENHUMA coluna nova: em 2026-08-10 o
   dono foi explícito de que multiplicar colunas piora a leitura ("a gente não
   sabe se tem que ir de cima para baixo ou da direita para a esquerda").
   Em tela grande o app fica MAIS LARGO, não mais fragmentado.
   ══════════════════════════════════════════════════════════════════════════════ */
@media screen and (min-width: 1440px) and (min-height: 500px) {

  :root { --d-gutter-x: 48px; --d-gutter-y: 48px; --d-col-gap: 40px; }

  #app                       { max-width: 1320px; }
  #app:has(#page-revisao)    { max-width: 1400px; }
  #app:has(#page-adm-painel) { max-width: 1440px; }

  /* coluna de controles da entrada mais folgada; o relato fica ainda mais largo.
     Esta é a ÚNICA tela em duas colunas — a de narração, aprovada pelo dono. */
  #app:has(#page-revisao) #page-entrada.page.active {
    grid-template-columns: minmax(360px, 420px) minmax(0, 1fr);
  }
}

    /* ── impressão ────────────────────────────────────────────────────────────── */
    @media print {
      body { background: #fff; color: #000; }
      .btn, nav, #install-banner, .disclaimer { display: none !important; }
    }
