/* ==========================================================================
   JEEnius — "Inside the engine"
   Cinematic homepage layer. Loaded ONLY by index.html, on top of app.css.
   Scoped to body.jx so about/products/contact/404 are untouched.

   Structure of this file
     1  stage tokens (dark = night sky, light = daylight blueprint)
     2  page shell + the persistent WebGL stage
     3  typography scale
     4  controls (buttons, nav, marks)
     5  scene primitives (sticky holds, progress, rails)
     6  the eight scenes
     7  motion fallbacks: reduced motion, no-WebGL, no-JS
     8  responsive
   ========================================================================== */

/* ==========================================================================
   1  STAGE TOKENS
   The brand tokens in app.css stay authoritative for colour identity.
   These add the depth range a cinematic page needs: four grounds instead of
   two, plus a luminance token the WebGL layer reads back through JS.
   ========================================================================== */

body.jx {
  /* light — "daylight blueprint": ink on warm paper, gold as the marker */
  --void: #F3F0E7;
  --void-2: #F8F6F0;
  --veil: rgba(15, 32, 29, .06);
  --veil-2: rgba(15, 32, 29, .12);
  --hair: rgba(15, 32, 29, .14);
  --glow: #1B3B36;
  --beam: #2E7D5B;
  --spark: #8A6A00;
  --ink-x: #0B1815;
  --scrim: rgba(243, 240, 231, .92);
  --panel: rgba(250, 248, 243, .93);
  --panel-line: rgba(15, 32, 29, .10);
  --r-panel: 18px;
  --lift: 0 26px 60px -34px rgba(15, 32, 29, .40);
  --dur: .7s;
  --out: cubic-bezier(.16, 1, .3, 1);
}

body.jx.is-dark,
.dark body.jx {
  /* dark — "night sky": the engine seen from inside */
  --void: #050D0B;
  --void-2: #081613;
  --veil: rgba(127, 216, 190, .07);
  --veil-2: rgba(127, 216, 190, .14);
  --hair: rgba(160, 220, 200, .16);
  --glow: #7FD8BE;
  --beam: #3DDC97;
  --spark: #FFD700;
  --ink-x: #F2FBF7;
  --scrim: rgba(5, 13, 11, .88);
  --panel: rgba(10, 26, 23, .90);
  --panel-line: rgba(160, 220, 200, .14);
  --lift: 0 30px 70px -34px rgba(0, 0, 0, .78);
}

/* ==========================================================================
   2  PAGE SHELL + WEBGL STAGE
   ========================================================================== */

/* Lenis's required stylesheet, inlined rather than pulled from a second CDN
   file. This is not optional decoration: app.css sets `html { scroll-behavior:
   smooth }` for anchor links on the other pages, and Lenis drives scrolling by
   writing a new scroll position every frame. With native smooth-scroll on, the
   browser eases toward each of those per-frame targets instead of applying
   them, the two loops fight, and the page crawls: measured at 8px of movement
   for 9,600px of wheel input. Keyed on Lenis's own class, so if the Lenis
   script never loads, `scroll-behavior: smooth` correctly stays in charge. */
html.lenis, html.lenis body { height: auto; }
html.lenis-smooth { scroll-behavior: auto !important; }
html.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
html.lenis-stopped { overflow: hidden; }
html.lenis-smooth iframe { pointer-events: none; }

body.jx {
  background: var(--void);
  color: var(--ink-x);
  overflow-x: clip;
}

body.jx .hidden { display: none !important; }

/* the single canvas that carries every scene. One renderer, one loop. */
/* --stage-dim is the single owner of how present the world is. journey.js
   writes it on <html>; nothing else animates these opacities, so the three
   scroll ranges that step the field back can never fight each other. */
.jx-stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.1s var(--out);
  contain: strict;
}
html.jx-gl .jx-stage { opacity: var(--stage-dim, 1); transition: opacity .25s linear; }
.jx-stage canvas { display: block; width: 100%; height: 100%; }

/* CSS understudy: shown until (or instead of) WebGL. Never a bare gradient —
   it carries the same two-shell geometry the 3D core does. */
