/* Gamification — leaderboard + achievements pages.
   Reuses theme tokens from modern-docs.css. */

.gam-shell {
  max-width: 980px;
  margin: 32px auto;
  padding: 0 16px;
}
.gam-title {
  font-family: var(--font-sans);
  font-size: 24px;
  font-weight: 600;
  color: var(--text-0);
  margin: 0 0 6px;
}
.gam-subtitle {
  font-size: 14px;
  color: var(--text-2);
  margin: 0 0 24px;
}

/* Smoothly-animatable angle for the rotating gradient borders on the
   podium rows. Registered via @property so the conic-gradient sweep can
   tween (a raw custom prop can't be interpolated). Browsers without
   @property fall back to a static gradient ring, which still looks fine. */
@property --lb-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

/* Leaderboard gets a wider shell than the achievements page so the top-3
   cards can step out past the base column without overflowing the
   viewport. The base column (`.lb-inner`) stays centered and aligns the
   header with the rank 4+ rows. */
.gam-shell--lb { max-width: 1120px; }
.lb-inner {
  max-width: 860px;
  margin: 0 auto;
}

.lb-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.lb-row {
  position: relative;
  display: grid;
  grid-template-columns: 34px 44px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 11px 16px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
  transition: border-color 130ms ease, transform 130ms ease, background 130ms ease;
}
.lb-row:hover {
  border-color: var(--accent);
  background: var(--bg-2);
  transform: translateX(2px);
}

/* ── Rank medallion ───────────────────────────────────────────────────── */
.lb-medal {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--text-3);
  background: var(--bg-3);
  border: 1px solid var(--border);
  justify-self: center;
}
.lb-medal--1,
.lb-medal--2,
.lb-medal--3 {
  color: #1a1306;
  border: none;
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.55), 0 1px 4px rgba(0,0,0,0.35);
}
.lb-medal--1 { background: linear-gradient(145deg, #ffe9a8 0%, #e6b531 45%, #b8860b 100%); }
.lb-medal--2 { background: linear-gradient(145deg, #f2f5f8 0%, #c3ccd6 45%, #8c95a1 100%); }
.lb-medal--3 { background: linear-gradient(145deg, #f4c89a 0%, #d68a4e 45%, #a25a23 100%); color: #2a1608; }

/* ── Avatar ───────────────────────────────────────────────────────────── */
.lb-avatar-wrap {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.lb-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  object-fit: cover;
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 700;
  color: var(--text-0);
  box-shadow: 0 0 0 1px var(--border);
}

/* ── Main column (name / handle / stats) ──────────────────────────────── */
.lb-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.lb-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.lb-name {
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-0);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lb-handle {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-3);
}

/* Worn badges — small circular chips, same source as the profile strip. */
.lb-badges {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
}
.lb-badge {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  line-height: 1;
  background: var(--bg-3);
  border: 1px solid var(--border);
}
.lb-badge--super {
  background: linear-gradient(145deg, rgba(255,180,84,0.22), rgba(255,138,75,0.12));
  border-color: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow, rgba(255,180,84,0.4));
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* Contribution stats (comments / snippets). */
.lb-stats {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 3px;
}
.lb-stat {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
}
.lb-stat svg { color: var(--text-3); flex: 0 0 auto; }

/* ── Score column (XP + level) ────────────────────────────────────────── */
.lb-score {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  text-align: right;
}
.lb-xp {
  font-family: var(--font-mono);
  font-size: 16px;
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
}
.lb-xp-unit {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-3);
  margin-left: 3px;
  letter-spacing: 0.06em;
}
.lb-level {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--text-3);
}

/* ── Podium (top 3) ───────────────────────────────────────────────────── */
.lb-row--podium {
  padding: 16px 20px;
  background: var(--bg-2);
  border-color: transparent;
  /* Override the column-flex `stretch` so the stepped widths below take
     effect and the cards stay centered over the base column. */
  align-self: center;
}
.lb-row--podium .lb-medal { width: 34px; height: 34px; font-size: 14px; }
.lb-row--podium .lb-avatar-wrap,
.lb-row--podium .lb-avatar { width: 56px; height: 56px; }
.lb-row--podium .lb-avatar { font-size: 18px; }
.lb-row--podium .lb-name { font-size: 16px; }
.lb-row--podium .lb-xp { font-size: 18px; }
.lb-row--podium { grid-template-columns: 38px 56px 1fr auto; }

/* Rotating gradient border. The masked ::before paints only the 2px ring
   (background fills the content box, mask subtracts it) so it never covers
   the row, and pointer-events:none lets clicks reach the link. */
.lb-row--podium::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(from var(--lb-angle), var(--lb-c1), var(--lb-c2), var(--lb-c3), var(--lb-c2), var(--lb-c1));
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
          mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  animation: lb-spin 4.5s linear infinite;
}
/* Stepped sizing: each podium step is a bit wider + taller than the one
   below, so first place reads as the biggest card. Widths are relative to
   the centered base column (`.lb-inner`, 860px). */
.lb-row--podium-3 { width: 105%; }
.lb-row--podium-2 { width: 110%; padding: 18px 22px; }
.lb-row--podium-1 { width: 120%; padding: 22px 26px; }
.lb-row--podium-1 {
  --lb-c1: #b8860b; --lb-c2: #ffe9a8; --lb-c3: #f5c542;
  animation: lb-pulse 2.8s ease-in-out infinite;
}
.lb-row--podium-2 { --lb-c1: #8c95a1; --lb-c2: #f2f5f8; --lb-c3: #c3ccd6; }
.lb-row--podium-3 { --lb-c1: #a25a23; --lb-c2: #f4c89a; --lb-c3: #d68a4e; }

@keyframes lb-spin {
  to { --lb-angle: 360deg; }
}
@keyframes lb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245,197,66,0.0), 0 0 16px rgba(245,197,66,0.18); }
  50%      { box-shadow: 0 0 0 4px rgba(245,197,66,0.10), 0 0 30px rgba(245,197,66,0.42); }
}

@media (prefers-reduced-motion: reduce) {
  .lb-row--podium::before { animation: none; }
  .lb-row--podium-1 { animation: none; box-shadow: 0 0 22px rgba(245,197,66,0.3); }
}

/* Below the wide breakpoint there isn't room for the stepped-out cards to
   extend past the base column without overflowing the viewport, so the base
   column goes full width and the podium cards drop back to 100%. They keep
   the stepped padding so first place still feels biggest. */
@media (max-width: 1080px) {
  .lb-inner { max-width: none; }
  .lb-row--podium-1,
  .lb-row--podium-2,
  .lb-row--podium-3 { width: 100%; }
}

@media (max-width: 560px) {
  .lb-stats { display: none; }
  .lb-row { gap: 10px; padding: 10px 12px; }
}

.ach-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}

