/* ════════════════════════════════════════════════════════════════════════
   THE ACADEMY SKIN — the override layer that brings the Academy in line
   with the new Code page (public/css/codes-next.css).

   Loaded AFTER academy.css. It does not restate anything that already
   works; it corrects only what breaks the brand law
   (/Volumes/SSD II/Breathe Native/BRANDING.md):

     • PAINT, DON'T REFRACT (:6470) — glass is reserved for what you TAP.
       Every static surface here (status chips, state pills, draft tags,
       the lesson kind) drops its backdrop-filter and paints a directional
       gradient in its Domain's own accent instead.
     • NO PURE BLACK, NO PURE WHITE, EXCEPT TEXT (:7414) — the veils over
       the Academy artwork were near-black washes and the Tools of Light
       band was a pure-white one. Both are repainted in colour.
     • ONE RADIUS PLUS THE CAPSULE — 18px / 3px / 2px / 50% all collapse
       to --an-r, or to the capsule where the thing is a chip.
     • NO DROP SHADOWS, EVER — every box-shadow inside an Academy page is
       removed, including the two that were faking a rule with an inset.
     • CONTRAST IS BOUGHT WITH LIGHT, NOT WITH BLACK (:2161) — the hero
       type is lifted to the light end of the range and the scrim behind
       it is the Domain's own colour deepened, never a black veil. And it
       is never a full-cover wash: Arian's standing rule is "don't cover
       up the silver in the back of the hero image, put the writing over
       the image", so every scrim is bounded — it hugs the type column and
       feathers out, top, bottom and side, leaving the plate to read.

   Colour arrives as --accent / --accent-2, which the Academy routes
   already set on every Domain, Series and Module hero.
   ════════════════════════════════════════════════════════════════════════ */

/* .dstack is the front page's stack of Domain pads (domain-stack.css): the
   pads there are the hub's own, so they wear this skin too. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse, .dstack) {
  /* THE radius. One. Same value as the Code page's --cn-r. */
  --an-r: 20px;
  --an-accent: var(--accent, var(--cyan));
  --an-accent-2: var(--accent-2, var(--an-accent));
  /* The ground a scrim falls to: the Domain's colour DEEPENED, so the
     fall-off carries hue. Never #000 — a black floor is a crushed floor. */
  --an-deep: color-mix(in srgb, var(--an-accent) 20%, #0B0D12);
  --an-hair: rgba(255, 255, 255, .13);
  --an-surface: rgba(255, 255, 255, .06);
  /* The pool the sticky back arrow rests in. Barely tinted, because it
     travels above every band on the page, light or dark. */
  --an-rail: color-mix(in srgb, var(--an-accent) 8%, #0B0D12);
  /* The geometry is drawn by codes-next.css, which paints in --code-accent. */
  --code-accent: var(--an-accent);
}
/* ⚠️ A custom property is substituted where it is DECLARED, so declaring the
   trio once on <body> froze it at the fallback cyan — the Domain's own colour
   is set further down, on the hero section and on each tile. Re-declare it at
   every element the Academy routes paint --accent onto, and the colour
   resolves there instead. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse, .dstack)
  :is(.aca-hero, .aca-dhero, .aca-shero, .aca-mhero, .aca-lhero, .aca-sband,
      .card-domain, .opanel, .card-journey, .card-tool, .mi, .aca-meta, .ladder) {
  --an-accent: var(--accent, var(--cyan));
  --an-accent-2: var(--accent-2, var(--accent, var(--cyan)));
  --an-deep: color-mix(in srgb, var(--accent, var(--cyan)) 20%, #0B0D12);
  --code-accent: var(--accent, var(--cyan));
}
/* A light band flips the hairlines to ink, or the surfaces turn to milk. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) .env--light {
  --an-hair: rgba(10, 12, 18, .14);
  --an-surface: rgba(10, 12, 18, .05);
}

/* ════════════════════════════════════════════════════════════════════════
   NO DROP SHADOWS, EVER.
   A blanket, because a shadow that creeps back in from a shared component
   is exactly how this rule dies. Focus rings are re-drawn as outlines
   underneath, so nothing loses its keyboard indicator.
   ════════════════════════════════════════════════════════════════════════ */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) main *,
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) main *::before,
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) main *::after { box-shadow: none; }

:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) main :is(input, textarea, select):focus {
  outline: 1.5px solid var(--focus); outline-offset: 2px;
}

/* The two "shadows" that were really rules. Painted as stripes instead, so
   they cost nothing and break no law. (These two carry their own rule rather
   than the blanket's, because a two-class selector outranks it.) */
:is(.page-academy, .page-domain, .page-series, .page-module) .ladder__step.is-current {
  box-shadow: none;
  background:
    linear-gradient(180deg, var(--accent, var(--electric)) 0 2px, transparent 2px),
    linear-gradient(172deg, color-mix(in srgb, var(--accent, var(--electric)) 13%, transparent), transparent 66%);
}
:is(.page-module, .page-lesson, .page-series) .lesson.is-current {
  box-shadow: none;
  background: linear-gradient(90deg, var(--accent, var(--electric)) 0 2px, transparent 2px);
}

/* ════════════════════════════════════════════════════════════════════════
   PAINT, DON'T REFRACT.
   Status chips, state pills, draft tags and the lesson-kind pill are read,
   not tapped. They lose the lens and gain a 158° painted gradient that
   runs accent → accent-2 and falls away, the same move the Code page's
   folds make.
   ════════════════════════════════════════════════════════════════════════ */
/* ⚠️ :not() on the three word-only badges, deliberately. They are not bubbles
   at all — they are single words painted with background-clip:text, and any
   `background:` shorthand written after theirs resets background-clip to
   border-box and turns the word into a filled lozenge with invisible type.
   Leave their rules in academy.css alone rather than restating them here. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse)
  :is(.stage, .state, .aca-lhero__kind):not(.stage--domain):not(.stage--done):not(.opanel__chip) {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background:
    linear-gradient(158deg,
      color-mix(in srgb, var(--an-accent) 26%, transparent) 0%,
      color-mix(in srgb, var(--an-accent-2) 11%, transparent) 60%,
      transparent 100%);
}

/* The FREE chip this file used to repair is gone from the markup — Arian
   asked for it off the Orientation panel on 2026-09-21 — so its rules went
   with it rather than being left to rot. The shorthand trap it documented is
   still real and is written up on .aca-sband__num in academy.css. */

/* The draft tag sits on artwork and has to stay legible, so it paints in
   light rather than in the accent — ice, never pure white. */
:is(.page-academy, .page-domain, .page-series, .page-module) .draft-tag {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: linear-gradient(158deg, rgba(240, 243, 246, .94), rgba(211, 216, 222, .84) 74%);
}

/* ════════════════════════════════════════════════════════════════════════
   ONE RADIUS PLUS THE CAPSULE.
   Before: 999px, 18px, 50%, 3px, 2px. After: --an-r and the capsule.
   Cards and panels take the radius; anything chip-shaped takes the pill.
   ════════════════════════════════════════════════════════════════════════ */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse, .dstack)
  :is(.card-domain, .opanel, .card-journey, .card-tool, .mi, .aca-locked, .bones,
      .paywall__glass, .tol-grid, .aca-prose img, .aca-prose video, .prose img, .prose video) {
  border-radius: var(--an-r);
}
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse)
  :is(.draft-tag, .card__pro, .aca-focus li, .mi__rel li,
      .aca-stamp, .lbtn, .lesson__done, .prose code, .art__slot-mark, .plate__orb) {
  border-radius: var(--r-pill);
}
/* A rounded card has to clip what it paints inside itself. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-youniverse)
  :is(.card-journey, .aca-locked) { overflow: hidden; }

/* ════════════════════════════════════════════════════════════════════════
   TYPE OVER ARTWORK.
   Arian: the words over the plates are hard to read. The brand answer is
   range — lift the ink to the light end and let the scrim be the Domain's
   own colour, not a black sheet. The scrim is cut to the type column and
   feathered on every side, so the plate reads above it, below it and past
   its right edge.
   ════════════════════════════════════════════════════════════════════════ */