.jx-understudy {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% 42%, var(--veil) 0%, transparent 62%),
    radial-gradient(80% 60% at 78% 12%, color-mix(in srgb, var(--spark) 14%, transparent) 0%, transparent 60%),
    var(--void);
  opacity: var(--stage-dim, 1);
  transition: opacity .9s var(--out);
}
html.jx-gl .jx-understudy { opacity: 0; }
.jx-understudy i {
  position: absolute;
  left: 50%;
  top: 44%;
  border: 1px solid var(--veil-2);
  border-radius: 50%;
  transform: translate(-50%, -50%) rotate(0deg);
  aspect-ratio: 1;
}
.jx-understudy i:nth-child(1) { width: 34vmax; animation: jxSpin 58s linear infinite; }
.jx-understudy i:nth-child(2) { width: 52vmax; border-style: dashed; opacity: .6; animation: jxSpin 96s linear infinite reverse; }
.jx-understudy i:nth-child(3) { width: 18vmax; border-color: color-mix(in srgb, var(--spark) 34%, transparent); animation: jxSpin 40s linear infinite; }
@keyframes jxSpin { to { transform: translate(-50%, -50%) rotate(360deg); } }

/* Everything readable sits above the stage. The nav and the mobile menu are
   deliberately NOT in this list: app.css already fixes them, and re-declaring
   position here would drop the menu back into flow and push the whole page
   down by its height. */
body.jx main,
body.jx footer { position: relative; z-index: 2; }

/* film grain: one fixed, pointer-events-none layer. Never on a scroller. */
.jx-grain {
  position: fixed;
  inset: -50%;
  z-index: 3;
  pointer-events: none;
  opacity: .028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  contain: strict;
}
body.jx.is-dark .jx-grain { opacity: .05; }

/* ==========================================================================
   3  TYPOGRAPHY
   Fraunces stays the JEEnius display face (brand continuity with
   jee.jeenius.tech and neet.jeenius.tech). JetBrains Mono is new: it carries
   the data register — years, counts, coverage — so numbers read as readings
   off an instrument rather than as marketing.
   ========================================================================== */

body.jx { font-family: 'Plus Jakarta Sans', system-ui, sans-serif; }

.jx-mono {
  font-family: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

.jx-kicker {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--spark);
}
.jx-kicker::before {
  content: "";
  width: 22px;
  height: 1px;
  background: currentColor;
  opacity: .7;
}

.jx-h1 {
  font-family: 'Fraunces', Georgia, serif;
  font-optical-sizing: auto;
  font-weight: 500;
  font-size: clamp(38px, min(6.6vw, 11vh), 92px);
  line-height: 1.02;
  letter-spacing: -.03em;
  color: var(--ink-x);
  margin: 0;
  text-wrap: balance;
}
.jx-h2 {
  font-family: 'Fraunces', Georgia, serif;
  font-optical-sizing: auto;
  font-weight: 500;
  font-size: clamp(28px, min(4.4vw, 7.2vh), 56px);
  line-height: 1.06;
  letter-spacing: -.028em;
  color: var(--ink-x);
  margin: 0;
  text-wrap: balance;
}
.jx-h3 {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600;
  font-size: clamp(20px, min(2.2vw, 3.4vh), 26px);
  line-height: 1.16;
  letter-spacing: -.02em;
  color: var(--ink-x);
  margin: 0;
}

/* the emphasised phrase inside a headline: same family, italic, with the
   descender clearance italic Fraunces needs */
.jx-em {
  font-style: italic;
  color: var(--glow);
  line-height: 1.12;
  padding-bottom: 2px;
  display: inline-block;
}

.jx-lead {
  font-size: clamp(15.5px, min(1.35vw, 2.3vh), 19px);
  line-height: 1.6;
  color: color-mix(in srgb, var(--ink-x) 72%, transparent);
  max-width: 54ch;
  margin: 0;
}
.jx-note {
  font-size: 12.5px;
  line-height: 1.6;
  color: color-mix(in srgb, var(--ink-x) 52%, transparent);
  max-width: 62ch;
  margin: 0;
}

/* ==========================================================================
   4  CONTROLS
   ========================================================================== */

.jx-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.jx-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 26px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  isolation: isolate;
  transition: transform .32s var(--out), box-shadow .32s var(--out), background-color .3s var(--out), border-color .3s var(--out), color .3s var(--out);
}
.jx-btn svg { width: 17px; height: 17px; flex: none; }
.jx-btn .jx-arr { transition: transform .34s var(--out); }
.jx-btn:hover .jx-arr { transform: translateX(4px); }
.jx-btn:active { transform: translateY(1px) scale(.985); }

/* primary: solid brand green in light, luminous mint in dark. Contrast is
   checked against its own fill in both modes, not against the page. */
