/* DUNGEON RUN design tokens (DESIGN.md section 8).
   Every color, shadow, type size, spacing step and timing value lives here. main.css uses only these.
   Later phases add to this file instead of inventing values in component CSS.

   Palette source of truth is data/config.json "palette", injected at boot as --pal-<name>.
   Everything below derives from those. The plain named-color fallbacks only ever show if
   config.json itself fails to load, so the error screen is still readable. */

:root {
  /* ---------- Palette (from config.json) ---------- */
  --color-void: var(--pal-background, black);
  --color-stone: var(--pal-stone, dimgray);
  --color-torch: var(--pal-torch, orange);
  --color-blood: var(--pal-danger, red);
  --color-bone: var(--pal-text, white);
  --color-necromancy: var(--pal-necromancy, green);
  --color-darkhold: var(--pal-darkhold, purple);
  --color-elemental: var(--pal-elemental, gold);

  /* ---------- Darkness and stone ---------- */
  --color-pitch: color-mix(in srgb, var(--color-void) 60%, black);
  --color-stone-deep: color-mix(in srgb, var(--color-stone) 42%, var(--color-void));
  --color-stone-mid: color-mix(in srgb, var(--color-stone) 72%, var(--color-void));
  --color-stone-warm: color-mix(in srgb, var(--color-stone) 86%, var(--color-torch));
  --color-iron: color-mix(in srgb, var(--color-stone) 82%, var(--color-bone));
  --color-iron-dark: color-mix(in srgb, var(--color-iron) 45%, var(--color-void));
  --color-mortar: color-mix(in srgb, var(--color-pitch) 70%, transparent);
  --color-dirt: color-mix(in srgb, var(--color-stone) 92%, var(--color-torch));

  /* ---------- Fire ---------- */
  --color-flame: color-mix(in srgb, var(--color-torch) 55%, var(--color-elemental));
  --color-ember: color-mix(in srgb, var(--color-torch) 62%, var(--color-blood));
  --color-torch-dim: color-mix(in srgb, var(--color-torch) 55%, var(--color-void));
  --color-torch-glow: color-mix(in srgb, var(--color-torch) 42%, transparent);
  --color-torch-haze: color-mix(in srgb, var(--color-torch) 14%, transparent);
  --color-blood-glow: color-mix(in srgb, var(--color-blood) 45%, transparent);
  --color-blood-deep: color-mix(in srgb, var(--color-blood) 30%, var(--color-void));
  --color-blood-bright: color-mix(in srgb, var(--color-blood) 78%, var(--color-bone));
  --color-hp-loss: color-mix(in srgb, var(--color-ember) 65%, var(--color-bone));

  /* ---------- Text on stone: old vellum, not white ---------- */
  --color-text: var(--color-vellum-bright);
  --color-text-dim: var(--color-vellum-dim);
  --color-text-faint: var(--color-vellum-faint);
  --color-text-on-fire: var(--color-pitch);
  --color-log-player: color-mix(in srgb, var(--color-torch) 70%, var(--color-text-dim));
  --color-log-enemy: color-mix(in srgb, var(--color-blood) 70%, var(--color-text-dim));
  --color-log-summon: color-mix(in srgb, var(--color-necromancy) 75%, var(--color-text-dim));

  /* ---------- Vellum (card stock) and ink ---------- */
  --color-vellum: color-mix(in srgb, color-mix(in srgb, var(--color-bone) 72%, var(--color-torch)) 86%, var(--color-stone));
  --color-vellum-burnt: color-mix(in srgb, var(--color-vellum) 45%, var(--color-ember));
  --color-ink: color-mix(in srgb, var(--color-void) 86%, var(--color-stone));
  --color-ash: color-mix(in srgb, var(--color-bone) 36%, var(--color-stone));
  --color-scrim: color-mix(in srgb, var(--color-pitch) 78%, transparent);

  /* ---------- Creatures ---------- */
  --color-robe: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 78%, var(--color-darkhold)) 70%, var(--color-bone));
  --color-vermin: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 74%, var(--color-torch)) 76%, var(--color-bone));
  --color-risen: color-mix(in srgb, var(--color-necromancy) 42%, var(--color-vermin));
  --color-bat: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 70%, var(--color-darkhold)) 80%, var(--color-bone));
  --color-bones: color-mix(in srgb, var(--color-bone) 72%, var(--color-stone));
  --color-goblin: color-mix(in srgb, color-mix(in srgb, var(--color-necromancy) 45%, var(--color-stone)) 85%, var(--color-bone));
  --color-wraith: color-mix(in srgb, var(--color-ash) 80%, var(--color-bone));
  --color-flesh: color-mix(in srgb, color-mix(in srgb, var(--color-bone) 70%, var(--color-blood)) 75%, var(--color-stone));
  --color-hide: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 82%, var(--color-blood)) 85%, var(--color-bone));
  --color-inquisitor: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 70%, var(--color-darkhold)) 88%, var(--color-bone));
  --color-shell: color-mix(in srgb, color-mix(in srgb, var(--color-blood) 50%, var(--color-torch)) 72%, var(--color-stone));
  --color-necro-glow: color-mix(in srgb, var(--color-necromancy) 45%, transparent);
  --color-spider: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 60%, var(--color-darkhold)) 72%, var(--color-bone));
  --color-ghoul: color-mix(in srgb, color-mix(in srgb, var(--color-bone) 62%, var(--color-necromancy)) 72%, var(--color-stone));
  --color-acolyte: color-mix(in srgb, color-mix(in srgb, var(--color-blood) 45%, var(--color-stone)) 85%, var(--color-bone));
  --color-hound: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 70%, var(--color-torch)) 72%, var(--color-bone));
  --color-stolen: color-mix(in srgb, var(--color-darkhold) 60%, var(--color-bone));
  --filter-stolen: drop-shadow(0 0 8px var(--color-shard-glow));

  /* ---------- Schools (DESIGN.md section 4). A card picks --school-<its school>. ---------- */
  --school-necromancy: var(--color-necromancy);
  --school-darkhold: var(--color-darkhold);
  --school-elemental: var(--color-elemental);
  --school-neutral: color-mix(in srgb, var(--color-bone) 82%, var(--color-torch));
  --school-curse: var(--color-ash);

  /* ---------- The book and its fittings: dark aged pages, vellum ink, bronze, steel ---------- */
  --color-page: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 90%, var(--color-torch)) 85%, var(--color-void));
  --color-page-mid: color-mix(in srgb, var(--color-page) 60%, var(--color-void));
  --color-page-low: color-mix(in srgb, var(--color-page) 32%, var(--color-void));
  --color-vellum-bright: color-mix(in srgb, var(--color-vellum) 72%, var(--color-bone));
  --color-vellum-dim: color-mix(in srgb, var(--color-vellum) 72%, var(--color-stone));
  --color-vellum-faint: color-mix(in srgb, var(--color-vellum) 48%, var(--color-stone));
  --color-bronze: color-mix(in srgb, color-mix(in srgb, var(--color-torch) 22%, var(--color-vellum)) 34%, var(--color-stone));
  --color-bronze-edge: color-mix(in srgb, color-mix(in srgb, var(--color-torch) 48%, var(--color-vellum)) 42%, var(--color-stone));
  --color-torch-hot: color-mix(in srgb, var(--color-torch) 58%, var(--color-bone));
  --color-hp-text: color-mix(in srgb, var(--color-blood) 58%, var(--color-bone));
  --color-steel: color-mix(in srgb, color-mix(in srgb, var(--color-darkhold) 50%, var(--color-necromancy)) 42%, var(--color-bone));
  --color-scheme-number: color-mix(in srgb, var(--color-darkhold) 70%, var(--color-bone));
  --color-countdown: color-mix(in srgb, var(--color-darkhold) 55%, var(--color-bone));
  --color-steel-edge: color-mix(in srgb, var(--color-steel) 40%, var(--color-stone));
  --color-steel-plate: color-mix(in srgb, var(--color-steel) 14%, var(--color-plaque-low));
  --color-plaque-top: color-mix(in srgb, color-mix(in srgb, var(--color-stone) 88%, var(--color-torch)) 80%, var(--color-void));
  --color-plaque-low: color-mix(in srgb, var(--color-stone) 38%, var(--color-void));
  --color-bronze-top: color-mix(in srgb, color-mix(in srgb, var(--color-torch) 24%, var(--color-stone)) 82%, var(--color-void));
  --color-bronze-low: color-mix(in srgb, color-mix(in srgb, var(--color-torch) 14%, var(--color-stone)) 45%, var(--color-void));
  --color-room-top: color-mix(in srgb, var(--color-stone) 42%, var(--color-void));
  --color-room-mid: color-mix(in srgb, var(--color-stone) 12%, var(--color-void));
  --color-room-low: var(--color-pitch);

  /* ---------- Gilt: the edge of a rare card (DESIGN.md section 4) ---------- */
  --color-gilt: color-mix(in srgb, var(--color-elemental) 62%, var(--color-torch));
  --color-gilt-deep: color-mix(in srgb, var(--color-gilt) 52%, var(--color-ink));
  --color-gilt-glow: color-mix(in srgb, var(--color-gilt) 45%, transparent);
  --color-ember-glow: color-mix(in srgb, var(--color-ember) 50%, transparent);

  /* ---------- Type (DESIGN.md section 2) ---------- */
  --font-display: "IM Fell English SC", "Iowan Old Style", Georgia, serif;
  --font-text: "Spectral", "Iowan Old Style", Georgia, serif;

  --type-xs: 14px;
  --type-sm: 16px;
  --type-md: 17px;
  --type-lg: 20px;
  --type-xl: 23px;
  --type-2xl: 28px;
  --type-3xl: 34px;
  --type-4xl: 48px;
  --type-5xl: 64px;

  --weight-text: 400;
  --weight-bold: 600;
  --weight-heavy: 800;
  --weight-display: 400; /* IM Fell English SC comes in one weight; faking bold smears it */
  --weight-display-heavy: 400;

  --leading-tight: 1;
  --leading-snug: 1.15;
  --leading-text: 1.3;
  --tracking-display: 0.05em;
  --tracking-title: 0.12em;
  --tracking-label: 0.09em;
  --tracking-card-name: 0.02em;

  /* ---------- Space (dense: DESIGN.md section 7) ---------- */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 12px;
  --space-6: 16px;
  --space-7: 22px;
  --space-8: 30px;
  --gap-region: var(--space-2);

  /* ---------- Worn edges: no uniform radius ---------- */
  --radius-worn-2: 7px 3px 9px 4px / 3px 9px 4px 8px;
  --radius-worn-3: 4px 10px 3px 7px / 9px 4px 8px 3px;
  --radius-chip: 2px 4px 3px 5px;
  --radius-plaque: 3px 10px 4px 9px;
  --radius-tag: 2px 8px 2px 8px;
  --radius-button: 2px 10px 2px 10px;
  --radius-page: 3px 11px 3px 11px;
  --radius-page-alt: 11px 3px 11px 3px;
  --radius-well: 2px 5px 2px 4px;
  --radius-log: 8px;
  --radius-wax: 47% 53% 50% 46% / 52% 46% 54% 48%;
  --radius-round: 50%;
  --chipped-corners: polygon(0 7px, 7px 0, calc(100% - 11px) 0, 100% 9px, 100% calc(100% - 6px), calc(100% - 7px) 100%, 9px 100%, 0 calc(100% - 10px));

  /* ---------- Sizes ---------- */
  --tap: 44px;
  --measure: 40em;
  --hairline: 1px;
  --rule: 2px;
  --icon-sm: 18px;
  --icon-md: 24px;
  --orb-size: 44px;
  --badge-size: 34px;
  --seal-size: 38px;
  --edge-w: 3px;
  --art-well-h: clamp(30px, 6.5dvh, 62px);
  --art-well-h-short: clamp(22px, 4dvh, 34px);
  --card-max-w: 236px;
  --art-glyph-size: 68%;
  --opacity-sigil: 0.5;
  --opacity-ornament: 0.85;
  --seal-offset: -10px;
  --seal-clearance: 24px;
  --seal-tuck: 22px;
  --sigil-size: 30px;
  --card-w: 186px;
  --card-min-w: 112px;
  --card-min-h: 184px;
  --card-band: 3px;
  --card-lift: -14px;
  --card-band-gap: 2px;
  --ornament-inset: 4px;
  --ornament-inset-ancient: 7px;
  --ornament-len: 14px;
  --ornament-thick: 2px;
  --call-tag-offset: -10px;
  --medallion-size: 30px;
  --companion-w: 340px;
  --companion-max-w: 460px;
  --readout-w: 64px;
  --memory-card-w: clamp(64px, 16vw, 130px);
  --memory-glyph: 58%;
  --memory-cols: 6;
  --memory-cols-narrow: 4;
  --event-choice-w: 300px;
  --relic-w: 260px;
  --ladder-w: 560px;
  --hand-headroom: 26px;
  --hand-footroom: 18px;
  --hpbar-h: 22px;
  --hpbar-min-w: 112px;
  --unit-min-w: 140px;
  --summon-min-w: 140px;
  --intent-max-w: 200px;
  --slot-gutter: 22px;
  --unit-chrome: 130px;
  --unit-chrome-crowded: 150px;
  --chip-row-h: 24px;
  --span-boss: 2.4;
  --span-boss-extra: 1.4; /* --span-boss less the one slot every creature has */
  --tag-row-h: 42px;
  --card-row-w: 160px;
  --choice-w: 220px;
  --choice-h: 170px;
  --icon-xl: 44px;
  --sheet-max-w: 980px;
  --slab-w: 560px;
  --map-pad: 34px;
  --stamp-size: 52px;
  --stamp-size-boss: 68px;
  --map-line: 3px;
  --map-line-strong: 4px;
  --map-dash: 2 9;
  --opacity-faded: 0.38;
  --opacity-ahead: 0.82;
  --amount-w: 1.6em;
  --pile-w: 64px;
  --button-min-w: 150px;
  --button-h: 58px;
  --field-h-portrait: clamp(240px, 37dvh, 520px);
  --field-pad-x: clamp(8px, 4vw, 30px);
  --log-w: clamp(230px, 27vw, 340px);
  --log-min-h: 96px;
  --torch-w: clamp(22px, 3.2vw, 34px);
  --torch-h: clamp(50px, 8dvh, 80px);
  --torch-top: 6%;
  --torch-inset: 15%;
  --torch-glow-size: clamp(240px, 46vw, 600px);
  --torch-glow-center: 22%;
  --torch-flame-base: 40%;

  /* Sprites: scale communicates threat (DESIGN.md section 5). Aspect ratios match each viewBox in index.html.
     A crowded board shrinks everyone to fit (--slot-w in main.css). */
  --sprite-h-player: clamp(110px, 19dvh, 230px);
  --sprite-h-vermin: clamp(56px, 10dvh, 112px);
  --sprite-h-small: clamp(68px, 12dvh, 136px);
  --sprite-h-medium: clamp(88px, 15dvh, 170px);
  --sprite-h-large: clamp(108px, 18dvh, 205px);
  --sprite-h-elite: clamp(140px, 26dvh, 290px);
  --sprite-h-boss: clamp(160px, 32dvh, 360px);
  --sprite-h-default: var(--sprite-h-medium);
  --aspect-player: 100 / 140;
  --aspect-rat: 140 / 92;
  --aspect-bat: 160 / 80;
  --aspect-mote: 60 / 48;
  --aspect-barnacle: 80 / 60;
  --aspect-wretch: 100 / 100;
  --aspect-skeleton: 100 / 150;
  --aspect-bone-wall: 130 / 90;
  --aspect-wraith: 100 / 150;
  --aspect-blob: 130 / 92;
  --aspect-shaman: 100 / 124;
  --aspect-shieldbearer: 110 / 124;
  --aspect-brute: 150 / 150;
  --aspect-leech: 110 / 150;
  --aspect-torturer: 140 / 170;
  --aspect-questioner: 110 / 180;
  --aspect-crab: 240 / 140;
  --aspect-spider: 120 / 80;
  --aspect-ghoul: 100 / 130;
  --aspect-acolyte: 100 / 150;
  --aspect-kennel: 150 / 170;
  --aspect-hound: 120 / 80;
  --aspect-default: 1;

  /* ---------- Light (DESIGN.md section 1): falloff stops, placed by components ---------- */
  --falloff-flame: color-mix(in srgb, var(--color-torch) 28%, transparent) 0, color-mix(in srgb, var(--color-torch) 11%, transparent) 30%, color-mix(in srgb, var(--color-torch) 4%, transparent) 60%, transparent 100%;
  --falloff-pool: color-mix(in srgb, var(--color-torch) 16%, transparent) 0, transparent 70%;
  --falloff-held: color-mix(in srgb, var(--color-torch) 22%, transparent) 0, color-mix(in srgb, var(--color-torch) 6%, transparent) 45%, transparent 75%;
  --falloff-lit-surface: color-mix(in srgb, var(--color-bone) 22%, transparent) 0, transparent 70%;
  --falloff-vignette: transparent 35%, color-mix(in srgb, var(--color-pitch) 70%, transparent) 75%, var(--color-pitch) 100%;
  --falloff-torch-pool: color-mix(in srgb, var(--color-torch) 17%, transparent), transparent 62%;
  --falloff-torch-side: color-mix(in srgb, var(--color-torch) 13%, transparent), transparent 60%;
  --falloff-blood-floor: color-mix(in srgb, var(--color-blood-deep) 30%, transparent), transparent 55%;
  /* The room every screen stands in: a torch overhead, one on each wall, something red in the floor, near-black between. */
  --surface-room:
    radial-gradient(90% 55% at 50% 2%, var(--falloff-torch-pool)),
    radial-gradient(60% 40% at 4% 38%, var(--falloff-torch-side)),
    radial-gradient(60% 40% at 96% 38%, var(--falloff-torch-side)),
    radial-gradient(120% 90% at 50% 120%, var(--falloff-blood-floor)),
    linear-gradient(to bottom, var(--color-room-top), var(--color-room-mid) 48%, var(--color-room-low));
  /* Plaques: HUD, panels, sheets. Lit from above, falling into dark at the bottom edge. */
  --surface-plaque:
    radial-gradient(ellipse 70% 120% at 50% 0%, var(--falloff-pool)),
    linear-gradient(to bottom, var(--color-plaque-top), var(--color-plaque-low));
  --surface-bronze:
    radial-gradient(ellipse 80% 90% at 50% 0%, var(--falloff-pool)),
    linear-gradient(to bottom, var(--color-bronze-top), var(--color-bronze-low));
  /* A screen's board: recessed stone under a torch, the corners lost in dark. */
  --surface-board:
    radial-gradient(ellipse 70% 40% at 50% 0%, var(--falloff-torch-pool)),
    radial-gradient(ellipse 115% 105% at 50% 40%, var(--falloff-vignette)),
    linear-gradient(to bottom, var(--color-plaque-top), var(--color-pitch));
  /* The fight's stage: masonry wall, a dirt floor, light pooling where the creatures stand. */
  --surface-field:
    radial-gradient(ellipse 75% 34% at 50% 100%, var(--falloff-pool)),
    radial-gradient(ellipse 115% 105% at 50% 40%, var(--falloff-vignette)),
    linear-gradient(to bottom, transparent var(--floor-line), var(--color-dirt) var(--floor-line), var(--color-stone-deep)),
    var(--texture-masonry),
    var(--texture-mottle),
    linear-gradient(to bottom, var(--color-stone-mid), var(--color-pitch));
  --surface-field-size: auto, auto, auto, var(--texture-masonry-size), var(--texture-mottle-size), auto;
  --surface-field-boss: radial-gradient(ellipse 45% 70% at 76% 62%, var(--falloff-shard)), var(--surface-field);
  --surface-field-boss-size: auto, var(--surface-field-size);
  --surface-choice: radial-gradient(ellipse 90% 70% at 50% 20%, var(--falloff-held)), var(--surface-plaque);
  --surface-slab: radial-gradient(ellipse 90% 50% at 50% 0%, var(--falloff-torch-pool)), var(--surface-plaque);
  --surface-hud-light: radial-gradient(ellipse 45% 220% at 6% 0%, var(--falloff-pool));
  --surface-target-pool: radial-gradient(ellipse 85% 75% at 50% 75%, var(--falloff-held));
  --surface-risen-pool: radial-gradient(ellipse 85% 75% at 50% 75%, var(--falloff-risen));
  --surface-outcome-veil: radial-gradient(ellipse 80% 80% at 50% 50%, var(--falloff-vignette));
  --surface-log:
    radial-gradient(ellipse 80% 45% at 25% 0%, var(--falloff-pool)),
    linear-gradient(to bottom, var(--color-page-mid), var(--color-pitch));
  --surface-intent: linear-gradient(to bottom, color-mix(in srgb, var(--color-bronze-top) 95%, transparent), color-mix(in srgb, var(--color-page-low) 95%, transparent));
  --surface-well:
    radial-gradient(70% 90% at 50% 40%, color-mix(in srgb, var(--well-light, var(--color-torch)) 16%, transparent), transparent 70%),
    var(--color-page-low);
  --falloff-risen: color-mix(in srgb, var(--color-necromancy) 20%, transparent) 0, color-mix(in srgb, var(--color-necromancy) 6%, transparent) 45%, transparent 75%;
  --falloff-shard: color-mix(in srgb, var(--color-darkhold) 22%, transparent) 0, color-mix(in srgb, var(--color-darkhold) 7%, transparent) 50%, transparent 80%;

  /* ---------- Texture (DESIGN.md section 3) ---------- */
  --texture-mottle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420'%3E%3Cfilter id='m' x='0' y='0' width='1' height='1'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012' numOctaves='4' stitchTiles='stitch' seed='7'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1.6 -0.62'/%3E%3C/filter%3E%3Crect width='420' height='420' filter='url(%23m)'/%3E%3C/svg%3E");
  --texture-mottle-size: 420px;
  --texture-masonry: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='128' height='76'%3E%3Cg fill='none' stroke='black' stroke-opacity='0.6' stroke-width='3'%3E%3Cpath d='M0 1.5H128M0 39.5H128M1.5 0V38M65.5 38V76'/%3E%3C/g%3E%3Cg fill='none' stroke='white' stroke-opacity='0.07'%3E%3Cpath d='M3 4.5H128M0 42.5H64M67 42.5H128'/%3E%3C/g%3E%3C/svg%3E");
  --texture-masonry-size: 128px 76px;
  /* Noise, laid over a surface in overlay blend at low opacity: rough stone, old paper (DESIGN.md section 3). */
  --texture-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n' x='0' y='0' width='1' height='1'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  --texture-noise-size: 220px;
  --texture-noise-fine: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='c' x='0' y='0' width='1' height='1'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23c)' opacity='0.6'/%3E%3C/svg%3E");
  --texture-noise-fine-size: 160px;
  --blend-noise: overlay;
  --opacity-noise: 0.09;
  --opacity-noise-room: 0.06;
  --opacity-noise-page: 0.1;
  --floor-line: 72%;

  /* ---------- Built surfaces ---------- */
  --surface-wax: radial-gradient(circle at 35% 30%, var(--color-flame), var(--color-torch) 55%, var(--color-ember));
  --surface-blood: linear-gradient(to bottom, var(--color-blood-bright), var(--color-blood) 60%, var(--color-blood-deep));

  /* ---------- Depth (DESIGN.md section 3): recessed board, raised cards, modal above all ---------- */
  --shadow-recess:
    inset 0 3px 0 var(--color-pitch),
    inset 0 14px 26px -8px var(--color-pitch),
    inset 0 -1px 0 color-mix(in srgb, var(--color-bone) 7%, transparent),
    inset 0 0 0 var(--hairline) color-mix(in srgb, var(--color-pitch) 80%, transparent);
  --shadow-niche:
    inset 0 2px 0 var(--color-pitch),
    inset 0 18px 30px -10px var(--color-pitch),
    inset 6px 0 18px -10px var(--color-pitch);
  --shadow-ledge:
    inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-bone) 10%, transparent),
    0 3px 0 var(--color-pitch),
    0 10px 18px -6px var(--color-pitch);
  --shadow-card:
    0 2px 0 var(--color-ink),
    0 12px 20px -6px var(--color-pitch),
    0 3px 8px color-mix(in srgb, var(--color-pitch) 60%, transparent);
  --shadow-card-lifted:
    0 18px 30px -6px var(--color-pitch),
    0 0 26px var(--color-torch-glow),
    0 0 0 var(--rule) var(--color-torch);
  --shadow-modal:
    0 0 0 var(--hairline) var(--color-pitch),
    0 30px 60px -10px var(--color-pitch),
    0 0 140px color-mix(in srgb, var(--color-pitch) 80%, transparent);
  --shadow-seal:
    inset 0 2px 1px color-mix(in srgb, var(--color-bone) 40%, transparent),
    inset 0 -3px 4px color-mix(in srgb, var(--color-ember) 70%, var(--color-pitch)),
    0 3px 5px color-mix(in srgb, var(--color-pitch) 80%, transparent);
  --shadow-button:
    inset 0 2px 0 color-mix(in srgb, var(--color-bone) 45%, transparent),
    inset 0 -4px 0 color-mix(in srgb, var(--color-ember) 60%, var(--color-pitch)),
    0 4px 0 var(--color-pitch),
    0 0 26px var(--color-torch-glow);
  --shadow-pile:
    2px -2px 0 -1px var(--color-stone-mid),
    4px -4px 0 -2px var(--color-stone-deep),
    0 4px 8px var(--color-pitch);
  --shadow-hpbar:
    inset 0 2px 4px var(--color-pitch),
    0 0 0 var(--hairline) var(--color-iron-dark),
    0 0 0 var(--rule) var(--color-pitch);
  --shadow-carved-divider: inset var(--hairline) 0 0 color-mix(in srgb, var(--color-bone) 6%, transparent);
  --shadow-scratch: inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-bone) 4%, transparent);
  --shadow-text-carved: 0 -1px 0 var(--color-pitch), 0 1px 0 color-mix(in srgb, var(--color-bone) 14%, transparent);
  --shadow-text-lit: 0 0 14px var(--color-torch-glow), 0 1px 0 var(--color-pitch);
  --shadow-text-blood: 0 0 14px var(--color-blood-glow), 0 1px 0 var(--color-pitch);
  --glow-torch: 0 0 18px var(--color-torch-glow), 0 0 44px var(--color-torch-haze);
  --glow-target: 0 0 0 var(--rule) var(--color-torch), 0 0 28px var(--color-torch-glow);
  --glow-intent: 0 0 18px var(--color-blood-glow);
  --glow-scheme: 0 0 16px color-mix(in srgb, var(--color-darkhold) 40%, transparent);
  --shadow-text-scheme: 0 0 12px color-mix(in srgb, var(--color-darkhold) 60%, transparent), 0 1px 0 var(--color-pitch);
  --shadow-stamp:
    0 0 0 var(--hairline) var(--color-bronze),
    inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-vellum) 12%, transparent),
    inset 0 -4px 8px color-mix(in srgb, var(--color-pitch) 60%, transparent),
    0 3px 6px color-mix(in srgb, var(--color-pitch) 70%, transparent);
  --shadow-stamp-walked: 0 0 0 var(--hairline) var(--color-torch-dim), inset 0 3px 8px var(--color-pitch);
  --shadow-stamp-open: 0 0 0 var(--hairline) var(--color-torch-hot), 0 0 0 calc(var(--rule) * 2) var(--color-torch-glow), 0 0 22px var(--color-torch-glow);
  --shadow-stamp-here: 0 0 0 var(--rule) var(--color-torch), 0 0 0 calc(var(--rule) * 3) var(--color-torch-glow), 0 0 26px var(--color-torch-glow);
  --shadow-card-frame-map:
    inset 0 0 0 var(--hairline) color-mix(in srgb, var(--color-vellum) 7%, transparent),
    inset 0 0 120px 30px color-mix(in srgb, var(--color-pitch) 70%, transparent);
  --surface-map:
    radial-gradient(ellipse 70% 55% at 50% 45%, color-mix(in srgb, var(--color-torch) 10%, transparent), transparent 70%),
    linear-gradient(to bottom, var(--color-page), var(--color-page-mid) 60%, var(--color-page-low));
  --surface-stamp: radial-gradient(circle at 38% 30%, var(--color-bronze-top), var(--color-page-low));
  --surface-stamp-open: radial-gradient(circle at 38% 30%, color-mix(in srgb, var(--color-torch) 30%, var(--color-bronze-top)), var(--color-page-low));
  --filter-path-lit: drop-shadow(0 0 4px var(--color-torch-glow));
  --glow-summon-selected: 0 0 0 var(--rule) var(--color-necromancy), 0 0 28px var(--color-necro-glow);
  --shadow-number: 0 0 2px var(--color-pitch), 0 0 2px var(--color-pitch), 0 3px 0 var(--color-pitch), 0 0 14px var(--color-blood-glow);
  --shadow-number-blocked: 0 0 3px var(--color-pitch), 0 2px 0 var(--color-pitch);
  --shadow-key-lit: inset 0 0 0 var(--rule) var(--color-ember), 0 0 18px var(--color-torch-glow);
  --shadow-board: var(--shadow-recess), inset 0 0 90px 24px color-mix(in srgb, var(--color-pitch) 72%, transparent);
  --shadow-vignette:
    inset 0 0 180px 60px color-mix(in srgb, var(--color-pitch) 92%, transparent),
    inset 0 0 50px 10px color-mix(in srgb, var(--color-pitch) 60%, transparent);
  --shadow-plaque:
    inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-vellum) 8%, transparent),
    inset 0 -10px 22px color-mix(in srgb, var(--color-pitch) 60%, transparent),
    0 6px 18px color-mix(in srgb, var(--color-pitch) 55%, transparent);
  --shadow-bronze:
    0 0 22px color-mix(in srgb, var(--color-torch) 18%, transparent),
    inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-torch-hot) 18%, transparent),
    inset 0 -8px 14px color-mix(in srgb, var(--color-pitch) 45%, transparent),
    0 4px 10px color-mix(in srgb, var(--color-pitch) 60%, transparent);
  --shadow-bronze-pressed:
    0 0 14px color-mix(in srgb, var(--color-torch) 12%, transparent),
    inset 0 2px 6px color-mix(in srgb, var(--color-pitch) 70%, transparent);
  --shadow-tag:
    0 0 16px color-mix(in srgb, var(--color-torch) 20%, transparent),
    inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-torch-hot) 14%, transparent);
  --shadow-well:
    inset 0 3px 14px color-mix(in srgb, var(--color-pitch) 85%, transparent),
    0 0 0 var(--hairline) color-mix(in srgb, var(--color-vellum) 10%, transparent);
  --shadow-text-ink: 0 var(--hairline) 0 var(--color-pitch);
  --shadow-number-glow: 0 0 14px color-mix(in srgb, var(--color-torch) 30%, transparent);
  --filter-sprite: drop-shadow(0 14px 18px color-mix(in srgb, var(--color-pitch) 85%, transparent));
  --filter-glyph: drop-shadow(0 0 8px color-mix(in srgb, var(--well-light, var(--color-torch)) 55%, transparent));
  --glow-cost: 0 0 16px color-mix(in srgb, var(--color-torch) 50%, transparent);
  --color-mod-chip: color-mix(in srgb, var(--color-pitch) 70%, transparent);
  --color-shard-glow: color-mix(in srgb, var(--color-darkhold) 55%, transparent);
  --glow-beam: 0 0 22px var(--color-shard-glow), 0 0 0 var(--hairline) var(--color-darkhold);
  --shadow-text-beam: 0 0 12px var(--color-shard-glow), 0 1px 0 var(--color-pitch);

  /* ---------- Filters ---------- */
  --filter-unlit: grayscale(0.85) brightness(0.55) contrast(0.95);
  --filter-lit: brightness(1.08);
  --filter-raised: drop-shadow(0 2px 0 var(--color-pitch));
  --filter-risen: drop-shadow(0 0 8px var(--color-necro-glow));
  --mirror: scaleX(-1);
  --filter-glow-blood: drop-shadow(0 0 6px var(--color-blood-glow));
  --filter-hurt: drop-shadow(0 0 14px var(--color-blood)) brightness(1.7);
  --filter-healed: drop-shadow(0 0 14px var(--color-necromancy)) brightness(1.4);
  --filter-beam: drop-shadow(0 0 24px var(--color-darkhold)) brightness(1.3);
  --filter-taken: drop-shadow(0 0 18px var(--color-darkhold)) brightness(1.6) saturate(0.4);
  --filter-armor-break: drop-shadow(0 0 16px var(--color-bone)) brightness(1.7);

  /* ---------- Motion (DESIGN.md section 6): nothing that responds to the player runs over 400ms ---------- */
  --dur-press: 100ms;
  --dur-fast: 150ms;
  --dur-med: 250ms;
  --dur-hit: 300ms;
  --dur-die: 350ms;
  --dur-reduced: 1ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in: cubic-bezier(0.6, 0, 0.9, 0.4);
  --ease-punch: cubic-bezier(0.3, 1.6, 0.5, 1);
  --shake-distance: 9px;
  --shake-settle: 4px;
  --press-depth: 3px;
  --die-drop: 14px;
  --die-scale: 0.92;
  --pop-scale: 1.18;
  --dur-shed: 350ms;
  --shed-drop: 46px;
  --shed-spin: 40deg;
  --taken-rise: -22px;
  --flip-from: 0.1 1;

  /* Health bars drain, damage numbers punch out, rise and fall away (DESIGN.md section 6).
     The lost chunk of a health bar lingers for --dur-loss-hold, then follows the bar down. */
  --dur-drain: 250ms;
  --dur-loss-hold: 120ms;
  --dur-loss: 250ms;
  --dur-number: 400ms;
  --dur-number-stagger: 120ms;
  --number-top: 30%;
  --number-punch-rise: 10px;
  --number-rise: 26px;
  --number-fall: 12px;
  --number-scale-start: 0.5;
  --number-scale-punch: 1.3;
  --number-scale-end: 0.9;
  --z-number: 1;

  /* ---------- Ambient life (DESIGN.md sections 1 and 5) ----------
     Idle loops that respond to nothing: torch flicker and breathing. Exempt from the 400ms rule.
     Slow, faint, and irregular: the cycle lengths share no common beat, so the pattern never visibly repeats.
     --clock is set by render.js on every redraw; the negative delay keeps each loop in step with the page
     clock, so a redrawn element picks up mid-cycle instead of restarting. */
  --clock-unit: -1ms;
  --ambient-delay: calc(var(--clock, 0) * var(--clock-unit));
  --ease-ambient: ease-in-out;
  --dur-flicker: 3.7s;
  --dur-sway: 5.3s;
  --dur-flame: 2.3s;
  --dur-flame-fade: 1.7s;
  --dur-accent-flicker: 4.1s;
  --dur-breathe: 2.9s;
  --dur-breathe-player: 3.6s;
  --torch-stagger: 1.9s;
  --flicker-low: 0.78;
  --flicker-mid: 0.9;
  --sway-low: 0.97;
  --sway-high: 1.035;
  --flame-tall: 0.95 1.07;
  --flame-short: 1.03 0.94;
  --accent-dim: brightness(0.92);
  --accent-bright: brightness(1.06);
  --breathe-in: 1.012 1.03;
  --breathe-rise: 0 -3px;
  /* The stepped flicker of a torch on the wall: jumps, not fades. */
  --dur-torch-flicker: 5.5s;
  --flicker-step-1: 0.95;
  --flicker-step-2: 0.8;
  --flicker-step-3: 0.86;
  --flicker-step-4: 0.76;

  --z-app: 1;
  --z-overlay: 10;
}

