/* ============================================================================
   THE FIGURE SECTIONS — science, methodology, network (below, "section 2,
   3, 4" are these three, in that order, as in layers.js).
   One figure, pinned on the right, carries all three, so they read as one
   band-canvas (§11.2, one mechanism: a scroll-driven figure). It starts as
   the Radar canvas, turns into the hub's core, then gains its rays and its
   orbits.
   Markup: js/render/figure.js, science.js, method.js, network.js.
   Behaviour: js/behaviour/layers.js.

   Two modes:
   - Static (default): prefers-reduced-motion, or below 980px. Every
     element is in its final state; nothing depends on scroll (§8.3). The
     canvas sits beside section 2's text and the whole hub under it.
     Below 980px the whole hub is hidden and section 3 shows its own hub,
     core and rays only, with the four points in its corners.
   - Live (.layers.is-live, set by layers.js): the figure is pinned, and the
     scroll position drives it. Sections 2 and 3 never pin: their text rolls
     past the figure like a picker, and the figure holds still while a
     text is level with it and changes with the scroll in between.

   Recorded exceptions, decided by the client:
   - Above the {motion.slow} cap: counter count-up (1200ms), the section-4
     ring draw on first load (1.6s, the hub component's own entrance),
     the section-3 ray settle (900ms), shot (3s) and sparkle (1.8s), the
     section-4 ring draw (800ms).
   - Section 3 fires its rays at each point in turn until the reader picks
     one. The shots only sparkle; the text changes on a pick alone.
   ========================================================================= */

/* ============================================================================
   LAYOUT — text column left, figure column right, both inside the 1200px
   container.
   ========================================================================= */
.layers {
  /* tier-3, scoped */
  --layers-text: 610px;   /* the hero's text column, so the page keeps one measure */
  --layers-fig:  calc(var(--layout-container-max) - 2 * var(--space-6) - var(--space-12) - var(--layers-text));
  --layers-accent: color-mix(in srgb, var(--purple-700) 75%, var(--purple-300));   /* 9.0:1 on white */

  /* The spinning rays' box pokes past the screen edge (the beams are
     transparent there). clip, not hidden: hidden would break position: sticky. */
  overflow-x: clip;
  display: grid;
  /* the left gutter keeps room for the conduit's lane (conduit.css) */
  grid-template-columns:
    minmax(var(--conduit-lane, var(--space-6)), 1fr)
    [text-start] minmax(0, var(--layers-text)) [text-end]
    var(--space-12)
    [fig-start] minmax(0, var(--layers-fig)) [fig-end]
    minmax(var(--space-6), 1fr);
}

/* Static: the hub has a row of its own, under section 2 (whose own figure
   is the canvas). Live mode pins it beside all three (LIVE MODE below). */
.layer,
.stage          { grid-column: text-start / fig-end; }
.layer--science { grid-row: 1; }
.stage          { grid-row: 2; }
.layer--method  { grid-row: 3; }
.layer--network { grid-row: 4; }

/* ============================================================================
   THE FIGURE — hub and Radar canvas share one box
   ========================================================================= */
.stage__pin {
  height: 100%;
  display: grid;
  place-items: center;
}
.stage__fig {
  position: relative;
  width: min(100%, 640px);
}
.stage__canvas { display: none; }   /* static mode shows the canvas in section 2 */

/* Two layers of the hub fade with the scroll (--o-*, layers.js). */
.stage {
  --o-rays: 1;
  --o-orbits: 1;
}
.stage .hub__svg    { opacity: var(--o-rays); }
.stage .hub__orbits { opacity: var(--o-orbits); }

/* Faded out by the scroll: out of hover too. */
.stage[data-rays-off] .hub__svg { visibility: hidden; }

/* The rays turn under the pointer, so the component's own hover lift would
   flicker as a ray slides away: switched off. */
.stage .hub__band { pointer-events: none; }
.stage .hub__sector:hover { transform: none; }

/* The layer a section introduces grows a little while that section is on
   screen (data-accent, scroll). The stage stops clipping so the outer ring
   has room to grow. */
.stage .hub__stage { overflow: visible; }
.stage .hub__svg,
.stage .hub__orbits { transition: scale var(--motion-slow); }
.stage[data-accent="rays"] .hub__svg   { scale: 1.05; }

/* A community label that is hovered, focused or selected spotlights its ring,
   as the hub's own labels did. */
