:root {
    color-scheme: dark;

    /* Tema "Quest Forge" — noite arcana: fundo roxo-quase-preto, superficies de vidro roxo,
       acento primario roxo eletrico (#5b23ff) e acento de destaque lima (#e4ff30). Espelha o
       PaletteDark do MudTheme em MainLayout.razor para que o "chrome" do MudBlazor (app bar,
       drawers, dialogs) e o CSS isolado das paginas usem a mesma paleta. */
    --qf-bg: #0f0d1a;
    --qf-bg-alt: #151226;
    --qf-surface: #1a162a;
    --qf-surface-2: #191530;
    --qf-surface-3: #241f3a;
    --qf-border: #2a2247;
    --qf-border-strong: #3a2f63;

    --qf-text-primary: #edecf5;
    --qf-text-secondary: #b1adc6;
    --qf-text-muted: #8d88a6;
    --qf-text-faint: #6a6685;

    --qf-primary: #5b23ff;
    --qf-primary-strong: #4a1ad0;
    --qf-primary-hover: #6d3aff;
    --qf-primary-contrast: #ffffff;
    --qf-primary-soft-bg: rgba(91, 35, 255, 0.12);
    --qf-primary-soft-border: rgba(91, 35, 255, 0.4);
    --qf-focus-ring: rgba(228, 255, 48, 0.7);

    /* Acento de destaque (lima) — titulos, estados ativos, botoes de acao chave */
    --qf-accent:         #e4ff30;
    --qf-accent-bright:  #f0ffa3;
    --qf-accent-soft-bg: rgba(228, 255, 48, 0.10);
    --qf-accent-border:  rgba(228, 255, 48, 0.28);

    --qf-secondary: #b18aff;
    --qf-tertiary: #4fa8ff;
    --qf-info: #008bff;
    --qf-info-text: #4fa8ff;
    --qf-success: #3DAA70;
    --qf-success-soft-bg: rgba(61, 170, 112, 0.18);
    --qf-success-text: #6FE3A4;
    --qf-warning: #E0A93E;
    --qf-warning-soft-bg: rgba(224, 169, 62, 0.18);
    --qf-warning-text: #F0C975;
    --qf-danger: #E0566B;
    --qf-danger-strong: #B23A52;
    --qf-danger-dim: #6E2A38;
    --qf-danger-soft-bg: rgba(224, 86, 107, 0.18);
    --qf-danger-text: #F2879A;

    /* Camada RPG — mantida para compatibilidade de nomes; agora repontada para o acento lima
       (antes dourado) para que os estados "ativo"/destaque herdados por Mesa/toolbar/zoom
       sigam a nova identidade sem reescrever cada .razor.css. */
    --qf-rpg-gold:         #e4ff30;
    --qf-rpg-gold-bright:  #f0ffa3;
    --qf-rpg-gold-dim:     rgba(91, 35, 255, 0.35);
    --qf-rpg-gold-soft-bg: rgba(228, 255, 48, 0.10);
    --qf-rpg-gold-border:  rgba(228, 255, 48, 0.30);
    --qf-rpg-parchment:    #1a162a;
    --qf-rpg-leather:      #12101f;
    --qf-rpg-accent:       #b18aff;
    --qf-rpg-font-heading: "Cinzel", "Palatino Linotype", Georgia, serif;
    --qf-font-body:        "Alegreya Sans", "Segoe UI", system-ui, sans-serif;
}

