/* ===== /css/rajdhani-fonts.css ===== */
/* Rajdhani Self-Hosted Fonts - Optimized for Performance */
/* Latin subset, WOFF2 format, font-display: swap */

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

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

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

/* ===== /css/tokens.css ===== */
/* ============================================================================
   BLOOD CAFÉ — DESIGN TOKENS
   Added 2026-09-03. Loaded LAST so it is the single authority on colour, spacing,
   radius and elevation.

   WHY THIS FILE EXISTS
   The site had two competing visual languages: an original neon purple/cyan system
   in styles.css and a later black/bone/blood "reaper" theme layered on top, with
   reaper hijacking some of the old variables (--neon-cyan -> red) but not others.
   Worse, --muted, --purple, --brand and --cyan were referenced 111 times across the
   site while being defined in only a handful of page-local <style> blocks — three
   pages used var(--muted) without ever defining it, so that text silently fell back
   to an inherited colour.

   The direction is "tactical command centre", not "neon casino": a near-black ground,
   quiet elevated surfaces, hairline borders, ONE hot accent (blood red) used sparingly
   for emphasis and state, and a cool steel-blue as the single secondary. Depth comes
   from layered surfaces and hairlines, not from glow.
   ============================================================================ */

:root {
  /* ---- ground & surfaces: four deliberate elevations, not ad-hoc greys ---- */
  --bc-bg-0:#060607;                 /* page ground */
  --bc-bg-1:#0b0c0e;                 /* section band */
  --bc-surface-1:#101115;            /* card */
  --bc-surface-2:#16181d;            /* raised card / hover */
  --bc-surface-3:#1d2026;            /* input, well, table header */

  /* ---- borders: hairlines do the structural work ---- */
  --bc-border:rgba(233,230,221,.10);
  --bc-border-strong:rgba(233,230,221,.18);
  --bc-border-accent:rgba(255,60,68,.45);

  /* ---- text ---- */
  --bc-text:#e9e6dd;                 /* bone */
  --bc-text-2:#b9b3a8;
  --bc-text-3:#898376;               /* muted — WCAG AA on every surface above */
  --bc-text-inverse:#0b0c0e;

  /* ---- accents. ONE hot colour, one cool. Everything else is semantic. ---- */
  --bc-accent:#ff3c44;               /* blood — emphasis, active state, focus */
  --bc-accent-deep:#b00710;          /* filled controls (7.3:1 with white) */
  --bc-accent-dim:rgba(255,60,68,.14);
  --bc-steel:#7f93b5;                /* the single cool secondary */
  --bc-steel-dim:rgba(127,147,181,.14);

  /* ---- semantic ---- */
  --bc-ok:#3ddc84; --bc-warn:#f5a524; --bc-bad:#ff4d4f; --bc-info:#5cc8ff;

  /* ---- radius scale ---- */
  --bc-r-xs:3px; --bc-r-sm:6px; --bc-r-md:10px; --bc-r-lg:14px; --bc-r-pill:999px;

  /* ---- spacing scale (4px base) ---- */
  --bc-s-1:4px; --bc-s-2:8px; --bc-s-3:12px; --bc-s-4:16px;
  --bc-s-5:24px; --bc-s-6:32px; --bc-s-7:48px; --bc-s-8:64px;

  /* ---- elevation. Shadows are for depth, never decoration. ---- */
  --bc-e-1:0 1px 2px rgba(0,0,0,.5);
  --bc-e-2:0 4px 14px rgba(0,0,0,.45);
  --bc-e-3:0 12px 34px rgba(0,0,0,.55);
  --bc-focus:0 0 0 3px rgba(255,60,68,.35);

  /* ---- type scale ---- */
  --bc-fs-xs:11px; --bc-fs-sm:13px; --bc-fs-base:15px; --bc-fs-lg:18px;
  --bc-fs-xl:22px; --bc-fs-2xl:28px; --bc-fs-3xl:38px;
  --bc-lh-tight:1.2; --bc-lh:1.6;
  --bc-measure:72ch;                 /* readable line length for prose */

  --bc-motion:180ms cubic-bezier(.4,0,.2,1);

  /* ---- LEGACY ALIASES ------------------------------------------------------
     Every old variable now resolves through the system above, so the two visual
     languages become one without rewriting several thousand existing rules. The
     four that were never defined anywhere are defined here for the first time. */
  --muted:var(--bc-text-3);
  --purple:var(--bc-steel);
  --cyan:var(--bc-steel);
  --brand:var(--bc-accent);
  --text-primary:var(--bc-text);
  --text-secondary:var(--bc-text-2);
  --text-muted:var(--bc-text-3);
  --border:var(--bc-border);
  --border-bright:var(--bc-border-accent);
  --bg-primary:var(--bc-bg-0);
  --bg-secondary:var(--bc-bg-1);
  --bg-card:var(--bc-surface-1);
  --bg-card-hover:var(--bc-surface-2);
  --bg-input:var(--bc-surface-3);
  --success:var(--bc-ok);
  --warning:var(--bc-warn);
  --danger:var(--bc-bad);
  --info:var(--bc-info);
  --shadow-sm:var(--bc-e-1);
  --shadow-md:var(--bc-e-2);
  --shadow-lg:var(--bc-e-3);
}

