/*
 * SteadyHash Ventures — base + component styles
 * Consumes tokens from design-system.css. Goal 2 ships the foundational shell
 * (reset, header, hero, footer); Goal 3 fills in full sections; Goal 5 adds the
 * full-bleed hero canvas treatment.
 */

/* ---------- Reset / base ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* In-page anchor navigation (header links, hero CTAs) glides instead of jumping.
     Reduced motion switches this back to instant (see the media query below). */
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: var(--weight-regular);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--color-ink);
  background: var(--color-bg);
}

a {
  color: inherit;
  text-decoration: none;
}

img {
  max-width: 100%;
  display: block;
}

:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 2px;
}

/* ---------- Layout primitives ---------- */
.container {
  width: 100%;
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: var(--section-py);
}

.section--alt {
  background: var(--color-bg-alt);
}

.eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: var(--weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: transparent;
  transition: background var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
  border-bottom: 1px solid transparent;
}

.site-header.is-scrolled {
  background: rgba(255, 255, 255, 0.85);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom-color: var(--color-border);
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
}

/* Brand link wrapping the official SteadyHash Ventures wide lockup (SVG <img>). */
.wordmark {
  display: inline-flex;
  align-items: center;
  flex: none;
  color: var(--color-ink);
}

/* The brand logo is the official wide lockup (public/images/logo-wide.svg): the "#"
   mark + "SteadyHash" / "Ventures" wordmark as one piece of artwork. Height-locked so
   it sits comfortably in the 64px header bar; width is intrinsic (auto) to preserve the
   550×150 aspect ratio. A quiet scale on hover keeps it feeling interactive. */
.wordmark__logo {
  display: block;
  height: 38px;
  width: auto;
  transition: transform var(--dur-fast) var(--ease),
    opacity var(--dur-fast) var(--ease);
}

/* Footer uses the taller STACKED lockup (public/images/logo-stack.svg, 311×223), so it
   is sized by a larger height to read as the footer's brand block. */
.wordmark--stacked .wordmark__logo {
  height: 88px;
}

.wordmark:hover .wordmark__logo {
  transform: scale(1.03);
  opacity: 0.9;
}

.nav {
  display: none;
  gap: var(--space-6);
}

.nav a {
  font-size: var(--fs-small);
  color: var(--color-muted);
  transition: color var(--dur-fast) var(--ease);
}

.nav a:hover {
  color: var(--color-ink);
}

@media (min-width: 880px) {
  .nav {
    display: flex;
  }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  /* min-height keeps the pill a comfortable >=44px touch target on mobile. */
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  font-size: var(--fs-small);
  font-weight: var(--weight-regular);
  white-space: nowrap;
  border: 1px solid var(--color-ink);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}

.btn--primary {
  background: var(--color-ink);
  color: #fff;
}

.btn--primary:hover {
  background: var(--color-ink-soft);
}

.btn--primary .btn-arrow {
  transition: transform var(--dur-fast) var(--ease);
}

.btn--primary:hover .btn-arrow {
  transform: translate(2px, -2px);
}

.btn--ghost {
  background: transparent;
  color: var(--color-ink);
  border-color: var(--color-border-strong);
}

.btn--ghost:hover {
  border-color: var(--color-ink);
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-small);
  color: var(--color-ink);
}

.link-arrow .btn-arrow {
  transition: transform var(--dur-fast) var(--ease);
}

.link-arrow:hover .btn-arrow {
  transform: translateX(3px);
}

/* Inline directional glyphs (views/partials/icons/arrow-*.html) sit in a
   .btn-arrow span that owns the nudge transition above. Size the SVG to ~1em so it
   tracks the adjacent text; line-height:0 removes descender space. */
.btn-arrow {
  display: inline-flex;
  line-height: 0;
}

.btn-arrow svg {
  width: 1em;
  height: 1em;
  display: block;
}

/* ---------- Anchored sections clear the sticky header ---------- */
/* .duo-card is included because the #research / #founders anchors sit on the cards
   themselves (inside the closing .section), not on a section wrapper — without it
   they landed tucked under the sticky header. */
