/* Fontes self-hosted (UI-7). Propshaft resolve as url() relativas para o caminho
   com digest; font-src 'self' na CSP cobre. font-display: swap. */
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/spectral-400-1be4eae3.woff2") format("woff2"); }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/spectral-500-0c8349dc.woff2") format("woff2"); }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 600; font-display: swap; src: url("/assets/spectral-600-b0ba95ac.woff2") format("woff2"); }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 700; font-display: swap; src: url("/assets/spectral-700-d4c449b2.woff2") format("woff2"); }
/* JetBrains Mono é fonte variável — um arquivo cobre 100–800. */
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 100 800; font-display: swap; src: url("/assets/jetbrains-mono-var-68dbce1c.woff2") format("woff2"); }

/* Tokens da UI-7. Nomes históricos (--bg, --panel, --gold…) mudam de valor,
   não de nome — o CSS existente herda. Aliases do design-system somados. */
:root {
  color-scheme: dark;         /* controles nativos (select, textarea, file, scrollbar) seguem o tema escuro */

  /* Fundos */
  --bg: #0b0a08;              /* fundo da página */
  --bg-secondary: #100f0c;    /* header, faixas alternadas */
  --bg-tertiary: #14130f;     /* menu mobile aberto, rodapés de card */
  --panel: #17160f;           /* superfície SÓ da landing (hero/chips/botão outline); cards do app usam --bg-secondary desde a consolidação UI-7e */
  --surface: #17160f;         /* alias do design system */
  --surface-raised: #1a1913;  /* inputs, dropdown, modal (fatias futuras) */

  /* Bordas */
  --border: #232019;          /* base / cards */
  --border-2: #241f19;        /* divisores */
  --border-3: #2c2a22;        /* inputs, toggles */
  --border-4: #34301f;        /* dropdown, realce */

  /* Texto */
  --text: #ece8dd;            /* principal / ênfase */
  --text-secondary: #d7d3c8;  /* corpo */
  --text-tertiary: #cbc7bc;   /* terciário */
  --muted: #8b877c;           /* muted claro (labels, meta) */
  --muted-2: #6f6b61;         /* muted médio */
  --muted-3: #57534b;         /* muted escuro / placeholder */

  /* Dourado unificado (resolve os dois dourados; alinha com favicons) */
  --gold: #c6a05a;
  --gold-border: #4a4025;     /* borda / sublinhado dourado */
  --gold-light: #e9dfbb;      /* runeword */
  --gold-hover: #d4b06a;      /* dourado mais claro/suave: nomes de entrada, hover */
  --skill-line-lit: #7a6a48;  /* seta de dependência da árvore de skills, acesa (pai+filho aprendidos) */
  --skill-line-dim: #37332a;  /* seta de dependência da árvore de skills, apagada */

  /* Raridade e semântica */
  --green: #5ab04a;           /* sucesso / itens set */
  --blue: #6a7cff;            /* itens magic */
  --yellow: #e6e650;          /* atenção informativa (viewing-banner) */
  --orange: #dfa14c;          /* aviso (notice-banner), itens crafted */
  --red: #d05050;             /* perigo / morte */
  --hardcore: #c96a52;        /* rótulo do modo hardcore — vermelho-tijolo do mock */
  --violet: #a874d8;          /* glifos de gema (ametista) */
  --rare-new: #d9cf4f;        /* itens rare */
  --rune-new: #d0913e;        /* runas */
  --base-new: #cbc7bc;        /* itens base */
  --prop-color: #8a8aff;      /* propriedades / stats (Inspector, fatia futura) */

  /* Tipografia */
  --font-sans: ui-sans-serif, system-ui, sans-serif;
  --font-serif: "Spectral", Georgia, "Times New Roman", serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", monospace;

  --page-pad: 1.5rem;
  --container: 71.25rem;   /* 1140px — largura do mock (header + main + footer) */

  /* Landing de marketing — tons do mock não cobertos pelos tokens gerais.
     A landing usa cores exatas do design aprovado; onde o token geral servia
     (--bg, --gold, --green, --prop-color…), ele foi reutilizado. */
  --landing-band: #0e0d0a;       /* faixas escuras alternadas de seção */
  --landing-footer-bg: #0a0907;  /* fundo do rodapé site-wide */
  --landing-nav-border: #1c1a15; /* divisores finos (nav, faixas) */
  --landing-body: #b8b4a8;       /* corpo de parágrafo hero/seções */
  --landing-eyebrow: #a08a5a;    /* eyebrow + badge dourado suave */
  --landing-orange: #c98a52;     /* "need Sol" / morte na timeline */
  --rune-bg: #241c12;            /* tile de runa (ilustração) */
  --rune-border: #3d2f1c;
  --tooltip-bg: #050505;         /* fundo do tooltip de item */
  --track-bg: #2a2620;           /* trilho das barras (roll/grail) */
}

body {
  background: var(--bg);
  color: var(--text-secondary);
  font-family: var(--font-sans);
  line-height: 1.5;
  margin: 0;
  /* Antialiasing suave (macOS): sem isto o subpixel engrossa o texto e tudo
     parece "pesado" — o mock usa antialiased, então acompanhamos. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* Shell da app: header e footer sangram a viewport inteira (fundo/borda de
   ponta a ponta, sem "barras pretas" nas laterais); só o conteúdo (main) fica
   centrado na largura do container — mesma estrutura da landing. */
main { display: block; max-width: var(--container); margin: 0 auto; padding: var(--page-pad); }

a { color: var(--gold); }
::selection { background: var(--gold); color: var(--bg-tertiary); }
::placeholder { color: var(--muted-3); }

/* Header (UI-7): barra gradiente 3px no topo + fundo #100f0c, sangrando até as
   bordas da coluna via margens negativas que cancelam o padding do body.
   Sticky com blur (UI-7e): acompanha o scroll como a nav da landing — fundo
   semitransparente + backdrop-filter deixam o conteúdo passar por baixo. */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background:
    linear-gradient(90deg, #201d15, var(--gold-border), #201d15) top / 100% 3px no-repeat,
    rgba(16, 15, 12, 0.86);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid #211f19;
}
/* Conteúdo do header centrado na largura do container; o fundo/gradiente/borda
   do .site-header é que sangram a viewport. */
.site-header-inner { max-width: var(--container); margin: 0 auto; padding: 0.85rem var(--page-pad); }

/* Marca: glifo (escudo + cálice em negativo, currentColor → --gold) + wordmark
   Spectral dourado. */
.brand { display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; flex: none; }
.brand-glyph { height: 1.4em; width: auto; color: var(--gold); flex: none; }
.brand-text { font-family: var(--font-serif); font-weight: 600; font-size: 1.25rem; color: var(--gold); letter-spacing: 0.01em; }

/* Linha desktop: marca | locale | nav | (auto) busca | dropdown do usuário. */
.site-header-desktop { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; row-gap: 0.6rem; }
.site-header-mobile { display: none; }
.site-nav { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; row-gap: 0.5rem; font-size: 0.9rem; }
.site-header form { display: inline; }
.push-right { margin-left: auto; }

/* font-size mora no contêiner .site-nav (não aqui): o item "Wiki" é um
   div.nav-group, não um a.nav-link, e precisa do mesmo font-size pra alinhar o
   line-box com os irmãos na flex row (issue #104). */
.site-nav .nav-link { text-decoration: none; white-space: nowrap; color: var(--muted); }
.site-nav .nav-link:hover { color: var(--gold); }
/* Página corrente em destaque (aria-current) — claro sobre os muted irmãos. */
.nav-link[aria-current="page"] { color: var(--text); }

.link-button {
  background: none; border: 0; color: var(--gold);
  font: inherit; font-size: 0.85em; cursor: pointer; text-decoration: underline; padding: 0;
}
.link-button.danger { color: var(--red); }

/* Busca do header (UI-7e): campo com lupa dentro de uma caixa com borda —
   input sem borda própria. Empurrada à direita no desktop; ocupa a linha no
   mobile. Especificidade .site-header .header-search vence o `.site-header form`. */
.site-header .header-search {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 0.4rem;
  background: var(--bg-tertiary); border: 1px solid var(--border-3); border-radius: 8px;
  padding: 0.4rem 0.65rem;
}
/* Desktop: a busca é o elemento elástico da linha — comprime PRIMEIRO, antes de
   qualquer wrap. Mantém margin-left:auto (empurra o grupo à direita). Escopo
   -desktop preserva a busca full-width do painel mobile. */
.site-header-desktop .header-search { flex: 1 1 0; min-width: 6rem; max-width: 15rem; }
.header-search-icon { width: 0.85rem; height: 0.85rem; color: var(--muted-2); flex: none; }
/* A lupa é um botão de submit (issue #10): com o campo vazio cai na /search
   dedicada; com texto, busca. Reset para não parecer botão — só o glifo. */
.header-search-button {
  background: none; border: 0; padding: 0; margin: 0;
  display: inline-flex; align-items: center; flex: none; cursor: pointer;
}
.header-search-button:hover .header-search-icon,
.header-search-button:focus-visible .header-search-icon { color: var(--text); }
.header-search-button:focus-visible { outline: 1px solid var(--gold-border); outline-offset: 2px; border-radius: 4px; }
.header-search input[type="search"] {
  background: transparent; color: var(--text-secondary);
  border: 0; padding: 0; font: inherit; font-size: 0.8rem;
  flex: 1; width: 100%; min-width: 0;
}
.header-search input[type="search"]:focus { outline: none; }

/* Menu do usuário: dropdown puro-CSS via <details>. */
.user-menu { position: relative; flex: none; }
.user-menu summary {
  list-style: none; cursor: pointer;
  color: var(--muted); font-size: 0.85rem;
  display: inline-flex; align-items: center; max-width: 100%;
}
.user-menu summary::-webkit-details-marker { display: none; }
/* Caret é flex-item (flex:none) — SEMPRE visível; o ellipsis fica no label. */
.user-menu summary::after { content: "▾"; flex: none; margin-left: 0.25rem; }
/* Email com teto: comprime com ellipsis sem empurrar o caret pra fora da linha. */
.user-menu-label {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0; max-width: 11rem;
}
.user-menu[open] summary { color: var(--text); }
.user-menu-items {
  position: absolute; right: 0; top: calc(100% + 0.6rem); z-index: 20;
  display: flex; flex-direction: column; gap: 0.15rem; min-width: 12rem;
  background: var(--surface-raised); border: 1px solid var(--border-4); border-radius: 9px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
  padding: 0.5rem;
}
.user-menu-items a { font-size: 0.85rem; text-decoration: none; color: var(--text-tertiary); padding: 0.45rem 0.6rem; border-radius: 6px; }
.user-menu-items a:hover { background: #201f18; }
.user-menu-items .link-button { padding: 0.45rem 0.6rem; text-decoration: none; }
.user-menu-items form { display: inline; text-align: left; }
/* Admin é o primeiro item do dropdown (só admin), área especial: dourado + uma
   hairline discreta separando-o dos itens comuns. O seletor precisa do `a` pra
   vencer `.user-menu-items a` (senão a cor volta a text-tertiary — issue #3).
   A borda vive NO próprio link admin, então some junto com ele pro não-admin. */
.user-menu-items a.user-menu-admin {
  color: var(--gold); margin-bottom: 0.35rem; padding-bottom: 0.55rem;
  border-bottom: 1px solid var(--border-2);
}

/* Header mobile (≤48rem): hamburger <details>, sem JS. Ativado no media query. */
.site-header-mobile > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 0.55rem;
}
.site-header-mobile > summary::-webkit-details-marker { display: none; }
.site-header-mobile .hamburger { margin-left: auto; font-size: 1.3rem; line-height: 1; color: #b8b4a8; padding: 0.2rem 0.25rem; }
.mobile-panel {
  display: flex; flex-direction: column; gap: 0.15rem;
  background: var(--bg-tertiary);
  margin: 0.85rem calc(-1 * var(--page-pad)) calc(-0.85rem);
  padding: 0.75rem var(--page-pad) 1rem;
  border-top: 1px solid var(--border-2);
}
.mobile-panel .mobile-nav { display: flex; flex-direction: column; }
.mobile-panel .nav-link { text-decoration: none; color: var(--text-secondary); font-size: 0.95rem; padding: 0.55rem 0.6rem; border-radius: 7px; }
.mobile-panel .nav-link:hover { background: #211f18; color: var(--gold); }
.mobile-panel .nav-link[aria-current="page"] { color: var(--gold); }
.mobile-panel .link-button { text-decoration: none; padding: 0.55rem 0.6rem; font-size: 0.95rem; }
/* Mobile: mesmo tratamento do dropdown — dourado + hairline abaixo do Admin
   (base plana pra linha limpa). Como a borda está no link, o não-admin não herda
   separador órfão. */
.mobile-panel .user-menu-admin {
  color: var(--gold); margin: 0 0 0.35rem; padding: 0.55rem 0.6rem 0.6rem;
  border-radius: 7px 7px 0 0; border-bottom: 1px solid var(--border-2);
}
.mobile-panel .header-search { margin: 0 0 0.35rem; display: flex; }
.mobile-panel .header-search input[type="search"] { flex: 1; width: 100%; box-sizing: border-box; }
.menu-sep { height: 1px; background: var(--border-2); margin: 0.5rem 0; }

/* Submenu do Wiki no header desktop (issue #62): CSS puro, abre no hover E no
   focus-within (teclado). O item Wiki continua navegando pra /wiki; o painel só
   oferece atalhos pras seções (Calculators, Runewords). Painel com a mesma
   linguagem do dropdown do usuário (surface-raised + borda + sombra). */
.nav-group { position: relative; }
/* O gatilho pode ser .nav-link (site header) ou âncora simples (landing). */
.nav-group > a::after {
  content: "▾"; margin-left: 0.25rem; font-size: 0.7em; color: var(--muted-2);
}
/* Ponte invisível cobrindo o gap item↔painel: o mouse cruza sem derrubar o hover. */
.nav-group::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 0.5rem; }
.nav-sub {
  /* Centralizado sob o gatilho: com trigger curto ("Wiki") e painel largo, o
     alinhamento à esquerda pendia todo o menu para a direita. */
  position: absolute; left: 50%; transform: translateX(-50%); top: calc(100% + 0.45rem); z-index: 40;
  /* Sem min-width: o painel abraça o rótulo mais largo (links têm nowrap) —
     11rem deixava um vazio grande com rótulos curtos. */
  display: none; flex-direction: column; gap: 0.15rem;
  background: var(--surface-raised); border: 1px solid var(--border-4); border-radius: 9px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6); padding: 0.4rem;
}
.nav-group:hover .nav-sub, .nav-group:focus-within .nav-sub { display: flex; }
/* Especificidade dupla de propósito: na landing, .landing-nav-anchors a
   venceria uma classe só. */
.nav-sub .nav-sub-link {
  font-size: 0.85rem; text-decoration: none; color: var(--text-tertiary);
  padding: 0.4rem 0.6rem; border-radius: 6px; white-space: nowrap;
}
.nav-sub .nav-sub-link:hover { background: #201f18; color: var(--gold); }

/* Submenu aninhado de Calculators (issue #103): o item Calculators do painel do
   Wiki é um grupo — hover/focus-within abre um flyout à direita com as 5
   calculadoras. O link continua navegando pra /wiki/calculators. Mesma linguagem
   visual do .nav-sub (surface-raised + borda + sombra). */
.nav-sub-group { position: relative; }
/* Caret ▸ no rótulo Calculators (mesma linguagem do ▾ do .nav-group). O trigger
   vira flex pra caber rótulo (nowrap) + seta com o espaço entre eles. */
.nav-sub .nav-sub-group-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
}
.nav-sub .nav-sub-group-trigger::after {
  content: "▸"; font-size: 0.7em; color: var(--muted-2);
}
/* Ponte invisível cobrindo o gap trigger↔flyout: o mouse cruza sem derrubar o hover. */
.nav-sub-group::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 100%; width: 0.55rem;
}
.nav-sub-flyout {
  /* -0.4rem compensa o próprio padding do painel: o 1º item alinha com o trigger. */
  position: absolute; left: calc(100% + 0.4rem); top: -0.4rem; z-index: 41;
  display: none; flex-direction: column; gap: 0.15rem;
  background: var(--surface-raised); border: 1px solid var(--border-4); border-radius: 9px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6); padding: 0.4rem;
}
.nav-sub-group:hover .nav-sub-flyout, .nav-sub-group:focus-within .nav-sub-flyout { display: flex; }

/* Subnav mobile do Wiki (issue #62): <details> aninhado no painel hamburger, sem
   JS. O summary reusa .nav-link; o ▾ fica à direita e os links internos recuam.
   Links são block (não flex no <details>: navegadores aplicam display em
   <details> de forma inconsistente e os itens caíam lado a lado no Safari). */
.mobile-panel .mobile-subnav-summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
}
.mobile-panel .mobile-subnav-summary::-webkit-details-marker { display: none; }
.mobile-panel .mobile-subnav[open] > .mobile-subnav-summary { color: var(--gold); }
.mobile-panel .mobile-subnav-link { display: block; padding-left: 1.4rem; }

.token-reveal {
  border: 1px solid var(--gold); border-radius: 4px;
  padding: 0.75rem; margin-bottom: 1rem;
}
.token-reveal p { margin: 0 0 0.35rem; }
.token-reveal .token-value { color: var(--gold); user-select: all; word-break: break-all; }

.viewing-banner {
  display: flex; align-items: center; gap: 1rem;
  border: 1px solid var(--yellow); border-radius: 4px; color: var(--yellow);
  padding: 0.5rem 0.75rem; margin-bottom: 1rem;
}
.viewing-banner form { display: inline; }

.history-actions { display: flex; gap: 0.75rem; align-items: center; }
.history-actions form { display: inline; }
.history-actions a { font-size: 0.85em; }

/* Paginação do histórico (issue #14): mesmo idioma mono do mode-toggle —
   ‹ Newer / Older › com "Page N of M" no meio; link desabilitado nem entra. */
.pager { display: flex; align-items: center; gap: 1rem; margin-top: 1rem; font-family: var(--font-mono); font-size: 0.8rem; }
.pager-link {
  color: var(--muted-2); text-decoration: none;
  border: 1px solid var(--border); border-radius: 7px; padding: 0.3rem 0.7rem;
}
.pager-link:hover { color: var(--text); border-color: var(--gold-border); }
.pager-status { color: var(--muted); }

.device-form { display: flex; gap: 0.5rem; margin-bottom: 1.5rem; }
.device-form input {
  background: var(--surface-raised); color: var(--text-secondary);
  border: 1px solid var(--border-3); border-radius: 7px; padding: 0.45rem 0.7rem; font: inherit;
}
.device-form input[type="text"] { flex: 1; max-width: 20rem; }
.device-form input[type="submit"] { cursor: pointer; color: var(--gold); }

.browser-sessions { margin-top: 2.5rem; border-top: 1px solid var(--border); padding-top: 1.5rem; }
.browser-sessions .table-scroll { margin-bottom: 1rem; }

.flash { padding: 0.5rem 0.75rem; border-radius: 7px; }
.flash-alert { color: var(--red); border: 1px solid var(--red); }
.flash-notice { color: var(--green); border: 1px solid var(--green); }

/* Botões partilhados (página de download, confirm dialog). A landing usa suas
   próprias classes .landing-btn (ver bloco Landing no fim do arquivo). */
.button-primary, .button-secondary {
  padding: 0.55rem 1.35rem; border-radius: 7px; text-decoration: none;
}
.button-primary { background: var(--gold); color: var(--bg); font-weight: 600; border: 0; }
.button-secondary { border: 1px solid var(--border-3); color: var(--text); }
/* Card: a superfície padrão de conteúdo agrupado (dashboard). */
.cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin: 1.5rem 0; }
.cards-3 { grid-template-columns: repeat(3, 1fr); }
.cards-4 { grid-template-columns: repeat(4, 1fr); }
/* Superfície de card unificada (dashboard, grail, admin, download, upload): fundo
   mais fundo que --panel (funde com a página em vez de "saltar"), cantos macios,
   respiro maior e título Spectral 400 — era só do dashboard (mock), virou base
   pra todo card. */
.card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px; padding: 1.6rem 1.75rem; }
.card h3 { font-family: var(--font-serif); font-size: 1.35rem; font-weight: 400; margin-top: 0; }
.card h3 a { text-decoration: none; }
.card .empty { margin-bottom: 0; }
.card-list { list-style: none; padding: 0; margin: 0; }
.card-list li { padding: 0.15rem 0; }

/* Dashboard (UI-7e): cabeçalho da página, cabeçalho de card com contagem,
   chips do stash, barra do grail e a caixa de upload arrastar-e-soltar. */
.dash-head { margin-bottom: 2.25rem; }
.dash-eyebrow { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--landing-eyebrow); margin: 0 0 0.6rem; }
/* Título de página: grande e com tracking NEGATIVo (o mock usa -0.5px). O h1
   global aplica +0.01em — em serifa bold isso "espalha" e pesa; aqui apertamos. */
.dash-title { font-size: 3.25rem; line-height: 1; margin: 0; letter-spacing: -0.01em; }
.cards.dash-cards { margin-top: 0; gap: 1.25rem; }

/* Lista de entradas (Characters, Runewords): nome linkado + meta, com respiro
   maior entre linhas (mock usa 14px). */
.entry-list { display: flex; flex-direction: column; gap: 0.85rem; }
.entry-list li { padding: 0; }
/* Nome da entrada: dourado um tom mais claro/suave e sublinhado com FOLGA
   (border-bottom + padding), não colado ao texto como o text-decoration. */
.entry-name {
  color: var(--gold-hover); text-decoration: none;
  border-bottom: 1px solid var(--gold-border); padding-bottom: 2px;
}
.entry-name:hover { border-color: var(--gold); }

.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }
.card-head h3 { margin-bottom: 0.25rem; }
.card-count { font-family: var(--font-mono); font-size: 0.68rem; color: var(--muted-3); flex: none; }
.card-more {
  display: inline-block; margin-top: 0.75rem; padding-top: 0.7rem;
  border-top: 1px solid var(--border-2);
  font-family: var(--font-mono); font-size: 0.72rem; text-decoration: none;
}
.accent-green { color: var(--green); }

/* Chips (contagens do stash): mesma família dos .tag, num grid que quebra. */
.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.chip {
  font-family: var(--font-mono); font-size: 0.68rem; color: var(--text-tertiary);
  background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 6px;
  padding: 0.2rem 0.5rem;
}
.stash-list li + li { margin-top: 0.9rem; }
.stash-line { display: flex; align-items: baseline; gap: 0.4rem 0.75rem; flex-wrap: wrap; }
.stash-mode { color: var(--text); }
.stash-mode.hardcore { color: var(--hardcore); }
.stash-gold { font-family: var(--font-mono); font-size: 0.8rem; color: var(--gold); }

/* Barra de progresso do grail — trilho + preenchimento (largura via .roll-fill--N). */
.dash-bar { height: 6px; background: var(--track-bg); border-radius: 3px; overflow: hidden; margin-top: 0.9rem; }
.dash-bar-fill { display: block; height: 100%; background: var(--gold); }
.dash-bar-label { font-family: var(--font-mono); font-size: 0.72rem; color: var(--gold); margin: 0.5rem 0 0; }

/* Linha de estatística (grail/backups): número mono claro numa coluna + rótulo
   muted — o número "salta", o rótulo recua (leveza do mock). O min-width alinha
   os rótulos numa coluna; grail (95/403) precisa de mais largura que backups. */