.layers:has(.community__btn:is(:hover, :focus-visible, [aria-pressed="true"])) .hub__orbit { opacity: 0.3; }
.layers:has(.community li:nth-child(1) .community__btn:is(:hover, :focus-visible, [aria-pressed="true"])) .hub__orbit:nth-of-type(1),
.layers:has(.community li:nth-child(2) .community__btn:is(:hover, :focus-visible, [aria-pressed="true"])) .hub__orbit:nth-of-type(2),
.layers:has(.community li:nth-child(3) .community__btn:is(:hover, :focus-visible, [aria-pressed="true"])) .hub__orbit:nth-of-type(3),
.layers:has(.community li:nth-child(4) .community__btn:is(:hover, :focus-visible, [aria-pressed="true"])) .hub__orbit:nth-of-type(4) {
  opacity: 1; filter: saturate(1.3) brightness(1.05);
}

/* ============================================================================
   2–4 · THE LAYER SECTIONS
   ========================================================================= */
.layer {
  padding-block: var(--space-section);
}
.layer__pin {
  display: grid;
  grid-template-columns: minmax(0, var(--layers-text)) minmax(0, var(--layers-fig));
  column-gap: var(--space-12);
  align-items: center;
}

.layer__title {
  margin: 0;
  font-size: var(--type-h1);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--color-ink);
}
.layer__subhead {
  margin: var(--space-4) 0 0;
  font-size: var(--type-h3);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--layers-accent);
}
.layer__body {
  margin: var(--space-6) 0 0;
  max-width: 60ch;
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--color-body);
}
/* §10.1 link: in running text, underlined at rest. */
.layer__body a {
  color: var(--color-action-primary);
  text-decoration: underline; text-underline-offset: 3px;
  border-radius: var(--radius-sm);
  transition: color var(--motion-fast);
}
.layer__body a:hover  { color: var(--color-action-primary-hover); }
.layer__body a:active { color: var(--color-action-primary-active); }
.layer__body a:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
/* Bullets under the text, or in its place. */
.layer__list { margin-top: var(--space-3); padding-left: 1.25em; }
.layer__list li + li { margin-top: var(--space-2); }

/* --- section 3: the four points of the method ---------------------------
   Static: a two-by-two list under the abstract. Live: see LIVE MODE below. */
.points {
  margin: var(--space-8) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6);
}
.points {
  --points-trace: color-mix(in srgb, var(--graphic-violet) 45%, var(--purple-300));   /* the orbit rings' violet */
}
.points__item { margin: 0; }

/* Section 3's own hub, core and rays only: shown below 980px alone
   (RESPONSIVE below), where the points sit in its corners. */
.method-fig { display: none; }

/* Each point is a button that swaps the sub-headline and text above it.
   The negative margin gives it a padded hit area without moving the text. */
.points__btn {
  --point-color: var(--purple-300);   /* live: layers.js sets the colour of the ray aimed at it */
  position: relative;
  display: inline-block;
  margin: calc(-1 * var(--space-2));
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  font: 600 var(--type-h4) / 1.4 var(--font-body);
  color: var(--color-ink);
  text-align: inherit;
  cursor: pointer;
  transform-origin: left center;
  transition: color var(--motion-fast), scale var(--motion-medium);
}
/* the short stroke over each point */
.points__btn::before {
  content: "";
  display: block;
  width: var(--space-6);
  height: 2px;
  margin-bottom: var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--point-color);
  transition: width var(--motion-medium), height var(--motion-medium), background-color var(--motion-slow);
}
.points__btn:hover  { color: var(--color-action-primary-hover); }
.points__btn:active { color: var(--color-action-primary-active); }
.points__btn:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.points__btn:disabled { color: var(--color-muted); cursor: not-allowed; }
/* Hover and focus hint that the point is a button: a longer stroke and a
   title 3% larger. */
.points__btn:is(:hover, :focus-visible) { scale: 1.03; }
.points__btn:is(:hover, :focus-visible)::before { width: calc(var(--space-6) + var(--space-3)); }
/* Picked by the reader (never by the automatic shots): its stroke grows, the
   title grows a little, and the other points step back. */
.points__btn[aria-pressed="true"] { scale: 1.08; }
.points__btn[aria-pressed="true"]::before { width: var(--space-12); height: 3px; }
.points:has([aria-pressed="true"]) .points__btn:not([aria-pressed="true"]) { color: var(--color-muted); }

