:root {
  --ground: #EAE6DE;
  --ground-2: #E4DFD5;
  --raised: #F3EFE7;
  --ink: #1E2230;
  --ink-soft: #474C57;
  --neutral: #857F74;
  --hairline: #CFC8BC;

  /* Brand: from the Rai Wealth Management logo */
  --navy: #1E2C4A;         /* brand navy: tiles, buttons, deep UI */
  --navy-deep: #16213E;    /* deepest navy, footer */
  --gold: #B08D3A;         /* antique gold: large / decorative accents */
  --gold-soft: #C9AC6A;    /* gold for text on dark grounds */
  --gold-ink: #6E5417;     /* AA-safe gold for small text on cream */
  --gold-tint: #ECE2CC;    /* soft gold wash, icon chips */

  /* Accent aliases → decorative gold (kept so existing rules resolve) */
  --clay: #B08D3A;
  --clay-deep: #8A6B22;
  --clay-tint: #ECE2CC;

  --maxw: 1200px;
  --gutter: clamp(20px, 5vw, 64px);
  /* Height of the sticky header. One value, two jobs: it sets the bar itself and
     it sets `scroll-padding-top` on the root, so an anchor jump stops below the
     bar instead of under it. The responsive breakpoints below redefine it rather
     than setting `.nav { height }` directly, so the two can never drift apart. */
  --header-h: 92px;
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 14px;
  --shadow: 0 1px 2px rgba(28,34,48,.05), 0 12px 34px -18px rgba(28,34,48,.24);
  --ease: cubic-bezier(.22,.61,.36,1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: var(--header-h); -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: "Figtree", system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  font-feature-settings: "tnum" 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: "Schibsted Grotesk", system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.017em;
  margin: 0;
  color: var(--ink);
}
p { margin: 0; }
a { color: inherit; text-decoration: none; }

/* Figures on this site are always read inline — "£3,000,000" inside a sentence
   or a headline stat — and never stacked into a column that has to align.
   Tabular figures pad the comma out to a full digit advance, which opens a
   visible gap inside the number, so proportional lining figures are correct. */
.tnum { font-variant-numeric: lining-nums proportional-nums; font-feature-settings: "tnum" 0, "lnum" 1; }

.wrap { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }

.eyebrow {
  font-family: "Figtree", sans-serif;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin: 0 0 18px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.eyebrow::before {
  content: "";
  width: 26px; height: 1px;
  background: var(--clay);
  opacity: .55;
  display: inline-block;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: "Figtree", sans-serif;
  font-weight: 600;
  font-size: 15px;
  line-height: 1;
  padding: 15px 24px;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .35s var(--ease), background .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
  white-space: nowrap;
}
.btn-primary { background: var(--navy); color: #F6F2E9; box-shadow: 0 10px 24px -12px rgba(30,44,74,.55); }
.btn-primary:hover { background: var(--navy-deep); transform: translateY(-2px); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--hairline); }
.btn-ghost:hover { border-color: var(--ink); transform: translateY(-2px); }
.btn-arrow svg { transition: transform .35s var(--ease); }
.btn-arrow:hover svg { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { .btn:hover { transform: none; } }

/* A disabled button had no styling at all, so the double-click guard on every
   form was invisible: .btn sets its own background, colour and cursor, which
   override what the browser would otherwise grey out. The button looked live
   for the whole round trip.
   Opacity and cursor rather than pointer-events:none — that would suppress the
   not-allowed cursor too, which is the one piece of feedback worth having. */
.btn[disabled] { opacity: .55; cursor: not-allowed; }
.btn[disabled]:hover { transform: none; }
.btn-primary[disabled]:hover { background: var(--navy); }
.btn-ghost[disabled]:hover { border-color: var(--hairline); }

:where(a, button, input, textarea, [tabindex]):focus-visible {
  outline: 2.5px solid var(--navy);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- Header ---------- */
header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--ground) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s, background .3s;
}
header.scrolled { border-color: var(--hairline); background: color-mix(in srgb, var(--ground) 92%, transparent); }
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: var(--header-h);
}
.brand { display: flex; align-items: center; gap: 14px; }
.brand-mark {
  width: 56px; height: 56px;
  border-radius: var(--r-md);
  background: var(--navy);
  display: grid; place-items: center;
  flex: none;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.07);
}
.brand-mark img { width: 27px; height: auto; display: block; }
.brand-name {
  font-family: "Schibsted Grotesk", sans-serif;
  font-weight: 600;
  font-size: clamp(20px, 2vw, 24px);
  letter-spacing: -0.015em;
  line-height: 1.05;
  /* The nav carries seven links plus the login pill and the menu button.
     Without this the firm's name breaks onto two lines around 1440px. */
  white-space: nowrap;
}
.nav-links { display: flex; align-items: center; gap: 30px; }
/* Seven links since #28 — six from the client's list plus Planning, which he
   asked for back after the Planning tools shipped. The eighth item on the bar
   is the Client Login pill in .nav-actions. Tighten before the row runs out of
   width. */
@media (max-width: 1500px) { .nav-links { gap: 22px; } }
/* And tighten again through the band above the drawer's handover, which is
   1260px since #28. Turning Client Login into a pill (#25) cost the row 24px it
   did not have; the tightening paid for it and is kept because it is what lets
   the handover sit as low as it does — with seven links there are six gaps, so
   this is worth 24px. The band it covers, 1261-1360, is where the row is under
   pressure, and the wide screens above it are left alone. Measured in headless
   Chrome: with this the longest row on the site fits from 1223px, which is what
   1260 is set from. */
