/* ════════════════════════════════════════════════════════════════
   blatt.com: Momentum extension layer
   Loads AFTER momentum.css. Momentum owns the tokens; this file owns
   the editorial and dimensional layer that only the founder property
   needs: the vault dial, the portals, the section rail, the reveal
   choreography.

   Rules enforced here, no exceptions:
     · No fully-rounded controls. 10px is the ceiling on anything a
       person can click. Nothing in this file uses 50% or 999px.
     · No italics. Emphasis is weight, colour, size.
     · Russo One display, Inter body.
     · Gold forward on black. Red is absent, there is no urgency to sell
       on a positioning page.

   V1.0.0 · 2026-08-04
   ════════════════════════════════════════════════════════════════ */

:root {
  /* Fluid type scale. Clamped so the display never outgrows a phone
     and never looks timid on a 27 inch monitor. */
  /* Viewport-based fallback only. The hero headline is really sized off
     its own column, further down, because a two column hero means the
     viewport is not what the text has to fit inside. */
  /* Type scale, tightened 2026-08-07.
     Anric's verdict on the first version was "very big, very clunky". He
     was right, and the reason is that every step was set for a landing
     page while these are reading pages. A 46px section heading above
     15px body text is a 3:1 jump; the eye reads that as shouting, and it
     forces card headings up to 25px, which is where the boxes started to
     look clunky.
     Now roughly 1.35 between adjacent steps, which is close enough to a
     minor third to feel deliberate and quiet. The hero still carries the
     page because it is the only thing above 40px. */
  --b-step-hero:  clamp(30px, 3.9vw, 54px);
  --b-step-h2:    clamp(22px, 2.4vw, 32px);
  --b-step-h3:    clamp(15px, 1.15vw, 18px);
  --b-step-lead:  clamp(16px, 1.15vw, 18px);
  --b-step-body:  clamp(14px, 0.95vw, 15.5px);
  --b-step-micro: clamp(10px, 0.72vw, 11.5px);

  /* Rhythm */
  --b-section-y:  clamp(72px, 9vw, 148px);
  --b-gutter:     clamp(20px, 4vw, 56px);
  --b-max:        1240px;
  --b-max-text:   72ch;

  /* Surfaces layered on the Momentum palette */
  /* Pure black. #05050a was the old value and it is why Anric saw "a blue
     background": its blue channel sits above red and green, so the whole
     page carried a cool cast. CLAUDE.md specifies #000 / #1a1a1a surfaces,
     and gold reads warmer against true black than against blue-black. */
  --b-ink:            #000000;
  --b-panel:          linear-gradient(158deg, rgba(250,189,89,0.055) 0%, rgba(0,0,0,0.9) 62%);
  --b-hairline:       rgba(250,189,89,0.16);
  --b-hairline-firm:  rgba(250,189,89,0.34);
  --b-text-ivory:     #ece6da;

  /* Per-site temperature. Overridden on <body data-site="..."> below.
     Both stay inside the Momentum palette. Only warmth and rhythm move. */
  --b-temp-wash:   rgba(250,189,89,0.05);
  --b-temp-edge:   rgba(250,189,89,0.28);
  --b-temp-body:   var(--mv-text-secondary);

  --b-ease:        cubic-bezier(0.22, 0.61, 0.36, 1);
  --b-ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
}

/* Anric: cooler, harder, tighter. Capital and mechanics. */
/* Anric's page used to run cool: a blue-grey wash at rgba(160,170,190) and
   blue-grey body text at #c4c8d0. Between them they tinted every card
   surface and every paragraph, which is most of what read as blue.
   Both are warm now. His page stays distinguishable from Lauralouise's by
   being QUIETER, a lower wash and tighter section rhythm, rather than by
   being a different temperature. Two founders on one brand should not look
   like two brands. */
body[data-site="anric"] {
  --b-temp-wash: rgba(250,189,89,0.042);
  --b-temp-edge: rgba(250,189,89,0.3);
  --b-temp-body: #cdc6b8;
  --b-section-y: clamp(64px, 8vw, 132px);
}

/* Lauralouise: warmer, more open. Identity, story, health. */
body[data-site="lauralouise"] {
  --b-temp-wash: rgba(250,189,89,0.075);
  --b-temp-edge: rgba(250,189,89,0.4);
  --b-temp-body: #d8d0c2;
  --b-section-y: clamp(80px, 10vw, 160px);
}

/* ── Base ──────────────────────────────────────────────────────── */

html { scroll-behavior: smooth; }

body {
  background: var(--b-ink);
  color: var(--b-temp-body);
  font-size: var(--b-step-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* The canonical atmospheric gear texture.
   Anric: "the gear motive is too visible, obscuring the text. That needs to
   get much darker and be barely visible in the background."
   It was at opacity 0.5 while the comment above it claimed it was dialled
   well down, which it plainly was not: at half strength a 1500px photograph
   sits behind body copy and competes with it. 0.09 is the level where it
   registers as depth and stops being a picture.
   LOCAL as of 2026-08-10. It was being fetched from
   assets.cdn.filesafe.space, which was described in this comment as an
   unavoidable external dependency. It was not: the identical file was
   already in this repository at
   capitalmagnet-site/public/assets/6883e0809353ce68d51dab5b.jpeg and is now
   referenced from /assets/brand/gear.jpeg by its existing blob. No page on
   this property loads an image from an outside host any more. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  background-image:
    radial-gradient(ellipse 1100px 800px at 50% -10%, rgba(250,189,89,0.09) 0%, transparent 68%),
    url('/assets/brand/gear.jpeg');
  background-size: auto, 1500px auto;
  background-position: center, 90% 4%;
  background-repeat: no-repeat, no-repeat;
  background-attachment: fixed;
  opacity: 0.09;
  pointer-events: none;
}
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  /* Neutral black, not rgba(5,5,10). Darkened and pulled inward so the
     texture is held to the top of the viewport and everything behind the
     reading column goes to near-black. */
  background: radial-gradient(ellipse 140% 100% at 50% 0%, transparent 26%, rgba(0,0,0,0.97) 100%);
  pointer-events: none;
}

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

a { color: var(--mv-gold); text-decoration: none; }

/* One visible focus treatment for the entire property. */
:focus-visible {
  outline: 2px solid var(--mv-gold);
  outline-offset: 2px;
  border-radius: 4px;
}

.b-skip {
  position: absolute;
  left: 16px;
  top: -60px;
  z-index: 300;
  background: var(--mv-gold);
  color: #000;
  font-family: var(--mv-font-display);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 12px 20px;
  border-radius: 8px;
  transition: top 0.2s var(--b-ease);
}
.b-skip:focus { top: 16px; }

.b-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.b-shell {
  width: 100%;
  max-width: var(--b-max);
  margin: 0 auto;
  padding-inline: var(--b-gutter);
}
.b-shell--text { max-width: calc(var(--b-max-text) + var(--b-gutter) * 2); }

/* ── Type ──────────────────────────────────────────────────────── */

h1, h2, h3, h4, .b-display {
  font-family: var(--mv-font-display);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: 0.005em;
  color: var(--mv-text-primary);
  text-wrap: balance;
}

/* Shimmer is reserved for page titles and the brand mark. Using it on
   every heading would cheapen it to decoration. */