/* --- section 4: community labels ----------------------------------------
   Static: a row of pills above the abstract. Live: see LIVE MODE below. */
.community {
  --community-fill: color-mix(in srgb, var(--purple-100) 50%, var(--purple-050));   /* the hub's pill tone */
  --community-line: var(--purple-300);                                               /* live: the line at rest */
  --community-ring: color-mix(in srgb, var(--graphic-violet) 45%, var(--purple-300)); /* the orbit rings' violet */
  --points-trace: var(--community-ring);                                              /* the sparkle, as in section 3 */
  margin: var(--space-6) 0 0;
  padding: 0;
  list-style: none;
  display: flex; flex-wrap: wrap; gap: var(--space-2);
}
.community__btn {
  display: inline-flex; align-items: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius-pill);
  background: var(--community-fill);
  color: var(--color-action-primary);
  font: 600 var(--type-label) / 1 var(--font-body);
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background-color var(--motion-fast), color var(--motion-fast), translate var(--motion-medium);
}
.community__btn:hover  { background: var(--purple-100); }
.community__btn:active { background: var(--color-canvas-pressed); color: var(--color-action-primary-active); }
.community__btn:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
/* Selected: ringed in the orbits' violet, name in ink. */
.community__btn[aria-pressed="true"] {
  background: var(--purple-100);
  color: var(--color-ink);
  box-shadow: inset 0 0 0 2px var(--community-ring);
}
.community__btn:disabled { background: var(--purple-050); color: var(--color-muted); cursor: not-allowed; }
/* Labels only for now: not clickable, not hoverable, out of the tab order
   (tabindex in render/network.js). */
.community__btn { pointer-events: none; cursor: default; }
/* the name: the sparkle runs round it; padded by negative margins so the
   text itself does not move */
.community__name {
  position: relative;
  display: inline-block;
  margin: calc(-1 * var(--space-1)) calc(-1 * var(--space-2));
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  transform-origin: left center;
  transition: scale var(--motion-medium);
}

/* The abstracts share one grid cell, so the cell keeps the tallest height.
   Section 3 stacks sub-headline + text pairs, section 4 stacks text only. */
.abstracts { display: grid; margin-top: var(--space-6); }
.abstracts--method { margin-top: 0; }
.abstracts--subhead { margin-top: var(--space-4); }   /* the sub-headline's own gap under the title */
.abstracts > * { grid-area: 1 / 1; margin: 0; visibility: hidden; }
.abstracts > .is-on { visibility: visible; animation: layers-fade-in var(--motion-medium); }
@keyframes layers-fade-in { from { opacity: 0; } }

/* --- the three counters (sections 2 and 4) ------------------------------ */
.counters {
  margin: var(--space-12) 0 0;
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-hairline);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  transition: opacity var(--motion-slow), transform var(--motion-slow);
}
.counters__item {
  padding: 0 var(--space-6);
  border-left: 1px solid var(--color-hairline-soft);
  display: flex;
  flex-direction: column;
}
.counters__item:first-child { padding-left: 0; border-left: 0; }

.counters dt {
  order: 1;   /* figure above label, figures level even when a label wraps; dt stays first in the DOM */
  margin-top: var(--space-2);
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
/* A small line naming the period the counters cover (section 4); it takes
   the counters' top margin so it sits just above their rule. */
.counters__note {
  margin: var(--space-12) 0 var(--space-2);
  font-size: var(--type-caption);
  line-height: 1.4;
  color: var(--color-muted);
}
.counters__note + .counters { margin-top: 0; }

/* Numerals in data: Space Grotesk's defined home (§4.2 data-label, §4.3). */
.counters__figure {
  margin: 0;
  font-family: var(--font-accent);
  font-size: var(--type-h1);
  font-weight: 600;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--color-ink);
}

/* ============================================================================
   LIVE MODE — the figure pins, the scroll drives it
   ========================================================================= */
/* While layers.js switches mode, nothing transitions: hidden things (the
   section-3 points, the section-4 labels, the counters) start hidden rather
   than fading out over the figure on page load. */
.layers.is-switching *,
.layers.is-switching *::before,
.layers.is-switching *::after { transition: none !important; }

/* The figure beside all three sections, pinned. */
/* inside the container: its right edge meets the topbar button's. It ends
   early by however far section 4's text runs past the screen (--net-over,
   layers.js), so the figure still lets go as section 4's top reaches the
   screen's. */