/* ⚠️ THE OPERATOR MATTERS MORE THAN THE COLOUR.
   The old veils painted OVER the plate at normal blend, which does not just
   darken the highlights — it LIFTS the shadows, so the quiet dark half of
   every plate came up as one flat field and the silver in it disappeared.
   That is what "washed" means and it is the thing Arian keeps objecting to.
   Multiply cannot lift anything: it scales the plate by the Domain's own
   colour, so a bright plasma burst falls far and the dark detail beside it
   keeps its ratio. The picture is still there — it is the RANGE that moved,
   which is the brand's own definition of buying contrast (:2161). The light
   half of the buy is a separate screen layer on the media wrapper. */

/* — The hub hero, with the Domain plates cross-fading behind it ————— */
.page-academy .aca-hero__art { isolation: isolate; }
.page-academy .aca-hero__veil {
  mix-blend-mode: multiply;
  background:
    linear-gradient(99deg,
      color-mix(in srgb, var(--an-deep) 90%, transparent) 0%,
      color-mix(in srgb, var(--an-deep) 88%, transparent) 44%,
      color-mix(in srgb, var(--an-deep) 78%, transparent) 66%,
      color-mix(in srgb, var(--an-deep) 42%, transparent) 84%,
      transparent 96%);
  /* never a full cover: the plate keeps its head and its foot */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 90%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 90%, transparent 100%);
}
/* The light half: the accent's own glow at the near corner. Screen, so it can
   only add — the floor never gets crushed to buy it. */
.page-academy .aca-hero__art::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  mix-blend-mode: screen;
  background: radial-gradient(64% 58% at 3% 88%, color-mix(in srgb, var(--an-accent) 22%, transparent), transparent 74%);
}
/* The type's own separation: a tight contact shade in the Domain's deep,
   not a 44px black halo. */
.page-academy .aca-hero__art ~ .aca-hero__inner :is(.aca-hero__title, .aca-hero__sub, .aca-hero__intro, .eyebrow, .hud-list) {
  text-shadow: 0 1px 2px color-mix(in srgb, var(--an-deep) 88%, transparent);
}
/* Lift, don't veil. */
.page-academy .aca-hero__art ~ .aca-hero__inner :is(.aca-hero__sub, .aca-hero__intro .prose) { color: var(--fg); }

/* — The Domain hero ————————————————————————————————————————————————— */
.page-domain .aca-dhero__veil {
  mix-blend-mode: multiply;
  background:
    linear-gradient(99deg,
      color-mix(in srgb, var(--an-deep) 90%, transparent) 0%,
      color-mix(in srgb, var(--an-deep) 89%, transparent) 46%,
      color-mix(in srgb, var(--an-deep) 80%, transparent) 68%,
      color-mix(in srgb, var(--an-deep) 44%, transparent) 85%,
      transparent 97%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 8%, #000 91%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 8%, #000 91%, transparent 100%);
}
.page-domain .aca-dhero__media::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  mix-blend-mode: screen;
  background: radial-gradient(58% 58% at 4% 86%, color-mix(in srgb, var(--an-accent) 22%, transparent), transparent 74%);
}
/* A phone crops a 3:2 plate to a tall slice, so the type runs almost edge to
   edge and the hot part of the picture ends up under the tail of every line.
   The column widens with it; the head and the foot of the plate still read. */
@media (max-width: 760px) {
  .page-domain .aca-dhero__veil,
  .page-academy .aca-hero__veil {
    background:
      linear-gradient(99deg,
        color-mix(in srgb, var(--an-deep) 90%, transparent) 0%,
        color-mix(in srgb, var(--an-deep) 90%, transparent) 62%,
        color-mix(in srgb, var(--an-deep) 84%, transparent) 82%,
        color-mix(in srgb, var(--an-deep) 54%, transparent) 94%,
        transparent 100%);
  }
}
.page-domain .aca-dhero__media ~ .aca-dhero__inner :is(.aca-dhero__title, .aca-dhero__sub, .aca-dhero__goal, .aca-dhero__purpose, .aca-dhero__tf, .crumbs) {
  text-shadow: 0 1px 2px color-mix(in srgb, var(--an-deep) 88%, transparent);
}
.page-domain .aca-dhero__media ~ .aca-dhero__inner :is(.aca-dhero__goal, .aca-dhero__purpose, .aca-dhero__sub) { color: var(--fg); }
.page-domain .aca-dhero__media ~ .aca-dhero__inner .aca-dhero__tf { color: var(--fg); }
/* Swapped, 2026-09-21: the LABEL is white and the VALUE carries the colour.
   -webkit-text-fill-color has to be cleared too, or it outranks `color` on
   the label and leaves it transparent. */
