/* ============================================================================
   INSIGHT BAY, MATHEMATICS
   mathematics.css

   Sister file to space.css. Parts A and B below are the SAME code as that
   file, deliberately: /mathematics and /space have to be one object in two
   subjects, not two designs that happen to share a logo. If you change a
   shared value, change it in both, or the pages drift and a parent notices
   before you do.

   This file has three parts.

   PART A, BRAND BASE (mirrored, byte-for-byte, from /assets/css/styles.css).
            Present only so this page can be opened and reviewed on its own,
            with no other stylesheet loaded. If you would rather link the
            existing site stylesheet, delete PART A and add
            <link rel="stylesheet" href="/assets/css/styles.css"> before this
            file. Nothing below depends on PART A being local, it only
            consumes --ib-* custom properties, which either file provides.

   PART B, THE CINEMATIC PAGE KIT. Everything is namespaced .sx-*. Void
            panels, numbered chapters, tiles, the timeline, the stage switch,
            the FAQ and the final call to action. Shared with /space, which is
            why the prefix stays .sx-. It adds no new colours, no new radii,
            no new type family. Every value resolves back to an --ib-* token.

   PART C, THE MATHEMATICS LAYER, namespaced .mx-*. Graph-paper voids, the
            unit-circle hero, the scroll-driven secant-to-tangent scene, the
            eight-strand explorer and the growth interactive. Nothing in
            PART C is used by /space.

   Design rule that governs the whole page:
   ----------------------------------------
   The cinematic passages ("void" panels) are ALWAYS dark, in both light and
   dark mode, exactly as the site footer is already always dark. They are not
   a second theme. They are the existing dark surface, used at full height.
   Inside a void panel we re-point the --ib-* tokens to their dark values, so
   .ib-btn, .ib-eyebrow, .ib-card and every other brand component keeps working
   untouched. That is the whole trick, and it is why the page cannot drift.
   ========================================================================= */


/* ==========================================================================
   PART A, BRAND BASE (mirror of styles.css)
   ========================================================================== */

:root {
  --ib-bg: #F5F1EB;
  --ib-bg-soft: #FAF7F2;
  --ib-bg-deep: #EEE9DD;
  --ib-ink: #20201E;
  --ib-ink-soft: #4A4742;
  --ib-ink-muted: #6B655C;
  --ib-line: #E2DCCF;
  --ib-line-strong: #C9C0AE;
  --ib-accent: #C96442;
  --ib-accent-ink: #B2502F;
  --ib-accent-ink-hover: #A0482A;
  --ib-accent-hover: #B25535;
  --ib-accent-soft: #F3DDCF;
  --ib-gold: #B58A3A;
  --ib-success: #4F7A4A;
  --ib-shadow: 0 1px 2px rgba(32,32,30,.04), 0 0.5rem 1.5rem -0.5rem rgba(32,32,30,.12);
  --ib-shadow-lg: 0 0.25rem 0.75rem rgba(32,32,30,.06), 0 1.5rem 3rem -1rem rgba(32,32,30,.18);
  --ib-bg-hero-top: #FFFDF8;
  --ib-grid-line: rgba(32,32,30,.05);
  --ib-nav-bg: rgba(245,241,235,0.85);
  --ib-card-bg: #FFFFFF;
  --ib-footer-bg: #20201E;
  --ib-footer-text: #F5F1EB;
  --ib-footer-text-soft: rgba(245,241,235,.85);
  --ib-footer-text-faint: rgba(245,241,235,.55);
  --ib-footer-line: rgba(245,241,235,.12);
  --ib-emphasis-bg: #20201E;
  --ib-emphasis-text: #F5F1EB;
  --ib-emphasis-text-soft: rgba(245,241,235,.85);
  --ib-emphasis-text-faint: rgba(245,241,235,.6);
  --ib-emphasis-line: rgba(245,241,235,.15);
  --ib-radius-sm: 0.5rem;
  --ib-radius: 0.875rem;
  --ib-radius-lg: 1.375rem;
  --ib-font-serif: 'Inter','Helvetica Neue',Arial,system-ui,sans-serif;
  --ib-font-sans: 'Inter','Helvetica Neue',Arial,system-ui,sans-serif;
  --ib-font-mono: 'IBM Plex Mono',ui-monospace,'SFMono-Regular',Menlo,monospace;
  --ib-font-stamp: 'Inter','Helvetica Neue',Arial,system-ui,sans-serif;
  --ibe-out: cubic-bezier(.22,.61,.21,1);
  --ibe-pop: cubic-bezier(.3,1.25,.4,1);
  --ibe-spring: cubic-bezier(.34,1.45,.5,1);
  --ib-dur-1: .16s;
  --ib-dur-2: .3s;
  --ib-dur-3: .55s;
  --ib-field-line: #948871;
}

[data-theme="dark"] {
  --ib-bg: #1A1916;
  --ib-bg-soft: #1E1D1A;
  --ib-bg-deep: #232220;
  --ib-ink: #F2EFE8;
  --ib-ink-soft: #C9C4BB;
  --ib-ink-muted: #8E8A82;
  --ib-line: #343129;
  --ib-line-strong: #45413A;
  --ib-accent: #E8845E;
  --ib-accent-ink: #E8845E;
  --ib-accent-ink-hover: #F19770;
  --ib-accent-hover: #F19770;
  --ib-accent-soft: #3D2A20;
  --ib-gold: #D9B265;
  --ib-success: #7AAE73;
  --ib-shadow: 0 1px 2px rgba(0,0,0,.4), 0 0.5rem 1.5rem -0.5rem rgba(0,0,0,.55);
  --ib-shadow-lg: 0 0.25rem 0.75rem rgba(0,0,0,.45), 0 1.5rem 3rem -1rem rgba(0,0,0,.7);
  --ib-bg-hero-top: #1F1D1A;
  --ib-grid-line: rgba(242,239,232,.06);
  --ib-nav-bg: rgba(26,25,22,0.85);
  --ib-card-bg: #211F1C;
  --ib-footer-bg: #141311;
  --ib-footer-text: #F2EFE8;
  --ib-footer-text-soft: rgba(242,239,232,.85);
  --ib-footer-text-faint: rgba(242,239,232,.55);
  --ib-footer-line: rgba(242,239,232,.12);
  --ib-emphasis-bg: #232120;
  --ib-emphasis-text: #F2EFE8;
  --ib-emphasis-text-soft: rgba(242,239,232,.85);
  --ib-emphasis-text-faint: rgba(242,239,232,.6);
  --ib-emphasis-line: rgba(242,239,232,.1);
  --ib-field-line: #6F6960;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* Several components below set display:grid/flex, which would otherwise beat
   the UA rule for [hidden]. The tab explorer depends on this holding. */
[hidden] { display: none !important; }
body {
  margin: 0;
  background: var(--ib-bg);
  color: var(--ib-ink);
  font-family: var(--ib-font-sans);
  font-feature-settings: "ss01","cv11";
  line-height: 1.6;
  font-size: 1rem;
}
body, .ib-nav, .ib-mobile-menu, .ib-card, .ib-footer, input, textarea, select, button, a {
  transition: background-color .25s, color .2s, border-color .2s;
}
body h1, body h2, body h3, body h4, body h5 {
  font-family: var(--ib-font-sans);
  color: var(--ib-ink);
  letter-spacing: -.015em;
  line-height: 1.15;
  font-weight: 700;
  text-transform: none;
  margin: 0;
}
body h1 { font-size: clamp(2.4rem, 4.8vw, 3.8rem); font-weight: 800; letter-spacing: -.025em; }
body h2 { font-size: clamp(1.7rem, 3.2vw, 2.4rem); letter-spacing: -.02em; }
body h3 { font-size: clamp(1.15rem, 1.8vw, 1.35rem); }
h1, h2, h3, blockquote { overflow-wrap: break-word; }
p { margin: 0; }
a { color: var(--ib-accent-ink); text-decoration: none; }
a:hover { color: var(--ib-accent-hover); }
img, svg { max-width: 100%; }
ul { margin: 0; padding: 0; list-style: none; }

a:focus-visible, button:focus-visible, .ib-btn:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ib-accent);
  outline-offset: 2px;
  border-radius: 0.25rem;
}

.ib-container { max-width: 73.75rem; margin-inline: auto; padding-inline: 1.25rem; min-width: 0; }
.ib-section { padding-block: 5rem; min-width: 0; }
.ib-band { max-width: 51.25rem; }

.ib-eyebrow {
  font-family: var(--ib-font-sans);
  font-size: .95rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ib-accent);
  font-weight: 700;
}