/* Per-track ladder rendering. Each track gets a horizontal rung chain
   so the user sees their progression at a glance — earned rungs glow
   with the accent, locked rungs grey out. */
.ach-track {
  margin: 22px 0 6px;
  padding: 16px 18px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.ach-track-hd {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
.ach-track-icon { font-size: 22px; }
.ach-track-title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-0);
}
.ach-track-progress {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  padding: 3px 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 99px;
  letter-spacing: 0.04em;
}
.ach-rungs {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: 6px;
}
.ach-rung {
  flex: 1 1 140px;
  min-width: 120px;
  padding: 12px 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  transition: border-color 120ms ease, background 120ms ease, opacity 120ms ease;
}
.ach-rung-icon { font-size: 28px; }
.ach-rung-name {
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-1);
}
.ach-rung-meta {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
}
.ach-rung-xp {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--accent);
}
.ach-rung.is-earned {
  background: var(--accent-glow);
  border-color: var(--accent);
}
.ach-rung.is-earned .ach-rung-name { color: var(--text-0); }
.ach-rung.is-locked {
  filter: grayscale(0.7);
  opacity: 0.55;
}
.ach-rung-arrow {
  display: flex;
  align-items: center;
  font-size: 18px;
  color: var(--text-3);
}

.ach-section-title {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-0);
  margin: 28px 0 12px;
}
.ach-standalone-section { margin-top: 6px; }
.ach-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  position: relative;
  transition: border-color 120ms ease, transform 120ms ease;
}
.ach-card:hover { transform: translateY(-2px); border-color: var(--accent); }
.ach-card.is-locked { opacity: 0.55; }
.ach-card.is-earned { border-color: var(--accent); }
.ach-card.is-earned::after {
  content: '✓';
  position: absolute;
  top: 8px;
  right: 12px;
  color: var(--accent);
  font-size: 14px;
  font-weight: 700;
}
.ach-icon {
  font-size: 28px;
  line-height: 1;
}
.ach-name {
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-0);
}
.ach-desc {
  font-size: 12px;
  color: var(--text-2);
  line-height: 1.4;
}
.ach-xp {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent);
  font-weight: 700;
}

/* ─── Achievements page rework (2026-05) ─────────────────────────────
   Engagement section: 5 cards, one per track. Each card has its own
   progress bar with 5 level nodes pinned to their thresholds + a row
   of "L1/L2/L3/L4/L5" level chips showing XP rewards. The achievement
   unlocks only when level 5 is reached.

   One-off section: 2-column responsive grid of milestone cards. */

.gam-section-title {
  font-family: var(--font-sans);
  font-size: 18px;
  font-weight: 600;
  color: var(--text-0);
  margin: 28px 0 6px;
}
.gam-section-help {
  font-size: 12.5px;
  color: var(--text-3);
  margin: 0 0 14px;
}

/* ── Engagement cards (compact, single-row) ───────────────────────────
   The card title was the achievement's L5 name — same as the final
   rung label — so it was confusing AND took a whole header row. Now
   each card is a single dense row:

     [icon]  ✓ Current  ━━━━━●━━━━━━  Next  +XP

   Plus a subtle gray meta line below:
     "13 / 25 comments"

   When the achievement is unlocked, the row collapses to:
     [icon]  ✓ Final-name                                Unlocked
   with the meta line showing the final count. */