.page-domain .aca-dhero__media ~ .aca-dhero__inner .aca-dhero__tf em { color: var(--fg); -webkit-text-fill-color: currentColor; }

/* — The Orientation panel ——————————————————————————————————————————
   The plate arrives with its light column on the right. The wash used to
   run to near-black across the whole left half; now it is the Domain's
   deep, and it stops at 58% so the column is untouched. */
.page-academy .opanel__art::after {
  mix-blend-mode: multiply;
  background:
    linear-gradient(96deg,
      color-mix(in srgb, var(--an-deep) 92%, transparent) 0%,
      color-mix(in srgb, var(--an-deep) 88%, transparent) 34%,
      color-mix(in srgb, var(--an-deep) 50%, transparent) 48%,
      transparent 62%);
}
@media (max-width: 900px) {
  .page-academy .opanel__art::after {
    background:
      linear-gradient(180deg,
        transparent 0%,
        color-mix(in srgb, var(--an-deep) 44%, transparent) 38%,
        color-mix(in srgb, var(--an-deep) 88%, transparent) 66%,
        color-mix(in srgb, var(--an-deep) 94%, transparent) 100%);
  }
}

/* — The Domain tiles on the hub ————————————————————————————————————
   Before, a 4,5,7 wash lay over the whole picture and crushed to .94 at
   the foot. Now the top third is untouched and the foot is the Domain's
   own colour, deepened. */
:is(.page-academy, .page-domain, .dstack) .card-domain__art::after {
  mix-blend-mode: multiply;
  background:
    linear-gradient(180deg,
      transparent 0%,
      transparent 30%,
      color-mix(in srgb, var(--an-deep) 46%, transparent) 54%,
      color-mix(in srgb, var(--an-deep) 86%, transparent) 78%,
      color-mix(in srgb, var(--an-deep) 94%, transparent) 100%);
}
:is(.page-academy, .page-domain, .dstack) .card-domain__art::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  mix-blend-mode: screen;
  background: radial-gradient(92% 52% at 14% 100%, color-mix(in srgb, var(--an-accent) 20%, transparent), transparent 74%);
}

/* — The Tools of Light band ————————————————————————————————————————
   Its plate wash was pure white at .76/.82 — a full cover in the one
   colour the brand law forbids on a surface. Repainted in ice, and opened
   up through the middle so the picture is there at all. */
.page-academy .aca-meta__media::after {
  background:
    linear-gradient(94deg, rgba(237, 240, 243, .72) 0%, rgba(237, 240, 243, .4) 32%, rgba(237, 240, 243, .14) 52%, rgba(237, 240, 243, .44) 78%, rgba(237, 240, 243, .78) 100%),
    linear-gradient(180deg, rgba(237, 240, 243, .46) 0%, rgba(226, 230, 235, .1) 36%, rgba(237, 240, 243, .3) 100%);
}
.page-academy .aca-meta--plated :is(.sec-head__titles > *, .sec-head__action) {
  text-shadow: 0 1px 10px rgba(237, 240, 243, .95);
}
:is(.page-academy, .dstack) .card-domain--meta.card-domain--plated .card-domain__art::after {
  background: linear-gradient(180deg, rgba(237, 240, 243, 0) 0%, rgba(237, 240, 243, .46) 46%, rgba(237, 240, 243, .84) 76%, rgba(237, 240, 243, .95) 100%);
}