@media (max-width: 1360px) { .nav-links { gap: 18px; } }
.nav-links a {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-soft);
  position: relative;
  white-space: nowrap;
  transition: color .25s;
}
.nav-login { white-space: nowrap; }
.nav-links a::after {
  content: ""; position: absolute; left: 0; bottom: -6px;
  width: 100%; height: 1.5px; background: var(--clay);
  transform: scaleX(0); transform-origin: left;
  transition: transform .3s var(--ease);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after { transform: scaleX(1); }
.nav-actions { display: flex; align-items: center; gap: 14px; }
/* Client Login is the header's only action now. #24 took the "Speak to us"
   ghost button out of this slot and #25 gives the slot to the login, so the
   login takes the ghost button's treatment with it: a hairline pill, ink text,
   the same lift on hover. As a plain text link it read as one more menu item
   that happened to sit outside the menu — the reporter of #25 was pointing at
   the button, and this is the button.

   position: relative is load-bearing: the "Client" word is pulled out of flow
   below 520px (see the block near the foot of this file) and an absolutely
   positioned box with no positioned ancestor lands wherever the page's origin
   is, which on a phone is a fresh 1px of horizontal overflow.

   The label is wrapped in .nav-login-label so that the glyph and the words are
   two flex items rather than three. Left as a bare span plus a text node, the
   7px gap below applies twice and the pill is 4px wider — 4px this row does not
   have at 1201px. .nav-login-label needs no styles of its own; it exists to be
   one box. */
.nav-login {
  font-size: 15px; font-weight: 600; color: var(--ink);
  display: inline-flex; align-items: center; gap: 7px;
  position: relative;
  padding: 10px 12px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  transition: border-color .3s var(--ease), transform .35s var(--ease);
}
.nav-login:hover { border-color: var(--ink); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { .nav-login:hover { transform: none; } }
.nav-login svg { opacity: .7; }
.nav-toggle { display: none; }

/* ---------- Hero ---------- */
.hero { padding: clamp(28px, 5vw, 56px) 0 clamp(52px, 7vw, 92px); }
.hero-grid {
  display: grid;
  grid-template-columns: 1.02fr 1fr;
  gap: clamp(24px, 4vw, 56px);
  align-items: stretch;
}
.hero-copy { align-self: center; padding-right: clamp(0px, 2vw, 20px); }
.hero h1 {
  font-size: clamp(40px, 6.4vw, 74px);
  font-weight: 600;
  letter-spacing: -0.03em;
  margin-bottom: 22px;
}
.hero h1 em {
  font-style: normal;
  color: var(--clay);
}
.hero-lede {
  font-size: clamp(17px, 1.5vw, 19px);
  color: var(--ink-soft);
  max-width: 46ch;
  margin-bottom: 30px;
}
.hero-cta { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 34px; }
.hero-values {
  display: flex; flex-wrap: wrap; gap: 10px 22px;
  padding-top: 26px;
  border-top: 1px solid var(--hairline);
}
.hero-values span {
  font-family: "Schibsted Grotesk", sans-serif;
  font-weight: 600;
  font-size: 15px;
  display: inline-flex; align-items: center; gap: 9px;
  color: var(--ink);
}
.hero-values span::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--clay); display: inline-block;
}
.hero-media {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  min-height: 420px;
  background: var(--ground-2);
  box-shadow: var(--shadow);
}
.hero-media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.hero-media:hover img { transform: scale(1.035); }
@media (prefers-reduced-motion: reduce) { .hero-media:hover img { transform: none; } }
.hero-media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(16,21,34,0) 55%, rgba(16,21,34,.30) 100%);
  pointer-events: none;
}
.hero-badge {
  position: absolute;
  left: 18px; bottom: 18px;
  z-index: 2;
  background: color-mix(in srgb, var(--raised) 92%, transparent);
  backdrop-filter: blur(6px);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: 13px 17px;
  max-width: 260px;
  box-shadow: 0 8px 22px -14px rgba(33,30,26,.5);
}
.hero-badge strong {
  font-family: "Schibsted Grotesk", sans-serif;
  font-size: 15px; display: block; margin-bottom: 2px;
}
.hero-badge small { font-size: 13px; color: var(--ink-soft); line-height: 1.4; }

/* ---------- Section scaffolding ---------- */
section { position: relative; }
.band { padding: clamp(60px, 9vw, 112px) 0; }
.band-raised { background: var(--ground-2); }
.sec-head { max-width: 640px; margin-bottom: clamp(34px, 5vw, 54px); }
.sec-head.center { margin-inline: auto; text-align: center; }
.sec-head.center .eyebrow { justify-content: center; }
.sec-head h2 { font-size: clamp(30px, 4vw, 46px); margin-bottom: 16px; }
.sec-head p { color: var(--ink-soft); font-size: clamp(16px, 1.4vw, 18px); }

/* ---------- About us: the values and the firm, one section ----------

   #28 merged what were two bands (#values and #firm) into one, because the
   client asked for a single "About Us" item in the header rather than two.
   The band keeps one lockup — eyebrow "About us" over the <h2> The Firm
   already carried — and each half now leads with an .about-subhead <h3>.

   The old ids ride on the two halves rather than on the band. They are linked
   from the footer of hand-written pages and may have been shared or indexed,
   and an href to an id nothing carries is not a 404 — it is a silent jump to
   the top of the page, which is worse because nothing reports it. */
.about-part + .about-part { margin-top: clamp(46px, 6vw, 78px); }
/* The Subhead role — the same step the photographic card headlines use, so no
   new number enters the type ramp. It sits one step under the band's Headline
   and one step over the Title the value cards carry, which is what makes the
   merged band read as one section with two halves rather than two sections. */
.about-subhead {
  font-size: clamp(25px, 2.4vw, 30px);
  line-height: 1.15;
  margin-bottom: 22px;
}
.values-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.value-card {
  background: var(--raised);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 30px 28px 32px;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .4s var(--ease);
}
.value-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--clay) 34%, var(--hairline)); }
@media (prefers-reduced-motion: reduce) { .value-card:hover { transform: none; } }
/* h4, not h3: the cards sit under the "What we stand on" subhead inside the
   About Us band, so they are one level deeper than they were when Values was
   a band of its own. The size is unchanged. */
.value-card h4 { font-size: 24px; margin-bottom: 12px; }
.value-card p { color: var(--ink-soft); font-size: 15.5px; }

/* ---------- The firm — the second half of the About Us band ----------

   #61 and #62 turned this half inside out. The portrait used to sit beside a
   single tall column that ran the biography, signed it with the name and title
   at the foot, and then listed four credentials. Two things were wrong with
   that. The name arrived at the very bottom of the section, and the square
   frame left about 700px of empty column under it at 1440px, because the
   narrative was more than twice as tall as the photograph.

   So the left column is the person now — photograph, then name, title and
   firm directly beneath it, then the credentials — and the right column is
   only the narrative. The credentials fill the space the frame used to waste,
   and the two paragraphs that restated them (the NDA/MBA/certifications one
   and the private-banking one) came out: #62 asked for the résumé to be
   brought up under the photograph precisely because saying it twice in one
   section is what the client was reading. */
