/* Academy hub.
   Layout intent: one obvious next action at the top, then the map that gives
   it context, then evidence, then the thing it all builds toward. A learner
   who reads only the first screen should still know exactly what to do. */

.top {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-5);
  background: rgba(10, 10, 15, 0.82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}

.top-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.top-brand img { width: 26px; height: 26px; }
.top-brand small {
  display: block;
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink-mute);
}

.top-stats {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

/* Stat pills use tabular figures so the numbers do not jitter as they change */
.stat {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  background: var(--s-2);
  border: 1px solid var(--line);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-mute);
}

.stat b { color: var(--ink); font-weight: 700; }
.stat.is-fire b { color: #fb923c; }
.stat.is-gem b { color: var(--brand-lift); }

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--sp-7) var(--sp-5) var(--sp-9);
}

.section { margin-top: var(--sp-8); }

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-5);
  margin-bottom: var(--sp-5);
}

.section-head h2 { font-size: var(--t-2xl); margin-top: 6px; }
.section-head p { color: var(--ink-mute); font-size: var(--t-sm); margin-top: 4px; max-width: 62ch; }

/* ------------------------------------------------------------- continue */

.continue-row {
  display: grid;
  grid-template-columns: minmax(0, 1.85fr) minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: stretch;
}

.continue {
  position: relative;
  overflow: hidden;
  padding: var(--sp-6);
  border-radius: var(--r-lg);
  background:
    radial-gradient(120% 140% at 100% 0%, rgba(139, 92, 246, 0.16), transparent 58%),
    var(--s-2);
  border: 1px solid var(--brand-edge);
}

.continue-where {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brand-lift);
}

.continue-where span { color: var(--ink-mute); }

.continue h1 {
  font-size: var(--t-3xl);
  margin: var(--sp-3) 0 var(--sp-2);
}

.continue-goal {
  color: var(--ink-body);
  font-size: var(--t-lg);
  max-width: 54ch;
}

.continue-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  margin: var(--sp-5) 0 var(--sp-2);
  font-size: var(--t-sm);
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}

.continue .bar { margin-bottom: var(--sp-5); }

.continue-actions { display: flex; align-items: center; gap: var(--sp-3); }

/* Step-type legend: makes the 20/80 shape of a unit visible before entering */
.step-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

.step-dot {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 600;
  background: var(--s-3);
  border: 1px solid var(--line);
  color: var(--ink-mute);
}

.step-dot.done { background: var(--ok-wash); border-color: var(--ok-edge); color: var(--ok); }
.step-dot.now { background: var(--brand-wash); border-color: var(--brand-edge); color: var(--brand-lift); }

.side-stack { display: flex; flex-direction: column; gap: var(--sp-4); }

.side-card {
  padding: var(--sp-5);
  border-radius: var(--r-md);
  background: var(--s-2);
  border: 1px solid var(--line);
  flex: 1;
}

.side-card h3 { font-size: var(--t-md); margin-bottom: var(--sp-2); }
.side-card p { font-size: var(--t-sm); color: var(--ink-mute); }

.side-card.is-due { border-color: var(--warn-edge); background: linear-gradient(var(--warn-wash), var(--warn-wash)), var(--s-2); }

.due-list { display: flex; flex-wrap: wrap; gap: 6px; margin: var(--sp-3) 0 var(--sp-4); }

.ratio { display: flex; gap: 3px; margin-top: var(--sp-3); }
.ratio span {
  height: 28px;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  font-size: var(--t-xs);
  font-weight: 700;
  color: var(--ink);
}
.ratio .r-theory { background: var(--info-wash); color: var(--info); border: 1px solid rgba(96, 165, 250, 0.3); }
.ratio .r-practice { background: var(--brand-wash); color: var(--brand-lift); border: 1px solid var(--brand-edge); }

/* ---------------------------------------------------------------- track */

.track {
  display: grid;
  /* auto-fit, not a fixed six: the course is seven levels now and any hard
     count silently squeezes or orphans a card the next time one is added. */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--sp-3);
}

/* Tinted with the level's own accent from curriculum.js, the same way the
   landing draws it — six identical grey tiles gave a learner nothing to
   recognise a level by. */
