/* -----------------------------------------------------------------------------
   VALEON — leaderboards
   The phone is the system of record (v0.6 §3.3); this page publishes what the
   phones sent up.

   §9 holds: the chrome here is desaturated, thin and technical. The only family
   colour on the page is in the Community breakdown, where the seven families
   are the subject rather than the decoration — the same exemption the family
   cards get.
   -------------------------------------------------------------------------- */

.lb-hero {
  padding: var(--space-8) 0 var(--space-6);
  text-align: center;
}
.lb-hero h1 { margin-bottom: var(--space-3); }
.lb-hero p {
  max-width: 620px;
  margin: 0 auto;
  color: var(--ink-mid);
}

.lb-panel {
  padding-bottom: var(--space-9);
  position: relative;
}

/* A soft pool behind the board, the same device MenuChrome.Backdrop() uses in
   the game and .hero::before uses on the landing page.
   Without it the drifting shards pass straight through a data table, and a
   ranked list is the one surface on this site where legibility outranks
   spectacle (§9 - the UI is an instrument panel, not part of the show). */
.lb-panel::before {
  content: "";
  position: absolute;
  inset: -2% -4% -1%;
  background: radial-gradient(ellipse 70% 60% at 50% 45%, rgba(5, 8, 18, 0.88), transparent 78%);
  pointer-events: none;
  z-index: -1;
}

/* ----- Controls: tabs on the left, level picker on the right ------------- */
.lb-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.lb-tabs {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.lb-tab {
  padding: 0.5rem 1rem;
  border: 1px solid var(--grid-line-warm);
  border-radius: var(--radius-2);
  background: transparent;
  color: var(--ink-mid);
  font-family: var(--font-display);
  letter-spacing: var(--track-wide);
  font-size: 0.82rem;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--dur-1) var(--ease-out),
              border-color var(--dur-1) var(--ease-out),
              background var(--dur-1) var(--ease-out);
}
.lb-tab:hover { color: var(--ink-hi); border-color: var(--ink-mid); }

/* Keyed off aria-selected rather than a class, so the styling cannot drift
   away from what assistive technology is being told. */
.lb-tab[aria-selected="true"] {
  color: var(--cryo);
  border-color: var(--cryo);
  background: rgba(51, 230, 255, 0.06);
}
/* A visible focus ring is not optional once arrow keys move focus between
   tabs — without it a keyboard user cannot see where they are. */
.lb-tab:focus-visible {
  outline: 2px solid var(--cryo);
  outline-offset: 2px;
}

.lb-level {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.lb-level label {
  font-family: var(--font-display);
  font-size: 0.72rem;
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  color: var(--ink-lo);
}
.lb-level select {
  appearance: none;
  padding: 0.5rem 2.2rem 0.5rem 0.85rem;
  border: 1px solid var(--grid-line-warm);
  border-radius: var(--radius-2);
  background-color: rgba(14, 22, 38, 0.6);
  color: var(--ink-hi);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  cursor: pointer;
  /* Inline chevron — an external asset for a 10px triangle is not worth a
     request, and this one inherits the text colour. */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23A8B0C7' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.85rem center;
  background-size: 10px 6px;
}
.lb-level select:hover { border-color: var(--ink-mid); }
.lb-level select:focus-visible { outline: 2px solid var(--cryo); outline-offset: 2px; }
.lb-level[hidden] { display: none; }

.lb-blurb {
  color: var(--ink-lo);
  font-size: 0.88rem;
  margin: 0 0 var(--space-5);
}

/* ----- Status ------------------------------------------------------------ */
.lb-status {
  max-width: 720px;
  margin: 0 auto var(--space-6);
  text-align: center;
  padding: var(--space-6);
  border: 1px dashed var(--grid-line-warm);
  border-radius: var(--radius-3);
  color: var(--ink-mid);
}
.lb-status.err { color: var(--plasma); border-color: rgba(255, 41, 140, 0.4); }
.lb-status .k {
  font-family: var(--font-display);
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  font-size: 0.72rem;
  color: var(--ink-lo);
  margin-bottom: var(--space-2);
}

/* ----- Ranked table ------------------------------------------------------ */
.lb-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: 0.9rem;
  /* Fixed layout so the columns are sized by these rules rather than by
     whatever the longest player name happens to be. It is also what makes
     ellipsis truncation work on a td at all: under `auto` layout a cell
     grows to fit its content and the overflow rules never engage. */
  table-layout: fixed;
}
.lb-table th.lb-rank,  .lb-table td.lb-rank  { width: 64px; }
.lb-table th.lb-value, .lb-table td.lb-value { width: 8.5rem; }
.lb-table th, .lb-table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--grid-line);
}
.lb-table th {
  font-family: var(--font-display);
  font-size: 0.72rem;
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  color: var(--ink-lo);
  white-space: nowrap;
}
.lb-table tbody tr { transition: background var(--dur-1) var(--ease-out); }
.lb-table tbody tr:hover { background: rgba(51, 230, 255, 0.04); }

