/* The Ladder (public/ladder.js): the rank tiers on the rim of a wheel, centered, with no frame. Its dark field and the
   focused tier's glow sit in the page's own background and fade out at every edge, so the wheel reads as something in
   the room rather than a card on it. Every row is placed from one number, --focus, set on .ladder: its distance from
   the row's own index (--i) turns it round the wheel, shrinks, dims and softens it. The glow is the only glow, and it
   is the focused tier's own (--ladder-glow, read from ranks.css). Your standing adds a short note either side.
   Loaded on its own by the front page, so every token has a fallback. */
@property --ladder-glow { syntax: '<color>'; inherits: true; initial-value: transparent; }
@property --focus { syntax: '<number>'; inherits: true; initial-value: 0; }

.ladder {
  --row-h: 46px;
  position: relative; isolation: isolate; display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 360px) minmax(0, 1fr);
  grid-template-areas: "left wheel right"; height: clamp(340px, 46vh, 440px); color: var(--text); color-scheme: dark;
  transition: --ladder-glow 700ms var(--ease, ease);
}
/* The field: a faint nebula in the player's own color (--accent): a few clouds of it and of its lighter partner, a slow
   swirl through them, a darker lane, and a small light of the focused tier just behind its plaque, all under a fine
   grain so the dark never bands. It is feathered into the page all round, with no edge of its own, and turns very
   slowly; reduced motion holds it still. */
.ladder::before { content: ""; position: absolute; inset: -14% -8%; z-index: -1; pointer-events: none;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(14% 20% at 50% 50%, color-mix(in srgb, var(--ladder-glow) 22%, transparent), transparent 100%),
    radial-gradient(24% 32% at 38% 40%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 100%),
    radial-gradient(18% 26% at 64% 60%, color-mix(in srgb, var(--accent-2, var(--accent)) 14%, transparent), transparent 100%),
    radial-gradient(12% 16% at 57% 30%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 100%),
    radial-gradient(30% 9% at 45% 66%, color-mix(in srgb, var(--sea-deep) 70%, transparent), transparent 100%),
    conic-gradient(from 150deg at 51% 49%, transparent 0 8%, color-mix(in srgb, var(--accent) 9%, transparent) 17%, transparent 29% 52%,
      color-mix(in srgb, var(--accent-2, var(--accent)) 7%, transparent) 63%, transparent 75%),
    radial-gradient(46% 54% at 50% 50%, color-mix(in srgb, var(--sea-deep) 55%, transparent) 0 30%, transparent 100%);
  background-size: 180px 180px, auto, auto, auto, auto, auto, auto, auto;
  background-blend-mode: soft-light, normal, normal, normal, normal, normal, normal, normal;
  opacity: .8;
  -webkit-mask-image: radial-gradient(closest-side, black 35%, transparent); mask-image: radial-gradient(closest-side, black 35%, transparent);
  animation: ladder-nebula 70s var(--ease-in-out, ease-in-out) infinite alternate; }
@keyframes ladder-nebula { from { transform: rotate(-4deg) scale(1); } to { transform: rotate(4deg) scale(1.07); } }
:root.reduce-motion .ladder::before { animation: none; }

/* The wheel, with an eye line through its middle: the height every tier comes level with at the front. Its top and
   bottom fade, so tiers turn away into the dark rather than off an edge. A mask clips to the wheel's own box, so the box
   reaches --wheel-bleed past the column on each side (the rows keep their place): the focused card's glow, and the
   Emperor's crown, fade out in the room instead of stopping at a straight edge. The notes either side sit above it. */
.ladder { --wheel-bleed: 44px; }
.ladder-side { position: relative; z-index: 1; }
.ladder-wheel { grid-area: wheel; position: relative; margin: 0 calc(var(--wheel-bleed) * -1); padding: 0; list-style: none; perspective: 900px; transform-style: preserve-3d;
  cursor: grab; touch-action: none; user-select: none; outline: 0;
  -webkit-mask-image: linear-gradient(transparent, black 14%, black 86%, transparent); mask-image: linear-gradient(transparent, black 14%, black 86%, transparent); }
.ladder::after { content: ""; position: absolute; inset-inline: 12%; top: 50%; height: 1px; z-index: -1; pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ladder-glow) 70%, transparent) 30% 70%, transparent); opacity: .55; }
.ladder-wheel:active { cursor: grabbing; }
/* Keyboard focus marks the tier in focus, not the whole wheel. */
.ladder .ladder-wheel:focus-visible { outline: none; }
.ladder-wheel:focus-visible .ladder-row.on { outline: 2px solid var(--accent); outline-offset: 3px; }
.ladder-row {
  --d: calc(var(--i) - var(--focus));
  --ad: max(var(--d), calc(var(--d) * -1));
  position: absolute; inset-inline: calc(var(--space-6, 12px) + var(--wheel-bleed)); top: 50%; height: var(--row-h); margin-top: calc(var(--row-h) / -2);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4, 8px); padding: 0 var(--space-7, 14px);
  border: 1px solid color-mix(in srgb, var(--rank-edge) 38%, transparent); border-radius: var(--radius, 7px);
  background: var(--rank-texture, none), var(--rank-base);
  color: var(--rank-ink); font: 700 var(--fs-xl, 18px)/1 var(--font-head); letter-spacing: .06em; text-transform: uppercase;
  transform: translateZ(calc(var(--wheel-r, 160px) * -1)) rotateX(calc(var(--d) * 17deg)) translateZ(var(--wheel-r, 160px));
  opacity: clamp(0, calc(1 - var(--ad) * .2 + var(--lean, 0)), 1);
  /* Out of focus a tier's card is dulled: its colors drained and darkened, softer the further round it is. */
  filter: saturate(.5) brightness(.62) blur(calc(max(var(--ad) - 1.4, 0) * .6px));
  backface-visibility: hidden; will-change: transform, opacity;
  transition: color var(--dur, 160ms) var(--ease, ease), font-size var(--dur-slow, 260ms) var(--ease, ease);
}
.ladder-band { font: 600 var(--fs-xs, 11px) var(--font-ui); letter-spacing: 0; text-transform: none; color: var(--text-3); white-space: nowrap; }
.ladder-row.near { --lean: .3; filter: saturate(.8) brightness(.85); }
/* The tier in focus is its rank card: its texture, edge and sheen, one card at a time. */
.ladder-row.on { height: calc(var(--row-h) + 16px); margin-top: calc((var(--row-h) + 16px) / -2); color: var(--rank-ink);
  font-size: var(--fs-3xl, 24px); box-shadow: 0 12px 34px rgb(0 0 0 / .5); filter: none; }