.stat-row { display: flex; align-items: baseline; gap: 0.6rem; }
.stat-num { font-family: var(--font-mono); font-size: 0.9rem; color: var(--text); flex: none; }
.stat-label { color: var(--muted); }
.grail-stats .stat-num { min-width: 4.25rem; }
.backup-stats .stat-num { min-width: 1.75rem; }

/* Caixa de upload arrastar-e-soltar (dashboard). Borda tracejada; o clique
   inteiro cai no <label>/link — o padding mora no .dropzone-inner, não na
   borda. Estado is-dragging (JS) acende como o hover. NÃO mover este bloco para
   ANTES de .card no fonte: o dashboard usa `class="dropzone card"`, mesma
   especificidade (0,1,0) — quem sobrepõe bg/border/padding é a ordem, .dropzone
   tem que vir depois. */
.dropzone {
  padding: 0; display: grid; background: var(--landing-band);
  border: 1px dashed var(--border-4); border-radius: 14px;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.dropzone:hover, .dropzone.is-dragging { border-color: var(--gold-border); background: var(--bg-secondary); }
.dropzone.is-dragging { border-style: solid; }
/* .dropzone é grid de célula única → o inner (label/link) estica pra altura
   toda do card (que o grid externo iguala à do vizinho), e o justify-content
   centra o conteúdo — sem depender de height:100%. */
.dropzone-inner {
  display: flex; flex-direction: column; justify-content: center; gap: 0.7rem;
  padding: 1.4rem 1.5rem; cursor: pointer; text-decoration: none;
}
.dropzone-head { display: flex; align-items: center; gap: 0.8rem; }
.dropzone-icon {
  width: 40px; height: 40px; flex: none; border-radius: 9px;
  border: 1px solid var(--border-4); color: var(--gold);
  display: inline-flex; align-items: center; justify-content: center;
}
.dropzone-icon svg { width: 18px; height: 18px; }
.dropzone-title { font-family: var(--font-serif); font-size: 1.3rem; color: var(--text); }
.dropzone-hint { font-size: 0.85rem; color: var(--muted); line-height: 1.5; }
.dropzone-hint code { color: var(--text-tertiary); }
/* Input escondido mas acessível — o clique no <label> abre o seletor nativo. */
.dropzone-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }

/* Variante full-width da página /upload: ocupa a largura toda, mais alta pra
   ser um alvo de drop confortável, conteúdo centrado (ícone + título + hint). */
.dropzone--page { margin: 1.5rem 0; min-height: 11rem; }
.dropzone--page .dropzone-inner { align-items: center; text-align: center; }

.form-errors {
  color: var(--red); border: 1px solid var(--red); border-radius: 4px;
  padding: 0.5rem 0.75rem 0.5rem 2rem; max-width: 20rem;
}

.auth-form { display: flex; flex-direction: column; gap: 0.5rem; max-width: 20rem; }
.auth-form input, .auth-form textarea, .auth-form select {
  background: var(--surface-raised); color: var(--text-secondary);
  border: 1px solid var(--border-3); border-radius: 7px; padding: 0.45rem 0.7rem; font: inherit;
}
.auth-form input[type="submit"] { cursor: pointer; color: var(--gold); }

/* "Sign in with Google" (issue #98): divisor "ou" + botão social nas telas de
   auth, e a linha de conta conectada nas settings. O "G" mantém as cores oficiais
   (SVG inline); o botão segue a paleta do site (sem fundo branco no tema escuro). */
.auth-alt { max-width: 20rem; }
.auth-divider { display: flex; align-items: center; gap: 0.75rem; color: var(--muted); font-size: 0.85rem; margin: 1.1rem 0; }
.auth-divider::before, .auth-divider::after { content: ""; flex: 1; height: 1px; background: var(--border-3); }
.google-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  padding: 0.5rem 1rem; cursor: pointer; font: inherit;
  background: var(--surface-raised); color: var(--text);
  border: 1px solid var(--border-3); border-radius: 7px;
}
.google-btn:hover { border-color: var(--muted); }
.google-g { flex: none; }
.auth-alt form.button_to { margin: 0; }
.auth-alt .google-btn { width: 100%; }

/* Settings → Contas conectadas: provedor à esquerda, status/ação à direita. */
.connection { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.connection form.button_to { margin: 0; }
.connection-provider { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--text); }
.connection-status { color: var(--muted); font-size: 0.9rem; }
.connection-action { cursor: pointer; font: inherit; }

/* Feedback (UI-7c): rótulo empilhado sobre o controle; caixa de mensagem mais
   larga que os forms de auth e redimensionável na vertical. */
.feedback-form { max-width: 32rem; }
.feedback-form label { display: flex; flex-direction: column; gap: 0.25rem; }
.feedback-form textarea { resize: vertical; }

/* Settings (issues #39/#16): seções empilhadas (mesmo idioma do /devices) +
   a zona de perigo destacada em vermelho. */
.settings-section { margin: 1.75rem 0; }
.settings-account { margin: 0 0 1.25rem; }
.settings-account div { display: flex; gap: 0.75rem; padding: 0.15rem 0; }
.settings-account dt { color: var(--muted); min-width: 9rem; flex: none; }
.settings-account dd { margin: 0; color: var(--text-secondary); }
.settings-locale { display: flex; align-items: flex-end; gap: 0.5rem; flex-wrap: wrap; }
.settings-locale label { display: flex; flex-direction: column; gap: 0.25rem; }
.settings-locale select {
  background: var(--surface-raised); color: var(--text-secondary);
  border: 1px solid var(--border-3); border-radius: 7px; padding: 0.45rem 0.7rem; font: inherit;
}
.settings-locale input[type="submit"] {
  cursor: pointer; color: var(--gold); background: none;
  border: 1px solid var(--border-3); border-radius: 7px; padding: 0.45rem 0.9rem; font: inherit;
}
/* Zona de perigo: card em vermelho — a deleção é irreversível. */
.danger-zone {
  border: 1px solid var(--red); border-radius: 14px;
  padding: 1.25rem 1.5rem; background: var(--bg-secondary);
}
.danger-zone h2 { color: var(--red); margin-top: 0; }
.button-danger {
  display: inline-block; padding: 0.55rem 1.35rem; border-radius: 7px;
  border: 1px solid var(--red); color: var(--red); text-decoration: none;
}
.button-danger:hover { background: var(--red); color: var(--bg); }
.settings-delete-list { color: var(--text-secondary); max-width: 32rem; }
.settings-delete-form { margin-top: 1.25rem; }
.settings-delete-submit { color: var(--red) !important; border-color: var(--red) !important; }
h1 { font-family: var(--font-serif); font-weight: 700; letter-spacing: 0.01em; color: var(--text); }
h1 small { color: var(--muted); font-size: 0.55em; font-weight: normal; }
h2, h3 { font-family: var(--font-serif); color: var(--gold); }
h2 { font-weight: 600; }
h3 { font-weight: 600; margin-bottom: 0.25rem; }
code { font-family: var(--font-mono); color: var(--muted); }
/* .meta é texto secundário genérico (inclui frases descritivas) → sans muted.
   O mono fica reservado a tokens curtos: tags/chips, th, toggles/pills, código. */
.meta, .empty { color: var(--muted); }

table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 0.4rem 0.75rem 0.4rem 0; border-bottom: 1px solid var(--border); }
th { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted-2); font-weight: normal; }

dl.attributes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.25rem 1.5rem; margin: 0; }
dl.attributes div { display: flex; justify-content: space-between; gap: 1rem; border-bottom: 1px solid var(--border); }
dl.attributes dt { color: var(--muted); }
dl.attributes dd { margin: 0; font-family: var(--font-mono); text-align: right; }
/* Atributo decomposto: total (linha de cima) sobre "base N · +M itens" menor. */
.attr-value { display: inline-flex; flex-direction: column; align-items: flex-end; }
.attr-breakdown { font-size: 0.68rem; color: var(--muted-2); }

/* Advanced stats (issue #47): espelho do painel do jogo na aba Atributos —
   somas CRUAS dos itens (set de armas ativo + charms), cada linha já no texto
   do próprio jogo. Cabeçalho dourado como as seções de skill; lista densa
   multi-coluna na cor de props do inspetor. */
.advanced-stats { margin-top: 1.75rem; }
.advanced-stats h3 { margin: 0 0 0.6rem; padding-bottom: 0.35rem; border-bottom: 1px solid var(--gold-border); }
.advanced-stats-list { columns: 3; column-gap: 1.75rem; list-style: none; padding: 0; margin: 0; color: var(--prop-color); }
.advanced-stats-list li { break-inside: avoid; padding: 0.15rem 0; font-size: 0.9rem; }

/* Combate e Resistências (issue #47, fase 2): totais derivados na aba Atributos.
   Cabeçalhos dourados como as demais seções. Resistências numa grade densa —
   valor capado em destaque sobre "/ max", o raw no title (tooltip nativo, sem
   JS). Neutro: o design-system não define cor canônica por elemento. */
.combat-block, .resist-block { margin-top: 1.75rem; }
.combat-block h3, .resist-block h3 { margin: 0 0 0.6rem; padding-bottom: 0.35rem; border-bottom: 1px solid var(--gold-border); }
.resist-list { list-style: none; padding: 0; margin: 0.75rem 0 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.35rem 1.5rem; }
.resist { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding: 0.15rem 0; border-bottom: 1px solid var(--border); }
.resist-name { color: var(--muted); }
.resist-value { font-family: var(--font-mono); text-align: right; white-space: nowrap; }
.resist-current { font-size: 1.05rem; color: var(--text); }
.resist-max { color: var(--muted-2); font-size: 0.8rem; }
.resist-note { margin: 0.85rem 0 0; font-size: 0.72rem; }

/* Breakpoints (issue #102): FCR/FHR/FBR do personagem na aba Atributos — total
   atual + a escada de tiers em colunas %/frames (a wiki condensada, coluna atual
   acesa) e o próximo alvo numa subline, com deep-link à calculadora. Mesmo
   cabeçalho dourado das seções vizinhas. */
.breakpoints-block { margin-top: 1.75rem; }
.breakpoints-block h3 { margin: 0 0 0.6rem; padding-bottom: 0.35rem; border-bottom: 1px solid var(--gold-border); }
.breakpoint-list { list-style: none; padding: 0; margin: 0.75rem 0 0; }
.breakpoint { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem; padding: 0.55rem 0; border-bottom: 1px solid var(--border); }
.breakpoint-mode { color: var(--muted); min-width: 9.5rem; }
.breakpoint-total { font-family: var(--font-mono); font-size: 1.05rem; color: var(--text); min-width: 2.75rem; }
.breakpoint-body { flex: 1 1 15rem; }
/* Escada em block com colunas inline-block: cada coluna é um átomo que expõe a
   linha de FRAMES (sua última linha) como baseline. Assim o frame atual assenta
   na MESMA linha do rótulo/total, o % flutua acima desse eixo e a subline desce
   abaixo — o eixo da row passa pelos frames, não pelo topo do bloco. */
.breakpoint-ladder { line-height: 1.15; }
.breakpoint-step { display: inline-block; vertical-align: baseline; text-align: center; margin: 0 0.6rem 0.2rem 0; }
.breakpoint-req { display: block; font-size: 0.7rem; line-height: 1.2; color: var(--muted-2); }
.breakpoint-fps { display: block; font-family: var(--font-mono); font-size: 0.9rem; color: var(--muted); }
.breakpoint-step.is-current .breakpoint-req { color: var(--gold); }
.breakpoint-step.is-current .breakpoint-fps { color: var(--gold); font-weight: 700; }
.breakpoint-next { display: block; margin-top: 0.2rem; font-size: 0.78rem; color: var(--muted); }
.breakpoint-next--maxed { color: var(--gold); }
.breakpoint-ias-note { flex: 1 1 15rem; font-size: 0.85rem; color: var(--muted); }
.breakpoint-calc { white-space: nowrap; }
.breakpoint-note { margin: 0.85rem 0 0; font-size: 0.72rem; }

ul.skills { columns: 3; padding-left: 1.25rem; margin: 0; }

/* Aba Skills (issue #19): árvore completa da classe. Os 3 grupos (abas da
   classe) fluem em colunas via auto-fit — 3 quando cabe, menos ao estreitar,
   sem media query. Cada linha espelha o attr-value: total grande + subline
   "base N · +M items". */
.skill-tree { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem 1.75rem; margin-bottom: 1.5rem; }
.skill-group h3 { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; margin: 0 0 0.4rem; padding-bottom: 0.35rem; border-bottom: 1px solid var(--gold-border); }
.skill-group-points { font-family: var(--font-mono); font-size: 0.8rem; font-weight: normal; color: var(--muted); }
.skill-list { list-style: none; padding: 0; margin: 0; }
.skill { display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem; padding: 0.35rem 0; border-bottom: 1px solid var(--border); }
/* Skill não aprendida: presente (lê-se a árvore como "o que é possível") mas apagada. */
.skill-unlearned { opacity: 0.45; }
.skill-info { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.skill-name { color: var(--text); }
.skill-desc { font-size: 0.72rem; line-height: 1.3; color: var(--muted); }
.skill-value { display: inline-flex; flex-direction: column; align-items: flex-end; flex: none; font-family: var(--font-mono); }
.skill-total { font-size: 1.05rem; color: var(--text); }
.skill-breakdown, .skill-req { font-size: 0.68rem; color: var(--muted-2); }
/* Skill vira gatilho do inspetor (#46): o tile inteiro é o botão, mesmo layout
   flex de duas colunas (o reset vem de .item-trigger). Affordance discreta: só
   o nome sublinha no hover, não a linha inteira. Zero mudança em repouso. */
.skill-trigger { display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem; flex: 1; min-width: 0; }
.skill-list .item-trigger:hover { text-decoration: none; }
.skill-list .item-trigger:hover .skill-name { text-decoration: underline; }

/* --- Aba Skills · Tree view (#64) ------------------------------------------
   Toggle Tree/List no cabeçalho + a árvore posicional (grid 3×6) espelhando o
   jogo. O grid da .skill-canvas casa EM PX com o SVG de dependências gerado no
   server (SkillTreeHelper): repeat(3, 66px) × auto-rows 65px, gap 30/40 — se um
   mudar, o outro muda junto. O tile é o ícone da skill downscaled (#94); sem webp
   da skill o tile de texto usa a MESMA célula. */
.skills-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem; }
.skills-head h2 { margin: 0; }
.skills-head .skill-view-toggle { margin-bottom: 0; }
.skill-view-eyebrow { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted-3); }

/* Tree ↔ List e a troca de aba: só a visibilidade muda (Stimulus); fade sutil de
   entrada ao (re)exibir o bloco. */
.skill-tree-view, .skill-list-view { animation: skillFade 0.18s ease; }

/* Tab bar das árvores: nome serif + pontos mono; ativa com sublinhado dourado. */
.skill-tree-tabs { display: flex; gap: 0.4rem; border-bottom: 1px solid var(--border-2); margin-bottom: 1.75rem; flex-wrap: wrap; }
.skill-tree-tab {
  display: inline-flex; align-items: baseline; gap: 0.5rem;
  background: none; border: 0; border-bottom: 2px solid transparent;
  margin: 0 0 -1px; padding: 0.5rem 0.75rem; cursor: pointer; color: var(--muted-2);
}
.skill-tree-tab-name { font-family: var(--font-serif); font-weight: 600; font-size: 1.1rem; letter-spacing: 0.01em; }
.skill-tree-tab-points { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted-3); }
.skill-tree-tab.active { border-bottom-color: var(--gold); color: var(--text); }
.skill-tree-tab.active .skill-tree-tab-points { color: var(--muted); }
.skill-tree-tab:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; border-radius: 4px; }

/* Canvas rolável em telas estreitas (mesmo padrão do .table-scroll — a PÁGINA
   nunca rola na horizontal; o canvas de 476px rola dentro do próprio wrapper). O
   padding dá folga para a sombra dos tiles aprendidos (overflow-x:auto também
   recorta no eixo y). */
.skill-canvas-scroll { overflow-x: auto; padding: 10px 16px 20px; }
.skill-canvas {
  position: relative; width: 278px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(3, 66px); grid-auto-rows: 65px;
  gap: 30px 40px; animation: skillTreeIn 0.22s ease;
}

/* Posição do tile no grid — utilitárias (a CSP bloqueia style inline). */
.skill-canvas .gc-1 { grid-column: 1; }
.skill-canvas .gc-2 { grid-column: 2; }
.skill-canvas .gc-3 { grid-column: 3; }
.skill-canvas .gr-1 { grid-row: 1; }
.skill-canvas .gr-2 { grid-row: 2; }
.skill-canvas .gr-3 { grid-row: 3; }
.skill-canvas .gr-4 { grid-row: 4; }
.skill-canvas .gr-5 { grid-row: 5; }
.skill-canvas .gr-6 { grid-row: 6; }

/* SVG de dependências: sob os tiles, sem capturar clique. A seta herda a cor da
   linha (marker fill=context-stroke). */
.skill-tree-lines { position: absolute; inset: 0; overflow: visible; pointer-events: none; z-index: 0; }
.skill-tree-line { stroke-width: 2; }
.skill-tree-line--lit { stroke: var(--skill-line-lit); }
.skill-tree-line--dim { stroke: var(--skill-line-dim); }

/* O tile é o skill_trigger (#46) com outro conteúdo (nome + badge). Sobrepõe o
   layout flex de duas colunas do .skill-trigger (descendente vence). */