/* ════════════════════════════════════════════════════════════════════════
   THE WAY BACK.
   The sticky arrow has height 0 and z-index 12, so on a long Academy hero
   it drew straight through the body text scrolling under it. It keeps its
   stickiness — that is the point of it — and gains a small painted scrim
   that travels with it: bounded to the arrow itself (it carries no word
   now), feathered on every side. Nothing else on the plate is covered.
   ════════════════════════════════════════════════════════════════════════ */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) .page-back::before {
  content: ''; position: absolute; z-index: -1; pointer-events: none;
  left: calc(var(--gutter) * -.4); top: -1.2rem; height: 4.4rem;
  width: 5rem;
  /* A radial, so it feathers on all four sides — a pool of light the word
     sits in, not a bar across the plate. Barely tinted: this rail sits
     outside the hero, where no Domain has claimed the colour yet. */
  background: radial-gradient(62% 56% at 26% 50%,
    color-mix(in srgb, var(--bg) 92%, transparent) 0%,
    color-mix(in srgb, var(--bg) 64%, transparent) 46%,
    transparent 80%);
}
/* Over a dark band the pool goes with it — app.js already tells the arrow
   which kind of ground it is standing on. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) .page-back:has(.back-link.over-dark)::before {
  background: radial-gradient(62% 56% at 26% 50%,
    color-mix(in srgb, var(--an-rail) 86%, transparent) 0%,
    color-mix(in srgb, var(--an-rail) 58%, transparent) 46%,
    transparent 80%);
}
/* With a scrim of its own the arrow no longer needs a black halo. */
:is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
    .page-journeys, .page-journey, .page-youniverse) .back-link.over-dark {
  color: #f2f4f7;
  text-shadow: 0 1px 2px color-mix(in srgb, var(--an-deep) 86%, transparent);
}
/* And the heroes give it a lane to rest in, so at the top of the page it
   sits over the plate rather than over the first line of the heading. */
@media (max-width: 760px) {
  :is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
      .page-journeys, .page-journey, .page-youniverse).has-back
    :is(.aca-hero__inner, .aca-dhero__inner, .aca-shero__inner, .aca-mhero__inner, .aca-lhero) {
    padding-top: calc(var(--nav-h) + 4.4rem);
  }
}
@media (min-width: 761px) {
  :is(.page-academy, .page-domain, .page-series, .page-module, .page-lesson,
      .page-journeys, .page-journey, .page-youniverse).has-back
    :is(.aca-hero__inner, .aca-dhero__inner, .aca-shero__inner, .aca-mhero__inner, .aca-lhero) {
    padding-top: calc(var(--nav-h) + clamp(3.4rem, 7vw, 5.6rem));
  }
}
/* ⚠️ A LESSON NEVER GOT ITS LANE. Its hero pads the SECTION, not an __inner,
   and rhythm.css's [class*="hero"]:not(.hero):not([class*="__"]) is the same
   (0,3,0) as the two rules above and loads last — so it won, the Lesson's
   hero kept 32px under the bar, and the arrow sat on the breadcrumb. The
   __inner heroes never matched that rule, which is why only Lessons showed
   it. Doubled class, the way .aca-dhero__inner.wrap gets out of it. */
@media (max-width: 760px) {
  .page-lesson.has-back .aca-lhero.env { padding-top: calc(var(--nav-h) + 4.4rem); }
}
@media (min-width: 761px) {
  .page-lesson.has-back .aca-lhero.env { padding-top: calc(var(--nav-h) + clamp(3.4rem, 7vw, 5.6rem)); }
}

/* ════════════════════════════════════════════════════════════════════════
   LIVING GEOMETRY.
   The Series, Module and Lesson heroes carry no plate at all — they were
   flat panels of --bg. They get the Code page's breathing sacred geometry
   instead, drawn by codes-next.css from the same .geo classes, in the
   Domain's own accent. The Domain hero gets it too, held right back where
   a cover plate is already doing the work.

   ⚠️ MARKUP THE MAIN SESSION STILL OWES THIS: the Series and Lesson heroes
   already render <div class="aca-hero__geo">…</div> (src/routes/academy.js
   :303, :665). The DOMAIN hero (.aca-dhero) and the MODULE hero
   (.aca-mhero) do not, and everything below is written for it. The line is
   the same one, as the first child of the section:
     <div class="aca-hero__geo" aria-hidden="true">
       ${geometry(domain.slug, { size: 760 })}
     </div>
   ════════════════════════════════════════════════════════════════════════ */
/* codes-next.css already carries .aca-hero__geo — its box, its opacity and the
   accent stroke. Two things it cannot know are added here:
     • .geo__node fills with var(--code-accent) and has NO fallback, so on an
       Academy page the travelling nodes of the `orbits` form computed to black.
       The --code-accent declaration at the top of this file gives them the
       Domain's colour.
     • Over a photographic plate .34 is a second picture rather than a
       backdrop. Behind a Domain cover it drops to a whisper. */