.hero,
.section,
.site-footer,
.duo-card {
  scroll-margin-top: calc(var(--header-h) + var(--space-4));
}

/* ---------- Hero ---------- */
/* The quant-landscape canvas sits on the RIGHT of the hero, bleeding to the top
   and right edges (no card / no border) so it "emerges" from the corner exactly
   like pd/homepage.png. The copy sits in the normal flow on the left and is
   layered ABOVE the visual (z-index), so the headline can overflow/overlap onto
   the terrain. The hero is pulled up under the transparent sticky header so the
   visual reaches the very top of the page. */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  /* Full-viewport cinematic stage (user-directed, supersedes the Goal 9 82svh/820px
     compact band): on desktop the hero owns the whole first screen so the quant
     landscape reads monumental rather than a strip with the next section peeking in.
     svh tracks the *small* viewport so browser chrome doesn't overflow; the vh line
     is the older-engine fallback. */
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
  margin-top: calc(-1 * var(--header-h));
  padding-block: calc(var(--header-h) + var(--space-5)) var(--space-7);
}

.hero .container {
  position: relative;
  z-index: 1;
}

.hero__content {
  /* Goal 9: widened from 600px so the headline spans a wider column as in
     pd/homepage.png. The lede keeps its own 46ch cap for readability and the
     visual's left-edge mask keeps the copy clear of the terrain. */
  max-width: 760px;
}

.hero__headline {
  font-family: var(--font-display);
  font-weight: var(--weight-thin);
  font-size: var(--fs-display);
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-5);
}

/* Live-accent underline (A+B hybrid pass): a 2px rule in the live-data accent draws
   across under "Quantitative Edge." once the hero intro settles (the 2.7s delay
   tracks INTRO_DUR in quant-landscape.js) — the one piece of page chrome that
   borrows the data color. Without JS it renders already drawn. */
.hero__headline-accent {
  position: relative;
  display: inline-block;
}

.hero__headline-accent::after {
  content: "";
  position: absolute;
  left: 0.03em;
  bottom: -0.08em;
  width: 100%;
  height: 2px;
  background: var(--color-live);
  transform-origin: left;
  transition: transform 1.1s var(--ease) 2.7s;
}

.js .hero__headline-accent::after {
  transform: scaleX(0);
}

.js .reveal.is-visible .hero__headline-accent::after {
  transform: scaleX(1);
}

.hero__lede {
  max-width: 46ch;
  color: var(--color-muted);
  font-size: 1.0625rem;
  margin: 0 0 var(--space-5);
}

.hero__stats {
  display: flex;
  flex-wrap: wrap;
  /* Goal 9: tighter stat columns + margin so the copy stack reads denser. */
  gap: var(--space-6);
  margin: 0 0 var(--space-5);
}

.hero__stat dt {
  font-size: var(--fs-h3);
  font-weight: var(--weight-regular);
}

.hero__stat dd {
  margin: var(--space-1) 0 0;
  font-size: var(--fs-small);
  color: var(--color-muted);
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
}

/* ---------- Hero visual: full-bleed 3D quant landscape ---------- */
/* Full-bleed across the whole hero (user-directed large-screen pass; was a 72%
   right column). The horizontal mask still fades the terrain out under the copy
   on the left while the field stays dense across the right two thirds, so the
   landscape spans edge to edge without costing headline legibility. */
.hero__visual {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right,
      transparent 0%, rgba(0, 0, 0, 0.4) 34%, #000 62%);
  mask-image: linear-gradient(to right,
      transparent 0%, rgba(0, 0, 0, 0.4) 34%, #000 62%);
}

.quant-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}

.hero__visual.is-canvas-active .quant-canvas {
  opacity: 1;
}

.hero__visual.is-canvas-active .quant-mesh {
  opacity: 0;
}

.quant-mesh {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  perspective: 720px;
  transition: opacity var(--dur) var(--ease);
}