.ib-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .85rem 1.4rem; border-radius: 62.4375rem;
  font-weight: 500; font-size: .95rem;
  transition: .18s; border: 1px solid transparent; cursor: pointer;
  font-family: inherit; text-decoration: none;
}
.ib-btn-primary { background: var(--ib-ink); color: var(--ib-bg); }
.ib-btn-primary:hover { background: var(--ib-accent-ink); color: #fff; transform: translateY(-1px); }
.ib-btn-accent { background: var(--ib-accent-ink); color: #fff; }
.ib-btn-accent:hover { background: var(--ib-accent-ink-hover); color: #fff; transform: translateY(-1px); }
.ib-btn-ghost { background: transparent; color: var(--ib-ink); border-color: var(--ib-line-strong); }
.ib-btn-ghost:hover { background: var(--ib-bg-deep); color: var(--ib-ink); }

.ib-card {
  background: var(--ib-bg-soft);
  border: 1px solid var(--ib-line);
  border-radius: var(--ib-radius);
  padding: 1.75rem;
  transition: transform .25s, box-shadow .25s, border-color .25s;
}
.ib-card:hover { border-color: var(--ib-line-strong); box-shadow: var(--ib-shadow); transform: translateY(-2px); }

.ib-reveal { opacity: 0; transform: translateY(1.75rem); transition: opacity .8s, transform .8s cubic-bezier(.2,.7,.2,1); }
.ib-reveal.is-visible { opacity: 1; transform: translateY(0); }

/* --- Navigation (mirror) ------------------------------------------------- */
.ib-nav {
  position: sticky; top: 0; z-index: 50;
  background: var(--ib-nav-bg);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--ib-line);
}
.ib-nav-inner { display: flex; align-items: center; justify-content: space-between; height: 4.25rem; }
.ib-logo {
  font-family: var(--ib-font-sans); font-size: 1.3rem; font-weight: 700;
  color: var(--ib-ink); letter-spacing: -.02em;
  display: flex; align-items: center; gap: .5rem;
}
.ib-logo:hover { color: var(--ib-ink); }
.ib-logo-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.875rem; height: 1.875rem; background: var(--ib-accent); color: #fff;
  border-radius: 0.5rem; font-style: italic; font-weight: 700; font-size: 1.05rem;
}
.ib-nav-links { display: none; gap: 2rem; }
.ib-nav-links a { color: var(--ib-ink-soft); font-size: .92rem; font-weight: 500; position: relative; }
.ib-nav-links a:hover, .ib-nav-links a.active { color: var(--ib-ink); }
.ib-nav-links a.active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1.375rem;
  height: 2px; background: var(--ib-accent);
}
.ib-nav-actions { display: flex; align-items: center; gap: .75rem; }
.ib-theme-toggle, .ib-menu-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.375rem; height: 2.375rem; border-radius: 62.4375rem;
  border: 1px solid var(--ib-line-strong); background: transparent;
  color: var(--ib-ink); cursor: pointer; padding: 0;
}
.ib-theme-toggle:hover, .ib-menu-toggle:hover { background: var(--ib-bg-deep); }
.ib-theme-toggle__moon { display: none; }
[data-theme="dark"] .ib-theme-toggle__sun { display: none; }
[data-theme="dark"] .ib-theme-toggle__moon { display: block; }
.ib-nav .ib-btn-primary { display: none; padding: .55rem 1.1rem; font-size: .875rem; }
.ib-mobile-menu {
  display: none; padding: 1rem 1.25rem 1.5rem;
  border-top: 1px solid var(--ib-line); background: var(--ib-bg-soft);
}
.ib-mobile-menu.open { display: block; }
/* Never let the open menu run off a short screen (landscape phones). */
.ib-mobile-menu.open { max-height: calc(100vh - 4.25rem); max-height: calc(100dvh - 4.25rem); overflow-y: auto; }
.ib-mobile-menu a {
  display: block; padding: .65rem 0; color: var(--ib-ink);
  font-weight: 500; border-bottom: 1px solid var(--ib-line);
}
.ib-mobile-menu a:last-of-type { border-bottom: none; }
@media (min-width: 900px) {
  .ib-nav-links { display: flex; }
  .ib-nav .ib-btn-primary { display: inline-flex; }
  .ib-menu-toggle { display: none; }
}

/* --- Footer (mirror) ----------------------------------------------------- */
.ib-footer {
  background: var(--ib-footer-bg); color: var(--ib-footer-text);
  padding: 4rem 0 2rem; margin-top: 0;
}
/* .ib-footer a sets display:block and out-specifies .ib-logo, which collapses
   the gap between the mark and the wordmark. Restore it here. */
.ib-footer a.ib-logo { display: inline-flex; gap: .5rem; color: var(--ib-footer-text); padding: 0; }
.ib-footer h4 {
  color: var(--ib-footer-text); font-size: .78rem; letter-spacing: .16em;
  text-transform: uppercase; font-weight: 600; margin-bottom: 1rem; opacity: .7;
}
.ib-footer a { color: var(--ib-footer-text-soft); display: block; padding: .25rem 0; font-size: .92rem; }
/* On any touch device the footer is a column of 32px targets, and an iPad in
   landscape is 1024 CSS px wide, so a width query alone misses it. Ask about
   the pointer instead. Nothing else competes for the space down there. */