.jx-btn--go {
  background: #1B3B36;
  color: #FFFFFF;
  box-shadow: 0 14px 34px -18px rgba(15, 32, 29, .8);
}
.jx-btn--go:hover { background: #244A44; transform: translateY(-2px); box-shadow: 0 22px 48px -20px rgba(15, 32, 29, .7); }
body.jx.is-dark .jx-btn--go { background: #7FD8BE; color: #05201B; box-shadow: 0 0 0 1px rgba(127, 216, 190, .3), 0 18px 46px -20px rgba(61, 220, 151, .5); }
body.jx.is-dark .jx-btn--go:hover { background: #9FE8D2; }

/* secondary: outlined, always legible because it owns a real border */
.jx-btn--line {
  background: color-mix(in srgb, var(--void-2) 94%, transparent);
  color: var(--ink-x);
  border-color: var(--hair);
}
.jx-btn--line:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--glow) 60%, transparent);
  background: color-mix(in srgb, var(--glow) 10%, var(--void-2));
}
@media (prefers-reduced-transparency: reduce) {
  .jx-btn--line { background: var(--void-2); }
}

.jx-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 700;
  color: color-mix(in srgb, var(--ink-x) 66%, transparent);
  border-bottom: 1px solid transparent;
  transition: color .25s var(--out), border-color .25s var(--out);
}
.jx-link:hover { color: var(--glow); border-color: currentColor; }

/* ---- navigation: a hairline over the hero, a floating pill after ---- */
body.jx .nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 68px;
  display: flex;
  align-items: center;
  background: transparent;
  border: 0;
  transition: background-color .45s var(--out), box-shadow .45s var(--out);
}
body.jx .nav.scrolled {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--void) 97%, transparent),
    color-mix(in srgb, var(--void) 88%, transparent));
  box-shadow: 0 1px 0 var(--panel-line);
}
body.jx .nav .brand { color: var(--ink-x); font-weight: 800; letter-spacing: -.02em; }
body.jx .nav-link {
  position: relative;
  font-size: 14px;
  font-weight: 600;
  color: color-mix(in srgb, var(--ink-x) 64%, transparent);
}
body.jx .nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -6px;
  height: 1px;
  width: 100%;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .34s var(--out);
}
body.jx .nav-link:hover { color: var(--ink-x); }
body.jx .nav-link:hover::after { transform: scaleX(1); }
body.jx .nav-link[aria-current="true"] { color: var(--glow); }
body.jx .nav-link[aria-current="true"]::after { transform: scaleX(1); }
body.jx .icon-btn { color: var(--ink-x); border-color: var(--hair); background: transparent; }
body.jx .icon-btn:hover { background: var(--veil); }

/* scroll progress: a single hairline under the nav. It is the only chrome
   that reports position, which is why there is no "scroll" cue anywhere. */
.jx-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 100%;
  z-index: 60;
  transform-origin: left;
  transform: scaleX(0);
  background: linear-gradient(90deg, var(--glow), var(--spark));
  pointer-events: none;
}

/* index.html carries no Tailwind, so the nav owns its own responsive rules.
   One line, 68px tall, at every width. */