.eng-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.eng-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  /* Extra bottom-padding reserves room for the absolutely-positioned
     "X / Y noun" meta line that sits below the bar without pushing it
     up. Top + bottom kept slightly different on purpose. */
  padding: 9px 14px 18px;
  transition: border-color 160ms ease;
}
.eng-card.is-unlocked {
  border-color: var(--accent);
  background: linear-gradient(135deg, var(--bg-1) 0%, var(--accent-glow) 220%);
}

/* Single-row layout. Five tracks total: icon, current rung, bar,
   next rung, (in unlocked state) the "Unlocked" pill replaces the bar
   + next-rung columns. */
.eng-card-row {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) minmax(70px, 1.4fr) minmax(0, 1fr);
  align-items: center;   /* vertical-center the icon + rungs + bar on the row baseline */
  gap: 10px;
  min-height: 24px;      /* a touch taller than text line-height so the row breathes */
}
.eng-card.is-unlocked .eng-card-row {
  grid-template-columns: 22px minmax(0, 1fr) auto;
}
.eng-card-icon { font-size: 18px; line-height: 1; display: inline-flex; align-items: center; }

.eng-card-pill {
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--bg-0);
  background: var(--accent);
  border: 1px solid var(--accent);
  padding: 2px 9px;
  border-radius: 99px;
  box-shadow: 0 0 8px var(--accent-glow);
  text-transform: uppercase;
}

.eng-rung {
  display: inline-flex;
  align-items: center;       /* vertical-center the check + label + xp */
  gap: 6px;
  min-width: 0;
  font-family: var(--font-sans);
  line-height: 1.2;
}
/* Left side (current rung): primary text — slightly bigger and WHITE
   so it reads as "you, right now". The check glyph still glows accent. */
.eng-rung--current {
  justify-content: flex-start;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-0);
}
/* Right side (next rung): secondary — smaller, gray, with the XP
   reward sitting next to it in accent orange. The orange XP is the
   visual "reward incoming" hook. */
.eng-rung--next {
  justify-content: flex-end;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  text-align: right;
}
/* Right-side arrow indicating "here's what's coming next". Subtle but
   directional so the eye reads left=now, arrow=motion, right=goal. */
.eng-rung-arrow {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-3);
  font-weight: 700;
}
.eng-rung-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.eng-rung-label.is-faded { color: var(--text-3); font-weight: 500; font-style: italic; }
.eng-rung-xp {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);     /* the reward callout — orange so it pops */
  letter-spacing: 0.02em;
}

/* Progress sub-column: just holds the bar in normal flow, and the
   "X / Y noun" meta is ABSOLUTE-positioned underneath it (see
   `.eng-bar ~ .eng-card-meta` below). That way the bar's vertical
   position is dictated solely by the row's align-items: center (so
   it lines up with the left/right rung labels), and the meta sits
   visually beneath without taking layout height — i.e. the meta
   doesn't push the bar up. */
.eng-card-progress {
  position: relative;
  display: block;
  min-width: 0;
}
.eng-bar {
  position: relative;
  display: block;
  height: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 99px;
  overflow: hidden;
}
.eng-bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: linear-gradient(90deg, var(--accent) 0%, #ffb454 100%);
  transition: width 520ms cubic-bezier(.2,.7,.2,1);
  pointer-events: none;
}
.eng-card-meta {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
  letter-spacing: 0.02em;
}
/* Locked cards (bar present): meta is pinned absolutely below the bar.
   Doesn't take layout height → bar stays centered with the labels. */
.eng-bar ~ .eng-card-meta {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
}
.eng-card.is-unlocked .eng-card-meta {
  color: var(--text-2);
  /* Unlocked card has no bar — meta sits inline, no need to absolute it. */
}

@media (max-width: 560px) {
  .eng-card-row { grid-template-columns: 22px 1fr; gap: 6px; }
  .eng-card.is-unlocked .eng-card-row { grid-template-columns: 22px 1fr auto; }
  .eng-card-progress, .eng-rung--next { display: none; }
}

/* One-off milestones — compact 2-column grid. */
.ach-oneoff-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
@media (max-width: 600px) {
  .ach-oneoff-grid { grid-template-columns: 1fr; }
}
.ach-oneoff-card {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 8px 12px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 8px;
  transition: border-color 120ms ease, transform 120ms ease;
  min-height: 44px;
}
.ach-oneoff-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.ach-oneoff-card.is-locked { opacity: 0.6; }
/* Earned milestone. Calm surface with a neutral border — same family
   as the engagement "earned" card. The +XP chip on the right already
   carries the success accent, no need to flood the whole card. The
   thicker border distinguishes it from a locked card without orange. */
.ach-oneoff-card.is-earned {
  background: var(--bg-2);
  border-color: var(--text-3);
  border-width: 2px;
}
.ach-oneoff-icon { font-size: 22px; line-height: 1; text-align: center; }
.ach-oneoff-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ach-oneoff-name {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-0);
  line-height: 1.2;
}
.ach-oneoff-desc {
  font-size: 11px;
  color: var(--text-2);
  line-height: 1.3;
}
.ach-oneoff-xp {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent);
  font-weight: 700;
}

