/* ============================================================
   WR EVENT DESIGN SYSTEM - component layer
   Every value here reads from a token custom property set by
   ds.js applyTheme(). No component knows any event's name.
   ============================================================ */

@font-face {
  font-family: 'Serpentine Sans ICG';
  src: url('fonts/SerpentineSansICG-Regular.ttf') format('truetype');
  font-display: block;
}
@font-face {
  font-family: 'Beaufort for LOL';
  src: url('fonts/BeaufortforLOL-Medium.ttf') format('truetype');
  font-weight: 500;
  font-display: block;
}
@font-face {
  font-family: 'Beaufort for LOL';
  src: url('fonts/BeaufortforLOL-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: block;
}
@font-face {
  font-family: 'Beaufort for LOL';
  src: url('fonts/BeaufortforLOL-Heavy.ttf') format('truetype');
  font-weight: 900;
  font-display: block;
}

.ds-scope {
  --ds-primary:#FF5133; --ds-accent:#FFE177; --ds-secondary:#FF9908;
  --ds-surface:#131629; --ds-surface-alt:#080B25; --ds-text:#FFFAE9; --ds-muted:#97A1A5;
  --ds-node-radius:50%; --ds-ring-w:2px; --ds-glow:0 0 14px;
  --ds-frame-a:#FF9908; --ds-frame-b:#080B25;
  --ds-motif-a:#080B25; --ds-motif-b:#080B25;
  --ds-motif-stroke: color-mix(in srgb, var(--ds-text) 55%, transparent);
  --ds-ring: color-mix(in srgb, var(--ds-text) 45%, transparent);
  --ds-motif-shape:none; --ds-motif-o:.55;
  --ds-display:Archivo; --ds-body:Archivo; --ds-tracking:.1em; --ds-case:uppercase;
  --ds-dur:320ms;
  --ds-node-size:64px;
  color: var(--ds-text);
  font-family: var(--ds-body), system-ui, sans-serif;
}

/* ---- motif on/off (paths themselves live in shapes.js) ---- */
.ds-shape-on   { --ds-motif-o: .92; }
.ds-shape-none { --ds-motif-o: 0; }

/* ============================ NODE ============================
   frame (div: shape + ring + glow) > motif (svg, stroked) > payload > count */
.ds-node {
  position: relative;
  width: var(--ds-node-size);
  height: var(--ds-node-size);
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  transition: transform var(--ds-dur) ease, filter var(--ds-dur) ease;
  /* Effective values. States remap these to their token override when the
     event ships one (--ds-st-*), and fall back to the shared defaults. */
  --ds-frame-bg-eff: linear-gradient(180deg, var(--ds-frame-a), var(--ds-frame-b));
  --ds-ring-eff: var(--ds-ring);
  --ds-ring-img-eff: none;
  --ds-ink-eff: var(--ds-text);
  --ds-corner-eff: var(--ds-accent);
  --ds-motif-a-eff: var(--ds-motif-a);
  --ds-motif-b-eff: var(--ds-motif-b);
  --ds-motif-stroke-eff: var(--ds-motif-stroke);
}
/* A diamond node is the square frame rotated (SOL: rotate 45deg). The inset
   pulls the square in first so the rotated corners land exactly on the box
   edges - the footprint never grows. Motif, payload and count stay upright. */
.ds-node__frame {
  position: absolute; inset: var(--ds-frame-inset, 0);
  border-radius: var(--ds-node-radius);
  background: var(--ds-frame-bg-eff);
  border: var(--ds-ring-w) solid var(--ds-ring-eff);
  /* Gradient ring (SOL claimable): border-image only works at radius 0,
     so events with a radius keep their solid ring untouched. */
  border-image: var(--ds-ring-img-eff);
  box-shadow: 0 0 0 transparent;
  transform: rotate(var(--ds-frame-rotate, 0deg));
  transition: box-shadow var(--ds-dur) ease, border-color var(--ds-dur) ease, background var(--ds-dur) ease;
}
.ds-base {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  opacity: var(--ds-motif-o);
  transition: opacity var(--ds-dur) ease;
}
.ds-base__motif-grad {
  stroke: var(--ds-motif-stroke-eff);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.ds-base__motif-corner { fill: var(--ds-corner-eff); }
.ds-base__motif-pupil  { fill: var(--ds-pupil-eff, transparent); }
.ds-base__motif-ink    { fill: var(--ds-ink-eff); }

/* Motif layers gated to specific states (SOL: gold diamond on claimed and
   locked, offset deco squares on claimable). Hidden everywhere else. */
.ds-base .ds-only { display: none; }
.ds-node.is-claimed   .ds-only-claimed,
.ds-node.is-claimable .ds-only-claimable,
.ds-node.is-locked    .ds-only-locked { display: inline; }

/* No shadow here: event icons carry their own inline glow/shadow effects.
   48.5% = the 34px slot on the 70px Figma node, the fit Ke approved.
   The svg is absolutely positioned: as a grid item its percentage height
   could not resolve against the auto row, so tall icons sized themselves
   by viewBox aspect and overflowed the box (the giant lock). */
.ds-node__payload {
  position: relative; z-index: 2;
  width: 48.5%; height: 48.5%;
  color: var(--ds-ink-eff);
}
.ds-node__payload img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ds-node__payload svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ds-node__payload svg path:not([fill]) { fill: currentColor; }
.ds-node__count {
  position: absolute; z-index: 3;
  right: 7%; bottom: 4%;
  font-family: var(--ds-body), sans-serif;
  font-size: calc(var(--ds-node-size) * .2);
  font-weight: 700;
  color: var(--ds-ink-eff);
  text-shadow: 0 1px 2px rgba(0,0,0,.3);
}

/* ---- states ----
   Shared rules; a token states block re-skins any of them per event. */
.ds-node.is-claimed {
  --ds-frame-bg-eff: var(--ds-st-claimed-bg, linear-gradient(180deg, var(--ds-frame-a), var(--ds-frame-b)));
  --ds-ring-eff: var(--ds-st-claimed-ring, var(--ds-ring));
  --ds-ink-eff: var(--ds-st-claimed-ink, var(--ds-text));
  --ds-corner-eff: var(--ds-st-claimed-corner, var(--ds-accent));
  --ds-motif-a-eff: var(--ds-st-claimed-motif-a, var(--ds-motif-a));
  --ds-motif-b-eff: var(--ds-st-claimed-motif-b, var(--ds-motif-b));
  --ds-motif-stroke-eff: var(--ds-st-claimed-motif-stroke, var(--ds-motif-stroke));
  --ds-pupil-eff: var(--ds-st-claimed-pupil, transparent);
}

.ds-node.is-claimable {
  --ds-frame-bg-eff: var(--ds-st-claimable-bg, linear-gradient(180deg, var(--ds-frame-a), var(--ds-frame-b)));
  --ds-ring-eff: var(--ds-st-claimable-ring, var(--ds-accent));
  --ds-ring-img-eff: var(--ds-st-claimable-ring-img, none);
  --ds-ink-eff: var(--ds-st-claimable-ink, var(--ds-text));
  --ds-corner-eff: var(--ds-st-claimable-corner, var(--ds-accent));
  --ds-motif-a-eff: var(--ds-st-claimable-motif-a, var(--ds-motif-a));
  --ds-motif-b-eff: var(--ds-st-claimable-motif-b, var(--ds-motif-b));
  --ds-motif-stroke-eff: var(--ds-st-claimable-motif-stroke, var(--ds-motif-stroke));
  --ds-pupil-eff: var(--ds-st-claimable-pupil, transparent);
}
.ds-node.is-claimable .ds-node__frame {
  border-width: var(--ds-ring-w-active, calc(var(--ds-ring-w) * 1.6));
  box-shadow: var(--ds-glow) color-mix(in srgb, var(--ds-accent) 45%, white);
}
/* the reward reads bigger than the glyph icons */
.ds-node.is-claimable .ds-node__payload { width: 62%; height: 62%; }

.ds-node.is-locked {
  --ds-frame-bg-eff: var(--ds-st-locked-bg, linear-gradient(180deg, var(--ds-frame-a), var(--ds-frame-b)));
  --ds-ring-eff: var(--ds-st-locked-ring, var(--ds-ring));
  --ds-ink-eff: var(--ds-st-locked-ink, var(--ds-text));
  --ds-corner-eff: var(--ds-st-locked-corner, var(--ds-accent));
  --ds-motif-a-eff: var(--ds-st-locked-motif-a, var(--ds-motif-a));
  --ds-motif-b-eff: var(--ds-st-locked-motif-b, var(--ds-motif-b));
  --ds-motif-stroke-eff: var(--ds-st-locked-motif-stroke, var(--ds-motif-stroke));
  --ds-pupil-eff: var(--ds-st-locked-pupil, transparent);
}

.ds-node.is-story .ds-node__frame,
.ds-node.is-game  .ds-node__frame { border-color: var(--ds-accent); }

.ds-node.is-major { --ds-node-size: calc(var(--ds-track-size, 64px) * 1.8); }

/* ---- combat node (event extra, Soul Fighter) ----
   Taller silhouette; fills are pure semantics so it is theme-portable:
   lit = text on secondary flipped, dim = the inverse. */
/* Footprint = the square body, same as every node. The number tab
   overflows above it, the sub-fight diamonds hang below it, so combat
   bottoms align with the other squares in any row. */
.ds-node.is-combat { height: var(--ds-node-size); overflow: visible; }
.ds-combat {
  position: absolute;
  left: 0; top: calc(var(--ds-node-size) * -0.323);
  width: 100%; height: calc(var(--ds-node-size) * 1.443);
  display: block; overflow: visible;
}
.ds-combat .cb-bg     { stroke: var(--ds-muted); stroke-width: 1; }
.ds-combat .cb-tab    { stroke: var(--ds-muted); stroke-width: 1; }
.ds-combat .cb-slot   { stroke: var(--ds-muted); stroke-width: 1; fill: var(--ds-secondary); }
.ds-combat .cb-slot.is-first { fill: var(--ds-text); }
.ds-combat .cb-index  {
  font-family: var(--ds-display), sans-serif;
  font-size: 12px; letter-spacing: .04em;
}
.ds-node.is-combat.is-lit .cb-bg,
.ds-node.is-combat.is-lit .cb-tab    { fill: var(--ds-text); }
.ds-node.is-combat.is-lit .cb-ink    { fill: var(--ds-secondary); }
.ds-node.is-combat.is-lit .cb-index  { fill: var(--ds-secondary); }
.ds-node.is-combat.is-lit .cb-corner { fill: var(--ds-accent); }
.ds-node.is-combat.is-dim .cb-bg     { fill: var(--ds-secondary); }
.ds-node.is-combat.is-dim .cb-tab    { fill: transparent; }
.ds-node.is-combat.is-dim .cb-ink    { fill: var(--ds-text); }
.ds-node.is-combat.is-dim .cb-index  { fill: var(--ds-text); }
.ds-node.is-combat.is-dim .cb-corner { fill: var(--ds-muted); }


/* ---- lantern node (event extra, Sentinels of Light) ----
   A hanging lamp: tassels behind, ornate body, light face, flame, index.
   Fills are pure semantics so it is theme-portable. Footprint = the node
   box, top-aligned; the tassels hang below it (combat's rule mirrored). */
.ds-node.is-lantern { overflow: visible; }
.ds-lantern {
  position: absolute;
  left: 1.55%; top: 0;
  width: 96.9%; height: calc(var(--ds-node-size) * 1.242);
  display: block; overflow: visible;
}
.ds-lantern .ln-chain { stroke: var(--ds-muted); fill: none; }
.ds-lantern .ln-body  { fill: var(--ds-secondary); stroke: var(--ds-primary); stroke-width: 2; }
.ds-lantern .ln-face  { fill: var(--ds-text); stroke: var(--ds-primary); }
.ds-lantern .ln-gold  { fill: var(--ds-primary); stroke: var(--ds-primary); }
.ds-lantern .ln-index {
  fill: var(--ds-secondary);
  font-family: var(--ds-display), serif;
  font-weight: 900; font-size: 20px;
}

/* ---- game icon: gradient blade (Ke's spec, 2026-08-25) ----
   Top sword: --ds-primary -> --ds-text 50% along the blade, 1px stroke,
   0/4/4 shadow in --ds-surface-alt. Both swords carry the shadow. */
.ds-swords { overflow: visible; }
.ds-swords__under {
  fill: var(--ds-text);
  filter: drop-shadow(0 4px 4px var(--ds-surface-alt));
}
.ds-swords__top {
  stroke: var(--ds-text);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 4px 4px var(--ds-surface-alt));
}

/* ============================ TRACK ============================ */
.ds-track {
  --ds-track-size: var(--ds-node-size);
  display: flex; align-items: center; width: 100%;
}
.ds-connector {
  flex: 1 1 auto;
  height: 2px; min-width: 12px;
  background: color-mix(in srgb, var(--ds-text) 14%, transparent);
  transition: background var(--ds-dur) ease;
}
.ds-connector.is-filled { background: color-mix(in srgb, var(--ds-primary) 85%, transparent); }

/* ============================ CHAMPION ROW ============================ */
.ds-champs { display: flex; align-items: center; gap: 10px; }
.ds-champ { position: relative; width: 46px; height: 46px; flex: 0 0 auto; }
.ds-champ__portrait {
  position: absolute; inset: 0;
  border-radius: var(--ds-node-radius);
  border: 2px solid color-mix(in srgb, var(--ds-text) 80%, transparent);
  background: color-mix(in srgb, var(--ds-secondary) 45%, var(--ds-surface-alt));
  overflow: hidden;
}
.ds-champ__portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Clipped portrait (champBadge.clip): the shape comes from an SVG clipPath
   in shapes.js, the ring and inspection square from the decor layer. */
.ds-champ__portrait.is-clipped { border: none; border-radius: 0; background: none; }
/* No z-index: the decor comes before the portrait in the DOM, so the
   portrait covers it - the lines only peek past the picture's edge. */
.ds-champ__decor { position: absolute; inset: 0; pointer-events: none; }
.ds-champ__decor svg { display: block; width: 100%; height: 100%; overflow: visible; }
/* Index badge: the event's exact star (SVG, from shapes.js) with the digit
   layered above it. Sized a touch larger than the old clip badge so the
   star's points have room to read. */
.ds-champ__index {
  position: absolute; z-index: 2;
  left: -9px; bottom: -9px;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  color: var(--ds-text);
  font-size: 11px; font-weight: 700;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0,0,0,.55);
}
.ds-champ__index svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.ds-champ__index > span { position: relative; z-index: 1; }
/* SF-style badge: centered plate hanging off the bottom edge, display face */
.ds-champ__index.is-center {
  left: 50%; bottom: -10px;
  transform: translateX(-50%);
  width: 27px; height: 19px;
}
.ds-champ__index.is-display > span {
  font-family: var(--ds-display), sans-serif;
  font-size: 9px; font-weight: 400;
  letter-spacing: .02em;
}
/* SOL-style badge: index circle centered on the bottom edge */
.ds-champ__index.is-bottom {
  left: 50%; bottom: -11px;
  transform: translateX(-50%);
  width: 20px; height: 20px;
}
.ds-champ__index.is-bottom.is-display > span { font-size: 10px; font-weight: 700; }

/* ============================ CHROME ============================ */
.ds-header { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }
.ds-title {
  font-family: var(--ds-display), Georgia, serif;
  font-weight: 700;
  letter-spacing: var(--ds-tracking);
  text-transform: var(--ds-case);
  color: var(--ds-accent);
  transition: color var(--ds-dur) ease, letter-spacing var(--ds-dur) ease;
}
.ds-dates { font-size: 12px; letter-spacing: .1em; color: var(--ds-primary); }
.ds-tabs {
  display: flex; gap: 28px;
  padding-bottom: 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--ds-text) 18%, transparent);
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: color-mix(in srgb, var(--ds-text) 45%, transparent);
}
.ds-tabs .is-on { color: var(--ds-accent); }
.ds-caption { font-size: 12px; color: color-mix(in srgb, var(--ds-text) 62%, transparent); }

/* ============================ SURFACE ============================ */
.ds-surface {
  background: var(--ds-surface);
  transition: background var(--ds-dur) ease;
}

@media (prefers-reduced-motion: reduce) {
  .ds-node, .ds-node__frame, .ds-connector, .ds-title, .ds-surface { transition: none; }
}