.layers.is-live .stage { grid-column: fig; grid-row: 1 / span 3; margin-bottom: var(--net-over, 0px); }
.layers.is-live .layer--method  { grid-row: 2; }
.layers.is-live .layer--network { grid-row: 3; }
.layers.is-live .stage__pin {
  position: sticky;
  top: 0;
  height: 100vh;
}
/* Room for the topbar above and below, so it never covers the figure. */
.layers.is-live .stage__fig {
  width: min(100%, calc(100vh - 2 * (var(--layout-topbar) + var(--space-4))), 720px);
}

.layers.is-live .layer {
  grid-column: text;
  padding-block: 0;
  min-height: 100vh;
}
.layers.is-live .layer__pin {
  display: flex;
  align-items: center;
  min-height: 100vh;
}
.layers.is-live .layer__fig { display: none; }

/* Sections 2 and 3 never pin: each is one screen, its text centred, so one
   text follows the other by a screen, and section 2's text is level with
   the figure just as the figure pins. layers.js fades and shrinks the text
   ([data-roll]) as it moves away from the figure's centre line. */
.layers.is-live [data-roll] { transform-origin: left center; }

/* Counters wait until their section lands. */
.layers.is-live .counters.is-waiting { opacity: 0; transform: translateY(var(--space-2)); }

/* Section 4 does not pin: it is one screen, and the figure lets go as its
   top reaches the screen's, with its headline just under the labels. Its
   text starts below the lowest label; layers.js measures --labels-bottom.
   The scroll unrolls the labels on the way in and runs the lines on just
   after (layers.js step 8); the page itself never stops. */
.layers.is-live .layer--network .layer__pin {
  box-sizing: border-box;
  align-items: flex-start;
  padding-top: calc(var(--labels-bottom, 30vh) + var(--space-8));
}

/* --- section 4: the orbit rings draw on, as in the hub's first entrance ----
   Undrawn (data-orbits="off") until section 4 arrives. A transition on
   --hub-draw (registered by the component) makes the draw reversible. */
.layers.is-live .stage[data-orbits] .hub__orbit {
  animation: none;
  transition:
    --hub-draw 0.4s cubic-bezier(0.65, 0, 0.35, 1) calc(var(--i) * 0.1s),
    opacity var(--motion-slow), filter var(--motion-slow);
}
.layers.is-live .stage[data-orbits="off"] .hub__orbit {
  --hub-draw: 0deg;
  transition-duration: 0.5s, var(--motion-slow), var(--motion-slow);
  transition-delay: 0s;
}
.layers.is-live .stage[data-orbits="on"] .hub__orbit { --hub-draw: 360deg; }
.layers.is-live .stage .hub__halo { transition: opacity var(--motion-slow); }
.layers.is-live .stage[data-orbits="off"] .hub__halo { opacity: 0; }

/* --- section 3: the points sit in the figure's four corners, around the
   rays. layers.js lays the list over the pinned figure (--px, --py, --ps):
   fixed, so they hold still while the text rolls on under them. They
   come in from the corners while the text is level with the figure. */
.layers.is-live .points {
  position: fixed;
  left: var(--px); top: var(--py);
  width: var(--ps); height: var(--ps);
  margin: 0;
  display: block;
  pointer-events: none;
}
.layers.is-live .points__item {
  position: absolute;
  max-width: 36%;
  opacity: 0;
  visibility: hidden;   /* out of the tab order while hidden */
  translate: var(--dx) var(--dy);
  /* leaving: fast, so a quick scroll cannot drag them away half-faded */
  transition: opacity var(--motion-fast), translate var(--motion-fast), visibility 0s 160ms;
}
.layers.is-live .points__item:nth-child(1) { top: 0;    left: 0;  --dx: 8px;  --dy: 8px; }
.layers.is-live .points__item:nth-child(2) { top: 0;    right: 0; --dx: -8px; --dy: 8px; }
.layers.is-live .points__item:nth-child(3) { bottom: 0; left: 0;  --dx: 8px;  --dy: -8px; }
.layers.is-live .points__item:nth-child(4) { bottom: 0; right: 0; --dx: -8px; --dy: -8px; }
.layers.is-live .points__item:nth-child(even) { text-align: right; }
.layers.is-live .points__item:nth-child(even) .points__btn { transform-origin: right center; }
.layers.is-live .points__item:nth-child(even) .points__btn::before { margin-left: auto; }
.layers.is-live .points.is-shown .points__item {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
  /* arriving: slower, one after another ({motion.stagger}) */
  transition:
    opacity var(--motion-slow) calc(var(--i) * 80ms),
    translate var(--motion-slow) calc(var(--i) * 80ms),
    visibility 0s calc(var(--i) * 80ms);
}
.layers.is-live .points.is-shown .points__btn { pointer-events: auto; }