/* Cinzel self-hosted — subset latin, pesos 400/600/700 */
@font-face {
    font-family: "Cinzel";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/fonts/cinzel-regular.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Cinzel";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/fonts/cinzel-semibold.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Cinzel";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/fonts/cinzel-bold.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

html, body {
    background-color: var(--qf-bg);
    color: var(--qf-text-primary);
    font-family: var(--qf-font-body, "Alegreya Sans", "Segoe UI", system-ui, sans-serif);
}

/* Na Mesa (redesign "Quest Forge - Mesa") a pagina vira uma tomada de tela cheia com cabecalho
   proprio (.mesa-topbar); o MudAppBar global fica redundante e, por conflito de stacking-context
   com o MudMainContent, chegava a vazar por cima do canto direito do cabecalho da Mesa (a pilula
   de sessao ficava coberta pela mud-toolbar). Escondê-lo enquanto uma .mesa-page existe resolve o
   vazamento sem afetar Entrada/Dashboard/CharacterCreator (que nao tem .mesa-page). :has() e
   suportado em todos os navegadores-alvo (Chromium/Firefox atuais). */
body:has(.mesa-page) .mud-appbar {
    display: none !important;
}

/* Front-door de login (Login.razor): a pagina e uma tomada de tela cheia com marca propria dentro
   do cartao. O MudAppBar herdado do MainLayout ("QUEST FORGE" no topo) fica redundante e o
   padding-top que o MudMainContent reserva para o appbar empurra o cartao para baixo do centro.
   Escondemos o appbar e zeramos o offset enquanto uma .login-page existir — mesmo padrao :has()
   usado pela .mesa-page acima, sem afetar Entrada/Dashboard/CharacterCreator. */
body:has(.login-page) .mud-appbar {
    display: none !important;
}

body:has(.login-page) .qf-main-content {
    padding-top: 0 !important;
}

/* Wordmark da barra superior (MudAppBar). Regra global (nao escopada): o <MudText> que carrega
   .appbar-title e renderizado por um componente filho (MudText), entao um seletor ::deep de
   MainLayout.razor.css nao tem ancestral escopado onde ancorar e nunca casa — ver memoria
   "web-black-theme-design-system" (bug de CSS-isolation pai/filho). Aqui, no CSS global, casa
   sempre. Cinzel + caixa alta + tracking largo para o wordmark "QUEST FORGE" da nova identidade. */
.appbar-title {
    font-family: var(--qf-rpg-font-heading, "Cinzel", "Palatino Linotype", Georgia, serif);
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--qf-accent-bright, #f0ffa3);
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* Titulo de secao de cartao ("Personagens", "Aplicar dano", "Selecionado", "Habilidades"),
   reutilizado por Mesa.razor e varios componentes filhos (ApplyDamagePanel, CharacterListSidebar,
   SelectedTokenPanel). CSS isolation do Blazor escopa por componente, entao uma regra global
   aqui evita duplicar o mesmo bloco em cada .razor.css — uma regra isolada em Mesa.razor.css so
   bateria nos elementos literalmente escritos em Mesa.razor, nao nos componentes filhos que
   tambem usam essas classes. */
/* ==========================================================================
   Design system "Combat Log Card" (claude.ai/design, arquivo Combat Log
   Card.dc.html, opcao 3A "Barra completa — exemplo final"): tokens exatos do
   design aplicados a sidebar de preparacao/chat, aos cards de rolagem/ataque
   do chat e ao modal de ataque (4A). Definidos em :root (nao em .mesa-page)
   porque o modal de ataque renderiza no MudDialogProvider, fora da arvore da
   Mesa. Fontes: Sora + JetBrains Mono (App.razor).
   ========================================================================== */
:root {
    --dc-font: 'Sora', sans-serif;
    --dc-mono: 'JetBrains Mono', monospace;
    --dc-bg-panel: #13101d;
    --dc-bg-card: #1a1726;
    --dc-bg-inner: #211c31;
    --dc-bg-inner-hover: #1e1a2c;
    --dc-bg-footer: #161226;
    --dc-border: #2b2540;
    --dc-border-hover: #4a3f6b;
    --dc-text: #e8e4f2;
    --dc-text-soft: #b8b0cc;
    --dc-text-mut: #8a8299;
    --dc-text-dim: #6b6580;
    --dc-text-faint: #55506a;
    --dc-purple: #6d28d9;
    --dc-purple-bright: #7c3aed;
    --dc-indigo-bg: #2b2264;
    --dc-indigo-border: #4338ca;
    --dc-indigo-text: #c7d2fe;
    --dc-indigo: #6366f1;
    --dc-indigo-soft: #a5b4fc;
    --dc-roll-bg: #16233e;
    --dc-roll-border: #244a7a;
    --dc-roll-blue: #60a5fa;
    --dc-roll-blue-soft: #93b4e0;
    --dc-green-bg: #123626;
    --dc-green-border: #1f5c3d;
    --dc-green: #4ade80;
    --dc-green-name: #7dd3a8;
    --dc-red: #f87171;
    --dc-miss-bg: #2b2233;
    --dc-miss-border: #3d3450;
    --dc-miss-text: #9088a3;
    --dc-monster-bg: #3d1220;
}

/* Cabecalho de secao no padrao do design "Combat Log Card": rotulo Sora 10.5px
   #8a8299 (letter-spacing 1.5px) seguido de um fio de 1px #2b2540 que preenche
   a linha (::after flex 1). Acoes opcionais a direita (contador, "+ MP3")
   entram como irmaos depois do fio. */
.mesa-section-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--dc-text-mut, #8a8299);
    margin: 0;
    font-family: var(--dc-font, 'Sora', sans-serif);
}

.mesa-section-title::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--dc-border, #2b2540);
    order: 1;
}