.b-shimmer {
  background: linear-gradient(94deg,
    #ffffff 0%, #fff2d6 18%, var(--mv-gold) 38%,
    #b7822f 52%, var(--mv-gold) 66%, #fff2d6 84%, #ffffff 100%);
  background-size: 260% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: bShimmer 9s linear infinite;
}
@keyframes bShimmer {
  from { background-position: 0% center; }
  to   { background-position: 260% center; }
}

.b-eyebrow {
  font-family: var(--mv-font-display);
  font-size: var(--b-step-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--mv-gold);
  display: flex;
  align-items: center;
  gap: 12px;
}
.b-eyebrow::before {
  content: '';
  width: 26px;
  height: 2px;
  background: linear-gradient(90deg, var(--mv-gold), transparent);
  flex: none;
}

.b-lead {
  font-size: var(--b-step-lead);
  line-height: 1.6;
  color: var(--b-text-ivory);
  max-width: 62ch;
}

.b-prose p { margin-bottom: 1.15em; max-width: var(--b-max-text); }
.b-prose p:last-child { margin-bottom: 0; }
.b-prose strong { color: var(--mv-text-primary); font-weight: 700; }
.b-prose .b-gold { color: var(--mv-gold); font-weight: 600; }

/* Emphasis without slant, per the brand rule. */
.b-emph {
  color: var(--mv-gold);
  font-weight: 700;
  font-style: normal;
}

/* ── Navigation ────────────────────────────────────────────────── */

.b-nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 18px var(--b-gutter);
  background: rgba(0,0,0,0);
  border-bottom: 1px solid transparent;
  transition: background 0.35s var(--b-ease), border-color 0.35s var(--b-ease), padding 0.35s var(--b-ease);
}
.b-nav[data-stuck="true"] {
  background: rgba(0,0,0,0.86);
  backdrop-filter: blur(14px) saturate(1.3);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  border-bottom-color: var(--b-hairline);
  padding-block: 12px;
}

.b-mark {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--mv-font-display);
  font-size: 15px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mv-text-primary);
}
.b-mark svg { width: 26px; height: 26px; flex: none; }
.b-mark .b-mark-sub {
  font-size: 10px;
  letter-spacing: 0.24em;
  color: var(--mv-text-muted);
  display: block;
  margin-top: 3px;
}

.b-nav-links {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 30px);
  list-style: none;
}
.b-nav-links a {
  font-family: var(--mv-font-display);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mv-text-muted);
  padding: 8px 2px;
  border-bottom: 1px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}
.b-nav-links a:hover,
.b-nav-links a:focus-visible { color: var(--mv-gold); border-bottom-color: var(--mv-gold); }
.b-nav-links a[aria-current="page"] { color: var(--mv-text-primary); border-bottom-color: var(--b-hairline-firm); }

@media (max-width: 860px) {
  .b-nav-links { display: none; }
}

/* Scroll progress. A hairline, not a bar. */
.b-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--mv-gold-dark), var(--mv-gold), #fff2d6);
  z-index: 101;
  will-change: transform;
}

/* ── Buttons ───────────────────────────────────────────────────── */

.b-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 28px;
  border: 2px solid transparent;
  border-radius: 10px;          /* ceiling for any control on this site */
  font-family: var(--mv-font-display);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: transform 0.25s var(--b-ease-out), box-shadow 0.25s var(--b-ease), border-color 0.25s, color 0.25s, background 0.25s;
}
.b-btn svg { width: 14px; height: 14px; flex: none; }

.b-btn--gold {
  background: linear-gradient(135deg, #ffd98a 0%, var(--mv-gold) 46%, var(--mv-gold-dark) 100%);
  color: #0a0a06;
  font-weight: 700;
  box-shadow: 0 10px 30px -12px rgba(250,189,89,0.55);
}
.b-btn--gold:hover { box-shadow: 0 18px 44px -14px rgba(250,189,89,0.75); }

/* Specular sweep. Fires on hover only, once, and never loops. */
.b-btn--gold::after {
  content: '';
  position: absolute;
  inset: 0 auto 0 -40%;
  width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,0.55), transparent);
  transform: translateX(-120%);
  pointer-events: none;
}
.b-btn--gold:hover::after,
.b-btn--gold:focus-visible::after { animation: bSweep 0.85s var(--b-ease) 1; }
@keyframes bSweep {
  to { transform: translateX(420%); }
}

.b-btn--line {
  background: rgba(250,189,89,0.04);
  border-color: var(--b-hairline-firm);
  color: var(--mv-gold);
}
.b-btn--line:hover { border-color: var(--mv-gold); background: rgba(250,189,89,0.1); }

.b-btn--quiet {
  padding: 12px 0;
  border: 0;
  border-bottom: 1px solid var(--b-hairline);
  border-radius: 0;
  color: var(--mv-text-muted);
  background: none;
}
.b-btn--quiet:hover { color: var(--mv-gold); border-bottom-color: var(--mv-gold); }

.b-btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
}

/* ── Hero ──────────────────────────────────────────────────────── */

.b-hero {
  position: relative;
  min-height: min(100svh, 900px);
  display: grid;
  align-items: center;
  padding-block: clamp(120px, 16vh, 190px) clamp(64px, 10vh, 110px);
  overflow: hidden;
  isolation: isolate;
}

.b-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.82fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
@media (max-width: 900px) {
  .b-hero-grid { grid-template-columns: 1fr; gap: 44px; }
  .b-hero { min-height: auto; }
}

.b-hero h1 {
  font-size: var(--b-step-hero);
  text-transform: uppercase;
  margin: 22px 0 0;
  /* Last resort only. If a single word still cannot fit, break it rather
     than let it run out of the column and get clipped by the body. */
  overflow-wrap: break-word;
}

/* Size the headline against the COLUMN, not the viewport. A word like
   CREDENTIALS has to fit inside roughly 620px of grid track, and vw
   knows nothing about that track. 11cqi keeps the longest word on this
   property inside its column at every width, in Russo One and in the
   wider fallback face that shows while Russo One is still loading. */
@supports (container-type: inline-size) {
  .b-hero-copy { container-type: inline-size; }
  .b-hero h1 { font-size: clamp(32px, 11cqi, 88px); }
}
.b-hero h1 .b-line { display: block; }
.b-hero .b-lead { margin-top: 26px; }
.b-hero .b-btn-row { margin-top: 38px; }

/* Particle field. Sits behind the dial, in front of the page texture. */
.b-hero-canvas {
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.55;
  pointer-events: none;
}

/* ── The vault dial ────────────────────────────────────────────── */
/* Four SVG plates at different depths under one 3D transform. The
   pointer tilts the stage, each plate drifts at its own rate, and the
   parallax between plates is what sells the depth. Faceted geometry
   throughout, because round is a bug in this brand. */

.b-dial {
  position: relative;
  width: min(100%, 540px);
  aspect-ratio: 1;
  margin-inline: auto;
  perspective: 1400px;
  perspective-origin: 50% 44%;
}

.b-dial-stage {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: transform 0.5s var(--b-ease-out);
  will-change: transform;
}

.b-plate {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}
.b-plate svg { width: 100%; height: 100%; overflow: visible; }
.b-plate path,
.b-plate polygon,
.b-plate line { vector-effect: non-scaling-stroke; }

.b-plate--outer { transform: translateZ(-90px); animation: bSpin 108s linear infinite; }
.b-plate--mid   { transform: translateZ(-24px); animation: bSpinRev 76s linear infinite; }
.b-plate--inner { transform: translateZ(46px);  animation: bSpin 44s linear infinite; }
.b-plate--core  { transform: translateZ(104px); }

/* from and to must carry the SAME transform function list, otherwise the
   browser falls back to matrix interpolation and a 360 degree turn
   resolves to the identity matrix, meaning nothing appears to move. */
@keyframes bSpin {
  from { transform: translateZ(var(--z, 0px)) rotate(0deg); }
  to   { transform: translateZ(var(--z, 0px)) rotate(360deg); }
}
@keyframes bSpinRev {
  from { transform: translateZ(var(--z, 0px)) rotate(0deg); }
  to   { transform: translateZ(var(--z, 0px)) rotate(-360deg); }
}

.b-plate--outer { --z: -90px; }
.b-plate--mid   { --z: -24px; }
.b-plate--inner { --z: 46px; }

/* Gold rim light behind the mechanism. */
.b-dial::before {
  content: '';
  position: absolute;
  inset: 14%;
  background: radial-gradient(ellipse at 50% 46%, rgba(250,189,89,0.28) 0%, rgba(250,189,89,0.06) 46%, transparent 70%);
  filter: blur(26px);
  z-index: -1;
  animation: bBreathe 7s ease-in-out infinite;
}
@keyframes bBreathe {
  0%, 100% { opacity: 0.7; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.06); }
}

.b-core-mark {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  transform: translateZ(1px);
}
.b-core-mark span {
  font-family: var(--mv-font-display);
  font-size: clamp(20px, 3.4vw, 34px);
  letter-spacing: 0.26em;
  text-indent: 0.26em;
  color: var(--mv-gold);
  text-shadow: 0 0 26px rgba(250,189,89,0.5);
}