.skill-canvas .skill-tile {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.2rem; text-align: center; border-radius: 9px; padding: 0.35rem 0.5rem;
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.skill-canvas .skill-tile:hover { text-decoration: none; transform: translateY(-1px); }
.skill-tile-name { font-family: var(--font-serif); font-weight: 600; font-size: 0.84rem; line-height: 1.15; }
.skill-tile-badge { font-family: var(--font-mono); }

/* As variantes precisam do prefixo .skill-canvas: com uma classe só, o reset
   do .item-trigger (background none/border 0, definido DEPOIS no arquivo)
   empata em especificidade e vence — o tile ficava sem fundo nem borda. */
.skill-canvas .skill-tile--learned { background: linear-gradient(#211d17, #191510); border: 1px solid var(--gold-border); box-shadow: 0 0 0 1px rgba(198, 160, 90, 0.08), 0 6px 16px rgba(0, 0, 0, 0.5); }
.skill-tile--learned .skill-tile-name { color: var(--text); }
.skill-tile--learned .skill-tile-badge { font-size: 0.72rem; color: var(--gold); background: #2a2314; border-radius: 5px; padding: 0.05rem 0.4rem; }

.skill-canvas .skill-tile--locked { background: var(--bg-tertiary); border: 1px solid var(--border); }
.skill-tile--locked .skill-tile-name { color: var(--muted-2); }
.skill-tile--locked .skill-tile-badge { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-3); }
.skill-tile-badge--passive { font-size: 0.9rem; letter-spacing: 0; }

/* Tile-ÍCONE (#94): o webp (moldura de bronze embutida) É o tile — sem fundo/borda
   de card (a moldura já é a borda), sem padding, para a arte preencher a célula. As
   regras --learned/--locked acima definem fundo/borda; estas vêm DEPOIS e, na mesma
   especificidade, vencem. O nome vai pro aria-label do botão; o badge sobrepõe o
   canto inferior direito, como no jogo. */
.skill-canvas .skill-tile--icon { padding: 0; gap: 0; background: none; border: 0; box-shadow: none; }
.skill-tile-icon { display: block; width: 100%; height: 100%; }
.skill-tile-icon img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* Badge de pontos FORA da moldura (como no painel do jogo): caixinha escura, número
   em gold, ancorada rente ao canto inferior direito, vazando pro gap entre colunas
   (GX=40 comporta) — nunca cobre a arte. Só o tile-ícone APRENDIDO tem badge; o
   locked em modo ícone fica só com o ícone escuro (o nível-req vai pro title/aria). */
.skill-tile--icon .skill-tile-badge {
  position: absolute; left: calc(100% + 3px); bottom: 0;
  padding: 0.02rem 0.28rem; border-radius: 4px;
  border: 1px solid var(--gold-border); background: rgba(10, 8, 4, 0.92);
  color: var(--gold); font-size: 0.66rem; line-height: 1.3; letter-spacing: 0;
  text-transform: none; white-space: nowrap;
}

/* Locked: a MESMA arte dessaturada/escurecida (padrão análogo à runa não-possuída em
   .rune-missing .item-icon--img img), SEM badge. */
.skill-tile--icon.skill-tile--locked .skill-tile-icon img {
  filter: grayscale(1) brightness(0.5);
  opacity: 0.55;
}

/* Rodapé "N points spent" por aba. */
.skill-tree-footer { max-width: 278px; margin: 1.75rem auto 0; border-top: 1px solid var(--border-2); padding-top: 0.85rem; text-align: center; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }

@keyframes skillFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes skillTreeIn { from { opacity: 0; transform: translateY(6px) scale(0.99); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .skill-tree-view, .skill-list-view, .skill-canvas { animation: none; }
  .skill-canvas .skill-tile, .skill-canvas .skill-tile:hover { transition: none; transform: none; }
}

ul.items { list-style: none; padding: 0; margin: 0 0 1rem; }
ul.items.columns { columns: 3; }
/* Stack zerado nas abas de materiais: como no jogo, presente mas apagado.
   Escopado a .columns para não apagar itens comuns (todo item v102+ carrega
   o campo com 0). */
ul.items.columns li.stack-empty { opacity: 0.35; }
h4 { color: var(--muted); font-weight: normal; margin: 0.5rem 0 0.25rem; }
ul.items > li { padding: 0.15rem 0; }
ul.sockets { list-style: none; padding-left: 1.5rem; color: var(--muted); }
ul.sockets li::before { content: "◈ "; }

/* Glifo de item (iconografia autoral, SVG inline): dimensiona pela fonte e
   herda a cor do texto via currentColor — runa apagada apaga o glifo junto.
   O "tile" de pedra (lote 1.5) dá a leitura instantânea de "isto é uma runa",
   como nos sites de referência — a pedra é conceito genérico, o glifo é nosso. */
.item-icon {
  display: inline-flex;
  padding: 0.14em;
  background: linear-gradient(145deg, #343139 55%, #26242b);
  border: 1px solid #403d47;
  border-radius: 22%;
  vertical-align: -0.1em;
}
.item-icon svg { width: 0.9em; height: 0.9em; }

/* Ícone do jogo (PNG, issue #83): a pedra do jogo tem forma e alpha próprios —
   ela É o ícone, sem moldura. Diferente do SVG, NÃO herda o "tile" de chip do
   .item-icon (zera padding/background/border): flutua solta e maior (1.5em) pra
   ganhar destaque. O wrapper carrega o tamanho; a img preenche 100% dele. Ancorada
   ao meio da linha (a caixa de 1.5em é mais alta que o texto do título). */
.item-icon--img {
  width: 1.5em; height: 1.5em;
  padding: 0; background: none; border: none; border-radius: 0;
  vertical-align: middle;
}
.item-icon--img img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* Itens de 1×2 células (chaves pk*, troféus ua*): a arte é 2× mais alta que larga.
   No quadrado de 1.5em o object-fit: contain os deixava finos (~0.75em de largura);
   o wrapper mais alto devolve presença, e a img segue contain (agora limitada pela
   largura → ~1em × 2em). Marcado no servidor: ItemIconsHelper lê a proporção do PNG,
   porque CSS puro não mede a imagem. */
.item-icon--tall { height: 2em; }

/* Gema na LISTAGEM parecia levemente pequena ao lado do texto (feedback lote 2):
   sobe ~6,7% (1.6em) só no contexto de listagem (.item-trigger — stash, characters,
   search, grail). A modal do inspetor não mostra mais glifo no header (#87), então
   o ajuste fica escopado à listagem. Runas e materiais seguem em 1.5em. */
.item-trigger .item-icon--gems { width: 1.6em; height: 1.6em; }

/* Centragem vertical da pedra do jogo (#83). A pedra PNG é 1.5em, mais alta que o
   texto ao lado: em todo wrapper onde ela divide a linha com o nome, o wrapper vira
   flex centrado — senão a pedra assenta na baseline (contexto flex) ou no x-height
   (inline) e sobe em relação ao texto. Refino de elemento compartilhado → vai na
   BASE, disparado só pela pedra via :has(.item-icon--img): chip SVG e itens sem
   pedra ficam intactos. Wrappers que já centram por conta própria (.rwcat-rune,
   .inspector-socket, .wcube-input, .rwcat-rune-row, .rwcat-rune-btn) não precisam.
   Cobre: título de card (.item-trigger: stash/grail/characters/inspector), inputs
   de receita (.rune-chain > span) e elegíveis do cube (.wcube-eligible-item). */
.item-trigger:has(> .item-icon--img),
.rune-chain > span:has(.item-icon--img),
.wcube-eligible-item:has(.item-icon--img) {
  display: inline-flex; align-items: center; gap: 0.3rem;
}
/* Soquetes: cada runa/gema numa linha própria (bloco), então a li é flex (não
   inline-flex) pra empilhar; o ◈ do ::before, o glifo e o nome centram juntos. */
ul.sockets li:has(.item-icon--img) {
  display: flex; align-items: center; gap: 0.3rem;
}

/* Runa não-possuída (stash com stack 0, input de receita faltando): o PNG do jogo
   não "apaga" pela cor do texto como o SVG (currentColor) — recebe um tratamento
   próprio de cinza + escuro, nos MESMOS contêineres que apagam o SVG
   (.stack-empty, .rune-missing). Runa possuída fica plena, sem filter. */
.stack-empty .item-icon--img img,
.rune-missing .item-icon--img img {
  filter: grayscale(1) brightness(0.55);
  opacity: 0.55;
}

.slot { color: var(--muted); }
.tag { font-family: var(--font-mono); font-size: 0.7em; color: var(--muted-2); border: 1px solid var(--border-3); border-radius: 4px; padding: 0.05em 0.4em; margin-left: 0.3em; }
.tag-dead { color: var(--red); border-color: var(--red); }
.tag-on { color: var(--green); border-color: var(--green); }
.tag-off { color: var(--muted); border-color: var(--border); }

/* Aviso em faixa (login/download indisponível, upload manual desligado). */
.notice-banner {
  display: flex; align-items: center; gap: 1rem;
  border: 1px solid var(--orange); border-radius: 4px; color: var(--orange);
  padding: 0.5rem 0.75rem; margin-bottom: 1rem;
}

.q-magic { color: var(--blue); }
.q-rare { color: var(--rare-new); }
.q-set { color: var(--green); }
.q-unique { color: var(--gold); }
.q-crafted { color: var(--orange); }
.q-rune { color: var(--rune-new); }
/* Runeword: dourado mais claro que unique + chip "runeword" para desambiguar. */
.q-runeword { color: var(--gold-light); }
.q-inferior, .q-normal, .q-superior { color: var(--base-new); }

/* Runewords (Fase 3b): corrente de runas — acesa = a conta tem estoque para
   aquela posição, apagada = falta (mesma semântica do stack-empty do stash). */
ul.runewords { list-style: none; padding: 0; margin: 0 0 1.5rem; display: grid; gap: 0.45rem; }
.runeword-row {
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 9px;
  padding: 0.55rem 0.9rem;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 1rem;
}
.runeword-name { min-width: 9rem; font-family: var(--font-serif); }
.rune-chain { display: inline-flex; flex-wrap: wrap; gap: 0.4rem; }
.rune-chain .rune-missing { opacity: 0.35; }
.tag-ready { color: var(--green); border-color: var(--green); }
/* Linha própria dentro do runeword-row (flex): ocupa a largura toda. */
.cube-eligible { flex-basis: 100%; }

/* Receitas do cubo (issue #11): nome+badge = "head". No desktop é uma linha
   flexível; no mobile (bloco ≤48rem) a .runeword-row vira coluna. O status
   ready/missing das runewords vive agora no catálogo /wiki/runewords, como
   .rwcat-own (issue #62). */
.rw-head { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 0.4rem; }

/* Soquetes (UI-7b): nesting expansível — as runas/gemas socketadas ficam
   recolhidas atrás de um resumo com a contagem, como no mock do stash. */
/* Soquetes = rodapé do card (issue #85): separador sutil, mono muted, "◈ N sockets".
   TODO item com soquetes tem rodapé — expansível (<details>, clique lista o que está
   engastado) quando há itens; linha simples (.socket-list--empty) quando os soquetes
   estão vazios, mesmo visual sem cursor/expandir. A fonte fica no summary/linha (não no
   <details>) pra a lista ul.sockets não herdar o mono do rótulo. */
details.socket-list,
.socket-list--empty { margin: 0.55rem 0 0; padding-top: 0.4rem; border-top: 1px solid var(--border); }
details.socket-list > summary,
.socket-list--empty { font-family: var(--font-mono); font-size: 0.7rem; color: var(--muted); }
details.socket-list > summary { list-style: none; cursor: pointer; }
details.socket-list > summary::-webkit-details-marker { display: none; }
details.socket-list > summary::before,
.socket-list--empty::before { content: "◈ "; }
details.socket-list ul.sockets { padding-left: 0.75rem; margin-top: 0.3rem; }

/* Characters (UI-7b): tabela no desktop; no mobile (≤48rem) a tabela some e
   entram cards — a linha vira nome + nível, classe · modo, save · snapshots. */
.character-cards { display: none; }
.character-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 9px; padding: 0.85rem 1rem; }
.character-card-top { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.character-card-name { font-family: var(--font-serif); font-size: 1.05rem; color: var(--gold-hover); text-decoration: none; }
.character-card-level { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-tertiary); white-space: nowrap; }
.character-card-sub { color: var(--muted); font-size: 0.85rem; margin-top: 0.35rem; }
.character-card-meta { font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted-2); margin-top: 0.35rem; }
.character-card-ident { display: inline-flex; align-items: center; gap: 0.6rem; min-width: 0; }

/* ── Classes de personagem: sigilos autorais + cor por classe ──────────────
   Import do design (Characters.dc.html / ClassGlyph.dc.html). Cada .cls-<slug>
   injeta só a cor da classe (--cc), em oklch harmonizado (L/C próximos, matiz
   ao redor da roda). Tile e rótulo consomem --cc; sem .cls-* nada é colorido. */
.cls-amazon      { --cc: oklch(0.76 0.14 55); }   /* laranja-brasa */
.cls-assassin    { --cc: oklch(0.70 0.15 350); }  /* violeta-carmim */
.cls-barbarian   { --cc: oklch(0.67 0.17 28); }   /* vermelho-guerra */
.cls-druid       { --cc: oklch(0.73 0.13 150); }  /* verde-floresta */
.cls-necromancer { --cc: oklch(0.76 0.045 255); } /* aço-osso */
.cls-paladin     { --cc: oklch(0.82 0.13 90); }   /* âmbar-sagrado */
.cls-sorceress   { --cc: oklch(0.73 0.12 235); }  /* azul-gélido */
.cls-warlock     { --cc: oklch(0.69 0.14 305); }  /* violeta-arcano */

.class-glyph {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 1.75rem; height: 1.75rem;   /* 28px; contexto ajusta abaixo */
  border-radius: 5px; color: var(--cc);
  background: color-mix(in oklab, var(--cc) 15%, var(--bg-secondary));
  border: 1px solid color-mix(in oklab, var(--cc) 40%, var(--bg-secondary));
}
.class-glyph svg { width: 66%; height: 66%; }
.entry-list .class-glyph { width: 1.5rem; height: 1.5rem; }  /* dashboard: mais compacto */

/* Retrato-bolha de classe (lote 3, webp): já é redondo com anel dourado próprio,
   então sem chip (fundo/borda/raio zerados) — a arte É o ícone, flutua solta e
   generosa. object-fit: contain preserva o círculo dentro da caixa quadrada. */
.class-glyph--img {
  background: none; border: none; border-radius: 0; padding: 0;
  width: 2.75rem; height: 2.75rem;
}
.class-glyph--img img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Escopos: a arte pede mais presença que o sigilo — vence os tamanhos por contexto
   com a mesma especificidade (0,2,0). */
.entry-list .class-glyph--img { width: 2.6rem; height: 2.6rem; }        /* dashboard */
.char-ident .class-glyph--img { width: 2.4rem; height: 2.4rem; }        /* tabela de personagens */
.character-card-ident .class-glyph--img { width: 2.6rem; height: 2.6rem; }  /* cards mobile */
/* Peso normal (não 500): a cor já separa a classe do modo muted; em 500 o
   rótulo lê ~5% mais "gordo" que o mock. */
.class-label { color: var(--cc); font-weight: 400; }

/* Modo: hardcore acende no vermelho-tijolo; softcore fica muted, como o mock. */
.mode { color: var(--muted); }
.mode.hardcore { color: var(--hardcore); }

/* ── Tabela de personagens em painel (revamp do mock) ────────────────────────
   O wrapper .table-scroll vira cartão: fundo, borda e cantos arredondados; a
   tabela sangra até as bordas (padding lateral nas células de ponta). */
.characters-panel { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px; }
/* Escala de tipo do mock: corpo da tabela ~14px (não os 16px do body), nome
   15.5px, cabeçalho 10.5px. Sem isso tudo fica ~10% maior = "pesado". */
table.characters { font-size: 0.9rem; }
table.characters th,
table.characters td { padding: 0.9rem 1rem; border-bottom: 1px solid var(--border-2); }
table.characters thead th { font-size: 0.66rem; letter-spacing: 0.08em; color: var(--muted-3); border-bottom-color: var(--border); }
table.characters .entry-name { font-size: 0.97rem; }
table.characters .col-time { font-size: 0.82rem; }
table.characters th:first-child,
table.characters td:first-child { padding-left: 1.6rem; }
table.characters th:last-child,
table.characters td:last-child { padding-right: 1.6rem; text-align: right; }
table.characters tbody td { vertical-align: middle; }
table.characters tbody tr:last-child td { border-bottom: none; }
/* Headers ordenáveis (issue #24): cada th é um <button> transparente que herda o
   visual do cabeçalho. Seta dourada na coluna ativa (via aria-sort), afundância
   neutra e sutil no hover das inativas. A caixa da seta reserva largura sempre
   (sem shift de layout ao ativar/hover). */
table.characters thead th button {
  appearance: none; -webkit-appearance: none; background: none; border: 0;
  padding: 0; margin: 0; font: inherit; letter-spacing: inherit; color: inherit;
  text-align: inherit; display: inline-flex; align-items: center;
  gap: 0.35rem; cursor: pointer;
}
table.characters thead th button::after {
  content: ""; display: inline-block; width: 0.72em; text-align: center;
  font-size: 0.82em; line-height: 1;
}
table.characters thead th:not([aria-sort]) button:hover::after { content: "↕"; color: var(--muted-3); }
table.characters thead th[aria-sort="ascending"] button::after { content: "▲"; color: var(--gold); }
table.characters thead th[aria-sort="descending"] button::after { content: "▼"; color: var(--gold); }
table.characters thead th button:focus-visible { outline: 1px solid var(--gold-border); outline-offset: 2px; border-radius: 3px; }
.char-ident { display: inline-flex; align-items: center; gap: 0.7rem; }
/* Lista de personagens do dashboard: glifo + uma única linha de texto
   (nome · classe · nível · backup), tudo na mesma base — o glifo centraliza
   contra a linha. */
.dash-char { display: flex; align-items: center; gap: 0.55rem; }
.dash-char-line { min-width: 0; }
.character-head { display: flex; align-items: center; gap: 0.7rem; }
.character-head .class-glyph { width: 1.9rem; height: 1.9rem; align-self: flex-start; margin-top: 0.2rem; }
/* Retrato no cabeçalho do personagem: maior e centrado na linha do título (sem o
   nudge de topo que o sigilo SVG precisava). */
.character-head .class-glyph--img { width: 3.25rem; height: 3.25rem; align-self: center; margin-top: 0; }
.col-mono { font-family: var(--font-mono); }
.col-muted { color: var(--muted); }
.col-num { font-variant-numeric: tabular-nums; }

/* ── Toolbar de filtros da listagem (issue #1) ───────────────────────────────
   Import do design "Characters Final". Filtragem client-side (Stimulus): a barra
   é um painel da mesma família dos cards. Componente nomeado genérico (.filter-*)
   — outras listagens poderão reusar. Larguras/estados sempre via classe/atributo
   (a CSP style-src :self proíbe style=""). */
.filter-bar {
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px;
  padding: 1.125rem 1.25rem; margin-bottom: 1.25rem;
  display: flex; flex-direction: column; gap: 0.9rem;
}
.filter-bar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
/* Linha do nível: divisor interno acima, como no mock. */
.filter-bar-level { border-top: 1px solid var(--border-2); padding-top: 0.9rem; gap: 1rem; }

/* Busca por nome: mesmo idioma da busca do header — lupa + input transparente
   num campo de input. Elemento elástico da linha (comprime primeiro). */
.filter-search {
  flex: 1 1 12.5rem; min-width: 12.5rem;
  display: flex; align-items: center; gap: 0.55rem;
  background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 9px;
  padding: 0.55rem 0.8rem;
}
.filter-search-icon { width: 0.85rem; height: 0.85rem; color: var(--muted-2); flex: none; }
.filter-search-input {
  background: transparent; border: 0; padding: 0; outline: none;
  color: var(--text-secondary); font: inherit; font-size: 0.84rem;
  flex: 1; width: 100%; min-width: 0;
}

/* Select de classe: o color-scheme:dark do :root já escurece o popup nativo. */
.filter-select {
  background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 9px;
  padding: 0.55rem 0.75rem; color: var(--text-secondary); font: inherit; font-size: 0.82rem;
  outline: none; cursor: pointer;
}

/* Segmented control de modo (chips): base do mode-toggle, num trilho. */
.filter-chips {
  display: inline-flex; gap: 0.3rem; padding: 0.25rem;
  background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 9px;
}
.filter-chip {
  cursor: pointer; font-family: var(--font-mono); font-size: 0.75rem;
  padding: 0.35rem 0.75rem; border: 0; border-radius: 6px;
  background: transparent; color: var(--muted);
}
.filter-chip[aria-pressed="true"] { background: #26241c; color: var(--text); }

/* Contador + Reset à direita (margin-left auto). Contador na cor da eyebrow
   (mesmo dourado suave da página); Reset só aparece com filtro ativo. */
.filter-count {
  margin-left: auto; display: flex; align-items: center; gap: 0.75rem;
  font-family: var(--font-mono); font-size: 0.78rem; color: var(--landing-eyebrow);
  white-space: nowrap;
}
.filter-reset {
  cursor: pointer; background: transparent; border: 0; font: inherit; font-size: 0.78rem;
  color: var(--muted); border-bottom: 1px solid var(--border-3); padding: 0 0 1px;
}
.filter-reset:hover { color: var(--text-secondary); }

/* Dual-range de nível — sliders nativos, accent dourado; display normalizado. */
.filter-level-label {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted-3); flex: none; white-space: nowrap;
}
.filter-range { flex: 1 1 10rem; min-width: 10rem; display: flex; align-items: center; gap: 0.55rem; }
.filter-range-label { font-family: var(--font-mono); font-size: 0.62rem; color: var(--muted-2); flex: none; }
.filter-range input[type="range"] { flex: 1; min-width: 0; accent-color: var(--gold); }
.filter-level-display {
  font-family: var(--font-mono); font-size: 0.8rem; color: var(--gold);
  min-width: 6rem; text-align: right; white-space: nowrap;
}

/* Vazio filtrado (dentro do painel da tabela e do bloco de cards): distinto do
   vazio de conta sem personagem (.empty). "Clear filters" = ação do Reset. */
.filter-empty { padding: 2.5rem 1.6rem; text-align: center; font-size: 0.9rem; color: var(--muted-2); }
.filter-clear {
  cursor: pointer; background: transparent; border: 0; font: inherit; font-size: inherit;
  color: var(--gold);
}
.filter-clear:hover { color: var(--gold-hover); }

.mode-toggle { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.25rem; }
.mode-toggle .mode-option {
  font-family: var(--font-mono); color: var(--muted-2); text-decoration: none;
  border: 1px solid var(--border); border-radius: 7px;
  font-size: 0.75rem; padding: 0.3rem 0.7rem;
  /* A opção pode ser <a> OU <button>: sem este reset, o <button> inativo fica
     com o fundo nativo do navegador (pílula cinza) e o rótulo ilegível. */
  background: none; cursor: pointer;
}
.mode-toggle .mode-option.active { background: #26241c; border-color: var(--gold-border); color: var(--text); }
/* Chips de categoria do /search: mesmo idioma do mode-toggle, mas podem ser
   muitos — quebram linha em vez de estourar a largura. */
.search-types { flex-wrap: wrap; gap: 0.5rem; }
/* Abas de página (Fase UI-6): navegação secundária server-side — mesma base
   do mode-toggle, quebra linha como os chips do search. */
.page-tabs { flex-wrap: wrap; gap: 0.5rem; }

/* Central de ajuda (Fase UI-4). */
.help-guides { list-style: none; padding: 0; }
.help-guides li { padding: 0.75rem 0; border-bottom: 1px solid var(--border); }
.help-guides h3 { margin: 0 0 0.25rem; }
.help-guide h2 { margin-top: 1.75rem; }
/* Bloco de código: mesma superfície no guia de ajuda e na referência da API
   (/docs/api) — a regra é da BASE, não um override por página. */
.help-guide pre,
.api-code {
  background: var(--surface-raised); border: 1px solid var(--border-3); border-radius: 7px;
  padding: 0.75rem; overflow-x: auto;
}
.help-guide code { color: var(--gold); }

/* Rodapé site-wide (3 colunas). Sangra até as bordas da coluna via margens
   negativas que cancelam o padding do body (mesmo truque do header). Na landing,
   o body é full-bleed (padding:0), então o fundo escuro cobre a viewport inteira. */
.site-footer {
  background: var(--landing-footer-bg);
  border-top: 1px solid var(--landing-nav-border);
  margin-top: 2.75rem;
}
body.landing-page .site-footer { margin: 0; }
.site-footer-inner { max-width: var(--container); margin: 0 auto; padding: 2.75rem var(--page-pad) 2.5rem; }
.site-footer-top {
  display: flex; justify-content: space-between; gap: 2rem; flex-wrap: wrap;
  margin-bottom: 1.9rem;
}
.site-footer-brand { max-width: 19rem; }
.site-footer-brand .brand-glyph { height: 1.25rem; }
.site-footer-brand .brand-text { font-size: 1.1rem; }
.site-footer-tagline { font-size: 0.8rem; color: var(--muted-2); line-height: 1.6; margin: 0.75rem 0 0; }
.site-footer-cols { display: flex; gap: 3.75rem; flex-wrap: wrap; }
.site-footer-col { display: flex; flex-direction: column; }
.site-footer-col-title {
  font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-3); margin: 0 0 0.9rem; font-weight: 400;
}
.site-footer-col a { font-size: 0.875rem; color: var(--text-tertiary); text-decoration: none; margin-bottom: 0.6rem; }
.site-footer-col a:hover { color: var(--gold); }
/* Coluna "larga" (Recursos): os links fluem em duas sub-colunas balanceadas via
   CSS multi-column — contagens futuras continuam equilibradas sem mexer aqui. */
.site-footer-col-wide .site-footer-col-links { columns: 2; column-gap: 2.5rem; }
.site-footer-col-wide .site-footer-col-links a { display: block; break-inside: avoid; }
/* Barra inferior (UI-7e): seletor de idioma à esquerda, disclaimer à direita —
   uma linha no desktop, empilha (o disclaimer desce) quando não cabe. */
.site-footer-bottom {
  border-top: 1px solid var(--landing-nav-border); padding-top: 1.4rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.25rem 1.5rem; flex-wrap: wrap;
}
.site-footer-lang { display: flex; align-items: center; gap: 0.75rem; flex: none; }
.site-footer-lang-label {
  font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-3);
}
.site-footer-disclaimer {
  margin: 0; flex: 1 1 18rem; text-align: right;
  font-size: 0.75rem; color: var(--muted-3); line-height: 1.6; max-width: none;
}

/* Seletor de idioma (rodapé, site-wide) — popover abre pra CIMA. */
.lang-menu { position: relative; }
.lang-menu-summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.5rem;
  border: 1px solid var(--border-3); border-radius: 7px; padding: 0.4rem 0.75rem;
  font-size: 0.8rem; color: var(--gold);
  background: var(--bg-tertiary);
}
.lang-menu-summary::-webkit-details-marker { display: none; }
.lang-menu-summary:hover { border-color: var(--border-2); }
.lang-menu-current { color: var(--gold); }
.lang-menu-caret { color: var(--muted-2); font-size: 0.85rem; line-height: 1; transition: transform 0.15s ease; }
.lang-menu[open] .lang-menu-caret { transform: rotate(180deg); }
.lang-menu-panel {
  position: absolute; bottom: calc(100% + 0.4rem); left: 0; z-index: 20; min-width: 12rem;
  display: flex; flex-direction: column; padding: 0.35rem;
  background: var(--bg-secondary); border: 1px solid var(--border-2); border-radius: 9px;
  box-shadow: 0 -12px 30px rgba(0, 0, 0, 0.45);
}
.lang-menu-panel form { display: block; }
.lang-menu-option {
  width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  font: inherit; font-size: 0.85rem; color: var(--text-secondary);
  padding: 0.45rem 0.6rem; border-radius: 6px;
}
.lang-menu-option:hover { background: #211f18; color: var(--gold); }
.lang-menu-option.active { color: var(--gold); }
.lang-menu-code { font-family: var(--font-mono); font-size: 0.68rem; color: var(--muted-2); }

@media (max-width: 48rem) {
  .site-footer-cols { gap: 2.25rem; }
  /* Empilhado: o disclaimer desce sob o seletor de idioma e lê alinhado à esq. */
  .site-footer-disclaimer { text-align: left; }
}

/* Páginas legais (Termos/Privacidade): coluna de leitura estreita e ritmo. */
.legal-page { max-width: 68ch; }
.legal-page h2 { margin-top: 1.7rem; }
.legal-page p, .legal-page ul { margin-top: 0.6rem; line-height: 1.6; }
.legal-page ul { padding-left: 1.2rem; }
.legal-page li { margin-top: 0.3rem; }

/* Upload manual (Fase UI-5): a caixa arrastar-e-soltar (.dropzone/.dropzone--page)
   é compartilhada com o dashboard; ver o bloco Dashboard acima. */
.onboarding { margin-bottom: 1.5rem; }
.upload-results { margin-top: 1.5rem; }
.upload-results ul { list-style: none; padding: 0; margin: 0.75rem 0; }
.upload-results li { padding: 0.3rem 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.upload-status.upload-ok { color: var(--green); }
.upload-status.upload-error { color: var(--red); }

/* Busca de itens (Fase UI-3): filtro nas páginas + campo global no header. */
.item-search { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 1rem; }
.item-search input {
  background: var(--surface-raised); color: var(--text-secondary);
  border: 1px solid var(--border-3); border-radius: 7px; padding: 0.45rem 0.7rem; font: inherit;
}
.item-search input[type="search"] { flex: 1; max-width: 20rem; }
.item-search input[type="submit"] { cursor: pointer; color: var(--gold); }

/* Responsividade (Fase UI-1) — a página nunca rola na horizontal;
   tabelas largas rolam dentro do próprio wrapper. */
.table-scroll { overflow-x: auto; }
.table-scroll table { min-width: max-content; width: 100%; }

/* Breakpoint intermediário (issue #12): entre ~768px e o hamburger, aperta gaps
   e fonte da nav pra ganhar espaço antes de qualquer wrap do header. */
@media (max-width: 64rem) {
  .site-header-desktop { gap: 0.6rem; }
  .site-nav { gap: 0.6rem; font-size: 0.85rem; }
}

/* Troca desktop↔hamburger do HEADER (issue #12) — media query PRÓPRIO, dissociado
   dos demais blocos de 48rem do site (tabelas/cards etc. seguem em 48rem). Fica em
   58rem: com "Stash" no pt-BR E no es (decisão do Filipe, 2026-07-08), o locale
   mais largo passa a ser o francês ("Personnages"), que quebra a linha desktop até
   912px; 58rem (928px) mantém ≥16px de folga acima desse crossover, garantindo ZERO
   wrap no desktop em todos os idiomas — e janela de meia-tela em monitor 1920
   (960px) fica com o nav desktop (medido: fr 912 · de 908 · en 900 · pt-BR/es ~864). */
@media (max-width: 58rem) {
  .site-header-desktop { display: none; }
  .site-header-mobile { display: block; }
}

@media (max-width: 48rem) {
  .cards { grid-template-columns: 1fr; }
  .dash-title { font-size: 2.7rem; }
  ul.items.columns, ul.skills, .advanced-stats-list { columns: 2; }
  dl.attributes { grid-template-columns: repeat(2, 1fr); }

  /* Characters: troca tabela → cards (UI-7b). */
  .characters-desktop { display: none; }
  .character-cards { display: flex; flex-direction: column; gap: 0.6rem; }

  /* Runewords & receitas do cubo (issue #11): a linha vira coluna — nome /
     correntes / foot, cada grupo numa linha própria, num padrão consistente
     em vez do flex-wrap desordenado. */
  .runeword-row { flex-direction: column; align-items: stretch; gap: 0.3rem; }
  .runeword-name { min-width: 0; }
}

@media (max-width: 34rem) {
  :root { --page-pad: 1rem; }
  .dash-title { font-size: 2.3rem; }
  ul.items.columns, ul.skills, .advanced-stats-list { columns: 1; }
  dl.attributes { grid-template-columns: 1fr; }

  /* Toolbar de filtros no estreito: busca e select ocupam a linha; cada slider
     ganha a linha cheia; o contador empurra o Reset para a direita. */
  .filter-search, .filter-select { flex-basis: 100%; }
  .filter-count { margin-left: 0; width: 100%; }
  .filter-range { flex-basis: 100%; }
}

/* Área /admin — reaproveita .card/.cards; o stat é só um número grande + rótulo. */
.admin-nav { display: flex; gap: 1rem; margin: 0.5rem 0 1rem; }
.admin-stat { display: flex; flex-direction: column; gap: 0.25rem; text-align: center; }
.admin-stat-value { font-size: 1.8em; font-weight: 600; color: var(--gold); }
.admin-flags, .admin-feedbacks, .admin-users { border-collapse: collapse; width: 100%; margin-top: 1rem; }
.admin-flags th, .admin-flags td,
.admin-users th, .admin-users td,
.admin-feedbacks th, .admin-feedbacks td { text-align: left; padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--border); }
.admin-flags th, .admin-flags td,
.admin-users th, .admin-users td { vertical-align: middle; }
.admin-feedbacks th, .admin-feedbacks td { vertical-align: top; }
/* th herda o padrão do redesign (mono/uppercase/muted-2 do `th` global) —
   sem override próprio, o /admin fala o mesmo idioma das outras tabelas. */
.feedback-message { min-width: 18rem; }
.feedback-message p { margin: 0 0 0.4rem; }
.flag-note-form { display: flex; gap: 0.35rem; align-items: center; }
.flag-note-form input[type="text"] { background: var(--surface-raised); border: 1px solid var(--border-3); color: var(--text-secondary); border-radius: 7px; font: inherit; font-size: 0.85em; padding: 0.2rem 0.4rem; }
.flag-note-form input[type="submit"] { background: none; border: 0; color: var(--gold); font: inherit; font-size: 0.8em; cursor: pointer; }

/* Modal (UI-7d): <dialog> temático, centrado pelo showModal() nativo.
   Componente reutilizável — a Fase INS vai reusar pro modal de item. */
dialog.modal {
  margin: auto; padding: 0; border: 1px solid var(--border-4); border-radius: 12px;
  background: var(--surface-raised); color: var(--text);
  max-width: 26rem; width: calc(100% - 2rem);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
}
dialog.modal::backdrop { background: rgba(0, 0, 0, 0.6); }
.modal-inner { padding: 1.25rem; }
.modal-message { color: var(--text-secondary); margin: 0 0 1.1rem; }
.modal-actions { display: flex; justify-content: flex-end; gap: 0.6rem; margin-top: 0; }
.modal-actions button { font: inherit; cursor: pointer; }
/* Bottom-sheet no mobile: cola embaixo, largura total, cantos só no topo. Precisa
   vir DEPOIS do `dialog.modal` base (mesma especificidade) para vencer por ordem
   de fonte quando o media query casa — senão a base re-centraliza no mobile. */
@media (max-width: 48rem) {
  dialog.modal {
    margin: auto auto 0; width: 100%; max-width: none;
    border-radius: 12px 12px 0 0; max-height: 85vh; overflow: auto;
  }
}

/* Inspetor de item (INS-3 runa/gema, INS-4 item real): reusa o <dialog
   class="modal">, um pouco mais largo que o confirm. Bottom-sheet no mobile já
   vem por herança do .modal; um item real pode ser alto, então limita a altura
   e rola o próprio diálogo (Esc/backdrop fecham). */
dialog.modal.item-inspector { max-width: 29rem; max-height: 85vh; overflow: auto; }
.item-inspector .modal-inner { position: relative; }
/* Marcador de identidade (#30): recorte que o hover-preview clona. No modal é
   transparente ao layout (display:contents) — não muda nada visualmente. */
.inspector-identity { display: contents; }
.inspector-close { position: absolute; top: 0.4rem; right: 0.55rem; margin: 0; }
.inspector-close button {
  background: none; border: 0; color: var(--muted-2); font-size: 1.5rem;
  line-height: 1; cursor: pointer; padding: 0.1rem 0.35rem;
}
.inspector-close button:hover, .inspector-close button:focus-visible { color: var(--text); }

.inspector-head { display: flex; align-items: center; gap: 0.7rem; margin: 0 1.5rem 1rem 0; }
.inspector-name { font-family: var(--font-serif); font-size: 1.15rem; display: block; }
.inspector-sub { color: var(--muted); font-size: 0.82rem; }
/* Descrição longa da skill (#46): parágrafo legível abaixo do cabeçalho. */
.inspector-skill-desc { margin: 0 0 1rem; color: var(--text-secondary); font-size: 0.9rem; line-height: 1.4; }

/* Painel de arte do jogo (lote 3) — COMPARTILHADO entre card do stash, item do
   personagem e modal do inspetor: fundo sutil que recua (--bg, mais fundo que a
   superfície), proporção NATIVA preservada (width/height auto sob tetos). Só o teto
   da imagem muda por contexto. */
.item-art-panel {
  margin: 0; flex: none; display: flex; align-items: center; justify-content: center;
  background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem;
}
.item-art-panel img { display: block; width: auto; height: auto; max-width: 5rem; max-height: 9.5rem; }

/* Modal: à esquerda do miolo, com o título já no topo em largura cheia (a casca
   divide só o que vem abaixo). A arte da modal respira um pouco mais que a do card. */
.inspector-art-shell { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 1rem; align-items: start; }
.inspector-art img { max-width: 6.5rem; max-height: 11rem; }
/* No hover-preview (tooltip compacto) a arte grande não entra — só o texto; a
   casca colapsa para uma coluna. */
.hover-preview-body .inspector-art { display: none; }
.hover-preview-body .inspector-art-shell { display: block; }

.inspector-props-title, .inspector-group-label {
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted-2); font-weight: normal;
}
.inspector-props-title { margin: 0 0 0.6rem; }
.inspector-group-label { margin: 0 0 0.25rem; }
.inspector-group + .inspector-group { margin-top: 0.8rem; }
.inspector-props { list-style: none; padding: 0; margin: 0; color: var(--prop-color); }
.inspector-props li { padding: 0.1rem 0; }
/* Bônus parciais de set em verde (item da cor de set), mais específico que a
   cor de prop padrão e que o .q-set global (mesma especificidade, ordem). */
.inspector-props.q-set { color: var(--green); }
/* Socketados e sequência de runas (#61): corrente HORIZONTAL no idioma
   .rune-chain (glifo + nome), quebrando linha naturalmente. Cor de texto neutra. */
.inspector-sockets { color: var(--text-secondary); }
.inspector-socket { display: inline-flex; align-items: center; gap: 0.3rem; }

/* Qualidade de roll (INS-5 p2): onde o valor rolado caiu dentro do range do
   catálogo. A largura da barra vem de uma classe .roll-fill--N (CSP proíbe
   style inline); o % exato fica no texto. */
.inspector-rolls { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.65rem; }
.roll-line { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; color: var(--prop-color); }
.roll-pct { font-family: var(--font-mono); font-size: 0.75rem; color: var(--gold); flex: none; }
.roll-bar { margin-top: 0.3rem; height: 6px; border-radius: 3px; background: var(--surface-raised); border: 1px solid var(--border-3); overflow: hidden; }
.roll-fill { height: 100%; background: var(--gold); }
/* Tom do roll: verde bom (≥80%), dourado ok (≥45%), vermelho fraco. */
.roll-fill.is-high { background: var(--green); }
.roll-pct.is-high { color: var(--green); }
.roll-fill.is-low { background: var(--red); }
.roll-pct.is-low { color: var(--red); }
.roll-range { display: block; margin-top: 0.22rem; font-family: var(--font-mono); font-size: 0.68rem; color: var(--muted); }
.roll-fill--0 { width: 0; }     .roll-fill--5 { width: 5%; }     .roll-fill--10 { width: 10%; }
.roll-fill--15 { width: 15%; }  .roll-fill--20 { width: 20%; }   .roll-fill--25 { width: 25%; }
.roll-fill--30 { width: 30%; }  .roll-fill--35 { width: 35%; }   .roll-fill--40 { width: 40%; }
.roll-fill--45 { width: 45%; }  .roll-fill--50 { width: 50%; }   .roll-fill--55 { width: 55%; }
.roll-fill--60 { width: 60%; }  .roll-fill--65 { width: 65%; }   .roll-fill--70 { width: 70%; }
.roll-fill--75 { width: 75%; }  .roll-fill--80 { width: 80%; }   .roll-fill--85 { width: 85%; }
.roll-fill--90 { width: 90%; }  .roll-fill--95 { width: 95%; }   .roll-fill--100 { width: 100%; }

.inspector-body-props + .inspector-body-props { margin-top: 1rem; }

/* Seções colapsáveis do inspetor (#60): Roll quality e Set bonuses viram
   <details open> nativos (zero JS, CSP-safe). O título mono (h2.inspector-props-title)
   passa a morar no <summary>; um chevron autoral por pseudo-elemento marca o
   estado e rotaciona ao abrir/fechar. Reusa a casca .inspector-body-props (a
   margem entre seções segue valendo — o combinador é por classe). */
.inspector-fold > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 0.5rem;
}
.inspector-fold > summary::-webkit-details-marker { display: none; }
.inspector-fold > summary .inspector-props-title { margin: 0; }
.inspector-fold[open] > summary { margin-bottom: 0.6rem; }
.inspector-fold > summary::after {
  content: ""; flex: none; width: 0.4rem; height: 0.4rem; margin-left: auto;
  border-right: 1.5px solid var(--muted-2); border-bottom: 1.5px solid var(--muted-2);
  transform: rotate(45deg); transition: transform 0.15s ease;
}
.inspector-fold[open] > summary::after { transform: rotate(-135deg); }
.inspector-fold > summary:hover::after { border-color: var(--muted); }