@media (hover: none), (max-width: 859px) {
  .ib-footer a { padding: .55rem 0; }
  .ib-footer-legal a { padding: .35rem 0; }
  .ib-nav .ib-logo { padding-block: .5rem; }
}
.ib-social-row a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.625rem; height: 2.625rem; margin-left: -0.5625rem; border-radius: 62.4375rem; padding: 0;
}
.ib-social-row a:hover { background: rgba(242,239,232,.08); }
.ib-footer a:hover { color: var(--ib-accent); }
.ib-footer p { color: var(--ib-footer-text-soft); font-size: .92rem; }
.ib-footer-grid { display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 860px) { .ib-footer-grid { grid-template-columns: 1.4fr repeat(3, 1fr); } }
.ib-footer-bottom {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem;
  border-top: 1px solid var(--ib-footer-line); margin-top: 3rem; padding-top: 1.5rem;
  font-size: .82rem; color: var(--ib-footer-text-faint);
}
.ib-footer-legal { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.ib-footer-legal a { display: inline; font-size: .82rem; color: var(--ib-footer-text-faint); }

/* --- Sticky CTA + scroll progress (mirror) ------------------------------- */
.ib-scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 70;
  background: linear-gradient(90deg, var(--ib-accent), var(--ib-gold));
  transform: scaleX(0); transform-origin: 0 50%; pointer-events: none;
  will-change: transform;
}
.ib-sticky-cta {
  position: fixed; left: 50%; bottom: 1rem; transform: translate(-50%, 0); z-index: 60;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .95rem 1.4rem; background: var(--sx-accent-solid); color: var(--sx-on-accent);
  border-radius: 62.4375rem; font-size: .95rem; font-weight: 600;
  box-shadow: 0 12px 32px -8px rgba(32,32,30,.35), 0 2px 4px rgba(32,32,30,.18);
  border: 1px solid color-mix(in srgb, var(--ib-accent) 70%, #000);
  transition: opacity .2s, transform .25s, background .15s;
  white-space: nowrap; max-width: calc(100% - 2rem);
}
.ib-sticky-cta:hover { background: var(--ib-accent-hover); color: var(--sx-on-accent); }
.ib-sticky-cta.is-hidden { opacity: 0; transform: translate(-50%, 120%); pointer-events: none; }
[data-theme="dark"] .ib-sticky-cta { box-shadow: 0 12px 32px -8px rgba(0,0,0,.55), 0 2px 4px rgba(0,0,0,.4); }

.sx-skip {
  position: absolute; left: -624.9375rem; top: 0; z-index: 100;
  background: var(--ib-accent-ink); color: #fff; padding: .75rem 1.25rem;
  border-radius: 0 0 var(--ib-radius-sm) 0;
}
.sx-skip:focus { left: 0; color: #fff; }


/* ==========================================================================
   PART B, SPACE EXPLORATION EXTENSION
   ========================================================================== */

/* --------------------------------------------------------------------------
   B.-1  Two accessibility tokens the brand is missing
   ---------------------------------------------------
   Two AA failures exist on insightbay.net today and would be inherited here
   verbatim. Both come from the same root cause: --ib-accent is a *surface*
   colour being used as a *text* colour, and no token says what colour text
   goes ON the accent.

     1. .ib-eyebrow uses --ib-accent. #C96442 on the cream #F5F1EB is 3.46:1.
        AA needs 4.5:1 for text this size. The brand already owns the fix, --ib-accent-ink (#B2502F) is 4.9:1 and is visually indistinguishable
        at eyebrow size.
     2. White text on the dark-mode accent #E8845E is 2.66:1. On a bright
        accent the label has to go dark; #17120F measures about 9:1.

   Both are recommended site-wide, not just here. See ACCESSIBILITY.md.
   -------------------------------------------------------------------------- */
:root {
  --sx-accent-text:  #B2502F;   /* accent used as TEXT, on a light surface */
  --sx-gold-text:    #8A6620;   /* --ib-gold is 2.95:1 on cream; this is 4.9 */
  --sx-accent-solid: #B2502F;   /* accent used as a filled SURFACE          */
  --sx-on-accent:    #FFFFFF;   /* label colour on that surface             */
}
[data-theme="dark"] {
  --sx-accent-text:  #E8845E;
  --sx-accent-solid: #E8845E;
  --sx-on-accent:    #17120F;
  --sx-gold-text:    #D9B265;   /* already 8.4:1 on the dark surface */
}
.ib-eyebrow { color: var(--sx-accent-text); }

/* --------------------------------------------------------------------------
   B.0  The void surface
   The one structural idea on this page. A .sx-void panel is permanently dark
   in both themes, the same move the footer already makes, and it re-points
   the brand tokens locally so every .ib-* component inside it stays correct.
   -------------------------------------------------------------------------- */
.sx-void {
  --ib-bg:            #0C0B0A;
  --ib-bg-soft:       #121110;
  --ib-bg-deep:       #171614;
  --ib-bg-hero-top:   #17150F;
  --ib-card-bg:       #141312;
  --ib-ink:           #F2EFE8;
  --ib-ink-soft:      #CAC4BA;
  --ib-ink-muted:     #8C867D;
  --ib-line:          #2A2723;
  --ib-line-strong:   #3C3833;
  --ib-accent:        #E8845E;
  --ib-accent-ink:    #E8845E;
  --ib-accent-ink-hover: #F19770;
  --ib-accent-hover:  #F19770;
  --ib-accent-soft:   #3D2A20;
  --ib-gold:          #D9B265;
  --ib-grid-line:     rgba(242,239,232,.05);
  --sx-accent-text:   #E8845E;
  --sx-accent-solid:  #E8845E;
  --sx-on-accent:     #17120F;
  --sx-gold-text:     #D9B265;
  --ib-shadow:        0 1px 2px rgba(0,0,0,.5), 0 0.625rem 1.875rem -0.625rem rgba(0,0,0,.7);
  --ib-shadow-lg:     0 0.375rem 1.125rem rgba(0,0,0,.5), 0 1.875rem 3.75rem -1.25rem rgba(0,0,0,.8);

  position: relative;
  isolation: isolate;
  background: var(--ib-bg);
  color: var(--ib-ink);
  overflow: hidden;
}
.sx-void h1, .sx-void h2, .sx-void h3, .sx-void h4 { color: var(--ib-ink); }
.sx-void p { color: var(--ib-ink-soft); }
.sx-void .ib-btn-primary { background: var(--ib-ink); color: #14120F; }
.sx-void .ib-btn-primary:hover { background: #fff; color: #14120F; }
/* ACCESSIBILITY FIX, please read before "correcting" this back.
   The brand's accent button is white text on --ib-accent-ink. In light mode
   that is #fff on #B2502F = 4.6:1 and passes AA. In DARK mode the site raises
   --ib-accent-ink to #E8845E, and #fff on #E8845E is 2.66:1, a WCAG AA
   failure that exists on insightbay.net today, on every dark-mode page.
   On a dark surface the correct move is to keep the bright accent and invert
   the label: #17120F on #E8845E measures about 9:1. Recommended site-wide. */
.sx-void .ib-btn-accent { background: var(--sx-accent-solid); color: var(--sx-on-accent); }
.sx-void .ib-btn-accent:hover { background: var(--ib-accent-hover); color: var(--sx-on-accent); }
.sx-void .ib-card { background: var(--ib-card-bg); border-color: var(--ib-line); }

/* Everything a void panel draws sits behind its content. */
.sx-void > .ib-container,
.sx-void > .sx-wide { position: relative; z-index: 2; }

/* --------------------------------------------------------------------------
   B.1  Deep-space background layers
   Three cheap layers, composited on the GPU, never repainted:
     .sx-stars, <canvas>, three parallax depths, drawn once per frame
     .sx-neb, CSS radial gradients, translated very slowly
     .sx-grain, a static SVG noise tile, kills gradient banding
   -------------------------------------------------------------------------- */
.sx-layer {
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
}
.sx-stars { display: block; width: 100%; height: 100%; }

.sx-neb {
  background:
    radial-gradient(58% 44% at 18% 12%,  rgba(201,100,66,.20), transparent 62%),
    radial-gradient(46% 38% at 84% 26%,  rgba(122, 92, 160, .16), transparent 64%),
    radial-gradient(70% 50% at 52% 100%, rgba(181,138,58,.14), transparent 66%),
    radial-gradient(90% 70% at 50% 45%,  rgba(20,18,26,.55), transparent 70%);
  /* PERF: no filter:blur() here. Radial gradients are already soft, so the
     blur bought nothing visible and cost a full-layer re-raster every frame
     the layer moved. Measured: removing it roughly doubled scroll frame rate
     in software rasterisation. */
  /* Oversized once, so translation never exposes an edge. */
  transform: translate3d(0,0,0) scale(1.18);
  opacity: .9;
}
/* Aurora glow, the warm light that seems to come from below the horizon.

   PERF NOTE, because this looks like an odd way to write it:
   this started as a separate .sx-aurora element with a conic-gradient and
   filter: blur(38px). Two problems. A 38 px blur across a full-viewport layer
   is among the most expensive things a compositor can be asked for, and it
   was a SECOND full-viewport promoted layer stacked on the nebula, which
   overlaps it almost exactly. Both are now folded into the single .sx-neb
   layer on the two panels that need them, built from wide elliptical
   gradients that are soft by construction. One layer, no filter, same look.
   Measured on software rasterisation with no GPU at all: 7 fps to 60. */
.sx-hero .sx-neb,
.sx-final .sx-neb {
  background:
    radial-gradient(58% 44% at 18% 12%,  rgba(201,100,66,.20), transparent 62%),
    radial-gradient(46% 38% at 84% 26%,  rgba(122,92,160,.16), transparent 64%),
    radial-gradient(75% 55% at 22% 108%, rgba(201,100,66,.26), transparent 72%),
    radial-gradient(65% 48% at 58% 116%, rgba(181,138,58,.18), transparent 70%),
    radial-gradient(90% 60% at 88% 104%, rgba(122,92,160,.14), transparent 74%),
    radial-gradient(90% 70% at 50% 45%,  rgba(20,18,26,.55), transparent 70%);
  will-change: transform;
  animation: sx-drift 68s var(--ibe-out) infinite alternate;
}
@keyframes sx-drift {
  /* Translate only. The original keyframes also animated scale() from 1.12 to
     1.18, and scaling a promoted layer re-rasterises it at every new scale
     factor, which defeats the point of promoting it. The scale is fixed on
     the base rule; only the position moves. */
  0%   { transform: translate3d(-1.6%,  1.4%, 0) scale(1.18); }
  100% { transform: translate3d( 1.6%, -1.4%, 0) scale(1.18); }
}

.sx-grain {
  /* PERF: no mix-blend-mode. A blend mode forces the entire stacking context
     to be composited on every frame instead of taking the fast path; at 4.5%
     opacity over a near-black surface the visual difference is nil. */
  opacity: .05;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.7'/></svg>");
}

/* PERF: a void panel's ambient layers only animate while that panel is on
   screen. There are five void panels; without this, five full-width gradient
   layers are being stepped forward at all times, four of them invisibly.
   JS adds .is-onscreen via IntersectionObserver. */
.sx-void:not(.is-onscreen) .sx-neb,
.sx-void:not(.is-onscreen) .sx-meteor,
.sx-void:not(.is-onscreen) .sx-orbit-spin { animation-play-state: paused; }

/* A hairline horizon that closes a void panel without a hard edge. */
.sx-void::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(232,132,94,.35), transparent);
  z-index: 3; pointer-events: none;
}

/* Mouse / scroll parallax. JS writes --sx-px and --sx-py in the -1..1 range. */
.sx-parallax {
  transform: translate3d(calc(var(--sx-px, 0) * var(--sx-depth, 0.375rem)),
                         calc(var(--sx-py, 0) * var(--sx-depth, 0.375rem)), 0);
  transition: transform .5s var(--ibe-out);
  will-change: transform;
}

/* --------------------------------------------------------------------------
   B.2  Hero
   -------------------------------------------------------------------------- */
.sx-hero { padding-block: clamp(4.5rem, 11vh, 8rem) clamp(3.5rem, 9vh, 6.5rem); }
.sx-hero-grid { display: grid; gap: 3rem; align-items: center; }
@media (min-width: 1000px) { .sx-hero-grid { grid-template-columns: 1.08fr .92fr; gap: 4rem; } }

.sx-hero h1 {
  font-size: clamp(2.6rem, 5.6vw, 4.35rem);
  line-height: 1.04;
  letter-spacing: -.03em;
  margin-top: 1.1rem;
}
.sx-hero h1 .sx-accent { color: var(--ib-accent); display: block; }
.sx-hero-sub {
  margin-top: 1.5rem; font-size: clamp(1.05rem, 1.5vw, 1.2rem);
  max-width: 34ch; color: var(--ib-ink-soft);
}
.sx-hero-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2.25rem; }

/* The four facts a parent needs before they scroll. */
.sx-facts {
  display: grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: 1px; margin-top: 3rem;
  background: var(--ib-line); border: 1px solid var(--ib-line);
  border-radius: var(--ib-radius); overflow: hidden;
}
@media (min-width: 720px) { .sx-facts { grid-template-columns: repeat(4, minmax(0,1fr)); } }
.sx-fact { background: var(--ib-bg); padding: 1.1rem 1.15rem; }
.sx-fact dt {
  font-family: var(--ib-font-mono); font-size: 1.5rem; font-weight: 500;
  color: var(--ib-accent); letter-spacing: -.02em; line-height: 1.1;
}
.sx-fact dd { margin: .35rem 0 0; font-size: .82rem; color: var(--ib-ink-muted); line-height: 1.45; }

/* Hero art: an orbital diagram that draws itself, not a decorative blob. */
.sx-orbit-wrap { position: relative; aspect-ratio: 1 / 1; max-width: 31.25rem; margin-inline: auto; width: 100%; }
.sx-orbit { width: 100%; height: 100%; overflow: visible; }
.sx-orbit .ring { fill: none; stroke: rgba(242,239,232,.16); stroke-width: 1; }
.sx-orbit .ring-lit { stroke: rgba(232,132,94,.55); stroke-dasharray: 1 1; }
.sx-orbit .planet { fill: url(#sxPlanet); }
.sx-orbit .halo { fill: url(#sxHalo); }
.sx-orbit .tick { stroke: rgba(242,239,232,.28); stroke-width: 1; }
.sx-orbit .label {
  font-family: var(--ib-font-mono); font-size: 9.5px; letter-spacing: .16em;
  fill: rgba(242,239,232,.5); text-transform: uppercase;
}
.sx-orbit .craft { fill: var(--ib-accent); }
.sx-orbit-labels text {
  text-anchor: middle;
  paint-order: stroke;
  stroke: #0C0B0A; stroke-width: 5px; stroke-linejoin: round;
}
.sx-orbit-spin { transform-origin: 250px 250px; animation: sx-spin 44s linear infinite; }
@keyframes sx-spin { to { transform: rotate(360deg); } }

/* Constellation overlay: strokes draw themselves once, on entry. */
.sx-constellation path, .sx-constellation line {
  stroke: rgba(242,239,232,.30); stroke-width: 1; fill: none;
  stroke-dasharray: var(--len, 400); stroke-dashoffset: var(--len, 400);
}
.is-visible .sx-constellation path,
.is-visible .sx-constellation line {
  animation: sx-draw 2.4s var(--ibe-out) forwards;
}
@keyframes sx-draw { to { stroke-dashoffset: 0; } }
.sx-constellation circle { fill: rgba(242,239,232,.75); }

/* Meteors: two, rare, never in the reader's way. */
.sx-meteor {
  position: absolute; width: 9.375rem; height: 1px; z-index: 1;
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.85));
  opacity: 0; transform: rotate(24deg);
  animation: sx-meteor 14s linear infinite;
}
.sx-meteor--2 { animation-delay: 7.5s; animation-duration: 19s; width: 6.875rem; }
@keyframes sx-meteor {
  0%   { opacity: 0; transform: translate3d(0,0,0) rotate(24deg); }
  2%   { opacity: .9; }
  9%   { opacity: 0; transform: translate3d(46vw, 22vw, 0) rotate(24deg); }
  100% { opacity: 0; transform: translate3d(46vw, 22vw, 0) rotate(24deg); }
}

/* --------------------------------------------------------------------------
   B.3  Chapter headers, the page reads as chapters, so they are numbered.
   -------------------------------------------------------------------------- */
.sx-chapter { max-width: 47.5rem; }
.sx-chapter .ib-eyebrow { display: flex; align-items: baseline; gap: .8rem; }
.sx-chapter .sx-num {
  font-family: var(--ib-font-mono); font-size: .8rem; letter-spacing: .1em;
  color: var(--ib-ink-muted); font-weight: 400;
}
.sx-chapter h2 { margin-top: 1rem; font-size: clamp(1.9rem, 3.6vw, 2.75rem); }
.sx-chapter .sx-lede {
  margin-top: 1.1rem; font-size: clamp(1.05rem, 1.4vw, 1.18rem);
  color: var(--ib-ink-soft); max-width: 62ch;
}
.sx-body { max-width: 62ch; }
.sx-body p + p { margin-top: 1.1rem; }
.sx-body p { color: var(--ib-ink-soft); font-size: 1.05rem; }

.sx-pull {
  margin: 2.5rem 0 0; padding-left: 1.5rem;
  border-left: 2px solid var(--ib-accent);
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  line-height: 1.35; letter-spacing: -.015em;
  color: var(--ib-ink); font-weight: 600; max-width: 26ch;
}
.sx-pull cite { display: block; margin-top: .85rem; font-size: .85rem; font-style: normal;
  font-weight: 400; letter-spacing: .04em; color: var(--ib-ink-muted); }

/* --------------------------------------------------------------------------
   B.4  Mars scene, the "where it all points" panel
   -------------------------------------------------------------------------- */
.sx-mars { padding-block: clamp(4rem, 9vh, 7rem) 0; }
.sx-mars-stage { position: relative; margin-top: 3rem; }
.sx-mars-svg { display: block; width: 100%; height: auto; }
.sx-mars-caption {
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; align-items: baseline;
  font-family: var(--ib-font-mono); font-size: .72rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ib-ink-muted);
  padding-bottom: 1.25rem;
}
.sx-mars-caption b { color: var(--ib-accent); font-weight: 500; }
/* The rover crosses the crater as you scroll, and crosses back as you scroll
   up. space.js writes --sx-rover-x on the <svg> in viewBox units; both the
   vehicle and the clip that reveals its trail read the same number, so the
   track can never get ahead of the wheels. Transform only, one composited
   layer, no layout and no repaint. */
.sx-mars-svg { --sx-rover-x: 31.875rem; }
.sx-rover { transform: translateX(var(--sx-rover-x)); will-change: transform; }
.sx-trail-clip { transform: translateX(var(--sx-rover-x)); }

/* On a phone the scene would otherwise collapse to a 130px strip. Fix the
   height and let preserveAspectRatio="slice" crop the sides instead, which
   also means the rover enters and leaves the frame properly. */
@media (max-width: 700px) {
  .sx-mars-svg { height: 13.125rem; }
}

/* --------------------------------------------------------------------------
   B.5  The eight fields × three stages explorer
   The centrepiece. One control, twenty-four real syllabi behind it.
   -------------------------------------------------------------------------- */
.sx-stage-switch {
  display: inline-flex; padding: 0.25rem; gap: 0.25rem; margin-top: 2rem;
  background: var(--ib-bg-deep); border: 1px solid var(--ib-line);
  border-radius: 62.4375rem; position: relative; flex-wrap: wrap;
}
.sx-stage-switch button {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-size: .88rem; font-weight: 500;
  color: var(--ib-ink-muted); padding: .6rem 1.15rem; border-radius: 62.4375rem;
  transition: color var(--ib-dur-1), background var(--ib-dur-2) var(--ibe-out);
  white-space: nowrap;
}
.sx-stage-switch button:hover { color: var(--ib-ink); }
.sx-stage-switch button[aria-selected="true"] {
  background: var(--sx-accent-solid); color: var(--sx-on-accent);
  box-shadow: 0 2px 10px -2px rgba(201,100,66,.5);
}
.sx-stage-switch .sx-sw-grade {
  font-family: var(--ib-font-mono); font-size: .72rem; opacity: .75; margin-right: .5rem;
}

.sx-stage-head { margin-top: 2.25rem; display: grid; gap: 1.5rem; }
@media (min-width: 900px) { .sx-stage-head { grid-template-columns: 1fr auto; align-items: end; } }
.sx-stage-head h3 { font-size: clamp(1.4rem, 2.4vw, 1.9rem); letter-spacing: -.02em; }
.sx-stage-head p { margin-top: .6rem; color: var(--ib-ink-soft); max-width: 68ch; font-size: 1rem; }
.sx-stage-stats { display: flex; gap: 1.75rem; }
.sx-stage-stats div { text-align: left; }
.sx-stage-stats b {
  display: block; font-family: var(--ib-font-mono); font-size: 1.6rem;
  font-weight: 500; color: var(--ib-accent); line-height: 1;
}
.sx-stage-stats span { font-size: .76rem; color: var(--ib-ink-muted); letter-spacing: .02em; }

.sx-fields {
  display: grid; gap: 1rem; margin-top: 2.25rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16.875rem), 1fr));
}
.sx-field {
  border: 1px solid var(--ib-line); border-radius: var(--ib-radius);
  background: var(--ib-card-bg); padding: 1.5rem 1.5rem 1.6rem;
  position: relative; overflow: hidden;
  transition: border-color var(--ib-dur-2), transform var(--ib-dur-2) var(--ibe-out), box-shadow var(--ib-dur-2);
}
.sx-field::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(120% 90% at 0% 0%, rgba(232,132,94,.10), transparent 55%);
  opacity: 0; transition: opacity var(--ib-dur-2); pointer-events: none;
}
.sx-field:hover, .sx-field:focus-within {
  border-color: var(--ib-line-strong); transform: translateY(-0.1875rem); box-shadow: var(--ib-shadow);
}
.sx-field:hover::before, .sx-field:focus-within::before { opacity: 1; }
.sx-field-top { display: flex; align-items: flex-start; gap: .85rem; }
.sx-field-icon {
  flex: 0 0 auto; width: 2.375rem; height: 2.375rem; border-radius: 0.625rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ib-accent-soft); color: var(--ib-accent);
  transition: transform var(--ib-dur-2) var(--ibe-spring);
}
.sx-field:hover .sx-field-icon { transform: translateY(-2px) rotate(-4deg); }
.sx-field-icon svg { width: 1.25rem; height: 1.25rem; }
.sx-field h4 { font-size: 1.08rem; font-weight: 700; letter-spacing: -.01em; }
.sx-field .sx-field-tag {
  display: block; margin-top: .2rem; font-size: .85rem; color: var(--ib-ink-muted);
}
.sx-field ul { margin-top: 1.15rem; display: grid; gap: .55rem; }
.sx-field li {
  position: relative; padding-left: 1.1rem; font-size: .9rem;
  color: var(--ib-ink-soft); line-height: 1.45;
}
.sx-field li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 0.3125rem; height: 0.3125rem; border-radius: 50%; background: var(--ib-accent); opacity: .8;
}
/* Content swap: fade + rise, staggered by index via --i. */
.sx-field[data-swapping] { }
.sx-field ul.is-swapping li { opacity: 0; transform: translateY(0.375rem); }
.sx-field ul li {
  opacity: 1; transform: none;
  transition: opacity .34s var(--ibe-out), transform .34s var(--ibe-out);
  transition-delay: calc(var(--i, 0) * 28ms);
}