.firm-grid {
  display: grid;
  grid-template-columns: 0.78fr 1.22fr;
  gap: clamp(28px, 5vw, 64px);
  /* Both columns hang from the top. They are deliberately different lengths —
     the person's column is the longer one now — and centring either against
     the other would read as a mistake rather than a choice. */
  align-items: start;
}
/* The person: photograph, plaque, credentials, as one stack. */
.firm-aside { display: flex; flex-direction: column; gap: 20px; }
.firm-figure { margin: 0; }   /* drop the UA figure margin */
/* The frame. It stays a box of its own rather than becoming the <figure>,
   because the caption sits below it now and this box clips to a square: a
   figcaption inside overflow:hidden with aspect-ratio:1/1 would be cropped
   away. The margin reset stays because the standalone author page,
   prototypes/about-abhineet-rai.html, uses .firm-portrait as its <figure>. */
.firm-portrait {
  position: relative;
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  /* Square, because the founder's headshot is a square original. A 4:5 frame
     would force a 1.25x upscale on a 399px file and read soft. */
  aspect-ratio: 1 / 1;
  background: var(--ground-2);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow);
}
.firm-portrait img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center top;
}
/* The plaque under the photograph: name, then title, then firm. This is the
   only place the name appears in the section — see the comment in index.html
   above the markup. */
.firm-plaque {
  display: flex; flex-direction: column; gap: 2px;
  font-family: "Schibsted Grotesk", sans-serif;
  line-height: 1.35;
  margin-top: 16px;
}
.firm-plaque strong { font-size: 19px; font-weight: 600; letter-spacing: -0.017em; }
/* Gold-Ink is the AA-safe gold for small text on cream, the same role the
   eyebrows and the credential ticks use. */
.firm-role { font-size: 14px; font-weight: 600; color: var(--gold-ink); }
.firm-org { font-size: 14px; font-weight: 500; color: var(--neutral); }
/* The homepage frame carries no figcaption over the image. These overlay rules
   are the standalone author page's: prototypes/about-abhineet-rai.html loads
   this stylesheet and puts a figcaption inside .firm-portrait.who-portrait,
   where the caption is the only place the name appears. */
.firm-portrait figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 34px 22px 18px;
  background: linear-gradient(180deg, rgba(16,21,34,0) 0%, rgba(16,21,34,.72) 100%);
  color: #F4F1E9;
  font-family: "Schibsted Grotesk", sans-serif;
  font-weight: 600; font-size: 14px; line-height: 1.4;
  display: flex; flex-direction: column;
}
.firm-portrait figcaption strong { font-size: 18px; }
.firm-portrait figcaption span { color: var(--gold-soft); font-weight: 500; }
.firm-portrait .ph-glyph {
  width: 76px; height: 76px; border-radius: 50%;
  background: color-mix(in srgb, var(--clay) 16%, var(--raised));
  border: 1px solid color-mix(in srgb, var(--clay) 30%, var(--hairline));
  display: grid; place-items: center;
  color: var(--clay);
  font-family: "Schibsted Grotesk", sans-serif;
  font-weight: 700; font-size: 26px;
  margin-bottom: 16px;
}
.firm-portrait .ph-inner { text-align: center; padding: 0 24px; }
.firm-portrait .ph-inner p { font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; }
.firm-portrait .ph-tag {
  position: absolute; left: 14px; top: 14px;
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-soft);
  background: color-mix(in srgb, var(--raised) 85%, transparent);
  border: 1px solid var(--hairline);
  padding: 5px 9px; border-radius: 999px;
}
/* .firm-body carried the band's <h2> until #28 merged Values and The Firm, and
   the "The firm" <h3> until #62 lifted that out to head both columns. What is
   left here is the narrative. */
.firm-body > p { color: var(--ink-soft); margin-bottom: 18px; max-width: 58ch; }
.firm-body > p:last-child { margin-bottom: 0; }
/* One column, not the two it used to run in: the credentials sit in the
   portrait's column now, which is half the width. The UA list padding goes so
   the ticks line up with the left edge of the photograph above them. */
.cred-list { display: grid; margin: 0; padding: 0; }
.cred-list li {
  list-style: none;
  padding: 13px 0;
  border-top: 1px solid var(--hairline);
  font-size: 15px;
  display: flex; gap: 11px; align-items: flex-start;
}
.cred-list li svg { flex: none; margin-top: 3px; color: var(--gold-ink); }
.cred-list li strong { font-weight: 600; }
.cred-list li small { display: block; color: var(--neutral); font-size: 13px; }
/* The way out of the band and into /about/abhineet-rai/, which is the register
   behind every line of the list above it. Last item in the .firm-aside stack,
   so it takes the stack's gap and needs no margin of its own; Gold-Ink rather
   than Gold-Soft because this sits on cream, not on a dark card. */
.firm-more {
  display: inline-flex; align-items: center; gap: 8px;
  align-self: start;
  font-size: 15px; font-weight: 600;
  color: var(--gold-ink);
  border-bottom: 1px solid var(--hairline);
  padding-bottom: 3px;
}
.firm-more:hover { color: var(--ink); border-bottom-color: var(--gold); }
.firm-more svg { transition: transform .35s var(--ease); }
.firm-more:hover svg { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) { .firm-more:hover svg { transform: none; } }

/* ---------- Services ----------
   Every service is a photographic card that opens its own file page.
   Spans are set per-card with --span on a 6-column track, so the grid
   keeps an editorial rhythm rather than reading as a uniform product grid. */
.svc-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 20px; }
.svc {
  grid-column: span var(--span, 2);
  position: relative;
  overflow: hidden;
  min-height: 400px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  /* navy while the photograph loads, so the cream card text is never
     cream-on-cream during that window (or if the image 404s) */
  background: var(--navy-deep);
  display: flex; flex-direction: column;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .4s var(--ease);
}
.svc img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 1s var(--ease); }
/* Scrim sits on the card, not on the text block, so the amount of photograph
   left visible does not shrink as the copy grows. */
