/* ==========================================================================
   DCY Multi-Fund Website: shared design system
   Rebuilt from reference/dcy-homepage-analysis.md (dcy.fund teardown)
   ========================================================================== */

/* ---- Reset ---- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
img { max-width: 100%; display: block; }
button, input, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

/* ---- Tokens ---- */
:root {
  --page: #F5F5F5;
  --ink: #000000;
  --muted: #A8A8A8;
  --faint: rgba(0, 0, 0, 0.4);
  --card: #FFFFFF;
  --radius: 10px;
  --container: 1200px;
  --gutter: 40px;
  --font-display: 'Satoshi', 'Inter', -apple-system, sans-serif;
  --font-body: 'Inter', -apple-system, sans-serif;
  --font-label: 'Poppins', 'Inter', sans-serif;
  /* default accent (DCY black), overridden per fund below */
  --accent: #000000;
  --accent-soft: rgba(0, 0, 0, 0.06);
  --shadow-soft:
    inset 0 3px 1px rgba(255, 255, 255, 1),
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 4px 10px rgba(0, 0, 0, 0.08),
    0 12px 24px rgba(0, 0, 0, 0.06);
  --shadow-primary:
    0 2px 4px rgba(0, 0, 0, 0.18),
    0 8px 18px rgba(0, 0, 0, 0.22),
    0 20px 40px rgba(0, 0, 0, 0.12);
  --shadow-card:
    0 1px 2px rgba(0, 0, 0, 0.04),
    0 8px 24px rgba(0, 0, 0, 0.06),
    0 24px 48px rgba(0, 0, 0, 0.05);
}