.level {
  --accent: var(--brand-lift);
  position: relative;
  padding: var(--sp-4);
  border-radius: var(--r-md);
  overflow: hidden;
  background:
    radial-gradient(120% 130% at 12% 0%,
      color-mix(in srgb, var(--accent) 14%, transparent), transparent 62%),
    var(--s-1);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.level:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--accent) 46%, transparent);
}

.level-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.level .level-num { color: var(--accent); }

/* 26px, not 22px. This is a decorative watermark and its tint sits around
   3.5:1 — below the 4.5 AA threshold for normal text, but above the 3:1 one
   for large text, which starts at 24px. Sizing up keeps it a watermark and
   makes it pass; darkening it enough to pass at 22px would have made it loud
   enough to compete with the level name. */
.level-glyph {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1;
  color: color-mix(in srgb, var(--accent) 70%, transparent);
}

.level.is-live, .level.is-next { background: var(--s-2); }
.level.is-planned { opacity: 0.62; }

.level-num {
  font-family: var(--font-code);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  letter-spacing: 0.1em;
}

.level h3 { font-size: var(--t-md); margin: var(--sp-2) 0 2px; }
.level .level-sub { font-size: var(--t-xs); color: var(--ink-mute); min-height: 2.4em; }

.level .bar { margin-top: var(--sp-3); }
.level-foot {
  display: flex;
  justify-content: space-between;
  margin-top: var(--sp-2);
  font-size: var(--t-xs);
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- units */

.units {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: var(--sp-3);
}

.unit {
  display: block;
  padding: var(--sp-4);
  border-radius: var(--r-md);
  background: var(--s-2);
  border: 1px solid var(--line);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.unit:hover:not(.locked) { transform: translateY(-2px); border-color: var(--s-5); }
.unit.current { border-color: var(--brand); background: linear-gradient(var(--brand-wash), var(--brand-wash)), var(--s-2); }
.unit.done { border-color: var(--ok-edge); }
.unit.locked { opacity: 0.45; cursor: not-allowed; }

.unit-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--sp-3);
}

.unit-n {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border-radius: var(--r-sm);
  background: var(--s-4);
  font-family: var(--font-code);
  font-size: var(--t-sm);
  font-weight: 700;
  color: var(--ink-mute);
}

.unit.done .unit-n { background: var(--ok-wash); color: var(--ok); }
.unit.current .unit-n { background: var(--brand); color: #fff; }

.unit h3 { font-size: var(--t-md); margin-bottom: 4px; }
.unit p { font-size: var(--t-sm); color: var(--ink-mute); }
.unit .bar { margin-top: var(--sp-3); }

/* --------------------------------------------------------------- skills */

.skills {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--sp-3);
}

.skill {
  padding: var(--sp-4);
  border-radius: var(--r-md);
  background: var(--s-2);
  border: 1px solid var(--line);
}

.skill-top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: var(--sp-3); }
.skill-top span { font-size: var(--t-sm); color: var(--ink); font-weight: 600; }
.skill-top b { font-size: var(--t-sm); color: var(--ink-mute); font-variant-numeric: tabular-nums; }
.skill small { display: block; margin-top: var(--sp-2); font-size: var(--t-xs); color: var(--ink-faint); }
.skill.is-due { border-color: var(--warn-edge); }
.skill.is-due small { color: var(--warn); }

/* ------------------------------------------------------------- projects */
/* The four briefs that end the level, and the one band on this page that is
   deliberately NOT a card in the grid.
   A learner scrolls past twenty-four identical unit cards; the thing they will
   put in front of an employer cannot look like the twenty-fifth. So this
   breaks out of the section rhythm: its own floor pulled edge to edge, a rule
   above and below it, one project per row instead of a grid, a set number in
   display weight, and each brief in its OWN accent rather than in the level's
   violet — four colours read as a set of four, one colour reads as more units. */
.projects-band {
  position: relative;
  /* Pulled out to the page edge by exactly the wrap own padding, so the band
     reaches the rule on both sides and never one pixel further — a phone that
     scrolls sideways is the bug this shape invites. */
  margin-inline: calc(var(--sp-5) * -1);
  padding: var(--sp-8) var(--sp-5) calc(var(--sp-8) + var(--sp-2));
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(168, 85, 247, 0.10), transparent 62%),
    var(--s-1);
  border-block: 1px solid var(--line);
}