/* ============================================================================
   COMPONENTS
   Deliberately low-specificity and additive. The goal is depth and hierarchy from
   surface, hairline and weight — not from glow. Every effect below earns its place
   by making structure easier to read; anything that was only there to "look gamer"
   has been left out.
   ============================================================================ */

/* ---- surfaces ------------------------------------------------------------ */
.panel, .card, .seo-callout, .ss-section, .sc-total-display, .guide-section {
  border-radius: var(--bc-r-md);
}
.card, .panel {
  background: linear-gradient(180deg, var(--bc-surface-1), var(--bc-bg-1));
  border: 1px solid var(--bc-border);
  box-shadow: var(--bc-e-1);
  transition: border-color var(--bc-motion), transform var(--bc-motion), box-shadow var(--bc-motion);
}
/* Lift only where a card is actually interactive — a static panel that moves on
   hover is noise, and it was previously applied to both. */
a.card:hover, .card[onclick]:hover, .card[role="button"]:hover, .sphere-card:hover {
  border-color: var(--bc-border-accent);
  box-shadow: var(--bc-e-2);
  transform: translateY(-2px);
}

/* ---- tables: the site is data-heavy, so these matter most ---------------- */
table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
th {
  text-align: left; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  font-size: var(--bc-fs-xs); color: var(--bc-text-2);
  background: var(--bc-surface-3);
  border-bottom: 1px solid var(--bc-border-strong);
  padding: 10px 12px; position: sticky; top: 0; z-index: 2;
}
td { padding: 10px 12px; border-bottom: 1px solid var(--bc-border); vertical-align: top; }
tbody tr { transition: background var(--bc-motion); }
tbody tr:hover { background: rgba(255,255,255,.03); }
tbody tr:last-child td { border-bottom: 0; }
/* Numbers read far faster right-aligned and tabular. */
td:has(> strong:only-child), .num, td.num, th.num { text-align: right; }

/* Wide tables scroll inside their own container, never the page. */
.table-scroll, .max-values-table-wrap, .ss-table-wrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--bc-border); border-radius: var(--bc-r-md);
  background: var(--bc-surface-1);
}
.table-scroll > table, .table-scroll table { margin: 0; }
/* A hairline hint that there is more to the right, which disappears at the end. */
.table-scroll { background-image: linear-gradient(to left, rgba(255,60,68,.10), transparent 34px); background-repeat: no-repeat; background-position: right; background-size: 34px 100%; }

/* ---- buttons ------------------------------------------------------------- */
.btn, button.primary, .btn-primary {
  border-radius: var(--bc-r-sm);
  transition: background var(--bc-motion), border-color var(--bc-motion), transform var(--bc-motion);
}
.btn:hover { border-color: var(--bc-border-accent); }
.btn:active, button:active { transform: translateY(1px); }

/* ---- badges & pills ------------------------------------------------------ */
.badge, .pill, .chip, .mk, .tag {
  border-radius: var(--bc-r-pill);
  font-size: var(--bc-fs-xs); letter-spacing: .03em;
}

/* ---- callouts: one shape, colour carries the meaning --------------------- */
.seo-note, .tip-box, .mistake-box, .ss-callout, .sc-cond-note {
  border-left: 3px solid var(--bc-accent);
  border-radius: 0 var(--bc-r-md) var(--bc-r-md) 0;
  padding: var(--bc-s-3) var(--bc-s-4);
  line-height: var(--bc-lh);
}
.tip-box   { border-left-color: var(--bc-info); }
.mistake-box { border-left-color: var(--bc-bad); }