.quant-mesh__plane {
  width: 150%;
  height: 150%;
  background-image:
    linear-gradient(var(--color-border) 1px, transparent 1px),
    linear-gradient(90deg, var(--color-border) 1px, transparent 1px);
  background-size: 28px 28px;
  transform: rotateX(58deg) rotateZ(0deg);
  transform-origin: center 60%;
  opacity: 0.7;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 35%, #000 35%, transparent 78%);
  mask-image: radial-gradient(120% 90% at 50% 35%, #000 35%, transparent 78%);
  animation: mesh-drift 16s linear infinite;
}

@keyframes mesh-drift {
  to {
    background-position: 0 56px;
  }
}

.signal {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-accent);
  box-shadow: 0 1px 3px rgba(17, 24, 39, 0.35);
  animation: signal-pulse 4s var(--ease) infinite;
}

.signal--1 { top: 24%; left: 38%; animation-delay: 0s; }
.signal--2 { top: 18%; left: 56%; animation-delay: 0.8s; }
.signal--3 { top: 30%; left: 48%; animation-delay: 1.6s; }
.signal--4 { top: 26%; left: 66%; animation-delay: 2.4s; }
.signal--5 { top: 36%; left: 54%; animation-delay: 3.2s; }

@keyframes signal-pulse {
  0%, 100% { opacity: 0.35; transform: translateY(0); }
  50% { opacity: 1; transform: translateY(-3px); }
}

/* ---------- Section heads ---------- */
.section-head {
  max-width: 40ch;
  /* Goal 9: tightened (was --space-8) so the heading sits closer to its cards,
     in step with the compacted section rhythm. */
  margin-bottom: var(--space-7);
}

.section-head .eyebrow {
  margin: 0 0 var(--space-4);
}

.section-title {
  font-family: var(--font-display);
  font-weight: var(--weight-thin);
  font-size: var(--fs-h1);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
}

/* ---------- Feature rows (Focus / Presence — 3-up) ---------- */
/* A lead column (eyebrow + title + Learn More) followed by two flat feature
   columns. No card chrome — the columns sit directly on the page like
   pd/homepage.png. */
.feature__grid {
  display: grid;
  gap: var(--space-7);
}

@media (min-width: 760px) {
  .feature__grid {
    grid-template-columns: 1.25fr 1fr 1fr;
    gap: var(--space-8);
    align-items: start;
  }
}

/* Hairline rule separating the Presence row from Focus above (matches the
   divider in pd/homepage.png). The padding restores breathing room above.
   Creative pass: the rule is a ::before that DRAWS ITSELF left→right when the
   row reveals (a quiet drafting gesture); without JS it renders already drawn. */
.feature--divided .feature__grid {
  position: relative;
  padding-top: var(--section-py);
}

.feature--divided .feature__grid::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--color-border);
}

.js .feature--divided .feature__grid::before {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease);
}

.js .feature--divided .feature__grid.is-visible::before {
  transform: scaleX(1);
}

.feature__lead .eyebrow {
  margin: 0 0 var(--space-4);
}

.feature__title {
  font-family: var(--font-display);
  font-weight: var(--weight-thin);
  font-size: var(--fs-h1);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-5);
  max-width: 16ch;
}

.feature__item {
  display: block;
}

/* Focus reticle / hexagon marks. Faint single-weight art that firms up on hover
   (DESIGN.md §6). line-height:0 strips inline-box descender space. */
.feature__icon {
  display: inline-flex;
  line-height: 0;
  color: var(--color-faint);
  margin-bottom: var(--space-5);
  transition: transform var(--dur) var(--ease), color var(--dur) var(--ease);
  transform-origin: center;
}

.feature__icon svg,
.icon {
  width: 36px;
  height: 36px;
  display: block;
}

.feature__item:hover .feature__icon {
  transform: scale(1.08) rotate(6deg);
  color: var(--color-muted);
}

.feature__name {
  font-size: var(--fs-h3);
  font-weight: var(--weight-medium);
  margin: 0 0 var(--space-3);
}

.feature__body {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--fs-small);
  line-height: 1.6;
  max-width: 30ch;
}

/* ---------- Presence skyline line-art (Hong Kong / UAE) ---------- */
/* Faint single-weight silhouette sitting ABOVE the hub label (DESIGN.md §6). The
   wrapper + the SVG's width/height attributes reserve a fixed 3:1 box so the art
   never causes layout shift. */
