/* Tema e ajustes do editor de regras, para CodeMirror 5.
 *
 * O que este arquivo faz e o que NÃO faz:
 *
 *  - As classes do MENU de sugestões — .cm-completionIcon, .cm-completionLabel,
 *    .cm-completionDetail e as variantes de ícone — continuam vindo do CSS
 *    congelado (app.css), verbatim. É o visual estilo VSCode que o React já
 *    tinha, e o rule-editor.js emite exatamente a mesma marcação de três
 *    partes para que aquelas regras casem.
 *  - O que muda de nome é só o CONTÊINER: o CM6 chamava .cm-tooltip-autocomplete
 *    e li[aria-selected]; o CM5 chama .CodeMirror-hints e .CodeMirror-hint-active.
 *    As declarações abaixo são cópias das de app.css, com o seletor trocado.
 *
 * O tema de sintaxe (.cm-s-fz) é escrito em termos dos tokens HSL do projeto.
 * Como `.dark` vive no <html> e os tokens viram sozinhos, UM único tema cobre
 * os dois modos — melhor que o React, que recalculava isDark e trocava o
 * objeto de tema inteiro.
 *
 * RESSALVA HONESTA: o plano previa amostrar as cores exatas com
 * getComputedStyle no editor React em execução. Isso não é mais possível — o
 * SPA não compila sem Node. As cores de token abaixo foram derivadas da paleta
 * do @uiw/codemirror-theme-github, não medidas. É o único ponto do portal onde
 * a paridade de cor é aproximada em vez de verificada, e está registrado como
 * tal no CLAUDE.md.
 */

/* ------------------------------------------------------------- moldura ---- */
.CodeMirror {
  height: auto;
  min-height: 200px;
  background: transparent;
  color: hsl(var(--foreground));
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;
  font-size: 13px;
  line-height: 1.6;
}

.CodeMirror-scroll {
  min-height: 200px;
}

.CodeMirror-gutters {
  background: transparent;
  border-right: 1px solid hsl(var(--border));
}

.CodeMirror-linenumber {
  color: hsl(var(--muted-foreground));
  opacity: 0.6;
}

.CodeMirror-cursor {
  border-left: 1px solid hsl(var(--foreground));
}

.CodeMirror-activeline-background {
  background: hsl(var(--muted) / 0.4);
}

.CodeMirror-selected,
.CodeMirror-focused .CodeMirror-selected {
  background: hsl(var(--primary) / 0.25);
}

.CodeMirror-matchingbracket {
  color: hsl(var(--primary)) !important;
  border-bottom: 1px solid hsl(var(--primary));
}

.CodeMirror-placeholder {
  color: hsl(var(--muted-foreground));
  opacity: 0.6;
}

/* -------------------------------------------------------- realce de sintaxe */
.cm-s-fz .cm-comment  { color: hsl(215 14% 52%); font-style: italic; }
.cm-s-fz .cm-string   { color: hsl(215 80% 68%); }
.cm-s-fz .cm-number   { color: hsl(28 90% 62%); }
.cm-s-fz .cm-atom     { color: hsl(28 90% 62%); }
.cm-s-fz .cm-keyword  { color: hsl(348 80% 66%); }
.cm-s-fz .cm-def      { color: hsl(265 75% 72%); }
.cm-s-fz .cm-variable { color: hsl(var(--foreground)); }
.cm-s-fz .cm-operator { color: hsl(348 80% 66%); }
.cm-s-fz .cm-bracket  { color: hsl(var(--muted-foreground)); }

/* ------------------------------------------ contêiner do menu de sugestões --
 * Cópia das declarações de .cm-tooltip-autocomplete do app.css, com o seletor
 * do CM5. Os !important vieram junto: sem eles as regras próprias do
 * codemirror.css, carregado depois, voltam a vencer.
 */
.CodeMirror-hints {
  z-index: 2147483647 !important;
  background: hsl(var(--popover)) !important;
  border: 1px solid hsl(var(--border)) !important;
  border-radius: 6px !important;
  box-shadow: 0 8px 24px hsl(0 0% 0% / 0.15), 0 2px 8px hsl(0 0% 0% / 0.1) !important;
  overflow-y: auto !important;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace !important;
  font-size: 13px !important;
  max-height: 260px !important;
  padding: 4px 0 !important;
  margin: 0 !important;
  list-style: none !important;
}

.dark .CodeMirror-hints {
  box-shadow: 0 8px 24px hsl(0 0% 0% / 0.4), 0 2px 8px hsl(0 0% 0% / 0.3) !important;
}

.CodeMirror-hint {
  padding: 4px 8px !important;
  display: flex !important;
  align-items: center !important;
  gap: 8px !important;
  color: hsl(var(--foreground)) !important;
  cursor: pointer !important;
  border-radius: 0 !important;
  white-space: nowrap !important;
  max-width: none !important;
}