.jx-navlinks { display: flex; align-items: center; gap: 30px; }
.jx-burger { display: none; }
@media (max-width: 880px) {
  .jx-navlinks { display: none; }
  .jx-burger { display: inline-flex; }
  .jx-navcta { display: none; }
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

body.jx .mobile-menu {
  background: var(--void);
  border-bottom: 1px solid var(--panel-line);
}
body.jx .mobile-menu a { color: var(--ink-x); }

/* ==========================================================================
   5  SCENE PRIMITIVES
   Every scene is a tall <section> whose inner .jx-hold is position:sticky.
   Sticky (not ScrollTrigger pin) means no pin-spacers, no layout jump on
   refresh, and it still works with JS switched off.
   ========================================================================== */

.jx-scene { position: relative; }
.jx-hold {
  position: sticky;
  top: 0;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.jx-wrap {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(72px, 11vh, 96px) 26px clamp(52px, 9vh, 84px);
}

/* the readable panel: a soft scrim so copy stays AA-legible over the field */
.jx-panel {
  background: var(--panel);
  border: 1px solid var(--panel-line);
  border-radius: var(--r-panel);
  box-shadow: var(--lift);
}

/* scene-level scrim: keeps contrast over the brightest part of the field */
.jx-hold::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Copy has to clear AA over a field that is sometimes very busy, so the
     scrim holds full strength across the whole reading column and only then
     falls away. A weaker centre-weighted wash left the corridor scene
     unreadable. */
  background: radial-gradient(120% 96% at var(--sx, 30%) 50%,
    var(--scrim) 0%, var(--scrim) 26%,
    color-mix(in srgb, var(--void) 62%, transparent) 58%,
    color-mix(in srgb, var(--void) 22%, transparent) 76%,
    transparent 92%);
}
/* the scrim follows the copy, so the field stays clear on the other side */
.jx-pattern { --sx: 72%; }
.jx-predict, .jx-worlds { --sx: 50%; }
/* the two worlds scene puts its copy in a band across the top, with the
   lattice and the helix reaching into it from both sides, so it needs a band
   rather than the default centre-weighted wash */
.jx-worlds .jx-hold::before {
  background:
    radial-gradient(58% 34% at 50% 30%, var(--scrim) 0%, var(--scrim) 42%, transparent 100%),
    radial-gradient(120% 60% at 50% 100%, color-mix(in srgb, var(--void) 55%, transparent), transparent 70%);
}
.jx-wrap { position: relative; z-index: 1; }

/* copy blocks lifted by the journey timeline */
.jx-rise { will-change: transform, opacity; }

/* SplitText line masks: the mask has to be on the line box, not the glyphs,
   or Fraunces' descenders get clipped as each line rises */
.jx-line { overflow: hidden; padding-bottom: .06em; }

/* Short desktop windows: a hold that is taller than the viewport hides its own
   bottom, because sticky pins the top. Below 700px of height the scenes stop
   holding and simply scroll past.

   This is deliberately a static media query rather than a JS measurement.
   A JS guard has to wait for fonts, so it can only add its class after first
   paint, and toggling any layout property that late is a layout shift: the
   measured cost of the JS version of this exact rule was a CLS of 1.0.
   The section heights are untouched either way, so the world's timing and the
   scroll length of every scene are identical in both branches. */
@media (min-width: 901px) and (max-height: 700px) and (prefers-reduced-motion: no-preference) {
  .jx-hold { position: static; align-items: flex-start; }
  .jx-hold::before {
    background: linear-gradient(180deg,
      color-mix(in srgb, var(--void) 62%, transparent),
      color-mix(in srgb, var(--void) 88%, transparent) 70%);
  }
  .jx-wrap { padding-top: clamp(88px, 13vh, 108px); }
}

/* Scene lengths. A scene's height IS its duration: the sticky hold stays put
   for exactly this much scroll, which is the whole timing system. Scenes that
   have to resolve a sequence (the solve, the tunnel) get more room.
   Released entirely under 900px and under reduced motion. */
@media (min-width: 901px) and (prefers-reduced-motion: no-preference) {
  #scene-enter   { height: 128svh; }
  #scene-archive { height: 235svh; }
  #scene-pattern { height: 250svh; }
  #engine        { height: 300svh; }
  #scene-predict { height: 235svh; }
  /* --pan is written by journey.js: exactly the distance the rail travels */
  #scene-product { height: calc(100svh + var(--pan, 60vw)); }
  #pick          { height: 205svh; }
}

/* a hairline rule used instead of card borders wherever grouping is enough */
.jx-rule { height: 1px; background: var(--hair); border: 0; margin: 0; }

/* ==========================================================================
   6  THE SCENES
   ========================================================================== */

/* ---- 01 ENTER ----------------------------------------------------------- */
.jx-hero .jx-hold { align-items: center; }
.jx-hero .jx-wrap { padding-top: 92px; padding-bottom: 56px; max-width: 1180px; }
/* Sized so the headline lands on exactly two lines at every desktop width and
   the calls to action stay above the fold on a 720px-tall laptop. */
.jx-hero__inner { max-width: min(100%, 1020px); }
.jx-hero .jx-h1 { margin: clamp(12px, 2.2vh, 20px) 0 0; font-size: clamp(34px, min(5.2vw, 9vh), 72px); }
.jx-hero .jx-lead { margin: clamp(15px, 2.6vh, 24px) 0 0; max-width: 46ch; }
.jx-hero .jx-actions { margin-top: clamp(20px, 3.6vh, 34px); }

/* ---- 02 THE ARCHIVE ----------------------------------------------------- */
/* copy sits high and narrow; the readout is a full-width instrument band
   beneath it, so this scene does not repeat the two-column shape of 03 or 04 */
.jx-archive .jx-wrap { display: grid; gap: clamp(26px, 4.6vh, 46px); align-content: center; }
.jx-archive__copy { max-width: 46ch; }
.jx-readout {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--panel-line);
  border: 1px solid var(--panel-line);
  border-radius: var(--r-panel);
  overflow: hidden;
}
.jx-readout > div { background: var(--void-2); padding: clamp(14px, 2.3vh, 22px) 20px; }
.jx-readout dt {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink-x) 52%, transparent);
  margin: 0 0 8px;
}
.jx-readout dd {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--glow);
}
.jx-readout dd small { font-size: .5em; letter-spacing: 0; }
.jx-readout p { margin: 8px 0 0; font-size: 12.5px; color: color-mix(in srgb, var(--ink-x) 58%, transparent); }