/* DCY-level pages (gate, hub, legal): the house colour is black, not a fund accent */
body[data-fund="dcy"]      { --accent: #000000; --accent-soft: rgba(0, 0, 0, .06);      --tile-grad: linear-gradient(160deg, #3D3D3D, #000000); }

/* Per-fund accents (logo/brochure-derived) */
body[data-fund="btc"]      { --accent: #F7931A; --accent-soft: rgba(247, 147, 26, .10); --tile-grad: linear-gradient(160deg, #F0B268, #E39332); }
body[data-fund="usd"]      { --accent: #32B85F; --accent-soft: rgba(50, 184, 95, .10);  --tile-grad: linear-gradient(160deg, #8BDFA7, #45A766); }
body[data-fund="digital"]  { --accent: #3376B9; --accent-soft: rgba(51, 118, 185, .10); --tile-grad: linear-gradient(160deg, #8BB5DF, #4576A7); }
body[data-fund="emerging"] { --accent: #7462D1; --accent-soft: rgba(116, 98, 209, .10); --tile-grad: linear-gradient(135deg, #08B8B7, #7462D1); }

body {
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--page);
  overflow-x: hidden;
}

.container { max-width: var(--container); margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }
.narrow { max-width: 800px; margin-left: auto; margin-right: auto; }

/* ---- Typography ---- */
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 500; }
.h2 {
  font-size: 56px;
  line-height: 1.2;
  letter-spacing: -0.56px;
  color: var(--ink);
}
.h2 .accent { color: var(--accent); }
.sub {
  font-family: var(--font-display);
  font-size: 24px;
  line-height: 1.5;
  font-weight: 500;
  color: var(--muted);
}
.eyebrow {
  font-family: var(--font-display);
  font-size: 12px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 16px;
}
.section-head { text-align: center; max-width: 720px; margin: 0 auto 48px; }
.section-head p.lead { margin-top: 16px; color: var(--ink); }

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 24px;
  border: 0;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6;
  cursor: pointer;
  transition: transform .2s ease, box-shadow .2s ease, opacity .2s ease,
              background-color .2s ease, color .2s ease;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px) scale(.99); }
.btn-primary { background: var(--ink); color: #FFF; box-shadow: var(--shadow-primary); }
.btn-primary:hover { transform: translateY(-2px); }
.btn-primary:disabled { opacity: .35; cursor: not-allowed; transform: none; }
.btn-soft { background: var(--page); color: var(--ink); box-shadow: var(--shadow-soft); }
/* Soft buttons darken into the primary treatment on hover (matches dcy.fund):
   solid ink fill, white label, no lift; the inset highlight drops away. */
.btn-soft:hover { background: var(--ink); color: #FFF; box-shadow: var(--shadow-primary); }
.btn-soft.accent-label { color: var(--accent); }
.btn-soft.accent-label:hover { color: #FFF; }

/* ---- Header ---- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  background: rgba(245, 245, 245, 0);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}
.site-header .bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 32px 16px;
}
.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.brand img { width: 38px; height: 38px; border-radius: 9px; }
.brand img.main-logo { width: auto; height: 24px; border-radius: 0; }
.brand .wordmark { font-family: var(--font-display); font-weight: 700; font-size: 20px; letter-spacing: .02em; }
.brand .divider { width: 1px; height: 22px; background: rgba(0, 0, 0, .15); }
.brand .fund-label { font-family: var(--font-label); font-weight: 300; font-size: 14px; color: var(--accent); white-space: nowrap; }
.header-actions { display: flex; align-items: center; gap: 12px; }
/* The legal pages carry no header "Contact us" button, which elsewhere sets the
   bar height; without it the bar collapses to 52px against 74px on the fund
   pages. Hold the rhythm on desktop; below 780px the button is hidden
   everywhere, so the heights already match. */
@media (min-width: 781px) {
  body[data-public] .site-header .bar { min-height: 74px; }
}

/* Fund switcher dropdown */
.switcher { position: relative; }
.switcher > button svg { transition: transform .2s ease; }
.switcher.open > button svg { transform: rotate(180deg); }
.switcher-menu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  /* 200px, not 260: the rows measure 185px at their natural width now that the
     labels are bare product names. The floor only has to clear that, plus a
     little slack, and stay wider than the trigger button (158px). */
  min-width: 200px;
  background: var(--card);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  padding: 8px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.switcher.open .switcher-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.switcher-menu a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
}
.switcher-menu a:hover { background: var(--page); }
.switcher-menu a.current { background: var(--accent-soft); }
.switcher-menu img { width: 30px; height: 30px; border-radius: 7px; }
.switcher-menu .all { border-top: 1px solid rgba(0, 0, 0, .06); margin-top: 6px; padding-top: 10px; color: var(--faint); }

/* Mobile menu */
.hamburger { display: none; background: none; border: 0; width: 40px; height: 40px; cursor: pointer; padding: 8px; }
.hamburger span { display: block; height: 2px; background: var(--ink); margin: 5px 0; border-radius: 2px; transition: transform .2s ease, opacity .2s ease; }
.mobile-menu {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(245, 245, 245, .96);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  padding: 100px 24px 40px;
  flex-direction: column;
  gap: 8px;
}
.mobile-menu.open { display: flex; }
.mobile-menu a { display: flex; align-items: center; gap: 14px; padding: 14px 12px; border-radius: 10px; font-size: 17px; font-weight: 500; }
.mobile-menu a img { width: 36px; height: 36px; border-radius: 8px; }
.mobile-menu a.current { background: #FFF; box-shadow: var(--shadow-card); }
body.menu-locked { overflow: hidden; }

/* ---- Hero ---- */
/* The hero fills the first screen exactly, so the landing view is the hero and
   nothing else: the founder band's top edge is the first thing you scroll to,
   never a line sitting in the lower third of the fold. Two units, in this
   order, because the fallback matters more than it looks: `100svh` is the
   *small* viewport height, i.e. the height with the mobile browser chrome
   showing, so the section can't grow taller than what is actually on screen
   when the URL bar is out. Anything that doesn't know `svh` gets `100vh`.

   min-height, not height: on a short window (or a long headline) the copy plus
   its padding can exceed the fold, and the hero has to grow rather than clip.
   The flex column then centres .inner in whatever height wins, and the
   asymmetric padding below biases it off dead centre — see the padding note. */
.hero {
  position: relative;
  background: #FFFFFF;
  padding: 200px var(--gutter) 140px;
  text-align: center;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Background video, on the fund pages that ship one (BTC, USD, Digital
   Dynamic). Backmost layer of the hero, where the `opacity` IS the white veil: it
   composites over the hero's own #FFF, which is what keeps the headline
   legible over the centred motif in the footage. The hero's ::after radial
   gradient is transparent at dead centre, so without this the motif would sit
   at full contrast directly behind the H1. Fund pages with no video keep the
   .glyph watermark instead, because the two together read as a double watermark, so
   a page carries one or the other, never both.

   The veil is per-fund because the clips are not equally bright, and what has
   to stay constant is the COMPOSITED backdrop (~196/255), not the opacity.
   Solve `veil × L + (1 - veil) × 255 = 196` for each clip's measured central
   luminance L. BTC/USD sit at L≈142–149 → .55. See --hero-video-veil below. */
.hero-video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: var(--hero-video-veil, .55);
  pointer-events: none;
  user-select: none;
}
/* Digital Dynamic's clip is dark navy (central L≈77 against ≈150 for BTC/USD),
   so the shared veil is not enough on its own. Two ways to land it on the same
   backdrop: drop the veil to .33, or brighten the footage and keep the veil.
   Both measure the same (~226 vs ~231 rendered), but veil-alone turns the clip
   into flat grey mud with hard rectangular edges, because opacity crushes the
   mid-tones the geometry lives in. Brightening lifts those mids instead, so the
   particle wave and light streaks still read. Hence: brighten, don't fade. */
body[data-fund="digital"] .hero-video { filter: brightness(1.8) saturate(.85); }
/* Emerging Tech's clip is darker still (central L≈62, against ≈77 for Digital
   Dynamic and ≈147 for BTC/USD), and its subject is thin teal circuitry rather
   than a solid motif. Brightness alone cannot carry it: the bright nodes clip
   long before the dark navy ground lifts, so pushing past ~1.9 blows the teal
   to white and buys almost nothing (measured: 2.0 → 176, 2.8 → 191, still short
   of the ~196 target). So this one splits the difference the other two make
   separately, brighten AND drop the veil, landing at ~193 composited, in line
   with Digital Dynamic's rendered ~191, with ~9% of pixels clipped instead of
   the ~14% a veil-preserving brightness would cost. */
body[data-fund="emerging"] .hero-video { --hero-video-veil: .40; filter: brightness(1.7); }
.hero .glyph {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -52%);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 560px;
  line-height: 1;
  color: var(--accent);
  opacity: .07;
  pointer-events: none;
  user-select: none;
}
.hero .blob {
  position: absolute;
  width: 720px; height: 720px;
  top: -180px; left: 50%;
  transform: translateX(-50%);
  background: radial-gradient(circle, var(--accent-soft) 0%, rgba(255,255,255,0) 65%);
  animation: drift 14s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes drift {
  from { transform: translateX(-62%) translateY(0); }
  to   { transform: translateX(-38%) translateY(48px); }
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(50% 50% at 50% 50%, rgba(255,255,255,0) 0%, rgba(255,255,255,.9) 78%, #FFF 100%);
  pointer-events: none;
}
/* On the video heroes the copy must not sit on the clip's centred motif (the
   coin, the globe, the particle wave), the one part of the footage worth
   seeing — its white halo would wash out exactly that. The video is
   object-fit: cover, so the motif is always at the hero's centre, whatever
   height the fold gives it; the copy therefore has to sit *below* centre.

   Since the hero flex-centres, what does that is not either padding on its own
   but the difference between them: .inner is centred in the content box, so an
   unequal pair shifts it by half the gap, here (330 - 100) / 2 = 115px down.
   That offset is what clears the motif, and it holds at every viewport height
   — measured 900/1200/844(mobile), copy top always ~115px past centre.

   The absolute values still matter on a short window, where min-height stops
   binding and the hero falls back to padding + content: 330/100 is then the
   real box, and the bottom half has to stay ≥ the halo's 90px vertical inset
   (see invariant 2 below) or the seam it exists to prevent comes back.

   Scoped with :has() rather than by fund, so a hero gets this if and only if
   it ships a clip. */
.hero:has(.hero-video) { padding-top: 330px; padding-bottom: 100px; }
.hero .inner { position: relative; z-index: 1; max-width: 820px; margin: 0 auto; }
/* Over a video the copy needs its own white bed. .sub is --muted (#A8A8A8),
   which clears only ~2.4:1 on plain white; the footage measures ~142–149/255
   behind the text (steady across every frame of both clips), which composites
   to ~193–197 and would drop the subline to ~1.4:1. The hero's ::after vignette
   is no help here: it whitens the edges and is transparent at dead centre,
   which is exactly where the copy sits. This halo lifts the text back onto
   near-white while the video stays visible around it. .inner is its own
   stacking context (z-index: 1), so z-index: -1 puts the halo above the
   video but under the copy. Scoped by the sibling selector, so heroes with
   no video are untouched.

   Two sizing invariants, both about not leaving a visible edge:

   1. The ramp must reach alpha 0 *at* the box boundary. `closest-side` puts the
      ellipse exactly on all four sides, so the entire perimeter is transparent.
      The old `58% 58%` overshot the box by 16%, so the ramp was still at ~.22
      alpha when the box ran out, a hard-edged white rectangle sitting over the
      footage. Faint per pixel, but a dead-straight line across the hero reads
      instantly.
   2. The box must stay inside the hero. .hero is overflow: hidden and this halo
      paints above the ::after vignette (.inner is a stacking context at
      z-index 1, so its z-index: -1 child still sits above the section's own
      ::after), so a clip through non-zero alpha is a seam as well. Left/right
      may overflow: that clip lands on the viewport edge, where there is no
      adjacent pixel to step against. The vertical inset may not: it has to
      stay under the hero's padding-bottom (100px here, 60px on mobile).

   Hence -90px vertically and a generous -260px horizontally, which buys back
   the coverage the smaller ellipse would otherwise cost: alpha at the outermost
   headline and subline glyphs goes from ~.25 to ~.31–.33, so the copy sits on a
   slightly better bed than before, not a worse one. */
.hero-video ~ .inner::before {
  content: "";
  position: absolute;
  inset: -90px -260px;
  z-index: -1;
  background: radial-gradient(closest-side at 50% 50%,
              rgba(255,255,255,.9) 0%, rgba(255,255,255,.72) 55%, rgba(255,255,255,0) 100%);
  pointer-events: none;
}
.hero .sub { margin-top: 24px; }

/* ---- Founder note ---- */
.founder {
  position: relative;
  background: rgba(255, 255, 255, 0.3);
  padding: 100px var(--gutter);
  text-align: center;
  overflow: hidden;
}
.founder .statement {
  font-family: var(--font-display);
  font-size: 24px;
  line-height: 1.5;
  font-weight: 500;
  max-width: 900px;
  margin: 0 auto;
}
.founder .subline { margin-top: 24px; font-size: 16px; color: var(--ink); }

/* ---- Key facts strip ---- */
.facts { padding: 120px var(--gutter) 20px; }
.facts-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  max-width: 1028px;
  margin: 0 auto;
}
.fact {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 28px 24px;
}
.fact .k {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 10px;
}
.fact .v { font-family: var(--font-display); font-size: 22px; font-weight: 700; line-height: 1.3; }
.fact .v .unit { color: var(--accent); }
.fact .note { margin-top: 6px; font-size: 13px; color: var(--faint); }
.facts .fineprint { max-width: 1028px; margin: 20px auto 0; font-size: 12px; color: var(--faint); }
.todo-flag { color: #B45309; font-weight: 600; }

/* ---- Status ledger (Emerging Tech) ---------------------------------------
   The Key Facts strip above answers "what are the terms". A fund that has not
   launched has no terms to answer with, so this page shows its universe
   instead, the themes it is being built to own.

   Two marquees drifting against each other, full-bleed and masked at both
   edges so the set reads as continuous rather than as a list that happens to
   end. Opposing directions are what say "these are peers", where one long row
   would have read as a ranking.

   Deliberately a different object from .fact: hairline pills, no shadow, no
   arrows, no dots. The controls a carousel normally needs are what would have
   made this look like a widget bolted onto a quiet page. */
.soon { padding: 120px var(--gutter) 20px; }
.themes {
  /* Break the section gutter so the rows bleed off both edges. */
  margin: 56px calc(var(--gutter) * -1) 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 90px, #000 calc(100% - 90px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 90px, #000 calc(100% - 90px), transparent 100%);
}
.theme-row { overflow: hidden; }
.theme-track {
  display: flex;
  width: max-content;
  animation: theme-drift 64s linear infinite;
}
/* The second row runs the other way, and slower, so the two never lock into
   a repeating pair the eye can predict. */
.theme-track.rev { animation-duration: 78s; animation-direction: reverse; }
.themes:hover .theme-track { animation-play-state: paused; }
.theme-set { display: flex; gap: 14px; padding-right: 14px; }
/* -50% lands exactly on the start of the duplicate set, so the loop has no seam. */
@keyframes theme-drift { to { transform: translateX(-50%); } }

.theme {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "e n" "e c";
  align-items: center;
  column-gap: 14px;
  padding: 12px 26px 12px 18px;
  background: var(--card);
  border: 1px solid rgba(0, 0, 0, .10);
  border-radius: 999px;
  white-space: nowrap;
  transition: border-color .25s ease, color .25s ease;
}
.theme .e { grid-area: e; font-size: 22px; line-height: 1; }
.theme .n {
  grid-area: n;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.01em;
}
.theme .c {
  grid-area: c;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .36);
  transition: color .25s ease;
}
.theme:hover { border-color: var(--accent); }
.theme:hover .c { color: var(--accent); }

.soon .fineprint { max-width: 1028px; margin: 32px auto 0; font-size: 12px; color: var(--faint); text-align: center; }

/* ---- Sections ---- */
.section { padding: 160px var(--gutter) 100px; }
.section.tight { padding-top: 120px; }

/* ---- Form card ---- */
.form-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  max-width: 640px;
  margin: 0 auto;
  padding: 40px;
}
.field { margin-bottom: 20px; text-align: left; }
.field label { display: block; font-size: 14px; margin-bottom: 8px; }
.field input[type="text"], .field input[type="email"], .field textarea {
  width: 100%;
  height: 48px;
  padding: 12px;
  font-size: 16px;
  background: var(--page);
  border: 1px solid transparent;
  border-radius: var(--radius);
  outline: none;
  transition: border-color .15s ease, background .15s ease;
}
.field textarea { height: auto; min-height: 104px; line-height: 1.6; resize: vertical; display: block; }
.field input:focus, .field textarea:focus { border-color: var(--accent); background: #FFF; }
.field input::placeholder, .field textarea::placeholder { color: var(--faint); }
.consent { display: flex; gap: 12px; align-items: flex-start; margin: 24px 0; text-align: left; }
.consent input[type="checkbox"] {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  margin-top: 3px;
  accent-color: var(--accent);
  cursor: pointer;
}
.consent label { font-size: 14px; line-height: 1.6; color: var(--faint); cursor: pointer; }
.form-card .btn { width: 100%; }
.form-status { margin-top: 16px; font-size: 14px; display: none; }
.form-status.ok { display: block; color: #15803D; }
.form-status.err { display: block; color: #B91C1C; }

/* ---- Isometric brochure plane (every product page) ----
   Each product's investment brochure laid out as one tilted plane behind the
   heading and the form — the section's backdrop, filling it corner to corner.
   The point is volume: a wall of pages says "there is a real document here" in
   a way a couple of thumbnails cannot. The pages, the 112 tiles, how many
   copies each page gets and which cell each one lands in all come out of
   make-doc-previews.py; do not hand-edit the markup.

   That script solves the arrangement against the numbers below — the transform,
   the gap, --iso-w, and the size of the form card that covers the middle — to
   keep a recognisable page from showing twice in the window a visitor actually
   sees. Change any of them and the arrangement is stale: re-run
   `python3 make-doc-previews.py --layout`. */
.iso-section {
  /* One grey, declared once: the backdrop, every fade that dissolves into it,
     and the veil that holds the plane back. All three are the same colour at
     different alphas and have to be kept in step — note that a gradient to
     plain `transparent` is a gradient to transparent *black*, which would
     smudge every edge grey-to-charcoal. A step darker than --page so the
     section reads as its own block, and the pages as paper laid on it. */
  --iso-bg: #E8E8E8;
  --iso-bg-0: rgba(232, 232, 232, 0);
  --iso-veil: rgba(232, 232, 232, .55);
  position: relative;
  background: var(--iso-bg);
  overflow: hidden;
}
/* The heading and the form ride over the plane. The form card is opaque, so it
   masks the busiest part of the grid all by itself and the pages read down
   either flank of it. */
.iso-section > .section-head,
.iso-section > .form-card { position: relative; z-index: 1; }
/* The heading has no card under it, and now that the pages run wall to wall it
   can land on a dark one. A soft local wash keeps it the loudest thing in the
   section without clearing the grid behind it. z-index:-1 sits inside the
   head's own stacking context, so it covers the plane and not the words. */
.iso-section > .section-head::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: -1;
  width: 165%;
  height: 300%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(232, 232, 232, .88), var(--iso-bg-0) 100%);
  pointer-events: none;
}
.iso-section > .form-card {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, .05),
    0 12px 32px rgba(0, 0, 0, .10),
    0 32px 64px rgba(0, 0, 0, .08);
}

.iso-stage {
  /* Plane width drives everything: the tiles are fractions of it. It has to be
     big enough that the *rotated* plane circumscribes the section — a tilted
     rectangle leaves triangular gaps at the corners of the box it covers, so
     the plane is roughly twice the section in each direction. 3100px over
     8 columns keeps a tile at ~410px on screen while covering a 1920 viewport
     corner to corner; shrink it and bare grey appears in the corners first. */
  --iso-w: 3100px;
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
/* Fading into the backdrop colour rather than masking: it is a known flat
   colour, so gradient overlays are exact, and they avoid mask-composite, which
   still needs prefixing to work in Safari. All three layers live on one
   pseudo-element, and it needs the z-index — an ::before would sit *under* the
   plane, since both are positioned and DOM order would decide. */
.iso-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(to bottom, var(--iso-bg) 0%, var(--iso-bg-0) 6%,
                    var(--iso-bg-0) 94%, var(--iso-bg) 100%),
    linear-gradient(to right, var(--iso-bg) 0%, var(--iso-bg-0) 4%,
                    var(--iso-bg-0) 96%, var(--iso-bg) 100%),
    /* Unlike the band version, this one is veiled everywhere, not just at the
       rim: 56px of black heading has to sit on top of it and stay the loudest
       thing in the section. Enough wash that the pages become texture, not so
       much that they stop being pages. */
    radial-gradient(120% 120% at 50% 50%, var(--iso-veil) 0%, rgba(232, 232, 232, .82) 100%);
}

.iso-plane {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--iso-w);
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 24px;
  /* Read right to left: spin the grid in its own plane, tip it away, then
     centre it. No perspective — the reference is a parallel projection, and a
     vanishing point would make the far tiles read as smaller pages. */
  transform: translate(-50%, -50%) rotateX(56deg) rotateZ(-40deg);
}
.iso-plane img {
  width: 100%;
  /* Load-bearing: the height attribute is a presentational hint, which still
     beats an unset property, and a definite height switches aspect-ratio off
     entirely — without this every tile renders at its intrinsic height. */
  height: auto;
  aspect-ratio: 16 / 9;
  border-radius: 3px;
  /* The ring is doing the work, not the shadow: most of these pages are white
     on a light grey floor, so without an edge they bleed into each other and
     into the band. */
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .07),
    0 10px 26px rgba(0, 0, 0, .13);
}

/* ---- Contact cards ---- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  max-width: 1028px;
  margin: 0 auto;
}
.contact-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 40px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.icon-tile {
  width: 64px; height: 64px;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #FFF;
}
.icon-tile.accented { background: linear-gradient(180deg, var(--accent) 0%, #FFFFFF 160%); }
.icon-tile.dark { background: linear-gradient(180deg, #000000 0%, #FFFFFF 175%); }
.contact-card p { color: var(--ink); max-width: 380px; }

/* ---- FAQ ---- */
.faq-section { background: #FFF; }
.faq-list { max-width: 900px; margin: 0 auto; }
.faq-item { border-bottom: 1px solid rgba(0, 0, 0, .08); }
.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  background: none;
  border: 0;
  text-align: left;
  padding: 24px 4px;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 500;
  cursor: pointer;
}
.faq-q svg { flex: 0 0 auto; transition: transform .25s ease; color: var(--accent); }
.faq-item.open .faq-q svg { transform: rotate(180deg); }
.faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height .35s ease;
}
.faq-a .content { padding: 0 4px 24px; font-size: 15px; line-height: 1.7; color: rgba(0, 0, 0, .72); }
.faq-a .content p + p { margin-top: 10px; }
.faq-a .content ul { margin: 10px 0 10px 20px; }
.faq-a .content li + li { margin-top: 6px; }
.faq-outro { text-align: center; margin-top: 40px; font-size: 15px; }
.faq-outro a { color: var(--accent); font-weight: 500; }