.sx-overlap {
  margin-top: 2rem; padding: 1.5rem 1.6rem;
  border: 1px dashed var(--ib-line-strong); border-radius: var(--ib-radius);
  background: transparent; display: grid; gap: .9rem;
}
@media (min-width: 820px) { .sx-overlap { grid-template-columns: 11.875rem 1fr; gap: 2rem; align-items: start; } }
.sx-overlap h4 { font-size: .95rem; letter-spacing: -.005em; }
.sx-overlap p { font-size: .95rem; color: var(--ib-ink-soft); }

/* --------------------------------------------------------------------------
   B.6  Twelve-year timeline
   -------------------------------------------------------------------------- */
.sx-timeline { margin-top: 3rem; display: grid; gap: 1.25rem; }
@media (min-width: 940px) { .sx-timeline { grid-template-columns: repeat(3, 1fr); gap: 1.5rem; } }
.sx-tl {
  position: relative; border: 1px solid var(--ib-line); border-radius: var(--ib-radius);
  background: var(--ib-bg-soft); padding: 1.75rem 1.6rem 1.6rem;
  overflow: hidden;
}
.sx-tl::before {
  content: ""; position: absolute; top: 0; left: 0; height: 0.1875rem; width: 100%;
  background: linear-gradient(90deg, var(--ib-accent), var(--ib-gold));
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 1.1s var(--ibe-out);
}
.sx-tl.is-visible::before { transform: scaleX(1); }
.sx-tl:nth-child(2)::before { transition-delay: .12s; }
.sx-tl:nth-child(3)::before { transition-delay: .24s; }
.sx-tl-grade {
  font-family: var(--ib-font-mono); font-size: .78rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--sx-gold-text);
}
.sx-tl h3 { margin-top: .5rem; font-size: 1.45rem; }
.sx-tl .sx-tl-line { margin-top: .35rem; color: var(--ib-ink-muted); font-size: .92rem; }
.sx-tl p { margin-top: 1rem; font-size: .95rem; color: var(--ib-ink-soft); }
.sx-tl ul { margin-top: 1.2rem; display: grid; gap: .5rem; border-top: 1px solid var(--ib-line); padding-top: 1.2rem; }
.sx-tl li { font-size: .88rem; color: var(--ib-ink-soft); padding-left: 1.35rem; position: relative; }
.sx-tl li::before {
  content: "→"; position: absolute; left: 0; color: var(--ib-accent);
  font-size: .82rem; line-height: 1.6;
}
.sx-tl-sub {
  margin-top: 1.4rem; font-family: var(--ib-font-mono); font-size: .74rem;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ib-ink-muted);
}
.sx-tl-sub + ul { margin-top: .8rem; border-top: 0; padding-top: 0; }
.sx-tl-end {
  margin-top: 1.4rem; padding-top: 1.2rem; border-top: 1px solid var(--ib-line);
  font-size: .92rem; color: var(--ib-ink-soft);
}
.sx-tl-end b {
  display: block; margin-bottom: .45rem;
  font-family: var(--ib-font-mono); font-size: .74rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--sx-accent-text); font-weight: 700;
}

