/*
   ⛔⛔ THE STACKING CONTRACT (issue #532). Read this before typing a z-index anywhere.

   Floating panes are stacked by dm-panes.js in three BANDS:

       const BAND_BASE = [10, 200, 400];   // normal, pinned, always-on-top

   A pane's z is its band base plus its position within the band, so an always-on-top pane can sit a
   little above 400. Anything meant to cover the table must therefore clear 400 by a comfortable margin —
   and NOTHING in this codebase said so, which is how six of eight full-window dialogs came to sit below
   the pinned band. Dave plays with his windows pinned, so the "attack or leave it" prompt opened BEHIND
   them: invisible, un-clickable, and claiming aria-modal="true" while a pane took the clicks.

   ⚠️ The bands are bounded on purpose (a counter that only ever went up once walked past the page
   chrome). They were bounded to protect exactly these dialogs, and then nobody moved the dialogs above
   them. Use these tokens rather than a number, so the next dialog cannot repeat it.
*/
:root {
    /* ── BELOW the panes, on purpose. Surfaces the floating windows are meant to sit over. ── */

    /* The expanded table: the shell leaves the flow and takes the window. Panes float over it. */
    --dm-layer-shell: 80;
    /* The whole-map view. Above the expanded shell, still under the panes — a window the player
       dragged somewhere stays where they put it when the map is opened. */
    --dm-layer-map: 90;

    /* ── ABOVE the panes. Anything that must cover the table whatever is pinned. ── */

    /* Over the board and the panes, under a dialog: veils, scrims, drag shadows. */
    --dm-layer-scrim: 900;
    /* Every full-window dialog. Above every pane band including always-on-top. */
    --dm-layer-dialog: 1000;
    /* A dialog raised over another dialog — the bench over the character sheet, and its own header. */
    --dm-layer-dialog-over-dialog: 1100;
    /* Nothing may sit above this. Reserved for a hold that must not be dismissed by accident. */
    --dm-layer-blocking: 1200;
}

h1:focus {
    outline: none;
}

/* Global Blazor error boundaries keep a failed component action from terminating the circuit. */
.global-error {
    max-width: 48rem;
    margin: 3rem auto;
    padding: 1.5rem;
    border: 1px solid #8b5047;
    background: #241714;
    color: #eee2cf;
}