.projects-head { max-width: 68ch; margin-bottom: var(--sp-6); }
.projects-head h2 {
  margin-top: 6px;
  font-size: var(--t-3xl, var(--t-2xl));
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.projects-head p { margin-top: var(--sp-3); color: var(--ink-mute); font-size: var(--t-sm); line-height: 1.65; }

.projects { display: grid; gap: var(--sp-3); }

.project {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr) 190px;
  gap: var(--sp-5);
  align-items: center;
  padding: var(--sp-5);
  border-radius: var(--r-lg);
  background: var(--s-2);
  /* The accent lives on one edge rather than all four: a full accent border on
     four cards in four colours is a fruit bowl, a rail reads as a spine. */
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  color: inherit;
  text-decoration: none;
  transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}
a.project:hover {
  transform: translateY(-2px);
  background: var(--s-3);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  border-left-color: var(--accent);
}
.project.is-locked { opacity: 0.5; cursor: not-allowed; }

/* The number is the loudest thing in the row, which is the point: these are
   numbered work, not a menu. */
.project-mark { text-align: center; }
.project-mark b {
  display: block;
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--accent);
}
.project-mark span {
  display: block;
  margin-top: 6px;
  font-family: var(--font-code);
  font-size: var(--t-sm);
  color: var(--ink-faint);
}

.project-body h3 {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  letter-spacing: -0.01em;
}
.project-body p { margin-top: 4px; color: var(--ink-body); font-size: var(--t-sm); line-height: 1.6; max-width: 62ch; }

.project-proves { margin: var(--sp-3) 0 0; padding: 0; list-style: none; display: grid; gap: 3px; }
.project-proves li {
  position: relative;
  padding-left: 18px;
  font-size: var(--t-xs);
  color: var(--ink-mute);
  line-height: 1.55;
}
.project-proves li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--accent);
  font-size: 10px;
}

.project-side { display: grid; gap: var(--sp-3); justify-items: end; text-align: right; }
.project-stack { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }
.project-stack code {
  padding: 2px 7px;
  border-radius: var(--r-sm);
  background: var(--s-3);
  border: 1px solid var(--line);
  color: var(--ink-mute);
  font-family: var(--font-code);
  font-size: 11px;
}
.project-hours {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.project-go { white-space: nowrap; }
.project-lock strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  color: var(--ink-faint);
}
.project-lock span { font-size: var(--t-xs); color: var(--ink-faint); }

@media (max-width: 860px) {
  /* Stacked, and the number goes inline with the title: a 92px column beside a
     190px column leaves a phone nothing for the sentence in between. */
  .project { grid-template-columns: 56px minmax(0, 1fr); gap: var(--sp-4); align-items: start; }
  .project-mark b { font-size: 28px; }
  .project-side {
    grid-column: 1 / -1;
    grid-auto-flow: column;
    justify-items: start;
    justify-content: space-between;
    align-items: center;
    text-align: left;
    width: 100%;
  }
  .project-stack { justify-content: flex-start; }
}

/* The AI track: shown as a real destination, styled as clearly not-yet-open
   so it reads as a promise about sequencing rather than available content. */
.next-track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--sp-3);
}

/* One card per AI branch. The dashed outline read as an unfinished
   placeholder; a solid panel tinted with the branch's own accent matches how
   the landing page presents the same five branches. */
.next-track article {
  --accent: var(--brand-lift);
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-radius: var(--r-md);
  background: var(--s-1);
  border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
}

.next-track span {
  flex: none;
  font-family: var(--font-code);
  font-size: var(--t-sm);
  font-weight: 700;
  /* --brand-lift at full opacity: the accent at 0.8 measured 3.44:1 here. */
  color: var(--brand-lift);
}

.next-track article h3 {
  margin: 0 0 var(--sp-2);
  font-size: var(--t-md);
}

.next-track article ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 6px;
}

.next-track article li {
  position: relative;
  padding-left: 13px;
  font-size: var(--t-sm);
  line-height: 1.5;
  color: var(--ink-mute);
}

/* A short rule in the branch colour instead of a bullet — bullets at this
   size on a dark panel read as noise. */
.next-track article li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 7px;
  height: 1.5px;
  border-radius: 1px;
  background: var(--accent);
  opacity: 0.8;
}

.foot {
  margin-top: var(--sp-9);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line-soft);
  display: flex;
  justify-content: space-between;
  font-size: var(--t-sm);
  color: var(--ink-faint);
}