.CodeMirror-hint-active,
.CodeMirror-hint:hover {
  background: hsl(var(--primary) / 0.15) !important;
  color: hsl(var(--foreground)) !important;
}

/* -------------------------------------------------- glifos dos ícones -----
 * O app.css CONGELADO dá aos .cm-completionIcon-* o tamanho (16x16), o
 * arredondamento e um FUNDO tingido por tipo — e nada mais. Não existe regra de
 * `content` em ponta nenhuma do projeto, então os ícones saíam como
 * quadradinhos coloridos VAZIOS: a cor distinguia os tipos para quem já
 * soubesse o código de cores de cabeça, e para mais ninguém.
 *
 * Um caractere só, herdando a `color` que o app.css já fixa por tipo — o mesmo
 * glifo serve nos dois temas, porque quem vira é o token, não o desenho. O
 * elemento já é `display:flex` centrado, com `font-size:10px` e
 * `font-weight:600` (tudo !important, no app.css), então o ::before entra
 * centrado e legível sem mais nenhuma declaração aqui.
 *
 * ⚠️ A escapada \0192 em vez do glifo literal porque este arquivo é servido
 * como estático e não declara @charset: com um Content-Type sem charset, o byte
 * literal fica à mercê do padrão do navegador.
 *
 * ⚠️ Os QUATRO primeiros são os únicos tipos que o servidor emite hoje (ver
 * Suggestion.Type em portal/suggestions.go). Os três seguintes existem porque o
 * app.css já os tinge: um tipo novo sem glifo voltaria ao quadrado vazio, e é
 * um defeito que ninguém percebe até estar na tela.
 *
 * ⚠️ A regra genérica vem PRIMEIRO de propósito. Todas têm a mesma
 * especificidade (uma classe + um pseudoelemento), então quem decide é a ordem
 * do arquivo — e o que se quer é que a específica vença.
 */
.cm-completionIcon::before {
  content: "\2022"; /* bullet, para um tipo que não conhecemos */
}

.cm-completionIcon-keyword::before {
  content: "K";
}

.cm-completionIcon-variable::before {
  content: "V";
}

.cm-completionIcon-function::before {
  content: "\0192"; /* f minuscula com gancho */
}

.cm-completionIcon-constant::before {
  content: "C";
}

.cm-completionIcon-namespace::before {
  content: "N";
}

.cm-completionIcon-class::before {
  content: "T";
}

/* O item de CORREÇÃO do menu (rule-editor.js, itemDeCorrecao): um tipo que o
 * app.css congelado não tinge, então fundo e cor entram aqui, no tom do erro.
 * O `!important` é o mesmo que o app.css usa nos irmãos — sem ele a regra
 * genérica de lá venceria. */
.cm-completionIcon-fix {
  background: hsl(var(--destructive) / 0.2) !important;
  color: hsl(var(--destructive)) !important;
}

.cm-completionIcon-fix::before {
  content: "!";
}

.cm-completionIcon-property::before {
  content: "P";
}

/* ----------------------------------------------------------------- hover --
 * ⚠️ Este comentário JÁ DISSE que ".cm-fz-hover já existe no CSS congelado;
 * aqui só entra o posicionamento" — e essa era a premissa falsa que escondeu o
 * defeito. Existir, existe: o app.css tem um bloco com fundo, borda e padding.
 * Só que ele está escrito como `.cm-tooltip-hover .cm-fz-hover`, e
 * `.cm-tooltip-hover` é classe do CodeMirror 6, que saiu do projeto junto com o
 * bundler. O seletor não casa com nada desde o port, então o balão saía como
 * TEXTO CRU sobre a página: sem fundo, sem borda, sem padding, por cima do que
 * houvesse embaixo.
 *
 * As declarações abaixo são aquelas mesmas, com o ancestral morto removido — a
 * mesma dívida que o bloco de .CodeMirror-hints, no topo deste arquivo, já
 * tinha pago para o menu.
 *
 * `fixed` pelo mesmo motivo do .cm-fz-doc: o rule-editor.js posiciona com
 * charCoords(..., 'window'), que é coordenada de viewport.
 */
.cm-fz-hover {
  position: fixed;
  z-index: 62;
  max-width: 28rem;
  padding: 6px 8px;
  font-size: 12px;
  line-height: 1.4;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: hsl(var(--popover-foreground));
  background: hsl(var(--popover));
  border: 1px solid hsl(var(--border));
  border-radius: 6px;
  box-shadow: 0 8px 24px hsl(0 0% 0% / 0.12), 0 2px 8px hsl(0 0% 0% / 0.08);
  pointer-events: none;
}

.dark .cm-fz-hover {
  box-shadow: 0 8px 24px hsl(0 0% 0% / 0.4), 0 2px 8px hsl(0 0% 0% / 0.3);
}

.cm-fz-hover-titulo {
  font-weight: 600;
}