/* Subgrupo colapsável (#61): os tiers da escada de set viram folds aninhados
   dentro do fold de Set bonuses. O chevron do subgrupo é menor e mais apagado
   que o do nível h2, para hierarquizar a leitura. */
.inspector-fold--sub > summary { gap: 0.4rem; }
.inspector-fold--sub > summary::after {
  width: 0.3rem; height: 0.3rem; border-width: 1.25px;
  border-right-color: var(--muted-3); border-bottom-color: var(--muted-3);
}
.inspector-fold--sub[open] > summary { margin-bottom: 0.25rem; }
.inspector-fold--sub > summary:hover::after { border-color: var(--muted-2); }

/* Modal de skill (#46/#49): mais respiro que a modal de item — várias seções
   curtas empilhadas (descrição, nível atual, próximo nível, sinergias). Escopado
   a .skill-inspector para NÃO afetar a modal de item. O margin-top vale para
   TODA seção (inclusive a que segue o marcador de identidade display:contents,
   onde o combinador de irmão adjacente não alcança — era o "NEXT LEVEL colado").
   Linhas com mais entrelinha; a descrição respira antes da 1ª seção. */
.skill-inspector .inspector-body-props { margin-top: 1.25rem; }
.skill-inspector .inspector-skill-desc { margin-bottom: 1.25rem; }
.skill-inspector .inspector-props li { padding: 0.22rem 0; line-height: 1.5; }

.inspector-foot {
  margin-top: 1rem; padding-top: 0.7rem; border-top: 1px solid var(--border-3);
  font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted);
}
/* Rodapé com link (modal de material #17: "Ver no Cube"): fonte normal, dourado. */
.inspector-foot-link { font-family: inherit; font-size: 0.85rem; }

/* Hover-preview do inspetor (#30): balão desktop-only, mesma família visual do
   modal (superfície escura, borda, nome na cor da raridade via .inspector-name).
   A posição (fixed) vem do controller via CSSOM — fora da CSP de style-src, que
   só alcança style="" no HTML. Corte honesto: só quando transborda (.is-clipped)
   o fim ganha um fade; o rodapé "clique para detalhes" fica SEMPRE visível,
   fora da área cortada. z-index acima do conteúdo (o modal é <dialog> top-layer,
   não conflita). pointer-events:none — o balão nunca intercepta o mouse. */
.item-hover-preview {
  position: fixed; top: 0; left: 0; z-index: 60;
  width: 20rem; max-width: calc(100vw - 16px);
  display: flex; flex-direction: column;
  pointer-events: none;
  background: var(--surface-raised);
  border: 1px solid var(--border-4); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
  overflow: hidden;
}
.item-hover-preview[hidden] { display: none; }
.hover-preview-body { padding: 0.85rem 1rem 0.35rem; max-height: 60vh; overflow: hidden; }
.item-hover-preview.is-clipped .hover-preview-body {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 2rem), transparent);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 2rem), transparent);
}
/* No balão o cabeçalho não reserva a margem do × de fechar (não há botão). */
.hover-preview-body .inspector-head { margin-right: 0; margin-bottom: 0.6rem; }
.hover-preview-hint {
  flex: none; padding: 0.5rem 1rem; border-top: 1px solid var(--border-3);
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted-2); background: var(--surface-raised);
}

/* Modal de material (#17): "para que serve no cubo". Cada receita = título
   (output + tag de estado) sobre a cadeia de inputs; a cadeia reusa
   .rune-chain/.rune-missing do /cube. Linguagem visual da modal, dados do /cube. */
.inspector-recipes { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.7rem; }
.inspector-recipe { display: grid; gap: 0.2rem; }
.recipe-head { display: flex; align-items: baseline; gap: 0.35rem; }
.recipe-output { font-family: var(--font-serif); color: var(--text); }
.inspector-empty { color: var(--muted); margin: 0; }

/* Gatilho do inspetor: a tile continua parecendo tile, só clicável e focável. */
.item-trigger {
  background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit;
  cursor: pointer; text-align: left; border-radius: 4px;
}
.item-trigger:hover { text-decoration: underline; }
.item-trigger:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; }

/* Aba Usos (INS-6): segmented control Properties · Usos. Mesmo idioma do
   mode-toggle/chips (mono, ativo com fundo elevado), mas segmentos de largura
   igual. Só aparece quando há conteúdo de uso; senão a modal fica como antes. */
.inspector-tablist {
  display: flex; gap: 0.3rem; padding: 3px; margin: 0.25rem 0 1rem;
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 8px;
}
.inspector-tab {
  flex: 1 1 0; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted-2); text-align: center; cursor: pointer;
  background: none; border: 1px solid transparent; border-radius: 6px; padding: 0.35rem 0.4rem;
}
.inspector-tab[aria-selected="true"] { background: #26241c; border-color: var(--gold-border); color: var(--text); }
.inspector-tab:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 1px; }
.inspector-uses-count { color: var(--muted-2); }
.inspector-panel:focus-visible { outline: none; }

/* Aba Histórico (#50): unique/set com data de achado no diário do jogo. Uma
   linha com a data (destaque do texto) + a nota de fonte muted (.inspector-foot,
   com o divisor superior que já separa fato de anotação). */
.inspector-history-line { margin: 0; color: var(--text); }

/* Linhas de uso: bolinha de estado + nome + meta à direita em mono. Verde =
   pronta/tem, vermelho (danger) = falta, muted = neutro/info (catálogo). */
.inspector-uses { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.4rem; }
.inspector-uses-section .inspector-props-title { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.uses-section-count { color: var(--muted-3); }
.use-row { display: flex; align-items: baseline; gap: 0.5rem; }
.use-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--muted-3); align-self: flex-start; margin-top: 0.35rem; }
.use-name { flex: 1 1 auto; color: var(--text-secondary); }
/* Runeword que linka pra wiki (#61): herda a cor da .use-name (não vira dourado
   de link); sublinhado sutil só no hover/foco. */
a.use-name { text-decoration: none; }
a.use-name:hover, a.use-name:focus-visible { text-decoration: underline; text-underline-offset: 2px; }
.use-meta { flex: none; font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted); text-align: right; }
.use-row--ready .use-dot { background: var(--green); }
.use-row--ready .use-meta { color: var(--green); }
.use-row--missing .use-dot { background: var(--red); }
.use-row--missing .use-meta { color: var(--red); }
.set-piece--missing { opacity: 0.4; }
.use-more { font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted-2); padding-top: 0.1rem; }

/* Progresso do set: N/M dourado no título + barra verde (reusa .roll-bar/.roll-fill,
   largura por classe .roll-fill--N, CSP-safe) + as M peças have/missing. */
.set-progress-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin-bottom: 0.5rem; }
.set-progress-head .inspector-props-title { margin: 0; }
.set-progress-count { font-family: var(--font-mono); font-size: 0.8rem; color: var(--gold); }
.set-progress-bar { margin: 0 0 0.7rem; }

/* Quests (issue #51): progresso por dificuldade. Reusa o idioma das use-row —
   bolinha de estado + nome + meta —, estendido para linha de 3 colunas: dot,
   nome+recompensa empilhados, status à direita em mono. Completa = verde (como
   use-row--ready), em progresso = dourada, não iniciada = apagada (dot muted). */
.quests-summary { font-family: var(--font-mono); color: var(--muted); margin: 0 0 1.25rem; }
.quest-act { margin-bottom: 1.5rem; }
.quest-act h3 { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.quest-act-count { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted-3); }
.quest-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.45rem; }
.quest-row { display: flex; align-items: baseline; gap: 0.6rem; }
.quest-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--muted-3); align-self: flex-start; margin-top: 0.45rem; }
.quest-info { flex: 1 1 auto; display: flex; flex-direction: column; gap: 0.1rem; }
.quest-name { color: var(--text-secondary); }
.quest-reward { font-size: 0.8rem; color: var(--muted); }
.quest-status { flex: none; font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted-2); text-align: right; white-space: nowrap; }
.quest-row--completed .quest-dot { background: var(--green); }
.quest-row--completed .quest-status { color: var(--green); }
/* Leitores de tela anunciam ::before — a linha sai "✓ Completa", sem redundância. */
.quest-row--completed .quest-status::before { content: "\2713\00a0"; }
.quest-row--in-progress .quest-dot { background: var(--gold); }
.quest-row--in-progress .quest-status { color: var(--gold); }
.quest-row--not-started { opacity: 0.55; }

/* Página de download do watcher (Fase 4b). Hero como a landing; reusa
   .card/.cards-3, .button-primary/secondary, tabela .devices, .notice-banner. */
.download-hero { max-width: 44rem; }
.download-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 1.5rem 0 0.5rem; }
.download-button { display: inline-flex; align-items: baseline; gap: 0.5rem; }
.download-size { font-family: var(--font-mono); font-size: 0.8em; opacity: 0.75; }
.download-version { margin-top: 0; }
.download-steps, .download-notes { margin-top: 2rem; }
.download-notes-list { color: var(--muted); padding-left: 1.1rem; margin: 0.5rem 0 1rem; }
.download-notes-list li { padding: 0.15rem 0; }
.download-notes-list code, .download-sha { word-break: break-all; }
.download-checksums { margin: 1rem 0 1.25rem; }
.download-checksums summary { cursor: pointer; color: var(--gold); }
.download-sha { color: var(--muted); }

/* ============================================================================
   LANDING de marketing (layout "landing"). Todo o mock inline foi portado para
   classes — a CSP (style-src :self, sem 'unsafe-inline') proíbe style="".
   Larguras "dinâmicas" que na verdade são estáticas usam classes: as barras de
   roll reusam .roll-fill--N (passo 5%), a barra do grail usa .landing-grail-fill
   (28.9% exato, one-off). Container ~1160px; body.landing-page é full-bleed.
   ========================================================================= */
html { scroll-behavior: smooth; }
body.landing-page { max-width: none; margin: 0; padding: 0; }
body.landing-page main { max-width: none; padding: 0; }

.landing-container { max-width: 1160px; margin: 0 auto; padding: 0 30px; }