@media (max-width: 1000px) {
  .continue-row { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .wrap { padding: var(--sp-5) var(--sp-4) var(--sp-8); }
  /* The wrap narrows on a phone; the band has to narrow with it. */
  .projects-band { margin-inline: calc(var(--sp-4) * -1); padding-inline: var(--sp-4); }
  .continue { padding: var(--sp-5); }
  .continue h1 { font-size: var(--t-2xl); }
  .top-stats .stat.is-hideable { display: none; }

  /* The header was 97px wider than a 375px phone: brand, four stat pills and
     the language switcher were all on one non-wrapping row. Let it wrap and
     let the switcher take the second line — a learner on a phone should not
     have to scroll sideways to see the page they are on. */
  .top {
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
  }

  .top-stats {
    width: 100%;
    margin-left: 0;
    flex-wrap: wrap;
    justify-content: flex-start;
  }

  .stat { padding: 5px 9px; font-size: var(--t-xs); }
  .lang-switch { margin-left: auto; }
}

/* Below ~380px even the wrapped row is tight, so the streak and gem pills go;
   XP is the one number worth keeping on the smallest screens. */
@media (max-width: 380px) {
  .top-stats .stat.is-gem { display: none; }
}

/* The Arena card. Marked, not shouted: it is the one card on the hub with a
   deadline, and a weekly deadline nobody notices is one nobody enters. */
.side-card.is-arena {
  border-color: var(--brand-edge);
  background: linear-gradient(160deg, var(--brand-wash), var(--s-2));
}

.arena-standing {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}

.arena-standing span { font-size: var(--t-xs); color: var(--ink-mute); text-transform: uppercase; letter-spacing: 0.08em; }
.arena-standing b { font-family: var(--font-code); font-size: var(--t-lg); color: var(--brand-lift); font-variant-numeric: tabular-nums; }


/* The date under "nothing to review". Quiet, but present: the absence of a
   review is only useful information when it comes with when the next one
   lands. */
.review-next {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line-soft);
  font-size: var(--t-sm);
  color: var(--brand-lift);
}

/* Units still being written carry a dot instead of a number. A number in a
   sequence is a promise that the step exists; giving one to an empty placeholder
   is what made finishing unit 2 lead to unit 4. */
.unit-n.is-planned {
  background: transparent;
  color: var(--ink-faint);
  box-shadow: inset 0 0 0 1px var(--line);
}

/* Badges already held.
 *
 * THE BOX HAD TO GO. Each shield used to sit inside a rounded rectangle with
 * its own border, so the eye met a card first and a medal second — two
 * containers competing, with dead space round the shield's point where the
 * card kept going and the shield did not. A struck object does not come in a
 * box; it sits on the surface and casts a shadow onto it. So the shield IS the
 * card now: the drop shadow gives it height, and the hover lights it in the
 * level's own accent instead of drawing a rectangle round it.
 *
 * A grid rather than a wrapping flex row, because eight shields wrapping 5 + 3
 * leave a ragged second row that reads as a mistake. */
.badge-shelf {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: var(--sp-5) var(--sp-4);
  justify-items: center;
}
.badge-chip {
  display: block;
  line-height: 0;
  border-radius: 0;
  /* Two shadows: a tight one that seats the shield on the page, and a wide
     soft one in its own accent that reads as the metal catching light. */
  filter:
    drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))
    drop-shadow(0 2px 3px color-mix(in srgb, var(--accent, #A855F7) 22%, transparent));
  transition: transform var(--dur) var(--ease), filter var(--dur) var(--ease);
}
.badge-chip:hover {
  transform: translateY(-5px) scale(1.02);
  filter:
    drop-shadow(0 14px 26px rgba(0, 0, 0, 0.6))
    drop-shadow(0 0 18px color-mix(in srgb, var(--accent, #A855F7) 55%, transparent));
}
/* A shield is a pointed object; a rectangular focus ring round one is the box
   this design just removed, so the ring follows the metal instead. */
.badge-chip:focus-visible { outline: none; }
.badge-chip:focus-visible .unit-badge { filter: drop-shadow(0 0 0 2px var(--accent, #A855F7)); }

@media (prefers-reduced-motion: reduce) {
  .badge-chip, .badge-chip:hover { transition: none; transform: none; }
}

.badge-chip svg { width: 168px; height: auto; }