/* ---- Other funds strip ---- */
.other-funds { background: #FFF; padding: 100px var(--gutter) 120px; }
.other-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  max-width: 1028px;
  margin: 0 auto;
}
.fund-tile {
  background: var(--card);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  transition: transform .2s ease, box-shadow .2s ease;
}
.fund-tile:hover { transform: translateY(-4px); box-shadow: 0 2px 4px rgba(0,0,0,.05), 0 16px 40px rgba(0,0,0,.10); }
.fund-tile img { width: 52px; height: 52px; border-radius: 12px; }
.fund-tile .name { font-family: var(--font-display); font-weight: 700; font-size: 18px; }
.fund-tile .desc { font-size: 14px; color: rgba(0, 0, 0, .6); line-height: 1.6; flex: 1; }
.fund-tile .go { font-size: 14px; font-weight: 500; }

/* ---- Footer ---- */
.site-footer {
  position: relative;
  background: #FFF;
  padding: 80px 60px 40px;
  text-align: center;
  overflow: hidden;
}
.socials { display: flex; justify-content: center; gap: 20px; margin-bottom: 60px; }
.socials a {
  width: 44px; height: 44px;
  border-radius: 12px;
  background: var(--page);
  box-shadow: var(--shadow-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .2s ease;
}
.socials a:hover { transform: translateY(-2px); }
.legal-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 28px; margin-bottom: 24px; font-size: 14px; position: relative; z-index: 1; }
.legal-links a:hover { color: var(--accent); }
.copyright { font-size: 13px; color: var(--faint); position: relative; z-index: 1; }