/* ── Section rail ──────────────────────────────────────────────── */

.b-section {
  position: relative;
  padding-block: var(--b-section-y);
  border-top: 1px solid var(--b-hairline);
  /* The nav is fixed, so an in-page jump would otherwise land with the
     heading tucked underneath it. */
  scroll-margin-top: clamp(72px, 9vh, 100px);
}
.b-section:first-of-type { border-top: 0; }

/* The travelling gold seam on each section top edge, a Momentum motif. */
.b-section::before {
  content: '';
  position: absolute;
  inset: -1px 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, var(--mv-gold) 50%, transparent 100%);
  background-size: 220% 100%;
  animation: bSeam 9s linear infinite;
  opacity: 0.7;
}
.b-section:first-of-type::before { display: none; }
@keyframes bSeam {
  from { background-position: -110% 0; }
  to   { background-position: 210% 0; }
}

.b-section-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(16px, 3vw, 40px);
  align-items: start;
  margin-bottom: clamp(34px, 4.5vw, 62px);
}
.b-section-num {
  font-family: var(--mv-font-display);
  font-size: clamp(13px, 1.2vw, 15px);
  letter-spacing: 0.2em;
  color: var(--mv-gold);
  padding-top: 0.5em;
  position: relative;
}
.b-section-num::after {
  content: '';
  display: block;
  width: 1px;
  height: calc(100% - 2.2em);
  margin: 12px auto 0;
  background: linear-gradient(180deg, var(--b-hairline-firm), transparent);
}
.b-section h2 {
  font-size: var(--b-step-h2);
  text-transform: uppercase;
}
.b-section-head .b-lead { margin-top: 18px; }

@media (max-width: 640px) {
  .b-section-head { grid-template-columns: 1fr; gap: 12px; }
  .b-section-num::after { display: none; }
}

/* ── Panels ────────────────────────────────────────────────────── */

.b-panel {
  position: relative;
  background: var(--b-panel);
  border: 1px solid var(--b-hairline);
  border-radius: 12px;
  padding: clamp(24px, 3vw, 38px);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: border-color 0.3s var(--b-ease), transform 0.4s var(--b-ease-out);
}
.b-panel--wash { background: linear-gradient(158deg, var(--b-temp-wash) 0%, rgba(0,0,0,0.9) 62%); }

.b-grid {
  display: grid;
  gap: clamp(14px, 1.6vw, 22px);
}
.b-grid--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* Rewritten 2026-08-07. Anric: "unsymmetrical boxes", twice, about the
   two sections built on this grid. Two causes, both here.
   FIRST: align-items:start was deliberate and wrong. The old comment
   said it kept a card with no approved blurb from stretching. What it
   actually did was give every card in a row a different height, so
   nothing lined up anywhere on the page. Ragged bottoms across a row of
   boxes is the single loudest way a layout reads as unfinished.
   Cards now stretch, and .b-card pins its own meta row to the bottom
   with margin-top:auto, so the bottom edges AND the last line of every
   card agree. That is what makes a grid look composed rather than
   assembled.
   SECOND: auto-fit chose the column count from available width, so five
   practice areas became 3+2 and eleven ventures became 3+3+3+2, leaving
   a half-empty last row at most widths. Explicit counts per breakpoint
   are predictable, and the last-row rule below centres any remainder so
   an orphan reads as intentional. */
.b-grid--3 { grid-template-columns: 1fr; }
@media (min-width: 620px)  { .b-grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .b-grid--3 { grid-template-columns: repeat(3, 1fr); } }

.b-grid--4 { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }

/* ── Portal cards (the two founders) ───────────────────────────── */

.b-portals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: clamp(18px, 2.4vw, 30px);
  perspective: 1200px;
}

.b-portal {
  position: relative;
  display: block;
  padding: clamp(30px, 3.4vw, 46px);
  border: 1px solid var(--b-hairline);
  border-radius: 12px;
  background:
    linear-gradient(162deg, rgba(250,189,89,0.07) 0%, rgba(0,0,0,0.92) 58%);
  overflow: hidden;
  isolation: isolate;
  transform-style: preserve-3d;
  transform: rotateX(var(--px, 0deg)) rotateY(var(--py, 0deg)) translateZ(0);
  transition: transform 0.45s var(--b-ease-out), border-color 0.35s, box-shadow 0.45s var(--b-ease);
  will-change: transform;
}
.b-portal:hover,
.b-portal:focus-visible {
  border-color: var(--b-hairline-firm);
  box-shadow: 0 30px 70px -34px rgba(250,189,89,0.5);
}

/* Cursor-tracked sheen. Falls back to a static corner glow with no JS. */
.b-portal::before {
  content: '';
  position: absolute;
  inset: -30%;
  z-index: -1;
  background: radial-gradient(420px circle at var(--mx, 30%) var(--my, 0%),
              rgba(250,189,89,0.16) 0%, transparent 62%);
  opacity: 0;
  transition: opacity 0.4s var(--b-ease);
}
.b-portal:hover::before,
.b-portal:focus-visible::before { opacity: 1; }

.b-portal-role {
  font-family: var(--mv-font-display);
  font-size: var(--b-step-micro);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--mv-gold);
}
.b-portal h3 {
  font-size: clamp(27px, 3.4vw, 42px);
  text-transform: uppercase;
  margin: 14px 0 0;
  transform: translateZ(28px);
}
.b-portal p {
  margin-top: 16px;
  color: var(--b-temp-body);
  max-width: 42ch;
  transform: translateZ(14px);
}
.b-portal-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 24px;
  list-style: none;
}
/* Squared tags. Never pills. */
.b-portal-tags li {
  font-family: var(--mv-font-display);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mv-text-muted);
  border: 1px solid var(--b-hairline);
  border-radius: 6px;
  padding: 6px 10px;
}
.b-portal-go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 30px;
  font-family: var(--mv-font-display);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mv-gold);
}
.b-portal-go svg { width: 26px; height: 8px; transition: transform 0.3s var(--b-ease-out); }
.b-portal:hover .b-portal-go svg,
.b-portal:focus-visible .b-portal-go svg { transform: translateX(7px); }

/* ── Framework cards ───────────────────────────────────────────── */

.b-card {
  position: relative;
  padding: clamp(22px, 2.2vw, 30px);
  border: 1px solid var(--b-hairline);
  border-radius: 10px;
  background: linear-gradient(160deg, var(--b-temp-wash) 0%, rgba(0,0,0,0.86) 60%);
  transition: border-color 0.3s, transform 0.4s var(--b-ease-out), background 0.3s;
  height: 100%;
}
.b-card:hover { border-color: var(--b-temp-edge); transform: translateY(-4px); }
.b-card-key {
  font-family: var(--mv-font-display);
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--mv-gold);
  text-transform: uppercase;
}
.b-card h3 {
  font-size: var(--b-step-h3);
  margin: 12px 0 10px;
  text-transform: uppercase;
}
.b-card p { color: var(--b-temp-body); font-size: 15px; }
.b-card-meta {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--b-hairline);
  font-size: 13px;
  color: var(--mv-text-muted);
}

/* Cards whose title is a link out to a venture. */
.b-card h3 a { color: inherit; }
.b-card:hover h3 a { color: var(--mv-gold); }
.b-card-meta a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--mv-text-muted);
  font-family: var(--mv-font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
}
.b-card-meta a svg { width: 20px; height: 7px; transition: transform 0.3s var(--b-ease-out); }
.b-card:hover .b-card-meta a { color: var(--mv-gold); }
.b-card:hover .b-card-meta a svg { transform: translateX(5px); }

/* The core product gets weight without a second colour. */
.b-card--featured {
  border-color: var(--b-hairline-firm);
  background: linear-gradient(160deg, rgba(250,189,89,0.1) 0%, rgba(0,0,0,0.88) 62%);
}

/* ── Hero role line ────────────────────────────────────────────── */
/* Sits under the name. This is the line a search engine and a reader
   both use to work out what the person actually is. */
