/* ============================================================
   WEALTHDOOR GROUP — Design System v7 "Paper"
   ------------------------------------------------------------
   A white canvas, a cool slate ramp, and hairlines for structure.
   Colour enters only through the logo, one pinpoint brand mark,
   and the photography the client supplies.

   Five rules this file exists to enforce:
     1. The page ground is #fff. There are no dark sections.
     2. Every grey on the site comes out of one 12-step ramp.
        Nothing is hand-mixed.
     3. Three button tiers, one radius. Solid ink, quiet fill,
        hairline outline. Nothing else, ever.
     4. Structure is drawn with 1px hairlines, not with boxes,
        shadows, or colour.
     5. Every image slot is a .frame — a grey, rounded, correctly
        proportioned box that stays presentable while empty and
        becomes the photo the moment an <img> is dropped inside.
   ============================================================ */

/* Newsreader now loads its ITALIC axis as well (v61). The second clause
   of every headline is set in it -- see the v61 block at the end of this
   file. It has to be a real italic: a serif faux-obliqued by the browser
   shears the letterforms and is exactly the thing the client would read
   as a different font. Plus Jakarta Sans stays upright-only; nothing in
   the sans stack is italicised. */
@import url('https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,300;0,6..72,400;0,6..72,500;0,6..72,600;0,6..72,700;1,6..72,400;1,6..72,500;1,6..72,600;1,6..72,700&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap');

:root {
  /* ---- The ramp -------------------------------------------------
     One cool slate scale. Slightly blue-cast so it sits under the
     logo without fighting it, and so white looks like paper rather
     than like a gap. Every neutral on the site is one of these. */
  --n-0:   #ffffff;
  --n-25:  #fcfcfd;
  --n-50:  #f7f8fa;
  --n-100: #eff1f4;
  --n-200: #e4e7ec;
  --n-300: #d2d7de;
  --n-400: #a8afbb;
  --n-500: #6b727d;
  --n-600: #4e555f;
  --n-700: #363c45;
  --n-800: #22272e;
  --n-900: #111519;

  /* ---- Semantic ground ---- */
  --paper: var(--n-0);
  --paper-2: var(--n-25);   /* a band so quiet it reads as white */
  --soft: #f3f5fc;          /* image slots, quiet surfaces — brand tinted */
  --soft-2: #e8ecf8;        /* hover on quiet surfaces */
  --line: #e2e6f1;          /* hairline, tinted so structure isn't grey */
  --line-strong: #ccd3e6;
  --line-faint: #eef1fa;

  /* ---- Semantic type ---- */
  --ink: var(--n-900);      /* headlines, buttons */
  --ink-soft: var(--n-700);
  --muted: var(--n-600);    /* body copy — 7.4:1 on paper */
  --faint: var(--n-500);    /* labels, dates, the second line of a headline */
  --ghosted: var(--n-400);  /* placeholder hints only */

  /* ---- Brand ----------------------------------------------------
     Both colours are taken straight out of the logo. They have jobs,
     and the jobs are the whole rule:

       BLUE  = action and identity. Every primary button, every link,
               every active state, and the tinted grounds.
       ORANGE = the punctuation mark. Dots, small rules, the live
               marker. Never a fill larger than a few pixels.

     Type stays ink and slate. Colour lives in surfaces and actions,
     which is how you get a branded page without a blue page. */
  --brand-50:  #f2f4fd;   /* the tinted ground — barely there */
  --brand-100: #e5e9fa;
  --brand-200: #c9d0f3;
  --brand-500: #2438c9;
  --brand-600: #16249c;   /* primary button hover */
  --brand-700: #0013a0;   /* the logo blue */
  --brand-900: #000c63;
  --brand: var(--brand-700);
  --brand-ring: rgba(0, 19, 160, 0.2);

  --accent-50:  #fef3ee;
  --accent-200: #fbc9b3;
  --accent: #f05a29;      /* the logo orange -- the only orange */
  /* --accent-700: #c23f14 retired in v24. It was the browner shade
     that made emphasised words disagree with the mark. Nothing
     references it now; kept here as a note so it is not reinvented. */

  /* ---- Section ground (v16) -------------------------------------
     v10 alternated white with a warm cream. The client saw it built
     and rejected it: "remove the light peach colour in the sections,
     add the light blue only". So the same three tokens now hold a
     cool tint pulled out of --brand-500 instead of out of the logo
     orange. The NAMES are unchanged on purpose — .band--warm and
     --warm-* are referenced ~40 times across 18 pages, and renaming
     them buys nothing but a chance to miss one. Read "warm" as
     "the tinted band" wherever it appears below.

     These are deliberately weak (a ~3% wash). The "dont keep too much
     blue" rule still holds: this is a ground tone, not a blue section,
     and it must never get strong enough to read as coloured. */
  --warm-50:   #f5f8fd;   /* the tinted band */
  --warm-100:  #eaf0fa;   /* a quiet surface sitting on that band */
  --warm-line: #dde5f3;   /* hairline that survives on tinted ground */

  /* Kept so older markup keeps resolving. All of these now point at
     the neutral palette rather than the old navy/cream one. */
  --blue: var(--ink); --blue-deep: #000; --blue-abyss: var(--ink);
  --blue-lift: var(--ink-soft); --blue-tint: var(--soft); --blue-line: var(--line);
  --orange: var(--ink); --orange-deep: #000; --orange-tint: var(--soft);
  --cream: var(--paper); --sand: var(--soft);
  --on-dark: var(--muted); --on-dark-dim: var(--faint); --on-dark-line: var(--line);
  --navy-900: var(--ink); --navy-800: var(--ink); --navy-700: var(--ink); --navy-600: var(--ink-soft);
  --ivory: var(--paper); --stone-200: var(--line); --stone-300: var(--line-strong);
  --muted-dark: var(--faint); --navy-text: var(--muted); --navy-text-dim: var(--faint);
  --orange-soft: var(--soft);

  /* ---- Space: a 4px scale. Sections and gaps pick from this. ---- */
  --s-1: 0.25rem; --s-2: 0.5rem;  --s-3: 0.75rem; --s-4: 1rem;
  --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4rem;
  --s-9: 6rem;

  /* ---- System ---- */
  --maxw: 1240px;
  --measure: 58ch;
  --gutter: clamp(1.25rem, 4vw, 3.25rem);
  --radius-xs: 6px;
  --radius: 10px;        /* buttons, inputs, small cards */
  --radius-lg: 16px;     /* image slots, large cards */
  --radius-xl: 22px;     /* full-bleed media panels */
  --radius-pill: 999px;

  /* Shadows are for lift on interaction only — never for decoration. */
  --shadow-sm: 0 1px 2px rgba(17, 21, 25, 0.05);
  --shadow-md: 0 12px 32px -18px rgba(17, 21, 25, 0.2);
  --shadow-lg: 0 30px 70px -40px rgba(17, 21, 25, 0.28);
  --shadow-btn: 0 1px 2px rgba(17, 21, 25, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.09);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, 'JetBrains Mono', Menlo, Consolas, monospace;

  --z-nav: 100;
  --z-overlay: 200;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-sans);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.6;
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--ink); color: #fff; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 4px; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.018em;
  color: var(--ink);
}
.display { font-size: clamp(2.6rem, 6vw, 4.9rem); line-height: 1.02; letter-spacing: -0.03em; }
.h2 { font-size: clamp(1.8rem, 3.1vw, 2.5rem); letter-spacing: -0.022em; }
.h3 { font-size: clamp(1.3rem, 2.1vw, 1.75rem); }

/* The reference move: headline in two tones. The first line states the
   thing, the second recedes to grey and finishes the sentence. */
.mute { color: var(--faint); }

/* ---- Micro type ----------------------------------------------
   Reference B sets its smallest labels in a monospace, which is
   what stops a page this quiet from reading as unfinished. All
   eyebrows, section numbers, dates and codes use it. */
.mono {
  font-family: var(--font-mono); font-size: 0.78rem; font-weight: 500;
  letter-spacing: 0.09em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
.eyebrow, .kicker {
  font-family: var(--font-mono); font-size: 0.78rem; font-weight: 500;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--faint);
}
/* Eyebrow with a brand pinpoint, then the label in ink and the
   qualifier in grey — reference B's "#1 Global partner". */
.eyebrow--dot { display: inline-flex; align-items: center; gap: 0.55rem; }
.eyebrow--dot::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); flex: none;
}
.eyebrow strong { color: var(--ink); font-weight: 500; }
.lead { font-size: clamp(1.02rem, 1.25vw, 1.16rem); line-height: 1.6; color: var(--muted); max-width: var(--measure); }
.body { color: var(--muted); max-width: var(--measure); }
.body + .body { margin-top: 1.1rem; }

/* ---------- Layout ---------- */
/* The vertical hairlines that bound the content column are drawn by the
   wraps themselves. Sections stack flush, so the segments join into one
   continuous rule down the page. */
.wrap {
  max-width: var(--maxw); margin: 0 auto;
  padding-inline: var(--gutter);
  border-inline: 1px solid var(--line);
}
.section { padding-block: clamp(3.25rem, 5.4vw, 5.25rem); }
.section--tight { padding-block: clamp(2.25rem, 3.8vw, 3.5rem); }
.center { text-align: center; }
.divide-top { border-top: 1px solid var(--line); }
@media (max-width: 900px) { .wrap { border-inline: 0; } }

/* ============================================================
   BUTTONS
   ------------------------------------------------------------
   Three tiers and one radius, on purpose. Every reference page
   we worked from puts exactly one solid black button on screen
   and lets the second action sit in a quiet grey fill; the
   outline tier exists only for a third action in the same row.

     .btn--primary   solid ink        one per view
     .btn--ghost     quiet grey fill  the companion action
     .btn--accent    hairline outline third emphasis only

   Shape: 10px. Three of the four references use a rounded rect
   in this range; only one uses a full pill, and a pill reads as
   consumer-app rather than as a regulated adviser. Pills stay
   reserved for non-interactive chips (.badge, .pill, .sitepill),
   which keeps shape itself meaningful: rounded rect = you can
   press it, pill = it is a label.
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  font-family: var(--font-sans); font-weight: 600; font-size: 0.92rem;
  letter-spacing: -0.005em;
  padding: 0.8rem 1.35rem; border-radius: var(--radius);
  border: 1px solid transparent; cursor: pointer; line-height: 1.25;
  transition: background 0.2s var(--ease), color 0.2s var(--ease),
              border-color 0.2s var(--ease), box-shadow 0.2s var(--ease),
              transform 0.12s var(--ease);
  white-space: nowrap; -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* nowrap is right on a desktop button and wrong on a phone: a long label
   like "Explore Wealthdoor Private Client, India" runs past its card and
   gets clipped. Below this width the label wraps instead. */
@media (max-width: 560px) {
  .btn { white-space: normal; text-align: center; max-width: 100%; }
}

/* Tier 1 — the brand blue. This is the single loudest element on any
   page, so it is the one that decides whether the site reads as a
   brand or as a wireframe. Black here looked like an unstyled default. */
.btn--primary, .btn--light {
  background: var(--brand); color: #fff;
  box-shadow: 0 1px 2px rgba(0, 12, 99, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
.btn--primary:hover, .btn--light:hover {
  background: var(--brand-600);
  box-shadow: 0 4px 14px -4px rgba(0, 19, 160, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}

/* Kept for the rare place a neutral solid is genuinely wanted. */
.btn--ink { background: var(--ink); color: #fff; box-shadow: var(--shadow-btn); }
.btn--ink:hover { background: var(--n-800); }

/* Tier 2 — quiet grey fill. Carries a hairline so it holds its shape
   when it sits on the grey .band as well as on paper. */
.btn--ghost, .btn--outline-light {
  background: var(--soft); color: var(--ink); border-color: var(--line);
}
.btn--ghost:hover, .btn--outline-light:hover {
  background: var(--soft-2); border-color: var(--line-strong);
}

/* Tier 3 — hairline outline. */
.btn--accent { background: var(--paper); color: var(--brand); border-color: var(--line-strong); }
.btn--accent:hover { border-color: var(--brand); background: var(--brand-50); }

/* Inverted, for the rare moment a button sits on an image. */
.btn--onmedia { background: var(--paper); color: var(--ink); box-shadow: var(--shadow-md); }
.btn--onmedia:hover { background: var(--soft); }

.btn--sm { padding: 0.55rem 1rem; font-size: 0.85rem; border-radius: var(--radius-xs); }
.btn--lg { padding: 1rem 1.7rem; font-size: 0.98rem; }
.btn--block { width: 100%; }
.btn .arrow { transition: transform 0.25s var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

/* A button row, so pages stop hand-rolling flex in a style attribute. */
.btnrow { display: flex; gap: 0.7rem; flex-wrap: wrap; align-items: center; }

/* Text link with rule */
.tlink { font-weight: 600; font-size: 0.92rem; color: var(--brand); display: inline-flex; align-items: center; gap: 0.4rem; border-bottom: 1px solid var(--brand-200); padding-bottom: 2px; transition: border-color 0.25s var(--ease); }
.tlink:hover { border-color: var(--brand); }
.tlink .arrow { transition: transform 0.25s var(--ease); }
.tlink:hover .arrow { transform: translateX(3px); }

/* ============================================================
   DETAIL LAYER
   ------------------------------------------------------------
   The small components that separate the reference pages from a
   plain white page: an announcement pill, a proof row under the
   buttons, a qualifier line, drafting marks, and a ruled logo
   grid. None of them use colour; all of them are hairline work.
   ============================================================ */

/* ---- Announce: a pill that wraps a link, dot + headline + action.
   Reference D puts this above the headline. ---- */
.announce {
  display: inline-flex; align-items: center; gap: 0.7rem;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius-pill); padding: 0.3rem 0.35rem 0.3rem 0.9rem;
  font-size: 0.82rem; color: var(--muted); margin-bottom: 1.6rem;
  max-width: 100%; box-shadow: var(--shadow-sm);
  transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.announce:hover { border-color: var(--line-strong); box-shadow: var(--shadow-md); }
.announce__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
/* min-width:0 is what lets the label shrink instead of forcing the
   pill — and with it the whole hero grid track — to its full width. */
.announce__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.announce__text strong { color: var(--ink); font-weight: 600; }
.announce__go {
  display: inline-flex; align-items: center; gap: 0.35rem; flex: none;
  background: var(--soft); color: var(--ink); border-radius: var(--radius-pill);
  padding: 0.32rem 0.75rem; font-size: 0.82rem; font-weight: 600;
  transition: background 0.22s var(--ease);
}
.announce:hover .announce__go { background: var(--soft-2); }
.announce:hover .announce__go .arrow { transform: translateX(2px); }
.announce__go .arrow { transition: transform 0.25s var(--ease); }

/* ---- Trust row: the rating-and-source line the references put
   directly under the buttons. Marks, then the claim in grey. ---- */
.trust {
  display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap;
  margin-top: 1.7rem; font-size: 0.84rem; color: var(--faint);
}
.trust__marks { display: inline-flex; gap: 0.18rem; color: var(--ink); }
.trust__marks svg { width: 15px; height: 15px; fill: currentColor; }
.trust strong { color: var(--ink); font-weight: 600; }
.trust__sep { width: 1px; height: 15px; background: var(--line); flex: none; }

/* ---- Microline: the small qualifier under a CTA. ---- */
.microline {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  margin-top: 1.15rem; font-size: 0.82rem; color: var(--faint);
}
.microline > span { display: inline-flex; align-items: center; gap: 0.42rem; }
.microline svg { width: 13px; height: 13px; stroke: var(--ghosted); stroke-width: 2; fill: none; flex: none; }

/* ---- Drafting marks --------------------------------------------
   Reference B frames its hero like a printed sheet. Corner crop
   marks on the content column and a hatched band closing the
   section. Both are pure CSS, both are decorative, both vanish on
   small screens where they would only add noise. ---- */
.marked { position: relative; }
.marked::before, .marked::after {
  content: ''; position: absolute; width: 11px; height: 11px;
  border-color: var(--brand-200); border-style: solid; pointer-events: none;
}
.marked::before { top: 0; left: 0; border-width: 1px 0 0 1px; }
.marked::after { top: 0; right: 0; border-width: 1px 1px 0 0; }
.marked__b { position: absolute; left: 0; right: 0; bottom: 0; height: 0; pointer-events: none; }
.marked__b::before, .marked__b::after {
  content: ''; position: absolute; bottom: 0; width: 11px; height: 11px;
  border-color: var(--line-strong); border-style: solid;
}
.marked__b::before { left: 0; border-width: 0 0 1px 1px; }
.marked__b::after { right: 0; border-width: 0 1px 1px 0; }

.hatch {
  height: 34px;
  background-image: repeating-linear-gradient(
    -45deg, var(--brand-200) 0 1px, transparent 1px 9px);
  border-block: 1px solid var(--line);
}

/* ---- Graph-paper band: reference A's faint grid behind a stat row. */
.gridband { position: relative; }
.gridband::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(to right, var(--line-faint) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line-faint) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
}
.gridband > * { position: relative; z-index: 1; }

/* ---- Logo grid: reference B rules its logo row into cells rather
   than scrolling it. Quieter and more institutional than a marquee. */
.logogrid {
  display: grid; grid-template-columns: repeat(5, 1fr);
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: var(--paper);
}
.logogrid > * {
  display: grid; place-items: center; text-align: center;
  padding: 1.35rem 1rem; font-size: 0.83rem; font-weight: 500;
  color: var(--faint); border-right: 1px solid var(--line);
  transition: color 0.22s var(--ease), background 0.22s var(--ease);
}
.logogrid > *:last-child { border-right: 0; }
.logogrid > *:hover { color: var(--ink); background: var(--soft); }
@media (max-width: 900px) {
  .logogrid { grid-template-columns: repeat(2, 1fr); }
  .logogrid > * { border-bottom: 1px solid var(--line); }
  .logogrid > *:nth-child(2n) { border-right: 0; }
  .hatch { display: none; }
  .marked::before, .marked::after, .marked__b { display: none; }
}

/* ---- Split head: headline left, supporting copy and actions right.
   Reference C's section opener. ---- */
.splithead {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.85fr);
  gap: clamp(1.6rem, 5vw, 4.5rem); align-items: end;
}
.splithead__aside { padding-bottom: 0.4rem; }
.splithead__aside .lead { max-width: 40ch; }
.splithead__aside .btnrow { margin-top: 1.5rem; }
@media (max-width: 860px) { .splithead { grid-template-columns: 1fr; align-items: start; } }

/* ============================================================
   FRAME — the image slot
   ------------------------------------------------------------
   Empty, it is a proportioned grey card with a quiet label.
   To fill it, drop an <img> inside; the label sits behind and
   the image covers it. Nothing else has to change.

     <div class="frame frame--16x9">
       <span class="frame__hint">Image · 16:9</span>
       <img src="assets/img/your-photo.jpg" alt="" />
     </div>
   ============================================================ */
.frame {
  position: relative; overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--soft);
  border: 1px solid var(--line);
  aspect-ratio: 16 / 10;
  display: grid; place-items: center;
}
.frame > img, .frame > video {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
}
.frame__hint {
  font-size: 0.78rem; font-weight: 500;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--ghosted);
  text-align: center; padding: 1rem; z-index: 0;
}
.frame--1x1 { aspect-ratio: 1 / 1; }
.frame--4x3 { aspect-ratio: 4 / 3; }
.frame--3x2 { aspect-ratio: 3 / 2; }
.frame--16x9 { aspect-ratio: 16 / 9; }
.frame--4x5 { aspect-ratio: 4 / 5; }
.frame--tall { aspect-ratio: 3 / 4; }
.frame--flush { border-radius: 0; border: 0; border-bottom: 1px solid var(--line); }

/* A caption chip that sits on top of the image once there is one. */
.frame .tag, .split__media .tag, .card__media .tag {
  position: absolute; left: 1rem; bottom: 1rem; z-index: 2;
  background: rgba(255, 255, 255, 0.92); backdrop-filter: blur(8px);
  color: var(--ink); font-size: 0.81rem; font-weight: 500;
  padding: 0.45rem 0.8rem; border-radius: var(--radius-pill);
  border: 1px solid var(--line);
}
.card__media .tag { top: 1rem; bottom: auto; }

/* ---------- Nav ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-nav);
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease);
}
.nav.scrolled { border-color: var(--line); }
.nav__inner { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); height: 74px; display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; }
.nav__progress { display: none; }

.brand { display: inline-flex; align-items: center; }
.brand__logo { height: 28px; width: auto; }
.brand__sub {
  margin-left: 0.7rem; padding-left: 0.7rem; border-left: 1px solid var(--line);
  font-family: var(--font-mono); font-size: 0.77rem; font-weight: 500;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--faint);
  align-self: center; white-space: nowrap;
}
.brand__word { font-family: var(--font-sans); font-weight: 700; font-size: 1.3rem; letter-spacing: -0.03em; color: var(--ink); line-height: 1; }
.brand__word .dot { color: var(--accent); }

.nav__links { display: flex; align-items: center; gap: 1.7rem; }
.nav__links a { font-size: 0.91rem; font-weight: 500; color: var(--muted); transition: color 0.2s var(--ease); }
.nav__links a:hover { color: var(--brand); }
.nav__cta { display: flex; align-items: center; gap: 0.7rem; }
.nav__toggle { display: none; background: none; border: 0; cursor: pointer; width: 40px; height: 40px; }
.nav__toggle span { display: block; width: 20px; height: 1.5px; background: var(--ink); margin: 5px auto; transition: 0.3s var(--ease); }

.mobilemenu { position: fixed; inset: 74px 0 0; z-index: var(--z-nav); background: var(--paper); transform: translateY(-110%); visibility: hidden; pointer-events: none; transition: transform 0.4s var(--ease), visibility 0s linear 0.4s; padding: var(--gutter); display: flex; flex-direction: column; gap: 0.2rem; overflow-y: auto; }
.mobilemenu.open { transform: translateY(0); visibility: visible; pointer-events: auto; transition: transform 0.4s var(--ease), visibility 0s; }
.mobilemenu a { font-family: var(--font-display); font-size: 1.45rem; padding: 0.65rem 0; border-bottom: 1px solid var(--line); }

/* ---------- Hero ---------- */
.hero {
  position: relative; background: var(--paper); color: var(--ink);
  padding-block: clamp(7rem, 11vw, 9.5rem) clamp(3rem, 6vw, 5rem);
  overflow: hidden;
}
.hero__bg, .hero__grain, .hero__arc, .moment__arc { display: none; }
.hero__inner { position: relative; z-index: 2; width: 100%; max-width: var(--maxw); margin: 0 auto; padding-inline: var(--gutter); border-inline: 1px solid var(--line); }
.hero h1 { max-width: 18ch; text-wrap: balance; }
.hero p.lead { margin-top: 1.5rem; max-width: 48ch; }
.hero__cta { display: flex; gap: 0.75rem; margin-top: 2.4rem; flex-wrap: wrap; align-items: center; }
.hero__stats { display: flex; gap: clamp(1.5rem, 4vw, 3.5rem); margin-top: 3.4rem; flex-wrap: wrap; }
.hero__stat { max-width: 20ch; }
.hero__stat .n { font-family: var(--font-display); font-size: clamp(1.8rem, 3vw, 2.4rem); color: var(--ink); line-height: 1; }
.hero__stat .l { font-size: 0.86rem; color: var(--muted); margin-top: 0.5rem; }
@media (max-width: 900px) { .hero__inner { border-inline: 0; } }

/* ---- Feature hero ---------------------------------------------
   Headline left, image slot right, and on a wide screen the slot
   runs off the right edge of the viewport. That asymmetry is the
   single move that makes reference A read as a designed page
   rather than a two-column template: the content column keeps its
   hairline on the left, and the picture escapes it on the right. */
.hero--feature { padding-block: clamp(6.5rem, 10vw, 9rem) clamp(3rem, 6vw, 5rem); }
.hero--feature .hero__inner {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: clamp(2rem, 4vw, 4rem); align-items: center;
}
.hero__copy { position: relative; z-index: 3; }
.hero--feature h1 { max-width: 100%; font-size: clamp(2.3rem, 4.3vw, 3.65rem); text-wrap: pretty; }
.hero--feature p.lead { max-width: 42ch; }
.hero--feature .hero__media { width: 100%; }
.hero--feature .hero__media .frame { border-radius: var(--radius-xl); }

@media (min-width: 1180px) {
  /* Run the media out to the viewport edge and square it off there.
     The offset is the gap between the content column's right edge
     and the viewport: half the leftover outside --maxw, plus the
     gutter. width:auto is required — width:100% would pin the item
     back to its grid track and swallow the negative margin. */
  .hero--feature .hero__media {
    width: auto;
    margin-right: min(0px, calc((var(--maxw) - 100vw) / 2 - var(--gutter)));
  }
  .hero--feature .hero__media .frame {
    border-top-right-radius: 0; border-bottom-right-radius: 0; border-right: 0;
  }
}
@media (max-width: 980px) {
  /* minmax(0,1fr), not 1fr: a bare 1fr track floors at min-content,
     so one nowrap child would push the column past the viewport. */
  .hero--feature .hero__inner { grid-template-columns: minmax(0, 1fr); }
  .hero--feature h1 { max-width: 17ch; }
}
@media (max-width: 600px) {
  .hero__cta .btn { flex: 1 1 100%; }
  .microline { gap: 0.45rem 1.1rem; }
}

/* Small pill above the headline. Pill shape is reserved for labels
   like this — anything you can press is a rounded rect. */
.hero__tag, .badge {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-sans); font-size: 0.81rem; font-weight: 500;
  color: var(--muted); background: var(--soft);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  padding: 0.4rem 0.9rem; margin-bottom: 1.5rem;
  letter-spacing: 0; text-transform: none;
}
.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }

.scrollcue { display: none; }

/* ---------- Credential strip -- REMOVED (v29) -----------------
   The ruled row of five registrations that sat directly under the
   hero is gone at the client's request. The same facts are still
   on the page, in the Regulation section, where they are stated
   in full rather than abbreviated to a chip. */

/* ---------- Section heads ---------- */
.sechead { max-width: 46rem; }
.sechead .h2 { margin-top: 0.75rem; }
.sechead .lead { margin-top: 1rem; }
.sechead--wide { max-width: 56rem; }
.lede { max-width: 44rem; margin-inline: auto; text-align: center; }
.lede .h2 { margin-top: 0.75rem; }
.lede .lead { margin-top: 1rem; margin-inline: auto; }

/* Section label: mono number, mono label, then a rule that runs out
   to the edge of the column. The rule is what ties the section
   openers to the vertical hairlines on .wrap. */
.seclabel {
  display: flex; align-items: center; gap: 0.7rem;
  font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 1.1rem;
}
.seclabel__n { color: var(--brand); font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.09em; font-variant-numeric: tabular-nums; }
.seclabel::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* ============================================================
   PROSE DEFAULTS
   ------------------------------------------------------------
   The legal and policy pages set their body as bare h3 / p / ul
   straight inside .wrap, with no wrapper to hang styles on. Give
   that the same rhythm, measure and hairline rules as the rest
   of the site so those pages read as typeset documents instead
   of as unstyled text. Scoped to unclassed elements so nothing
   that already carries a class is touched.
   ============================================================ */
.wrap > h3:not([class]) {
  font-family: var(--font-sans); font-size: 1.05rem; font-weight: 600;
  letter-spacing: -0.005em; color: var(--ink);
  margin-top: 2.6rem; padding-top: 1.5rem; margin-bottom: 0.7rem;
  border-top: 1px solid var(--line);
}
.wrap > h3:not([class]):first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.wrap > h4:not([class]) { font-family: var(--font-sans); font-size: 0.98rem; font-weight: 600; margin-top: 1.6rem; margin-bottom: 0.45rem; }
.wrap > p:not([class]) { color: var(--muted); max-width: 74ch; margin-bottom: 1rem; }
.wrap > ul:not([class]), .wrap > ol:not([class]) {
  color: var(--muted); max-width: 74ch; margin: 0 0 1.3rem 1.15rem;
  display: grid; gap: 0.55rem;
}
.wrap > ul:not([class]) li::marker, .wrap > ol:not([class]) li::marker { color: var(--line-strong); }
.wrap > h3:not([class]) + p:not([class]) { margin-top: 0; }

/* ---------- Statement ---------- */
.statement { max-width: 52rem; }
.statement .h2 { margin-bottom: 1.3rem; }
.statement p { font-size: clamp(1.06rem, 1.45vw, 1.28rem); line-height: 1.55; color: var(--muted); max-width: 42ch; font-family: var(--font-display); }
.statement--center { margin-inline: auto; text-align: center; }
.statement--center p { max-width: 34ch; margin-inline: auto; }

/* ---------- Promise ---------- */
.promise { max-width: 46rem; }
.promise__quote { font-family: var(--font-display); font-size: clamp(1.35rem, 2.3vw, 1.85rem); line-height: 1.32; color: var(--ink); }
.promise__quote strong { color: var(--faint); font-weight: 400; }
.promise__body { margin-top: 1.5rem; font-size: 1.02rem; line-height: 1.65; color: var(--muted); max-width: 54ch; }
.promise__rule { width: 40px; height: 2px; background: var(--accent); margin-bottom: 1.8rem; }

/* ---------- Numbered index + panel (tabs) ---------- */
/* Left column is a numbered contents list; the selected entry shows its
   image slot and copy on the right. Same markup and same script as the
   old horizontal tabs — only the geometry changed. */
.tabs { margin-top: clamp(2rem, 4vw, 3.2rem); display: grid; grid-template-columns: minmax(210px, 17rem) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
.tabs__list { display: flex; flex-direction: column; gap: 0; border-bottom: 0; grid-column: 1; grid-row: 1; }
.tabs__tab {
  appearance: none; background: none; border: 0; cursor: pointer; font: inherit;
  padding: 0.7rem 0; display: grid; grid-template-columns: 2.6rem 1fr auto; align-items: baseline; gap: 0.5rem;
  text-align: left; font-size: 0.98rem; font-weight: 500; color: var(--faint);
  transition: color 0.22s var(--ease);
}
.tabs__tab::after { content: '›'; font-size: 1.1rem; line-height: 1; color: var(--line-strong); transition: color 0.22s var(--ease), transform 0.22s var(--ease); }
.tabs__tab .tabs__n { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 0.82rem; letter-spacing: 0.04em; color: inherit; }
.tabs__tab:hover { color: var(--ink-soft); }
.tabs__tab[aria-selected="true"] { color: var(--ink); font-weight: 600; }
.tabs__tab[aria-selected="true"] .tabs__n { color: var(--brand); }
.tabs__tab[aria-selected="true"]::after { color: var(--brand); transform: translateX(2px); }

.tabs__panel { grid-column: 2; grid-row: 1; display: block; }
.tabs__panel[hidden] { display: none; }
.tabs__panel[data-active] { animation: panelin 0.45s var(--ease) both; }
@keyframes panelin { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .tabs__panel[data-active] { animation: none; } }

/* Image slot first, copy underneath — the reference stacking. */
.tabs__media { position: relative; overflow: hidden; border-radius: var(--radius-lg); background: var(--soft); border: 1px solid var(--line); aspect-ratio: 16 / 10; display: grid; place-items: center; margin-bottom: 1.6rem; }
.tabs__media > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.tabs__body h3 { font-family: var(--font-sans); font-size: 1.18rem; font-weight: 600; letter-spacing: -0.01em; }
.tabs__body > p { color: var(--muted); margin-top: 0.7rem; font-size: 0.98rem; max-width: 52ch; }
.tabs__points { list-style: none; margin-top: 1.3rem; display: grid; gap: 0.55rem; }
.tabs__points li { position: relative; padding-left: 1.15rem; font-size: 0.95rem; color: var(--muted); }
.tabs__points li::before { content: ''; position: absolute; left: 0; top: 0.6em; width: 4px; height: 4px; border-radius: 50%; background: var(--accent); }
.tabs__cta { margin-top: 1.6rem; }
@media (max-width: 860px) {
  .tabs { grid-template-columns: 1fr; gap: 1.6rem; }
  .tabs__list { grid-column: 1; grid-row: 1; }
  .tabs__panel { grid-column: 1; grid-row: 2; }
}

/* ---------- Split feature ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.split--textfirst .split__media { order: 2; }
.split__media { position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4/3; background: var(--soft); border: 1px solid var(--line); display: grid; place-items: center; }
.split__media > img, .split__media > .ph { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.ph { display: grid; place-items: center; background: var(--soft); color: var(--faint); font-family: var(--font-sans); font-size: 0.82rem; letter-spacing: 0.06em; text-transform: uppercase; }
.ph--navy { background: var(--soft); }

/* ---------- Cards: brands ---------- */
.brandcards { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.brandcard {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
  display: flex; flex-direction: column; overflow: hidden; padding: 0;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.brandcard:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); }
/* 21/9, not 16/9 — see v21 in the notes at the foot of this file. */
.brandcard__media { position: relative; aspect-ratio: 21/9; overflow: hidden; background: var(--soft); border-bottom: 1px solid var(--line); display: grid; place-items: center; }
.brandcard__media > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.brandcard__inner { padding: clamp(1.5rem, 2.4vw, 2rem); display: flex; flex-direction: column; flex: 1; }
.brandcard h3 { font-family: var(--font-sans); font-size: 1.18rem; font-weight: 600; letter-spacing: -0.01em; }
.brandcard p { color: var(--muted); margin-top: 0.6rem; font-size: 0.96rem; }
.brandcard__mark { height: 26px; width: auto; align-self: flex-start; margin-bottom: 1.2rem; }
.brandcard__sites { margin-top: auto; padding-top: 1.4rem; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.sitepill {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.83rem; font-weight: 500; color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  padding: 0.42rem 0.85rem; transition: border-color 0.22s var(--ease), color 0.22s var(--ease);
}
.sitepill:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-50); }

/* ---------- Brand architecture (v10) ----------------------------
   The "United under one goal" diagram off jpmorganchase.com/about:
   the parent mark on top, a bracket, and each child brand shown as
   its own mark with one line saying who it serves. It answers the
   only question a stranger has on a group site — which of these do
   I actually deal with — before they read a single card.

   HTML and CSS, never SVG: the marks are the real logo files, the
   bracket is two borders, and the type stays live so it reflows and
   stays legible on a phone. Same rule as the .infog layer.        */
.barch { display: grid; justify-items: center; gap: 0; width: 100%; }
.barch__parent {
  font-family: var(--font-sans); font-weight: 600; font-size: 0.78rem;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill); padding: 0.5rem 1.1rem;
}
.band--warm .barch__parent { border-color: var(--warm-line); }
/* The bracket. A stem down from the parent, then a rule with two legs
   dropping to the children — all borders, so it inherits the hairline
   colour on both the white and the warm ground. */
.barch__stem { width: 1px; height: 26px; background: var(--line-strong); }
.barch__bracket {
  width: 100%; height: 22px;
  border-left: 1px solid var(--line-strong);
  border-right: 1px solid var(--line-strong);
  border-top: 1px solid var(--line-strong);
}
.barch__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
.barch__cell { min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 0.7rem; text-align: center; padding: 1.25rem 0.75rem 0; }
.barch__cell img { height: 24px; width: auto; }
.barch__role { font-size: 0.85rem; line-height: 1.55; color: var(--muted); max-width: 22ch; }
.band--warm .barch__stem { background: var(--warm-line); }
.band--warm .barch__bracket { border-color: var(--warm-line); }
@media (max-width: 520px) {
  /* Stacked, the bracket is drawing a relationship that is no longer
     there. Drop it and let the two children read as a plain list. */
  .barch__bracket { display: none; }
  .barch__row { grid-template-columns: minmax(0, 1fr); gap: 1.4rem; }
  .barch__cell { padding-top: 1.4rem; }
}

/* ---------- Three-up feature cards ---------- */
/* Tinted slot on top, heading and grey copy beneath — reference 3. */
.trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem, 3vw, 2.4rem); }
.trio__item .frame { margin-bottom: 1.3rem; aspect-ratio: 4 / 3.4; }
.trio__item h3 { font-family: var(--font-sans); font-size: 1.05rem; font-weight: 600; letter-spacing: -0.005em; }
.trio__item p { color: var(--muted); font-size: 0.95rem; margin-top: 0.6rem; }
/* Goldman's three-across cards close on a bare arrow rather than a
   button. It reads as "there is more here" without adding a third
   button weight to a section that already has two. */
.trio__go {
  display: inline-flex; align-items: center; margin-top: 1rem;
  font-size: 1.05rem; color: var(--brand);
  transition: transform 0.25s var(--ease);
}
.trio__item:hover .trio__go { transform: translateX(4px); }
@media (max-width: 900px) { .trio { grid-template-columns: 1fr; } }

/* ---------- Regulation ---------- */
/* minmax(0,…) plus min-width:0 on the children, both load-bearing. The
   coverage matrix inside this grid carries a min-width so it stays
   readable, and it scrolls inside .dscroll. Without these two, that
   min-width floors the track and pushes the whole page sideways. */
.regsplit { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
.regsplit > * { min-width: 0; }
.regbadges { display: grid; gap: 0.9rem; }
.regbadges--row { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: clamp(1.4rem, 3vw, 2.2rem); }
@media (max-width: 860px) { .regbadges--row { grid-template-columns: minmax(0, 1fr); } }
.regbadge { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.3rem 1.4rem; transition: border-color 0.3s var(--ease); }
.regbadge:hover { border-color: var(--brand-200); }
.regbadge__code { font-family: var(--font-sans); font-size: 0.92rem; font-weight: 700; letter-spacing: 0.02em; color: var(--ink); }
.regbadge__name { font-size: 0.84rem; font-weight: 500; color: var(--faint); margin-top: 0.15rem; }
.regbadge__note { font-size: 0.9rem; color: var(--muted); margin-top: 0.6rem; }
.proofline { border-left: 2px solid var(--accent); padding-left: 1.3rem; margin-top: 1.8rem; font-size: 1rem; color: var(--muted); max-width: 56ch; }

/* ---------- Lists ---------- */
.svclist { display: grid; grid-template-columns: 1fr 1fr; gap: 0 clamp(2rem, 5vw, 4rem); border-top: 1px solid var(--line); }
.svc { display: grid; gap: 0.25rem; padding-block: 1.25rem; border-bottom: 1px solid var(--line); }
.svc dt { font-weight: 600; font-size: 0.99rem; color: var(--ink); }
.svc dd { color: var(--muted); font-size: 0.94rem; }

.steps { display: grid; gap: 0; border-top: 1px solid var(--line); max-width: 60rem; }
.stepr { display: grid; grid-template-columns: 4rem 1fr; gap: clamp(1rem, 3vw, 2rem); padding-block: clamp(1.5rem, 3vw, 2.2rem); border-bottom: 1px solid var(--line); }
.stepr__n { font-family: var(--font-sans); font-size: 0.9rem; font-weight: 600; color: var(--faint); font-variant-numeric: tabular-nums; padding-top: 0.35rem; }
.stepr h3 { font-family: var(--font-sans); font-size: 1.1rem; font-weight: 600; margin-bottom: 0.5rem; }
.stepr p { color: var(--muted); max-width: 56ch; font-size: 0.96rem; }

.divisions { border-top: 1px solid var(--line); }
.division {
  display: grid; grid-template-columns: 4rem 1fr minmax(0, 28rem);
  gap: clamp(1rem, 3vw, 2.5rem); align-items: start;
  padding-block: clamp(1.6rem, 3vw, 2.4rem);
  border-bottom: 1px solid var(--line);
  transition: background 0.3s var(--ease);
}
.division:hover { background: var(--soft); }
.division__n { font-family: var(--font-sans); font-size: 0.9rem; font-weight: 600; color: var(--faint); font-variant-numeric: tabular-nums; padding-top: 0.3rem; }
.division h3 { font-family: var(--font-sans); font-size: clamp(1.15rem, 1.8vw, 1.4rem); font-weight: 600; }
.division p { color: var(--muted); font-size: 0.97rem; }
.division__more { margin-top: 0.8rem; }

/* ---------- Join us / CTA ---------- */
.joinus { max-width: 44rem; }
.joinus .h2 { margin-bottom: 0.9rem; }
.joinus p { color: var(--muted); font-size: 1.05rem; margin-bottom: 1.9rem; max-width: 50ch; }
.ctaband { text-align: center; max-width: 60ch; margin: 0 auto; }
.ctaband h2 { margin-bottom: 0.9rem; }
.ctaband p { color: var(--muted); margin-bottom: 1.9rem; }

/* ---------- Bento / verticals / doors ---------- */
.bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem; }
.bento > * { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.6rem; transition: border-color 0.3s var(--ease); }
.bento > *:hover { border-color: var(--brand-200); }
.bento .span-3 { grid-column: span 3; } .bento .span-2 { grid-column: span 2; } .bento .span-4 { grid-column: span 4; } .bento .span-6 { grid-column: span 6; }
.bento .feature__ico { width: 38px; height: 38px; border-radius: 10px; background: var(--soft); color: var(--ink); display: grid; place-items: center; margin-bottom: 1rem; }
.bento h3 { font-family: var(--font-sans); font-size: 1.02rem; font-weight: 600; margin-bottom: 0.4rem; }
.bento p { color: var(--muted); font-size: 0.94rem; }
.bento .accent-card { background: var(--soft); border-color: var(--line); }

.verticals { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.vertical { position: relative; border-radius: var(--radius-lg); padding: clamp(1.6rem, 2.6vw, 2.4rem); background: var(--paper); border: 1px solid var(--line); transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease); }
.vertical:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); }
.vertical__tag { font-size: 0.78rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); font-weight: 600; }
.vertical h3 { font-family: var(--font-sans); font-size: 1.15rem; font-weight: 600; margin: 0.7rem 0 0.5rem; }
.vertical p { color: var(--muted); max-width: 46ch; font-size: 0.96rem; }
.vertical__list { list-style: none; margin-top: 1.3rem; display: grid; gap: 0.6rem; }
.vertical__list li { display: flex; gap: 0.6rem; align-items: flex-start; font-size: 0.95rem; color: var(--muted); }
.vertical__list .dot { color: var(--accent); flex: none; margin-top: 0.15rem; }
.vertical__cta { margin-top: 1.6rem; }

.doors { display: grid; grid-template-columns: repeat(12, 1fr); gap: 1rem; }
.door { position: relative; grid-column: span 4; min-height: 300px; border-radius: var(--radius-lg); overflow: hidden; background: var(--soft); color: var(--ink); cursor: pointer; display: flex; flex-direction: column; justify-content: flex-end; padding: 1.6rem; border: 1px solid var(--line); transition: border-color 0.3s var(--ease); }
.door:hover { border-color: var(--line-strong); }
.door__bg, .door__veil { display: none; }
.door__content { position: relative; z-index: 2; }
.door__num { font-size: 0.78rem; letter-spacing: 0.12em; color: var(--faint); text-transform: uppercase; }
.door__title { font-family: var(--font-sans); font-size: 1.15rem; font-weight: 600; margin: 0.4rem 0 0.35rem; }
.door__desc { font-size: 0.92rem; color: var(--muted); max-width: 34ch; }
.door__link { margin-top: 1rem; font-size: 0.85rem; font-weight: 600; color: var(--brand); display: inline-flex; align-items: center; gap: 0.4rem; }
.door--wide { grid-column: span 8; } .door--tall { grid-column: span 6; } .door--lead { grid-column: span 12; min-height: 220px; }

/* ---------- Metrics / figures / stats ---------- */
.metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1.4rem, 3vw, 2.4rem); }
.metric { border-left: 2px solid var(--brand-500); padding: 0.1rem 0 0.3rem 1.25rem; }
.metric .n { font-family: var(--font-display); font-size: clamp(2.2rem, 4vw, 3.1rem); color: var(--ink); line-height: 1; }
.metric .n .u { color: var(--faint); }
.metric .l { color: var(--muted); font-size: 0.92rem; margin-top: 0.55rem; max-width: 22ch; }
.metric--onnavy .n { color: var(--ink); } .metric--onnavy .l { color: var(--muted); }

/* Figures: reference A hangs each number off a vertical rule rather
   than sitting it under a horizontal one. It reads as a measured
   quantity instead of a card, and it lets the row breathe. */
.figures__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1.5rem, 3vw, 2.5rem); }
.figure { border-left: 2px solid var(--brand-500); padding: 0.1rem 0 0.35rem 1.25rem; }
.figure .n { font-family: var(--font-display); font-size: clamp(2.4rem, 5vw, 3.7rem); line-height: 1; color: var(--ink); }
.figure .n .u { color: var(--faint); font-size: 0.55em; margin-left: 0.1em; }
.figure .l { color: var(--muted); font-size: 0.9rem; margin-top: 0.6rem; max-width: 24ch; }

.statband, .statband3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem, 3vw, 2.5rem); }
.stat { border-left: 2px solid var(--brand-500); padding: 0.1rem 0 0.3rem 1.25rem; }
.stat .n { font-family: var(--font-display); font-size: clamp(2rem, 3.4vw, 2.8rem); color: var(--ink); line-height: 1; }
.stat .n .u { color: var(--faint); }
.stat .l { color: var(--muted); font-size: 0.93rem; margin-top: 0.55rem; }

.process { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.2rem; }
.step { position: relative; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.step__n { font-family: var(--font-sans); font-size: 0.85rem; font-weight: 600; color: var(--faint); font-variant-numeric: tabular-nums; }
.step h3 { font-family: var(--font-sans); font-size: 1.02rem; font-weight: 600; margin: 0.5rem 0 0.45rem; }
.step p { font-size: 0.93rem; color: var(--muted); }

/* ---------- Accordion ---------- */
.compliance { display: grid; grid-template-columns: 0.8fr 1.2fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.acc { border-top: 1px solid var(--line); }
.acc__item { border-bottom: 1px solid var(--line); }
.acc__btn { width: 100%; text-align: left; background: none; border: 0; cursor: pointer; padding: 1.25rem 0; display: flex; justify-content: space-between; align-items: center; gap: 1rem; font-family: var(--font-sans); font-size: 1.02rem; font-weight: 500; color: var(--ink); }
.acc__btn .ico { flex: none; width: 22px; height: 22px; display: grid; place-items: center; transition: transform 0.3s var(--ease); color: var(--faint); font-family: var(--font-sans); font-size: 1.05rem; border: 0; }
.acc__item.open .acc__btn .ico { transform: rotate(45deg); color: var(--brand); }
.acc__panel { max-height: 0; overflow: hidden; transition: max-height 0.4s var(--ease); }
.acc__panel p { color: var(--muted); font-size: 0.96rem; padding-bottom: 1.25rem; max-width: 66ch; }

/* ---------- People ---------- */
.people { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.person { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease); }
.person:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); }
.person__photo { position: relative; aspect-ratio: 4/5; background: var(--soft); overflow: hidden; display: grid; place-items: center; border-bottom: 1px solid var(--line); }
.person__photo > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.person__photo .mono { font-family: var(--font-sans); font-size: 0.82rem; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); }
.person__body { padding: 1.2rem 1.3rem 1.4rem; }
.person__name { font-family: var(--font-sans); font-size: 1.05rem; font-weight: 600; }
.person__role { font-size: 0.84rem; color: var(--faint); font-weight: 500; margin-top: 0.2rem; }
.person__bio { font-size: 0.92rem; color: var(--muted); margin-top: 0.65rem; }

/* ---------- News ---------- */
.news { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; display: flex; flex-direction: column; transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease); }
.card:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); }
.card__media { position: relative; aspect-ratio: 16/9; background: var(--soft); border-bottom: 1px solid var(--line); display: grid; place-items: center; overflow: hidden; }
.card__media > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.card__body { padding: 1.2rem 1.3rem 1.5rem; flex: 1; display: flex; flex-direction: column; }
.card__title { font-family: var(--font-sans); font-size: 1.04rem; font-weight: 600; line-height: 1.35; margin: 0.45rem 0; }
.card__date { font-size: 0.81rem; color: var(--faint); }
.card__excerpt { font-size: 0.92rem; color: var(--muted); margin-top: 0.5rem; }
.card__more { margin-top: auto; padding-top: 1rem; font-size: 0.87rem; font-weight: 600; color: var(--brand); display: inline-flex; gap: 0.4rem; align-items: center; }

/* ---------- Insights grid (v12) -------------------------------
   Was a horizontal scroller that bled off the right edge. Two
   problems with that: the fourth story was invisible unless you
   thought to drag, and a sideways-scrolling row inside a normally
   scrolling page is the other big "slide deck" tell. All four now
   sit in a grid that reflows 4 -> 2 -> 1. */
.railhead { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.newsgrid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.2rem; margin-top: clamp(1.8rem, 3vw, 2.6rem);
}
@media (max-width: 1040px) { .newsgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .newsgrid { grid-template-columns: minmax(0, 1fr); } }
.railcard { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; display: flex; flex-direction: column; transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease); }
.railcard:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); }
.railcard__media { position: relative; aspect-ratio: 16/10; overflow: hidden; background: var(--soft); border-bottom: 1px solid var(--line); display: grid; place-items: center; }
.railcard__media > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.railcard__body { padding: 1.3rem 1.4rem 1.5rem; display: flex; flex-direction: column; flex: 1; }
.railcard__kind { font-size: 0.77rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--brand); }
.railcard__title { font-family: var(--font-sans); font-size: 1rem; font-weight: 600; line-height: 1.35; margin-top: 0.55rem; color: var(--ink); }
.railcard__date { font-size: 0.81rem; color: var(--faint); margin-top: auto; padding-top: 1rem; }

/* ---------- Segments ---------- */
.dualsegment { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.segment { position: relative; border-radius: var(--radius-lg); padding: clamp(1.6rem, 2.8vw, 2.4rem); overflow: hidden; min-height: 260px; display: flex; flex-direction: column; justify-content: flex-end; color: var(--ink); background: var(--paper); border: 1px solid var(--line); transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease); }
.segment:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); }
.segment--hni, .segment--retail { background: var(--paper); }
.segment h3 { font-family: var(--font-sans); font-size: 1.25rem; font-weight: 600; margin-top: 0.5rem; }
.segment p { color: var(--muted); font-size: 0.96rem; max-width: 38ch; margin-top: 0.6rem; }
.segment .btn { margin-top: 1.3rem; align-self: flex-start; }

/* ============================================================
   MICRO-LABEL CONSOLIDATION
   ------------------------------------------------------------
   Everything on the site that is a code, a count, a date or a
   category — not prose — is set in the mono face at one size.
   Collected here rather than repeated so the smallest type on
   the site can only ever change in one place.
   ============================================================ */
.railcard__kind, .card__date, .railcard__date, .vertical__tag,
.door__num, .step__n, .stepr__n, .division__n, .person__role,
.footer__col h4, .table th, .regbadge__name, .frame__hint,
.person__photo .mono, .ph, .breadcrumb, .grouptag {
  font-family: var(--font-mono);
  letter-spacing: 0.07em;
  font-variant-numeric: tabular-nums;
}
.railcard__kind, .vertical__tag, .door__num, .footer__col h4,
.table th, .frame__hint, .person__photo .mono, .ph {
  text-transform: uppercase; font-weight: 500;
}
.regbadge__code { font-family: var(--font-mono); letter-spacing: 0.04em; color: var(--brand); }

/* ---------- Odds and ends ---------- */
.pill { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.81rem; font-weight: 500; padding: 0.38rem 0.8rem; border-radius: var(--radius-pill); background: var(--soft); color: var(--muted); border: 1px solid var(--line); }
.pill--ghost, .pill--navy { background: var(--soft); border: 1px solid var(--line); color: var(--muted); }

.certs { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.cert { display: inline-flex; align-items: center; gap: 0.5rem; border: 1px solid var(--line); border-radius: var(--radius-pill); padding: 0.45rem 0.9rem; font-size: 0.84rem; font-weight: 500; color: var(--muted); background: var(--paper); transition: border-color 0.25s var(--ease); }
.cert:hover { border-color: var(--brand-200); }
.cert .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); flex: none; }

.quote { font-family: var(--font-display); font-size: clamp(1.4rem, 2.6vw, 2.05rem); line-height: 1.3; color: var(--ink); max-width: 26ch; }
.quotegrid { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem; }
.attr { margin-top: 1.2rem; font-size: 0.9rem; color: var(--faint); }

.logos { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.9rem; }
.logo { height: 58px; border: 1px solid var(--line); border-radius: var(--radius); display: grid; place-items: center; color: var(--faint); font-weight: 500; font-size: 0.83rem; background: var(--paper); }

/* A quiet band, used where a section needs to separate from its
   neighbours. This is what `.dark` and `.ecosystem` now resolve to —
   there is no dark section anywhere on the site. */
.band, .ecosystem, .dark, .dark--blue { background: var(--brand-50); color: var(--ink); }
.band .frame, .ecosystem .frame, .band .card, .ecosystem .card,
.band .brandcard, .ecosystem .brandcard, .band .person, .ecosystem .person,
.band .railcard, .ecosystem .railcard, .band .segment, .ecosystem .segment { background: var(--paper); }
.band .marquee::before, .band .marquee::after { background: none; }

/* The warm variant (v10). Same band, warm ground. Scoped to a modifier
   rather than retinting .band itself so the other seventeen pages are
   untouched until this is signed off on the homepage. The hairline has
   to move with it — a cool #e2e6f1 rule on cream reads faintly lilac. */
.band--warm { background: var(--warm-50); }
.band--warm .frame, .band--warm .tabs__media,
.band--warm .brandcard__media, .band--warm .railcard__media { background: var(--warm-100); }
.band--warm .frame, .band--warm .card, .band--warm .brandcard,
.band--warm .person, .band--warm .railcard, .band--warm .segment,
.band--warm .infog, .band--warm .vertical, .band--warm .bento > *,
.band--warm .regbadge { border-color: var(--warm-line); }
.band--warm .divide-top, .band--warm hr { border-color: var(--warm-line); }

.moment { position: relative; }
.disclaimer { font-size: 0.8rem; line-height: 1.7; color: var(--faint); }
.disclaimer strong { color: var(--muted); }

/* ---------- Tables ---------- */
.tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); }
.table { width: 100%; border-collapse: collapse; font-size: 0.94rem; min-width: 520px; }
.table th, .table td { text-align: left; padding: 0.95rem 1.05rem; border-bottom: 1px solid var(--line); }
.table th { font-size: 0.79rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); font-weight: 600; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--soft); }
.table .y { color: var(--ink); font-weight: 600; }
.table .n { color: var(--faint); font-weight: 600; }

/* ---------- Forms ---------- */
.form { display: grid; gap: 1rem; max-width: 560px; }
.field { display: grid; gap: 0.4rem; }
.field label { font-size: 0.86rem; font-weight: 500; color: var(--muted); }
.field input, .field textarea, .field select { font-family: var(--font-sans); font-size: 0.95rem; padding: 0.8rem 0.95rem; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--paper); color: var(--ink); transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease); }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(14, 14, 17, 0.07); outline: none; }
.field textarea { min-height: 130px; resize: vertical; }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }

/* ---------- Contact ---------- */
.contactsplit { display: grid; grid-template-columns: 1fr 0.9fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.contactinfo { display: grid; gap: 1.3rem; }
.contactinfo .ci { display: flex; gap: 0.85rem; align-items: flex-start; }
.contactinfo .ci .ico { width: 36px; height: 36px; border-radius: 10px; background: var(--soft); color: var(--ink); display: grid; place-items: center; flex: none; }
.contactinfo .ci h4 { font-family: var(--font-sans); font-size: 0.96rem; font-weight: 600; }
.contactinfo .ci p { font-size: 0.93rem; color: var(--muted); margin-top: 0.15rem; }

/* ---------- Page hero (inner pages) ---------- */
.pagehero, .pagehero--dark { background: var(--paper); color: var(--ink); padding: clamp(7.5rem, 11vw, 9.5rem) var(--gutter) clamp(2.75rem, 5vw, 4.5rem); position: relative; border-bottom: 1px solid var(--line); }
.pagehero::before, .pagehero::after { content: none; }
.pagehero__inner { position: relative; z-index: 2; max-width: var(--maxw); margin: 0 auto; }
.pagehero h1 { max-width: 17ch; margin-top: 1rem; font-size: clamp(2.3rem, 4.6vw, 3.6rem); }
.pagehero p.lead { margin-top: 1.2rem; }
.pagehero--dark h1, .pagehero--dark p.lead { color: inherit; }
.breadcrumb { font-size: 0.83rem; color: var(--faint); }
.breadcrumb a:hover { color: var(--brand); }
.hero--dark { background: var(--paper); color: var(--ink); }
.hero--dark h1, .hero--dark .h2 { color: var(--ink); }
.hero--dark p.lead { color: var(--muted); }

/* ---------- Footer ---------- */
.footer { background: var(--paper); color: var(--muted); border-top: 1px solid var(--line); }
.footer__top { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 2rem; padding-block: clamp(3rem, 5.5vw, 4.5rem); }
.footer__brand .brand { margin-bottom: 1rem; }
.footer__brand p { color: var(--muted); font-size: 0.92rem; max-width: 34ch; }
.footer__col h4 { font-family: var(--font-sans); font-size: 0.79rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); margin-bottom: 0.9rem; font-weight: 600; }
.footer__col a { display: block; color: var(--muted); font-size: 0.92rem; padding: 0.3rem 0; transition: color 0.22s var(--ease); }
.footer__col a:hover { color: var(--brand); }
.footer__bottom { border-top: 1px solid var(--line); padding-block: 1.5rem; display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; font-size: 0.83rem; color: var(--faint); }
.footer__bottom a:hover { color: var(--ink); }
.grouptag { border-top: 1px solid var(--line); padding-block: 1.3rem; font-size: 0.87rem; color: var(--faint); }
.grouptag a { color: var(--muted); border-bottom: 1px solid var(--line); }
.grouptag a:hover { color: var(--brand); border-color: var(--brand); }

/* ---- INFOGRAPHICS ----------------------------------------------
   A .infog is a drawn explanation that occupies the slot a photograph
   would. It carries the same ground, hairline and radius as .frame, so
   a page that mixes drawn and photographic slots still reads as one
   system.

   Everything here is HTML and CSS. No SVG text, no asset files. That is
   deliberate: text inside a scaled <svg> shrinks with the viewBox and
   becomes unreadable on a phone, and an exported diagram goes stale the
   moment the palette moves. These restyle themselves from the tokens.

   Six diagram types, each with one job:
     .dconv    many inputs resolve into one thing
     .dchart   a quantity climbing toward a target
     .dstack   layers sitting on a shared foundation
     .dflow    a sequence, with a path we do NOT take
     .dtree    an entity structure
     .dmatrix  who is covered by what, and where
------------------------------------------------------------------ */
.infog {
  position: relative; display: flex; flex-direction: column; gap: 1.05rem;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: clamp(1.15rem, 2.6vw, 1.75rem);
}
/* When it stands in for a photo slot it takes the slot's tinted ground. */
.infog--slot { background: var(--soft); }
.infog__cap {
  display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap;
  font-family: var(--font-mono); font-size: 0.77rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faint);
}
.infog__cap b { color: var(--brand); font-weight: 600; }
.infog__body { flex: 1; display: flex; flex-direction: column; justify-content: center; }
/* The diagram classes below re-declare display:grid on this same element.
   justify-content:center means "centre the children vertically" in flex
   column, but "centre the column TRACKS horizontally" in grid — which
   collapsed the chart into a narrow strip. Every grid diagram therefore
   states its own single full-width column and resets the alignment. */
.dchart, .dstack, .dtree { grid-template-columns: minmax(0, 1fr); justify-content: stretch; }
.dconv { justify-content: stretch; }
/* The disclaimer line. On a regulated site an illustrative diagram has
   to say so, in the diagram, not in a footnote somewhere else. */
.infog__note {
  margin-top: auto; padding-top: 0.8rem; border-top: 1px solid var(--line-faint);
  font-size: 0.82rem; line-height: 1.5; color: var(--muted);
}

/* Shared node chip. Every box in every diagram is one of these. */
.dnode {
  display: flex; align-items: center; gap: 0.5rem; min-width: 0;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius-xs); padding: 0.5rem 0.7rem;
  font-size: 0.82rem; font-weight: 500; line-height: 1.3; color: var(--ink-soft);
}
.dnode--key { background: var(--brand-50); border-color: var(--brand); color: var(--ink); font-weight: 600; }
.dnode--quiet { border-style: dashed; color: var(--faint); background: transparent; }
.dnode--centre { justify-content: center; text-align: center; }
.dnode__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); flex: none; }
.dnode--stack { flex-direction: column; align-items: center; text-align: center; gap: 0.2rem; }
.dnode small { font-size: 0.79rem; font-weight: 500; line-height: 1.35; color: var(--faint); }

/* 1 · Convergence — a column of inputs collected into one outcome. */
.dconv { display: grid; grid-template-columns: minmax(0, 1fr) 30px minmax(0, 0.9fr); align-items: center; }
.dconv__in { display: grid; gap: 0.4rem; }
.dconv__join { position: relative; align-self: stretch; margin-block: 0.9rem; }
.dconv__join::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: 12px;
  border: 1px solid var(--line-strong); border-left: 0;
  border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
}
.dconv__join::after {
  content: ''; position: absolute; left: 12px; right: 0; top: 50%;
  height: 1px; background: var(--brand-500);
}

/* 2 · Bar chart — contributions climbing toward a goal line. Bar
   heights are inline (they are data, not styling). */
.dchart { display: grid; gap: 0.55rem; }
.dchart__plot {
  position: relative; display: flex; align-items: flex-end;
  gap: clamp(3px, 0.9vw, 7px); height: clamp(104px, 15vw, 148px);
  border-bottom: 1px solid var(--line-strong);
}
.dchart__bar { flex: 1; min-width: 0; background: var(--brand-200); border-radius: 2px 2px 0 0; }
.dchart__bar:last-child { background: var(--brand); }
.dchart__goal { position: absolute; left: 0; right: 0; top: 6%; border-top: 1px dashed var(--accent); }
.dchart__goal span {
  position: absolute; right: 0; top: -1.3rem; font-family: var(--font-mono);
  font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent);
}
.dchart__x {
  display: flex; justify-content: space-between; gap: 1rem;
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--faint);
}

/* 3 · Stack — surfaces sitting on one shared core. */
.dstack { display: grid; gap: 0; }
.dstack__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.45rem; }
.dstack__link { height: 16px; position: relative; }
.dstack__link::before {
  content: ''; position: absolute; left: 16.66%; right: 16.66%; top: 50%;
  height: 1px; background: var(--line-strong);
}
.dstack__link i { position: absolute; top: 0; height: 50%; width: 1px; background: var(--line-strong); }
.dstack__link i:nth-child(1) { left: 16.66%; }
.dstack__link i:nth-child(2) { left: 50%; }
.dstack__link i:nth-child(3) { left: 83.33%; }
.dstack__link i:nth-child(4) { left: 50%; top: 50%; }
.dstack__base { background: var(--brand-50); border-color: var(--brand-200); }

/* 4 · Flow — the sequence, and the one it is not. */
.dflow { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.dflow__arrow { flex: none; color: var(--brand); font-size: 0.95rem; line-height: 1; }
.dflow__not {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  margin-top: 0.9rem; padding-top: 0.9rem; border-top: 1px dashed var(--line);
}
.dflow__not .dnode { text-decoration: line-through; text-decoration-color: var(--accent); }
.dflow__lbl {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--faint); flex: none;
}

/* 5 · Tree — the group and what hangs off it. */
.dtree { display: grid; gap: 0; }
.dtree__drop { height: 16px; position: relative; }
.dtree__drop::before { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--line-strong); }
.dtree__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; position: relative; }
/* The horizontal bar that gathers the three columns. Its ends stop at
   the centre of the outer columns, not at the edge of the row. */
.dtree__row::before {
  content: ''; position: absolute; top: -16px; left: 16.66%; right: 16.66%;
  height: 1px; background: var(--line-strong);
}
.dtree__col { display: grid; gap: 0.4rem; align-content: start; position: relative; }
.dtree__col::before { content: ''; position: absolute; top: -16px; left: 50%; height: 16px; width: 1px; background: var(--line-strong); }
.dtree__leaf {
  font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.04em;
  color: var(--brand); background: var(--brand-50); border-radius: var(--radius-xs);
  padding: 0.4rem 0.55rem; text-align: center; line-height: 1.35;
}
.dtree__leaf--none { color: var(--faint); background: var(--soft); }

/* 6 · Matrix — coverage, jurisdiction by business.
   No .dscroll wrapper any more. It used to sit in an overflow-x
   box with a 400px min-width, so on a phone the India column was
   off-screen behind a sideways drag — the one column an Indian
   visitor most needs. The table now compresses instead: the
   min-width is gone and the cells tighten under 560px. */
.dmatrix { width: 100%; border-collapse: separate; border-spacing: 0; }
.dmatrix th, .dmatrix td { text-align: left; padding: 0.8rem 0.85rem 0.8rem 0; vertical-align: top; border-bottom: 1px solid var(--line); }
.dmatrix th:last-child, .dmatrix td:last-child { padding-right: 0; }
.dmatrix thead th {
  font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faint); font-weight: 500;
  border-bottom: 1px solid var(--line-strong); padding-top: 0;
}
.dmatrix tbody th { font-family: var(--font-sans); font-size: 0.88rem; font-weight: 600; color: var(--ink); }
.dmatrix tbody tr:last-child th, .dmatrix tbody tr:last-child td { border-bottom: 0; }
/* flex-start, not center: the last row's label wraps to two lines and a
   centred dot floats beside the second line instead of the first. */
.dcell { display: inline-flex; align-items: flex-start; gap: 0.42rem; font-size: 0.82rem; font-weight: 600; color: var(--brand); }
.dcell i { width: 6px; height: 6px; border-radius: 50%; background: var(--brand); flex: none; margin-top: 0.45em; }
.dcell--none { color: var(--faint); font-weight: 500; }
.dcell--none i { background: var(--line-strong); }
/* Compression rather than a sideways drag. */
@media (max-width: 560px) {
  .dmatrix th, .dmatrix td { padding: 0.65rem 0.5rem 0.65rem 0; }
  .dmatrix tbody th { font-size: 0.82rem; }
  .dmatrix td { font-size: 0.82rem; }
  .dcell { font-size: 0.82rem; gap: 0.3rem; }
}

@media (max-width: 520px) {
  /* Under this width a three-column diagram is unreadable, so the
     grouping bars are dropped and everything becomes one column. */
  .dconv { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
  .dconv__join { display: none; }
  /* Stacked, the three branches run together as one list. A bigger gap
     between branches than within one is what re-separates them. */
  .dstack__row, .dtree__row { grid-template-columns: minmax(0, 1fr); }
  .dtree__row { gap: 1.15rem; }
  .dtree__row::before, .dtree__col::before, .dstack__link i { display: none; }
  .dstack__link { height: 10px; }
  .dstack__link::before { left: 50%; right: auto; width: 1px; height: 100%; top: 0; }
}

/* ---------- Reveal ---------- */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: 0.07s; }
.reveal[data-delay="2"] { transition-delay: 0.14s; }
.reveal[data-delay="3"] { transition-delay: 0.21s; }

/* ---------- Responsive ---------- */
/* Between the hamburger breakpoint (860px) and roughly a laptop the
   six nav links plus two CTAs do not fit, and the links wrap to a
   second line inside a fixed-height bar. Tighten the row and drop the
   secondary CTA through that window rather than moving the hamburger
   breakpoint up, which would take the links away from screens that
   can still hold them. */
/* These two nav breakpoints are the only ones on the site written in em
   rather than px, and the reason is SC 1.4.4. Media-query em resolves against
   the browser's default font size, so when someone raises that setting the bar
   collapses before its contents outgrow it. In px the bar kept its desktop
   layout at any font size and pushed "Find your practice" and the CTA off the
   right edge with no way to scroll to them. 65em and 53.75em are 1040px and
   860px at the default 16px, so nothing moves for anyone who has not changed
   that setting. Keep both in em if you retune them. */
@media (max-width: 65em) {
  .nav__links { gap: 1.05rem; }
  .nav__links a { font-size: 0.86rem; white-space: nowrap; }
  .nav__cta .btn--ghost { display: none; }
}

@media (max-width: 1024px) {
  .doors .door { grid-column: span 6; }
  .doors .door--wide, .doors .door--tall { grid-column: span 12; }
  .bento .span-3, .bento .span-2, .bento .span-4 { grid-column: span 3; }
  .footer__top { grid-template-columns: 1fr 1fr; }
  .people, .news { grid-template-columns: repeat(2, 1fr); }
  .process { grid-template-columns: repeat(2, 1fr); }
  .quotegrid { grid-template-columns: 1fr; }
  .logos { grid-template-columns: repeat(2, 1fr); }
  .division { grid-template-columns: 3rem 1fr; }
  .division > p { grid-column: 2; }
  .brandcards { grid-template-columns: 1fr; }
  .regsplit { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1080px) { .figures__grid { grid-template-columns: repeat(2, 1fr); } }
/* The hamburger handover, in em for the reason given above. Everything else
   that used to sit in this block stays on the 860px query below: those are
   content-grid breakpoints and they answer to viewport width, not to type. */
@media (max-width: 53.75em) {
  .nav__links, .nav__cta .btn--ghost { display: none; }
  .nav__toggle { display: block; }
  .brand__sub { display: none; }
}
@media (max-width: 860px) {
  .verticals { grid-template-columns: 1fr; }
  .split { grid-template-columns: 1fr; }
  .split--textfirst .split__media { order: 0; }
  .compliance { grid-template-columns: 1fr; }
  .metrics { grid-template-columns: 1fr 1fr; }
  .statband, .statband3 { grid-template-columns: 1fr; }
  .dualsegment { grid-template-columns: 1fr; }
  .contactsplit { grid-template-columns: 1fr; }
  .form__row { grid-template-columns: 1fr; }
  .svclist { grid-template-columns: 1fr; }
}
@media (max-width: 640px) { .figures__grid { grid-template-columns: 1fr; } }
@media (max-width: 560px) {
  .doors .door { grid-column: span 12; }
  .bento .span-3, .bento .span-2, .bento .span-4 { grid-column: span 6; }
  .metrics { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr; }
  .people, .news, .process { grid-template-columns: 1fr; }
  .logos { grid-template-columns: 1fr; }
  .stepr, .division { grid-template-columns: 1fr; gap: 0.5rem; }
  .stepr__n, .division__n { padding-top: 0; }
  body { font-size: 16px; }
  .brand__logo { height: 25px; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Print ---------- */
@media print {
  .nav, .mobilemenu { display: none; }
  body { background: #fff; }
  .wrap { border-inline: 0; }
}

/* ---------- Scroll to top (v10) ----------------------------------
   Lifted from jpmorganchase.com, where it sits bottom-right on every
   long page. Hidden until you are a screen and a half down, so it
   never competes with the hero. .totop is inert until JS adds .on,
   which keeps it out of the tab order for anyone who has not
   scrolled. */
.totop {
  position: fixed; right: clamp(1rem, 3vw, 2rem); bottom: clamp(1rem, 3vw, 2rem);
  width: 44px; height: 44px; border-radius: 50%; z-index: 60;
  display: grid; place-items: center;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--line-strong); box-shadow: var(--shadow-md);
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease), visibility 0.25s;
}
.totop.on { opacity: 1; visibility: visible; transform: none; }
.totop:hover { border-color: var(--brand); color: var(--brand); }
.totop svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; }
@media print { .totop { display: none; } }

/* ---------- Stage hero (v11) -------------------------------------
   The client asked for a full-screen hero with the photograph behind
   the words and "some blue colour" in it. That is a deliberate,
   scoped exception to rule 1 at the top of this file — it applies to
   .hero--stage on the homepage and nowhere else. Every other section
   is still white or warm.

   The blue is not a flat panel. It is a gradient cut from the logo
   blue (--brand-900) laid over the photograph, heaviest on the left
   where the type sits and thinning to almost nothing on the right so
   the picture still reads as a picture. That is what keeps this from
   becoming the "too much blue" page: the blue is doing legibility
   work, not decoration.

   Contrast floor: white on the lightest point of the scrim over the
   brightest slide measures above 7:1, so the headline, the lead and
   the microline all clear AAA. Test again if a slide is swapped for
   a brighter one. */
.hero--stage {
  min-height: 100svh;
  display: grid; align-items: center;
  padding-block: calc(74px + clamp(2.5rem, 7vw, 5.5rem)) clamp(4.5rem, 9vw, 7rem);
  background: var(--brand-900);
  color: #fff;
  isolation: isolate;
}
@supports not (min-height: 100svh) { .hero--stage { min-height: 100vh; } }

.hero__slides { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hero__slide {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: center 42%;
  opacity: 0; transform: scale(1.055);
  transition: opacity 1.4s var(--ease), transform 9s linear;
  will-change: opacity, transform;
}
.hero__slide.is-on { opacity: 1; transform: scale(1); }

/* Two passes. The first is the horizontal wash that carries the blue
   and buys the type its contrast. The second darkens the bottom edge
   so the microline and the dots do not sit on a bright building.

   The stops are anchored to the copy column, not to percentages.
   Percentages were tried and cannot work: the copy ends at 86% of
   the hero at 760px wide but only 57% at 1728px, so any single
   percentage ramp is either too weak to read at the narrow end or
   heavy enough to erase the photograph at the wide end — which it
   did. --copy-end reproduces the right edge of .hero__copy in
   viewport coordinates ((100vw - maxw)/2 clamped at 0, plus the
   gutter, plus the 46rem copy measure), so the wash stays dense
   under the type and falls away 10rem later at every width.

   90deg, not the old 100deg: with a tilted gradient a px stop
   measures along the gradient line rather than across the page, so
   the stops would no longer line up with the column they exist to
   protect. The diagonal was decoration; the alignment is not.

   The alpha values are a measured trade, not a taste call. Every
   glyph was sampled against all three slides; a heavier ramp was
   tried first and scored 8.7-10.2:1, but it veiled 66-87% of the
   picture — contrast bought by deleting the photograph the hero
   exists to show. A lighter one dropped to 3.68:1 and failed.

   Re-measured 2026-08-12 against the three slides now in the markup
   (boardroom, NYC dusk, Mumbai night), at 390 / 1180 / 1440px, worst
   pixel under each glyph box. The drift moves the crop, so each slide
   was measured at both ends of both keyframes -- scale 1.005 and
   1.075, each with its own translate -- and the figure below is the
   worst of all four states across all three photographs:

     smallest number anywhere      390px   1180px   1440px
       headline (large, 3:1)        4.26     4.52     4.70
       lead, ghost CTA, reg marks   5.78     6.33     5.47
       .gcard--hero, ink on glass     —      7.28     7.21

   The headline over hero-boardroom.jpg is the binding case at every
   width and it is nowhere near failing. The NYC frame's low sun sits
   at the left, directly under the copy column, and the 0.88 end of
   the ramp is what absorbs it. Nothing here needed changing for the
   new photographs. (.gcard--hero is display:none below 860px, which
   is why the third row is empty at 390.)

   Re-measure before touching these, and re-measure whenever a slide
   is swapped: the floor is set by the photograph, not by the CSS. */
.hero__scrim {
  --copy-end: calc(max((100vw - var(--maxw)) / 2, 0px) + var(--gutter) + 46rem);
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(90deg,
      rgba(var(--scrim), 0.88) 0,
      rgba(var(--scrim), 0.80) calc(var(--copy-end) * 0.55),
      rgba(var(--scrim), 0.56) var(--copy-end),
      rgba(var(--scrim), 0.18) calc(var(--copy-end) + 10rem),
      rgba(var(--scrim), 0.07) 100%),
    linear-gradient(to top, rgba(var(--scrim-deep), 0.48) 0%, rgba(var(--scrim-deep), 0) 38%);
}

/* Narrow screens: the horizontal wash cannot work here. --copy-end resolves
   to 20px + 46rem = 756px, so at 375-860px the whole viewport sits inside the
   first two stops (0.88-0.80) and the photograph is erased — the exact failure
   the wash was written to avoid at the wide end. Below 860px the copy spans the
   full column anyway, so there is no column to protect and the ramp turns
   vertical: dense under the headline, lightest under the buttons, closing again
   at the bottom edge for the microline and the dots.

   The alphas are the worst case, not a taste call: composited over a pure-white
   photo pixel, 0.66 navy gives L=0.120, so #fff scores 6.16:1 and the 0.88-white
   microline 5.25:1, both over the 4.5:1 AA floor; the 0.66-white headline half
   scores 3.3:1 against the 3:1 large-text floor. No photograph can score worse
   than white, so this holds for any slide. */
@media (max-width: 860px) {
  .hero__scrim {
    background: linear-gradient(180deg,
      rgba(var(--scrim), 0.80) 0%,
      rgba(var(--scrim), 0.72) 40%,
      rgba(var(--scrim), 0.66) 74%,
      rgba(var(--scrim), 0.74) 100%);
  }
}

.hero--stage .hero__inner {
  z-index: 2;
  min-width: 0;
  border-inline-color: rgba(255, 255, 255, 0.18);
}
.hero--stage .hero__copy { max-width: 46rem; }
.hero--stage .marked::before, .hero--stage .marked::after,
.hero--stage .marked__b::before, .hero--stage .marked__b::after { border-color: rgba(255, 255, 255, 0.34); }

.hero--stage h1 { color: #fff; max-width: 100%; font-size: clamp(2.5rem, 5.4vw, 4.4rem); text-wrap: balance; }
.hero--stage h1 .mute { color: rgba(255, 255, 255, 0.66); }
.hero--stage p.lead { color: rgba(255, 255, 255, 0.94); max-width: 44ch; }
.hero--stage .microline { color: rgba(255, 255, 255, 0.88); margin-top: 3rem; }
.hero--stage .microline svg { stroke: rgba(255, 255, 255, 0.62); }

/* The announce pill and both buttons have to be re-tiered for the
   dark ground. The rule stays the one from the top of this file —
   three tiers, one radius — the values just invert. Primary goes
   white-on-blue rather than blue-on-blue, which would vanish. */
.hero--stage .announce {
  background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.26);
  color: #fff; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.hero--stage .announce:hover { border-color: rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.16); }
.hero--stage .announce__go { background: rgba(255, 255, 255, 0.14); color: #fff; }
.hero--stage .announce:hover .announce__go { background: rgba(255, 255, 255, 0.24); }
.hero--stage .btn--primary { background: #fff; color: var(--brand-900); border-color: #fff; }
.hero--stage .btn--primary:hover { background: rgba(255, 255, 255, 0.88); border-color: rgba(255, 255, 255, 0.88); }
.hero--stage .btn--ghost {
  background: rgba(255, 255, 255, 0.06); color: #fff; border-color: rgba(255, 255, 255, 0.44);
}
.hero--stage .btn--ghost:hover { background: rgba(255, 255, 255, 0.14); border-color: #fff; }
.hero--stage .btn:focus-visible { outline-color: #fff; }

/* Dots. Buttons, so they are reachable and operable from the
   keyboard — an auto-advancing carousel with no manual control is
   the accessibility failure people actually hit. */
.hero__dots {
  position: absolute; z-index: 3; left: 50%; transform: translateX(-50%);
  bottom: clamp(1.6rem, 3.5vw, 2.6rem);
  display: flex; gap: 0.55rem;
}
.hero__dot {
  width: 30px; height: 3px; padding: 0; border: 0; cursor: pointer;
  border-radius: 2px; background: rgba(255, 255, 255, 0.32);
  transition: background 0.3s var(--ease), width 0.3s var(--ease);
}
.hero__dot:hover { background: rgba(255, 255, 255, 0.6); }
.hero__dot.is-on { background: #fff; width: 46px; }
.hero__dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

@media (max-width: 720px) {
  .hero--stage { padding-block: calc(74px + 2.5rem) 5.5rem; }
  .hero--stage .hero__slide { object-position: center 38%; }
  /* Narrow screens have no room for the gradient to fall off
     sideways, so the wash goes vertical instead. */
  .hero__scrim {
    background:
      linear-gradient(to top, rgba(var(--scrim), 0.95) 12%, rgba(var(--scrim), 0.8) 52%, rgba(var(--scrim), 0.52) 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__slide { transition: opacity 0.01ms; transform: none; }
  .hero__slide.is-on { transform: none; }
}

/* ============================================================
   GLASS (v12)
   ------------------------------------------------------------
   Glassmorphism only where there is something behind the glass
   worth blurring. On a mostly-white document a frosted panel over
   white is just a grey box with extra GPU cost, so this is scoped
   to the two places with a photograph underneath: the nav while it
   sits over the hero, and the hero's own controls.

   Every rule pairs backdrop-filter with a solid-ish background
   fallback, because backdrop-filter is the first thing to be
   dropped under Reduce Transparency and in older WebViews. The
   fallback must stay legible on its own.
   ============================================================ */

/* SUPERSEDED BY v59, KEPT ON A DORMANT GUARD. Everything below was
   written when the hero ran full-bleed underneath the fixed nav, so the
   nav had to turn into dark glass with a white logo to sit on the
   photograph. v59 made the hero an inset rounded panel that starts below
   the nav, which puts the bar back on the page ground -- and the dark
   treatment left a white logo on a pale lavender strip.

   The rules are intact but their guard is now `.hero--underlap`, a class
   nothing carries. Put that class on <body> to get the old behaviour
   back; delete the block if the inset hero is permanent.
   (This is also what the reference does: its nav sits on the cream
   ground above the framed hero, not on the image.) */

/* --- Nav over the hero -------------------------------------
   The nav was opaque white glass pinned over a dark blue hero: a
   hard white slab cutting the top off the photograph. Over the
   hero it is now dark glass and reads as part of the image;
   .scrolled (already toggled by main.js at 12px) hands it back to
   the white treatment for the rest of the page. */
.brand__logo--light { display: none; }

@supports selector(:has(*)) {
  body:has(.hero--underlap) .nav:not(.scrolled) {
    background: rgba(var(--scrim), 0.22);
    backdrop-filter: saturate(130%) blur(16px);
    -webkit-backdrop-filter: saturate(130%) blur(16px);
    border-bottom-color: rgba(255, 255, 255, 0.14);
  }
  body:has(.hero--underlap) .nav:not(.scrolled) .nav__links a { color: rgba(255, 255, 255, 0.86); }
  body:has(.hero--underlap) .nav:not(.scrolled) .nav__links a:hover { color: #fff; }
  body:has(.hero--underlap) .nav:not(.scrolled) .nav__toggle span { background: #fff; }
  body:has(.hero--underlap) .nav:not(.scrolled) .brand__logo--dark { display: none; }
  body:has(.hero--underlap) .nav:not(.scrolled) .brand__logo--light { display: block; }

  /* The two nav buttons have to invert too, or they stay as a white
     pill and a blue pill on top of blue glass. */
  body:has(.hero--underlap) .nav:not(.scrolled) .btn--ghost {
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    color: #fff; border-color: rgba(255, 255, 255, 0.4);
  }
  body:has(.hero--underlap) .nav:not(.scrolled) .btn--ghost:hover {
    background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.6);
  }
  body:has(.hero--underlap) .nav:not(.scrolled) .btn--primary {
    background: #fff; color: var(--brand-900); border-color: #fff;
  }
  body:has(.hero--underlap) .nav:not(.scrolled) .btn--primary:hover { background: rgba(255, 255, 255, 0.88); }
}

/* Reduce Transparency / no backdrop-filter: fall back to a solid
   scrim dark enough for white nav type on its own. */
@supports selector(:has(*)) and (not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)))) {
  body:has(.hero--underlap) .nav:not(.scrolled) { background: rgba(var(--scrim), 0.72); }
}

/* --- Hero controls ------------------------------------------
   The carousel dots sit on whatever the current photograph puts
   under them, which changes every five seconds. A glass tray
   gives them one constant background instead of three. */
.hero__dots {
  padding: 0.6rem 0.85rem;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(10px) saturate(130%);
  -webkit-backdrop-filter: blur(10px) saturate(130%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero__dots { background: rgba(var(--scrim), 0.55); }
}

/* The hero's secondary button, on the same principle. */
.hero--stage .btn--ghost {
  backdrop-filter: blur(8px) saturate(120%);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
}

/* ============================================================
   STRUCTURE WIDGETS (v13)
   ------------------------------------------------------------
   The client walked through a reference layout with widgets this
   site did not have: an assurance strip under the businesses, a
   two-market "global reach" panel, a values grid, a pull-quote
   band, a "why us" grid, a closing CTA band, an on-page contact
   form, and a newsletter strip.

   Two rules govern everything below.

   1. Glass only where something sits behind it. A translucent
      card on flat white is not glass, it is a white card with
      extra paint. So the glass widgets sit on .band--warm or
      .gridband, where the warm ground or the graph-paper grid
      actually shows through the blur. Every one pairs
      backdrop-filter with a background that is legible without
      it, because backdrop-filter is dropped under Reduce
      Transparency.

   2. Colour still obeys the header of this file. Orange stays a
      2px rule and a small label; blue stays actions, one CTA
      band, and icon strokes. No large orange fills, no blue page.
   ============================================================ */

/* ---- The icon badge, shared by every widget below ----------
   One circle, one 1.6px stroke, one brand colour. Written once
   so five different grids cannot drift apart. */
.ibadge {
  width: 2.9rem; height: 2.9rem; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.66);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
}
.ibadge svg:not(.ico) { width: 1.3rem; height: 1.3rem; fill: none; stroke: var(--brand); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ibadge--sm { width: 2.35rem; height: 2.35rem; }
.ibadge--sm svg:not(.ico) { width: 1.1rem; height: 1.1rem; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ibadge { background: var(--paper); }
}

/* The short orange rule that separates a card title from its body.
   Two pixels tall — the "punctuation mark" size the palette
   header allows, not a fill. */
.crule { display: block; width: 34px; height: 2px; background: var(--accent); border-radius: 2px; margin: 0.8rem 0 0.85rem; }
.crule--centre { margin-inline: auto; }

/* ---- Assurance strip -- REMOVED (v29) ---------------------
   The glass pill that closed the businesses section carried four
   claims: advice that puts you first, one institutional standard,
   regulated where we advise, fee only no commissions. Removed at
   the client's request. The first three are said properly in
   #standard and #regulation; the fourth is gone from the site. */

/* ---- Global reach -----------------------------------------
   Left: what "two markets" actually means, as a ruled list
   rather than four more cards. Right: the two markets as
   photographs, over the group's four measured figures. */
.reach { display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(2rem, 4.5vw, 4rem); align-items: center; }
.reachlist { list-style: none; margin: clamp(1.6rem, 2.6vw, 2.2rem) 0 0; padding: 0; }
.reachlist li { display: flex; gap: 1rem; align-items: flex-start; padding-block: 1.05rem; }
.reachlist li + li { border-top: 1px solid var(--line); }
.reachlist h3 { font-family: var(--font-sans); font-size: 1rem; font-weight: 600; letter-spacing: -0.005em; color: var(--ink); }
.reachlist p { font-size: 0.91rem; line-height: 1.55; color: var(--muted); margin-top: 0.3rem; max-width: 46ch; }

.reachpanel {
  border-radius: var(--radius-xl);
  padding: clamp(1rem, 1.8vw, 1.4rem);
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(18px) saturate(145%);
  -webkit-backdrop-filter: blur(18px) saturate(145%);
}
.reachpanel__map { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; }
.markettile { position: relative; overflow: hidden; border-radius: var(--radius-lg); aspect-ratio: 4 / 3.2; background: var(--soft); }
.markettile > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
/* White type sits on the bottom of an arbitrary photograph, so it
   gets its own scrim rather than trusting the picture. */
.markettile::after {
  content: ''; position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(to top, rgba(0, 12, 99, 0.84) 0%, rgba(0, 12, 99, 0.5) 30%, rgba(0, 12, 99, 0.06) 62%, rgba(0, 12, 99, 0) 80%);
}
.markettile__label { position: absolute; z-index: 3; left: 0.9rem; right: 0.9rem; bottom: 0.8rem; }
.markettile__label b { display: block; font-family: var(--font-sans); font-size: 0.96rem; font-weight: 600; letter-spacing: -0.005em; color: #fff; }
.markettile__label span { display: block; font-size: 0.79rem; font-weight: 500; color: rgba(255, 255, 255, 0.92); margin-top: 0.12rem; }
.reachpanel__stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.rstat { text-align: center; padding-inline: 0.2rem; }
.rstat b { display: block; font-family: var(--font-display); font-weight: 400; font-size: clamp(1.7rem, 2.7vw, 2.2rem); line-height: 1; color: var(--ink); }
/* `> span`, not `span`: the figure is <b><span data-count="2">2</span></b>,
   so a descendant selector caught the counter too and rendered the number
   at label size in label orange. The <b> asks for 2.2rem and got 0.79rem. */
.rstat > span { display: block; font-size: 0.79rem; font-weight: 600; color: var(--accent); margin-top: 0.4rem; }
.rstat small { display: block; font-size: 0.78rem; line-height: 1.4; color: var(--muted); margin-top: 0.18rem; }
@media (max-width: 940px) { .reach { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 460px) { .reachpanel__stats { grid-template-columns: 1fr 1fr; row-gap: 1rem; } }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .reachpanel { background: var(--paper); }
}

/* ---- Values grid ------------------------------------------ */
.valuegrid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: clamp(0.9rem, 1.6vw, 1.25rem); margin-top: clamp(2rem, 3.4vw, 2.8rem); }
.valuecard {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: clamp(1.5rem, 2.4vw, 2rem) clamp(1rem, 1.6vw, 1.35rem);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.58);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px) saturate(145%);
  -webkit-backdrop-filter: blur(14px) saturate(145%);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}
.valuecard:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.valuecard h3 { font-family: var(--font-display); font-size: 1.14rem; font-weight: 500; line-height: 1.25; color: var(--ink); margin-top: 1.05rem; }
.valuecard p { font-size: 0.88rem; line-height: 1.55; color: var(--muted); }
@media (max-width: 1080px) { .valuegrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .valuegrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px)  { .valuegrid { grid-template-columns: minmax(0, 1fr); } }

/* ---- Pull-quote band -------------------------------------- */
.quoteband {
  position: relative; overflow: hidden;
  margin-top: clamp(2.2rem, 3.6vw, 3.2rem);
  display: grid; grid-template-columns: 1.45fr 1fr; align-items: stretch;
  border-radius: var(--radius-xl);
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(16px) saturate(145%);
  -webkit-backdrop-filter: blur(16px) saturate(145%);
}
.quoteband__body { padding: clamp(1.7rem, 3vw, 2.6rem); display: flex; gap: 1.2rem; align-items: flex-start; }
.quoteband__q { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.3rem, 2.2vw, 1.8rem); line-height: 1.3; color: var(--ink); }
.quoteband__q em { font-style: normal; color: var(--accent); }
.quoteband__by { font-size: 0.88rem; color: var(--muted); margin-top: 0.95rem; }
.quoteband__media { position: relative; overflow: hidden; min-height: 190px; background: var(--soft); }
.quoteband__media > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 860px) {
  .quoteband { grid-template-columns: minmax(0, 1fr); }
  .quoteband__media { order: -1; min-height: 0; aspect-ratio: 16 / 6.5; }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .quoteband { background: var(--paper); }
}

/* ---- Why-us grid ------------------------------------------
   Distinguished from .valuegrid by a 3px rule across the top,
   alternating blue and orange so the row has a rhythm without
   colouring in four whole cards. */
.whygrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(1rem, 1.8vw, 1.4rem); margin-top: clamp(2rem, 3.4vw, 2.8rem); }
.whycard {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: clamp(1.7rem, 2.6vw, 2.2rem) clamp(1.2rem, 1.8vw, 1.6rem);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px) saturate(145%);
  -webkit-backdrop-filter: blur(14px) saturate(145%);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}
.whycard::before { content: ''; position: absolute; inset: 0 0 auto 0; height: 3px; background: var(--brand); }
.whycard--accent::before { background: var(--accent); }
.whycard:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.whycard h3 { font-family: var(--font-display); font-size: 1.18rem; font-weight: 500; line-height: 1.25; color: var(--ink); margin-top: 1.05rem; }
.whycard p { font-size: 0.89rem; line-height: 1.55; color: var(--muted); }
@media (max-width: 920px) { .whygrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .whygrid { grid-template-columns: minmax(0, 1fr); } }

/* ---- Closing CTA band -------------------------------------
   The one deliberately blue surface below the hero. It is a
   single band at the end of the page, not a theme: the brief
   says do not make the site blue, and one closing band is how
   a finance site signs off without becoming one. */
.closer {
  position: relative; overflow: hidden;
  border-radius: var(--radius-xl);
  margin-top: clamp(2.2rem, 3.6vw, 3.2rem);
  display: grid; grid-template-columns: 1.2fr 1fr;
  gap: clamp(1.6rem, 3vw, 2.6rem); align-items: center;
  padding: clamp(1.9rem, 3.4vw, 3rem);
  background: linear-gradient(105deg, var(--brand-900) 0%, var(--brand-700) 58%, var(--brand-600) 100%);
}
.closer__bg { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; }
.closer::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(90deg, rgba(0, 12, 99, 0.93) 0%, rgba(0, 12, 99, 0.84) 52%, rgba(0, 12, 99, 0.52) 100%);
}
.closer__body, .closer__card { position: relative; z-index: 2; }
.closer__body h2 { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.7rem, 2.9vw, 2.3rem); line-height: 1.18; color: #fff; letter-spacing: -0.018em; }
.closer__body h2 em { font-style: normal; color: var(--accent); }
.closer__body p { font-size: 1rem; line-height: 1.6; color: rgba(255, 255, 255, 0.92); margin-top: 0.95rem; max-width: 44ch; }
.closer__card {
  display: flex; gap: 1rem; align-items: flex-start;
  border-radius: var(--radius-lg); padding: clamp(1.3rem, 2.2vw, 1.7rem);
  background: rgba(255, 255, 255, 0.13);
  border: 1px solid rgba(255, 255, 255, 0.26);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
}
.closer__card .ibadge { background: rgba(255, 255, 255, 0.92); border-color: rgba(255, 255, 255, 0.55); }
.closer__card h3 { font-family: var(--font-sans); font-size: 1rem; font-weight: 600; color: #fff; }
.closer__card p { font-size: 0.91rem; line-height: 1.55; color: rgba(255, 255, 255, 0.9); margin-top: 0.35rem; }
.closer__go { display: inline-flex; align-items: center; gap: 0.45rem; margin-top: 0.9rem; font-size: 0.93rem; font-weight: 600; color: #fff; border-bottom: 1px solid rgba(255, 255, 255, 0.5); padding-bottom: 2px; transition: border-color 0.25s var(--ease); }
.closer__go:hover { border-bottom-color: #fff; }
@media (max-width: 860px) { .closer { grid-template-columns: minmax(0, 1fr); } }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .closer__card { background: rgba(0, 8, 62, 0.62); }
}

/* ---- Contact: on-page form -------------------------------- */
.getintouch { display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(2rem, 4.5vw, 4rem); align-items: start; }
.formcard {
  border-radius: var(--radius-xl);
  padding: clamp(1.5rem, 2.6vw, 2.2rem);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
}
.formcard h3 { font-family: var(--font-display); font-weight: 500; font-size: clamp(1.25rem, 2vw, 1.55rem); color: var(--ink); }
.formcard > p { font-size: 0.93rem; line-height: 1.6; color: var(--muted); margin-top: 0.7rem; }
.formcard .form { max-width: none; margin-top: 1.3rem; }
.formcard .btn { width: 100%; justify-content: center; }
.formnote { display: flex; gap: 0.55rem; align-items: flex-start; font-size: 0.81rem; line-height: 1.5; color: var(--faint); }
.formnote svg:not(.ico) { width: 0.95rem; height: 0.95rem; flex: none; margin-top: 0.18rem; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.contactpoints { list-style: none; margin: clamp(1.6rem, 2.6vw, 2.2rem) 0 0; padding: 0; }
.contactpoints li { display: flex; gap: 1rem; align-items: flex-start; padding-block: 1.05rem; }
.contactpoints li + li { border-top: 1px solid var(--line); }
.contactpoints h3 { font-family: var(--font-sans); font-size: 1rem; font-weight: 600; color: var(--ink); }
.contactpoints p { font-size: 0.91rem; line-height: 1.55; color: var(--muted); margin-top: 0.3rem; max-width: 44ch; }
.contactdirect { display: flex; align-items: center; gap: 0.8rem; margin-top: 1.6rem; font-size: 0.94rem; color: var(--muted); flex-wrap: wrap; }
.contactdirect a { font-weight: 600; color: var(--brand); }
@media (max-width: 880px) { .getintouch { grid-template-columns: minmax(0, 1fr); } }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .formcard { background: var(--paper); }
}

/* ---- Newsletter strip -------------------------------------- */
.newsstrip {
  margin-top: clamp(2.2rem, 3.6vw, 3rem);
  display: grid; grid-template-columns: auto 1fr auto;
  gap: clamp(1rem, 2.4vw, 2rem); align-items: center;
  border-radius: var(--radius-xl);
  padding: clamp(1.3rem, 2.4vw, 1.9rem) clamp(1.4rem, 2.6vw, 2.1rem);
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid var(--line);
  backdrop-filter: blur(16px) saturate(145%);
  -webkit-backdrop-filter: blur(16px) saturate(145%);
}
.newsstrip__t { display: flex; align-items: center; gap: 0.95rem; }
.newsstrip__t h3 { font-family: var(--font-display); font-weight: 500; font-size: 1.18rem; line-height: 1.25; color: var(--ink); max-width: 16ch; }
.newsstrip__t h3 em { font-style: normal; color: var(--accent); }
.newsstrip > p { font-size: 0.91rem; line-height: 1.55; color: var(--muted); max-width: 48ch; }
.newsform { display: flex; gap: 0.55rem; }
.newsform input { font-family: var(--font-sans); font-size: 0.92rem; padding: 0.72rem 0.95rem; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--paper); color: var(--ink); min-width: 15rem; transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease); }
.newsform input:focus { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(14, 14, 17, 0.07); outline: none; }
@media (max-width: 1020px) { .newsstrip { grid-template-columns: minmax(0, 1fr); } .newsform input { min-width: 0; flex: 1; } }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .newsstrip { background: var(--paper); }
}

/* ---- Trio: icon badge + rule ------------------------------- */
.trio__item .ibadge { margin-bottom: 0.95rem; }
.trio__item .crule { margin: 0.7rem 0 0.75rem; }
.trio__item .crule + p { margin-top: 0; }

/* ---- Footer: the columns the reference layout carries -------
   Insights and Resources were links the site had but the footer
   never surfaced, and there was nowhere on the page to find an
   office, an inbox, or a social account. Ground stays paper: the
   "no dark sections" rule in this file's header still holds. */
.footer__top--wide { grid-template-columns: 1.45fr minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.3fr); }
.footer__social { display: flex; gap: 0.5rem; margin-top: 1.3rem; }
.footer__social a {
  width: 2.25rem; height: 2.25rem; display: grid; place-items: center;
  border-radius: var(--radius-pill); border: 1px solid var(--line);
  background: var(--paper); color: var(--muted);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.footer__social a:hover { color: var(--brand); border-color: var(--brand-200); background: var(--brand-50); }
.footer__social svg { width: 1rem; height: 1rem; fill: currentColor; }
.footer__col p { font-size: 0.9rem; line-height: 1.55; color: var(--muted); }
.footer__sub { display: flex; align-items: stretch; margin-top: 0.95rem; max-width: 20rem; border: 1px solid var(--line-strong); border-radius: var(--radius); overflow: hidden; background: var(--paper); }
.footer__sub input { flex: 1; min-width: 0; border: 0; background: none; padding: 0.68rem 0.85rem; font-family: var(--font-sans); font-size: 0.9rem; color: var(--ink); }
.footer__sub input:focus { outline: none; }
.footer__sub button { border: 0; cursor: pointer; background: var(--brand); color: #fff; padding: 0 1rem; font-size: 1rem; line-height: 1; transition: background 0.25s var(--ease); }
.footer__sub button:hover { background: var(--brand-600); }
.footer__contact { border-top: 1px solid var(--line); padding-block: 1.7rem; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; }
.fcontact { display: flex; gap: 0.8rem; align-items: flex-start; }
.fcontact svg:not(.ico) { width: 1.1rem; height: 1.1rem; flex: none; margin-top: 0.15rem; fill: none; stroke: var(--brand); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.fcontact b { display: block; font-family: var(--font-sans); font-size: 0.85rem; font-weight: 600; color: var(--ink); margin-bottom: 0.25rem; }
.fcontact p { font-size: 0.89rem; line-height: 1.55; color: var(--muted); }
.fcontact a { color: var(--muted); }
.fcontact a:hover { color: var(--brand); }
@media (max-width: 1080px) { .footer__top--wide { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .footer__contact { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px)  { .footer__top--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Phones: the four link lists still read fine two-up; only the brand block
   and the subscribe column need the full width, so they span. Stacking all
   five made the footer 2224px tall on a 375px screen. */
@media (max-width: 560px) {
  .footer__top--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.6rem 1.4rem; }
  .footer__top--wide > .footer__brand,
  .footer__top--wide > .footer__col--sub { grid-column: 1 / -1; }
  .footer__sub { max-width: 22rem; }
}

/* Label kept for screen readers where the design carries only a
   placeholder (the newsletter strip and the footer subscribe). */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Centred section head. .seclabel ends in a flex:1 hairline that
   runs to the right edge — correct under a left-aligned head,
   wrong under a centred one, where it reads as an accidental
   underline across the column. Here the eyebrow centres and the
   rule becomes a short orange mark below it, matching the card
   titles in the same sections. */
.sechead--centre { text-align: center; margin-inline: auto; }
.sechead--centre .seclabel { justify-content: center; flex-direction: column; gap: 0.7rem; }
.sechead--centre .seclabel::after { flex: none; width: 34px; height: 2px; background: var(--accent); border-radius: 2px; }
.sechead--centre .lead { margin-inline: auto; }

/* Card titles run to one or two lines in the same row, which left
   the one-line cards' bodies sitting higher than the rest. Reserve
   two lines so the rule and the body copy line up across the row. */
.valuecard h3, .whycard h3 { min-height: 2.5em; display: flex; align-items: center; }
@media (max-width: 420px) { .valuecard h3 { min-height: 0; } }
@media (max-width: 520px) { .whycard h3 { min-height: 0; } }


/* --- v14 · form fields must shrink with their grid track (mobile) ------------
   Inputs/selects/textareas carry an intrinsic min-content width (size=20,
   cols=20) that pushed the grid track wider than the card on narrow screens. */
.form { grid-template-columns: minmax(0, 1fr); }
.form__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.field input, .field textarea, .field select { width: 100%; max-width: 100%; min-width: 0; }
@media (max-width: 860px) { .form__row { grid-template-columns: minmax(0, 1fr); } }


/* ===========================================================================
   ECOSYSTEM (v15) — #what-we-do on index.html
   ---------------------------------------------------------------------------
   Replaces the vertical .tabs index with the hub-and-three-cards layout the
   client supplied. The reference is a rendered mockup, so everything here is
   HTML + CSS per the INFOGRAPHICS rule: the arc is a bordered circle, the
   connectors are 1px divs, and nothing is an SVG that would go stale.

   The arc is one circle, not four. A circle's four border edges meet on the
   45-degree diagonals, so border-left-color paints the upper-left quadrant and
   border-right-color the upper-right — which is exactly the orange-to-blue
   sweep in the reference, for one element and no gradient mask.

   Colour: the section still obeys the file header. Orange is the 34x2px .crule,
   one card's 3px top accent, one word of the headline, and the left half of a
   1px arc. Blue is the hub ring, the icon strokes and the Learn more links.
   ======================================================================== */

.eco { position: relative; margin-top: clamp(2.4rem, 4vw, 3.4rem); }

/* --- the hub ------------------------------------------------------------ */
.eco__hub {
  position: relative; z-index: 3;
  width: max-content; margin: 0 auto;
  display: flex; flex-direction: column; align-items: center;
  padding: clamp(1rem, 1.8vw, 1.35rem) clamp(1.6rem, 3vw, 2.4rem) clamp(0.9rem, 1.5vw, 1.15rem);
  border-radius: var(--radius-xl);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .eco__hub { background: var(--paper); }
}
.eco__hub img { height: 30px; width: auto; display: block; }
.eco__hublabel {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brand);
  margin-top: 0.6rem;
}

/* --- the connectors ----------------------------------------------------- */
/* A bus under the hub with three drops. Pure 1px rules, absolutely placed
   against .eco, so the cards below stay a plain grid and reflow on their own. */
.eco__wires {
  position: relative; z-index: 1; pointer-events: none;
  height: clamp(2.8rem, 4.6vw, 3.8rem);
}
/* The centre drop runs the full height: hub to bus, then bus to the middle
   card. The bus spreads at 50%, and the two outer drops fall from there.
   16.6% is the centre of a third — it lands on each outer card's midline. */
.eco__bus {
  position: absolute; left: 16.6%; right: 16.6%; top: 50%; height: 1px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--brand-200) 50%, var(--brand) 100%);
  opacity: 0.6;
}
.eco__drop { position: absolute; width: 1px; }
.eco__drop--c { left: 50%; top: 0; bottom: 0; background: linear-gradient(180deg, var(--brand-200), rgba(201, 208, 243, 0.25)); }
.eco__drop--l { left: 16.6%; top: 50%; bottom: 0; background: linear-gradient(180deg, var(--accent), rgba(240, 90, 41, 0.2)); }
.eco__drop--r { right: 16.6%; top: 50%; bottom: 0; background: linear-gradient(180deg, var(--brand), rgba(0, 19, 160, 0.18)); }

/* --- the three cards ---------------------------------------------------- */
.eco__grid {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.1rem, 2vw, 1.6rem);
}
.ecocard {
  position: relative; display: flex; flex-direction: column;
  border-radius: var(--radius-lg); overflow: hidden;
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(16px) saturate(145%);
  -webkit-backdrop-filter: blur(16px) saturate(145%);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ecocard { background: var(--paper); }
}
.ecocard:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.ecocard::before { content: ''; position: absolute; inset: 0 0 auto 0; height: 3px; z-index: 4; background: var(--brand); }
.ecocard--accent::before { background: var(--accent); }

/* The badge overlaps the top edge, so it needs room above the title rather
   than absolute positioning — absolute would sit it on the 3px accent bar and
   clip against overflow:hidden. */
.ecocard__badge { margin: clamp(1.3rem, 2.2vw, 1.7rem) 0 0 clamp(1.3rem, 2.2vw, 1.7rem); }
.ecocard__body { padding: 1rem clamp(1.3rem, 2.2vw, 1.7rem) clamp(1.2rem, 2vw, 1.5rem); }
.ecocard__body h3 { font-size: clamp(1.18rem, 1.5vw, 1.4rem); line-height: 1.22; }
.ecocard__body .crule { margin: 0.75rem 0 0.85rem; }
.ecocard__body p { color: var(--muted); font-size: 0.95rem; line-height: 1.6; margin: 0; }
/* The 16/9 photograph that used to close each card is gone (v29). Each
   business is now signed off by the brand that actually runs it, which is
   the one thing a reader cannot infer from the copy above. Sits on the
   tint so the plate reads as a footer to the card, not as a second card.
   margin-top:auto keeps the three plates on one line whatever the body
   copy does. */
.ecocard__brand {
  margin-top: auto;
  display: flex; flex-direction: column; align-items: center; gap: 0.7rem;
  padding: clamp(1.4rem, 2.4vw, 1.9rem) 1rem;
  background: var(--warm-50);
  border-top: 1px solid var(--line-faint);
}
/* Height, not width: the two lockups have very different aspect ratios and
   matching their boxes would leave one of them visibly larger. 26px on the
   Wealthdoor arc against 22px on the Nestvest lockup is the optical match
   measured in v21 -- the arc spends its top two thirds above the x-height,
   the lockup does not. */
.ecocard__logo { height: 26px; width: auto; display: block; }
.ecocard__logo--nv { height: 22px; aspect-ratio: 5131 / 1000; }
.ecocard__brandname {
  margin: 0;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faint);
}
.ecocard__go {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 1rem clamp(1.3rem, 2.2vw, 1.7rem);
  font-size: 0.9rem; font-weight: 600; color: var(--brand);
  border-top: 1px solid var(--line-faint);
}
.ecocard__go .arrow { transition: transform 0.25s var(--ease); }
.ecocard:hover .ecocard__go .arrow { transform: translateX(4px); }

/* --- ecosystem section shell ------------------------------------------- */
.ecosec { position: relative; }
.ecosec > .wrap { position: relative; z-index: 1; }
.ecosec h2 em { font-style: normal; color: var(--accent); }

/* The wide background ellipse that used to sit behind the headline -- a
   3.1:1 arc with an orange dot on one shoulder and a blue one on the other
   -- is gone (v29, client request). It was drawn decoration: it organized
   nothing, and with the wires below it the section was carrying two
   separate diagrams of the same relationship. */

/* --- responsive --------------------------------------------------------- */
@media (max-width: 940px) {
  .eco__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: clamp(2rem, 4vw, 2.8rem); }
  .eco__hub { margin-bottom: 0; }
  /* Two-up leaves the third card under a wire that no longer points at it,
     and a stacked hub-and-bus draws a relationship that is not on screen. */
  .eco__wires { display: none; }
}
@media (max-width: 620px) {
  .eco__grid { grid-template-columns: minmax(0, 1fr); }
  .eco__hub { width: auto; }
}

/* ============================================================
   v16 · "remove the peach, remove the grid lines, make each section
   look full-screen, headlines bigger and bold, no infographics"
   ------------------------------------------------------------
   Four client notes landed together and they all pull the same way:
   fewer drawn lines, more air, and one louder voice per section.
   This block is last in the file so it wins on cascade order; the
   rules it overrides are left where they are so the history reads.
   ============================================================ */

/* ---- 1 · No drawn background texture -------------------------
   Three separate things were reading as "grid lines in the
   background", and all three are off:
     .hatch      — the 34px diagonal rule strip under the hero
     .gridband   — the 46px graph-paper wash behind #global / #why
     .wrap       — the vertical hairlines that bounded every section
   The .wrap borders are the important one. They ran the full height
   of the page and are what made the layout read as a ruled grid
   rather than as a sequence of full-width sections. Sections are now
   separated by ground colour alone, which is what the reference does. */
.hatch { display: none; }
.gridband::before { display: none; }
.wrap { border-inline: 0; }
.divide-top { border-top-color: var(--line-faint); }

/* The hero carried the same frame twice over: .hero__inner's own
   border-inline, plus the .marked corner brackets pinned to those
   edges. Both are gone ("in the hero banner remove the side lines").
   The .marked / .marked__b markup was deleted from index.html — the
   homepage hero was the only place on the site that used it, so the
   class definitions up at line 364 are now dead. Left in place: they
   are part of the documented class library and cost nothing. */
.hero__inner { border-inline: 0; }

/* ---- 2 · Full-screen sections --------------------------------
   Not min-height:100vh — a short section forced to a screen height
   just parks its content in the middle of a void, and on a 812px
   phone it turns a five-line block into three scrolls of nothing.
   What actually reads as "full screen" is the air around the
   content, so the vertical rhythm roughly doubles instead. */
.section { padding-block: clamp(4.5rem, 8.5vw, 8.5rem); }
.section--tight { padding-block: clamp(3rem, 5vw, 4.75rem); }

/* ---- 3 · Headlines, bigger and bold --------------------------
   Newsreader now loads 600 and 700 (see the @import at the top of
   this file). 600 is the working weight: at 700 the serif's thin
   strokes fatten faster than the thick ones and a 5rem headline
   starts to look printed rather than set. */
h1, h2, h3, h4 { font-weight: 600; letter-spacing: -0.026em; }
.display { font-size: clamp(2.9rem, 6.4vw, 5.4rem); font-weight: 600; letter-spacing: -0.034em; }
.h2 { font-size: clamp(2.15rem, 4.1vw, 3.4rem); line-height: 1.08; }
.h3 { font-size: clamp(1.35rem, 2.2vw, 1.85rem); }
.sechead .lead, .sechead--centre .lead { font-size: clamp(1.06rem, 1.35vw, 1.22rem); }

/* The reference sets one word of each centred headline in orange
   rather than greying the second line. Scoped to <em> so it is
   opt-in per headline and cannot repaint the 17 other pages. */
.h2 em, h2 em { font-style: normal; color: var(--accent); }

/* ---- 4 · Image slots where the diagrams were ------------------
   The three HTML/CSS infographics (.dflow, .dtree, .dmatrix) are out
   of index.html at the client's request, and the space is held open
   for photography instead. The placeholder is a real layout box, not
   a spacer: it holds the exact footprint the image will occupy, so
   nothing reflows when the picture arrives. Drop an <img> inside and
   the caption is covered automatically — it sits at z-index 0 and the
   image is absolutely positioned above it. */
.imgslot {
  position: relative; overflow: hidden;
  aspect-ratio: 4 / 3.05;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background:
    linear-gradient(180deg, var(--brand-50), var(--soft));
  display: grid; place-items: center;
}
.imgslot > img {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
}
.imgslot__note {
  position: relative; z-index: 0;
  display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
  text-align: center; padding: 1.5rem; margin: 0;
}
.imgslot__note b {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brand);
}
.imgslot__note span {
  font-size: 0.95rem; line-height: 1.5; color: var(--muted); max-width: 24ch;
}
.band--warm .imgslot { border-color: var(--warm-line); }

/* ---- 5 · Tinted ground, consequences -------------------------
   --warm-* is now a cool tint, so two rules that were tuned against
   cream need re-pointing. .band--warm .frame used --warm-100 as a
   photo backing, which on a blue tint reads as a blue box behind a
   loading image; --soft is the neutral equivalent. */
.band--warm .frame, .band--warm .tabs__media,
.band--warm .brandcard__media, .band--warm .railcard__media { background: var(--soft); }

/* ============================================================
   v17 · THE FOOTER GROUND  ("change the colour of the footer")
   ------------------------------------------------------------
   The footer was --paper: the same near-white as the page, which
   meant the site simply ran out rather than closing. It is now the
   deep brand navy, which is what the client's own reference image
   shows and what the sector expects — a compliance foot is a place
   the eye should recognise as the end of the document.

   This is the SECOND scoped exception to "there are NO dark
   sections" (the first is .hero--stage on index.html). It is not a
   licence to darken anything else. The reasoning is specific: the
   footer is chrome, not content, it carries no advisory copy that
   has to be read at length, and every contrast pair below was set
   against #000c63 rather than inherited from the light ramp.

   The footer is shared markup on all 18 pages, so this lands
   everywhere at once — same as the v16 palette retarget.

   Contrast against --brand-900 #000c63, MEASURED in the browser on
   the composited colour, not estimated from the alpha:
     rgba(255,255,255,.78) links       10.44:1
     rgba(255,255,255,.72) disclaimer   8.99:1
     rgba(255,255,255,.64) bottom bar    7.26:1
     rgba(255,255,255,.62) col labels    6.87:1  (uppercase 0.79rem)
   Nothing here drops below 4.5:1. The first pass had the labels at
   .52 and the bottom bar at .56; those measured 4.62 and 5.27, which
   clears the floor but leaves nothing for a slightly different
   screen. Both were lifted. If you re-tint this footer, re-measure —
   alpha does not map linearly to contrast on a ground this dark.
   The disclaimer is the smallest type on the page at 0.8rem, so it
   is held at .72, NOT at the --faint equivalent it used on white.
   ============================================================ */
.footer { background: var(--brand-900); color: rgba(255, 255, 255, 0.78); border-top: 0; }

.footer__brand p { color: rgba(255, 255, 255, 0.72); }
.footer__col h4 { color: rgba(255, 255, 255, 0.62); }
.footer__col p { color: rgba(255, 255, 255, 0.72); }
.footer__col a { color: rgba(255, 255, 255, 0.78); }
.footer__col a:hover { color: #fff; }

/* The Nestvest sites put a text wordmark here instead of a logo file. */
.footer .brand__word, .footer .brand__word .dot { color: #fff; }

.footer__social a {
  color: rgba(255, 255, 255, 0.82);
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.06);
}
.footer__social a:hover {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.14);
}

/* The subscribe field inverts: white submit on navy, not brand-blue
   on navy, which at this size is two dark colours touching. */
.footer__sub { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.26); }
.footer__sub input { color: #fff; }
.footer__sub input::placeholder { color: rgba(255, 255, 255, 0.52); }
.footer__sub button { background: #fff; color: var(--brand-900); }
.footer__sub button:hover { background: rgba(255, 255, 255, 0.86); }

.footer__contact { border-top-color: rgba(255, 255, 255, 0.16); }
.fcontact svg { stroke: var(--accent); }
.fcontact b { color: #fff; }
.fcontact p { color: rgba(255, 255, 255, 0.72); }
.fcontact a { color: rgba(255, 255, 255, 0.78); border-bottom: 1px solid rgba(255, 255, 255, 0.28); }
.fcontact a:hover { color: #fff; border-bottom-color: #fff; }

.footer__bottom { border-top-color: rgba(255, 255, 255, 0.16); color: rgba(255, 255, 255, 0.64); }
.footer__bottom a { color: rgba(255, 255, 255, 0.64); }
.footer__bottom a:hover { color: #fff; }

.footer .disclaimer { color: rgba(255, 255, 255, 0.72); }
.footer .disclaimer strong { color: #fff; }

.footer .grouptag { border-top-color: rgba(255, 255, 255, 0.16); color: rgba(255, 255, 255, 0.62); }
.footer .grouptag a { color: rgba(255, 255, 255, 0.82); border-bottom-color: rgba(255, 255, 255, 0.3); }
.footer .grouptag a:hover { color: #fff; border-bottom-color: #fff; }

/* The dark-ink logo disappears on navy. The white variant already
   exists — it is what the transparent nav uses over the hero. */
.footer .brand__logo { filter: none; }

/* ---- v17b · Nav logo size ("in the top bar increase the size of
   the logo") ---------------------------------------------------
   28px -> 42px, a 50% lift. Scoped to .nav on purpose: .brand__logo
   is shared with the footer, and the footer lockup is sized against
   a paragraph of body copy, not against a 74px bar.

   42px is the ceiling, not a round number. The bar is a HARD 74px
   and that value is hardcoded in four other places (.mobilemenu's
   inset, and the two hero padding calcs at lines ~1416 and ~1549),
   so the bar cannot grow without those drifting out of sync. At 42px
   the logo clears 16px above and below — still optical breathing
   room. Past ~46px it starts to crowd the rule and the nav reads as
   a letterhead. If a bigger logo is ever needed, convert 74px to a
   --nav-h custom property FIRST and fix all five call sites. */
.nav .brand__logo { height: 42px; }
@media (max-width: 560px) { .nav .brand__logo { height: 34px; } }

/* ============================================================
   v18 · SECTION AUDIT  ("make each and every section proper")
   A pass over every section on index.html at 1280/768/375.
   Most were sound. These three were not.
   ============================================================ */

/* ---- 2 · Five value cards were too narrow to read ------------
   repeat(5, 1fr) inside the 1240px wrap gave each card 212px, and
   after padding that is ~24 characters a line over five lines.
   Body copy stops reading as prose somewhere around 30 characters.
   Three-up is the honest fit at this width, and with five cards
   that means a trailing row of two — so this is a centred flex
   wrap, not a grid: grid would jam the orphan row hard left.
   The old breakpoints below 1080px already went 3/2/1 and still
   apply, so only the desktop case changes. */
@media (min-width: 1081px) {
  .valuegrid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }
  .valuegrid > .valuecard {
    flex: 0 1 clamp(17rem, 24vw, 21rem);
  }
}


/* ==================================================================
   v19 · CRAFT PASS
   A review of index.html against two outside checklists the client
   supplied in Skills/: the Vercel Web Interface Guidelines and Emil
   Kowalski's design-engineering notes. Everything below is a defect
   those checklists surfaced, not a restyle. Nothing here changes a
   colour, a typeface, or a layout.

   These rules live in the shared stylesheet, so like the v16 palette
   and the v17 footer they land on all eighteen pages. That is the
   correct behaviour for every one of them — a skip link and a focus
   ring are not homepage features — but it is a departure from
   "index.html only" and is recorded here so nobody is surprised.

   NOT changed, deliberately, after checking:
   - Easing. The checklist says the built-in CSS curves are too weak
     and to use a custom one. --ease is already
     cubic-bezier(0.16, 1, 0.3, 1), a strong expo-out, and it is used
     on every transition in the file. Nothing to fix.
   - Font loading. Already preconnected in every <head> and already
     &display=swap on the @import.
   - Heading order. One <h1>, then h2/h3/h4 with no level skipped.
   ================================================================== */

/* ---- 1 · Anchor links landed under the fixed nav ----------------
   The nav is 74px and fixed. Every in-page link on the homepage
   (#standard, #what-we-do, #brands, #regulation, #contact) scrolled
   its target flush to the top of the viewport, which put the section
   label and often the headline behind the bar. scroll-padding on the
   scroll container fixes all of them at once, and keeps working for
   any anchor added later — the alternative, scroll-margin-top on
   each target, has to be remembered every time.

   The extra 1rem is breathing room, so the heading does not sit
   welded to the underside of the bar. */
html {
  scroll-padding-block-start: calc(74px + 1rem);
  scroll-behavior: smooth;
  color-scheme: light;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ---- 2 · Skip link ---------------------------------------------
   The nav holds ten focusable elements before the content starts. A
   keyboard or screen-reader user had to tab through all of them on
   every page. Visible only when focused, which is the whole point:
   it must be the first thing in the tab order and invisible to
   everyone else. */
.skiplink {
  position: fixed; top: 0; left: 50%;
  transform: translate(-50%, -110%);
  z-index: calc(var(--z-nav) + 10);
  background: var(--brand); color: #fff;
  font-family: var(--font-sans); font-size: 0.9rem; font-weight: 600;
  padding: 0.7rem 1.2rem;
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: var(--shadow-md);
  transition: transform 0.18s var(--ease);
}
/* :focus, not :focus-visible. This element exists only for keyboard
   users and is never reachable any other way, so the focus-visible
   heuristic buys nothing — and when focus is moved programmatically
   (a "skip to content" shortcut, a testing harness) focus-visible
   does not match and the link stays off-screen while holding focus,
   which strands the user on an invisible control. */
.skiplink:focus {
  transform: translate(-50%, 0);
  outline: 2px solid #fff; outline-offset: -4px;
}

/* ---- 3 · A focus ring the footer had thrown away ---------------
   .footer__sub input carried `outline: none` with nothing put back,
   so tabbing into the footer subscribe field showed no focus at all.
   The ring goes on the wrapper rather than the input because the
   input and its button share one visual control. */
.footer__sub:focus-within {
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18);
}

/* ---- 4 · Touch --------------------------------------------------
   touch-action: manipulation drops the ~300ms double-tap-to-zoom
   wait that mobile Safari still applies to anything tappable. */
a, button, [role="link"], .btn, input[type="submit"], summary {
  touch-action: manipulation;
}
.mobilemenu, .field textarea {
  overscroll-behavior: contain;
}
/* The drawer is fixed over the page; the page must not scroll behind it. */
body.menu-open { overflow: hidden; }

/* ---- 5 · Hover states behind a hover query ---------------------
   A touch device fires :hover on tap and then keeps it applied until
   the next tap elsewhere, so a card the user merely touched stays
   lifted and shadowed. Every transform-on-hover is now gated. The
   non-transform hovers (colour, border) are left alone: they are
   harmless when they stick, and gating them would cost the visual
   feedback on hybrid laptops. */
@media (hover: none) {
  .valuecard:hover, .whycard:hover, .ecocard:hover { transform: none; }
  .btn:hover .arrow,
  .tlink:hover .arrow,
  .announce:hover .announce__go .arrow,
  .trio__item:hover .trio__go,
  .ecocard:hover .ecocard__go .arrow { transform: none; }
}

/* ---- 6 · Press feedback ----------------------------------------
   .btn already dips on press. Nothing else did, so tapping the
   announcement bar, a news card or a hero dot gave no signal at all
   until the next page painted — on a slow connection that reads as
   a dead control.

   Only genuine click targets are listed. .ecocard, .brandcard and
   .trio__item look like buttons but are <article>/<div> wrappers
   with a link inside; scaling those on press would animate a
   non-control, which is worse than no feedback.

   Two ratios, because one does not fit both sizes. 0.97 on the
   small controls, per the reference; 0.99 on .railcard, which is a
   ~330px card where 0.97 reads as a lurch rather than a press.

   Each transition re-states the properties the base rule already
   animated. `transition` is a shorthand: declaring it again with
   only `transform` would silently drop the border-colour and
   box-shadow transitions those hovers depend on. */
.announce { transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), transform 0.12s var(--ease); }
.tlink    { transition: border-color 0.25s var(--ease), transform 0.12s var(--ease); }
.railcard { transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease), transform 0.12s var(--ease); }
.hero__dot { transition: background 0.3s var(--ease), width 0.3s var(--ease), transform 0.12s var(--ease); }
.footer__social a { transition: color 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease), transform 0.12s var(--ease); }

.announce:active, .tlink:active,
.hero__dot:active, .footer__social a:active { transform: scale(0.97); }
.railcard:active { transform: scale(0.99); }

/* .ecocard__go is a full-bleed strip across the bottom of a card
   that clips its children. Scaling it would pull it off both edges
   and show the card behind. It presses with colour instead. */
.ecocard__go { transition: background 0.15s var(--ease); }
.ecocard__go:active { background: var(--brand-50); }

@media (prefers-reduced-motion: reduce) {
  .announce:active, .tlink:active, .hero__dot:active,
  .footer__social a:active, .railcard:active { transform: none; }
}


/* ==================================================================
   v20 · THE TINT MARKS MEANING, NOT EVERY OTHER SECTION
   "rn it is one section white n another one is lil light blue —
    dont keep alternating, think n keep only important sections
    like that ... in the hero banner reduce the blue colour a lil"

   Two changes, and one thing they turned up on the way.
   ================================================================== */

/* ---- 1 · The scrim comes off the pure brand navy ----------------
   The hero wash was rgb(0, 12, 99) — the brand blue at full
   saturation, blue eight times over green with no red at all. It
   read as a blue filter laid over the photograph rather than as
   shade on it.

   The new value is DESATURATED, NOT LIGHTENED, and that distinction
   is the whole point. Every alpha in the three scrim variants is
   untouched, so the photograph is veiled exactly as much as before.

   It does cost a little contrast, and the reason is worth writing
   down because the solid colour predicts the wrong sign. As a solid,
   rgb(14,20,74) is DARKER than rgb(0,12,99) — luminance 0.01087 vs
   0.01164. But the scrim is never solid; it composites at alpha over
   whatever the photograph shows, and the worst case is a white pixel.
   Composited, R goes 0 -> 14 and G goes 12 -> 20, and green carries
   0.7152 of the luminance weight, so the ground ends up marginally
   LIGHTER and every ratio slips by roughly 0.15-0.50.

   Measured in-browser against the resolved gradient stops, sampling
   each element's actual inked extent (not its box, which for the
   flex .microline overruns the text by ~190px and reads far too
   dark a stop). Desktop, 1280, over a pure-white photo pixel:

     element          px   alpha    was     now   needs
     headline         69   0.617   5.21    4.95    3.0
     headline .mute   69   0.705   4.13    3.97    3.0
     lead             16   0.710   6.59    6.26    4.5
     microline        13   0.687   5.59    5.32    4.5
     announce         13   0.807  10.14    9.64    4.5
     ghost button     16   0.805  10.07    9.57    4.5

   Mobile, 375, against the <=720 vertical ramp: 6.98 / 4.44 / 9.28 /
   11.26 / 5.32, all likewise passing. Nothing crosses its floor.

   Re-measure if you change these numbers. Do not change them to
   "lighten the hero": lighten means alpha, and alpha is load
   bearing — v11 tried a lighter ramp and the headline failed at
   3.68:1. */
:root {
  --scrim: 14, 20, 74;       /* was 0, 12, 99  — the wash */
  --scrim-deep: 10, 14, 48;  /* was 0, 8, 62   — the bottom edge */
}

/* ---- 2 · Four bands, not six, and they are not alternating -----
   Before: standard / brands / values / who-we-are / insights /
   contact were tinted and the rest white, which is strict
   alternation — thirteen sections in a stripe. A stripe carries no
   information: every section looks equally important, which is the
   same as none of them being important.

   Now the tint marks the page's four anchors, and nothing else:

     #standard    the promise — fee only, fiduciary. The claim the
                  whole firm rests on, and already the one section
                  carrying .moment.
     #brands      the fork. Where a visitor self-selects into a
                  practice. The single most valuable click on the page.
     #regulation  the trust anchor. For a registered adviser this is
                  what separates the firm from an app.
     #contact     the destination.

   Read down the page they are a spine: our promise, our practices,
   our regulation, talk to us. No two are adjacent — the gaps run
   2, 1, 4, 2 sections — so each one reads as a chapter marker
   rather than as a stripe.

   The change is in index.html (the band/band--warm classes), not
   here. This comment is where the reasoning lives. If a fifth
   section ever wants the tint, the question to answer first is
   which of these four it outranks.
   ---------------------------------------------------------------- */

/* ---- 3 · Glass had nothing left behind it ----------------------
   Found while re-banding, and it is the reason the cards on the
   white sections looked like outlines rather than objects.

   v12 set the rule: glass only where something sits behind it.
   That held while .gridband painted a 46px graph-paper wash and
   .band--warm was on half the page. v16 removed the texture and
   this pass removes most of the bands — so backdrop-filter across
   the homepage was blurring flat white. A frosted panel over white
   is white. .valuecard at rgba(255,255,255,.58) over #ffffff is
   literally #ffffff: the card was its 1px border and nothing else.

   So the tint moves from the band to the card. A card is now a
   solid surface that contrasts with whatever ground it is on:
   tinted on white, white on the tinted bands. That is what makes
   the four remaining bands legible as bands — the cards no longer
   compete with them.

   Glass is KEPT in exactly the three places that still have a
   photograph behind them: the nav while it sits over the hero, the
   hero's own controls, and .closer__card. Everything else here is
   a straight solid, which also returns the GPU cost of fourteen
   backdrop-filters on one page. */

/* On the white ground: the card carries the tint. */
.eco__hub, .ecocard, .reachpanel,
.valuecard, .quoteband, .whycard, .formcard, .newsstrip {
  background: var(--warm-50);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* On a tinted band: the card goes white so it lifts off the ground.
   Same rule read the other way round. */
.band--warm .eco__hub, .band--warm .ecocard,
.band--warm .reachpanel, .band--warm .valuecard, .band--warm .quoteband,
.band--warm .whycard, .band--warm .formcard, .band--warm .newsstrip {
  background: var(--n-0);
  border-color: var(--warm-line);
}

/* .ibadge is a 40px icon chip that has to separate from whatever is
   immediately BEHIND it, which is not always the section. Three of
   its eleven placements sit on bare section ground with no card at
   all — .trio__item in #experience, .reachlist li in #global and
   .contactpoints li in #contact — and keying the chip off .band--warm
   painted those three the exact colour they were sitting on, leaving
   a 1px ring and a hairline shadow to carry a 40px element.

   There are only two grounds in the system, so the chip is simply the
   opposite of its host. Read the four rules in order — each one flips
   the previous where the surface underneath has flipped:

     ground   card?   host is   chip is
     white    no       white     tint     <- rule 1
     white    yes      tint      white    <- rule 2
     band     no       tint      white    <- rule 3
     band     yes      white     tint     <- rule 4

   Specificity already sorts rules 2 and 3 (both 0,2,0 — source order
   decides) and puts rule 4 (0,3,0) on top, so the order below is load
   bearing. .closer__card .ibadge at ~1871 stays translucent white on
   purpose: that one sits on a photograph, not on either ground. */
.ibadge {
  background: var(--warm-50);
  border-color: var(--warm-line);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.eco__hub .ibadge, .ecocard .ibadge, .reachpanel .ibadge,
.valuecard .ibadge, .quoteband .ibadge, .whycard .ibadge,
.formcard .ibadge, .newsstrip .ibadge {
  background: var(--n-0);
  border-color: var(--line);
}
.band--warm .ibadge {
  background: var(--n-0);
  border-color: var(--line);
}
.band--warm .eco__hub .ibadge,
.band--warm .ecocard .ibadge, .band--warm .reachpanel .ibadge,
.band--warm .valuecard .ibadge, .band--warm .quoteband .ibadge,
.band--warm .whycard .ibadge, .band--warm .formcard .ibadge,
.band--warm .newsstrip .ibadge {
  background: var(--warm-50);
  border-color: var(--warm-line);
}

/* ---- 4 · The hero's load plate matched the OLD scrim -------------
   .hero--stage paints --brand-900 (#000c63 = rgb(0,12,99)) behind the
   photograph. That is character for character the navy section 1 just
   took out of the scrim, so until the LCP image decodes the hero
   flashed the full-saturation blue this pass exists to remove, then
   settled into the desaturated one. Point it at the same token the
   scrim uses so the plate and the veil cannot drift apart again.
   --brand-900 itself is untouched: it is a palette token used
   elsewhere, and this is a hero-local concern. */
.hero--stage { background: rgb(var(--scrim)); }


/* ==================================================================
   v20b · THE MOBILE PASS
   "see each n every section in detail ... see in the mobile
    verstion also"

   Audited at 375x812 with device emulation on. Five findings, all
   real, none cosmetic. Document scroll width is 375 — no horizontal
   overflow anywhere except the hero's own Ken Burns slide, which
   overhangs by design.
   ================================================================== */

/* ---- 1 · A 16px floor on every field, or iOS zooms the page -----
   The fields resolved to 14.4-15.2px. Mobile Safari zooms the whole
   viewport whenever a focused input is under 16px, and it does not
   zoom back out on blur — the reader is left pinching their way back
   to a page they were halfway through. This is the one place a fixed
   px value beats the type scale: the number is a browser threshold,
   not a design decision, so it cannot be expressed in rem against a
   root that changes. Applied to every page, since every page that
   has a field has this bug.

   Named selectors, not a bare `input`: .field input is 0,1,1 and a
   bare element is 0,0,1, and a media query adds no specificity at
   all — the first draft of this rule lost to line 1070 and every
   field stayed at 15.2px. Verified resolved, not just written. */
@media (max-width: 640px) {
  .field input, .field textarea, .field select,
  .newsform input, .footer__sub input { font-size: 16px; }
}

/* ---- 2 · The carousel dots were a 30x3px target -----------------
   Three buttons, each 30 wide and 3 TALL, which is the visual bar
   and nothing else — well under the 24px WCAG 2.2 minimum and far
   under what a thumb can actually find. The bar has to stay 3px or
   it stops reading as a progress rule, so the target grows around
   it instead: the button keeps its painted size and gains a
   transparent ::before that reaches full finger height. Nothing
   moves on screen. */
.hero__dot { position: relative; }
.hero__dot::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* ---- 3 · #careers cards were 106px of text per column -----------
   The grid carried grid-template-columns:1fr 1fr as an INLINE style,
   which outranks every media query in this file, so it stayed two-up
   at 375 and gave each paragraph a 106px measure — roughly thirteen
   characters, nine lines of rag for two sentences. The inline style
   is gone from the markup and the intent lives here, where a
   breakpoint can reach it. minmax(0, 1fr) because a bare 1fr floors
   at min-content and would be pushed open by the longest word. */
.bento--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 560px) {
  .bento--pair { grid-template-columns: minmax(0, 1fr); }
}

/* ---- 4 · Footer links under the 24px minimum --------------------
   All six sit in the footer: the three mailto addresses measured
   19px tall and the three footer-bottom links 17px, both below WCAG
   2.2 AA target size. They are text links inside running copy, so
   they cannot be padded into blocks without breaking the line — the
   target extends vertically only, which grows the hit box without
   moving the baseline or the line box around it. */
.footer a[href^="mailto:"], .footer__bottom a { position: relative; }
.footer a[href^="mailto:"]::after, .footer__bottom a::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  height: 24px;
  transform: translateY(-50%);
}

/* ---- 5 · The two logo bitmaps reflowed after decode -------------
   Both wealthdoor-logo.png placements are sized by CSS height with
   no width or height attribute, so their width was unknown until
   the bitmap decoded. The height is fixed, so there was no vertical
   shift, but the logo snapped from 0 to its true width and shoved
   the row. Declaring the intrinsic ratio reserves the width up
   front. Done in CSS rather than as width/height attributes because
   both sit inside #brands, and that markup stays as it is. */
.barch__cell img, .brandcard__mark { aspect-ratio: 878 / 290; }


/* ================================================================
   v21 · THE NESTVEST LOCKUP
   ================================================================
   #brands used to set nestvest as live text — a bold Plus Jakarta
   "nestvest" with an orange full stop — because there was no asset.
   There is one now: assets/img/nestvest-logo.svg, the horizontal
   lockup (bird-on-nest mark, then the serif wordmark whose "v" is an
   upward arrow). It is composed from the two brand source files as
   vector, so it stays crisp at any size and needs no @2x bitmap.

   Its ratio is 5131:1000, far wider than the wealthdoor bitmap's
   878:290, so the shared reflow guard above has to be overridden
   rather than reused — hence a class instead of another element
   selector, and hence it sits after that rule.

   The heights are NOT the same as their wealthdoor siblings, and
   they are deliberately SMALLER. Equal box heights would be wrong
   here because the two logos spend their height very differently.
   Measuring the ink rows of wealthdoor-logo.png, the arc takes the
   top two thirds and the wordmark's x-height band is only 31% of
   the 290px canvas. In this lockup the wordmark is 78% of the
   canvas and its own x-height is 71% of that, so 55% of the box is
   x-height — nearly twice the ratio. Matched at 26px the nestvest
   wordmark drew almost double the size of "wealthdoor" next to it
   and swamped the row.

   Sized side by side against the 26px bitmap, 22px is where the two
   read as equals: nestvest's serif is much lighter than the bold
   wealthdoor wordmark, so a slightly larger x-height is what it
   takes to balance, and below about 20px the bird loses its egg.

   The photo band on both cards drops from 16/9 to 21/9 (declared up
   at .brandcard__media, not here, so there is one aspect-ratio for
   that element rather than a base and an override). At the 1240px
   max width each card is ~600px, so the image goes 338px -> 257px.
   The photographs are already cropped with the subject centred and
   object-fit: cover holds that centre, so the 81px comes off the
   ceiling and floor, not off anyone's face.

   The ratio is repeated on both rules rather than hoisted into a
   shared .mark--nv. A bare class is (0,1,0) and .barch__cell img is
   (0,1,1), so the wealthdoor bitmap's ratio won and the lockup drew
   at 3.03:1 — squashed to 94px wide instead of 159px. Two chained
   selectors clear it; a lone class cannot. */
.brandcard__mark.mark--nv { aspect-ratio: 5131 / 1000; width: auto; height: 24px; }
.barch__cell img.mark--nv { aspect-ratio: 5131 / 1000; width: auto; height: 22px; }


/* ================================================================
   v22 · THE ORANGE IS THE LOGO ORANGE, AND THE RULES COME OFF
   ================================================================

   1 · The emphasised word in a headline was the wrong orange.

   wealthdoor-logo.png contains exactly two opaque colours: #0013A0
   across 69,508 pixels and #F05A29 across 9,568. So the brand orange
   is #F05A29, which is what --accent has always held. But every
   <em> in a headline was painted --accent-700 (#c23f14), a brick
   that reads noticeably browner and duller beside the mark. That is
   most obvious in #what-we-do, where "businesses" sits a few hundred
   pixels below the logo in .eco__hub and the two are compared
   directly.

   The em rules now use --accent. This is a contrast decision as much
   as a colour one, so the numbers matter. #F05A29 on white measures
   3.39:1 -- under the 4.5:1 normal-text floor but over the 3:1
   large-text floor. Every selector changed is a headline: .h2 is
   clamp(2.15rem, 4.1vw, 3.4rem), so 34.4px at its very smallest,
   comfortably past the 24px large-text threshold at any weight.

   Two orange <em>s were deliberately LEFT on --accent-700, and it
   would be a regression to "finish the job" by changing them:

     .quoteband__q em   clamp(1.3rem, 2.2vw, 1.8rem) at weight 400.
                        Bottoms out at 20.8px, which is under 24px,
                        so it is normal text and needs 4.5:1.
     .newsstrip__t h3 em  1.18rem flat -- 18.9px. Same reasoning.

   #c23f14 scores 5.23:1 on white, so both clear the normal-text
   floor. They are a darker shade of the same brand hue, not a
   different colour, and at that size the difference is invisible.

   ^ SUPERSEDED BY v24. Both are on --accent now, and v24 pays the
   contrast cost in type rather than in hue. See the foot of file.

   2 · Every section had a hairline across the top.

   .divide-top put a 1px border on 24 of the 26 section elements, so
   the page read as a stack of ruled rows -- the line under one
   section is what you actually see, which is why it reads as a
   bottom border. taste-skill/SKILL.md:652 is explicit: hairlines
   drawn to make a page "feel designed" are banned; keep them only
   where they organise real content. These organised nothing. The
   v20 pass already gave the page its rhythm through four tinted
   bands and clamp(4.5rem, 8.5vw, 8.5rem) of section padding, so the
   rules were doing a job that was already done, twice.

   The border is dropped in CSS rather than by stripping the class
   from 26 sections across 13 files: the markup stays as it is, and
   one line brings the rules back if they are ever wanted. Three
   declarations set it, at 215, 1047 and 2180, so all three are
   overridden here at the foot of the file.

   hr is untouched. It is a real element used inside content, not
   section furniture. */
.divide-top,
.band--warm .divide-top { border-top: 0; }

/* ================================================================
   v24 · THE LAST OF THE LINES, AND ONE HEADLINE THAT WANTED ROOM
   ================================================================

   1 · The hairlines that survived v22.

   v22 took the border off .divide-top and read the page as done.
   It was not. Walking the rendered DOM and collecting every element
   over 200px wide that paints a top or bottom edge turns up two
   rules still drawing full-width rules the page does not need:

     p.seclabel::after       10 instances, #e2e6f1
     .reachlist li + li       3 instances, #e2e6f1
     .contactpoints li + li   2 instances, #e2e6f1

   .seclabel::after is the one the eye actually catches. It is the
   rule that runs from the end of a section label out to the edge of
   the column, and because a label sits at the top of a section, the
   rule you see below any given block of content is the *next*
   section's label rule. That is why it reads as a bottom border on
   every section -- the same illusion v22 diagnosed for .divide-top,
   from a second source it missed.

   It cannot be deleted at 639, because .sechead--centre at 1995
   restyles this same pseudo-element into the little 34x2 orange
   dash under a centred label and never re-declares `content`. Drop
   the base rule and the dash goes with it -- three of them on this
   page alone. So the pseudo-element keeps its content and loses its
   box, and the centred variant puts the box back.

   The two list rules are a closer call, and they go for a different
   reason than "no hairlines": those rows are already separated by
   1.05rem of block padding and each one leads with an icon, so the
   rule is decoration on a list that was legible without it.

   .reachlist and .contactpoints are the same component twice --
   identical display, gap and padding-block at 1731 and 1901 -- so
   they are treated as one. Missing the second is easy: #contact
   sits 12,000px down the page, and a fix verified only at #global
   looks complete while half the lines are still there.

   Everything else the scan found stays. Cards, inputs, .frame,
   .imgslot, .regbadge and the footer rules bound real objects or
   real controls -- they are edges with a job, not section
   furniture, and the brief was the lines under the sections. */
.seclabel::after { display: none; }
.sechead--centre .seclabel::after { display: block; }
.reachlist li + li,
.contactpoints li + li { border-top: 0; }

/* 2 · "One promise, across three businesses." on one line.

   The <br /> in the markup is gone, but that alone would only have
   moved the break, not removed it: .sechead is capped at 46rem =
   736px and the headline measures ~884px set on one line at its
   54.4px display size. It would have wrapped in the same place and
   looked identical, which is the trap here.

   So the centred head gets its own cap. 60rem = 960px clears 884px
   with room for the letter-spacing to breathe, and still sits well
   inside the 1240px wrap. The cap is only widened for the *centred*
   variant, because that is the one holding a display headline meant
   to be read as a banner; left-aligned .sechead keeps 46rem.

   .lead has to be pulled back to 46rem by hand. It was inheriting
   its measure from the 736px parent, and letting it stretch to 960
   would put the body copy at roughly 105 characters -- well past
   the 75ish where a line stops being comfortable to track. The
   headline wants width; the sentence under it does not.

   text-wrap: balance is on the h2 so that if a narrow viewport does
   force a wrap, it breaks into even lines instead of leaving one
   word stranded. */
.sechead--centre { max-width: min(60rem, 100%); }
.sechead--centre .h2 { text-wrap: balance; }
.sechead--centre .lead { max-width: 46rem; margin-inline: auto; }

/* 3 · Paying for the logo orange in type instead of in hue.

   Every orange on the site is now #F05A29 exactly, including the
   two <em>s v22 held back. v22 was right that they were the risky
   ones and wrong about the numbers, which were read off the CSS
   rather than off the rendered page:

     .quoteband__q em   v22 said 20.8px. Rendered at desktop it is
                        28.8px -- 2.2vw wins over the 1.3rem floor
                        until about 1090px viewport. Large text
                        already; 3.18:1 on the --warm-50 ground
                        clears the 3:1 floor.
     .newsstrip__t h3 em  18.88px at weight 500. Genuinely normal
                        text, genuinely 3.39:1 on white, genuinely
                        under 4.5:1. v22's one real catch.

   Two small type changes settle both rather than reintroducing a
   second orange. The quote's clamp floor goes 1.3rem -> 1.5rem so
   it stays >= 24px at every viewport instead of only wide ones, and
   the news <em> goes to weight 700, which at 18.88px crosses the
   14pt-bold threshold and moves it to the same 3:1 floor. Bolding
   an emphasised word is what <em> is for, so it costs nothing.

   The result: one orange, matching the mark, and no text below its
   WCAG AA floor. */
.quoteband__q { font-size: clamp(1.5rem, 2.2vw, 1.8rem); }
.newsstrip__t h3 em { font-weight: 700; }


/* ================================================================
   v25 · WHAT WE BELIEVE BECOMES A SECTION, AND THE TRIO GOES
   ================================================================

   #believe was four lines of markup: a heading split off from a
   single sentence, sitting in a .split meant for a heading beside
   an image. It read as a caption to nothing. The section directly
   under it, #experience, was three equal cards in a row -- the
   layout taste-skill-v1 bans outright at line 114, "the generic
   '3 equal cards horizontally' feature row", and the client asked
   for it gone. Both problems have the same answer, so they are
   solved together: the convictions that were trapped in the card
   row move up into #believe and become the thing it was missing.

   The copy is rewritten rather than moved. The trio said what we
   DO -- start with the goal, one adviser, advice you can check --
   and #standard immediately below already says "advice that puts
   you first, not what earns us the most", while #regulation says
   the fee-only part again at 482 and .contactpoints says it a
   third time at #contact. Lifting the words verbatim would have
   put the same sentence on screen four times. So #believe now
   states the WHY -- a plan begins with a life, advice is a
   relationship, trust has to be checkable -- and leaves the
   mechanics to the two sections built to carry them. The page
   argues once and then evidences itself.

   LAYOUT. Three things, and the obvious move is three columns
   again, which is the banned row wearing a different section id.
   It is an editorial stack instead: a wide belief set at display
   scale, then numbered rows where the ordinal, the claim and the
   reasoning each hold their own column. Reading down a numbered
   list is what a manifesto wants anyway -- convictions are ordered,
   features are parallel, and the vertical form says which of the
   two this is.

   Rows are separated by space, never by a rule. v24 spent its
   length removing hairlines from this page; adding three back here
   would undo it, and taste-skill-v1:53 asks for logic-grouping
   "via purely negative space" regardless. 2.6rem of gap does the
   work a border was doing.

   GROUND. #believe stays white. It is not an oversight: v20's rule
   is that no two tinted grounds may touch, and with #experience
   deleted #believe now sits directly against .band--warm
   #standard. Tinting it would put two warm bands edge to edge and
   collapse the rhythm the bands exist to create.

   LEFT BEHIND. .statement at 670-674 was written for the old
   #believe and is now referenced by no page; it stays in the file
   under the same convention as every superseded block here, so the
   history reads. .trio at 799-811 looks equally dead from
   index.html and is NOT -- _m.html still renders it. Deleting it
   on the strength of a grep against this page alone would take a
   live layout down with it. */
.creed__stmt {
  max-width: 20ch;
  text-wrap: balance;
  margin-block: 1.1rem clamp(2.8rem, 5vw, 4.2rem);
}

.creed { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(2rem, 3.4vw, 2.6rem); }
.creed__item {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr) minmax(0, 1.35fr);
  gap: clamp(1rem, 2.6vw, 2.4rem);
  align-items: start;
}
.creed__n {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  padding-top: 0.42rem;
}
.creed__t {
  font-family: var(--font-display);
  font-size: clamp(1.18rem, 1.75vw, 1.5rem);
  font-weight: 500;
  line-height: 1.24;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: balance;
  margin: 0;
}
.creed__p {
  font-size: 0.98rem;
  line-height: 1.66;
  color: var(--muted);
  max-width: 58ch;
  margin: 0;
}

/* Under 900px the three columns stop being columns. The ordinal
   goes inline above the claim rather than beside it, because a
   3.25rem gutter on a 375px screen spends 9% of the width on two
   digits. */
@media (max-width: 900px) {
  .creed__stmt { max-width: 24ch; }
  .creed__item { grid-template-columns: 1fr; gap: 0.55rem; }
  .creed__n { padding-top: 0; }
  .creed__p { max-width: 62ch; }
}


/* ================================================================
   v26 · THE ELEGANCE PASS
   ================================================================

   A designer's read of the whole page, with taste-skill-v1 as the
   brief. Three things were wrong and all three were the same kind
   of wrong: the page was saying more than it needed to, in more
   boxes than it needed.

   1 · #believe said it twice. The section shipped in v25 with a
   display statement, a supporting paragraph under it, and three
   two-sentence reasonings -- around 208 words before the reader
   reaches #standard, which is the section that actually has to
   sell something. Worse, #why further down states the same four
   convictions almost verbatim across its whycards ("legally bound
   to act in your interest", "a named person holding your whole
   picture", "you can look us up"). A manifesto that is restated
   400px later is not a manifesto, it is a draft. So the sub-
   paragraph is gone entirely and each reasoning is cut to one
   clause -- 63 words, a 70% cut. The claims now sit on a single
   line each at desktop, which is what makes the numbered stack
   scan as a list rather than as three small essays.
   .creed__head and .creed__sub were deleted with the copy; what
   survives is .creed__stmt, which only has to hold the statement
   and set the space beneath it.

   2 · Two of the three IMAGE placeholders are now photographs.
   They pointed at standard-fees.jpg, who-we-are.jpg and
   regulation.jpg, none of which exist on disk -- the page was
   shipping three empty boxes with the word "Image" in them.
   Deleting #experience in v25 freed exp-goal.jpg (a goal written
   by hand beside the charts) and exp-check.jpg (a magnifier over
   a printed statement of holdings and fees); they go to #standard
   and #regulation respectively, where the subject matter is
   already what the copy is about. exp-adviser.jpg was NOT reused
   -- it is on this page already, in .quoteband.

   3 · #who-we-are had no photograph left and is not getting a
   fabricated one. Rather than keep an empty 4:3 box next to the
   copy, the section drops to .splithead: headline low-left,
   supporting copy and the button aligned to its baseline on the
   right. It is the one text-only section on a page of image
   splits, which gives the run of sections a beat of quiet before
   #regulation -- the same job the empty box was failing to do.
   This is taste-skill-v1:226, "are cards omitted in favour of
   spacing where possible", answered honestly.

   .imgslot keeps its placeholder rules. One slot is gone and two
   are filled, but the component is how a photograph gets dropped
   into this page later, and .imgslot__note is what makes an
   unfilled one legible instead of blank. */

/* The regulator badges were the last 3-across card row on the
   page. The content has to stay -- these are disclosure facts,
   not features -- but the chrome does not: three bordered boxes
   directly under a section that already carries a photograph and
   a ruled pull-quote is four framed things stacked. Cards give
   way to a single top rule and hairline dividers, which is the
   "divide-y" grouping taste-skill-v1:53 asks for and reads much
   closer to a filing than a feature grid. */
.regbadges--row {
  gap: 0;
  border-top: 1px solid var(--warm-line);
  margin-top: clamp(1.8rem, 3.4vw, 2.6rem);
}
.regbadge {
  background: none;
  border: 0;
  border-radius: 0;
  padding: clamp(1.2rem, 2vw, 1.6rem) clamp(1.2rem, 2.4vw, 2rem) 0 0;
}
.regbadge + .regbadge {
  border-left: 1px solid var(--warm-line);
  padding-left: clamp(1.2rem, 2.4vw, 2rem);
}
/* No hover: there is no longer a box edge for it to light up, and
   a border-colour transition on a divider shared with the panel
   next door would make the wrong element look interactive. */
.regbadge:hover { border-color: var(--warm-line); }
.regbadge__note { max-width: 34ch; }

/* Below 860px .regbadges--row is already one column, so the
   divider has to turn ninety degrees with it. */
@media (max-width: 860px) {
  .regbadge { padding-right: 0; }
  .regbadge + .regbadge {
    border-left: 0;
    border-top: 1px solid var(--warm-line);
    padding-left: 0;
  }
}


/* ================================================================
   v27 · THE VALUES ROW GOES BACK TO FIVE
   ================================================================

   The client sent a full-page comp. On it, OUR VALUES is five
   columns in a single row and each card carries two short lines.
   The live page was three-up with an orphan row of two, which
   v18's note at 2381 chose deliberately: repeat(5, 1fr) inside a
   1240px wrap left 212px a card, and the copy then ran ~24
   characters over five lines, below the ~30 where prose stops
   reading.

   That reasoning was sound about the measure and wrong about the
   cause. The fix for 24-character lines is not a wider card, it is
   less copy -- the same call already made in v26 for #believe.
   Each value is cut to one sentence of roughly 55 characters, so
   the card is three lines, not five, and 24 characters over three
   lines reads as a caption, which is what these are. Five-up also
   removes the orphan row, which was the uglier of the two problems:
   two cards centred under three reads as a layout that ran out.

   So the min-width:1081px flex-wrap override at 2390 is reverted
   to the grid it was suppressing. It stays in the file, superseded,
   under the same convention as every other retired block here.

   The headline loses its <br /> and its full-line emphasis. The
   comp puts one word in orange -- "everything" -- and so does
   #what-we-do, whose "businesses" is the only orange word in that
   headline. A whole line of accent on a screen that also carries
   five orange .crule dashes was the most orange thing on the page. */
@media (min-width: 1081px) {
  .valuegrid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    justify-content: stretch;
  }
  .valuegrid > .valuecard { flex: initial; }
}

/* Centred leads were wrapping to a widow: "…what we say no / to."
   under OUR VALUES, "…advice that puts you / first." under OUR
   ECOSYSTEM. v24 gave .sechead--centre .h2 text-wrap: balance and
   stopped there; the sentence under it needs the same treatment
   or the block ends on a two-character line. */
.sechead--centre .lead { text-wrap: balance; }

/* Same widow, left-aligned this time: the hero lead broke as
   "...across the US and / India." balance fixes it without
   touching the measure. */
.hero .lead { text-wrap: balance; }


/* ================================================================
   v28 · #BELIEVE, SECOND CUT
   ================================================================

   v26 took this section from ~208 words to 63 by deleting the
   sub-paragraph and shortening each reasoning to a clause. The
   client asked for less again, so the reasonings go entirely.
   Three convictions, stated and left alone -- 30 words in the
   whole section, and nothing on screen that a reader has to
   finish before the next line starts.

   Losing the third column changes what the layout should be. The
   v25/v26 row -- ordinal, claim, reasoning -- only earned its
   width because something sat in the right-hand track. With that
   gone, a full-width row would strand the claim in the left third
   of a 1240px wrap with 800px of nothing beside it. So the
   section splits: the label and the statement hold the left, the
   three convictions stack on the right at display scale. The two
   columns are close enough in height to read as a spread rather
   than a heading with a list bolted under it.

   The statement is cut too, from "Your plan should be built
   around your goals, not an industry average." to "Built around
   your goals, not an average." Half a column is not the full
   measure it had, and the long version ran five lines against a
   right column of three -- the imbalance the split was meant to
   fix. The short version, held to 13ch, is three lines of display
   type against three convictions: 214px of lede against 175px of
   list, near enough to level. 18ch was tried first and ran four
   lines, and a 26ch cap on .creed__t wrapped two of the three
   convictions onto a second line; both are gone.

   .creed__t stops being an <h3>. With no paragraph beneath it,
   it is not heading anything; it is the content. The ordinals
   stay aria-hidden -- <ol> already tells a screen reader that
   this is a numbered list of three, and reading "zero one" over
   the top of it is noise. */
.creed__split {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

/* Overrides the v25 rule: no trailing margin now that the
   statement sits beside the list instead of above it. */
.creed__stmt {
  max-width: 13ch;
  margin-block: 1.1rem 0;
}

.creed { gap: clamp(1.5rem, 2.6vw, 2.1rem); }
.creed__item {
  grid-template-columns: 2.6rem minmax(0, 1fr);
  gap: clamp(0.75rem, 1.4vw, 1.1rem);
  align-items: baseline;
}
.creed__n { padding-top: 0; }
.creed__t {
  font-family: var(--font-display);
  font-size: clamp(1.28rem, 2vw, 1.72rem);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.014em;
  color: var(--ink);
  text-wrap: balance;
  margin: 0;
}

@media (max-width: 900px) {
  .creed__split { grid-template-columns: 1fr; gap: clamp(2rem, 6vw, 2.8rem); }
  .creed__stmt { max-width: 22ch; }
  .creed__item { grid-template-columns: 2.2rem minmax(0, 1fr); }
  .creed__t { max-width: none; }
}

/* =====================================================================
   v41 — 2026-08-10 — CAREERS PAGE
   ---------------------------------------------------------------------
   careers.html is rebuilt from the client's "Careers & Culture" document
   and reuses the homepage vocabulary wherever one already fits, so the
   two pages read as one site: .pagehero, .split + .imgslot, .sechead,
   .seclabel, .bento--pair, .divisions (the five values), .steps (the
   hiring process), .joinus, and the warm band rhythm.

   Three things the homepage had no component for, added here:

   .afternote  A single closing line after a list — the "how we work
               together" habits under the values, and the "don't see your
               role" line under the join CTA. Muted, indented to the list's
               text column so it reads as a footnote to what precedes it
               rather than a new paragraph of body copy.

   .voices     Two employee quotes, side by side. Deliberately NOT the
               homepage .quoteband: that component pairs one quote with a
               photograph, and we have no employee photography. Rather than
               invent a face, these are text-only, attributed by team and
               market only. They are the sample stories from the client's
               document and are marked as placeholders in the HTML.

   .teamlist   Eight teams. Eight cards would have been a wall, and the
               taste rules bar a generic three-across card row anyway, so
               this is a divided list in two columns: the group reads as
               one object held together by rules, not eight boxes. Each row
               is a hairline-separated pair of title and one sentence.
   ===================================================================== */

.afternote {
  color: var(--muted);
  font-size: 0.97rem;
  max-width: 62ch;
  margin-top: clamp(1.6rem, 2.6vw, 2.2rem);
}
.divisions + .afternote { padding-left: 0; }
@media (min-width: 861px) {
  .divisions + .afternote { padding-left: calc(4rem + clamp(1rem, 3vw, 2.5rem)); }
}

/* ---------- Voices ---------- */
.voices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 1.8vw, 1.5rem);
}
.voice {
  margin: 0;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 2.6vw, 2.2rem);
  display: flex;
  flex-direction: column;
  transition: border-color 0.3s var(--ease);
}
.voice:hover { border-color: var(--brand-200); }
.voice__q {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.8vw, 1.45rem);
  font-weight: 500;
  line-height: 1.34;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: pretty;
  margin: 0;
}
.voice__q::before { content: '\201C'; }
.voice__q::after { content: '\201D'; }
.voice__body {
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.65;
  margin-top: 1.05rem;
}
.voice__by {
  margin-top: auto;
  padding-top: 1.3rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ---------- Team list ---------- */
.teamlist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 4.5rem);
  border-top: 1px solid var(--line);
}
.teamrow {
  padding-block: clamp(1.15rem, 2vw, 1.6rem);
  border-bottom: 1px solid var(--line);
}
.teamrow h3 {
  font-family: var(--font-sans);
  font-size: 1.06rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.35rem;
}
.teamrow p {
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.6;
  max-width: 48ch;
}

/* Warm-band inheritance. The v20 band rules name each component that has
   a hairline explicitly, so the three added above have to opt in or they
   render a cool grey line on a warm ground. */
.band--warm .voice,
.band--warm .divisions,
.band--warm .division,
.band--warm .teamlist,
.band--warm .teamrow,
.band--warm .steps,
.band--warm .stepr { border-color: var(--warm-line); }
.band--warm .division:hover { background: var(--warm-100); }

@media (max-width: 900px) {
  .voices { grid-template-columns: minmax(0, 1fr); }
  .teamlist { grid-template-columns: minmax(0, 1fr); }
}

/* The site is now two pages, so the primary nav needs a current-page
   state for the first time. Weight only -- a rule or a colour would put
   a second accent on a page that already spends its one on the headline
   verb. */
.nav__links a[aria-current='page'] { color: var(--ink); font-weight: 600; }

/* ============================================================
   v29 · "remove the proof strip, the assure strip, the arc, the
   fee-only line, and the grey half of every headline"
   ------------------------------------------------------------
   Six client notes, all subtractive except two. The removals are
   recorded next to the rules they replaced (search "REMOVED
   (v29)"); what follows is only what needed new CSS.
   ============================================================ */

/* ---- 1 · Headlines are one colour --------------------------
   Every h1/h2 on the site was written as two halves: an inked
   clause and a <span class="mute"> clause at --faint (#8892ab,
   3.97:1 on white). It was doing two jobs at once -- marking a
   grammatical break AND lowering the second clause's voice --
   and the second job is the one the client is reading as a
   headline that fades out. The break is already carried by the
   line wrap and by the sentence itself.

   Scoped to headings rather than deleting .mute, because .mute
   is a general utility and body copy may want it later. The
   hero rule is restated at equal specificity: .hero--stage h1
   .mute is (0,2,1) and a bare h1 .mute (0,1,1) would lose to it
   however late it sits in the file.

   The orange <em> is untouched. That one IS the accent, it is
   the logo orange, and it stays. */
h1 .mute, h2 .mute, h3 .mute, h4 .mute,
.display .mute, .h2 .mute { color: inherit; }
.hero--stage h1 .mute { color: inherit; }

/* ---- 2 · Regulator marks in the hero -----------------------
   The client asked for "the SEC logo and the SEBI logo" beside
   the two registration lines. Neither official seal ships with
   this project, and both are government trademarks whose use by
   a regulated firm is a compliance decision, not a design one --
   a plausible-looking seal drawn here would be a fabricated
   credential on the page that states the firm's registrations.

   So the marks are typographic, and deliberately the SAME marks
   already used in #regulation (.regbadge__code): the site says
   SEC and SEBI in its own voice, twice, consistently. When the
   official artwork is cleared it drops straight in -- the
   markup comment in index.html carries the swap, and
   .regmark__art is already sized for it. */
.regmark {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; min-width: 3.1rem; padding: 0.16rem 0.42rem;
  font-family: var(--font-sans);
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.11em;
  line-height: 1.35; text-transform: uppercase;
  border-radius: var(--radius-xs);
  color: var(--brand); background: var(--brand-50);
  border: 1px solid var(--brand-200);
}
.regmark__art { height: 20px; width: auto; flex: none; display: block; }
/* One chip, then its sentence -- so the gap inside a pair has to be
   tighter than the gap between the pairs, or the two read as four. */
.microline--reg { gap: 0.7rem 1.6rem; }
.microline--reg > span { gap: 0.58rem; }

/* On the hero the chips sit on a photograph, so they invert: the
   brand blue has nothing to hold on to there. 1px of white at 42%
   over the scrim measures 4.6:1 against the chip label. */
.hero--stage .regmark {
  color: #fff;
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.42);
}
@media (max-width: 560px) {
  .regmark { min-width: 2.8rem; font-size: 0.62rem; }
  .microline--reg { gap: 0.6rem 1.1rem; }
}

/* ---- 3 · "01 02 03, make it better in design" --------------
   The three convictions were a tiny mono ordinal (0.78rem, the
   size of a form label) sitting beside a 1.72rem display line.
   Nothing about that said "these are the three things"; the
   numbers read as list furniture and the column read as loose
   text. Two changes:

   The ordinal becomes a real numeral -- display face, the same
   size as the statement it marks -- so the pair reads as one
   typographic unit instead of a label plus a sentence. It is
   set in --brand-200, which is quiet enough to sit behind the
   words at that size. It does NOT take the accent: this section
   already spends its one orange on "your goals" in the
   statement, and three big orange numerals beside it would be a
   second, louder claim on the same eye.

   The statements then get room. gap goes from a flat 2.1rem to
   3.0rem, which is what actually makes three lines read as
   three convictions rather than as a wrapped paragraph -- and
   the right column had the vertical space to spend, since the
   lede beside it runs three lines of display type.

   No rule, no card, no bullet. The numeral is the structure. */
.creed { gap: clamp(2rem, 3.4vw, 3rem); }
.creed__item {
  grid-template-columns: minmax(2.9rem, auto) minmax(0, 1fr);
  gap: clamp(0.9rem, 1.7vw, 1.35rem);
  align-items: baseline;
}
.creed__n {
  font-family: var(--font-display);
  font-size: clamp(1.28rem, 2vw, 1.72rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.3;
  color: var(--brand-200);
  padding-top: 0;
}
/* Hanging the numerals outside the text column keeps the three
   statements on one hard left edge, which is the thing being
   read. Only above 900px -- stacked, there is no column to hang
   from and the numeral belongs above its line. */
@media (min-width: 901px) {
  .creed__item { margin-left: calc(-1 * clamp(0.9rem, 1.7vw, 1.35rem) - 2.9rem); }
  .creed { padding-left: calc(clamp(0.9rem, 1.7vw, 1.35rem) + 2.9rem); }
}

/* ---- 4 · The promise loses its grey half too ---------------
   .promise__quote strong was --faint at weight 400: a <strong>
   rendering lighter and thinner than the sentence around it,
   and the same two-tone headline the client is removing --
   here on the one line that states the promise. Inked, and
   given the weight the tag was asking for. */
.promise__quote strong { color: var(--ink); font-weight: 600; }

/* ---- 5 · The first hero slide is a new photograph ----------
   Slide 1 changed at the client's request: the boardroom-with-
   market-screens is out, a lounge conversation behind glass is in.
   Two consequences, both handled here rather than by touching the
   scrim, which is shared by all three slides and was measured
   against them.

   Contrast first, because the file header asks for it. The scrim
   was re-measured over the new photograph by compositing it over
   every pixel of the copy column at 375/760/1024/1440/1728px: the
   new slide scores 5.27-7.17:1 for white type where the outgoing
   one scored 4.15-6.61:1. It is a brighter picture but a flatter
   one, and it clears the old floor at every width, so the alphas
   below stay untouched. See CREDITS.md for the method.

   Crop second. The source is 16:9 and the hero is taller than it
   is wide on a phone, so `cover` throws away roughly three
   quarters of the frame -- and dead centre of this particular
   picture is the back of someone's head. Pulling the crop to 68%
   puts the two people who are facing each other in the window
   instead. Scoped to :first-child: the other two slides are
   skylines, which are composed centrally and would be spoiled by
   the same shift. */
@media (max-width: 720px) {
  .hero--stage .hero__slide:first-child { object-position: 68% 42%; }
}

/* ============================================================
   v30 · "believe: better. ecosystem: no hub, no wires, photos
   back, logo top right. brands: real buttons, equal size.
   global: home keeps the headline, the subtext, a CTA and the
   picture -- the rest moves to an About page, and About grows
   subsections in the nav."  (client, 2026-08-11)
   ============================================================

   Six asks, in the order they were given. Each is numbered
   below and each says what it replaced, because every one of
   them supersedes something written two or three revisions ago
   that still reads as current if you only look at the CSS.

   ---- 1 · #believe, third cut ------------------------------

   v28 cut this section to a lede and three display lines, and
   v29 turned the ordinals into display numerals. What was left
   is honest but thin: three sentences floating in a column
   with nothing holding them, and a left column of two elements
   against a right column of three, so the split reads as
   lopsided rather than as a pair.

   Three changes, no new colour and no new motion:

   The convictions get their reasoning back. v26 deleted it to
   cut 208 words to 63, and that was right about the words and
   wrong about the shape -- a claim with no sentence under it
   is a slogan, and this is the section where a stranger decides
   whether the firm means it. .creed__p already exists from v25;
   it is used again rather than reinvented. The three sentences
   are drawn from copy already on this page (the goal-first
   process in #standard, the named adviser in #why, the
   published disclosures in #regulation), so nothing here is a
   claim the site does not already make and stand behind.

   The rows get a hairline. Nothing separated the three before
   except vertical space, which at this type size reads as one
   loose paragraph. A 1px --line above each item turns the
   column into a register -- and because the min-width:901px
   rule below hangs the numerals outside the text column, the
   rule runs the full width including the numeral, which is
   what makes the ordinals read as an index rather than as
   decoration. gap goes to 0: the padding inside each row now
   does that job, and keeping both would double it.

   The lede gets the subtext and one link. The subtext is the
   line from the message document that this section was always
   meant to carry, and the link points at #standard, which is
   the section that defines the promise the three convictions
   are drawn from. Both are quiet: the subtext is body copy at
   --muted, the link is the same brand blue as every other
   in-page link. It costs the accent nothing -- the one orange
   in this section is still the <em> on "your goals".  */

.creed { gap: 0; }
.creed__item {
  padding-block: clamp(1.3rem, 2.1vw, 1.85rem);
  border-top: 1px solid var(--line);
}
.creed__p { margin-top: 0.6rem; max-width: 52ch; }

/* The lede column. max-width on the subtext rather than on the
   column, so the seclabel and the statement keep their own
   measures (13ch on the statement, set in v28). */
.creed__sub {
  margin-top: 1.15rem;
  font-size: 0.98rem;
  line-height: 1.66;
  color: var(--muted);
  max-width: 34ch;
}
.creed__go {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin-top: 1.5rem;
  font-size: 0.92rem; font-weight: 600; color: var(--brand);
}
.creed__go .arrow { transition: transform 0.25s var(--ease); }
.creed__go:hover .arrow { transform: translateX(4px); }

/* Stacked, the numeral sits in a 2.2rem column beside the claim
   (v28) and the reasoning has to clear it, or it hangs under
   the digits. Subgrid would be the clean answer; it is not safe
   enough across the browsers this site supports, so the content
   is wrapped in .creed__c and the row stays two columns at
   every width. */
@media (max-width: 900px) {
  .creed__p { max-width: none; }
  .creed__sub { max-width: 46ch; }
}

/* ---- 2 · The ecosystem loses its diagram ------------------

   v29 built this section as a wiring diagram: a glass hub
   carrying the Wealthdoor mark, a 1px bus under it, three drops
   falling onto the cards, and a logo plate closing each card.
   The client has asked for all of it out except the marks, and
   for the photographs to come back where the plates were.

   The diagram is the right thing to lose. It drew a structure
   the page already states twice -- the brand architecture in
   #brands says "one group, two child brands" with the marks
   themselves, and the section head says "one promise, across
   three businesses". A third telling in 1px rules added a
   drawing to look at, not a fact to read. And it was fragile:
   .eco__wires was already display:none below 940px, so two
   thirds of visitors never saw the diagram the layout above
   them was built around.

   What replaces it is the arrangement each card was missing.
   The mark moves to the head of the card, opposite the icon --
   a masthead, which is where a reader looks for "whose is
   this", and where it no longer needs .ecocard__brandname
   repeating in type what the logo already says. The photograph
   takes the foot, on margin-top:auto so the three pictures line
   up across the row whatever the copy above them does. That
   ordering matters: icon and mark, then the claim, then the
   people it is about, then the way in. Photo-first would have
   made three magazine cards; photo-last makes three statements
   with evidence under them.

   .eco__hub, .eco__wires, .eco__bus, .eco__drop, .ecocard__brand
   and .ecocard__brandname are now referenced by no page. They
   stay in the file under the same convention as every other
   superseded block here.  */

/* The masthead. space-between, not a grid: the two marks have
   very different widths and any fixed column would leave one of
   them floating short of the right edge -- which is the exact
   corner the client asked for. */
.ecocard__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  padding: clamp(1.3rem, 2.2vw, 1.7rem) clamp(1.3rem, 2.2vw, 1.7rem) 0;
}
.ecocard__badge { margin: 0; }
/* Height, not width -- the optical match measured in v21, scaled
   down from 26/22 to 20/17 now that the mark is a masthead
   beside a 40px icon rather than a plate of its own. */
.ecocard__logo { height: 20px; width: auto; display: block; flex: none; }
.ecocard__logo--nv { height: 17px; aspect-ratio: 5131 / 1000; }

/* The photograph. 16/9 as it was before v29 -- CREDITS.md
   records that ratio as the contract for these three files, and
   the crops were chosen against it. */
.ecocard__media {
  margin-top: auto;
  position: relative; overflow: hidden;
  aspect-ratio: 16 / 9;
  background: var(--soft);
  border-top: 1px solid var(--line-faint);
}
.ecocard__media > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
/* .ecocard__body had margin-top:auto's job before; the media has
   it now, so the body sits tight under the masthead and the gap
   opens between copy and photograph instead. */
.ecocard__body { padding-top: 1.15rem; }

/* ---- 3 · The brand sites become buttons -------------------

   .sitepill was a 0.83rem hairline pill at --muted: the same
   weight as a tag, on the one element in the card that is the
   point of the card. Two of them, sized by their own text, so
   "wealthdoor.us" and "wealthdoor.in" came out different widths
   and the pair read as a wrapped list rather than as a choice
   between two countries.

   A 1fr 1fr grid fixes the widths at both ends -- inside each
   card, and across the two cards, which are themselves equal
   columns -- so all four buttons match. They take the quiet
   filled treatment the site already uses for a secondary
   action: --brand-50 ground, --brand-200 edge, brand blue label
   at 600. Not btn--primary: these two sit under a paragraph
   that is not a call to action, and two solid blue buttons per
   card, four on the row, would outrank the hero's own CTA.

   The arrow goes to the right edge rather than trailing the
   word, which is what makes them read as destinations. */
.brandcard__sites { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.sitepill {
  justify-content: space-between;
  padding: 0.72rem 0.95rem;
  border-radius: var(--radius);
  font-size: 0.9rem; font-weight: 600;
  color: var(--brand);
  background: var(--brand-50);
  border-color: var(--brand-200);
  transition: background 0.22s var(--ease), border-color 0.22s var(--ease), color 0.22s var(--ease);
}
.sitepill:hover { background: var(--brand-100); border-color: var(--brand-500); color: var(--brand-600); }
.sitepill .arrow { transition: transform 0.25s var(--ease); }
.sitepill:hover .arrow { transform: translateX(3px); }

/* Under 420px the two names plus an arrow will not sit side by
   side without the type dropping below 0.8rem. One column, full
   width, still equal. */
@media (max-width: 420px) {
  .brandcard__sites { grid-template-columns: 1fr; }
}

/* ---- 4 · #global on the homepage is now a door, not a room -

   The section carried the whole argument for two markets: a
   headline, a subtext, four reasoned points with icons, two
   market tiles and a four-figure stats strip. That is an About
   page's worth of material sitting six sections into a homepage
   whose job is to route people, and it was the longest thing on
   the page by some way.

   The client's cut is the right one. The homepage keeps the
   claim (headline plus subtext), one way in, and the picture --
   the two market tiles, which are the only part of the panel
   that says "United States and India" without being read. The
   four points and the stats now open the Global reach section
   on about.html, where a reader who followed the CTA is asking
   for exactly that.

   Two consequences here. The column ratio widens a little in
   the panel's favour: with the list gone the left column is
   four short elements, and 1fr/1.05fr left it looking like a
   caption beside a picture. And .reachpanel now holds only the
   map, so its own padding is what separates the tiles from the
   card edge -- no stats strip, no border above them, nothing to
   change there.  */
.reach--brief { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); }
.reach__cta { margin-top: clamp(1.7rem, 2.6vw, 2.2rem); }
@media (max-width: 940px) {
  .reach--brief { grid-template-columns: minmax(0, 1fr); }
}

/* ---- 5 · "About us" grows subsections ---------------------

   The nav was six flat links and About pointed at an anchor
   halfway down the homepage. There is a real About page now, and
   the client asked for the sections under it to be reachable
   from the bar.

   A disclosure, not a hover menu. The trigger is a <button> with
   aria-expanded, and it opens on click -- which is what the
   client described, and it is also the only pattern that works
   on a touchpad, a phone in desktop width, and a keyboard
   without a separate story for each. Hover-only submenus fail
   all three and are the single most common accessibility defect
   in a marketing nav. The panel's first row is the page itself
   ("About overview"), so making the trigger a button costs the
   reader nothing: the page is still one press away.

   The panel is a floating card, not a strip of the bar. It has
   to read over a photograph (the nav sits transparent above the
   hero on index.html) as well as over white, so it takes a
   solid --paper ground and its own border and shadow rather
   than inheriting the bar's glass. That also means the inverted
   nav rules at 1567 do not need a counterpart here: the links
   inside the panel are always on white.  */

/* Both of these stretch so the panel can be positioned off the
   bottom of the BAR rather than off the bottom of the button. The
   button is ~20px tall in a 74px bar, so 100% + a gap measured
   from it lands at 57px -- eighteen pixels above the bar's own
   edge, with the card overlapping the nav it is meant to hang
   from. .nav__links has to stretch as well or .navdrop has only
   its own 20px row to stretch into. Neither changes what is
   drawn: both are flex boxes with align-items:center, so their
   children stay where they were. The 74px is not repeated here --
   it comes from .nav__inner, which is the one place it is set. */
.nav__links { align-self: stretch; }
.navdrop { position: relative; display: flex; align-items: center; align-self: stretch; }
/* Matches .nav__links a exactly -- same size, weight and colour --
   so the button does not read as a control sitting in a row of
   links. The reset is explicit because a <button> inherits none
   of it. */
.navdrop__btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0; border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: 0.91rem; font-weight: 500;
  color: var(--muted); line-height: inherit;
  transition: color 0.2s var(--ease);
}
.navdrop__btn:hover, .navdrop__btn[aria-expanded='true'] { color: var(--brand); }
/* The current-page treatment the nav already uses for links. */
.navdrop__btn.is-current { color: var(--ink); font-weight: 600; }

/* A caret drawn from two borders: no glyph, so it cannot pick up
   a font's own baseline, and it rotates rather than swapping. */
.navdrop__chev {
  width: 0.42rem; height: 0.42rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-0.12em) rotate(45deg);
  transition: transform 0.25s var(--ease);
}
.navdrop__btn[aria-expanded='true'] .navdrop__chev { transform: translateY(0.06em) rotate(-135deg); }

.navdrop__panel {
  position: absolute; top: calc(100% + 0.5rem); left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  min-width: 13.5rem;
  display: flex; flex-direction: column;
  padding: 0.5rem;
  border-radius: var(--radius-lg);
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
}
/* [hidden] is the state; the attribute is toggled from JS so the
   panel is out of the tab order when shut, which display:none by
   class alone does not guarantee if the class is ever missed. */
.navdrop__panel[hidden] { display: none; }
.navdrop__panel a {
  padding: 0.56rem 0.7rem;
  border-radius: var(--radius-xs);
  font-size: 0.89rem; font-weight: 500; color: var(--muted);
  white-space: nowrap;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.navdrop__panel a:hover { background: var(--warm-50); color: var(--brand); }
/* The overview row names the page the rest are anchors within,
   so it is separated rather than styled differently. */
.navdrop__panel a:first-child {
  color: var(--ink); font-weight: 600;
  margin-bottom: 0.3rem; padding-bottom: 0.66rem;
  border-bottom: 1px solid var(--line-faint);
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
}

/* Above the hero the button is white type like every other link
   in the bar. Restated at the same specificity as the rule at
   1567 and after it, so it wins on order rather than on weight. */
@supports selector(:has(*)) {
  body:has(.hero--underlap) .nav:not(.scrolled) .navdrop__btn { color: rgba(255, 255, 255, 0.86); }
  body:has(.hero--underlap) .nav:not(.scrolled) .navdrop__btn:hover,
  body:has(.hero--underlap) .nav:not(.scrolled) .navdrop__btn[aria-expanded='true'] { color: #fff; }
}

/* Below 860px .nav__links is display:none and the drawer takes
   over, so the sub-items become indented rows under About us
   rather than a second disclosure. A 1.25rem indent and a rule
   down the left side: at 1.45rem display type, indent alone is
   not enough to read as nesting. */
.mobilemenu__sub {
  font-size: 1.05rem;
  padding-left: 1.25rem;
  color: var(--muted);
  border-left: 1px solid var(--line);
}


/* =====================================================================
   v42 — 2026-08-11 — OFFICIAL REGULATOR MARKS, AND A PICTURE FOR CAREERS
   ---------------------------------------------------------------------
   Two client notes.

   1 · "add the logos at the side of the SEC n SEBI n in the hero banner
   also." This supersedes the v-earlier .regmark chips, which were
   typographic on purpose -- the comment on that block said the artwork
   should not go in until its use was cleared. The client has now
   supplied both files and asked for them, so the chips become tiles and
   the .regmark__art hook that block reserved is finally used.

   Both marks are dark ink meant for white paper: the SEC seal is navy
   and gold, SEBI is a blue gradient. Neither survives being dropped on
   the hero photograph, so in the hero each one sits in a white tile.
   In #regulation the ground is already near-white (--warm-50) and the
   SEBI file has had its white knocked out to alpha, so both sit
   directly on the band with no tile at all -- the section spent v27
   removing three card borders and should not get two back.

   2 · "in the Careers section add the image." It was the only section
   in that run without one. The four role boxes moved out of the right
   half and became a divided list under the copy; the photograph takes
   the half they left.
   ===================================================================== */

/* ---- 1 · The hero tiles ------------------------------------------
   .regmark's own rule sets a min-width, letter-spacing and uppercase
   sizing for a two-to-four letter word. An image needs none of it, so
   the modifier unsets the type metrics and keeps only the box. The
   1px white border reads as the tile's own edge on the photograph;
   on paper --line does the same job. */
.regmark--art {
  min-width: 0;
  padding: 0.34rem 0.46rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  letter-spacing: normal;
}
/* The seal is a coin, so its tile is one too: a circle inside a
   rounded square leaves four corners of white doing nothing, and at
   this size that dead margin is most of what you see. */
.regmark--seal { border-radius: 999px; padding: 0.24rem; }
.regmark__art { height: 30px; width: auto; flex: none; display: block; }
/* SEBI is a stacked mark with two lines of small type under the
   logotype, so at a shared 30px it out-measures the seal and its
   caption turns to mush. 25px puts the two on the same optical
   weight and keeps the logotype, not the caption, doing the work. */
.regmark__art--wide { height: 25px; }

/* .hero--stage .regmark inverts the chip to white-on-scrim. A tile
   holding artwork must win that back, and matching specificity later
   in the file is what does it. */
.hero--stage .regmark--art {
  background: #fff;
  border-color: rgba(255, 255, 255, 0.55);
}

/* ---- 2 · The marks in #regulation --------------------------------
   The mark and its code share a baseline row rather than stacking,
   because "SEC" set under the SEC seal is the same word twice. The
   row keeps its height when it is empty, which is what holds the
   third badge's code -- "Scope", which has no regulator -- on the
   same line as the other two across the divided row. */
.regbadge__mark {
  display: flex;
  align-items: center;
  gap: 0.62rem;
  min-height: 2.1rem;
  margin-bottom: 0.15rem;
}
.regbadge__mark img { height: 2.1rem; width: auto; flex: none; display: block; }
.regbadge__img--wide { height: 1.85rem; }
@media (max-width: 560px) {
  .regbadge__mark { min-height: 1.8rem; }
  .regbadge__mark img { height: 1.8rem; }
  .regbadge__img--wide { height: 1.6rem; }
}

/* ---- 3 · The careers list and its photograph ---------------------
   .teamlist is the two-column divided list from careers.html. Inside
   half a .split it only has room for one column, and the measure has
   to come in with it. */
.teamlist--stack { grid-template-columns: minmax(0, 1fr); }
.teamlist--stack .teamrow p { max-width: 44ch; }

/* .split centres its two children, so a 4:3.05 slot beside a column
   carrying a heading, a lead, four rows and a button sits as a short
   band with air above and below it. Squaring the slot matches the
   two heights without cropping the photograph any harder. */
.imgslot--tall { aspect-ratio: 1 / 1.06; }
@media (max-width: 900px) { .imgslot--tall { aspect-ratio: 4 / 3.05; } }


/* ============================================================
   v43 · 2026-08-11 · CAREERS PAGE, SECOND PASS
   ------------------------------------------------------------
   The client sent a full-page comp for careers.html and asked for
   "this design with this content". Four things in that comp are new
   to the site and are built here: a split hero with an arched
   photograph, a bordered figure block beside the opening copy, a
   solid navy line-band in the middle of the page, and a two-part
   closing CTA.

   Two things in the comp were deliberately not built, and the
   markup carries the same note:

   -- The comp's figures read "500+ People" and "25+ Years". Neither
      is a number this firm has published anywhere, and a careers
      page is the last place to estimate one. The .statcard holds
      four counts that can each be checked against another section
      of this site instead.
   -- The comp's testimonials are three named people with headshots.
      The source document has two unattributed sample stories. Real
      names and faces are not something to invent, so #voices keeps
      the two it has and keeps its PLACEHOLDER warning.

   The v41 careers block further up is not removed. Everything it
   set -- .divisions, .steps, .teamlist, .voices -- is still on the
   page; this block adds beside it rather than over it.
   ============================================================ */

/* h2 em has been the accent italic since v14, but the careers h1 is
   the first display-size headline to want the same treatment. */
.pagehero h1 em, .display em { font-style: normal; color: var(--accent); }

/* --- HERO ------------------------------------------------------
   The comp puts a tall arched photograph beside the headline. An
   arch is a semicircle on a rectangle, so the radius has to be half
   the column width and nothing else -- 999px lets the browser work
   that out at any width without a magic number to keep in sync. */
.pagehero--split { padding-bottom: clamp(3.5rem, 6vw, 5.5rem); }
.chero {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.chero__copy { min-width: 0; }
.chero__copy h1 { max-width: 14ch; }
.chero__copy .lead { max-width: 46ch; }
.chero__art {
  position: relative;
  aspect-ratio: 5 / 6;
  border-radius: 999px 999px var(--radius-lg) var(--radius-lg);
  overflow: hidden;
  background: var(--soft);
  box-shadow: var(--shadow-md);
}
.chero__art img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The three chips under the CTAs restate the page's promise in the
   fewest possible words. .pill already exists; it has never carried
   an icon before, so only the svg rule is new. */
.pillrow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 2.1rem;
  padding: 0;
  list-style: none;
}
.pill svg {
  width: 1rem;
  height: 1rem;
  flex: none;
  fill: none;
  stroke: var(--brand);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- FIGURES BESIDE THE OPENING COPY ---------------------------
   Four counts in a 2x2. This is one bordered block divided into
   quadrants rather than four separate cards: four boxes in a row
   was the pattern the homepage spent v27 removing, and the numbers
   read as one set anyway. */
.statcard {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  overflow: hidden;
}
.statcard > div {
  padding: clamp(1.35rem, 2.4vw, 1.9rem);
  border-top: 1px solid var(--line-faint);
  border-left: 1px solid var(--line-faint);
}
.statcard > div:nth-child(-n + 2) { border-top: 0; }
.statcard > div:nth-child(odd) { border-left: 0; }
.statn {
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 3.4vw, 2.9rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--brand);
}
.statl {
  margin-top: 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink);
}
.statd {
  margin-top: 0.5rem;
  font-size: 0.855rem;
  line-height: 1.5;
  color: var(--muted);
}

/* --- THE NAVY LINE-BAND ----------------------------------------
   One sentence on a dark ground, halfway down. It is the only place
   on the page where the reading stops, which is the whole point of
   it -- five values above, four kinds of people below, and a breath
   in between. No photograph: the hero already carries one, and a
   picture here would give the eye somewhere else to go. */
.legacy {
  background: var(--brand-900);
  color: #fff;
  padding-block: clamp(4.2rem, 7.5vw, 6.4rem);
}
.legacy__grid { max-width: 46rem; }
@media (max-width: 760px) { .legacy__q br { display: none; } }
.legacy__q {
  font-family: var(--font-display);
  font-size: clamp(1.85rem, 3.6vw, 2.85rem);
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.022em;
  color: #fff;
  text-wrap: balance;
}
.legacy__q em { font-style: normal; color: var(--accent); }
.legacy__by {
  margin-top: 1.4rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

/* --- LIFE AT WEALTHDOOR ----------------------------------------
   Three columns, not three cards. Scope, Growth and Belonging are
   different facets of one answer, and boxing them makes the reader
   compare them instead of adding them up. A hairline across the top
   of each is enough to say where one ends. */
.lifecols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.6rem, 3.6vw, 3rem);
  margin-top: clamp(2.2rem, 3.6vw, 3rem);
}
.lifecol { padding-top: 1.5rem; border-top: 1px solid var(--warm-line); }
.lifecol h3 {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
  margin-top: 1rem;
}
.lifecol p {
  margin-top: 0.6rem;
  font-size: 0.92rem;
  line-height: 1.62;
  color: var(--muted);
  max-width: 34ch;
}

/* --- CLOSING CTA -----------------------------------------------
   The comp ends on a heading and a bare circular arrow. An arrow
   with no label says nothing to a screen reader and nothing to a
   reader in a hurry either, so the button keeps its words. The
   "no role for me" case is the second column, held apart by a rule
   rather than by a second box. */
.joinband {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.joinband__main .h2 { margin-top: 0.2rem; }
.joinband__lead {
  margin-top: 1.1rem;
  margin-bottom: 1.9rem;
  font-size: 1.02rem;
  line-height: 1.62;
  color: var(--muted);
  max-width: 48ch;
}
.joinband__aside {
  padding-left: clamp(1.4rem, 2.6vw, 2.2rem);
  border-left: 1px solid var(--warm-line);
}
.joinband__aside h3 {
  font-family: var(--font-display);
  font-size: 1.12rem;
  font-weight: 500;
  color: var(--ink);
}
.joinband__aside p {
  margin-top: 0.6rem;
  margin-bottom: 1.1rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--muted);
}

/* --- NARROWER SCREENS ------------------------------------------ */
@media (max-width: 1020px) {
  .lifecols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lifecol:last-child { grid-column: 1 / -1; }
  .lifecol p { max-width: 52ch; }
}
@media (max-width: 900px) {
  .chero { grid-template-columns: minmax(0, 1fr); gap: 2.6rem; }
  /* Stacked, the arch would run to the full width of the page and
     the semicircle would swallow the top third of the photograph.
     Capping it keeps the shape readable as an arch. */
  .chero__art { max-width: 26rem; margin-inline: auto; aspect-ratio: 5 / 5.6; }
  .chero__copy h1, .chero__copy .lead { max-width: none; }
  .joinband { grid-template-columns: minmax(0, 1fr); gap: 2.2rem; }
  .joinband__aside {
    padding-left: 0;
    padding-top: 1.5rem;
    border-left: 0;
    border-top: 1px solid var(--warm-line);
  }
  .joinband__main .h2 br { display: none; }
}
@media (max-width: 620px) {
  .lifecols { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  .lifecol:last-child { grid-column: auto; }
  .statcard > div { padding: 1.15rem 1.1rem; }
  .statd { font-size: 0.82rem; }
  .legacy__grid { max-width: none; }
}


/* ============================================================
   v44 · 2026-08-11 · TWO REGULATORS, TWO PANELS
   ------------------------------------------------------------
   #regulation carried a third panel headed "Scope / Where this
   applies", holding the caveat that Institutional Solutions is not
   a regulated adviser. The client asked for that text off the page.
   The caveat is a disclosure rather than a design element, so it
   moved into the footer's general disclaimer instead of vanishing.

   That leaves two panels in a grid built for three. Left alone the
   row would sit two-thirds full with a column of dead space on the
   right, which reads as something missing rather than something
   removed. --two closes the row up to match what is in it.

   The v27 treatment is untouched: still one top rule and a hairline
   between, still no boxes.
   ============================================================ */
.regbadges--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }


/* ============================================================
   v45 · 2026-08-11 · CAREERS PAGE, BUILT TO THE COMP
   ------------------------------------------------------------
   The client re-sent the careers comp with "exact like this, only
   what is there in the image". So the page is now the comp's seven
   blocks and nothing else: hero, why we're here, values, the legacy
   band, life at Wealthdoor, voices, and the closing CTA. Four
   sections that were on the page from the source PDF -- who we look
   for, the eight teams, the five hiring steps, the disclosures note
   -- came off, because they are not in the comp.

   The v43 block above set .chero, .statcard, .lifecols, .joinband
   and .legacy against the earlier reading of the same comp. Those
   selectors are re-cut here rather than removed, so the diff shows
   what the second pass changed: the arch grew rings and a wash, the
   figures grew icons, the navy band became an image card, and the
   closing CTA became three parts instead of two.

   Two things the comp asks for that the markup handles differently,
   both noted where they occur: the figures 500+/25+ are the
   client's own claim and carry a confirm-before-launch comment, and
   the three named voices are placeholders with monogram avatars
   rather than stock faces attached to invented names.
   ============================================================ */

/* The comp sets every section label in the accent. That is still one
   accent colour, and on a page with no charts and no data it is the
   only thing carrying brand through the scroll. */
.careerspg .seclabel { color: var(--accent); }
.careerspg .seclabel::before { background: var(--accent); }
.careerspg .sechead--centre .seclabel::after { display: none; }

/* The comp emphasises inside headings in the logo blue, not the
   accent -- "real lives", "standards", "purpose, ownership and
   growth". em stays accent for the two display lines. */
.careerspg .hl { color: var(--brand); }

/* Section headings on this page sit a step below the site's default
   .h2. The comp runs six of them down one scroll, and at the homepage
   size every one of them takes an extra line. */
.careerspg .h2 { font-size: clamp(1.8rem, 3.2vw, 2.6rem); line-height: 1.16; }

/* --- HERO ------------------------------------------------------ */
.chero {
  /* v43 made .chero itself the two-column grid. v45 moves the grid on
     to .chero__grid inside the wrap, so the section has to hand back
     the display it was given or the whole hero lands in column one. */
  display: block;
  position: relative;
  overflow: hidden;
  padding: clamp(7.5rem, 11vw, 9.75rem) 0 clamp(3.5rem, 6vw, 5rem);
  border-bottom: 1px solid var(--line-faint);
}
/* The wash behind the arch. It is on the section, not the image, so
   it can run past the arch on both sides the way the comp's does. */
.chero::before {
  content: '';
  position: absolute;
  inset: 0 -10% -20% 42%;
  background:
    radial-gradient(58% 60% at 62% 34%, rgba(0, 19, 160, 0.11), transparent 72%),
    radial-gradient(46% 46% at 84% 74%, rgba(240, 90, 41, 0.07), transparent 74%);
  pointer-events: none;
}
.chero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
/* The site display ramp tops out at 5.4rem, which is a homepage-hero
   size. At that size "Opportunity is at" breaks in two and the comp's
   three-line stack becomes four. This is a page hero, not the front
   door, so it steps down. */
.careerspg .chero__copy h1 { margin-top: 0.9rem; font-size: clamp(2.5rem, 4.4vw, 3.7rem); }
.chero__lead {
  margin-top: 1.3rem;
  max-width: 38ch;
  font-size: 1.03rem;
  line-height: 1.66;
  color: var(--muted);
}

.chero__stage { position: relative; }
.chero__art {
  position: relative;
  z-index: 2;
  aspect-ratio: 1 / 1.02;
  border-radius: 999px 999px var(--radius-lg) var(--radius-lg);
  overflow: hidden;
  background: var(--soft);
  box-shadow: 0 30px 60px -34px rgba(0, 19, 160, 0.4);
}
.chero__art img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Stepped-out copies of the same arch. Percentages, not pixels, so
   the three curves stay concentric as the column resizes. */
.chero__ring {
  position: absolute;
  z-index: 1;
  border: 1px solid;
  border-radius: 999px 999px var(--radius-lg) var(--radius-lg);
  pointer-events: none;
}
.chero__ring--1 { inset: -3.4% -3.4% -1.7%; border-color: rgba(0, 19, 160, 0.3); }
.chero__ring--2 { inset: -7.4% -7.4% -3.6%; border-color: rgba(240, 90, 41, 0.42); }

.herochips {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0;
  margin-top: 2.4rem;
  padding: 0;
  list-style: none;
}
.herochip {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0 clamp(1rem, 2vw, 1.5rem);
  font-size: 0.86rem;
  line-height: 1.35;
  color: var(--muted);
}
.herochip:first-child { padding-left: 0; }
.herochip + .herochip { border-left: 1px solid var(--line); }
.herochip strong { display: block; font-weight: 600; color: var(--ink); }

/* --- FIGURES --------------------------------------------------- */
.split--wide { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); align-items: center; }
.statcard {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.statcell {
  display: flex;
  align-items: center;
  gap: clamp(0.8rem, 1.6vw, 1.15rem);
  padding: clamp(1.4rem, 2.6vw, 2.1rem);
  border-top: 1px solid var(--line-faint);
  border-left: 1px solid var(--line-faint);
}
.statcell:nth-child(-n + 2) { border-top: 0; }
.statcell:nth-child(odd) { border-left: 0; }
.statcell .ibadge { flex: none; }
.statn {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 2.6vw, 2.15rem);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.statl {
  display: block;
  margin-top: 0.15rem;
  font-size: 1rem;
  font-weight: 500;
  /* v43 set this label as an all-caps micro-label. The comp sets it in
     sentence case at reading size, so both of v43's typographic
     switches have to be turned back off by name. */
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
}
.statd { display: block; margin-top: 0.25rem; font-size: 0.82rem; line-height: 1.45; color: var(--faint); }

/* --- VALUES ---------------------------------------------------- */
/* The comp drops the accent rule under each value title and sets the
   title itself in the logo blue. Same five-across grid otherwise. */
.valuegrid--v2 .valuecard h3 { color: var(--brand); min-height: 2.4em; }
.valuegrid--v2 .valuecard p { color: var(--muted); }

/* --- THE LEGACY BAND ------------------------------------------- */
/* Navy on the left, photograph on the right, one card. The image is
   masked into the navy rather than butted against it, which is what
   stops the join reading as two boxes side by side. */
.legacyband {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  align-items: stretch;
  margin-top: clamp(2rem, 3.6vw, 2.8rem);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--brand-900);
  min-height: clamp(9.5rem, 13vw, 11.5rem);
}
.legacyband__body {
  position: relative;
  z-index: 2;
  /* The mark sits directly above the quote, not beside it. Laid out as a
     row it aligned to the top of the panel and left a hole in the corner
     with the quote floating away below it. */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.35rem;
  padding: clamp(1.8rem, 3.4vw, 2.9rem);
}
.legacyband__mark {
  font-family: var(--font-display);
  font-size: 2.6rem;
  line-height: 0.7;
  color: var(--accent);
}
.legacyband__q {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.3vw, 1.85rem);
  font-weight: 400;
  line-height: 1.3;
  color: #fff;
}
.legacyband__media { position: relative; }
/* Taken out of flow on purpose. In an auto-height grid row, height: 100%
   on the image has nothing to resolve against and falls back to auto, so
   the photograph laid itself out at its full 3:2 intrinsic ratio and
   stretched the band to 364px -- half again as tall as the min-height it
   was supposed to sit at. Absolute means the quote decides the height and
   the photograph fills whatever that turns out to be. */
.legacyband__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.legacyband__media::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(90deg, var(--brand-900) 0%, rgba(0, 12, 99, 0.72) 32%, rgba(0, 12, 99, 0.12) 78%, rgba(0, 12, 99, 0.12) 100%);
}

/* --- LIFE AT WEALTHDOOR ---------------------------------------- */
.lifegrid {
  display: grid;
  grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
  gap: clamp(2rem, 4.5vw, 3.6rem);
  align-items: center;
}
.lifecols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  margin-top: 0;
}
.lifecol {
  padding: 0 clamp(1rem, 2vw, 1.6rem);
  border-top: 0;
}
.lifecol:first-child { padding-left: 0; }
.lifecol + .lifecol { border-left: 1px solid var(--line); }
.lifecol h3 {
  margin-top: 1.1rem;
  font-family: var(--font-display);
  font-size: 1.06rem;
  font-weight: 600;
  line-height: 1.28;
  color: var(--ink);
}
.lifecol p { margin-top: 0.65rem; font-size: 0.87rem; line-height: 1.58; color: var(--muted); max-width: none; }

/* --- VOICES ----------------------------------------------------- */
.voiceshead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-bottom: clamp(1.6rem, 2.8vw, 2.2rem);
}
.voiceshead .h2 { margin-top: 0.6rem; }

.rail { display: flex; align-items: center; gap: clamp(0.6rem, 1.4vw, 1rem); }
.rail__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: clamp(0.9rem, 1.8vw, 1.3rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* Vertical breathing room only. The 0.2rem of horizontal padding this
     used to carry became the snap origin, so a track sitting at its start
     reported scrollLeft: 3 and the prev button never disabled. */
  padding: 0.3rem 0;
  margin: -0.3rem 0;
}
.rail__track::-webkit-scrollbar { display: none; }
.rail__track > * { scroll-snap-align: start; }

.railbtn {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), opacity 0.25s var(--ease);
}
.railbtn:hover:not(:disabled) { border-color: var(--brand); color: var(--brand); }
.railbtn:disabled { opacity: 0.35; cursor: default; }

.voicecard {
  display: flex;
  flex-direction: column;
  padding: clamp(1.2rem, 2.2vw, 1.6rem);
  border: 1px solid var(--warm-line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  min-width: 0;
}
.voicecard__mark {
  font-family: var(--font-display);
  font-size: 1.65rem;
  line-height: 0.7;
  color: var(--accent);
}
.voicecard blockquote {
  margin-top: 0.7rem;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--muted);
  flex: 1 1 auto;
}
.voicecard__by { display: flex; align-items: center; gap: 0.7rem; margin-top: 1.3rem; font-size: 0.8rem; color: var(--faint); }
.voicecard__by strong { display: block; font-size: 0.9rem; font-weight: 600; color: var(--ink); }
/* Initials, not a stock face. See the note in careers.html. */
.avatar {
  flex: none;
  width: 2.3rem;
  height: 2.3rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--brand-50);
  border: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--brand);
}

/* --- CLOSING CTA ------------------------------------------------ */
.ctaband {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 0.72fr);
  align-items: center;
  /* The original .ctaband (line 835) was a centred 60ch column for the old
     closing block. This one is a full-width three-part band, so the three
     properties that made it a narrow centred column have to be named and
     turned off -- none of them are set by anything above. */
  max-width: none;
  margin: 0;
  text-align: left;
  gap: clamp(1.6rem, 3.4vw, 3rem);
  padding: clamp(1.9rem, 3.6vw, 3rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(70% 130% at 88% 88%, rgba(0, 19, 160, 0.09), transparent 70%),
    radial-gradient(60% 120% at 6% 6%, rgba(240, 90, 41, 0.07), transparent 68%),
    var(--soft);
}
.ctaband__main .h2 { font-size: clamp(1.7rem, 3vw, 2.35rem); }
.ctaband__main p { margin: 0.9rem 0 0; font-size: 0.93rem; line-height: 1.6; color: var(--muted); max-width: 34ch; }
.ctaband__go {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.gocircle {
  width: 2.9rem;
  height: 2.9rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--brand);
  color: #fff;
  transition: transform 0.25s var(--ease);
}
.ctaband__go:hover .gocircle { transform: translateX(3px); }
.ctaband__aside { padding-left: clamp(1.3rem, 2.4vw, 2rem); border-left: 1px solid var(--line-strong); }
.ctaband__aside h3 { font-size: 0.95rem; font-weight: 600; color: var(--ink); }
.ctaband__aside p { margin: 0.5rem 0 0.9rem; font-size: 0.87rem; line-height: 1.55; color: var(--muted); }

/* --- NARROWER SCREENS ------------------------------------------- */
@media (max-width: 1080px) {
  .ctaband { grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr); }
  .ctaband__go { grid-column: 1; }
  .ctaband__aside { grid-column: 2; grid-row: 1 / span 2; align-self: stretch; }
}
@media (max-width: 900px) {
  .chero { padding-top: clamp(6.5rem, 12vw, 8rem); }
  .chero::before { inset: 34% -20% -20% -20%; }
  .chero__grid { grid-template-columns: minmax(0, 1fr); gap: 2.8rem; }
  .chero__lead { max-width: none; }
  .chero__stage { max-width: 25rem; margin-inline: auto; width: 100%; }
  .chero__art { aspect-ratio: 1 / 1.06; }
  .lifegrid { grid-template-columns: minmax(0, 1fr); gap: 2.4rem; }
  .split--wide { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
  .legacyband { grid-template-columns: minmax(0, 1fr); }
  .legacyband__media { min-height: 9rem; }
  .legacyband__media::before {
    background: linear-gradient(180deg, var(--brand-900) 0%, rgba(0, 12, 99, 0.45) 55%, rgba(0, 12, 99, 0.15) 100%);
  }
  .lifecols { grid-template-columns: minmax(0, 1fr); }
  .lifecol { padding: 0; }
  .lifecol + .lifecol { border-left: 0; border-top: 1px solid var(--line); padding-top: 1.5rem; margin-top: 1.5rem; }
  .ctaband { grid-template-columns: minmax(0, 1fr); gap: 1.6rem; }
  .ctaband__go, .ctaband__aside { grid-column: 1; grid-row: auto; }
  .ctaband__aside { padding-left: 0; padding-top: 1.4rem; border-left: 0; border-top: 1px solid var(--line-strong); }
  /* Below this width the two buttons and the track cannot share a row: the
     buttons eat about 100px, and a card with a 15.5rem floor is then wider
     than the box it scrolls inside, so the last card can never come fully
     into view and "next" never reaches its end state. The track takes the
     full width and the buttons drop underneath it, right-aligned. */
  .rail { display: grid; grid-template-columns: 1fr auto auto; column-gap: 0.6rem; row-gap: 1rem; }
  /* The floor has to stay: with a 0 minimum the three cards simply shrink
     to fit the box, the track stops overflowing, and there is nothing left
     to scroll. */
  .rail__track { grid-row: 1; grid-column: 1 / -1; grid-auto-columns: minmax(15.5rem, 84%); }
  .rail [data-rail='prev'] { grid-row: 2; grid-column: 2; }
  .rail [data-rail='next'] { grid-row: 2; grid-column: 3; }
}
@media (max-width: 620px) {
  .statcard { grid-template-columns: minmax(0, 1fr); }
  .statcell { border-left: 0; border-top: 1px solid var(--line-faint); padding: 1.2rem 1.1rem; }
  .statcell:first-child { border-top: 0; }
  .herochips { gap: 0.9rem 0; }
  .herochip { padding-left: 0; padding-right: 1rem; }
  .herochip + .herochip { border-left: 0; }
  /* The rings are a percentage of the arch, so on a phone they step out
     far enough to sit on the edge of the screen. Pulled in so the gutter
     still reads as a margin. */
  .chero__ring--1 { inset: -2.2% -2.2% -1.1%; }
  .chero__ring--2 { inset: -4.8% -4.8% -2.4%; }
}

/* ============================================================
   v46 · 2026-08-11 · ONE TYPE SCALE ACROSS THE PAGES
   ------------------------------------------------------------
   The client compared the homepage against the careers page and
   asked for the section headlines and the subtext to be the same
   size and the same colour everywhere. Two separate drifts had to
   be closed.

   1. The homepage had two subtext sizes. A section opener wrapped
      in .sechead got 1.35vw; the seven openers that are bare
      siblings (seclabel + h2 + lead, no wrapper) fell through to
      the plain .lead ramp at 1.25vw. Same role, same look now.
      Scoped to .section so the hero's own lead, which is white
      over a photograph and deliberately smaller, is left alone.

   2. The careers page had its own scale and its own emphasis
      colour. v45 stepped .h2 down and set every section label in
      the accent because the design comp did; it also emphasised a
      word of each heading in the logo blue, which is a colour the
      homepage never uses for type. All three go back to the site's
      defaults. The comp's look inside the sections -- the arch,
      the stat card, the legacy band, the story rail -- is
      untouched; this is only the type.

      Emphasis now follows the homepage's own rule rather than the
      comp's: the one centred head on the page keeps a single word
      in the accent, exactly as #what-we-do, #values and #why do,
      and the left-aligned heads carry no colour at all, exactly as
      #brands, #global, #regulation and #contact do.
   ============================================================ */

.section .lead { font-size: clamp(1.06rem, 1.35vw, 1.22rem); }

.careerspg .seclabel { color: var(--faint); }
.careerspg .seclabel::before { background: none; }
.careerspg .sechead--centre .seclabel::after { display: block; }

.careerspg .hl { color: inherit; }
.careerspg .sechead--centre .hl { color: var(--accent); }

.careerspg .h2 { font-size: clamp(2.15rem, 4.1vw, 3.4rem); line-height: 1.08; }
.ctaband__main .h2 { font-size: clamp(2.15rem, 4.1vw, 3.4rem); }

/* The hero lead is the page's subtext too, and it was set from the
   comp at a size that belongs to neither ramp. */
.chero__lead { font-size: clamp(1.06rem, 1.35vw, 1.22rem); max-width: 34ch; }

/* The body copy under the two split headings did the same job as a
   .lead on the homepage and was sitting at the bare paragraph size. */
.careerspg .split--wide p.body,
.careerspg .lifegrid p.body { font-size: clamp(1.06rem, 1.35vw, 1.22rem); line-height: 1.6; }

/* The two split sections were laid out around a heading a step
   smaller than the site's. At the real .h2 size #why-us ran to three
   lines in a 491px column and #life to four in a 474px one, so the
   columns move rather than the type.

   #why-us keeps the comp's copy-beside-figures split, widened.
   #life follows the homepage instead: heading and copy across the
   top, the three columns full width underneath -- which is how
   #brands, #global and #regulation are already built, and the reason
   a 54px heading sits comfortably on those. */
.careerspg .split--wide { grid-template-columns: minmax(0, 1.14fr) minmax(0, 0.86fr); }
.careerspg .lifegrid { grid-template-columns: minmax(0, 1fr); gap: clamp(2.2rem, 3.6vw, 3rem); }
.careerspg .lifecols { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Measured rather than guessed: the widest line of that heading is
   520px, so the copy column only needs an even half and the stat
   card can have the rest. At 0.86fr the four descriptions underneath
   the figures were each breaking across two lines. */
.careerspg .split--wide { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

/* With the card back at half the row, three of the four descriptions
   sit on one line and "Of collective experience" was the only one
   still breaking. A little less padding is enough to even them up. */
.careerspg .statcell { padding: clamp(1.4rem, 2.2vw, 1.75rem); }

/* The five value cards on the homepage set their titles in ink. The
   careers ones were in the logo blue, from the comp. */
.careerspg .valuegrid--v2 .valuecard h3 { color: var(--ink); }

/* Last one-off on the page: the aside heading in the closing band was
   at 0.95rem, a size nothing else on the site uses. Moved on to the
   small-heading size the rest of both pages share. */
.careerspg .ctaband__aside h3 { font-size: 1.06rem; }

/* The about page had the same two drifts, found by measuring it rather
   than assuming the shared stylesheet had covered it.

   Its opening lead sits in .pagehero, not in a .section, so the rule
   above missed it and it was still on the bare .lead ramp. It is the
   page's own subtext and reads as one -- dark type on paper, not the
   homepage's white-over-photograph hero -- so it takes the subtext size
   like every other opener.

   And the label above the closing block was rendering at 16.8px in
   --muted: .joinus p (line 834) sets a size and a colour on every
   paragraph in the block, and the label is a paragraph. It only needs
   the two properties named back. */
.pagehero p.lead { font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
.joinus .seclabel { font-size: 0.78rem; color: var(--faint); }

/* ============================================================
   v47 · 2026-08-11 · ONE FOOTER, AND NO ACCENT IN A HEADLINE
   ------------------------------------------------------------
   Two instructions, one of which is entirely a markup change and
   is recorded here only so the reasoning sits with the rest.

   The footer: about.html and careers.html were carrying a shorter
   version of the homepage's -- no .footer__contact row, a trimmed
   disclaimer, and about.html had its own "About us" column where
   the other two have "Company". All three are now the same block,
   byte for byte, apart from the same-page anchors: the homepage
   links to #standard, the sub-pages to index.html#standard, which
   is the same destination written the only way each page can write
   it. The disclaimer now carries id="disclosures" on every page so
   the "Disclosures" link resolves locally rather than bouncing the
   reader to the homepage.

   The accent in headlines: every <em> in a heading has been painted
   --accent since v14, and the careers page did the same through .hl.
   The client has asked for headlines with no orange in them at all,
   on every page. Rather than unpick nine <em>s across three files --
   which would lose the record of where the emphasis was intended,
   and would drift again the moment a heading is edited -- the colour
   is turned off at the one place it is switched on. The <em>s stay
   in the markup, still font-style: normal, so a heading now reads in
   a single weight of ink.

   Scoped to headings on purpose. The accent is still the site's one
   accent colour and still does its work everywhere else: the rule
   under a centred section label, .crule, .promise__rule, the list
   dots, the buttons, the quote mark on the careers legacy band. The
   two pull quotes (.quoteband__q on the homepage and about) keep
   their orange phrase as well -- those are quotations set large, not
   section headlines, and taking the colour out of a quote leaves it
   with nothing to mark it as one.
   ============================================================ */

h1 em, h2 em, h3 em, h4 em,
.display em, .pagehero h1 em,
.h2 em, .h2 .hl, .h2 .mute,
.ecosec h2 em, .closer__body h2 em, .newsstrip__t h3 em,
.legacy__q em,
.careerspg .sechead--centre .hl,
.sechead--centre .h2 em { color: inherit; }

/* ============================================================
   v48 · 2026-08-11 · NO ACCENT COLOUR IN THREE PLACES
   ------------------------------------------------------------
   The client asked for the orange and the blue to come out of the
   announcement widget at the top of the hero, out of #why, and out
   of .ecosec. Everything named below is a place where one of those
   two colours was doing decorative work.

   Where the colour is removed, the shape stays: a 3px bar is still
   a 3px bar, the 34x2 dash is still a dash. They move on to
   --line-strong, which is the same grey-blue hairline the cards are
   already outlined in, so the detail reads as an edge rather than
   as a mark. The icons go to --ink and the "Learn more" link goes
   with them.

   The alternation in both card rows disappears with this -- #why ran
   blue / orange / blue / orange across four cards and .ecosec ran
   orange / blue / blue across three. There is nothing left to
   alternate once both colours are gone, and four identical bars are
   the honest result rather than an oversight.

   NOT touched, because neither is an accent:
   - the pale card and media tints (--soft, --warm-50). They are the
     band system the whole site is built on, not colour.
   - the .closer band at the foot of #why. That is a photograph under
     a navy wash, the same device as the legacy band on careers, and
     it is a panel rather than a colour applied to something.
   ============================================================ */

/* The dot is a "there is something new here" marker. On the hero it
   sits in white type over a photograph, so it takes the colour of the
   text it belongs to rather than a fixed one, and steps back a little
   so it reads as a marker and not a bullet. */
.announce__dot { background: currentColor; opacity: 0.55; }

#why .ibadge svg:not(.ico),
.ecosec .ibadge svg:not(.ico) { stroke: var(--ink); }

#why .crule,
.ecosec .crule { background: var(--line-strong); }

#why .sechead--centre .seclabel::after,
.ecosec .sechead--centre .seclabel::after { background: var(--line-strong); }

.whycard::before, .whycard--accent::before,
.ecocard::before, .ecocard--accent::before { background: var(--line-strong); }

/* Hover was tinting the card edge brand-200, a pale blue. */
.whycard:hover { border-color: var(--line-strong); }

.ecocard__go { color: var(--ink); }
.ecocard__go:active { background: var(--soft); }

/* ============================================================
   v49 · 2026-08-11 · THREE SECTIONS, ASKED FOR BY THE CLIENT
   ------------------------------------------------------------
   1. #global gets its four-figure strip back inside the panel.
      That is markup only -- .reachpanel__stats and .rstat were
      never removed from this stylesheet when the strip moved to
      about.html, so the component styles itself. What did go
      stale is the prose above .reach--brief (~line 3823), which
      still says "no stats strip, no border above them". It is
      wrong now. Per the convention of this file nothing above is
      edited, so this note supersedes it: the brief panel carries
      two market tiles AND the stats strip, and the strip's own
      border-top is the divider between them.

   2. #values keeps its label, headline and subtext, and sends
      the reader to about.html#our-values for the five values
      themselves. The five cards and the quote band are gone
      from the homepage markup. The .valuegrid and .quoteband
      rules stay in this file because about.html still uses
      them -- do not delete them for being unused here.

      A .sechead is a block of type that normally has something
      under it. On its own it needs the section not to collapse
      around it, and the button under the subtext needs its own
      air rather than the 1.2rem the subtext gets.

   3. #careers: the four roles are now an icon and one line
      each. The row was a stacked h3 + p; it becomes a badge
      beside that pair. Centring the two against the badge keeps
      the pair reading as one item, which is why the h3's own
      bottom margin comes down -- at 0.35rem the optical centre
      sat visibly low. Below 560px the badge is dropped rather
      than shrunk: at that width the row has about 30 characters
      to give, and the text is worth more than the ornament.

   The icons here take --ink, not --brand. The badges in #why
   and .ecosec were turned to ink in v48 at the client's
   request, and these sit on the same page; a blue icon three
   sections below an ink one reads as an oversight rather than
   as a decision.
   ============================================================ */

#values .sechead--centre { padding-block: clamp(0.4rem, 1vw, 1rem); }
#values .reach__cta { margin-top: clamp(1.5rem, 2.4vw, 2rem); }

.teamlist--icons .teamrow {
  display: flex;
  align-items: center;
  gap: clamp(0.85rem, 1.6vw, 1.1rem);
}
.teamlist--icons .teamrow > div { min-width: 0; }
.teamlist--icons .teamrow h3 { margin-bottom: 0.2rem; }
.teamlist--icons .ibadge svg:not(.ico) { stroke: var(--ink); }

@media (max-width: 560px) {
  .teamlist--icons .ibadge { display: none; }
}

/* ============================================================
   v50 · 2026-08-11 · SIX SECTIONS, ONE ROUND OF NOTES
   ------------------------------------------------------------
   Everything below answers a specific instruction. Where a rule
   supersedes an older one it says so; per this file's habit the
   older rule stays where it is.
   ============================================================ */

/* ---- 1 · Photographs answer the cursor -------------------------
   Every photograph on this page sat in a frame that never moved.
   A picture that does nothing under the pointer reads as printed;
   a picture that moves too much reads as an advert. So: a slow
   1.035 push on the image inside its own frame, and a barely
   perceptible warming of the frame edge. The frame never moves --
   the crop does, inside it -- which is why overflow:hidden on the
   container is doing the real work here.

   The transition is on the image, not on a hover selector, so it
   eases back out as well as in. .imgslot is on the two big split
   photographs and the careers portrait; the four __media rules
   cover the ecosystem cards, the brand cards, the insight rail
   and the generic card. .hero__slides is deliberately excluded:
   it is already animating on its own timer, and a hover push on
   a crossfading slideshow fights it. */
.imgslot > img,
.ecocard__media > img,
.brandcard__media > img,
.railcard__media > img,
.card__media > img,
.tabs__media > img {
  transition: transform 0.7s var(--ease), filter 0.7s var(--ease);
}
.imgslot:hover > img,
.ecocard:hover .ecocard__media > img,
.brandcard:hover .brandcard__media > img,
.railcard:hover .railcard__media > img,
.card:hover .card__media > img,
.tabs__media:hover > img {
  transform: scale(1.035);
  filter: saturate(1.04) contrast(1.02);
}
.imgslot { transition: border-color 0.4s var(--ease); }
.imgslot:hover { border-color: var(--line-strong); }
.band--warm .imgslot:hover { border-color: var(--warm-line); }

@media (prefers-reduced-motion: reduce) {
  .imgslot > img, .ecocard__media > img, .brandcard__media > img,
  .railcard__media > img, .card__media > img, .tabs__media > img {
    transition: none;
  }
  .imgslot:hover > img, .ecocard:hover .ecocard__media > img,
  .brandcard:hover .brandcard__media > img,
  .railcard:hover .railcard__media > img,
  .card:hover .card__media > img, .tabs__media:hover > img {
    transform: none;
  }
}

/* ---- 2 · The regulator widgets on the hero ---------------------
   Supersedes .regmark--art in the hero: the mark plus a run of
   text was two loose objects on a photograph. Each regulator now
   has a panel -- glass over the scrim, the mark on its own white
   tile inside it, the short name over the market.

   The white tile is not decoration. Both marks are dark artwork
   with no clear space of their own, and dropping either straight
   onto a photograph is what makes a regulator's mark look like
   it has been pasted on. */
.regwidgets { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: clamp(1.5rem, 2.6vw, 2.1rem); }
.regwidget {
  display: inline-flex; align-items: center; gap: 0.7rem;
  padding: 0.5rem 0.9rem 0.5rem 0.5rem;
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.11);
  border: 1px solid rgba(255, 255, 255, 0.34);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
}
.regwidget__mark {
  flex: none; display: grid; place-items: center;
  background: #fff; border-radius: var(--radius-xs);
  padding: 0.3rem 0.4rem;
}
.regwidget__mark--seal { border-radius: 999px; padding: 0.2rem; }
.regwidget__mark img { height: 28px; width: auto; display: block; }
.regwidget__art--wide { height: 23px !important; }
.regwidget__t { display: flex; flex-direction: column; line-height: 1.25; }
.regwidget__t b {
  font-family: var(--font-sans); font-size: 0.82rem; font-weight: 700;
  letter-spacing: 0.06em; color: #fff;
}
.regwidget__t > span { font-size: 0.78rem; color: rgba(255, 255, 255, 0.82); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .regwidget { background: rgba(17, 21, 25, 0.42); }
}
@media (max-width: 560px) {
  .regwidgets { gap: 0.5rem; }
  .regwidget { padding: 0.42rem 0.7rem 0.42rem 0.42rem; gap: 0.55rem; }
  .regwidget__mark img { height: 23px; }
  .regwidget__art--wide { height: 19px !important; }
  .regwidget__t b { font-size: 0.76rem; }
  .regwidget__t > span { font-size: 0.72rem; }
}

/* ---- 3 · #values, off the centre line --------------------------
   .splithead aligns its two columns on their baselines (align-
   items:end), which is right when the right column is a paragraph
   ending level with the headline. Here it also carries a button,
   so the column is taller and the headline would ride up. Top
   alignment, and the headline gets the padding instead. */
#values .splithead { align-items: start; }
#values .splithead > .reveal:first-child { padding-top: 0.2rem; }
.splithead__cta { margin-top: clamp(1.4rem, 2.2vw, 1.8rem); }

/* ---- 4 · #who-we-are gets a photograph -------------------------
   .split--flip puts the media first on a wide screen and last on
   a narrow one. Reading order on mobile stays headline-then-
   picture, which is the order the copy was written in. */
.split--flip > *:first-child { order: -1; }
@media (max-width: 900px) { .split--flip > *:first-child { order: 1; } }

.imgslot--who { aspect-ratio: 4 / 4.2; }
@media (max-width: 900px) { .imgslot--who { aspect-ratio: 4 / 3.05; } }

/* Two facts, divided, not boxed -- same grouping as the careers
   list two sections down, so the page has one way of showing a
   short labelled pair rather than two. */
.whofacts {
  margin-top: clamp(1.5rem, 2.6vw, 2rem);
  border-top: 1px solid var(--line);
}
.whofacts > div {
  padding-block: clamp(0.95rem, 1.7vw, 1.25rem);
  border-bottom: 1px solid var(--line);
}
.whofacts dt {
  font-family: var(--font-mono);
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 0.4rem;
}
.whofacts dd { margin: 0; color: var(--muted); font-size: 0.98rem; line-height: 1.6; max-width: 46ch; }
.whois__cta { margin-top: clamp(1.5rem, 2.4vw, 1.9rem); }

/* ---- 5 · #regulation, the registrations as the subject ---------
   Supersedes the .regbadges--row treatment on this page: that
   block styled the two entries as a hairline-divided strip under
   a photograph. They are the right-hand half now, inside one
   panel, so the styling that stripped their card returns as a
   panel around the pair. .regbadges rules are left alone because
   about.html still uses them.

   The panel is white on the warm band -- the same figure/ground
   the #global reach panel uses, so the two "here is the evidence"
   blocks on this page look like the same kind of object. */
.regpanel {
  background: var(--n-0);
  border: 1px solid var(--warm-line);
  border-radius: var(--radius-lg);
  padding: clamp(1.4rem, 2.6vw, 2rem);
  box-shadow: var(--shadow-sm);
}
.regreg { display: flex; gap: clamp(0.9rem, 1.8vw, 1.25rem); align-items: flex-start; }
.regreg + .regreg {
  margin-top: clamp(1.3rem, 2.4vw, 1.8rem);
  padding-top: clamp(1.3rem, 2.4vw, 1.8rem);
  border-top: 1px solid var(--line);
}
.regreg__mark {
  flex: none; display: grid; place-items: center;
  width: 3.6rem; height: 3.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  background: var(--n-0);
  padding: 0.35rem;
}
.regreg__mark--seal { border-radius: 999px; padding: 0.2rem; }
.regreg__mark img { max-width: 100%; height: auto; display: block; }
.regreg__mark--seal img { width: 100%; height: auto; }
.regreg__art--wide { width: 100%; }
.regreg__c { min-width: 0; }
.regreg__code {
  font-family: var(--font-mono);
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--faint);
}
.regreg__c h3 {
  font-family: var(--font-sans);
  font-size: 1.06rem; font-weight: 600; color: var(--ink);
  margin: 0.25rem 0 0.4rem;
}
.regreg__c p { color: var(--muted); font-size: 0.95rem; line-height: 1.6; }

/* The registration numbers are the part somebody actually checks,
   so they get the mono face the rest of the site uses for things
   that are looked up rather than read. */
.regreg__ids { display: flex; flex-wrap: wrap; gap: 0.35rem 1.6rem; margin-top: 0.75rem; }
.regreg__ids > div { display: flex; align-items: baseline; gap: 0.45rem; }
.regreg__ids dt { font-size: 0.8rem; color: var(--faint); }
.regreg__ids dd {
  margin: 0; font-family: var(--font-mono);
  font-size: 0.82rem; font-weight: 600; color: var(--ink);
  letter-spacing: 0.02em;
}
.regpanel__note {
  margin-top: clamp(1.2rem, 2.2vw, 1.6rem);
  padding-top: clamp(0.9rem, 1.6vw, 1.2rem);
  border-top: 1px solid var(--line-faint);
  font-size: 0.82rem; line-height: 1.55; color: var(--faint);
}
@media (max-width: 520px) {
  .regreg { gap: 0.85rem; }
  .regreg__mark { width: 3rem; height: 3rem; }
}

/* The wide crop for the photograph now under the copy in #regulation.
   16/7 rather than the standard 4/3.05: at full column width a 4:3
   picture under a heading, a lead and a button makes the column half
   again as tall as the panel beside it, and the section goes lopsided. */
.imgslot--wide { aspect-ratio: 16 / 7; margin-top: clamp(1.8rem, 3vw, 2.4rem); }
@media (max-width: 900px) { .imgslot--wide { aspect-ratio: 16 / 9; } }

/* ============================================================
   v51 · 2026-08-11 · A THREE-PART TOP BAR
   ------------------------------------------------------------
   The client sent jpmorganchase.com's menu as the reference and
   asked for the same three parts. Read left to right it is:

     1. the category list   -- every top-level section of the
                               site, set large, one per row,
                               with the open one marked
     2. the section links   -- what is inside that category
     3. one featured card   -- a picture, a title, a way in

   Why it replaces .navdrop rather than sitting beside it: a
   single 13.5rem card hanging under one word of the bar could
   only ever hold one category. The reference's whole idea is
   that you can see the shape of the site without closing the
   menu and opening another one. That is worth the extra panel.

   The trigger buttons deliberately keep .navdrop__btn as well
   as .megabtn. Everything that class already does -- the type
   matching the links beside it, the caret, and the white-over-
   photograph inversion at 3936 -- is exactly what these need,
   and duplicating it is how the two drift apart.

   .navdrop / .navdrop__panel are now referenced by no page.
   The rules stay per this file's habit; do not build on them.

   BREAKPOINT NOTE. The panel is desktop-only. Below 860px the
   bar's link row is display:none (line 1268-ish), so the
   triggers do not exist and the panel can never be opened --
   the drawer below takes the same five categories and stacks
   them as an accordion instead.
   ============================================================ */

/* ---- The panel ------------------------------------------------
   Absolute inside .nav, which is fixed, so it hangs off the bar
   and scrolls with nothing. max-height + overflow so a long
   category list on a laptop screen scrolls inside the panel
   rather than off the bottom of it. The 74px is the bar height
   set on .nav__inner. */
.mega {
  position: absolute; top: 100%; left: 0; right: 0;
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 30px 60px -34px rgba(17, 21, 25, 0.28);
  max-height: calc(100vh - 74px);
  overflow-y: auto;
  animation: megaIn 0.28s var(--ease) both;
}
.mega[hidden] { display: none; }
@keyframes megaIn { from { opacity: 0; transform: translateY(-0.6rem); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .mega { animation: none; } }

/* The bar is translucent glass by default and over the homepage
   hero it is glass on a photograph. With a solid white panel
   hanging off it, anything showing through reads as a seam. JS
   also adds .scrolled while the panel is open, which brings the
   hairline and the dark logo back; this only has to close the
   last of the transparency. */
.nav.mega-open { background: var(--paper); }

/* Everything under the bar dims. Not for drama -- the panel is
   white on white, and without this its bottom edge is the only
   thing separating the menu from the page behind it. */
.mega__scrim {
  position: fixed; inset: 74px 0 0;
  z-index: calc(var(--z-nav) - 1);
  background: rgba(17, 21, 25, 0.26);
  animation: fadeIn 0.28s var(--ease) both;
}
.mega__scrim[hidden] { display: none; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.mega__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 2fr);
  gap: clamp(2rem, 4vw, 3.8rem);
  padding-block: clamp(1.7rem, 2.8vw, 2.4rem) clamp(2rem, 3.4vw, 2.9rem);
}

/* ---- 1 · The category list ------------------------------------
   Display serif, one per row, hairline between. The reference
   boxes its open row; a box is the one thing this site does not
   draw, so the open row takes the pale tinted ground the panel
   links already use on hover, and the caret appears on it. */
.mega__cats { display: flex; flex-direction: column; border-top: 1px solid var(--line-faint); }
.mega__cat {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; text-align: left;
  padding: clamp(0.62rem, 1.15vw, 0.88rem) 0.7rem;
  border: 0; border-bottom: 1px solid var(--line-faint);
  background: none; cursor: pointer;
  font-family: var(--font-display);
  font-size: clamp(1.18rem, 1.75vw, 1.6rem);
  font-weight: 400; letter-spacing: -0.02em; line-height: 1.16;
  color: var(--faint);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
.mega__cat:hover { color: var(--ink-soft); background: var(--warm-50); }
.mega__cat[aria-selected='true'] { color: var(--ink); background: var(--warm-50); }
.mega__catchev {
  flex: none; width: 0.46rem; height: 0.46rem;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  opacity: 0; transition: opacity 0.2s var(--ease);
}
.mega__cat[aria-selected='true'] .mega__catchev { opacity: 1; }

/* ---- 2 + 3 · The links and the featured card ------------------ */
.mega__pane {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.94fr);
  gap: clamp(1.6rem, 3vw, 3rem);
}
.mega__pane[hidden] { display: none; }

.mega__links { display: flex; flex-direction: column; }
.mega__links a {
  padding: 0.5rem 0;
  font-size: 0.98rem; font-weight: 600; color: var(--ink);
  transition: color 0.18s var(--ease), transform 0.25s var(--ease);
}
.mega__links a:hover { color: var(--brand); transform: translateX(2px); }
/* The first row names the destination the rest are anchors
   inside, so it is separated rather than restyled. */
.mega__links a:first-child { padding-bottom: 0.72rem; margin-bottom: 0.3rem; border-bottom: 1px solid var(--line-faint); }
.mega__links .mega__note {
  margin-top: auto; padding-top: 1.1rem;
  font-size: 0.85rem; line-height: 1.6; color: var(--faint); max-width: 34ch;
}

.mega__feat {
  display: flex; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  overflow: hidden; background: var(--warm-50);
  transition: border-color 0.25s var(--ease);
}
.mega__feat:hover { border-color: var(--line-strong); }
.mega__feat-media { display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--soft); }
.mega__feat-media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.7s var(--ease); }
.mega__feat:hover .mega__feat-media img { transform: scale(1.04); }
.mega__feat-body { padding: clamp(0.9rem, 1.6vw, 1.15rem); }
.mega__feat-kind {
  display: block;
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
}
.mega__feat-title {
  display: block; margin-top: 0.42rem;
  font-family: var(--font-display); font-size: 1.08rem; line-height: 1.3;
  letter-spacing: -0.015em; color: var(--ink);
}
.mega__feat-go {
  display: inline-flex; align-items: center; gap: 0.4rem;
  margin-top: 0.7rem;
  font-size: 0.85rem; font-weight: 600; color: var(--brand);
}
.mega__feat:hover .mega__feat-go .arrow { transform: translateX(3px); }
.mega__feat-go .arrow { transition: transform 0.25s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .mega__feat-media img, .mega__links a { transition: none; }
  .mega__feat:hover .mega__feat-media img { transform: none; }
}

/* Between 860 and 1040 the bar is tight: five triggers, a logo
   and two buttons. The ghost button is already dropped at 1040
   by the rule at ~1262; the triggers close up to match. */
@media (max-width: 1040px) {
  .mega__grid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.85fr); }
  .mega__pane { grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr); }
}
@media (max-width: 860px) {
  .mega, .mega__scrim { display: none !important; }
}

/* ============================================================
   v51b · THE SAME THREE PARTS, STACKED, IN THE DRAWER
   ------------------------------------------------------------
   Below 860px the drawer is the menu. It carries the same five
   categories in the same order, as an accordion: one open at a
   time, so the whole shape of the site is one thumb-reach away
   without a 25-row scroll.

   Only one panel is open at a time on purpose. Five categories
   expanded is 1,200px of list on a 375px screen, which is the
   scroll the accordion exists to avoid.
   ============================================================ */
.mm { display: flex; flex-direction: column; }
.mm__cat {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; text-align: left;
  padding: 0.72rem 0;
  border: 0; border-bottom: 1px solid var(--line);
  background: none; cursor: pointer;
  font-family: var(--font-display); font-size: 1.45rem; font-weight: 400;
  letter-spacing: -0.02em; color: var(--ink);
}
.mm__chev {
  flex: none; width: 0.5rem; height: 0.5rem;
  border-right: 1.6px solid var(--faint); border-bottom: 1.6px solid var(--faint);
  transform: translateY(-0.15em) rotate(45deg);
  transition: transform 0.25s var(--ease);
}
.mm__cat[aria-expanded='true'] .mm__chev { transform: translateY(0.06em) rotate(-135deg); }
.mm__panel { display: flex; flex-direction: column; padding: 0.35rem 0 0.7rem; }
.mm__panel[hidden] { display: none; }
/* .mobilemenu a sets 1.45rem display type on every anchor in the
   drawer. These are the level below that, so all four properties
   are named back rather than left to inherit. */
.mobilemenu .mm__panel a {
  font-family: var(--font-sans); font-size: 1rem; font-weight: 500;
  color: var(--muted);
  padding: 0.52rem 0 0.52rem 1.25rem;
  border-bottom: 0; border-left: 1px solid var(--line);
}
.mobilemenu .mm__panel a:active { color: var(--brand); }
.mm__foot { display: flex; flex-direction: column; gap: 0.7rem; padding-top: 1.3rem; }
.mobilemenu .mm__foot .btn { font-size: 0.95rem; }

/* The bar's own current-page marker, matching the one the links
   already use at 3444. It is a class rather than aria-current
   because these are buttons that open a panel, not links to the
   page -- aria-current on a control that does not navigate is a
   lie to a screen reader. */
.navdrop__btn--current { color: var(--ink); font-weight: 600; }
@supports selector(:has(*)) {
  body:has(.hero--underlap) .nav:not(.scrolled) .navdrop__btn--current { color: #fff; }
}

/* ---------------------------------------------------------------
   v52 · 2026-08-11 · TOP BAR SNAGS
   Found by opening the thing at 375 and looking at it.
   --------------------------------------------------------------- */

/* .mobilemenu a at 515 puts 1.45rem display serif on every anchor in
   the drawer, which caught the two footer buttons and turned them into
   serif headlines wearing a button's clothes. The panel links were
   already pulled back at 5473; these are the other two. */
.mobilemenu .mm__foot .btn {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  padding: 0.85rem 1.2rem;
  border-bottom: 0;
}

/* #regulation lost its photograph, so the left column is now four short
   elements against a two-entry panel roughly twice its height. Top
   alignment was right when both sides were tall; now it leaves the
   heading stranded at the ceiling with a column of nothing under it.
   Centre it. Only this section -- align-items:start at 793 is still
   what every other two-column split wants. */
.regsplit { align-items: center; }
@media (max-width: 900px) { .regsplit { align-items: start; } }

/* ONE page-hero type scale. about.html was on .pagehero at
   clamp(2.3rem, 4.6vw, 3.6rem) and careers on .careerspg at
   clamp(2.5rem, 4.4vw, 3.7rem) -- close enough that nobody would call
   it a bug and far enough apart that the two pages did not line up
   when you flicked between them. This is the one value. It stays a
   step below the 5.4rem .display ramp, which is a front-door size. */
.pagehero h1,
.chero__copy h1,
.careerspg .chero__copy h1 {
  margin-top: 0.9rem;
  font-size: clamp(2.4rem, 4.5vw, 3.6rem);
}

/* about.html's hero is now .chero, and its h1 runs to two lines of six
   and five words. The 14ch cap at 4091 was cut for "Opportunity is at
   our door." and would break this one after "The group". */
.chero__copy h1 { max-width: 20ch; }

/* Three lines out of a 20ch measure, so let the browser even them up
   rather than leaving one word stranded on the last line. */
.chero__copy h1 { text-wrap: balance; }

/* The org bracket at 751 is width:100%, so its two arms drop at the
   left and right EDGES of the block while the two cells they are meant
   to point at sit at the centres of two equal columns -- 25% and 75%.
   The arms missed the logos by about 250px each and the thing read as
   a box rather than a bracket. A bracket half the width, centred,
   lands its arms exactly on 25% and 75%. */
.barch__bracket { width: 50%; }
@media (max-width: 700px) { .barch__bracket { width: 100%; } }


/* ---------------------------------------------------------------
   v53 · 2026-08-11 · WEALTHDOOR PRIVATE (wealthdoor.us)
   The practice site was rebuilt on the supplied content. Everything
   it needed already existed except these six pieces. They are
   written generically -- none of them is name-scoped to that page --
   because each is a gap in the system, not a one-off.
   --------------------------------------------------------------- */

/* A sentence set beside the copy rather than inside it. The brief
   called it a "hero callout"; a boxed callout would be the loudest
   object on the first screen, so it is a hairline aside instead --
   the same 2px rule the section labels use, turned on its side. */
.pullnote {
  margin-top: clamp(2rem, 3.4vw, 2.8rem);
  padding-left: clamp(1rem, 1.6vw, 1.4rem);
  border-left: 2px solid var(--line-strong);
  font-family: var(--font-display);
  font-size: clamp(1.02rem, 1.35vw, 1.16rem);
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: 34ch;
}

/* .whycard is a centred card: badge, title, rule, one line of body.
   Four of the sections here carry three-to-five bullets instead, and
   centred bullets are unreadable -- the markers stop lining up the
   moment a line wraps. Same card, left-aligned, with a real list. */
.whycard--list { align-items: flex-start; text-align: left; }
/* .whycard h3 at 1951 reserves two lines so the rule and the body line
   up across a row of cards; keep that, but start the type at the top of
   the reserved box instead of centring it -- a one-line title floating
   in the middle of a two-line box next to a two-line neighbour reads as
   a mistake once the text is left-aligned. */
.whycard--list h3 { align-items: flex-start; }
/* ...and drop the reservation entirely on a row whose titles are all one
   line, where it buys nothing and leaves a blank line of air between
   every title and its rule. */
.eco__grid .whycard--list h3 { min-height: 0; }
.whycard--list .crule { margin-inline: 0; }
/* display:grid does not remove the marker, and a native disc sitting
   outside the padding box alongside the ::before dot was two bullets
   per line, one of them hanging off the card. */
.whycard__list { margin-top: 0.15rem; display: grid; gap: 0.55rem; width: 100%; list-style: none; }
.whycard__list li {
  position: relative;
  padding-left: 1.05rem;
  font-size: 0.89rem;
  line-height: 1.55;
  color: var(--muted);
}
.whycard__list li::before {
  content: '';
  position: absolute; left: 0; top: 0.62em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--line-strong);
}

/* The client profiles are numbered I-IV in the brief. A roman numeral
   is the badge on those cards, so it takes the badge's slot and the
   .stepr__n treatment rather than becoming a second heading. */
.whycard__n {
  font-family: var(--font-mono);
  font-size: 0.9rem; font-weight: 600; letter-spacing: 0.08em;
  color: var(--faint);
  line-height: 2.9rem;
}

/* A named attributed quotation -- bigger than .promise__quote, which
   is a statement of position, and set on its own with a rule under it.
   Used for the CEO perspective. */
.pquote { max-width: 52rem; margin-inline: auto; text-align: center; }
.pquote__t {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.35rem, 2.5vw, 2rem);
  line-height: 1.34;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: pretty;
}
.pquote__by {
  margin-top: clamp(1.4rem, 2.2vw, 1.9rem);
  display: flex; flex-direction: column; gap: 0.2rem; align-items: center;
}
.pquote__by::before {
  content: ''; width: 34px; height: 2px; border-radius: 2px;
  background: var(--line-strong); margin-bottom: 1rem;
}
.pquote__name { font-size: 0.95rem; font-weight: 600; color: var(--ink); }
.pquote__role {
  font-family: var(--font-mono); font-size: 0.76rem; font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--faint);
}

/* Help text under a field. .formnote is the whole-form footer; this is
   per-field, so it is smaller and sits tight under its input. */
.field__hint { font-size: 0.79rem; line-height: 1.45; color: var(--faint); }

/* Type-to-add tag field. The brief asks for more than one country per
   visitor, so this is a real multi-value control rather than a text box
   people have to comma-separate. The wrapper is styled to look exactly
   like .field input -- same border, radius, padding and focus ring --
   and the real input inside it is stripped bare, so focus lands on the
   box the way it does on every other field. */
.tagfield {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem;
  padding: 0.45rem 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.tagfield:focus-within { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(14, 14, 17, 0.07); }
.tagfield input[type='text'] {
  flex: 1 1 9rem; min-width: 0;
  border: 0; background: none; padding: 0.35rem 0.45rem;
  box-shadow: none;
}
.tagfield input[type='text']:focus { border: 0; box-shadow: none; outline: none; }
.tagfield__list { display: contents; }
.tagfield__tag {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.3rem 0.35rem 0.3rem 0.65rem;
  border-radius: var(--radius-pill);
  background: var(--soft);
  border: 1px solid var(--line);
  font-size: 0.84rem; color: var(--ink);
}
.tagfield__x {
  width: 1.15rem; height: 1.15rem; flex: none;
  display: grid; place-items: center;
  border-radius: 50%; border: 0; background: none; cursor: pointer;
  font-size: 0.95rem; line-height: 1; color: var(--faint);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.tagfield__x:hover { background: var(--line); color: var(--ink); }

/* Orange on the practice site follows the homepage's own settlement:
   the .crule dashes and badge glyphs were pulled to neutrals in #why
   and .ecosec at 4965 and this page is built from the same cards, so
   it gets the same treatment rather than reintroducing the orange
   that was taken out. .accent stays on the buttons and the arrow. */
.privatepg .crule { background: var(--line-strong); }
.privatepg .ibadge svg:not(.ico) { stroke: var(--ink); }
.privatepg .sechead--centre .seclabel::after { background: var(--line-strong); }

/* Required-document lines that are not links yet. .footer__col a is the
   only thing styled in that column, so a bare <span> came out at the
   wrong weight and colour. */
.footer__col span { display: block; color: rgba(255, 255, 255, 0.5); font-size: 0.9rem; padding-block: 0.32rem; }

/* ---------------------------------------------------------------
   v54 · 2026-08-11 · NESTVEST SITES ON THE SHARED CHROME
   nestvest.us and nestvest.in were the last two pages still on the
   old placeholder layout: a live-text "Nestvest." lockup in the nav,
   a grey "Hero image · 4:3" box where the photograph goes, and
   inline background colours instead of the band alternation. They
   now run the same nav, .chero arch and section rhythm as everything
   else. The only thing that needed new CSS is the mark.
   --------------------------------------------------------------- */

/* The real Nestvest mark is a tight-cropped 5131:1000 SVG, where the
   Wealthdoor logo is a PNG carrying its own whitespace — which is why
   .nav .brand__logo sits at 42px (v21). Matching that number here
   would make Nestvest read roughly twice the size of its parent. The
   group site already settled this ratio at 22–24px in the ecosystem
   cards (.mark--nv, .ecocard__logo--nv); the nav gets a shade more
   room than a card does, and no more. */
.nav .brand__logo--nv,
.footer .brand__logo--nv { height: 26px; aspect-ratio: 5131 / 1000; width: auto; }
@media (max-width: 560px) {
  .nav .brand__logo--nv { height: 22px; }
}
/* No filter is applied on the dark footer. The colour mark's blues run
   #1D449E to #68A3F3, and the dark end of that sits almost on top of the
   footer ground (#000c63) — so the footer loads nestvest-logo-white.svg
   instead, a flat white knockout of the same geometry. That mirrors the
   group footer, which swaps to wealthdoor-logo-white.png rather than
   filtering the colour file. */

/* The credential row that replaced the three brand sites' dead .marquee.
   .logogrid brings its own box; this only gives it air between the hero
   and the first section. */
.credrow { padding-block: clamp(1.8rem, 3.4vw, 2.8rem); }

/* ---------------------------------------------------------------
   v55 · 2026-08-11 · MOBILE SWEEP
   Fixes found testing all seven pages at 375x812.
   --------------------------------------------------------------- */

/* .logogrid drops to two columns under 900 (417). Five credentials
   divide evenly across five columns and not at all across two — the
   fifth cell was landing alone in row three, leaving a lit hairline
   stub where its border-right ran into empty space. An odd last child
   takes the whole row instead. :last-child:nth-child(odd) only ever
   matches when the count is odd, so an even row is untouched. */
@media (max-width: 900px) {
  .logogrid > *:last-child:nth-child(odd) { grid-column: 1 / -1; border-right: 0; }
}

/* ---------------------------------------------------------------
   v56 · 2026-08-11 · THE REGULATOR ROW IS NOT A BUTTON ROW
   Client: "in the hero banner sec n sebi it's looking like buttons,
   it shouldn't be like buttons."

   Correct, and it was structural rather than a near miss. The hero's
   secondary CTA is .hero--stage .btn--ghost: translucent white fill,
   1px light border, var(--radius), backdrop blur. .regwidget (5107)
   was translucent white fill, 1px light border, var(--radius),
   backdrop blur. Two rows of the same object, stacked, the lower row
   inert -- so the eye reads four controls and two of them do nothing.

   The capsule goes. What it was actually there for was the artwork:
   both regulator marks are dark, neither carries clear space of its
   own, and dropping either straight onto a photograph is what makes
   a regulator's mark look pasted on. That job belongs to
   .regwidget__mark, the small white tile, which stays. The wrapper
   was only ever holding the tile and the text together.

   The row is a credential line now: a hairline above it, wider gaps
   so the two read as separate credentials rather than a segmented
   control, and the type straight on the scrim -- which is where the
   headline and the lede already sit, at 5.27-7.17:1 (see the file
   header on the hero scrim). Nothing here is clickable, and now
   nothing here looks it.
   --------------------------------------------------------------- */
.regwidgets {
  gap: clamp(1.5rem, 2.8vw, 2.4rem);
  margin-top: clamp(1.9rem, 3.2vw, 2.6rem);
  padding-top: clamp(1.2rem, 2.2vw, 1.6rem);
  border-top: 1px solid rgba(255, 255, 255, 0.2);
  /* The rule is as wide as the credentials, not as wide as the copy
     column -- two marks are ~360px and the column is 736px, so a
     full-bleed rule would run 376px out into bare photograph. It
     falls back to the column width once the pair wraps on a phone. */
  width: fit-content; max-width: 100%;
}
.regwidget {
  padding: 0; gap: 0.62rem;
  background: none; border: 0; border-radius: 0;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
/* The no-backdrop-filter fallback (5131) darkened the capsule so the
   glass still read as a panel. There is no panel to rescue now. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .regwidget { background: none; }
}
@media (max-width: 560px) {
  .regwidgets { gap: 1.1rem 1.4rem; }
  .regwidget { padding: 0; }
}

/* =========================================================================
   v57 -- 2026-08-12 -- photography for wealthdoor.us
   -------------------------------------------------------------------------
   The .us page ran eight sections on two layout families: a grid of
   icon cards and a grid of list cards. Four of those grids in a row is
   the repetition the taste skill bans, and a page about people who have
   built something across two countries had exactly two photographs on
   it.

   Two new families here, both photo-led:

     .pgrid / .pcard -- a 2x2 media grid for "Who we serve". Two columns,
       not four, because a 280px-wide photograph is decoration and a
       600px-wide one is evidence.
     .procsplit      -- a tall image column standing beside the numbered
       process. This is the page's second use of the split family (the
       first is #discipline). It is a deliberate deviation: the sections
       are five apart, the proportions differ (0.78/1.22 against 1/1),
       and the alternative -- a fifth card grid -- is worse.

   The photographs themselves carry a hard constraint from the client:
   no faces anywhere, but the frames must still read as wealth. So the
   whole set is architecture, light and empty rooms. Nobody's face means
   nobody else's story; the client reads their own into the frame.
   ========================================================================= */

.pgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.2rem, 2.2vw, 1.9rem);
  margin-top: clamp(2rem, 3.4vw, 2.8rem);
}

.pcard {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--n-0);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease),
              transform 0.3s var(--ease);
}
/* #who-we-serve is a .band--warm, so the card border wants the warm
   line the rest of that band uses, not the neutral one. */
.band--warm .pcard { border-color: var(--warm-line); }

.pcard__media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 7.6;
  background: var(--soft);
}
.pcard__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transform: scale(1.001);
  transition: transform 0.7s var(--ease);
}
.pcard:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.pcard:hover .pcard__media img { transform: scale(1.045); }

.pcard__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  padding: clamp(1.4rem, 2.1vw, 1.85rem) clamp(1.3rem, 1.9vw, 1.7rem)
           clamp(1.6rem, 2.3vw, 2rem);
}
/* Same mono numeral as .whycard__n, but it sits above the heading here
   instead of in a badge slot, so it loses the 2.9rem badge line-height. */
.pcard__n {
  font-family: var(--font-mono);
  font-size: 0.82rem; font-weight: 600; letter-spacing: 0.12em;
  color: var(--faint);
  line-height: 1;
  margin-bottom: 0.85rem;
}
.pcard__body h3 {
  font-family: var(--font-display);
  font-size: clamp(1.16rem, 1.5vw, 1.32rem);
  font-weight: 500; line-height: 1.25;
  color: var(--ink);
  /* .valuecard h3, .whycard h3 (1951) forces a 2.5em flex box to keep
     four short headings on one baseline. These headings are long and
     already sit under a photograph of fixed height, so they do not
     need it and it would strand a line of air on the two-line ones. */
  min-height: 0;
}

@media (max-width: 860px) {
  .pgrid { grid-template-columns: minmax(0, 1fr); }
  .pcard__media { aspect-ratio: 16 / 8.4; }
}

/* --- the process, with a column of light beside it --------------------- */

.procsplit {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(2rem, 4.4vw, 4rem);
  align-items: start;
  margin-top: clamp(2.8rem, 5vw, 4rem);
}
.procsplit__media {
  position: sticky;
  /* .nav__inner is 74px; this clears it with room to breathe. */
  top: 104px;
  margin: 0;
  overflow: hidden;
  aspect-ratio: 3 / 4.3;
  border-radius: var(--radius-lg);
  border: 1px solid var(--warm-line);
  background: var(--soft);
}
.procsplit__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* .steps caps itself at 60rem for the full-width case. Inside the
   split the column is already narrower than that, so the cap only
   gets in the way at large viewports. */
.procsplit__c .steps { max-width: none; }

@media (max-width: 900px) {
  .procsplit { grid-template-columns: minmax(0, 1fr); gap: clamp(1.6rem, 3vw, 2.2rem); }
  .procsplit__media { position: static; aspect-ratio: 16 / 9; }
}
@media (max-width: 560px) {
  .procsplit__media { aspect-ratio: 4 / 3; }
}

/* =========================================================================
   v58 -- 2026-08-12 -- the second colour stops being blue
   -------------------------------------------------------------------------
   Client, looking at the private-equity reference: "in our website there
   are only 2 colours -- instead of light blue make other one".

   True, and it was a self-inflicted problem. Blue was doing three jobs at
   once: identity (the logo), action (every button and link) and ground
   (every tinted band, every hairline, every quiet surface). Three jobs,
   one hue, so the page read as white-and-blue and nothing else.

   Ground now hands its job back. The tinted band, the quiet surfaces and
   the hairlines move onto a warm stone; blue keeps identity and action
   and gets to mean something again. Warm ground under a cool mark is the
   pairing the reference is built on, and it is what makes a white page
   read as expensive rather than as empty.

   NOT a return to v10. The client rejected that ground with "remove the
   light peach colour in the sections" -- peach is a saturated orange
   tint, and it was pulled straight out of the logo accent. This is a
   near-grey: 4-5 points of chroma, warm enough that it is visibly not
   blue and never enough to read as a colour. Both notes are satisfied.

   Token names are unchanged for the same reason as v16 -- --warm-* and
   .band--warm appear ~40 times across 18 pages. "warm" is now literally
   accurate again.
   ========================================================================= */

:root {
  /* The tinted band and its furniture. */
  --warm-50:   #f7f5f1;   /* the tinted band -- was #f5f8fd */
  --warm-100:  #efeae1;   /* a quiet surface sitting on that band */
  --warm-line: #e7e0d4;   /* hairline that survives on tinted ground */

  /* Quiet surfaces and structure. Image slots, input fills, card
     hairlines -- everything that was carrying a blue cast for no
     reason other than that it was easy. */
  --soft:        #f5f2ed;
  --soft-2:      #ebe6dc;
  --line:        #e6e1d8;
  --line-strong: #d3ccbf;
  --line-faint:  #f1ede6;

  /* The neutral ramp keeps its cool cast for TYPE -- ink on warm ground
     wants to stay slightly cool or the whole page yellows. Only the two
     lightest steps move, because those are used as surfaces. */
  --n-50:  #f8f6f3;
  --n-100: #f1ede6;

  /* --brand-50 stays blue. It is not a ground: it is the tint behind
     brand chips and the active nav state, and those should read as the
     mark. Same for --brand-ring. */
}

/* The neutral scale is also referenced directly in a handful of places
   that pre-date the semantic tokens. Nudged to match rather than
   rewritten, so nothing has to be hunted down. */
:root {
  --n-200: #e5e0d8;
  --n-300: #d3ccc1;
}

/* --faint is the eyebrow, the date, the second line of a headline --
   small text, so it has to clear 4.5:1. It sat at 4.85:1 on white and
   4.46:1 on the new stone ground, which is a fail by a hair. One step
   down the ramp puts it at 4.79 / 5.22:1 and it is not perceptibly
   darker. --n-500 itself is left alone; only the semantic token moves,
   because --n-500 is also a border colour in two places where the extra
   weight would show. */
:root { --faint: #666d78; }

/* =========================================================================
   v59 -- 2026-08-12 -- the homepage, against the Siwa Capital reference
   -------------------------------------------------------------------------
   Client sent the reference boards and named what they wanted taken from
   them: the rounded stage, the glassmorphism figure cards, "numbers on
   it", minimal patterns on the widgets, and the ecosystem cards rebuilt.

   What the reference is actually doing, section by section, is one move
   repeated: a photograph is never just a photograph. It is a rounded
   panel with a frosted card of evidence sitting on it. That is the whole
   trick, and it is why the page reads as a firm with a track record
   rather than as a brochure.

   THE HARD CONSTRAINT ON COPYING IT. The reference's cards say $90M+ AUM
   and $35M/$55M by fund. We are a regulated adviser and we do not have
   those numbers, so every figure in every card below is one already
   stated elsewhere on this page and checkable against it: two markets
   (the two regulator widgets), three businesses (the three ecosystem
   cards), one promise (#standard). The same four figures already run in
   #global. Nothing here was invented, and nothing about performance,
   assets or clients goes in these cards later either.
   ========================================================================= */

/* --- 1 · the hero becomes an inset rounded stage ------------------------
   The reference frames its hero as a panel floating on the page ground
   rather than bleeding to the edges. It works because the ground is warm
   (v58) -- on a white page the same inset just looks like a mistake.

   The nav is fixed and 74px, so the panel starts below it and the hero's
   own 74px top padding allowance comes off. Height is the viewport minus
   the nav minus both margins, so the panel still fills the first screen. */
.hero--stage {
  --stage-gap: clamp(0.5rem, 1vw, 0.9rem);
  margin: calc(74px + var(--stage-gap)) var(--stage-gap) 0;
  /* Was clamp(16px, 1.8vw, 26px). Snapped to the token: a fluid radius
     lands on a different number at every width, so nothing else on the
     page ever matched it. Four radii now, 6 / 10 / 16 / 22, everywhere. */
  border-radius: var(--radius-xl);
  overflow: hidden;
  min-height: calc(100svh - 74px - var(--stage-gap) * 2);
  padding-block: clamp(3rem, 7vw, 5.5rem) clamp(7rem, 11vw, 9rem);
}
@supports not (min-height: 100svh) {
  .hero--stage { min-height: calc(100vh - 74px - var(--stage-gap) * 2); }
}
/* .hero__inner carries 1px side rules that used to run the full height of
   a full-bleed hero. Inside a rounded panel they collide with the corner
   radius, and there is now an actual edge doing that job. */
.hero--stage .hero__inner { border-inline: 0; }

/* --- 2 · the glass figure card -----------------------------------------
   Dark frosted, not light frosted. A light card over a photograph needs
   the photograph to be dark to read, which is not a promise any of the
   three hero slides can keep. Dark-over-anything is the safe direction,
   and it is what the reference uses.

   Every alpha below is measured, not chosen. Each hero photograph was
   composited under an 18px blur at the card's exact box and the worst
   (brightest) pixel taken, against a 4.5:1 floor because the label text
   is small:

     fill 0.52 + blur    white  0.90-white  0.84-white
       hero-office        5.87     5.13       4.71    <- the binding case
       hero-newyork       7.76     6.67       6.07
       hero-mumbai       10.74     9.07       8.14
       exp-goal           4.47     3.97       3.69    <- fails, see --slot

   So the two label greys are 0.90 and 0.84, not the 0.72 an eyebrow
   normally gets, and .gcard--slot carries its own heavier fill. The blur
   is doing most of the work -- it collapses local highlights before the
   fill has to cover them -- so the no-backdrop-filter fallback goes to a
   flat 0.72, measured unblurred (worst 7.04). Re-measure all of this if a
   hero slide is swapped or a card is moved over a different photograph. */
.gcard {
  position: relative;
  overflow: hidden;
  z-index: 3;
  padding: clamp(1.1rem, 1.7vw, 1.45rem) clamp(1.2rem, 1.9vw, 1.6rem);
  border-radius: var(--radius-lg); /* was clamp(14px,1.3vw,18px) -- see .hero--stage */
  background: rgba(18, 20, 26, 0.52);
  border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(18px) saturate(130%);
  -webkit-backdrop-filter: blur(18px) saturate(130%);
  box-shadow: 0 18px 40px -24px rgba(0, 0, 0, 0.55);
  color: #fff;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .gcard { background: rgba(18, 20, 26, 0.72); }
}

/* The minimal pattern the client asked for: a 3px dot grid, masked to a
   corner so it decays instead of tiling out flat. One repeating unit, no
   image, no extra request. */
.gcard__pat {
  position: absolute; inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.5) 0.9px, transparent 0.9px);
  background-size: 14px 14px;
  opacity: 0.28;
  -webkit-mask-image: radial-gradient(120% 120% at 100% 0%, #000 0%, transparent 62%);
          mask-image: radial-gradient(120% 120% at 100% 0%, #000 0%, transparent 62%);
}
.gcard > *:not(.gcard__pat) { position: relative; z-index: 1; }

.gcard__k {
  font-family: var(--font-mono);
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.84);
  margin: 0 0 0.9rem;
}
.gcard__row { display: flex; gap: clamp(1.4rem, 2.4vw, 2.2rem); }
.gcard__fig { display: flex; flex-direction: column; gap: 0.3rem; }
.gcard__n {
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 3.1vw, 2.7rem);
  font-weight: 400; line-height: 0.95;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.gcard__l {
  font-size: 0.78rem; line-height: 1.42;
  color: rgba(255, 255, 255, 0.90);
}

/* Placement: bottom-right of the hero stage, clear of the copy column and
   of .hero__dots. It is decoration below 1100px -- there is no width left
   beside the copy -- so it drops out rather than stacking under the CTAs
   and pushing the fold down. */
.gcard--hero {
  position: absolute;
  right: clamp(1.2rem, 3vw, 3rem);
  bottom: clamp(3.6rem, 6vw, 5rem);
  max-width: 22rem;
}
@media (max-width: 1100px) { .gcard--hero { display: none; } }

/* On an .imgslot the card sits inside the frame, bottom-left, exactly as
   the reference does it. .imgslot is already position:relative.

   Heavier fill than the hero's: exp-goal.jpg is a bright overhead desk
   shot and 0.52 left the 0.90 label at 3.97:1. 0.64 puts it at 5.61. */
.gcard--slot {
  background: rgba(18, 20, 26, 0.64);
  position: absolute;
  left: clamp(0.8rem, 1.6vw, 1.2rem);
  bottom: clamp(0.8rem, 1.6vw, 1.2rem);
  right: auto;
  max-width: min(20rem, calc(100% - 1.6rem));
}
/* The generic fallback above sits before this rule and would lose the
   cascade to it, so the slot restates its own. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .gcard--slot { background: rgba(18, 20, 26, 0.78); }
}
/* On a phone the slot card was covering more than half the photograph,
   with one numeral floating in all that space. It shrinks and the figure
   lies down beside its label instead of above it. */
@media (max-width: 520px) {
  .gcard--slot {
    left: 0.6rem; bottom: 0.6rem; right: auto;
    max-width: calc(100% - 1.2rem);
    padding: 0.8rem 0.95rem;
  }
  .gcard--slot .gcard__k { margin-bottom: 0.6rem; }
  .gcard--slot .gcard__fig { flex-direction: row; align-items: center; gap: 0.7rem; }
  .gcard__n { font-size: 1.85rem; }
  .gcard__l { font-size: 0.74rem; }
}

/* --- 3 · the underlined text link --------------------------------------
   The reference uses "More on Our Approach" with a rule under it instead
   of a third button. Applied to the ecosystem cards, where three ghost
   buttons in a row were three controls competing with the section's one
   real CTA. */
.tlink {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0; border: 0; background: none;
  font-family: var(--font-sans);
  font-size: 0.88rem; font-weight: 600;
  color: var(--ink);
  border-bottom: 1px solid var(--line-strong);
  border-radius: 0;
  padding-bottom: 0.3rem;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.tlink:hover { border-color: var(--ink); }
.tlink:active { background: none; }
.tlink .arrow { transition: transform 0.25s var(--ease); }
.tlink:hover .arrow { transform: translateX(3px); }

/* --- 4 · the ecosystem widgets -----------------------------------------
   The client asked for these specifically. What was wrong with them: a
   3px bar across the top (a leftover from when it carried brand colour,
   long since greyed out and now just a line), a solid white fill, and a
   card that was a stack of four unrelated blocks -- badge, heading, photo,
   link -- with nothing ordering them.

   Now: a numeral orders them, the surface is frosted so the section's
   pattern shows through, and the top bar goes. Three cards, three
   numbers, one column each. */
.ecocard {
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-radius: var(--radius-lg);
}
.ecocard::before { display: none; }
.ecocard:hover { border-color: var(--line-strong); box-shadow: var(--shadow-lg); }

/* The same dot grid as the glass card, in ink instead of white, decaying
   from the top-right corner. It sits under the head so the badge and the
   logo have texture behind them and the body copy does not. */
.ecocard__pat {
  position: absolute; inset: 0 0 auto 0; height: 12rem;
  pointer-events: none; z-index: 0;
  background-image: radial-gradient(rgba(17, 21, 25, 0.5) 0.9px, transparent 0.9px);
  background-size: 15px 15px;
  opacity: 0.09;
  -webkit-mask-image: radial-gradient(110% 110% at 100% 0%, #000 0%, transparent 68%);
          mask-image: radial-gradient(110% 110% at 100% 0%, #000 0%, transparent 68%);
}
.ecocard__head, .ecocard__body, .ecocard__media, .ecocard__go { position: relative; z-index: 1; }

/* Bottom-right, on the footer line, opposite the "Learn more" link --
   NOT top-right, where it landed on the brand lockup. */
.ecocard__ix {
  position: absolute; z-index: 2;
  bottom: 0.42rem;
  right: clamp(1.3rem, 2.2vw, 1.7rem);
  font-family: var(--font-mono);
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.12em;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.ecocard__go { margin-inline: clamp(1.3rem, 2.2vw, 1.7rem); width: fit-content; }

/* A pattern field behind the whole section: two very soft warm blooms,
   the reference's out-of-focus shapes. Pure gradient, no image, and it
   never touches the type -- .ecosec > .wrap is already z-index 1. */
.ecosec::before {
  content: '';
  position: absolute; inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(38rem 26rem at 12% 18%, rgba(140, 125, 104, 0.10), transparent 62%),
    radial-gradient(34rem 24rem at 88% 78%, rgba(0, 19, 160, 0.055), transparent 60%);
}

/* --- 5 · two-tone headlines --------------------------------------------
   The reference sets the second half of every headline in a warm taupe.
   v47 had flattened these to `color: inherit` -- but that rule was there
   to get ORANGE out of headlines, at the client's request, and this is
   not orange: it is a desaturated warm grey off the same stone the bands
   now use. The no-orange rule stands; --accent still appears nowhere in a
   headline.

   #8c7d68 measures 4.00:1 on white and 3.67:1 on the stone band. These
   are headline-sized (>=24px), so the bar is 3:1 and both clear it. Do
   not lighten it toward the reference's lighter tan without re-measuring
   -- one step lighter fails. */
:root { --h-second: #8c7d68; }
h1 .mute, .display .mute,
.h2 .mute, .h2 em, h2 em,
.ecosec h2 em, .sechead--centre .h2 em,
.closer__body h2 em { color: var(--h-second); }
/* Two exceptions, both dark grounds. Taupe is a mid-tone: it works as
   the quieter half of a headline on paper and turns to mud on navy.
   The stage hero keeps the translucent white it was measured at, and the
   .closer band gets a light warm tint of the same family instead. */
.hero--stage h1 .mute { color: rgba(255, 255, 255, 0.66); }
.closer__body h2 em, .closer h2 em { color: #ded2be; }  /* 8.92:1 measured
     over the brightest pixel of the band's photograph under its own
     0.93->0.84 scrim; white on the same worst pixel is 13.32:1. */
/* Quotations are not headlines; v47 deliberately left these alone. */
.legacy__q em, .quoteband__q em { color: inherit; }

/* --- 6 · the figures in #global get the reference's weight -------------
   Same markup, same four numbers. They were set at body scale with the
   label above the figure doing more work than the figure. */
.reachpanel__stats .rstat b {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 3.6vw, 3.1rem);
  font-weight: 400; line-height: 0.95;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* The label was --accent orange. Two reasons it goes: at 12.6px it
   measured 3.28:1 on the panel, under the 4.5:1 floor for small text --
   and under a 50px serif numeral, four orange words read as four
   warnings. Ink label, grey sublabel, which is the reference's order.
   `> span` on purpose: .rstat's <b> has a counter <span> inside it. */
.reachpanel__stats .rstat > span {
  margin-top: 0.55rem;
  color: var(--ink);
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* ============================================================
   v60 · 2026-08-12 — the homepage copy pass
   ------------------------------------------------------------
   The copy rewrite was almost entirely text-for-text, so there
   is very little here. Two blocks changed shape rather than
   wording, and only those two needed CSS.
   ============================================================ */

/* -- 1. The mid-page .closer card lost its <h3> and its <p> ---
   The client asked for the "Your message reaches the right team,
   not a queue" line to go, and for the CTA to read "Talk to an
   adviser" -- which was word-for-word what the <h3> above it
   already said. Rather than print the same four words twice, the
   heading was folded into the link, leaving the card as a badge
   and one action.

   .closer__go at ~1837 carries margin-top: 0.9rem, which exists
   to clear the heading and the paragraph that used to sit above
   it. With nothing above it that margin drops the link below the
   badge it is meant to sit beside, so it is zeroed here and the
   card's own align-items is centred for this variant only. Size
   goes up a step because the link is now the card's only voice. */
.closer__card:has(.closer__go--lg) { align-items: center; }
.closer__go--lg {
  margin-top: 0;
  font-size: 1rem;
}
/* :has() is in every browser this site targets, but if it is not
   supported the rule above is dropped whole and the card falls
   back to align-items: flex-start -- badge and link top-aligned,
   which is still legible, just less balanced. Nothing breaks. */

/* -- 2. #contact lost its three benefit blocks ----------------
   "A personal approach", "Advice you can check" and "A long-term
   partnership" were removed from the markup: by that point in the
   page all three have already been made at length in #believe,
   #why and #regulation. The .contactpoints rules at ~1861 are now
   dead on index.html; they are left in place because the same
   component is still used elsewhere and because the blocks may
   come back.

   What is left in the left column is a label, a headline, a lead
   and one email line, against a form that is several times taller.
   .contactdirect's 1.6rem top margin was measured against the
   bottom edge of a list; hung off a lead it reads as cramped, so
   it gets a rule and a hairline to sit under -- the same hairline
   the list used to provide. */
.getintouch .contactdirect {
  margin-top: clamp(1.8rem, 2.8vw, 2.4rem);
  padding-top: clamp(1.4rem, 2.2vw, 1.8rem);
  border-top: 1px solid var(--line);
}
/* Measured after the removal: the left column is 329px against a
   658px form, so .getintouch's align-items: start left a hole half
   the height of the band under the email line. The copy is centred
   against the form instead -- no filler, just the column hung from
   the middle. Scoped to #contact because the other .getintouch on
   the site (wealthdoor.us #begin) still carries a tall accordion
   and wants its top alignment. */
#contact .getintouch { align-items: center; }
@media (max-width: 860px) { #contact .getintouch { align-items: start; } }

/* =========================================================================
   v61 -- 2026-08-12 -- black headlines, a cooler ground, light glass
   -------------------------------------------------------------------------
   Three notes from the client, against the Siwa Capital reference:

     1. "i dont like the colour of the headlines make it black only where
        wantd to heighlight make it italic form of that which is same
        family one fornt style"
     2. "i dont like the colour on the section at the backgroun instited
        of that use other one"
     3. "on the images glassmorfisumm is dont add the black shade to it
        keep only glassmorfisum lil blue light very light blue"

   Read together they are one instruction, not three: stop using colour to
   do a job that shape, weight or light can do. Emphasis moves from hue to
   posture, ground moves from a tint to a neutral, and the glass stops
   being a black card with blur behind it and becomes actual glass.
   ========================================================================= */

/* -- 1 - Headlines are black. Emphasis is italic. --------------------------
   This supersedes the v59 taupe (--h-second, ~6285) outright. That block
   picked a warm grey off the band colour and measured it carefully; the
   client simply does not want a second colour in a headline, which is
   their call to make and the same call they made about orange in v47.

   The mechanism is now the italic of the SAME family at the SAME weight --
   Newsreader Italic, loaded at the top of this file. One family, one
   style, exactly as asked. It reads as emphasis at every size, it survives
   greyscale printing and a colourblind reader, and it cannot fail a
   contrast check because it is the same ink as the rest of the line.

   Every selector below already carried `font-style: normal` from the
   accent-colour era (~1767, 1824, 1887, 2109, 2187, 4089, 4203). Those
   rules are still in the file and still win by source order over anything
   earlier, so each one is restated here rather than edited in place.
   Specificity is matched, not raised. */
h1 em, h2 em, h3 em, h4 em,
.display em, .pagehero h1 em, .pagehero h1 em, .display em,
.h2 em, h2 em, .h2 .hl, .h2 .mute,
.ecosec h2 em, .closer__body h2 em, .newsstrip__t h3 em,
.sechead--centre .h2 em, .careerspg .sechead--centre .hl,
h1 .mute, h2 .mute, h3 .mute, h4 .mute, .display .mute {
  font-style: italic;
  color: inherit;
}
/* The dark grounds. Both were exceptions under v59 because a mid-tone
   taupe turns to mud on navy; with the colour gone there is nothing left
   to except. They inherit the white of their own headline and the italic
   does the work, so the stage hero drops its 0.66 dim -- a dimmed clause
   was the "headline that fades out" the client objected to back in v47. */
.hero--stage h1 .mute { color: inherit; font-style: italic; }
.closer__body h2 em, .closer h2 em { color: inherit; font-style: italic; }
/* The two pull quotes come along. They are not headlines, which is why
   v47 left them alone, but they use the same <em> to mark a phrase and
   that phrase has had no colour and no italic since v47 -- so it has been
   marked as emphatic in the markup and rendered as nothing at all. */
.quoteband__q em, .legacy__q em { font-style: italic; color: inherit; }

/* -- 2 - The tinted band goes neutral -------------------------------------
   v58 moved ground from a light blue to a warm stone, on the client's
   "instead of light blue make other one". The stone is now the one they
   do not want. Both notes are satisfied by taking the tint out entirely:
   #f4f5f7 is a neutral at 3 points of chroma -- cool enough that it can
   never read as the peach they rejected in v10, colourless enough that it
   can never read as the blue they rejected in v58.

   This is also what the reference actually does. Its warm cream is the
   PAGE FRAME behind the site, not a section ground; inside the frame every
   band is white or a neutral near-grey, and the only colour in a surface
   is the slate on the criteria tiles. Ground is now the quietest thing on
   the page again, which leaves the light blue below free to be the one
   tinted surface -- and therefore to read as deliberate.

   Token names stay --warm-* for the third time, for the reason given in
   v16 and v58: they appear ~40 times across 18 pages. The name is now
   wrong. The alternative is a rename touching every page for no visual
   gain. */
:root {
  --warm-50:   #f4f5f7;   /* the tinted band -- was #f7f5f1 stone */
  --warm-100:  #e9ebef;   /* a quiet surface sitting on that band */
  --warm-line: #e0e3e9;   /* hairline that survives on that ground */

  --soft:        #f4f5f7;
  --soft-2:      #e8eaee;
  --line:        #e5e7ec;
  --line-strong: #ccd0d8;
  --line-faint:  #eff1f4;

  --n-50:  #f7f8f9;
  --n-100: #eef0f3;
}
/* The .ecosec bloom field from v59 was two warm radials mixed to the stone.
   Same shapes, re-mixed: one neutral, one the same faint blue as the glass,
   so the section's soft light and its widgets are lit from one source. */
.ecosec::before {
  background:
    radial-gradient(38rem 26rem at 12% 18%, rgba(120, 132, 155, 0.10), transparent 62%),
    radial-gradient(34rem 24rem at 88% 78%, rgba(70, 110, 190, 0.07), transparent 60%);
}

/* -- 3 - The glass stops being black --------------------------------------
   v59 built .gcard as rgba(18,20,26,0.52) -- a near-black card with a blur
   behind it and white type on top. That is a scrim wearing glass as a
   costume, and the client has named it: no black shade, keep the glass,
   tint it very light blue.

   So it inverts. The fill is a very light blue at 0.66, the type is the
   page's own ink, and the blur does the legibility work instead of the
   darkness. Measured over every pixel of all four photographs a card can
   land on, each downsampled and Gaussian-blurred at r=9 to stand in for
   backdrop-filter:

              worst ink on glass      (AA floor 4.5:1)
     hero-office     7.28
     hero-newyork    8.19
     hero-mumbai     7.54
     exp-goal        7.28
     .closer band    7.50   (light glass over the navy scrim, right half)

   That is the WORST pixel in each frame, not the average, so there is real
   headroom -- v59's black card ran at 4.71 in the same test. Note the
   floor is 4.5 and not 3.0 even for the big numerals, because the label
   under each one is small text and shares the surface.

   One colour for all type on the card. --ink-soft was tried for the labels
   and measures 4.41 on two of the four frames, which fails; the labels are
   separated by size and weight instead. Do not reintroduce a second grey
   here without re-running the measurement above. */
.gcard {
  background: rgba(232, 240, 251, 0.66);
  border: 1px solid rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(20px) saturate(125%);
  -webkit-backdrop-filter: blur(20px) saturate(125%);
  box-shadow: 0 20px 44px -28px rgba(22, 34, 62, 0.42);
  color: var(--ink);
}
/* v59's slot card carried its own darker fill because exp-goal.jpg is the
   brightest photograph on the site and a dark card lost contrast on it. A
   LIGHT card gains contrast on a bright frame, so the exception is now
   pointless -- flattened back to the shared fill. */
.gcard--slot { background: rgba(232, 240, 251, 0.66); }
.gcard__k { color: var(--ink); }
.gcard__n { color: var(--ink); }
.gcard__l { color: var(--ink); opacity: 0.82; }  /* The label is quieter
     than its numeral by opacity, not by a second colour, so it cannot
     drift off the ink. 0.82 measures 5.38-5.89:1 across the five frames
     above. It was set at 0.72 first and that fails -- 4.35:1 on
     hero-office and exp-goal -- so this number is a floor, not a taste
     decision. Anything below 0.78 fails AA on the small label. */
/* White dots disappear on a light card. Same grid, inked instead. */
.gcard__pat {
  background-image: radial-gradient(rgba(38, 62, 110, 0.30) 0.9px, transparent 0.9px);
  opacity: 0.22;
}
/* Both @supports fallbacks from v59 inverted too: with no blur available
   the fill has to carry the contrast alone, so it goes nearly opaque. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .gcard, .gcard--slot { background: rgba(238, 244, 252, 0.94); }
}

/* The mid-page .closer card is the same component in a different place --
   glass on a photograph, just one with a navy wash over it. It was
   translucent white with white type, which is the same trick as the black
   card and just as hard to read. Now it matches the .gcard family: light
   glass, ink type. On navy this reads as a lit pane rather than a hole. */
.closer__card {
  background: rgba(232, 240, 251, 0.66);
  border: 1px solid rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(20px) saturate(125%);
  -webkit-backdrop-filter: blur(20px) saturate(125%);
  color: var(--ink);
}
.closer__card h3 { color: var(--ink); }
.closer__card p { color: var(--ink); opacity: 0.82; }  /* same floor as
     .gcard__l -- measured 5.50:1 over the navy band. */
.closer__go--lg, .closer__card .closer__go {
  color: var(--ink);
  border-bottom-color: rgba(17, 21, 25, 0.32);
}
.closer__card .closer__go:hover { border-bottom-color: var(--ink); }
/* The badge inside it was a translucent white disc, invisible on a light
   pane. It takes the blue the glass is tinted with, at full strength. */
.closer__card .ibadge {
  background: rgba(255, 255, 255, 0.86);
  border-color: rgba(38, 62, 110, 0.16);
  color: var(--ink);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .closer__card { background: rgba(238, 244, 252, 0.94); }
}

/* =======================================================================
   v62 · 2026-08-12 — the ecosystem widgets, the brand lockup, and the
   glass loses its tint

   Four client notes, all from the same reference set (Siwa Capital):

     1. "redesign the widgets in this section Our ecosystem modern style
        like i have attached. add the pattern to the widget, in the widget
        only. remove the small line in it."
     2. "remove the small line everywhere in the homepage, it's there below
        the Our ecosystem, remove that."
     3. "in our brands section keep the wealthdoor logo on top. at the
        wealthdoor logo place make one Wealthdoor Private ... Private below
        the Wealthdoor in blue ... instead of orange in the logo make it
        gold. Nestvest is same on the right side."
     4. "on top of the images there is a glassmorphism, is right. remove
        the colour in it, keep only glassmorphism."

   Note 1's second clause is the interesting one. The pattern was in two
   places: a dot grid inside each card AND a pair of soft blooms painted
   across the whole section behind them (.ecosec::before, added v59,
   re-mixed v61). "in the widget only" settles that — the field behind the
   section goes, and the pattern lives inside the card where the reference
   puts it.
   ------------------------------------------------------------------- */

/* --- 1 · every small rule on the page comes out ------------------------
   Two elements, same 34x2px dash, same job: .crule inside a card and
   .seclabel::after under a centred section label. They are decorative,
   they are already aria-hidden in the markup, and hiding them here rather
   than deleting eleven spans across three pages keeps one rule to reverse
   if the client wants them back.

   The .careerspg line has to be restated. v46 turned that dash back on at
   (0,2,1) after v33 had switched it off, so a bare selector here would
   lose the cascade on careers.html and leave one page with a dash. */
.crule,
.sechead--centre .seclabel::after,
.careerspg .sechead--centre .seclabel::after { display: none; }
/* The label was a flex column whose only reason for a gap was the dash
   sitting under it. With the dash gone the gap is padding on nothing. */
.sechead--centre .seclabel { gap: 0; }

/* --- 2 · the Wealthdoor Private lockup ---------------------------------
   A brand-extension lockup, built the way these normally are: the parent
   mark, then the descriptor under the wordmark, letterspaced out to the
   wordmark's own width so the two read as one object.

   Two decisions worth recording.

   The gold. assets/img/wealthdoor-private-logo.png is the group mark with
   every orange pixel swapped for #a8842c and the alpha channel left
   untouched -- the file is straight-alpha two-colour art, so a nearest-
   colour swap is exact and the anti-aliased edges come through clean.
   #a8842c measures 3.50:1 on white against the orange it replaces at
   3.39:1, so the mark is no less legible than it is today. The obvious
   golds are all worse: #c9a227 is 2.42:1, #bf9b30 2.64:1, #b8933a 2.89:1.
   Do not lighten it toward those without accepting that trade.

   The descriptor is real text, not part of the PNG, so it stays crisp at
   any density and can be restyled without re-cutting the asset. It is
   aria-hidden and the mark's alt carries "Wealthdoor Private", so a
   screen reader hears the brand once, not twice. */
.wdlock { display: inline-flex; flex-direction: column; align-items: stretch; gap: 0.34rem; }
.wdlock__mark { display: block; width: auto; height: 24px; aspect-ratio: 878 / 290; }
.wdlock__desc {
  display: block; text-align: center;
  font-family: var(--font-sans); font-weight: 600;
  font-size: 0.58rem; line-height: 1;
  letter-spacing: 0.42em;
  text-indent: 0.42em;          /* cancels the trailing letter-space so the
                                   word optically centres on the wordmark */
  text-transform: uppercase;
  color: var(--brand);          /* "Private below the Wealthdoor in blue" */
  white-space: nowrap;
}
.wdlock--sm .wdlock__mark { height: 20px; }
.wdlock--sm .wdlock__desc { font-size: 0.5rem; letter-spacing: 0.4em; text-indent: 0.4em; }

/* --- 3 · the brand architecture widget ---------------------------------
   The parent slot was the words "Wealthdoor Group" in a pill; the client
   asked for the logo on top. .barch__parent still carries its own type
   rules from line 746 -- they now style nothing, but line-height has to
   go to 0 or the pill keeps a text line's worth of height around a 22px
   image. */
.barch__parent { line-height: 0; padding: 0.55rem 1.15rem; }
.barch__parent img { display: block; height: 22px; width: auto; aspect-ratio: 878 / 290; }
/* .barch__cell img is (0,1,1) and would win over .wdlock__mark's (0,1,0),
   which is how the lockup lost its 24px in the first draft. */
.barch__cell .wdlock__mark { height: 24px; }
.barch__cell .wdlock { align-self: center; }

/* On the brand card the lockup replaces a bare <img class="brandcard__mark">
   and inherits that class, so it keeps the 1.2rem gap under it -- but
   flex-start has to be restated, because .wdlock sets align-items for its
   own children and the card's flex context sets it for the lockup. */
.brandcard__mark.wdlock { align-self: flex-start; }
.brandcard__mark .wdlock__mark { height: 26px; }
.brandcard__mark .wdlock__desc { font-size: 0.62rem; }

/* --- 4 · the ecosystem widgets ----------------------------------------
   The reference builds every tile the same way: mark at the top, image
   inset inside the card rather than bleeding to its edge, title and copy
   under it, and a ring pattern decaying out of one corner. That is the
   whole redesign -- the card was already the right components in the
   wrong order, with a photograph welded to the bottom edge.

   Order in the markup is now head / media / body / link. Before, .media
   carried margin-top:auto to pin itself to the floor of the card; that
   job moves to .body, so cards with two lines of copy and cards with
   three still land their links on the same line. */
.ecocard {
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.74);
}
.ecocard__head { padding: clamp(1.25rem, 2vw, 1.55rem) clamp(1.25rem, 2vw, 1.55rem) 0; }
.ecocard__media {
  margin: clamp(1.1rem, 1.8vw, 1.35rem) clamp(1.25rem, 2vw, 1.55rem) 0;
  aspect-ratio: 16 / 10;
  border: 1px solid var(--line-faint);
  border-top: 1px solid var(--line-faint);   /* the old rule set only the top */
  border-radius: 13px;
}
.ecocard__body {
  flex: 1;
  padding: clamp(1.1rem, 1.8vw, 1.35rem) clamp(1.25rem, 2vw, 1.55rem) 0;
}
.ecocard__body h3 { font-size: clamp(1.2rem, 1.6vw, 1.46rem); letter-spacing: -0.01em; }
.ecocard__body p { margin-top: 0.6rem; }
.ecocard__go {
  position: relative;
  margin: clamp(1.1rem, 1.8vw, 1.35rem) clamp(1.25rem, 2vw, 1.55rem) clamp(1.3rem, 2.1vw, 1.6rem);
}
/* The numeral moves out of the bottom-right corner and into the masthead
   opposite the mark. It was absolutely positioned; it is a flex child of
   .ecocard__head now, so every one of those offsets has to be unwound. */
.ecocard__ix {
  position: static; inset: auto;
  flex: none;
  font-size: 0.8rem; letter-spacing: 0.14em;
  color: var(--line-strong);
}

/* The pattern. Concentric rings out of the top-right corner, which is the
   reference's device, drawn as a repeating-radial-gradient so it is one
   declaration and no image request. It replaces the v59 dot grid.

   The mask is doing the real work: without it the rings run the full
   height of the card and the body copy sits on a striped ground. Masked
   to the top-right quadrant they read as texture behind the mark and
   fade out before they reach the photograph. */
.ecocard__pat {
  position: absolute; inset: 0; height: auto;
  background-image: repeating-radial-gradient(circle at 100% 0,
      rgba(17, 21, 25, 0.9) 0 1.2px, transparent 1.2px 26px);
  background-size: auto;
  opacity: 0.11;
  -webkit-mask-image: radial-gradient(74% 56% at 100% 0, #000 0%, rgba(0, 0, 0, 0.5) 46%, transparent 76%);
          mask-image: radial-gradient(74% 56% at 100% 0, #000 0%, rgba(0, 0, 0, 0.5) 46%, transparent 76%);
}

/* "in the widget only". The section-wide bloom field goes; the pattern is
   now something the cards carry, not something painted behind them. */
.ecosec::before { display: none; }

/* --- 5 · the glass stops being blue -----------------------------------
   v61 tinted these a very light blue at the client's request; the note
   now is "remove the colour in it, keep only glassmorphism". So the fill
   is plain white and, because white carries further than the tint did,
   it can be thinner: 0.62 instead of 0.66. That is the point of the note
   -- less paint, more photograph, the blur still doing the legibility
   work.

   Measured over every pixel of each photograph a glass card can land on,
   downsampled and Gaussian-blurred to emulate backdrop-filter, worst
   pixel not average:

     frame                     ink      label (0.82)
     hero-office               7.35     5.42
     hero-newyork              8.38     6.00
     hero-mumbai               7.65     5.59
     exp-goal                  7.36     5.42
     .closer band (scrimmed)   7.49     5.50

   Every one of those beats the blue fill it replaces at a higher alpha,
   and the v59 black card scored 4.71. The 0.82 label opacity is unchanged
   and is still a floor, not a preference -- 0.72 measured 4.35:1 and
   failed AA. */
.gcard, .gcard--slot { background: rgba(255, 255, 255, 0.62); }
.closer__card { background: rgba(255, 255, 255, 0.62); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .gcard, .gcard--slot, .closer__card { background: rgba(255, 255, 255, 0.93); }
}
/* The dot grid on the glass and the badge outline were both mixed with
   blue to sit with the tint. With the tint gone they are neutral ink. */
.gcard__pat { background-image: radial-gradient(rgba(17, 21, 25, 0.32) 0.9px, transparent 0.9px); }
.closer__card .ibadge { border-color: rgba(17, 21, 25, 0.14); }

/* --- 6 · alignment, after looking at it --------------------------------
   Both lockups are taller than the marks they sit beside -- 33px against
   20px in the ecosystem head, 38px against 22px in the brand tree -- so
   putting one in a row of three (or two) pushed everything under it down
   and left the cards out of register with each other. Measured: the
   ecosystem heads came out 58.2px / 45.3px / 45.3px and the three
   photographs started 13px apart.

   Fixed by reserving the lockup's height in every cell, not by shrinking
   the lockup. */

/* The tree cell becomes a two-row grid instead of a flex column: row one
   is a fixed slot the mark centres in whatever its height, row two is the
   role. Both cells get identical tracks, so the two lines of role copy
   start on the same line. */
.barch__cell {
  display: grid;
  grid-template-rows: 2.6rem auto;
  align-items: center; justify-items: center;
}

/* The ecosystem head aligns on the TOP of the wordmark, not on the centre
   of the box. Centring would drop the lone marks 7px below the lockup's
   wordmark, which is the one line the eye actually tracks across three
   cards. The numeral gets a nudge to sit on that same line. */
.ecocard__head {
  align-items: flex-start;
  min-height: calc(clamp(1.25rem, 2vw, 1.55rem) + 2.25rem);
}
.ecocard__ix { align-self: flex-start; margin-top: 0.28rem; color: var(--faint); }

/* The descriptor is small and sits close under the wordmark, so the space
   below the whole lockup has to be a shade larger than it was under a
   bare mark or the h3 crowds it. */
.brandcard__mark.wdlock { margin-bottom: 1.4rem; }

/* --- 7 · the space the rule was holding open --------------------------
   Hiding .crule took its margins with it and left every heading sitting
   directly on its paragraph -- measured 0.0px between the h3's box and
   the p's on .whycard. The dash was carrying 0.8rem above and 0.85rem
   below; the replacement is deliberately tighter than that, because a
   divider's worth of air with no divider in it reads as a mistake.

   .trio__item has to be named. v21 set `.trio__item .crule + p` to
   margin-top:0 at (0,2,1), which outranks a bare `.crule + p`. */
.crule + p, .crule + ul,
.trio__item .crule + p { margin-top: 0.75rem; }

/* ======================================================================
   v51 · 2026-08-12 · hero motion, the Private descriptor, and a
   photographed contact band
   ====================================================================== */

/* --- 1 · the hero drift ------------------------------------------------
   The slides already scaled 1.055 -> 1 over 9s, but the dwell is 5s, so
   every slide was cut off two-fifths of the way through its own move and
   the next one restarted from the top. The result was motion you could
   measure and not see.

   It is a keyframe now, running the length of the dwell plus the fade, so
   each photograph completes a move instead of being interrupted mid-way.
   Toggling .is-on restarts the animation, which is exactly the retrigger
   we want and is why this is an animation rather than a transition.

   The move is a scale AND a small translate: a pure zoom reads as a lens
   pushing in, a zoom with drift reads as a camera. Direction alternates by
   slide so three in a row do not all pan the same way. 1.5% of the frame
   is the whole budget -- at 6% you notice the picture moving, which is the
   failure mode for a photograph sitting behind a headline. */
@keyframes heroDriftA {
  from { transform: scale(1.075) translate3d(1.1%, 0.7%, 0); }
  to   { transform: scale(1.005) translate3d(-0.4%, -0.3%, 0); }
}
@keyframes heroDriftB {
  from { transform: scale(1.005) translate3d(-0.9%, -0.5%, 0); }
  to   { transform: scale(1.075) translate3d(0.5%, 0.4%, 0); }
}
.hero__slide { transition: opacity 1.4s var(--ease); transform: scale(1.02); }
.hero__slide.is-on { animation: heroDriftA 11s var(--ease) forwards; }
.hero__slide:nth-child(even).is-on { animation-name: heroDriftB; }

/* --- 2 · the Private descriptor ---------------------------------------
   0.42em tracked the word out to the wordmark's exact width, which is the
   textbook way to set a brand-extension descriptor and, at this size, the
   client reads as gappy rather than as considered. Pulled back to 0.24em:
   still unmistakably a letterspaced descriptor, no longer a row of loose
   letters. It now sits narrower than the mark and centres under it, which
   the existing text-align/text-indent pair already handles -- the indent
   just has to follow the tracking or the word centres a half-space off. */
.wdlock__desc { letter-spacing: 0.24em; text-indent: 0.24em; }
.wdlock--sm .wdlock__desc { letter-spacing: 0.23em; text-indent: 0.23em; }

/* --- 3 · the photographed contact band --------------------------------
   Full-bleed photograph, scrim, content on top -- the composition from the
   client's reference.

   One departure from that reference, deliberately. Its floating panel is
   dark glass with white type. Ours holds a form with four inputs and a
   select, and a form is the one place on a page where legibility beats
   composition: .formcard and .newsstrip are already light frosted panels
   with backdrop-filter, and light glass over a photograph is both closer
   to how the rest of this site handles inputs and much easier to fill in.
   So the panel stays light and only the copy beside it goes white -- the
   same treatment the hero already uses for type over a photograph.

   The scrim is two passes for the same reason the hero's is: a horizontal
   wash that darkens the copy side and buys the white type its contrast,
   then a flat pass so the light glass panel has something to sit against
   and does not float on a bright window. */
.moment--shot { position: relative; isolation: isolate; overflow: hidden; }
.moment--shot > .wrap { position: relative; z-index: 2; }
.moment__bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 46%;
}
/* First pass at these values buried the photograph -- the band read as a flat
   navy gradient with no handshake in it, which defeats the point of putting a
   photograph there at all. Retuned by eye against the render: the wash still
   peaks at 0.80 behind the headline, where white type has to hold up, but it
   falls away much faster and bottoms out at 0.16 instead of 0.34, so the right
   two-thirds of the frame is the picture rather than the scrim. The vertical
   pass is now nearly clear through the middle and only weights the top and
   bottom edges, which is what keeps the band from meeting the sections above
   and below on a hard seam. */
.moment__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(100deg, rgba(0, 12, 99, 0.80) 0%, rgba(0, 12, 99, 0.62) 30%, rgba(0, 12, 99, 0.24) 58%, rgba(0, 12, 99, 0.16) 100%),
    linear-gradient(180deg, rgba(6, 9, 26, 0.26) 0%, rgba(6, 9, 26, 0.04) 42%, rgba(6, 9, 26, 0.34) 100%);
}

/* The copy column, now over a photograph. */
.getintouch--glass .seclabel { color: rgba(255, 255, 255, 0.72); }
.getintouch--glass .h2 { color: var(--n-0); }
.getintouch--glass .h2 .mute { color: rgba(255, 255, 255, 0.62); }
.getintouch--glass .lead { color: rgba(255, 255, 255, 0.86); }
.getintouch--glass .contactdirect { color: rgba(255, 255, 255, 0.78); }
.getintouch--glass .contactdirect a { color: var(--n-0); text-decoration: underline; text-underline-offset: 0.22em; text-decoration-thickness: 1px; }

/* Both panels are already frosted; over a photograph they need a shade
   more opacity to stay readable, and a lighter border, because --line on
   a dark photograph is a dark line on a light panel edge. */
.moment--shot .formcard,
.moment--shot .newsstrip {
  background: rgba(255, 255, 255, 0.86);
  border-color: rgba(255, 255, 255, 0.55);
  box-shadow: 0 30px 70px -34px rgba(4, 8, 32, 0.75);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .moment--shot .formcard,
  .moment--shot .newsstrip { background: var(--paper); }
}

/* The band lost .band--warm, so it also lost the warm hairline that
   .divide-top was drawing. On a photograph the divider should read as the
   edge of the picture, not as a rule sitting on it. */
.moment--shot.divide-top { border-top-color: transparent; }

@media (prefers-reduced-motion: reduce) {
  .hero__slide,
  .hero__slide.is-on { animation: none; transform: none; transition: opacity 0.01ms; }
}

/* ======================================================================
   v52 · 2026-08-12 · real glass on the contact band
   ====================================================================== */

/* --- 1 · less blue over the picture ---
   v51 backed the wash off once already; the client wants it down again.
   The peak drops 0.80 -> 0.72 and, more to the point, the tail drops
   0.16 -> 0.08, so the right-hand half of the frame is very nearly the
   photograph on its own. The vertical pass is now almost clear through
   the middle -- 0.02 -- and only weights the top and bottom edges, where
   its job is to stop the band butting into the sections either side on a
   hard line rather than to darken anything.

   Reducing it that far did cost legibility, and the fix is the third layer
   rather than putting the wash back. The copy runs to about 46% of the
   frame, and the strip from 30-45% of the photograph is the bright one --
   sunlight through the window behind the handshake. Measured against the
   actual pixels under each text box, the lead bottomed out at 4.23:1 and
   the direct-email line at 4.31:1, both under the 4.5 floor for type that
   size. So there is now a soft pool anchored off the left edge that adds
   about 0.19 of navy exactly where the type sits and is gone by 68% of the
   width. That buys the contrast back without darkening the half of the
   picture the client was objecting to: at 70% across it contributes 0.035,
   which is nothing. Re-measured after: lead 4.89, email line 5.12, label
   4.97, headline 4.45. */
.moment__scrim {
  background:
    radial-gradient(115% 105% at 4% 52%, rgba(0, 12, 99, 0.26) 0%, rgba(0, 12, 99, 0.16) 38%, rgba(0, 12, 99, 0.04) 56%, rgba(0, 12, 99, 0) 68%),
    linear-gradient(100deg, rgba(0, 12, 99, 0.72) 0%, rgba(0, 12, 99, 0.58) 32%, rgba(0, 12, 99, 0.20) 60%, rgba(0, 12, 99, 0.08) 100%),
    linear-gradient(180deg, rgba(6, 9, 26, 0.22) 0%, rgba(6, 9, 26, 0.02) 44%, rgba(6, 9, 26, 0.28) 100%);
}

/* The copy was semi-transparent white against a wash that is no longer
   doing as much work, so the alphas come up too -- free contrast that
   costs the picture nothing, unlike more blue. The headline's italic half
   goes 0.62 -> 0.70, which is what puts it over the 3:1 large-text floor
   at 3.07 rather than under it. */
.getintouch--glass .seclabel { color: rgba(255, 255, 255, 0.84); }
.getintouch--glass .h2 .mute { color: rgba(255, 255, 255, 0.70); }
.getintouch--glass .lead { color: rgba(255, 255, 255, 0.90); }
.getintouch--glass .contactdirect { color: rgba(255, 255, 255, 0.90); }

/* --- 2 · the panels are glass now, not white cards ---
   At 0.86 white these were opaque. The blur was doing nothing you could
   see, because nothing was getting through to be blurred -- which is the
   usual way "glassmorphism" ends up as a white card with a blur property
   on it. Two changes make it real:

   - the fill comes down to where the photograph reads through it (0.55 on
     the form, 0.5 on the strip, which is lighter because it sits over the
     darker bottom of the frame);
   - the blur goes up to 30px. That matters more than the opacity. A weak
     blur over a busy photograph shows recognisable shapes behind the type
     and reads as dirt; a wide one turns the same backdrop into soft colour
     fields, so the picture is present as light and hue rather than as
     detail, and the type stays on an even ground.

   The two edge treatments are what actually sell it as a pane of glass:
   a light border, and an inset highlight along the top edge standing in
   for the light catching a real bevel. The drop shadow lifts it off the
   photograph so it reads as floating rather than as a hole cut in it. */
.moment--shot .formcard,
.moment--shot .newsstrip {
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.5);
  backdrop-filter: blur(30px) saturate(165%);
  -webkit-backdrop-filter: blur(30px) saturate(165%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.62),
    0 34px 80px -36px rgba(3, 7, 30, 0.72);
}
.moment--shot .newsstrip { background: rgba(255, 255, 255, 0.5); }

/* The one thing a lighter panel costs is the smallest type on it. --faint
   on 0.55 white over this photograph computes to about 3.2:1, which was
   already marginal at 0.86 and is not acceptable now. The note and the
   strip's supporting line move up to --muted; nothing else on these panels
   was close enough to the floor to need it. */
.moment--shot .formnote { color: var(--muted); }

/* Reduce Transparency, and browsers without backdrop-filter, get a solid
   panel -- a 0.55 fill with no blur behind it is unreadable, not merely
   less pretty. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .moment--shot .formcard,
  .moment--shot .newsstrip { background: var(--paper); border-color: var(--line); }
}

/* ======================================================================
   v53 · 2026-08-12 · the ecosystem band, full width, copy on the picture
   ====================================================================== */

/* The band is a direct child of .ecosec rather than of .wrap, which is the
   whole trick: .section only sets padding-block, so anything outside .wrap
   is already the width of the viewport. No negative margins, no 100vw, so
   nothing to go wrong when a scrollbar appears.

   z-index 1 puts it level with .ecosec > .wrap, above the section's bloom
   field, which is drawn on .ecosec::before. */
.ecobleed {
  position: relative; z-index: 1;
  margin-top: clamp(2.4rem, 4.4vw, 3.6rem);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
}

.ecopanel {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: flex-end;
  min-height: clamp(25rem, 33vw, 33rem);
}

/* The photograph is an element rather than a background-image so it can
   carry real alt text and its own width/height, and so it can be lazy. */
.ecopanel__bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.75s var(--ease);
}
/* Each photograph is landscape and each panel is roughly square, so all
   three lose a third of their width to the crop. These pick which third:
   the clipboard and the laptop in 01, the jar and the hand above it in 02,
   the corner of the building in 03. */
.ecopanel:nth-child(1) .ecopanel__bg { object-position: center 46%; }
.ecopanel:nth-child(2) .ecopanel__bg { object-position: 68% 58%; }
/* The glass-facade photograph is landscape and the panel is nearly square, so
   `cover` throws away almost half the width. Centred, the window landed on open
   sky and the panel read as a pale gradient with nothing in it -- and the top
   edge dissolved into the white section above. Pulled left to 18% so the crop
   holds the building's corner and the reflected cladding, which is the part of
   the frame that actually says "institution". Vertically the image is scaled to
   exactly the panel height, so the y term does nothing here. */
.ecopanel:nth-child(3) .ecopanel__bg { object-position: 18% center; }

/* Bottom-weighted, and deliberately weak at the top. The point of the
   redesign is that the picture is visible, so the scrim only has to be
   opaque where the words actually are -- the top 30% of each panel is
   barely touched, the bottom is nearly solid. The second layer is a flat
   wash carrying enough navy to tie three quite different photographs
   (warm wood, warm skin, cold blue glass) into one band. */
/* Mood only. This layer used to carry the legibility as well, with the ramp
   expressed in percentages of the panel -- which works at exactly one panel
   height and nowhere else. Stacked at 375px the panels get shorter while the
   copy gets taller, so the same 66% stop that sat below the heading on desktop
   landed above it on a phone. Measured over the actual photographs, the three
   headings came out at 3.64:1, 2.42:1 and 4.49:1 against white -- the middle
   one not far off invisible over the shirt in that frame.
   Legibility is now anchored to the copy instead (see .ecopanel__body::before),
   and all this does is settle the picture. */
.ecopanel__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 8, 34, 0.16) 0%, rgba(4, 8, 34, 0.06) 42%, rgba(4, 8, 34, 0.22) 100%);
  transition: opacity 0.4s var(--ease);
}

/* The only separation between panels. A gutter or a radius here would put
   the cards back; a hairline reads as a join in one surface. */
.ecopanel + .ecopanel::before {
  content: ''; position: absolute; z-index: 3;
  left: 0; top: 0; bottom: 0; width: 1px;
  background: rgba(255, 255, 255, 0.22);
}

/* width: 100% because the panel is a flex row and the body would otherwise
   shrink to its longest line. That was invisible while the wash lived on the
   panel; now that the wash is a child of the body it showed up immediately as
   a hard vertical edge partway across each photograph. It also widens the
   stretched link to the full panel, which is what a panel-sized target should
   have been all along. Line length is still held by max-width on the copy. */
.ecopanel__body {
  position: relative; z-index: 2; width: 100%;
  padding: clamp(1.6rem, 2.6vw, 2.4rem);
  color: var(--n-0);
}
/* The wash that makes the copy readable, sized to the copy rather than to the
   panel. It starts 5.5rem above the first line and is already at 0.58 by the
   time any text begins, so the worst pixel a headline can land on is a blown
   white highlight -- which still clears 5:1. Because the box grows with the
   text, a panel that wraps to four lines on a phone gets four lines of cover
   instead of the three the desktop percentages happened to give it.
   z-index: -1 keeps it behind the type: .ecopanel__body already establishes a
   stacking context at z-index 2, so a negative child paints under the copy but
   still over the photograph and the scrim outside it. */
.ecopanel__body::before {
  content: ''; position: absolute; z-index: -1; pointer-events: none;
  inset: -5.5rem 0 0 0;
  background: linear-gradient(180deg, rgba(0, 12, 99, 0) 0, rgba(0, 12, 99, 0.58) 5.5rem, rgba(0, 12, 99, 0.92) 100%);
}
.ecopanel__ix {
  display: block;
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  /* 0.72 measured at 4.13:1 on panel 02 -- under the 4.5 small-text floor.
     It is aria-hidden and decorative, but it is still ink on a page, and the
     fix costs nothing. */
  letter-spacing: 0.16em; color: rgba(255, 255, 255, 0.86);
  margin-bottom: clamp(0.9rem, 1.6vw, 1.2rem);
}
/* Each business signs itself with its own mark, in the white variant --
   all three exist, so none of them needs a plate to sit on.

   The first pass sized each logo by eye, which staggered the three
   headings: a 1.5rem mark and a 1.15rem mark push the copy under them to
   different heights, and across a row of panels that misalignment is the
   first thing you see. The box is one fixed height for all three now, and
   object-fit: contain sits each mark inside it at its own aspect ratio.
   Optical size is tuned with padding, which shrinks the content box while
   leaving the box itself alone -- so the marks look right relative to each
   other and the headings still start on the same line.

   Panel 01 carries the full Private lockup rather than the bare mark. The
   first pass used the mark alone, and panels 01 and 03 then showed what is
   very nearly the same wordmark side by side -- the only difference being
   the gold in the "oo", which is not a difference a reader is going to
   register across a gap of 460px. The descriptor is the thing that says
   these are two different businesses, so it has to be there.

   That makes 01's brand taller than the other two, hence the slot: a fixed
   box with its contents sitting on the bottom edge, so a two-line lockup
   and a one-line mark still put the heading beneath them on the same
   line. */
.ecopanel__brand {
  display: flex; align-items: flex-end; min-height: 2.5rem;
  margin-bottom: clamp(0.85rem, 1.5vw, 1.1rem);
}
.ecopanel__logo {
  display: block; width: auto; height: 1.6rem;
  object-fit: contain; object-position: left bottom;
}
.ecopanel__logo--nv { padding-block: 0.24rem; }
/* The lockup's descriptor is --brand blue, which is invisible on a dark
   photograph. Only the colour changes; the tracking that pins it to the
   wordmark's width is set in v51 and stays. */
.wdlock--inv .wdlock__desc { color: rgba(255, 255, 255, 0.82); }

.ecopanel__body h3 {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.28rem, 1.75vw, 1.6rem); line-height: 1.2;
  color: var(--n-0);
}
/* min-height reserves three lines whatever the copy actually runs to.
   The panels are bottom-aligned, so without it a two-line paragraph lifts
   its heading a line higher than its neighbours' -- and three headings at
   three different heights across one strip is the first thing the eye
   catches. Trimming the copy to match would fix it at exactly one window
   width and break again at the next, because the columns are fluid. */
.ecopanel__body p {
  margin-top: 0.6rem;
  font-size: 0.95rem; line-height: 1.6;
  color: rgba(255, 255, 255, 0.88);
  max-width: 32ch; min-height: 4.8em;
}

.ecopanel__go {
  display: inline-flex; align-items: center; gap: 0.45rem;
  margin-top: clamp(1rem, 1.8vw, 1.35rem);
  font-size: 0.92rem; font-weight: 600; color: var(--n-0);
  text-decoration: underline; text-underline-offset: 0.3em;
  text-decoration-thickness: 1px; text-decoration-color: rgba(255, 255, 255, 0.45);
  transition: text-decoration-color 0.25s var(--ease);
}
/* Stretched so the whole panel is the hit area, which is what a reader
   expects of a picture this size. It sits above the scrim and below
   nothing, so it does not cover any other link -- there is only one per
   panel. */
.ecopanel__go::after { content: ''; position: absolute; inset: 0; z-index: 4; }
.ecopanel__go .arrow { transition: transform 0.25s var(--ease); }

.ecopanel:hover .ecopanel__bg { transform: scale(1.05); }
.ecopanel:hover .ecopanel__scrim { opacity: 0.9; }
.ecopanel:hover .ecopanel__go { text-decoration-color: var(--n-0); }
.ecopanel:hover .ecopanel__go .arrow { transform: translateX(3px); }
.ecopanel__go:focus-visible { outline: 2px solid var(--n-0); outline-offset: 3px; }

/* Three columns stop working before the usual breakpoint, because these
   panels are as tall as they are and the copy has to fit across a third
   of the screen. Below 1000px they stack into three full-width bands --
   which is the same idea, just one at a time, and the hairline turns
   horizontal to match. */
@media (max-width: 1000px) {
  .ecobleed { grid-template-columns: minmax(0, 1fr); }
  .ecopanel { min-height: clamp(19rem, 54vw, 25rem); }
  .ecopanel + .ecopanel::before { left: 0; right: 0; top: 0; bottom: auto; width: auto; height: 1px; }
  .ecopanel__body p { max-width: 46ch; min-height: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .ecopanel__bg, .ecopanel:hover .ecopanel__bg { transition: none; transform: none; }
}

/* ======================================================================
   v54 · 2026-08-12 · one design system for the homepage
   ----------------------------------------------------------------------
   The client's note, in order: filled icons instead of outlines; a
   picture in "Our values"; "Why Wealthdoor" rebuilt from the section
   down, not just the cards; glass and pattern on the ecosystem panels;
   and blue as the CTA colour everywhere.

   The through-line is materials. Before this pass the homepage had one
   surface -- a white or pale-grey card with a hairline -- repeated in
   every section, and the only thing distinguishing one section from the
   next was the words in it. It now has four, used deliberately:

     paper      white or --brand-50, hairline, drawn pattern
     brand      --brand-700 to --brand-900, white type, ring pattern
     photo      an image under a scrim
     glass      backdrop-filter, a 1px inner border and an inset
                highlight, only ever over a photograph

   Glass is the one that gets abused, so it has a rule here: it only goes
   on top of a photograph. Frosted glass over a flat colour is just a
   lighter flat colour with a performance cost.
   ====================================================================== */

/* ---- 1 · The icon system --------------------------------------------
   Every icon on this site was a 1.6px outline at 24px. At the sizes we
   actually use them -- 1.3rem inside a 40px chip -- an outline that thin
   is four grey hairs; it disappears against a tinted chip and it fights
   the type, which is 400-600 weight and much darker. Filled shapes hold
   their silhouette at any size and read as one object rather than as a
   drawing of one.

   The new icons are two-tone: a solid body at full opacity and a
   secondary mass at 0.3, both painted from currentColor. One colour
   token per icon, so a badge on paper and the same badge on navy are the
   same file with a different `color`.

   This is scoped to svg.ico rather than applied to .ibadge svg, because
   about.html, careers.html and the four brand sites still carry the
   outline set. Converting those is a separate job on separate pages;
   until then both live side by side without either one breaking. */
.ico { fill: currentColor; stroke: none; }
/* stroke-width is inherited through the SVG cascade from the old rule,
   and a filled path with a stroke on it grows by half a pixel on every
   edge -- enough to close the counters in the smaller marks. */
.ibadge .ico, .fcontact .ico, .formnote .ico { stroke: none; stroke-width: 0; }

/* .ibadge set its colour with `stroke`, which a filled icon ignores.
   Colour moves to the chip and the icon inherits it, so one declaration
   now drives both the outline set (via currentColor on stroke) and the
   filled set (via fill). */
.ibadge { color: var(--brand); }
.ibadge .ico { width: 1.35rem; height: 1.35rem; }
.ibadge--sm .ico { width: 1.15rem; height: 1.15rem; }

/* The chip for a dark surface. This is the liquid-glass recipe and it is
   the only one used on this page: a blur, a 1px inner border to give the
   pane an edge, and a top inset highlight so light appears to catch it.
   Without all three it is a grey box. */
.ibadge--glass {
  color: #fff;
  background: rgba(255, 255, 255, 0.13);
  border: 1px solid rgba(255, 255, 255, 0.24);
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ibadge--glass { background: rgba(255, 255, 255, 0.2); }
}
/* On the brand band there is no photograph to blur, so the same chip
   drops the filter and states its fill outright. */
.ibadge--onbrand {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: rgba(255, 255, 255, 0.14);
}

/* The footer icons were --accent orange (v?, line 2302), which has been
   against a standing instruction for several rounds. They are on navy,
   so they take the light end of the blue ramp rather than --brand, which
   would be invisible there. */
.fcontact svg { stroke: var(--brand-200); color: var(--brand-200); }
.formnote .ico { color: currentColor; }

/* ---- 2 · CTAs, blue-led ---------------------------------------------
   .btn--primary was already brand blue. The gap was tier two: a grey
   fill with a grey hairline, which reads as "disabled" sitting next to a
   saturated blue primary, and puts a neutral in the middle of a section
   that is otherwise entirely blue and paper. It becomes the palest step
   of the same ramp -- still clearly secondary, but the same family.

   The hero and the sticky nav override .btn--ghost for their own
   backgrounds (see .hero--stage and the .hero--underlap block); both
   sit later in the cascade than this and are unaffected. */
.btn--ghost {
  background: var(--brand-50); color: var(--brand-900); border-color: var(--brand-100);
}
.btn--ghost:hover {
  background: var(--brand-100); border-color: var(--brand-200);
}

/* White on brand: the inverse primary, for the two places a CTA sits on
   a navy field. */
.btn--onbrand {
  background: #fff; color: var(--brand-900); border-color: #fff;
  box-shadow: 0 1px 2px rgba(0, 8, 50, 0.3), inset 0 -1px 0 rgba(0, 12, 99, 0.06);
}
.btn--onbrand:hover { background: var(--brand-50); border-color: var(--brand-50); }
.btn--onbrand:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* ---- 3 · #values gets its picture -----------------------------------
   The client asked for an image here. The section is four lines of type
   and a button; beside a photograph it becomes a proper spread, and the
   photograph stops the page running three flat text sections in a row.

   The picture is architecture rather than people. "Our values" has no
   literal subject, and every attempt at one -- a handshake, a family on
   a lawn -- is a stock cliche that says less than the words next to it.
   An atrium says light, order and restraint, which is what the copy is
   actually claiming. */
.valsplit {
  display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.82fr);
  gap: clamp(1.8rem, 4.6vw, 4.2rem); align-items: center;
}
.valsplit__cta { margin-top: clamp(1.5rem, 2.4vw, 2rem); }

.valshot {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 5;
  box-shadow: var(--shadow-lg);
}
.valshot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Two jobs in one layer: a hairline grid drawn over the picture, which
   ties it to the pattern tiles in the section below, and the bottom ramp
   that the caption sits on. The grid is masked to the top two-thirds so
   it never crosses the caption -- a pattern behind text is noise. */
.valshot__pat {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.14) 1px, transparent 1px),
    linear-gradient(180deg, rgba(0, 12, 99, 0) 42%, rgba(0, 12, 99, 0.58) 100%);
  background-size: 46px 46px, 46px 46px, 100% 100%;
}

/* A glass caption, over a photograph, with all three ingredients. The
   ramp above already carries it to 0.58 navy at the bottom edge, so the
   pane's own 0.4 composites to roughly 0.75 -- white type on that clears
   the small-text floor with room to spare, and the picture is still
   legible through it, which is the point of using glass at all. */
.glasschip {
  position: absolute; z-index: 2;
  left: clamp(0.75rem, 1.4vw, 1.1rem); right: clamp(0.75rem, 1.4vw, 1.1rem);
  bottom: clamp(0.75rem, 1.4vw, 1.1rem);
  padding: clamp(0.85rem, 1.5vw, 1.1rem);
  border-radius: var(--radius);
  background: rgba(0, 12, 99, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 8px 24px rgba(0, 8, 50, 0.22);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glasschip { background: rgba(0, 12, 99, 0.72); }
}
.glasschip__k {
  display: block;
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.15em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.88);
}
.glasschip__v {
  display: block; margin-top: 0.4rem;
  font-size: 0.88rem; line-height: 1.5; color: rgba(255, 255, 255, 0.94);
}

@media (max-width: 900px) {
  .valsplit { grid-template-columns: 1fr; gap: 2rem; }
  .valshot { aspect-ratio: 16 / 10; }
}

/* ---- 4 · #why, rebuilt ----------------------------------------------
   What was here: a centred headline over four identical grey cards,
   each with an outlined icon, a centred rule and a centred paragraph.

   Three problems. Four equal boxes assert that the four points are
   interchangeable, and they are not -- the fiduciary duty is the claim
   and the other three are how it is kept. Centred type in a narrow
   column is the slowest thing on a page to read, because the eye has to
   find a new left edge on every line. And the card itself -- pale fill,
   hairline, 3px bar -- was the same object used in five other sections.

   Now: the section opens on the page's left margin like every other
   section, and the four points are a bento. Nothing is centred, no two
   tiles are the same width, and each tile is a different material. The
   fiduciary tile is brand blue and the widest; the photograph runs full
   height down the right; the two supporting points are small paper
   tiles. The hierarchy is in the geometry, so the copy does not have to
   announce it. */
#why .splithead { align-items: start; }
#why .splithead__aside { padding-bottom: 0; }

.whybento {
  margin-top: clamp(2.4rem, 4.2vw, 3.4rem);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(0.8rem, 1.3vw, 1.15rem);
}
/* Explicit columns only. Rows are left to auto-placement: tile 3 claims
   both rows of the right-hand block, and tiles 2 and 4 are pushed to row
   two because their columns are already taken in row one. Writing the
   rows out as well would mean two sources of truth for the same fact. */
.whytile:nth-child(1) { grid-column: 1 / 8; }
.whytile:nth-child(2) { grid-column: 1 / 5; }
.whytile:nth-child(3) { grid-column: 8 / 13; grid-row: 1 / 3; }
.whytile:nth-child(4) { grid-column: 5 / 8; }

.whytile {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-lg);
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.whytile__in {
  position: relative; z-index: 1;
  padding: clamp(1.4rem, 2.2vw, 2rem);
  display: flex; flex-direction: column; height: 100%;
}
.whytile h3 {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.12rem, 1.5vw, 1.4rem); line-height: 1.22;
  margin-top: clamp(1.5rem, 2.6vw, 2.4rem);
}
.whytile p {
  margin-top: 0.6rem;
  font-size: 0.94rem; line-height: 1.62;
  max-width: 40ch;
}

/* The pattern layer. Always a pseudo-free child span so it can be
   masked independently of the tile's own background, and always
   pointer-events: none. */
.whytile__pat {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
}
/* Concentric rings, struck from a point outside the tile so only the
   arcs cross it -- the reference's motif, drawn rather than imported.
   The mask fades them out towards the copy so they never sit behind a
   line of text. */
.whytile__pat--rings {
  background-image: repeating-radial-gradient(circle at 84% -8%, rgba(255, 255, 255, 0.1) 0 1px, transparent 1px 30px);
  -webkit-mask-image: linear-gradient(200deg, #000 0%, rgba(0, 0, 0, 0.15) 62%, transparent 88%);
  mask-image: linear-gradient(200deg, #000 0%, rgba(0, 0, 0, 0.15) 62%, transparent 88%);
}
.whytile__pat--grid {
  background-image:
    linear-gradient(rgba(0, 19, 160, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 19, 160, 0.07) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: linear-gradient(215deg, #000 0%, transparent 72%);
  mask-image: linear-gradient(215deg, #000 0%, transparent 72%);
}
.whytile__pat--hatch {
  background-image: repeating-linear-gradient(135deg, rgba(0, 19, 160, 0.075) 0 1px, transparent 1px 10px);
  -webkit-mask-image: linear-gradient(215deg, #000 0%, transparent 68%);
  mask-image: linear-gradient(215deg, #000 0%, transparent 68%);
}

/* Material one: brand. */
.whytile--lead {
  background: linear-gradient(152deg, var(--brand-700) 0%, var(--brand-900) 100%);
  color: #fff;
}
.whytile--lead h3 { color: #fff; font-size: clamp(1.35rem, 2vw, 1.85rem); }
.whytile--lead p { color: rgba(255, 255, 255, 0.86); font-size: 1rem; max-width: 44ch; }

/* Material two: tinted paper with a drawn pattern. The hairline is the
   pale blue step rather than --line, so the tile belongs to the same
   family as the brand one instead of reading as leftover chrome. */
.whytile--pat {
  background: var(--brand-50);
  border: 1px solid var(--brand-100);
}
.whytile--pat h3 { color: var(--ink); }
.whytile--pat p { color: var(--muted); }

/* Material three: a photograph. The client asked for an image in one of
   the cards; this is the one, because "one adviser who knows you" is the
   only one of the four claims with a person in it. Full height of the
   block so the row has an anchor on the right. */
.whytile--shot { min-height: clamp(22rem, 34vw, 30rem); display: flex; align-items: flex-end; }
.whytile__bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: 58% center;
  transition: transform 0.7s var(--ease);
}
.whytile__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(2, 8, 40, 0.1) 0%, rgba(2, 8, 40, 0.32) 100%);
}
/* The glass panel. Sized to its copy and pinned to the bottom of the
   tile, so a wrap to an extra line grows the pane rather than pushing
   text off the treated area -- the mistake the ecosystem panels made in
   the previous round, where the cover was a percentage of the panel and
   the copy was not.

   0.5 navy over an already-darkened photograph lands near 0.66
   composited, which measures above 4.5:1 for the body copy against the
   brightest pixel the crop contains. */
.whytile__glass {
  position: relative; z-index: 2; margin: clamp(0.7rem, 1.2vw, 1rem);
  padding: clamp(1.2rem, 1.9vw, 1.6rem);
  border-radius: var(--radius);
  color: #fff;
  background: rgba(0, 12, 99, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 10px 30px rgba(0, 8, 50, 0.26);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .whytile__glass { background: rgba(0, 12, 99, 0.8); }
}
.whytile__glass h3 { color: #fff; margin-top: clamp(1rem, 1.8vw, 1.4rem); }
.whytile__glass p { color: rgba(255, 255, 255, 0.9); }
.whytile--shot:hover .whytile__bg { transform: scale(1.045); }

/* ---- 5 · the closer -------------------------------------------------
   This was a photograph of New York with a translucent box on it, which
   is the same device the contact band uses two sections later, and the
   picture was carrying nothing the words needed. It is a drawn surface
   now, using the same rings as the lead tile -- so the section opens and
   closes on one motif. */
.whycloser {
  position: relative; isolation: isolate; overflow: hidden;
  margin-top: clamp(1.6rem, 2.6vw, 2.2rem);
  border-radius: var(--radius-xl);
  background: linear-gradient(118deg, var(--brand-900) 0%, var(--brand-700) 62%, var(--brand-600) 100%);
  color: #fff;
  padding: clamp(1.9rem, 3.4vw, 3.2rem);
  display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(1.6rem, 3.4vw, 3rem); align-items: center;
}
.whycloser__pat {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: repeating-radial-gradient(circle at 88% 118%, rgba(255, 255, 255, 0.11) 0 1px, transparent 1px 32px);
  -webkit-mask-image: linear-gradient(285deg, #000 0%, transparent 70%);
  mask-image: linear-gradient(285deg, #000 0%, transparent 70%);
}
.whycloser__copy, .whycloser__act { position: relative; z-index: 1; }
.whycloser__copy h2 {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.65rem, 2.9vw, 2.4rem); line-height: 1.12; color: #fff;
}
.whycloser__copy p {
  margin-top: 0.85rem; max-width: 46ch;
  font-size: clamp(0.98rem, 1.15vw, 1.06rem); line-height: 1.6;
  color: rgba(255, 255, 255, 0.84);
}
.whycloser__act {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: clamp(1rem, 1.8vw, 1.4rem);
}

/* The bento holds to about 1040px, below which the lead tile's copy
   starts to break badly across seven of twelve columns. It goes to two
   columns with the photograph across the top, then to one. */
@media (max-width: 1040px) {
  .whybento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .whytile:nth-child(1) { grid-column: 1 / 3; }
  .whytile:nth-child(2) { grid-column: 1 / 2; }
  .whytile:nth-child(3) { grid-column: 1 / 3; grid-row: auto; }
  .whytile:nth-child(4) { grid-column: 2 / 3; }
  .whytile--shot { min-height: clamp(19rem, 42vw, 24rem); }
  .whycloser { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .whybento { grid-template-columns: minmax(0, 1fr); }
  .whytile:nth-child(1), .whytile:nth-child(2),
  .whytile:nth-child(3), .whytile:nth-child(4) { grid-column: 1 / 2; }
  .whytile h3 { margin-top: 1.2rem; }
}
@media (prefers-reduced-motion: reduce) {
  .whytile, .whytile__bg, .whytile--shot:hover .whytile__bg { transition: none; transform: none; }
}

/* ---- 6 · the ecosystem panels get their glass -----------------------
   The copy on these three photographs was sitting on a gradient wash --
   correct for legibility, but a gradient with nothing holding it is a
   smudge, and the client's note was that these should read as designed
   widgets. The wash becomes a pane: the same recipe as everywhere else
   on this page, with a hairline pattern inside it so it has a texture of
   its own rather than only borrowing the photograph's.

   0.6 navy is not an arbitrary number. Composited over a pure white
   pixel -- the worst case any of these three crops can produce, and 02
   genuinely contains blown highlights -- it measures 4.9:1 against white
   type, clearing the 4.5 floor for the body copy. The scrim underneath
   and the blur both push the real figure higher. */
.ecopanel { padding: clamp(0.9rem, 1.5vw, 1.35rem); }
.ecopanel__body {
  width: auto;
  padding: clamp(1.3rem, 2.1vw, 1.9rem);
  border-radius: var(--radius);
  background: rgba(0, 12, 99, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.19);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 12px 34px rgba(0, 8, 50, 0.28);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ecopanel__body { background: rgba(0, 12, 99, 0.86); }
}
/* Replaces the ramp that used to live here. Kept at a very low alpha:
   at 0.05 the hatch is felt rather than seen, which is all a pane this
   size can take before it starts competing with the wordmark on it. */
.ecopanel__body::before {
  inset: 0; border-radius: inherit;
  background-image: repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 11px);
  background-color: transparent;
}
/* The pane is inset from the panel, so a link stretched to the pane no
   longer covers the picture. Pulled back out by the panel's own padding
   -- 1.35rem is the top of the clamp, and overshooting is harmless
   because .ecopanel clips. */
.ecopanel__go::after { inset: -3rem; }
.ecopanel:hover .ecopanel__body { background: rgba(0, 12, 99, 0.66); }
@media (max-width: 1000px) {
  .ecopanel { padding: clamp(0.8rem, 2.4vw, 1.1rem); }
}

/* ============================================================
   v55 — 2026-08-12 — the filled icon set, finished

   The previous block introduced svg.ico and painted it with
   `fill: currentColor`, but the outline rules it was meant to sit
   beside outranked it:

     .ibadge svg            (0,1,1)  fill: none
     #why .ibadge svg       (1,1,1)  stroke: var(--ink)
     .ico                   (0,1,0)  fill: currentColor

   so every filled path had fill:none and a stroke it no longer draws
   with -- ten empty circles on the homepage. The fix is to scope the
   outline rules to svg:not(.ico) at their source rather than pile a
   heavier selector on top: about.html, careers.html and the four brand
   sites still carry the outline set, and it keeps working untouched.

   Optical size: the icon is half the chip, in both sizes. 2.9rem chip
   -> 1.45rem icon, 2.35rem chip -> 1.18rem. Filled marks carry more
   weight than a 1.6px outline at the same box, so half is the ceiling,
   not the target -- past it the chip stops reading as a chip.

   The secondary mass in every two-tone mark is now .32 across the page
   (it was .3 / .35 / .45 / .55, which read as four different icon
   families under one stroke). One value, one family. */
.ibadge .ico { width: 1.45rem; height: 1.45rem; }
.ibadge--sm .ico { width: 1.18rem; height: 1.18rem; }

/* The same collision as .ibadge, in the two places an icon sits inline
   with text rather than in a chip: .formnote under the contact form and
   .fcontact in the contact column. Their outline rules carried the box
   as well as the paint, so scoping those to :not(.ico) left the filled
   marks with no size. Sized here, optically matched to the line they
   sit on rather than to each other -- .formnote runs at 0.9rem type. */
.formnote .ico { width: 0.95rem; height: 0.95rem; flex: none; margin-top: 0.18rem; }
.fcontact .ico { width: 1.1rem; height: 1.1rem; flex: none; margin-top: 0.15rem; }

/* ======================================================================
   v56 · 2026-08-12 · the contact glass, measured
   ====================================================================== */

/* The previous block took these two panels down to 0.55 and 0.5 white to
   make the glass real, and recorded --faint on the note at "about 3.2:1".
   That figure was an average. Measured the way the button check requires
   -- worst pixel, not mean -- the panels came out well under the floor:

     panel      fill   --muted      --ink
     form card  0.55    2.58:1     6.27:1
     news strip 0.50    2.08:1     5.06:1

   The worst pixel is at roughly (920, 689) in a 1180-wide frame, which is
   the dark shoulder of the handshake photograph sitting directly behind
   the note under the form. Method: the photograph mapped through its own
   object-fit: cover / object-position: 50% 46% box, the three scrim layers
   composited in paint order, a 7.5px blur on a quarter-scale copy to stand
   in for backdrop-filter: blur(30px), then the panel fill over every pixel.

   Two changes, both needed -- neither alone clears 4.5:1 on the strip:

   - the fills come up to 0.68, and the strip stops being the lighter of
     the two. It sits over the bottom of the frame, which is the darker
     end, so a lighter fill there was backwards;
   - every --muted run on these panels moves to --ink-soft. That is the
     card's supporting line, the four field labels, the note, and the
     strip's second line. --muted is a light-ground colour; on glass over
     a photograph it has nothing to hold on to.

   Measured after, worst pixel: --ink-soft 5.42:1 on the card and 5.22:1
   on the strip, --ink 8.94:1 and 8.62:1. The photograph still reads
   through -- 0.68 with a 30px blur is soft colour behind the type, which
   was the point of the previous block, and 0.68 is a long way from the
   0.86 that made the blur decorative.

   Re-measure if the photograph changes. The floor is set by the picture,
   not by the CSS -- same note as main.css:1437 on the hero. */
.moment--shot .formcard,
.moment--shot .newsstrip { background: rgba(255, 255, 255, 0.68); }

.moment--shot .formcard > p,
.moment--shot .formcard .form label,
.moment--shot .formnote,
.moment--shot .newsstrip p { color: var(--ink-soft); }

/* One warning about the name: `.ico` means two unrelated things in this
   project. On an <svg> it selects the filled two-tone icon set and turns
   off the outline paint (see v55). On a <span> inside .acc__btn it is the
   accordion's "+" glyph, which predates the icon set and is styled at
   main.css:911. The two never meet -- one is an SVG, the other a text
   node in a component that has no SVG in it -- but do not "tidy" the
   generic .ico rule into something that assumes an SVG box, and do not
   give .ico a width here: .acc__btn .ico sets its own 22px and the icon
   set is sized by its chip (.ibadge .ico), on purpose. */

/* ======================================================================
   v57 · 2026-08-12 · the homepage review, section by section
   ----------------------------------------------------------------------
   The client walked the page top to bottom and left about twenty notes.
   Most were markup and are answered in index.html; the ones that needed
   CSS are below, in page order, each against the note it answers.

   Two of them are the same note in different sections -- "centre the
   ecosystem boxes", "just keep the logo in the centre and enlarged" --
   and they are worth reading together. This page had settled into one
   habit: every card, everywhere, left-aligned with the mark small in the
   top-left corner. That is right for a card you read and wrong for a card
   whose subject IS the mark. Both sections below now centre on the thing
   the reader is meant to look at.
   ====================================================================== */

/* ---- #believe -------------------------------------------------------
   "the built around your goals, not an average should come down to
   centre in the vertical direction."

   The lede is three lines of display type; the list beside it is three
   items running roughly twice that height. Aligned to the top, the
   headline sat against the first item and left a large hole under
   itself. align-items: center is the whole fix -- it costs nothing on
   mobile, where the grid is already one column and there is nothing to
   centre against. */
.creed__split { align-items: center; }

/* "gray numbers 01, 02, 03 is very faint on the what we believe."
   They were --brand-200 (#c9d0f3), which is a tint meant for fills and
   hairlines, not for type -- it measures about 1.5:1 on white. They are
   aria-hidden and decorative, so there is no legal floor to hit, but a
   numeral you cannot see is not doing the job the layout gives it: these
   three are the only structure the list has, since it deliberately has no
   rule, no card and no bullet. --brand-500 is the same hue with enough
   weight to count the items by. */
.creed__n { color: var(--brand-500); }

/* ---- #what-we-do ----------------------------------------------------
   "boxes in center alignment for the our ecosystem ... center alignment
   rather than left alignment."

   The glass pane goes full width of its panel and everything inside it
   centres: the mark, the heading, the paragraph and the link. The
   paragraph keeps its measure and gets auto margins, because a centred
   line that runs the full width of the pane is centred in name only --
   the eye needs the short measure to see the axis. */
.ecobleed--centred .ecopanel__body { width: 100%; text-align: center; }
.ecobleed--centred .ecopanel__brand { justify-content: center; }
.ecobleed--centred .ecopanel__body p { margin-inline: auto; }
/* .wdlock is a two-row lockup (mark over descriptor) with
   align-items: stretch, so the descriptor can track out to the
   wordmark's width. Centring the row it sits in does not centre it --
   the lockup has to be told it is a centred block itself. */
.ecobleed--centred .wdlock { align-items: center; }
.ecobleed--centred .ecopanel__logo { object-position: center bottom; margin-inline: auto; }

/* ---- #brands --------------------------------------------------------
   "remove the title and the logo as it is repetitive. just keep logo in
   the center and enlarged"; "add tag line ..."; "highlight taglines
   under logo."

   The mark is the title now, so it is set at roughly twice the old size
   and put on the card's centre line, with the tagline directly under it
   as the one line that tells the two businesses apart. The tagline is
   the loudest thing in the card after the mark -- it is a chip rather
   than another grey paragraph, because "highlight" is what was asked for
   and because a coloured chip is the only way to outrank a 48px logo
   without shouting. */
.brandcard--centred .brandcard__inner {
  align-items: center; text-align: center;
}
.brandcard--centred .brandcard__title { margin: 0; }
.brandcard--centred .brandcard__mark.wdlock,
.brandcard--centred .brandcard__mark {
  align-self: center; margin-bottom: 0;
}
.brandcard--centred .brandcard__mark .wdlock__mark { height: clamp(38px, 3.4vw, 48px); }
/* The descriptor's tracking is set as a ratio to the wordmark's width
   (v51), so enlarging the mark without enlarging this would leave
   "Private" as a short word floating under a wide one. It scales with
   it. */
.brandcard--centred .brandcard__mark .wdlock__desc { font-size: clamp(0.88rem, 0.8vw, 1.1rem); }
.brandcard--centred .brandcard__mark.mark--nv { height: clamp(34px, 3vw, 44px); }

.brandcard__tag {
  display: inline-block;
  margin-top: clamp(1rem, 1.7vw, 1.35rem);
  padding: 0.42rem 0.95rem;
  border-radius: var(--radius-pill);
  background: var(--brand-50);
  border: 1px solid var(--brand-100);
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(0.96rem, 1.15vw, 1.08rem); line-height: 1.3;
  color: var(--brand-700);
  text-wrap: balance;
}
/* The body copy under the chip drops a step, so the order down the card
   reads mark, tagline, explanation -- three sizes, not two the same. */
.brandcard--centred .brandcard__inner > p { font-size: 0.92rem; max-width: 40ch; }
.brandcard--centred .brandcard__sites { justify-items: center; width: 100%; }

/* A photograph butting straight into a white panel on a hard line is the
   join you notice. The veil is a short fade at the foot of the image
   only -- it does not darken the picture, it just softens the edge. */
.brandcard__media { position: relative; }
.brandcard__veil {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(180deg, rgba(0, 12, 99, 0) 58%, rgba(0, 12, 99, 0.14) 100%);
}

/* ---- #global --------------------------------------------------------
   "the numbers of 2 3 4 1 subtext lines should be darker."
   The sublabel was --muted at 12.5px. It is the line that says what each
   figure means, so it goes to --n-700: still clearly secondary to the
   ink label above it, but no longer the palest type in the panel. */
.reachpanel__stats .rstat small { color: var(--n-700); }

/* The two market tiles are photographs with a label on them, and they
   were the last images on this page still sitting at their natural crop
   with nothing holding them. Same treatment as everywhere else now. */
.markettile { position: relative; overflow: hidden; border-radius: var(--radius); }

/* ---- #who-we-are ----------------------------------------------------
   "image needs to be improved."
   The photograph changed in the markup. This is the overlay that ties it
   to the other two treated images on the page (.valshot, .whytile--shot):
   a hairline grid at low alpha, masked off before it reaches the bottom
   third, so it reads as a considered surface rather than a snapshot
   dropped into a box. */
.imgslot { position: relative; }
.imgslot__pat {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.13) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.13) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: linear-gradient(200deg, #000 0%, transparent 66%);
  mask-image: linear-gradient(200deg, #000 0%, transparent 66%);
}

/* The two facts were grey label over grey sentence under a grey lead --
   three greys in a column, so they read as small print. Each entry hangs
   off a brand keyline now and the term sits in brand blue, which makes
   the pair the section's evidence rather than a footnote to it. */
.whofacts--keyed { border-top: 0; }
.whofacts--keyed > div {
  border-bottom: 0;
  border-left: 2px solid var(--brand-200);
  padding: 0.1rem 0 0.1rem clamp(0.9rem, 1.5vw, 1.15rem);
}
.whofacts--keyed > div + div { margin-top: clamp(1rem, 1.8vw, 1.35rem); }
.whofacts--keyed dt { color: var(--brand-700); }
.whofacts--keyed dd { color: var(--n-700); }

/* ---- #regulation ----------------------------------------------------
   "center around held to highest duty of care."

   The section used to run copy left and a panel of registrations right,
   which made the registrations the subject and the duty of care their
   caption. It is inverted: the statement is centred and alone at the
   top, and the two registrations sit under it as a matched pair of
   evidence, one card each at equal weight. Neither regulator is bigger
   than the other, which matters -- they are two equal registrations in
   two markets, not a primary and a secondary. */
.regcentre { display: flex; flex-direction: column; align-items: center; }
.regcentre__stmt { max-width: 18ch; margin-inline: auto; }
.regcentre .sechead--centre .lead { max-width: 56ch; margin-inline: auto; margin-top: 1.2rem; }
.regduo {
  width: 100%; max-width: 62rem;
  margin-top: clamp(2.2rem, 3.8vw, 3.2rem);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 1.8vw, 1.4rem);
}
/* Overrides the base .regreg, which is a horizontal row built for the
   old right-hand panel. As a card it is a centred column: mark on top,
   then the regulator's short code, then the market, then the sentence. */
.regreg--card {
  flex-direction: column; align-items: center; text-align: center;
  gap: clamp(0.9rem, 1.6vw, 1.2rem);
  background: var(--n-0);
  border: 1px solid var(--warm-line);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 2.6vw, 2.1rem);
  box-shadow: var(--shadow-sm);
}
.regreg--card + .regreg--card { margin-top: 0; border-top: 0; padding-top: clamp(1.5rem, 2.6vw, 2.1rem); }
.regreg--card .regreg__mark { width: 4.4rem; height: 4.4rem; display: grid; place-items: center; }
.regreg--card .regreg__c p { max-width: 38ch; margin-inline: auto; }
.regcentre__cta { margin-top: clamp(2rem, 3.2vw, 2.6rem); }
@media (max-width: 720px) {
  .regduo { grid-template-columns: minmax(0, 1fr); }
}

/* ---- #contact -------------------------------------------------------
   "start a conversation a get in touch needs to be improved. it is too
   big."

   The band opened on a full .h2 and a .lead -- the same weight the page
   gives "Why Wealthdoor" and "Our ecosystem" -- for what is, in the end,
   a contact form. Everything in it comes down one step: the heading to
   .h2--sm, the copy to body scale, and the gap and the card padding in
   with them. The section keeps its full-bleed photograph, so it still
   reads as an event on the page; it just stops competing with the
   sections that carry the argument. */
.h2--sm { font-size: clamp(1.45rem, 2.3vw, 1.9rem); }
.getintouch--tight { gap: clamp(1.6rem, 3vw, 2.8rem); align-items: center; }
.getintouch--tight .seclabel { margin-bottom: 0.7rem; }
/* The copy under the heading is a plain <p>, not a .lead, so the
   white-on-photograph colour rules keyed to .lead do not reach it. */
.getintouch--glass p { color: rgba(255, 255, 255, 0.9); }
.getintouch--glass .contactdirect { margin-top: 1.2rem; }
.formcard--tight { padding: clamp(1.25rem, 2.1vw, 1.7rem); }
.formcard--tight h3 { font-size: clamp(1.1rem, 1.6vw, 1.3rem); }
.formcard--tight .form { margin-top: 1rem; }

/* ======================================================================
   v58 · 2026-08-12 · three defects found while checking v57 on screen
   ====================================================================== */

/* --- 1 · the clipped "PRIVATE" ----------------------------------------
   The Wealthdoor Private lockup is a <span class="wdlock brandcard__mark">,
   so it inherits the rules written for a bare <img class="brandcard__mark">
   at line 725 and line 2804: a hard height of 26px and aspect-ratio
   878/290. On the old left-aligned card that was harmless, because the
   lockup was 26px anyway. Enlarging the mark for the centred card left
   the 26px box in place, and .wdlock is a flex column -- so the wordmark
   and the descriptor were shrunk to fit it, and "PRIVATE" spilled out
   below and was overprinted by the tagline chip.
   The box has to stop being a fixed-size image box; the lockup sizes
   itself from its two rows. */
.brandcard--centred .brandcard__mark.wdlock {
  height: auto;
  width: auto;
  aspect-ratio: auto;
}
/* An inline-flex baselines on its first row, so the descriptor hangs
   below the line box even once the height is free. Making the heading
   the flex container blockifies the lockup and the overflow goes. */
.brandcard--centred .brandcard__title {
  display: flex;
  justify-content: center;
}

/* --- 2 · the brand card crop -------------------------------------------
   21/9 over a 2:3 portrait keeps about a sixth of the picture, and the
   sixth it kept was the middle of two torsos. 16/9 is still a letterbox
   above a centred logo, but it is enough of the frame for a face to
   survive; the two images carry their own object-position inline. */
.brandcard--centred .brandcard__media { aspect-ratio: 16 / 9; }

/* --- 3 · the market tile labels ----------------------------------------
   .markettile::after is a bottom-anchored scrim that is effectively clear
   above 62% of the tile. That was safe while the label was one short line
   at the bottom; at narrow widths "SEC registered adviser" wraps and the
   label climbs past halfway, so white type ended up on a pale sky at
   about 3.5:1.
   The wash is anchored to the label instead of to the tile, so it cannot
   be outrun by a wrap: at 0.86 over a worst-case white pixel the small
   text reads 8.9:1. */
.markettile__label { isolation: isolate; }
.markettile__label::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: -0.7rem -0.9rem -0.85rem -0.9rem;
  background: linear-gradient(
    to top,
    rgba(0, 12, 99, 0.9) 0%,
    rgba(0, 12, 99, 0.86) 72%,
    rgba(0, 12, 99, 0.55) 90%,
    rgba(0, 12, 99, 0) 100%
  );
}

/* v58a · the wash above turned both market tiles into navy blocks: the
   label wraps to two lines in a 121px tile, so its own gradient plus the
   tile-wide ::after scrim left almost none of the photograph showing --
   and new photographs for this section are the reason it was touched.
   The label keeps its guarantee; the tile scrim drops to a tint, because
   it no longer has to carry the type on its own. */
.markettile::after {
  background: linear-gradient(
    to top,
    rgba(0, 12, 99, 0.3) 0%,
    rgba(0, 12, 99, 0.12) 46%,
    rgba(0, 12, 99, 0) 76%
  );
}
.markettile__label::before {
  inset: -0.55rem -0.9rem -0.85rem -0.9rem;
  background: linear-gradient(
    to top,
    rgba(0, 12, 99, 0.82) 0%,
    rgba(0, 12, 99, 0.78) 78%,
    rgba(0, 12, 99, 0.42) 92%,
    rgba(0, 12, 99, 0) 100%
  );
}

/* ======================================================================
   v63 · 2026-08-13 · the internal pages, rewritten to the content spec
   ----------------------------------------------------------------------
   The client supplied finished copy for About, Careers and a new Open
   roles page, each item carrying a design note. Six of those notes ask
   for a shape the stylesheet does not have yet, and the markup was
   written against them first, so everything below exists to make the
   new About and Open roles markup render as specified rather than to
   restyle anything that already worked.
   ====================================================================== */

/* --- 1 · the About hero stops borrowing the careers arch --------------
   "Wide rectangular image, not an arch ... about should feel more
   editorial and institutional than careers ... one CTA only."

   The arch is careers' signature shape. Sharing it made the two page
   heroes near-identical at a glance, which is the opposite of what the
   note asks for. So About stacks instead of splitting: the copy runs as
   one column, then a single 21:9 band beneath it at the full width of
   the wrap. Wide-and-low is the institutional shape -- it reads as a
   masthead rather than a portrait, and it gives the photograph no
   silhouette to compete with the headline. */
.chero--editorial .chero__grid { display: block; }
.chero--editorial .chero__copy { max-width: 58ch; }
.chero--editorial .chero__copy h1 { max-width: 18ch; }
.chero--editorial .chero__lead { max-width: 56ch; }
.chero--editorial .chero__stage { margin-top: clamp(2.4rem, 4.6vw, 3.8rem); }
/* The arch is three declarations: the aspect ratio, the pill radius and
   the lifted shadow. All three go. A 21:9 band sitting flat on the page
   with a hairline is the editorial treatment; the drop shadow was what
   made the careers arch float, and floating is the wrong register here. */
.chero--editorial .chero__art {
  aspect-ratio: 21 / 9;
  border-radius: var(--radius-lg);
  box-shadow: none;
  border: 1px solid var(--line);
}
/* The section wash was aimed at the right-hand 58% of the hero, where
   the careers arch stands. With the picture moved under the copy it
   would fall on empty white, so it is retuned to a wide, low blue
   behind the whole band -- and the orange radial is dropped outright,
   the same removal made across the homepage on 2026-08-12. */
.chero--editorial::before {
  inset: 0 -12% 26% -12%;
  background: radial-gradient(64% 70% at 26% 26%, rgba(0, 19, 160, 0.07), transparent 74%);
}
@media (max-width: 720px) {
  /* 21:9 is 168px tall on a 390px screen -- a letterbox, not a picture.
     Below the breakpoint it opens up to 3:2, which is the source's own
     ratio, so the crop stops working at all. */
  .chero--editorial .chero__art { aspect-ratio: 3 / 2; }
  .chero--editorial::before { inset: 0 -20% 30% -20%; }
}

/* --- 2 · Our story, as one measured column ----------------------------
   "One narrow editorial text column. No cards. No image required ...
   should read more like a serious company profile than a marketing
   section."

   62ch is the cap. Wider and the eye starts losing the line return on
   the way back -- the specific failure a four-paragraph company profile
   cannot afford, because there is nothing else on the page to recover
   the reader's place. It is deliberately not centred: the column keeps
   the same left edge as every other section on the page, so removing
   the photograph did not also move the text. */
.storycol { max-width: 62ch; }
.storycol .body + .body { margin-top: 1rem; }

/* --- 3 · a label above the group diagram ------------------------------
   "THE BUSINESSES WE RUN" is an eyebrow for the diagram, not for the
   section -- the section already has one. It sits far enough below the
   two-column intro to read as belonging to the drawing beneath it, and
   it is given the hairline so the diagram reads as its own block. */
.diaglabel {
  margin-top: clamp(2.6rem, 5vw, 4rem);
  padding-top: clamp(1.4rem, 2.4vw, 2rem);
  border-top: 1px solid var(--warm-line);
}

/* The parent slot in the diagram is the group wordmark, which reads
   just "wealthdoor" -- the same word as the Private lockup below it.
   The descriptor is what tells the two apart, so it is set exactly like
   .wdlock__desc. .barch__parent zeroes its line-height to sit tight
   around a 22px image, so this has to hand a line-height back. */
.barch__parentdesc {
  display: block;
  margin-top: 0.34rem;
  text-align: center;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.58rem;
  line-height: 1;
  letter-spacing: 0.42em;
  text-indent: 0.42em;         /* cancels the trailing letter-space */
  text-transform: uppercase;
  color: var(--brand);
  white-space: nowrap;
}

/* --- 4 · two markets, weighted the same -------------------------------
   "One US image and one India image. Both images should have the same
   colour temperature, clarity, crop ratio and visual weight. Neither
   market should look secondary."

   One shared aspect ratio does the second half of that on its own. The
   arrangement is what changed: with the 2/3/4/1 counters gone from
   under them, two side-by-side tiles measured 245x286 against a
   770-tall list beside them -- a panel a third the height of its
   neighbour reads as a caption to it, and each market got a thumbnail.
   Stacked, each tile takes the full 550 of the column at 3:2, the pair
   comes to 747 against the list's 770, and neither market is the small
   one because neither is beside the other. */
.reachpanel--duo .reachpanel__map { grid-template-columns: minmax(0, 1fr); gap: 0.9rem; }
.reachpanel--duo .markettile { aspect-ratio: 3 / 2; }

/* --- 5 · a short closing section --------------------------------------
   "Keep this section short. Roughly half the height of a major content
   section." .section is clamp(4.5rem, 8.5vw, 8.5rem) top and bottom, so
   this is that ramp halved rather than a new set of numbers -- it stays
   in proportion as the viewport changes. */
.section--compact { padding-block: clamp(2.25rem, 4.25vw, 4.25rem); }

/* --- 6 · the Open roles page ------------------------------------------
   One sentence of news and one thing to do. No cards, no filter bar and
   no photograph: dressing up an empty list reads worse than a plainly
   written no, and every element added here would be an element the
   reader has to check for a role that is not in it.

   The page has no hero band, so the section carries the clearance the
   fixed nav needs itself -- same top ramp as .chero. */
.section--roles { padding-block: clamp(7.5rem, 11vw, 9.75rem) clamp(4.5rem, 8vw, 7.5rem); }
/* .display tops out at 5.4rem, which is the homepage front-door size.
   Four words of bad news do not get the front door's type. */
.rolespg .display { font-size: clamp(2.4rem, 4.2vw, 3.5rem); }
.rolespg .storycol .body { max-width: 54ch; }
/* The supporting line is the page's footnote: it answers "so what do I
   do next" after the button, and it is set below the button and below
   the body size so it never competes with either. */
.rolesnote {
  margin-top: clamp(2.2rem, 4vw, 3rem);
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  max-width: 40ch;
  font-size: 0.9rem;
  color: var(--faint);
}

/* --- 7 · the three careers hero proof points, at their new lengths ----
   The client's replacement copy is longer than what was there: the three
   chips measure 185 + 198 + 182 against a 531px hero column at 1382, so
   "Two markets / US and India." fell to a second row on its own and the
   set stopped reading as one rule of three.

   Flex was sizing each chip to its own content, which means the layout
   holds or breaks depending on the wording. Equal grid columns take that
   dependency out: each chip gets a third of the column whatever it says,
   and every chip keeps the same width whatever it says.

   Three across needs about 120px of text per cell. The hero column only
   has that from roughly 1150 up: measured at 1024 the cells came out
   147px wide and "In every decision." ran to three lines. So between the
   stacking breakpoint and 1150 the chips run as a single stacked list --
   the same shape the phone rules already produce, borrowed rather than
   invented, and the arch beside them is tall enough to carry it. */
@media (min-width: 1150px) {
  .careerspg .herochips { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .careerspg .herochip { padding: 0 0.65rem; gap: 0.5rem; font-size: 0.82rem; }
  .careerspg .herochip:first-child { padding-left: 0; }
}
@media (min-width: 721px) and (max-width: 1149px) {
  .careerspg .herochips { gap: 0.9rem 0; }
  .careerspg .herochip { flex: 0 0 100%; padding-left: 0; padding-right: 1rem; }
  .careerspg .herochip + .herochip { border-left: 0; }
}

/* ======================================================================
   v64 · 2026-08-13 · the blue comes off the glass

   Client note, in their words: "in Our ecosystem section remove the blue
   colour in it keep only glassmorfisum n remove the lines also in the
   widgets ... in Our values section in the image glass morfisum widget
   remove the blue colour in it same in Why Wealthdoor section also".

   Worth recording WHY this is a safe change rather than a taste swap.
   The navy in these three panes was never decoration -- it was the
   contrast substrate. White type on a pane whose only opacity comes from
   blur will fail against a blown highlight, and two of these crops
   contain blown highlights. So the tint is not deleted, it is turned
   neutral at an alpha that still measures. Every figure below is the
   worst pixel the crop can produce (pure white underneath), not an
   average -- an average has passed things here before that failed.

     #111519 @ 0.62 over white ................. 5.13:1
     #111519 @ 0.50 + a 0.32 scrim (= 0.66) .... 5.89:1
     #111519 @ 0.40 + a 0.58 ramp (= 0.748) .... 8.12:1

   All three clear the 4.5 floor for body copy, and the blur pushes the
   real figure higher again. If anyone lowers these alphas, re-measure --
   neutral grey has less headroom than navy did at the same number.
   ====================================================================== */

/* ---- 1 · #what-we-do, the ecosystem panes --------------------------
   The hatch inside the pane goes with the tint. It was there to give the
   glass a texture of its own; a neutral pane over a photograph already
   reads as glass, and the client sees the hatch as lines on a widget,
   which is a fair reading of it. */
.ecopanel__body { background: rgba(17, 21, 25, 0.62); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ecopanel__body { background: rgba(17, 21, 25, 0.88); }
}
.ecopanel:hover .ecopanel__body { background: rgba(17, 21, 25, 0.68); }
.ecopanel__body::before { display: none; }
/* The scrim goes neutral with it. Left navy it would tint the pane blue
   from underneath, which is the thing being removed. */
.ecopanel__scrim {
  background: linear-gradient(180deg, rgba(10, 12, 14, 0.16) 0%, rgba(10, 12, 14, 0.06) 42%, rgba(10, 12, 14, 0.22) 100%);
}

/* ---- 2 · #brands, the two site buttons -----------------------------
   "make the buttons .us n .in in equal sizes of the widget, divide in
   equal size of the widget." The grid was already 1fr 1fr; what broke it
   was justify-items:center from the centred-card variant, which sizes
   each pill to its own text -- so wealthdoor.us and wealthdoor.in came
   out different widths inside identical columns. Stretch puts them back
   on the column, which is exactly half the card each. */
.brandcard--centred .brandcard__sites { justify-items: stretch; }

/* ---- 3 · #global, the market photographs ---------------------------
   "for the images add the blue gradient like liner." A single blue ramp
   now runs the height of each tile instead of the flat tint v58a left
   behind plus a separate plate behind the label. One gradient doing both
   jobs is cleaner than two stacked, and it is the one place on this page
   where blue on a photograph is still wanted.

   Angled a few degrees off vertical so it reads as a wash across the
   picture rather than a bar at the bottom, and it starts higher and
   stronger than v58a's tint did -- that is the visible change.

   THE LABEL PLATE STAYS. It was the first thing I took out, on the
   argument that one gradient should do both jobs, and measuring it
   killed the idea: at 390px the tile is 121px tall and the label wraps
   to 67px of it, so the top line sits about a third of the way down the
   picture where the tile ramp is only 0.18 -- 2.1:1 over the brightest
   pixel in the India crop. This is the same trap v58a documents two
   blocks up. The plate is lightened instead, from 0.82 to 0.72, so that
   composited with the stronger tile ramp underneath it lands at 0.84 --
   where v58a's pairing landed, 12.9:1, and no darker than before. */
.markettile::after {
  background: linear-gradient(
    196deg,
    rgba(36, 56, 201, 0) 4%,
    rgba(36, 56, 201, 0.2) 38%,
    rgba(0, 19, 160, 0.42) 68%,
    rgba(0, 12, 99, 0.58) 100%
  );
}
.markettile__label::before {
  background: linear-gradient(
    to top,
    rgba(0, 12, 99, 0.72) 0%,
    rgba(0, 12, 99, 0.68) 78%,
    rgba(0, 12, 99, 0.46) 92%,
    rgba(0, 12, 99, 0) 100%
  );
}

/* ---- 4 · #values, the caption on the photograph --------------------
   The hairline grid stays -- it is drawn on the picture, not on the
   widget, and it is what ties this frame to the tiles below. Only the
   navy comes out: the ramp it sits on as well as the pane itself, for
   the same reason as the ecosystem scrim. */
.valshot__pat {
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.14) 1px, transparent 1px),
    linear-gradient(180deg, rgba(17, 21, 25, 0) 42%, rgba(17, 21, 25, 0.58) 100%);
}
.glasschip {
  background: rgba(17, 21, 25, 0.4);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 8px 24px rgba(0, 0, 0, 0.22);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glasschip { background: rgba(17, 21, 25, 0.72); }
}

/* ---- 5 · #why, the glass panel on the photograph -------------------- */
.whytile__scrim {
  background: linear-gradient(180deg, rgba(10, 12, 14, 0.1) 0%, rgba(10, 12, 14, 0.32) 100%);
}
.whytile__glass {
  background: rgba(17, 21, 25, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 10px 30px rgba(0, 0, 0, 0.26);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .whytile__glass { background: rgba(17, 21, 25, 0.82); }
}

/* ---- 6 · #regulation, after the regulators' marks came out ----------
   The seal and the SEBI logo were the top item in each card and set its
   rhythm; with them gone the card would start on a mono code with a
   4.4rem hole above it, because .regreg--card sized the mark slot. The
   slot goes, and the code takes over as the card's mark -- larger, in
   brand, with the rule under it doing the separating the logo used to do
   by simply being a different kind of thing. */
.regreg--card .regreg__mark { display: none; }
.regreg--card .regreg__code {
  font-size: 1.05rem; letter-spacing: 0.2em; text-indent: 0.2em;
  color: var(--brand);
  padding-bottom: clamp(0.7rem, 1.2vw, 0.95rem);
  border-bottom: 1px solid var(--warm-line);
  margin-inline: auto; width: fit-content; min-width: 7rem;
}
.regreg--card .regreg__c h3 { margin-top: clamp(0.9rem, 1.5vw, 1.2rem); }

/* ======================================================================
   v65 · 2026-08-13 · the glass goes white, and the phone gets a pass

   Client, in one message: reduce the blue in the Why Wealthdoor tiles;
   every widget sitting on top of an image is to be WHITE, with no grey in
   it; reduce the grey in the ecosystem panes; fix the spacing between the
   two brand cards; drop the 01/02/03 numbering; and go through the
   homepage on a phone.

   The white instruction is the one with consequences. v64 turned those
   three panes from navy to neutral dark, because a dark pane with white
   type is the easy way to stay readable over an unknown photograph. White
   glass inverts the whole stack: the type has to go to ink, the icon chips
   have to stop being white-on-white, the ecosystem links and logos have to
   come off their white variants, and the scrims underneath -- which exist
   to DARKEN the photo -- now work against the brief, because a white pane
   over a darkened photograph is exactly the grey the client is objecting
   to. So the scrims are inverted too: they lift the bottom of each picture
   instead of sinking it, which is what makes the pane read as white rather
   than as a grey smear.

   Contrast, measured the usual way -- on the worst pixel, which for dark
   ink on light glass is the DARKEST pixel behind the pane, not the
   brightest. Worst case is a pane over pure black with no lift at all:

     white @ 0.74 over #000 ...... backdrop L 0.4735
       --ink       #111519 ....... 9.06:1
       body        #2b3138 ....... 6.47:1
       --brand-700 #0013a0 ....... 6.48:1

   Every real photograph is lighter than that, and the lift scrims only
   raise it, so 0.74 is a floor rather than a typical figure. It is also
   low enough that the picture still reads through the pane, which was the
   client's requirement two rounds ago and has not been withdrawn.
   ====================================================================== */

/* ---- 1 · the shared white-glass material ----------------------------
   Same three ingredients the taste skill requires -- blur, a 1px edge, a
   top inset highlight -- inverted for a light pane: the edge is a white
   rim rather than a white hairline on dark, and the highlight sits at
   near-opaque white because on light glass the catch of light is the
   brightest thing on the pane, not a suggestion of one. */
.ecopanel__body,
.whytile__glass,
.glasschip {
  background: rgba(255, 255, 255, 0.74);
  border: 1px solid rgba(255, 255, 255, 0.66);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 30px rgba(10, 14, 24, 0.14);
  color: var(--ink);
}
/* No backdrop-filter means no blur to carry the pane, so the alpha has to
   do all of it. 0.9 keeps the same ink readable without the pane turning
   into a solid card. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ecopanel__body,
  .whytile__glass,
  .glasschip { background: rgba(255, 255, 255, 0.9); }
}
/* #2b3138 rather than --muted. --muted (#4e555f) measures 3.70:1 on the
   0.74 pane over black, which fails; this sits between --muted and --ink,
   reads as secondary next to the heading, and clears 6.4:1. */
.ecopanel__body p,
.whytile__glass p,
.glasschip .glasschip__v { color: #2b3138; }
.ecopanel__body h3,
.whytile__glass h3,
.glasschip .glasschip__k { color: var(--ink); }

/* The icon chip was white-on-translucent-white, which on a white pane is
   a chip you cannot see. It becomes a light chip with a brand-blue glyph
   and a faint ink rim -- the same chip the paper tiles already use, so
   the two materials now share one icon treatment. */
.ecopanel__body .ibadge--glass,
.whytile__glass .ibadge--glass,
.glasschip .ibadge--glass {
  color: var(--brand);
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(17, 21, 25, 0.1);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

/* ---- 2 · #what-we-do, the ecosystem panes --------------------------- */
/* v64's navy wash behind the copy is now the opposite of what is wanted:
   it is the grey. The pane's own alpha replaces it. */
.ecopanel__body::before { display: none; }
.ecopanel__body {
  border-radius: var(--radius);
  padding: clamp(1.25rem, 2.1vw, 1.9rem);
}
.ecopanel:hover .ecopanel__body { background: rgba(255, 255, 255, 0.8); }
/* Inverted: this used to sink the bottom of the photograph so white type
   would hold on it. It now lifts the bottom so the white pane sitting
   there reads white. The top stop is still a slight sink, because the
   photographs themselves are better with a little weight at the top. */
.ecopanel__scrim {
  background: linear-gradient(
    180deg,
    rgba(10, 14, 24, 0.12) 0%,
    rgba(10, 14, 24, 0.02) 34%,
    rgba(255, 255, 255, 0.16) 70%,
    rgba(255, 255, 255, 0.34) 100%
  );
}
/* The link was white with a white underline, on what is now a white pane. */
.ecopanel__go { color: var(--brand); text-decoration-color: rgba(0, 19, 160, 0.35); }
.ecopanel:hover .ecopanel__go { color: var(--brand-900); text-decoration-color: var(--brand); }
.ecopanel__go:focus-visible { outline-color: var(--brand); }
/* The marks are the dark variants now (see index.html), so the descriptor
   goes back to brand blue -- v51's tracking is untouched. */
.ecopanel__brand .wdlock__desc { color: var(--brand); }
/* 01/02/03 removed at the client's instruction. The rule stays so the
   class cannot quietly reappear with styling attached to it. */
.ecopanel__ix { display: none; }

/* ---- 3 · #values and #why, the panes on photographs ----------------- */
/* Both patterned overlays carried a navy bottom ramp for the same reason
   the ecosystem scrim did. Both are lifted instead. The hairline grid on
   the values shot goes from white to ink, because a white grid over a
   lightened photograph is invisible. */
.valshot__pat {
  background-image:
    linear-gradient(rgba(17, 21, 25, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(17, 21, 25, 0.07) 1px, transparent 1px),
    linear-gradient(180deg, rgba(255, 255, 255, 0) 44%, rgba(255, 255, 255, 0.3) 100%);
}
.whytile__scrim {
  background: linear-gradient(
    180deg,
    rgba(10, 14, 24, 0.08) 0%,
    rgba(10, 14, 24, 0.02) 40%,
    rgba(255, 255, 255, 0.3) 100%
  );
}

/* ---- 4 · #why, reducing the blue in the tiles ----------------------- */
/* The lead tile was a solid navy gradient -- the single loudest block of
   blue on the page after the closer. It becomes paper with a blue cast:
   the tint is still unmistakably of the brand family, but it is a wash
   rather than a field, and the type goes to ink. Hierarchy is kept by the
   accent rule and the larger heading, not by shouting in navy.

   The closer band below is deliberately NOT touched. The client asked for
   blue-led CTAs two rounds ago and this is the section's CTA; the
   instruction here was about the widgets. */
.whytile--lead {
  background:
    linear-gradient(152deg, rgba(36, 56, 201, 0.1) 0%, rgba(0, 19, 160, 0.05) 100%),
    var(--n-0);
  border: 1px solid var(--brand-100);
  color: var(--ink);
}
.whytile--lead h3 { color: var(--ink); }
.whytile--lead p { color: var(--muted); }
/* The rings were struck in white for a navy field. On paper they need to
   be blue, and fainter -- the same motif, a third of the shout. */
.whytile__pat--rings {
  background-image: repeating-radial-gradient(circle at 84% -8%, rgba(0, 19, 160, 0.08) 0 1px, transparent 1px 30px);
}
/* A brand hairline along the top edge: the one piece of saturated blue
   left on the tile, and the thing that still marks it as the lead. */
.whytile--lead::after {
  content: ''; position: absolute; z-index: 2; pointer-events: none;
  left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, var(--brand-500), var(--brand-900));
}
/* The chip on the lead tile was the dark-surface glass variant. On paper
   it needs the paper variant. */
.whytile--lead .ibadge--glass {
  color: var(--brand);
  background: var(--brand-50);
  border: 1px solid var(--brand-100);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: none;
}
/* The two patterned tiles were --brand-50 on --brand-100, which next to a
   now-pale lead tile read as three shades of the same blue in a row. They
   step back to near-white so the blue that is left has somewhere to sit. */
.whytile--pat {
  background: #fbfcfe;
  border: 1px solid var(--warm-line);
}
.whytile__pat--grid {
  background-image:
    linear-gradient(rgba(0, 19, 160, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 19, 160, 0.05) 1px, transparent 1px);
}
.whytile__pat--hatch {
  background-image: repeating-linear-gradient(135deg, rgba(0, 19, 160, 0.05) 0 1px, transparent 1px 10px);
}

/* ---- 5 · #brands, the two cards' internal spacing ------------------- */
/* Measured at 708px: the Wealthdoor Private title box is 58px tall (a
   mark over a "Private" descriptor) and the Nestvest one is 34px (a mark
   alone). Everything below inherited that 24px difference -- tagline at
   91px vs 68px from the top of the card, paragraph at 135 vs 112, the
   site buttons at 182 vs 159 -- so the two cards never lined up on a
   single row.

   The fix is one box for both marks, bottom-aligned, sized off the same
   clamp the lockup's mark uses plus one line for the descriptor. It
   tracks the viewport with the mark instead of being a magic number. */
.brandcard--centred .brandcard__title {
  min-height: calc(clamp(38px, 3.4vw, 48px) + 1.35rem);
  display: flex; align-items: flex-end; justify-content: center;
}
.brandcard--centred .brandcard__tag { margin-top: clamp(0.9rem, 1.6vw, 1.25rem); }

/* ---- 6 · the phone ---------------------------------------------------
   Audited at 375px. No horizontal overflow and every grid already
   collapses to one column, so the layout was sound; what failed was
   touch. The UI skill's floor is 44x44 with 8px between targets, and 33
   of the page's controls were under it -- the worst being the hero
   pagination dots at 30x3px, which is a 3-pixel-tall tap target.

   Where a control's SIZE is part of the design (the dots are a 3px bar on
   purpose), the hit area is grown with a transparent pseudo-element
   instead of the box, so nothing moves visually. */
.hero__dot { position: relative; }
.hero__dot::after {
  content: ''; position: absolute; inset: -20px -6px;
}
@media (max-width: 768px) {
  .nav__toggle { width: 44px; height: 44px; }
  /* `display: inline-flex` here was a mistake: it sits after the
     860px rule that hides .nav__cta .btn--ghost, so it put "Find
     your practice" back on the phone header, where it wrapped to
     four lines in an 89px box. .btn is already inline-flex, so the
     declaration bought nothing and cost the breakpoint. */
  .nav__actions .btn,
  .nav .btn--sm { min-height: 44px; align-items: center; }
  /* Footer links were 33px tall in a stacked column, which puts adjacent
     targets inside each other's error radius. Padding takes them to 44
     and gives the 8px separation at the same time. */
  .footer__col a { padding: 0.65rem 0; min-height: 44px; display: flex; align-items: center; }
  .footer__social a { width: 44px; height: 44px; }
  .fcontact a, .footer a[href^="mailto:"], .footer a[href^="tel:"] {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .subscribe input, .subscribe button,
  .fform input, .fform button { min-height: 46px; }
  /* The ecosystem panes stack full-bleed on a phone; at that width the
     desktop padding leaves the copy in a narrow ribbon. */
  .ecopanel__body { padding: clamp(1.1rem, 4.6vw, 1.5rem); }
}

/* ---- 7 · about.html, the values cards ------------------------------- */
/* Five identical centred boxes in a five-column row, each with a chip, a
   heading forced to a 2.5em flex box and one line of grey text. At
   1240px that is 210px per card, which is why the headings needed
   force-fitting in the first place: "Built for generations" does not fit
   on one line in 210px at any size worth reading.

   It is a bento now, in the same language as the homepage's Why tiles so
   the two pages stop looking like different projects: two wide tiles on
   the first row, three on the second, left-aligned, no forced heading
   heights, and the first commitment carrying the lead treatment because
   "client first" is the one the other four follow from. */
.valbento {
  margin-top: clamp(2.2rem, 4vw, 3.2rem);
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(0.8rem, 1.3vw, 1.15rem);
}
.valtile:nth-child(1) { grid-column: span 3; }
.valtile:nth-child(2) { grid-column: span 3; }
.valtile:nth-child(3),
.valtile:nth-child(4),
.valtile:nth-child(5) { grid-column: span 2; }
.valtile {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-lg);
  padding: clamp(1.4rem, 2.2vw, 2rem);
  background: #fbfcfe;
  border: 1px solid var(--warm-line);
  text-align: left;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}
.valtile:hover { border-color: var(--brand-200); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.valtile__pat {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(0, 19, 160, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 19, 160, 0.05) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: linear-gradient(215deg, #000 0%, transparent 72%);
  mask-image: linear-gradient(215deg, #000 0%, transparent 72%);
}
.valtile > *:not(.valtile__pat) { position: relative; z-index: 1; }
.valtile h3 {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.08rem, 1.4vw, 1.3rem); line-height: 1.22;
  color: var(--ink);
  margin-top: clamp(1.2rem, 2.2vw, 1.8rem);
  min-height: 0;
}
.valtile p {
  margin-top: 0.6rem;
  font-size: 0.94rem; line-height: 1.62; color: var(--muted);
  max-width: 38ch;
}
.valtile--lead {
  background:
    linear-gradient(152deg, rgba(36, 56, 201, 0.1) 0%, rgba(0, 19, 160, 0.05) 100%),
    var(--n-0);
  border-color: var(--brand-100);
}
.valtile--lead::after {
  content: ''; position: absolute; z-index: 2; pointer-events: none;
  left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, var(--brand-500), var(--brand-900));
}
.valtile--lead .valtile__pat {
  background-image: repeating-radial-gradient(circle at 84% -8%, rgba(0, 19, 160, 0.08) 0 1px, transparent 1px 30px);
  background-size: auto;
  -webkit-mask-image: linear-gradient(200deg, #000 0%, rgba(0, 0, 0, 0.15) 62%, transparent 88%);
  mask-image: linear-gradient(200deg, #000 0%, rgba(0, 0, 0, 0.15) 62%, transparent 88%);
}
.valtile--lead h3 { font-size: clamp(1.22rem, 1.8vw, 1.55rem); }
.valtile--lead p { font-size: 1rem; max-width: 42ch; }
/* Two per row, then one. Three 2-column tiles on a tablet would be 170px
   each, which is the problem this replaced. */
@media (max-width: 900px) {
  .valbento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .valtile:nth-child(1) { grid-column: span 2; }
  .valtile:nth-child(2),
  .valtile:nth-child(3),
  .valtile:nth-child(4),
  .valtile:nth-child(5) { grid-column: span 1; }
}
@media (max-width: 560px) {
  .valbento { grid-template-columns: minmax(0, 1fr); }
  .valtile:nth-child(n) { grid-column: span 1; }
}


/* ================================================================
   v66 · 2026-08-13 — closing the last eight phone touch targets
   ----------------------------------------------------------------
   v65's mobile block cut the sub-44px controls from 33 to 8. The
   eight that survived did so because four of the selectors named
   classes this site does not use, and two controls fail for a
   reason a width declaration cannot fix. Measured, not guessed:

   1 · .nav__toggle came out 27x44. The height took; the width did
       not, because the button is a flex item inside .nav__cta and
       `width` is only a basis there — flex-shrink pulled it back
       to its content width. It needs flex: 0 0 44px.
   2 · .brand is inline-flex around a 34px-tall bitmap. No amount
       of width helps; it needs a min-height and centred contents.
   3 · .hero__dot::after was inset -20px -6px on a 30px dot, which
       lands at 42px wide — two short. -8px gives 46.
   4 · The contact email lives in .contactdirect, not .fcontact.
   5 · The newsletter field lives in .footer__sub, not .subscribe
       or .fform.
   6 · The footer-bottom links already carry a 24px pseudo target
       from an earlier pass. 24 is not 44; on the phone it grows.

   Every fix here is phone-only. On a pointer device these controls
   are already comfortably clickable and enlarging them would open
   gaps in the header and footer rhythm for no gain.
   ================================================================ */

@media (max-width: 768px) {
  /* 1 · stop the burger shrinking as a flex item */
  .nav__toggle { flex: 0 0 44px; width: 44px; min-width: 44px; height: 44px; }

  /* 2 · the header wordmark */
  .brand { min-height: 44px; align-items: center; }

  /* 3 · the hero dot's invisible hit box. The dot itself is a 3px
     pill, so the inset carries the whole target: -21px vertical
     puts it at 45px tall, -8px horizontal at 46px wide.

     The 46px was never all reachable. Adjacent dots sit 0.55rem apart,
     so their hit boxes overlap and the sibling on top takes the outer
     pixels — probing with elementFromPoint gave each dot 39px of
     exclusive width, not 46. Widening the gap to 0.875rem puts the
     centres 44px apart, which is what actually makes each dot a 44px
     target. Phone only; the desktop row already probes at 55x45. */
  .hero__dot::after { inset: -21px -8px; }
  .hero__dots { gap: 0.875rem; }

  /* 4 · the contact email over the photograph. The link sits in a
     wrapped flex row of running copy, so it grows vertically only —
     padding it would break the line box it shares with its label. */
  .contactdirect a { position: relative; }
  .contactdirect a::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* 5 · the newsletter field and its submit button */
  .footer__sub input, .footer__sub button { min-height: 46px; }
  .footer__sub button { min-width: 46px; }

  /* 6 · grow the existing footer text-link targets from 24 to 44 */
  .footer a[href^="mailto:"]::after, .footer__bottom a::after { height: 44px; }

  /* 7 · about.html / careers.html / open-roles.html. The breadcrumb
     crumb is 16px and the .creed__go arrow link 24px. Both are text
     links — the crumb shares its line with a slash separator, and
     .creed__go is the last thing in its column, where a min-height
     would open 20px of dead space under the section. Same vertical
     pseudo target as the footer links: the hit box grows, the
     baseline does not move. */
  /* 8 · the header. With the ghost button back in its box there is
     room for "Contact us" on one line — it had been breaking into
     three. Nothing in a 44px-tall header should wrap. */
  .nav__cta .btn { white-space: nowrap; }

  /* 9 · the newsletter form over the contact photograph. Side by
     side at 375px the field came out 141px wide, which shows about
     fourteen characters of an email address — you cannot check what
     you typed. Stacked, both controls get the full column. */
  .newsform { flex-wrap: wrap; }
  .newsform input, .newsform button { flex: 1 0 100%; }

  /* 10 · careers.html's story-rail arrows are 40x40 buttons. These
     are real controls, not running copy, so they simply grow — the
     rail header has room and 44 is the floor. */
  .railbtn { width: 44px; height: 44px; }

  .breadcrumb a, .creed__go { position: relative; }
  .breadcrumb a::after, .creed__go::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }
}

/* ==================================================================
   v67 — 2026-08-13 — the About page, second pass
   ------------------------------------------------------------------
   Client: "about us page is not as per expectations ... it should
   follow the same design style of the homepage ... about us hero
   section also not good ... Our story section also make it a little
   more better ... Who we are section, in the background add the
   infinity from the logo in very light orange one ... Global mindset
   icon is not good ... Global reach section image gradient is not
   good, follow the same style from the hero banner ... in Global
   reach the icon style is different from the home page, not filled,
   make it filled icons."

   Seven items, six of them here (the icons are markup and are done in
   about.html, where each one is commented at the point of change).

   The thread running through all of them is the first sentence of the
   brief: the About page was assembled from components nothing else on
   the site uses -- .chero--editorial, a lone .storycol, an outline
   icon set -- so it did not look like a page of this site. Each rule
   below replaces one of those one-offs with the homepage's own
   component. Nothing new is invented where something already exists.
   ================================================================== */

/* --- 1 · the hero is now the homepage's hero --------------------------
   about.html was moved on to .hero--stage in the markup, so almost
   everything it needs -- the scrim, the white type tiers, the inverted
   buttons, the photograph behaviour -- it already inherits. What is
   left is the difference between a landing hero and an interior one.

   The homepage hero is min-height:100svh because it is the first thing
   a visitor sees and it has three photographs to cycle. An interior
   page has neither excuse: filling the screen before saying anything
   makes the reader scroll to find out they are in the right place. So
   the svh floor comes off and the band is sized by its own copy, with
   a clamp underneath it to stop it collapsing on a wide screen where
   the headline fits on one line. 30rem is roughly the point where the
   photograph still reads as a photograph rather than a strip.

   The 74px in the top padding is the fixed nav, same as .hero--stage:
   this section carries the nav's clearance itself because there is
   nothing above it to do so. */
.hero--interior {
  min-height: clamp(30rem, 66vh, 40rem);
  padding-block: calc(74px + clamp(2.2rem, 5vw, 4rem)) clamp(3rem, 6vw, 4.75rem);
}
@supports not (min-height: 100svh) { .hero--interior { min-height: clamp(30rem, 66vh, 40rem); } }
/* The interior hero has no dots tray at the bottom edge, so the copy
   does not need to hold clear of one, and the headline can take the
   optical centre of the frame. */
.hero--interior .hero__inner { align-self: center; }
/* Two sizes down from the homepage's 4.4rem ceiling. The homepage h1 is
   the loudest thing on the site and should stay that way; an interior
   masthead that matches it flattens the hierarchy between them. */
.hero--interior h1 { font-size: clamp(2.15rem, 4.2vw, 3.4rem); max-width: 17ch; }
.hero--interior p.lead { max-width: 52ch; }

/* The breadcrumb was written for dark ink on white. Over the
   photograph it needs the same two-tier treatment as everything else
   on the scrim: the live link at full white, the current page muted,
   because a crumb that reads at the same weight as its parent is not
   telling you where you are. */
.breadcrumb--onphoto { color: rgba(255, 255, 255, 0.66); }
.breadcrumb--onphoto a { color: rgba(255, 255, 255, 0.94); text-decoration: none; }
.breadcrumb--onphoto a:hover { color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.breadcrumb--onphoto [aria-current] { color: #fff; font-weight: 500; }

/* Three figures on a rule. Deliberately not cards: the client removed
   the frosted figure card from the homepage hero for being one object
   too many in an opening frame, and putting three of them back here
   would be re-adding the thing that was taken out. A hairline and a
   row of numbers is the lightest form the information has.

   The rule is white at 0.22 rather than --line: --line is a warm grey
   mixed for white grounds and disappears entirely on a photograph. */
.herofacts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.6rem, 3.4vw, 3.2rem);
  margin-top: clamp(2.2rem, 4vw, 3rem);
  padding-top: clamp(1.2rem, 2.2vw, 1.6rem);
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  list-style: none;
}
.herofacts b {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.7rem, 2.6vw, 2.15rem);
  line-height: 1;
  color: #fff;
}
.herofacts span {
  display: block;
  margin-top: 0.42rem;
  font-size: 0.79rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.86);
}

@media (max-width: 720px) {
  /* Phone: the picture has less width to be interesting in, so the band
     gets a little more height rather than less, and the facts drop to a
     two-up so the three numbers do not each get 90px and wrap. */
  .hero--interior { min-height: clamp(27rem, 74vh, 34rem); }
  .hero--interior h1 { max-width: none; }
  .herofacts { gap: 1.1rem 1.8rem; }
  .herofacts li { flex: 0 0 calc(50% - 0.9rem); }
}

/* --- 2 · Our story, split ---------------------------------------------
   "Our story section also make it a little more better."

   The 62ch measure was the right decision for a column of running
   prose and it is kept -- .storycol is unchanged. What changed is that
   the column is no longer alone on the row. 5fr/7fr rather than an
   even split: the standfirst is three lines and the rows are three
   paragraphs, so an even split would leave the left column short and
   the right one cramped at the same time.

   The rows are <li> on hairlines, not cards. The brief for this
   section was explicitly "no cards", and the point of the rule here is
   different anyway: a card says "this is a separate thing", a rule
   says "this is the next part of the same argument", which is what
   three consecutive answers about one structure are. */
.storygrid {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: clamp(2.2rem, 5vw, 4.5rem);
  align-items: start;
}
.storystand {
  margin-top: 1.4rem;
  font-size: clamp(1.06rem, 1.35vw, 1.22rem);
  line-height: 1.55;
  color: var(--muted);
  max-width: 34ch;
}
.storyrows { list-style: none; margin: 0; padding: 0; }
.storyrows li {
  padding-block: clamp(1.1rem, 2vw, 1.5rem);
  border-top: 1px solid var(--line);
}
.storyrows li:last-child { border-bottom: 1px solid var(--line); }
.storyrows h3 {
  font-family: var(--font-sans);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.storyrows p {
  margin-top: 0.5rem;
  font-size: 0.96rem;
  line-height: 1.62;
  color: var(--muted);
  max-width: 62ch;
}
/* MOBILE OVERRIDE, per the taste skill: an asymmetric two-column
   layout has to fall back to one strict column below the breakpoint,
   not to two narrow ones. */
@media (max-width: 860px) {
  .storygrid { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .storystand { max-width: 52ch; }
}

/* --- 3 · the logo infinity behind the group diagram --------------------
   "In the background add the infinity from the logo in very light
   orange one."

   Placement first: it is anchored to .barch, not to the section. The
   diagram is a parent mark over a bracket over two cells, which leaves
   the band's lower half open on both sides of the two cells -- that
   gap is where the mark goes, so it fills the hole it was asked to
   decorate. Centred and slightly below middle for the same reason.

   Weight second, and this is the part that is easy to get wrong. The
   band is --warm-50 (#f5f8fd), a near-white, so orange at any normal
   alpha stops being background and becomes a second subject competing
   with a diagram made of thin navy rules. 0.09 is the ceiling that
   still reads as a watermark from a normal viewing distance; the ring
   is drawn as a stroke rather than a fill because the wordmark draws
   it as a stroke, and because a solid lemniscate at any alpha would
   read as a shape sitting behind the cells rather than a mark drawn on
   the paper.

   vector-effect is deliberately NOT set: the stroke is meant to scale
   with the mark, so a wide screen gets a proportionally heavier line,
   which is how the logo behaves. */
.barchfield { position: relative; }
.barchfield > .barch { position: relative; z-index: 1; }
.infinitymark {
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 52%;
  transform: translate(-50%, -50%);
  /* Sized against the diagram, not the section. The drawing measures
     240px tall at 1240; the mark's own ratio is 182:110, so 40rem of
     width comes out at ~387 tall -- half again as tall as what it sits
     behind, which is enough to read as a ground without escaping the
     band. It was 58rem first and that put 56px of orange loop below
     the section's own bottom edge, on to the white section beneath. */
  width: min(40rem, 58%);
  pointer-events: none;
  line-height: 0;
}
.infinitymark svg { display: block; width: 100%; height: auto; overflow: visible; }
/* Opacity on the group, alpha 1 on the stroke -- see the note in the
   markup. 0.11 here reads the same as the 0.09 stroke alpha it
   replaces, because that value was being doubled across a third of
   the mark's area and the eye was averaging the two. */
.infinitymark__loops { opacity: 0.11; }
.infinitymark circle {
  fill: none;
  stroke: var(--accent);
  stroke-width: 15;
}
@media (max-width: 720px) {
  /* On a phone the diagram stacks into a tall single column, so a mark
     centred on it would run behind the type for its whole height. It
     narrows and moves up into the bracket area, which is the one part
     of the stacked diagram that is still mostly empty. */
  .infinitymark { width: 104%; top: 50%; }
  /* Lighter on the phone, and not for taste. The stacked diagram is 360
     tall in a 335 column, so there is no clear ground left to put a mark
     on -- wherever it goes it goes behind type. 0.08 keeps the body copy
     over it at 6.4:1 against --muted, and centring it at 50% means it
     sits behind both cells equally rather than decorating only the
     first one. */
  .infinitymark__loops { opacity: 0.08; }
}
@media print { .infinitymark { display: none; } }

/* --- 4 · the market photographs, on the hero's gradient ----------------
   "Global reach section image gradient is not good, follow the same
   style from the hero banner -- same gradient in the images."

   What was there: a single 196deg blue ramp, i.e. a diagonal bar
   crossing each tile. The hero does not do that, and the difference is
   not decorative. The hero's scrim is two passes with two jobs -- a
   horizontal wash that carries the blue and buys the type its
   contrast, plus a short bottom ramp that stops the last line sitting
   on a bright building. That construction is copied here verbatim,
   which is exactly what was asked for.

   It also fixes the thing that made the diagonal look wrong: a tilted
   gradient measures its stops along the gradient line rather than
   across the tile, so the densest part landed in a corner instead of
   under the label. 90deg puts the density where the words are.

   The tokens are the hero's own --scrim / --scrim-deep rather than
   raw brand hex, so the two surfaces cannot drift apart the next time
   one of them is touched. Alphas are scaled down from the hero's
   0.88/0.48 because a 3:2 tile is a fraction of the hero's area and
   the same numbers would leave nothing of the photograph.

   Contrast is measured, not assumed, and it is measured on the
   brightest pixel behind each glyph -- see the note above the hero
   scrim for why the worst pixel and not the average. */
.markettile::after {
  background:
    linear-gradient(90deg,
      rgba(var(--scrim), 0.72) 0%,
      rgba(var(--scrim), 0.58) 30%,
      rgba(var(--scrim), 0.30) 62%,
      rgba(var(--scrim), 0.12) 100%),
    linear-gradient(to top,
      rgba(var(--scrim-deep), 0.62) 0%,
      rgba(var(--scrim-deep), 0) 42%);
}
/* The label plate stays, for the reason the v58 note records: at 390px
   the tile is short enough that a wrapped label's top line sits above
   the bottom ramp entirely. It is lightened again -- the tile ramp
   underneath it is doing more work now than the diagonal did -- so the
   pair lands in the same place it did before rather than darker. */
.markettile__label::before {
  background: linear-gradient(
    to top,
    rgba(var(--scrim-deep), 0.44) 0%,
    rgba(var(--scrim-deep), 0.38) 78%,
    rgba(var(--scrim-deep), 0.18) 92%,
    rgba(var(--scrim-deep), 0) 100%
  );
}

/* --- 5 · the reach list, now that its icons are filled -----------------
   The three converted icons carry an opacity:.32 backing shape, which
   the outline versions did not. Against the --warm-50 band the badge
   needed no change; the list rows did, slightly -- with the icons
   heavier the 1.1rem gap read as tight. This is a two-pixel judgement,
   documented only so the next person knows it was deliberate. */
.reachlist > li { gap: clamp(0.9rem, 1.6vw, 1.2rem); }


/* ═══════════════════════════════════════════════════════════════════════
   v68 · 2026-08-13 · ABOUT: FOUR CORRECTIONS
   ───────────────────────────────────────────────────────────────────────
   Client, verbatim: "in the about us page in the herobanner dont keep
   exat as homepage lil diffent make it plz, Our story that 3 things amke
   it wigdets use skills floder ui n taste add wigdets with teh icons, Who
   we are section the graph the weatlhdoor group logo remov ethe box to it
   just make it lil big n wealthdoor pravite is lokking lil strached fix
   it in that only lines are not visiable make it visiable, Global reach
   make the iamge lil small"

   Four of the five are composition. One is a real bug -- the stretched
   Private wordmark -- and it was not confined to this page.
   ═════════════════════════════════════════════════════════════════════ */

/* --- 1 · the hero, in the family but not the same frame ---------------
   .hero--stage keeps doing the work: the --brand-900 ground, the white
   display tiers, the inverted primary button, the band's inset and
   radius. .hero--split changes only the composition -- copy on the brand
   ground at left, photograph held in a panel at right, instead of the
   homepage's photograph running full-bleed behind the words.

   The grid is 1fr / 0.86fr rather than even halves. Even halves read as
   a template; the copy column earns the extra because it carries four
   things (breadcrumb, headline, lead, fact rail) against the panel's
   one. */
.hero--split .hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
  gap: clamp(2rem, 4.5vw, 4.5rem);
  align-items: center;
}
.hero--split .hero__copy { max-width: 36rem; }
/* The headline steps down from .hero--interior's 3.4rem ceiling: it is
   in a column roughly half the band now, and 17ch at 3.4rem breaks to
   four lines there. */
.hero--split h1 { font-size: clamp(2.05rem, 3.5vw, 3rem); max-width: 15ch; }
.hero--split p.lead { max-width: 40ch; }

/* The panel. A tall crop, not a square: the picture is a tower, and the
   portrait ratio is also what makes the composition read as deliberate
   rather than as a photo dropped into the right half. */
.hero--split .hero__panel {
  position: relative;
  margin: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 4.5;
  background: var(--brand-900);
  box-shadow: 0 30px 70px -40px rgba(0, 0, 0, 0.65);
}
.hero--split .hero__panel img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: center 42%;
}
/* A light tie back to the ground so the panel is part of the band and
   not a window cut into it. Low alpha -- the photograph is the one thing
   in this hero that is allowed to be bright. */
.hero--split .hero__panel::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(var(--scrim-deep), 0.45) 0%,
    rgba(var(--scrim-deep), 0.06) 46%,
    rgba(var(--scrim-deep), 0) 70%);
  pointer-events: none;
}
/* Without this the left half is flat navy. One off-centre radial, one
   light source, no second object. It sits under .hero__inner (z-index 2
   on .hero--stage) and over the section background. */
.hero--split .hero__wash {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(115% 85% at 8% 18%, rgba(36, 56, 201, 0.5) 0%, rgba(36, 56, 201, 0) 62%),
    radial-gradient(80% 60% at 96% 96%, rgba(36, 56, 201, 0.26) 0%, rgba(36, 56, 201, 0) 70%);
}

/* Below 900 the two columns stack. The panel goes second -- the words
   are what the reader came for, and a tall photograph at the top of a
   phone screen pushes the headline under the fold. It also loses the
   portrait ratio there, because a 4:4.5 crop on a 375 screen is 420px
   of picture. */
@media (max-width: 900px) {
  .hero--split .hero__inner { grid-template-columns: minmax(0, 1fr); gap: clamp(1.8rem, 5vw, 2.6rem); }
  .hero--split .hero__copy { max-width: none; }
  .hero--split h1 { max-width: 14ch; }
  .hero--split .hero__panel { aspect-ratio: 16 / 10; }
  .hero--split .hero__wash {
    background: radial-gradient(120% 60% at 20% 0%, rgba(36, 56, 201, 0.5) 0%, rgba(36, 56, 201, 0) 68%);
  }
}

/* --- 2 · Our story, as widgets ----------------------------------------
   The rows were hairline-separated text. As cards they carry a badge
   each, which is the whole point of the request -- but a card is only
   worth its border if it is holding something, so the icon is what
   justifies the box, not the other way round.

   The old .storyrows li border-top/bottom at v67 is superseded, not
   deleted: it is above this block, so this wins on order. */
.storyrows { display: grid; gap: clamp(0.7rem, 1.3vw, 0.95rem); }
.storyrows li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.85rem, 1.6vw, 1.1rem);
  align-items: start;
  padding: clamp(1.1rem, 2vw, 1.4rem);
  background: var(--n-0);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  transition: transform 0.22s var(--ease), box-shadow 0.22s var(--ease), border-color 0.22s var(--ease);
}
/* Kills v67's rules rather than editing them in place. */
.storyrows li,
.storyrows li:last-child { border-top-color: var(--line); border-bottom-color: var(--line); }
.storyrows li:hover {
  transform: translateY(-2px);
  border-color: var(--warm-line);
  box-shadow: 0 12px 32px -20px rgba(17, 21, 25, 0.32);
}
@media (prefers-reduced-motion: reduce) { .storyrows li:hover { transform: none; } }
.storyrows h3 { margin-top: 0.12rem; }
.storyrows p { max-width: 56ch; }

/* --- 3 · the group diagram --------------------------------------------
   (a) The parent pill is removed. It was a border drawn around a logo
       that has its own silhouette, and it was holding the wordmark down
       to 22px to keep the pill from swelling. 34px is the size the mark
       reads at once nothing is boxing it, and it now sits clearly above
       the 24px children instead of level with them. */
.barch--drawn .barch__parent {
  background: none;
  border: 0;
  padding: 0;
  border-radius: 0;
}
.barch--drawn .barch__parent img { height: 34px; }
.barch--drawn .barch__parentdesc { margin-top: 0.44rem; }

/*  (b) The connectors. --warm-line is #dde5f3 against a #f4f5f7 band --
       a 1.06:1 hairline, which is to say invisible, which is exactly what
       the client saw. The diagram's entire claim is that a parent has two
       children, and it was drawing that claim in a colour the band ate.

       #8b96b0 measures 2.5:1 against the band. That is short of the 3:1
       WCAG floor for a graphical object, so the relationship is not left
       to the line alone -- the layout states it too -- but it is four
       times the delta it had, and going darker starts to read as a table
       rule rather than a drawn connector. Weight goes to 1.5px for the
       same reason: visibility bought with size costs less than visibility
       bought with contrast. */
.barch--drawn .barch__stem { width: 1.5px; height: 30px; background: #8b96b0; }
.barch--drawn .barch__bracket {
  border-left-width: 1.5px;
  border-right-width: 1.5px;
  border-top-width: 1.5px;
  border-color: #8b96b0;
}
.band--warm .barch--drawn .barch__stem { background: #8b96b0; }
.band--warm .barch--drawn .barch__bracket { border-color: #8b96b0; }

/*  (c) The stretched Private wordmark -- a real bug, and not only here.

       .wdlock is a flex column with align-items:stretch, so the mark was
       stretched to the width of the widest child. That child is
       .wdlock__desc, and "PRIVATE CLIENT" at 0.42em tracking is 104px
       wide. The img has height:24px and width:auto, so auto resolved to
       the stretched cross size and the aspect-ratio could not save it:
       measured 104x24 = 4.335 against the file's true 3.028.

       It only ever showed here, which is why it lasted. Stretch is a
       no-op wherever the descriptor is narrower than the mark, and it is
       in both other lockups -- the footer's is "PRIVATE" at 46.5 against
       a 60.5 mark, and the brand card sets the mark to width:100% with
       height:auto, so the ratio comes off the aspect-ratio either way.
       "PRIVATE CLIENT" is the only descriptor long enough to win the
       stretch. Measured on index.html after the fix: footer 60.5x20 and
       brand card 131.7x43.5, both at 3.027, both unchanged.

       align-self:center takes the mark out of the stretch and it draws at
       its own ratio again. */
.wdlock__mark { align-self: center; }
/* The descriptor is now the wider of the two, so it gets pulled in to
   sit under the wordmark rather than out past it. */
.barch__cell .wdlock__desc { letter-spacing: 0.26em; text-indent: 0.26em; font-size: 0.55rem; }

/* --- 4 · Global reach, smaller picture --------------------------------
   Was 1fr / 1.05fr with the tiles at 3:2 -- the panel was the wider
   column and the two stacked tiles ran 747px against a 770px list, so
   the pictures were setting the height of the section.

   1.12 / 0.88 with a 16:10 crop takes roughly a third off the panel and
   hands the room to the four points, which are the argument the section
   is actually making. The tiles keep one shared ratio, so neither market
   is the small one -- that constraint from v58 is not what changed. */
.reach { grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr); align-items: start; }
.reachpanel--duo .markettile { aspect-ratio: 16 / 10; }
@media (max-width: 940px) {
  /* Stacked, "smaller" stops meaning a narrower column and starts
     meaning a shorter one, and the panel is capped so two tiles do not
     become a second full screen under the list. */
  .reach { grid-template-columns: minmax(0, 1fr); }
  .reachpanel--duo { max-width: 34rem; }
}

/*  (d) Follow-on from (c), measured after the stretch was fixed. At its
       true ratio the Private wordmark is 72.7px wide and the descriptor
       under it was 101.3 -- the label was half again wider than the mark
       it labels, which is the same imbalance the stretch had been hiding.

       Two moves, not one: the descriptor tightens from 0.26em to 0.17em,
       and the mark goes 24px -> 30px. Tracking alone could not close it
       (0.05em would be needed, at which point it stops reading as a
       letterspaced descriptor), and size alone would leave the mark
       overhanging. They meet at roughly 91px each.

       The row track has to grow with it. .barch__cell is a 2.6rem/auto
       grid so both cells' role copy starts on the same line; a 30px mark
       plus its descriptor is 44px and would have pushed one column's
       copy down a line on its own. */
.barch--drawn .barch__cell .wdlock__mark { height: 30px; }
.barch--drawn .barch__cell .wdlock__desc { font-size: 0.56rem; letter-spacing: 0.17em; text-indent: 0.17em; }
.barch--drawn .barch__cell { grid-template-rows: 3.1rem auto; }

/*  (e) And the alignment that (d) exposed. .barch__cell is a two-row grid
       so both columns' role copy starts on the same line -- that is what
       the track was added for at v49 -- but the cell also sets
       align-items:center, which centres each role in the auto track.
       The two roles are three lines and two lines, so they were starting
       10px apart and the track was doing nothing. It reads as a wobble
       between the two brands rather than as a mistake, which is why it
       survived this long. */
.barch--drawn .barch__role { align-self: start; }

/* ─────────────────────────────────────────────────────────────────────────
   v58 · 2026-08-13 · About hero: client artwork in place of the blue

   Client, 2026-08-13: use the supplied wave artwork as the about hero
   background "instite of the blue color".

   The artwork is near-white -- it measures 225-255 R, 227-255 G, 236-255 B,
   so its darkest pixel is still lighter than --soft. Every piece of type in
   this hero was white on navy (headline, lead, breadcrumb, the three
   herofacts, and a white-filled primary button, all set by the .hero--stage
   rules from line 1159). Dropping the artwork in without touching the type
   would have left a hero that is legibly blank. So this is not a background
   swap, it is an inversion: the artwork goes in and the whole hero flips to
   dark type on light.

   Everything is scoped to .hero--stage.hero--interior, two classes, which
   clears the single-class .hero--stage background at line 1987 without
   touching it. That matters -- index.html shares .hero--stage and must stay
   navy. .hero--interior, .hero--split, .hero__wash, .hero__panel,
   .herofacts and .breadcrumb--onphoto are about.html only, so the rest of
   the block is safe by construction.

   Three specific decisions:

   - the blue radial .hero__wash is switched off rather than recoloured.
     It exists to lift a flat navy field; over artwork that already has its
     own movement it only muddies the waves.

   - the primary button goes back to the ordinary blue fill. .hero--stage
     inverts it to white-on-navy (line 1227) because it sits on a dark
     stage; on white that button is a white rectangle. Returning it to
     var(--brand) also puts this hero back inside the "all CTAs blue" rule,
     which the homepage hero still has to break for contrast reasons.

   - the card gets a hairline. --paper is #ffffff and .hero--stage is an
     inset rounded card, so a near-white hero on a white page has no edge
     at all. One --line border is what makes it read as a panel.

   Contrast. There is no scrim between the type and the image here, so the
   floor is set by the single darkest pixel under each glyph box -- not the
   average, and not the lightest. The artwork was mapped through its own
   center/cover box at both breakpoints (desktop paints it 1297x730 with a
   -70px x-offset; mobile scales it to 1572 wide and shows the middle 374)
   and the minimum-luminance pixel taken under each text box, +6px for
   antialiasing bleed:

                            desktop 1280   mobile 390   floor
     h1.display                 14.38          18.18     3.0
     h1 .mute                    6.67              -     3.0
     .lead                       9.59           9.41     4.5
     .breadcrumb--onphoto        6.08           7.47     4.5
     .herofacts b               17.42          16.53     3.0
     .herofacts span             7.28           6.85     4.5

   Binding case is the breadcrumb at 6.08:1, 35% clear of its floor. The
   darkest pixel anywhere in the visible desktop crop is rgb(227,227,236),
   which is 5.90:1 even against --muted, the lightest ink on the page. All
   of that is a property of THIS file: swap the artwork and re-measure.
   ───────────────────────────────────────────────────────────────────────── */
.hero--stage.hero--interior {
  background: #fff url("../img/about-hero-wave.jpg") center / cover no-repeat;
  color: var(--ink);
  border: 1px solid var(--line);
}
.hero--stage.hero--interior .hero__wash { background: none; }
.hero--stage.hero--interior .hero__inner { border-inline-color: var(--line); }

.hero--stage.hero--interior h1 { color: var(--ink); }
.hero--stage.hero--interior h1 .mute { color: var(--muted); }
.hero--stage.hero--interior p.lead { color: var(--ink-soft); }

.hero--stage.hero--interior .breadcrumb--onphoto { color: var(--muted); }
.hero--stage.hero--interior .breadcrumb--onphoto a { color: var(--ink-soft); }
.hero--stage.hero--interior .breadcrumb--onphoto a:hover { color: var(--brand-700); }
.hero--stage.hero--interior .breadcrumb--onphoto [aria-current] { color: var(--ink); }

.hero--stage.hero--interior .herofacts { border-top-color: var(--line); }
.hero--stage.hero--interior .herofacts b { color: var(--ink); }
.hero--stage.hero--interior .herofacts span { color: var(--muted); }

.hero--stage.hero--interior .btn--primary {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}
.hero--stage.hero--interior .btn--primary:hover {
  background: var(--brand-600);
  border-color: var(--brand-600);
}
.hero--stage.hero--interior .btn:focus-visible { outline-color: var(--brand-700); }

/* ═════════════════════════════════════════════════════════════════════════
   v59 · 2026-08-13 · #values: the slot changes shape to fit the picture

   Client, 2026-08-13: use the supplied blocks-and-pawn still life in
   #values "replace with the exsting image".

   The outgoing values-light.jpg was 1300x1950, a 2:3 portrait, and
   .valshot was built around it at aspect-ratio 4/5. The new picture is
   1448x1086, a 4:3 landscape, and -- this is the part that forced a CSS
   change rather than a one-line src swap -- its meaning is horizontal.
   It reads left to right: five upright blocks, the blue pawn, then the
   toppling row arrested against it. Under object-fit: cover a 4:3 image
   in a 4:5 box keeps only 60% of its width, 290px cut off each side. The
   left cut takes the first standing block whole; the right cut takes the
   last falling one. Both ends of the sentence, gone, leaving a pawn and
   some blocks with no before and no after.

   So the box was refitted to the picture. 4/3 is the source ratio exactly
   -- zero crop on desktop.

   This also fixes a proportion the portrait slot had always had. At a
   1161px viewport the copy column is 288px tall and the figure was 565:
   the picture was running nearly twice the height of the thing it was
   meant to sit beside, and .valsplit centres them, so the section was a
   short paragraph floating against a tall slab. At 4/3 the same column
   gives 339px against the copy's 288. They now read as a pair.

   The mobile ratio is re-declared, not inherited. The 16/10 rule lives in
   a max-width query earlier in the file; a bare .valshot here would be
   later in source order at equal specificity and would beat it at every
   width. 16/10 against a 4:3 source crops 91px off the top and bottom --
   blank wall above, bare floor below, blocks untouched (they run y470 to
   y870 of 1086). Checked, not assumed.

   Nothing else in this section needed touching. .valshot__pat and
   .glasschip were already flipped light-first in an earlier round -- ink
   hairlines at 0.07 and a white bottom ramp instead of the original navy
   -- which is the right treatment for a near-white photograph and is why
   the caption still reads over it.
   ───────────────────────────────────────────────────────────────────────── */
.valshot { aspect-ratio: 4 / 3; }

/* Mobile: the caption comes off the picture.

   The 16/10 mobile slot was fine for the atrium, which had no subject and
   could lose its bottom half to a caption without losing anything. This
   picture cannot. At 390px the slot is 350x219 and the glass chip is 96px
   tall -- 44% of the frame, sitting exactly where the blocks and the pawn
   are. Measured on screen: the chip covered from 51% to 95% of the figure
   height, leaving the tops of the blocks and a sliver of the pawn's head.
   The picture was unreadable, which is a worse outcome than the atrium
   ever had because the atrium was not saying anything specific.

   Two ways out: make the frame taller, or move the caption. Taller does
   not work -- even at 4/3 the chip still lands across the blocks. So the
   caption goes below the picture and stops being glass at all: on a phone
   there is no reason to float type over a photograph when there is a whole
   column underneath it. .valshot drops its ratio and becomes an ordinary
   block that grows to fit both children; the shadow and the radius move
   from the figure to the image so the caption is not inside the card; and
   .valshot__pat is pinned to the image's box with inset/aspect-ratio so it
   cannot spill over the caption. The pat's bottom ramp is dropped with it
   -- that ramp existed only to seat the chip -- and the hairline grid,
   which is the part that ties this frame to the tiles below, stays. */
@media (max-width: 900px) {
  .valshot {
    aspect-ratio: auto;
    overflow: visible;
    border-radius: 0;
    box-shadow: none;
  }
  .valshot img {
    aspect-ratio: 4 / 3;
    height: auto;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
  }
  .valshot__pat {
    inset: 0 0 auto 0;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-lg);
    background-image:
      linear-gradient(rgba(17, 21, 25, 0.07) 1px, transparent 1px),
      linear-gradient(90deg, rgba(17, 21, 25, 0.07) 1px, transparent 1px);
    background-size: 46px 46px, 46px 46px;
  }
  .glasschip {
    position: static;
    margin-top: 0.95rem;
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* ======================================================================
   v60 · 2026-08-13 · two client photographs, and the story column
   centred
   ----------------------------------------------------------------------
   Client: "add this image in the Who we are section replace with the
   existing one n also update the image in the career section ... in the
   about us page our story that section make the left content in the
   middle to the widgets on the right"

   1 · #who-we-are and #careers both took a landscape photograph into a
   near-square slot. .imgslot--who was 4/4.2 (0.95) and .imgslot--tall
   was 1/1.06 (0.94); the pictures are 1.54 and 1.50. object-fit: cover
   therefore kept 62% and 63% of their width -- a 19% bite out of each
   side. Measured against the actual frames that is not trimming
   background: the boardroom shot lost the near woman down to one hand
   and cut the far man through the face, and the desk still life lost
   the mug on one side and the laptop on the other, which is most of
   what makes it an arrangement.

   Same call as .valshot in v59: the slot moves, not the picture. Each
   goes to the shape the photograph already is --

     .imgslot--who   4/3  keeps 87% of 1556x1011 (all four people whole)
     .imgslot--tall  3/2  keeps 100% of 1536x1024 (exactly its ratio)

   Both slots are used once each, on index.html, so neither ratio is
   load-bearing anywhere else -- grep before reusing these classes.

   The mobile rule is restated here on purpose. Below 900px both slots
   already dropped to the .imgslot base 4/3.05, which is 1.31 and would
   crop the desk again; .imgslot--tall keeps 3/2 the whole way down. The
   restatement is also what stops a source-order accident: these bare
   single-class rules sit at the end of the file and would otherwise
   beat the earlier @media at every width.

   2 · .storygrid was align-items: start, so the three-line standfirst
   sat at the top of a column the height of three widgets and left a
   long drop of white under it. Centring is only meaningful while there
   are two columns, so it is scoped above the 860px fallback. */
.imgslot--who { aspect-ratio: 4 / 3; }
.imgslot--tall { aspect-ratio: 3 / 2; }

@media (max-width: 900px) {
  .imgslot--who { aspect-ratio: 4 / 3; }
  .imgslot--tall { aspect-ratio: 3 / 2; }
}

@media (min-width: 861px) {
  .storygrid { align-items: center; }
}


/* ======================================================================
   v61 · 2026-08-13 · THE CAREERS PAGE, RECOMPOSED
   ----------------------------------------------------------------------
   Client: "remove this section - Voices of the firm from the career page
   - n make the career page better ... hero section n How we work n Why
   we're here in this reduce the content n Life at Wealthdoor use skills
   to make it better, taste skills n ui skills"

   Design read: a careers page for a regulated wealth manager has to read
   like an employer of consequence, not a startup. Light, editorial, one
   idea per screen, and short enough that a candidate skimming on a phone
   gets the whole argument in three scrolls. Dials, from the taste skill's
   own table for a trust-first regulated brief in "redesign, preserve"
   mode: variance 4, motion 3, density 4. Nothing here changes the page's
   information architecture, its anchors or its voice.

   1 · HERO. The opening stack was five text elements deep: eyebrow,
   headline, lead, button, and a three-item proof strip wedged under the
   button at 0.86rem. Four is the limit and a proof strip is the one
   thing that is not allowed to be the fifth. The three facts are not
   the problem, their position is, so they come out of the copy column
   and run the full width of the page under a rule, where they read as
   the base the hero stands on rather than something stuck to the
   headline. Same three facts, same icons, one size up.

   .herochips / .herochip keep their rules for now and are unused, the
   same way .chero__ring has been since v45.

   2 · WHY WE'RE HERE. Copy cut from 77 words to 30 and from two
   paragraphs to one, which is what the client asked for. The picture
   also swaps sides: the hero is copy-left picture-right and so was
   this, so the first two things a reader met had the same shape.
   .split--flip already handles the mobile order, sending the picture
   back below the copy under 900px.

   3 · HOW WE WORK. Five equal cards in one row is the shape that gave
   each standard a 120px column at 1400px and broke every description
   over four ragged centred lines. Five is also where a card grid stops
   being a grid and starts being a list in boxes. It is now a list: one
   numbered row each, full width, hairline between, left aligned, at a
   size a person reads rather than scans. Numerals are drawn from an
   <ol> so the count survives with the figures hidden from the reader.

   Measured at 1400px: description column 700px, every row one or two
   lines, none of them ragged.

   4 · LIFE AT WEALTHDOOR. Kept as three columns, since it is now the
   only N-across block on the page, but the type was set for a card
   (0.87rem body, 1.06rem heading) and it has not been in a card since
   v45. Both go up a step and the columns get air.

   5 · EYEBROWS. Four of six sections carried a .seclabel. When every
   section is announced the announcement stops meaning anything. Two are
   left, the hero and "How we work", the one section whose heading does
   not name itself. Both dropped sections keep their headings, their ids
   and their places in the menu.
   ---------------------------------------------------------------------- */

/* --- 1 · HERO -------------------------------------------------------- */
.chero__cta { margin-top: 2rem; }

/* Named .cheroband, not .herofacts. .herofacts already exists, on
   about.html's interior hero, where it sits on a photograph and sets
   its span in rgba(255,255,255,.86). Built under the obvious name this
   strip inherited that rule and drew three white icons on three
   near-white badges: present, sized, invisible. Same failure as the
   filled icons in v42, found the same way, by reading the computed
   colour rather than trusting the screenshot. */
.cheroband {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  margin: clamp(3rem, 5.5vw, 4.5rem) 0 0;
  padding: clamp(1.5rem, 2.4vw, 2rem) 0 0;
  border-top: 1px solid var(--line);
  list-style: none;
}
.cheroband__item {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0 clamp(1.2rem, 2.6vw, 2.2rem);
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--muted);
}
.cheroband__item:first-child { padding-left: 0; }
.cheroband__item + .cheroband__item { border-left: 1px solid var(--line); }
.cheroband__item .ibadge { flex: none; }
.cheroband__item strong { display: block; font-weight: 600; color: var(--ink); }

/* --- 2 · WHY WE'RE HERE ---------------------------------------------- */
/* The inline margins these three carried went with the eyebrow that
   used to set the top of the column. */
.whycopy .h2 { margin-top: 0; }
.whycopy p.body { margin-top: 1.4rem; }
.whycopy .creed__go { margin-top: 1.7rem; }

/* --- 3 · HOW WE WORK ------------------------------------------------- */
.stdlist {
  margin: clamp(2.4rem, 3.8vw, 3.2rem) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--warm-line);
}
.stdrow {
  display: grid;
  grid-template-columns: 4rem minmax(0, 17rem) minmax(0, 1fr);
  align-items: baseline;
  gap: 0 clamp(1rem, 2.4vw, 2rem);
  padding: clamp(1.15rem, 2vw, 1.6rem) 0;
  border-bottom: 1px solid var(--warm-line);
}
/* The figure is the quiet part. It is the same brand blue as the row
   heading at a fifth of the weight, so it indexes the list without
   competing with the words next to it. */
.stdrow__n {
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 1.2vw, 1.05rem);
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--brand);
  opacity: 0.5;
  font-variant-numeric: tabular-nums;
}
.stdrow__t {
  font-family: var(--font-display);
  font-size: clamp(1.14rem, 1.5vw, 1.32rem);
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
}
.stdrow__d {
  font-size: clamp(0.97rem, 1.15vw, 1.05rem);
  line-height: 1.6;
  color: var(--muted);
}

@media (max-width: 860px) {
  /* Three columns in a 700px row leaves the description 260px, which is
     narrower than it was in the cards this replaced. Below that the row
     folds: figure and heading on one line, description under both. */
  .stdrow {
    grid-template-columns: 2.6rem minmax(0, 1fr);
    row-gap: 0.45rem;
  }
  .stdrow__d { grid-column: 2; }
}

/* --- 4 · LIFE AT WEALTHDOOR ------------------------------------------ */
.lifehead p.body { margin-top: 1.3rem; }
.careerspg .lifecols { margin-top: clamp(2.6rem, 4vw, 3.4rem); }
.careerspg .lifecol h3 { font-size: clamp(1.1rem, 1.4vw, 1.22rem); margin-top: 1.2rem; }
.careerspg .lifecol p {
  margin-top: 0.75rem;
  font-size: clamp(0.95rem, 1.1vw, 1.02rem);
  line-height: 1.62;
}

/* --- 5 · THE TWO GRIDS THAT DID NOT FOLD ----------------------------- */
/* Both of these were three fixed-share columns with no lower bound, so
   on a 375px phone they each computed to three 112px cells. Measured,
   not guessed: at 375 "In every decision." needs 128px and "Wide scope.
   Real impact." needs 143px, so neither fits and both were running to
   three and four lines.

   .cheroband is mine, from item 1 above: it replaced .herochips, which
   had its own stacking rules at the media queries near line 8244, and I
   did not carry them across. Same shape as those: three across only
   where each cell has room for a line of text, stacked below, with the
   hairline moving from the left edge to the top. */
@media (max-width: 760px) {
  .cheroband {
    grid-template-columns: minmax(0, 1fr);
    margin-top: clamp(2.2rem, 6vw, 3rem);
  }
  .cheroband__item { padding: 0; }
  .cheroband__item + .cheroband__item {
    border-left: 0;
    border-top: 1px solid var(--line);
    margin-top: 1.05rem;
    padding-top: 1.05rem;
  }
}

/* .careerspg .lifecols is not mine and predates this round: the rule
   near line 4881 sets three columns with no media query, so it beats
   both `@media (max-width: 620px)` and the `@media (max-width: 760px)`
   block that already switches .lifecol's border from left to top and
   drops its padding. Only the track list needed overriding; the rest
   of that block was already correct and already applying. */
@media (max-width: 760px) {
  .careerspg .lifecols { grid-template-columns: minmax(0, 1fr); }
}

/* Same grid, second half of the same fault. Below 1020 the base rule at
   line 4307 pulls the last column out to `grid-column: 1 / -1`, which is
   right for the homepage's two-up but wrong here, where the careers
   override keeps three tracks: between 761 and 1020 the section drew two
   columns and then a full-width third. Three fit down to 760, where the
   rule above stacks them, so the span comes off. */
@media (max-width: 1020px) {
  .careerspg .lifecol:last-child { grid-column: auto; }
}

/* --- 6 · AND THE SPLIT, WHICH NEVER STACKED -------------------------- */
/* Third of the same kind, found while checking the two above on a phone.
   The careers override of .split--wide at line 4887 carries no media
   query either, so it beat `@media (max-width: 900px) { .split--wide {
   1fr } }` and #why-us stayed two columns all the way down: at 375 the
   paragraph was setting in a 160px column beside a 160px photograph and
   ran to eleven lines. 900 is the base breakpoint and the one where
   .split--flip already flips its order, so the copy leads once stacked. */
@media (max-width: 900px) {
  .careerspg .split--wide { grid-template-columns: minmax(0, 1fr); }
}

/* =====================================================================
   v69 · 2026-08-13 · A ROUND OF CLIENT CORRECTIONS
   Nine instructions in one message. Four of them are CSS and they are
   all subtractive: two blue rules, one drop shadow, one missing gap.
   ===================================================================== */

/* --- 1 · THE TWO BLUE TOP EDGES ------------------------------------- */
/* Client: "in the Fiduciary first widget remove the blue colour on top
   edge" and "Client first wigdet remove the blue colour from top from
   that widget". Same device on two pages: a 3px brand gradient struck
   across the top of whichever tile leads its bento, added in v64 as the
   last saturated blue left after the lead tiles went from navy fields to
   paper. Both come off.

   What still marks the lead tile once the rule is gone: it is wider than
   its neighbours, its heading is a step larger, its paragraph is a step
   larger, and it carries the blue-cast wash and the ring pattern that
   the others do not. The rule was the loudest of those signals, not the
   only one, so the hierarchy survives it.

   display:none rather than deleting the v64 and v66 blocks, because
   those blocks carry the reasoning for the whole tile treatment and the
   ::after is four lines inside them. */
.whytile--lead::after,
.valtile--lead::after { display: none; }

/* --- 2 · THE GLOBAL REACH PANEL LOSES ITS SHADOW -------------------- */
/* Client: "Global reach this section there is a image remove the shadow
   for that". The two market photographs carry no shadow themselves; the
   one under them belongs to .reachpanel, the glass box they sit in, set
   at the base rule near line 1729. Off on both pages -- the homepage
   #global and about.html#global-reach are the same component, and a
   shadow on one and not the other would read as a mistake.

   The 1px --line border stays. It is what separates the panel from the
   band behind it now that the shadow does not, and on about.html the
   panel sits on --warm and needs the edge. */
.reachpanel { box-shadow: none; }

/* --- 3 · AN ICON INSIDE A BUTTON ------------------------------------ */
/* New, for the closer on the homepage #why: the headset used to be a
   40px .ibadge above the button and is now inside it. Sized in em, not
   rem, so it tracks the button it is in -- .btn is 0.92rem and .btn--lg
   steps up from there, and an icon that did not follow would read as
   pasted on at one of the two sizes.

   1.15em against the label's cap height sits the glyph slightly proud
   of the type, which is what stops it reading as a punctuation mark.
   flex:none because .btn is a flex row and the label should take the
   slack, not the icon. */
.btn__ico { display: inline-flex; flex: none; align-items: center; }
.btn__ico .ico { width: 1.15em; height: 1.15em; }

/* --- 4 · THE GAP THAT WAS NEVER THERE ------------------------------- */
/* Client: "Wealthdoor Group / About ... b/w this lines there is no space
   add some space". Measured, not guessed: the gap was 0.00px. .breadcrumb
   carries no margin-bottom and .display no margin-top, so the headline
   set directly on the breadcrumb's line box.

   1.1rem is 17.6px, which is exactly the gap .seclabel already opens
   above every section heading on this page -- so the hero eyebrow now
   sits at the same distance from its headline as every other eyebrow on
   the site, rather than at a number picked to look right. */
.hero__copy .breadcrumb { margin-bottom: 1.1rem; }

/* --- 5 · .infinitymark IS NOW UNUSED -------------------------------- */
/* The mark was removed from about.html#who-we-are on the client's
   instruction and nothing else in the site draws it. Its rules near line
   9015, and .barchfield with them, are dead as of this version. Left in
   place under the same convention as .rail, .voicecard and .herochips:
   this file keeps retired blocks until a cleanup pass takes them all
   together, so that one round's deletion does not silently break a
   component another round is about to bring back. */

/* =====================================================================
   v70 · 2026-08-13 · THE LONE SITE BUTTON GOES FULL WIDTH
   "in the Our brands wealthdoor private widget button bottom
   wealthdoor.in full size widget."

   .brandcard__sites has been a 1fr 1fr grid since v37, because both
   cards used to carry two buttons and the point was that all four came
   out the same width. Deleting the wealthdoor.us pill earlier today
   left the Wealthdoor card with one button sitting in the left column
   and 243px of empty grid beside it at 1280 -- a half-width button
   under a full-width paragraph, which reads as a button that failed to
   load rather than as a deliberate single destination.

   :only-child rather than a modifier class on the card, for two
   reasons. It needs no markup, and it maintains itself: if the brand
   ever gets a second client site back, the second pill arrives and the
   rule stops applying on its own, with the pair returning to equal
   halves without anyone remembering to take a class off.

   The Nestvest card is untouched -- two children, so no only-child --
   and under 420px the grid is already one column, where the rule is a
   no-op because 1 / -1 is the only column there is. */
.brandcard__sites > .sitepill:only-child { grid-column: 1 / -1; }

/* =====================================================================
   v71 · 2026-08-14 · TWO RETIREMENTS, NO NEW RULES

   #why lost its .splithead. The client asked for the supporting line to
   sit "just below the headline", so the section head is a .sechead now,
   which is what Our brands and Global perspective already use: label,
   h2, lead, all on the same left margin. Nothing new was needed in CSS
   because .sechead already carries the 0.75rem / 1rem rhythm.

   That leaves these two rules matching nothing:

       #why .splithead        { align-items: start; }
       #why .splithead__aside { padding-bottom: 0; }

   They are kept above at 7456, per this file's convention of retiring
   dead rules in place rather than deleting them, so the next person can
   see that the section used to have a two-column head and why it does
   not any more. .splithead itself is still live on about.html and is
   not dead code.

   The footer's mail glyph also changed, but only in the HTML: the solid
   envelope has been replaced with the duotone one already used by the
   "Get in touch" row twenty lines below it in the same footer. Nothing
   in CSS distinguishes the two, so there is no rule here. */

/* =====================================================================
   v72 · 2026-08-14 · THE SUBSCRIBE ARROW WAS WHITE ON WHITE

   "in the fotter Stay informed part in the text input box there is no
   arrow visiable."

   It was there the whole time, painted white at 50% on a white button.
   The culprit is 40 lines up:

       .footer__col span { display: block; color: rgba(255,255,255,.5);
                           font-size: .9rem; padding-block: .32rem; }

   written for label spans in the footer's link columns. Those spans are
   gone -- swept through the rewrites of the last fortnight -- and the
   only element on any of the four pages that still matches that
   selector is <span class="arrow"> inside the newsletter submit button,
   which happens to live inside a .footer__col. So a rule that means
   nothing to the design was setting the colour, the size and the
   display mode of the one glyph it could still reach, and setting them
   all wrong: white on the white button, block-level inside a button
   with no alignment, and 0.32rem of padding-block stretching a 14px
   glyph into a 25px box sat 8px from the top.

   Two rules rather than one deletion. The .footer__col span rule is
   left where it is, per this file's habit of retiring rules in place,
   and the button states what it wants instead. This also survives
   someone putting a span back into a footer column later.

   Contrast measured on the result: --brand-900 on #fff is 17.4:1. The
   placeholder next to it was checked at the same time and left alone --
   rgba(255,255,255,.52) composited over the field's own translucent
   ground is 4.84:1 against it, which passes. */
.footer__sub button { display: flex; align-items: center; justify-content: center; font-family: inherit; }
.footer__sub button .arrow {
  display: inline; color: inherit; font-size: 1.05rem; line-height: 1; padding-block: 0;
}

/* ======================================================================
   v73 · 2026-08-15 · careers.html: the hero banner, and How we work
   becomes widgets
   ----------------------------------------------------------------------
   Client: "make the carrer page better the herobanner ... make the
   better of the how it works also ... make this part better in the
   carrer page make it widget types."

   1 · HERO. Four changes, none of them to the composition. The arch
   stays on the right, the copy stays on the left, because that shape is
   what about.html and this page share and one of the two is not worth
   breaking for novelty.

     a. Top padding. It ran to 9.75rem at the top of the ramp. Under a
        74px fixed nav that pushes the eyebrow 230px down a 800px
        viewport, and the hero then reads as content that has slipped
        rather than content that has been given room. 8.5rem is the new
        ceiling. Scoped to .careerspg so about.html's hero, which has a
        breadcrumb above the eyebrow and needs the extra, is untouched.

     b. Headline. 3.7rem to 4rem at the top of the ramp, with the
        tracking pulled in a step. Five words over two lines carries the
        larger size; this was measured before it was changed, and the
        line count does not move at 1280, 1024 or 375.

     c. Lead measure. It was capped at 34ch, which set a 19-word
        sentence over four lines in a column with room for three. 46ch.

     d. The button row. It is a row now, so it needs to be a flex line
        that wraps rather than two inline-blocks that touch.

   2 · HOW WE WORK. .stdlist / .stdrow, the numbered rows this replaces,
   are left in the file below with the rest of the retired rules. They
   are no longer matched by any page.

   The grid is six columns so that three-across and two-across can share
   it: the first three tiles take two columns each, the last two take
   three each. Five cells, five standards, nothing padded. The two wide
   tiles run their heading and description side by side, which is the
   only structural difference between them and the narrow three -- same
   fill, same hairline, same radius, same hover.
   ---------------------------------------------------------------------- */

/* --- 1 · HERO -------------------------------------------------------- */
.careerspg .chero { padding-top: clamp(6.75rem, 9vw, 8.5rem); }
.careerspg .chero__copy h1 {
  font-size: clamp(2.6rem, 4.7vw, 4rem);
  letter-spacing: -0.022em;
}
.careerspg .chero__lead { max-width: 46ch; }
.chero__cta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem; }

/* --- 2 · HOW WE WORK ------------------------------------------------- */
.stdgrid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(0.9rem, 1.5vw, 1.3rem);
  margin: clamp(2.4rem, 3.8vw, 3.2rem) 0 0;
  padding: 0;
  list-style: none;
}
.stdtile {
  grid-column: span 2;
  display: flex;
  flex-direction: column;
  gap: 0.95rem;
  padding: clamp(1.5rem, 2.3vw, 2rem);
  border-radius: var(--radius-lg);
  background: var(--warm-50);
  border: 1px solid var(--warm-line);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}
/* On the tinted band the tile goes white, the same way .whycard and
   .valuecard do a few thousand lines up. Written out rather than added
   to that selector list so the list keeps meaning "the cards that were
   there in v29". */
.band--warm .stdtile { background: var(--n-0); border-color: var(--warm-line); }
.stdtile:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
/* Same treatment the numerals had as rows: brand blue at a fifth of the
   weight of the heading beside it, tabular so 01 and 05 occupy the same
   box. It indexes the tile, it is not a display figure. */
.stdtile__n {
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--brand);
  /* 0.65 is the floor, not a look: the brand blue faded on white composites
     to #5966c1, which is 5.13:1. At the 0.5 this started on it came out at
     3.5:1 and axe flagged it against WCAG 2.0 SC 1.4.3. */
  opacity: 0.65;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.stdtile__t {
  font-family: var(--font-display);
  font-size: clamp(1.14rem, 1.45vw, 1.28rem);
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
}
.stdtile__d {
  margin-top: 0.6rem;
  font-size: clamp(0.95rem, 1.1vw, 1.02rem);
  line-height: 1.6;
  color: var(--muted);
}

/* The two on the bottom row. Three columns each is roughly half the
   page. The first attempt at these set the heading and the description
   side by side to use that width; measured at 1360 it gave the heading
   a 208px column it did not need and left the description 254px, which
   is NARROWER than the 301px the small tiles give it. Splitting a
   494px box in two makes both halves worse than the box. So they stack
   like the other three and the description simply stops at a sensible
   measure; the rest of the width is the room the bottom row is for. */
.stdtile--wide { grid-column: span 3; }
.stdtile--wide .stdtile__d { max-width: 48ch; }

/* Six columns need roughly 200px a cell before the headings start
   breaking. Below that it is two up, with the fifth tile spanning the
   pair so the grid does not end on a half-empty row. */
@media (max-width: 1020px) {
  .stdgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stdtile, .stdtile--wide { grid-column: span 1; }
  .stdtile:last-child { grid-column: span 2; }
}
@media (max-width: 640px) {
  .stdgrid { grid-template-columns: minmax(0, 1fr); }
  .stdtile, .stdtile--wide, .stdtile:last-child { grid-column: span 1; }
}

/* Retired in place. .stdlist and .stdrow were the numbered rows this
   round replaced; nothing on any page carries those classes now. They
   are at line 9696 and are left there, like .chero__ring, .herochips,
   .rail, .voicecard and the rest. */


/* ======================================================================
   v74 · 2026-08-18 · CAREERS: the hero banner and the standards bento,
   second pass
   ----------------------------------------------------------------------
   The read first, because most of what follows is restraint.

   The hero cannot be restaged. Measured at 1360 the arch is 628px tall
   and its bottom sits at 736; the strip under it starts at 747 and ends
   near 830, inside an 860px fold with about 30px to spare. The arch is
   square-ish by aspect-ratio, so any extra height is width times a
   constant and the picture grows fastest exactly where there is least
   room. Making it taller, dropping the copy to its baseline, or giving
   the picture the full bleed all push the proof strip below the fold,
   and that strip is the only thing in the hero that says what the firm
   is. So the arch stays the size it is. What changed is the type, the
   spacing steps between the four stack elements, and the strip, which
   was the weakest thing in the banner: three facts set at 0.95rem in
   the body font, reading like a caption row rather than the base the
   hero stands on.

   1 · HERO
     a. Headline. 4rem to 4.3rem at the top of the ramp with the
        tracking pulled another step. The line breaks in this headline
        are hard <br />s, so the only wrapping risk is "Opportunity is
        at" outgrowing its column. The first draft raised the FLOOR of
        the clamp too, 2.6rem to 2.75rem, and that was wrong: measured
        at 375 the line ran to 344px of a 354px column, which still
        fits, but a 360px phone -- and plenty of Android handsets are
        360 -- would have broken it over two lines. The floor is back
        at 2.6rem, the size this line has already been proved at. Only
        the ceiling moved, and the vw term does not overtake the floor
        until about 823px wide, so nothing below a small laptop
        changes at all.

     b. The four steps of the stack were 0.9 / unset / 2rem, which is
        not a scale. 1.05 / 1.45 / 2.15rem is: each gap is roughly half
        again the one above it, so the eye reads label-headline as one
        unit and the button row as a separate decision.

     c. The strip. The first line of each item goes into the display
        font at 1.05rem, which is the same treatment every other small
        heading on this site gets, and the second line keeps the muted
        body size. That is the difference between a caption and a fact.
        The strip also comes up a step closer to the hero it belongs to.

   2 · THE STANDARDS BENTO
     a. Arrangement. See the note in careers.html: the wide pair moved
        to the top row so the largest cell carries 01, not 05.

     b. Scale. The wide tiles now set their heading a step larger than
        the narrow three. A bento wants its cells to differ in more than
        area, and on a light page with no coloured fills available --
        every tile on a warm band is white -- type scale is the honest
        lever. Nothing else about the two kinds of tile differs.

     c. The numeral. It was 0.95rem brand blue at half opacity in the
        top-left corner of a card, which at that size and that alpha is
        a mark you have to look for. It now runs a hairline out to the
        edge of the tile beside it: same figure, same colour, but it
        reads as a register line across the top of every tile and it
        fills the corner the old one left empty. The rule is drawn with
        ::after on the numeral itself, so the markup did not change and
        screen readers still get the count from the <ol>.
   ---------------------------------------------------------------------- */

/* --- 1 · HERO -------------------------------------------------------- */
.careerspg .chero__copy h1 {
  margin-top: 1.05rem;
  font-size: clamp(2.6rem, 5.05vw, 4.3rem);
  letter-spacing: -0.025em;
}
.careerspg .chero__lead { margin-top: 1.45rem; }
.careerspg .chero__cta { margin-top: 2.15rem; }

.careerspg .cheroband { margin-top: clamp(2.7rem, 4.4vw, 3.7rem); }
.careerspg .cheroband__item strong {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: -0.008em;
  line-height: 1.2;
  margin-bottom: 0.18rem;
}

/* --- 2 · THE STANDARDS BENTO ----------------------------------------- */
/* Register line. flex:1 lets the rule take whatever the figure leaves,
   so it ends on the tile's padding edge at every column width without a
   single measurement being written down. */
.stdtile__n {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  font-size: 1rem;
  letter-spacing: 0.08em;
  /* Kept in step with the base rule above. See the note there before
     lowering this: below 0.61 the numerals stop meeting 4.5:1 on white. */
  opacity: 0.65;
}
.stdtile__n::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--brand-100);
}
.stdtile__t { font-size: clamp(1.18rem, 1.5vw, 1.32rem); }

/* The wide pair. Larger padding, larger heading, same everything else.
   The 48ch cap stays: it is what stops a 13-word sentence running the
   full half-page and setting one long line. */
.stdtile--wide { padding: clamp(1.7rem, 2.6vw, 2.35rem); }
.stdtile--wide .stdtile__t { font-size: clamp(1.34rem, 1.78vw, 1.54rem); }

/* Below 1020 the two kinds of tile share a column, so the size split
   between them stops meaning anything and would just read as one
   heading being bigger for no reason. */
@media (max-width: 1020px) {
  .stdtile--wide { padding: clamp(1.5rem, 2.3vw, 2rem); }
  .stdtile--wide .stdtile__t { font-size: clamp(1.18rem, 1.5vw, 1.32rem); }
}

/* ======================================================================
   v75 · 2026-08-30 · CONTACT BAND: the photograph comes out, a drawn
                      gradient goes in
   ====================================================================== */

/* Client direction: behind "Start a conversation", replace the handshake
   photograph with a navy-to-pale vertical gradient carrying a fine dot
   grid.

   It is drawn in CSS rather than shipped as an image file, and that is not
   a shortcut. A ramp this long and this smooth is the one thing an 8-bit
   JPEG cannot hold: across a 1382px band it bands visibly, and the usual
   answer -- adding grain to hide the banding -- would fight the clean look
   the gradient is here for. Drawn, it is exact at every width, every zoom
   level and every DPR, and it costs no request and no bytes.

   .moment__bg was an <img>; it is a <span> now. Everything else about the
   layer stack is unchanged, so the z-index order (ground 0, scrim 1,
   content 2) still holds. object-fit on the old rule is simply inert on a
   span and is left alone rather than special-cased.

   Stops were read off the reference: near-black navy at the top, through
   royal blue across the middle where the white copy sits, to a pale
   blue-white at the foot. The dot grid is a single 1px white dot on a 24px
   lattice at 0.055 alpha -- visible against the dark top, and self-erasing
   toward the pale bottom, which is how it behaves in the reference. */
.moment--shot .moment__bg {
  background-color: #050b18;
  background-image:
    radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.055) 1px, transparent 0),
    linear-gradient(180deg,
      #050b18 0%,
      #061127 9%,
      #08203f 20%,
      #0b2e58 32%,
      #10457a 45%,
      #1a5a97 56%,
      #3f7cae 66%,
      #6f9bc2 75%,
      #a8c1d8 85%,
      #ccdae7 94%,
      #dde6ef 100%);
  background-size: 24px 24px, 100% 100%;
  background-repeat: repeat, no-repeat;
}

/* The scrim is retired here, and deliberately so. Every layer in it existed
   to rescue a photograph: a left-anchored pool to buy the white copy its
   contrast over a bright window, a 100deg wash to darken the copy side, a
   180deg pass to stop the picture meeting the sections above and below on a
   hard seam. None of those problems exist against a ground we draw
   ourselves. Keeping the washes would only muddy a gradient that is already
   the exact colour it is supposed to be.

   Measured after the swap, worst pixel, ground sampled with the glyphs
   hidden so the type is not compared against its own pixels:

     seclabel          9.02:1   need 4.5
     headline         11.03:1   need 3.0
     its italic half   6.29:1   need 3.0
     the lead          7.62:1   need 4.5
     "Prefer email?"   6.24:1   need 4.5
     the email link    7.26:1   need 4.5

   The same nodes over the old photograph ran 4.45 to 5.12, so the drawn
   ground is worth roughly two to six times the margin the scrim was
   fighting for. Panels: form labels 5.55-6.10, "Get in touch" 8.97,
   newsstrip heading 13.24, its supporting line 7.88. */
.moment--shot .moment__scrim { background: none; }

/* --- the two glass panels, on a ground that is now light at the foot ---
   Both panels were tuned to float on a dark photograph: a white border and
   a white inset highlight, which read as a lit bevel against navy. The
   newsstrip sits at 75-89% of the band, which is exactly where the gradient
   has gone pale, so a white edge on it is now a white line on white -- the
   panel loses its shape entirely.

   The fix is an edge that does not depend on which end of the ramp it lands
   on: a hairline in the band's own navy at low alpha, which darkens against
   the pale foot and disappears into the dark head, plus a shadow doing the
   lifting it was already doing. The formcard spans 15-69% and still sits
   mostly on blue, so it keeps its highlight and only gains the navy
   hairline underneath. */
.moment--shot .formcard,
.moment--shot .newsstrip {
  border-color: rgba(10, 32, 74, 0.14);
}
.moment--shot .newsstrip {
  background: rgba(255, 255, 255, 0.62);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 22px 50px -30px rgba(6, 20, 56, 0.5);
}

/* The band used to end on the dark bottom edge of a photograph and meet the
   footer without a seam. It now ends pale, and the footer under it is dark,
   so the join is a hard light-to-dark edge. That edge is left in place --
   it is the honest bottom of the gradient the client asked for -- but the
   footer's own top hairline is dropped, because a light rule drawn on top
   of a pale-to-dark join reads as a rendering fault rather than a divider. */
.moment--shot + .footer { border-top-color: transparent; }

/* ═════════════════════════════════════════════════════════════════════
   wealthdoor.us redesign (2026-10-09, client)
   "Keep the design language consistent with the Wealthdoor homepage …
   the .us page should look more refined and visually stronger."

   Everything here is scoped to .privatepg or to a modifier that only
   wealthdoor.us/index.html uses, so no group page moves.
   ═════════════════════════════════════════════════════════════════════ */

/* --- 1 · the hero: the homepage's stage, photograph full-bleed ---------
   Round 2 (client): "Keep the image as the background with the text over
   it, and add a subtle blue layer … use the same font style and overall
   typography from the main Wealthdoor homepage."

   So the round-1 split composition is gone and nothing here sets type:
   the h1, lead, buttons, copy width and both scrims are the homepage's
   own .hero--stage / .hero__scrim rules, untouched. That scrim is
   already measured for white type over any photograph (see the
   .hero__scrim note), so the only layer added is the blue: one brand
   light falling from the top-left, which sits on top of the navy wash.
   It is lighter than the wash only where the wash is already 0.8+, and
   over the bright sky it darkens, so it can only raise the worst pixel. */
.hero--us .hero__slide { object-position: 50% 46%; }
.hero--us::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(70% 90% at 0% 0%, rgba(36, 56, 201, 0.34) 0%, rgba(36, 56, 201, 0) 62%),
    linear-gradient(0deg, rgba(36, 56, 201, 0.10), rgba(36, 56, 201, 0.10));
}
/* The homepage reserves 7-9rem under its copy for the floating figure
   cards. This page has none, so the facts bar takes that room instead. */
.hero--us { padding-block: clamp(3rem, 7vw, 5.5rem) clamp(3rem, 6vw, 4.6rem); }

/* The three registrations as one dark glass bar under the buttons: the
   homepage's dark-over-anything glass (.gcard), read across. The vertical
   hairlines are joins between cells, not a rule across the top. */
.herofacts--glass {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  max-width: 42rem;
  margin-top: clamp(2.4rem, 4.4vw, 3.4rem);
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--radius-lg);
  background: rgba(10, 14, 48, 0.42);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: 0 14px 36px rgba(0, 8, 50, 0.26);
  overflow: hidden;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .herofacts--glass { background: rgba(10, 14, 48, 0.72); }
}
.herofacts--glass li { flex: none; min-width: 0; padding: clamp(0.95rem, 1.6vw, 1.2rem) clamp(1rem, 1.8vw, 1.4rem); }
.herofacts--glass li + li { border-left: 1px solid rgba(255, 255, 255, 0.16); }
.herofacts--glass b { font-size: clamp(1.3rem, 1.8vw, 1.6rem); }
.herofacts--glass span { color: rgba(255, 255, 255, 0.9); }

/* Phone: one row per registration, the mark beside its description. */
@media (max-width: 560px) {
  .herofacts--glass { grid-template-columns: minmax(0, 1fr); }
  .herofacts--glass li { display: flex; align-items: baseline; gap: 0.75rem; padding: 0.8rem 1rem; }
  .herofacts--glass li + li { border-left: 0; border-top: 1px solid rgba(255, 255, 255, 0.14); }
  .herofacts--glass b { flex: 0 0 4.6rem; font-size: 1.2rem; }
  .herofacts--glass span { margin-top: 0; }
}

/* --- 2 · sections --------------------------------------------------- */
/* The pullnote moved from the hero to the discipline column, under the
   body copy it summarises. */
.privatepg .promise .pullnote { margin-top: 1.6rem; }

/* Card photographs are people, so the crop keeps the top of the frame. */
.privatepg .pcard__media img { object-position: 50% 22%; }

/* The closing headline is long; at full .h2 size it ran five lines
   beside a four-row accordion. */
.qsplit .h2 { font-size: clamp(1.8rem, 3vw, 2.5rem); }

/* The process photograph is two people across a landscape frame; the
   shared 3:4.3 portrait crop would cut one of them out. On this page
   the split goes nearer even and the frame nearly square, which keeps
   both faces at every width. */
.privatepg .procsplit { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr); }
.privatepg .procsplit__media { aspect-ratio: 1 / 1.02; }
.privatepg .procsplit__media img { object-position: 56% 40%; }
@media (max-width: 900px) {
  .privatepg .procsplit { grid-template-columns: minmax(0, 1fr); }
  .privatepg .procsplit__media { aspect-ratio: 16 / 10; }
}

/* The week ranges were run into the step titles behind an em dash. They
   are metadata, so they are set as a small label beside the title. */
.stepr__when {
  display: inline-block;
  margin-left: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  vertical-align: 0.18em;
}

/* Before we speak: copy left, questions right, aligned to the top. */
.qsplit {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.qsplit .acc { margin-top: 0.4rem; }
@media (max-width: 900px) {
  .qsplit { grid-template-columns: minmax(0, 1fr); }
}

/* --- 3 · Begin: the homepage's contact band, on a photograph -----------
   .moment--shot draws the homepage gradient on a span and switches the
   scrim off. This page puts a photograph back in the ground (an <img>,
   so it can lazy-load), so the gradient is cleared and a scrim restored.
   The scrim follows the original photo-era recipe: dense navy on the
   left where the white copy sits, thinning across the form so the city
   still reads, and a pass top and bottom to close the band. The form
   panel is opaque enough to carry its own contrast. */
.moment--photo .moment__bg {
  background: none;
  object-fit: cover;
  object-position: 50% 62%;
  width: 100%; height: 100%;
}
.moment--photo .moment__scrim {
  background:
    linear-gradient(100deg,
      rgba(var(--scrim-deep), 0.86) 0%,
      rgba(var(--scrim-deep), 0.80) 50%,
      rgba(var(--scrim-deep), 0.40) 68%,
      rgba(var(--scrim-deep), 0.16) 100%),
    linear-gradient(180deg,
      rgba(6, 9, 26, 0.30) 0%,
      rgba(6, 9, 26, 0) 40%,
      rgba(6, 9, 26, 0.40) 100%);
}
.moment--photo .formcard {
  background: rgba(255, 255, 255, 0.90);
  border-color: rgba(255, 255, 255, 0.5);
}
/* .getintouch--glass p turns every paragraph in the band white, which is
   right for the copy column and wrong inside the white panel. The
   homepage form has no paragraphs; this one has a field hint and the
   privacy note, so they are put back on ink. */
.moment--photo .formcard p { color: var(--muted); }
/* A dark photograph meets the dark footer, so the footer's hairline is
   back to doing its job. */
.moment--photo + .footer { border-top-color: rgba(255, 255, 255, 0.1); }
@media (max-width: 900px) {
  .moment--photo .moment__scrim {
    background: linear-gradient(180deg,
      rgba(var(--scrim-deep), 0.88) 0%,
      rgba(var(--scrim-deep), 0.80) 45%,
      rgba(var(--scrim-deep), 0.70) 100%);
  }
}

/* ═════════════════════════════════════════════════════════════════════
   wealthdoor.us, round 2 (2026-10-09, client)
   "Remove the top shade line from all the widgets … follow the same
   glassmorphism style used in Our Ecosystem."

   One material for every widget on the page: the Ecosystem's white
   glass (white 0.74, blur 20 / saturate 1.5, a white rim, a white top
   highlight, a soft shadow). Where it sits on a photograph the picture
   is its ground; where it sits on the page, the section gets a quiet
   brand light behind it so the blur has something to catch.
   ═════════════════════════════════════════════════════════════════════ */

/* --- 0 · no top bars --------------------------------------------------- */
.privatepg .whycard::before,
.privatepg .whytile--lead::after { display: none; }

/* --- 1 · the glass, as one recipe ------------------------------------- */
.privatepg .whycard,
.pillrail,
.mktpanel__glass,
.privatepg .pcard__body,
.whytile--glasspat {
  background: rgba(255, 255, 255, 0.74);
  border: 1px solid rgba(255, 255, 255, 0.66);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 30px rgba(10, 14, 24, 0.14);
  color: var(--ink);
}
/* On the page ground there is no photograph to separate the pane from,
   so the rim goes to the pale brand step and the shadow tints blue. */
.privatepg .whycard,
.pillrail,
.whytile--glasspat {
  border-color: rgba(229, 233, 250, 0.95);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 14px 34px rgba(0, 19, 160, 0.07);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .privatepg .whycard, .pillrail, .mktpanel__glass,
  .privatepg .pcard__body, .whytile--glasspat { background: rgba(255, 255, 255, 0.92); }
}
/* #2b3138, as on the Ecosystem panes: --muted fails on 0.74 glass over a
   black pixel, this clears 6.4:1. */
.privatepg .whycard p, .privatepg .whycard li,
.pillrail p, .mktpanel__glass p,
.privatepg .pcard__body li, .whytile--glasspat p { color: #2b3138; }

/* The brand light behind the glass. Two soft pools on the section's own
   ground, low enough to read as light, not as a blue section. */
.privatepg #what-we-do,
.uswhy {
  background:
    radial-gradient(48% 62% at 6% 92%, rgba(36, 56, 201, 0.10) 0%, rgba(36, 56, 201, 0) 70%),
    radial-gradient(40% 54% at 96% 8%, rgba(36, 56, 201, 0.08) 0%, rgba(36, 56, 201, 0) 70%),
    var(--brand-50);
}
.privatepg .whycard:hover { border-color: var(--brand-100); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.92), 0 18px 40px rgba(0, 19, 160, 0.11); }

/* --- 2 · Global perspective, local expertise --------------------------
   The homepage's #global idea at this page's scale: one market per
   panel, the photograph edge to edge, the registration on a glass pane
   pinned to its foot (the Ecosystem panel, exactly). */
.mktpair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.8rem, 1.3vw, 1.15rem);
  margin-top: clamp(2.2rem, 4vw, 3.2rem);
}
.mktpanel {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: flex-end;
  min-height: clamp(27rem, 38vw, 35rem);
  padding: clamp(0.9rem, 1.5vw, 1.35rem);
  border-radius: var(--radius-xl);
  background: var(--brand-900);
}
.mktpanel__bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.75s var(--ease);
}
.mktpanel:hover .mktpanel__bg { transform: scale(1.04); }
/* The Mumbai frame is mostly sky; the waterfront is in its lower third. */
.mktpanel:nth-child(2) .mktpanel__bg { object-position: 50% 72%; }
.mktpanel__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 8, 34, 0.14) 0%, rgba(4, 8, 34, 0) 38%, rgba(4, 8, 34, 0.22) 100%);
}
.mktpanel__glass {
  position: relative; z-index: 2; width: 100%;
  padding: clamp(1.25rem, 2.1vw, 1.9rem);
  border-radius: var(--radius);
}
.mktpanel__top { display: flex; align-items: center; gap: 0.85rem; }
.mktpanel__mark {
  flex: none; width: 48px; height: 48px;
  display: grid; place-items: center; overflow: hidden;
  border-radius: 50%;
  background: #fff;
  border: 1px solid var(--brand-100);
}
.mktpanel__mark img { width: 80%; height: auto; }
.mktpanel__mark--seal img { width: 100%; height: 100%; object-fit: cover; }
.mktpanel__code {
  font-family: var(--font-mono);
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.14em;
  color: var(--brand-700);
}
.mktpanel__glass h3 {
  margin-top: clamp(1rem, 1.8vw, 1.35rem);
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.45rem, 2.2vw, 1.95rem); line-height: 1.12; letter-spacing: -0.02em;
  color: var(--ink);
}
.mktpanel__glass p { margin-top: 0.55rem; font-size: 0.95rem; line-height: 1.6; max-width: 46ch; }
.mktpanel__ids { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }
.mktpanel__ids div {
  display: inline-flex; align-items: baseline; gap: 0.45rem;
  padding: 0.38rem 0.8rem;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--brand-100);
}
.mktpanel__ids dt {
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: #2b3138;
}
.mktpanel__ids dd { font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600; color: var(--ink); }

/* The three pillars, one glass rail read across. */
.pillrail {
  list-style: none;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: clamp(0.8rem, 1.3vw, 1.15rem);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.pillrail li {
  display: flex; align-items: flex-start; gap: 1rem;
  padding: clamp(1.2rem, 2vw, 1.6rem) clamp(1.1rem, 1.9vw, 1.5rem);
}
.pillrail li + li { border-left: 1px solid var(--brand-100); }
.pillrail h3 {
  font-family: var(--font-display); font-weight: 500;
  font-size: 1.1rem; line-height: 1.25; color: var(--ink);
}
.pillrail p { margin-top: 0.3rem; font-size: 0.9rem; line-height: 1.55; }
.pillrail .ibadge { background: var(--brand-50); border-color: var(--brand-100); box-shadow: none; }
.mktnote {
  margin-top: 1.1rem;
  font-size: 0.8rem; color: var(--muted); text-align: center;
}
@media (max-width: 900px) {
  .mktpair { grid-template-columns: minmax(0, 1fr); }
  .mktpanel { min-height: clamp(24rem, 80vw, 30rem); }
  .pillrail { grid-template-columns: minmax(0, 1fr); }
  .pillrail li + li { border-left: 0; border-top: 1px solid var(--brand-100); }
}

/* --- 3 · Who we serve: the Ecosystem panel, four times ----------------
   The photograph fills the card and the copy sits on a glass pane at its
   foot, so the picture carries the card instead of being a header strip
   on a white box. */
.privatepg .pcard {
  position: relative; isolation: isolate;
  justify-content: flex-end;
  min-height: clamp(31rem, 42vw, 37rem);
  padding: clamp(0.8rem, 1.3vw, 1.15rem);
  border: 0;
  border-radius: var(--radius-xl);
  background: var(--brand-900);
}
.privatepg .pcard:hover { box-shadow: 0 22px 48px rgba(0, 12, 99, 0.18); }
.privatepg .pcard__media {
  position: absolute; inset: 0; z-index: 0;
  aspect-ratio: auto;
}
.privatepg .pcard__media::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 8, 34, 0.12) 0%, rgba(4, 8, 34, 0) 34%, rgba(4, 8, 34, 0.2) 100%);
}
.privatepg .pcard__media img { object-position: 50% 18%; }
.privatepg .pcard__body {
  position: relative; z-index: 2;
  padding: clamp(1.2rem, 2vw, 1.7rem);
  border-radius: var(--radius);
}
.privatepg .pcard__n { color: var(--brand-700); }
.privatepg .pcard__body h3 { font-size: clamp(1.25rem, 1.7vw, 1.45rem); letter-spacing: -0.01em; }
@media (max-width: 760px) {
  .privatepg .pcard { min-height: clamp(30rem, 120vw, 34rem); }
}

/* --- 4 · Why Wealthdoor: the homepage bento, one step up --------------
   The homepage's lead tile went pale with a 3px bar (removed, above).
   Here it keeps the full brand field it was designed with, so the one
   claim the other three rest on is the one dark surface in the section;
   the two quiet tiles are glass, and the custody tile is a photograph
   under the same glass. */
.whybento--us .whytile--lead {
  background:
    radial-gradient(90% 80% at 100% 0%, rgba(36, 56, 201, 0.55) 0%, rgba(36, 56, 201, 0) 62%),
    linear-gradient(152deg, var(--brand-700) 0%, var(--brand-900) 100%);
  border: 0;
  color: #fff;
  box-shadow: 0 18px 44px rgba(0, 12, 99, 0.22);
}
.whybento--us .whytile--lead .whytile__pat--rings {
  background-image: repeating-radial-gradient(circle at 84% -8%, rgba(255, 255, 255, 0.11) 0 1px, transparent 1px 30px);
}
.whybento--us .whytile--lead h3 {
  color: #fff;
  font-size: clamp(1.8rem, 2.8vw, 2.5rem); letter-spacing: -0.025em; line-height: 1.08;
}
.whybento--us .whytile--lead p { color: rgba(255, 255, 255, 0.88); font-size: 1.02rem; max-width: 40ch; }
.whybento--us .whytile--lead .ibadge--glass {
  color: #fff;
  background: rgba(255, 255, 255, 0.13);
  border: 1px solid rgba(255, 255, 255, 0.24);
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.whytile__marks {
  list-style: none;
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  margin-top: auto; padding-top: clamp(1.4rem, 2.6vw, 2.2rem);
}
.whytile__marks li {
  padding: 0.42rem 0.95rem;
  border-radius: var(--radius-pill);
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.02em;
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.24);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
}
.whytile--glasspat h3 { color: var(--ink); }
.whytile--glasspat .ibadge { background: var(--brand-50); border-color: var(--brand-100); box-shadow: none; }
.whybento--us .whytile--shot .whytile__bg { object-position: 50% 50%; }
.whybento--us .whytile--shot .whytile__glass { border-radius: var(--radius); }
.whybento--us .whytile--shot .whytile__glass h3 { color: var(--ink); }
.whybento--us .whytile--shot .whytile__glass p { color: #2b3138; }
.whybento--us .whytile:hover { transform: translateY(-2px); }

/* Phone: the panes grow taller than the panels, so the photograph is
   given a fixed window above the pane instead of a minimum height, and
   is never hidden behind the copy. */
@media (max-width: 560px) {
  .mktpanel { min-height: 0; padding-top: 12rem; }
  .privatepg .pcard { min-height: 0; padding-top: 14rem; }
}

/* Two columns: the shared bento puts tile 2 and tile 4 on different rows
   either side of the photograph, leaving a hole beside each. Here the two
   glass tiles pair up under the lead and the photograph closes the block. */
@media (max-width: 1040px) {
  .whybento--us .whytile:nth-child(2) { grid-row: 2; }
  .whybento--us .whytile:nth-child(4) { grid-row: 2; }
  .whybento--us .whytile:nth-child(3) { grid-row: 3; }
}
@media (max-width: 620px) {
  .whybento--us .whytile:nth-child(n) { grid-row: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .mktpanel__bg, .mktpanel:hover .mktpanel__bg,
  .whybento--us .whytile:hover { transition: none; transform: none; }
}

/* ═════════════════════════════════════════════════════════════════════
   wealthdoor.us, round 3 (2026-10-09, client)
   Hero type lighter, less italic; quieter section grounds; new service
   icons; the Begin form on the homepage's glass, with a fixed select and
   a shorter message box. Scoped to .privatepg / .hero--us / .moment--photo.
   ═════════════════════════════════════════════════════════════════════ */

/* --- 1 · hero headline ------------------------------------------------
   Was 600 weight at 70px with a twelve-word italic clause. The headline
   drops to 500 and a step smaller; the second sentence is upright at
   400, and only its last four words keep the italic, the same short
   accent the homepage's "built around you." carries. */
.hero--us.hero--stage h1 {
  font-weight: 500;
  font-size: clamp(2.35rem, 4.5vw, 3.85rem);
  line-height: 1.07;
  letter-spacing: -0.024em;
  max-width: 17ch;
}
.hero--us.hero--stage h1 .mute { font-style: normal; font-weight: 400; color: inherit; }
.hero--us.hero--stage h1 .mute em { font-style: italic; font-weight: 400; }

/* --- 2 · the section grounds ------------------------------------------
   The two brand pools (0.10 / 0.08 over --brand-50) read as a blue
   section. What we do goes back to paper and Why Wealthdoor to the warm
   band, each with one pool at a third of the old strength. */
.privatepg #what-we-do {
  background:
    radial-gradient(44% 56% at 4% 96%, rgba(36, 56, 201, 0.035) 0%, rgba(36, 56, 201, 0) 70%),
    var(--paper);
}
.uswhy {
  background:
    radial-gradient(40% 52% at 96% 4%, rgba(36, 56, 201, 0.03) 0%, rgba(36, 56, 201, 0) 70%),
    var(--warm-50);
}

/* --- 3 · service icons ------------------------------------------------
   The 40px pale circle with a 22px two-tone glyph was too faint to
   carry three headline cards. Each service now gets a drawn line icon
   on a solid brand tile, a rounded square so it does not repeat the
   circular chips used elsewhere on the page. Decorative (aria-hidden):
   the h3 beside it carries the meaning. */
.privatepg .ibadge.svcmark {
  width: 3.25rem; height: 3.25rem;
  border-radius: 14px;
  border: 0;
  color: #fff;
  background:
    radial-gradient(120% 90% at 20% 0%, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0) 55%),
    linear-gradient(150deg, var(--brand-700) 0%, var(--brand-900) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 12px 24px -12px rgba(0, 19, 160, 0.55);
}
.privatepg .ibadge.svcmark svg:not(.ico) {
  width: 1.6rem; height: 1.6rem;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}

/* --- 4 · Begin: the homepage form glass -------------------------------
   Round 1 made this panel 0.90 white so it would carry its own contrast
   on the photograph. The client wants the homepage's panel, so the
   homepage values are restated here: 0.68 white, blur 30 / saturate
   1.65, white rim, white top highlight, the deep shadow. */
.moment--photo .formcard {
  background: rgba(255, 255, 255, 0.68);
  border: 1px solid rgba(255, 255, 255, 0.5);
  backdrop-filter: blur(30px) saturate(165%);
  -webkit-backdrop-filter: blur(30px) saturate(165%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.62),
    0 34px 80px -36px rgba(3, 7, 30, 0.72);
}
.moment--photo .formcard p,
.moment--photo .formcard .field__hint { color: var(--ink-soft); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .moment--photo .formcard { background: var(--paper); border-color: var(--line); }
}

/* The native select drew its own inner padding and arrow, so its text
   sat 5px further in than every input above it and the arrow hugged
   the border. Drawn by hand: same padding and height as an input, the
   chevron inset by the same 0.95rem. */
.privatepg .field select {
  -webkit-appearance: none; appearance: none;
  line-height: normal;
  padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2321252b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.95rem center;
  background-size: 14px 14px;
  cursor: pointer;
}

/* The message box was 130px, the tallest thing in the panel. */
.privatepg .formcard textarea { min-height: 5.75rem; }

/* Footer "PRIVATE" sub-label was --faint grey on the navy footer
   (3.26:1, fails AA). Same white-on-navy as the footer copy. */
.footer .brand__sub { color: rgba(255, 255, 255, 0.72); border-left-color: rgba(255, 255, 255, 0.24); }

/* Round 3 hero photo: Midtown at dusk (Pexels 40081298). The skyline
   sits just under the middle of the frame; hold it there so the towers
   rise behind the buttons and the quiet sky carries the headline. */
.hero--us .hero__slide { object-position: 50% 58%; }

/* What we do icons, round 4 (client): the solid navy gradient tile
   went. The three marks are now the page's own two-tone filled set
   (.ico, .32 secondary mass) on the same light chip as every other
   section, one size up so they lead their cards. */
.privatepg .ibadge.svcmark {
  width: 3.75rem; height: 3.75rem; border-radius: 50%;
  color: var(--brand);
  background: var(--brand-50); border: 1px solid var(--brand-100);
  box-shadow: none;
}
.privatepg .ibadge.svcmark .ico { width: 2rem; height: 2rem; }
/* Nasdaq slide: on narrow screens pull the crop right so the MarketSite facade shows */
@media (max-width: 760px) { .hero--us .hero__slide--nasdaq { object-position: 88% 58%; } }
/* .us hero headline: three lines on wider screens, broken at the sentence,
   "You built a life across borders. / Your wealth strategy should be /
   built the same way." Phones keep natural wrapping. */
@media (min-width: 761px) {
  .hero--us.hero--stage .hero__copy { max-width: 60rem; }
  .hero--us.hero--stage h1 { max-width: none; width: fit-content; font-size: clamp(2.5rem, 4.4vw, 3.85rem); }
  .hero--us.hero--stage h1 .hl,
  .hero--us.hero--stage h1 .mute em { display: block; white-space: nowrap; }
  .hero--us.hero--stage .lead { max-width: 36rem; }
}
/* .us hero headline: the same three lines on every screen. Below 761px the
   size follows the viewport so "Your wealth strategy should be" fits. */
.hero--us.hero--stage h1 .hl,
.hero--us.hero--stage h1 .mute em { display: block; }
.hero--us.hero--stage h1 .hl,
.hero--us.hero--stage h1 .mute { white-space: nowrap; }
@media (max-width: 760px) {
  .hero--us.hero--stage h1 { max-width: none; font-size: clamp(1.3rem, 6.9vw, 2.6rem); }
}

/* ==========================================================================
   WEALTHDOOR FOR ADVISORS (wealthdoor.us/advisors.html), added 2026-10-09.
   Copy is Azer's PDF narration. Everything here is scoped to .advpg or
   an adv* class, so nothing on the families page moves.
   ========================================================================== */


/* Hero: navy stage with the product as the picture. */
.hero--adv::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(60% 80% at 100% 10%, rgba(36, 56, 201, 0.55) 0%, rgba(36, 56, 201, 0) 65%),
    radial-gradient(50% 70% at 0% 100%, rgba(36, 56, 201, 0.28) 0%, rgba(36, 56, 201, 0) 60%);
}
.hero--adv { padding-block: clamp(3rem, 6vw, 5rem); }
.advhero { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.hero--adv .hero__copy { max-width: 40rem; }
.advhero__eyebrow { font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: rgba(255, 255, 255, 0.86); margin-bottom: 1.3rem; display: flex; align-items: center; gap: 0.6rem; }
.advhero__eyebrow::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.hero--adv h1 { font-weight: 500; font-size: clamp(2.2rem, 4.3vw, 3.7rem); line-height: 1.07; letter-spacing: -0.024em; }
.hero--adv h1 .mute em { font-style: italic; }
.hero--adv p.lead { margin-top: 1.4rem; max-width: 40rem; }
.hero--adv .hero__cta { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* The mockup. Plain HTML, ink on white, so it is a picture of a product
   and not glass laid on for effect. */
.advmock { position: relative; margin: 0; padding-bottom: 3.2rem; max-width: 26rem; justify-self: end; width: 100%; }
.advmock__app {
  background: #fff; color: var(--ink); border-radius: var(--radius-lg);
  padding: 1.25rem 1.3rem 1.3rem; box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.55);
}
.advmock__bar { display: flex; align-items: center; gap: 0.6rem; padding-bottom: 0.95rem; margin-bottom: 1rem; border-bottom: 1px solid var(--line); }
.advmock__logo { width: 30px; height: 30px; border-radius: 8px; background: #0f5c4a; color: #fff; display: grid; place-items: center; font: 600 0.72rem/1 var(--font-sans); letter-spacing: 0.02em; }
.advmock__firm { font-weight: 600; font-size: 0.95rem; }
.advmock__k { font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted); margin: 0.2rem 0 0.6rem; }
.advmock__goal { margin-bottom: 0.85rem; }
.advmock__row { display: flex; justify-content: space-between; font-size: 0.86rem; margin-bottom: 0.35rem; }
.advmock__row span:last-child { font-variant-numeric: tabular-nums; color: var(--muted); }
.advmock__track { display: block; height: 7px; border-radius: 99px; background: #e8efec; overflow: hidden; }
.advmock__track span { display: block; height: 100%; border-radius: inherit; background: #0f5c4a; }
.advmock__alloc { display: flex; gap: 3px; height: 12px; border-radius: 99px; overflow: hidden; margin-top: 0.2rem; }
.advmock__alloc span:nth-child(1), .advmock__legend li:nth-child(1) i { background: #0f5c4a; }
.advmock__alloc span:nth-child(2), .advmock__legend li:nth-child(2) i { background: #3f8f7a; }
.advmock__alloc span:nth-child(3), .advmock__legend li:nth-child(3) i { background: #9cc7b9; }
.advmock__alloc span:nth-child(4), .advmock__legend li:nth-child(4) i { background: #d5e6df; }
.advmock__legend { list-style: none; padding: 0; margin: 0.7rem 0 0; display: flex; flex-wrap: wrap; gap: 0.35rem 0.9rem; font-size: 0.76rem; color: var(--muted); }
.advmock__legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 0.35rem; vertical-align: 0; }
.advmock__ok { display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 1rem; font-size: 0.8rem; font-weight: 600; color: #0b4a3b; background: #e8f2ee; border-radius: 99px; padding: 0.3rem 0.7rem 0.3rem 0.4rem; }
.advmock__ok svg { width: 18px; height: 18px; fill: currentColor; }
.advmock__console {
  position: absolute; left: -2.2rem; bottom: 0; width: 15.5rem;
  background: var(--brand-50); color: var(--ink); border: 1px solid var(--brand-100);
  border-radius: var(--radius-lg); padding: 0.85rem 1rem 0.95rem;
  box-shadow: 0 24px 48px -24px rgba(0, 0, 0, 0.6);
}
.advmock__console .advmock__k { color: var(--brand-700); margin-top: 0; }
.advmock__console dl { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.4rem; margin: 0; }
.advmock__console dt { font-size: 0.7rem; color: var(--muted); }
.advmock__console dd { margin: 0.1rem 0 0; font: 600 1.15rem/1.1 var(--font-sans); font-variant-numeric: tabular-nums; color: var(--brand-900); }
.advmock__cap { position: absolute; right: 0; bottom: 0.35rem; font-size: 0.74rem; color: rgba(255, 255, 255, 0.8); text-align: right; max-width: 9.5rem; line-height: 1.35; }

/* Why */
.advwhy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
.advwhy .h2 { text-wrap: balance; }
.advwhy__body .lead + .lead { margin-top: 1rem; }
.advpoints { list-style: none; padding: 0; margin: clamp(2.5rem, 5vw, 3.5rem) 0 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--line); }
.advpoints li { padding: 1.6rem clamp(1rem, 2.5vw, 2rem) 0.4rem 0; }
.advpoints li + li { padding-left: clamp(1rem, 2.5vw, 2rem); border-left: 1px solid var(--line); }
.advpoints p { margin-top: 1rem; color: var(--muted); font-size: 0.98rem; line-height: 1.6; }
.advpoints strong { display: block; color: var(--ink); font-weight: 600; font-size: 1.05rem; margin-bottom: 0.3rem; }

/* Two-tone icon chip */
.advico { flex: none; width: 42px; height: 42px; border-radius: var(--radius); background: var(--brand-50); color: var(--brand-700); display: inline-grid; place-items: center; }
.advico svg { width: 22px; height: 22px; fill: currentColor; }
.advico--inv { background: rgba(255, 255, 255, 0.12); color: #fff; }

/* Platform */
.advh2 { max-width: 22ch; text-wrap: balance; }
.advplat { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.6fr); gap: clamp(1.5rem, 3.5vw, 3rem); margin-top: clamp(2rem, 4vw, 3rem); align-items: stretch; }
.advlead { background: var(--brand-900); color: #fff; border-radius: var(--radius-lg); padding: clamp(1.5rem, 3vw, 2.2rem); display: flex; flex-direction: column; }
.advlead h3 { font-family: var(--font-display); font-weight: 500; font-size: 1.6rem; margin-top: 1.2rem; }
.advlead p { color: rgba(255, 255, 255, 0.9); margin-top: 0.6rem; line-height: 1.6; }
.advlead__swatch { margin-top: auto; padding-top: 2rem; display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem; }
.advlead__chip { display: inline-flex; align-items: center; gap: 0.5rem; background: #fff; color: var(--ink); border-radius: 99px; padding: 0.3rem 0.85rem 0.3rem 0.3rem; font-size: 0.85rem; font-weight: 600; }
.advlead__chip b { width: 24px; height: 24px; border-radius: 50%; background: #0f5c4a; color: #fff; display: grid; place-items: center; font-size: 0.62rem; }
.advlead__dots { display: inline-flex; gap: 4px; }
.advlead__dots i { width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.6); }
.advlead__dots i:nth-child(1) { background: #0f5c4a; } .advlead__dots i:nth-child(2) { background: #3f8f7a; } .advlead__dots i:nth-child(3) { background: #d5e6df; }
.advlead__url { font-family: var(--font-mono); font-size: 0.76rem; color: rgba(255, 255, 255, 0.86); }
.advfeat { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 clamp(1.5rem, 3vw, 2.5rem); margin: 0; }
.advfeat > div { padding: 1.25rem 0; border-top: 1px solid var(--warm-line); }
.advfeat dt { display: flex; align-items: center; gap: 0.8rem; font-weight: 600; font-size: 1.02rem; color: var(--ink); }
.advfeat dd { margin: 0.55rem 0 0 calc(42px + 0.8rem); color: var(--muted); font-size: 0.95rem; line-height: 1.6; }
.band--warm .advico { background: #fff; }

/* Models */
.advbridge { font-family: var(--font-display); font-size: clamp(1.25rem, 2.2vw, 1.6rem); line-height: 1.35; color: var(--brand-700); max-width: 36ch; margin-bottom: clamp(2rem, 4vw, 3rem); padding-bottom: clamp(1.5rem, 3vw, 2rem); border-bottom: 1px solid var(--line); }
.advmodels { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
.advmodels .h2 { text-wrap: balance; }
.advchecks { list-style: none; padding: 0; margin: 0; }
.advchecks li { position: relative; padding: 1.05rem 0 1.05rem 2.2rem; border-top: 1px solid var(--line); color: var(--muted); line-height: 1.6; }
.advchecks li:last-child { border-bottom: 1px solid var(--line); }
.advchecks li::before {
  content: ""; position: absolute; left: 0; top: 1.25rem; width: 20px; height: 20px; border-radius: 50%;
  background: var(--brand-50) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='m5.8 10.3 2.7 2.7 5.6-5.8' fill='none' stroke='%230013a0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 100% no-repeat;
}
.advchecks strong { color: var(--ink); font-weight: 600; }

/* How it works */
.advsteps { list-style: none; padding: 0; margin: clamp(2rem, 4vw, 3rem) 0 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(1rem, 2.5vw, 2rem); counter-reset: none; }
.advsteps li { position: relative; padding-top: 1.6rem; border-top: 2px solid var(--warm-line); }
.advsteps li::before { content: ""; position: absolute; top: -2px; left: 0; width: 2.5rem; height: 2px; background: var(--brand-700); }
.advsteps__n { font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600; letter-spacing: 0.08em; color: var(--brand-700); }
.advsteps h3 { font-family: var(--font-sans); font-size: 1.1rem; font-weight: 600; margin: 0.7rem 0 0.5rem; }
.advsteps p { color: var(--muted); font-size: 0.95rem; line-height: 1.6; }

/* Pricing */
.advprice { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(1rem, 2.5vw, 1.75rem); margin-top: clamp(2rem, 4vw, 3rem); align-items: start; }
.advplan { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(1.5rem, 3vw, 2.2rem); background: #fff; }
.advplan--main { background: var(--brand-900); border-color: var(--brand-900); color: #fff; }
.advplan h3 { font-family: var(--font-sans); font-size: 1.05rem; font-weight: 600; display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.advplan__opt { font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--brand-700); background: var(--brand-50); border-radius: 99px; padding: 0.2rem 0.55rem; }
.advplan__price { margin: 0.9rem 0 1rem; color: var(--muted); font-size: 1rem; }
.advplan--main .advplan__price { color: rgba(255, 255, 255, 0.86); }
.advplan__amt { font-family: var(--font-display); font-size: clamp(2.4rem, 4vw, 3.2rem); font-weight: 500; letter-spacing: -0.02em; color: var(--ink); line-height: 1; margin-right: 0.25rem; }
.advplan--main .advplan__amt { color: #fff; }
.advplan__from { font-size: 0.9rem; }
.advplan > p:not(.advplan__price) { color: var(--muted); line-height: 1.6; }
.advplan--main > p:not(.advplan__price) { color: rgba(255, 255, 255, 0.92); }
.advplan--main .btn { margin-top: 1.6rem; }
.advplan--main .btn--primary { background: #fff; color: var(--brand-900); border-color: #fff; }
.advplan--main .btn--primary:hover { background: rgba(255, 255, 255, 0.88); }
.advplan--main .btn:focus-visible { outline-color: #fff; }
.advtable { margin-top: 1.4rem; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.advtable table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.advtable thead th { background: var(--brand-900); color: #fff; font-weight: 600; font-size: 0.8rem; letter-spacing: 0.02em; text-align: left; padding: 0.75rem 1rem; }
.advtable thead th:last-child, .advtable td { text-align: right; }
.advtable tbody th { font-weight: 500; text-align: left; color: var(--ink); }
.advtable tbody th, .advtable td { padding: 0.75rem 1rem; border-top: 1px solid var(--line); font-variant-numeric: tabular-nums; }
.advtable td { font-weight: 600; color: var(--brand-900); }
.advtable tbody tr:nth-child(even) { background: var(--soft); }
.advnote { margin-top: 1.4rem; color: var(--muted); font-size: 0.92rem; }

/* Responsive */
@media (max-width: 980px) {
  .advhero { grid-template-columns: minmax(0, 1fr); }
  .advmock { justify-self: start; margin-left: 2.2rem; max-width: 24rem; }
  .advplat { grid-template-columns: minmax(0, 1fr); }
  .advsteps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 2rem; }
}
@media (max-width: 760px) {
  .advwhy, .advmodels, .advprice { grid-template-columns: minmax(0, 1fr); }
  .advpoints { grid-template-columns: minmax(0, 1fr); }
  .advpoints li, .advpoints li + li { padding: 1.4rem 0; border-left: 0; }
  .advpoints li + li { border-top: 1px solid var(--line); }
  .advfeat { grid-template-columns: minmax(0, 1fr); }
  .advmock { margin-left: 1.2rem; max-width: none; width: calc(100% - 1.2rem); }
  .advmock__console { left: -1.2rem; width: 14rem; }
  .advmock__cap { max-width: 7rem; }
}
@media (max-width: 520px) {
  .advsteps { grid-template-columns: minmax(0, 1fr); }
  .advtable table { font-size: 0.88rem; }
  .advtable thead th, .advtable tbody th, .advtable td { padding: 0.65rem 0.75rem; }
}
/* advisors: pass 2 */
.advlead h3, .advplan--main h3 { color: #fff; }
.band--warm .advico.advico--inv { background: rgba(255, 255, 255, 0.12); }
.advmock { padding-bottom: 0; }
.advmock__app { padding-bottom: 3.6rem; }
.advmock__row--k { align-items: center; margin: 0.4rem 0 0.55rem; }
.advmock__row--k .advmock__k { margin: 0; }
.advmock__ok { margin-top: 0; font-size: 0.74rem; padding: 0.2rem 0.6rem 0.2rem 0.3rem; }
.advmock__console { position: relative; left: auto; bottom: auto; margin: -2.6rem 0 0 -2.2rem; }
.advmock__cap { position: static; max-width: none; text-align: right; margin-top: -1.2rem; padding-left: 15rem; }
.advlead__app { margin-top: 1.8rem; background: #fff; border-radius: var(--radius); padding: 1rem; display: grid; gap: 0.6rem; justify-items: start; }
.advlead__app .advlead__chip { padding-left: 0; }
.advlead__line { display: block; width: 100%; height: 8px; border-radius: 99px; background: #e8efec; }
.advlead__line--s { width: 62%; }
.advlead__btn { margin-top: 0.3rem; background: #0f5c4a; color: #fff; font-size: 0.8rem; font-weight: 600; border-radius: 8px; padding: 0.5rem 0.9rem; }
.advlead__swatch { padding-top: 1.4rem; }
.advbridge { max-width: none; margin: clamp(2rem, 4vw, 3rem) 0 0; padding: clamp(1.5rem, 3vw, 2rem) 0 0; border-bottom: 0; border-top: 1px solid var(--warm-line); display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.6rem 2rem; }
.advbridge a { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 600; color: var(--brand-700); text-decoration: none; }
.advbridge a:hover { text-decoration: underline; }
@media (max-width: 760px) {
  .advmock__console { margin-left: -1.2rem; }
  .advmock__cap { text-align: left; padding-left: 0; margin-top: 0.8rem; }
}
.advlead__swatch { margin-top: 0; }
@media (min-width: 981px) { .advlead { align-self: start; position: sticky; top: calc(74px + 1.5rem); } }
.advmock__cap { padding-left: 0; width: fit-content; max-width: 12rem; margin-left: auto; }
@media (max-width: 760px) { .advmock__cap { margin-left: 0; max-width: none; } }

/* ==========================================================================
   ADVISORS · round 2 · 2026-10-09
   Client: fill the highlighted text, design every section with the skills
   folder, rethink the hero widget so "Your Firm" makes sense, and follow
   the homepage's style. The homepage's materials are reused rather than
   imitated: .whybento/.whytile for Why, the lead-tile paper and rings for
   the platform tile, the closer's rings for the pricing card.
   ========================================================================== */

/* ---- example-firm palettes -----------------------------------------
   One set of custom properties per fictional firm. Anything inside a
   [data-brand] element paints from these, so switching the attribute
   re-skins the hero app and the platform tile together. White on each
   --fb measured: Alder 7.9:1, Kestrel 10.0:1, Bayline 6.8:1. */
[data-brand="alder"]   { --fb: #0f5c4a; --fb2: #3f8f7a; --fb3: #9cc7b9; --fb4: #d5e6df; --fbt: #e8efec; --fbi: #0b4a3b; }
[data-brand="kestrel"] { --fb: #7a1f3d; --fb2: #b04a6a; --fb3: #e2a9bb; --fb4: #f3dde4; --fbt: #f4e8ec; --fbi: #5e1730; }
[data-brand="bayline"] { --fb: #8a4b0f; --fb2: #c07a2e; --fb3: #e8c08f; --fb4: #f4e3cc; --fbt: #f6eee3; --fbi: #6b390a; }

/* ---- hero widget ---------------------------------------------------- */
.advmock { max-width: 27rem; }
.advmock__pick { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-bottom: 1rem; }
.advmock__pickk { font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: rgba(255, 255, 255, 0.86); margin-right: 0.2rem; }
.advmock__sw {
  display: inline-flex; align-items: center; gap: 0.45rem; min-height: 2.25rem;
  padding: 0.35rem 0.85rem 0.35rem 0.45rem; border-radius: 99px;
  font: 600 0.82rem/1 var(--font-sans); color: #fff;
  background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.34);
  cursor: pointer; transition: background-color 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.advmock__sw i { width: 1.1rem; height: 1.1rem; border-radius: 50%; background: var(--fb); box-shadow: 0 0 0 2px #fff; }
.advmock__sw:hover { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.6); }
.advmock__sw[aria-pressed="true"] { background: #fff; color: var(--ink); border-color: #fff; }
.advmock__sw[aria-pressed="true"] i { box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px var(--fb); }
.advmock__sw:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.advmock__win { background: #fff; color: var(--ink); border-radius: var(--radius-lg); box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.6); }
.advmock__chrome { position: relative; display: flex; align-items: center; gap: 0.75rem; padding: 0.6rem 0.8rem; background: #f3f4f6; border-bottom: 1px solid var(--line); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
.advmock__dots { display: inline-flex; gap: 5px; }
.advmock__dots i { width: 9px; height: 9px; border-radius: 50%; background: #d4d7dc; }
.advmock__addr { display: inline-flex; align-items: center; gap: 0.4rem; min-width: 0; max-width: 15rem; flex: 1; background: #fff; border: 1px solid var(--line); border-radius: 99px; padding: 0.28rem 0.7rem; font-family: var(--font-mono); font-size: 0.72rem; color: #3a4048; }
.advmock__addr svg { flex: none; width: 11px; height: 11px; fill: #3a4048; }
.advmock__addr span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.advmock__app { border-radius: 0 0 var(--radius-lg) var(--radius-lg); box-shadow: none; padding-bottom: 3.4rem; }
.advmock__bar { position: relative; }
.advmock__logo { background: var(--fb); }
.advmock__track { background: var(--fbt); }
.advmock__track span { background: var(--fb); }
.advmock__alloc span:nth-child(1), .advmock__legend li:nth-child(1) i { background: var(--fb); }
.advmock__alloc span:nth-child(2), .advmock__legend li:nth-child(2) i { background: var(--fb2); }
.advmock__alloc span:nth-child(3), .advmock__legend li:nth-child(3) i { background: var(--fb3); }
.advmock__alloc span:nth-child(4), .advmock__legend li:nth-child(4) i { background: var(--fb4); }
.advmock__ok { color: var(--fbi); background: var(--fbt); }
.advmock__foot { position: relative; display: flex; justify-content: flex-end; margin-top: 1rem; }
.advmock__cta { display: inline-block; background: var(--fb); color: #fff; font-size: 0.8rem; font-weight: 600; border-radius: 8px; padding: 0.55rem 1rem; }
.advmock__logo, .advmock__track, .advmock__track span, .advmock__alloc span, .advmock__legend i,
.advmock__ok, .advmock__cta, .advlead__chip b, .advlead__btn, .advlead__line, .advmock__sw i {
  transition: background-color 0.45s var(--ease), color 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
.advmock__console { margin-top: -2.4rem; }
.advmock__cap { max-width: 17rem; margin-top: 0.9rem; line-height: 1.45; }

/* The three annotation tags. Ink pills with the logo's orange as a dot,
   hanging off the right edge of the window beside the thing they name,
   so the copy is never covered. They fold into the rows on a phone. */
.advtag {
  position: absolute; top: 50%; right: 0; transform: translate(62%, -50%);
  display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap;
  background: var(--ink); color: #fff; border-radius: 99px;
  font: 600 0.74rem/1 var(--font-sans); letter-spacing: 0.01em;
  padding: 0.42rem 0.7rem 0.42rem 0.55rem; box-shadow: 0 8px 20px -8px rgba(0, 0, 0, 0.5);
}
.advtag::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.advmock__chrome .advtag { right: 0.8rem; }
.advmock__bar .advtag { right: -1.3rem; }
.advmock__foot .advtag { right: -1.3rem; }
.advmock__foot .advmock__cta { margin-right: 4.2rem; }

@media (max-width: 1180px) {
  /* No gutter to hang into: the tags sit at the end of their rows. */
  .advtag { position: static; transform: none; flex: none; }
  .advmock__bar .advtag { margin-left: auto; }
  .advmock__hi { display: none; }
  .advmock__foot { justify-content: space-between; align-items: center; }
  .advmock__foot .advmock__cta { margin-right: 0; }
}
@media (max-width: 520px) {
  .advmock__dots { display: none; }
  .advmock__addr { max-width: none; }
  .advmock__chrome .advtag { display: none; }
  .advmock__sw { font-size: 0.78rem; padding-right: 0.7rem; }
}

/* ---- Why: the homepage bento, three tiles -------------------------- */
.advbento { margin-top: clamp(2.4rem, 4.2vw, 3.4rem); }
.advbento .whytile:nth-child(1) { grid-column: 1 / 8; }
.advbento .whytile:nth-child(2) { grid-column: 1 / 8; }
.advbento .whytile:nth-child(3) { grid-column: 8 / 13; grid-row: 1 / 3; }
.advbento .whytile--shot { min-height: clamp(24rem, 36vw, 32rem); }
.advgen { list-style: none; margin: clamp(1.4rem, 2.4vw, 2rem) 0 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem; }
.advgen li { position: relative; background: #fff; border: 1px solid var(--brand-100); border-radius: var(--radius); padding: 0.75rem 0.85rem; }
.advgen li + li::before { content: ""; position: absolute; left: -0.6rem; top: 50%; width: 0.6rem; height: 1px; background: var(--brand-100); }
.advgen b { display: block; font-size: 0.86rem; font-weight: 600; color: var(--ink); }
.advgen span { display: block; margin-top: 0.2rem; font-size: 0.78rem; line-height: 1.4; color: var(--muted); }
@media (max-width: 1040px) {
  .advbento .whytile:nth-child(1), .advbento .whytile:nth-child(2),
  .advbento .whytile:nth-child(3) { grid-column: 1 / 3; grid-row: auto; }
}
@media (max-width: 620px) {
  .advbento .whytile:nth-child(1), .advbento .whytile:nth-child(2),
  .advbento .whytile:nth-child(3) { grid-column: 1 / 2; }
  .advgen { grid-template-columns: minmax(0, 1fr); }
  .advgen li + li::before { left: 1.2rem; top: -0.6rem; width: 1px; height: 0.6rem; }
}

/* ---- Platform: the lead tile in the homepage's lead material -------- */
/* The old .advlead painted navy and pinned itself with position:sticky
   from 981px; keep the sticky, swap the navy for the lead tile's paper. */
.advlead { isolation: isolate; overflow: hidden; color: var(--ink);
  background: linear-gradient(152deg, rgba(36, 56, 201, 0.1) 0%, rgba(0, 19, 160, 0.05) 100%), var(--n-0);
  border: 1px solid var(--brand-100); }
@media (max-width: 980px) { .advlead { position: relative; } }
.advlead > *:not(.whytile__pat) { position: relative; z-index: 1; }
.advlead h3 { color: var(--ink); }
.advlead p { color: var(--muted); }
.advlead .ibadge { background: var(--brand-50); border-color: var(--brand-100); }
.advlead__app { border: 1px solid var(--line); box-shadow: 0 14px 30px -18px rgba(10, 14, 24, 0.35); }
.advlead__chip b { background: var(--fb); }
.advlead__line { background: var(--fbt); }
.advlead__btn { background: var(--fb); }
.advlead__url { margin-top: 0.2rem; color: #3a4048; }

/* ---- Models: one heading row, then the console and the checks ------ */
#models .advmodels { margin-top: clamp(2rem, 4vw, 3rem); align-items: center; }
.advacct { margin: 0; }
.advacct__card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(1.1rem, 2vw, 1.5rem); box-shadow: 0 24px 50px -30px rgba(10, 14, 24, 0.35); }
.advacct__head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.6rem 1rem; padding-bottom: 0.9rem; border-bottom: 1px solid var(--line); }
.advacct__head .advmock__k { margin: 0; }
.advacct__key { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; color: var(--muted); }
.advacct__key i { width: 9px; height: 9px; border-radius: 3px; }
.advacct__key i + i, .advacct__key i:not(:first-child) { margin-left: 0.5rem; }
.advacct__key .is-own { background: var(--ink); }
.advacct__key .is-wd { background: var(--brand-700); }
.advacct__list { list-style: none; margin: 0; padding: 0; }
.advacct__list li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 0.85rem; padding: 0.85rem 0; border-bottom: 1px solid var(--line); }
.advacct__list li:last-child { border-bottom: 0; padding-bottom: 0.2rem; }
.advacct__av { width: 2.2rem; height: 2.2rem; border-radius: 50%; display: grid; place-items: center; background: var(--soft); color: var(--ink); font-size: 0.72rem; font-weight: 600; }
.advacct__who b { display: block; font-size: 0.92rem; font-weight: 600; color: var(--ink); }
.advacct__who small { display: block; font-size: 0.78rem; color: var(--muted); margin-top: 0.1rem; }
.advacct__m { font-size: 0.78rem; font-weight: 600; border-radius: 99px; padding: 0.32rem 0.7rem; white-space: nowrap; }
.advacct__m { display: inline-flex; align-items: center; gap: 0.4rem; }
.advacct__m::before { content: ""; width: 7px; height: 7px; border-radius: 2px; background: currentColor; }
.advacct__m.is-own { background: #eef0f2; color: var(--ink); }
.advacct__m.is-wd { background: var(--brand-50); color: var(--brand-700); }
.advacct__cap { margin-top: 0.8rem; font-size: 0.82rem; color: var(--muted); }
@media (max-width: 760px) { #models .advwhy .lead { margin-top: 0; } }

/* ---- How it works: four cards on one track ------------------------- */
.advsteps { position: relative; margin-top: clamp(2.6rem, 4.6vw, 3.6rem); gap: clamp(0.9rem, 1.6vw, 1.3rem); }
/* The track runs through the middle of the cards, behind them, so it
   shows only in the gaps between steps. */
.advsteps::before { content: ""; position: absolute; z-index: 0; left: 0; right: 0; top: 50%; height: 2px; transform: translateY(-50%); background: linear-gradient(90deg, var(--brand-100), var(--brand-700)); }
.advsteps li { position: relative; z-index: 1; }
.advsteps li { border-top: 0; background: #fff; border: 1px solid var(--warm-line); border-radius: var(--radius-lg); padding: 2.4rem clamp(1.2rem, 1.8vw, 1.5rem) 1.5rem; margin-top: 0; }
.advsteps li::before { display: none; }
.advsteps__n { position: absolute; top: -1.25rem; left: clamp(1.2rem, 1.8vw, 1.5rem); width: 2.5rem; height: 2.5rem; border-radius: 50%; display: grid; place-items: center; background: #fff; border: 2px solid var(--brand-700); font-size: 0.78rem; }
.advsteps h3 { margin-top: 0.2rem; }
.advsteps__live { position: relative; isolation: isolate; overflow: visible; background: linear-gradient(140deg, var(--brand-900), var(--brand-700)) !important; border-color: var(--brand-900) !important; }
.advsteps__live h3 { color: #fff; }
.advsteps__live p { color: rgba(255, 255, 255, 0.9); }
.advsteps__live .advsteps__n { background: var(--brand-700); color: #fff; border-color: #fff; }
@media (max-width: 980px) {
  .advsteps::before { display: none; }
  .advsteps { row-gap: 2.4rem; }
}

/* ---- Pricing: the closer's rings on the platform card -------------- */
.advplan--main { position: relative; isolation: isolate; overflow: hidden; background: linear-gradient(140deg, var(--brand-900) 0%, var(--brand-700) 100%); }
.advplan--main > *:not(.advplan__pat) { position: relative; z-index: 1; }
.advplan__pat { position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: repeating-radial-gradient(circle at 100% 110%, rgba(255, 255, 255, 0.1) 0 1px, transparent 1px 30px);
  -webkit-mask-image: linear-gradient(300deg, #000 0%, transparent 65%); mask-image: linear-gradient(300deg, #000 0%, transparent 65%); }
.advnote strong { color: var(--ink); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .advmock__sw, .advmock__logo, .advmock__track, .advmock__track span, .advmock__alloc span, .advmock__legend i,
  .advmock__ok, .advmock__cta, .advlead__chip b, .advlead__btn, .advlead__line, .advmock__sw i { transition: none; }
}
.advmock__pickk { flex-basis: 100%; margin: 0 0 0.1rem; }