/* ---- Floating CTA ---- */
.floating-cta {
  position: fixed;
  bottom: 66px;
  right: 20px;
  z-index: 30;
  padding: 10px 16px;
}

/* ---- Scroll reveal ---- */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .8s ease, transform .8s ease; }
.reveal.revealed { opacity: 1; transform: none; }
.reveal.d1 { transition-delay: .1s; }
.reveal.d2 { transition-delay: .2s; }
.reveal.d3 { transition-delay: .3s; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .hero .blob { animation: none; }
  .soon-badge::before { animation: none; }
  /* Drift off, but the themes must stay reachable, so the rows become plain
     horizontal scrollers rather than a frozen crop of the first four. */
  .theme-track { animation: none; }
  .theme-row { overflow-x: auto; }
}

/* ==========================================================================
   Gate (index.html)
   ========================================================================== */
.gate-body { min-height: 100vh; display: flex; flex-direction: column; }
.gate-header { padding: 24px 32px; display: flex; align-items: center; gap: 12px; }
.gate-main { flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 20px 80px; }
.gate-card {
  background: var(--card);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  max-width: 640px;
  width: 100%;
  padding: 48px;
}
.gate-card h1 { font-size: 28px; letter-spacing: -0.3px; margin-bottom: 8px; }
.gate-card .tag {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 16px;
}
.gate-statement {
  font-size: 14px;
  line-height: 1.7;
  color: rgba(0, 0, 0, .72);
  background: var(--page);
  border-radius: var(--radius);
  padding: 20px;
  margin: 20px 0 24px;
  max-height: 300px;
  overflow-y: auto;
}
.gate-statement p + p { margin-top: 10px; }
/* What the click stands for, kept outside the scrollable statement box so it is
   always visible next to the button (the click is the only affirmative act). */
.gate-confirm { font-size: 14px; line-height: 1.6; color: var(--faint); margin-bottom: 24px; }
.gate-footer { padding: 100px 24px 56px; text-align: center; font-size: 13px; color: var(--faint); }
/* Same tile size and spacing as the site footer; only the colours change,
   because the gate sits on --page instead of a white footer. */
.gate-footer .socials { margin-bottom: 32px; }
.gate-footer .socials a { background: var(--card); color: var(--ink); }

/* ==========================================================================
   Hub (funds.html)
   ========================================================================== */
.hub-hero { padding: 200px var(--gutter) 60px; text-align: center; background: #FFF; }
.hub-grid-section { padding: 60px var(--gutter) 140px; }
.hub-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  max-width: 1028px;
  margin: 0 auto;
}
.hub-tile {
  background: var(--card);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
  padding: 40px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  transition: transform .22s ease, box-shadow .22s ease;
  position: relative;
  overflow: hidden;
}
.hub-tile::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 5px;
  background: var(--tile-accent, var(--accent));
  opacity: 0;
  transition: opacity .22s ease;
}
.hub-tile:hover { transform: translateY(-6px); box-shadow: 0 2px 6px rgba(0,0,0,.05), 0 24px 56px rgba(0,0,0,.12); }
.hub-tile:hover::before { opacity: 1; }
.hub-tile img { width: 64px; height: 64px; border-radius: 15px; }
.hub-tile .name { font-family: var(--font-display); font-weight: 700; font-size: 22px; }
.hub-tile .desc { font-size: 15px; line-height: 1.65; color: rgba(0, 0, 0, .62); flex: 1; }
.hub-tile .go { font-weight: 500; font-size: 14px; color: var(--tile-accent, var(--accent)); }
.hub-tile[data-accent="btc"]      { --tile-accent: #F7931A; }
.hub-tile[data-accent="usd"]      { --tile-accent: #32B85F; }
.hub-tile[data-accent="digital"]  { --tile-accent: #3376B9; }
.hub-tile[data-accent="emerging"] { --tile-accent: #7462D1; }

/* ---- Talk-to-us bar (funds hub) -------------------------------------------
   Both contact channels, on the page and always visible, so a visitor
   interested in several funds, or none in particular, can reach us without
   having to pick one first. The hub carries this instead of a header
   "Contact us" button; the fund pages keep their full Contact section. */
.talkbar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 11px;
  padding: 26px 20px 24px;
  text-align: center;
  background: rgba(255, 255, 255, .82);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-top: 1px solid rgba(0, 0, 0, .06);
}
.talkbar .k {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .34);
}
.talk-row { display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap; }
.talk-q { font-size: 14px; color: rgba(0, 0, 0, .62); }
.talkbar .btn { padding: 9px 18px; font-size: 13px; }
.talk-mail {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(0, 0, 0, .25);
}
.talk-mail:hover { text-decoration-color: var(--ink); }
/* Second instance, straight off the stage. The section under it is pure white, so
   the base bar's near-white wash would dissolve into it and the CTA would read as
   the top of the "Who is DCY" story: hold the page tone and rule both edges
   instead, so it stands as its own band between the hero and the story. */
.talkbar--stage {
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom: 1px solid rgba(0, 0, 0, .06);
}
@media (max-width: 900px) {
  .talkbar { gap: 14px; padding: 30px 20px 26px; }
  .talk-row { gap: 14px; }
}

/* Draft-content badge (Emerging Tech + unverified figures) */
.draft-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #FEF3C7;
  color: #92400E;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  padding: 6px 12px;
  border-radius: 999px;
  margin-bottom: 20px;
}

/* Pre-launch status pill (Emerging Tech hero). Same object as .draft-badge but
   accent-tinted rather than amber: this one is a fact about the fund shown to
   investors, not an internal warning about unverified copy. Sits over the hero
   video, so the fill is opaque: the .inner halo behind it is not enough on its
   own to hold a 12px label at this weight. The dot pulses; it is the only
   moving thing in the copy block, and it stops under reduced-motion. */
.soon-badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: #FFF;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: 7px 15px;
  border-radius: 999px;
  margin-bottom: 24px;
}
.soon-badge::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  animation: soon-pulse 2.4s ease-in-out infinite;
}
@keyframes soon-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* ==========================================================================
   HUB STORY SECTIONS: "Who is DCY" + "How to allocate"
   --------------------------------------------------------------------------
   Two below-the-fold sections carried by the funds hub, sourced from
   Additional_Docs/Who_DCY.pdf and Additional_Docs/Allocation_DCY.pdf.

   Why everything is namespaced (.hubsec-* / .who-* / .alloc-*): the hub ships
   its own <style> block on very generic class names:
   .stage/.pane/.thumb/.field/.hint. A bare .stage here would inherit
   hub-panel styling on that page.

   Why no var(--accent): the hub's body carries data-fund of whichever fund is
   on stage, so --accent shifts as the stage advances. These sections speak for
   DCY as a manager rather than for one fund and must read identically however
   the stage lands, so they use fixed neutrals plus the three fund colours,
   never the page accent.

   A shorter variant (figures + pillars + donuts, without the chronology and the
   four-regime strip) was trialled against this one and dropped: the regime
   strip is the argument the profile splits rest on, so cutting it left the
   donuts unexplained. Both sections are now unconditional; there is no
   variant switch. See README "Hub story sections".

   Both sections are now built from the same devices: hairlines, a left-aligned
   axis, oversized display numerals, tabular figures, and no card, radius or
   shadow anywhere. They differ by ground (paper for the ledger, page grey for
   the analytical plate) and by structure, not by design language. The opening
   spread is literally shared: .who-open and .alloc-open are the same rules.
   ========================================================================== */
