@import url('../fonts/fonts.css');

/* ==========================================================================
   NextGen Scientific - Reg A+ landing page

   Visual identity follows the client's existing brand, recovered from their
   previous site: near-black surfaces, a classical serif for display, and the
   olive/violet pairing from their theme stylesheet.

   Placeholder markers for unfinished items are hidden by default so the page
   previews clean. Append ?dev=1 to the URL to reveal them.
   ========================================================================== */

:root {
  /* Brand palette, taken from the brand's own values rather than sampled.
     Green leads, violet is the accent.

     The -lift variants are pale and are for dark backgrounds only. Both fail
     contrast on white, so do not use them for text on light surfaces. */
  --violet: #58469c;
  --violet-lift: #af9beb;
  --violet-deep: #453873;
  /* Clears WCAG AA on light backgrounds, which a lighter tint did not. */
  --olive: #616c33;
  --olive-lift: #b9ca73;
  --olive-deep: #4e5823;

  /* Diagram only, not a brand colour. Used for the "gene still switched on"
     circles in the mechanism figure, which should not read as a good outcome. */
  --maroon: #7b2430;

  /* surfaces */
  --black: #08090a;
  --near-black: #101215;
  --char: #1a1d21;
  --paper: #ffffff;
  --paper-alt: #f6f6f4;
  --paper-warm: #f2f1ec;

  /* ink */
  --ink: #14161a;
  --ink-soft: #4c5460;
  --ink-faint: #5e6672;   /* darkened to clear AA at small sizes */
  --on-dark: #f4f3ef;
  --on-dark-soft: #b3b8b4;
  --line: #e4e4df;
  --line-dark: rgba(255, 255, 255, .13);

  --wrap: 1180px;
  --measure: 64ch;
  --radius: 4px;
  --radius-lg: 10px;

  /* Display face for headings and figures. Named --display rather than --serif
     because it no longer is one: the client picked Archivo, a grotesque. */
  --display: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* Capped so the 18-word headline still leaves the hero CTAs above the fold
     on a ~900px-tall laptop viewport. */
  --step-hero: clamp(2.35rem, 1.45rem + 2.7vw, 3.85rem);
  --step-h2: clamp(2rem, 1.4rem + 2.1vw, 3.15rem);
  --step-h3: clamp(1.18rem, 1.05rem + .5vw, 1.42rem);
  --step-body: clamp(1rem, .96rem + .18vw, 1.09rem);

  --ease: cubic-bezier(.22, .61, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 5.5rem; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--step-body)/1.68 var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img, svg, video, iframe { max-width: 100%; display: block; }
img { height: auto; }

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -.02em;
  margin: 0 0 .55em;
  text-wrap: balance;
}
h1 { font-size: var(--step-hero); }
h2 { font-size: var(--step-h2); }
h3 { font-size: var(--step-h3); letter-spacing: -.01em; }
h4 { font-family: var(--sans); font-size: 1rem; margin: 0 0 .5em; }

p { margin: 0 0 1.15em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }
/* Emphasis in body copy steps the colour up from --ink-soft to full --ink as
   well as the weight: on a page this text-heavy, weight alone is easy to miss,
   and a darker tone raises contrast rather than lowering it. Scoped to running
   text so the uses inside the donut, the legend and the participation cards
   keep their own type treatment. */
strong { font-weight: 650; }
p > strong, li > strong { font-weight: 680; color: var(--ink); }
.section--dark p > strong, .section--black p > strong,
.hero p > strong,
.section--dark li > strong, .section--black li > strong { color: var(--on-dark); }
.caveat > strong { color: inherit; }

a { color: var(--violet); text-underline-offset: .18em; }
:focus-visible { outline: 3px solid var(--violet); outline-offset: 3px; border-radius: 3px; }
/* The solid violet disappears against the near-black sections, so the pale
   variant takes over there. Both directions clear 3:1 against their own
   background, which is what WCAG 2.2 requires of a focus indicator. */
.section--dark :focus-visible,
.section--black :focus-visible,
.hero :focus-visible,
.nav :focus-visible,
.notfound :focus-visible { outline-color: var(--violet-lift); }

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }

/* Same outer box as .wrap, deliberately.

   This used to be a narrower container centred in the viewport, which meant the
   five sections using it began about 160px further right than every other
   section on the page. Zoom out and the left edge of the page visibly stepped
   in and out; the mechanism section did it twice, because its intro was narrow
   and its figure was not.

   The narrow measure was only ever about line length, so it belongs on the
   content, not on the container. Every section now shares one left edge, and
   the text inside these keeps its shorter measure. Paragraphs are capped
   tighter still by the global `p` rule. */