/* Card tokens that depend on the card's own school color. --school is set on each card from its data,
   so these must be computed on the card itself rather than on :root.
   A card is a page torn from the book: dark aged stock, vellum ink, a glowing edge strip in its school's
   color, a recessed art well. */
.card {
  --card-edge: var(--color-bronze);
  --card-ornament: var(--color-gilt);
  --shadow-rarity: 0 0 0 0 transparent;
  --card-stock-top: var(--color-page);
  --card-stock-mid: var(--color-page-mid);
  --card-stock-low: var(--color-page-low);
  --card-ink: color-mix(in srgb, var(--color-vellum) 86%, var(--color-stone));
  --card-name-ink: var(--color-vellum-bright);
  --card-number: color-mix(in srgb, var(--school) 38%, var(--color-vellum-bright));
  --card-mod-edge: color-mix(in srgb, var(--school) 45%, transparent);
  --well-light: var(--school);
  --surface-card:
    radial-gradient(ellipse 90% 40% at 50% 0%, color-mix(in srgb, var(--color-vellum) 8%, transparent), transparent 70%),
    linear-gradient(to bottom, var(--card-stock-top), var(--card-stock-mid) 56%, var(--card-stock-low));
  --surface-grain: var(--texture-noise-fine);
  --surface-grain-size: var(--texture-noise-fine-size);
  --surface-grain-opacity: var(--opacity-noise-page);
  --surface-edge: linear-gradient(to bottom, transparent, var(--school), transparent);
  --glow-edge: 0 0 14px var(--school);
  --shadow-page-depth:
    inset 0 var(--hairline) 0 color-mix(in srgb, var(--color-vellum) 13%, transparent),
    inset 0 -26px 40px color-mix(in srgb, var(--color-pitch) 60%, transparent);
  --shadow-card-frame:
    inset 0 0 0 var(--hairline) color-mix(in srgb, var(--color-vellum) 7%, transparent),
    var(--shadow-page-depth);
}