.b-hero-role {
  margin-top: 16px;
  font-family: var(--mv-font-display);
  font-size: clamp(13px, 1.25vw, 16px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mv-gold);
}

/* ── Fact lists ────────────────────────────────────────────────── */

.b-facts { list-style: none; display: grid; gap: 14px; margin-top: 16px; }
.b-facts li {
  display: grid;
  gap: 3px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--b-hairline);
  font-size: 14px;
}
.b-facts li:last-child { border-bottom: 0; padding-bottom: 0; }
.b-facts strong {
  font-family: var(--mv-font-display);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mv-text-primary);
}
.b-facts span { color: var(--b-temp-body); }

/* ── FAQ ───────────────────────────────────────────────────────── */
/* Open by default. A collapsed answer is still crawlable, but the goal
   here is for an answer engine to quote a visible one. */

.b-faq { display: grid; gap: 2px; }
.b-faq details {
  background: linear-gradient(160deg, var(--b-temp-wash) 0%, rgba(0,0,0,0.82) 60%);
  border: 1px solid var(--b-hairline);
  border-radius: 10px;
  padding: clamp(18px, 2vw, 26px);
}
.b-faq summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.b-faq summary::-webkit-details-marker { display: none; }
.b-faq summary::after {
  content: '';
  margin-left: auto;
  width: 10px; height: 10px;
  border-right: 2px solid var(--mv-gold);
  border-bottom: 2px solid var(--mv-gold);
  transform: rotate(45deg) translateY(-2px);
  transition: transform 0.25s var(--b-ease);
  flex: none;
}
.b-faq details[open] summary::after { transform: rotate(225deg) translateY(-2px); }
.b-faq summary h3 {
  display: inline;
  font-size: var(--b-step-h3);
  letter-spacing: 0.02em;
}
.b-faq summary:focus-visible { outline: 2px solid var(--mv-gold); outline-offset: 4px; }
.b-faq p {
  margin-top: 14px;
  max-width: 76ch;
  color: var(--b-temp-body);
}

/* ── Gallery ───────────────────────────────────────────────────── */
/* Rendered only when real photographs exist. */

.b-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: clamp(12px, 1.5vw, 20px);
}
.b-gallery figure {
  margin: 0;
  border: 1px solid var(--b-hairline);
  border-radius: 10px;
  overflow: hidden;
  background: rgba(0,0,0,0.5);
}
.b-gallery img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}
.b-gallery figcaption {
  padding: 12px 14px;
  font-size: 13px;
  color: var(--mv-text-muted);
  border-top: 1px solid var(--b-hairline);
}

/* ── Pillars ───────────────────────────────────────────────────── */

.b-pillar {
  position: relative;
  padding: clamp(26px, 2.6vw, 36px) clamp(22px, 2.4vw, 30px);
  border: 1px solid var(--b-hairline);
  border-radius: 10px;
  background: rgba(0,0,0,0.5);
  overflow: hidden;
  height: 100%;
  transition: border-color 0.3s, background 0.3s;
}
.b-pillar::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: linear-gradient(90deg, var(--mv-gold), transparent);
  transform: scaleX(0.16);
  transform-origin: 0 50%;
  transition: transform 0.5s var(--b-ease-out);
}
.b-pillar:hover { border-color: var(--b-temp-edge); background: rgba(250,189,89,0.035); }
.b-pillar:hover::after { transform: scaleX(1); }
.b-pillar h3 { font-size: var(--b-step-h3); text-transform: uppercase; margin-bottom: 10px; }
.b-pillar p { font-size: 15px; }

/* ── Stat blocks ───────────────────────────────────────────────── */

.b-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1px;
  background: var(--b-hairline);
  border: 1px solid var(--b-hairline);
  border-radius: 10px;
  overflow: hidden;
}
.b-stat {
  background: rgba(0,0,0,0.9);
  padding: clamp(22px, 2.4vw, 32px);
}
.b-stat-num {
  font-family: var(--mv-font-display);
  font-size: clamp(30px, 4vw, 50px);
  color: var(--mv-gold);
  line-height: 1;
  display: block;
}
.b-stat-label {
  display: block;
  margin-top: 12px;
  font-size: 13px;
  color: var(--mv-text-muted);
  letter-spacing: 0.06em;
}

/* ── Ladder (numbered steps, zones, rings) ─────────────────────── */

.b-ladder { list-style: none; counter-reset: rung; }
.b-ladder li {
  counter-increment: rung;
  position: relative;
  padding: 22px 0 22px clamp(52px, 5vw, 76px);
  border-bottom: 1px solid var(--b-hairline);
}
.b-ladder li:last-child { border-bottom: 0; }
.b-ladder li::before {
  content: counter(rung, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 24px;
  font-family: var(--mv-font-display);
  font-size: 13px;
  letter-spacing: 0.16em;
  color: var(--mv-gold);
  border: 1px solid var(--b-hairline-firm);
  border-radius: 6px;      /* squared. never a circle. */
  padding: 5px 8px;
  line-height: 1;
}
.b-ladder h3 {
  font-size: 17px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}
.b-ladder p { font-size: 15px; max-width: 62ch; }

/* ── Pull quote ────────────────────────────────────────────────── */

.b-quote {
  position: relative;
  padding: clamp(30px, 4vw, 54px) clamp(24px, 3.4vw, 52px);
  border-left: 2px solid var(--mv-gold);
  background: linear-gradient(90deg, rgba(250,189,89,0.07), transparent 72%);
  border-radius: 0 10px 10px 0;
}
.b-quote p {
  font-family: var(--mv-font-display);
  font-size: clamp(19px, 2.3vw, 31px);
  line-height: 1.32;
  color: var(--mv-text-primary);
  text-wrap: balance;
}
.b-quote cite {
  display: block;
  margin-top: 20px;
  font-style: normal;          /* no italics anywhere in this brand */
  font-family: var(--mv-font-display);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mv-gold);
}

/* ── Work / offer rows ─────────────────────────────────────────── */

.b-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 20px 30px;
  align-items: center;
  padding: clamp(20px, 2.2vw, 28px) 0;
  border-bottom: 1px solid var(--b-hairline);
  transition: padding-left 0.35s var(--b-ease-out);
}
.b-row:hover { padding-left: 10px; }
.b-row h3 { font-size: var(--b-step-h3); text-transform: uppercase; }
.b-row p { margin-top: 8px; font-size: 15px; max-width: 58ch; }
.b-row-kind {
  font-family: var(--mv-font-display);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mv-gold);
  margin-bottom: 10px;
  display: block;
}
@media (max-width: 620px) {
  .b-row { grid-template-columns: 1fr; }
}

/* ── Capture form ──────────────────────────────────────────────── */

.b-capture {
  display: grid;
  gap: 16px;
  max-width: 560px;
  margin-top: 28px;
}
.b-capture-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
}
@media (max-width: 520px) {
  .b-capture-line { grid-template-columns: 1fr; }
}
.b-capture input[type="email"] {
  border-radius: 10px;
  border: 1px solid var(--b-hairline-firm);
  padding: 15px 16px;
  font-size: 15px;
}
.b-consent {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 13px;
  color: var(--mv-text-muted);
  line-height: 1.5;
}
.b-consent input[type="checkbox"] {
  width: 17px;
  height: 17px;
  margin-top: 2px;
  flex: none;
  accent-color: var(--mv-gold);
  border-radius: 4px;
}
.b-form-status {
  min-height: 22px;
  font-size: 14px;
  font-weight: 600;
}
.b-form-status[data-state="ok"]  { color: #6ee7a0; }
.b-form-status[data-state="err"] { color: #ffb4c2; }

/* ── Footer ────────────────────────────────────────────────────── */

.b-footer {
  border-top: 1px solid var(--b-hairline);
  padding-block: clamp(48px, 6vw, 80px) 40px;
  background: rgba(0,0,0,0.55);
}
.b-footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(150px, 1fr));
  gap: 36px;
}
/* Those 150px minimums cannot all fit on a phone, and auto-fit will not
   drop below its own minimum, so the tracks have to be restated rather
   than left to collapse on their own. */