/* Botões da landing */
.landing-btn {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-size: 0.875rem; font-weight: 600; border-radius: 8px; text-decoration: none;
  padding: 0.5rem 0.95rem; white-space: nowrap; border: 1px solid transparent;
}
.landing-btn-gold { background: var(--gold); color: #14130f; }
.landing-btn-gold:hover { background: #d4b06a; }
.landing-btn-outline { background: var(--panel); color: var(--text); border-color: var(--border-4); font-weight: 500; }
.landing-btn-outline:hover { border-color: var(--gold-border); }
.landing-btn-lg { font-size: 1rem; padding: 0.85rem 1.6rem; border-radius: 10px; }

/* ---- Nav de marketing (sticky, blur) ---- */
.landing-nav {
  position: sticky; top: 0; z-index: 40;
  background: rgba(11, 10, 8, 0.82); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--landing-nav-border);
}
.landing-nav-inner {
  max-width: 1160px; margin: 0 auto; padding: 0.9rem 30px;
  display: flex; align-items: center; gap: 1.35rem;
}
.landing-nav-brand .brand-glyph { height: 1.6rem; }
.landing-nav-brand .brand-text { font-size: 1.3rem; }
.landing-nav-anchors { display: flex; align-items: center; gap: 1.35rem; font-size: 0.875rem; margin-left: 0.5rem; }
.landing-nav-anchors a { color: var(--muted); text-decoration: none; }
.landing-nav-anchors a:hover { color: var(--gold); }
.landing-nav-actions { margin-left: auto; display: flex; align-items: center; gap: 1rem; }
.landing-nav-signin { color: var(--text-secondary); font-size: 0.875rem; text-decoration: none; white-space: nowrap; }
.landing-nav-cta { white-space: nowrap; }
.landing-nav-signin:hover { color: var(--gold); }

/* ---- Hero ---- */
.landing-hero { position: relative; overflow: hidden; }
.landing-hero-glow {
  position: absolute; top: -180px; left: 50%; transform: translateX(-50%);
  width: 900px; height: 520px; max-width: 100%; pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(198, 160, 90, 0.13), transparent 68%);
}
.landing-hero-inner {
  max-width: 1160px; margin: 0 auto; padding: 4.9rem 30px 2.5rem;
  position: relative; text-align: center;
}
.landing-badge {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.06em;
  color: var(--landing-eyebrow); border: 1px solid var(--border-4); border-radius: 999px;
  padding: 0.375rem 0.875rem; margin: 0 0 1.75rem;
}
.landing-badge-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex: none; }
.landing-h1 {
  font-family: var(--font-serif); font-weight: 700; font-size: 4.75rem; line-height: 1.02;
  margin: 0 0 1.4rem; color: var(--text); letter-spacing: -0.01em;
}
.landing-hero-sub { max-width: 620px; margin: 0 auto 0.9rem; font-size: 1.1875rem; color: var(--landing-body); line-height: 1.6; }
.landing-hero-actions { display: flex; gap: 0.875rem; justify-content: center; margin: 2rem 0 1rem; flex-wrap: wrap; }
.landing-hero-actions--center { margin-bottom: 0; }
.landing-hero-micro { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted-2); margin: 0; }

/* ---- Mock de browser ---- */
.landing-browser {
  margin: 3.4rem auto 0; max-width: 1000px; width: 100%;
  border: 1px solid var(--border-3); border-radius: 14px 14px 0 0;
  background: var(--bg-secondary); box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
  overflow: hidden; text-align: left;
}
.landing-browser-bar { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1rem; border-bottom: 1px solid var(--landing-nav-border); }
.landing-browser-dot { width: 11px; height: 11px; border-radius: 50%; background: #3a352a; flex: none; }
.landing-browser-url {
  margin: 0 auto; font-family: var(--font-mono); font-size: 0.6875rem; color: var(--muted-2);
  background: var(--surface-raised); border: 1px solid var(--border); border-radius: 6px; padding: 0.25rem 2.75rem;
}
.landing-browser-body { padding: 1.6rem 1.9rem 1.9rem; }
.landing-browser-head { display: flex; align-items: baseline; gap: 0.9rem; margin-bottom: 1.1rem; flex-wrap: wrap; }
.landing-browser-title { font-family: var(--font-serif); font-size: 1.625rem; color: var(--text); }
.landing-browser-meta { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); }
.landing-gold { color: var(--gold); }
.landing-rw-row {
  display: flex; flex-direction: column; gap: 0.5rem; padding: 0.75rem 0.875rem;
  background: var(--panel); border: 1px solid var(--border); border-radius: 9px; margin-bottom: 0.45rem;
}
.landing-rw-foot { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.landing-rw-name { font-family: var(--font-serif); font-size: 1.0625rem; flex: none; }
.landing-rw-name--gold { color: var(--gold); }
.landing-rw-name--muted { color: var(--muted); }
.landing-rw-runes { display: flex; align-items: center; gap: 0.375rem; flex: 1; flex-wrap: wrap; }
.landing-rune { display: inline-flex; align-items: center; gap: 0.3rem; margin-right: 0.25rem; }
/* Runa/gema = miniatura real do jogo via item_glyph (#92): o PNG do jogo (camada
   trocável do guardrail 4c) ou o SVG autoral de fallback. Dimensionadas por
   contexto SEM tocar na base .item-icon(--img). As runas/gemas destes mocks são
   todas 1×1 (nunca --tall). */
.landing-rune .item-icon--img { width: 1.4em; height: 1.4em; }
.landing-rune-label { font-size: 0.75rem; color: #a8a498; }
.landing-rw-status { font-family: var(--font-mono); font-size: 0.75rem; flex: none; }
.landing-rw-status--green { color: var(--green); }
.landing-rw-status--orange { color: var(--landing-orange); }

/* ---- Trust strip ---- */
.landing-trust { border-top: 1px solid var(--landing-nav-border); border-bottom: 1px solid var(--landing-nav-border); background: var(--landing-band); }
.landing-trust-inner { max-width: 1160px; margin: 0 auto; padding: 1.6rem 30px; display: flex; gap: 2.5rem; justify-content: center; flex-wrap: wrap; }
.landing-stat { text-align: center; }
.landing-stat-num { font-family: var(--font-serif); font-weight: 700; font-size: 1.875rem; color: var(--gold); line-height: 1; }
.landing-stat-label { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.03em; color: var(--muted-2); margin-top: 0.45rem; text-transform: uppercase; }

/* ---- Blocos de seção ---- */
.landing-section { padding: 5.5rem 0; }
.landing-band { background: var(--landing-band); border-top: 1px solid var(--landing-nav-border); padding: 5.5rem 0; }
.landing-anchor { scroll-margin-top: 72px; }
.landing-head-center { text-align: center; margin-bottom: 3.25rem; }
.landing-head-center--narrow { max-width: 720px; margin-left: auto; margin-right: auto; }
.landing-eyebrow { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.1em; color: var(--landing-eyebrow); text-transform: uppercase; margin: 0 0 0.9rem; }
.landing-h2 { font-family: var(--font-serif); font-weight: 700; font-size: 2.625rem; margin: 0; color: var(--text); }
.landing-h2--left { text-align: left; font-size: 2.375rem; line-height: 1.12; margin-bottom: 1.1rem; }
.landing-lead { max-width: 620px; margin: 0.9rem auto 0; font-size: 1.03rem; color: var(--muted); line-height: 1.6; }
.landing-lead em, .landing-body em { color: var(--text-tertiary); font-style: italic; }
.landing-body { font-size: 1.03rem; color: var(--landing-body); line-height: 1.65; margin: 0 0 1.35rem; }

.landing-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.landing-split { display: grid; grid-template-columns: 1fr 1fr; gap: 3.5rem; align-items: center; }
.landing-split--wide-left { grid-template-columns: 1.05fr 1fr; }

.landing-card { background: var(--bg-secondary); border: 1px solid var(--border-2); border-radius: 12px; padding: 1.6rem 1.5rem; }
.landing-card-title { font-family: var(--font-serif); font-weight: 400; font-size: 1.3rem; color: var(--text); margin: 0 0 0.6rem; }
.landing-card-title--gold { color: var(--gold); }
.landing-card-body { font-size: 0.9rem; color: var(--muted); line-height: 1.55; margin: 0 0 1.1rem; }
.landing-step-num {
  font-family: var(--font-mono); font-size: 0.8125rem; color: var(--gold);
  border: 1px solid var(--border-4); border-radius: 8px; width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center; margin-bottom: 1.1rem;
}

/* ---- Checklist (history) ---- */
.landing-checklist { display: flex; flex-direction: column; gap: 0.75rem; }
.landing-check { display: flex; align-items: center; gap: 0.7rem; font-size: 0.94rem; color: var(--text-tertiary); }
.landing-check-mark { color: var(--green); flex: none; }

/* ---- Painéis de ilustração ---- */
.landing-panel { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px; padding: 1.6rem; }
.landing-panel-label { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted-2); margin-bottom: 1.1rem; }

/* Timeline */
.landing-timeline { position: relative; padding-left: 24px; }
.landing-timeline-rail { position: absolute; left: 5px; top: 4px; bottom: 12px; width: 2px; background: #241f19; }
.landing-tl-item { position: relative; padding-bottom: 1.4rem; }
.landing-tl-dot { position: absolute; left: -23px; top: 2px; width: 12px; height: 12px; border-radius: 50%; }
.landing-tl-dot--gold { background: var(--gold); border: 2px solid var(--gold); }
.landing-tl-dot--dim { background: var(--surface-raised); border: 2px solid #3a352a; }
.landing-tl-dot--muted { background: var(--surface-raised); border: 2px solid var(--muted); }
.landing-tl-row { display: flex; align-items: baseline; gap: 0.65rem; flex-wrap: wrap; }
.landing-tl-date { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); width: 104px; flex: none; }
.landing-tl-event { font-size: 0.9rem; }
.landing-tl-event--gold { color: var(--gold); }
.landing-tl-event--dim { color: var(--text-tertiary); }
.landing-tl-event--muted { color: var(--muted); }
.landing-tl-badge {
  margin-left: auto; font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted-2);
  border: 1px solid var(--border-2); border-radius: 5px; padding: 0.15rem 0.45rem;
}
.landing-tl-badge--gold { color: var(--gold); border-color: var(--gold-border); }
.landing-tl-restore { margin: 0.5rem 0 0 114px; }
.landing-tl-restore-btn { font-family: var(--font-mono); font-size: 0.6875rem; color: var(--gold); border: 1px solid var(--gold-border); border-radius: 6px; padding: 0.25rem 0.625rem; }

/* Inspeção (tooltip + roll card) */
.landing-inspect { position: relative; }
.landing-inspect-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem 0.75rem; background: var(--panel); border: 1px solid var(--border-3); border-radius: 9px; position: relative; }
.landing-inspect-row .item-icon--img { width: 1.625em; height: 1.625em; } /* Sol ~26px */
.landing-inspect-name { font-size: 0.9375rem; color: var(--rune-new); }
.landing-inspect-count { margin-left: auto; font-family: var(--font-mono); font-size: 0.6875rem; color: var(--muted-2); }
.landing-tooltip {
  position: absolute; left: 8px; top: calc(100% + 10px); z-index: 5; width: 250px; max-width: calc(100% - 16px);
  background: var(--tooltip-bg); border: 1px solid #3a352a; box-shadow: 0 16px 44px rgba(0, 0, 0, 0.6); padding: 0.8rem 0.95rem;
}
.landing-tooltip-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.55rem; }
.landing-tooltip-name { font-family: var(--font-serif); font-size: 0.9375rem; color: var(--rune-new); }
.landing-tooltip-req { font-family: var(--font-mono); font-size: 0.625rem; color: var(--muted-2); }
.landing-tooltip-prop { font-size: 0.78rem; line-height: 1.5; color: var(--prop-color); }
.landing-tooltip-foot { font-size: 0.6875rem; color: var(--muted-2); margin-top: 0.55rem; padding-top: 0.5rem; border-top: 1px solid #211f1a; }
.landing-roll-card { margin-top: 9.5rem; padding: 1rem 1rem 0.5rem; background: var(--bg-tertiary); border: 1px solid var(--border-2); border-radius: 10px; }
.landing-roll { margin-bottom: 0.95rem; }
.landing-roll-head { display: flex; justify-content: space-between; font-size: 0.78rem; margin-bottom: 0.375rem; }
.landing-roll-label { color: var(--landing-body); }
.landing-roll-val { font-weight: 600; font-family: var(--font-mono); }
.landing-roll-val--green { color: var(--green); }
.landing-roll-val--gold { color: var(--gold); }
.landing-roll-track { height: 5px; background: var(--track-bg); border-radius: 3px; overflow: hidden; }
.landing-roll-fill { display: block; height: 100%; border-radius: 3px; }
.landing-roll-fill--green { background: var(--green); }
.landing-roll-fill--gold { background: var(--gold); }

/* Definition list (inspect points) */
.landing-deflist { display: flex; flex-direction: column; gap: 0.875rem; }
.landing-def { display: flex; gap: 0.8rem; align-items: flex-start; }
.landing-def-key { font-family: var(--font-mono); color: var(--gold); font-size: 0.8125rem; margin-top: 1px; flex: none; }
.landing-def-val { font-size: 0.94rem; color: var(--landing-body); line-height: 1.55; }

/* ---- Mobile section (chips + phone) ---- */
.landing-chips { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.landing-chip { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-tertiary); background: var(--panel); border: 1px solid var(--border-3); border-radius: 999px; padding: 0.45rem 0.875rem; }
.landing-phone-wrap { display: flex; justify-content: center; }
.landing-phone {
  box-sizing: border-box; width: 300px; max-width: 100%; height: 600px; background: var(--bg-secondary);
  border: 1px solid var(--border-3); border-radius: 34px; padding: 12px; overflow: hidden;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55); position: relative;
}
.landing-phone-notch { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); width: 100px; height: 6px; border-radius: 3px; background: var(--border); }
.landing-phone-screen { box-sizing: border-box; height: 100%; background: var(--landing-band); border-radius: 24px; overflow: hidden; padding: 40px 16px 16px; display: flex; flex-direction: column; }
.landing-phone-top { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1.1rem; }
.landing-phone-brand { font-family: var(--font-serif); font-size: 0.9375rem; color: var(--gold); }
.landing-phone-burger { margin-left: auto; color: var(--muted-2); }
.landing-phone-title { font-family: var(--font-serif); font-size: 1.375rem; color: var(--text); margin-bottom: 0.25rem; }
.landing-phone-sub { font-family: var(--font-mono); font-size: 0.625rem; color: var(--muted-2); margin-bottom: 0.9rem; }
.landing-phone-item { display: flex; align-items: center; gap: 0.55rem; padding: 0.55rem 0.5rem; border-radius: 7px; margin-bottom: 2px; }
.landing-phone-item.is-highlight { background: var(--surface-raised); }
/* Arte real do jogo no mock (#92): caixa compacta e sem moldura (a base
   .item-icon--img já zera padding/fundo/borda). O retrato ganha --tall (2em na
   base); aqui é capado pra a linha não estourar o mock de 600px. */
.landing-phone-item .item-icon--img { width: 1.5em; height: 1.5em; }
.landing-phone-item .item-icon--tall { width: 1.5em; height: 1.85em; }
.landing-phone-item-name { font-size: 0.8125rem; }
.landing-phone-item-name--gold { color: var(--gold); }
.landing-phone-item-name--green { color: var(--green); }
.landing-phone-item-name--rare { color: var(--rare-new); }
.landing-phone-item-name--blue { color: var(--blue); }
.landing-phone-sheet { margin: auto -16px -16px; background: var(--surface-raised); border-top: 1px solid var(--border-4); border-radius: 16px 16px 0 0; padding: 0.9rem 1rem 1.1rem; }
.landing-phone-grabber { display: block; width: 32px; height: 4px; border-radius: 2px; background: #3a352a; margin: 0 auto 0.6rem; }
.landing-phone-sheet-name { font-family: var(--font-serif); font-size: 1.0625rem; color: var(--gold); }
.landing-phone-sheet-sub { font-family: var(--font-mono); font-size: 0.625rem; color: #7d7a70; margin: 0.2rem 0 0.55rem; }
.landing-phone-sheet-prop { font-size: 0.75rem; color: var(--prop-color); line-height: 1.5; }

/* ---- Trio de inteligência ---- */
.landing-mini-list { display: flex; flex-direction: column; gap: 0.45rem; }
.landing-mini-row { display: flex; align-items: center; gap: 0.55rem; padding: 0.55rem 0.7rem; background: var(--panel); border: 1px solid var(--border); border-radius: 7px; }
.landing-mini-row .landing-rw-name { width: auto; flex: none; font-size: 0.9375rem; }
.landing-mini-status { margin-left: auto; font-family: var(--font-mono); font-size: 0.6875rem; }
.landing-mini-status--green { color: var(--green); }
.landing-mini-status--orange { color: var(--landing-orange); }
.landing-mini-row .item-icon--img { width: 1.4em; height: 1.4em; } /* gema real (#92) */
.landing-mini-item { font-size: 0.84rem; color: var(--text-tertiary); }
.landing-mini-count { margin-left: auto; font-family: var(--font-mono); font-size: 0.625rem; color: #a8a498; }
.landing-grail-head { display: flex; align-items: baseline; gap: 0.65rem; margin-bottom: 0.9rem; }
.landing-grail-pct { font-family: var(--font-serif); font-weight: 700; font-size: 2.125rem; color: var(--gold); line-height: 1; }
.landing-grail-frac { font-family: var(--font-mono); font-size: 0.6875rem; color: var(--muted-2); }
.landing-grail-bar { height: 6px; background: var(--track-bg); border-radius: 3px; overflow: hidden; }
.landing-grail-fill { display: block; width: 28.9%; height: 100%; background: var(--gold); }

/* ---- Multi-device (conflito) ---- */
.landing-conflict { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 0; }
.landing-conflict-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 11px; padding: 1.1rem 1.35rem; min-width: 190px; }
.landing-conflict-card--resolved { background: var(--bg-tertiary); border-color: var(--gold-border); }
.landing-conflict-when { font-family: var(--font-mono); font-size: 0.625rem; color: var(--muted-2); margin-bottom: 0.375rem; }
.landing-conflict-when--gold { color: var(--gold); }
.landing-conflict-char { font-size: 0.875rem; color: var(--text-tertiary); }
.landing-conflict-char--bright { color: var(--text); }
.landing-conflict-detail { font-size: 0.78rem; color: var(--muted); }
.landing-conflict-detail--green { color: var(--green); }
.landing-conflict-arrows { font-family: var(--font-mono); font-size: 1.25rem; color: var(--gold); padding: 0 1.25rem; }
.landing-conflict-gap { width: 40px; }

/* ---- CTA final ---- */
.landing-final { border-top: 1px solid var(--landing-nav-border); position: relative; overflow: hidden; }
.landing-final-glow {
  position: absolute; bottom: -160px; left: 50%; transform: translateX(-50%);
  width: 820px; height: 420px; max-width: 100%; pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(198, 160, 90, 0.14), transparent 68%);
}
.landing-final-inner { max-width: 800px; margin: 0 auto; padding: 6rem 30px; text-align: center; position: relative; }
.landing-final-title { font-size: 3.25rem; line-height: 1.08; margin-bottom: 1.1rem; }
.landing-final-body { font-size: 1.125rem; color: var(--landing-body); line-height: 1.6; margin: 0 auto 1.9rem; max-width: 500px; }

/* ---- Responsivo da landing ---- */
@media (max-width: 48rem) {
  .landing-nav-anchors { display: none; }
  .landing-h1 { font-size: 3.1rem; }
  .landing-h2 { font-size: 2rem; }
  .landing-h2--left { font-size: 1.85rem; }
  .landing-final-title { font-size: 2.4rem; }
  .landing-grid-3 { grid-template-columns: 1fr; }
  .landing-split, .landing-split--wide-left { grid-template-columns: 1fr; gap: 2.25rem; }
  .landing-section, .landing-band { padding: 3.75rem 0; }
  .landing-hero-inner { padding-top: 3rem; }
  .landing-conflict-arrows { transform: rotate(90deg); padding: 0.75rem 0; width: 100%; text-align: center; }
  .landing-conflict-gap { width: 100%; height: 0.75rem; }
  .landing-conflict-card { min-width: 0; width: 100%; max-width: 320px; }
}
@media (max-width: 34rem) {
  .landing-nav-actions { gap: 0.6rem; }
  .landing-h1 { font-size: 2.5rem; }
  .landing-container, .landing-hero-inner, .landing-nav-inner, .landing-trust-inner, .landing-final-inner { padding-left: 1rem; padding-right: 1rem; }
  .landing-browser-body { padding: 1.1rem 1.1rem 1.3rem; }
}

/* ============================================================
   Wiki pública + calculadoras (issue #55)
   Reusa --card/tabelas/mode-toggle; grid 372px/1fr do mock que
   colapsa em coluna única no mobile. Prefixos wiki-/calc-.
   ============================================================ */

/* Hub + índice: cards clicáveis (link block). */
.wiki-intro { color: var(--muted); max-width: 42rem; line-height: 1.55; margin: 0.75rem 0 0; }
.wiki-cards { margin-top: 1.75rem; }
a.wiki-card { display: flex; flex-direction: column; text-decoration: none; color: inherit; }
a.wiki-card:hover { border-color: var(--gold-border); }
.wiki-card h3 { color: var(--gold-hover); }
.wiki-card-desc { color: var(--muted); margin: 0.4rem 0 0.9rem; line-height: 1.5; }
.wiki-card-go { font-family: var(--font-mono); font-size: 0.72rem; color: var(--gold); margin-top: auto; }
.wiki-more { margin-top: 1.5rem; }

/* Cabeçalho da calculadora. */
.calc-head { margin-bottom: 1.25rem; }
.calc-breadcrumb a { color: var(--landing-eyebrow); }
.calc-title-row { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; }
.calc-h1 { font-family: var(--font-serif); font-weight: 700; font-size: 2.5rem; line-height: 1; margin: 0; letter-spacing: -0.01em; color: var(--text); }
.calc-badge { font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600; color: var(--bg); background: var(--gold); padding: 0.18rem 0.5rem; border-radius: 5px; }
.calc-desc { max-width: 42rem; }
.calc-tabs { margin-top: 1rem; }

/* Grid config + resultados. */
.calc-grid { display: grid; grid-template-columns: 23.25rem 1fr; gap: 1.5rem; align-items: start; }
.calc-results { min-width: 0; display: flex; flex-direction: column; gap: 1.1rem; }

/* Painel de configuração. */
.calc-panel { align-self: start; }
.calc-panel-title { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted-2); margin-bottom: 1rem; padding-bottom: 0.7rem; border-bottom: 1px solid var(--border-2); }
.calc-field { display: grid; grid-template-columns: 6rem 1fr; align-items: center; gap: 0.75rem; margin-bottom: 0.7rem; }
.calc-label { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); }
.calc-label-stat { color: var(--gold-hover); }

/* Select com caret próprio (o nativo é removido via appearance:none). */
.calc-select { position: relative; }
.calc-select select { appearance: none; -webkit-appearance: none; width: 100%; background: var(--bg-tertiary); border: 1px solid var(--border-3); border-radius: 7px; color: var(--text); font: inherit; font-size: 0.85rem; padding: 0.5rem 1.8rem 0.5rem 0.7rem; cursor: pointer; }
.calc-select::after { content: "▼"; position: absolute; right: 0.7rem; top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--muted-2); font-size: 0.6rem; }

/* Stepper − [input] + */
.calc-stepper { display: flex; align-items: stretch; height: 2.2rem; }
.calc-step { width: 2.15rem; display: flex; align-items: center; justify-content: center; background: var(--bg-tertiary); border: 1px solid var(--border-3); color: var(--muted); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0; }
.calc-step:first-child { border-radius: 7px 0 0 7px; border-right: none; }
.calc-step:last-child { border-radius: 0 7px 7px 0; border-left: none; }
.calc-step:hover { color: var(--text); background: var(--surface-raised); }
.calc-stepper input[type="number"] { width: 100%; min-width: 0; text-align: center; background: var(--bg-tertiary); border: 1px solid var(--border-3); color: var(--text); font-family: var(--font-mono); font-size: 0.9rem; outline: none; -moz-appearance: textfield; }
.calc-stepper input[type="number"]::-webkit-outer-spin-button,
.calc-stepper input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.calc-checks { display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem; margin: 0.9rem 0; padding-top: 0.9rem; border-top: 1px solid var(--border-2); }
.calc-check { display: flex; align-items: center; gap: 0.5rem; cursor: pointer; font-size: 0.85rem; color: var(--text-tertiary); user-select: none; }
.calc-note { color: var(--muted); font-size: 0.82rem; line-height: 1.5; margin: 0.5rem 0 0.9rem; }
.calc-warlock-note { color: var(--gold-hover); }
.calc-noscript-submit { display: inline-block; margin: 0.3rem 0 0.6rem; font-family: var(--font-mono); font-size: 0.78rem; }
/* Regra de autor com display vence o [hidden] do UA — restaura o none quando o
   controller esconde o submit (com JS o botão de submit noscript é redundante). */