.hubsec {
  position: relative;
  z-index: 5;
  padding: 104px var(--gutter) 96px;
  background: var(--page);
  border-top: 1px solid rgba(0, 0, 0, .06);
}
.hubsec > .container { max-width: 1180px; }
/* Paper ground for the ruled "Who is DCY" register, so its hairlines read as a
   document rather than as dividers floating on the page grey, and so the
   change of treatment between it and the analytical allocation section below
   is explained by a change of ground. */
.hubsec--paper { background: var(--card); }

.hubsec-fine {
  max-width: 1028px;
  margin: 40px auto 0;
  font-size: 12px;
  line-height: 1.7;
  color: var(--faint);
}

/* ==========================================================================
   WHO IS DCY: editorial ledger
   --------------------------------------------------------------------------
   Rewritten from a centred head + three shadowed cards + a five-column pastel
   rail. That arrangement read as generic template output, and it buried the
   one claim only DCY can make, an unbroken fifteen-year record, in a small
   widget at the very bottom.

   The record is now the structure of the section: an opening spread, a figures
   band ruled like a row in a fund report, the two narrative pillars as margin
   notes, then the five phases as a vertical chronology.

   The devices are hairlines, left alignment, oversized display numerals and
   tabular figures. There is deliberately no card, no border-radius and no
   box-shadow anywhere in this section; those were the generic tells. The one
   --era colour per phase is still the brochure's own band colour, carried on a
   continuous vertical spine instead of five pastel dots.

   Scoped classes rather than generic .hubsec-* ones, because the hub page ships
   its own <style> block on very generic names. See README "Hub story sections".
   ========================================================================== */

/* ---- Opening spread, shared with the allocation section below -------------
   Both hub sections open the same way, so these four rules carry both sets of
   class names instead of being duplicated. Edit here and both sections move. */
.who-open,
.alloc-open {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  column-gap: 72px;
  align-items: end;
  padding-bottom: 52px;
}
/* Eyebrow spans both columns and trails a hairline to the right edge: the
   masthead rule that sets the section's left-aligned axis. */
.who-eyebrow,
.alloc-eyebrow {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 34px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .42);
}
.who-eyebrow::after,
.alloc-eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(0, 0, 0, .14);
}
.who-h2,
.alloc-h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(38px, 4.8vw, 62px);
  line-height: 1.02;
  letter-spacing: -.035em;
  color: var(--ink);
}
.who-lead,
.alloc-lead {
  font-size: 16.5px;
  line-height: 1.78;
  color: rgba(0, 0, 0, .6);
  padding-bottom: 6px;
}

/* ---- Figures band ---- */
.who-figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid rgba(0, 0, 0, .16);
  border-bottom: 1px solid rgba(0, 0, 0, .16);
}
.who-fig {
  padding: 36px 30px 34px;
  border-left: 1px solid rgba(0, 0, 0, .1);
}
.who-fig:first-child { border-left: 0; padding-left: 0; }
.who-fig-v {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(42px, 4.3vw, 58px);
  line-height: 1;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}
.who-fig-k {
  margin-top: 16px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .45);
}
.who-fig-k sup { font-size: 9px; }

/* ---- The two pillars, as margin notes ------------------------------------
   --who-margin is the shared left-margin width for the notes and the
   chronology: both hang off the same axis, so the section reads as one
   register rather than two unrelated blocks. */
.who-notes {
  --who-margin: 148px;
  display: grid;
  row-gap: 36px;
  margin-top: 62px;
}
.who-note {
  display: grid;
  grid-template-columns: var(--who-margin) minmax(0, 1fr);
  column-gap: 40px;
}
.who-note-k {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .42);
  padding-top: 6px;
}
.who-note-t {
  max-width: 68ch;
  font-size: 16px;
  line-height: 1.8;
  color: rgba(0, 0, 0, .66);
}

/* ---- The chronology ------------------------------------------------------
   Six phases. The years and the boundaries are measured off the brochure
   timeline's axis rather than estimated: 2010 · 2010–2014 · 2014–2018 ·
   2018–2024 · 2024– · 2026–. Consecutive .who-era::before segments butt
   together into one continuous vertical line that changes colour at each
   boundary, as the horizontal rail does in the brochure. The last segment
   fades out instead of stopping: that phase is still running. The last two
   phases both run to today — they overlap rather than hand off, which the
   year labels carry; the spine stays one unbroken line. */
.who-eras {
  --who-margin: 148px;
  --spine: 2px;
  list-style: none;
  margin-top: 76px;
  border-top: 1px solid rgba(0, 0, 0, .16);
}
.who-era {
  position: relative;
  display: grid;
  grid-template-columns: var(--who-margin) minmax(0, 1fr);
  column-gap: 40px;
  padding: 26px 0;
  border-bottom: 1px solid rgba(0, 0, 0, .08);
}
.who-era::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--who-margin);
  width: var(--spine);
  background: var(--era);
}
.who-era:last-child::before {
  background: linear-gradient(to bottom, var(--era) 42%, transparent);
}
/* Flat square marker on the spine, aligned to the year's cap height. */
.who-era::after {
  content: "";
  position: absolute;
  top: 30px;
  left: calc(var(--who-margin) - 3.5px);
  width: 9px;
  height: 9px;
  background: var(--era);
}
.who-era-y {
  text-align: right;
  padding-right: 28px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  color: rgba(0, 0, 0, .42);
  white-space: nowrap;
}
/* Wrapper for the second column, so the name and the prose stack as one cell
   rather than becoming two grid items. */
.who-era-body { display: block; min-width: 0; }
.who-era-n {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -.012em;
}
.who-era-t {
  display: block;
  margin-top: 9px;
  max-width: 68ch;
  font-size: 14px;
  line-height: 1.7;
  color: rgba(0, 0, 0, .56);
}
/* Left-aligned on the section's axis; .hubsec-fine centres its own block. The
   measure is released to the full container so the fine print runs the same
   length as the closing hairline above it, the way a prospectus footnote spans
   its text block, instead of stopping short of the rule mid-column. */
.who-fine { max-width: none; margin-left: 0; margin-right: 0; }

/* ==========================================================================
   HOW TO ALLOCATE: analytical plate
   --------------------------------------------------------------------------
   Rewritten from four shadowed regime cards plus three donut cards. Two
   problems: the brochure's own centrepiece (a single price path running
   through all four regimes) was missing, so the four "stages" were asserted
   rather than shown; and the card grids were the same generic tell the
   "Who is DCY" section was rebuilt to remove. The donuts themselves stayed,
   the deck's form and the right one for a three-way split, but they lost the
   cards, the shadows, the centred heads and the legend repeated three times.

   It is now two figures on one axis, in the same register as the ledger above:
   hairlines, oversized numerals, tabular figures, no card, radius or shadow.

     .cyc   the cycle. A stylised price path across four tinted bands, the four
            phases read beneath it, and a 3-fund x 4-phase matrix underneath.
     .prof  the three investor profiles, each a donut on the shared axis with
            its three percentages ruled beside it.

   --alloc-margin is the same left-margin axis as the ledger's --who-margin, so
   the chart's plot area, the phase columns, the matrix and the profile rings all
   hang off one line down the page.

   ALIGNMENT: .cyc-plot-row / .cyc-phases / .cyc-mx are three separate grids
   sharing `--alloc-margin + 4 equal columns` and carrying NO column gap. That
   is what lets the SVG's band boundaries at 25/50/75% land exactly on the
   column edges. Introducing a column-gap anywhere breaks the alignment.

   Fund colours are fixed hexes, never var(--accent) (see the header note).
   Their green and orange sit at ΔE 7.1 under protanopia, the 6–8 floor band,
   so every mark that carries a fund is also labelled with the fund's name.
   ========================================================================== */
.cyc, .prof { --alloc-margin: 148px; }

/* ---- The cycle: plot ------------------------------------------------------
   preserveAspectRatio="none" lets the plot fill whatever width the column band
   gives it while keeping 1 SVG unit = 1px vertically; every stroke carries
   vector-effect: non-scaling-stroke so the horizontal squeeze cannot thicken
   the line. That is also why there are no arrowheads or circular markers
   inside the SVG, where they would render as ellipses; the trend arrows are HTML
   siblings layered over it instead (see .cyc-trends). */
.cyc-plot-row {
  display: grid;
  grid-template-columns: var(--alloc-margin) repeat(4, minmax(0, 1fr));
  margin-top: 8px;
}
.cyc-cap {
  grid-column: 1;
  align-self: end;
  padding: 0 24px 16px 0;
}
.cyc-cap-k {
  display: block;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink);
}
.cyc-cap-t {
  display: block;
  margin-top: 7px;
  font-size: 11.5px;
  line-height: 1.55;
  color: rgba(0, 0, 0, .42);
}
.cyc-plot { grid-column: 2 / -1; position: relative; }
.cyc-svg { display: block; width: 100%; height: 250px; pointer-events: none; }