.feature__skyline {
  margin-bottom: var(--space-5);
}

.presence-card__skyline {
  width: 100%;
  height: auto;
  display: block;
  color: var(--color-border-strong);
  opacity: 0.9;
  transition: color var(--dur) var(--ease), opacity var(--dur) var(--ease);
}

/* Quiet hover emphasis (a JS-free stand-in for the §6 "re-draws on hover" cue:
   restarting a stroke-dash draw on hover needs JS and risks jank, so the line
   simply firms up in ink instead). */
.feature__item--art:hover .presence-card__skyline {
  color: var(--color-muted);
  opacity: 1;
}

/* Stroke-in reveal. Default = fully drawn so a no-JS page still shows the skyline.
   When JS is active (.js) the path starts undrawn and strokes in left-to-right once
   the feature grid scrolls into view (.is-visible, set by public/js/main.js).
   pathLength="1" on the path normalises the dash so no JS measurement is needed. */
.presence-card__skyline path {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

.js .presence-card__skyline path {
  stroke-dashoffset: 1;
  transition: stroke-dashoffset var(--dur-slow) var(--ease);
}

.js .feature__grid.is-visible .presence-card__skyline path {
  stroke-dashoffset: 0;
}

/* ---------- Closing 2-up row (Research / For Founders) ---------- */
.duo__grid {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 920px) {
  .duo__grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* Each closing card is a light surface panel split into a lead column and a
   visual column (dark research tile / 3D cube cluster). */
.duo-card {
  background: var(--color-bg-alt);
  border-radius: var(--radius);
  /* Goal 12: business-smart padding — stepped down from --space-7 (48px) to --space-6
     (32px) so the Research / For-Founders cards read tighter, matching pd/homepage.png
     (the 48px inset left the cards too airy). */
  padding: var(--space-6);
  display: grid;
  gap: var(--space-6);
  transition: box-shadow var(--dur) var(--ease);
}

.duo-card:hover {
  box-shadow: var(--shadow-md);
}

@media (min-width: 560px) {
  .duo-card {
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }
}

.duo-card__lead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.duo-card__lead .eyebrow {
  margin: 0 0 var(--space-4);
}

.duo-card__title {
  font-family: var(--font-display);
  font-weight: var(--weight-light);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-5);
}

.duo-card__lead .link-arrow {
  margin-top: auto;
}

/* Dark "Latest Research" feature tile inside the research card. */
.research-feature {
  position: relative;
  background: var(--color-ink);
  color: #fff;
  border-radius: var(--radius-sm);
  padding: var(--space-6);
  min-height: 230px;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.research-feature__tag {
  margin: 0;
  color: var(--color-faint);
}

.research-feature__title {
  font-size: var(--fs-h3);
  font-weight: var(--weight-regular);
  line-height: 1.3;
  margin: 0;
  max-width: 22ch;
}

.research-feature__meta {
  margin: auto 0 0;
  /* keep clear of the absolutely-positioned corner arrow */
  padding-right: var(--space-6);
  font-size: var(--fs-small);
  color: var(--color-faint);
}

.research-feature__corner {
  position: absolute;
  right: var(--space-5);
  bottom: var(--space-5);
  line-height: 0;
  color: #fff;
}

.research-feature__corner svg {
  width: 18px;
  height: 18px;
}

/* 3D cube cluster (Three.js) inside the founders card. */
.founders-bricks {
  position: relative;
  min-height: 230px;
  align-self: stretch;
}

.founders-bricks__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
}

.founders-bricks.is-3d-active .founders-bricks__canvas {
  display: block;
}

.founders-bricks.is-3d-active .founders-bricks__fallback {
  display: none;
}

/* CSS fallback stack — a loose isometric cluster of light cubes shown until/unless
   the Three.js scene activates (no WebGL, reduced motion, or script blocked). */
.founders-bricks__fallback {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1fr;
  gap: 8px;
  place-content: center;
  padding: var(--space-5);
}

.founders-bricks__fallback span {
  background: linear-gradient(150deg, #ffffff, #e9ebef);
  border: 1px solid var(--color-border);
  border-radius: 4px;
  box-shadow: var(--shadow-sm);
  aspect-ratio: 1;
}

.founders-bricks__fallback span:nth-child(1) { transform: translateY(18px); }
.founders-bricks__fallback span:nth-child(5) { transform: translateY(-10px); }
.founders-bricks__fallback span:nth-child(6) { transform: translateY(8px); }

/* ---------- Footer (minimal — name, tagline, contact email only) ---------- */
.site-footer {
  background: var(--color-bg-alt);
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-8);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
}

.footer__tagline {
  margin: var(--space-3) 0 0;
  max-width: none;
  font-size: var(--fs-small);
  color: var(--color-muted);
  white-space: nowrap;
}

.site-footer a {
  color: var(--color-muted);
  transition: color var(--dur-fast) var(--ease);
}

.site-footer a:hover {
  color: var(--color-ink);
}

.footer__email {
  font-size: var(--fs-body);
  color: var(--color-ink);
}

.footer-bottom {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-small);
  color: var(--color-faint);
}