/* Acao/indicador a direita do fio (contador de movimentacoes, "+ MP3"): order 2
   posiciona depois do ::after (order 1), reproduzindo "rotulo · fio · acao". */
.mesa-section-title .mesa-section-action {
    order: 2;
    letter-spacing: normal;
    text-transform: none;
}

.mesa-section-icon {
    display: none;
}

/* Headings temáticos RPG — Cinzel apenas em títulos >= 14px */
.mesa-session-code,
.turn-hud-name {
    font-family: var(--qf-rpg-font-heading);
}

/* ==========================================================================
   Tema cinemático da Mesa (feature mesa-design-cinematico, techspec.md)
   Camada de tokens `--qf-cine-*` ESCOPADA a `.mesa-page` — nao substitui os
   `--qf-*` base, que continuam servindo Entrada/Dashboard/CharacterCreator
   sem alteracao visual. Os tokens abaixo sao a fonte para o degrade
   indigo -> roxo do fundo full-bleed da Mesa e para os paineis de vidro
   (glassmorphism) que serao construidos nas tasks seguintes (GlassPanel,
   layout full-bleed, reestilizacao dos paineis filhos).
   ========================================================================== */
.mesa-page {
    --qf-cine-bg-0: #241f3a;
    --qf-cine-bg-1: #151226;
    --qf-cine-bg-2: #0f0d1a;
    --qf-cine-grad-primary: linear-gradient(135deg, #5b23ff 0%, #b18aff 100%);
    --qf-cine-glass-bg: rgba(26, 22, 42, 0.88);
    --qf-cine-glass-border: rgba(91, 35, 255, 0.16);
    --qf-cine-glass-gloss: linear-gradient(180deg, rgba(255, 255, 255, .05), transparent 55%);
    --qf-cine-glow-turn: rgba(228, 255, 48, 0.55); /* lima so em momentos-chave (turno ativo) */
    --qf-cine-blur: 16px;
    --qf-cine-ease: cubic-bezier(0.22, 1, 0.36, 1);

    /* Fundo cinematico roxo-quase-preto (radial, base full-bleed do mapa). */
    background:
        radial-gradient(120% 90% at 50% 30%, var(--qf-cine-bg-0) 0%, var(--qf-cine-bg-1) 55%, var(--qf-cine-bg-2) 100%);
}

/* --------------------------------------------------------------------------
   Keyframes globais compartilhados da camada cinematica — composite-only
   (apenas transform/opacity, nunca box-shadow/filter animados: evita
   repaint continuo por cima do canvas grande do mapa/fog, ver techspec.md
   "Decisoes Principais"). Consumidos pelas classes utilitarias abaixo e,
   nas proximas tasks, pelos paineis de vidro e pela entrada orquestrada.
   -------------------------------------------------------------------------- */
@keyframes mesa-cine-fade-scale-in {
    from {
        opacity: 0;
        transform: scale(.96);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes mesa-cine-slide-in-left {
    from {
        opacity: 0;
        transform: translateX(-24px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes mesa-cine-slide-in-right {
    from {
        opacity: 0;
        transform: translateX(24px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes mesa-cine-shimmer-sweep {
    from {
        transform: translateX(-100%);
    }

    to {
        transform: translateX(100%);
    }
}

@keyframes mesa-cine-pulse-opacity {
    0%, 100% {
        opacity: .35;
    }

    50% {
        opacity: .85;
    }
}

/* Classes utilitarias de entrada/efeito — pensadas para serem aplicadas
   pelos componentes das proximas tasks (GlassPanel, Mesa.razor, paineis
   filhos) sem duplicar `animation-name`/timing em cada `.razor.css`. */
.mesa-cine-enter-fade {
    animation: mesa-cine-fade-scale-in .5s var(--qf-cine-ease) both;
}

.mesa-cine-enter-slide-left {
    animation: mesa-cine-slide-in-left .45s var(--qf-cine-ease) both;
}

.mesa-cine-enter-slide-right {
    animation: mesa-cine-slide-in-right .45s var(--qf-cine-ease) both;
}

.mesa-cine-pulse {
    animation: mesa-cine-pulse-opacity 1.8s ease-in-out infinite;
}

/* Sweep de shimmer via pseudo-elemento (transform-only) — alternativa
   composite-only ao shimmer por `background-position` ja usado no
   skeleton estatico de Mesa.razor.css (que anima uma propriedade nao
   composite e fica de fora do escopo desta camada cinematica). */
.mesa-cine-shimmer {
    position: relative;
    overflow: hidden;
}

.mesa-cine-shimmer::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, .12) 50%, transparent 100%);
    transform: translateX(-100%);
    animation: mesa-cine-shimmer-sweep 1.6s ease-in-out infinite;
}

/* --------------------------------------------------------------------------
   Kill-switch central de `prefers-reduced-motion` — bloco unico que cobre
   toda a camada cinematica da Mesa (techspec.md "Decisoes Principais"):
   zera delays de cascata, remove pulsos/sweeps continuos e converte as
   animacoes de entrada com slide em fades curtos (<=150ms).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .mesa-page [class*="mesa-cine-enter-"] {
        animation-delay: 0ms !important;
    }

    .mesa-page .mesa-cine-pulse,
    .mesa-page .mesa-cine-shimmer::after {
        animation: none !important;
    }

    .mesa-page .mesa-cine-enter-fade {
        animation-duration: 150ms !important;
    }

    .mesa-page .mesa-cine-enter-slide-left,
    .mesa-page .mesa-cine-enter-slide-right {
        animation-name: mesa-cine-fade-scale-in !important;
        animation-duration: 150ms !important;
        transform: none !important;
    }
}

/* ==========================================================================
   Camada de efeitos do redesign da Mesa (design "Quest Forge - Mesa", projeto
   claude.ai/design "Redesign da plataforma RPG"): keyframes e micro-interacoes
   reproduzidos 1:1 do mockup. Os keyframes qf* sao globais (sem custo enquanto
   nao referenciados); as micro-interacoes de botao, o scrollbar fino e a cor de
   placeholder ficam ESCOPADOS a `.mesa-page` para nao regredir MudBlazor/demais
   paginas.
   ========================================================================== */

/* Pulso do ponto de status "ao vivo" no cabecalho (dot azul da sessao). */
@keyframes qfPulse {
    0%, 100% {
        opacity: 1;
        box-shadow: 0 0 0 0 rgba(0, 139, 255, 0.5);
    }

    50% {
        opacity: 0.7;
        box-shadow: 0 0 0 5px rgba(0, 139, 255, 0);
    }
}

/* Brilho de "brasa" que respira sobre o topo do mapa cinematico. */
@keyframes qfEmber {
    0%, 100% {
        opacity: 0.5;
    }

    50% {
        opacity: 0.9;
    }
}

/* Entrada com leve subida (estado vazio do mapa, mensagens do chat/dados). */
@keyframes qfRise {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Entrada lateral da ficha (drawer que desliza da esquerda). */
@keyframes qfSlideIn {
    from {
        opacity: 0;
        transform: translateX(-40px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Fade do backdrop do modal da ficha. */
@keyframes qfFadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* Micro-interacao "elastica" de todos os botoes da Mesa (design: hover levanta
   1.5px, active afunda 0.5px e encolhe; curva com overshoot). Escopada a
   .mesa-page para nao afetar os botoes do MudBlazor fora da mesa. */
.mesa-page button {
    transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
        box-shadow 0.25s ease, background 0.2s ease, color 0.2s ease,
        border-color 0.2s ease, opacity 0.2s ease, filter 0.2s ease;
    will-change: transform;
}

.mesa-page button:not(:disabled):hover {
    transform: translateY(-1.5px);
}

.mesa-page button:not(:disabled):active {
    transform: translateY(0.5px) scale(0.96);
    transition-duration: 0.07s;
}

.mesa-page button:focus-visible {
    outline: 2px solid var(--qf-focus-ring, rgba(228, 255, 48, 0.7));
    outline-offset: 2px;
}

/* Scrollbar fino roxo (design). */
.mesa-page ::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

.mesa-page ::-webkit-scrollbar-track {
    background: transparent;
}

.mesa-page ::-webkit-scrollbar-thumb {
    background: rgba(91, 35, 255, 0.25);
    border-radius: 3px;
}

.mesa-page ::-webkit-scrollbar-thumb:hover {
    background: rgba(91, 35, 255, 0.45);
}

.mesa-page * {
    scrollbar-color: rgba(91, 35, 255, 0.25) transparent;
    scrollbar-width: thin;
}

.mesa-page input::placeholder {
    color: var(--qf-text-faint, #6a6685);
}

/* Slider de volume da trilha (design: trilho fino roxo com fill, thumb lima). A
   classe .qf-vol e usada no markup do SoundtrackPanel; regra global porque o
   <input type="range"> vive num componente filho (CSS-isolation pai/filho). */
.mesa-page input[type="range"].qf-vol {
    -webkit-appearance: none;
    appearance: none;
    height: 3px;
    border-radius: 2px;
    background: linear-gradient(90deg, #5b23ff 0%, #5b23ff var(--fill, 100%), rgba(255, 255, 255, 0.12) var(--fill, 100%));
    outline: none;
}

.mesa-page input[type="range"].qf-vol::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #e4ff30;
    border: 2px solid #191530;
    box-shadow: 0 0 6px rgba(91, 35, 255, 0.6);
    cursor: pointer;
}

.mesa-page input[type="range"].qf-vol::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border: 2px solid #191530;
    border-radius: 50%;
    background: #e4ff30;
    box-shadow: 0 0 6px rgba(91, 35, 255, 0.6);
    cursor: pointer;
}

/* Reduced-motion: sem pulso/brasa contínuos nem overshoot elastico. */
@media (prefers-reduced-motion: reduce) {
    .mesa-page button {
        transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease;
        will-change: auto;
    }

    .mesa-page button:not(:disabled):hover,
    .mesa-page button:not(:disabled):active {
        transform: none;
    }
}


/* Skin "Combat Log Card" (claude.ai/design, opcao 4A "Seleção como cards"): o painel inteiro E o
   card do modal do design — fundo #1a1726, borda #2b2540, raio 16px, sombra profunda. Regras
   globais (nao CSS isolado) porque o mesmo card e desenhado por dois componentes
   (CombatAttackPanel inline/flutuante e AttackRollDialog dentro do MudDialogProvider). */
.combat-attack-panel {
    display: flex;
    flex-direction: column;
    width: 100%;
    background: var(--dc-bg-card, #1a1726);
    border: 1px solid var(--dc-border, #2b2540);
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
    font-family: var(--dc-font, 'Sora', sans-serif);
}

/* Cabecalho: tile 32px do alvo sobre #3d1220, titulo/subtitulo e botao fechar. */
.combat-attack-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--dc-border, #2b2540);
}

.combat-attack-target-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 10px;
    background: var(--dc-monster-bg, #3d1220);
    font-size: 16px;
    line-height: 1;
}

.combat-attack-heading {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.combat-attack-title {
    color: var(--dc-text, #e8e4f2);
    font-weight: 700;
    font-size: 14px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combat-attack-subtitle {
    color: var(--dc-text-dim, #6b6580);
    font-size: 11px;
}

.combat-attack-close {
    margin-left: auto;
    flex-shrink: 0;
    border: none;
    background: transparent;
    color: var(--dc-text-faint, #55506a);
    font-size: 15px;
    line-height: 1;
    padding: 2px;
    cursor: pointer;
    transition: color .15s ease;
}

.combat-attack-close:hover:not(:disabled) {
    color: var(--dc-text-soft, #b8b0cc);
}

/* Cards de selecao de ataque (4A): selecionado tem borda roxa #6d28d9, anel translucido, fundo
   #211c31 e radio preenchido; os demais ficam transparentes com hover #4a3f6b. */
.combat-attack-options {
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Duas secoes empilhadas (Ataques + Habilidades): a segunda nao repete o padding do topo. */
.combat-attack-options + .combat-attack-options {
    padding-top: 0;
}

/* Rotulo de grupo ("Ataques"/"Habilidades") quando o diálogo lista ataques E habilidades. */
.combat-attack-group-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--dc-text-dim, #6b6580);
    padding: 2px 2px 0;
}

.combat-attack-option {
    display: flex;
    align-items: center;
    gap: 12px;
    background: transparent;
    border: 1px solid var(--dc-border, #2b2540);
    border-radius: 12px;
    padding: 11px 12px;
    cursor: pointer;
    font-family: inherit;
    text-align: left;
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}

.combat-attack-option:hover:not(:disabled):not(.is-selected) {
    border-color: var(--dc-border-hover, #4a3f6b);
    background: var(--dc-bg-inner-hover, #1e1a2c);
}

.combat-attack-option:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.combat-attack-option.is-selected {
    background: var(--dc-bg-inner, #211c31);
    border-color: var(--dc-purple, #6d28d9);
    box-shadow: 0 0 0 1px rgba(109, 40, 217, 0.35);
}

.combat-attack-option-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    background: var(--dc-bg-inner, #211c31);
    font-size: 17px;
    line-height: 1;
}

.combat-attack-option.is-selected .combat-attack-option-icon {
    background: var(--dc-indigo-bg, #2b2264);
}

.combat-attack-option-info {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.combat-attack-option-name {
    color: var(--dc-text-soft, #b8b0cc);
    font-weight: 700;
    font-size: 13.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combat-attack-option.is-selected .combat-attack-option-name {
    color: var(--dc-text, #e8e4f2);
}

.combat-attack-option-expr {
    color: var(--dc-text-dim, #6b6580);
    font-size: 11px;
    font-family: var(--dc-mono, 'JetBrains Mono', monospace);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combat-attack-radio {
    margin-left: auto;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 2px solid var(--dc-miss-border, #3d3450);
}

.combat-attack-option.is-selected .combat-attack-radio {
    border-color: var(--dc-purple-bright, #7c3aed);
}

.combat-attack-radio-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--dc-purple-bright, #7c3aed);
}

/* Preview da rolagem (4A: box azul com o dado e a formula em mono). */
.combat-attack-preview {
    margin: 0 16px 12px;
    background: var(--dc-roll-bg, #16233e);
    border: 1px solid var(--dc-roll-border, #244a7a);
    border-radius: 10px;
    padding: 8px 12px;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
}

.combat-attack-preview-text {
    color: var(--dc-roll-blue-soft, #93b4e0);
    font-size: 11.5px;
    font-family: var(--dc-mono, 'JetBrains Mono', monospace);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Rodape (4A): CANCELAR (contorno) e ROLAR ATAQUE (roxo #6d28d9, hover #7c3aed). */
.combat-attack-actions {
    display: flex;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--dc-border, #2b2540);
    background: var(--dc-bg-footer, #161226);
}

.combat-attack-cancel {
    flex: 1 1 0;
    text-align: center;
    padding: 11px 0;
    border-radius: 10px;
    border: 1px solid var(--dc-border, #2b2540);
    background: transparent;
    color: var(--dc-text-mut, #8a8299);
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: border-color .15s ease, color .15s ease;
}

.combat-attack-cancel:hover:not(:disabled) {
    border-color: var(--dc-border-hover, #4a3f6b);
    color: var(--dc-text-soft, #b8b0cc);
}

.combat-attack-cancel:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.combat-attack-button {
    flex: 1.6 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    text-align: center;
    padding: 11px 0;
    border-radius: 10px;
    border: none;
    background: var(--dc-purple, #6d28d9);
    color: #ffffff;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: background-color .15s ease;
}

.combat-attack-button:hover:not(:disabled) {
    background: var(--dc-purple-bright, #7c3aed);
}

.combat-attack-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.combat-attack-error {
    font-size: 12px;
    color: var(--dc-red, #f87171);
    margin: 0;
    padding: 0 16px 12px;
    background: var(--dc-bg-footer, #161226);
}
    padding: 0 16px 12px;
.combat-attack-empty {
    margin: 0;
    padding: 12px 16px;
    color: var(--dc-text-dim, #6b6580);
    font-size: 12px;
}

/* AttackRollDialog (modal de ataque 4A): o card .combat-attack-panel desenha o proprio
   fundo/borda/sombra do design — o paper do MudDialog vira uma casca transparente sem padding.
   Regra global porque o paper e ancestral do markup do componente (CSS isolado nao alcanca). */
.mud-dialog:has(.combat-attack-panel) {
    background: transparent;
    box-shadow: none;
    width: 340px;
    max-width: calc(100vw - 24px);
}

.mud-dialog:has(.combat-attack-panel) .mud-dialog-content {
    padding: 0;
    margin: 0;
}

/* O card 4A ja tem cabecalho proprio ("Atacar {alvo}" + ✕) — a barra de titulo do MudDialog
   ficaria vazia/duplicada por cima dele. */
.mud-dialog:has(.combat-attack-panel) .mud-dialog-title {
    display: none;
}

/* Editar ficha (design "Barra Lateral Personagens" — modal tabbed DADOS/ATAQUES/HABILIDADES):
   reskin leve do MudDialog para a superficie escura arredondada do mock, sem reescrever os campos
   MudBlazor do formulario validado. Regra global porque o paper do MudDialog e ancestral do markup
   do componente (CSS isolado nao alcanca), escopada pela classe .character-edit-dialog aplicada no
   proprio MudDialog. */
.mud-dialog.character-edit-dialog {
    background: #101019;
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 16px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}

.mud-dialog.character-edit-dialog .mud-dialog-title {
    font-weight: 800;
    letter-spacing: 0.01em;
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

/* Aba ativa e indicador no roxo da marca (o mock usa a barra deslizante roxa sob a aba atual). */
.mud-dialog.character-edit-dialog .mud-tabs-toolbar .mud-tab.mud-tab-active {
    color: #b7abff;
}

.mud-dialog.character-edit-dialog .mud-tab-slider {
    background: #7c6cff;
}

/* Campos de texto/número com o fundo escuro do mock, mantendo o comportamento do MudBlazor. */
.mud-dialog.character-edit-dialog .mud-input-slot {
    background: #13131f;
    border-radius: 9px 9px 0 0;
}

/* Inventário do jogador via token selecionado (feature prd-inventario-modal-token, task 4.0):
   mesmo reskin escuro do MudDialog usado por .character-edit-dialog acima, escopado pela classe
   global .inventory-dialog aplicada no InventoryDialog (o paper do MudDialog e ancestral do
   InventoryPanel filho — CSS-isolado nao alcança, footgun ja registrado no design system). */
.mud-dialog.inventory-dialog {
    background: #101019;
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 16px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
    min-width: 320px;
}

.mud-dialog.inventory-dialog .mud-dialog-title {
    font-weight: 800;
    letter-spacing: 0.01em;
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