.cyc-bands rect { transition: opacity .3s ease; }
.cyc-bands [data-b="1"] { fill: rgba(169, 178, 126, .17); }
.cyc-bands [data-b="2"] { fill: rgba(89, 181, 124, .15); }
.cyc-bands [data-b="3"] { fill: rgba(224, 169, 78, .15); }
.cyc-bands [data-b="4"] { fill: rgba(212, 120, 111, .15); }
/* The range boxes sit on top of the band wash, so each regime reads as two
   tints: where the price is, and where it is not. Same hue, same alpha again;
   the doubling is what makes the box edge visible without a stroke. */
.cyc-zones rect { transition: opacity .3s ease; }
.cyc-zones [data-b="1"] { fill: rgba(169, 178, 126, .17); }
.cyc-zones [data-b="2"] { fill: rgba(89, 181, 124, .15); }
.cyc-zones [data-b="3"] { fill: rgba(224, 169, 78, .17); }
.cyc-zones [data-b="4"] { fill: rgba(212, 120, 111, .15); }
.cyc-rules line { stroke: rgba(0, 0, 0, .10); stroke-width: 1; vector-effect: non-scaling-stroke; }
.cyc-axis { stroke: rgba(0, 0, 0, .22); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* fill and vector-effect are on the <path> in the markup, because neither property
   inherits into a <use> instance. Stroke and opacity do. */
.cyc-line use {
  stroke: rgba(0, 0, 0, .8);
  stroke-width: 1.7;
  stroke-linejoin: round;
  stroke-linecap: round;
  transition: opacity .3s ease;
}
/* ---- The cycle: trend arrows ---------------------------------------------
   HTML rather than SVG, for the arrowheads (see the note in funds.html). The
   shaft is a border on the span, the head a chevron rotated 45° on ::after, so
   one element is one arrow. `left` and `top` are percentages of the plot, and
   the SVG maps 250 user units to its 250px height 1:1, so a `top` of 61% is
   also y=153 in the path's own coordinates; that is how these were placed
   against the line. The two sloped arrows rotate about their left edge, which
   makes `width` the arrow's length rather than its horizontal reach; the extra
   width on 2 and 4 restores the reach that cos(angle) takes away. */
.cyc-trends { position: absolute; inset: 0; pointer-events: none; }
.cyc-trends span {
  position: absolute;
  height: 0;
  border-top: 1.5px solid var(--regime);
  transform-origin: left center;
  opacity: .8;
  transition: opacity .3s ease;
}
.cyc-trends span::after {
  content: "";
  position: absolute;
  right: -1px;
  top: 0;
  width: 6px;
  height: 6px;
  border-top: 1.5px solid var(--regime);
  border-right: 1.5px solid var(--regime);
  transform: translateY(-50%) rotate(45deg);
}
.cyc-trends [data-b="1"] { --regime: #A9B27E; left:  2.4%; top: 61%; width: 20.5%; }
/* 2 is the short one on purpose: its price line crosses the band diagonally,
   so a full-width arrow at the trend's own angle lands on the line and gets
   eaten by the line's texture. Held above it instead, in the upper-left of the
   range box, where the band is empty. */
.cyc-trends [data-b="2"] { --regime: #59B57C; left: 27.5%; top: 52%; width: 18%; transform: rotate(-31deg); }
.cyc-trends [data-b="3"] { --regime: #E0A94E; left: 52.4%; top: 62%; width: 20.5%; }
.cyc-trends [data-b="4"] { --regime: #D4786F; left: 77.4%; top: 46%; width: 22%; transform: rotate(21deg); }

/* Hover targets: one per band, stopping at the baseline. Deliberately inert
   spans: nothing is hidden without them, so there is nothing to focus. */
.cyc-hit { position: absolute; top: 0; bottom: 14px; width: 25%; }
.cyc-hit[data-b="1"] { left: 0; }
.cyc-hit[data-b="2"] { left: 25%; }
.cyc-hit[data-b="3"] { left: 50%; }
.cyc-hit[data-b="4"] { left: 75%; }

/* ---- The cycle: the four phases, as the plot's own x-axis ---------------- */
.cyc-phases {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-left: var(--alloc-margin);
  list-style: none;
}
/* Consecutive 2px rules butt together into one continuous four-colour bar
   under the plot, and each vertical hairline sits on a band boundary. */
.cyc-phase {
  padding: 18px 22px 26px 20px;
  border-top: 2px solid var(--regime);
  transition: opacity .3s ease;
}
.cyc-phase + .cyc-phase { border-left: 1px solid rgba(0, 0, 0, .1); }
.cyc-phase-h {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -.02em;
  color: var(--ink);
}
.cyc-phase-no {
  font-size: 40px;
  line-height: .9;
  letter-spacing: -.05em;
  font-variant-numeric: tabular-nums;
  color: var(--regime-ink);
}
.cyc-phase-d {
  margin-top: 12px;
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--regime-ink);
}
.cyc-phase-t {
  margin-top: 11px;
  font-size: 13px;
  line-height: 1.68;
  color: rgba(0, 0, 0, .56);
}

/* ---- The cycle: the fund matrix ---------------------------------------- */
.cyc-mx-wrap { overflow-x: auto; }
.cyc-mx {
  width: 100%;
  min-width: 470px;
  table-layout: fixed;
  border-collapse: collapse;
  border-top: 1px solid rgba(0, 0, 0, .22);
  border-bottom: 1px solid rgba(0, 0, 0, .22);
}
.cyc-mx-c1 { width: var(--alloc-margin); }
.cyc-mx-cap {
  caption-side: top;
  text-align: left;
  padding: 30px 0 12px;
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .38);
}
/* The phase columns are already labelled by the axis row above on wide
   screens; the numeric head only earns its keep once that row has stacked. */
.cyc-mx-head { display: none; }
.cyc-mx tbody tr:not(:last-child) > * { border-bottom: 1px solid rgba(0, 0, 0, .08); }
.cyc-mx-f {
  text-align: left;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: rgba(0, 0, 0, .78);
  padding: 13px 24px 13px 0;
}
.cyc-mx-f .alloc-dot { margin-right: 10px; }
.cyc-mc {
  padding: 13px 20px;
  border-left: 1px solid rgba(0, 0, 0, .1);
  transition: opacity .3s ease;
}
/* A neutral wash, not a fund tint: it marks "this is the phase's strongest
   fit" without adding a fifth colour to a row that already has one. */
.cyc-mc[data-trend="up2"] { background: rgba(0, 0, 0, .035); }
.cyc-mc[data-trend="up2"] .cyc-w { color: var(--ink); font-weight: 600; }
/* One arrow glyph, rotated per state, so the four states read as one scale:
   steepest = strongest fit for the regime, flat = no meaningful direction,
   down = loses value. Every cell is worded as well as drawn. */
.cyc-arw { display: inline-block; width: 15px; height: 15px; margin-right: 10px; vertical-align: middle; color: var(--trend-c); }
.cyc-arw svg { display: block; width: 100%; height: 100%; transform: rotate(var(--trend-r)); }
.cyc-w { vertical-align: middle; font-size: 11.5px; font-weight: 500; color: rgba(0, 0, 0, .58); }
.cyc-mc[data-trend="up2"]  { --trend-c: #1E7A42; --trend-r: -45deg; }
.cyc-mc[data-trend="up1"]  { --trend-c: #1E7A42; --trend-r: -22deg; }
.cyc-mc[data-trend="flat"] { --trend-c: #C2882B; --trend-r: 0deg; }
.cyc-mc[data-trend="down"] { --trend-c: #B3261E; --trend-r: 38deg; }

/* ---- The cycle: hover focus ----------------------------------------------
   The dim rules fire whenever data-focus is set, and the four restore
   selectors below win on source order, which only works while every dim rule
   stays at exactly (0,3,0) specificity, the same as a restore. That is what
   :where() is doing here: it groups the two plot layers without adding a class
   to the count. Adding a plain descendant class to any dim selector would
   outrank the restores and the focused phase would dim along with the rest.
   Everything is fully legible with no focus set, so this only ever sharpens. */
.cyc[data-focus] :where(.cyc-bands, .cyc-zones, .cyc-line, .cyc-trends) [data-b] { opacity: .22; }
.cyc[data-focus] .cyc-phase { opacity: .4; }
.cyc[data-focus] .cyc-mc { opacity: .34; }
.cyc[data-focus="1"] [data-b="1"],
.cyc[data-focus="2"] [data-b="2"],
.cyc[data-focus="3"] [data-b="3"],
.cyc[data-focus="4"] [data-b="4"] { opacity: 1; }

/* ---- The three investor profiles ---------------------------------------- */
.prof { margin-top: 72px; --ring: 172px; }
.prof-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 40px;
  flex-wrap: wrap;
  padding-bottom: 18px;
  border-bottom: 1px solid rgba(0, 0, 0, .22);
}
/* The figure's own title and subtitle, in the same relationship the page uses at
   full size (.h2 over .sub): both in the display face, the subtitle a step down
   and lighter rather than a different family. The old pair sat at 12/11.5px with
   the subtitle in body Inter, which put the head of the figure below the type it
   introduces — .prof-n is 19px and .prof-t 13.5px directly underneath. */
.prof-cap-k {
  display: block;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--ink);
}
.prof-cap-t {
  display: block;
  margin-top: 6px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  color: rgba(0, 0, 0, .5);
}
.prof-legend { list-style: none; display: flex; flex-wrap: wrap; gap: 10px 22px; }
.prof-legend li { display: flex; align-items: center; gap: 9px; font-size: 12px; color: rgba(0, 0, 0, .6); }

/* The three profiles side by side, in the same device as the four phase columns
   above them: equal columns hanging off --alloc-margin, separated by vertical
   hairlines, closed at the top by the figure head's own rule. Same padding as
   .cyc-phase, so a profile name sits on the same left edge as the phase name
   above it and the whole plate reads as one strip of columns.

   Not the deck's version of this slide, which is three shadowed cards with
   centred heads; that grid is the generic tell this section was rebuilt to
   remove. Below 1080px the strip becomes three stacked ledger rows instead:
   three columns of prose stop being wide enough to set at around 26ch. */
.prof-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-left: var(--alloc-margin);
}
.prof-row { padding: 30px 22px 4px 20px; }
.prof-row + .prof-row { border-left: 1px solid rgba(0, 0, 0, .1); }
.prof-n {
  margin-bottom: 22px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -.02em;
}
/* The ring. r=52 in a 120 box, so C = 2π·52 = 326.726 and one percent of the
   circle is 3.2673 units. Every segment is a full circle wearing

     stroke-dasharray:   (pct × 3.2673 − 2.2)   999
     stroke-dashoffset:  −(cumulative % × 3.2673)

   999 is any length past C, so the dash pattern cannot repeat; the 2.2 is the
   gap that lets the page ground show between segments, the same spacer the
   stacked bars used; and rotate(-90) in the markup moves the 0% mark from
   3 o'clock to 12. The values are hard-set as attributes rather than derived in
   calc(), because calc() inside stroke-dasharray is the one part of this that
   is not safe everywhere. Butt caps (the default) keep the gaps square, in the
   same flat register as the rest of the section: no rounded ends anywhere.

   No hover layer, deliberately: every segment's name and value is already on
   screen beside the ring, so a tooltip would have nothing to reveal. */
.prof-ring {
  display: block;
  width: 100%;
  max-width: var(--ring);
  height: auto;
  fill: none;
}
.prof-arc { stroke: var(--fund-c); stroke-width: 10; }

/* The numbers the ring cannot carry: 30 against 30 inside one profile, and the
   progression between the three. Hairline rows rather than a box, percentages
   right-aligned on the column's own edge so they read down the page too. */
.prof-vals { margin-top: 26px; }
.prof-val { display: flex; align-items: baseline; gap: 10px; padding: 7px 0; }
.prof-val + .prof-val { border-top: 1px solid rgba(0, 0, 0, .07); }
.prof-val dt {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  font-size: 12.5px;
  color: rgba(0, 0, 0, .72);
}
.prof-val dd {
  flex: none;
  margin-left: auto;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
/* The 0% row. Muted, and its swatch is hollow: a filled fund colour would claim
   an allocation that is not there. */
.prof-val-0 dt, .prof-val-0 dd { color: rgba(0, 0, 0, .42); }
.prof-val-0 .alloc-dot { background: none; box-shadow: inset 0 0 0 1.5px rgba(0, 0, 0, .2); }
.prof-t {
  margin-top: 20px;
  padding-bottom: 4px;
  font-size: 13.5px;
  line-height: 1.7;
  color: rgba(0, 0, 0, .56);
}

/* per-fund swatch and bar colours, shared by every mark in the section */
[data-f="digital"] { --fund-c: #3376B9; --fund-fill: rgba(51, 118, 185, .17); }
[data-f="btc"]     { --fund-c: #F7931A; --fund-fill: rgba(247, 147, 26, .20); }
[data-f="usd"]     { --fund-c: #32B85F; --fund-fill: rgba(50, 184, 95, .17); }
.alloc-dot {
  display: inline-block;
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--fund-c);
  vertical-align: middle;
}

/* ---- The closing statement ----------------------------------------------
   Was a tinted block with a green left border. Now a ruled editorial close on
   the section's own axis: the argument the matrix has just made in full. */
.alloc-close {
  margin-top: 64px;
  padding-top: 40px;
  max-width: 74ch;
  border-top: 1px solid rgba(0, 0, 0, .22);
  font-family: var(--font-display);
  font-size: clamp(19px, 2vw, 26px);
  font-weight: 500;
  line-height: 1.46;
  letter-spacing: -.022em;
  color: rgba(0, 0, 0, .52);
}
.alloc-close strong { color: var(--ink); font-weight: 700; }

@media (max-width: 1080px) {
  /* Narrow the shared left margin; the axis holds, the prose gets the room. */
  .who-notes, .who-eras { --who-margin: 116px; }
  .who-note, .who-era { column-gap: 30px; }
  .who-era-y { padding-right: 22px; }
  .cyc, .prof { --alloc-margin: 116px; }

  /* The strip becomes three stacked ledger rows: at this width a third of the
     plate is about 26ch, which is too narrow to set the profile descriptions.
     Each row keeps the pairing that matters, the ring beside its own numbers,
     with the name over the pair and the prose beneath it. */
  .prof { --ring: 128px; }
  .prof-strip { grid-template-columns: minmax(0, 1fr); margin-left: 0; }
  .prof-row {
    display: grid;
    grid-template-columns: var(--ring) minmax(0, 1fr);
    grid-template-areas: "name name" "ring vals" "text text";
    align-items: center;
    padding: 26px 0;
    border-left: 0;
  }
  .prof-row + .prof-row { border-left: 0; border-top: 1px solid rgba(0, 0, 0, .08); }
  .prof-n { grid-area: name; margin-bottom: 18px; }
  .prof-ring { grid-area: ring; }
  /* Capped, or the value column takes the whole remaining width and each
     percentage ends up an inch of empty ground away from its own label. */
  .prof-vals { grid-area: vals; margin-top: 0; padding-left: 30px; max-width: 320px; }
  .prof-t { grid-area: text; margin-top: 22px; padding-bottom: 0; max-width: 68ch; }

  .cyc-phase { padding: 16px 14px 22px 13px; }
  .cyc-phase-no { font-size: 34px; }
  .cyc-phase-h { font-size: 16.5px; }
  .cyc-mc { padding: 12px 14px; }
  .cyc-arw { margin-right: 8px; }
  .cyc-w { font-size: 11px; }
}

/* The plot keeps its full width all the way down, being the one element that
   still reads when squeezed, but below this width the four phase columns are
   too narrow for prose, so the axis row stacks and the matrix picks up the
   numeric column head that the axis row was providing. */
@media (max-width: 900px) {
  .cyc-plot-row { grid-template-columns: minmax(0, 1fr); }
  .cyc-cap { grid-column: 1; align-self: start; padding: 0 0 18px; }
  .cyc-cap-t { margin-top: 4px; }
  .cyc-plot { grid-column: 1; }
  .cyc-svg { height: 200px; }

  .cyc-phases { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-left: 0; }
  .cyc-phase { padding: 16px 20px 24px 0; }
  .cyc-phase:nth-child(even) { padding-left: 24px; border-left: 1px solid rgba(0, 0, 0, .1); }
  .cyc-phase:nth-child(odd) { border-left: 0; }

  .cyc, .prof { --alloc-margin: 124px; }
  .cyc-mx-head { display: table-row; }
  .cyc-mx-head th {
    padding: 12px 20px;
    text-align: left;
    border-left: 1px solid rgba(0, 0, 0, .1);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: rgba(0, 0, 0, .45);
  }
  .cyc-mx thead > tr > * { border-bottom: 1px solid rgba(0, 0, 0, .08); }

  .prof { margin-top: 56px; }
}

@media (max-width: 809px) {
  .hubsec { padding: 76px var(--gutter) 72px; }
  .cyc-phases { grid-template-columns: minmax(0, 1fr); }
  .cyc-phase { padding: 16px 0 24px; }
  .cyc-phase:nth-child(even) { padding-left: 0; border-left: 0; }
  .cyc-phase-t { max-width: 62ch; }
  .alloc-close { margin-top: 48px; padding-top: 32px; }

  /* Phones: the left margin column has nowhere to go, so the labels move
     above their prose and the whole register hangs off a spine at the far
     left edge instead. The order and the type sizes are unchanged. */
  .who-open, .alloc-open { grid-template-columns: 1fr; row-gap: 22px; padding-bottom: 38px; }
  .who-eyebrow, .alloc-eyebrow { margin-bottom: 26px; }
  .who-lead, .alloc-lead { padding-bottom: 0; }

  .who-figures { grid-template-columns: 1fr; }
  .who-fig { padding: 26px 0; border-left: 0; border-top: 1px solid rgba(0, 0, 0, .1); }
  .who-fig:first-child { border-top: 0; padding-top: 30px; }
  .who-fig-k { margin-top: 12px; }

  .who-notes { margin-top: 46px; row-gap: 30px; }
  .who-note { grid-template-columns: 1fr; }
  .who-note-k { padding-top: 0; margin-bottom: 10px; }

  /* Tighter pills and a narrower edge mask: a 90px fade eats a third of a
     phone screen and hides whole themes rather than softening them. */
  .themes {
    margin-top: 40px;
    gap: 12px;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 36px, #000 calc(100% - 36px), transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 36px, #000 calc(100% - 36px), transparent 100%);
  }
  .theme-set { gap: 10px; padding-right: 10px; }
  .theme { padding: 10px 20px 10px 15px; column-gap: 11px; }
  .theme .e { font-size: 19px; }
  .theme .n { font-size: 14px; }

  .who-eras { --who-margin: 0px; margin-top: 54px; }
  .who-era { grid-template-columns: 1fr; row-gap: 8px; padding: 24px 0 24px 26px; }
  .who-era::before { left: 3px; }
  .who-era::after { top: 27px; left: -1px; }
  .who-era-y { text-align: left; padding-right: 0; }
}

/* Phones. What has to give at this width is label fit rather than layout: a
   matrix cell stops being wide enough to set its label on one line beside its
   mark, so it stacks the label above instead of clipping it; a clipped
   "Digital Dynam" would be worse. The matrix also drops its min-width here so
   it fits without a hidden horizontal scroll, which was cutting its own
   caption. The rings shrink, and their value rows are free to wrap rather than
   overflow (dt carries min-width: 0, dd never shrinks). */
@media (max-width: 560px) {
  .cyc-svg { height: 190px; }
  /* A band is ~85px wide here. The sloped arrows keep a fixed CSS angle while
     the plot keeps a fixed height, so at this width they flatten out of step
     with the line they annotate, and the phase list underneath already says
     Sideways / Rising / Choppy / Falling in words. */
  .cyc-trends { display: none; }
  .cyc-phase-no { font-size: 30px; }
  .cyc-phase-h { font-size: 16px; }

  .cyc, .prof { --alloc-margin: 82px; }
  .cyc-mx { min-width: 0; }
  .cyc-mx-cap { padding-top: 26px; letter-spacing: .12em; }
  .cyc-mx-f { font-size: 11.5px; padding-right: 10px; }
  .cyc-mx-f .alloc-dot { margin-right: 7px; }
  .cyc-mx-head th { padding: 10px 8px; font-size: 11px; }
  .cyc-mc { padding: 10px 8px; }
  .cyc-arw { display: block; width: 13px; height: 13px; margin: 0 0 5px; }
  .cyc-w { font-size: 10px; }

  .prof { --ring: 104px; }
  .prof-cap-k { font-size: 15.5px; }
  .prof-cap-t { font-size: 13px; }
  .prof-vals { max-width: 240px; padding-left: 22px; }
  .prof-val dt { font-size: 11.5px; gap: 8px; }
  .prof-val dd { font-size: 13.5px; }
}

/* 320px. The section's two paddings (.hubsec + .container) leave 240px, which is
   the point at which a five-column matrix stops fitting a word like "Exposed"
   in a cell. Tightened rather than restructured; .cyc-mx-wrap still scrolls, so
   even if a future label outgrows this, nothing is cut off. */
@media (max-width: 360px) {
  .cyc, .prof { --alloc-margin: 64px; }
  .cyc-mx-f { font-size: 11px; padding-right: 6px; }
  .cyc-mx-head th { padding: 10px 5px; }
  .cyc-mc { padding: 10px 5px; }
  .cyc-w { font-size: 9.5px; }

  /* 8px short of holding "Digital Dynamic" on one line at 360, so the ring and
     the gutter give it up. It still wraps rather than clips if a future label
     is longer: dt carries min-width: 0. */
  .prof { --ring: 84px; }
  .prof-vals { padding-left: 12px; }
  .prof-val { gap: 8px; }
  .prof-val dt { font-size: 11px; gap: 7px; }
}

/* ==========================================================================
   Legal pages (privacy / cookies / terms / disclaimer)
   ========================================================================== */
.legal-main { max-width: 820px; margin: 0 auto; padding: 170px var(--gutter) 90px; }
.legal-main .updated {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 500;
  color: var(--muted);
  margin: 12px 0 48px;
}
.legal-main h2 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  margin: 44px 0 14px;
}
.legal-main p { margin-bottom: 14px; color: rgba(0, 0, 0, .72); }
.legal-main p strong { color: var(--ink); }
.legal-main ul { margin: 0 0 14px 22px; color: rgba(0, 0, 0, .72); }
.legal-main li { margin-bottom: 8px; }
.legal-main a { text-decoration: underline; }
.legal-main a:hover { color: var(--accent); }

/* ==========================================================================
   Responsive: mobile (≤ 809px)
   ========================================================================== */
@media (max-width: 809px) {
  :root { --gutter: 20px; }
  .h2 { font-size: 36px; line-height: 1.2; }
  .sub { font-size: 20px; line-height: 1.25; }
  .site-header .bar { padding: 12px 20px 8px; }
  .brand .wordmark { font-size: 17px; }
  .brand img { width: 32px; height: 32px; }
  .brand img.main-logo { width: auto; height: 20px; }
  .brand .fund-label { font-size: 12px; }
  .header-actions .btn, .header-actions .switcher { display: none; }
  .hamburger { display: block; }
  .hero { padding: 140px 18px 80px; }
  /* Same idea as desktop, scaled to the phone: the 220/60 split biases the copy
     (220 - 60) / 2 = 80px below the motif at the hero's centre. 100svh matters
     most here — with 100vh alone, iOS sizes the hero to the *large* viewport
     and the bottom of the copy sits under the URL bar on landing. */
  .hero:has(.hero-video) { padding-top: 220px; padding-bottom: 60px; }
  /* Invariant 2 above: vertical inset must stay under padding-bottom, which is
     60px here rather than 100px, otherwise the halo is clipped at the hero's
     bottom edge and the seam comes back at the founder boundary. */
  .hero-video ~ .inner::before { inset: -50px -120px; }
  .hero .glyph { font-size: 300px; }
  .founder { padding: 80px var(--gutter); }
  .founder .statement { font-size: 20px; line-height: 1.35; }
  .section { padding: 100px var(--gutter) 70px; }
  .facts { padding-top: 80px; }
  .facts-grid { grid-template-columns: 1fr; }
  .form-card { padding: 28px 20px; }
  /* One column, and the A4 page stops growing with it: at full mobile width a
     single sheet is taller than the viewport and pushes the fan off-screen.
     Its caption keeps the full measure, which is the intended asymmetry. */
  /* Counterintuitively the phone needs a *larger* plane: the section is narrow
     and very tall there, and fourteen rows only reach the bottom if the cells
     grow. Tiles end up large relative to the screen, but the form card covers
     most of them anyway. */
  .iso-stage { --iso-w: 2150px; }
  .contact-grid { grid-template-columns: 1fr; }
  .other-grid { grid-template-columns: 1fr; }
  .hub-hero { padding: 150px var(--gutter) 40px; }
  .hub-grid { grid-template-columns: 1fr; }
  .hub-tile { padding: 28px 24px; }
  .site-footer { padding: 56px 24px 32px; }
  .floating-cta { display: none; }
  .gate-card { padding: 32px 24px; }
  .faq-q { font-size: 16px; }
  .legal-main { padding: 130px var(--gutter) 70px; }
  .legal-main .h2 { font-size: 32px; }
}