.page-domain .aca-dhero:has(.aca-dhero__media) .aca-hero__geo { opacity: .1; }
/* The Module hero is not in codes-next's isolation list. */
:is(.page-module, .page-journey) .aca-mhero { position: relative; isolation: isolate; }
:is(.page-module, .page-journey) .aca-mhero > .wrap { position: relative; z-index: 1; }

/* A painted ground under the geometry, so the Series and Module heroes
   are a lit room rather than a flat panel. Directional, in the Domain's
   accent, falling away — the Code page's own recipe. */
:is(.page-series, .page-module, .page-lesson, .page-journey) :is(.aca-shero, .aca-mhero, .aca-lhero) {
  background:
    radial-gradient(112% 88% at 82% 4%, color-mix(in srgb, var(--an-accent) 17%, transparent), transparent 64%),
    linear-gradient(158deg, var(--bg) 0%, color-mix(in srgb, var(--an-deep) 46%, var(--bg)) 66%, var(--an-deep) 100%);
}
.page-domain .aca-dhero:not(:has(.aca-dhero__media)) {
  background:
    radial-gradient(112% 88% at 82% 4%, color-mix(in srgb, var(--an-accent) 17%, transparent), transparent 64%),
    linear-gradient(158deg, var(--bg) 0%, color-mix(in srgb, var(--an-deep) 46%, var(--bg)) 66%, var(--an-deep) 100%);
}

/* Series and Module numbers and rules pick up the Domain's colour, the way
   the Code page's numeral does. */
:is(.page-series, .page-module, .page-lesson) :is(.aca-shero__num, .aca-mhero__num, .aca-lhero__num) { color: var(--an-accent); }
@supports (-webkit-background-clip: text) or (background-clip: text) {
  :is(.page-series, .page-module, .page-lesson) :is(.aca-shero__num, .aca-mhero__num, .aca-lhero__num) {
    /* width + background-size, for the reason written out at .ladder__num in
       academy.css: the paint is clipped to the letters but SIZED to the box,
       and these are block <p> elements filling the hero — the ramp was spread
       across the whole page width under a line of small type, so it read as
       one flat colour. 90deg, not 135: over a single short line a diagonal
       spends most of its range above and below the letters.
       repeat-y covers any glyph that overruns its line box. */
    width: fit-content;
    background-image: linear-gradient(90deg, var(--an-accent), var(--an-accent-2));
    background-size: calc(100% - .02em) 100%; background-repeat: repeat-y;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
  }
}
/* ⚠️ --accent, NOT --an-accent, on these two: they sit on the ICE band,
   where no Domain has set --accent, so the cyan fallback measured 1.3:1 on
   #edf0f3 — worse than the electric they already had (3.9:1). Fall back to
   the electric and only take the Domain's colour when there actually is one. */
:is(.page-module, .page-lesson) .mod__principle,

/* ════════════════════════════════════════════════════════════════════════
   THE SMALL PANELS, painted rather than outlined in nothing.
   Same 158° fall-off as the Code page's folds, so an Academy panel and a
   Code fold are visibly the same object.
   ════════════════════════════════════════════════════════════════════════ */
:is(.page-module, .page-lesson, .page-series, .page-domain) :is(.aca-locked, .bones) {
  border-color: var(--an-hair);
  background: linear-gradient(158deg, var(--an-surface), transparent 70%);
}
/* The YOUNIVERSE carries the Academy's Journeys band now (routes/pages.js),
   so its cards wear the same wash. */
:is(.page-academy, .page-domain, .page-youniverse) .card-journey {
  border-color: var(--an-hair);
  background: linear-gradient(158deg, color-mix(in srgb, var(--an-accent) 9%, var(--bg-2)), var(--bg-2) 70%);
}

/* ════════════════════════════════════════════════════════════════════════
   MOTION IS SLOW AND PREMIUM. The plate drift is a 9s linear ramp that
   stops dead at the end of its run; give it the house curve and let it
   breathe both ways instead.
   ════════════════════════════════════════════════════════════════════════ */