.global-error h1 { margin-top: 0; color: #e5a59a; }
.global-error a { color: #e6b85c; }

.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;
}

html,body{background:#080c14;color:#e7eaf2}body{margin:0;background:radial-gradient(circle at 14% 0,#202847 0,transparent 32%),#080c14;font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}#blazor-error-ui{background:#5f2429;color:#fff}
.app-nav{height:3rem;display:flex;align-items:center;justify-content:space-between;padding:0 2rem;border-bottom:1px solid #27334f;background:#0b101b}.app-nav a{color:#dbe4fb;text-decoration:none;font-size:.8rem;font-weight:700}.forge-voice{max-width:860px;margin:2rem auto;padding:1.5rem}.forge-voice .lede{color:#9da8c5;font-size:.85rem;line-height:1.6;max-width:60ch}.voice-warning{margin:1rem 0;padding:.9rem 1rem;border:1px solid #7a4a2a;border-radius:10px;background:#241a12;color:#e8c9a8;font-size:.8rem}.voice-warning ul{margin:.5rem 0 .5rem 1rem;padding:0}.cast-card h3{margin:1.25rem 0 .5rem;color:#dcb763;font-size:.8rem;letter-spacing:.06em;text-transform:uppercase}.assign-row{display:grid;grid-template-columns:11rem minmax(0,16rem) 1fr;gap:.75rem;align-items:center;margin:.55rem 0;color:#bfc9e5;font-size:.8rem}.assign-name{font-weight:700}.assign-why{color:#8b96b8;font-size:.75rem;line-height:1.4}.vd-rate{color:#8b96b8;font-size:.75rem;margin:.35rem 0 0;line-height:1.5}.vd-warn{color:#e8c9a8;font-weight:700;margin-right:.4rem}.voice-subnav{display:flex;gap:1rem;align-items:center;margin:.25rem 0 1rem;font-size:.8rem}.voice-subnav a{color:#8b96b8;text-decoration:none;border-bottom:1px solid transparent}.voice-subnav a:hover{color:#dbe4fb;border-bottom-color:#34405c}.voice-subnav [aria-current]{color:#dcb763;font-weight:700}.forge-voice .voice-secondary{background:#1a2133;color:#aab5cf;font-weight:600}.forge-voice .new-name{padding:.55rem;background:#0c111c;color:#fff;border:1px solid #34405c;border-radius:8px;min-width:16rem}.save-bar{position:sticky;bottom:0;padding:.75rem 0;background:linear-gradient(transparent,#0b101b 40%)}@media (max-width:720px){.assign-row{grid-template-columns:1fr}}.voice-hint{color:#8b96b8;font-size:.78rem;line-height:1.5;border-left:2px solid #34405c;padding-left:.75rem;margin:1rem 0 1.5rem}.voice-card{margin:1rem 0;padding:1.25rem;border:1px solid #303b57;border-radius:14px;background:#141a2a}.sample-card{background:#101627}.voice-card label{display:block;margin:.8rem 0;color:#bfc9e5;font-size:.8rem}.voice-card textarea,.voice-card select{display:block;width:100%;box-sizing:border-box;margin-top:.35rem;padding:.6rem;background:#0c111c;color:#fff;border:1px solid #34405c;border-radius:8px}.voice-card textarea{min-height:4rem}.voice-card button{margin-right:.5rem;padding:.6rem .8rem;border:0;border-radius:8px;background:#dcb763;color:#18120a;font-weight:700}.voice-disclosure{color:#9da8c5;font-size:.8rem}
.dsp-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}.dsp-value{float:right;color:#dcb763;font-weight:700}.voice-card input[type=range]{width:100%;margin-top:.4rem;accent-color:#dcb763;background:transparent}.preset-row{margin:.6rem 0 1rem}.preset-button{margin:0 .5rem .5rem 0;padding:.4rem .7rem;border:1px solid #34405c;border-radius:8px;background:#0c111c;color:#bfc9e5;font-size:.75rem;font-weight:600;cursor:pointer}.preset-button:hover{border-color:#dcb763;color:#dcb763}
/* #869 — the ancestry/class voice grid and its add dialog. ⛔ Every selector is qualified with
   .forge-voice: a bare `table` or `.voice-grid` would reach any page that later renders one, which is
   exactly how a bare element selector gets everywhere. Values are the surrounding palette's, not new
   ones — the borders, the card background and the gold are all already in this file. */
.forge-voice .voice-grid{width:100%;border-collapse:collapse;margin:.75rem 0 1rem;font-size:.78rem;color:#bfc9e5}
.forge-voice .voice-grid th{text-align:left;padding:.4rem .5rem;color:#8b96b8;font-weight:700;border-bottom:1px solid #303b57;text-transform:uppercase;letter-spacing:.04em;font-size:.7rem}
.forge-voice .voice-grid td{padding:.45rem .5rem;border-bottom:1px solid #232c42}
.forge-voice .voice-grid tr:last-child td{border-bottom:0}
.forge-voice .voice-grid button{margin:0;padding:.3rem .6rem;font-size:.72rem}
/* The score that decides which rule wins, shown so an author can see it rather than infer it. */
.forge-voice .voice-specificity{color:#dcb763;font-weight:700;text-align:right;width:4rem}
/* Present for screen readers, absent to the eye — the grid's Remove column has no visible heading. */
.forge-voice .visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.normalize-row{display:flex;align-items:center;gap:.5rem;margin:1rem 0 .4rem}.normalize-row input[type=checkbox]{width:auto;accent-color:#dcb763}
.fx-group{margin-top:.7rem;border-top:1px solid #232c44}.fx-group summary{list-style:none;cursor:pointer;padding:.7rem 0;color:#8b96b8;font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;display:flex;align-items:center;user-select:none}.fx-group summary::-webkit-details-marker{display:none}.fx-group summary::before{content:"▸";display:inline-block;margin-right:.5rem;color:#dcb763;transition:transform .15s ease}.fx-group[open] summary::before{transform:rotate(90deg)}.fx-group .dsp-row{padding-bottom:.6rem}
.character-picker{display:block;margin:1.5rem 0;color:#bfc9e5;font-size:.85rem;font-weight:600}.character-picker select{display:block;width:100%;box-sizing:border-box;margin-top:.4rem;padding:.7rem;background:#141a2a;color:#fff;border:1px solid #dcb763;border-radius:8px;font-size:1rem}
/* ⚠️ DELETED: the original POC "tabletop" prototype stylesheet.
   ================================================================================================
   It was one line, it styled a layout (`.tabletop`) that no component has rendered for many
   milestones, and it did it with BARE ELEMENT SELECTORS that reached the whole application:

       button { padding:.5rem; margin-left:.5rem; }     <-- every button on the site
       input  { width:70%; padding:.5rem; }             <-- every input on the site
       .journal, aside { border:1px solid #777; padding:1rem; ... }

   `button { margin-left:.5rem }` is what put the black vertical stripes through every battle map.
   A map cell is a <button>. In a 40px grid track it was shoved 8px right and rendered 32px wide,
   leaving an 8px gap between every column and none at all between rows — vertical lines, regular,
   full height, on every map, at every zoom, since the POC. `.map-cell` sets `padding:0` and so
   happened to beat half of the rule; nothing set `margin`, so the other half stood.

   It only became obvious once unexplored squares were painted opaque (#230): before that the cells
   were transparent, and the gaps merely let un-fogged artwork through in 8px strips — which reads
   as "the map looks off" rather than as a layout bug, and cost three wrong diagnoses.

   Kept as a comment rather than a silent deletion because the lesson is the rule, not the file: an
   unscoped element selector in a global stylesheet is a change to every component that will ever
   exist, including the ones written years later by somebody who never reads this file. */
.thin-panel{padding:1rem;border:1px solid #303b57;border-radius:14px;background:#111827d9}.thin-heading{margin-bottom:.8rem}.thin-heading h3{margin:0;font-family:Georgia,serif;font-size:1rem}.empty-note,.result-note,.budget,.thin-panel li,.thin-panel p{font-size:.73rem;color:#9ca8c5}.initiative-list{list-style:none;padding:0;margin:0;display:grid;gap:.4rem}.initiative-list li{display:grid;grid-template-columns:2rem 1fr auto;gap:.5rem;align-items:center;padding:.45rem .55rem;border:1px solid #293550;border-radius:8px}.initiative-list li.active{border-color:#d7ad55;background:#2b2517}.initiative-list em{font-style:normal;color:#f0cb75}.thin-action,.travel-list button{width:100%;border:1px solid #3c4a68;border-radius:9px;background:#202b42;color:#e8edf8;padding:.65rem;text-align:left;margin:.45rem 0 0}.thin-action:hover,.travel-list button:hover{border-color:#7394c2;background:#263653}.thin-action:disabled,.travel-list button:disabled{opacity:.55}.travel-list{display:grid;gap:.35rem}.travel-list button strong,.travel-list button span{display:block}.travel-list button span{font-size:.67rem;color:#9ca8c5;margin-top:.2rem}.result-note{padding:.55rem;background:#0b111d;border-radius:8px}.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.4rem}.stat-grid span{padding:.5rem;background:#0c121f;border-radius:8px}.stat-grid small,.stat-grid strong{display:block}.stat-grid small{color:#7885a4;font-size:.6rem}.stat-grid strong{font-size:.78rem;margin-top:.15rem}.actor-detail h4{font-size:.7rem;color:#c5cee3;margin:.8rem 0 .3rem}.actor-detail ul{margin:0;padding-left:1rem}

/* The sign-in / register / account card. GLOBAL on purpose: these rules used to live in
   Login.razor.css, and Blazor scoped CSS only ever reaches the one component it belongs to — so
   /register and /account, which use exactly the same markup, rendered with no styling at all and fell
   back to this file's element defaults. Everything is nested under .login-shell so making it global
   cannot leak into any other page. */
.login-shell{min-height:100vh;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:clamp(1.5rem,4vw,4rem);color:#e7eaf2;background:linear-gradient(rgba(8,12,20,.55),rgba(8,12,20,.92)),url('/images/bg-landing.jpg');background-size:cover;background-position:center;flex-direction:column;gap:1.25rem}
.login-card{width:100%;max-width:380px;box-sizing:border-box;background:#0e1320d9;border:1px solid #303b57;border-radius:18px;padding:clamp(1.6rem,3vw,2.4rem);box-shadow:0 22px 70px #03060d80;text-align:center}
.login-shell .eyebrow{font-size:.72rem;font-weight:800;letter-spacing:.16em;color:#dcb763;margin:0 0 .5rem}
.login-card h1{margin:0 0 .5rem;font-family:Georgia,serif;font-size:1.7rem;color:#faf7ef}
/* /account carries a second card below its heading, so the card style has to cover an h2 as well: one
   page, one h1. Sized down rather than restyled, so the two cards still read as the same object. */
.login-card h2{margin:0 0 .5rem;font-family:Georgia,serif;font-size:1.25rem;color:#faf7ef}
.login-shell .subhead{margin:0 0 1.6rem;color:#aab5cf;font-size:.85rem;line-height:1.5}
.login-shell .subhead a{color:#e8c36a}
.login-card label{display:block;font-size:.78rem;font-weight:700;color:#b7c2df;margin:0 0 .5rem;text-align:left}
.login-card input{width:100%;box-sizing:border-box;background:#141b2b;color:#eef2fb;border:1px solid #34405c;border-radius:10px;padding:.85rem;font-size:1rem;text-align:center;letter-spacing:.1em;margin:0 0 1rem}
.login-card input:last-of-type{margin-bottom:0}
.login-shell .error{margin:.9rem 0 0;color:#ff9fa3;font-size:.82rem}
/* The .error twin, for the one thing these cards had no way to say: it worked. */
.login-shell .notice{margin:.9rem 0 0;color:#9bd3a7;font-size:.82rem}
.login-shell .enter-button{margin:1.6rem 0 0;width:100%;box-sizing:border-box;border:0;border-radius:12px;padding:1rem;font-weight:800;font-size:1rem;background:linear-gradient(135deg,#c69446,#e8c36a);color:#16110a;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:.5rem;text-decoration:none}
.login-shell .enter-button:hover{filter:brightness(1.08)}
.login-card.alternate{padding-top:1.4rem;padding-bottom:1.4rem}
.login-card.alternate .subhead{margin-bottom:0}

/* Temporary hit points (issue #169), for the panels styled globally rather than by a scoped sheet.
   Its own colour because it is not hit points: spent first, and never healed back. */
.actor-detail .temp-hp{margin-left:.3rem;padding:0 .28rem;border-radius:4px;font-size:.78em;color:#8fd4ff;background:rgba(90,209,255,.14);border:1px solid rgba(90,209,255,.35)}

/* The close button every dialog and panel shares (Dave's play note 6, 2026-08-12).
   ================================================================================================
   GLOBAL but OPT-IN: a component asks for it by putting `dm-close` in its own class list. That is the
   deliberate opposite of the deleted `button {}` rule above, which reached every component that would
   ever exist. Nothing inherits this by accident.

   Red on purpose, and ONE red. Before this there were five hand-rolled close buttons in two unrelated
   palettes — gold-on-brown for the sheet, bench and shop, grey-on-navy for the picker and toolkit — and
   no two agreed. The transparent background is the load-bearing choice: it is what lets a single rule
   sit correctly on both a brown panel and a navy one.

   ⚠️ A COMPONENT'S OWN SCOPED CSS BEATS THIS FILE. Blazor compiles `.sheet-close` to
   `.sheet-close[b-abc123]`, which scores 0,2,0 against this rule's 0,1,0 — so a component that adopts
   the class while keeping its old colour and border declarations will silently look exactly as it did
   before, and the adoption will appear to have done nothing. Adopting means DELETING those declarations
   and keeping only genuine layout in the scoped rule (flex, and where the button sits in a parent grid). */
.dm-close{display:grid;place-items:center;width:2.1rem;height:2.1rem;padding:0;border:1px solid #8f4f43;
    border-radius:50%;background:transparent;color:#ffb1a0;font-size:1.1rem;line-height:1;cursor:pointer}
.dm-close:hover,.dm-close:focus-visible{color:#ff9c87;border-color:#c55;background:#281717}

/* ── The shared voice designer (VoiceDesigner.razor) ─────────────────────────────────────────────
   ⚠️ GLOBAL, not scoped, and that is load-bearing. This component is rendered inside the Voice Lab
   page AND inside the Adventure Studio's dialog; a scoped sheet belonging to either host would not
   reach it, which is the trap that has cost this project three separate CSS outages. The existing
   .fx-group / .dsp-row / .preset-button rules above are global for the same reason and still apply. */
.voice-designer { display: grid; gap: .7rem; }

/* ⛔ These restate what `.voice-card input[type=range]`, `.voice-card label` etc. give the component on
   the Voice Lab page. They are NOT duplication for its own sake: inside a ForgeDialog there is no
   .voice-card ancestor, so without them the sliders lose `width:100%` and collapse to their intrinsic
   size, and every control loses its dark field. The failure is visual only, so no test would catch it —
   the component would simply look broken in one of its two homes. */
.voice-designer input[type=range] { width: 100%; margin-top: .4rem; accent-color: #dcb763; background: transparent; }
.voice-designer label { display: block; margin: .5rem 0; color: #bfc9e5; font-size: .8rem; }
.voice-designer textarea, .voice-designer select, .voice-designer input[type=text], .voice-designer input:not([type]) {
    display: block; width: 100%; box-sizing: border-box; margin-top: .35rem; padding: .6rem;
    background: #0c111c; color: #fff; border: 1px solid #34405c; border-radius: 8px; }
.voice-designer textarea { min-height: 3.4rem; }
.vd-identity { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .6rem; }
.vd-identity label, .vd-test label { display: grid; gap: .25rem; }
.vd-identity .vd-wide, .vd-test .vd-wide { grid-column: 1 / -1; }
.vd-identity textarea, .vd-test textarea { min-height: 3.2rem; resize: vertical; }
.vd-hint { margin: 0; font-size: .82rem; color: #8996b5; }
.vd-check { display: flex; align-items: center; gap: .45rem; }
.vd-check input { width: auto; }

/* The test widget. Set apart with a rule above it because it is the one control here that spends
   money — it should not read as just another slider. */
.vd-test { display: grid; gap: .5rem; padding-top: .6rem; border-top: 1px solid #2a3348; }
.vd-test-actions { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
/* ⛔ Qualified with .voice-designer, and NOT because it is tidier. `.voice-card button` in the Voice
   Lab's styles is (0,1,1) and beat a bare `.vd-play` (0,1,0), so the test button came out gold there —
   and would have come out green in the Adventure Studio's dialog, which has no .voice-card ancestor.
   A shared component whose appearance depends on who is hosting it is the bug this avoids. */
.voice-designer .vd-play { padding: .5rem .9rem; font-weight: 700; cursor: pointer; border-radius: 8px;
    border: 1px solid #4f7a5e; background: #1b2a20; color: #cfe8d8; }
.voice-designer .vd-play:hover:not(:disabled) { background: #24382b; border-color: #6fa584; }
.voice-designer .vd-play:disabled { opacity: .6; cursor: wait; }
.vd-error { font-size: .82rem; color: #f0b7c0; }

.voice-actions { display: flex; align-items: center; gap: .6rem; margin-top: .6rem; flex-wrap: wrap; }
.voice-error { font-size: .82rem; color: #f0b7c0; }
.save-profile:disabled { opacity: .6; cursor: default; }

/* The voice popup's body. Bounded height because the designer is tall — five effect groups and a test
   widget — and a dialog that grows past the viewport puts its own confirm button off screen. */
.voice-dialog-body { display: grid; gap: .6rem; max-height: 62vh; overflow-y: auto; padding-right: .3rem; }
.voice-clear { justify-self: start; padding: .4rem .7rem; border: 1px solid #4a3a4a; border-radius: 8px;
    background: #1c1420; color: #d6b9d6; font: inherit; cursor: pointer; }
.voice-clear:hover { border-color: #8d6a8d; }

/* The legal pages (/privacy, /terms). A wider, left-aligned variant of .login-card: the card is
   capped at 380px and centred because it exists to hold a sign-in form, and a policy read at that
   width is a column of two-word lines. Everything else — background, border, eyebrow, headings — is
   inherited, so these pages look like the rest of the site without a second stylesheet. */
.legal-card{max-width:52rem;text-align:left}
.legal-card h1{text-align:center}
.legal-card .eyebrow{text-align:center}
.legal-card h2{margin:2rem 0 .6rem;font-family:Georgia,serif;font-size:1.1rem;color:#e8c36a}
.legal-card p{margin:0 0 1rem;color:#c6cfe4;font-size:.92rem;line-height:1.65}
.legal-card ul{margin:0 0 1rem;padding-left:1.2rem;color:#c6cfe4;font-size:.92rem;line-height:1.65}
.legal-card li{margin:0 0 .5rem}
.legal-card strong{color:#eef2fb}
.legal-card a{color:#e8c36a}
.legal-card .legal-date{text-align:center;color:#8f9bb8;font-size:.8rem;margin-bottom:2rem}
.legal-card .legal-footer{margin-top:2.5rem;padding-top:1.25rem;border-top:1px solid #303b57;text-align:center;font-size:.85rem}

/* /account's billing statement (M23 §7). The card is .legal-card for the reason the legal pages are:
   a table of pots and dates read at the sign-in card's 380px is a column of two-word lines. Only the
   table needs rules of its own; everything else is inherited. ⚠️ Dave reviews UI himself and has not
   seen this — it is deliberately plain rather than tuned. */
.allowance-table{width:100%;border-collapse:collapse;margin:0 0 1rem;font-size:.86rem;color:#c6cfe4}
.allowance-table th{text-align:left;padding:.4rem .5rem;border-bottom:1px solid #303b57;color:#8f9bb8;font-weight:600}
.allowance-table td{padding:.4rem .5rem;border-bottom:1px solid #1e2740}
.legal-card .notice{margin:0 0 1rem;padding:.7rem .9rem;border:1px solid #4a5a7a;border-radius:10px;color:#dbe4f7;font-size:.88rem}
.legal-card .error{margin:0 0 1rem;padding:.7rem .9rem;border:1px solid #7a4a4a;border-radius:10px;color:#f3d9d9;font-size:.88rem}
