/* ============================================================
   A8 Achievements — styling
   Source design: docs/superpowers/specs/2026-05-16-a8-achievements-badge-demo.html
   Goal: render achievement badges with the prototype's polish while
   respecting Phoenix theme variables for light/dark mode.

   Sections:
     1. Design tokens (scoped to .achievements-page-shell + global badge defaults)
     2. Badge atom (.badge, .sigil) — hover/cursor/tilt fix
     3. Category backgrounds ([data-cat="…"])
     4. Per-tier motion (gated by prefers-reduced-motion)
     5. Modal
     6. Earn burst + confetti
     7. Almost + streak cards
     8. Timeline ladder (.ladder-timeline + .ladder-rail + .ladder-thresholds)
     9. Page hero / sections / legend
    10. Responsive
   ============================================================ */

/* 1 — Design tokens ----------------------------------------- */
/* Surface + ink tokens read directly from Phoenix's theme variables, which
   already flip on `<html data-bs-theme="light|dark">`. Hardcoded fallbacks
   are kept as a defence in depth: if a page somehow loads this stylesheet
   without Phoenix's theme.min.css, dark-mode colors apply so the page is
   still legible. Previously these tokens fell back to dark colors UNCONDI-
   TIONALLY, which is why the stat tiles + legend + almost/streak cards
   stayed dark on the light theme.

   `.ach-modal-backdrop` is included in this scope because the modal is
   rendered OUTSIDE the page shell (it's appended after the shell so a
   click anywhere on the page can open it). Without scoping the tokens to
   the backdrop too, `var(--ach-card)` inside the modal resolved to the
   fallback hardcoded value — which in light mode meant dark text on a
   transparent/dark background, "cannot be read at all". */