.lb-table td.lb-rank {
  color: var(--ink-lo);
  width: 64px;
  font-variant-numeric: tabular-nums;
}
/* The podium stays desaturated — §9. Rank reads through brightness and weight,
   not through colour, which is what the rest of the UI does too. */
.lb-table td.lb-rank-1 { color: var(--quantum); text-shadow: 0 0 12px rgba(240, 245, 255, 0.45); font-weight: 700; }
.lb-table td.lb-rank-2 { color: var(--ink-hi); font-weight: 700; }
.lb-table td.lb-rank-3 { color: var(--ink-mid); font-weight: 700; }

.lb-table td.lb-player {
  color: var(--ink-hi);
  /* Names are player-supplied and arbitrary length; truncate rather than let
     one push the value column off a phone. Works because the table is
     table-layout: fixed — see above. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lb-table th.lb-value, .lb-table td.lb-value {
  text-align: right;
  color: var(--cryo);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ----- Community --------------------------------------------------------- */
.lb-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}
.lb-stat {
  padding: var(--space-5);
  border-left: 2px solid var(--cryo);
  background: rgba(14, 22, 38, 0.35);
  border-radius: 0 var(--radius-2) var(--radius-2) 0;
}
.lb-stat .k {
  font-family: var(--font-display);
  font-size: 0.72rem;
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  color: var(--ink-lo);
  margin-bottom: var(--space-2);
}
.lb-stat .v {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--ink-hi);
  letter-spacing: var(--track-wide);
  font-variant-numeric: tabular-nums;
}

.lb-subhead {
  font-size: 0.86rem;
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  color: var(--ink-mid);
  margin-bottom: var(--space-5);
}

.lb-families {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.lb-family {
  display: grid;
  grid-template-columns: 34px 110px 1fr auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--grid-line);
  border-radius: var(--radius-3);
  background: rgba(14, 22, 38, 0.3);
  transition: border-color var(--dur-2) var(--ease-out);
}
.lb-family:hover { border-color: color-mix(in oklab, var(--_glow) 45%, transparent); }
.lb-family-icon svg.shard { width: 30px; height: 30px; overflow: visible; }
.lb-family-name {
  font-family: var(--font-display);
  font-size: 0.78rem;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--_glow, var(--ink-hi));
}
.lb-family-bar {
  height: 6px;
  background: var(--grid-line);
  border-radius: 3px;
  overflow: hidden;
}
.lb-family-fill {
  height: 100%;
  min-width: 2px;
  background: var(--_glow, var(--cryo));
  box-shadow: 0 0 12px color-mix(in oklab, var(--_glow, var(--cryo)) 60%, transparent);
  transition: width var(--dur-4) var(--ease-out);
}
.lb-family-count {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--ink-mid);
  font-variant-numeric: tabular-nums;
  min-width: 5ch;
  text-align: right;
}