.page-academy .aca-hero--rotating .aca-hero__plate.is-on img {
  animation: acaDrift 18s cubic-bezier(.4, 0, .2, 1) both;
}
@keyframes acaDrift {
  from { transform: scale(1.02); }
  to   { transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  .page-academy .aca-hero--rotating .aca-hero__plate.is-on img { animation: none; }
}

/* ── The Domain page was a wall ───────────────────────────────────────────
   Four Series × ten Modules printed inline made SYSTEM RESET 16,000px tall
   on a phone. The Modules are folded now; these give the four bands room to
   breathe instead of running into each other. */
.aca-sband { padding-block: clamp(1.8rem, 5vw, 2.8rem); }
.aca-sband + .aca-sband { border-top: 1px solid var(--line); }
.aca-sband__head { align-items: start; gap: clamp(.8rem, 3vw, 1.4rem); margin-bottom: .9rem; }
.aca-sband__purpose { max-width: 42rem; margin-bottom: 1.1rem; }
.aca-sband__fold { margin-top: .4rem; }
/* Inside an Academy band the fold is ink, not white-on-dark. */
.env--light .cn-fold { border-color: var(--line); background: linear-gradient(158deg, rgba(10,12,18,.04), transparent 70%); }
.env--light .cn-fold > summary { color: var(--fg-2); }
.env--light .cn-fold[open] > summary { color: var(--fg); }
.env--light .cn-fold__body { color: inherit; }
.aca-sband__more { margin-top: 1.1rem; }

/* ── DECLUTTER ────────────────────────────────────────────────────────────
   Arian: "I see spacing issues and cluttered." Measured, then fixed. */

/* 1. Every Academy hero started at pixel 0 under a 68px fixed top bar, so
      the first lines of type were simply behind it. */
.aca-hero, .aca-dhero, .aca-shero, .aca-lhero, .aca-mhero {
  padding-top: calc(var(--nav-h) + clamp(1.2rem, 4vw, 2.4rem));
}

/* 2. The back link floats with height:0 and was drawing straight through
      hero body text. It keeps its no-box treatment; it just gets enough
      light behind it to stay legible over anything — contrast bought with
      light, per the brand guide, never a dark plate. */
.page-back > a {
  padding: .4rem .7rem .4rem 0;
  text-shadow: 0 0 18px rgba(0, 0, 0, .55), 0 0 6px rgba(0, 0, 0, .5);
}

/* 3. Domain tiles were 44% of the screen EACH — six of them made the hub a
      scroll marathon. Shorter, so three are in view at once. */
@media (max-width: 720px) {
  .card-domain .card__link, .card-domain > a { min-height: 0; }
  .card-domain { --tile-h: 230px; }
  .card-domain .card-domain__art, .card-domain picture, .card-domain img { max-height: var(--tile-h); }
}

/* 4. Section rhythm. Bands were running into each other with no breath
      between them and no line to say where one ended. */
.page-academy .section, .page-domain .section, .page-series .section { padding-block: clamp(2rem, 6vw, 3.6rem); }
.page-academy .section + .section, .page-domain .section + .section { border-top: 1px solid var(--line); }

/* 5. Chip rows wrapped into ragged stacks. One row, scrollable, on a phone. */
@media (max-width: 620px) {
  .aca-focus { display: flex; flex-wrap: wrap; gap: var(--s-1); }
  .aca-focus li { margin: 0; }
}

/* 6. The lesson list inside an open fold was flush to the edge. */
.cn-fold__body .aca-mods, .cn-fold__body .aca-focus { margin-top: .8rem; }
/* MODULES, and larger. Arian, 2026-09-21: "instead of 10 MODULES just have it
   say MODULES, and have it be larger." The word is set on the span rather
   than the summary so the +/- mark beside it keeps its own size. Only the
   Series band's fold — the Codes folds share .cn-fold and are left alone. */
.aca-sband__fold > summary > span { font-size: clamp(.9rem, 1.35vw, 1.15rem); letter-spacing: .14em; }

/* ── CONSISTENCY ──────────────────────────────────────────────────────────
   Arian: "consistency in sizes etc need fixing." Measured on the hub:
   the START HERE panel was 308px tall against the Domain tiles' 340px, its
   heading was 24px against their 17px, and its eyebrow 9px against their
   11px numeral. Three different sizes for the same job on one screen —
   which is the brand guide's own diagnosis of "multiple apps, not one app".
   Every value below is now the SAME value the Domain tiles already use. */
.opanel { min-height: 340px; }
.opanel__title { font-size: 17px; letter-spacing: .1em; line-height: 1.25; }
.opanel__label { font-size: 17px; letter-spacing: .1em; }

/* The tiles and the panel sit on one grid with one gap, so the rhythm down
   the page is even rather than ragged. */
.aca-domains .grid, .aca-domains .cards { gap: clamp(.9rem, 2.4vw, 1.2rem); }

/* On a phone the panel and the tiles are the same height, so scrolling past
   them has a beat instead of stuttering. */
@media (max-width: 720px) {
  .opanel, .card-domain { min-height: 230px; }
  .opanel__title, .card-domain__title { font-size: 16px; }
  .opanel__label { font-size: 16px; }
  .card-domain__num { font-size: 10px; }
}

/* ON A PHONE THE ARROW STAYS IN ITS LANE. Sticky, it rode over the first
   tile on the way down, so it was made a row of its own above the content —
   but the top bar is FIXED and see-through and every hero starts under it, so
   that row sat BENEATH the bar: at the top of a Module or a Lesson the arrow
   ran into the logo, and the bar's glass buttons washed out on the light
   strip the row left (Arian's photo of Lesson 01, 2026-09-23). Every hero
   already reserves a lane for the arrow under the bar (.has-back … padding-
   top, in components.css and above), so it is set in that lane, out of the
   flow, and scrolls away with the page instead of riding over the tiles. */
@media (max-width: 720px) {
  .page-back { position: absolute; left: 0; right: 0; top: calc(var(--nav-h) + 6px); height: 0; padding-block: 0; }
  .page-back > a { text-shadow: none; }
}

/* ── FOUR QUADRANTS ON A PHONE ────────────────────────────────────────────
   The rungs used to scroll sideways one at a time, like the Code deck.
   Arian, 2026-09-23: "kill the horizontal feature and fit all 4 series in a
   square with 4 quadrants that fit them all in one view." Two by two on a
   phone, four across on a wide screen; the hairlines are the grid's own gap
   over a ruled ground, so no rung draws a border of its own. */
.ladder {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
  margin: 0; padding: 0; overflow: visible;
  background: var(--line);
}
.ladder > .ladder__step { width: auto; background: var(--bg); border: 0; }
.ladder__step > a, .ladder__step > span { min-height: 0; }
/* The rung you are standing on is lit, so the deck has a place. */
.ladder__step.is-current { background: var(--bg-2, var(--bg)); box-shadow: none; }
.ladder__step.is-current > a, .ladder__step.is-current > span { border-top: 2px solid var(--accent, var(--electric)); }
@media (min-width: 900px) {
  .ladder { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 899px) {
  /* Small enough that the number and the name still share a line in a
     quadrant 176px wide — INTEGRATE is the longest. */
  .ladder__step > a, .ladder__step > span { padding: .85rem .7rem .95rem; gap: .2rem; }
  /* And if a name is ever too long even so, it drops under its number whole
     rather than breaking inside the word (INTEGRAT / E, on a 390 phone). */
  .ladder__head { flex-wrap: wrap; row-gap: .1rem; }
  .ladder__num { font-size: 1.2rem; }
  .ladder__title { font-size: .74rem; letter-spacing: .06em; overflow-wrap: normal; word-break: normal; hyphens: none; }
  .ladder__line { font-size: .72rem; line-height: 1.4; }
}
/* THE BAND FITS ITS RUNGS. It had 32px of its own padding and rhythm.css's
   64px on the .wrap inside — .section--tight is not .section, so the rule for
   plain bands reached it (0,4,0, loaded last) — 96px of ice above the rungs
   and 96 below on a phone. Five classes to get past it, as before. */
.aca-ladder.env.section--tight { padding-block: 0; }
.aca-ladder.env.env--light.section--tight > .wrap { padding-block: clamp(.9rem, 3vw, 1.6rem); }