/* ---- 03 THE PATTERN ----------------------------------------------------- */
.jx-pattern .jx-wrap { display: grid; grid-template-columns: minmax(0, 440px) minmax(0, 1fr); gap: 66px; align-items: center; }
.jx-chapters { list-style: none; margin: 0; padding: 0; }

.jx-chap {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 18px;
  width: 100%;
  padding: clamp(7px, 1.4vh, 13px) 4px;
  background: none;
  border: 0;
  text-align: left;
  color: color-mix(in srgb, var(--ink-x) 62%, transparent);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  transition: color .3s var(--out), padding-left .34s var(--out);
}
.jx-chap:hover { color: var(--ink-x); padding-left: 12px; }
.jx-chap__n {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 13px;
  font-weight: 700;
  color: color-mix(in srgb, var(--ink-x) 40%, transparent);
  transition: color .3s var(--out);
}
.jx-chap:hover .jx-chap__n { color: var(--spark); }
.jx-chap__bar {
  grid-column: 1 / -1;
  margin-top: 7px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--glow), var(--spark));
  transform-origin: left;
  transform: scaleX(var(--w, 0));
  opacity: .42;
  transition: opacity .3s var(--out), transform .5s var(--out);
}
.jx-chap:hover .jx-chap__bar { opacity: 1; }
.jx-subjects { display: flex; gap: 8px; margin: 0 0 20px; padding: 0; list-style: none; }
.jx-tab {
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--panel-line);
  background: transparent;
  color: color-mix(in srgb, var(--ink-x) 60%, transparent);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: all .28s var(--out);
}
.jx-tab:hover { color: var(--ink-x); border-color: var(--hair); }
.jx-tab[aria-selected="true"] { background: var(--glow); border-color: transparent; color: var(--void); }

/* ---- 04 THE ENGINE ------------------------------------------------------ */
.jx-engine .jx-h2 { font-size: clamp(26px, min(3.3vw, 5.4vh), 44px); }
.jx-engine .jx-wrap { display: grid; grid-template-columns: minmax(0, 450px) minmax(0, 1fr); gap: clamp(34px, 4vw, 58px); align-items: center; }
.jx-pipe { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.jx-pipe { margin-top: clamp(20px, 3.4vh, 34px); }
.jx-step {
  position: relative;
  padding: clamp(11px, 1.7vh, 17px) 22px clamp(11px, 1.7vh, 17px) 58px;
  border-radius: 14px;
  transition: opacity .5s var(--out), transform .5s var(--out), background-color .5s var(--out);
}
html.jx-drive .jx-step { opacity: .32; transform: translateY(6px); }
html.jx-drive .jx-step.on { opacity: 1; transform: none; background: var(--panel); }
.jx-step__i {
  position: absolute;
  left: 20px;
  top: clamp(12px, 1.9vh, 18px);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--hair);
  display: grid;
  place-items: center;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  color: color-mix(in srgb, var(--ink-x) 55%, transparent);
  transition: all .45s var(--out);
}
.jx-step.on .jx-step__i { background: var(--glow); border-color: transparent; color: var(--void); }
.jx-step h3 { font-size: 15.5px; font-weight: 700; margin: 0 0 3px; color: var(--ink-x); letter-spacing: -.01em; }
.jx-step p { margin: 0; font-size: 12.75px; line-height: 1.45; color: color-mix(in srgb, var(--ink-x) 64%, transparent); }
/* the connective thread between steps */
.jx-step::after {
  content: "";
  position: absolute;
  left: 30.5px;
  top: clamp(34px, 4.2vh, 42px);
  bottom: -2px;
  width: 1px;
  background: var(--hair);
}
.jx-step:last-child::after { display: none; }

/* One panel, two halves: the method drawn, then the method run on a real
   question. The diagram is the section's picture; the card is its proof. */
.jx-vis {
  border-radius: var(--r-panel);
  background: var(--panel);
  border: 1px solid var(--panel-line);
  box-shadow: var(--lift);
  overflow: hidden;
}
.jx-solve {
  padding: clamp(16px, 2.4vh, 24px) clamp(18px, 2vw, 26px) clamp(16px, 2.4vh, 22px);
  border-top: 1px solid var(--panel-line);
}