/* ----- Narrow ------------------------------------------------------------ */
@media (max-width: 640px) {
  .lb-controls { flex-direction: column; align-items: stretch; }
  .lb-level { justify-content: space-between; }
  .lb-table th, .lb-table td { padding: var(--space-3) var(--space-2); }
  .lb-table td.lb-rank { width: 44px; }

  /* The bar is the first thing worth losing — the number carries the same
     information and the name must not truncate to nothing. */
  .lb-family { grid-template-columns: 28px 1fr auto; }
  .lb-family-bar { display: none; }
  .lb-family-icon svg.shard { width: 24px; height: 24px; }
}

/* ==========================================================================
   Your stats — the signed-in panel above the boards.

   Deliberately the same furniture as the boards below it (.lb-panel, .lb-table,
   .lb-status) rather than a second visual language, because it is the same kind
   of thing seen from one player's side. What separates them is the heading and
   the totals grid; everything else is shared, which is also why this section is
   short.
   ========================================================================== */
.lb-me {
  padding-bottom: var(--space-7);
}

/* [hidden] has to win here, and by default it does not.
   The UA sheet says [hidden] { display: none }, which is a plain element-level
   rule - so any class that sets display beats it. Three things in this panel do
   exactly that: .btn is inline-flex, .lb-me-totals is grid and .lb-me-levels is
   block. The result was a Sign out button and an empty per-level table both
   sitting on screen while signed OUT, with the hidden attribute set correctly
   on both and doing nothing. */
.lb-me [hidden] { display: none !important; }

.lb-me-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.lb-me-head h2 {
  margin: var(--space-2) 0 0;
  font-size: clamp(1.3rem, 3.4vw, 1.9rem);
}

/* ----- Login with: four cards, four columns ------------------------------ */
.lb-me-providers { margin-top: var(--space-5); }

.lb-login-label {
  display: block;
  font-family: var(--font-display);
  font-size: 0.72rem;
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  color: var(--ink-lo);
  margin-bottom: var(--space-4);
}

/* Four across, as asked. Two across under 46rem rather than four thin slivers -
   a card has to be wide enough to hold a logo at a size worth having, and four
   of those do not fit a phone. Never one column: two keeps it a grid. */
.lb-login-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
}

@media (max-width: 46rem) {
  .lb-login-grid { grid-template-columns: repeat(2, 1fr); }
}

.lb-provider {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);

  padding: var(--space-5) var(--space-3);
  border: 1px solid var(--grid-line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.02);
  color: var(--ink-mid);
  cursor: pointer;

  /* The card is the button. A nested <button> inside a card would give two hit
     targets for one action and a tab stop that lands on the wrong one. */
  font: inherit;

  /* Positioned for the ring, and isolated so the ring's stacking cannot be
     reordered by whatever the panel around it is doing. Motion is NOT set here:
     PAtilt writes an inline transform on mousemove and the two would fight. */
  position: relative;
  isolation: isolate;

  transition:
    border-color var(--dur-1) var(--ease-out),
    background var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}

/* ----- The neon on hover -------------------------------------------------

   Two layers, and neither of them is a blurred rectangle sitting behind the
   card. That was the first attempt and it washes colour across the card FACE:
   the background here is rgba(255,255,255,0.02), so anything behind it shows
   straight through, and a negative z-index escapes to whichever ancestor forms
   a stacking context - .lb-panel, whose own ::before then paints over it.

   So: a crisp ring drawn IN the border area, and an outer bloom made of
   box-shadows. Both stay outside the card's face, and both take a colour the
   card already carries. */

/* The ring. Background clipped to the border area by the two-mask trick -
   paint the padding box and the border box, then exclude one from the other,
   which leaves exactly the ring. It is the only way to put a GRADIENT in a
   border, and Google needs one. */
.lb-provider::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.6px;
  background: var(--ring, var(--brand));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-1) var(--ease-out);
}

.lb-provider:hover {
  /* The resting border goes transparent so the ring is the only edge. An
     absolutely positioned ::before resolves inset:0 against the PADDING box, so
     the ring sits just inside the border rather than on it - leaving both drawn
     puts a grey line outside a neon one. */
  border-color: transparent;
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink-hi);
  box-shadow: var(--bloom);
}

.lb-provider:hover::before { opacity: 1; }

.lb-provider:focus-visible {
  outline: 2px solid var(--cryo);
  outline-offset: 3px;
}