/* ---------- Small-screen safeguards ---------- */
.hero__headline,
.section-title,
.feature__title,
.duo-card__title,
.research-feature__title {
  overflow-wrap: break-word;
}

/* On tablet/phone the hero fills the screen (user-directed): the copy is centered
   in a full-viewport band and the simplified quant-landscape becomes a calm,
   full-bleed background behind it, fading toward the bottom so the stacked copy
   stays legible. */
@media (max-width: 880px) {
  /* Fill the viewport so the hero reads as a deliberate full-screen opening on
     mobile rather than a short stacked band. svh tracks the *small* viewport so
     browser chrome never pushes the field into an overflow; vh is the older-engine
     fallback. The base .hero already centers its content (flex / align-items). */
  .hero {
    min-height: 100vh;
    min-height: 100svh;
    padding-block: calc(var(--header-h) + var(--space-7)) var(--section-py-sm);
  }
  /* Full-bleed background covering the whole hero (not just a top band). Lower
     opacity + a soft downward fade keep the headline and CTAs readable over it. */
  .hero__visual {
    width: 100%;
    opacity: 0.5;
    -webkit-mask-image: linear-gradient(to bottom,
        #000 0%, rgba(0, 0, 0, 0.55) 60%, transparent 96%);
    mask-image: linear-gradient(to bottom,
        #000 0%, rgba(0, 0, 0, 0.55) 60%, transparent 96%);
  }
  /* Compact the header so the brand lockup and the CTA share one tidy row once the
     nav is hidden — the logo shrinks, spacing tightens, and the CTA trims its padding
     so "Apply for Funding" never wraps or crowds the logo. */
  .site-header .container {
    gap: var(--space-3);
  }
  .site-header .wordmark__logo {
    height: 32px;
  }
  .site-header .btn--primary {
    padding-inline: var(--space-4);
  }
}

@media (max-width: 480px) {
  :root {
    --fs-display: clamp(2.25rem, 11vw, 2.75rem);
  }
  .footer__email {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* Allow the tagline to wrap on very narrow phones rather than overflow. */
  .footer__tagline {
    white-space: normal;
  }
}

/* ---------- Scroll reveal ---------- */
.js .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* ---------- Section choreography (creative pass) ---------- */
/* Staggered child reveal: inside a revealing section the lead column rises first,
   then each feature/visual column follows a beat later — the page unfolds in
   sequence instead of arriving as monolithic blocks. Hidden states are gated by
   .js so a no-JS page renders everything in place. */
.js .reveal .feature__lead,
.js .reveal .feature__item,
.js .duo-card.reveal .duo-card__lead,
.js .duo-card.reveal .research-feature,
.js .duo-card.reveal .founders-bricks {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.js .reveal.is-visible .feature__lead,
.js .reveal.is-visible .feature__item,
.js .duo-card.reveal.is-visible .duo-card__lead,
.js .duo-card.reveal.is-visible .research-feature,
.js .duo-card.reveal.is-visible .founders-bricks {
  opacity: 1;
  transform: none;
}

/* Feature rows: the two topic columns follow the lead at 120ms beats. */
.js .reveal.is-visible .feature__item:nth-of-type(1) {
  transition-delay: 120ms;
}

.js .reveal.is-visible .feature__item:nth-of-type(2) {
  transition-delay: 240ms;
}

/* Closing 2-up row: each card's visual follows its lead; the Founders card (2nd)
   trails the Research card by a beat so the row reads left→right. */
.js .duo-card.reveal.is-visible .research-feature,
.js .duo-card.reveal.is-visible .founders-bricks {
  transition-delay: 150ms;
}

.js .duo__grid .reveal:nth-child(2).is-visible .duo-card__lead {
  transition-delay: 120ms;
}

.js .duo__grid .reveal:nth-child(2).is-visible .founders-bricks {
  transition-delay: 270ms;
}

/* ---------- Research tile: live dot + self-drawing sparkline ---------- */
/* The pulsing dot borrows the live-data accent (color = live data, per the hero's
   A+B pass); the sparkline strokes in left→right when the card reveals, echoing
   the hero's chart line on the dark tile. */
.live-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-live);
  margin-right: var(--space-2);
  vertical-align: 1px;
  animation: live-pulse 2.6s var(--ease) infinite;
}

@keyframes live-pulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.35;
  }
}