@media (max-width: 720px) {
  .b-footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
}
@media (max-width: 460px) {
  .b-footer-grid { grid-template-columns: minmax(0, 1fr); gap: 26px; }
}
.b-footer h4 {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mv-gold);
  margin-bottom: 16px;
}
.b-footer ul { list-style: none; display: grid; gap: 10px; }
.b-footer a { color: var(--mv-text-muted); font-size: 14px; }
.b-footer a:hover { color: var(--mv-gold); }
.b-footer-base {
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--b-hairline);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 26px;
  justify-content: space-between;
  font-size: 12px;
  color: var(--mv-text-dim);
  letter-spacing: 0.06em;
}

/* ── Reveal choreography ───────────────────────────────────────── */
/* One fade, one small rise. Nothing slides in from the edge of the
   screen, because that reads as a template. */

.b-reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.7s var(--b-ease), transform 0.7s var(--b-ease-out);
}
.b-reveal[data-shown="true"] { opacity: 1; transform: none; }
.b-reveal[data-delay="1"] { transition-delay: 0.07s; }
.b-reveal[data-delay="2"] { transition-delay: 0.14s; }
.b-reveal[data-delay="3"] { transition-delay: 0.21s; }
.b-reveal[data-delay="4"] { transition-delay: 0.28s; }

/* No JS: everything must still be visible and readable. */
.no-js .b-reveal { opacity: 1; transform: none; }

/* ════════════════════════════════════════════════════════════════
   THE CREST
   The family mark, lit rather than pasted onto the page. Four layers,
   all CSS except the crest itself:

     halo   a radial key light above and behind it
     sweep  a slow conic pass, which is what makes the glass read as
            glass instead of a flat panel
     glass  the plate the mark sits on, with an inner top highlight
     floor  the reflection, masked to fade out

   The <img> is never filtered, scaled non-uniformly or recoloured, so
   the crest is always the crest. With CSS off it degrades to a plain
   image, which is a correct result rather than a broken one.
   ════════════════════════════════════════════════════════════════ */

.b-crest {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  /* Above the rotating plates. The plates move, this does not, and that
     contrast is the entire depth cue. */
  z-index: 2;
}

/* Two sizes, and the orb is sized with each of them rather than off the
   crest, because the constraint is the MECHANISM: the mid plate spans
   about 74% of the dial, so an orb wider than that crosses a hairline
   that is supposed to read as a bezel in front of it. */
.b-crest--lg { --crest-size: min(58%, 320px); --orb-size: min(72%, 398px); }
.b-crest--md { --crest-size: min(50%, 240px); --orb-size: min(66%, 318px); }

/* The crest is a mark, not a product shot. No plate, no border, no box:
   the box was fighting it. Depth comes from the shadow it casts and the
   light behind it, which is how struck metal actually reads. */
.b-crest-mark {
  position: relative;
  width: var(--crest-size);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  animation: bCrestFloat 9s ease-in-out infinite;
}
/* Layered drop-shadows on the alpha channel: a tight contact shadow, a
   soft cast shadow, then two gold glows at different radii. Nothing here
   touches the artwork's own colour. */
.b-crest-mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter:
    drop-shadow(0 2px 3px rgba(0,0,0,0.7))
    drop-shadow(0 8px 14px rgba(0,0,0,0.85))
    drop-shadow(0 0 34px rgba(250,189,89,0.5))
    drop-shadow(0 0 90px rgba(250,189,89,0.2));
}

.b-crest-halo {
  position: absolute;
  width: calc(var(--crest-size) * 2.5);
  aspect-ratio: 1;
  background: radial-gradient(circle at 50% 42%,
    rgba(255,242,214,0.26) 0%,
    rgba(250,189,89,0.14) 26%,
    rgba(250,189,89,0.04) 48%,
    transparent 68%);
  filter: blur(20px);
  animation: bBreathe 7s ease-in-out infinite;
}

/* The conic pass. One full turn every 22 seconds, heavily blurred and
   clipped to a squared frame, so it reads as a light travelling over a
   surface rather than as a rotating graphic. */
.b-crest-sweep {
  position: absolute;
  /* Same layer as the orb, later in the DOM, so the pass travels OVER
     the glass. Below the orb it is simply invisible. */
  z-index: 1;
  width: calc(var(--crest-size) * 1.55);
  aspect-ratio: 1;
  border-radius: 12px;
  background: conic-gradient(from 0deg,
    transparent 0deg,
    rgba(255,246,226,0.20) 34deg,
    rgba(250,189,89,0.10) 62deg,
    transparent 108deg,
    transparent 240deg,
    rgba(250,189,89,0.13) 292deg,
    transparent 350deg);
  filter: blur(14px);
  opacity: 0.9;
  animation: bSweep 22s linear infinite;
}

/* The reflection. Flipped, faded, and masked so it dies out rather than
   ending on a hard edge. */
.b-crest-floor {
  position: absolute;
  top: 50%;
  margin-top: calc(var(--crest-size) * 0.56);
  width: calc(var(--crest-size) * 0.9);
  height: calc(var(--crest-size) * 0.42);
  background: radial-gradient(ellipse at 50% 0%,
    rgba(250,189,89,0.20) 0%, rgba(250,189,89,0.05) 42%, transparent 74%);
  filter: blur(9px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 92%);
          mask-image: linear-gradient(to bottom, #000 0%, transparent 92%);
}

@keyframes bSweep {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes bCrestFloat {
  0%, 100% { transform: translateY(0)     rotateX(0deg); }
  50%      { transform: translateY(-9px)  rotateX(2.4deg); }
}

/* When the dial is holding the crest, the mechanism steps back: the
   plates lose a little contrast so the mark is unambiguously the
   subject and the machinery is the setting. */
.b-dial--holds .b-plate { opacity: 0.72; }
.b-dial--holds .b-plate--inner { opacity: 0.55; }

/* ════════════════════════════════════════════════════════════════
   THE ORB
   A dark glass globe held inside the faceted plates, with the crest
   struck over the front of it. Gold graticule, gold limb, one key
   light from the upper left.

   ON THE ROUND-CORNER RULE: the house rule is that fully-rounded
   BUTTONS, CHIPS, TAGS and BADGES are a bug. This is a sphere, not a
   control. A globe that is not round is not a globe. Every actual
   control on this site is still 6-10px.

   The layers, back to front:

     body   the sphere itself. Limb darkening and the terminator are
            one radial gradient offset to the light, so the shading is
            physical rather than a vignette pasted on top.
     grid   the graticule. Masked towards the terminator so the lines
            die out where the surface turns away, which is the single
            cue that makes it read as a sphere and not as a circle
            with lines in it.
     spec   the specular highlight. Small, tight, and off-centre.
     limb   the Fresnel rim on the dark side, where a glass sphere
            picks up the light behind it.
   ════════════════════════════════════════════════════════════════ */

.b-orb {
  position: absolute;
  width: var(--orb-size);
  aspect-ratio: 1;
  /* Behind the crest, in front of the halo. The sweep passes over it,
     so the travelling light reads as light on glass. */
  z-index: 1;
  /* One turn. Every derived delay below divides this, so changing the
     tempo of the globe is a one-number edit. */
  --orb-turn: 64s;
  animation: bBreathe 11s ease-in-out infinite;
}

.b-orb-body,
.b-orb-grid,
.b-orb-spec,
.b-orb-limb {
  position: absolute;
  inset: 0;
  border-radius: 50%;
}

.b-orb-body {
  background:
    radial-gradient(circle at 33% 27%,
      rgba(255, 244, 222, 0.26) 0%,
      rgba(250, 189, 89, 0.13) 20%,
      rgba(140, 100, 40, 0.10) 40%,
      rgba(12, 10, 8, 0.66) 72%,
      rgba(3, 3, 3, 0.90) 100%),
    radial-gradient(circle at 50% 50%,
      rgba(0, 0, 0, 0.30) 58%,
      rgba(0, 0, 0, 0.78) 100%);
  box-shadow:
    inset 0 0 0 1px rgba(250, 189, 89, 0.26),
    inset -16px -20px 44px rgba(0, 0, 0, 0.72),
    inset 10px 12px 30px rgba(255, 240, 214, 0.05),
    0 0 46px rgba(250, 189, 89, 0.14);
}

/* The graticule. Hairlines, non-scaling so they stay hairlines at every
   orb size, and masked so they fade into the terminator. */
.b-orb-grid {
  overflow: visible;
  -webkit-mask-image: radial-gradient(circle at 33% 27%,
    rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 0.72) 46%,
    rgba(0, 0, 0, 0.22) 78%, transparent 100%);
          mask-image: radial-gradient(circle at 33% 27%,
    rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 0.72) 46%,
    rgba(0, 0, 0, 0.22) 78%, transparent 100%);
}
.b-orb-grid ellipse,
.b-orb-grid line {
  fill: none;
  vector-effect: non-scaling-stroke;
  stroke: rgba(250, 189, 89, 0.42);
  stroke-width: 0.8;
}
.b-orb-eq   { stroke: rgba(255, 242, 214, 0.62) !important; stroke-width: 1.1 !important; }
.b-orb-axis { stroke: rgba(250, 189, 89, 0.24) !important; stroke-width: 0.8 !important; }