.calc-noscript-submit[hidden] { display: none; }
.calc-copy { display: block; width: 100%; margin-top: 0.5rem; background: transparent; border: 1px solid var(--gold-border); border-radius: 8px; color: var(--gold-hover); font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600; padding: 0.6rem; cursor: pointer; }
.calc-copy:hover { border-color: var(--gold); color: var(--gold); }

/* Hero FPA/frames. */
.calc-hero { display: grid; grid-template-columns: auto 1fr; gap: 1.4rem; align-items: center; }
.calc-hero-main { text-align: center; min-width: 6.5rem; }
.calc-hero-num { font-family: var(--font-serif); font-weight: 700; font-size: 3.6rem; line-height: 0.9; color: var(--gold); }
.calc-hero-label { font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted-2); margin-top: 0.4rem; }
.calc-hero-side { border-left: 1px solid var(--border); padding-left: 1.4rem; }
.calc-callout { font-family: var(--font-mono); font-size: 0.9rem; font-weight: 600; }
.calc-callout-need { color: var(--gold); }
.calc-callout-best { color: var(--green); }
.calc-context { font-size: 0.82rem; color: var(--muted); margin-top: 0.5rem; line-height: 1.5; }

/* Notas de info (motor IAS). */
.calc-infos { display: flex; flex-direction: column; gap: 0.45rem; }
.calc-info { display: flex; gap: 0.55rem; background: var(--bg-tertiary); border: 1px solid var(--border); border-left: 2px solid var(--gold-border); border-radius: 6px; padding: 0.55rem 0.8rem; font-size: 0.8rem; color: var(--text-tertiary); line-height: 1.5; }
.calc-info-i { color: var(--muted-2); font-style: italic; }

/* Tabela de breakpoints. */
.calc-table-card { padding: 0; overflow: hidden; }
.calc-table-name { font-family: var(--font-serif); font-size: 0.95rem; color: var(--gold-hover); padding: 0.8rem 1.1rem 0.65rem; border-bottom: 1px solid var(--border-2); }
.calc-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.calc-table th { text-align: left; font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted-2); padding: 0.7rem 1.1rem; border-bottom: 1px solid var(--border); }
.calc-table td { padding: 0.55rem 1.1rem; border-bottom: 1px solid var(--border-2); }
.calc-table tr:last-child td { border-bottom: none; }
.calc-cell-stat { font-family: var(--font-mono); color: var(--text-secondary); }
.calc-cell-frames { font-family: var(--font-mono); color: var(--text); }
.calc-row-active td { background: rgba(198, 160, 90, 0.1); }
.calc-row-active .calc-cell-stat { color: var(--gold-hover); box-shadow: inset 2px 0 0 var(--gold); }
.calc-row-active .calc-cell-frames { color: var(--gold); }
.calc-here { font-family: var(--font-mono); font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-2); margin-left: 0.5rem; }

/* Placeholder do motor IAS + fórmula + créditos. */
.calc-loading { color: var(--muted-2); font-family: var(--font-mono); font-size: 0.82rem; padding: 2.5rem 0; }
.calc-noscript { color: var(--muted); }
.calc-formula { margin-top: 1.25rem; }
.calc-formula-text { font-size: 0.82rem; color: var(--text-tertiary); line-height: 1.6; margin: 0; }
.calc-credits { margin-top: 2.25rem; padding-top: 1.25rem; border-top: 1px solid var(--border-2); }
.calc-credits p { max-width: 52rem; line-height: 1.7; margin: 0; }

/* Mobile: config acima dos resultados, campos empilhados, alvos de toque. */
@media (max-width: 48rem) {
  .calc-grid { grid-template-columns: 1fr; }
  .calc-h1 { font-size: 2rem; }
  .calc-field { grid-template-columns: 5.5rem 1fr; gap: 0.6rem; }
  .calc-stepper { height: 2.75rem; }
  .calc-step { width: 2.75rem; font-size: 1.1rem; }
  .calc-hero { grid-template-columns: 1fr; gap: 1rem; }
  .calc-hero-side { border-left: none; border-top: 1px solid var(--border); padding-left: 0; padding-top: 1rem; }
}

@media (max-width: 34rem) {
  .calc-field { grid-template-columns: 1fr; align-items: stretch; gap: 0.35rem; }
  .calc-label { margin-bottom: 0.1rem; }
}

/* ============================================================================
   Catálogo público de runewords da wiki (issue #57). Reusa .rune-chain/.item-icon
   e os tokens da paleta; o que é layout desta página leva prefixo .rwcat-.
   ========================================================================= */

/* O atributo [hidden] não vence um `display` de classe (barra de ativos, bandeja
   de comparação, tiles de runa filtrados…). Restaura a semântica dentro da
   feature — o JS liga/desliga via `hidden` e o elemento realmente some. */
.rwcat [hidden] { display: none !important; }

/* ── Slot de conta (issue #62): strip entre o cabeçalho e a toolbar ── */
.rwcat-account {
  display: flex; align-items: center; gap: 0.6rem 1rem; flex-wrap: wrap;
  margin: 1.4rem 0 0; padding: 0.85rem 1rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.rwcat-account-eyebrow {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted-2);
}
/* Toggle de modo reusa .mode-toggle/.mode-option (o reset de <button> já vem
   da base); o .active herda o fundo dourado da base. */
.rwcat-account-modes { margin-bottom: 0; gap: 0.4rem; }
/* As pílulas de modo do strip herdam a MESMA altura dos chips de status (mesmo
   line-height 1.5). Sem isto o <button> cai em line-height:normal (~2px menor) e
   a caixa fica mais baixa numa página sem chips — o /stash não tem chips no strip,
   então a altura só bate se a pílula for tão alta quanto o chip da /wiki/runewords. */
.rwcat-account-modes .mode-option { line-height: 1.5; }
.rwcat-account-totals { font-family: var(--font-mono); font-size: 0.8rem; color: var(--gold); }
.rwcat-account-chips { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-left: auto; }

/* Visibilidade por modo (100% CSS): o root carrega data-rwcat-mode; o modo
   inativo some — vale pros totais do strip E pros spans de status do card. */
.rwcat[data-rwcat-mode="softcore"] .rwcat-own--hardcore { display: none; }
.rwcat[data-rwcat-mode="hardcore"] .rwcat-own--softcore { display: none; }

/* CTA deslogado, no mesmo slot: convite a criar conta, botão dourado da landing.
   position:relative + o padding-right extra abrem uma calha à direita para o × de
   dispensa (issue #63) — assim o botão não sobrepõe as ações no desktop nem o
   título quando o bloco reflui no mobile. */
.rwcat-account--cta { align-items: flex-start; position: relative; padding-right: 2.7rem; }
.rwcat-account-cta-dismiss {
  position: absolute; top: 0.4rem; right: 0.4rem;
  width: 2rem; height: 2rem; padding: 0; border: 0; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; cursor: pointer; color: var(--muted-3); font-size: 1.2rem; line-height: 1;
}
.rwcat-account-cta-dismiss:hover { color: var(--gold); }
.rwcat-account-cta-dismiss:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; }
.rwcat-account-cta-text { flex: 1 1 22rem; min-width: 0; }
.rwcat-account-cta-title { font-family: var(--font-serif); font-size: 1.05rem; color: var(--text); margin: 0 0 0.25rem; }
.rwcat-account-cta-body { font-size: 0.85rem; color: var(--muted); margin: 0; line-height: 1.5; }
.rwcat-account-cta-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 0.4rem; }
.rwcat-account-cta-link { font-family: var(--font-mono); font-size: 0.76rem; color: var(--gold); text-decoration: none; }
.rwcat-account-cta-link:hover { color: var(--gold-hover); text-decoration: underline; }

/* ── Toolbar ── */
.rwcat-toolbar {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 1.5rem 0 0;
}
.rwcat-search { position: relative; display: flex; align-items: center; }
.rwcat-search-icon { position: absolute; left: 0.7rem; color: var(--muted-3); font-size: 0.85rem; pointer-events: none; }
.rwcat-search-input {
  background: var(--bg-tertiary); border: 1px solid var(--border-3); border-radius: 8px;
  padding: 0.5rem 0.7rem 0.5rem 1.9rem; color: var(--text); font: inherit; font-size: 0.9rem;
  width: 15rem; max-width: 100%; outline: none;
}
.rwcat-search-input:focus-visible { border-color: var(--gold-border); }
.rwcat-btn {
  font-family: var(--font-mono); font-size: 0.78rem; padding: 0.5rem 0.8rem; border-radius: 8px;
  cursor: pointer; border: 1px solid var(--border-3); background: var(--bg-tertiary);
  color: var(--muted); white-space: nowrap; display: inline-flex; align-items: center; gap: 0.35rem;
}
.rwcat-btn:hover { color: var(--text); border-color: var(--border-4); }
.rwcat-btn.active, .rwcat-btn[aria-pressed="true"] { background: #26241c; border-color: var(--gold-border); color: var(--text); }
.rwcat-btn:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; }
.rwcat-count { margin-left: auto; font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); }
.rwcat-count-shown { color: var(--gold); }
.rwcat-filters-btn { display: none; }
.rwcat-filters-badge { color: var(--gold); }

/* Sort: <details>/<summary> + menu (fecha via controller "menu"). */
.rwcat-sort { position: relative; }
.rwcat-sort > summary { list-style: none; }
.rwcat-sort > summary::-webkit-details-marker { display: none; }
.rwcat-sort-summary { user-select: none; }
.rwcat-sort-menu {
  position: absolute; right: 0; top: calc(100% + 0.4rem); z-index: 45; width: 12.5rem;
  background: var(--surface-raised); border: 1px solid var(--border-4); border-radius: 9px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55); padding: 0.35rem;
}
.rwcat-sort-option {
  display: block; width: 100%; text-align: left; font: inherit; font-size: 0.82rem;
  padding: 0.45rem 0.6rem; border-radius: 6px; border: 0; background: none;
  color: var(--text-secondary); cursor: pointer;
}
.rwcat-sort-option:hover { background: #211f18; }
.rwcat-sort-option.active { color: var(--gold); background: #211f18; }
/* O toggle de layout reusa .mode-option (o reset de <button> já vem da base),
   só ajusta o tom do rótulo. O .active herda o fundo dourado da base. */
.rwcat-layout { margin-bottom: 0; }
.rwcat-layout .mode-option { color: var(--muted); }
.rwcat-layout .mode-option.active { color: var(--text); }

/* ── Chips ativos ── */
.rwcat-active {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem;
  padding: 0.7rem 0.85rem; background: var(--bg-tertiary); border: 1px solid var(--border-2); border-radius: 10px;
}
.rwcat-active-label {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted-2);
}
.rwcat-active-chips { display: contents; }
.rwcat-active-chip {
  display: inline-flex; align-items: center; gap: 0.4rem; font: inherit; font-size: 0.78rem;
  padding: 0.25rem 0.5rem 0.25rem 0.6rem; border-radius: 6px; border: 1px solid var(--gold-border);
  background: #26241c; color: var(--text); cursor: pointer;
}
.rwcat-active-chip-x { color: var(--gold); font-size: 0.9rem; line-height: 1; }
.rwcat-clear {
  font-family: var(--font-mono); font-size: 0.74rem; color: var(--gold); background: none; border: 0;
  border-bottom: 1px solid var(--gold-border); cursor: pointer; padding: 0;
}
.rwcat-clear:hover { color: var(--gold-hover); }

/* ── Shell: sidebar + resultados ── */
.rwcat-shell {
  display: grid; grid-template-columns: 15.75rem 1fr; gap: 1.6rem; align-items: start; margin-top: 1.4rem;
}
/* Grid item tem min-width:auto implícito: sem este reset, a coluna 1fr não
   encolhe abaixo do min-content dos cards (rows compactos largos estouravam o
   track e vazavam além do viewport — o ellipsis do status nunca disparava). */
.rwcat-results-wrap { min-width: 0; }
/* Sticky COM scroll próprio: a sidebar (~1300px) é mais alta que o viewport —
   sem max-height+overflow, os filtros de baixo só apareceriam depois de rolar
   todo o conteúdo da direita. top desvia do site-header sticky (~58px);
   overscroll-behavior evita que o fim do scroll da sidebar arraste a página. */
.rwcat-sidebar {
  position: sticky; top: 4.5rem; display: grid; gap: 0.55rem;
  max-height: calc(100vh - 5.5rem); overflow-y: auto; overscroll-behavior: contain;
}
.rwcat-drawer-head { display: none; }

.rwcat-section {
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface); overflow: hidden;
}
.rwcat-section-head {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.7rem 0.8rem; cursor: pointer;
  user-select: none; list-style: none;
}
.rwcat-section-head::-webkit-details-marker { display: none; }
.rwcat-section-label { font-family: var(--font-serif); font-size: 0.95rem; color: var(--text); }
.rwcat-section-count {
  font-family: var(--font-mono); font-size: 0.62rem; color: var(--bg); background: var(--gold);
  border-radius: 20px; padding: 0.05em 0.45em;
}
.rwcat-section-chev { margin-left: auto; color: var(--muted-2); font-size: 1.05rem; transition: transform 0.12s; }
.rwcat-section[open] .rwcat-section-chev { transform: rotate(90deg); }
.rwcat-section-body { padding: 0 0.8rem 0.85rem; }

.rwcat-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.rwcat-chip {
  display: inline-flex; align-items: center; font: inherit; font-size: 0.76rem; padding: 0.3rem 0.55rem;
  border-radius: 6px; cursor: pointer; border: 1px solid var(--border-3); background: var(--bg-secondary);
  color: var(--muted); white-space: nowrap;
}
.rwcat-chip--mono { font-family: var(--font-mono); font-size: 0.72rem; }
.rwcat-chip:hover { color: var(--text-secondary); border-color: var(--border-4); }
.rwcat-chip[aria-pressed="true"] { background: #26241c; border-color: var(--gold-border); color: var(--text); }
.rwcat-chip:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; }

.rwcat-rune-search {
  width: 100%; background: var(--bg); border: 1px solid var(--border-3); border-radius: 7px;
  padding: 0.4rem 0.55rem; color: var(--text); font: inherit; font-size: 0.78rem; outline: none; margin-bottom: 0.7rem;
}
.rwcat-rune-search:focus-visible { border-color: var(--gold-border); }
.rwcat-rune-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.3rem; }
.rwcat-rune-btn {
  display: flex; flex-direction: column; align-items: center; gap: 0.15rem; padding: 0.35rem 0.15rem 0.3rem;
  border-radius: 7px; cursor: pointer; border: 1px solid var(--border); background: var(--bg); color: var(--muted);
  font: inherit;
}
.rwcat-rune-btn:hover { border-color: var(--border-4); }
.rwcat-rune-btn[aria-pressed="true"] { background: #26241c; border-color: var(--gold-border); color: var(--text); }
.rwcat-rune-btn:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 1px; }
.rwcat-rune-btn-name { font-size: 0.6rem; letter-spacing: 0.02em; }
.rwcat-sockets-label {
  font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted-3); margin: 0.9rem 0 0.5rem;
}

/* ── Resultados: grid detalhado / linhas compactas (mesmo DOM) ── */
.rwcat-results--detailed { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.75rem; }
.rwcat-results--compact { display: flex; flex-direction: column; gap: 0.4rem; }

.rwcat-card {
  position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 1rem 1.1rem 1.15rem; cursor: pointer; text-align: left;
  /* Coluna flex: o status de conta (.rwcat-card-own) ancora no rodapé via
     margin-top auto — mesma posição em todos os cards da linha, independente
     de quantas props cada um tem. O compacto sobrescreve para linha. */
  display: flex; flex-direction: column; align-items: stretch;
}
.rwcat-card:hover { border-color: var(--border-4); }
.rwcat-card--selected { border-color: var(--gold-border); }
/* Badge de seleção: oculto por padrão (o atributo [hidden] não vence o display
   do CSS), revelado só quando o card está selecionado no modo comparar. */
.rwcat-card-badge {
  position: absolute; top: 0.7rem; right: 0.8rem; width: 1.3rem; height: 1.3rem; border-radius: 50%;
  background: var(--gold); color: var(--bg); font-family: var(--font-mono); font-size: 0.72rem;
  display: none; align-items: center; justify-content: center;
}
.rwcat-card--selected .rwcat-card-badge { display: inline-flex; }
.rwcat-card-head { display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap; }
.rwcat-card-name {
  font-family: var(--font-serif); font-weight: 600; font-size: 1.3rem; text-decoration: none;
}
.rwcat-card-name:hover { text-decoration: underline; }
.rwcat-card-patch { margin-left: 0; }
.rwcat-chain { margin: 0.7rem 0; }
.rwcat-rune { display: inline-flex; align-items: center; gap: 0.3rem; }
.rwcat-rune-name { font-size: 0.78rem; color: var(--gold-hover); }
.rwcat-card-meta {
  font-size: 0.82rem; color: var(--muted); padding-bottom: 0.7rem; border-bottom: 1px solid var(--border-2);
}
.rwcat-bases { color: var(--muted); }
.rwcat-tech { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-tertiary); }
.rwcat-dot { color: var(--border-4); }
.rwcat-card-props { margin-top: 0.7rem; display: grid; gap: 0.5rem; }
.rwcat-prop-block { display: grid; gap: 0.15rem; }
.rwcat-prop-label {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--muted-2); margin-bottom: 0.1rem;
}
.rwcat-prop { font-size: 0.82rem; line-height: 1.5; color: var(--prop-color); }

/* Status de conta no card (issue #62): separador fino + um span por modo (o CSS
   de modo esconde o inativo). Verde = pronta; laranja = faltam runas. Aparece
   nos DOIS layouts. */
.rwcat-card-own { margin-top: auto; padding-top: 0.7rem; border-top: 1px solid var(--border); }
/* No card mais alto da linha o margin-top:auto do rodapé colapsa a zero; o
   respiro mínimo entra como margin-bottom das props — só quando há rodapé
   (deslogado não ganha espaço morto). */
.rwcat-card:has(> .rwcat-card-own) > .rwcat-card-props { margin-bottom: 0.7rem; }
.rwcat-own { font-family: var(--font-mono); font-size: 0.75rem; }
.rwcat-own--ready { color: var(--green); }
.rwcat-own--missing { color: var(--orange); }

/* Compact: um único DOM — esconde props/nomes de runa e reflui o card em linha. */
.rwcat-results--compact .rwcat-card {
  /* row explícito: a base agora é coluna flex (rodapé de status ancorado). */
  display: flex; flex-direction: row; align-items: center; gap: 1rem; padding: 0.55rem 0.9rem; border-radius: 9px;
}
.rwcat-results--compact .rwcat-card-head { flex: none; width: 10rem; }
.rwcat-results--compact .rwcat-card-name { font-size: 1rem; }
.rwcat-results--compact .rwcat-chain { margin: 0; }
.rwcat-results--compact .rwcat-rune-name { display: none; }
.rwcat-results--compact .rwcat-card-meta { flex: 1; padding-bottom: 0; border-bottom: 0; }
.rwcat-results--compact .rwcat-card-props { display: none; }
/* Status de conta sobrevive ao compacto (sem separador, encostado à direita).
   Encolhe com ellipsis em vez de estourar a linha — lista longa de faltantes
   numa viewport estreita não pode gerar scroll horizontal. */
.rwcat-results--compact .rwcat-card-own { margin: 0; padding: 0; border-top: 0; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rwcat-results--compact .rwcat-card-badge { top: -0.4rem; right: auto; left: -0.4rem; width: 1.1rem; height: 1.1rem; font-size: 0.62rem; }

/* ── Estado vazio ── */
.rwcat-empty {
  padding: 3.5rem 1.25rem; text-align: center; border: 1px dashed var(--border-3); border-radius: 12px; color: var(--muted-2);
}
.rwcat-empty-title { font-family: var(--font-serif); font-size: 1.3rem; color: var(--muted); margin-bottom: 0.4rem; }
.rwcat-empty-body { font-size: 0.85rem; margin: 0; }

/* ── Bandeja de comparação ── */
.rwcat-tray {
  position: sticky; bottom: 0; z-index: 30; display: flex; align-items: center; gap: 0.9rem; flex-wrap: wrap;
  margin-top: 1.4rem; padding: 0.8rem 1rem; background: rgba(20, 19, 15, 0.94); backdrop-filter: blur(10px);
  border: 1px solid var(--border-4); border-radius: 10px;
}
.rwcat-tray-eyebrow {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted-2);
}
.rwcat-tray-items { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.rwcat-tray-hint { font-size: 0.8rem; color: var(--muted-2); }
.rwcat-tray-chip {
  display: inline-flex; align-items: center; gap: 0.45rem; font-size: 0.82rem; color: var(--text);
  padding: 0.3rem 0.5rem 0.3rem 0.65rem; background: var(--bg-tertiary); border: 1px solid var(--border-4); border-radius: 7px;
}
.rwcat-tray-chip .q-runeword { font-family: var(--font-serif); }
.rwcat-tray-chip-x, .rwcat-tray-done {
  color: var(--muted); font-size: 0.9rem; line-height: 1; background: none; border: 0; cursor: pointer;
}
.rwcat-tray-actions { margin-left: auto; display: flex; align-items: center; gap: 0.7rem; }
.rwcat-tray-go[disabled] { opacity: 0.5; cursor: default; }
.rwcat-tray-go:not([disabled]) { background: var(--gold); border-color: var(--gold); color: var(--bg); }

/* ── Modal de comparação (reusa dialog.modal) ── */
/* Precisa de dialog.modal.<classe> (como o item-inspector) para vencer o
   max-width: 26rem da base — só .rwcat-compare-modal perde por especificidade. */
dialog.modal.rwcat-compare-modal { max-width: 62rem; }
.rwcat-compare-head { display: flex; align-items: center; gap: 0.9rem; margin-bottom: 1rem; }
.rwcat-compare-title { font-family: var(--font-serif); font-weight: 600; font-size: 1.3rem; color: var(--text); }
.rwcat-compare-close {
  margin-left: auto; background: none; border: 0; color: var(--muted); font-size: 1.4rem; line-height: 1; cursor: pointer;
}
/* overflow-x: quando nem o teto de 62rem comporta as colunas (mobile/bottom-sheet,
   3 colunas de 15rem), as colunas rolam horizontalmente dentro da modal. */
.rwcat-compare-cols { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(15rem, 1fr); gap: 0.9rem; overflow-x: auto; }
/* Base compartilhada dos três compares: o clone do stash é um <li> solto (fora do
   <ul> que zera o marcador), então herdaria o disco branco da UA. list-style aqui
   inibe o marcador de qualquer item-de-lista clonado; inócuo pros clones <article>
   de runewords/cube. */
.rwcat-compare-col { list-style: none; }
.rwcat-compare-col .rwcat-card { cursor: default; }
.rwcat-compare-col .rwcat-card:hover { border-color: var(--border); }

/* ── Página de detalhe ── */
.rwcat-detail-head { display: flex; align-items: baseline; gap: 0.9rem; flex-wrap: wrap; margin-top: 0.35rem; }
.rwcat-detail-name { font-family: var(--font-serif); font-weight: 700; font-size: 2.2rem; margin: 0; }
.rwcat-detail-tags { display: flex; gap: 0.35rem; }
.rwcat-detail-meta { color: var(--muted); margin: 0.5rem 0 0; }
.rwcat-detail-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 1rem; margin-top: 1.5rem; }
.rwcat-detail-section-title {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted-2); margin: 0 0 0.8rem; border: 0;
}
.rwcat-runes-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.rwcat-rune-row { display: flex; align-items: center; gap: 0.6rem; }
.rwcat-rune-row-body { display: flex; flex-direction: column; }
.rwcat-rune-row-name { color: var(--text-tertiary); }
.rwcat-rune-row-level { font-family: var(--font-mono); font-size: 0.68rem; color: var(--muted-2); }
.rwcat-detail-props { display: grid; gap: 0.6rem; }
.rwcat-detail-facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.9rem 1.4rem;
  margin: 1.5rem 0 0; padding-top: 1.2rem; border-top: 1px solid var(--border-2);
}
.rwcat-detail-facts dt {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted-2);
}
.rwcat-detail-facts dd { margin: 0.2rem 0 0; color: var(--text-secondary); }
.rwcat-detail-back { margin-top: 1.75rem; }
.rwcat-back-link { font-family: var(--font-mono); font-size: 0.8rem; }