/* ---- stat emphasis: the number is the message ---------------------------- */
.stat-value, .sc-total-value, .bs-value {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  line-height: var(--bc-lh-tight);
}
.stat-label, .bs-label, .sc-total-label {
  font-size: var(--bc-fs-xs); letter-spacing: .12em; text-transform: uppercase;
  color: var(--bc-text-3);
}

/* ---- prose: cap the measure so long-form guides stay readable ------------ */
.seo-page > p, .guide-section > p, .ss-section > p { max-width: var(--bc-measure); }

/* ---- interaction states -------------------------------------------------- */
a { transition: color var(--bc-motion); }
:focus-visible { outline: 2px solid var(--bc-accent) !important; outline-offset: 2px; box-shadow: var(--bc-focus); }

/* ---- honour reduced motion everywhere ------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; scroll-behavior:auto !important;
  }
  .card:hover, a.card:hover, .sphere-card:hover { transform:none; }
}

/* Empty states should read as a deliberate answer, not a gap in the page. */
/* No opacity fade: it composited --bc-text-3 down to 3.67:1 inside .empty-note.
   The dashed border and wording already read as an empty state. */
.sect.is-empty { }
.empty-note {
  border: 1px dashed var(--bc-border-strong);
  border-radius: var(--bc-r-md);
  padding: var(--bc-s-4);
  color: var(--bc-text-3);
  background: var(--bc-surface-1);
}

/* ============================================================================
   TARGET SIZE — WCAG 2.2 AA (2.5.8 Target Size Minimum, 24x24 CSS px)
   Applied to discrete controls only. Links inline in a sentence are explicitly
   exempted by the success criterion and are left alone, because padding them out
   would wreck the line rhythm of long-form guides for no accessibility gain.
   ============================================================================ */
button,
[role="button"],
input[type="button"], input[type="submit"], input[type="checkbox"], input[type="radio"],
select,
.btn, .chip, .pill, .tab, .char-tab, .rarity-badge, .filter-btn,
.mobile-nav-item, .mobile-menu-item, .sc-add-btn, .sc-remove-btn {
  min-height: 24px;
  min-width: 24px;
}
/* Small chips get their hit area from padding rather than a forced box, so the
   visual size is unchanged while the target grows. */
.chip, .pill, .rarity-badge, .mk { padding-block: 5px; padding-inline: 10px; }

/* Icon-only controls need a real square. */
button:not(:has(> *)):empty, .icon-btn, .close-btn, .mobile-menu-close {
  min-width: 32px; min-height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
}

/* ============================================================================
   MOBILE BOTTOM BAR — usable tap targets
   Pages that hand-roll their own bottom bar were fitting 13 items across a 360px
   phone, giving each a 23px-wide hit area: under the WCAG 2.2 minimum and genuinely
   hard to hit. Give every item a real target and let the bar scroll horizontally
   rather than shrinking items to fit.
   ============================================================================ */
.mobile-nav-inner {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
}
.mobile-nav-inner::-webkit-scrollbar { display: none; }
/* The minimum itself is set at source in styles.css so there is one owner of it;
   this only adds the scroll affordance. */
.mobile-nav-item { scroll-snap-align: start; }
/* Fade the trailing edge so it is obvious there is more to scroll to. */
.mobile-nav::after {
  content: ""; position: absolute; right: 0; top: 0; bottom: 0; width: 26px;
  background: linear-gradient(to left, var(--bc-bg-1), transparent);
  pointer-events: none;
}

/* ============================================================================
   LAYOUT STABILITY (CLS)
   site-header.js replaces an empty <div id="site-header"> placeholder at runtime.
   The placeholder had no height, so every page reflowed the moment the header
   rendered — index.html measured a Cumulative Layout Shift of 0.32, three times the
   0.1 "good" threshold, and the biggest single contributor was the nav appearing.
   Reserving the header's real height removes the jump without changing the design.
   ============================================================================ */
#site-header:empty { display: block; min-height: 61px; }
#site-mobile-nav:empty { display: block; }
@media (max-width: 768px) {
  #site-header:empty { min-height: 97px; }
}
/* The hero image is the other contributor: give it an aspect ratio so the space is
   claimed before the image decodes. */
.reaper-hero { contain-intrinsic-size: auto 420px; }
.reaper-hero > .rh-inner { min-height: 1px; }


