/* =============================================================
   Deck Sandbox — Design Tokens
   Camada 1: nada aqui conhece componentes. Só vocabulário.
   ============================================================= */

:root {
  color-scheme: dark;

  /* ---------- Espaço lógico da mesa -------------------------
     O Battlefield NÃO trabalha em pixels de tela. Ele trabalha em
     "table units" (tu). 1600x900 tu é o canvas canônico; o JSON
     guarda position.x / position.y sempre nesse espaço, e a tela
     apenas escala uniformemente via --bf-scale.
     Consequência: a mesma coordenada é válida em qualquer monitor,
     em qualquer mini-mapa e (na V2) em qualquer cliente remoto.
  ---------------------------------------------------------- */
  --bf-w: 1600;
  --bf-h: 900;
  --bf-scale: 1;      /* escala EFETIVA = ajuste x zoom do usuário (ADR-0033) */
  --bf-snap: 10;      /* granularidade do snap, em tu */

  /* Deslocamento da visão, em px de TELA. Derivado de um centro em tu
     (ADR-0033): quem guarda o enquadramento é o JS, em table units — isto
     aqui é só o resultado já convertido, para o compositor consumir. */
  --bf-pan-x: 0;
  --bf-pan-y: 0;

  /* ---------- Carta ---------------------------------------- */
  --card-w: 118px;                              /* largura base (1 tu = 1px) */
  --card-ratio: 1.3968;                         /* 88mm / 63mm */
  --card-h: calc(var(--card-w) * var(--card-ratio));
  --card-radius: 5px;

  /* O respiro entre os dois ocupantes da faixa de baixo da carta — o botão
     de virar e o selo de marcadores (JG-22). Até 2026-09-14 eles nasciam no
     mesmo ponto e o botão cobria 100% do selo; agora dividem uma linha flex
     e é este `gap` que os separa.

     É um token e não um número no `card.css` pela mesma razão do
     `--hand-lift` e do `--hand-grip-h` (ADR-0051/0068/0071): faixa disputada
     tem o espaço dela nomeado, senão o próximo ocupante o descobre por
     tentativa. Ele escala com o canvas, como todo o resto da carta. */
  --card-strip-gap: 4px;

  /* O TAMANHO DA FICHA GENÉRICA, como FRAÇÃO da carta (JG-24).

     Fração e não `px` por dois motivos que se somam: ela escala com a mesa
     como todo o resto (`--card-w` é a unidade do plano lógico, ADR-0001), e
     o JS precisa do MESMO número — `cardRect` monta a caixa lógica da peça,
     e para a ficha ela é quadrada e menor.

     É NÚMERO PURO, e não `calc(var(--card-w) * 0.34)`, porque o
     `getPropertyValue` devolve o valor ESPECIFICADO de uma propriedade
     customizada: um `calc()` volta como texto e o `parseFloat` do `tokenPx`
     cairia no padrão calado. Assim o CSS deriva e o JS multiplica, e a
     fonte continua sendo uma só (ADR-0002). */
  --marker-scale: 0.34;

  /* Quanto a carta do CAMPO se inclina no hover, prevendo o tap (UX-4).
     Não é decoração: o duplo clique é o gesto mais usado da mesa e o menos
     descoberto, e até aqui passar o mouse numa carta do campo não dava
     retorno NENHUM — só `z-index`, que é invisível. O único sinal era o
     `cursor: grab`, que fala de arrastar.

     O ângulo é pequeno de propósito. Ele não mostra o resultado, mostra a
     INTENÇÃO — a carta "quer" girar, e o duplo clique completa o giro. E é
     um número só, lido pelos dois sentidos: a carta em pé inclina para
     `+hint`, a virada volta para `90deg − hint`. Duas cópias divergiriam
     no primeiro ajuste, e a segunda ficaria apontando para o lado errado. */
  --tap-hint: 5deg;
  /* O outro sentido, DERIVADO — a carta virada inclina de volta. Mora aqui,
     e não na regra do `:hover`, por um motivo de verificação: `:hover` não
     se força por script e `cssRules` de folha externa é recusado em
     `file://` (tests/README, armadilha 4), então um valor escrito lá dentro
     é invisível para a suíte. Como token, ele é lido por
     `getComputedStyle` e a derivação passa a ser afirmável.
     É o mesmo padrão de `--card-h`, que já é `calc()` de outro token. */
  --tap-hint-tapped: calc(90deg - var(--tap-hint));

  /* ---------- Nível de detalhe (ADR-0034 / ADR-0035) --------
     Os três botões de ajuste do LOD, juntos e aqui — o critério é a
     largura RENDERIZADA da carta, então mexer nestes números é mexer em
     quando cada desenho entra. Os limiares são lidos pelo JS, como
     `--card-w` já é: o CSS continua sendo a fonte única.

     Os valores atuais são os CALIBRADOS AO VIVO, e não os que a ADR-0035
     mediu (106px e 220ms) — confirmados como deliberados em 2026-08-12 e
     registrados na ADR-0051. Este comentário afirmava a fórmula antiga
     (`--card-w` × 0,90) enquanto o valor já era 75px: calibrar ao vivo é
     o objetivo destes tokens, e o preço é que o texto precisa acompanhar.

     Cuidado ao subir de ~118px: é a largura da carta no visualizador de
     pilha, que sai de `full` e volta ao quadro. E de ~99px: o campo NO
     AJUSTE mede 99,5px num monitor de 1920×1200.
     Desde o UX-13, `--lod-full-min` também é a DETENÇÃO da alça da mão e
     `--lod-low-max` é o PISO dela — mexer aqui move as duas.
  ---------------------------------------------------------- */
  --lod-low-max: 30px;    /* abaixo disto: bloco de identidade de cor */
  --lod-full-min: 75px;  /* daqui para cima: a carta impressa */

  /* O DEGRAU DO MEIO — arte sozinha, sem texto (ADR-0131).

     Entrou por relato de uso: a pilha de COMANDO mostrava "uma cor
     sólida" no lugar do comandante. A causa é que o texto do quadro tem
     tamanho FIXO (9,5px o nome, 8,5px o tipo) em qualquer largura, então
     head e rodapé comem ~43px de altura sempre — e a arte fica com o
     resto. Medido:

         30px → arte 0%  ·  42px → 28%  ·  53px → 42%  (a pilha)
         62px → 50%      ·  75px → 59%  ·  118px → 74%

     62px é onde a arte passa a valer METADE da carta: com o texto fixo em
     ~43px e a carta em 1,4× a largura, `1,4w − 43 = 0,7w` dá `w = 61,4`.
     Abaixo disso o quadro gasta mais da metade da carta com duas faixas
     que ninguém lê nesse tamanho.

     Derivado, mas ainda CALIBRÁVEL: "metade" é um critério defensável, não
     o único. Subir daqui devolve o quadro às pilhas do trilho; descer
     devolve a arte a cartas menores.

     Cabe INTEIRO entre os dois tokens acima de propósito — eles são o piso
     e a detenção da alça da mão (ADR-0051/0062) e o piso da visão inicial
     (ADR-0069), e este degrau não pode movê-los. */
  --lod-art-max: 62px;

  /* O QUARTO DEGRAU, e ele não troca o DESENHO — troca a FONTE (RV-4,
     ADR-0102). Acima daqui a camada impressa deixa de ser a `grid`
     (488×680) e passa a ser a `display` (672×936), escolhida por NÓS e
     não pelo `srcset`: o campo escala por `transform`, e a seleção de
     `srcset` não enxerga transform — ela pergunta a caixa de LAYOUT
     (~118px), que não muda com o zoom.

     165px é ~140% de `--card-w`, o ponto sugerido pelo dono do produto.
     É CALIBRAGEM, como `--zoom-boot-card`; a GARANTIA é derivada e mora
     no JS — `printedDensity()` nunca deixa este degrau cair abaixo de
     `--lod-full-min`, porque trocar a fonte de uma camada que ainda não
     existe não quer dizer nada. */
  --lod-large-min: 165px;  /* daqui para cima: a impressa em 672px */
  --lod-fade: 1000ms;      /* dissolução entre o quadro e a impressa, no ZOOM */
  /* A mesma dissolução, mas no DROP: soltar a carta da mão num campo
     afastado, onde ela deixa de ser impressa. Token próprio porque os
     dois momentos não pedem o mesmo tempo — o do zoom acompanha um gesto
     contínuo, o do drop acontece de uma vez, junto de uma mudança de
     posição e tamanho. Nasce herdando o do zoom; pôr um valor literal
     aqui desacopla os dois. */
  --lod-fade-drop: var(--lod-fade);

  /* ---------- Teto do zoom (UX-20, ADR-0054) ---------------
     Vizinho dos limiares de LOD de propósito: os dois respondem à mesma
     pergunta — "o quanto dá para chegar perto de ler a carta" — e mexer
     num sem olhar o outro é calibrar metade.

     `--zoom-max` está em ESCALA EFETIVA, na mesma unidade que o indicador
     do canto mostra: 200% aqui é o 200% que se lê lá. Não é fator do
     ajuste. O `%` no valor é o que separa os dois: `2` seria 2% de escala,
     que o `max()` abaixo absorve sem estragar nada, enquanto um `200` lido
     como fator daria 200× o ajuste.

     `--zoom-max-fit` é o outro teto, este em FATORES do ajuste — é o
     `ZOOM_MAX = 3` de antes, sobrevivendo com o papel que ele desempenhava
     bem: em monitor grande o ajuste já é quase 1:1, e 3× dá 253% sem
     precisar de alvo nenhum.

     O teto é o MAIOR dos dois, nunca o menor: cada um é uma GARANTIA
     ("chega pelo menos até aqui"), não um limite. Com `min` este token
     pioraria a janela grande em nome de melhorar a pequena, que é
     exatamente o contrário do item. Ver ADR-0054.

     Lidos a cada passada, como os limiares de LOD: arrastar o número no
     devtools vale na hora, sem recarregar.
  ---------------------------------------------------------- */
  --zoom-max: 200%;    /* escala efetiva garantida em qualquer janela */
  --zoom-max-fit: 3;   /* e nunca menos que este fator do ajuste */

  /* ---------- Piso do valor INICIAL da visão (UX-30, ADR-0069) ---
     A largura mínima que a carta do CAMPO tem quando a mesa nasce. Está
     em px de carta renderizada, e não em escala, de propósito: é a mesma
     unidade da escada de LOD logo acima, e é essa unidade que torna o
     número comparável em vez de arbitrário —

         30px  a carta é bloco de cor   (`--lod-low-max`)
         48px  a mesa NASCE aqui        (este token)
         75px  a carta impressa         (`--lod-full-min`)

     Veio do teste em aparelho: *"o campo começa de uma visão muito longe
     no mobile (18%); com 18% aparecem apenas as cores"*. Medido no padrão
     de hoje, deitado, a carta nascia com 24,5px — abaixo do primeiro
     degrau, e o relato está literalmente certo.

     O valor é CALIBRAGEM (o dono do produto pediu "perto dos 40%", e 48
     sobre 118 dá 40,7%); a GARANTIA é derivada e mora no JS: `bootMinScale()`
     nunca deixa o boot cair abaixo de `--lod-low-max`, aconteça o que
     acontecer com este número. É a mesma cisão do padrão da mão — token
     para o alvo (ADR-0062), derivação para o piso (ADR-0051).

     Não é limite: é o valor inicial. `⤢ enquadrar` continua indo ao ajuste
     verdadeiro, e depois do boot a visão é do usuário (ADR-0033).
  ---------------------------------------------------------- */
  --zoom-boot-card: 48px;

  /* ---------- Superfícies ---------------------------------- */
  --bg-app: #0b0e13;
  --bg-surface: #141920;
  --bg-surface-2: #1b222b;
  --bg-surface-3: #232c37;
  --bg-field: #10161e;

  --line: #262f3a;
  --line-strong: #35404e;

  /* ---------- Tipografia -----------------------------------
     A LETRA NÃO ERA VOCABULÁRIO até 2026-09-13, e era o buraco que a
     ADR-0239 D2 achou ao desenhar o site: ela morava em `table.css:18`,
     dentro da regra do `body` — e `table.css` é a folha do ESQUELETO DA
     MESA, que uma página do site não carrega. Herdar só o `tokens.css`
     dava ao site as cores e os espaços e **não** a letra: paleta certa,
     tipografia errada, que é o que o olho lê primeiro.

     SÃO TRÊS TOKENS E NÃO UM, e a divisão é a decisão. A família é
     vocabulário — vale para a mesa e para uma página de texto igual. O
     CORPO e a ENTRELINHA são densidade da mesa: 13px é o tamanho que faz
     a topbar e as zonas caberem, e uma landing page nesse tamanho seria
     ilegível. Um token único com o `font:` inteiro obrigaria o site a
     herdar a letra e depois desfazer o tamanho — que é herdar e corrigir,
     não herdar.
  ---------------------------------------------------------- */
  --font-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-ui-size: 13px;
  --font-ui-line: 1.45;

  /* A ESCALA DE LEITURA, e ela nasce aqui e não na folha do site porque a
     ADR-0239 D1 é explícita: *"se uma página do site precisa de um valor
     que não está em `tokens.css`, o valor entra em `tokens.css`"*. Uma
     segunda folha de vocabulário é a segunda cópia a manter em sincronia.

     `--measure` é a LARGURA DE LINHA, não um contêiner: texto corrido
     acima de ~75 caracteres perde o olho na volta da linha, e é a única
     medida desta lista que não é tamanho de letra. */
  --font-size-hero: clamp(28px, 5.2vw, 42px);
  --font-size-title: 19px;
  --font-size-body: 16px;
  --measure: 36rem;
  /* A LARGURA DA PÁGINA, e ela é token porque tem DOIS consumidores que
     precisam concordar: o miolo e o rodapé. Escrita duas vezes, ela
     desalinha na primeira vez que alguém mexer num dos dois — e o sintoma
     é o rodapé começando alguns pixels à esquerda do texto acima dele,
     que foi exatamente o que apareceu na primeira conferência de olho. */
  --page-max: 64rem;

  /* ---------- Texto ---------------------------------------- */
  --fg: #e6edf3;
  --fg-muted: #94a3b3;
  --fg-dim: #64707e;

  /* ---------- Acentos -------------------------------------- */
  --accent: #4f8cff;
  --accent-soft: rgba(79, 140, 255, 0.16);
  --accent-line: rgba(79, 140, 255, 0.55);

  --zone-library: #4f8cff;
  --zone-graveyard: #9b7fd4;
  --zone-exile: #e08a48;
  --zone-command: #4fc3a1;
  --zone-sideboard: #b0879b;

  --danger: #e5544b;
  --ok: #46b57e;

  /* ---------- Identidade de cor (MTG) ---------------------- */
  --c-white: #f4efdc;
  --c-blue: #4a9fe0;
  --c-black: #4a4551;
  --c-red: #d75a4a;
  --c-green: #4d9a5f;
  --c-gold: #d3b45b;
  --c-artifact: #8fa3b5;
  --c-land: #9c8567;

  /* ---------- Verso da carta -------------------------------
     Tom quente, tirado do marrom do verso impresso. É só a COR — o
     desenho é nosso (ver card.css). O verso antigo era azul-acinzentado
     e quase igual ao fundo do campo: carta virada parecia buraco no
     tabuleiro, não carta.

     A moldura é MAIS ESCURA que o miolo, como no impresso. Invertida, a
     carta vira um retângulo de contorno alaranjado que chama mais atenção
     que as cartas de frente.
  ---------------------------------------------------------- */
  --card-back-1: #3f2c19;      /* trama, tom escuro */
  --card-back-2: #4a3520;      /* trama, tom claro */
  --card-back-frame: #241608;  /* moldura interna, escura */
  --card-back-edge: #0f0904;   /* fio no limite da carta */
  --card-back-glow: rgba(206, 162, 104, 0.34);  /* miolo, onde o impresso tem o oval */

  /* ---------- Elevação ------------------------------------- */
  --sh-1: 0 1px 2px rgba(0, 0, 0, 0.5);
  --sh-2: 0 2px 6px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(0, 0, 0, 0.35);
  --sh-drag: 0 18px 34px rgba(0, 0, 0, 0.6), 0 0 0 1px var(--accent-line);

  /* ---------- Ritmo ---------------------------------------- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --radius: 8px;
  --radius-sm: 5px;

  /* ---------- Chrome / trilhos ----------------------------- */
  --topbar-h: 52px;
  /* A mão cresceu de 228px quando passou a mostrar a carta impressa: a
     carta sai da altura disponível, e a 228px ela ficava do mesmo tamanho
     de antes. Custa escala do campo (0,69 → 0,65 em 940px de altura), e é
     esse equilíbrio que a alça de redimensionar vai devolver ao usuário. */
  --hand-h: 268px;
  /* E o padrão não passa desta fração da janela (ADR-0062). O `--hand-h`
     acima é um px fixo, e px fixo não sabe de que tela está falando: 268
     são 37% de uma tela de 730px e 48% de uma de 560. Vale o MENOR dos
     dois — numa tela alta 1/3 seria uma mão maior do que ninguém pediu.
     Sem unidade de propósito: é fração, e é lida ao vivo como os limiares
     de LOD. Não é limite; quem arrasta continua indo ao teto. */
  --hand-default-f: 0.33;
  /* O quanto a carta da mão sobe no hover — e, pela mesma conta, o quanto
     a caixa das cartas sobe por cima da barra para caber isso (UX-28).
     Um número só para os dois, e é o par margem-negativa + `padding` no
     `.hand__cards` que o gasta. O `.hand__cards` rola em X, e
     `overflow-x: auto` obriga o eixo Y a não ser `visible`: a carta
     levantada é recortada pelo PRÓPRIO contêiner se ele não crescer.

     Eram dois números escritos à mão — 20px de `translateY` e 24px de
     `padding` —, que é a segunda verdade de sempre.

     **Não custa carta** (ADR-0068). Custou, em duas versões anteriores:
     era `padding` puro, tirado da altura da carta, e por isso a ADR-0066
     o zerou no aparelho e a ADR-0067 o zerou em todo lugar. Emprestando de
     cima em vez de tirar de dentro, o lift volta sem cobrar nada — a
     ADR-0067 fica revertida no valor e mantida no achado.

     Calibrável ao vivo, como os limiares de LOD e o `--lod-fade`. Zero
     desliga o lift inteiro; mexer aqui move o movimento e o espaço dele
     juntos, e nunca o tamanho da carta. */
  --hand-lift: 20px;
  /* A faixa de arrasto da alça da mão (UX-13). Vira token no UX-32 pelo
     mesmo motivo do `--hand-lift`: passou a ter DOIS consumidores. Nos
     formatos normais ela cai sobre a barra e não custa nada; no formato
     curto a barra sai da linha e a alça passa a cair sobre as CARTAS —
     então ali o `.hand__cards` reserva exatamente esta altura por dentro.

     Para fora não dá: a alça tem de ficar DENTRO da mão, senão come a
     faixa de baixo do campo, que é alvo de clique e de drop (ADR-0051). */
  --hand-grip-h: 8px;
  /* O respiro entre o `Mão ›` e o menu de ações da mão (JG-9). Maior que o
     `gap` da barra de propósito, e o motivo é de APARELHO e não de desenho:
     são dois alvos de 24px lado a lado numa barra estreita, com efeitos
     opostos — um recolhe a mão, o outro abre um menu. Colados, o dedo erra,
     e errar aqui faz a mão inteira sumir da tela.

     8px é o `gap` de 6 mais 8, e a soma dá 14px de vão entre as duas caixas
     de alvo. Token porque é calibragem de dedo, e calibragem de dedo se
     ajusta olhando o aparelho — não relendo o CSS. */
  --hand-actions-gap: 8px;
  --rail-w: 172px;      /* trilho de zonas (direita) */
  /* ---------- Painéis recolhidos (UX-23) -------------------
     As duas medidas do estado FECHADO. Não são "quase zero": recolher
     não pode apagar o alvo de drop nem a contagem — o trilho é onde se
     lê "quantas cartas tenho no grimório", e a pilha é para onde se
     arrasta a carta que vai ao cemitério. O que sobra é ponto de cor +
     número, que é a ADR-0056 ("isso é cor, não palavra") aplicada aqui.

     São CUSTO FIXO, no sentido da ADR-0052: valem o mesmo em qualquer
     tela, e é por isso que recolher rende mais quanto menor for a tela.
     `--rail-collapsed-w` cabe o ponto (6px) + a contagem (24px) + os
     respiros; abaixo disso a contagem quebra de linha.
  ---------------------------------------------------------- */
  --rail-collapsed-w: 54px;
  --hand-collapsed-h: 30px;

  /* "A ALTURA é o recurso escasso" — 0 ou 1, escrito pela media query em
     `table.css` e lido pelo JS. Existe para o JS não repetir o breakpoint:
     `chromeOutsideHand()` já pergunta ao CSS se o trilho virou faixa, em
     vez de reescrever os 860px, e este token é a mesma disciplina para a
     outra pergunta. Quem consome é o padrão de colapso da mão (ADR-0062):
     deitado ela nasce recolhida. */
  --fmt-short: 0;
  /* "A janela tem LARGURA para a coluna do preview do painel de deck" — 0 ou
     1, escrita pela media query em `deck.css` e lida pelo JS/spec, exatamente
     como o `--fmt-short` acima e pelo mesmo motivo.

     Ele nasceu de uma mutação que NÃO foi acusada (DK-7, ADR-0144): a spec
     perguntava ao `display` do próprio preview e depois confirmava o
     `display`, então esconder a coluna em TODA janela passava verde. Ramo de
     formato tem de vir do FORMATO — perguntar ao elemento que se está
     testando é escrever a tautologia com passos a mais. */
  --fmt-deck-preview: 0;
  --minimap-w: 0px;     /* Fase 1: colapsado. Fase 2: ver [data-phase="2"] */
  --minimap-vw: 206;    /* largura do viewport do mini-mapa, em px */

  /* ---------- Camadas -------------------------------------- */
  /* A FAIXA DA FICHA GENÉRICA, e ela é a única coisa DENTRO do canvas que
     tem faixa própria (JG-24, pedido de 2026-09-15: *"que ele sempre ganhe
     em primeiro plano em relação a cartas (…) a intenção é que a nível de
     z-index, ele sempre fique à frente das cartas"*).

     A razão é o que a ficha É: ela MARCA uma carta, então ficar atrás da
     coisa que ela marca é o único estado em que ela não cumpre a função.
     Carta atrás de carta é arranjo; ficha atrás de carta é ficha perdida.

     O número é grande de propósito, e não é gosto: o `--z` de uma carta é
     `maxZ`, que cresce UM por jogada e vive no artefato — ele sobrevive à
     partida salva. Uma faixa de +200 (a da seleção) seria alcançada em
     algumas centenas de jogadas; com 100.000 a carta precisaria de ~99.800
     jogadas na MESMA partida para encostar. As fichas mantêm a ordem
     relativa ENTRE si, porque a faixa é somada ao `--z` de cada uma. */
  --z-marker-lift: 100000;

  --z-field: 1;
  --z-hand: 20;
  --z-rail: 30;
  --z-peek: 800;      /* acima da mesa, abaixo do arrasto: durante um
                         gesto o painel some, então nunca disputa com ele */
  --z-drag: 900;
  --z-overlay: 1000;

  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);

  /* ---------- Tempos de movimento --------------------------
     Irmão do `--lod-fade`: os tempos que se calibra olhando, não
     calculando. Valem ao vivo no devtools.

     --drag-resize é o fantasma assumindo o tamanho da ZONA sob o cursor
     (ADR-0006) — é a única transição do caminho do arrasto. Ele pesa mais
     quanto mais longe está o zoom: puxar da mão para o campo enquadrado
     é ir de ~1,2 a ~0,4 de escala, e o mesmo tempo que parece certo de
     perto parece seco de longe.
  ---------------------------------------------------------- */
  --drag-resize: 160ms;

  /* ---------- Preview no hover (UX-10) ---------------------
     Os dois botões de calibragem do painel, e valem ao vivo — o atraso é
     lido do token a cada agendamento, como os limiares de LOD.

     --peek-w acima de `--lod-full-min` de propósito: é a escada que faz
     o painel mostrar a carta impressa, sem código de desenho próprio.
     --peek-delay existe porque atravessar a mão com o mouse piscaria um
     painel por carta no caminho; curto demais irrita, longo demais faz
     parecer que não funciona.
  ---------------------------------------------------------- */
  /* `min` de três, e a terceira entrou por medição (ADR-0063): 320px de
     largura são 447px de ALTURA, e um celular deitado tem 309px de
     viewport inteiro. O painel de leitura nascia cortado exatamente na
     tela que mais precisa dele — e `placePeek` só sabe clampear a
     POSIÇÃO, não o tamanho. Agora ele cabe por construção. */
  --peek-w: min(320px, 92vw, calc((100dvh - 24px) / 1.3968));
  /* A mesma conta para DUAS cartas lado a lado (ADR-0134): metade da
     largura disponível, descontado o vão entre elas. O teto de 320px por
     carta continua — em tela larga as duas saem no tamanho cheio, e é só
     em tela estreita que a divisão morde. */
  --peek-w-2: min(320px, 45vw, calc((100dvh - 24px) / 1.3968));
  --peek-delay: 260ms;
  /* O mesmo atraso, no TOQUE, e é outro trabalho: no mouse ele filtra
     quem só está atravessando a mão; no dedo ele separa UM toque de
     DOIS — o duplo toque vira/desvira, e sem esta folga a leitura
     piscaria em cima de cada vira/desvira. Token próprio pelo mesmo
     motivo do `--lod-fade-drop`: os dois momentos não pedem o mesmo
     tempo. Mais longo que o do mouse, e é para ficar. */
  --peek-delay-touch: 320ms;

  /* ---------- Menu de contexto (FN-1, ADR-0039) ------------
     Terceiro tempo calibrável ao vivo, irmão do --peek-delay: é o quanto
     o dedo fica parado até o menu abrir. Curto demais e todo arrasto que
     hesita vira menu; longo demais e o gesto parece não existir. Só vale
     para toque e caneta — no mouse quem abre o menu é o botão direito.
  ---------------------------------------------------------- */
  --menu-longpress: 480ms;
  /* Quanto o cursor fica parado até o hint próprio abrir (UX-1, ADR-0056).
     Irmão do `--peek-delay`, e mais curto que ele de propósito: o preview
     mostra uma carta que já está na tela, o hint responde "o que este
     ícone faz?" — quem parou em cima de um ícone já está perguntando.
     No toque quem manda é o `--menu-longpress`, que é o mesmo tempo de
     segurar do menu de contexto. */
  --hint-delay: 400ms;
  --menu-w: 232px;
  /* Teto do menu. Onze itens não cabem numa janela baixa, e rolar por
     dentro é melhor que estourar a viewport — o item de baixo ficaria
     fora da tela sem nenhuma pista disso. Token, e não literal no
     componente, porque é o que permite uma spec exercitar o clampe sem
     redimensionar a janela (o headless não redimensiona). */
  /* `dvh` e não `vh`: no celular `100vh` é a viewport GRANDE (sem a
     barra do navegador), então o menu ficava mais alto que a área visível
     e o teto não chegava a apertar — resultado, o item de baixo ficava
     fora da tela sem rolagem. O `.app` já usava `100dvh`; o menu tinha
     ficado para trás. Achado em aparelho, deitado (ADR-0060). */
  --menu-max-h: calc(100dvh - 16px);
}

/* Fase 2 abre o trilho de mini-mapas sem tocar em nenhum componente. */
:root:has(#app[data-phase="2"]),
#app[data-phase="2"] {
  --minimap-w: 244px;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