/* ── Responsivo: sidebar vira drawer, grid colapsa ── */
@media (max-width: 60rem) {
  .rwcat-shell { grid-template-columns: 1fr; }
  .rwcat-filters-btn { display: inline-flex; }
  .rwcat-sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 60; width: 19rem; max-width: 86%;
    background: var(--bg-secondary); border-right: 1px solid var(--border-2); padding: 1rem 0.9rem 2rem;
    overflow-y: auto; transform: translateX(-100%); transition: transform 0.2s ease; grid-auto-rows: min-content;
    max-height: none; /* o max-height do sticky desktop caparia o drawer (inset: 0) */
  }
  .rwcat-shell--drawer-open .rwcat-sidebar { transform: none; box-shadow: 0 0 0 100vw rgba(0, 0, 0, 0.55); }
  .rwcat-drawer-head { display: flex; align-items: center; justify-content: space-between; padding: 0.2rem 0.2rem 0.9rem; }
  .rwcat-drawer-title { font-family: var(--font-serif); font-size: 1.15rem; color: var(--text); }
  .rwcat-drawer-close { background: none; border: 0; color: var(--muted); font-size: 1.4rem; line-height: 1; cursor: pointer; }
  .rwcat-detail-grid { grid-template-columns: 1fr; }
}

@media (max-width: 48rem) {
  .rwcat-results--detailed { grid-template-columns: 1fr; }
  .rwcat-count { order: 3; }
  .rwcat-compare-cols { grid-auto-flow: row; grid-auto-columns: auto; }
  .rwcat-detail-name { font-size: 1.7rem; }
  .rwcat-results--compact .rwcat-card { flex-wrap: wrap; }
  .rwcat-results--compact .rwcat-card-head { width: auto; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Catálogo de cube recipes (.wcube-, issue #65). Reusa a base do catálogo de
   runewords (root .rwcat + .rwcat-account/.rwcat-toolbar/.rwcat-shell/.rwcat-card
   /.rwcat-chip/.rwcat-own/.rwcat-tray/.rwcat-compare-* + o grid de resultados
   .rwcat-results--detailed/--compact) e adiciona só o que é próprio do cube:
   cadeia de inputs, props do output e o rodapé de elegíveis.
   ══════════════════════════════════════════════════════════════════════════ */

.wcube-card { cursor: default; }
.wcube-card:hover { border-color: var(--border); }
/* #107: card alvo de âncora (#slug vindo do link de receita da aba Usos do
   inspetor). scroll-margin afasta do .site-header sticky (~58px) pra não ficar
   coberto; realce dourado sutil (borda + anel translúcido) marca qual card. */
.wcube-card { scroll-margin-top: 5.5rem; }
.wcube-card:target {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(198, 160, 90, 0.4);
}
.wcube-card-name { font-family: var(--font-serif); font-weight: 600; font-size: 1.2rem; color: var(--text); }
.wcube-card-cat {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--muted); align-self: center;
}

/* Cadeia de inputs: glifo + "N× Nome" / rótulo de predicado condicional. */
.wcube-inputs {
  display: flex; flex-wrap: wrap; gap: 0.3rem 0.65rem; margin: 0.7rem 0;
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--border-2);
}
.wcube-input { display: inline-flex; align-items: center; gap: 0.28rem; font-size: 0.82rem; color: var(--text-secondary); }
.wcube-input .item-icon { flex: none; }

/* Props do output: reusa .rwcat-card-props/.rwcat-prop; a linha Socketed é uma
   prop de destaque neutra (mono). */
.wcube-props { margin-top: 0.15rem; }
.wcube-socketed { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-tertiary); }

/* Nota de afixos aleatórios dos crafts. */
.wcube-craft-note { font-size: 0.74rem; color: var(--muted-2); font-style: italic; margin: 0.5rem 0 0; line-height: 1.45; }

/* Rodapé de status por modo: um bloco por modo (o CSS de modo esconde o
   inativo). Cada bloco = span ready/missing + (condicionais) linhas de elegíveis. */
.wcube-card-own { display: grid; gap: 0.35rem; }
.wcube-own-block { display: grid; gap: 0.3rem; }
.wcube-eligible { font-size: 0.75rem; color: var(--muted); line-height: 1.5; }
.wcube-eligible-label { font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.03em; text-transform: uppercase; color: var(--muted-2); margin-right: 0.3rem; }
.wcube-eligible .item-icon { vertical-align: -0.12em; }
.wcube-eligible-more { color: var(--muted-2); }

/* Nome do output no chip da bandeja de comparação. */
.wcube-tray-name { font-family: var(--font-serif); }

/* Compact: UM DOM só — o card reflui em linha (reusa .rwcat-results--compact
   .rwcat-card/.rwcat-card-head/.rwcat-card-own do gabarito). Props, nota de craft
   e elegíveis somem; os inputs viram só glifos (predicados condicionais, sem
   glifo, somem); o status encosta à direita e encolhe com ellipsis — nunca gera
   scroll horizontal em 390px (mesma lição do compacto das runewords). */
.rwcat-results--compact .wcube-card .rwcat-card-head { width: auto; flex: 0 0 13rem; }
.rwcat-results--compact .wcube-inputs {
  margin: 0; padding: 0; border-bottom: 0; flex: 1 1 auto; min-width: 0; gap: 0.3rem;
  flex-wrap: nowrap; overflow: hidden;
}
.rwcat-results--compact .wcube-input-text { display: none; }
.rwcat-results--compact .wcube-input:not(.wcube-input--glyph) { display: none; }
.rwcat-results--compact .wcube-props,
.rwcat-results--compact .wcube-craft-note,
.rwcat-results--compact .wcube-eligible { display: none; }
.rwcat-results--compact .wcube-card-own { display: block; }
.rwcat-results--compact .wcube-own-block { display: inline; }

@media (max-width: 48rem) {
  .rwcat-results--compact .wcube-card .rwcat-card-head { flex-basis: auto; }
}

/* ============================================================================
   Referência da API (/docs/api — issue #21)
   ----------------------------------------------------------------------------
   A página é RENDERIZADA a partir da spec (app/openapi/v1.yaml): método, path,
   campos, status e rate limit saem do YAML. Aqui só mora o idioma visual — que
   é o do site, não o de um Swagger UI: cards de operação com a mesma superfície
   do .card, tipografia Spectral/JetBrains da UI-7, chips no idioma do .tag.
   ============================================================================ */
.api-head { margin-bottom: 1.5rem; }
.api-lede { color: var(--landing-body); max-width: 46rem; margin: 1rem 0 0; }
.api-head-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.6rem; }

/* Duas colunas: índice fixo + corpo. O índice rola sozinho quando é mais alto
   que o viewport (mesmo padrão da .rwcat-sidebar). */
.api-layout {
  display: grid; grid-template-columns: 14.5rem minmax(0, 1fr);
  gap: 3rem; align-items: start; margin-top: 2.5rem;
}
.api-toc {
  position: sticky; top: 4.75rem;
  max-height: calc(100vh - 6.5rem); overflow-y: auto;
  border-right: 1px solid var(--border); padding-right: 1.1rem;
}
.api-toc-title {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-3); margin: 1.35rem 0 0.55rem;
}
.api-toc-title:first-child { margin-top: 0; }
.api-toc-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.api-toc-list li { min-width: 0; }
.api-toc-list a { color: var(--text-tertiary); text-decoration: none; font-size: 0.85rem; }
.api-toc-list a:hover { color: var(--gold-hover); }
/* min-width: 0 — item de flex/grid tem min-width AUTO por padrão: sem o reset, o
   path (uma "palavra" longa) impede a coluna de encolher, estoura o container e a
   PÁGINA passa a rolar na horizontal no mobile. Mesma pegadinha da .rwcat-sidebar. */
.api-toc-op { display: flex; align-items: center; gap: 0.45rem; min-width: 0; }
.api-toc-path { font-family: var(--font-mono); font-size: 0.76rem; min-width: 0; overflow-wrap: anywhere; }

/* scroll-margin: o header é sticky — sem isto a âncora para DEBAIXO dele. */
.api-section { margin-bottom: 3.5rem; scroll-margin-top: 5rem; }
.api-section-title { font-size: 1.9rem; margin: 0 0 1rem; }
.api-group-desc { color: var(--muted); margin: -0.35rem 0 1.75rem; }

/* Prosa vinda do markdown da spec. */
.api-prose { color: var(--text-secondary); }
.api-prose p { margin: 0 0 0.9rem; }
.api-prose ul { margin: 0 0 0.9rem; padding-left: 1.15rem; }
.api-prose li { margin-bottom: 0.5rem; }
.api-prose > :last-child { margin-bottom: 0; }
.api-prose strong { color: var(--text); font-weight: 600; }
.api-prose a { color: var(--gold-hover); }
/* Código inline: chip discreto. Dourado (como no guia de ajuda) seria berrante
   aqui — a densidade de `code` nesta página é muito maior. */
.api-prose code {
  font-family: var(--font-mono); font-size: 0.85em; color: var(--text);
  background: var(--bg-tertiary); border: 1px solid var(--border-2);
  border-radius: 4px; padding: 0.08em 0.32em;
}
.api-code { font-size: 0.82rem; }
.api-code code { color: var(--text-secondary); background: none; border: 0; padding: 0; font-size: 1em; }
/* O comando copiável (a cerca ```sh do getting started): um clique seleciona o
   bloco inteiro — mesmo recurso do .token-reveal, sem uma linha de JS. Vale só
   para a cerca de shell: nos exemplos JSON, `user-select: all` impediria copiar
   um trecho. */
.api-code--sh { user-select: all; border-color: var(--gold-border); }

/* Card de operação: a superfície do .card, com cabeçalho método+path. */
.api-op {
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px;
  padding: 1.6rem 1.75rem; margin-bottom: 1.75rem; scroll-margin-top: 5rem;
}
.api-op-head { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.api-op-path { font-family: var(--font-mono); font-size: 0.95rem; color: var(--text); }
/* Âncora sempre visível (fraca), nunca revelada no hover: no mobile hover não
   existe e o link sumiria. */
.api-op-anchor { color: var(--muted-3); font-family: var(--font-mono); text-decoration: none; }
.api-op-anchor:hover { color: var(--gold); }
.api-op-summary {
  font-family: var(--font-serif); font-size: 1.3rem; font-weight: 400;
  color: var(--text); margin: 0.9rem 0 0.8rem;
}

/* Método HTTP: a convenção de cor que todo dev já lê (GET verde, POST azul,
   PUT laranja), servida pelos tokens da paleta. */
.api-method {
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.06em;
  padding: 0.22em 0.55em; border-radius: 5px; border: 1px solid; flex: none;
}
.api-method--get { color: var(--green); border-color: color-mix(in oklab, var(--green) 45%, transparent); background: color-mix(in oklab, var(--green) 12%, var(--bg-tertiary)); }
.api-method--post { color: var(--blue); border-color: color-mix(in oklab, var(--blue) 45%, transparent); background: color-mix(in oklab, var(--blue) 12%, var(--bg-tertiary)); }
.api-method--put { color: var(--orange); border-color: color-mix(in oklab, var(--orange) 45%, transparent); background: color-mix(in oklab, var(--orange) 12%, var(--bg-tertiary)); }
.api-method--delete { color: var(--red); border-color: color-mix(in oklab, var(--red) 45%, transparent); background: color-mix(in oklab, var(--red) 12%, var(--bg-tertiary)); }
.api-method--mini { font-size: 0.56rem; padding: 0.14em 0.35em; }

/* Chips da operação: auth e RATE LIMIT. O limite é chip e não prosa de
   propósito — é o que derruba cliente em produção, e enterrado num parágrafo
   ninguém lê. O chip laranja avisa que GET e PUT de sidecars DIVIDEM o mesmo
   contador (mesmo controller, mesmo balde) e linka para o irmão. */
.api-op-meta { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 1.25rem; }
.api-chip {
  font-family: var(--font-mono); font-size: 0.7rem; color: var(--muted);
  background: var(--bg-tertiary); border: 1px solid var(--border-3);
  border-radius: 5px; padding: 0.28em 0.6em;
}
.api-chip--limit { color: var(--gold-hover); border-color: var(--gold-border); background: color-mix(in oklab, var(--gold) 8%, var(--bg-tertiary)); }
.api-chip--shared { color: var(--orange); border-color: color-mix(in oklab, var(--orange) 45%, transparent); background: color-mix(in oklab, var(--orange) 10%, var(--bg-tertiary)); text-decoration: none; }
.api-chip--public { color: var(--green); border-color: color-mix(in oklab, var(--green) 45%, transparent); background: color-mix(in oklab, var(--green) 10%, var(--bg-tertiary)); }

/* Subtítulo de bloco (Parameters, Request body, Responses): mono, como th. */
.api-op-sub {
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: normal;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted-2);
  margin: 1.75rem 0 0.6rem;
}
.api-mime { color: var(--muted-3); letter-spacing: 0; text-transform: none; margin-left: 0.4rem; }

/* Tabelas de campos. A .table-scroll continua sendo o wrapper (rede de segurança
   contra rolagem horizontal da PÁGINA), mas o `min-width: max-content` que ela
   impõe às tabelas de DADOS é errado aqui: a coluna de descrição é PROSA, e com
   max-content o leitor teria de rolar cada linha para terminar a frase. Aqui a
   descrição quebra. */
.table-scroll .api-table { min-width: 0; }
.api-table { font-size: 0.88rem; }
.api-table td:nth-child(2) { white-space: nowrap; }
.api-table th, .api-table td { padding: 0.55rem 0.9rem 0.55rem 0; vertical-align: top; border-bottom: 1px solid var(--border-2); }
.api-table tbody tr:last-child td { border-bottom: none; }
.api-table .api-prose { font-size: 0.88rem; color: var(--muted); }
.api-table .api-prose p { margin: 0 0 0.4rem; }
.api-field { font-family: var(--font-mono); font-size: 0.85rem; color: var(--gold-hover); }
/* Marcador só onde ele INFORMA: "required" no que você ENVIA (a pergunta é "o que
   preciso mandar?") e "optional" no que você RECEBE (a pergunta é "com o que posso
   contar?" — quase todo campo de resposta é garantido, então marcar os obrigatórios
   seria carimbar a tabela inteira e não dizer nada). */
.api-req { font-family: var(--font-mono); font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--orange); margin-left: 0.4rem; }
.api-opt { font-family: var(--font-mono); font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-3); margin-left: 0.4rem; }
.api-enum { font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted-3); }
.api-variant { font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted-2); margin: 1.1rem 0 0.35rem; }
/* Campo aninhado (os arquivos dentro do batch de sidecars): recuo + nome menos
   forte que o do nível de cima. */
.api-depth-1 td:first-child { padding-left: 1.1rem; }
.api-depth-2 td:first-child { padding-left: 2.2rem; }
.api-depth-3 td:first-child { padding-left: 3.3rem; }
.api-depth-1 .api-field, .api-depth-2 .api-field, .api-depth-3 .api-field { color: var(--text-tertiary); }

/* Respostas: status colorido pela classe (2xx verde, 4xx laranja = foi você,
   5xx vermelho = fomos nós). */
.api-responses { list-style: none; padding: 0; margin: 0; }
.api-response { border-top: 1px solid var(--border-2); padding: 1rem 0; }
.api-response:first-child { border-top: 0; padding-top: 0; }
.api-response:last-child { padding-bottom: 0; }
.api-response-head { display: flex; gap: 0.8rem; align-items: baseline; }
.api-response-desc { font-size: 0.9rem; }
.api-status {
  font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600;
  padding: 0.18em 0.5em; border-radius: 5px; border: 1px solid; flex: none;
}
.api-status--ok { color: var(--green); border-color: color-mix(in oklab, var(--green) 45%, transparent); background: color-mix(in oklab, var(--green) 12%, var(--bg-tertiary)); }
.api-status--client { color: var(--orange); border-color: color-mix(in oklab, var(--orange) 45%, transparent); background: color-mix(in oklab, var(--orange) 12%, var(--bg-tertiary)); }
.api-status--server { color: var(--red); border-color: color-mix(in oklab, var(--red) 45%, transparent); background: color-mix(in oklab, var(--red) 12%, var(--bg-tertiary)); }
.api-status--redirect { color: var(--muted); border-color: var(--border-3); background: var(--bg-tertiary); }

.api-examples { margin-top: 0.75rem; }
.api-example-summary { font-size: 0.8rem; color: var(--muted-2); margin: 0.75rem 0 0.35rem; }

/* Índice vira cartão acima do conteúdo quando não cabe ao lado (o corpo precisa
   de largura para as tabelas). Os links reflui em linhas — não some no mobile. */