.svc::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(16,21,34,0) 24%, rgba(14,18,30,.60) 54%, rgba(15,20,34,.88) 100%);
  pointer-events: none;
}
.svc:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--clay) 30%, var(--hairline)); }
.svc:hover img { transform: scale(1.045); }
@media (prefers-reduced-motion: reduce) {
  .svc:hover { transform: none; }
  .svc:hover img { transform: none; }
}
.svc-body {
  position: relative; z-index: 2;
  margin-top: auto;
  padding: clamp(24px, 3vw, 32px);
  color: #F6F0E8;
}
/* These cards are read at arm's length on a phone as often as on a desktop,
   so the type holds a near-desktop size all the way down rather than shrinking
   with the card. */
.svc-body h3 { color: #fff; font-size: clamp(25px, 2.4vw, 30px); margin-bottom: 10px; }
.svc-body p { color: rgba(255,255,255,.85); font-size: clamp(16.5px, 1.4vw, 18px); line-height: 1.5; margin: 0 0 16px; max-width: 46ch; }
.svc-more {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 15.5px; font-weight: 600;
  color: var(--gold-soft);
}
.svc-more svg { transition: transform .35s var(--ease); }
.svc:hover .svc-more svg { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) { .svc:hover .svc-more svg { transform: none; } }
.svc-tag { font-size: 12.5px; font-weight: 600; letter-spacing: .04em; color: var(--neutral); text-transform: uppercase; }

.partner-note {
  margin-top: 26px;
  font-size: 14.5px;
  color: var(--ink-soft);
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.partner-note a { color: var(--navy); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

/* ---------- Quote band ---------- */
.quoteband {
  position: relative;
  padding: clamp(72px, 11vw, 132px) 0;
  color: #F6F0E8;
  overflow: hidden;
}
.quoteband .qb-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.quoteband::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(14,19,33,.86) 0%, rgba(16,21,34,.62) 58%, rgba(18,24,40,.44) 100%);
}
.quoteband .wrap { position: relative; z-index: 2; }
.quoteband blockquote {
  margin: 0; max-width: 20ch;
  font-family: "Schibsted Grotesk", sans-serif;
  font-weight: 600;
  font-size: clamp(28px, 4.4vw, 52px);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
.quoteband .qb-sub { margin-top: 24px; max-width: 48ch; color: rgba(246,240,232,.82); font-size: 17px; }

/* ---------- Engagements ---------- */
.cases-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.case {
  background: var(--raised);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 28px 26px 26px;
  display: flex; flex-direction: column;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .4s var(--ease);
}
.case:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--clay) 30%, var(--hairline)); }
@media (prefers-reduced-motion: reduce) { .case:hover { transform: none; } }
.case-fig {
  font-family: "Schibsted Grotesk", sans-serif;
  font-weight: 700;
  font-size: clamp(28px, 3.4vw, 38px);
  letter-spacing: -0.02em;
  color: var(--clay-deep);
  margin-bottom: 6px;
}
.case-label { font-size: 12.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--neutral); margin-bottom: 16px; }
.case p { color: var(--ink-soft); font-size: 15px; }

/* ---------- Testimonials ---------- */
.quotes-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.tcard {
  background: var(--ground);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 34px 34px 30px;
  position: relative;
}
.band-raised .tcard { background: var(--raised); }
.tcard .mark {
  font-family: "Schibsted Grotesk", sans-serif;
  font-size: 60px; line-height: .6;
  color: color-mix(in srgb, var(--clay) 40%, transparent);
  height: 26px; display: block; margin-bottom: 6px;
}
.tcard blockquote { margin: 0 0 22px; font-size: 18px; line-height: 1.5; color: var(--ink); }
.tcard cite {
  font-style: normal; font-weight: 600;
  font-family: "Schibsted Grotesk", sans-serif;
  display: flex; align-items: center; gap: 12px;
}
.tcard cite .dot { width: 34px; height: 34px; border-radius: 50%; background: var(--clay-tint); color: var(--clay-deep); display: grid; place-items: center; font-size: 14px; }
.tcard cite small { display: block; font-weight: 500; color: var(--neutral); font-size: 13px; }

/* ---------- Newsletter ---------- */
.news-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 60px); align-items: center; }
.news-body h2 { font-size: clamp(28px, 3.6vw, 42px); margin-bottom: 16px; }
.news-body p { color: var(--ink-soft); margin-bottom: 12px; max-width: 50ch; }
.news-meta { font-size: 13.5px; color: var(--neutral); font-weight: 600; letter-spacing: .04em; }
.news-form {
  background: var(--raised);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 30px 30px 28px;
  box-shadow: var(--shadow);
}
/* Newsletter: lighter, inline-signup weight */
.news-form--light { background: transparent; border: 0; box-shadow: none; padding: 2px 0 0; }
/* Contact enquiry: the primary action, more presence, navy accent */
.news-form--primary { border-top: 3px solid var(--navy); box-shadow: 0 1px 2px rgba(28,34,48,.05), 0 20px 48px -22px rgba(28,34,48,.34); }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 7px; }
.field input, .field textarea {
  width: 100%;
  font: inherit; font-size: 15.5px;
  padding: 13px 15px;
  border-radius: var(--r-sm);
  border: 1px solid var(--hairline);
  background: var(--ground);
  color: var(--ink);
  transition: border-color .25s, box-shadow .25s;
}
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--navy);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--navy) 18%, transparent);
}
.field textarea { resize: vertical; min-height: 110px; }
/* Checkbox-with-a-sentence. Matches .quiz-consent, which is loaded on this page
   too but belongs to the quiz — a .quiz- class on the contact form would read
   as a copy-paste and invite someone to "tidy up" one of the two. */
.check-line { display: flex; gap: 11px; align-items: flex-start; margin: 18px 0 6px; font-size: 14.5px; line-height: 1.5; color: var(--ink-soft); }
.check-line input { margin: 3px 0 0; width: 17px; height: 17px; flex: none; accent-color: var(--navy); }
.check-line a { text-decoration: underline; text-underline-offset: 2px; }