/* ----- One brand per card ------------------------------------------------

   Google is the odd one and the reason the ring is a gradient at all: its four
   colours sit at fixed places on the G - red across the top, blue down the
   right where the bar is, green along the bottom, yellow up the left - so the
   conic runs from 0deg (top) clockwise through exactly that order, and the
   bloom is four separate shadows offset the same four ways rather than one
   even halo in an average colour. */
.lb-provider[data-provider="apple"] {
  --brand: #ffffff;
  --bloom: 0 0 26px -6px rgba(255, 255, 255, 0.85), 0 0 8px -3px rgba(255, 255, 255, 0.55);
}

.lb-provider[data-provider="google"] {
  --brand: #4285f4;
  --ring: conic-gradient(from 0deg,
            #ea4335 0deg 40deg,
            #4285f4 40deg 140deg,
            #34a853 140deg 230deg,
            #fbbc05 230deg 300deg,
            #ea4335 300deg 360deg);
  --bloom:
    0 -9px 22px -8px #ea4335,
    10px 0 22px -8px #4285f4,
    0 9px 22px -8px #34a853,
    -10px 0 22px -8px #fbbc05;
}

.lb-provider[data-provider="facebook"] {
  --brand: #1877f2;
  --bloom: 0 0 26px -6px #1877f2, 0 0 8px -3px rgba(24, 119, 242, 0.7);
}

.lb-provider[data-provider="discord"] {
  --brand: #5865f2;
  --bloom: 0 0 26px -6px #5865f2, 0 0 8px -3px rgba(88, 101, 242, 0.7);
}

/* Fixed box so a 24-unit mark and a 48-unit one land the same size, and the
   four names sit on one line however tall each logo happens to draw. */
.lb-provider-mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
}

.lb-provider-mark svg { width: 100%; height: 100%; display: block; }

.lb-provider-name {
  font-family: var(--font-display);
  font-size: 0.78rem;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

/* Reduced motion means no lift; the colour change alone still answers the
   pointer. */
/* An empty status box is still a box, and .lb-status is drawn with a dashed
   border - so a signed-out panel was showing an empty hashed rectangle under
   the cards with nothing in it. Scoped to .lb-me so the boards panel below
   keeps whatever behaviour it has. */
.lb-me .lb-status:empty { display: none; }

/* PAtilt already refuses to run under reduced motion and on touch, so there is
   no transform to undo here. The ring and bloom are not motion and stay. */

/* auto-fit rather than a fixed column count, so seven figures reflow from one
   row on a desktop down to two per line on a phone with no breakpoint to keep
   in step with the content. */
.lb-me-totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: var(--space-3);
  margin: var(--space-5) 0 var(--space-6);
}

.lb-me-stat {
  padding: var(--space-4);
  border: 1px solid var(--grid-line);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.015);
}

.lb-me-stat-value {
  font-family: var(--font-mono);
  font-size: 1.25rem;
  color: var(--ink-hi);
  line-height: 1.1;
}

.lb-me-stat-label {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-size: 0.66rem;
  letter-spacing: var(--track-huge);
  text-transform: uppercase;
  color: var(--ink-lo);
}

/* The per-level table is the one place on this site with a genuinely unbounded
   number of rows - a hundred levels - so it scrolls in its own box rather than
   pushing the public boards off the bottom of the page. */
.lb-me-levels {
  display: block;
  max-height: 26rem;
  overflow-y: auto;
}
.lb-me-levels thead,
.lb-me-levels tbody { display: table; width: 100%; table-layout: fixed; }

/* Sticky so the headings survive the scroll. Opaque, because the rows pass
   underneath them and a translucent header over moving text is unreadable. */
.lb-me-levels thead th {
  position: sticky;
  top: 0;
  background: var(--void);
  z-index: 1;
}

.lb-me-levels td.num,
.lb-me-levels th.num { text-align: right; }

.lb-me-levels td.stars {
  color: var(--solar);
  letter-spacing: 0.1em;
}

@media (max-width: 34rem) {
  .lb-me-head { flex-direction: column; }
}