.cm-fz-hover-corpo {
  margin-top: 2px;
  opacity: 0.85;
}

/* O balão de DIAGNÓSTICO (rule-editor.js, mostrarDiagnostico): a mensagem do
 * erro ou aviso sublinhado, a sugestão e o botão "Corrigir". Ao contrário do
 * balão de catálogo, recebe ponteiro — o botão precisa ser clicável —, e o
 * título leva a cor da severidade, a mesma do sublinhado. */
.cm-fz-hover-diagnostico {
  pointer-events: auto;
  font-family: inherit;
}

.cm-fz-hover-erro .cm-fz-hover-titulo {
  color: hsl(var(--destructive));
}

.cm-fz-hover-aviso .cm-fz-hover-titulo {
  color: #d97706;
}

.cm-fz-hover-acao {
  display: flex;
  align-items: center;
  margin-top: 6px;
}

.cm-fz-hover-acao button {
  font: inherit;
  font-size: 11px;
  line-height: 1.2;
  padding: 3px 10px;
  border-radius: 4px;
  border: 1px solid transparent;
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  cursor: pointer;
}

.cm-fz-hover-acao button:hover {
  opacity: 0.9;
}

.cm-fz-hover-atalho {
  margin-left: 8px;
  font-size: 11px;
  opacity: 0.7;
}

/* A bolinha da margem abre o balão ao clique (gutterClick). */
.cm-fz-marcador-erro,
.cm-fz-marcador-aviso {
  cursor: pointer;
}

/* ------------------------------------------------- painel de documentação --
 * O equivalente ao Completion.info do CM6, que o CM5 não tem. O texto longo de
 * cada item já viajava do servidor e só era alcançável passando o mouse sobre o
 * token DEPOIS de escrevê-lo — ou seja, tarde demais para ajudar a escolher.
 * Segue a mesma paleta e a mesma sombra de .CodeMirror-hints, para ler como uma
 * segunda coluna do mesmo popup, e não como outro widget.
 */
.cm-fz-doc {
  /* `fixed`, e não `absolute`: as coordenadas vêm de getBoundingClientRect, que
   * é VIEWPORT. O editor vive dentro de um diálogo `fixed` com rolagem própria,
   * e somar pageYOffset a uma coordenada de viewport para depois posicionar
   * contra o documento é converter duas vezes — e errar assim que a rolagem que
   * mexe for a do diálogo, que não toca no pageYOffset. Ver `posicionar`, no
   * rule-editor.js. */
  position: fixed;
  z-index: 61;
  max-width: 22rem;
  max-height: 260px;
  overflow-y: auto;
  padding: 8px 10px;
  font-size: 0.8125rem;
  line-height: 1.4;
  background: hsl(var(--popover));
  color: hsl(var(--popover-foreground));
  border: 1px solid hsl(var(--border));
  border-radius: 6px;
  box-shadow: 0 8px 24px hsl(0 0% 0% / 0.12), 0 2px 8px hsl(0 0% 0% / 0.08);
  pointer-events: none;
}

.dark .cm-fz-doc {
  box-shadow: 0 8px 24px hsl(0 0% 0% / 0.4), 0 2px 8px hsl(0 0% 0% / 0.3);
}

.cm-fz-doc-titulo {
  font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  margin-bottom: 4px;
}

/* ------------------------------------------- marcadores de snippet (Tab) --
 * O snippetCompletion do CM6 não tem equivalente no CM5. Os trechos por onde o
 * Tab anda ficam realçados enquanto o modo snippet está ativo; sair da região
 * o encerra, e o realce some junto.
 */
.cm-fz-tabstop {
  background: hsl(var(--primary) / 0.18);
  border-radius: 2px;
}

/* ------------------------------------------------------ erro sublinhado --
 * O addon lint do CM5 não é vendorado: traz plumbing assíncrono próprio e mais
 * CSS congelado. A marcação à mão usa a posição REAL (linha e coluna) que o
 * parser passou a devolver — antes o erro trazia só um offset de byte
 * interpolado no meio da mensagem.
 */
.cm-fz-erro {
  text-decoration: underline wavy hsl(var(--destructive));
  text-underline-offset: 3px;
}

.cm-fz-marcador-erro {
  color: hsl(var(--destructive));
  font-size: 0.7rem;
  line-height: 1;
}

/* O AVISO semântico, em âmbar: o nome que não existe no catálogo, sublinhado
 * no lugar em que está. O tom é o do painel (`text-amber-600` do Tailwind,
 * #d97706), escrito à mão porque o tema não tem token de aviso. */
.cm-fz-aviso {
  text-decoration: underline wavy #d97706;
  text-underline-offset: 3px;
}

.cm-fz-marcador-aviso {
  color: #d97706;
  font-size: 0.7rem;
  line-height: 1;
}

.CodeMirror-gutter.cm-fz-erros {
  width: 12px;
}