/* ---- the reasoning diagram ----
   A question enters, is matched against the archive, resolves to one concept,
   branches into reasoning, and lands on an answer. The five groups light in
   step with the five stages listed beside it, driven by the same scroll
   progress, so the drawing and the list are never out of sync. */
.jx-flow {
  display: block;
  /* scales by WIDTH so it fills the panel. Fitting by height letterboxed it
     into a thin strip and shrank the labels below reading size. */
  width: 100%;
  height: auto;
  max-height: clamp(112px, 19.5vh, 190px);
  padding: clamp(10px, 1.7vh, 18px) clamp(10px, 1.6vw, 18px) 2px;
  color: var(--glow);
  overflow: visible;
}
.jx-flow text {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .11em;
  text-anchor: middle;
  fill: color-mix(in srgb, var(--ink-x) 58%, transparent);
}
.jx-flow .fl-edge,
.jx-flow .fl-hex,
.jx-flow .fl-box,
.jx-flow .fl-tick,
.jx-flow .fl-check {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.jx-flow .fl-box { stroke-width: 1.7; }
.jx-flow .fl-tick { opacity: .62; }
.jx-flow .fl-node { fill: currentColor; stroke: none; }
.jx-flow .fl-node--hot,
.jx-flow .fl-edge--hot { color: var(--spark); }
.jx-flow .fl-check { stroke: var(--spark); stroke-width: 2; }
.jx-flow .fl-box--out { stroke: var(--spark); }

/* Default state is FINISHED: with no driver (gsap CDN down, reduced motion,
   no JS) the diagram is simply a complete diagram. */
.jx-flow .fl-stage { opacity: 1; }
.jx-flow .fl-edge { stroke-dasharray: 1; stroke-dashoffset: 0; }
html.jx-drive .jx-flow .fl-stage {
  opacity: .17;
  transition: opacity .55s var(--out);
}
html.jx-drive .jx-flow .fl-stage.on { opacity: 1; }
html.jx-drive .jx-flow .fl-stage .fl-edge { stroke-dashoffset: 1; }
html.jx-drive .jx-flow .fl-stage.on .fl-edge {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .75s var(--out);
}
.jx-solve__q {
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-x);
  margin: 0 0 clamp(11px, 1.9vh, 18px);
  font-weight: 600;
}
.jx-solve__line {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px;
  align-items: start;
  padding: clamp(6px, 1.15vh, 11px) 0;
  border-top: 1px solid var(--panel-line);
  transition: opacity .55s var(--out);
}
html.jx-drive .jx-solve__line { opacity: .18; }
html.jx-drive .jx-solve__line.on { opacity: 1; }
.jx-solve__tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--spark);
  padding-top: 3px;
  white-space: nowrap;
}
.jx-solve__line p { margin: 0; font-size: 13.5px; line-height: 1.55; color: color-mix(in srgb, var(--ink-x) 74%, transparent); }
.jx-solve__ans {
  margin-top: 16px;
  padding: 14px 18px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--glow) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--glow) 34%, transparent);
  display: flex;
  align-items: baseline;
  gap: 14px;
  transition: opacity .6s var(--out);
}
html.jx-drive .jx-solve__ans { opacity: .18; }
html.jx-drive .jx-solve__ans.on { opacity: 1; }
.jx-solve__ans span {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink-x) 58%, transparent);
}
.jx-solve__ans strong {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 19px;
  color: var(--glow);
}

/* ---- 05 THE PREDICTION -------------------------------------------------- */
.jx-predict .jx-wrap { max-width: 1120px; text-align: center; display: grid; justify-items: center; }
.jx-predict .jx-h2 { font-size: clamp(26px, min(3.6vw, 6vh), 48px); }
.jx-predict .jx-lead { margin-inline: auto; text-align: center; }
.jx-figure {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600;
  font-size: clamp(64px, min(11vw, 18.5vh), 158px);
  line-height: .84;
  letter-spacing: -.05em;
  color: var(--glow);
  margin: clamp(12px, 2.4vh, 26px) 0 6px;
}
.jx-figure sup { font-size: .28em; font-weight: 500; align-self: flex-start; margin-top: .34em; letter-spacing: 0; }
.jx-split {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  width: 100%;
  max-width: 900px;
  margin: clamp(15px, 2.6vh, 30px) 0 0;
  gap: 1px;
  background: var(--panel-line);
  border-top: 1px solid var(--panel-line);
  border-bottom: 1px solid var(--panel-line);
}
.jx-split > div { background: color-mix(in srgb, var(--void) 60%, transparent); padding: clamp(10px, 1.7vh, 17px) 14px; }
.jx-split dt { font-size: 12.5px; font-weight: 700; color: color-mix(in srgb, var(--ink-x) 58%, transparent); margin: 0 0 6px; }
.jx-split dd {
  margin: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: clamp(22px, 2.6vw, 32px);
  font-weight: 700;
  color: var(--ink-x);
  letter-spacing: -.02em;
}