/* Rarity reads from the frame, never a label (DESIGN.md section 4).
   Starter and common: a plain bronze-edged page. Uncommon: a doubled line of school color inside the edge.
   Rare: gilded: a gilt border, gilt corner ornaments (main.css) and a warm halo.
   Ancient: older than the book itself: scorched stock, an ember-gilt-school triple line in a black border,
   ornaments and an ember halo. */
.card[data-rarity="uncommon"] {
  --shadow-card-frame:
    inset 0 0 0 var(--hairline) color-mix(in srgb, var(--school) 70%, transparent),
    inset 0 0 0 calc(var(--hairline) + var(--card-band-gap)) var(--card-stock-mid),
    inset 0 0 0 calc(var(--hairline) * 2 + var(--card-band-gap)) color-mix(in srgb, var(--school) 55%, transparent),
    var(--shadow-page-depth);
}
.card[data-rarity="rare"] {
  --card-edge: var(--color-gilt);
  --shadow-card-frame:
    inset 0 0 0 var(--hairline) var(--color-gilt-deep),
    inset 0 0 0 calc(var(--hairline) + var(--card-band-gap)) var(--card-stock-mid),
    inset 0 0 0 calc(var(--hairline) * 2 + var(--card-band-gap)) color-mix(in srgb, var(--school) 60%, transparent),
    var(--shadow-page-depth);
  --shadow-rarity:
    0 0 0 var(--hairline) var(--color-gilt-deep),
    0 0 18px var(--color-gilt-glow);
}
/* The Dealer's Table: the backs of his cards, and a color for each face so pairs read at a glance. */
.memory-card {
  --surface-card-back:
    repeating-linear-gradient(45deg, var(--color-hatch) 0 var(--hairline), transparent var(--hairline) 9px),
    repeating-linear-gradient(-45deg, var(--color-hatch) 0 var(--hairline), transparent var(--hairline) 9px),
    radial-gradient(ellipse 70% 60% at 50% 40%, var(--falloff-held)),
    linear-gradient(to bottom, var(--color-page), var(--color-page-low));
  --color-hatch: color-mix(in srgb, var(--color-bronze-edge) 45%, transparent);
  --well-light: var(--face);
}
.memory-card {
  --glow-face: 0 0 18px color-mix(in srgb, var(--face) 40%, transparent);
  --filter-glyph: drop-shadow(0 1px 0 var(--color-ink));
}
.memory-card[data-face="0"] { --face: var(--color-necromancy); }
.memory-card[data-face="1"] { --face: var(--color-darkhold); }
.memory-card[data-face="2"] { --face: var(--color-elemental); }
.memory-card[data-face="3"] { --face: var(--color-blood); }
.memory-card[data-face="4"] { --face: var(--color-flame); }
.memory-card[data-face="5"] { --face: var(--color-ember); }
.memory-card[data-face="6"] { --face: var(--color-iron); }
.memory-card[data-face="7"] { --face: var(--color-bones); }
.memory-card[data-face="8"] { --face: var(--color-torch); }
.memory-card[data-face="9"] { --face: var(--color-risen); }