/* --- section 3: the rays hold still in an X, one aimed at each point
   (layers.js turns .hub__aim). Their regular sweep flashes stop; layers.js
   fires one slow shot at a time instead. --------------------------------- */
.layers.is-live .stage[data-aim] .hub__flash { animation: none; opacity: 0; }
.layers.is-live .stage[data-aim] .hub__sector.is-shot .hub__flash { animation: hub-flash 3s linear 1; }

/* --- section 4: the labels. Each is a thin violet line that leaves its ring
   at the top band and runs left, with its name at the far end. layers.js
   sets --x, --y, --w, --h and the line weight --t. Live, the list sits in
   the figure's box (.stage__fig), so the labels are pinned and let go with
   the rings. The rings draw as the section arrives; a little further on
   the lines unroll right to left, one after another, each played through
   in full (.is-shown, layers.js), so a scroll that stops cannot leave one
   half-drawn. */
.layers.is-live .community { margin: 0; }
.layers.is-live .community__btn {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  min-height: 0;
  padding: 0;
  gap: var(--space-3);
  border-radius: var(--radius-sm);
  background: none;
  clip-path: inset(-6px -6px -6px 100%);   /* the 6px leaves room for the focus ring */
  visibility: hidden;
  /* leaving: very fast, so a quick scroll back cannot catch them half-rolled */
  transition:
    clip-path 0.12s ease-in, visibility 0s 0.12s,
    color var(--motion-fast);
}
.layers.is-live .community__btn::after {
  content: "";
  flex: 1;
  height: var(--t);
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg,
    var(--community-line) 0%, var(--community-line) 82%,
    color-mix(in srgb, var(--community-line) 0%, transparent) 100%);   /* dissolves into the ring */
  transition: height var(--motion-fast);
}
.layers.is-live .community.is-shown .community__btn {
  clip-path: inset(-6px);
  visibility: visible;
  /* arriving: each 0.1s after the one above */
  transition:
    clip-path 0.3s cubic-bezier(0.22, 1, 0.36, 1) calc(var(--i) * 0.1s),
    visibility 0s calc(var(--i) * 0.1s),
    color var(--motion-fast);
}
/* Names set like the section-3 points, and they answer the same way: hover
   and focus grow the name 3% and run the sparkle; a pick grows it 8%, the
   other names step back, and the line takes its ring's colour and weight.
   Only the name scales, never the long line. */
.layers.is-live .community__btn {
  font: 600 var(--type-h4) / 1.2 var(--font-body);
  letter-spacing: 0;
  color: var(--color-ink);
}
.layers.is-live .community__btn:hover  { background: none; color: var(--color-action-primary-hover); --community-line: var(--community-ring); }
.layers.is-live .community__btn:active { background: none; color: var(--color-action-primary-active); }
.layers.is-live .community__btn:is(:hover, :focus-visible) .community__name { scale: 1.03; }
.layers.is-live .community__btn[aria-pressed="true"] {
  background: none;
  box-shadow: none;
  color: var(--color-ink);
  --community-line: var(--community-ring);
}
.layers.is-live .community__btn[aria-pressed="true"] .community__name { scale: 1.08; }
.layers.is-live .community__btn[aria-pressed="true"]::after { height: calc(var(--t) * 1.6); }
.layers.is-live .community:has([aria-pressed="true"]) .community__btn:not([aria-pressed="true"]) { color: var(--color-muted); }

/* Each ring's light streak finishes its lap at the ring's top, where the
   label's line leaves it, and layers.js then sparkles that label. The head
   of the streak sits 6deg into its gradient, so a lap ends at -6deg. It
   starts 40% of a lap in, so the first arrival comes soon after landing. */