/* --------------------------------------------------------------------------
   B.7  The rocket-equation interactive
   -------------------------------------------------------------------------- */
.sx-rocket { display: grid; gap: 2.5rem; margin-top: 3rem; align-items: start; }
@media (min-width: 980px) { .sx-rocket { grid-template-columns: 1.05fr .95fr; gap: 3.5rem; } }

.sx-eq {
  font-family: var(--ib-font-mono); font-size: clamp(1.05rem, 2vw, 1.35rem);
  color: var(--ib-ink); background: var(--ib-bg-deep);
  border: 1px solid var(--ib-line); border-radius: var(--ib-radius);
  padding: 1.4rem 1.5rem; margin-top: 1.5rem; overflow-x: auto;
  display: flex; align-items: center; gap: .1rem; line-height: 1.9;
}
.sx-frac { display: inline-flex; flex-direction: column; text-align: center; vertical-align: middle;
  margin: 0 .35rem; font-size: .82em; }
/* Direct children only, otherwise the <span class="sx-sub"> inside each
   numerator also matches :first-child and gets a stray rule under it. */
.sx-frac > span:first-child { border-bottom: 1px solid currentColor; padding: 0 .35rem .12rem; }
.sx-frac > span:last-child { padding: .12rem .35rem 0; }
.sx-sub { font-size: .68em; vertical-align: sub; }
.sx-sup { font-size: .68em; vertical-align: super; }

.sx-sliders { display: grid; gap: 1.5rem; margin-top: 1.75rem; }
.sx-slider label {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  font-size: .9rem; color: var(--ib-ink-soft); margin-bottom: .6rem;
}
.sx-slider output {
  font-family: var(--ib-font-mono); font-size: 1rem; color: var(--ib-accent); font-weight: 500;
}
/* The control is 28px tall and transparent; the 3px rail is drawn on the track
   pseudo-element. A 3px-tall input is a 3px-tall touch target, which is the
   difference between a thing a parent drags and a thing they give up on. */
.sx-slider input[type="range"] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 1.75rem;
  background: transparent; outline-offset: 4px; cursor: pointer; margin: 0;
}
.sx-slider input[type="range"]::-webkit-slider-runnable-track {
  height: 0.1875rem; border-radius: 62.4375rem; background: var(--ib-line-strong);
}
.sx-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 1.375rem; height: 1.375rem;
  border-radius: 50%; background: var(--ib-accent); cursor: grab;
  border: 3px solid var(--ib-bg);
  box-shadow: 0 2px 8px -1px rgba(0,0,0,.45);
  margin-top: -0.59375rem;
  transition: transform var(--ib-dur-1) var(--ibe-spring);
}
.sx-slider input[type="range"]::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.15); }
.sx-slider input[type="range"]::-moz-range-track {
  height: 0.1875rem; border-radius: 62.4375rem; background: var(--ib-line-strong);
}
.sx-slider input[type="range"]::-moz-range-thumb {
  width: 1.375rem; height: 1.375rem; border-radius: 50%; background: var(--ib-accent);
  cursor: grab; border: 3px solid var(--ib-bg);
}

/* The vehicle: a single column that fills with propellant as you drag. */
.sx-vehicle { display: grid; grid-template-columns: 4.875rem 1fr; gap: 1.75rem; align-items: start; }
.sx-stack {
  position: relative; border: 1px solid var(--ib-line-strong);
  border-radius: 2.5rem 2.5rem 0.625rem 0.625rem; overflow: hidden;
  background: var(--ib-bg-deep); height: 21.25rem;
  display: flex; flex-direction: column-reverse;
}
.sx-stack-fuel {
  background: linear-gradient(180deg, var(--ib-accent) 0%, #8f3d24 100%);
  height: var(--sx-fuel, 90%);
  transition: height .55s var(--ibe-out);
  position: relative;
}
.sx-stack-fuel::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: rgba(255,255,255,.55);
}
.sx-stack-dry {
  flex: 1 1 auto;
  background: repeating-linear-gradient(135deg,
    transparent 0 0.3125rem, var(--ib-grid-line) 0.3125rem 0.375rem);
}
.sx-readout { display: grid; gap: 1rem; align-content: center; }
.sx-readout div { border-left: 2px solid var(--ib-line); padding-left: .95rem; }
.sx-readout b {
  display: block; font-family: var(--ib-font-mono); font-size: 1.7rem;
  font-weight: 500; color: var(--ib-ink); letter-spacing: -.02em; line-height: 1.1;
}
.sx-readout span { font-size: .78rem; color: var(--ib-ink-muted); letter-spacing: .02em; }
.sx-readout .sx-hot b { color: var(--ib-accent); }
.sx-verdict {
  margin-top: 1.5rem; font-size: .92rem; padding: .9rem 1.05rem;
  border-radius: var(--ib-radius-sm); border: 1px solid var(--ib-line);
  background: var(--ib-bg-deep); color: var(--ib-ink-soft);
}
.sx-note {
  margin-top: 1.5rem; font-size: .82rem; color: var(--ib-ink-muted);
  border-top: 1px solid var(--ib-line); padding-top: 1rem; max-width: 62ch;
}

/* Three-ages ladder */
.sx-ages { display: grid; gap: 1rem; margin-top: 2.5rem; }
@media (min-width: 900px) { .sx-ages { grid-template-columns: repeat(3, 1fr); } }
.sx-age {
  border: 1px solid var(--ib-line); border-radius: var(--ib-radius);
  background: var(--ib-card-bg); padding: 1.6rem 1.7rem;
}
.sx-age .grade {
  font-size: .78rem; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 600; color: var(--ib-accent);
}
.sx-age h3 { margin: .5rem 0 .7rem; font-size: 1.15rem; }
.sx-age p { font-size: .93rem; color: var(--ib-ink-soft); }
.sx-age p + p { margin-top: .75rem; }

/* --------------------------------------------------------------------------
   B.8  Evidence / outcomes / careers
   -------------------------------------------------------------------------- */
.sx-cols { display: grid; gap: 1rem; margin-top: 2.5rem; }
@media (min-width: 760px)  { .sx-cols-2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .sx-cols-3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) { .sx-cols-4 { grid-template-columns: repeat(4, 1fr); } }

.sx-tile {
  border: 1px solid var(--ib-line); border-radius: var(--ib-radius);
  padding: 1.5rem 1.55rem; background: var(--ib-bg-soft);
  transition: border-color var(--ib-dur-2), transform var(--ib-dur-2) var(--ibe-out);
}
.sx-tile:hover { border-color: var(--ib-line-strong); transform: translateY(-2px); }
.sx-tile h4 { font-size: 1rem; }
.sx-tile .sx-kicker {
  font-family: var(--ib-font-mono); font-size: .74rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--sx-gold-text); display: block; margin-bottom: .7rem;
}
.sx-tile p { margin-top: .55rem; font-size: .92rem; color: var(--ib-ink-soft); }
.sx-tile ul { margin-top: .9rem; display: grid; gap: .45rem; }
.sx-tile li { font-size: .88rem; color: var(--ib-ink-soft); padding-left: 1rem; position: relative; }
.sx-tile li::before {
  content: ""; position: absolute; left: 0; top: .58em; width: 0.25rem; height: 0.25rem;
  border-radius: 50%; background: var(--ib-accent);
}

/* Employer marquee, static list, no scrolling gimmick, just typography. */
.sx-employers {
  margin-top: 2rem; display: flex; flex-wrap: wrap; gap: .55rem;
}
.sx-employers span {
  font-family: var(--ib-font-mono); font-size: .76rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ib-ink-soft);
  border: 1px solid var(--ib-line); border-radius: 62.4375rem; padding: .42rem .9rem;
  transition: border-color var(--ib-dur-2), color var(--ib-dur-2);
}
.sx-employers span:hover { border-color: var(--ib-accent); color: var(--ib-accent); }

/* The ITAR argument gets its own emphasis slab. */
.sx-slab {
  border-radius: var(--ib-radius-lg); padding: clamp(2rem, 4vw, 3.25rem);
  background: var(--ib-emphasis-bg); color: var(--ib-emphasis-text);
  border: 1px solid var(--ib-emphasis-line); margin-top: 3rem;
}
.sx-slab h3 { color: var(--ib-emphasis-text); font-size: clamp(1.35rem, 2.6vw, 1.85rem); max-width: 24ch; }
.sx-slab p { color: var(--ib-emphasis-text-soft); margin-top: 1.1rem; max-width: 64ch; font-size: 1.02rem; }
.sx-slab .sx-slab-grid {
  margin-top: 2.25rem; display: grid; gap: 1.5rem; border-top: 1px solid var(--ib-emphasis-line); padding-top: 2rem;
}
@media (min-width: 820px) { .sx-slab .sx-slab-grid { grid-template-columns: repeat(3, 1fr); gap: 2rem; } }
/* On wide screens the slab reads as a spread: claim on the left, argument on
   the right. Left-aligning both would leave half the slab empty. */
@media (min-width: 940px) {
  .sx-slab { display: grid; grid-template-columns: minmax(0,.92fr) minmax(0,1.08fr); column-gap: 3.5rem; }
  .sx-slab > h3 { grid-column: 1; max-width: 18ch; }
  .sx-slab > p  { grid-column: 2; margin-top: .3rem; max-width: none; }
  .sx-slab > .sx-slab-grid { grid-column: 1 / -1; }
}
.sx-slab .sx-slab-grid h4 { color: var(--ib-emphasis-text); font-size: .95rem; }
.sx-slab .sx-slab-grid p { color: var(--ib-emphasis-text-faint); font-size: .9rem; margin-top: .4rem; }

/* --------------------------------------------------------------------------
   B.9  How it runs / objections / FAQ
   -------------------------------------------------------------------------- */
.sx-runs { display: grid; gap: 2rem; margin-top: 2.5rem; }
@media (min-width: 880px) { .sx-runs { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; } }
.sx-run h4 { font-size: 1.05rem; }
.sx-run p { margin-top: .6rem; font-size: .94rem; color: var(--ib-ink-soft); }
.sx-run-rule { height: 2px; width: 2.125rem; background: var(--ib-accent); margin-bottom: 1.1rem; }