/* Honeypot. Off-screen rather than display:none — some bots skip hidden fields,
   and the point is that they fill this one. Each instance repeats these rules
   inline so a stylesheet failure cannot reveal it. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-note { font-size: 12.5px; color: var(--neutral); margin-top: 12px; }
.form-msg { font-size: 14.5px; margin-top: 14px; color: var(--clay-deep); font-weight: 600; min-height: 1em; }

/* ---------- Contact ---------- */
.contact-grid { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(28px, 5vw, 60px); }
.contact-info h2 { font-size: clamp(28px, 3.6vw, 42px); margin-bottom: 16px; }
.contact-info > p { color: var(--ink-soft); margin-bottom: 28px; max-width: 44ch; }
.contact-list { list-style: none; padding: 0; margin: 0; }
.contact-list li { display: flex; gap: 14px; align-items: flex-start; padding: 16px 0; border-top: 1px solid var(--hairline); }
.contact-list li:last-child { border-bottom: 1px solid var(--hairline); }
.contact-list .ci-ico { width: 38px; height: 38px; border-radius: 10px; background: var(--clay-tint); color: var(--clay-deep); display: grid; place-items: center; flex: none; }
.contact-list .ci-k { font-size: 12.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--neutral); font-weight: 600; margin-bottom: 2px; }
.contact-list .ci-v { font-size: 15.5px; font-weight: 500; }
.contact-list a.ci-v:hover { color: var(--navy); }

/* ---------- Market notes ticker ----------
   A hairline strip of official UK/EU statistics between the last band and the
   footer. Deliberately colourless: the Two-Metal Rule admits no third accent,
   so direction is carried by the written sign (+0.3% / −0.5%) rather than by
   red and green, which would import the trading-screen look the brief rules
   out. Figures use proportional lining numerals per the Proportional-Figures
   Rule — these read inline, they are not a column that has to align. */
.ticker {
  display: flex;
  align-items: center;
  gap: 22px;
  background: var(--ground-2);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  padding: 0 var(--gutter);
  overflow: hidden;
}
.ticker[hidden] { display: none; }

.ticker-label {
  flex: none;
  margin: 0;
  padding-right: 22px;
  border-right: 1px solid var(--hairline);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold-ink);
  white-space: nowrap;
}

/* The viewport clips; the track is what moves. */
.ticker-viewport { flex: 1 1 auto; overflow: hidden; }

.ticker-track {
  display: flex;
  align-items: center;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  width: max-content;
  animation: ticker-scroll var(--ticker-duration, 64s) linear infinite;
}
/* Pause when someone is trying to read it, or has tabbed into it. */
.ticker:hover .ticker-track,
.ticker:focus-within .ticker-track { animation-play-state: paused; }

@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }   /* the track holds the set twice */
}

.ticker-item {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 15px 0;
  white-space: nowrap;
  font-size: 14.5px;
}
/* Separator between items, drawn rather than typed so it never gets read out. */
.ticker-item::after {
  content: "";
  width: 3px; height: 3px;
  margin: 0 26px;
  border-radius: 50%;
  background: var(--hairline);
  align-self: center;
}
.ticker-k { color: var(--ink-soft); }
.ticker-v {
  font-family: "Schibsted Grotesk", system-ui, sans-serif;
  font-weight: 600;
  font-size: 16px;
  color: var(--ink);
  font-variant-numeric: lining-nums proportional-nums;
  font-feature-settings: "tnum" 0, "lnum" 1;
}
.ticker-d {
  color: var(--ink-soft);
  font-variant-numeric: lining-nums proportional-nums;
  font-feature-settings: "tnum" 0, "lnum" 1;
}
.ticker-t { color: var(--neutral); font-size: 12.5px; }

@media (max-width: 700px) {
  .ticker { flex-direction: column; align-items: stretch; gap: 0; padding-inline: 0; }
  .ticker-label {
    padding: 11px var(--gutter) 0;
    border-right: 0;
    font-size: 11px;
  }
  .ticker-item { font-size: 13.5px; padding: 11px 0 13px; }
  .ticker-v { font-size: 15px; }
  .ticker-item::after { margin: 0 20px; }
}

/* Reduced motion: stop the scroll AND let the list wrap, so the figures past
   the fold are still reachable instead of being clipped out of existence. */
@media (prefers-reduced-motion: reduce) {
  .ticker { padding-block: 4px; }
  .ticker-viewport { overflow: visible; }
  .ticker-track {
    animation: none;
    flex-wrap: wrap;
    width: auto;
    row-gap: 0;
  }
  .ticker-item[aria-hidden="true"] { display: none; }   /* drop the loop clone */
  .ticker-item--last::after { display: none; }
}

/* Edge-to-edge is right for a moving strip — the content is meant to run off
   the sides. It is wrong once reduced motion turns it into a static wrapped
   list on a phone, where the figures would touch the screen edge. */
@media (max-width: 700px) and (prefers-reduced-motion: reduce) {
  .ticker-track { padding-inline: var(--gutter); }
  /* Nothing scrolls here and nothing can be scrolled to, so a figure wider
     than the phone is a figure with its end cut off — the house price runs
     past 390px on its own, before the "(latest published)" qualifier is
     counted. Let the parts break onto a second line instead: same rule as the
     wrapped track above, applied inside the item. */
  .ticker-item { flex-wrap: wrap; white-space: normal; }
}

