@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  h1, h2, h3, h4 { @apply font-display; }

  /* Charm "essence" — a brilliant near-white baby-blue for discovered/combined runes (whiter than sky). */
  :root {
    --essence-text: #ecf5ff;
    --essence-shadow: 0 0 5px rgba(236, 246, 255, 0.95), 0 0 12px rgba(200, 226, 255, 0.72), 0 0 22px rgba(170, 206, 255, 0.45);
    --essence-glow: 0 0 18px 3px rgba(208, 232, 255, 0.6);
    --essence-ray: rgba(222, 240, 255, 0.34);
  }
}

@layer components {
  /* Surfaces */
  .panel {
    @apply rounded-xl border border-stone-700/70 bg-stone-900/60 shadow-card backdrop-blur-sm;
  }
  .panel-title {
    @apply font-display text-xs uppercase tracking-[0.18em] text-gold/90;
  }

  /* Shop drawer: the Shop collapses to a thin vertical rail on the board's left; hovering the rail
     expands the full Shop as an overlay panel. The panel is absolutely positioned so expanding it
     overlays the play field without reflowing it. Pure CSS :hover — no Stimulus, so it survives the
     Turbo board re-render for free and its Buy buttons stay clickable while open. */
  .shop-rail { @apply relative shrink-0 self-stretch; width: 2.75rem; }
  /* Collapsed tab: a full-height panel strip with vertically-set "The Shop"; fades out as it expands. */
  .shop-rail-tab {
    @apply panel flex h-full cursor-pointer items-center justify-center px-1 transition-opacity duration-500;
  }
  .shop-rail-tab span {
    @apply font-display text-xs uppercase tracking-[0.2em] text-gold/90;
    writing-mode: vertical-rl; transform: rotate(180deg);
  }
  /* Expanded overlay: hidden + click-through when collapsed, revealed on rail hover. w-max takes the
     Shop's natural width; z-50 + an opaque panel background so it clearly occludes the play field. */
  .shop-rail-panel {
    @apply invisible absolute left-0 top-0 z-50 w-max -translate-x-2 opacity-0 transition-all duration-500;
    pointer-events: none;
  }
  .shop-rail-panel > .panel { @apply bg-stone-900/95; }
  .shop-rail:hover .shop-rail-panel {
    @apply visible translate-x-0 opacity-100;
    pointer-events: auto;
  }
  .shop-rail:hover .shop-rail-tab { @apply opacity-0; }

  /* Parchment card face (shared by hand / play area / supply / discard).
     Fixed size (w-32 × h-44, matching .pile-slot) so the board doesn't reflow with content;
     long descriptions are shrunk to fit by the fit-text Stimulus controller. */
  .card-face {
    /* `isolate` makes each card its own stacking context so the z-10 cost badge stays contained and
       is overlapped along with its card (rather than floating above neighboring cards in a fan). */
    @apply relative isolate flex h-44 w-32 flex-col overflow-hidden rounded-lg border border-stone-900/40
           bg-gradient-to-b from-parchment to-parchment-dark text-stone-900 shadow-card
           transition duration-150 ease-out
           hover:-translate-y-2 hover:scale-[1.04] hover:shadow-glow hover:z-20;
  }
  .card-name { @apply px-1.5 pt-2 text-center font-display text-[12px] font-bold leading-tight; }
  .card-type { @apply px-1.5 text-center text-[9px] uppercase tracking-widest text-stone-700/80; }
  .card-desc { @apply mt-1 min-h-0 flex-1 overflow-hidden whitespace-pre-line px-2 pb-1 text-[10px] leading-snug text-stone-800; }
  /* Live computed amounts (Gm::DescriptionCalculator) — a saturated green, hue-separated from the
     near-black description text so players see at a glance which numbers update with game state. */
  .card-amount { @apply font-semibold; color: #15803d; }
  /* The gold cost circle, worn by every card face and by the condensed Shop chips.
     A caller sets only --coin-size; the numeral is DERIVED from it, so the coin reads as the same
     coin wherever it's drawn and at whatever scale. That's what keeps a Shop chip's coin identical
     to the coin on the Shop card beside it: the card face is painted at .card-mini's scale(.85), so
     its 1.5rem coin lands at 1.275rem — exactly the chip's — and the numeral rides along by the same
     factor. A full-size card (hand, play area) just gets a proportionally larger coin.
     Tune the numeral for every coin at once by changing --coin-numeral. */
  .cost-badge {
    @apply flex items-center justify-center rounded-full bg-gradient-to-b from-gold-light
           to-gold-dark font-bold text-stone-900 ring-1 ring-stone-900/40 shadow;
    --coin-base: 1.354rem;   /* the full-size card's coin — resize EVERY coin from here */
    --coin-numeral: 0.588;   /* numeral : coin — retune every numeral from here */
    width: var(--coin-size);
    height: var(--coin-size);
    font-size: calc(var(--coin-size) * var(--coin-numeral));
    line-height: 1;
  }
  /* The coin rides in the footer row (in flow), pushed right by ml-auto so card tags can later fill
     the space to its left without touching this. */
  .card-cost {
    @apply cost-badge ml-auto shrink-0;
    --coin-size: var(--coin-base);
  }
  /* The card's footer strip: tinted with the type colour (see CardsHelper::CARD_TYPE_STYLES),
     echoing the face's top edge. Carries the cost coin, and is the home for card tags (duration /
     gathering / pooling …) — add them as children before the coin and they land on the left. */
  .card-footer {
    @apply mt-auto flex shrink-0 items-center gap-1 px-1.5 py-0.5;
    /* A whisper of shadow along the top edge — the card body casting down onto the strip, so the two
       read as separate bands instead of the tint bleeding out of the description. */
    box-shadow: inset 0 2px 3px -1px rgba(0, 0, 0, 0.35);
  }
  /* Per-card token counter (Duration cards like Curse of Doom): top-LEFT, diagonally clear of the
     bottom-right gold cost coin; dark with a blood ring + glow to read as a menacing countdown. */
  .card-tokens {
    @apply absolute left-1 top-1 z-10 inline-flex h-6 items-center justify-center gap-0.5 rounded-full
           border border-blood-dark bg-stone-950 px-1.5 font-display text-[11px] font-bold text-blood-light shadow-glow-blood;
  }
  /* Disruption token straddling the draw pile's top edge: a violet "no-draw" badge (eats a draw). */
  .disruption-token {
    @apply absolute -top-2 left-1/2 z-20 inline-flex -translate-x-1/2 items-center gap-1 rounded-full
           border border-violet-400/70 bg-stone-950 px-2 py-0.5 font-display text-xs font-bold
           text-violet-200 shadow-glow;
  }
  /* Curse tokens in the Play Area title row: condensed colored pills (one letter + count), one per held
     curse; the per-curse color is applied inline (see CursesHelper). Hover for the full name + effect. */
  .curse-token {
    @apply inline-flex h-6 items-center gap-1 rounded-full border px-2 font-display
           text-[11px] font-bold shadow;
  }
  /* Each die's low→high pair on the advantage toast (keeps a pair visually grouped). */
  .toast-die-spread { @apply rounded-md bg-stone-900/40 px-0.5; }
  /* Opt a card-face out of the hover pop/lift (Discard pile, scry/reveal, Trash). Pair with _card_face's
     `static:` (which drops the cursor-tilt `card` controller) so hovering only highlights — the
     `.card-face` hover:shadow-glow stays — and shows the tooltip. */
  .card-face.card-static:hover { transform: none; }

  /* Equipped Items: a horizontal fan of ~70%-scale card faces (equip order, oldest at the left). Each
     card peeks from under the next; the most recently equipped sits fully visible on top (rightmost).
     Hovering a card lifts it to the front at full size for reading. The per-card left offset + the
     stack width are set inline (they depend on item count). */
  .equip-stack { @apply relative w-full; height: 124px; }
  .equip-card-slot { @apply absolute top-0; }
  .equip-card-slot:hover { z-index: 50; }
  .card-face.equip-card { transform: scale(0.7); transform-origin: top left; }
  .equip-card-slot:hover .card-face.equip-card { transform: scale(1); }

  /* Your Hand: a single-row fan that never wraps. Each card after the first pulls left by the
     count-derived --hand-overlap (set inline on the container), but min() caps it at a normal gap —
     so a few cards sit apart and a full hand overlaps like held cards. Hovering lifts a card and its
     Play button to the front. */
  .hand-card { @apply relative; }
  .hand-card:not(:first-child) { margin-left: min(0.75rem, var(--hand-overlap, 0.75rem)); }
  .hand-card:hover { z-index: 30; }

  /* 85%-scale card box (play-area fans + shop): a fixed 85% slot holding the full card-face scaled to
     fit, so the board compresses. Hovering pops the card toward full size, above its neighbours. */
  .card-mini { @apply relative; width: 109px; height: 150px; }
  .card-mini:hover { z-index: 30; }
  .card-mini > .card-face { transform: scale(0.85); transform-origin: top left; }
  .card-mini:hover > .card-face { transform: scale(1.04); }

  /* A single-row fan of card-minis (Duration / Purchased Queue / Played This Turn): never wraps; each
     card after the first pulls left by the count-derived --fan-overlap (set inline), capped at a gap. */
  .card-fan > .card-mini:not(:first-child) { margin-left: min(0.5rem, var(--fan-overlap, 0.5rem)); }

  /* Buttons */
  .btn-rune {
    @apply inline-flex items-center justify-center rounded border border-gold-dark
           bg-gradient-to-b from-gold to-gold-dark px-3 py-1 font-display text-[11px] font-bold
           uppercase tracking-wider text-stone-900 shadow transition hover:brightness-110
           active:translate-y-px disabled:cursor-not-allowed disabled:opacity-40 disabled:saturate-50;
  }
  .btn-danger {
    @apply inline-flex items-center justify-center rounded border border-blood-dark
           bg-gradient-to-b from-blood-light to-blood px-3 py-1 font-display text-[11px] font-bold
           uppercase tracking-wider text-stone-100 shadow transition hover:brightness-110 active:translate-y-px
           disabled:cursor-not-allowed disabled:opacity-50 disabled:grayscale disabled:hover:brightness-100
           disabled:active:translate-y-0;
  }

  /* Auth (sign-in email / code-entry) text inputs */
  .auth-input {
    @apply w-full rounded-md border border-stone-700 bg-stone-950/70 px-3 py-2 text-stone-100
           placeholder-stone-600 shadow-inner outline-none transition
           focus:border-gold focus:ring-1 focus:ring-gold/60;
  }

  /* Stat HUD */
  .stat-pill { @apply flex items-center gap-1.5 rounded-md border border-stone-700 bg-stone-800/80 px-2.5 py-1; }
  .stat-label { @apply text-[10px] uppercase tracking-wide text-stone-400; }
  .stat-value { @apply font-display text-base font-bold leading-none text-parchment; }

  /* Enemy tiers */
  .enemy-tier {
    @apply relative block w-full rounded-lg border border-stone-700 bg-gradient-to-b
           from-stone-800 to-stone-900/90 px-3 py-2 text-left;
  }
  .enemy-tier-targetable {
    @apply cursor-pointer border-blood-light shadow-glow-blood hover:from-blood-dark hover:to-stone-900 animate-pulse-glow;
  }

  /* Draw / discard pile stacks flanking the hand */
  .pile-slot { @apply relative h-44 w-32 shrink-0; }
  .card-back {
    @apply rounded-lg border-2 border-gold-dark/50 bg-gradient-to-br from-stone-700 to-stone-950 shadow-card;
    background-image: repeating-linear-gradient(45deg, rgba(201, 162, 39, 0.08) 0, rgba(201, 162, 39, 0.08) 6px, transparent 6px, transparent 12px);
  }
  .pile-empty {
    @apply flex h-full w-full items-center justify-center rounded-lg border-2 border-dashed border-stone-700 text-[10px] uppercase tracking-wide text-stone-600;
  }
  .pile-count {
    @apply absolute -bottom-2 -right-2 z-30 flex h-8 w-8 items-center justify-center rounded-full border border-gold-dark bg-stone-950 font-display text-sm font-bold text-gold shadow-glow;
  }

  /* Enemy: skeuomorphic stacks of trophy tokens, each paired with its attack die */
  .token-stack { @apply flex flex-col items-center; }
  .trophy-token {
    @apply block h-4 w-4 rounded-full border border-amber-900/70 bg-gradient-to-b from-gold-light to-gold-dark shadow;
  }
  .token-stack > .trophy-token + .trophy-token { margin-top: -9px; }
  .enemy-die { @apply h-7 w-7 shrink-0 drop-shadow; }
  .enemy-die-shape {
    fill: theme('colors.blood.DEFAULT');
    stroke: theme('colors.blood.light');
    stroke-width: 1.25;
    stroke-linejoin: round;
  }
  .enemy-die-text {
    fill: theme('colors.stone.100');
    font-size: 9px;
    font-weight: 700;
    text-anchor: middle;
    dominant-baseline: central;
  }
  /* A disrupted die (e.g. Arcane Blast): grayed out + a red ✕, removed from the next attack roll. */
  .enemy-die-disrupted .enemy-die-shape { fill: theme('colors.stone.600'); stroke: theme('colors.stone.500'); }
  .enemy-die-disrupted .enemy-die-text { fill: theme('colors.stone.400'); }
  .enemy-die-x { stroke: theme('colors.blood.light'); stroke-width: 2.5; stroke-linecap: round; }

  /* Condensed shop chips for the standard money / mastery cards */
  .shop-chip { @apply flex items-center justify-between gap-1 rounded-md border bg-stone-800/70 px-2 py-1; }
  /* The chip's cost: the same gold coin a card face wears, sat inline just before Buy (mirroring the
     face's top-right badge). Sized 1.275rem — NOT the face's 1.5rem — because a chip gets no
     .card-mini scale(.85) of its own, so it carries that factor here to land pixel-identical to the
     coins on the Shop cards beside it. Keep this in step if .card-mini's scale ever changes. */
  .chip-cost {
    @apply cost-badge shrink-0;
    --coin-size: calc(var(--coin-base) * 0.85); /* matches a Shop card's painted coin */
  }
  .btn-mini { @apply px-2 py-0.5 text-[10px]; }

  /* Hide native number-input spinners so a custom ▲/▼ stepper is the only control (Bounty Hunter spend prompt) */
  .no-spinner { -moz-appearance: textfield; appearance: textfield; }
  .no-spinner::-webkit-outer-spin-button,
  .no-spinner::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

  /* A locked / at-cap picker option: grayed out + non-interactive. The card-select controller toggles
     `is-dimmed` on the option's <label> once the selection cap is reached (the checkbox itself is also
     `disabled`, so the option can't be picked). Scoped to `label` so it out-ranks the option's own
     `cursor-pointer` utility, and so it never touches the set-aside cards / class-selection tiles, which
     carry their own stronger `.is-dimmed` rules. */
  label.is-dimmed { @apply cursor-not-allowed opacity-40 grayscale; }

  /* Mastery / Skill graduated track pointer */
  .mastery-knob {
    @apply flex h-6 w-9 items-center justify-center rounded-md border border-gold-dark
           bg-gradient-to-b from-gold-light to-gold-dark font-display text-xs font-bold text-stone-900 shadow-glow;
  }

  /* Enemy-attack toasts: a fixed, vertically-stacked column that auto-dismisses */
  .toast-stack {
    @apply pointer-events-none fixed right-4 top-4 z-50 flex w-60 flex-col gap-2;
  }
  .toast {
    @apply pointer-events-auto translate-x-6 rounded-lg border bg-stone-900/95 px-3 py-2 opacity-0
           shadow-glow backdrop-blur-sm transition duration-300 ease-out;
  }
  .toast-show { @apply translate-x-0 opacity-100; }
  .toast-hide { @apply translate-x-6 opacity-0; }
  .toast-injury { @apply border-blood-light/70; }
  .toast-buff { @apply border-gold/70; }
  .toast-quiet { @apply border-stone-700; }

  /* Unequip-to-equip focus mode: glowing, selectable equipped cards (gold; red when selected) */
  .unequip-glow { @apply rounded-lg ring-2 ring-gold/80 shadow-glow transition; }
  .unequip-glow.is-selected { @apply ring-blood-light shadow-glow-blood; }
  .toast-title { @apply font-display text-sm font-bold uppercase tracking-wide text-parchment; }
  .toast-body { @apply mt-0.5 flex items-center gap-1.5 text-sm text-stone-200; }
  .toast-injury-count { @apply font-display text-lg font-bold leading-none text-blood-light; }
  .toast-sub { @apply mt-1 text-[10px] uppercase tracking-widest text-stone-500; }

  /* Global Trash explorer: a toggle pinned to the Play Area's top-right corner that expands an
     on-demand floating panel of the match's trashed cards (grouped by name, duplicates stacked) over a
     dimmed board. The panel is position:fixed and pinned under the button by the `trash` controller. */
  .trash-toggle {
    @apply flex h-7 w-7 shrink-0 items-center justify-center rounded-md border
           border-stone-600 bg-stone-800/80 text-stone-300 shadow transition hover:border-gold hover:text-gold;
  }
  .trash-overlay { @apply fixed inset-0 z-40 bg-stone-950/80; }
  .trash-panel {
    @apply fixed z-50 max-h-[70vh] max-w-[90vw] overflow-auto rounded-xl border border-gold/50
           bg-stone-900/95 p-3 shadow-glow backdrop-blur-sm;
  }
  /* Focused floating scry window (reveal decisions): a board-level dim + a CENTERED panel whose cards
     lay out horizontally. Auto-shown while the decision is pending (no toggle); see _scry. */
  .scry-overlay { @apply fixed inset-0 z-40 bg-stone-950/80; }
  .scry-panel {
    @apply fixed left-1/2 top-1/2 z-50 max-h-[85vh] max-w-[92vw] -translate-x-1/2 -translate-y-1/2
           overflow-auto rounded-xl border border-gold/60 bg-stone-900/95 p-4 shadow-glow backdrop-blur-sm;
  }
  .scry-cards { @apply flex flex-row flex-wrap items-end justify-center gap-4; }
  /* Stacks grow right-to-left from the button and wrap to rows beneath once they reach the panel edge. */
  .trash-stacks { @apply flex flex-row-reverse flex-wrap justify-start gap-x-4 gap-y-3; }
  .trash-stack { @apply relative; }
  .trash-front { @apply absolute bottom-0 left-0 z-10; }
  /* "Underneath" duplicates: card-sized slabs peeking their top edge above the front face. */
  .trash-slab {
    @apply absolute left-0 z-0 rounded-lg border border-stone-900/40 bg-gradient-to-b from-parchment
           to-parchment-dark shadow-card;
    width: 128px;
    height: 176px;
    bottom: calc(var(--depth) * 10px); /* fan up ~10px: shows the 4px accent bar + a sliver of parchment */
  }
  /* Trash cards render `static:` (see _card_face / .card-static) so hovering highlights + tooltips
     without growing past the fixed panel and triggering scrollbars. */
  .trash-count {
    @apply absolute bottom-1 right-1 z-20 flex h-6 min-w-[1.5rem] items-center justify-center rounded-full
           border border-gold-dark bg-stone-950 px-1.5 font-display text-xs font-bold text-gold shadow-glow;
  }
  .trash-empty { @apply px-8 py-10 text-center text-sm italic text-stone-400; }

  /* ── Game Manual (How to Play) ─────────────────────────────────────────────── */

  /* A collapsible manual section — a panel whose <summary> is the clickable heading. Native
     <details>, so the disclosure costs zero JS and survives any Turbo render for free. The
     quickstart tier ships `open`; deeper tiers start closed so the first screen stays calm. */
  .manual-section { @apply panel overflow-hidden; }
  .manual-section + .manual-section { @apply mt-3; }
  .manual-section > summary {
    @apply flex cursor-pointer list-none items-center gap-3 px-4 py-3 font-display text-lg
           font-bold tracking-wide text-gold transition hover:bg-stone-800/40;
  }
  .manual-section > summary::-webkit-details-marker { display: none; }
  .manual-section[open] > summary { @apply border-b border-stone-700/60; }
  .manual-chevron { @apply h-3.5 w-3.5 shrink-0 text-gold/60 transition-transform duration-200; }
  .manual-section[open] > summary .manual-chevron { transform: rotate(90deg); }

  /* Section body copy. Spacing is handled here (rather than per-element utilities) so the prose
     ports over from docs/HOW_TO_PLAY.md as plain semantic markup. */
  .manual-body { @apply px-4 pb-4 pt-3 text-sm leading-relaxed text-stone-300; }
  .manual-body > * + * { @apply mt-3; }
  .manual-body strong { @apply font-semibold text-parchment; }
  .manual-body ul { @apply list-disc space-y-1.5 pl-5 marker:text-gold/50; }
  .manual-body ol { @apply list-decimal space-y-1.5 pl-5 marker:text-gold/50; }
  /* Subheads reuse the shared gold eyebrow rather than re-deriving it (see docs/FRONTEND.md). */
  .manual-body h3 { @apply panel-title mt-4; }

  /* Reference tables (symbols, glossary, tiers, classes). */
  .manual-table { @apply w-full border-collapse text-left text-xs; }
  .manual-table th {
    @apply border-b border-stone-700 px-2 py-1.5 font-display text-[10px] uppercase
           tracking-wider text-gold/80;
  }
  .manual-table td { @apply border-b border-stone-800/80 px-2 py-1.5 align-top text-stone-300; }
  .manual-table tr:last-child td { @apply border-b-0; }
  /* Long tables scroll inside the section rather than widening the page on mobile. */
  .manual-scroll { @apply -mx-1 overflow-x-auto px-1; }

  /* Tier eyebrow above each group of sections ("Get playing" / "Learn the systems" / "Go deeper").
     No `first:` variant here — each eyebrow is rendered by its own partial into a shared parent, so
     none of them is ever :first-child (a partial boundary is not a DOM boundary). */
  .manual-tier { @apply mb-2 mt-8 flex items-center gap-3; }
  .manual-tier-label { @apply font-display text-[11px] uppercase tracking-[0.25em] text-stone-500; }
  .manual-tier-rule { @apply h-px flex-1 bg-stone-800; }

  /* The "whole game in one line" pull-quote, and the quieter caveat note. */
  .manual-callout {
    @apply rounded-lg border border-gold/40 bg-stone-900/70 px-4 py-3 text-center font-display
           text-sm leading-relaxed text-parchment shadow-glow;
  }
  .manual-note {
    @apply rounded-md border-l-2 border-gold/50 bg-stone-900/50 px-3 py-2 text-xs text-stone-400;
  }

  /* ── Runes & Charms collection ─────────────────────────────────────────────── */

  /* Rough-hewn rune-stone: an irregular polygon of mottled grey stone with the rune carved large in the
     middle. .stone-a/-b/-c vary the outline + tone so the grid looks hand-cut, not minted. */
  .rune-stone { @apply relative flex flex-col items-center; }
  .rune-stone-face {
    @apply relative flex aspect-[5/6] w-full items-center justify-center transition;
    isolation: isolate;
    box-shadow: inset 0 2px 4px rgba(255, 255, 255, 0.14), inset 0 -6px 10px rgba(0, 0, 0, 0.55);
  }
  /* Stone grain: fractal-noise overlay, clipped with the stone (sits below the carved glyph). */
  .rune-stone-face::after, .charm-rune::after, .rune-socket.is-filled::after, .discovery-rune::after {
    content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='108'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='90' height='108' filter='url(/%23n)' opacity='0.6'/%3E%3C/svg%3E");
    background-size: cover; mix-blend-mode: overlay; opacity: 0.45;
  }
  .rune-stone-face.stone-a { clip-path: polygon(20% 3%, 50% 0%, 79% 5%, 93% 20%, 99% 45%, 95% 72%, 82% 92%, 56% 100%, 31% 97%, 11% 85%, 2% 58%, 6% 26%); background: radial-gradient(115% 90% at 34% 20%, rgba(255,255,255,0.2), transparent 55%), linear-gradient(158deg, #918f88, #76746d 46%, #565550); }
  .rune-stone-face.stone-b { clip-path: polygon(14% 7%, 42% 1%, 73% 3%, 91% 16%, 99% 42%, 99% 68%, 86% 89%, 61% 99%, 36% 100%, 15% 88%, 4% 62%, 3% 30%); background: radial-gradient(110% 85% at 60% 24%, rgba(255,255,255,0.17), transparent 55%), linear-gradient(150deg, #8a8983, #6f6e67 50%, #514f4a); }
  .rune-stone-face.stone-c { clip-path: polygon(24% 2%, 55% 2%, 81% 9%, 96% 28%, 98% 54%, 90% 80%, 75% 95%, 50% 100%, 26% 94%, 8% 80%, 1% 52%, 9% 22%); background: radial-gradient(120% 95% at 30% 18%, rgba(255,255,255,0.22), transparent 58%), linear-gradient(165deg, #95948d, #79786f 44%, #5b5953); }

  /* Carved, unlit glyph — darker than the stone; no essence has found it yet (Runes page). */
  .rune-glyph {
    @apply relative font-display text-4xl leading-none; z-index: 2;
    color: #312f2b; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.18), 0 -1px 1px rgba(0, 0, 0, 0.5);
  }
  .rune-stone.is-owned .rune-stone-face { @apply cursor-pointer; }
  .rune-stone.is-owned:hover .rune-stone-face { filter: brightness(1.12); box-shadow: inset 0 2px 4px rgba(255, 255, 255, 0.16), inset 0 -6px 10px rgba(0, 0, 0, 0.55), 0 0 14px 1px rgba(201, 162, 39, 0.3); }
  .rune-stone.is-empty { @apply opacity-50; }
  .rune-stone.is-empty .rune-stone-face { filter: grayscale(0.5) brightness(0.78); }
  .rune-stone.is-empty .rune-glyph { color: #2b2a27; }

  .rune-count {
    @apply absolute right-0 top-0 z-20 flex h-5 min-w-[1.25rem] items-center justify-center rounded-full
           border border-gold-dark bg-stone-950 px-1 font-display text-[11px] font-bold text-gold shadow;
  }
  .rune-stone.is-empty .rune-count { @apply hidden; }
  .rune-info { @apply mt-1.5 leading-tight; }
  .rune-name { @apply block font-display text-[10px] font-bold tracking-wide text-parchment; }
  .rune-translation { @apply block text-[9px] italic text-stone-400; }
  .rune-stone.is-empty .rune-name { @apply text-stone-500; }

  /* Crafting sockets — stone-shaped recesses a rune drops into; the runeword lights essence / red. */
  .rune-socket {
    @apply relative flex h-16 w-16 items-center justify-center font-display text-3xl text-stone-300 transition;
    isolation: isolate;
    clip-path: polygon(20% 3%, 50% 0%, 79% 5%, 93% 20%, 99% 45%, 95% 72%, 82% 92%, 56% 100%, 31% 97%, 11% 85%, 2% 58%, 6% 26%);
    /* Dark, opaque interior so the socket reads as a recessed hole. */
    background: linear-gradient(160deg, #26261f, #141410);
    /* The chiselled rim is a LIT inset ring on the inner edge — lighter than the dark centre. (An outer
       dark inset, or no inner light, leaves the edges darker than the face — the opposite of what we
       want.) A faint outer drop-shadow halo then separates the socket from the near-black panel, since
       clip-path clips an outer box-shadow away. */
    box-shadow: inset 0 0 0 1.5px rgba(210, 207, 192, 0.7), inset 0 0 11px 2px rgba(204, 201, 186, 0.42);
    filter: drop-shadow(0 0 2px rgba(150, 148, 138, 0.4));
  }
  .rune-socket.is-filled {
    @apply text-stone-100;
    background: radial-gradient(115% 90% at 34% 20%, rgba(255, 255, 255, 0.18), transparent 55%), linear-gradient(158deg, #918f88, #565550);
    box-shadow: inset 0 2px 4px rgba(255, 255, 255, 0.12), inset 0 -6px 10px rgba(0, 0, 0, 0.5);
  }
  .rune-socket.is-discovered { color: var(--essence-text); text-shadow: var(--essence-shadow); box-shadow: inset 0 0 14px rgba(208, 232, 255, 0.5); filter: drop-shadow(0 0 5px rgba(208, 232, 255, 0.85)) drop-shadow(0 0 1px rgba(236, 246, 255, 0.95)); }
  .rune-socket.is-attempted { color: theme('colors.blood.light'); text-shadow: 0 0 8px rgba(192, 57, 43, 0.85); box-shadow: inset 0 0 12px rgba(192, 57, 43, 0.4); filter: drop-shadow(0 0 5px rgba(192, 57, 43, 0.8)); }

  /* Tabs + book bookmarks */
  .tab { @apply rounded-t-md border-b-2 border-transparent px-4 py-2 font-display text-xs uppercase tracking-wider text-stone-400 transition hover:text-gold; }
  .tab.tab-active { @apply border-gold text-gold; }
  .bookmark {
    @apply rounded-b-md border border-t-0 px-3 py-1 font-display text-[11px] font-bold uppercase tracking-wide transition;
    color: #3c2c18; border-color: rgba(70, 50, 26, 0.6);
    background: linear-gradient(180deg, #d9b84a, #b3902c);
  }
  .bookmark:hover { filter: brightness(1.07); }

  /* The Charm Book — an aged tome with mottled parchment pages and a dark board cover. */
  .charm-book {
    @apply relative rounded-sm text-stone-800;
    border: 7px solid #2b2014;
    background: radial-gradient(130% 100% at 50% -5%, rgba(80, 55, 20, 0.16), transparent 42%), linear-gradient(180deg, #ece0c8, #d6c4a0);
    box-shadow: inset 0 0 52px rgba(110, 80, 35, 0.4), inset 0 0 6px rgba(50, 33, 12, 0.6), 0 10px 26px -6px rgba(0, 0, 0, 0.7);
  }
  .charm-book::before {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(/%23p)' opacity='0.5'/%3E%3C/svg%3E");
    mix-blend-mode: multiply; opacity: 0.12;
  }
  .charm-book > * { position: relative; z-index: 1; }
  .book-title { @apply text-center font-display text-2xl font-black tracking-wide; color: #46321d; }
  .book-section { @apply text-center text-[11px] uppercase tracking-[0.22em]; color: #7a6038; }
  .book-pagelabel { @apply text-[11px] uppercase tracking-wider; color: #6b5430; }

  /* Charm entries — framed grimoire panels inked on the parchment */
  .charm-entry { @apply flex flex-col items-center rounded-sm p-3 text-center; background: rgba(120, 90, 45, 0.1); border: 1px solid rgba(90, 67, 38, 0.32); }
  /* A completed charm reads darker; each of its runes is its own locus of light — a baby-blue flashlight
     pooling directly behind that single stone. */
  .charm-entry.is-discovered { background: rgba(58, 43, 18, 0.2); border-color: rgba(120, 150, 185, 0.42); }
  .charm-entry.is-discovered .charm-rune-group { position: relative; isolation: isolate; }
  .charm-entry.is-discovered .charm-rune-group::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    top: 1.125rem; left: 50%; width: 3.55rem; height: 3.55rem; transform: translate(-50%, -50%);
    /* A baby-blue flashlight behind each rune — bright, but not blinding. */
    background:
      radial-gradient(circle, rgba(206, 230, 255, 0.78), rgba(184, 214, 255, 0.34) 38%, transparent 68%),
      radial-gradient(circle, rgba(168, 204, 255, 0.34), transparent 76%);
  }
  .charm-name { @apply font-display text-sm font-bold tracking-wide; color: #38280f; }
  .charm-effect { @apply mt-1 text-[11px] leading-snug; color: #564223; }
  .charm-undiscovered { @apply mt-1 text-[11px] italic; color: #93805b; }

  /* Charm runes: little rough stones. Discovered → glowing essence glyph; undiscovered → empty hollow. */
  .charm-runes { @apply my-2 flex flex-wrap justify-center gap-1.5; }
  .charm-rune {
    @apply relative flex h-9 w-9 items-center justify-center font-display text-lg;
    isolation: isolate;
    clip-path: polygon(20% 3%, 50% 0%, 79% 5%, 93% 20%, 99% 45%, 95% 72%, 82% 92%, 56% 100%, 31% 97%, 11% 85%, 2% 58%, 6% 26%);
    background: linear-gradient(160deg, rgba(70, 52, 28, 0.5), rgba(40, 28, 14, 0.62));
    box-shadow: inset 0 2px 6px rgba(40, 25, 8, 0.6);
  }
  .charm-rune.is-stone {
    color: var(--essence-text); text-shadow: var(--essence-shadow);
    background: radial-gradient(115% 90% at 34% 20%, rgba(255, 255, 255, 0.18), transparent 55%), linear-gradient(158deg, #918f88, #565550);
    box-shadow: var(--essence-glow), inset 0 1px 2px rgba(255, 255, 255, 0.12);
  }
  /* A located-but-not-yet-completed rune: the same rough gray stone as the Runes page, glyph carved and
     UNLIT — no essence. (Essence is the reward for completing the whole runeword.) */
  .charm-rune.is-located {
    color: #2f2d28; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.16), 0 -1px 1px rgba(0, 0, 0, 0.4);
    background: radial-gradient(115% 90% at 34% 20%, rgba(255, 255, 255, 0.16), transparent 55%), linear-gradient(158deg, #918f88, #565550);
    box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.1), inset 0 -3px 6px rgba(0, 0, 0, 0.45);
  }
  /* Each discovered rune sits over its name, so the player can read the runeword that formed the charm. */
  .charm-rune-group { @apply flex flex-col items-center; }
  .charm-rune-name { @apply mt-1 block font-display text-[9px] font-bold leading-none tracking-tight; color: #5a4326; }
  .charm-rune-name--blank { color: #b6a88c; } /* the "?" under an unlocated slot */

  /* A hunt in progress: the Hummers known to be in the word (slot still unknown) + a redacted effect. */
  .charm-hums { @apply mt-1 text-[10px] leading-snug; color: #6c5836; }
  .charm-hum-runes { font-weight: 700; color: #2f4a63; text-shadow: 0 0 6px rgba(170, 206, 255, 0.45); }
  /* The effect, partly un-redacted: located words show; the rest are a heavy blur (over a same-length
     placeholder, so the real text never reaches the client). */
  .charm-effect--redacted { word-spacing: 1px; }
  .blurred-word { display: inline-block; filter: blur(3.5px); opacity: 0.8; user-select: none; }

  /* Discovery fanfare modal */
  .discovery-modal { @apply fixed inset-0 z-50 flex items-center justify-center p-4; }
  .discovery-backdrop { @apply absolute inset-0 bg-stone-950/80 backdrop-blur-sm; }
  .discovery-card {
    @apply relative z-10 flex w-full max-w-sm flex-col items-center rounded-2xl border bg-gradient-to-b from-stone-800 to-stone-950 p-8 text-center;
    border-color: rgba(208, 232, 255, 0.4); box-shadow: 0 0 44px 6px rgba(208, 232, 255, 0.35);
  }
  .discovery-eyebrow { @apply font-display text-[11px] uppercase tracking-[0.3em]; color: var(--essence-text); }
  .discovery-name { @apply mt-1 font-display text-3xl font-black text-parchment drop-shadow; }
  .discovery-runes { @apply relative my-6 flex justify-center gap-3; }
  .discovery-rune {
    @apply relative flex h-14 w-14 items-center justify-center font-display text-3xl; isolation: isolate;
    clip-path: polygon(20% 3%, 50% 0%, 79% 5%, 93% 20%, 99% 45%, 95% 72%, 82% 92%, 56% 100%, 31% 97%, 11% 85%, 2% 58%, 6% 26%);
    color: var(--essence-text); text-shadow: var(--essence-shadow);
    background: radial-gradient(115% 90% at 34% 20%, rgba(255, 255, 255, 0.2), transparent 55%), linear-gradient(158deg, #918f88, #565550);
    box-shadow: var(--essence-glow);
  }
  .discovery-effect { @apply text-sm leading-snug text-stone-300; }

  /* "A rune resonates" Hummer hint — a quieter, smaller cousin of the fanfare. */
  .hum-card {
    @apply relative z-10 flex w-full max-w-xs flex-col items-center rounded-2xl border bg-gradient-to-b from-stone-800 to-stone-950 p-6 text-center;
    border-color: rgba(208, 232, 255, 0.3); box-shadow: 0 0 30px 3px rgba(208, 232, 255, 0.2);
  }
  .hum-eyebrow { @apply font-display text-[11px] uppercase tracking-[0.25em]; color: var(--essence-text); }
  .hum-rune { @apply my-3; }
  .hum-message { @apply text-sm leading-snug text-stone-200; }
  .hum-actions { @apply mt-5 flex flex-wrap justify-center gap-3; }

  /* Radiant essence behind the fanfare reveal: a soft feathered glow (::after) with a few static
     light-rays mixed in (::before). No motion — the brilliance is meant to sit still. */
  .essence-rays { @apply relative isolate; }
  .essence-rays::before {
    content: ""; position: absolute; inset: -85%; z-index: -1; pointer-events: none;
    background: repeating-conic-gradient(from -90deg, transparent 0deg 27deg, var(--essence-ray) 27deg 30deg);
    -webkit-mask: radial-gradient(closest-side, transparent 13%, #000 32%, transparent 74%);
            mask: radial-gradient(closest-side, transparent 13%, #000 32%, transparent 74%);
  }
  .essence-rays::after {
    content: ""; position: absolute; inset: -40%; z-index: -1; pointer-events: none;
    background: radial-gradient(closest-side, rgba(208, 232, 255, 0.5), rgba(198, 224, 255, 0.16) 44%, transparent 72%);
  }
}
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *


 */