/* Rotation.
   ---------
   Turning the globe is one matrix per meridian and nothing else. From
   the projection derived in render.js, a meridian at longitude L is the
   base ellipse rx = R, ry = R cos TILT under

     matrix(cos L, -sin TILT sin L, 0, 1, 0, 0)

   so as L advances the meridian narrows AND leans, which is what makes
   the graticule read as a sphere rather than as a circle with lines in
   it. TILT is 20 degrees, so sin TILT is 0.34202, and the stops below
   are that formula sampled every 11.25 degrees of longitude.

   The sign on the second term decides which way the meridians lean, and
   it has to agree with the parallels: the pole tilts towards the viewer,
   so the near half of the equator hangs below centre. Flipping it is a
   68 unit error on a 200 unit sphere, which test/orb-geometry.mjs
   measures rather than leaving to the eye.

   The sampling interval is not a taste call. A browser lerps between
   stops, and linear interpolation of a cosine over an interval h is off
   by h squared over 8, so every halving of h buys a factor of four.
   22.5 degree samples came to 1.9 units of error on a 200 unit sphere,
   which at the size the orb is actually drawn is a few pixels of wobble
   in the width of a meridian. 11.25 brings it to 0.48, sub-pixel at any
   size this is used at. test/orb-geometry.mjs measures it rather than
   trusting the arithmetic in this comment.

   The two edge-on crossings are written as 0.004 rather than 0. At
   cos L = 0 the matrix has determinant 0, and a singular transform makes
   the browser drop the shape, so every meridian would blink out at
   exactly the moment it is edge-on and should be a bright vertical line.
   0.004 keeps a sliver, and unlike the 0.01 this started as, it stays
   under the interpolation error instead of becoming the dominant one. */
@keyframes bOrbMeridian {
  0%       { transform: matrix( 1.00000,  0.00000, 0, 1, 0, 0); }
  3.125%   { transform: matrix( 0.98079, -0.06672, 0, 1, 0, 0); }
  6.25%    { transform: matrix( 0.92388, -0.13089, 0, 1, 0, 0); }
  9.375%   { transform: matrix( 0.83147, -0.19002, 0, 1, 0, 0); }
  12.5%    { transform: matrix( 0.70711, -0.24184, 0, 1, 0, 0); }
  15.625%  { transform: matrix( 0.55557, -0.28438, 0, 1, 0, 0); }
  18.75%   { transform: matrix( 0.38268, -0.31599, 0, 1, 0, 0); }
  21.875%  { transform: matrix( 0.19509, -0.33545, 0, 1, 0, 0); }
  25%      { transform: matrix( 0.00400, -0.34202, 0, 1, 0, 0); }   /* edge-on */
  28.125%  { transform: matrix(-0.19509, -0.33545, 0, 1, 0, 0); }
  31.25%   { transform: matrix(-0.38268, -0.31599, 0, 1, 0, 0); }
  34.375%  { transform: matrix(-0.55557, -0.28438, 0, 1, 0, 0); }
  37.5%    { transform: matrix(-0.70711, -0.24184, 0, 1, 0, 0); }
  40.625%  { transform: matrix(-0.83147, -0.19002, 0, 1, 0, 0); }
  43.75%   { transform: matrix(-0.92388, -0.13089, 0, 1, 0, 0); }
  46.875%  { transform: matrix(-0.98079, -0.06672, 0, 1, 0, 0); }
  50%      { transform: matrix(-1.00000,  0.00000, 0, 1, 0, 0); }
  53.125%  { transform: matrix(-0.98079,  0.06672, 0, 1, 0, 0); }
  56.25%   { transform: matrix(-0.92388,  0.13089, 0, 1, 0, 0); }
  59.375%  { transform: matrix(-0.83147,  0.19002, 0, 1, 0, 0); }
  62.5%    { transform: matrix(-0.70711,  0.24184, 0, 1, 0, 0); }
  65.625%  { transform: matrix(-0.55557,  0.28438, 0, 1, 0, 0); }
  68.75%   { transform: matrix(-0.38268,  0.31599, 0, 1, 0, 0); }
  71.875%  { transform: matrix(-0.19509,  0.33545, 0, 1, 0, 0); }
  75%      { transform: matrix(-0.00400,  0.34202, 0, 1, 0, 0); }   /* edge-on */
  78.125%  { transform: matrix( 0.19509,  0.33545, 0, 1, 0, 0); }
  81.25%   { transform: matrix( 0.38268,  0.31599, 0, 1, 0, 0); }
  84.375%  { transform: matrix( 0.55557,  0.28438, 0, 1, 0, 0); }
  87.5%    { transform: matrix( 0.70711,  0.24184, 0, 1, 0, 0); }
  90.625%  { transform: matrix( 0.83147,  0.19002, 0, 1, 0, 0); }
  93.75%   { transform: matrix( 0.92388,  0.13089, 0, 1, 0, 0); }
  96.875%  { transform: matrix( 0.98079,  0.06672, 0, 1, 0, 0); }
  100%     { transform: matrix( 1.00000,  0.00000, 0, 1, 0, 0); }
}

/* transform-box: view-box makes 50% 50% resolve to the centre of the
   viewBox, which is where every meridian is centred. Left to its own
   devices a UA can resolve the origin against the element's own bounding
   box, and a meridian would then scale about its own left edge and swing
   across the sphere instead of narrowing in place. */
.b-orb-mer {
  transform-box: view-box;
  transform-origin: 50% 50%;
  animation: bOrbMeridian var(--orb-turn) linear infinite;
  /* Nine great circles 20 degrees apart. The cycle above is a full 360
     degree turn, so 20 degrees is a turn over 18, not over 9. Dividing
     by the count instead of by the spacing is the easy error here, and
     it clumps every meridian into a rotating fan. */
  animation-delay: calc(var(--orb-i, 0) * var(--orb-turn) / -18);
}

/* The key light on the surface. Blurred and clipped by the parent's
   radius, so it cannot bleed past the limb. */
.b-orb-spec {
  overflow: hidden;
  background: radial-gradient(ellipse 32% 24% at 31% 24%,
    rgba(255, 250, 238, 0.42) 0%,
    rgba(255, 236, 200, 0.16) 38%,
    transparent 72%);
  filter: blur(6px);
  mix-blend-mode: screen;
}

/* The Fresnel rim: bright where the surface turns away from the viewer
   on the far side of the key light. An inset ring alone reads as a
   drawn circle, so this is a gradient that only reaches full strength
   in the lower right. */
.b-orb-limb {
  background: radial-gradient(circle at 68% 74%,
    rgba(250, 189, 89, 0.30) 0%,
    rgba(250, 189, 89, 0.06) 34%,
    transparent 58%);
  box-shadow: inset 0 0 22px rgba(250, 189, 89, 0.10);
  mix-blend-mode: screen;
  opacity: 0.85;
}

/* The mark sits over the globe, and says so. Without this the crest and
   the orb are siblings at the same level and paint order decides, which
   is the kind of thing that silently reverses when a layer is added. */