.sx-faq { margin-top: 2.5rem; max-width: 53.75rem; border-top: 1px solid var(--ib-line); }
.sx-faq details { border-bottom: 1px solid var(--ib-line); }
.sx-faq summary {
  list-style: none; cursor: pointer; padding: 1.3rem 3rem 1.3rem 0;
  font-weight: 600; font-size: 1.03rem; color: var(--ib-ink);
  position: relative; transition: color var(--ib-dur-1);
}
.sx-faq summary::-webkit-details-marker { display: none; }
.sx-faq summary:hover { color: var(--ib-accent-ink); }
.sx-faq summary::after {
  content: ""; position: absolute; right: .35rem; top: 50%;
  width: 0.6875rem; height: 0.6875rem; margin-top: -0.4375rem;
  border-right: 2px solid var(--ib-accent); border-bottom: 2px solid var(--ib-accent);
  transform: rotate(45deg); transform-origin: 60% 60%;
  transition: transform var(--ib-dur-2) var(--ibe-out);
}
.sx-faq details[open] summary::after { transform: rotate(-135deg); }
.sx-faq .sx-faq-body { padding: 0 0 1.5rem; max-width: 68ch; }
.sx-faq .sx-faq-body p { color: var(--ib-ink-soft); font-size: .98rem; }
.sx-faq .sx-faq-body p + p { margin-top: .85rem; }
.sx-faq details[open] .sx-faq-body { animation: sx-fade .4s var(--ibe-out); }
@keyframes sx-fade { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* Educator */
.sx-educator { display: grid; gap: 2.5rem; align-items: center; margin-top: 2.5rem; }
@media (min-width: 900px) { .sx-educator { grid-template-columns: 16.75rem 1fr; gap: 3.5rem; } }
.sx-portrait {
  aspect-ratio: 4 / 5; border-radius: var(--ib-radius-lg); overflow: hidden;
  border: 1px solid var(--ib-line); background: var(--ib-bg-deep);
  position: relative; margin: 0;
}
/* A real photograph, not a monogram. Sized by the frame and cropped by the
   image, so the ratio is reserved before the file arrives and nothing shifts. */
.sx-portrait img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%; }
/* A hairline warm wash stops a greyscale headshot reading as stock photography
   dropped onto a cream page. */
.sx-portrait::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(201,100,66,.07), rgba(32,32,30,.10));
  mix-blend-mode: multiply;
}
/* In dark mode a light-background headshot is the brightest object on the page
   and pulls the eye away from the quote beside it. Sit it back into the surface. */
[data-theme="dark"] .sx-portrait::after {
  background: linear-gradient(180deg, rgba(232,132,94,.10), rgba(0,0,0,.34));
  mix-blend-mode: normal;
}
[data-theme="dark"] .sx-portrait img { filter: brightness(.86) contrast(1.03); }
.sx-void .sx-portrait img { filter: brightness(.86) contrast(1.03); }
/* On a phone a full-width 4:5 photograph is 480px of face. Cap it. */
@media (max-width: 899px) { .sx-portrait { max-width: 16.125rem; } }
.sx-quote {
  font-size: clamp(1.2rem, 2.2vw, 1.5rem); line-height: 1.4;
  letter-spacing: -.015em; font-weight: 600; color: var(--ib-ink); max-width: 30ch;
}
.sx-credentials { margin-top: 1.75rem; display: grid; gap: .55rem; }
.sx-credentials li { font-size: .93rem; color: var(--ib-ink-soft); padding-left: 1.5rem; position: relative; }
.sx-credentials li::before {
  content: ""; position: absolute; left: 0; top: .45em; width: 0.5625rem; height: 0.3125rem;
  border-left: 2px solid var(--ib-success); border-bottom: 2px solid var(--ib-success);
  transform: rotate(-45deg);
}

/* --------------------------------------------------------------------------
   B.10  Final CTA
   -------------------------------------------------------------------------- */
.sx-final { padding-block: clamp(5rem, 12vh, 8rem); text-align: center; }
.sx-final h2 { font-size: clamp(2rem, 4.4vw, 3.1rem); max-width: 18ch; margin-inline: auto; letter-spacing: -.03em; }
.sx-final .sx-lede { margin-inline: auto; text-align: center; }
.sx-final-actions { display: flex; flex-wrap: wrap; gap: .75rem; justify-content: center; margin-top: 2.25rem; }
.sx-final-fine {
  margin-top: 2.5rem; font-family: var(--ib-font-mono); font-size: .74rem;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ib-ink-muted);
}

/* Stage recap under the final call to action. Three statements, no links:
   nothing on this page is downloadable, so the plan is stated here instead. */
.sx-recap {
  display: grid; gap: 1rem; margin-top: 3rem; text-align: left;
  max-width: 58.75rem; margin-inline: auto;
}
@media (min-width: 820px) { .sx-recap { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; } }
.sx-recap > div {
  border-top: 2px solid var(--ib-accent);
  padding-top: 1.1rem;
}
.sx-recap b {
  display: block; font-family: var(--ib-font-mono); font-size: .74rem;
  letter-spacing: .16em; text-transform: uppercase; color: var(--sx-gold-text);
  font-weight: 500;
}
.sx-recap span { display: block; margin-top: .35rem; font-size: 1.15rem; font-weight: 700; color: var(--ib-ink); letter-spacing: -.01em; }
.sx-recap p { margin-top: .6rem; font-size: .9rem; color: var(--ib-ink-soft); line-height: 1.5; }

/* --------------------------------------------------------------------------
   B.11  Section rhythm and rules
   -------------------------------------------------------------------------- */
.sx-sec { padding-block: clamp(4.5rem, 9vh, 7rem); }
.sx-sec + .sx-sec:not(.sx-void) { border-top: 1px solid var(--ib-line); }
.sx-wide { max-width: 73.75rem; margin-inline: auto; padding-inline: 1.25rem; }
.sx-mt-1 { margin-top: 1rem; }
.sx-mt-2 { margin-top: 2rem; }
.sx-mt-3 { margin-top: 3rem; }

/* Nav sits over the hero until the hero has passed. Motion only, the nav is
   still the site nav, with the site's tokens, just temporarily transparent.

   To do that the nav has to overlay the hero rather than sit above it, so on
   THIS PAGE ONLY it is promoted from sticky to fixed and the hero pays back
   the 68px it took out of the flow. Scoped to body.sx-page so the shared
   component is untouched everywhere else. */