@media (max-width: 62rem) {
  /* minmax(0, 1fr) e não 1fr: a coluna precisa poder encolher abaixo do
     min-content do índice (ver o min-width: 0 acima) — senão a página inteira
     fica mais larga que a viewport e rola na horizontal. */
  .api-layout { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .api-toc {
    position: static; max-height: none; overflow: visible;
    background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 14px;
    padding: 1.2rem 1.35rem;
  }
  /* Índice em linhas que quebram (some o formato de coluna alta, que empurraria
     o conteúdo pra baixo da dobra no celular). */
  .api-toc-list { flex-direction: row; flex-wrap: wrap; gap: 0.5rem 1rem; }
  .api-toc-list li { max-width: 100%; }
}
@media (max-width: 48rem) {
  .api-op { padding: 1.3rem 1.15rem; }
  .api-section-title { font-size: 1.55rem; }
  .api-op-path { font-size: 0.85rem; overflow-wrap: anywhere; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Cofre da conta — índice canônico (issue #81). Converge para o padrão de
   visualização instantânea da wiki: o root leva a classe .rwcat para herdar a
   toolbar/sidebar/chips/tray/compare e a visibilidade por modo (data-rwcat-mode).
   O que é próprio do stash leva prefixo .stash-. ATENÇÃO: o root usa .stash-index,
   NÃO .stash-list (essa é do dashboard, .stash-list li + li em application.css:381,
   que vazaria margem pra todo card/soquete daqui).
   ══════════════════════════════════════════════════════════════════════════ */

/* Visibilidade por modo (100% CSS, sem JS): qualquer elemento marcado com
   data-stash-mode (card, linha de localização, resumo, nota de legado) do modo
   inativo some. O applyFilters do controller também gateia os cards por modo (a
   contagem exclui o modo inativo) — os dois concordam. */
.rwcat[data-rwcat-mode="softcore"] [data-stash-mode="hardcore"] { display: none; }
.rwcat[data-rwcat-mode="hardcore"] [data-stash-mode="softcore"] { display: none; }

/* Links de topo (Histórico + backup legado) — não são filtro; a sidebar abaixo
   só tem filtro de verdade. */
/* margin explícito zera o 1em default do <p> e dá respiro sob a caixa da conta
   (0.9rem acima; sem margem abaixo — o margin-top:1.5rem da toolbar governa o gap
   até ela, igual ao /wiki/runewords). */
.stash-toplinks { display: flex; flex-wrap: wrap; gap: 0.4rem 0.6rem; margin: 0.9rem 0 0; }
.stash-toplinks-sep { color: var(--border-4); }
.stash-toplinks a { font-family: var(--font-mono); font-size: 0.8rem; }

/* ── Resultados: um único DOM, Detailed vira card com props, Compact vira linha ── */
.stash-results { list-style: none; padding: 0; margin: 0; }
/* Cards levemente mais largos (o miolo agora é arte + props lado a lado): trilhos
   fluidos de no mín. ~21rem em vez das 2 colunas fixas — reflui sozinho e dá mais
   respiro horizontal ao par arte/props. */
.stash-results--detailed { display: grid; grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr)); gap: 0.5rem; align-content: start; }
.stash-results--compact { display: flex; flex-direction: column; gap: 0.1rem; }

/* Card inteiro clicável (stash-list#cardClick abre a modal); o trigger continua
   focável pelo teclado (a11y inalterada). */
.stash-card { position: relative; cursor: pointer; }
/* Cara de card em Detailed E no comparativo (fora do .stash-results). Coluna flex
   para o rodapé de posse (.stash-card-status) ancorar embaixo via margin-top:auto —
   mesma altura em cards vizinhos da grade, como o rodapé do card de runewords. */
.stash-results--detailed > .stash-card,
.stash-compare-col .stash-card {
  display: flex; flex-direction: column; align-items: stretch;
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 9px; padding: 0.5rem 0.75rem;
}
.stash-results--detailed > .stash-card:hover { border-color: var(--border-4); }
.stash-card-line { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.25rem 0.4rem; }
/* Detailed (e comparativo): o ícone inline do título some — a arte grande no slot
   abaixo já identifica. Em Compact o miolo é escondido e o ícone reaparece na linha
   (esta regra é escopada ao Detailed, então não o alcança lá). */
.stash-results--detailed .stash-card .stash-card-line .item-icon,
.stash-compare-col .stash-card .stash-card-line .item-icon { display: none; }
/* Miolo Detailed (issue #85): 2 colunas [slot fixo | props]. align-items:center
   centra as props verticalmente ao lado do slot — mata o buraco embaixo dos cards
   pobres, e o slot fica no meio dos cards ricos. */
.stash-card-main { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0.75rem; margin-top: 0.55rem; }
.stash-card-props { min-width: 0; display: grid; gap: 0.1rem; }
/* Slot de arte com proporcionalidade contínua (issue #85): a arte ocupa tantas células
   quantas ocupa no inventário do jogo — o helper carimba a combinação como CLASSE e o
   CSS multiplica --cw/--ch por --item-cell. Classe (não atributo style inline) porque o
   CSP é `style-src 'self' 'nonce'` sem unsafe-inline: o nonce não cobre `style=`, então
   um atributo inline seria descartado e tudo cairia no fallback 2×2. A caixa tem LARGURA
   FIXA (2 células) pra as colunas de props não desalinharem; a altura acompanha --ch
   (mínimo 2). Compartilhado entre o card do personagem e o Detailed do stash. */
.item-art-slot {
  --item-cell: 2rem;   /* o único número que o Filipe calibra */
  flex: none;
  width: calc(2 * var(--item-cell));
  height: calc(max(var(--ch, 2), 2) * var(--item-cell));
  display: flex; align-items: center; justify-content: center;
  /* sem padding: a arte de 2 células ocupa a largura CHEIA do slot (a caixa já é o
     tamanho da grade); largura fixa mantém o alinhamento das colunas de props. */
  padding: 0; color: var(--muted);
}
/* As 8 combinações do D2 (cw 1-2 × ch 1-4) definem --cw/--ch pela classe — o helper
   clampa qualquer arte inesperada pra dentro deste range, então não há combo órfã. */
.item-art-slot--1x1 { --cw: 1; --ch: 1; }
.item-art-slot--1x2 { --cw: 1; --ch: 2; }
.item-art-slot--1x3 { --cw: 1; --ch: 3; }
.item-art-slot--1x4 { --cw: 1; --ch: 4; }
.item-art-slot--2x1 { --cw: 2; --ch: 1; }
.item-art-slot--2x2 { --cw: 2; --ch: 2; }
.item-art-slot--2x3 { --cw: 2; --ch: 3; }
.item-art-slot--2x4 { --cw: 2; --ch: 4; }
/* Arte grande (webp) e PNG do lote 1-2 escalam pelas células: --cw × --ch × cell.
   contain como rede de segurança (a proporção já sai das próprias células). */
.item-art-slot > img,
.item-art-slot .item-icon--img img {
  display: block;
  width: calc(var(--cw, 2) * var(--item-cell));
  height: calc(var(--ch, 2) * var(--item-cell));
  object-fit: contain;
}
/* Glifo SVG (sem dimensões → 2×2): tamanho de destaque fixo, centrado. */
.item-art-slot .item-icon {
  width: 100%; height: 100%; padding: 0; background: none; border: 0; border-radius: 0;
  align-items: center; justify-content: center;
}
.item-art-slot .item-icon svg { width: 2.5rem; height: 2.5rem; }
.item-art-slot .item-icon--img { width: 100%; height: 100%; }
/* Stack sem props (chaves, tomos): a quantidade vira o conteúdo da coluna de props. */
.stack-qty { font-family: var(--font-mono); font-size: 0.94rem; color: var(--gold); }
.stash-prop-group + .stash-prop-group { margin-top: 0.3rem; }
/* Rótulo do slot (arma / armadura-elmo / escudo) nas props de runa/gema. */
.stash-prop-label {
  font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--muted-2); margin-bottom: 0.05rem;
}
.stash-prop { font-size: 0.8rem; line-height: 1.45; color: var(--prop-color); }
/* Rodapé de posse (runa/gema): check verde possuído × "faltando" muted, visual
   análogo ao status da runewords ("Ready to make"/"Missing"). */
/* margin-top:auto ancora o rodapé embaixo (cards vizinhos = mesma altura na grade);
   o separador (border-top) acompanha. No card mais alto da linha o auto colapsa a
   zero, então o respiro mínimo entra como margin-bottom das props (só quando há
   rodapé de posse). */
.stash-card-status { margin-top: auto; padding-top: 0.4rem; border-top: 1px solid var(--border); }
.stash-card:has(> .stash-card-status) > .stash-card-main { margin-bottom: 0.4rem; }
.stash-status { font-family: var(--font-mono); font-size: 0.72rem; }
.stash-status--owned { color: var(--green); }
.stash-status--missing { color: var(--muted); }
/* Compact: linha densa como a lista antiga; sem card, sem miolo/status/soquetes. */
.stash-results--compact > .stash-card { padding: 0.15rem 0; }
.stash-results--compact .stash-card-main,
.stash-results--compact .stash-card-status,
.stash-results--compact .socket-list { display: none; }
/* Stack zerado nas grades avançadas: presente mas apagado (regra visual única). */
.stash-card.stack-empty { opacity: 0.35; }

/* ── Compare: badge de seleção + cursor ── */
.stash-card-badge {
  display: none; position: absolute; top: -0.4rem; left: -0.4rem;
  width: 1.15rem; height: 1.15rem; border-radius: 50%; z-index: 2;
  background: var(--gold); color: var(--bg); font-family: var(--font-mono); font-size: 0.62rem;
  align-items: center; justify-content: center;
}
.stash-card--selected .stash-card-badge { display: inline-flex; }
.stash-card--selected { outline: 1px solid var(--gold-border); outline-offset: 1px; border-radius: 9px; }
.rwcat--comparing .stash-card { cursor: pointer; }
.stash-compare-col .stash-card { cursor: default; }
.stash-tray-name { font-family: var(--font-serif); }

@media (max-width: 48rem) {
  .stash-results--detailed { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Catálogo de itens — esqueleto de card compartilhado (.catalog-*) + posse do
   grail (.grail-*). O root leva .rwcat e herda toolbar/sidebar/chips/shell/empty/
   active; o slot de arte é o compartilhado (.item-art-slot). O card é irmão visual
   do .stash-card (título em cima, miolo [arte | meta], rodapé). As classes
   .catalog-card*, .catalog-results* e .catalog-compare-col vestem o grail (#86) E o
   catálogo público /wiki/items (#87) — renomeadas de .grail-* na #88 porque não são
   próprias do grail. O que é GENUINAMENTE do grail (posse) fica com prefixo .grail-:
   .grail-account-*, .grail-status* (três estados no rodapé), .grail-owned-location e
   .grail-card--missing (o card nunca-achado apagado).
   ══════════════════════════════════════════════════════════════════════════ */

/* Faixa de conta: % geral em destaque + x/y por categoria. */
.grail-account-pct { font-family: var(--font-serif); font-weight: 700; font-size: 1.9rem; color: var(--gold); line-height: 1; }
.grail-account-totals { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.catalog-account-sep { color: var(--border-4); }
.grail-explainer { margin: 0.9rem 0 0; }

/* Resultados: mesmo idioma do stash — Detailed vira card com arte+meta, Compact
   vira linha densa. */
.catalog-results { list-style: none; padding: 0; margin: 0; }
.catalog-results--detailed { display: grid; grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr)); gap: 0.5rem; align-content: start; }
.catalog-results--compact { display: flex; flex-direction: column; gap: 0.1rem; }

/* Card inteiro clicável (grail-list/wiki-items #cardClick abre a modal); o trigger
   continua focável pelo teclado. */
.catalog-card { position: relative; cursor: pointer; }
/* Cara de card em Detailed E no comparativo (fora do .catalog-results, o CSS de
   Detailed não o alcança — issue #87, compare do /wiki/items): coluna flex pro
   rodapé ancorar embaixo (margin-top:auto), mesma altura em cards vizinhos. */
.catalog-results--detailed > .catalog-card,
.catalog-compare-col .catalog-card {
  display: flex; flex-direction: column; align-items: stretch;
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 9px; padding: 0.5rem 0.75rem;
}
.catalog-results--detailed > .catalog-card:hover { border-color: var(--border-4); }
/* Compare (#87): seleção com borda dourada (reusa o token dos irmãos) e cursor
   inerte na coluna do comparativo. O badge numerado usa .rwcat-card-badge/
   .rwcat-card--selected compartilhados — só a borda precisa de especificidade
   maior que a do card em Detailed. */
.catalog-card.rwcat-card--selected { border-color: var(--gold-border); }
.catalog-compare-col .catalog-card { cursor: default; }
.catalog-card-line { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.25rem 0.4rem; }
/* Detailed: o ícone inline do título some SÓ nos cards com slot de arte (unique/
   set) — a arte grande abaixo já identifica. A runa (sem slot) mantém o PNG inline
   no título. Em Compact o miolo some e o ícone reaparece (regra escopada ao Detailed). */
.catalog-results--detailed .catalog-card--art .catalog-card-line .item-icon,
.catalog-compare-col .catalog-card--art .catalog-card-line .item-icon { display: none; }
/* Miolo Detailed: 2 colunas [slot fixo | meta], meta centrada ao lado do slot. */
.catalog-card-main { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0.75rem; margin-top: 0.55rem; }
/* Miolo em coluna: base/meta em cima, grupos de props abaixo (mesmo idioma do
   .stash-card-props, que reusamos aqui). */
.catalog-card-props { min-width: 0; display: grid; gap: 0.1rem; }
.catalog-card-meta { font-size: 0.8rem; line-height: 1.45; color: var(--muted); }
/* Respiro entre a meta e a 1ª linha de props quando o card tem props na face. */
.catalog-card-meta:not(:only-child) { margin-bottom: 0.15rem; }

/* Rodapé de posse (três estados): verde tenho / âmbar achado-não-possuo / muted
   faltando, + a data encostada à direita. margin-top:auto ancora embaixo; o
   respiro mínimo entra como margin-bottom do miolo quando o auto colapsa. */
.catalog-card-status { margin-top: auto; padding-top: 0.4rem; border-top: 1px solid var(--border); display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.catalog-card:has(> .catalog-card-status) > .catalog-card-main { margin-bottom: 0.4rem; }
.grail-status { font-family: var(--font-mono); font-size: 0.72rem; }
.grail-status--owned { color: var(--green); }
.grail-status--gone { color: var(--orange); }
.grail-status--missing { color: var(--muted); }
.catalog-card-status span[title] { font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted-2); margin-left: auto; }

/* Nunca achado: card apagado, mesmo grau do stack-empty. */
.grail-card--missing { opacity: 0.35; }
/* No compare (#89) o faltante foi escolhido de propósito pra ler o range default
   lado a lado: sobe a opacidade pra ficar legível, mas segue mais fraco que a
   coluna do possuído (o rodapé "Missing" também sinaliza a posse). */
.catalog-compare-col .grail-card--missing { opacity: 0.72; }

/* Compact: linha densa, sem miolo/rodapé (como a lista antiga). */
.catalog-results--compact > .catalog-card { padding: 0.15rem 0; }
.catalog-results--compact .catalog-card-main,
.catalog-results--compact .catalog-card-status { display: none; }

/* Linha de localização do item possuído na modal (muted, no rodapé). */
.grail-owned-location { color: var(--muted); }

@media (max-width: 48rem) {
  .catalog-results--detailed { grid-template-columns: 1fr; }
}

/* ── Equipamento do personagem como cards (issue #85) ────────────────────────
   Mesma linguagem do card Detailed do stash: grade fluida, título em cima e o
   miolo [slot fixo | props] reusando .item-art-slot / .stash-card-main /
   .stash-card-props. Sem toggle Compact aqui — o card é o único modo. */
ul.items.char-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr)); gap: 0.5rem; align-content: start; }
.char-item {
  display: flex; flex-direction: column; align-items: stretch;
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 9px; padding: 0.5rem 0.75rem;
}
.char-items > .char-item { padding: 0.5rem 0.75rem; }   /* vence o ul.items > li de 0.15rem */
/* Card inteiro clicável (issue #85, item-card): cursor só quando há modal para abrir
   — o card sem .item-trigger (item comum) não finge clicável. */
.char-item:has(.item-trigger) { cursor: pointer; }
.char-item-line { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.25rem 0.4rem; }
/* O título do card do personagem não carrega ícone inline (issue #85): a arte/glifo
   vive no slot fixo do miolo. */

/* ============================================================================
   Drop calculator da wiki (issue #99, fase 2). Form de settings (reusa os tokens
   das famílias .calc- e .rwcat-) + resultados no idioma rwcat. Compact é o DEFAULT: uma
   datatable via CSS grid + subgrid — colunas alinhadas entre as linhas, mas com
   o box da linha preservado (hover/borda). Detailed vira card (MESMO DOM). As
   células trazem um rótulo (.dropcalc-clabel) escondido no Compact e mostrado no
   Detailed. Prefixo .dropcalc-.
   ========================================================================= */
.dropcalc [hidden] { display: none !important; }

/* ── Painel de settings ── */
.dropcalc-panel { margin: 1.25rem 0 0; }
.dropcalc-panel-title { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted-2); margin-bottom: 1rem; padding-bottom: 0.7rem; border-bottom: 1px solid var(--border-2); }
/* Grade única de campos. Cada .dropcalc-field ocupa DUAS linhas da grade-mãe via
   subgrid (label em cima, controle embaixo): a linha dos labels tem a altura do
   maior rótulo do bloco (rótulo de locale largo pode quebrar em 2 linhas sem
   desalinhar) e a linha dos controles fica na mesma altura para todos. O
   `align-items: start` mantém cada bloco independente na vertical. */
.dropcalc-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); gap: 0.9rem 1rem; align-items: start; }
.dropcalc-field { grid-row: span 2; display: grid; grid-template-rows: subgrid; row-gap: 0.35rem; min-width: 0; }
.dropcalc-field--wide { grid-column: 1 / -1; }
/* Hint do personagem: linha própria de largura total logo abaixo dos controles —
   transborda pra baixo sem empurrar a altura/baseline dos vizinhos. */
.dropcalc-field--hint { grid-column: 1 / -1; }
/* Label alinhado à base da sua linha: rótulo de 1 ou 2 linhas encosta no controle. */
.dropcalc-label { align-self: end; font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted); line-height: 1.25; }
/* min-width:0 em TODA célula de controle + no próprio controle: sem isso o
   min-width:auto do grid item trava a largura no min-content (number input tem
   largura intrínseca ~180px) e o controle vaza por baixo da coluna vizinha em
   larguras intermediárias (o switch do Terror sobrepondo o MF — bug #99). Com
   min-width:0 + width:100% cada controle encolhe exatamente até o track. */
.dropcalc-select { position: relative; min-width: 0; }
.dropcalc-select select { appearance: none; -webkit-appearance: none; box-sizing: border-box; width: 100%; min-width: 0; height: 100%; background: var(--bg-tertiary); border: 1px solid var(--border-3); border-radius: 7px; color: var(--text); font: inherit; font-size: 0.85rem; padding: 0.5rem 1.8rem 0.5rem 0.7rem; cursor: pointer; }
.dropcalc-select::after { content: "▼"; position: absolute; right: 0.7rem; top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--muted-2); font-size: 0.6rem; }
/* box-sizing:border-box explícito: o number input renderiza content-box (regra
   `input` do UA vence o reset global `*`), então width:100% + padding vazaria a
   coluna (24.4px → sobreposição no vizinho). Com border-box, 100% = o track. */
.dropcalc-input { box-sizing: border-box; width: 100%; min-width: 0; background: var(--bg-tertiary); border: 1px solid var(--border-3); border-radius: 7px; color: var(--text); font: inherit; font-size: 0.85rem; padding: 0.5rem 0.7rem; outline: none; }
.dropcalc-input:focus-visible { border-color: var(--gold-border); }
/* Célula do checkbox: estica pra altura da linha dos controles e centra o switch
   (que NÃO estica — é um switch, flex:none); min-width:0 pra célula respeitar o
   track sem o switch vazar pra coluna vizinha. */
.dropcalc-check-cell { display: flex; align-items: center; min-height: 2.35rem; min-width: 0; }
/* Terror Zone como switch (affordance da maxroll), CSS puro e sem markup extra: o
   MESMO checkbox por baixo (name/valor/handler intactos) vira trilho + botão
   deslizante. O botão é um radial-gradient animado por background-position — sem
   `::before` no <input> (o Firefox não renderiza pseudo em input). Dourado ligado,
   neutro desligado; dark é o único tema. Altura 1.5rem = 24px de alvo de clique. */
.dropcalc-check-cell input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; flex: none; margin: 0; cursor: pointer;
  width: 2.6rem; height: 1.5rem; border-radius: 999px;
  border: 1px solid var(--border-3); background-color: var(--bg-tertiary);
  background-image: radial-gradient(circle 0.52rem, var(--muted-2) 96%, transparent 97%);
  background-repeat: no-repeat; background-size: 1.1rem 100%; background-position: 0.2rem 50%;
  transition: background-position 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.dropcalc-check-cell input[type="checkbox"]:hover { border-color: var(--border-4); }
.dropcalc-check-cell input[type="checkbox"]:checked {
  background-color: var(--gold); border-color: var(--gold);
  background-image: radial-gradient(circle 0.52rem, var(--bg) 96%, transparent 97%);
  background-position: calc(100% - 0.2rem) 50%;
}
.dropcalc-check-cell input[type="checkbox"]:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; }
/* Busca + select do item, empilhados na célula do controle (campo full-width). */
.dropcalc-item-control { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.dropcalc-hint { font-size: 0.68rem; color: var(--muted-3); margin: 0; line-height: 1.4; }
.dropcalc-submit { display: inline-block; margin-top: 1rem; font-family: var(--font-mono); font-size: 0.78rem; }

/* ── Estado vazio (nenhum monstro/item escolhido) ── */
.dropcalc-blank { margin-top: 1.6rem; padding: 1.6rem; text-align: center; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; }
.dropcalc-blank-title { font-family: var(--font-serif); font-size: 1.05rem; color: var(--text); margin: 0 0 0.4rem; }
.dropcalc-blank-body { color: var(--muted); font-size: 0.88rem; line-height: 1.5; margin: 0; max-width: 40rem; margin-inline: auto; }

/* ── Cabeçalho do resultado ── */
.dropcalc-result-head { margin-top: 1.6rem; }
.dropcalc-result-subject { font-family: var(--font-serif); font-size: 1.1rem; color: var(--text); margin: 0; }
.dropcalc-result-settings { font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted-2); margin: 0.25rem 0 0; }

/* ── Filtro de qualidade (segmentado, single-select) — reusa .mode-toggle ── */
.dropcalc-quality { flex-wrap: wrap; gap: 0.5rem; margin: 0.9rem 0 0; }

/* ── Toolbar (reusa .rwcat-search/.rwcat-btn/.rwcat-count/.rwcat-sort) ── */
.dropcalc-toolbar { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 1rem 0 0; }
.dropcalc-count { margin-left: auto; }
.dropcalc-count-total { color: var(--muted); }

/* ── Estado sem resultado da busca ── */
.dropcalc-empty { margin-top: 1.1rem; padding: 1.4rem; text-align: center; background: var(--surface); border: 1px dashed var(--border-3); border-radius: 10px; }
.dropcalc-empty-title { font-family: var(--font-serif); color: var(--text); margin-bottom: 0.3rem; }
.dropcalc-empty-body { color: var(--muted); font-size: 0.85rem; margin: 0; }

/* ── Resultados ── */
.dropcalc-scroll { margin-top: 0.9rem; }
/* COMPACT (default): grid-table. O container define as colunas; cabeçalho e
   linhas herdam via subgrid (span 1/-1), alinhando as células entre as linhas
   e mantendo o box da linha para hover/borda. */
.dropcalc-results--compact { display: grid; gap: 0; }
.dropcalc-results--monsters.dropcalc-results--compact {
  grid-template-columns: minmax(11rem, 2.2fr) repeat(5, minmax(3.6rem, 1fr));
}
.dropcalc-results--items.dropcalc-results--compact {
  grid-template-columns: minmax(11rem, 2fr) minmax(6rem, 1fr) minmax(9rem, 1.6fr) minmax(5rem, 1fr);
}
.dropcalc-results--compact .dropcalc-head,
.dropcalc-results--compact .dropcalc-row {
  display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center;
}
.dropcalc-head { border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--bg); z-index: 1; }
.dropcalc-hc { font-family: var(--font-mono); font-size: 0.64rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted-2); padding: 0.55rem 0.7rem; }
.dropcalc-hc-chance, .dropcalc-hc-magic, .dropcalc-hc-rare, .dropcalc-hc-set, .dropcalc-hc-unique { text-align: right; }
.dropcalc-results--compact .dropcalc-row { border-bottom: 1px solid var(--border-2); }
.dropcalc-results--compact .dropcalc-row:hover { background: rgba(198, 160, 90, 0.06); }
.dropcalc-c { display: flex; align-items: center; min-width: 0; padding: 0.4rem 0.7rem; font-size: 0.84rem; }
.dropcalc-results--compact .dropcalc-c-name { flex-direction: column; align-items: flex-start; gap: 0.05rem; }
.dropcalc-results--compact .dropcalc-c-chance,
.dropcalc-results--compact .dropcalc-c-magic,
.dropcalc-results--compact .dropcalc-c-rare,
.dropcalc-results--compact .dropcalc-c-set,
.dropcalc-results--compact .dropcalc-c-unique { justify-content: flex-end; }
/* Sem `color` aqui: a cor vem da classe de raridade do catálogo (.q-unique gold,
   .q-set green, .q-rune, .q-normal branco) aplicada no próprio span — igual à
   wiki/items. No modo items o nome é de MONSTRO (sem raridade): cor neutra abaixo. */
.dropcalc-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.dropcalc-results--items .dropcalc-name { color: var(--text); }
/* Linhas que são itens concretos (unique/set/runa/gema): clicáveis, com ficha no
   hover/tap (base branca e o modo items ficam de fora — não têm ficha). */
.dropcalc-row[data-wdrops-quality="unique"],
.dropcalc-row[data-wdrops-quality="set"],
.dropcalc-row[data-wdrops-quality="rune"],
.dropcalc-row[data-wdrops-quality="gem"] { cursor: pointer; }
.dropcalc-row[data-wdrops-quality="unique"]:hover .dropcalc-name,
.dropcalc-row[data-wdrops-quality="set"]:hover .dropcalc-name,
.dropcalc-row[data-wdrops-quality="rune"]:hover .dropcalc-name,
.dropcalc-row[data-wdrops-quality="gem"]:hover .dropcalc-name { text-decoration: underline; text-underline-offset: 2px; }
.dropcalc-sub { font-size: 0.7rem; color: var(--muted-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
/* O valor é o próprio texto da célula (sem wrapper, dieta de DOM). */
.dropcalc-c-chance { font-family: var(--font-mono); color: var(--gold); }
.dropcalc-c-magic, .dropcalc-c-rare, .dropcalc-c-set, .dropcalc-c-unique { font-family: var(--font-mono); color: var(--text-secondary); }
.dropcalc-c-area { color: var(--muted); }

/* DETAILED: cards (mesmo DOM). Os rótulos das colunas de qualidade voltam via
   `::before` (jargão fixo Magic/Rare/Set/Unique — igual nos 7 locales), então
   não pesam no DOM de cada linha. Nome é o título e a chance é o número grande;
   items específicos (unique/set) escondem o split de qualidade (é sempre N/A). */
.dropcalc-results--detailed { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.7rem; }
.dropcalc-results--detailed .dropcalc-head { display: none; }
.dropcalc-results--detailed .dropcalc-row {
  display: flex; flex-direction: column; gap: 0.4rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 0.8rem 0.9rem;
}
.dropcalc-results--detailed .dropcalc-c { padding: 0; justify-content: space-between; gap: 0.6rem; }
.dropcalc-results--detailed .dropcalc-c-name { flex-direction: column; align-items: flex-start; gap: 0.15rem; }
.dropcalc-results--detailed .dropcalc-name { font-family: var(--font-serif); font-size: 1rem; white-space: normal; }
.dropcalc-results--detailed .dropcalc-sub { white-space: normal; }
.dropcalc-results--detailed .dropcalc-c-chance { align-items: baseline; font-size: 1.15rem; }
.dropcalc-results--detailed .dropcalc-c-magic::before { content: "Magic"; }
.dropcalc-results--detailed .dropcalc-c-rare::before { content: "Rare"; }
.dropcalc-results--detailed .dropcalc-c-set::before { content: "Set"; }
.dropcalc-results--detailed .dropcalc-c-unique::before { content: "Unique"; }
.dropcalc-results--detailed .dropcalc-c-magic::before,
.dropcalc-results--detailed .dropcalc-c-rare::before,
.dropcalc-results--detailed .dropcalc-c-set::before,
.dropcalc-results--detailed .dropcalc-c-unique::before { font-family: var(--font-mono); font-size: 0.7rem; color: var(--muted-2); }
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="unique"] .dropcalc-c-magic,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="unique"] .dropcalc-c-rare,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="unique"] .dropcalc-c-set,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="unique"] .dropcalc-c-unique,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="set"] .dropcalc-c-magic,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="set"] .dropcalc-c-rare,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="set"] .dropcalc-c-set,
.dropcalc-results--detailed .dropcalc-row[data-wdrops-quality="set"] .dropcalc-c-unique { display: none; }

/* ── Mobile ── */
@media (max-width: 34rem) {
  .dropcalc-count { margin-left: 0; }
}