/* Relics: the edge tells the rarity, the way a card's frame does. */
.relic { --relic-edge: var(--color-iron); --relic-glow: transparent; --glow-relic: 0 0 18px var(--relic-glow); }
.relic[data-rarity="uncommon"] { --relic-edge: var(--color-darkhold); --relic-glow: color-mix(in srgb, var(--color-darkhold) 30%, transparent); }
.relic[data-rarity="rare"] { --relic-edge: var(--color-gilt); --relic-glow: var(--color-gilt-glow); }

.card[data-rarity="ancient"] {
  --card-stock-top: color-mix(in srgb, var(--color-page) 78%, var(--color-ember));
  --card-edge: var(--color-pitch);
  --ornament-inset: var(--ornament-inset-ancient);
  --shadow-card-frame:
    inset 0 0 0 var(--card-band) var(--color-ember),
    inset 0 0 0 calc(var(--card-band) + var(--hairline)) var(--color-pitch),
    inset 0 0 0 calc(var(--card-band) * 2 + var(--hairline)) var(--color-gilt),
    inset 0 0 0 calc(var(--card-band) * 2 + var(--hairline) * 2) var(--color-pitch),
    inset 0 0 0 calc(var(--card-band) * 2 + var(--hairline) * 3) var(--school),
    var(--shadow-page-depth);
  --shadow-rarity:
    0 0 0 var(--hairline) var(--color-ember),
    0 0 24px var(--color-ember-glow);
}