/* ---------- Footer ---------- */
footer { background: var(--navy-deep); color: #C4C8D4; padding: clamp(52px, 7vw, 80px) 0 34px; }
.foot-top { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 40px; padding-bottom: 40px; border-bottom: 1px solid rgba(255,255,255,.12); }
/* The footer carries the same lockup as the header. The header's chip sits on
   cream, so its own navy does the separating; down here the ground is navy too,
   which leaves the ring to draw the edge. */
.foot-logo { color: #F2EEE6; }
.foot-logo .brand-mark { box-shadow: inset 0 0 0 1px rgba(255,255,255,.12); }
.foot-logo .brand-name { white-space: normal; }
.foot-brand p { margin-top: 20px; font-size: 14.5px; color: #9AA0AE; max-width: 34ch; }
.foot-col h3 { color: #F2EEE6; font-size: 13px; letter-spacing: .1em; text-transform: uppercase; font-weight: 600; margin-bottom: 16px; }
.foot-col ul { list-style: none; margin: 0; padding: 0; }
.foot-col li { margin-bottom: 11px; }
.foot-col a { font-size: 14.5px; color: #A7ADBA; transition: color .2s; }
.foot-col a:hover { color: #F2EEE6; }
/* #74 — the client asked for the LinkedIn mark beside the word, as other
   firms' sites do, so that the logo is part of the link rather than decoration
   next to it. inline-flex keeps the mark centred against a 14.5px line without
   touching the other items in the list, which have no icon and must not gain
   the gap.

   The mark itself is LinkedIn's own "in" bug (.li-mark), carried in the markup
   rather than here: its two fills are fixed brand colours, not tokens, and a
   brand asset may not be recoloured. That is why it does not lift to #F2EEE6
   with the word on hover — the word still does. On this ground the reversed
   (white-square) colourway is the one LinkedIn publishes for dark backgrounds,
   and it is also the only one that holds: LinkedIn Blue #0A66C2 on #16213E is
   2.79:1, under the 3:1 WCAG 1.4.11 floor for a non-text graphic. The white
   square measures 15.89:1. See DESIGN.md, The Third-Party-Mark Exception. */
.foot-col a.foot-social { display: inline-flex; align-items: center; gap: 8px; }
.li-mark { flex: none; }
.foot-legal { padding-top: 30px; display: grid; gap: 18px; }
.risk-warning {
  font-size: 12.5px; line-height: 1.6; color: #969CAB;
  max-width: 100%;
  padding: 16px 18px;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--r-md);
  background: rgba(255,255,255,.02);
}
.risk-warning strong { color: #C9C2B5; }
/* Licence attribution and the "information, not advice" line for the ticker.
   Set to match the risk warning rather than shrunk beneath it — the
   Full-Size-Disclosure Rule applies to the data caveat as much as to the
   capital-at-risk one. */
.data-attribution {
  font-size: 12.5px; line-height: 1.6; color: #969CAB;
  max-width: 100%;
  padding: 16px 18px;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--r-md);
  background: rgba(255,255,255,.02);
}
.data-attribution strong { color: #C9C2B5; }
/* The firm's registered, regulatory and data-controller identity. This was a
   dashed-border placeholder until the details were supplied; the border is now
   the same solid hairline as the risk warning, because it is a statement rather
   than a visible gap. */
.reg-info {
  font-size: 12.5px; color: #A69F92; line-height: 1.6;
  padding: 16px 18px;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--r-md);
  background: rgba(255,255,255,.02);
}
.reg-info strong { color: var(--gold-soft); }
.reg-info a, .risk-warning a { color: #C9C2B5; text-decoration: underline; text-underline-offset: 2px; }
.reg-info a:hover, .risk-warning a:hover { color: #F2EEE6; }
.foot-base { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 14px; padding-top: 8px; font-size: 13px; color: #7E8494; }
.foot-base a { color: #7E8494; }
.foot-base a:hover { color: #CBD0DB; }

/* ---------- Modal ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(28,24,19,.55);
  backdrop-filter: blur(4px);
  display: grid; place-items: center;
  padding: 24px;
  opacity: 0; visibility: hidden;
  /* visibility is switched, never transitioned on the way in, and that is a
     correctness rule rather than a style choice.

     Transitioning it meant the first rendered frame after .open still held the
     start value — hidden — and site.js focuses the close button in that frame.
     focus() on a descendant of a visibility:hidden box is silently dropped, so
     focus stayed on the header link with the dialog open, and the focus trap
     never engaged: it only acts when the active element is already the first or
     last control inside the dialog. Three Tabs then walked to the page behind
     an aria-modal="true" dialog.

     It was a race, which is what made it survive review twice: it reproduces
     intermittently, on the mouse path or the keyboard path depending on the
     run, and a headless browser mostly wins the race and looks fine. Verified
     in HEADED Chrome, which is the only place this is trustworthy.

     `visibility 0s linear .3s` on the way out keeps the 300ms fade: opacity
     animates while visibility holds `visible`, and flips to hidden only once
     the fade has finished. On the way in the delay is 0s, so the computed value
     is `visible` at the first style recalc after .open. */
  transition: opacity .3s var(--ease), visibility 0s linear .3s;
}
.modal-overlay.open {
  opacity: 1; visibility: visible;
  transition: opacity .3s var(--ease), visibility 0s linear 0s;
}
.modal {
  background: var(--ground);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 34px 34px 30px;
  max-width: 420px; width: 100%;
  box-shadow: 0 30px 70px -30px rgba(0,0,0,.5);
  transform: translateY(12px) scale(.98);
  transition: transform .35s var(--ease);
}
.modal-overlay.open .modal { transform: none; }
/* .modal-overlay.open is listed explicitly: it now carries its own transition
   (see the block above), which is two classes and would otherwise out-specify a
   bare .modal-overlay here and reinstate the fade for the one person who has
   asked the operating system not to show them animation. */
@media (prefers-reduced-motion: reduce) { .modal, .modal-overlay, .modal-overlay.open { transition: none; } }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 6px; }
.modal-head h3 { font-size: 22px; }
.modal-close {
  background: transparent; border: 1px solid var(--hairline);
  width: 34px; height: 34px; border-radius: 9px; cursor: pointer;
  display: grid; place-items: center; color: var(--ink-soft); flex: none;
  transition: background .2s, border-color .2s;
}
.modal-close:hover { background: var(--raised); border-color: var(--ink); }
.modal .lock { width: 46px; height: 46px; border-radius: 12px; background: var(--clay-tint); color: var(--clay-deep); display: grid; place-items: center; margin-bottom: 18px; }
.modal p.mp { font-size: 15px; color: var(--ink-soft); margin-bottom: 18px; }
.modal .notice {
  font-size: 13.5px; color: var(--ink-soft);
  background: var(--clay-tint);
  border: 1px solid color-mix(in srgb, var(--clay) 22%, var(--hairline));
  border-radius: var(--r-sm);
  padding: 13px 15px; margin-bottom: 20px;
  display: flex; gap: 10px; align-items: flex-start;
}
.modal .notice svg { flex: none; margin-top: 2px; color: var(--clay-deep); }
.modal .btn { width: 100%; }
.modal .modal-alt { text-align: center; font-size: 13.5px; color: var(--neutral); margin-top: 16px; }
.modal .modal-alt a { color: var(--navy); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Reveal (fail-open: hidden state applies ONLY when JS enables it) ---------- */
html.reveal-on [data-reveal] { opacity: 0; transform: translateY(22px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
html.reveal-on [data-reveal].is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { html.reveal-on [data-reveal] { opacity: 1 !important; transform: none !important; transition: none; } }

.skip {
  position: absolute; left: 12px; top: 12px; z-index: 200;
  background: var(--ink); color: var(--ground);
  padding: 10px 16px; border-radius: 8px; font-weight: 600; font-size: 14px;
  transform: translateY(-160%);
  transition: transform .2s var(--ease);
}
.skip:focus { transform: translateY(0); }

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-media { min-height: 340px; order: -1; }
  .firm-grid { grid-template-columns: 1fr; }
  /* The founder's photograph did not render on a phone at all — reported by
     the client on #28, point 5. Below 960px this rule read
     `max-width: 360px; margin-inline: auto`, and that is a 0x0 image.

     Why. A grid item with an auto inline margin is not stretched to its track:
     the auto margins absorb the free space, and the box is sized to its own
     content instead. .firm-portrait's only content is an absolutely positioned
     <img>, which is out of flow and contributes nothing, so the content width
     resolved to 0 — and aspect-ratio: 1/1 made the height 0 with it. The
     figure measured 2x2 (its two 1px borders) and the image 0x0 at every width
     from 320 to 960, with the file itself loaded and complete. It was not a
     loading fault, a path fault or a `loading` attribute fault, which is why
     nothing in the network panel showed it.

     An explicit width is the fix: the box no longer has to be sized from its
     (empty) content, so the auto margins have real free space to centre and
     the aspect ratio has a real width to work from. Do not put this back to
     `max-width` + `margin-inline: auto` — that combination is the bug.

     Since #62 the frame is one box inside .firm-aside rather than the grid
     item itself, so the auto margins have nothing left to absorb and this rule
     resolves to the same 360px the stack below gives it. It stays as the guard
     the measurement bought: the box is still sized from an absolutely
     positioned child, and the next person to make it a grid item again would
     otherwise reintroduce a 0x0 portrait silently. */
  .firm-portrait { width: min(100%, 360px); margin-inline: auto; }
  /* The whole stack — photograph, plaque, credentials — takes the same width
     and the same centre, so the name sits directly under the frame and the
     credential ticks under its left edge. This is the grid item now, and it is
     sized with `width`, not `max-width`, for the reason above. */
  .firm-aside { width: min(100%, 360px); margin-inline: auto; }
  .contact-grid, .news-grid, .quotes-grid { grid-template-columns: 1fr; }
  .svc { grid-column: span 3; min-height: 320px; }
}
/* Nav fit: the row is the brand lockup, the links and Client Login, and every
   one of them is nowrap, so there is nothing left to give once the gaps are
   tightened. An over-wide header drags the whole document sideways — the defect
   6ff1da9 fixed for phones — so the drawer has to take over at the width the row
   actually stops fitting, and that width is 1200.

   Two separate holes this closes, both measured in headless Chrome:

   1. The drawer used to take over at 960, but the row had not fitted at 960 for
      some time. The home page header ran 162px past a 961px viewport, 108px past
      1024 and still 9px past 1160.

   2. Worse, and the real reason this is worth doing: above the old 1200px guard
      the "Speak to us" ghost button reappeared, and the row with it did not fit
      either. Swept in 20px steps across the band and 4px near its top edge, the
      home page was wider than the viewport at every width from 1220 to 1432 and
      clear again only at 1436 — 78px over at 1280 and about 35px at 1366, the
      two commonest laptop viewports there are. The band opens at 1201, where the
      old guard stops applying and the button reappears. Removing the ghost button
      is what closes that band; this breakpoint closes the one below it.

   The cost is real and it is not uniform. With the nav forced visible the rows
   fit from 1192px (home), 1032px (service and newsletter pages) and 880px (the
   Risk Profiler, whose row is shortest). Handing over at a single 1200 therefore
   takes a fitting desktop nav away from the Risk Profiler across a 320px band,
   and from the service and newsletter pages across ~170px. One breakpoint for
   the whole site was judged worth more than per-page thresholds, and #28
   reshapes this row anyway — revisit the number there.

   #28 is that revisit. It went to 1140 first and then to 1260, and the two
   numbers are worth keeping side by side because they are the same measurement
   taken of two different rows.

   #28 first cut the row to seven items — @abhineetrai's list — and made it the
   same seven on every page, where before the home page carried three items the
   service and newsletter pages did not. That closed the spread almost entirely:
   the rows fitted from 1110px on the home page and the Risk Profiler (both
   carry the gold "new" dot beside Risk Profiler, which quiz.css only ships to
   those two pages) and from 1092px everywhere else with a nav. 1140 was set
   from that.

   Then the client asked for Planning back, as an eighth item. That is the
   longest this row has ever been, and it costs about what you would expect: the
   fitting widths go to 1223px (home, Risk Profiler) and 1196px (service,
   archive, issue, Planning). privacy.html and disclaimer.html carry no nav at
   all and fit below 600px either way. One breakpoint still costs at most 27px
   of band.

   1260 rather than 1223 for the same reason 1140 was not 1110: the measurement
   is taken in headless Chrome, which draws overlay scrollbars. A classic 15-17px
   scrollbar takes that width out of the layout viewport, so a row that fits at
   1223 here needs about 1240 on a machine that shows one. 1260 clears that by
   20px, and it keeps the desktop nav on 1280, 1366, 1440 and 1600 — at 1280,
   the tighter of the two common laptop viewports, the row has 57px of slack on
   the bench and about 40px with a classic scrollbar.

   The band this gives up is 1141-1260, and that is the honest price of the
   eighth item rather than an oversight.

   Note the gap tiers interact with this and are all clear: 1261-1360 uses the
   18px gaps these figures were measured with; above 1360 the gaps widen to 22px,
   which costs six gaps x 4px = 24px, so the row wants ~1247 and has 114px of
   room at 1361; above 1500 the 30px gaps want ~1271 against 1501.

   Re-measure before moving it again: sweep with .nav-links forced visible and
   .nav-toggle forced hidden, and binary-search the narrowest viewport where
   document.documentElement.scrollWidth - window.innerWidth is 0. An earlier
   issue in this batch shipped a sideways scroll at 1280 and 1366 because a
   breakpoint was inherited rather than measured. */
@media (max-width: 1260px) {
  .nav-links { display: none; }
  .nav-toggle {
    display: inline-grid; place-items: center;
    width: 42px; height: 42px; border-radius: 10px;
    background: transparent; border: 1px solid var(--hairline); cursor: pointer; color: var(--ink);
  }
}
@media (max-width: 960px) {
  :root { --header-h: 82px; }
  .brand-mark { width: 48px; height: 48px; }
  .brand-mark img { width: 23px; }
}
@media (max-width: 760px) {
  .values-grid { grid-template-columns: 1fr; }
  .cases-grid { grid-template-columns: 1fr; }
  .svc-grid { grid-template-columns: 1fr; }
  .svc { grid-column: auto; min-height: 340px; }
  .foot-top { grid-template-columns: 1fr; gap: 30px; }
  .contact-grid { grid-template-columns: 1fr; }
}

/* ---------- The phone header: brand, client login, menu ----------

   Below the drawer's handover (1200px when this was written, 1260px since #28)
   the row is three things — the brand lockup, Client Login and
   the menu button — and all three are on one line down to 320px. The header
   used to run wider than the viewport on every page from 421px down (72px over
   at 430, 34px over at 390), which dragged the whole document sideways. The
   fix for that was font-size:0 on the client-login label, which bought the
   width back and left a padlock with no words as the only client-login
   affordance on a phone.

   #25 is a client saying he could not find the client login. An unlabelled
   icon is the likeliest reason: a padlock is a recognised affordance for
   "locked", not for "your account is through here". So the label comes back,
   and the width it needs is taken out of the brand lockup instead — each of
   the three tiers below is the tier that used to sit one band narrower.

   Every number here was measured in headless Chrome at 10px steps from 320 to
   1440 on the home page, a service page, the Risk Profiler, the newsletter,
   privacy and disclaimer, reading document.scrollWidth - window.innerWidth.
   Nothing overflows at any of them. If you change a font size or a padding in
   this section, re-measure — the margins at 375px and 430px are the thin ones. */

/* 561px and down: the lockup drops a size, so a labelled login fits beside it.
   This tier used to start at 420. It has to start here because the full
   "Client Login" pill is still on show down to 521, and at 521-534 the
   full-size lockup left it 13px short. */
@media (max-width: 560px) {
  :root { --header-h: 76px; }
  .nav { gap: 12px; }
  .nav-actions { gap: 10px; }
  .brand { gap: 10px; }
  .brand-name { font-size: 17px; }
  .brand-mark { width: 42px; height: 42px; border-radius: var(--r-sm); }
  .brand-mark img { width: 20px; }
}

/* 520px and down: the label sheds its first word rather than all of them.
   "Client" is pulled out of flow and "Login" stays visible, which is 58px
   narrower than the full label. It is clipped rather than removed, so the
   accessible name stays "Client Login" and the visible word is contained in
   it — what WCAG 2.5.3 asks for. */
@media (max-width: 520px) {
  /* The padding is doing real work: without it the pill is barely taller than
     its text next to a 42px menu button. It buys back most of the height a
     thumb needs without costing the width the overflow fix just recovered. */
  .nav-login { font-size: 13px; gap: 6px; padding: 10px 11px; }
  .nav-login-word {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .nav-login svg { opacity: .85; }

  /* The only .nav-actions ghost button left on the site is "Back to the site"
     on privacy.html and disclaimer.html, whose headers carry nothing else but
     the brand — no links, no drawer. It fits everywhere down to 521px and runs
     the header 41px past a 390px viewport, so it goes here rather than at the
     1200px it used to share with the removed "Speak to us" button. The brand
     lockup is itself a link home, so nothing becomes unreachable. */
  .nav-actions .btn-ghost { display: none; }
}

/* 420px and down — the iPhone-class widths, and the ones this issue is really
   about. This tier used to start at 360. */
@media (max-width: 420px) {
  .brand-name { font-size: 14px; }
  .brand-mark { width: 36px; height: 36px; }
  .brand-mark img { width: 17px; }
  .nav-toggle { width: 38px; height: 38px; }
}

/* 370px and down: 320-360px phones, where even the smallest lockup and the
   shortest label are 42px too wide for the line between them.

   The name wraps instead of disappearing. .brand-name is nowrap everywhere
   else because the firm's name breaking in two looks like a mistake at desktop
   widths — on a 320px phone it is the only way to keep the name and the
   client's door on the same bar, and it reads as a deliberate two-line lockup
   rather than an accident. min-width:0 is what lets the flex item shrink to it
   at all; without that, nowrap or not, the row cannot give. */
@media (max-width: 370px) {
  .brand { min-width: 0; }
  .brand-name { white-space: normal; font-size: 13px; line-height: 1.1; }
}

/* Mobile nav sheet

   The drawer is `position: fixed; inset: 0` and site.js puts `overflow: hidden`
   on <body> while it is open, so the drawer is the only thing on the page that
   can scroll. It could not: `overflow-y` defaulted to visible, so items past the
   bottom edge were unreachable rather than merely off-screen — no wheel, no
   drag, no keyboard. Measured with the drawer open at 390x659 (an iPhone 12 in
   Safari, once ~185px of browser chrome comes off the 844px screen): the eight
   items plus the Client Login button run to 706px and "Client Login" sat 47px
   past the fold with `msheet.scrollTop` pinned at 0. At 375x553 (an iPhone SE)
   "Contact Us" went too, and the same happened in any short desktop window.

   `overscroll-behavior: contain` stops a flick at the end of the list from
   handing the scroll to the page underneath. The safe-area padding keeps the
   last item clear of the home indicator on a notched phone; it resolves to the
   old 40px everywhere that reports no inset. */
.msheet {
  display: none;
  position: fixed; inset: 0; z-index: 90;
  background: var(--ground);
  padding: 104px var(--gutter) 40px;
  padding-bottom: max(40px, env(safe-area-inset-bottom, 0px));
  flex-direction: column; gap: 4px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.msheet.open { display: flex; }
.msheet a { font-family: "Schibsted Grotesk", sans-serif; font-weight: 600; font-size: 26px; padding: 14px 0; border-bottom: 1px solid var(--hairline); }
.msheet .btn { margin-top: 24px; }