.achievements-page-shell,
.achievements-section,
.ach-modal-backdrop {
  --ach-bronze:        #cd7f32;
  --ach-bronze-light:  #e6a36e;
  --ach-silver:        #d8d8e0;
  --ach-silver-light:  #f0f0f6;
  --ach-gold:          #f5c544;
  --ach-gold-light:    #ffe07a;
  --ach-platinum:      #c9d6ff;
  --ach-platinum-light:#ffffff;
  --ach-diamond:       #7be8ff;
  --ach-diamond-light: #d6f6ff;

  --ach-evo-cyan:    #5cc4ff;
  --ach-evo-magenta: #ff6bd6;
  --ach-evo-emerald: #6cf2b3;

  --ach-line:        var(--phoenix-border-color, rgba(255,255,255,0.10));
  --ach-line-strong: var(--phoenix-border-color, rgba(255,255,255,0.18));
  --ach-card:        var(--phoenix-emphasis-bg, #131a2a);
  /* color-mix gives a 5%-of-ink overlay which auto-flips per theme:
     near-black wash in light mode, near-white wash in dark mode. */
  --ach-card-hover:  color-mix(in srgb, var(--phoenix-emphasis-color, currentColor), transparent 95%);
  --ach-ink:         var(--phoenix-emphasis-color, #e8ecf3);
  --ach-ink-mute:    var(--phoenix-secondary-color, #8b94a8);
  --ach-ink-dim:     var(--phoenix-tertiary-color, #5b6479);

  --ach-font-display: 'Cormorant Garamond', 'Times New Roman', serif;
  --ach-font-mono:    'JetBrains Mono', ui-monospace, monospace;
}

/* 2 — Badge atom ------------------------------------------- */
/* These rules apply globally to .badge regardless of where it sits, so
   the embedded grid on the profile (legacy use-site) ALSO picks up
   cursor/hover fixes. */
.badge {
  --tier-color: var(--ach-silver);
  --tier-light: var(--ach-silver-light);
  --bg-inner:   #1a1f30;
  --bg-inner-2: #0d111c;

  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 18px 12px;
  position: relative;
  border-radius: 14px;
  transition: background-color .35s ease;
  isolation: isolate;
  cursor: pointer;
}
.badge:hover,
.badge:focus-visible {
  background: var(--ach-card-hover);
  outline: none;
}
.badge:focus-visible {
  box-shadow: 0 0 0 2px var(--phoenix-primary, #6366f1);
}

.badge[data-tier="bronze"]   { --tier-color: var(--ach-bronze);   --tier-light: var(--ach-bronze-light);   }
.badge[data-tier="silver"]   { --tier-color: var(--ach-silver);   --tier-light: var(--ach-silver-light);   }
.badge[data-tier="gold"]     { --tier-color: var(--ach-gold);     --tier-light: var(--ach-gold-light);     }
.badge[data-tier="platinum"] { --tier-color: var(--ach-platinum); --tier-light: var(--ach-platinum-light); }
.badge[data-tier="diamond"]  { --tier-color: var(--ach-diamond);  --tier-light: var(--ach-diamond-light);  }

.badge .sigil {
  width: 148px;
  height: 148px;
  position: relative;
  filter: drop-shadow(0 8px 24px rgba(0,0,0,0.5));
  transform-style: preserve-3d;
  transition: transform .5s cubic-bezier(.2,.7,.1,1);
}
html[data-bs-theme="light"] .badge .sigil {
  filter: drop-shadow(0 8px 24px rgba(20,24,40,0.16));
}
.badge:hover .sigil,
.badge:focus-visible .sigil {
  transform: translateY(-4px) rotateX(8deg) rotateY(-8deg) scale(1.04);
}
.badge .sigil svg { width: 100%; height: 100%; display: block; }

.badge h3 {
  font-family: var(--ach-font-display);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.01em;
  margin: 0;
  line-height: 1.15;
  color: var(--ach-ink);
}
.badge .meta {
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ach-ink-dim);
}
.badge .meta em { color: var(--ach-ink-mute); font-style: normal; }

/* Locked state */
.badge.locked .sigil { filter: grayscale(1) brightness(0.55); }
html[data-bs-theme="light"] .badge.locked .sigil { filter: grayscale(1) brightness(0.85) opacity(0.7); }
.badge.locked h3 { color: var(--ach-ink-mute); }
.badge.locked .sigil::after {
  content: "\1F512"; /* 🔒 */
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 34px;
  text-shadow: 0 2px 12px rgba(0,0,0,0.8);
}
.badge.locked.no-lock-icon .sigil::after,
.sigil.is-locked.no-lock-icon::after { content: none; }
.badge.locked.no-lock-icon .sigil,
.sigil.is-locked.no-lock-icon { filter: none; }
html[data-bs-theme="light"] .badge.locked.no-lock-icon .sigil,
html[data-bs-theme="light"] .sigil.is-locked.no-lock-icon { filter: none; }

/* Logo badges — auto-generated per-problem / per-demo --------
   A gold medal frame + dark disc + accent ring, with the problem/demo's
   own logo centered and tinted to its Phoenix accent (set via the
   --ach-accent custom prop on .logo-sigil). The disc stays dark in both
   themes to match the hand-drawn sigils; locked grayscale comes from the
   .badge.locked .sigil rule above. */
.badge .sigil .logo-sigil { position: absolute; inset: 0; display: block; }
.badge .sigil .logo-sigil-bg { position: absolute; inset: 0; }
.logo-sigil-disc { fill: #0e1430; }
.logo-sigil-ring { stroke: var(--ach-accent, #2f66e6); stroke-width: 1.6; opacity: .5; }
.badge .sigil .logo-sigil-logo {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--ach-accent, #2f66e6);
}
/* Higher specificity than `.badge .sigil svg { width:100% }` so the logo
   sits at medal scale inside the disc instead of filling the frame. */
.badge .sigil .logo-sigil-logo .ach-logo,
.badge .sigil .logo-sigil-logo img {
  width: 48%; height: 48%;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,.45));
}

/* 3 — Category backgrounds --------------------------------- */
[data-cat="submission"] { --bg-inner: #142042; --bg-inner-2: #070b1a; }
[data-cat="engagement"] { --bg-inner: #0e2a22; --bg-inner-2: #06140f; }
[data-cat="sharing"]    { --bg-inner: #241640; --bg-inner-2: #0e0820; }
[data-cat="invitation"] { --bg-inner: #3a1e0a; --bg-inner-2: #1a0e05; }
[data-cat="craft"]      { --bg-inner: #3d1232; --bg-inner-2: #1a0716; }
[data-cat="api"]        { --bg-inner: #0c2a24; --bg-inner-2: #04130f; }
[data-cat="account"]    { --bg-inner: #1a3d2a; --bg-inner-2: #08180f; }
[data-cat="explore"]    { --bg-inner: #0e2440; --bg-inner-2: #040a1a; }
[data-cat="egg"]        { --bg-inner: #1a0d40; --bg-inner-2: #08041a; }
[data-cat="security"]   { --bg-inner: #0d1e2a; --bg-inner-2: #04101a; }
[data-cat="style"]      { --bg-inner: #16142a; --bg-inner-2: #080718; }
[data-cat="compare"]    { --bg-inner: #1e1430; --bg-inner-2: #0a0716; }
[data-cat="template"]   { --bg-inner: #2a2210; --bg-inner-2: #120e05; }

html[data-bs-theme="light"] [data-cat="submission"] { --bg-inner: #dde6fa; --bg-inner-2: #aac1f4; }
html[data-bs-theme="light"] [data-cat="engagement"] { --bg-inner: #d8f0e3; --bg-inner-2: #8edcb4; }
html[data-bs-theme="light"] [data-cat="sharing"]    { --bg-inner: #ece0f7; --bg-inner-2: #c4a3eb; }
html[data-bs-theme="light"] [data-cat="invitation"] { --bg-inner: #fae5ce; --bg-inner-2: #f1c084; }
html[data-bs-theme="light"] [data-cat="craft"]      { --bg-inner: #fbdef0; --bg-inner-2: #f2a3d0; }
html[data-bs-theme="light"] [data-cat="api"]        { --bg-inner: #d3f0e5; --bg-inner-2: #7ed3b5; }
html[data-bs-theme="light"] [data-cat="account"]    { --bg-inner: #dff3e3; --bg-inner-2: #9bd5ad; }
html[data-bs-theme="light"] [data-cat="explore"]    { --bg-inner: #d8e7fa; --bg-inner-2: #a4c4f0; }
html[data-bs-theme="light"] [data-cat="egg"]        { --bg-inner: #e8def7; --bg-inner-2: #bca0eb; }
html[data-bs-theme="light"] [data-cat="security"]   { --bg-inner: #d6e4ef; --bg-inner-2: #92b6cf; }
html[data-bs-theme="light"] [data-cat="style"]      { --bg-inner: #e2dff5; --bg-inner-2: #b3aae8; }
html[data-bs-theme="light"] [data-cat="compare"]    { --bg-inner: #e8def7; --bg-inner-2: #bca0eb; }
html[data-bs-theme="light"] [data-cat="template"]   { --bg-inner: #f4e9c8; --bg-inner-2: #d6bd7a; }

/* 4 — Per-tier motion ------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .badge.earned[data-tier="bronze"]   .breathe { animation: ach-tier-bronze 8s ease-in-out infinite;   transform-origin: 50% 50%; }
  .badge.earned[data-tier="silver"]   .breathe { animation: ach-tier-silver 5s ease-in-out infinite;   transform-origin: 50% 50%; }
  .badge.earned[data-tier="gold"]     .breathe { animation: ach-tier-gold   4s ease-in-out infinite;   transform-origin: 50% 50%; }
  .badge.earned[data-tier="platinum"] .breathe { animation: ach-tier-platinum 3.5s ease-in-out infinite; transform-origin: 50% 50%; }
  .badge.earned[data-tier="diamond"]  .breathe { animation: ach-tier-diamond 3s ease-in-out infinite;   transform-origin: 50% 50%; }
  .badge.earned[data-tier="silver"]   .shimmer-rim { animation: ach-shimmer 4s linear infinite; }
  .badge.earned[data-tier="platinum"] .rotate-slow { animation: ach-rotate 30s linear infinite; transform-origin: 50% 50%; }
  .badge.earned[data-tier="diamond"]  .rotate-fast { animation: ach-rotate 14s linear infinite reverse; transform-origin: 50% 50%; }
  .badge.earned .breathe-default { animation: ach-tier-gold 5s ease-in-out infinite; transform-origin: 50% 50%; }
}
@keyframes ach-tier-bronze   { 0%, 100% { transform: scale(1); filter: brightness(1); } 50% { transform: scale(1.015); filter: brightness(1.08); } }
@keyframes ach-tier-silver   { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.025); } }
@keyframes ach-tier-gold     { 0%, 100% { filter: brightness(1) drop-shadow(0 0 0 rgba(245,197,68,0)); transform: scale(1); } 50% { filter: brightness(1.15) drop-shadow(0 0 14px rgba(245,197,68,0.45)); transform: scale(1.03); } }
@keyframes ach-tier-platinum { 0%, 100% { filter: brightness(1) drop-shadow(0 0 0 rgba(201,214,255,0)); transform: scale(1); } 50% { filter: brightness(1.2) drop-shadow(0 0 20px rgba(201,214,255,0.6)); transform: scale(1.04); } }
@keyframes ach-tier-diamond  { 0%, 100% { filter: brightness(1) drop-shadow(0 0 0 rgba(123,232,255,0)); transform: scale(1); } 50% { filter: brightness(1.25) drop-shadow(0 0 22px rgba(123,232,255,0.7)); transform: scale(1.04); } }
@keyframes ach-shimmer       { 0% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 300; } }
@keyframes ach-rotate        { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* 5 — Modal ------------------------------------------------
   All modal classes are prefixed `ach-` because Bootstrap (loaded via
   Phoenix's theme.min.css) ships `.modal { display: none }`,
   `.modal-backdrop { ... }` and `.modal-body { overflow-y: auto }`.
   Without the prefix, Bootstrap's display:none on the inner .modal
   element wins regardless of source order, so the backdrop dimmed the
   screen but the modal content stayed invisible. The prefix sidesteps
   the cascade fight entirely. */
.ach-modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(7,9,15,0.78);
  backdrop-filter: blur(8px);
  display: none;
  z-index: 1080;        /* above Phoenix navbar (z-index ~1030) */
  padding: 24px;
}
.ach-modal-backdrop.open { display: flex; align-items: center; justify-content: center; }
.ach-modal-backdrop .ach-modal {
  background: var(--ach-card);
  border: 1px solid var(--ach-line-strong);
  border-radius: 18px;
  max-width: min(560px, calc(100vw - 32px));
  width: 100%;
  padding: 32px;
  animation: ach-modal-in .35s cubic-bezier(.2,1.2,.3,1);
  position: relative;
}
@keyframes ach-modal-in {
  from { opacity: 0; transform: translateY(20px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
.ach-modal-close {
  position: absolute;
  top: 18px;
  inset-inline-end: 18px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--ach-line-strong);
  color: var(--ach-ink-mute);
  font-size: 16px;
  cursor: pointer;
  display: grid; place-items: center;
  transition: color .2s ease, border-color .2s ease;
}
.ach-modal-close:hover, .ach-modal-close:focus-visible {
  color: var(--ach-ink);
  border-color: var(--ach-ink);
  outline: none;
}
.ach-modal-hero { display: flex; align-items: center; gap: 24px; margin-bottom: 20px; }
.ach-modal-hero .sigil { width: 120px; height: 120px; flex-shrink: 0; position: relative; }
.ach-modal-hero .sigil svg { width: 100%; height: 100%; display: block; }
.ach-modal-hero h3 {
  font-family: var(--ach-font-display);
  font-weight: 600;
  font-size: 28px;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
  color: var(--ach-ink);
}
.ach-modal-hero .ach-modal-meta {
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ach-ink-dim);
}
.ach-modal-body p { color: var(--ach-ink-mute); font-size: 14px; }
.ach-modal-howto {
  margin-top: 18px;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px dashed var(--ach-line-strong);
  background: rgba(255,255,255,0.02);
}
html[data-bs-theme="light"] .ach-modal-howto { background: rgba(15,18,30,0.02); }
.ach-modal-howto h5 {
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ach-ink-mute);
  margin: 0 0 8px;
}
.ach-modal-howto p { margin: 0; font-size: 13px; }

/* Locked-state indicator on the modal sigil (class set by JS) */
.sigil.is-locked { filter: grayscale(1) brightness(0.55); }
html[data-bs-theme="light"] .sigil.is-locked { filter: grayscale(1) brightness(0.85) opacity(0.7); }
.sigil.is-locked::after {
  content: "\1F512";
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 28px;
  text-shadow: 0 2px 12px rgba(0,0,0,0.8);
}

/* 4b — Universal idle animations on earned badges ----------
   Most sigil SVGs don't carry the `.breathe` / `.shimmer-rim`/
   `.rotate-slow` hooks the tier-specific animations target, so without
   these rules the majority of earned badges sat dead-still. Two effects:
   (1) a sigil-level breath on the inner <svg> so every earned badge
       pulses, regardless of which class hooks the artist used; the
       animation targets the SVG element (not its `.sigil` wrapper) so
       it doesn't fight the hover-tilt transform on .sigil itself.
   (2) a tier-colored halo behind every earned badge — a soft radial
       glow that pulses in counter-phase to the breath, giving each
       badge a distinct "alive" feel and making locked vs. earned
       unmistakable at a glance. */
@media (prefers-reduced-motion: no-preference) {
  /* Sigil-level breath — pumped up so the pulse is clearly visible
     (prior 5%/12% was too subtle in user testing). Targets the inner
     <svg> so it doesn't compete with hover-tilt on the .sigil wrapper. */
  .badge.earned:not(.just-earned) .sigil > svg {
    animation: ach-sigil-breathe 3.4s ease-in-out infinite;
    transform-origin: 50% 50%;
    transform-box: fill-box;
  }
  @keyframes ach-sigil-breathe {
    0%, 100% { transform: scale(1);     filter: brightness(1); }
    50%      { transform: scale(1.09);  filter: brightness(1.22); }
  }

  /* Tier-colored halo behind the sigil — wider opacity sweep so the
     glow is unmistakable, not a barely-there blush. */
  .badge.earned .sigil::before {
    content: "";
    position: absolute;
    inset: -12%;
    border-radius: 50%;
    pointer-events: none;
    z-index: -1;
    background: radial-gradient(closest-side,
      color-mix(in srgb, var(--tier-color), transparent 40%),
      transparent 75%);
    filter: blur(14px);
    animation: ach-halo-pulse 3.6s ease-in-out infinite;
  }
  @keyframes ach-halo-pulse {
    0%, 100% { opacity: 0.30; transform: scale(0.88); }
    50%      { opacity: 1.00; transform: scale(1.18); }
  }

  /* Subtle continuous lift on every earned badge so the row is alive. */
  .badge.earned:not(.just-earned) {
    animation: ach-badge-float 6s ease-in-out infinite;
  }
  @keyframes ach-badge-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
  }
}

/* 6 — Earn burst + confetti -------------------------------- */
.badge.just-earned .sigil { animation: ach-earn-pop .9s cubic-bezier(.2,1.6,.4,1) 1; }
.badge.just-earned::before {
  content: "";
  position: absolute;
  inset: -30px;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--tier-color), transparent 55%), transparent 60%);
  animation: ach-earn-flash .9s ease-out 1;
  pointer-events: none;
  z-index: -1;
}
@keyframes ach-earn-pop {
  0%   { transform: scale(.5) rotate(-12deg); opacity: 0; }
  60%  { transform: scale(1.18) rotate(4deg); opacity: 1; }
  100% { transform: scale(1) rotate(0); }
}
@keyframes ach-earn-flash {
  0%   { opacity: 0; transform: scale(.4); }
  50%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.4); }
}
.confetti { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.confetti span {
  position: absolute;
  left: 50%; top: 50%;
  width: 6px; height: 6px;
  border-radius: 50%;
  opacity: 0;
}
.badge.just-earned .confetti span { animation: ach-confetti-burst 1.4s cubic-bezier(.2,.7,.2,1) forwards; }
@keyframes ach-confetti-burst {
  0%   { transform: translate(-50%,-50%) scale(.4); opacity: 1; }
  80%  { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(.2); opacity: 0; }
}

/* 7 — Almost + streak cards ------------------------------- */
.achievement-almost-card,
.achievement-streak-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 18px;
  border: 1px solid var(--ach-line-strong);
  border-radius: 14px;
  margin-bottom: 16px;
  background: var(--ach-card);
}
.achievement-almost-card {
  background:
    linear-gradient(110deg, rgba(245,197,68,0.10), rgba(92,196,255,0.08) 70%),
    var(--ach-card);
}
.almost-icon { width: 64px; height: 64px; flex-shrink: 0; }
.almost-icon .badge { padding: 0; gap: 0; }
.almost-icon .badge .sigil { width: 64px; height: 64px; filter: none; }
.almost-icon .badge h3, .almost-icon .badge .meta { display: none; }
.almost-text { flex: 1; min-width: 0; }
.almost-text h4 {
  font-family: var(--ach-font-display);
  font-weight: 600;
  font-size: 18px;
  margin: 0 0 4px;
  color: var(--ach-ink);
}
.almost-text p { font-size: 13px; color: var(--ach-ink-mute); margin: 0; }
.almost-bar { width: 220px; flex-shrink: 0; }
.almost-bar .progress {
  width: 100%; height: 6px;
  border-radius: 3px;
  background: var(--ach-line-strong);
  overflow: hidden;
}
.almost-bar .progress > span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--ach-gold), var(--ach-gold-light));
}
.almost-bar .progress-label {
  display: flex;
  justify-content: space-between;
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ach-ink-mute);
  margin-top: 6px;
}
.achievement-streak-card {
  background: linear-gradient(135deg, rgba(245,197,68,0.10), rgba(255,107,214,0.06) 70%), var(--ach-card);
  position: relative;
  overflow: hidden;
}
.streak-flame { font-size: 40px; line-height: 1; filter: drop-shadow(0 0 10px var(--ach-gold)); }
.streak-text { flex: 1; min-width: 0; }
.streak-text h4 {
  font-family: var(--ach-font-display);
  font-weight: 600;
  font-size: 22px;
  margin: 0 0 4px;
  color: var(--ach-ink);
}
.streak-text p { color: var(--ach-ink-mute); font-size: 13px; margin: 0; }

/* 8 — Timeline ladder ------------------------------------- */
.ladder-timeline {
  position: relative;
  margin-top: 40px;
  padding-top: 32px;
  border-top: 1px solid var(--ach-line);
}
.ladder-timeline:first-of-type { border-top: 0; margin-top: 12px; padding-top: 0; }

.ladder-head { margin-bottom: 16px; }
.ladder-name {
  font-family: var(--ach-font-display);
  font-weight: 500;
  font-size: 24px;
  letter-spacing: -0.01em;
  margin: 0 0 4px;
  color: var(--ach-ink);
}
.ladder-sub {
  color: var(--ach-ink-mute);
  font-size: 13.5px;
  margin: 0 0 8px;
  max-width: 70ch;
}
.ladder-current {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
.ladder-current-pill {
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ach-ink);
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--ach-line-strong);
  background: rgba(245,197,68,0.10);
}
.ladder-current-pill-complete {
  background: linear-gradient(90deg, rgba(123,232,255,0.18), rgba(201,214,255,0.18));
  border-color: var(--ach-diamond);
}
.ladder-current-pill-empty {
  background: transparent;
  color: var(--ach-ink-mute);
}

/* The track: a 2px rail behind the badges; centred vertically on
   the sigils. The fill width is driven by --earned (0..5) using a
   calc that maps "earned tier count" to "fraction of the rail
   between the first and last badge centres" (which sit at 10%/90%
   of the row width by our 5-column grid). */
.ladder-track-wrap {
  position: relative;
  padding: 0 4px;
}
.ladder-rail {
  position: absolute;
  top: 74px;             /* approx half sigil height (148/2) */
  left: 10%;
  right: 10%;
  height: 3px;
  background: var(--ach-line-strong);
  border-radius: 3px;
  z-index: 0;
}
.ladder-rail-fill {
  display: block;
  height: 100%;
  border-radius: 3px;
  /* (earned - 1) / 4 of the rail length; clamped at 0 when earned = 0 */
  width: max(0%, calc((var(--earned, 0) - 1) / 4 * 100%));
  background: linear-gradient(90deg,
    var(--ach-bronze),
    var(--ach-silver) 25%,
    var(--ach-gold) 50%,
    var(--ach-platinum) 75%,
    var(--ach-diamond));
  transition: width .6s cubic-bezier(.2,.7,.1,1);
  box-shadow: 0 0 12px rgba(245,197,68,0.25);
}
.ladder-states {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 12px 8px;
}

.ladder-thresholds {
  list-style: none;
  padding: 14px 4px 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 4px 8px;
  text-align: center;
}
.ladder-threshold {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-family: var(--ach-font-mono);
}
.ladder-threshold.locked { opacity: 0.55; }
.ladder-threshold.current { font-weight: 600; }
.ladder-threshold .th-marker {
  display: inline-grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 999px;
  border: 1px solid var(--ach-line-strong);
  background: var(--ach-card);
  margin-bottom: 2px;
}
.ladder-threshold.earned .th-marker {
  background: linear-gradient(180deg, var(--tier-light, var(--ach-gold-light)), var(--tier-color, var(--ach-gold)));
  border-color: var(--tier-color, var(--ach-gold));
  color: #07090f;
}
.ladder-threshold[data-tier="bronze"]   { --tier-color: var(--ach-bronze);   --tier-light: var(--ach-bronze-light); }
.ladder-threshold[data-tier="silver"]   { --tier-color: var(--ach-silver);   --tier-light: var(--ach-silver-light); }
.ladder-threshold[data-tier="gold"]     { --tier-color: var(--ach-gold);     --tier-light: var(--ach-gold-light); }
.ladder-threshold[data-tier="platinum"] { --tier-color: var(--ach-platinum); --tier-light: var(--ach-platinum-light); }
.ladder-threshold[data-tier="diamond"]  { --tier-color: var(--ach-diamond);  --tier-light: var(--ach-diamond-light); }
.ladder-threshold .th-check { font-size: 11px; font-weight: 700; }
.ladder-threshold .th-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ach-ink-dim);
  display: inline-block;
}
.ladder-threshold.current .th-marker {
  border-color: var(--ach-gold);
  background: var(--ach-card);
  box-shadow: 0 0 0 3px rgba(245,197,68,0.18);
}
.ladder-threshold.current .th-here {
  font-size: 11px;
  color: var(--ach-gold);
}
.ladder-threshold .th-tier {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ach-ink-dim);
}
.ladder-threshold.earned .th-tier { color: var(--ach-ink-mute); }
.ladder-threshold .th-value {
  font-size: 12px;
  color: var(--ach-ink-mute);
}
.ladder-threshold.current .th-value { color: var(--ach-ink); }

/* Badges inside a timeline ladder shrink slightly so 5 fit comfortably. */
.ladder-timeline .badge { padding: 12px 6px; gap: 10px; }
.ladder-timeline .badge .sigil { width: 120px; height: 120px; }
.ladder-timeline .badge h3 { font-size: 16px; }

/* 9 — Page hero / sections / legend ----------------------- */
.achievements-page-shell {
  max-width: 1200px;
  margin: 0 auto;
  padding: 32px 8px 96px;
  color: var(--ach-ink);
}
.ach-hero {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 32px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
.ach-hero-text { flex: 1 1 320px; min-width: 0; }
.ach-hero-title {
  font-family: var(--ach-font-display);
  font-weight: 500;
  font-size: clamp(34px, 5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin: 0 0 8px;
}
.ach-hero-lede {
  color: var(--ach-ink-mute);
  font-size: 15px;
  margin: 0;
  max-width: 50ch;
}
.ach-hero-stats {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.ach-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 16px;
  border: 1px solid var(--ach-line-strong);
  border-radius: 12px;
  background: var(--ach-card);
  min-width: 96px;
}
.ach-stat-num {
  font-family: var(--ach-font-display);
  font-weight: 600;
  font-size: 28px;
  line-height: 1;
  color: var(--ach-ink);
  letter-spacing: -0.02em;
}
.ach-stat-of {
  font-family: var(--ach-font-mono);
  font-weight: 400;
  font-size: 12px;
  color: var(--ach-ink-dim);
  margin-inline-start: 4px;
  letter-spacing: 0.05em;
}
.ach-stat-label {
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ach-ink-mute);
  margin-top: 4px;
}

.ach-legend {
  display: inline-flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--ach-card);
  border: 1px solid var(--ach-line-strong);
  font-family: var(--ach-font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ach-ink-mute);
  margin-bottom: 24px;
}
.legend-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  display: inline-block;
  vertical-align: -2px;
  margin-inline-end: 6px;
}
.legend-dot-bronze   { background: radial-gradient(circle at 30% 30%, var(--ach-bronze-light), var(--ach-bronze)); }
.legend-dot-silver   { background: radial-gradient(circle at 30% 30%, var(--ach-silver-light), var(--ach-silver)); }
.legend-dot-gold     { background: radial-gradient(circle at 30% 30%, var(--ach-gold-light), var(--ach-gold)); }
.legend-dot-platinum { background: conic-gradient(from 0deg, var(--ach-platinum), var(--ach-evo-cyan), var(--ach-evo-magenta), var(--ach-gold), var(--ach-platinum)); }
.legend-dot-diamond  { background: conic-gradient(from 60deg, var(--ach-diamond-light), var(--ach-evo-cyan), var(--ach-evo-magenta), var(--ach-diamond-light)); }

.ach-section { margin-top: 48px; }
.ach-section-title {
  font-family: var(--ach-font-display);
  font-weight: 500;
  font-size: 30px;
  letter-spacing: -0.015em;
  margin: 0 0 4px;
  color: var(--ach-ink);
}
.ach-section-sub {
  font-family: var(--ach-font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ach-ink-dim);
  margin: 0 0 20px;
}

/* Sub-section (group) within the Problems / Demos sections */
.ach-subgroup { margin-top: 24px; }
.ach-subgroup:first-of-type { margin-top: 0; }
.ach-subgroup-title {
  font-family: var(--ach-font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ach-ink-dim);
  margin: 0 0 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--ach-hairline, rgba(140, 150, 180, 0.18));
}

/* Generic states grids (used by oneshots + collectors, and existing embedded grid) */
.states { display: grid; gap: 24px 16px; }
.states-five { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.states-grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }

/* Legacy heading from the old embedded grid (kept for the profile-link card
   and any unmigrated embeds). */
.achievements-section { margin-top: 48px; }
.achievements-heading {
  font-family: var(--ach-font-display);
  font-weight: 500;
  font-size: 28px;
  letter-spacing: -0.015em;
  margin: 0 0 24px;
  color: var(--ach-ink);
}
.ladder { margin-top: 40px; }
.ladder:first-of-type { margin-top: 0; }
.ladder-title {
  font-family: var(--ach-font-display);
  font-weight: 500;
  font-size: 20px;
  margin: 0 0 12px;
  color: var(--ach-ink);
}

/* Utility from Bootstrap-without-Bootstrap */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* 10 — Responsive ----------------------------------------- */
@media (max-width: 1100px) {
  .ach-hero-stats { gap: 6px; }
  .ach-stat { padding: 10px 12px; min-width: 84px; }
}
@media (max-width: 880px) {
  .achievements-page-shell { padding: 24px 4px 64px; }
  .states-five {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .states-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Timeline collapses to a stacked layout on narrow viewports: the
     5-column ladder + thresholds become a 2-column grid (so a long
     ladder name doesn't shove badges off-screen). The rail no longer
     makes geometric sense across 2-column wrap, so hide it; the
     thresholds row keeps the earned/locked semantics via its own
     markers. */
  .ladder-timeline .ladder-states,
  .ladder-thresholds {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .ladder-timeline .badge .sigil { width: 96px; height: 96px; }
  .ladder-rail { display: none; }
  .achievement-almost-card,
  .achievement-streak-card { flex-wrap: wrap; }
  .almost-bar { width: 100%; }
}
@media (max-width: 480px) {
  .ach-hero { flex-direction: column; gap: 16px; }
  .ach-stat { min-width: 72px; }
  .ach-modal-backdrop { padding: 12px; }
  .ach-modal-backdrop .ach-modal { padding: 20px; }
  .ach-modal-hero { gap: 12px; }
  .ach-modal-hero .sigil { width: 84px; height: 84px; }
  .ach-modal-hero h3 { font-size: 22px; }
}