.wrap--narrow { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.wrap--narrow > * { max-width: 860px; }

.section { padding: clamp(3.75rem, 2rem + 6vw, 7.5rem) 0; position: relative; }
.section--paper { background: var(--paper); }
.section--alt { background: var(--paper-alt); }
.section--warm { background: var(--paper-warm); }
.section--dark { background: var(--near-black); color: var(--on-dark); }
.section--black { background: var(--black); color: var(--on-dark); }
.section--dark h2, .section--dark h3, .section--black h2, .section--black h3 { color: #fff; }
.section--dark p, .section--black p { color: var(--on-dark-soft); }
.section--dark a, .section--black a { color: #b9a9f0; }

/* section label ---------------------------------------------------------- */
.eyebrow {
  font-family: var(--sans);
  font-size: .74rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: var(--olive); margin: 0 0 1.1rem; display: flex; align-items: center; gap: .7rem;
}
.eyebrow::before {
  content: ""; width: 1.9rem; height: 1px; background: currentColor; opacity: .6; flex: none;
}
.section--dark .eyebrow, .section--black .eyebrow { color: var(--olive-lift); }
/* Alternate the label colour so the page is not uniformly olive. */
.eyebrow--violet { color: var(--violet); }
/* For an eyebrow used as a standalone label above a block, rather than sitting
   directly under a heading. */
.eyebrow--spaced { margin-top: 3.5rem; }
.section--dark .eyebrow--violet, .section--black .eyebrow--violet { color: #b9a9f0; }

.lede { font-size: 1.15em; line-height: 1.6; color: var(--ink-soft); }
.section--dark .lede, .section--black .lede { color: #d3d6d2; }

/* ---------- accessibility helpers --------------------------------------- */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--violet); color: #fff; padding: .8rem 1.2rem;
}
.skip-link:focus { left: 0; }

/* ---------- buttons ------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  font-family: var(--sans); font-size: .95rem; font-weight: 600; line-height: 1;
  padding: 1rem 1.75rem; border: 1px solid transparent; border-radius: var(--radius);
  text-decoration: none; cursor: pointer; text-align: center;
  transition: background-color .22s var(--ease), color .22s var(--ease),
              border-color .22s var(--ease), transform .22s var(--ease);
}
/* Long CTA labels such as "Invest Today (Accredited Investors)" must be allowed
   to wrap. Keeping nowrap here forced the whole page wider than a 360px screen.
   Only the short nav labels stay on one line. */
.nav .btn { white-space: nowrap; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

/* Green leads on primary actions. Violet is kept deliberately as the accent: on
   section labels, links, the mechanism section and the second arc of the
   proceeds chart, so the page does not read as uniformly green the way it
   did. Hover goes darker rather than to --olive-lift, because that light
   variant cannot carry white text. */
.btn--primary { background: var(--olive); color: #fff; }
.btn--primary:hover { background: var(--olive-deep); }
.btn--violet { background: var(--violet); color: #fff; }
.btn--violet:hover { background: var(--violet-deep); }
.btn--olive { background: var(--olive); color: #fff; }
.btn--olive:hover { background: var(--olive-deep); }
.btn--outline { background: transparent; color: var(--violet); border-color: rgba(88,70,156,.45); }
.btn--outline:hover { background: var(--violet); color: #fff; border-color: var(--violet); }
.btn--onDark { background: transparent; color: #fff; border-color: rgba(255,255,255,.4); }
.btn--onDark:hover { background: #fff; color: var(--black); border-color: #fff; }
.btn--sm { padding: .68rem 1.15rem; font-size: .86rem; }

.cta-group { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 2rem; }
.cta-note {
  margin-top: 1.2rem; max-width: 56ch;
  font-size: .875rem; line-height: 1.6; color: var(--ink-faint);
}
.section--dark .cta-note, .section--black .cta-note, .hero .cta-note { color: #9aa09b; }

/* ---------- announcement bar + nav --------------------------------------- */
.announce {
  /* max-width:none overrides the global `p` measure, which was clipping the
     bar to reading width instead of letting it span the viewport. */
  max-width: none; margin: 0;
  background: var(--olive-deep); color: #f0f2e6;
  font-size: .74rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  text-align: center; padding: .65rem 1.25rem; line-height: 1.5;
}

.nav {
  position: sticky; top: 0; z-index: 100;
  background: rgba(8, 9, 10, .82);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--line-dark);
  transition: background-color .3s var(--ease);
}
.nav__inner { display: flex; align-items: center; gap: 1.25rem; min-height: 72px; }
.nav__logo { flex: none; margin-right: auto; display: flex; align-items: center; }
.nav__logo img { height: 38px; width: auto; }

.nav__links { display: none; gap: 1.9rem; align-items: center; }
@media (min-width: 62rem) { .nav__links { display: flex; } }
.nav__link {
  position: relative; color: rgba(255,255,255,.76); text-decoration: none;
  font-size: .875rem; font-weight: 500; letter-spacing: .01em; padding: .4rem 0;
  transition: color .2s var(--ease);
}
.nav__link:hover { color: #fff; }
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.1rem; height: 2px;
  background: var(--olive-lift); transform: scaleX(0); transform-origin: left;
  transition: transform .28s var(--ease);
}
.nav__link:hover::after, .nav__link[aria-current="true"]::after { transform: scaleX(1); }
.nav__link[aria-current="true"] { color: #fff; }

/* Visible at every width, at the client's request. It used to be hidden below
   48rem, which left phone visitors with no Invest control in the bar at all:
   the only one was inside the collapsed menu, behind the toggle. */
.nav__cta { display: flex; gap: .55rem; flex: none; }

/* Investor Login leaves the bar wherever the menu toggle exists, and the copy
   in the drawer takes over. The client asked for the bar to carry one action on
   a phone, and Invest is the one that belongs there: login is for people who
   have already invested. Matching the toggle's own breakpoint means there is no
   width where the button is in both places or in neither. */
@media (max-width: 61.99rem) {
  .nav__login { display: none; }
}
/* Drawer copy, hidden above that width with the rest of the drawer. Full label
   here: the drawer is a column, so there is room the bar did not have. */
@media (min-width: 62rem) {
  .nav__drawerLogin { display: none; }
}
.nav__drawerLogin { justify-self: start; border-bottom: 0; }

/* Below 32rem the bar is carrying a logo, two buttons and the menu toggle. The
   full "Investor Login" label will not fit alongside them, so the first word is
   dropped and the button reads "Login". Everything tightens a little with it.
   Scoped to the bar: the drawer copy has room for the whole label. */
/* The label is wrapped in a single span so it is one flex item inside .btn.
   Left as a bare text node beside the inner span, "Investor" and "Login" became
   two flex items and picked up the button's .55rem gap on top of the word space,
   which read as "Investor  Login". */
@media (max-width: 32rem) {
  .nav__cta .nav__loginWord { display: none; }
  .nav__inner { gap: .6rem; }
  .nav__logo img { height: 30px; }
  .nav__cta { gap: .45rem; }
  .nav__cta .btn { padding-inline: .8rem; font-size: .82rem; }
}

/* A second step for the smallest screens, where even that does not fit. */
@media (max-width: 24rem) {
  .nav__inner { gap: .4rem; }
  .nav__logo img { height: 26px; }
  .nav__cta { gap: .35rem; }
  .nav__cta .btn { padding-inline: .55rem; font-size: .76rem; }
}

/* mobile menu ------------------------------------------------------------- */
.nav__toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none;
  background: transparent; border: 1px solid var(--line-dark); border-radius: var(--radius);
  color: #fff; cursor: pointer;
}
@media (min-width: 62rem) { .nav__toggle { display: none; } }
.nav__toggle span, .nav__toggle span::before, .nav__toggle span::after {
  content: ""; display: block; width: 18px; height: 2px; background: currentColor;
  transition: transform .25s var(--ease), opacity .2s var(--ease);
}
.nav__toggle span::before { transform: translateY(-6px); }
.nav__toggle span::after { transform: translateY(4px); }
.nav[data-open="true"] .nav__toggle span { background: transparent; }
.nav[data-open="true"] .nav__toggle span::before { transform: rotate(45deg); }
.nav[data-open="true"] .nav__toggle span::after { transform: translateY(-2px) rotate(-45deg); }

.nav__drawer {
  display: grid; gap: .25rem; overflow: hidden;
  max-height: 0; transition: max-height .34s var(--ease);
  border-top: 0 solid var(--line-dark);
}
.nav[data-open="true"] .nav__drawer { max-height: 30rem; border-top-width: 1px; }
@media (min-width: 62rem) { .nav__drawer { display: none; } }
.nav__drawer a {
  color: rgba(255,255,255,.85); text-decoration: none; padding: .85rem .2rem;
  font-size: .95rem; border-bottom: 1px solid rgba(255,255,255,.07);
}
.nav__drawer .btn { margin: .9rem 0; }

/* ---------- hero ---------------------------------------------------------- */
.hero {
  /* No bottom padding on the section itself. The photograph is meant to sit on
     the bottom edge, and the copy column carries its own breathing room
     instead. An earlier version kept the padding and pulled the art down with
     a negative margin, which overshot by 22px at 320 and 360 and clipped the
     fingertips: the exact "cut off" look this was meant to fix. */
  --hero-pad-b: clamp(3rem, 2rem + 4vw, 5.5rem);
  position: relative; background: var(--black); color: var(--on-dark);
  padding: clamp(3.5rem, 2rem + 7vw, 7rem) 0 0;
  overflow: hidden;
}
.hero::after {
  /* soft violet bloom behind the plant, keeps the black from going flat */
  content: ""; position: absolute; inset: auto -10% -30% 45%; height: 90%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(88,70,156,.34), transparent 70%);
  pointer-events: none;
}
.hero__grid { position: relative; z-index: 1; display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 60rem) { .hero__grid { grid-template-columns: 1.12fr .88fr; gap: 3.5rem; } }

.hero h1 { color: #fff; margin-bottom: .5em; }
/* The client asked for the two headline sentences to sit on separate lines.
   A block span rather than a <br>, so the break survives text-wrap: balance
   and each sentence still wraps normally at narrow widths.

   The second sentence is set smaller and lighter. That is partly typographic,
   giving the pair a clear first and second line, and partly practical: at full
   hero size two stacked sentences ran the headline past 600px tall and pushed
   the CTAs off a 900px laptop screen. */
.hero h1 .h1__line {
  display: block;
  margin-top: .3em;
  font-size: .62em;
  font-weight: 400;
  line-height: 1.15;
}
/* The hero sits on black but is not a .section--dark, so it needs the light
   text colours applied explicitly. Without this the lede inherited the
   light-background grey and dropped to 2.6:1. */
.hero .lede { color: #d2d6d1; }
.hero__points { list-style: none; margin: 0 0 .5rem; padding: 0; display: grid; gap: .85rem; }
.hero__points li {
  position: relative; padding-left: 1.8rem; color: #cdd2ce; font-size: 1rem; line-height: 1.5;
}
.hero__points li::before {
  content: ""; position: absolute; left: 0; top: .48em;
  width: .62rem; height: .62rem; border-radius: 50%;
  background: var(--olive-lift); box-shadow: 0 0 0 3px rgba(185,202,115,.25);
}

/* The photograph is cropped at the wrist, so any gap under it reads as the
   hand being cut off in mid-air. Sitting it on the section's bottom edge makes
   the crop read as the image running off the page instead.

   align-self:end puts it at the foot of its grid row, and the row ends where
   the section does because .hero carries no bottom padding. Nothing is pulled
   or clipped, so the two edges line up at every width. */
.hero__art { position: relative; justify-self: center; align-self: end; }

/* The bottom padding the section gives up, so the copy still has room beneath
   it when it is the taller of the two columns. On a phone the grid gap already
   separates copy from art, and the art must reach the bottom edge, so this
   only applies once the two sit side by side. */
@media (min-width: 60rem) { .hero__copy { padding-bottom: var(--hero-pad-b); } }
.hero__art img {
  display: block;
  width: auto; max-width: 100%;
  /* Height-capped rather than width-capped: the source is tall and portrait,
     and on a phone a width-based cap pushed the next section far down. */
  max-height: min(46vh, 26rem);
  filter: drop-shadow(0 30px 60px rgba(0,0,0,.6));
}
@media (min-width: 60rem) { .hero__art img { max-height: 34rem; } }

/* ---------- video --------------------------------------------------------- */
.video-frame {
  position: relative; aspect-ratio: 16/9; border-radius: var(--radius-lg);
  overflow: hidden; background: #0d0f11; border: 1px solid var(--line-dark);
}
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* Standing alone rather than in a two-column split, so it is capped and centred
   instead of running the full width of the wrap. */
.video-frame--solo { max-width: 56rem; margin-inline: auto; }

/* ---------- key figures --------------------------------------------------- */
.figures { display: grid; gap: 1px; background: var(--line-dark); border: 1px solid var(--line-dark); }
.figures--light { background: var(--line); border-color: var(--line); }
@media (min-width: 34rem) { .figures { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 60rem) { .figures { grid-template-columns: repeat(3, 1fr); } }
.figure { background: var(--near-black); padding: 2rem 1.6rem; }
.figures--light .figure { background: var(--paper); }
.figure__value {
  font-family: var(--display); font-size: clamp(1.9rem, 1.4rem + 1.7vw, 2.7rem);
  font-weight: 600; line-height: 1; letter-spacing: -.02em;
  /* tabular figures stop the number jittering while it counts up */
  font-variant-numeric: tabular-nums;
  color: #c7b8f5;
}
.figure__value--word { color: #fff; }
.figures--light .figure__value { color: var(--violet); }
/* subtle violet wash so the stat band is not flat black */
.figure { background: linear-gradient(155deg, #14141d 0%, var(--near-black) 62%); }
.figures--light .figure { background: var(--paper); }
.figure__label {
  margin: .6rem 0 0; font-size: .875rem; color: var(--on-dark-soft); letter-spacing: .01em;
}
.figures--light .figure__label { color: var(--ink-soft); }

/* ---------- cards --------------------------------------------------------- */
.cards { display: grid; gap: 1.5rem; grid-template-columns: 1fr; }
@media (min-width: 48rem) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .cards--3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 2rem 1.85rem; position: relative;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
}
.card:hover {
  transform: translateY(-4px);
  border-color: rgba(88,70,156,.3);
  box-shadow: 0 18px 40px -18px rgba(20,22,26,.28);
}
.card h3 { margin-bottom: .75rem; }
.card ul { margin: 0; padding-left: 1.15rem; }
.card li { margin-bottom: .5rem; color: var(--ink-soft); }
.card li:last-child { margin-bottom: 0; }
.card--onDark { background: var(--char); border-color: var(--line-dark); }
.card--onDark li, .card--onDark p { color: var(--on-dark-soft); }

/* ---------- two divisions ------------------------------------------------- */
.split { display: grid; gap: 1.5rem; }
@media (min-width: 52rem) { .split { grid-template-columns: 1fr 1fr; } }
.division { border-radius: var(--radius-lg); padding: 2.1rem 1.9rem; border: 1px solid; }
.division--onc { background: rgba(88,70,156,.055); border-color: rgba(88,70,156,.2); }
.division--con { background: rgba(109,122,58,.06); border-color: rgba(109,122,58,.22); }
.division__kicker {
  font-size: .72rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-faint); margin-bottom: .9rem;
}
.division h3 { margin-bottom: 1rem; }
.division ul { margin: 0; padding-left: 1.15rem; }
.division li { margin-bottom: .55rem; color: var(--ink-soft); }

/* ==========================================================================
   Serpentine progress flow

   Eight milestones alternating left and right down the page, joined by an
   S-curved spine that draws itself as the section scrolls into view. Compact by
   design: each milestone is only a year, a title and one line, so the old
   full-viewport-per-step treatment was far too much room for the content.

   Degrades safely: without JS the spine is simply drawn in full and every
   milestone is visible. Nothing here needs script to be readable.
   ========================================================================== */
.flow { position: relative; margin-top: 3.25rem; }

/* Starts hidden: the script rebuilds the path from the real icon positions and
   then reveals it. Without JS there is no spine, and the milestones simply read
   as a two-column list, which is fine. */
.flow__spine {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; overflow: visible; opacity: 0;
  transition: opacity .3s var(--ease);
}
html:not(.js) .flow__spine { display: none; }
.flow__spine path { fill: none; stroke-width: 2; stroke-linecap: round; }
.flow__base { stroke: rgba(20, 22, 26, .13); }
.flow__draw { stroke: var(--olive); }

/* One milestone per row, alternating sides. A two-column grid was packing two
   per row, which put the spine straight through the text. Each row is full
   width and the node is 44% of it, so node centres land on 22% and 78% -- the
   exact x coordinates the spine snakes between. */
.flow__list {
  list-style: none; margin: 0; padding: 0; position: relative; z-index: 1;
  display: grid; grid-template-columns: 1fr;
}
.flow__item { min-height: 8.5rem; }
.flow__node { width: 44%; text-align: center; }
.flow__item:nth-child(odd) .flow__node { margin-right: auto; }
.flow__item:nth-child(even) .flow__node { margin-left: auto; }

.flow__icon {
  width: 3.25rem; height: 3.25rem; border-radius: 50%; margin: 0 auto .8rem;
  display: grid; place-items: center;
  background: var(--paper); border: 2px solid rgba(20, 22, 26, .14);
  color: var(--ink-faint);
  transition: border-color .45s var(--ease), color .45s var(--ease),
              background-color .45s var(--ease), transform .45s var(--ease);
}
.flow__icon svg {
  width: 1.5rem; height: 1.5rem; fill: none;
  stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.flow__year {
  display: block; font-size: .74rem; font-weight: 650;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint);
  transition: color .45s var(--ease);
}
.flow__title {
  font-size: 1.12rem; margin: .3rem 0 .25rem;
  transition: color .45s var(--ease);
}
.flow__body { font-size: .9rem; color: var(--ink-soft); margin: 0 auto; max-width: 24ch; }

/* reached state */
.flow__item.is-on .flow__icon {
  background: var(--olive); border-color: var(--olive); color: #fff;
}
.flow__item.is-on .flow__year { color: var(--olive); }

/* enter animation */
.js .flow__item { opacity: 0; transform: translateY(16px); }
.js .flow__item.is-in {
  opacity: 1; transform: none;
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}

/* ---- phones: single column, spine becomes a straight rail on the left ---- */
@media (max-width: 47.99rem) {
  .flow__spine { display: none; }
  .flow__list { padding-left: 3.6rem; }
  .flow__item { min-height: 0; padding-bottom: 2rem; position: relative; }
  .flow__node { width: 100%; text-align: left; margin: 0 !important; }
  .flow__icon { margin: 0 0 .6rem; width: 2.75rem; height: 2.75rem; }
  .flow__body { margin: 0; max-width: none; }
  /* the rail, drawn per item so it stretches with the content */
  .flow__item::before {
    content: ""; position: absolute; left: -2.2rem; top: 2.75rem; bottom: -.35rem;
    width: 2px; background: rgba(20, 22, 26, .13);
  }
  .flow__item:last-child::before { display: none; }
  .flow__item.is-on::before { background: var(--olive); }
}

@media (prefers-reduced-motion: reduce) {
  .js .flow__item { opacity: 1; transform: none; }
  .flow__draw { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; }
}/* ---------- timeline (legacy static, kept for reference) ------------------ */
.timeline { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
@media (min-width: 60rem) { .timeline { grid-template-columns: repeat(4, 1fr); } }
.timeline__item { position: relative; padding: 0 0 2rem 2rem; }
@media (min-width: 60rem) { .timeline__item { padding: 3.4rem 1.25rem 0 0; } }
.timeline__item::before {
  content: ""; position: absolute; left: .3rem; top: .35rem; z-index: 1;
  width: 12px; height: 12px; border-radius: 50%; background: var(--olive);
  box-shadow: 0 0 0 4px rgba(109,122,58,.18);
}
@media (min-width: 60rem) { .timeline__item::before { left: 0; top: 1.9rem; } }
.timeline__item::after {
  content: ""; position: absolute; left: .8rem; top: 1.3rem; bottom: 0; width: 2px; background: var(--line);
}
@media (min-width: 60rem) {
  .timeline__item::after { left: 0; top: 2.42rem; bottom: auto; width: 100%; height: 2px; }
}
.timeline__item:last-child::after { display: none; }
.timeline__year { font-size: .8rem; font-weight: 650; letter-spacing: .08em; text-transform: uppercase; color: var(--violet); }
.timeline__title { font-family: var(--display); font-size: 1.12rem; font-weight: 600; margin: .35rem 0 .3rem; }
.timeline__body { font-size: .9rem; color: var(--ink-soft); margin: 0; }

/* ---------- paths list ---------------------------------------------------- */
.paths { list-style: none; margin: 0; padding: 0; counter-reset: p; display: grid; gap: 1rem; }
@media (min-width: 60rem) { .paths { grid-template-columns: repeat(3, 1fr); } }
.paths li {
  counter-increment: p; position: relative; padding: 1.9rem 1.6rem 1.6rem;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
  /* Same lift as .card. These sit directly below the three example cards in
     the value-creation section and are read as the same kind of object, so
     one row responding to the pointer and the other staying inert looked
     like a fault. Client asked for the two to be reconciled, 2026-08-13. */
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
}
.paths li:hover {
  transform: translateY(-4px);
  border-color: rgba(88,70,156,.3);
  box-shadow: 0 18px 40px -18px rgba(20,22,26,.28);
}
.paths li::before {
  content: counter(p, decimal-leading-zero);
  font-family: var(--display); font-size: .95rem; font-weight: 700; color: var(--olive);
  display: block; margin-bottom: .7rem; letter-spacing: .05em;
}
.paths strong { display: block; margin-bottom: .3rem; font-family: var(--display); font-size: 1.1rem; font-weight: 600; }
.paths span { font-size: .93rem; color: var(--ink-soft); }

/* ---------- comparison table ---------------------------------------------- */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--paper); }
table { border-collapse: collapse; width: 100%; min-width: 33rem; }
caption { text-align: left; padding: 1.15rem 1.5rem; font-size: .88rem; color: var(--ink-faint); }
th, td { padding: 1.05rem 1.5rem; text-align: left; border-bottom: 1px solid var(--line); }
thead th { font-family: var(--sans); font-size: .8rem; font-weight: 650; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); background: var(--paper-alt); }
tbody tr:last-child > * { border-bottom: 0; }
th[scope="row"] { font-weight: 600; }
.cell--neg { color: var(--ink-faint); }
.cell--pos { color: var(--olive-deep); font-weight: 600; }

/* ---------- use of proceeds ----------------------------------------------- */
.proceeds { display: grid; gap: 2.75rem; align-items: center; }
@media (min-width: 56rem) { .proceeds { grid-template-columns: minmax(0, 17rem) 1fr; } }
/* Segments follow the deck's written copy, not the deck's own chart.
   The two disagree. See REVIEW.md item 1. */
.donut { width: min(100%, 17rem); aspect-ratio: 1; margin-inline: auto; position: relative; }
.donut svg { width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.donut circle { fill: none; stroke-width: 10; }
.donut__ring { stroke: rgba(20, 22, 26, .08); }

/* Each segment sweeps in by growing its dasharray from zero to its true arc
   length. Duration and delay are set per segment in JS, proportional to how
   much of the ring that segment covers, so the four draw strictly one after
   another at a constant speed rather than overlapping. Timing is linear on
   purpose: easing each segment separately makes the line stutter at the joins
   instead of reading as one continuous stroke. */
.donut__seg {
  stroke-dasharray: 0 282.74;
  stroke-dashoffset: 0;
  transition: stroke-dasharray 0s linear;
}

.donut__hole {
  position: absolute; inset: 19%; border-radius: 50%;
  display: grid; place-content: center; text-align: center; gap: .15rem;
}
.donut__hole span { font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); }
.donut__hole strong { font-family: var(--display); font-size: 2rem; font-weight: 600; color: var(--violet); }

@media (prefers-reduced-motion: reduce) {
  .donut__seg { transition: none; }
}

.legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.15rem; }
.legend li { display: grid; grid-template-columns: auto auto 1fr; gap: .9rem; align-items: baseline; }
.legend .swatch { width: .8rem; height: .8rem; border-radius: 2px; align-self: center; }
.legend .pct { font-family: var(--display); font-size: 1.15rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.legend .desc { color: var(--ink-soft); font-size: .93rem; }
.legend .desc strong { display: block; color: var(--ink); font-family: var(--sans); font-size: .97rem; }

/* ---------- team ---------------------------------------------------------- */
.team { display: grid; gap: 2rem; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 58rem) { .team { grid-template-columns: repeat(4, 1fr); } }
.person { text-align: center; }
.person__photo {
  width: min(100%, 11rem); aspect-ratio: 1; margin: 0 auto 1.1rem;
  border-radius: 50%; overflow: hidden; background: var(--paper-warm);
  border: 1px solid var(--line); position: relative;
}
.person__photo img { width: 100%; height: 100%; object-fit: cover; }
.person__name { font-family: var(--display); font-size: 1.08rem; font-weight: 600; }
.person__role { color: var(--olive); font-size: .8rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; margin: .25rem 0 .6rem; }
.person p { font-size: .89rem; color: var(--ink-soft); margin: 0; max-width: none; }

.advisor { display: grid; gap: 1.75rem; align-items: center; justify-items: center; text-align: center; }
@media (min-width: 44rem) { .advisor { grid-template-columns: 11rem 1fr; text-align: left; justify-items: start; } }
.advisor .person__photo { margin-bottom: 0; }

.photo-missing {
  width: 100%; height: 100%; display: grid; place-items: center; text-align: center;
  padding: .8rem; font-size: .7rem; line-height: 1.35; color: var(--ink-faint);
  background: repeating-linear-gradient(45deg, #f0efea, #f0efea 8px, #e8e7e1 8px, #e8e7e1 16px);
}

/* ---------- logo strips ---------------------------------------------------- */
.logos { display: flex; flex-wrap: wrap; gap: 1.5rem 3rem; align-items: center; justify-content: center; }
.logos img { height: 44px; width: auto; }
.partners { text-align: center; color: var(--ink-soft); font-size: .95rem; max-width: 68ch; margin-inline: auto; }

/* ---------- FAQ ------------------------------------------------------------ */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; position: relative;
  padding: 1.45rem 3rem 1.45rem 0;
  font-family: var(--display); font-size: 1.1rem; font-weight: 600; letter-spacing: -.01em;
  transition: color .2s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--violet); }
.faq summary::after {
  content: ""; position: absolute; right: .5rem; top: 50%; width: 13px; height: 13px;
  margin-top: -6px;
  background:
    linear-gradient(currentColor, currentColor) center/100% 2px no-repeat,
    linear-gradient(currentColor, currentColor) center/2px 100% no-repeat;
  color: var(--violet); transition: transform .28s var(--ease);
}
.faq details[open] summary::after { transform: rotate(135deg); }
.faq details > div { padding-bottom: 1.6rem; }
.faq details > div p, .faq details > div li { color: var(--ink-soft); font-size: .97rem; }

/* ---------- legal + sources ------------------------------------------------ */
.legal { background: var(--paper-alt); }
.legal h3 { font-family: var(--sans); font-size: .95rem; font-weight: 650; margin-top: 2rem; }
.legal p, .legal li { font-size: .82rem; line-height: 1.62; color: var(--ink-soft); max-width: 86ch; }
.sources { font-size: .76rem; color: var(--ink-faint); padding-left: 1.3rem; margin-top: 1.5rem; }
@media (min-width: 56rem) { .sources { columns: 2; column-gap: 3rem; } }
.sources li {
  margin-bottom: .7rem; break-inside: avoid;
  /* The client asked for sources to be written out as full URLs rather than
     hyperlinked, 2026-08-13. A URL is one unbreakable token, so without this
     it sets the minimum width of the whole list and pushed the page to 493px
     on a 320px screen. This used to sit on ".sources a", which stopped
     matching anything the moment the links became plain text. */
  overflow-wrap: anywhere;
}

/* Collapsible sources. Present and crawlable, but folded away by default so
   the reference list does not dominate the foot of the page. */
.sources-toggle > summary {
  cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: .8rem;
  font-family: var(--display); font-size: 1.4rem; font-weight: 600; letter-spacing: -.01em;
  color: var(--ink); padding: .4rem 0;
}
.sources-toggle > summary::-webkit-details-marker { display: none; }
.sources-toggle > summary::after {
  content: "＋"; margin-left: auto; font-family: var(--sans); font-size: 1.1rem;
  color: var(--violet); font-weight: 400;
}
.sources-toggle[open] > summary::after { content: "－"; }
.sources-toggle__count {
  font-family: var(--sans); font-size: .8rem; font-weight: 500;
  color: var(--ink-faint); letter-spacing: .02em;
}

/* Footnote markers: present for anyone checking a claim, but quiet enough not
   to interrupt reading. */
sup a {
  font-size: .62em; font-weight: 600; text-decoration: none;
  color: var(--violet); opacity: .62; padding: 0 .06em;
  transition: opacity .18s var(--ease);
}
sup a:hover, sup a:focus-visible { opacity: 1; text-decoration: underline; }
/* .hero is listed explicitly because it is NOT a .section--dark or
   .section--black, it is its own dark block. The client's 2026-08-13 review
   put the first citations in the hero, and without this they inherited the
   light-background violet and measured 2.63:1 there. This is the second time
   that omission has produced a contrast defect; see REVIEW.md. */
.section--dark sup a, .section--black sup a, .hero sup a { color: #b9a9f0; }

.footer { background: var(--black); color: var(--on-dark-soft); padding: 4rem 0 3rem; font-size: .86rem; }
.footer img { height: 36px; margin-bottom: 1.5rem; }
.footer a { color: #c3b6f0; }
.footer p { max-width: 78ch; }

/* ==========================================================================
   Scroll reveal. Progressive enhancement: the initial hidden state is only
   applied when the .js class is present, so with JS disabled or broken the
   content renders normally instead of staying invisible.
   ========================================================================== */
.js [data-reveal] { opacity: 0; transform: translateY(22px); }
.js [data-reveal].is-visible {
  opacity: 1; transform: none;
  transition: opacity .75s var(--ease), transform .75s var(--ease);
}
.js [data-reveal].is-visible[data-reveal-delay="1"] { transition-delay: .09s; }
.js [data-reveal].is-visible[data-reveal-delay="2"] { transition-delay: .18s; }
.js [data-reveal].is-visible[data-reveal-delay="3"] { transition-delay: .27s; }
.js [data-reveal].is-visible[data-reveal-delay="4"] { transition-delay: .36s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
  .btn:hover, .card:hover { transform: none; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Placeholder markers for unfinished items.
   Hidden by default so the page previews clean for the client. Add ?dev=1 to
   the URL (which sets .dev on <html>) to reveal them during build review.
   Every one also carries a data-todo attribute, so `grep -r data-todo` finds
   them all regardless of this styling.
   ========================================================================== */
[data-todo] { position: relative; }

.dev [data-todo]::after {
  content: "TODO: " attr(data-todo);
  position: absolute; top: 0; right: 0; z-index: 5;
  background: #b42318; color: #fff;
  font-family: var(--sans); font-size: .58rem; font-weight: 700; letter-spacing: .05em;
  padding: .16rem .4rem; border-radius: 0 0 0 3px; pointer-events: none; white-space: nowrap;
}
.dev [data-todo] { outline: 1px dashed rgba(180,35,24,.5); outline-offset: 2px; }

.dev-flag {
  display: none;
  background: #7a1710; color: #fff; text-align: center;
  font-size: .78rem; font-weight: 600; padding: .55rem 1rem; letter-spacing: .04em;
}
.dev .dev-flag { display: block; }

/* Waitlist form. Fully built out so the section reads as finished, but it has
   no action and cannot transmit. Replaced wholesale by the HubSpot embed. */
.rform { margin-top: 1.5rem; display: grid; gap: .9rem; }
.rform__row { display: grid; gap: .9rem; }
@media (min-width: 26rem) { .rform__row { grid-template-columns: 1fr 1fr; } }

.rform__field { display: grid; gap: .38rem; }
.rform label, .rform legend {
  font-size: .78rem; font-weight: 600; letter-spacing: .04em; color: var(--ink-soft);
}
.rform input[type="text"], .rform input[type="email"], .rform input[type="tel"] {
  width: 100%; padding: .82rem 1rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: .95rem; background: var(--paper); color: var(--ink);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.rform input::placeholder { color: #9aa1ab; }
.rform input[type="text"]:focus, .rform input[type="email"]:focus, .rform input[type="tel"]:focus {
  outline: none; border-color: var(--violet);
  box-shadow: 0 0 0 3px rgba(88, 70, 156, .16);
}

.rform__fieldset { border: 0; padding: 0; margin: 0; }
.rform__choices { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .1rem; }
.rform__choice {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .58rem .9rem; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper); cursor: pointer; font-size: .9rem; font-weight: 500;
  color: var(--ink); min-height: 44px;
  transition: border-color .18s var(--ease), background-color .18s var(--ease);
}
.rform__choice:hover { border-color: rgba(88, 70, 156, .5); }
.rform__choice:has(input:checked) { border-color: var(--violet); background: rgba(88, 70, 156, .07); }
.rform__choice input { accent-color: var(--violet); width: 1rem; height: 1rem; }

.rform__consent {
  display: flex; gap: .6rem; align-items: flex-start;
  font-size: .82rem; font-weight: 400; line-height: 1.5; color: var(--ink-soft);
  cursor: pointer; margin-top: .2rem;
}
.rform__consent input { accent-color: var(--violet); width: 1.05rem; height: 1.05rem; margin-top: .12rem; flex: none; }

.rform__submit { width: 100%; margin-top: .3rem; }
.rform__note { font-size: .78rem; color: var(--ink-faint); margin: 0; }
/* Amber by default, which covers "you missed a field" and "that did not send".
   Both are states the reader has to act on. */
.rform__status {
  margin: 0; font-size: .84rem; font-weight: 500; color: #8a3b1e;
  background: #fdf2ec; border: 1px solid #f2d6c6; border-radius: var(--radius);
  padding: .7rem .85rem; display: none;
}
.rform__status.is-shown { display: block; }
/* Green only once the submission has actually been accepted. Measured 5.4:1 on
   its own background, so it does not rely on colour alone either: the wording
   says what happened. */
.rform__status[data-state="ok"] {
  color: #2f5d23; background: #eef6ea; border-color: #cfe3c6;
}

.video-stub {
  aspect-ratio: 16/9; border-radius: var(--radius-lg); display: grid; place-items: center;
  text-align: center; padding: 1.75rem; color: #8d968f; font-size: .88rem; line-height: 1.5;
  background: repeating-linear-gradient(45deg, #16191c, #16191c 11px, #1c2024 11px, #1c2024 22px);
  border: 1px solid var(--line-dark);
}
.strip-stub {
  padding: 2rem 1.5rem; text-align: center; color: var(--ink-faint); font-size: .9rem;
  border: 1px dashed var(--line); border-radius: var(--radius-lg); max-width: 60ch; margin-inline: auto;
}
.gap-marker { background: #fdeceb; border-bottom: 2px dotted #b42318; padding: 0 .3rem; }

/* ============================== 404 PAGE ==============================
   Standalone page, so it sets its own background rather than relying on a
   section wrapper. No nav and no footer: there is nothing to navigate to
   from here except the main page. */
.notfound {
  min-height: 100vh;
  min-height: 100svh;
  margin: 0;
  background: var(--black);
  color: var(--on-dark);
  display: grid;
  place-items: center;
  padding: 2rem 1.25rem;
}
.notfound__inner { max-width: 34rem; text-align: center; }
.notfound__logo { display: inline-block; margin-bottom: 3rem; }
.notfound__logo img { width: 180px; height: auto; display: block; }
.notfound__code {
  font-family: var(--display);
  font-size: clamp(3.5rem, 14vw, 5.5rem);
  line-height: 1;
  margin: 0 0 .5rem;
  color: var(--violet-lift);
  letter-spacing: -.02em;
}
.notfound h1 {
  font-size: clamp(1.5rem, 5vw, 2rem);
  margin: 0 0 1rem;
  color: var(--on-dark);
}
.notfound__lede {
  color: var(--on-dark-soft);
  max-width: 42ch;
  margin: 0 auto;
}
.notfound__cta { justify-content: center; margin-top: 2.25rem; }

/* Regulatory caveats that sit inside a section rather than in the disclosures
   block. Visually quieter than body copy but must stay legible: these are
   required qualifications on clinical claims, not fine print to be buried.
   Contrast is checked by contrast.py along with everything else. */
.caveat {
  margin-top: 2rem;
  padding: 1rem 1.15rem;
  border-left: 3px solid var(--olive);
  background: var(--paper-alt);
  color: var(--ink-soft);
  font-size: .9rem;
  line-height: 1.6;
  max-width: 68ch;
  border-radius: 0 var(--radius) var(--radius) 0;
}
.section--dark .caveat, .section--black .caveat {
  background: rgba(255,255,255,.05);
  border-left-color: var(--olive-lift);
  color: var(--on-dark-soft);
}

/* ===================== PRESS STRIP + FOUNDER PORTRAIT ==================== */

/* Wordmarks rather than logo images. See the note in index.html: naming a
   publication that covered the company is a sourced fact; reproducing its logo
   is a licensing question we have no answer to yet. */
.presswall {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1.25rem 2.75rem;
}
.presswall li {
  font-family: var(--display);
  font-size: clamp(1rem, .92rem + .4vw, 1.22rem);
  letter-spacing: -.01em;
  color: var(--ink-soft);
}
/* One continuous loop. The track holds the logo set twice and travels exactly
   half its own width, so the moment it resets the second set is sitting where
   the first one started and the seam cannot be seen. Percentages rather than
   pixels, so it holds at any width without measuring anything.

   The mask fades both ends, which is what stops a logo from appearing to be
   chopped off at the edge of the viewport. */
.presswall {
  /* The box is deliberately taller than a wordmark needs. Several of these are
     stacked marks with an icon above the name, and at wordmark height they
     shrank to nothing beside an 11:1 newspaper masthead. */
  --press-gap: 3.5rem;
  --press-box-w: 150px;
  --press-box-h: 56px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
/* Duration tracks the number of logos, not the clock: the travel distance is
   one full set, so adding logos to the set without extending this would speed
   the strip up. 63s keeps the same perceived pace as 46s did over eight. */
.presswall__track { display: flex; width: max-content; animation: presswall 63s linear infinite; }
.presswall__set {
  display: flex; align-items: center; gap: var(--press-gap);
  list-style: none; margin: 0; padding: 0 calc(var(--press-gap) / 2);
}

/* Each logo gets an identical box and is fitted inside it, rather than being
   sized by height alone. These eight range from 11:1 (a newspaper wordmark) to
   1.2:1 (a square mark); constraining only the height would render the wide
   ones as hairlines and the square ones as giants. A fixed box with
   object-fit: contain gives every publication the same optical weight. */
.presswall__set li {
  flex: 0 0 auto;
  width: var(--press-box-w); height: var(--press-box-h);
  display: flex; align-items: center; justify-content: center;
}
/* Full colour, reproduced exactly as supplied. These are other companies'
   trademarks, so leaving them unaltered is the safer choice as well as the
   client's preference. The identical box above is what keeps eight different
   palettes from looking scattered. */
.presswall__set img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  object-fit: contain;
}
@keyframes presswall { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* Hovering or tabbing near it stops the motion, so a logo can be looked at. */
.presswall:hover .presswall__track,
.presswall:focus-within .presswall__track { animation-play-state: paused; }

@media (max-width: 47.99rem) {
  .presswall { --press-gap: 2.25rem; --press-box-w: 112px; --press-box-h: 42px; }
}

/* Reduced motion: no travel at all. The duplicate set is removed rather than
   left running, and the real one wraps as a centred, static strip. */
@media (prefers-reduced-motion: reduce) {
  .presswall { -webkit-mask-image: none; mask-image: none; }
  .presswall__track { animation: none; width: 100%; }
  .presswall__track .presswall__set + .presswall__set { display: none; }
  .presswall__set { flex-wrap: wrap; justify-content: center; width: 100%; gap: 2rem 3rem; }
}

/* Stands in until the founder video is supplied. */
.founder-portrait { margin: 0; }
.founder-portrait img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  display: block;
}
.founder-portrait figcaption {
  margin-top: .85rem;
  font-size: .84rem;
  color: var(--ink-faint);
  text-align: center;
}
.section--dark .founder-portrait figcaption,
.section--black .founder-portrait figcaption { color: var(--on-dark-soft); }

/* ======================= MECHANISM DIAGRAM + PLATES ====================== */

/* Illustrates the light bulb / breaker box comparison in the deck copy. Inline
   SVG so it inherits the brand tokens and needs no second request. Text inside
   is real <text>, so it stays sharp at any size and is readable by assistive
   tech; the figure carries a single aria-label so the whole thing is announced
   as one description rather than as loose fragments. */
.mechfig { margin: 0; }
.mechfig__svg {
  width: 100%;
  height: auto;
  overflow: visible;
  color: var(--violet);          /* the arrowhead marker inherits this */
}
.mechfig__kicker {
  font-family: var(--sans); font-size: 12px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; fill: var(--olive);
}
.mechfig__kicker--alt { fill: var(--violet); }
.mechfig__title {
  font-family: var(--display); font-size: 25px; font-weight: 600; fill: var(--ink);
}
.mechfig__note {
  font-family: var(--sans); font-size: 13.5px; fill: var(--ink-soft);
}

/* A filled circle here is a gene still driving the tumour, so it should not
   read as a positive, which is why it is not green. Kept as its own token so a
   rebrand can move it in one place. Measured 9.1:1 against this section, well
   past the 3:1 that WCAG 2.2 asks of a graphic carrying meaning.

   The outline on the "switched off" circles was #c8ccc2, which measured 1.5:1
   and was effectively invisible. On/off is the one distinction this diagram
   exists to make, so the outline is now dark enough to see. */
.mechfig__gene circle { stroke-width: 2; }
.mechfig__gene.is-on circle  { fill: var(--maroon); stroke: var(--maroon); }
.mechfig__gene.is-off circle { fill: var(--paper); stroke: #7f857e; }
/* The cross marking the one blocked gene. Was #9aa19a at 2.4:1, under the 3:1
   floor for a graphic that carries meaning. */
.mechfig__gene path { stroke: #656b64; stroke-width: 2.5; stroke-linecap: round; }

.mechfig__hub rect { fill: var(--violet); }
.mechfig__hub text {
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: .02em; fill: #fff;
}
.mechfig__wire path {
  fill: none; stroke: var(--violet); stroke-width: 2; opacity: .55;
}

.mechfig__cap {
  margin-top: 1.5rem;
  font-size: .84rem;
  line-height: 1.6;
  color: var(--ink-faint);
  max-width: 76ch;
}

/* Two panels side by side, stacking on a phone.

   This used to be one 860-wide SVG that scrolled horizontally below 720px.
   That failed the deck's own "design for mobile-first" instruction: a phone
   showed the left panel only, with no scrollbar on iOS and no hint that the
   right panel existed. The right panel is the one that explains the compound,
   so half the diagram was effectively invisible on a phone. Nothing scrolls
   now, and both panels are always in view. */
.mechfig__panels { display: flex; gap: 2.5rem; align-items: flex-start; }
.mechfig__panels > .mechfig__svg { flex: 1 1 0; min-width: 0; height: auto; }
@media (max-width: 720px) {
  .mechfig__panels { flex-direction: column; gap: 2.25rem; }
  /* Stacked, each panel gets the full column, so cap it or the circles become
     comically large on a tablet-width phone.

     flex is reset because "flex: 1 1 0" above shares a row between the two
     panels, and once the direction is column that zero basis applies to their
     height instead. These panels only kept a height at all because a flex
     item's automatic minimum size transfers the aspect ratio, and that
     automatic minimum is switched off by the overflow:hidden below, which
     collapsed the panel to nothing. Sizing from content is what was meant
     here in the first place. */
  .mechfig__panels > .mechfig__svg {
    flex: 0 0 auto;
    width: 100%; max-width: 420px; margin: 0 auto;
  }

  /* Side by side, the left panel has to leave room for the space the right one
     spends on its hub and wires, so the five genes sit at the same height in
     both and the eye can compare them directly. Stacked, nothing needs to line
     up and that reserved room reads as a hole under the heading.

     So lift the lower half and shorten the box by the same amount. 78 user
     units is measured, not guessed: it puts the top of the circles at y=66,
     which is where the other panel's hub starts, giving both panels the same
     gap under their heading. 194 = 272 - 78, and the content ends at y=179,
     so the crop only ever removes empty space. */
  .mechfig__svg--left { aspect-ratio: 360 / 194; overflow: hidden; }
  .mechfig__svg--left .mechfig__lower { transform: translateY(-78px); }
}

/* ---------- inline diagrams ---------------------------------------------
   Three figures the client asked for, to break up the longest text blocks.

   Built from HTML boxes rather than SVG on purpose. Every label here is a
   short phrase lifted from the copy beside it, and in an SVG those labels
   would be baked into a fixed viewBox: they would shrink with the drawing on
   a narrow screen, ignore the reader's own font size, and need a second
   stacked copy for phones. As HTML they reflow, stay selectable and stay
   real text. The mechanism figure remains SVG because it is a drawing, not
   a set of labels. */
.dgm { margin: 2.75rem 0; }
.dgm__cap {
  margin: 1.25rem 0 0;
  font-size: .84rem; line-height: 1.6; color: var(--ink-faint); max-width: 76ch;
}
.dgm p { max-width: none; margin: 0; }

.dgm__tier {
  font-family: var(--sans);
  font-size: .72rem; font-weight: 650; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: .9rem;
}
.dgm__node {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper); padding: 1.15rem 1.25rem;
}
.dgm__nodeT { font-family: var(--display); font-size: 1.02rem; font-weight: 600; color: var(--ink); }
.dgm__nodeD { margin-top: .4rem; font-size: .88rem; line-height: 1.55; color: var(--ink-soft); }

/* --- fan: one compound out to the tumour types named in the copy --------- */
.fan { display: grid; gap: 1.75rem; }
@media (min-width: 52rem) {
  .fan { grid-template-columns: minmax(11rem, 14rem) 1fr; gap: 2.5rem; align-items: center; }
  /* The rule stands in for the connector an SVG would draw. */
  .fan__bands { border-left: 2px solid var(--line); padding-left: 2.5rem; }
}
/* The caption is the figure's third child, so once the figure is a two-column
   grid it would drop into the narrow first column and wrap to three lines. */
.fan > .dgm__cap { grid-column: 1 / -1; }
.fan__core {
  border: 1px solid var(--olive); border-radius: var(--radius-lg);
  background: rgba(109, 122, 58, .06);
  padding: 1.35rem 1.25rem; text-align: center; align-self: center;
}
.fan__coreSub {
  font-family: var(--sans);
  font-size: .7rem; font-weight: 650; letter-spacing: .13em; text-transform: uppercase;
  color: var(--olive-deep);
}
/* Two classes, so this beats the `.dgm p` margin reset on specificity rather
   than needing !important. */
.dgm .fan__coreName {
  font-family: var(--display); font-size: 1.35rem; font-weight: 600;
  color: var(--ink); margin-top: .3rem;
}
.fan__bands { display: grid; gap: 1.75rem; }
.fan__chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .6rem; }
.fan__chips li {
  border: 1px solid var(--line); border-radius: 100px;
  background: var(--paper); padding: .5rem 1rem;
  font-size: .92rem; color: var(--ink);
}
.fan__band--peer .fan__chips li { border-color: rgba(88, 70, 156, .35); }

/* ---------- link to the offering document --------------------------------
   Sits directly under a primary CTA, on the dark hero and again on white in
   How to invest, so both grounds are set explicitly.

   Note the first selector. `.hero` is its own dark block and is NOT
   `.section--dark` or `.section--black`, so none of the pale-on-dark rules
   further up reach it. That omission has already caused two contrast defects
   on this page, the sub-headline and the hero citations, so every colour here
   names .hero by hand rather than assuming it inherits. */
.doclink { margin-top: 1.1rem; font-size: .95rem; color: var(--ink-soft); }
.hero .doclink,
.section--dark .doclink,
.section--black .doclink { color: #9aa09b; }
/* Padding, not just line-height: this is a text link under a 44px button and
   needs to stay comfortably tappable at phone width. */
.doclink a { font-weight: 600; display: inline-block; padding: .3rem 0; }
.hero .doclink a,
.section--dark .doclink a,
.section--black .doclink a { color: #b9a9f0; }
/* nowrap so the size never breaks away from the format onto its own line */
.doclink__meta { font-size: .85em; white-space: nowrap; }

/* --- org: the corporate structure ---------------------------------------
   Boxes and CSS rules rather than the flat PNG the client supplied, so the
   labels stay real text: they reflow on a phone, follow the reader's own font
   size and can be selected and read aloud. Same reasoning as the other .dgm
   figures.

   --org-drop is the clear space a connector spans. It is used for the gap
   itself and for the height of the rule drawn down the middle of it, so the
   two can never drift apart. */
.org {
  --org-gap: 1rem;
  --org-drop: 2.2rem;
  --org-rule: 2px;
  display: grid; justify-items: center;
}
.org__box {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper); padding: 1.15rem 1.3rem; text-align: center;
  width: 100%; max-width: 26rem; margin-inline: auto;
}
/* Two classes so these beat the `.dgm p` reset on specificity, the same way
   .fan__coreName does, rather than needing !important. */
.dgm .org__name {
  font-family: var(--display); font-size: 1.05rem; font-weight: 600;
  line-height: 1.35; color: var(--ink);
}
.dgm .org__own {
  margin-top: .5rem;
  font-family: var(--display); font-size: .95rem; font-weight: 600;
  color: var(--violet);
}
.dgm .org__role { margin-top: .35rem; font-size: .88rem; line-height: 1.5; color: var(--ink-soft); }

/* The issuer and the holding company take the two solids, so the three
   operating businesses below stay light and read as one set. */
.org__box--issuer { background: var(--ink); border-color: var(--ink); }
.dgm .org__box--issuer .org__name { color: #fff; }
.dgm .org__box--issuer .org__role { color: var(--on-dark-soft); }
.org__box--parent { background: var(--olive); border-color: var(--olive); }
.dgm .org__box--parent .org__name { color: #fff; }
/* Not --olive-lift: that variant is for dark backgrounds and fails contrast
   here. This tint measures about 4.9:1 on the olive. */
.dgm .org__box--parent .org__role { color: #eef2e2; }

/* Vertical connector above the holding company and above the branch. */
.org__box--parent, .org__branch { position: relative; margin-top: var(--org-drop); }
.org__box--parent::before, .org__branch::before {
  content: ""; position: absolute; top: calc(var(--org-drop) * -1); left: 50%;
  width: var(--org-rule); height: var(--org-drop);
  margin-left: calc(var(--org-rule) / -2); background: var(--line);
}

.org__branch { list-style: none; padding: 0; display: grid; gap: var(--org-gap); width: 100%; }
/* Wrapper, not the card. The connectors live in this element's top padding, so
   putting the card's own background on it would draw the lines across the
   white instead of above it. */
.org__leaf { position: relative; }

@media (min-width: 46rem) {
  .org__branch { grid-template-columns: repeat(3, 1fr); }
  .org__leaf { padding-top: var(--org-drop); }

  /* The rule joining the three stubs. Each cell draws its own segment,
     overhanging by half the gap so neighbouring segments meet, and the two
     outer cells stop at their own centre. Written this way rather than as one
     bar with a percentage inset because the inset that would centre it depends
     on the gap as well as the column count, so a fixed percentage is only
     correct at one width. */
  .org__leaf::before {
    content: ""; position: absolute; top: 0; height: var(--org-rule);
    left: calc(var(--org-gap) / -2); right: calc(var(--org-gap) / -2);
    background: var(--line);
  }
  .org__leaf:first-child::before { left: 50%; }
  .org__leaf:last-child::before { right: 50%; }

  /* Stub from that rule down to the top of the card. */
  .org__leaf::after {
    content: ""; position: absolute; top: 0; left: 50%;
    width: var(--org-rule); height: var(--org-drop);
    margin-left: calc(var(--org-rule) / -2); background: var(--line);
  }
}

/* Below 46rem the three stack and carry no connectors between them. They are
   siblings, not a sequence, so a line joining them would say something the
   chart does not. The single rule from the holding company still lands on the
   group. */
@media (max-width: 45.99rem) {
  .org__branch { gap: var(--org-drop); }
}

/* --- moat: the three protections the copy lists ------------------------- */
.moat__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
@media (min-width: 52rem) { .moat__list { grid-template-columns: repeat(3, 1fr); } }
.moat__list > li { display: grid; }
.dgm .moat__n {
  font-family: var(--display); font-size: .95rem; font-weight: 600;
  color: var(--violet); margin-bottom: .5rem;
}

/* --- wheel: value creation, drawn as a turning cycle ---------------------
   Five steps sit on a circle around a hub, joined by arcs that run clockwise,
   so the sequence reads as a loop rather than a row of boxes.

   The steps are laid out by percentage of a square container rather than by
   SVG coordinates, so the labels stay real HTML text at the reader's own font
   size. Only the arcs are drawn. Below 46rem there is no room for a circle, so
   the same markup lays out as a numbered vertical list and the arcs are
   dropped: no duplicate content, only a different arrangement of it. */
.wheel {
  position: relative;
  width: min(100%, 42.5rem);
  aspect-ratio: 1;
  margin-inline: auto;
}
/* The colour sits on the <svg>, not on the <g>. An SVG marker resolves
   currentColor against its own ancestors in <defs>, not against the element
   that references it, so setting it on the group left the arrowheads inheriting
   the page's ink colour and rendering grey against violet arcs. */
.wheel__ring { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--violet); }
.wheel__arc { opacity: .6; }
.wheel__arc path { fill: none; stroke: currentColor; stroke-width: .4; }

.wheel__steps {
  position: absolute; inset: 0;
  margin: 0; padding: 0; list-style: none; counter-reset: wh;
}
.wheel__step {
  position: absolute; left: var(--x); top: var(--y);
  transform: translate(-50%, -50%);
  width: 10rem; text-align: center; counter-increment: wh;
}
/* Five points at 72 degree spacing, starting at the top and running clockwise,
   on a circle of radius 38% of the container. That radius clears the arcs by
   roughly 25px and still leaves each label inside the box. */
.wheel__step:nth-child(1) { --x: 50%;    --y: 12%; }
.wheel__step:nth-child(2) { --x: 86.14%; --y: 38.26%; }
.wheel__step:nth-child(3) { --x: 72.34%; --y: 80.74%; }
.wheel__step:nth-child(4) { --x: 27.66%; --y: 80.74%; }
.wheel__step:nth-child(5) { --x: 13.86%; --y: 38.26%; }

.wheel__dot {
  width: 2.3rem; height: 2.3rem; margin: 0 auto .55rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--violet); color: #fff;
  font-family: var(--sans); font-size: .92rem; font-weight: 650;
}
.wheel__dot::before { content: counter(wh); }
.dgm .wheel__t {
  font-family: var(--display); font-size: 1rem; font-weight: 600;
  line-height: 1.25; color: var(--ink);
}
.dgm .wheel__d {
  margin-top: .3rem; font-size: .82rem; line-height: 1.5; color: var(--ink-soft);
}

.wheel__hub {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 34%; aspect-ratio: 1; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 1rem;
  background: rgba(88, 70, 156, .06); border: 1px solid rgba(88, 70, 156, .3);
}
.dgm .wheel__hubName {
  font-family: var(--display); font-size: 1rem; font-weight: 600; color: var(--violet-deep);
}
.dgm .wheel__hubNote {
  margin-top: .35rem; font-size: .78rem; line-height: 1.45; color: var(--ink-soft);
}

@media (max-width: 45.99rem) {
  .wheel { aspect-ratio: auto; width: 100%; }
  .wheel__ring { display: none; }
  .wheel__steps { position: static; display: grid; gap: 1rem; }
  .wheel__step {
    position: static; transform: none; width: auto; text-align: left;
    border: 1px solid var(--line); border-radius: var(--radius-lg);
    background: var(--paper); padding: 1.1rem 1.2rem;
    display: grid; grid-template-columns: auto 1fr;
    column-gap: .9rem; align-items: start;
  }
  .wheel__dot { margin: 0; grid-row: 1 / span 2; width: 2rem; height: 2rem; font-size: .85rem; }
  .wheel__hub {
    position: static; transform: none; width: auto; aspect-ratio: auto;
    border-radius: var(--radius-lg); margin-top: 1rem; padding: .9rem 1.1rem;
  }
}

/* Photograph beside a block of text. */
.plate { margin: 0; }
.plate img {
  width: 100%; height: auto; display: block;
  border-radius: var(--radius-lg);
}
.plate figcaption {
  margin-top: .8rem; font-size: .82rem; line-height: 1.55;
  color: var(--ink-faint);
}
/* Media column drops under the text on narrow screens, and is capped so a tall
   portrait photograph does not push the next section off the fold. */
@media (max-width: 860px) {
  .split--media { grid-template-columns: 1fr; }
  .split--media .plate img { max-height: 60vh; width: auto; margin-inline: auto; }
}

/* Icons on the investment-case cards. The client's own, from their pitch deck,
   already drawn in the brand olive and violet. Decorative only: each repeats
   its own heading, so they are aria-hidden and carry empty alt. */
.card__icon {
  width: 44px;
  height: 44px;
  margin-bottom: 1rem;
  display: block;
}
@media (prefers-reduced-motion: no-preference) {
  .card:hover .card__icon { transform: translateY(-2px); }
  .card__icon { transition: transform .25s var(--ease); }
}