/* ---- 06 THE PRODUCT ----------------------------------------------------- */
.jx-product { background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--void-2) 88%, transparent) 18%, color-mix(in srgb, var(--void-2) 88%, transparent) 82%, transparent); }
.jx-product .jx-hold { display: block; }
.jx-product .jx-hold::before { display: none; }
.jx-product__head { max-width: 1240px; margin: 0 auto; padding: clamp(80px, 11vh, 96px) 26px clamp(20px, 3.4vh, 32px); }
.jx-rail { display: flex; gap: clamp(18px, 2vw, 30px); padding: 0 26px clamp(48px, 8vh, 84px); width: max-content; align-items: flex-end; }
.jx-shot { flex: none; }
.jx-shot img {
  height: clamp(260px, 44vh, 520px);
  width: auto;
  max-width: 82vw;
  border-radius: 20px;
  border: 1px solid var(--panel-line);
  box-shadow: var(--lift);
  background: #08131f;
}
.jx-shot figcaption {
  margin-top: 12px;
  font-size: 13.5px;
  line-height: 1.5;
  color: color-mix(in srgb, var(--ink-x) 66%, transparent);
  max-width: 30ch;
}
.jx-shot figcaption b { color: var(--ink-x); font-weight: 700; display: block; margin-bottom: 2px; }
/* the closing rail item is copy, not a screen, so it sizes by width */
.jx-shot--card { width: min(400px, 82vw); align-self: center; }

/* ---- 07 TWO WORLDS ------------------------------------------------------ */
.jx-worlds .jx-hold { align-items: stretch; }
.jx-worlds .jx-hold::before { display: none; }
.jx-worlds .jx-wrap { display: flex; flex-direction: column; justify-content: center; padding-block: clamp(78px, 9.4vh, 88px) clamp(34px, 6vh, 64px); }
.jx-worlds__head { text-align: center; max-width: 42ch; margin: 0 auto clamp(20px, 3.6vh, 44px); }
.jx-worlds__head .jx-lead { margin-inline: auto; }
.jx-diptych { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
.jx-world {
  --w-a: #1B3B36;
  --w-b: #FFD700;
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(20px, 3vh, 34px) clamp(20px, 2.4vw, 32px) clamp(18px, 2.8vh, 30px);
  border-radius: var(--r-panel);
  border: 1px solid var(--panel-line);
  background: var(--panel);
  overflow: hidden;
  isolation: isolate;
  transition: transform .5s var(--out), border-color .5s var(--out), box-shadow .5s var(--out);
}
.jx-world::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  background: radial-gradient(70% 70% at var(--mx, 50%) var(--my, 0%), color-mix(in srgb, var(--w-a) 42%, transparent), transparent 68%);
  opacity: .5;
  transition: opacity .5s var(--out);
}
.jx-world:hover { transform: translateY(-6px); border-color: color-mix(in srgb, var(--w-a) 55%, transparent); box-shadow: var(--lift); }
.jx-world:hover::before { opacity: 1; }
.jx-world--neet { --w-a: #14A89D; --w-b: #7FE6DC; }
body.jx.is-dark .jx-world { --w-a: #2E7D5B; }
body.jx.is-dark .jx-world--neet { --w-a: #14A89D; }
.jx-world__tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink-x) 56%, transparent);
}
.jx-world .jx-h3 { margin: 10px 0 8px; }
.jx-world p { margin: 0; font-size: 14.25px; line-height: 1.52; color: color-mix(in srgb, var(--ink-x) 70%, transparent); }
.jx-world__facts { list-style: none; margin: clamp(12px, 2.1vh, 20px) 0 0; padding: 0; display: grid; gap: clamp(6px, 1.1vh, 9px); }
.jx-world__facts li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 11px;
  align-items: baseline;
  font-size: 13.25px;
  color: color-mix(in srgb, var(--ink-x) 74%, transparent);
}
.jx-world__facts b {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--spark);
  min-width: 3.6em;
}
.jx-world__go { margin-top: auto; padding-top: clamp(15px, 2.6vh, 26px); display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }

/* ---- 08 CLOSE ----------------------------------------------------------- */
.jx-close { position: relative; z-index: 2; background: var(--void); }
.jx-close .jx-wrap { max-width: 1000px; padding-block: 96px 40px; }
.jx-proof { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px; margin: 40px 0 0; }
.jx-proof div { border-top: 1px solid var(--hair); padding-top: 16px; }
.jx-proof dt {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 20px;
  font-weight: 700;
  color: var(--ink-x);
  margin: 0 0 6px;
}
.jx-proof dd { margin: 0; font-size: 13.5px; line-height: 1.55; color: color-mix(in srgb, var(--ink-x) 62%, transparent); }

body.jx .faq-item { border-bottom: 1px solid var(--panel-line); }
body.jx .faq-q { color: var(--ink-x); }
body.jx .faq-a { color: color-mix(in srgb, var(--ink-x) 70%, transparent); }

body.jx .footer { position: relative; z-index: 2; background: #05100E; }
body.jx.is-dark .footer { background: #030B09; border-top: 1px solid rgba(160, 220, 200, .1); }

/* ==========================================================================
   7  FALLBACKS
   ========================================================================== */

/* no JS: every scene collapses to a normal, fully readable document */
html.no-js .jx-hold { position: static; min-height: 0; }
html.no-js .jx-scene { height: auto !important; }
html.no-js .jx-rail { flex-wrap: wrap; width: auto; }

/* reduced motion: no travel, no scrub, no parallax. Content is all present
   and the field holds one still frame. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .jx-scene { height: auto !important; }
  .jx-hold { position: static; min-height: 0; }
  .jx-hold::before { background: none; }
  .jx-wrap { padding-block: 72px; }
  .jx-step { background: none; }
  .jx-rail { flex-wrap: wrap; width: auto; padding-bottom: 40px; }
  .jx-understudy i { animation: none; }
  .jx-grain { display: none; }
  .jx-chap__bar { transition: none; opacity: 1; }
  .jx-progress { display: none; }
  .jx-btn, .jx-world, .jx-chap { transition: none; }
}

/* ==========================================================================
   8  RESPONSIVE
   Below 900px the page stops travelling and starts reading: sticky holds
   release, grids go single-column, the field drops to its light tier.
   ========================================================================== */

@media (max-width: 1080px) {
  .jx-archive .jx-wrap,
  .jx-pattern .jx-wrap,
  .jx-engine .jx-wrap { gap: 42px; }
}

@media (max-width: 900px) {
  .jx-scene { height: auto !important; }
  .jx-hold { position: static; min-height: 0; display: block; }
  .jx-hold::before {
    background: linear-gradient(180deg, color-mix(in srgb, var(--void) 55%, transparent), color-mix(in srgb, var(--void) 88%, transparent));
  }
  .jx-wrap { padding: 76px 20px; }

  .jx-hero .jx-hold { min-height: 100svh; display: flex; align-items: center; }
  .jx-hero .jx-wrap { padding-top: 104px; }
  .jx-hero__inner { max-width: 100%; }

  .jx-archive .jx-wrap,
  .jx-pattern .jx-wrap,
  .jx-engine .jx-wrap { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  .jx-pattern .jx-wrap > :first-child { order: -1; }

  .jx-diptych { grid-template-columns: minmax(0, 1fr); }
  .jx-proof { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .jx-split { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .jx-product .jx-hold { display: block; }
  .jx-product__head { padding: 76px 20px 24px; }
  .jx-rail {
    width: auto;
    padding: 0 20px 76px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .jx-rail::-webkit-scrollbar { display: none; }
  .jx-shot { scroll-snap-align: center; }
  .jx-shot img { height: min(56vh, 440px); }
  .jx-shot--card { width: min(300px, 82vw); }

  .jx-step { padding: 15px 16px 15px 52px; }
  .jx-step__i { left: 16px; top: 17px; }
  .jx-step::after { left: 26.5px; }

  .jx-grain { opacity: .03; }
}

@media (max-width: 520px) {
  .jx-readout { grid-template-columns: minmax(0, 1fr); }
  .jx-split { grid-template-columns: minmax(0, 1fr); }
  .jx-actions .jx-btn { flex: 1 1 100%; }
  .jx-figure { font-size: clamp(80px, 30vw, 140px); }
}