.layers.is-live .stage[data-orbits="on"] .hub__comet {
  --lap: calc((4s + var(--i) * 0.9s) * var(--speed));
  animation: hub-comet-home var(--lap) cubic-bezier(0.4, 0, 0.6, 1) calc(var(--lap) * -0.4) infinite;
}
@keyframes hub-comet-home {
  0%   { transform: rotate(354deg); opacity: 0; }
  8%   { opacity: 0.9; }
  96%  { opacity: 0.9; }
  100% { transform: rotate(-6deg); opacity: 0; }
}

/* --- the swap: as the text rolls from section 2 to 3, the canvas folds
   away and the hub rolls in to its centre, following the scroll both ways.
   layers.js sets --fold (canvas going, 0-1) and --grow (hub coming, 0-1);
   data-view hides whichever side is all the way out. ------------------- */
.layers.is-live .stage__canvas {
  display: block;
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  aspect-ratio: 1;
}
.layers.is-live .stage__hub,
.layers.is-live .stage__canvas { will-change: transform, opacity; }

.layers.is-live .stage { --fold: 0; --grow: 0; }
.layers.is-live .stage__hub {
  opacity: var(--grow);
  transform: scale(calc(0.15 + 0.85 * var(--grow))) rotate(calc(-180deg * (1 - var(--grow))));
}
/* at rest 20% over the hub's box, so the labels read */
.layers.is-live .stage__canvas {
  opacity: calc(1 - var(--fold));
  transform: scale(calc(1.2 - 0.9 * var(--fold))) rotate(calc(120deg * var(--fold)));
}
.layers.is-live .stage[data-view="canvas"] .stage__hub,
.layers.is-live .stage[data-view="hub"] .stage__canvas { visibility: hidden; }

/* ============================================================================
   RESPONSIVE (§13.1) — review at 1440, 1180, 980, 720, 480, 390.
   Below 980px the page is always static: copy first, figure under it.
   ========================================================================= */
@media (max-width: 979px) {
  .layers {
    display: block;
    padding-inline: var(--space-6);
  }
  .stage__fig { width: min(100%, 560px); margin-inline: auto; }
  .layer__pin { display: block; }
  .layer__fig { margin: var(--space-8) auto 0; max-width: 560px; }

  /* Section 2's canvas is the figure here: the full hub under it goes. */
  .stage { display: none; }

  /* Section 3: its own hub, core and rays only, with the four points in its
     corners, as in live mode. The rays hold still in the X that aims each
     at its point, and each point's stroke takes its ray's colour (know
     orange, learn green, cultivate violet, apply blue; see layers.js
     step 6). The hub and the list share one grid cell, so the list is the
     hub's size. */
  .layer--method .layer__text { display: grid; }
  .layer--method .method-fig,
  .layer--method .points {
    grid-area: 2 / 1;
    justify-self: center;
    width: min(100%, 480px);
    margin: var(--space-8) 0 0;
  }
  .method-fig { display: block; }
  .method-fig .hub__band { pointer-events: none; }
  .method-fig .hub__sector:hover { transform: none; }
  .method-fig .hub__rotor { animation: none; }
  .method-fig .hub__aim { transform: rotate(-45deg); }

  .layer--method .points { position: relative; display: block; }
  .layer--method .points__item { position: absolute; max-width: 38%; }
  .layer--method .points__item:nth-child(1) { top: 0;    left: 0;  --point-color: var(--radar-cpf); }
  .layer--method .points__item:nth-child(2) { top: 0;    right: 0; --point-color: var(--radar-ebs); }
  .layer--method .points__item:nth-child(3) { bottom: 0; left: 0;  --point-color: var(--radar-dmr); }
  .layer--method .points__item:nth-child(4) { bottom: 0; right: 0; --point-color: var(--radar-ahp); }
  .layer--method .points__item:nth-child(even) { text-align: right; }
  .layer--method .points__item:nth-child(even) .points__btn { transform-origin: right center; }
  .layer--method .points__item:nth-child(even) .points__btn::before { margin-left: auto; }
  .layer--method .points__btn { --point-color: inherit; font-size: var(--type-body-sm); line-height: 1.3; }
  .layer--method .points__btn::before { margin-bottom: var(--space-2); }
}

@media (max-width: 719px) {
  .layers { padding-inline: var(--space-4); }
  /* The three counters stay in one row: figures and labels set smaller. */
  .counters, .counters__note { margin-top: var(--space-8); }
  .counters__item { padding: 0 var(--space-3); }
  .counters__figure { font-size: var(--type-h2); }
  .counters dt { font-size: var(--type-caption); line-height: 1.4; }
}