.b-crest-mark { z-index: 2; }
.b-crest-floor { z-index: 3; }

/* ════════════════════════════════════════════════════════════════
   THE THREE DOORS
   The routing block on blatt.com. Not flat panels: each one is a lit
   surface with its own gradient, and the first is the product so it
   carries the strongest light.
   ════════════════════════════════════════════════════════════════ */

.b-doors {
  display: grid;
  grid-template-columns: 1.25fr 1fr 1fr;
  gap: clamp(14px, 1.6vw, 22px);
}
@media (max-width: 900px) { .b-doors { grid-template-columns: 1fr; } }

.b-door {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: clamp(24px, 2.6vw, 36px);
  border-radius: 10px;
  border: 1px solid var(--b-hairline-firm);
  text-decoration: none;
  overflow: hidden;
  isolation: isolate;
  background:
    linear-gradient(158deg, rgba(255,242,214,0.055) 0%, rgba(250,189,89,0.018) 34%, rgba(8,8,8,0.6) 100%),
    linear-gradient(#0b0b0b, #070707);
  box-shadow:
    inset 0 1px 0 rgba(255,246,226,0.12),
    0 20px 44px -30px rgba(0,0,0,0.95);
  transition: transform 0.45s var(--b-ease-out), border-color 0.45s var(--b-ease-out), box-shadow 0.45s var(--b-ease-out);
}

/* The travelling highlight, revealed on hover. Kept as a pseudo-element
   under the content (z-index 0 against the content's auto stacking) so
   it can never sit over the text. */
.b-door::before {
  content: '';
  position: absolute;
  inset: -40%;
  z-index: -1;
  background: conic-gradient(from 210deg at 30% 0%,
    rgba(250,189,89,0.16) 0deg, transparent 90deg, transparent 300deg, rgba(255,242,214,0.10) 360deg);
  opacity: 0;
  transition: opacity 0.5s var(--b-ease-out);
}
.b-door:hover, .b-door:focus-visible {
  transform: translateY(-4px);
  border-color: rgba(250,189,89,0.5);
  box-shadow:
    inset 0 1px 0 rgba(255,246,226,0.2),
    0 34px 60px -32px rgba(0,0,0,1),
    0 0 46px -22px rgba(250,189,89,0.5);
}
.b-door:hover::before, .b-door:focus-visible::before { opacity: 1; }

/* The registry is the only one of the three that is a product, so it
   gets the strongest surface and reads first. */
.b-door--registry {
  background:
    linear-gradient(158deg, rgba(250,189,89,0.15) 0%, rgba(250,189,89,0.04) 40%, rgba(8,8,8,0.72) 100%),
    linear-gradient(#0d0c10, #070709);
  border-color: rgba(250,189,89,0.38);
}

.b-door-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mv-gold);
  opacity: 0.85;
}
.b-door h3 {
  font-family: var(--mv-font-display);
  font-size: clamp(21px, 2.1vw, 30px);
  line-height: 1.12;
  color: var(--b-text-ivory);
}
.b-door-line {
  font-size: 15px;
  line-height: 1.6;
  color: var(--mv-text-muted);
  flex: 1;
}
.b-door-go {
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 600;
  color: var(--mv-gold);
}
.b-door-go svg { width: 24px; height: 8px; transition: transform 0.3s var(--b-ease-out); }
.b-door:hover .b-door-go svg, .b-door:focus-visible .b-door-go svg { transform: translateX(7px); }

/* ── Lit cards and held cards ──────────────────────────────────── */
/* `--lit` is the same gradient language as the doors, for blocks that
   are content rather than navigation. `--held` is a destination that is
   not live yet: visibly present, visibly not clickable. */

.b-card--lit {
  background:
    linear-gradient(158deg, rgba(255,242,214,0.05) 0%, rgba(250,189,89,0.015) 36%, rgba(8,8,8,0.55) 100%),
    linear-gradient(#0b0b0b, #080808);
  box-shadow: inset 0 1px 0 rgba(255,246,226,0.1), 0 18px 40px -30px rgba(0,0,0,0.9);
}
.b-card--held { opacity: 0.5; }
.b-card--held h3 { color: var(--mv-text-muted); }

.b-panel--lit {
  background:
    linear-gradient(158deg, rgba(255,242,214,0.06) 0%, rgba(250,189,89,0.02) 38%, rgba(8,8,8,0.6) 100%),
    linear-gradient(#0b0b0b, #080808);
  box-shadow: inset 0 1px 0 rgba(255,246,226,0.12), 0 18px 40px -30px rgba(0,0,0,0.9);
}

/* ── Testimonials: the wall ────────────────────────────────────── */
/* Nineteen named endorsements, each a different length. A grid would
   force every card to the height of the tallest in its row and leave
   craters. CSS columns let each card be exactly as tall as its quote,
   which is the whole reason a masonry wall reads as dense rather than
   as a gappy table. */

.b-quotes {
  column-count: 3;
  column-gap: clamp(14px, 1.5vw, 20px);
}
@media (max-width: 1000px) { .b-quotes { column-count: 2; } }
@media (max-width: 660px)  { .b-quotes { column-count: 1; } }

.b-quote {
  position: relative;
  /* A card must never be split across two columns. */
  break-inside: avoid;
  page-break-inside: avoid;
  margin: 0 0 clamp(14px, 1.5vw, 20px);
  padding: clamp(22px, 2.2vw, 30px) clamp(22px, 2.2vw, 30px) clamp(20px, 2vw, 26px);
  border-radius: 10px;
  border: 1px solid var(--b-hairline);
  background:
    linear-gradient(158deg, rgba(255,242,214,0.05) 0%, rgba(250,189,89,0.015) 34%, rgba(8,8,8,0.55) 100%),
    linear-gradient(#0a0a0a, #070707);
  box-shadow:
    inset 0 1px 0 rgba(255,246,226,0.1),
    0 16px 38px -30px rgba(0,0,0,0.95);
  transition: border-color 0.4s var(--b-ease-out), box-shadow 0.4s var(--b-ease-out), transform 0.4s var(--b-ease-out);
}
.b-quote:hover {
  transform: translateY(-3px);
  border-color: rgba(250,189,89,0.4);
  box-shadow:
    inset 0 1px 0 rgba(255,246,226,0.16),
    0 26px 50px -32px rgba(0,0,0,1),
    0 0 40px -24px rgba(250,189,89,0.45);
}

/* The opening quote mark, set in the display face and cropped by the
   card's own overflow so it reads as a watermark rather than a glyph. */
.b-quote::before {
  content: '\201C';
  position: absolute;
  top: -14px;
  left: 12px;
  font-family: var(--mv-font-display);
  font-size: 84px;
  line-height: 1;
  color: rgba(250,189,89,0.13);
  pointer-events: none;
}

.b-quote blockquote {
  position: relative;
  margin: 0;
  font-size: 15px;
  line-height: 1.68;
  color: var(--b-temp-body, var(--mv-text-muted));
}

.b-quote figcaption {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 16px;
  padding-top: 13px;
  border-top: 1px solid var(--b-hairline);
}
/* Weight, size and colour carry the hierarchy here. Never slant. */
.b-quote-name {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mv-gold);
}
.b-quote-role {
  font-size: 12.5px;
  color: var(--mv-text-muted);
  letter-spacing: 0.01em;
}
/* Quiet, and never removed in a redesign. */
.b-quote-memoriam {
  margin-top: 3px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(166,160,150,0.75);
}

/* ── Contact ───────────────────────────────────────────────────── */

.b-contact {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(14px, 1.6vw, 22px);
}
@media (max-width: 700px) { .b-contact { grid-template-columns: 1fr; } }

.b-contact-big {
  margin-top: 10px;
  font-size: clamp(17px, 1.7vw, 21px);
  font-weight: 600;
  color: var(--b-text-ivory);
  overflow-wrap: anywhere;
}
.b-contact-big a { color: inherit; text-decoration: none; }
.b-contact-big a:hover { color: var(--mv-gold); }
/* address defaults to italic in every browser, and italics are a bug
   in this brand. */
.b-contact-addr {
  font-style: normal;
  margin-top: 10px;
  font-size: 15px;
  line-height: 1.7;
  color: var(--mv-text-muted);
}

/* ── Program price line ────────────────────────────────────────── */

.b-row-price {
  margin-top: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--mv-gold);
}

/* ── The demoted third-person biography ────────────────────────── */
/* Real speakers are asked for one constantly. It stays on the page and
   it stays in the schema, it just does not open the page. */

.b-formal {
  margin-top: 26px;
  border-top: 1px solid var(--b-hairline);
  padding-top: 18px;
}
.b-formal summary {
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mv-gold);
  list-style: none;
}
.b-formal summary::-webkit-details-marker { display: none; }
.b-formal summary::before { content: '+ '; }
.b-formal[open] summary::before { content: '- '; }
.b-formal .b-prose { margin-top: 16px; }