/* ---------------------------------------------------------------------------
   Screen-reader-only text. Defined HERE because tokens.css is appended last to
   every page bundle, and .sr-only previously existed only in mobile.css /
   responsive-pro.css — which most pages do not load. Table captions and control
   labels added for the accessibility pass rely on it being present everywhere.
   --------------------------------------------------------------------------- */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border-width:0;
}
/* A skip link is only useful if it appears when it receives focus. */
.sr-only-focusable:focus, .sr-only-focusable:focus-visible{
  position:static; width:auto; height:auto; margin:0; overflow:visible;
  clip:auto; white-space:normal;
}

/* ---------------------------------------------------------------------------
   Sortable / filterable data tables (js/table-tools.js).
   Styled here so the controls inherit the same tokens on every page that opts
   in, rather than each page inventing its own header button.
   --------------------------------------------------------------------------- */
.bc-sort-btn{
  -webkit-appearance:none; appearance:none; background:none; border:0; padding:0;
  font:inherit; color:inherit; letter-spacing:inherit; text-transform:inherit;
  display:inline-flex; align-items:center; gap:6px; width:100%;
  text-align:left; cursor:pointer;
}
.bc-sort-btn:hover .bc-sort-label{ text-decoration:underline; }
/* The arrow is a state readout, so it must not be the ONLY signal — aria-sort on
   the th carries the same information for anyone not looking at the glyph. */
.bc-sort-arrow{ opacity:.45; font-size:.85em; line-height:1; }
.bc-sort-arrow::after{ content:"↕"; }
[aria-sort="ascending"] .bc-sort-arrow{ opacity:1; }
[aria-sort="ascending"] .bc-sort-arrow::after{ content:"↑"; }
[aria-sort="descending"] .bc-sort-arrow{ opacity:1; }
[aria-sort="descending"] .bc-sort-arrow::after{ content:"↓"; }
th[aria-sort="ascending"], th[aria-sort="descending"]{ color:var(--bc-accent, #a78bfa); }

.bc-table-filter{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:14px 0 8px;
}
.bc-table-filter-label{
  font-size:11px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--bc-text-3, #898376); font-weight:700;
}
.bc-table-filter-input{
  flex:1 1 200px; min-width:0; max-width:340px;
  padding:8px 12px; font:inherit; font-size:13px;
  color:var(--bc-text-1, #e9e6dd);
  background:var(--bc-surface-3, rgba(255,255,255,.04));
  border:1px solid var(--bc-border, rgba(233,230,221,.16));
  border-radius:var(--bc-r-sm, 8px);
}
.bc-table-filter-count{
  font-size:11px; letter-spacing:.08em; color:var(--bc-text-3, #898376);
  font-variant-numeric:tabular-nums;
}
@media (max-width:480px){
  .bc-table-filter-input{ max-width:none; }
}

/* A link inside running text must not be identified by colour alone (WCAG 1.4.1).
   The footer "Member Login" link measured 1.11:1 against the sentence around it —
   invisible to anyone who does not perceive that hue difference. Class-bearing links
   (buttons, tiles, nav) opt out, since they carry their own affordance. */
p > a:not([class]), li > a:not([class]), td > a:not([class]) { text-decoration: underline; text-underline-offset: 2px; }

/* ---------------------------------------------------------------------------
   Sphere input + its "copy to all matching slots" button (public/sphere-system.js).
   Neither class had a single CSS rule anywhere, so the button rendered as a raw
   user-agent control — a light-grey box below each field on a black page. It sits
   inside the field's right edge, where it belongs.
   --------------------------------------------------------------------------- */
.sphere-input-wrapper{ position:relative; display:block; }
.sphere-input-wrapper > .sphere-input-enhanced{ padding-right:40px; margin-bottom:0; display:block; }
.sphere-copy-btn{
  position:absolute; top:50%; right:6px; transform:translateY(-50%);
  -webkit-appearance:none; appearance:none;
  width:28px; height:28px; padding:0; line-height:1;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:14px; cursor:pointer;
  background:var(--bc-surface-2, rgba(255,255,255,.06));
  border:1px solid var(--bc-border, rgba(233,230,221,.16));
  border-radius:var(--bc-r-sm, 6px);
  color:var(--bc-text-2, #cfcabc);
  opacity:.65; transition:opacity .15s ease, border-color .15s ease, background .15s ease;
}
.sphere-copy-btn:hover, .sphere-copy-btn:focus-visible{
  opacity:1; background:var(--bc-surface-3, rgba(255,255,255,.10));
  border-color:var(--bc-border-accent, rgba(255,37,48,.45));
}