body.sx-page .ib-nav { position: fixed; top: 0; left: 0; right: 0; }
body.sx-page .sx-hero { padding-top: calc(4.25rem + clamp(3rem, 8vh, 6rem)); }
/* Anchor targets must clear the fixed bar. */
body.sx-page [id] { scroll-margin-top: 5.5rem; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

.ib-nav.sx-over {
  background: transparent; border-bottom-color: transparent;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
/* The over-hero ink swap lives on the bar row ONLY. The mobile menu panel is
   a sibling of .ib-nav-inner, so it keeps the page's real theme tokens and
   stays readable. Scoping these custom properties to .ib-nav itself made the
   open panel cream-on-cream in light mode (the invisible-menu bug). */
.ib-nav.sx-over .ib-nav-inner {
  --ib-ink: #F2EFE8; --ib-ink-soft: rgba(242,239,232,.78);
  --ib-line-strong: rgba(242,239,232,.28); --ib-bg-deep: rgba(242,239,232,.10);
  --ib-bg: #14120F;
}
.ib-nav.sx-over .ib-logo, .ib-nav.sx-over .ib-nav-links a { color: rgba(242,239,232,.82); }
.ib-nav.sx-over .ib-nav-links a:hover, .ib-nav.sx-over .ib-nav-links a.active { color: #F2EFE8; }
/* While the menu is open the nav is a menu surface, not a hero overlay.
   The page script adds .menu-open alongside the panel's .open; the bar takes
   its solid site surface back so logo, toggles and panel read in both themes. */
.ib-nav.sx-over.menu-open {
  background: var(--ib-nav-bg);
  border-bottom-color: var(--ib-line);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.ib-nav.sx-over.menu-open .ib-nav-inner {
  --ib-ink: #20201E; --ib-ink-soft: #4A4742;
  --ib-line-strong: #C9C0AE; --ib-bg-deep: #EEE9DD; --ib-bg: #F5F1EB;
}
[data-theme="dark"] .ib-nav.sx-over.menu-open .ib-nav-inner {
  --ib-ink: #F2EFE8; --ib-ink-soft: #C9C4BB;
  --ib-line-strong: #45413A; --ib-bg-deep: #232220; --ib-bg: #1A1916;
}
.ib-nav.sx-over.menu-open .ib-logo { color: var(--ib-ink); }

/* --------------------------------------------------------------------------
   B.12  Motion & accessibility guards
   Everything above is decoration. Turn it all off on request, and the page
   still reads, still converts, still passes contrast.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .ib-reveal { opacity: 1 !important; transform: none !important; }
  .sx-tl::before { transform: scaleX(1) !important; }
  .sx-constellation path, .sx-constellation line { stroke-dashoffset: 0 !important; }
  .sx-meteor, .sx-aurora { display: none; }
  .sx-neb { animation: none; }
  .sx-parallax { transform: none !important; }
  /* the rover stops crossing; space.js pins it mid-crater */
}

@media print {
  .sx-layer, .ib-sticky-cta, .ib-scroll-progress, .ib-nav, .sx-meteor { display: none !important; }
  .sx-void { background: #fff !important; color: #000 !important; }
  .ib-reveal { opacity: 1 !important; transform: none !important; }
}

@media (forced-colors: active) {
  .sx-field, .sx-tile, .sx-tl { border: 1px solid CanvasText; }
  .sx-stage-switch button[aria-selected="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; }
}


/* ==========================================================================
   PART C, THE MATHEMATICS LAYER
   ==========================================================================

   /space is lit by a starfield. /mathematics is lit by graph paper: the same
   near-black void surface, the same nebula, the same parallax dot canvas, but
   ruled. The dots stop reading as stars and start reading as plotted points,
   which is the whole idea of the page in one background layer.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   C.1  The ruled void
   Two superimposed repeating gradients, one minor rule and one major rule,
   translated very slowly. No filter, no blend mode, one composited layer,
   exactly the same budget the nebula already runs on.
   -------------------------------------------------------------------------- */
.mx-grid {
  --mx-cell: 2.875rem;
  background-image:
    linear-gradient(to right,  rgba(242,239,232,.055) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(242,239,232,.055) 1px, transparent 1px),
    linear-gradient(to right,  rgba(232,132,94,.10)  1px, transparent 1px),
    linear-gradient(to bottom, rgba(232,132,94,.10)  1px, transparent 1px);
  background-size:
    var(--mx-cell) var(--mx-cell),
    var(--mx-cell) var(--mx-cell),
    calc(var(--mx-cell) * 5) calc(var(--mx-cell) * 5),
    calc(var(--mx-cell) * 5) calc(var(--mx-cell) * 5);
  /* Fade the rule out at the edges so the panel has no visible seam. */
  -webkit-mask-image: radial-gradient(115% 90% at 50% 45%, #000 30%, transparent 78%);
          mask-image: radial-gradient(115% 90% at 50% 45%, #000 30%, transparent 78%);
  opacity: .9;
  animation: mx-rule 90s linear infinite alternate;
}
/* Promote the layer only while its panel is on screen. There are five void
   panels and two of them are thousands of pixels tall; pinning all five as
   compositor layers for the whole session costs real GPU memory for nothing. */
.sx-void.is-onscreen .mx-grid { will-change: transform; }
@keyframes mx-rule {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(calc(var(--mx-cell) * -2), calc(var(--mx-cell) * 1), 0); }
}
.sx-void:not(.is-onscreen) .mx-grid { animation-play-state: paused; }
@media (max-width: 700px) { .mx-grid { --mx-cell: 2.125rem; } }

/* --------------------------------------------------------------------------
   C.2  Hero: the proof, not the statement
   The unit circle that used to sit here was decoration: every mathematics site
   draws one, and it argued for nothing. This is Pythagoras done as a
   dissection. The nine unit squares on the short leg and the sixteen on the
   long leg lift off, turn into the frame of the hypotenuse, and tile its
   square exactly, twenty-five in all. Then they go home and it happens again,
   for as long as the hero is on screen and not one frame longer.

   The canvas is transparent on purpose. The starfield, the grid and the nebula
   behind it are other layers' work and have to show through. All the motion,
   the visibility gate and the phone haptics live in module 7b of
   mathematics.js; everything here is furniture.
   -------------------------------------------------------------------------- */
.mx-pyth-wrap { position: relative; max-width: 35rem; margin-inline: auto; width: 100%; }
.mx-pyth,
.mx-pyth-static { display: block; width: 100%; height: auto; aspect-ratio: 600 / 490; }
.mx-pyth { touch-action: manipulation; }

.mx-pyth-cap {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem 1.125rem;
  flex-wrap: wrap; margin-top: 0.75rem;
  font-family: var(--ib-font-mono); font-size: 0.75rem; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(242,239,232,.42);
}
.mx-pyth-eq  { color: rgba(242,239,232,.72); text-transform: none; letter-spacing: .10em; }
.mx-pyth-sum { color: var(--ib-accent); }

/* Revealed by mathematics.js only where navigator.vibrate exists and the
   pointer is coarse, i.e. on a phone. On a desktop it never appears, because
   an inert control is worse than no control. */
.mx-haptic {
  display: inline-flex; align-items: center; gap: 0.4375rem;
  font: inherit; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(242,239,232,.42); background: transparent;
  border: 1px solid var(--ib-line-strong); border-radius: 62.4375rem;
  padding: 0.3125rem 0.6875rem; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: color var(--ib-dur-1) var(--ibe-out), border-color var(--ib-dur-1) var(--ibe-out);
}
.mx-haptic[hidden] { display: none; }
.mx-haptic-dot {
  width: 0.375rem; height: 0.375rem; border-radius: 50%;
  background: var(--ib-line-strong);
  transition: background var(--ib-dur-1) var(--ibe-out);
}
.mx-haptic[aria-pressed="true"] { color: rgba(242,239,232,.72); border-color: rgba(232,132,94,.45); }
.mx-haptic[aria-pressed="true"] .mx-haptic-dot { background: var(--ib-accent); }
.mx-haptic:focus-visible { outline: 2px solid var(--ib-accent); outline-offset: 3px; }

/* --------------------------------------------------------------------------
   C.3  The secant scene
   /space drives a rover across a crater with the scroll position. This drives
   the second point of a chord down onto the first, which is calculus. Same
   contract: position is a pure function of where the panel sits in the
   viewport, so scrolling back up unmakes it exactly.
   -------------------------------------------------------------------------- */
.mx-curve-stage { position: relative; z-index: 2; margin-top: 2.5rem; }
/* The scene keeps ONE viewBox for its whole life. On a phone the full 1200-unit
   plot renders as a 150px strip, so the element box is narrowed by CSS and
   preserveAspectRatio="slice" crops the dead margins instead. Because the box
   comes from aspect-ratio it is reserved before a byte of script runs, which is
   the difference between a crop and a layout shift. */
.mx-curve-svg { display: block; width: 100%; height: auto; aspect-ratio: 1200 / 460; }
@media (max-width: 760px) { .mx-curve-svg { aspect-ratio: 940 / 460; } }
/* NOTE, do not add text-transform here. f and F, h and H are different symbols,
   and this caption sets both. The labels are hand-cased in the HTML instead. */
.mx-curve-caption {
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; align-items: baseline;
  font-family: var(--ib-font-mono); font-size: .74rem; letter-spacing: .16em;
  color: var(--ib-ink-muted); padding-bottom: 1.25rem;
}
.mx-curve-caption b { text-transform: uppercase; }
.mx-curve-caption b { color: var(--ib-accent); font-weight: 500; }

.mx-curve-svg .grid-line   { stroke: rgba(242,239,232,.07); stroke-width: 1; }
.mx-curve-svg .grid-major  { stroke: rgba(242,239,232,.13); stroke-width: 1; }
.mx-curve-svg .axis        { stroke: rgba(242,239,232,.34); stroke-width: 1.2; }
.mx-curve-svg .curve       { fill: none; stroke: rgba(242,239,232,.55); stroke-width: 2.4; stroke-linecap: round; }
.mx-curve-svg .tangent     { stroke: rgba(232,132,94,.30); stroke-width: 1.4; stroke-dasharray: 5 5; }
.mx-curve-svg .chord       { stroke: var(--ib-accent); stroke-width: 2.2; stroke-linecap: round; }
.mx-curve-svg .rise,
.mx-curve-svg .run         { stroke: rgba(217,178,101,.55); stroke-width: 1.2; stroke-dasharray: 3 4; }
.mx-curve-svg .pt          { fill: var(--ib-accent); }
.mx-curve-svg .pt-ring     { fill: none; stroke: rgba(232,132,94,.45); stroke-width: 1; }
.mx-curve-svg .tick-label  { font-family: var(--ib-font-mono); font-size: 13px; fill: rgba(242,239,232,.40); text-anchor: middle; }
.mx-curve-svg .pt-label    { font-family: var(--ib-font-mono); font-size: 15px; fill: rgba(242,239,232,.75); }
/* The Q label rides on top of the P label once the two points have all but
   merged, which is the moment the panel is making its point. Fade it out
   rather than let two labels collide. mathematics.js writes --mx-qfade. */
.mx-curve-svg .pt-q-label,
.mx-curve-svg .pt-q-ring { opacity: var(--mx-qfade, 1); }

/* On a phone the whole plot would otherwise be a 130 px strip. mathematics.js
   narrows the viewBox to the part that is doing the work; these sizes keep the
   labels and strokes legible inside that tighter window. */
@media (max-width: 760px) {
  .mx-curve-svg .tick-label { font-size: 22px; }
  .mx-curve-svg .pt-label   { font-size: 24px; }
  .mx-curve-svg .curve      { stroke-width: 4; }
  .mx-curve-svg .chord      { stroke-width: 3.6; }
  .mx-curve-svg .tangent    { stroke-width: 2.4; stroke-dasharray: 8 8; }
  .mx-curve-svg .pt         { r: 8px; }
  .mx-curve-svg .pt-ring    { r: 14px; stroke-width: 1.8; }
}

/* The live numbers. Deliberately large: they are the point of the panel. */
.mx-curve-readout {
  display: grid; gap: 1px; margin-top: 2.25rem;
  background: var(--ib-line); border: 1px solid var(--ib-line);
  border-radius: var(--ib-radius); overflow: hidden;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 720px) { .mx-curve-readout { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.mx-curve-readout > div { background: var(--ib-bg); padding: 1.05rem 1.15rem; }
.mx-curve-readout b {
  display: block; font-family: var(--ib-font-mono); font-size: 1.45rem; font-weight: 500;
  color: var(--ib-ink); letter-spacing: -.02em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.mx-curve-readout .is-hot b { color: var(--ib-accent); }
/* Same rule as the caption: no text-transform. These labels carry f(1+h) and
   f-prime(1), and an uppercased F is a different symbol from the one taught. */
.mx-curve-readout span { display: block; margin-top: .4rem; font-size: .74rem; color: var(--ib-ink-muted); letter-spacing: .06em; }

/* --------------------------------------------------------------------------
   C.4  Set mathematics without shipping a maths typesetter
   KaTeX costs a 23 kB stylesheet plus a wall of generated spans that nobody
   can edit afterwards. Everything on this page is one line of algebra, which
   the brand's own mono face sets correctly on its own.
   -------------------------------------------------------------------------- */
.mx-math {
  font-family: var(--ib-font-mono); font-size: 1.02rem; line-height: 1.9;
  color: var(--ib-ink); background: var(--ib-bg-deep);
  border: 1px solid var(--ib-line); border-left: 2px solid var(--ib-accent);
  border-radius: 0 var(--ib-radius-sm) var(--ib-radius-sm) 0;
  padding: 1rem 1.2rem; margin: 1.1rem 0; overflow-x: auto;
  font-variant-numeric: tabular-nums;
}
.mx-math + .mx-math { margin-top: .6rem; }
.mx-math em { font-style: italic; color: var(--ib-accent); font-weight: 500; }
.mx-math small { display: block; font-family: var(--ib-font-sans); font-size: .8rem;
  color: var(--ib-ink-muted); letter-spacing: .02em; margin-top: .45rem; line-height: 1.5; }
.mx-in {
  font-family: var(--ib-font-mono); font-size: .96em;
  background: var(--ib-bg-deep); border-radius: 0.25rem; padding: .08em .38em;
  white-space: nowrap;
}
.mx-sub { font-size: .7em; vertical-align: -.28em; }
.mx-sup { font-size: .7em; vertical-align: .42em; }

/* The three-ages ladder gets more room on this page than on /space, because
   here the working IS the argument. */
.mx-ladder { display: grid; gap: 1rem; margin-top: 2.5rem; }
@media (min-width: 1040px) { .mx-ladder { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; align-items: start; } }
.mx-rung {
  border: 1px solid var(--ib-line); border-radius: var(--ib-radius);
  background: var(--ib-card-bg); padding: 1.7rem 1.75rem 1.8rem;
  position: relative; overflow: hidden;
}
.mx-rung::before {
  content: ""; position: absolute; top: 0; left: 0; height: 0.1875rem; width: 100%;
  background: linear-gradient(90deg, var(--ib-accent), var(--ib-gold));
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 1.1s var(--ibe-out);
}
.is-visible .mx-rung::before { transform: scaleX(1); }
.is-visible .mx-rung:nth-child(2)::before { transition-delay: .12s; }
.is-visible .mx-rung:nth-child(3)::before { transition-delay: .24s; }
.mx-rung .grade {
  font-family: var(--ib-font-mono); font-size: .76rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--sx-gold-text); font-weight: 500;
}
.mx-rung h3 { margin: .55rem 0 .9rem; font-size: 1.18rem; line-height: 1.3; }
.mx-rung p { font-size: .95rem; color: var(--ib-ink-soft); }
.mx-rung p + p { margin-top: .8rem; }
.mx-rung .mx-rung-out {
  margin-top: 1.4rem; padding-top: 1.1rem; border-top: 1px solid var(--ib-line);
  font-size: .9rem; color: var(--ib-ink-soft);
}
.mx-rung .mx-rung-out b {
  display: block; margin-bottom: .4rem; font-family: var(--ib-font-mono);
  font-size: .74rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--sx-accent-text); font-weight: 700;
}

/* --------------------------------------------------------------------------
   C.5  The growth interactive
   The counterpart to the rocket equation. Drag it and watch the exponential
   walk away from the line. It reuses the .sx-slider / .sx-readout / .sx-verdict
   furniture; only the picture is new.
   -------------------------------------------------------------------------- */
.mx-bars {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem;
  align-items: end; height: 21.25rem; padding-top: 1.9rem;
  border-bottom: 1px solid var(--ib-line-strong);
}
.mx-bar { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; text-align: center; }
.mx-bar-fill {
  border-radius: 0.5rem 0.5rem 0 0; height: var(--mx-h, 20%);
  min-height: 0.1875rem;
  transition: height .5s var(--ibe-out);
  position: relative;
}
.mx-bar--linear .mx-bar-fill {
  background: repeating-linear-gradient(135deg, rgba(242,239,232,.16) 0 0.3125rem, rgba(242,239,232,.06) 0.3125rem 0.625rem);
  border: 1px solid var(--ib-line-strong); border-bottom: 0;
}
.mx-bar--exp .mx-bar-fill {
  background: linear-gradient(180deg, var(--ib-accent) 0%, #8f3d24 100%);
}
.mx-bar-fill::after {
  content: attr(data-value); position: absolute; left: 0; right: 0; top: -1.6rem;
  font-family: var(--ib-font-mono); font-size: .82rem; color: var(--ib-ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mx-bar-label {
  margin-top: .7rem; font-family: var(--ib-font-mono); font-size: .74rem;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ib-ink-muted);
}
.mx-bar--exp .mx-bar-label { color: var(--sx-accent-text); }
/* The bar column and its readout sit side by side, like the rocket stack. */
.mx-growth-vis { display: grid; gap: 1.75rem; }
@media (min-width: 560px) { .mx-growth-vis { grid-template-columns: 1fr 1fr; } }

/* --------------------------------------------------------------------------
   C.6  Board / examination chips
   Same object as the employer row on /space, different content, so it keeps
   the same rules and simply gets its own class name for clarity.
   -------------------------------------------------------------------------- */
.mx-boards { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: .55rem; }
.mx-boards span {
  font-family: var(--ib-font-mono); font-size: .76rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ib-ink-soft);
  border: 1px solid var(--ib-line); border-radius: 62.4375rem; padding: .42rem .9rem;
  transition: border-color var(--ib-dur-2), color var(--ib-dur-2);
}
.mx-boards span:hover { border-color: var(--ib-accent); color: var(--ib-accent); }

/* --------------------------------------------------------------------------
   C.7  The strand card, on top of .sx-field
   Only two differences from /space: the icon tile is squarer (these are
   glyphs, not pictograms) and a strand carries a one-line "what it is for"
   under the syllabus, which space handles in its overlap note instead.
   -------------------------------------------------------------------------- */
.sx-field .mx-field-for {
  margin-top: 1.2rem; padding-top: .95rem; border-top: 1px solid var(--ib-line);
  font-size: .84rem; color: var(--ib-ink-muted); line-height: 1.5;
}
.sx-field .mx-field-for b {
  color: var(--sx-accent-text); font-weight: 600; display: block;
  font-family: var(--ib-font-mono); font-size: .74rem; letter-spacing: .14em;
  text-transform: uppercase; margin-bottom: .35rem;
}
.mx-glyph {
  font-family: var(--ib-font-mono); font-size: .86rem; font-weight: 500;
  line-height: 1; letter-spacing: -.03em; white-space: nowrap;
}

/* --------------------------------------------------------------------------
   C.8  Motion guards for everything PART C adds
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .mx-grid { animation: none; }
  /* the dissection stops of its own accord; module 7b draws the finished
     proof once and never starts a loop */
  .mx-bar-fill { transition: none; }
  /* the chord stops closing; mathematics.js pins it at a readable h */
}

@media print {
  .mx-grid { display: none !important; }
  .mx-math { border-color: #999; }
}

@media (forced-colors: active) {
  .mx-rung, .mx-math, .mx-curve-readout > div { border: 1px solid CanvasText; }
  /* Every stroke collapses to CanvasText here, and the whole panel is "watch the
     chord settle onto the tangent". Weight and dash are the only channels left. */
  .mx-curve-svg .curve   { stroke-width: 5; }
  .mx-curve-svg .chord   { stroke-width: 2.5; stroke-dasharray: 14 6; }
  .mx-curve-svg .tangent { stroke-width: 1.5; stroke-dasharray: 3 6; }
  .mx-curve-svg .grid-line, .mx-curve-svg .grid-major { display: none; }
}


/* ============================================================
   Insight Bay — mobile footer density fix   (2026-08-09)
   Scoped to <= 767px. Desktop untouched.
   The footer link columns are plain <a> blocks inside
   .ib-footer-grid > div, so this targets that structure:
   every link group after the brand column flows into two
   newspaper columns (reading order preserved, top to bottom
   then across) and every link keeps a 44px tap target.
   No font-size, colour or copy is changed.
   Rollback: delete this block.
   ============================================================ */
@media (max-width: 767px) {
  .ib-footer { padding-top: 3rem; }

  .ib-footer-grid { row-gap: 1.5rem; }

  /* Skip the first child: that is the brand / bio / social column. */
  .ib-footer-grid > div + div {
    columns: 2;
    column-gap: 1.125rem;
  }

  .ib-footer-grid > div + div > h4 {
    column-span: all;
    -webkit-column-span: all;
    margin-bottom: .45rem;
  }

  .ib-footer-grid > div + div > a {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
    line-height: 1.3;
    padding: .25rem 0.375rem .25rem 0;
    overflow-wrap: anywhere;
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* Skip link: off-screen until focused (same rule as styles.css;
   this page does not load styles.css, so it was showing). */
.ib-skip{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;z-index:2000}
.ib-skip:focus,.ib-skip:focus-visible{left:.75rem;top:.75rem;width:auto;height:auto;overflow:visible;padding:.6rem 1.05rem;border-radius:.5rem;background:var(--ib-bg-deep,#12141a);color:var(--ib-ink,#f5f1eb);font-weight:600;text-decoration:none;outline:2px solid var(--ib-accent,#c2673c);outline-offset:2px}


/* ============================================================
   Wide screens (added 21 Sep 2026). Nothing changes below 1280px.
   Above it the layout grows with the window instead of sitting in
   a fixed 1180px column: the container keeps a slim outer margin
   and the whole type and spacing scale (all in rem) rises gently,
   from 16px at 1280 to 20px at 1920, capped at 22px, so every
   section keeps its proportions.
   ============================================================ */
@media (min-width: 1280px) {
  html { font-size: clamp(100%, calc(50% + 0.625vw), 137.5%); }
  .ib-container,
  .sx-wide { max-width: min(calc(84.375vw + 100px), 92rem); }
}


/* ============================================================
   Brand mark (21 Sep 2026). The rounded square and the slanted
   "i" follow the master logo artwork exactly: on its 800 unit
   grid the corner radius is 175, the dot is r 67.5 centred at
   (416.25, 218.75) and the stem is a 117.5 wide pill skewed by
   8 degrees. The box keeps the site accent colour. The letter in
   the markup stays for screen readers but is not painted.
   ============================================================ */
.ib-logo-mark {
  border-radius: 21.875%; color: transparent;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 800' fill='white'%3E%3Ccircle cx='416.25' cy='218.75' r='67.5'/%3E%3Crect x='391.25' y='337.5' width='117.5' height='306.25' rx='58.75' transform='skewX(-8)'/%3E%3C/svg%3E");
  background-position: center; background-size: 100% 100%; background-repeat: no-repeat;
}