/* ── Reduced motion ────────────────────────────────────────────── */
/* Nothing animates, nothing moves, nothing is hidden. The dial becomes
   a static composition and the page loses no information. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .b-reveal { opacity: 1; transform: none; }
  .b-dial-stage { transform: none; }
  .b-portal, .b-door { transform: none; }
  .b-hero-canvas { display: none; }
  /* The crest keeps its light and loses its movement. */
  .b-crest-sweep { display: none; }
  .b-crest-mark { transform: none; }
  /* The globe stops turning and stays a globe. The blanket
     animation-duration override above already freezes the meridians,
     but it freezes them wherever the clock happened to be, and with a
     negative delay that is a half-collapsed graticule. --orb-still is
     each meridian's exact matrix at its own longitude, computed in
     render.js from the same projection as the animation, so the still
     frame is a correct sphere rather than an arbitrary one. */
  .b-orb { animation: none; }
  .b-orb-mer { animation: none; transform: var(--orb-still); }
  .b-shimmer {
    animation: none;
    background-position: 30% center;
  }
}

/* ── Print ─────────────────────────────────────────────────────── */

/* ── Forced colours ───────────────────────────────────────────────── */
/* Forced-colours mode drops every background-image and box-shadow, which
   leaves the orb as a bare SVG graticule with no sphere under it: a wire
   scribble floating over the plates. There is no information in it, so it
   goes. The crest itself is an img and survives. */

@media (forced-colors: active) {
  .b-orb, .b-crest-halo, .b-crest-sweep, .b-crest-floor { display: none; }
}

@media print {
  body::before, body::after, .b-nav, .b-progress, .b-dial, .b-hero-canvas { display: none; }
  body { background: #fff; color: #000; }
  .b-shimmer { -webkit-text-fill-color: #000; color: #000; }
  .b-section { page-break-inside: avoid; border-top: 1px solid #999; }
}

/* ════════════════════════════════════════════════════════════════
   TEMPLATES
   What a member picks at checkout. A template changes the palette and
   the chrome only. Structure, schema and SEO stay identical across all
   three, because those are what make the page worth owning and they
   should not be something a customer can choose wrong.
   ════════════════════════════════════════════════════════════════ */

/* ── Dynasty ───────────────────────────────────────────────────── */
/* The registry's own language: platinum and silver on near-black,
   lifted from the live Blatt Domain Registry rather than invented, so a
   member's page feels like the card they bought. */

body[data-template="dynasty"] {
  --mv-gold:        #C0C0C0;
  --mv-gold-dark:   #808080;
  --b-hairline:      rgba(192, 192, 192, 0.16);
  --b-hairline-firm: rgba(192, 192, 192, 0.34);
  --b-temp-wash:     rgba(229, 228, 226, 0.05);
  --b-temp-edge:     rgba(229, 228, 226, 0.32);
  --b-temp-body:     #b9b9c0;
  --b-text-ivory:    #E5E4E2;
  --b-ink:           #0A0A0A;
}
body[data-template="dynasty"] .b-shimmer {
  background-image: linear-gradient(94deg,
    #ffffff 0%, #E5E4E2 18%, #C0C0C0 38%,
    #6e6e73 52%, #C0C0C0 66%, #E5E4E2 84%, #ffffff 100%);
}
body[data-template="dynasty"] .b-btn--gold {
  background: linear-gradient(145deg, #E5E4E2, #C0C0C0 46%, #808080);
  color: #0A0A0A;
}

/* ── Minimal ───────────────────────────────────────────────────── */
/* One screen and nothing else. For members who want a real address on
   the internet and no maintenance. The dial and the atmospherics come
   off: at this size they would be the entire page rather than an
   accent. */

body[data-template="minimal"] {
  --b-section-y: clamp(48px, 6vw, 88px);
  --b-temp-wash: rgba(250, 189, 89, 0.04);
}
body[data-template="minimal"]::before { opacity: 0.22; }
body[data-template="minimal"] .b-dial { display: none; }
body[data-template="minimal"] .b-hero-grid { grid-template-columns: minmax(0, 1fr); }
body[data-template="minimal"] .b-hero { min-height: auto; padding-block: clamp(120px, 20vh, 200px) clamp(40px, 6vh, 70px); }
body[data-template="minimal"] .b-hero-copy { max-width: 56ch; }
/* Size off the column, not the viewport. A single-column hero still has
   a column, and "SEBASTIAN" has to fit inside it without hyphenating. */
@supports (container-type: inline-size) {
  body[data-template="minimal"] .b-hero h1 { font-size: clamp(32px, 9.5cqi, 82px); }
}
body[data-template="minimal"] .b-section-num { display: none; }
body[data-template="minimal"] .b-section-head { grid-template-columns: minmax(0, 1fr); }

/* Booking is the only route in, so it gets the wide panel. */
.b-contact--call { grid-column: span 2; }
@media (max-width: 700px) { .b-contact--call { grid-column: span 1; } }
.b-contact-note { margin-top: 8px; font-size: 14px; color: var(--mv-text-muted); }

/* A title that is not out yet: present, named, and visibly not clickable. */
.b-row--soon { opacity: 0.62; }
.b-row-soon {
  font-family: var(--mv-font-display);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mv-text-muted);
  white-space: nowrap;
}

/* ── Portraits ─────────────────────────────────────────────────── */
/* Photograph first, then the words, then the panels. A person page whose
   first image sits eight sections down is a person page nobody believes. */

.b-about {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr) minmax(0, 0.9fr);
  gap: clamp(20px, 2.6vw, 40px);
  align-items: start;
}
.b-about--noaside { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr); }
@media (max-width: 1100px) {
  .b-about, .b-about--noaside { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.3fr); }
  .b-about > :last-child:not(:nth-child(-n+2)) { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .b-about, .b-about--noaside { grid-template-columns: minmax(0, 1fr); }
}

.b-portrait { position: sticky; top: clamp(84px, 11vh, 120px); }
@media (max-width: 760px) { .b-portrait { position: static; } }

.b-portrait figure {
  margin: 0;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--b-hairline-firm);
  background: #080808;
  box-shadow:
    inset 0 1px 0 rgba(255,246,226,0.1),
    0 30px 64px -34px rgba(0,0,0,1);
}
.b-portrait img { width: 100%; height: auto; display: block; }

/* The gallery grid. `sizes` in the markup is written against exactly this
   layout, so if these breakpoints change, change that string too or a
   phone starts downloading the 1696px file. */
.b-gallery {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.5vw, 20px);
}
@media (max-width: 1100px) { .b-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .b-gallery { grid-template-columns: minmax(0, 1fr); } }

.b-gallery figure {
  margin: 0;
  border: 1px solid var(--b-hairline);
  border-radius: 10px;
  overflow: hidden;
  background: #080808;
  transition: border-color 0.4s var(--b-ease-out), transform 0.4s var(--b-ease-out);
}
.b-gallery figure:hover {
  border-color: var(--b-hairline-firm);
  transform: translateY(-3px);
}
/* A fixed aspect keeps the grid even while the source portraits differ,
   and object-position favours the top so a face is never cropped off. */
.b-gallery img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: 50% 22%;
}
.b-gallery figcaption {
  padding: 12px 14px;
  font-size: 13px;
  color: var(--mv-text-muted);
  border-top: 1px solid var(--b-hairline);
}