.research-feature__spark {
  width: 120px;
  height: 28px;
  color: rgba(255, 255, 255, 0.45);
  margin-top: var(--space-2);
}

.research-feature__spark-dot {
  fill: var(--color-live);
}

.research-feature__spark path {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

.js .research-feature__spark path {
  stroke-dashoffset: 1;
  transition: stroke-dashoffset var(--dur-slow) var(--ease) 400ms;
}

.js .reveal.is-visible .research-feature__spark path {
  stroke-dashoffset: 0;
}

.js .research-feature__spark-dot {
  opacity: 0;
  transition: opacity var(--dur) var(--ease) 1000ms;
}

.js .reveal.is-visible .research-feature__spark-dot {
  opacity: 1;
}

/* Corner arrow answers a hover anywhere on the research card. */
.research-feature__corner {
  transition: transform var(--dur-fast) var(--ease);
}

.research-card:hover .research-feature__corner {
  transform: translate(2px, -2px);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  html {
    scroll-behavior: auto;
  }
  .js .reveal {
    opacity: 1;
    transform: none;
  }
  /* Choreographed children render in place immediately — no stagger, no rise. */
  .js .reveal .feature__lead,
  .js .reveal .feature__item,
  .js .duo-card.reveal .duo-card__lead,
  .js .duo-card.reveal .research-feature,
  .js .duo-card.reveal .founders-bricks {
    opacity: 1;
    transform: none;
  }
  /* Skylines, the Presence divider, and the research sparkline paint fully drawn
     immediately — no stroke-in / draw-across. */
  .js .presence-card__skyline path,
  .js .research-feature__spark path {
    stroke-dashoffset: 0;
  }
  .js .feature--divided .feature__grid::before {
    transform: none;
  }
  .js .research-feature__spark-dot {
    opacity: 1;
  }
}

/* Constrained / small-power devices: freeze the decorative hero animation. */
@media (max-width: 600px) {
  .quant-mesh__plane,
  .signal {
    animation: none;
  }
}

/* ---------- Research pages (/research + /research/<YYYY-MM>) ---------- */
/* Subpage hero band. Like .hero it slides under the transparent sticky header
   (negative top margin) so the bg-alt surface reaches the viewport top. */
/* Research pages (/research index + report articles) are styled by the
   dedicated reusable stylesheet public/css/research.css, loaded only on those
   pages via the layout's {{{ pageCss }}} slot (see lib/research.js). The
   homepage research-feature tile below stays here because the homepage never
   loads research.css. */

/* The homepage "Latest Research" tile is now an <a> to the newest report —
   give its corner arrow the same hover nudge as the other CTAs. */
a.research-feature .research-feature__corner svg {
  transition: transform var(--dur-fast) var(--ease);
}

a.research-feature:hover .research-feature__corner svg {
  transform: translate(2px, -2px);
}