.ladder-row.on .ladder-band { color: var(--rank-ink); opacity: .85; }
/* The player's own tier carries a mark on the rim while the wheel is turned elsewhere. */
.ladder-row.home:not(.on)::before { content: ""; position: absolute; left: calc(var(--space-4, 8px) * -1); top: 50%; width: 5px; height: 5px; margin-top: -2.5px;
  border-radius: 50%; background: var(--accent); }

/* Turned away from the player's tier, a chip under the wheel turns it back. */
.ladder-back { grid-area: wheel; align-self: end; justify-self: center; z-index: 1; margin-bottom: var(--space-2, 4px); min-height: 32px; padding: 0 var(--space-7, 14px);
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill, 999px); background: rgb(0 0 0 / .45); color: var(--text-2);
  font: 600 var(--fs-sm, 12px) var(--font-ui); cursor: pointer; transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.ladder-back:hover { color: var(--text); border-color: var(--accent); }
.ladder-back[hidden] { display: none; }
.ladder-said { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }

/* Your standing's notes either side of the wheel: your place on the left (a way to the Leaderboard), where you are going
   on the right. They
   dim while the wheel is turned to another tier, since they are about yours. */
.ladder-side { align-self: center; display: grid; gap: var(--space-2, 4px); min-width: 0; transition: opacity var(--dur-slow, 260ms) var(--ease, ease); }
.ladder-left { grid-area: left; justify-items: end; text-align: right; padding-right: var(--space-14, 28px); }
.ladder-place { display: grid; justify-items: end; gap: var(--space-2, 4px); padding: var(--space-4, 8px) var(--space-6, 12px); margin-right: calc(var(--space-6, 12px) * -1);
  border: 0; border-radius: var(--radius, 7px); background: none; color: inherit; font: inherit; text-align: right; cursor: pointer;
  transition: background var(--dur, 160ms) var(--ease, ease); }
.ladder-place:hover { background: rgb(255 255 255 / .04); }
.ladder-place:hover .ladder-kicker:first-child::after { content: " \2192 Leaderboard"; color: var(--text-2); }
.ladder-right { grid-area: right; justify-items: start; padding-left: var(--space-14, 28px); }
/* Turned to another tier, the notes are about that tier instead, set a little quieter. */
.ladder.away .ladder-figure { color: var(--text-2); }
.ladder-kicker { font: 650 var(--fs-xs, 11px) var(--font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); }
.ladder-figure { font: 800 clamp(40px, 4vw, 58px)/1 var(--font-head); font-variant-numeric: tabular-nums; color: var(--text); }
.ladder-figure-sm { font-size: clamp(26px, 2.4vw, 34px); }
.ladder-unit { margin-top: calc(var(--space-2, 4px) * -1); color: var(--text-2); font-weight: 600; }
.ladder-fact { color: var(--text-2); font-size: var(--fs-md, 13px); }
.ladder-fact b { color: var(--text); font-variant-numeric: tabular-nums; }
.ladder-left .ladder-fact:first-of-type { margin-top: var(--space-4, 8px); }
.ladder-next-name { font: 700 clamp(26px, 2.6vw, 36px)/1 var(--font-head); letter-spacing: .04em; text-transform: uppercase; color: var(--rank-edge); }
/* The tier's name borrows its colors from the tier's class, and only its colors: the Emperor's class also brings the
   card's drifting particles, which on an unpositioned name spread over the whole Ladder. */
.ladder-next-name.ladder-next-name::before, .ladder-next-name.ladder-next-name::after { content: none; }
/* How far through the current tier: the player's color filling toward the next. */
.ladder-meter { position: relative; width: min(180px, 100%); height: 4px; margin: var(--space-4, 8px) 0 var(--space-1, 2px); border-radius: 4px; background: rgb(255 255 255 / .1); overflow: hidden; }
.ladder-meter i { position: absolute; inset: 0 auto 0 0; width: calc(var(--p, 0) * 100%); border-radius: inherit; background: var(--accent); }

/* Calmer: the rows lie flat, one above another, dimmed by distance; nothing turns. */
:root.reduce-motion .ladder-row { transform: translateY(calc(var(--d) * var(--row-h) * -1.08)); filter: none; transition: none; }
:root.reduce-motion .ladder { transition: none; }

/* Narrow screens: the notes go under the wheel, side by side. */
@media (max-width: 860px) {
  .ladder { --wheel-bleed: 0px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "wheel wheel" "left right"; grid-template-rows: 320px auto; height: auto; }
  .ladder-left, .ladder-right { padding: var(--space-6, 12px); }
}