/* Companions wear their school's color: on their HUD seal and their plaque. */
.medallion, .companion {
  --companion-color: color-mix(in srgb, var(--school) 72%, var(--color-bone));
  --shadow-medallion:
    0 0 0 var(--rule) color-mix(in srgb, var(--school) 70%, var(--color-ink)),
    0 0 10px color-mix(in srgb, var(--school) 45%, transparent);
  --glow-companion: 0 0 22px color-mix(in srgb, var(--school) 22%, transparent);
}

/* An intent's number burns in the creature's harm color. Scoped to the tag, so a summon's (whose --color-blood
   is necromancy green) burns green. */
.intent { --intent-number: color-mix(in srgb, var(--color-blood) 78%, var(--color-bone)); }

/* Risen creatures fight for you: their eyes and their intent tag burn necromancy green instead of blood red.
   Health bars, damage numbers and hit flashes stay red: those mean damage, whoever takes it. */
.unit.summon {
  --color-blood: var(--color-necromancy);
  --color-blood-glow: var(--color-necro-glow);
  --glow-intent: 0 0 18px var(--color-necro-glow);
  --shadow-text-blood: 0 0 14px var(--color-necro-glow), 0 1px 0 var(--color-pitch);
}

/* Curses carry no school color: dead, ashen, unappealing on purpose (DESIGN.md section 4). */
.card[data-school="curse"] {
  --card-stock-top: color-mix(in srgb, var(--color-ash) 34%, var(--color-void));
  --card-stock-mid: color-mix(in srgb, var(--color-ash) 22%, var(--color-void));
  --card-stock-low: color-mix(in srgb, var(--color-ash) 12%, var(--color-void));
  --card-edge: color-mix(in srgb, var(--color-ash) 50%, var(--color-void));
  --card-ink: var(--color-ash);
  --card-name-ink: color-mix(in srgb, var(--color-ash) 80%, var(--color-bone));
  --card-number: var(--color-ash);
  --surface-edge: none;
  --glow-edge: none;
  --well-light: var(--color-ash);
}
