/* ============================================================================
   WEBFONTS — self-hosted (§08, §20). No third-party request, so nothing here
   needs explaining in the privacy notice.

   Both are variable fonts subset to the 140 characters this site actually
   uses. One file per family covers every weight the design calls for: 400
   body and headings, 500 UI, 600 wordmark. Kerning and ligatures are intact.
   font-display:swap so text is readable before the font lands.

   WOFF, not WOFF2: see README. The files are self-hosted either way, which
   is what §24 required.
   ============================================================================ */
@font-face{
  font-family:'Archivo';
  src:url('fonts/archivo-variable.woff') format('woff');
  font-weight:100 900;
  font-style:normal;
  font-display:swap;
}
@font-face{
  font-family:'Newsreader';
  src:url('fonts/newsreader-variable.woff') format('woff');
  font-weight:200 800;
  font-style:normal;
  font-display:swap;
}

/* ============================================================================
   ARKANA WEALTH — site.css
   Migrated from the Claude Design project "Arkana Wealth Homepage".
   Plain CSS. No framework, no build step, no design-system bundle.

   TOKENS FIRST (§23.3). Every colour, type size, spacing value and motion
   timing in this file is declared once below and referenced by name after.
   No hex value, font name, duration or spacing number appears outside the
   token block.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   01 — TOKENS · COLOUR (§07)
   ---------------------------------------------------------------------------- */
:root{
  /* Base palette — the seven brand colours */
  --limestone:#FAF8F4;      /* page ground */
  --bath:#F2EEE7;           /* alternating band ground */
  --ink:#16181C;            /* headings, body, footer ground, primary button */
  --graphite:#3A3E45;       /* lede paragraphs */
  --slate:#61656D;          /* captions, labels, rail notes */
  --chalk:#DFDAD1;          /* decorative dividing lines only */
  --bodleian:#1C3A5E;       /* links, markers, focus ring */
  --bodleian-deep:#132B47;  /* link and button hover */
  --claret:#8B2C1F;         /* the only error colour */

  /* Footer-only, on ink ground */
  --footer-body:#B9BEC5;
  --footer-muted:#8C939C;
  --footer-line:#2C3037;

  /* Composite grounds */
  --tint-hover:rgba(28,58,94,.028);    /* row hover — 2.8% bodleian */
  --tint-header:rgba(250,248,244,.92); /* header ground once scrolled */
  --tint-scrim:rgba(22,24,28,.55);     /* dialog backdrop — 55% ink */

  /* Semantic aliases — use these in components, not the raw values */
  --surface-page:var(--limestone);
  --surface-alt:var(--bath);
  --surface-inverse:var(--ink);
  --surface-hover-tint:var(--tint-hover);
  --surface-header-scrolled:var(--tint-header);
  --surface-scrim:var(--tint-scrim);

  --text-heading:var(--ink);
  --text-body:var(--ink);
  --text-lede:var(--graphite);
  --text-muted:var(--slate);
  --text-inverse:var(--limestone);
  --text-link:var(--bodleian);
  --text-link-hover:var(--bodleian-deep);
  --text-error:var(--claret);

  --border-hairline:var(--chalk);
  --border-field:var(--slate);   /* UI component boundary — 3:1, SC 1.4.11 */
  --border-strong:var(--ink);
  --border-inverse:var(--footer-line);

  --accent:var(--bodleian);   /* links, focus ring, progress hairline, hover tint */
  --marker:var(--ink);        /* every decorative diamond — never the accent */
  --focus-ring:var(--bodleian);
  /* The same ring, in the one place the page turns dark. --focus-ring is
     Bodleian blue, which reads clearly on the limestone ground (8.5:1) but
     only 1.54:1 against the footer's ink — below the 3:1 WCAG 2.2 asks of a
     focus indicator, so keyboard focus was effectively invisible down there.
     Reusing --text-inverse rather than inventing a colour keeps the ring in
     the footer's own palette: it is exactly the colour a footer link already
     turns on hover. Applied by the .ftr :focus-visible rule in §14.8, which
     overrides the colour only — width, offset and radius stay global, so the
     indicator is the same shape everywhere on the site. */
  --focus-ring-inverse:var(--text-inverse);
}

/* ----------------------------------------------------------------------------
   02 — TOKENS · TYPOGRAPHY (§08)
   ---------------------------------------------------------------------------- */
:root{
  --serif:'Newsreader',Georgia,'Times New Roman',serif;
  --sans:'Archivo',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --font-display:var(--serif);
  --font-body:var(--serif);
  --font-ui:var(--sans);

  /* Display */
  --fs-h1:clamp(38px,5.6vw,64px);
  --fs-h2:clamp(28px,3.4vw,40px);
  --fs-h3:24px;
  --fs-h3-sm:22px;
  --fs-h3-xs:21px;

  /* Reading */
  --fs-body:19px;
  --fs-body-sm:18px;
  --fs-lede:22px;
  --fs-prose:17.5px;
  --fs-prose-sm:17px;

  /* UI */
  --fs-ui:15px;
  --fs-ui-sm:14px;
  --fs-caption:16px;
  --fs-label:12.5px;
  --fs-eyebrow:12px;
  --fs-fine:13.5px;
  --fs-field:18px;          /* form input / textarea */
  --fs-mnav:30px;           /* mobile menu link */

  /* Line heights */
  --lh-h1:1.06;
  --lh-h2:1.18;
  --lh-h3:1.32;
  --lh-body:1.62;
  --lh-lede:1.55;
  --lh-ui:1.6;
  --lh-rail:1.5;
  --lh-footer:1.9;

  /* Tracking */
  --ls-h1:-.02em;
  --ls-h2:-.015em;
  --ls-eyebrow:.18em;
  --ls-step:.16em;
  --ls-label:.1em;
  --ls-nav:.02em;

  /* Weights */
  --fw-regular:400;
  --fw-medium:500;

  /* Underlines */
  --ul-offset:.18em;
  --ul-offset-ui:.2em;
  --ul-thickness:1px;
  --ul-thickness-hover:1.5px;
}

/* ----------------------------------------------------------------------------
   03 — TOKENS · MEASURE (§08, §09)
   Maximum paragraph measure plus the per-element measures the design sets.
   ---------------------------------------------------------------------------- */
:root{
  --measure:680px;          /* maximum paragraph measure */
  --measure-hero-h1:14ch;
  --measure-hero-lede:46ch;
  --measure-about-h2:26ch;
  --measure-services-h2:19ch;
  --measure-process-h2:20ch;
  --measure-practice-h2:21ch;
  --measure-insights-h2:22ch;
  --measure-contact-h2:16ch;
  --measure-svc-copy:56ch;
  --measure-status:52ch;
  --measure-privacy-note:46ch;
  --measure-ftr-brand:36ch;
  --measure-ftr-legal:104ch;
  --measure-cookie-copy:74ch;
  --measure-cookie-prefs:640px;
  --measure-404-h1:16ch;
}

/* ----------------------------------------------------------------------------
   04 — TOKENS · SPACING AND GRID (§09)
   Source values. Not snapped to a 4 or 8px grid — do not "tidy" them.
   ---------------------------------------------------------------------------- */
:root{
  --container:1280px;
  --rail:230px;
  --gutter:56px;
  --margin:80px;
  --hdr-h:88px;
  --hdr-h-sm:66px;

  --band-y:120px;
  --band-y-sm:76px;
  --band-y-md:96px;         /* tablet — between the mobile and desktop bands */
  --margin-md:48px;
  --art-hero-md:420px;
  --band-air-y:132px;       /* About — condensed column, a little more air */
  --band-air-y-sm:84px;
  --rule-y:64px;
  --rule-y-sm:44px;
  --row-y:36px;
  --row-y-sm:30px;

  --stack-1:8px;
  --stack-2:10px;
  --stack-3:18px;
  --stack-4:22px;
  --stack-5:26px;
  --stack-6:28px;
  --stack-7:52px;

  --radius:2px;
  --hairline:1px;
  --tap-min:48px;
  --tap-alt:48px;          /* §17 — was 44 in the source design */

  /* Illustration slots (§11.1) */
  /* The hero streetscape and the skyline are the only two elements allowed
     past the text column: both are panoramas, and stopping them at the reading
     measure is what made them read as inset pictures rather than views. The
     bleed is the viewport's own gutter, capped at the page margin — so it is
     exactly 0 until the container stops growing at 1280px, and it can never
     bring artwork closer to the screen edge than the gutter itself. No media
     query, no viewport-width overflow. */
  --art-bleed:clamp(0px, calc((100vw - var(--container)) / 2), var(--margin));
  /* The hero bleeds out of the content column, but no further than the page's
     own margin line: the drawing stops exactly where a full-width .wrap's
     padding edge would fall, so it reads as deliberate bleed rather than as
     artwork sliding off the screen. Same expression as --art-bleed above, with
     a wider cap — the skyline is capped at the margin, the hero at 220px, which
     is what stops it growing without limit on a very wide monitor.
     It was previously allowed to run to within 40px of the screen edge
     (--art-hero-edge, now removed): at 1440 that put the drawing 33px from the
     edge while every other element on the page stopped 152px from it, and the
     founder read that asymmetry as the hero falling off the page (2026-09-07,
     Option D). */
  --art-bleed-hero:clamp(0px, calc((100vw - var(--container)) / 2), 220px);
  --art-hero:760px;
  --art-hero-sm:320px;
  /* The service and practice drawings are sized by HEIGHT, not by a box side:
     see the optical-scale block in the ILLUSTRATIONS section. */
  --art-svc:118px;
  --art-svc-sm:84px;
  --art-prac:104px;
  --art-prac-md:118px;      /* at 1080 the practice grid halves its columns */
  --optical-prac-tallest:1.1;  /* the largest --optical of the three, below */

  /* Brand lockups.
     Two supplied files, two different shapes — not one logo in two colours:
       arkana-logo.svg                  355.4 x 97.4  wide, mark then wordmark
                                                      header and mobile menu
       arkana-logo-stacked-inverse.svg  189.6 x 225   tall, mark over wordmark
                                                      footer, drawn inline
     (assigned this way round 2026-09-11; sizes are the artwork's bounds)
     Height drives the size; width follows the file. The width/height ATTRIBUTES
     in the markup must match these heights: they are what reserves the box
     before the file loads, and what a browser with CSS off falls back to. */
  /* Ranges, not numbers: the lockup grows with the window instead of sitting
     at one size on a laptop and looking lost on a 27-inch monitor. Raised
     2026-09-10 from a flat 48 / 38 / 40 / 42 / 34.

     The ceiling is the header bar: 88px at rest, so 64px leaves 12px of air
     above and below. THE FLOOR IS THE GRID TRACK, and it is the reason the
     middle term is a slope rather than something gentler. The header is
     1fr auto 1fr with the navigation in the middle, so the brand's track is
     (container - nav - two gaps) / 2 — measured at 144.9px when the window is
     861px, the first pixel at which the navigation appears, and growing about
     0.4px per px of window from there. The lockup does not widen that track:
     the reset's img{max-width:100%} makes its minimum contribution nothing, so
     the track is the header's free space and the lockup has to fit inside it.
     The current artwork is 3.64753 : 1, so 144.9px of track is 39.7px of
     height, and anything taller is trimmed by the track while its height stays
     put — object-fit:contain then scales it down inside its box rather than
     letting it deform, but it is still smaller than it says it is. The middle
     term therefore follows the track's own growth with about 3% of headroom,
     reaching the 64px ceiling at roughly 1104px. Re-fitted 2026-09-10 when the
     final artwork replaced the earlier 3.3368 : 1 lockup; it was 11.5vw - 57px
     against that shape. **Re-measure the track at 861px before changing it.** */
  --brand-logo-h:clamp(38px, 10.6vw - 53px, 64px);        /* header, at rest */
  /* Tied to the value above rather than declared again, so the scrolled state
     cannot drift out of proportion — or out of the track it also has to fit. */
  --brand-logo-h-sm:calc(var(--brand-logo-h) * 0.75);     /* header, scrolled */
  --brand-logo-h-mnav:clamp(42px, 11vw, 46px);            /* mobile menu panel */
  /* Below 860px the navigation collapses into the menu button, so the track
     stops being the constraint and the bar (72px, 62px scrolled) is. */
  --brand-logo-h-phone:clamp(44px, 12vw, 48px);
  --brand-logo-h-phone-sm:calc(var(--brand-logo-h-phone) * 0.8);
  /* Footer — taller, because the words stack under the mark, and a range for
     the same reason the header lockup is one. At the 96px floor the wordmark's
     caps land at about 12px against 14px footer text; at the 118px ceiling,
     about 15px, which is where the lockup reads as a mark rather than as more
     text. Raised 2026-09-10 from a flat 88px.

     The width and height ATTRIBUTES on the inline SVG in all 14 footers are
     not a second copy of this number — they carry the RATIO (74.13 / 88 =
     0.84242), which is what width:auto scales by. Keep them proportional to
     each other; they do not have to match the heights here. */
  --ftr-logo-h:clamp(96px, 5rem + 3vw, 118px);

  /* Bare mark. No page uses .mark, and the standalone mark file went with the
     Oxonian assets (2026-09); the rule and its token are left alone because
     the Arkana mark exists as artwork and a future page may want it. */
  --mark:38px;
  --brand-gap:14px;

  /* Markers and arrows */
  --marker-w:7px;
  --marker-h:11px;
  --marker-sm-w:5px;
  --marker-sm-h:8px;
  --arrow-w:6px;
  --arrow-h:9px;
  --arrow-nudge:4px;
  --eyebrow-gap:12px;

  /* Hero */
  --hero-offset:72px;       /* below the resting header */
  --hero-lede-gap:30px;
  --hero-acts-gap:24px;
  --hero-acts-top:40px;

  /* Two-column reading grids */
  --duo-gap:80px;
  --duo-gap-hero:32px;      /* hero only — the drawing sits closer to its copy */
  --duo-gap-md:48px;
  --duo-gap-sm:56px;
  --grid-gap-sm:32px;       /* stacked grids below 860px */

  /* Annotation rail */
  --rail-top-gap:40px;
  --rail-indent:16px;
  --rail-pad-sm:8px;

  /* Service rows */
  --svc-art-col:168px;
  --svc-art-gap:36px;       /* artwork-to-heading gap on a service row */
  --svc-art-col-sm:112px;
  --svc-gap-sm:22px;
  --svc-rowgap-sm:14px;

  /* Insight notes */
  --note-pad:24px;
  --note-meta-gap:8px;
  --note-meta-bot:16px;
  --note-title-bot:12px;
  --note-underline:1px;
  --byline-gap:6px;         /* metadata line to byline — one block, read together */
  --byline-bot:20px;        /* byline to headline */
  --rail-x-pad:12px;
  --rail-x-focus-offset:8px;
  --rail-x-basis-sm:86%;

  /* Header and navigation */
  --hdr-gap:64px;
  --hdr-gap-md:36px;
  --nav-gap:38px;
  --nav-gap-md:28px;
  --nav-underline-gap:7px;
  --nav-marker-drop:3px;
  --mnav-pad-y:24px;
  --mnav-top-min:42px;
  --mnav-list-top:52px;
  --mnav-list-gap:8px;
  --mnav-link-pad:10px;
  --mnav-foot-top:48px;
  --mnav-foot-pad:24px;
  --menu-btn-pad:12px;
  --hdr-blur:14px;
  --hdr-saturate:140%;

  /* Buttons and links */
  --btn-pad-y:13px;
  --btn-pad-x:28px;
  --btn-disabled-alpha:.55;
  --tlink-gap:10px;

  /* Forms */
  --field-pad-y:10px;
  --field-select-pad-y:12px;
  --textarea-min:112px;
  /* 500 characters — the field's own maxlength — need 187px at 768, 243px at
     1440 and 299px at 1024, which is the widest the wrapped text ever gets on
     a real column. 320px therefore shows a full-length message with no internal
     scrolling at every width from tablet up, and caps the drag handle so the
     field cannot be pulled down the page indefinitely. On a phone the column is
     narrow enough that 500 characters genuinely need ~466px, so the viewport
     term takes over and the field scrolls inside itself instead of swallowing
     the screen. Measured, not guessed — see §14.7. */
  --textarea-max:320px;
  --field-err-top:8px;
  --field-bad-width:2px;
  --form-foot-top:8px;
  --form-status-bot:20px;
  --form-submit-gap:20px;   /* Send enquiry button to the Turnstile check */
  --form-done-pad-y:22px;
  --form-done-bar:2px;
  --turnstile-gap:14px;
  --turnstile-min:300px;  /* Cloudflare's widget will not render narrower */

  /* 404 — the only centred page on the site */
  --e404-acts-top:38px;
  --e404-acts-gap:14px;
  --e404-y:76px;            /* air above and below the block, symmetric */

  /* Contact block */
  --contact-copy-top:26px;
  --contact-address-top:32px;
  /* Common questions beneath the contact introduction */
  --faq-top:44px;           /* introduction to the questions (row gap, >860px) */
  --faq-q-pad:13px;         /* above and below a question — 48px row, tap-sized */
  --faq-icon:12px;          /* the plus that becomes a minus */

  /* Footer */
  --ftr-y-top:52px;
  --ftr-y-bot:32px;
  --ftr-gap:56px;
  --ftr-brand-gap:14px;
  --ftr-head-bot:20px;
  --ftr-social-chip:38px;
  --ftr-social-glyph:17px;
  --ftr-nav-social-inset:14px;  /* holds the LinkedIn chip off the content edge */
  --ftr-nav-gap:38px;
  --ftr-nav-gap-md:28px;
  --ftr-nav-gap-sm-x:26px;
  --ftr-nav-gap-sm-y:20px;
  --ftr-nav-top:30px;
  --ftr-nav-top-sm:26px;
  --ftr-nav-pad:20px;
  --ftr-legal-top:30px;
  --ftr-legal-top-sm:26px;
  --ftr-legal-pad:20px;
  --ftr-legal-line:9px;
  --ftr-base-top:16px;
  --ftr-base-gap:20px;
  --ftr-minor-gap:26px;
  --ftr-top-gap-sm:24px;

  /* Cookie consent shell */
  --cc-pad-top:26px;
  --cc-pad-bot:28px;
  --cc-pad-top-sm:22px;
  --cc-pad-bot-sm:24px;
  --cc-gap-sm:22px;
  --cc-acts-gap:14px;
  --cc-btn-min:158px;
  --cc-prefs-gap:18px;
  --cc-prefs-top:24px;
  --cc-prefs-pad:22px;
  --cc-row-gap:14px;
  --cc-box:18px;
  --cc-box-nudge:2px;

  /* Complaints dialog */
  --cmp-max:560px;
  --cmp-inset:20px;         /* clear of the viewport edge on a phone */
  --cmp-pad:28px;
  --cmp-pad-sm:22px;
  --cmp-body-top:16px;      /* heading row to the first paragraph */
  --cmp-gap:14px;
  --cmp-close-nudge:10px;   /* pulls the 48px target onto the box edge */
  --cmp-close-glyph:14px;

  /* Skip link */
  --skip-pad-y:14px;
  --skip-pad-x:22px;
  --skip-inset:12px;
  --offscreen:-9999px;

  /* Focus */
  --focus-width:2px;
  --focus-offset:3px;
  --focus-offset-field:4px;
  --focus-radius:1px;

  /* Interior pages, prose and risk warnings */
  --page-head-y:64px;       /* below the hero offset, interior pages sit tighter */
  --prose-h2-top:44px;
  --prose-h2-bot:14px;
  --prose-cta-top:52px;
  --risk-pad:18px;
  --risk-bar:2px;
  --risk-top:44px;
  --risk-line-gap:10px;     /* the tax sentence, set on its own line */
  --icon-btn:48px;          /* rail arrows — full tap target (§09, §17) */
  --portrait-ratio:4 / 5;
  --portrait-max-sm:260px;  /* stacked on a phone: one portrait, not a screenful */

  --icon-glyph:20px;
  --icon-stroke:1.6px;

  /* Oxford skyline — a wide band, not a square slot */
  --skyline-top:56px;
  --skyline-top-sm:40px;
  --skyline-max:100%;

  /* Email icon beside the contact address */
  --mailicon:17px;
  --mailicon-gap:10px;
  --mailicon-stroke:1.5px;

  /* Behavioural thresholds, read by site.js */
  --hdr-stuck-at:24px;      /* header state changes past this scroll */
  --spy-home-until:300px;   /* below this, "Home" is the current item */
  --bp-menu:860px;          /* mobile menu collapses above this width */

  /* Stacking order */
  --z-header:60;
  --z-mnav:70;
  --z-cookie:75;
  --z-modal:80;             /* the complaints dialog, over the banner */
  --z-skip:200;
}

/* ----------------------------------------------------------------------------
   05 — TOKENS · MOTION (§10)
   One easing curve. Exactly two behaviours: content fades up, lines draw once.
   ---------------------------------------------------------------------------- */
:root{
  --ease:cubic-bezier(.2,0,0,1);
  --t-fast:180ms;
  --t-base:260ms;
  --t-slow:620ms;
  --t-draw:1500ms;
  --t-reduced:.01ms;
  --reveal-y:10px;
  /* Illustrations settle a beat slower and a touch further than text, so they
     arrive rather than snap. Both are overridden to nothing under
     prefers-reduced-motion by the global rule below (§10). */
  --t-illus:760ms;
  --illus-rise:14px;
  --illus-delay:120ms;
  --reveal-delay-step:90ms;
  --len-fallback:600;       /* only until site.js measures the real length */
}

/* ----------------------------------------------------------------------------
   06 — BREAKPOINT TOKEN OVERRIDES (§09, §18)
   Two breakpoints: 1080px and 860px. Two, not five.
   ---------------------------------------------------------------------------- */
@media (max-width:1080px){
  :root{--margin:48px;--rail:178px;--gutter:36px;
    /* Three practice columns become two here, so the drawings get a wider
       column and can carry a little more weight without losing their margins. */
    --art-prac:var(--art-prac-md)}
}
@media (max-width:860px){
  :root{--margin:24px;--hdr-h:72px;--hdr-h-sm:62px;--band-y:var(--band-y-sm);
    --brand-logo-h:var(--brand-logo-h-phone);
    --brand-logo-h-sm:var(--brand-logo-h-phone-sm)}
}

/* ============================================================================
   RESET
   ============================================================================ */
*,*::before,*::after{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--hdr-h-sm) + var(--stack-6));
}
img,svg{max-width:100%;display:block}
ul{margin:0;padding:0;list-style:none}

/* ============================================================================
   ELEMENTS
   ============================================================================ */
body{
  margin:0;
  background:var(--surface-page);
  color:var(--text-body);
  font-family:var(--font-body);
  font-size:var(--fs-body);
  line-height:var(--lh-body);
  font-optical-sizing:auto;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3{
  font-family:var(--font-display);
  font-weight:var(--fw-regular);
  letter-spacing:var(--ls-h2);
  margin:0;
}
h1{font-size:var(--fs-h1);line-height:var(--lh-h1);letter-spacing:var(--ls-h1)}
h2{font-size:var(--fs-h2);line-height:var(--lh-h2)}
h3{font-size:var(--fs-h3);line-height:var(--lh-h3)}
p{margin:0 0 var(--stack-4);max-width:var(--measure)}
a{
  color:var(--text-link);
  text-decoration:underline;
  text-decoration-thickness:var(--ul-thickness);
  text-underline-offset:var(--ul-offset);
}
a:hover{color:var(--text-link-hover);text-decoration-thickness:var(--ul-thickness-hover)}
:focus-visible{
  outline:var(--focus-width) solid var(--focus-ring);
  outline-offset:var(--focus-offset);
  border-radius:var(--focus-radius);
}
@media (max-width:860px){body{font-size:var(--fs-body-sm)}}

/* ============================================================================
   LAYOUT AND TEXT UTILITIES
   ============================================================================ */
.wrap{max-width:var(--container);margin:0 auto;padding:0 var(--margin)}
.band{padding:var(--band-y) 0}
.band--alt{background:var(--surface-alt)}
.band--air{padding-top:var(--band-air-y);padding-bottom:var(--band-air-y)}

.vh{position:absolute;width:var(--hairline);height:var(--hairline);overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap}

/* Eyebrow — uppercase Archivo label preceded by the brand lozenge. */
.eyebrow{
  font-family:var(--font-ui);font-size:var(--fs-eyebrow);font-weight:var(--fw-medium);
  letter-spacing:var(--ls-eyebrow);text-transform:uppercase;color:var(--text-muted);
  margin:0 0 var(--stack-6);display:flex;align-items:center;gap:var(--eyebrow-gap);
  max-width:none;
}
.eyebrow::before{
  content:'';flex:none;width:var(--marker-w);height:var(--marker-h);background:var(--marker);
  clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%);
}

.lede{font-size:var(--fs-lede);line-height:var(--lh-lede);color:var(--text-lede)}
.muted{color:var(--text-muted);font-size:var(--fs-caption);line-height:var(--lh-lede);
  font-family:var(--font-ui);max-width:none}
.num{font-variant-numeric:tabular-nums lining-nums}

/* The broken rule — a hairline with one gap, painted in the band's own ground. */
/* One continuous hairline. The 16px break is withdrawn (§12). */
.rule{height:var(--hairline);background:var(--border-hairline);
  margin:var(--rule-y) 0;max-width:none}


/* Margin rail — a sticky column of Archivo notes beside the reading column. */
.railed{display:grid;grid-template-columns:var(--rail) minmax(0,1fr);
  gap:var(--gutter);align-items:start}
.rail{font-family:var(--font-ui);font-size:var(--fs-ui-sm);line-height:var(--lh-rail);
  color:var(--text-muted);position:sticky;top:calc(var(--hdr-h-sm) + var(--rail-top-gap))}
.rail p{margin:0 0 var(--stack-3);max-width:none;position:relative;
  padding-left:var(--rail-indent)}
.rail p::before{content:'';position:absolute;left:0;top:var(--stack-1);
  width:var(--marker-sm-w);height:var(--marker-sm-h);background:var(--marker);
  clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}
.rail p:last-child{margin-bottom:0}

/* Two-column reading grids for hero and contact. */
.duo{display:grid;grid-template-columns:1.15fr .85fr;gap:var(--duo-gap);align-items:center}
.duo--contact{grid-template-columns:1.05fr .95fr;align-items:start}
/* A grid item defaults to min-width:auto, which means it refuses to shrink
   below its content. The Turnstile widget has a hard 300px minimum, so without
   this the form column would be dragged wider than the page at 320px. With it,
   the widget scrolls inside its own slot and the page never moves sideways. */
.duo--contact > *{min-width:0}
/* Anchored to the bottom of the row rather than its middle. The drawing is a
   street elevation: it has a ground line, and floating it in the vertical
   centre of a much taller column is what made it read as a supporting icon
   instead of a hero. */
/* Anchored to the bottom of the row rather than its middle, and allowed to run
   out into the page margin. The drawing is a street elevation: it has a ground
   line, and the terrace should carry on past the frame rather than stop dead at
   the text column. justify-self:end pins the MARGIN box to the column, so the
   negative right margin is what puts the border box out into the gutter. */
.duo__art{
  justify-self:end;align-self:end;
  width:calc(100% + var(--art-bleed-hero));
  margin-right:calc(var(--art-bleed-hero) * -1);
  max-width:var(--art-hero);
}

/* Two columns, with the copy column pinned as closely as an fr ratio can get it
   to the lede's own 46ch measure, and every remaining pixel — a tighter gap,
   then the page margin, then part of the viewport gutter — given to the
   artwork. The content row is 1120px wide at and above 1281 (.wrap caps at
   --container and the padding is fixed), so this split is width-independent:
   1.03fr puts the copy column at 559.8px against a 560.14px measure whose
   longest rendered line is 549px. It is deliberately the largest share the
   artwork can take without the headline or the lede rewrapping — verified by
   counting rendered line boxes, not by eye. Do not raise it further.
   Below 1281 the grid is untouched. */
@media (min-width:1281px){
  .hero .duo{grid-template-columns:1.03fr .97fr;gap:var(--duo-gap-hero)}
}

@media (max-width:1080px){
  .duo{gap:var(--duo-gap-md)}
}
@media (max-width:860px){
  .railed{grid-template-columns:1fr;gap:var(--grid-gap-sm)}
  .rail{position:static;padding-bottom:var(--rail-pad-sm);
    border-bottom:var(--hairline) solid var(--border-hairline)}
  .rule{margin:var(--rule-y-sm) 0}
  .duo,.duo--contact{grid-template-columns:1fr;gap:var(--duo-gap-sm)}
  .duo__art{max-width:var(--art-hero-sm);justify-self:start}
  .band--air{padding-top:var(--band-air-y-sm);padding-bottom:var(--band-air-y-sm)}
}

/* ============================================================================
   MOTION — scroll reveal and line drawing (§10, §11.6)
   ============================================================================ */
.reveal{
  opacity:0;transform:translateY(var(--reveal-y));
  transition:opacity var(--t-slow) var(--ease),transform var(--t-slow) var(--ease);
}
.reveal.is-in{opacity:1;transform:none}
.reveal[data-d="1"]{transition-delay:calc(var(--reveal-delay-step) * 1)}
.reveal[data-d="2"]{transition-delay:calc(var(--reveal-delay-step) * 2)}
.reveal[data-d="3"]{transition-delay:calc(var(--reveal-delay-step) * 3)}
.reveal[data-d="4"]{transition-delay:calc(var(--reveal-delay-step) * 4)}

.draw path,.draw circle,.draw line,.draw polyline,.draw rect,.draw ellipse{
  stroke-dasharray:var(--len,var(--len-fallback));
  stroke-dashoffset:var(--len,var(--len-fallback));
  transition:stroke-dashoffset var(--t-draw) var(--ease);
}
.draw.is-in path,.draw.is-in circle,.draw.is-in line,
.draw.is-in polyline,.draw.is-in rect,.draw.is-in ellipse{stroke-dashoffset:0}

/* Reduced motion: nothing is hidden and nothing is lost — the full experience
   without movement (§10). */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    transition-duration:var(--t-reduced)!important;
    animation-duration:var(--t-reduced)!important;
  }
  .reveal{opacity:1!important;transform:none!important}
  .draw path,.draw circle,.draw line,.draw polyline,.draw rect,.draw ellipse{
    stroke-dashoffset:0!important;
  }
}

/* ============================================================================
   ILLUSTRATIONS (§21.3)
   The nine drawings are external <img> assets — greyscale PNGs in
   assets/img/, cropped to the artwork and sized for 2x/3x screens from the
   supplied originals, which are kept outside the repository (2026-09-21).
   No rule below reaches inside them.

   Every <img> carries its own intrinsic width/height attributes, and that is
   what reserves the box before load and keeps CLS at 0; a CSS aspect-ratio
   would be a second source for the same number, so there is none here (§11.7).
   The hero and the skyline are sized by width; the service and practice
   drawings are sized by height, for the optical reason set out below.
   ============================================================================ */
.illus{display:block;width:100%;height:auto}

/* Optical, not mathematical, sizing. The four service drawings and the three
   practice drawings each have their own proportions — a tall narrow jar reads
   smaller than a wide tree at the same height — so each carries a factor that
   trades height against width until the perceived masses match. The factors
   are the fourth root of the aspect ratio, inverted and normalised, which is
   the midpoint between matching heights and matching areas. */
.illus--svc{width:auto;height:calc(var(--art-svc) * var(--optical,1));max-width:100%}
.illus--prac{width:auto;height:calc(var(--art-prac) * var(--optical,1));max-width:100%}

/* Comments give each PNG's pixel size (aspect ratio is what matters). The
   factors were tuned to the earlier drawings' proportions and are unchanged. */
.illus--investment{--optical:1.03}   /* 214 x 260 */
.illus--retirement{--optical:1.14}   /* 171 x 288 — narrowest, so tallest */
.illus--protection{--optical:1.03}   /* 230 x 260 */
.illus--estate    {--optical:.95}    /* 287 x 240 — widest, so shortest */

.illus--cashflow{--optical:1}        /* 698 x 354 */
.illus--portal  {--optical:.98}      /* 750 x 347 */
.illus--reports {--optical:1.10}     /* 523 x 390 */

/* Entrance. The site's own reveal primitive, slowed and softened for artwork;
   no path drawing, no scaling, no parallax. */
.illus.reveal{
  transform:translateY(var(--illus-rise));
  transition:opacity var(--t-illus) var(--ease),transform var(--t-illus) var(--ease);
  transition-delay:var(--illus-delay);
}
.illus.reveal.is-in{transform:none}

/* ============================================================================
   CORE COMPONENTS — buttons, links, wordmark, mark, lozenge (§12)
   ============================================================================ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;min-height:var(--tap-min);
  font-family:var(--font-ui);font-size:var(--fs-ui);font-weight:var(--fw-medium);
  padding:var(--btn-pad-y) var(--btn-pad-x);
  border:var(--hairline) solid var(--border-strong);border-radius:var(--radius);
  text-decoration:none;cursor:pointer;
  transition:background var(--t-fast) var(--ease),color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease);
}
.btn--primary{background:var(--ink);color:var(--text-inverse)}
.btn--primary:hover{background:var(--bodleian);border-color:var(--bodleian);
  color:var(--text-inverse)}
.btn--secondary{background:transparent;color:var(--ink)}
.btn--secondary:hover{background:var(--ink);color:var(--text-inverse)}
.btn[disabled]{opacity:var(--btn-disabled-alpha);cursor:not-allowed}

.tlink{
  font-family:var(--font-ui);font-size:var(--fs-ui);color:var(--text-link);
  text-decoration:none;display:inline-flex;align-items:center;gap:var(--tlink-gap);
}
.tlink::after{
  content:'';flex:none;width:var(--arrow-w);height:var(--arrow-h);background:var(--marker);
  clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%);
  transition:transform var(--t-fast) var(--ease);
}
.tlink:hover{color:var(--text-link-hover);text-decoration:underline;
  text-underline-offset:var(--ul-offset-ui)}
.tlink:hover::after{transform:translateX(var(--arrow-nudge))}

/* A plain text link — no arrow. Used beside the hero's primary action. */
.plainlink{font-family:var(--font-ui);font-size:var(--fs-ui);color:var(--text-link);
  text-decoration:none}
.plainlink:hover{color:var(--text-link-hover);text-decoration:underline;
  text-underline-offset:var(--ul-offset-ui)}

/* The wordmark used to be live text set in Archivo beside the mark (.wm, with
   its own letter-spacing and split tokens). The supplied lockups carry the
   words as artwork, so that component and its tokens are withdrawn. Do not
   reintroduce a text wordmark beside the logo: it would be the name twice. */

.brand{display:flex;align-items:center;gap:var(--brand-gap);text-decoration:none;
  color:var(--ink);flex:none}

/* ----------------------------------------------------------------------------
   BRAND LOCKUPS
   The supplied files carry the mark and the wordmark together, so there is no
   separate text element to align any more.

   Height comes from a token; width follows the file's own proportions. The box
   is reserved before the SVG arrives by the width and height ATTRIBUTES in the
   markup, which the browser turns into an internal aspect ratio — that is what
   makes the load shift-free, and it is why those attributes must be kept in
   step with the heights below.

   The ratio is therefore already declared, once, in the markup. Do not repeat
   it as a CSS aspect-ratio: two sources for one number is how they drift.
   ---------------------------------------------------------------------------- */
.brand__logo{
  display:block;flex:none;
  height:var(--brand-logo-h);
  width:auto;
  /* The reset gives every image max-width:100%. If the header's brand track is
     ever narrower than the lockup, that cap trims the WIDTH while height holds
     its ground, and the artwork is squashed rather than scaled — measured at
     ratio 2.59 against a true 3.34 at a 861px window (2026-09-10, on the
     lockup that shipped before the final artwork; the current one is
     3.64753 : 1). The heights above are sized so it does not come to that;
     this makes sure that if it ever does, the lockup is scaled down inside its
     box instead of deformed. contain never crops. */
  object-fit:contain;object-position:left center;
  transition:height var(--t-base) var(--ease);
}
/* The footer lockup is inline SVG rather than an <img>, for one reason: it has
   to be the same colour as the sentence beside it, and an <img> cannot inherit
   currentColor. The supplied file paints itself black, which is invisible on
   this ground, so drawn inline with fill="currentColor" it takes the colour
   set here instead.

   That colour is --footer-body, which is the same token .ftr__brand p uses.
   The two must stay identical — if you change one, change the other. The
   artwork is arkana-logo-stacked-inverse.svg: the inline copy carries its
   paths unchanged, with the PDF page plate removed and the viewBox cropped to
   the artwork (21.395 6.036 189.555 225.012). That file is kept exactly as
   supplied, plate included, and no page loads it — never use it as an <img>. */
.ftr__logo{
  display:block;flex:none;align-self:flex-start;
  height:var(--ftr-logo-h);
  width:auto;
  color:var(--footer-body);
}

/* The bare mark is 26.18 x 24.01, not square. Height drives it so the supplied
   proportions are preserved exactly at every size. */
.mark{height:var(--mark);width:auto;flex:none;align-self:center;
  transition:height var(--t-base) var(--ease)}

/* ============================================================================
   HERO (§14.1)
   ============================================================================ */
.hero{padding-top:calc(var(--hdr-h) + var(--hero-offset));padding-bottom:var(--band-y)}
.hero__h1{max-width:var(--measure-hero-h1)}
.hero__lede{margin-top:var(--hero-lede-gap);max-width:var(--measure-hero-lede)}
.hero__acts{display:flex;gap:var(--hero-acts-gap);align-items:center;flex-wrap:wrap;
  margin-top:var(--hero-acts-top)}

/* Per-section heading measures. */
.h2--about{max-width:var(--measure-about-h2)}
.h2--services{max-width:var(--measure-services-h2)}
.h2--process{max-width:var(--measure-process-h2)}
.h2--practice{max-width:var(--measure-practice-h2)}
.h2--insights{max-width:var(--measure-insights-h2)}
.h2--contact{max-width:var(--measure-contact-h2)}

/* ============================================================================
   SERVICE ROWS — rows, never cards (§14.3)
   ============================================================================ */
.svc{border-top:var(--hairline) solid var(--border-hairline);margin-top:var(--stack-7)}
.svc__row{
  display:grid;grid-template-columns:var(--svc-art-col) minmax(0,1fr);
  gap:var(--gutter);align-items:center;padding:var(--row-y) 0;
  border-bottom:var(--hairline) solid var(--border-hairline);
  position:relative;cursor:default;
  transition:background var(--t-base) var(--ease);
}
/* A hairline draws across the top edge on hover. Hover only: the row is not a
   link, has no selected state and nothing to activate, so it is not focusable
   and there is no sticky "is-active" class. It is an affordance for reading. */
.svc__row::before{
  content:'';position:absolute;left:0;top:calc(var(--hairline) * -1);
  height:var(--hairline);width:0;background:var(--marker);
  transition:width var(--t-base) var(--ease);
}
.svc__row:hover{
  background:var(--surface-hover-tint);
}
.svc__row:hover::before{
  width:100%;
}
/* On a service row the artwork column is fixed and the four drawings are not
   the same width, so they are centred in it: the four rows then share one
   vertical axis instead of showing four ragged left edges. Vertical centring
   against the copy comes from .svc__row's own align-items:center.
   On a service page the same block sits above left-aligned prose, so it stays
   left-aligned there. */
/* Above 1080 the row used the full page gutter between artwork and heading,
   which read as two unrelated columns. 36px is what --gutter already takes at
   every width below 1081, so no new number enters the system. */
/* WHY THIS RULE EXISTS.
   .svc__row above declares "transition: background ..." for its hover tint.
   That shorthand has the same specificity as .reveal and is declared later, so
   it silently replaced .reveal's opacity/transform transition: the four rows
   were computing transition-property "background" and snapping from hidden to
   visible with no duration at all. That is why the section read as static.

   Naming all three properties here — at .svc__row.reveal, which outranks
   .reveal[data-d] — restores the reveal. The delays are per property on
   purpose: the reveal is staggered, the hover tint is not, so hovering the
   fourth row still tints immediately instead of waiting 360ms. The row is the
   reveal unit, so its artwork and its copy always move together. */
.svc__row.reveal{
  transition:
    background var(--t-base) var(--ease) 0s,
    opacity var(--t-slow) var(--ease) var(--reveal-d, 0s),
    transform var(--t-slow) var(--ease) var(--reveal-d, 0s);
}
/* The site's own waterfall step, reused — not a new timing system. */
.svc__row[data-d="1"]{--reveal-d:calc(var(--reveal-delay-step) * 1)}
.svc__row[data-d="2"]{--reveal-d:calc(var(--reveal-delay-step) * 2)}
.svc__row[data-d="3"]{--reveal-d:calc(var(--reveal-delay-step) * 3)}
.svc__row[data-d="4"]{--reveal-d:calc(var(--reveal-delay-step) * 4)}

.svc__row{column-gap:var(--svc-art-gap)}
.svc__art{display:flex;align-items:center}
/* CENTRED on one shared vertical axis. The four drawings are 100, 80, 108 and
   134px wide at their current scale, so no edge alignment can put them on a
   common axis: left- or right-aligning leaves the other edges 54px ragged.
   Their centres can share an axis, and do.

   This is optical centring, not merely geometric — measured, not assumed.
   Re-measured on the final PNGs (2026-09-21): the ink fills each file edge to
   edge in all four (no internal whitespace to compensate for), and the ink's
   centre of mass sits within 0.8px of the box centre in every case (+0.6,
   +0.1, -0.8, -0.3). Geometric centring therefore IS optical centring here,
   which is why there are no per-icon offsets. If the artwork is ever redrawn,
   re-measure before assuming that still holds.

   Icon scale is unchanged. Vertical centring against the copy comes from
   .svc__row's own align-items:center and is unchanged.
   On a service PAGE the same block sits above left-aligned prose, so it is
   left as it is — this rule is scoped to .svc__row. */
.svc__row .svc__art{width:100%;justify-content:center}
.svc__body h3{margin-bottom:var(--stack-1)}
.svc__body p{margin:0;color:var(--text-lede);font-size:var(--fs-prose);
  max-width:var(--measure-svc-copy)}

/* ============================================================================
   PROCESS STEPS — sequence carried by order and copy alone (§14.4).
   The "STEP ONE / TWO / THREE" labels were removed by founder instruction in
   2026-08, and .step__n went with them in 2026-09-07's cleanup: there is no
   numbered content anywhere on the site.
   ============================================================================ */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gutter);
  margin-top:var(--stack-7)}
.step{border-top:var(--hairline) solid var(--border-hairline);padding-top:var(--stack-5)}
.step h3{font-size:var(--fs-h3-sm);margin-bottom:var(--stack-2)}
.step p{font-size:var(--fs-prose-sm);color:var(--text-lede);margin:0}

/* ============================================================================
   PRACTICE ITEMS (§14.5)
   ============================================================================ */
.prac{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gutter);
  margin-top:var(--stack-7);align-items:start}
.prac__item{border-top:var(--hairline) solid var(--border-hairline);
  padding-top:var(--stack-5);display:flex;flex-direction:column;align-items:flex-start}
.prac__item h3{font-size:var(--fs-h3-xs);margin-bottom:var(--stack-2)}
.prac__item p{font-size:var(--fs-prose-sm);color:var(--text-lede);margin:0}
/* The drawings are left-aligned with the heading beneath them, which is where
   the eye expects them; sizing is height-driven, in the ILLUSTRATIONS block.

   The box is as tall as the tallest of the three and they sit on its floor.
   Optical sizing gives the three different heights on purpose, and without a
   shared box that difference pushed each heading to a different line — the
   headings were 12px apart. Now the three columns share one baseline for the
   artwork and one for every line of text beneath it. */
.prac__art{
  height:calc(var(--art-prac) * var(--optical-prac-tallest));
  display:flex;align-items:flex-end;
  margin-bottom:var(--stack-4);
}

/* ============================================================================
   INSIGHT NOTES (§14.6)
   ============================================================================ */
.notes{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gutter);
  margin-top:var(--stack-7)}
.note-item{border-top:var(--hairline) solid var(--border-hairline);
  padding-top:var(--note-pad);position:relative}
.note-item__meta{
  font-family:var(--font-ui);font-size:var(--fs-label);letter-spacing:var(--ls-label);
  text-transform:uppercase;color:var(--text-muted);margin-bottom:var(--note-meta-bot);
  display:flex;flex-wrap:wrap;gap:var(--note-meta-gap);align-items:baseline;
}
.note-item__meta span{white-space:nowrap}
.note-item h3{font-size:var(--fs-h3-sm);margin-bottom:var(--note-title-bot)}
.note-item h3 a{
  color:var(--text-heading);text-decoration:none;padding-bottom:var(--note-underline);
  background-image:linear-gradient(var(--ink),var(--ink));
  background-size:0 var(--note-underline);
  background-repeat:no-repeat;background-position:0 100%;
  transition:background-size var(--t-base) var(--ease);
}
.note-item:hover h3 a,.note-item h3 a:focus-visible{background-size:100% var(--note-underline)}
.note-item h3 a::before{content:'';position:absolute;inset:0}
.note-item p{font-size:var(--fs-prose-sm);color:var(--text-lede);margin:0}

/* Insights: horizontal scroll-snap rail. No auto-advance, no dots, no fade. */
.rail-x{
  display:flex;gap:var(--gutter);overflow-x:auto;scroll-snap-type:x mandatory;
  overscroll-behavior-x:contain;padding-bottom:var(--rail-x-pad);margin-top:var(--stack-7);
}
.rail-x .note-item{
  flex-grow:0;flex-shrink:0;
  flex-basis:calc((100% - var(--gutter) * 2) / 3);
  scroll-snap-align:start;min-width:0;
}
.rail-x:focus-visible{outline:var(--focus-width) solid var(--focus-ring);
  outline-offset:var(--rail-x-focus-offset)}
.rail-x__ctl{display:flex;gap:var(--stack-5);align-items:center;margin-top:var(--stack-5)}
.rail-x__btn{
  font-family:var(--font-ui);font-size:var(--fs-ui);background:none;border:0;
  padding:var(--mnav-link-pad) 0;min-height:var(--tap-alt);color:var(--text-link);
  cursor:pointer;
}
.rail-x__btn:hover{text-decoration:underline;text-underline-offset:var(--ul-offset-ui)}

@media (max-width:1080px){
  .steps,.notes,.prac{grid-template-columns:1fr 1fr}
  .rail-x .note-item{flex-basis:calc((100% - var(--gutter)) / 2)}
}
@media (max-width:860px){
  .steps,.notes,.prac{grid-template-columns:1fr;gap:var(--grid-gap-sm)}
  .svc__row{grid-template-columns:var(--svc-art-col-sm) minmax(0,1fr);
    gap:var(--svc-gap-sm);row-gap:var(--svc-rowgap-sm);padding:var(--row-y-sm) 0}
  .illus--svc{height:calc(var(--art-svc-sm) * var(--optical,1))}
  .rail-x .note-item{flex-basis:var(--rail-x-basis-sm)}
}

/* ============================================================================
   FORMS (§12, §14.7)
   ============================================================================ */
.field{margin-bottom:var(--stack-6)}
.field label{
  display:block;font-family:var(--font-ui);font-size:var(--fs-label);
  font-weight:var(--fw-medium);letter-spacing:var(--ls-label);text-transform:uppercase;
  color:var(--text-muted);margin-bottom:var(--stack-2);
}
/* Labels state no optionality on this form. */
.field .opt{display:none}
.field input,.field textarea,.field select{
  width:100%;font-family:var(--font-body);font-size:var(--fs-field);
  color:var(--text-body);background:transparent;border:0;
  border-bottom:var(--hairline) solid var(--border-field);
  padding:var(--field-pad-y) 0;border-radius:0;
  transition:border-color var(--t-fast) var(--ease);
}
/* The only growth here is the browser's own resize handle — there is no
   auto-grow script — so a max-height is all that is needed to stop the field
   being dragged the length of the page. Past it the textarea scrolls inside
   itself, which is native behaviour and needs no JavaScript. The vh line is the
   fallback for anything that does not understand svh; svh is what keeps the cap
   steady on a phone while the browser chrome slides away. */
.field textarea{
  resize:vertical;line-height:var(--lh-lede);
  min-height:var(--textarea-min);
  max-height:min(var(--textarea-max), 50vh);
  max-height:min(var(--textarea-max), 50svh);
}
.field select{font-family:var(--font-ui);font-size:var(--fs-caption);
  padding:var(--field-select-pad-y) 0;cursor:pointer}
.field input:focus,.field textarea:focus,.field select:focus{
  border-bottom-color:var(--accent)}
.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{
  outline:var(--focus-width) solid var(--focus-ring);outline-offset:var(--focus-offset-field)}
.field.is-bad input,.field.is-bad textarea{
  border-bottom-color:var(--text-error);border-bottom-width:var(--field-bad-width)}
.field__err{display:none;font-family:var(--font-ui);font-size:var(--fs-fine);
  color:var(--text-error);margin-top:var(--field-err-top)}
.field.is-bad .field__err{display:block}
.hp{position:absolute;left:var(--offscreen);width:var(--hairline);height:var(--hairline);
  overflow:hidden}

.form__foot{margin-top:var(--form-foot-top)}
/* Submit and the human check share a row, the check to the right of the
   button. It wraps beneath on narrow columns rather than squeezing either. */
.form__submit{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--form-submit-gap);
}
/* Never wider than the column: at 320px the widget is the widest thing on the
   page, and it must scroll inside itself rather than push the page sideways.
   It takes whatever width the row has left over, and centres the widget in it:
   beside the button on a wide column, and on its own full-width line once the
   row wraps. "safe" keeps the left edge reachable when the widget is wider
   than the space — an old browser that does not know the keyword drops the
   declaration and gets the previous left-aligned behaviour. */
.field--turnstile{margin-bottom:0;min-width:0;max-width:100%;overflow-x:auto;
  flex:1 1 var(--turnstile-min);display:flex;justify-content:safe center}
.form__status{font-family:var(--font-ui);font-size:var(--fs-ui);line-height:var(--lh-ui);
  margin:0 0 var(--form-status-bot);max-width:var(--measure-status)}
.form__status:empty{display:none}
.form__status[data-tone="bad"]{color:var(--text-error)}
.form__status[data-tone="good"]{color:var(--accent)}
.form__privacy{margin-top:var(--form-status-bot);font-size:var(--fs-fine);
  max-width:var(--measure-privacy-note)}
.form-done{border-left:var(--form-done-bar) solid var(--accent);
  padding:var(--form-done-pad-y) var(--stack-5);background:var(--surface-page)}
.form-done h3{font-size:var(--fs-h3-sm);margin-bottom:var(--stack-2)}
.form-done p{margin:0;font-size:var(--fs-prose-sm);color:var(--text-lede)}
.form-done[hidden]{display:none}

/* Cloudflare injects its own 300 x 65 framed iframe here, so this element is a
   plain slot: no border and no padding, because a box around a box reads as
   clutter and the chrome cost 38px the contact column does not have. The form
   column is 411–494px wide, the button is 147px, and the widget will not go
   below 300px — so bare is what lets it sit beside the button at all. */
.cf-turnstile{
  display:flex;align-items:center;gap:var(--turnstile-gap);
  max-width:100%;
  font-family:var(--font-ui);font-size:var(--fs-fine);line-height:var(--lh-rail);
  color:var(--text-muted);
}

/* Contact column */
.contact__copy{margin-top:var(--contact-copy-top)}
.contact__address{
  font-style:normal;font-family:var(--font-ui);font-size:var(--fs-caption);
  line-height:var(--lh-footer);color:var(--text-muted);
  margin-top:var(--contact-address-top);
}

/* Common questions (§14.7) — native <details>/<summary>, so the keyboard, the
   open state announced to screen readers and the toggle itself all come from
   the browser. No script. Closed by default, so nothing long shows on load.

   Above 860px the block sits in the space under the introduction: the form
   column spans both rows, and the second row is 1fr so the form's extra
   height lands BELOW the questions instead of opening a gap above them.
   Below 860px the grid is one column in source order — introduction, form,
   questions — so the form is never pushed down a phone screen. */
@media (min-width:861px){
  .duo--contact{grid-template-rows:auto 1fr;row-gap:var(--faq-top)}
  .contact__form{grid-column:2;grid-row:1 / span 2}
  .faq{grid-column:1;grid-row:2}
}
.faq__h{font-size:var(--fs-h3-sm);margin:0 0 var(--stack-3)}
.faq__item{border-top:var(--hairline) solid var(--border-hairline)}
.faq__item:last-of-type{border-bottom:var(--hairline) solid var(--border-hairline)}
/* Block, not flex: older Safari will not lay a <summary> out as a flex box. */
.faq__item summary{
  display:block;position:relative;list-style:none;cursor:pointer;
  min-height:var(--tap-min);
  padding:var(--faq-q-pad) calc(var(--faq-icon) + var(--stack-4)) var(--faq-q-pad) 0;
  font-size:var(--fs-prose-sm);line-height:var(--lh-h3);color:var(--text-heading);
  transition:color var(--t-fast) var(--ease);
}
.faq__item summary::-webkit-details-marker{display:none}
.faq__item summary:hover{color:var(--text-link)}
.faq__item summary::after{
  content:'';position:absolute;right:0;top:50%;
  width:var(--faq-icon);height:var(--faq-icon);margin-top:calc(var(--faq-icon) / -2);
  background:
    linear-gradient(currentColor,currentColor) center / 100% var(--icon-stroke) no-repeat,
    linear-gradient(currentColor,currentColor) center / var(--icon-stroke) 100% no-repeat;
  transition:background-size var(--t-fast) var(--ease);
}
.faq__item[open] summary::after{background-size:100% var(--icon-stroke),var(--icon-stroke) 0}
.faq__item p{margin:0;padding-bottom:var(--stack-3);font-size:var(--fs-prose-sm);
  color:var(--text-lede)}

/* ============================================================================
   HEADER (§13) — fixed, not sticky, so the height change cannot push content.
   ============================================================================ */
.hdr{
  position:fixed;inset:0 0 auto;z-index:var(--z-header);background:transparent;
  border-bottom:var(--hairline) solid transparent;
  transition:background var(--t-base) var(--ease),border-color var(--t-base) var(--ease);
}
.hdr.is-stuck{
  background:var(--surface-header-scrolled);
  backdrop-filter:saturate(var(--hdr-saturate)) blur(var(--hdr-blur));
  -webkit-backdrop-filter:saturate(var(--hdr-saturate)) blur(var(--hdr-blur));
  border-bottom-color:var(--border-hairline);
}
.hdr__in{
  max-width:var(--container);margin:0 auto;padding:0 var(--margin);height:var(--hdr-h);
  display:flex;align-items:center;gap:var(--hdr-gap);
  transition:height var(--t-base) var(--ease);
}
.hdr.is-stuck .hdr__in{height:var(--hdr-h-sm)}
.hdr.is-stuck .brand .brand__logo{height:var(--brand-logo-h-sm)}

/* Centred nav: a three-track header row. */
.hdr__in--centred{display:grid;grid-template-columns:1fr auto 1fr;
  gap:var(--stack-6);align-items:center}
.hdr__in--centred .nav{grid-column:2;justify-content:center}
.hdr__in--centred .menu-btn{grid-column:3;margin-left:0;justify-self:end}
/* Logo hard left. The supplied file already sets the mark against the wordmark,
   so there is no separate element left to nudge into alignment. */
.brand--left{grid-column:1;justify-self:start;align-items:center}

/* Scroll progress: one hairline advancing along the header's bottom edge. */
.hdr__progress{
  position:absolute;left:0;bottom:calc(var(--hairline) * -1);height:var(--hairline);
  width:100%;background:var(--accent);transform:scaleX(0);transform-origin:0 50%;
  opacity:0;transition:opacity var(--t-base) var(--ease);
}
.hdr.is-stuck .hdr__progress{opacity:1}

.nav{display:flex;gap:var(--nav-gap);font-family:var(--font-ui);font-size:var(--fs-ui);
  letter-spacing:var(--ls-nav)}
.nav a{color:var(--ink);text-decoration:none;position:relative;
  padding-bottom:var(--nav-underline-gap)}
.nav a::after{content:'';position:absolute;left:0;bottom:0;height:var(--hairline);
  width:0;background:var(--ink);transition:width var(--t-fast) var(--ease)}
.nav a:hover::after{width:100%}
.nav a[aria-current]::before{
  content:'';position:absolute;left:50%;bottom:calc(var(--nav-marker-drop) * -1);
  transform:translateX(-50%);width:var(--marker-sm-w);height:var(--marker-sm-h);
  background:var(--marker);clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%);
}

.menu-btn{
  display:none;margin-left:auto;font-family:var(--font-ui);font-size:var(--fs-ui);
  background:none;border:0;color:var(--ink);cursor:pointer;
  padding:var(--menu-btn-pad) 0;min-height:var(--tap-alt);
}

.mnav{
  position:fixed;inset:0;background:var(--surface-page);z-index:var(--z-mnav);
  padding:var(--mnav-pad-y) var(--margin);
  transform:translateY(calc(var(--reveal-y) * -1));opacity:0;pointer-events:none;
  transition:opacity var(--t-base) var(--ease),transform var(--t-base) var(--ease);
}
.mnav.is-open{opacity:1;transform:none;pointer-events:auto}
.mnav[hidden]{display:none}
.mnav__top{display:flex;justify-content:space-between;align-items:center;
  min-height:var(--mnav-top-min)}
/* Slightly smaller in the panel than in the header: it sits beside "Close"
   rather than a full navigation, and the panel margin is tighter. */
.mnav__top .brand__logo{height:var(--brand-logo-h-mnav)}
.mnav__list{margin-top:var(--mnav-list-top);display:flex;flex-direction:column;
  gap:var(--mnav-list-gap)}
.mnav__list a{font-family:var(--font-body);font-size:var(--fs-mnav);color:var(--ink);
  text-decoration:none;padding:var(--mnav-link-pad) 0}
.mnav__foot{margin-top:var(--mnav-foot-top);padding-top:var(--mnav-foot-pad);
  border-top:var(--hairline) solid var(--border-hairline)}
.mnav__close{font-family:var(--font-ui);font-size:var(--fs-ui);background:none;border:0;
  color:var(--ink);cursor:pointer;padding:var(--mnav-link-pad) 0;min-height:var(--tap-alt)}

/* ============================================================================
   FOOTER (§14.8) — the only inverse surface.
   ============================================================================ */
.ftr{
  background:var(--surface-inverse);color:var(--footer-body);
  padding:var(--ftr-y-top) 0 var(--ftr-y-bot);
  font-family:var(--font-ui);font-size:var(--fs-ui-sm);line-height:var(--lh-ui);
}
/* KEYBOARD FOCUS ON THE INK GROUND (2026-09-07, authorised launch fix).
   The global :focus-visible ring is Bodleian blue, which is right on the
   limestone page but gave only 1.54:1 against the footer's ink — under the
   3:1 WCAG 2.2 requires of a focus indicator, so a keyboard user could not
   see where they were in the footer. This overrides the COLOUR only, from a
   token that already belongs to the footer's palette; width, offset and
   radius still come from the one global rule, so the indicator keeps exactly
   the same shape it has everywhere else on the site. Covers every focusable
   thing in the footer — the five nav links, the LinkedIn chip, the privacy
   link and the cookie-settings button — because it is scoped to .ftr rather
   than listed control by control, so anything added later is covered too. */
.ftr :focus-visible{outline-color:var(--focus-ring-inverse)}
.ftr h2{
  font-family:var(--font-ui);font-size:var(--fs-eyebrow);font-weight:var(--fw-medium);
  letter-spacing:var(--ls-step);text-transform:uppercase;color:var(--footer-muted);
  margin:0 0 var(--ftr-head-bot);
}
.ftr a{color:var(--footer-body);text-decoration:none;
  transition:color var(--t-fast) var(--ease)}
.ftr a:hover{color:var(--text-inverse);text-decoration:underline;
  text-underline-offset:var(--ul-offset-ui)}
.ftr__top{display:flex;justify-content:space-between;align-items:flex-start;
  gap:var(--ftr-gap)}
.ftr__brand{display:flex;flex-direction:column;gap:var(--ftr-brand-gap);
  max-width:var(--measure-ftr-brand)}
.ftr__brand p{margin:0;color:var(--footer-body);text-wrap:pretty}
.ftr__nav{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--ftr-nav-gap);margin-top:var(--ftr-nav-top);
  padding-top:var(--ftr-nav-pad);border-top:var(--hairline) solid var(--border-inverse);
  font-size:var(--fs-ui);letter-spacing:var(--ls-nav);
}
/* LinkedIn is the last item in the footer nav and the only social link on the
   site. margin-left:auto pushes it to the far right of the row, and keeps it
   there on the right of whichever line it lands on once the nav wraps. It is
   last in the DOM too, so the keyboard order matches what is on screen.

   It keeps the bordered chip the old social row used — same box, same border,
   same glyph size, same hover — so it reads with the weight it had before it
   moved. --ftr-nav-social-inset holds it off the content edge: flush against
   it, the chip's border looked like a rendering artefact of the page edge
   rather than a deliberate control. */
.ftr__nav-social{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--ftr-social-chip);height:var(--ftr-social-chip);
  border:var(--hairline) solid var(--border-inverse);border-radius:var(--radius);
  margin-left:auto;margin-right:var(--ftr-nav-social-inset);
  transition:border-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease);
}
.ftr__nav-social:hover{border-color:var(--footer-body);text-decoration:none}
.ftr__nav-social svg{display:block;
  width:var(--ftr-social-glyph);height:var(--ftr-social-glyph);fill:currentColor}
.ftr__legal{
  margin-top:var(--ftr-legal-top);padding-top:var(--ftr-legal-pad);
  border-top:var(--hairline) solid var(--border-inverse);
  color:var(--footer-muted);font-size:var(--fs-label);
}
.ftr__legal p{max-width:var(--measure-ftr-legal);margin:0 0 var(--ftr-legal-line);
  color:var(--footer-muted)}
.ftr__base{
  margin-top:var(--ftr-base-top);display:flex;justify-content:space-between;
  gap:var(--ftr-base-gap);flex-wrap:wrap;color:var(--footer-muted);
  font-size:var(--fs-label);
}
.ftr__base p{margin:0}
.ftr__minor{display:flex;flex-wrap:wrap;gap:var(--ftr-minor-gap);align-items:center}
.ftr__minor button{
  font-family:var(--font-ui);font-size:var(--fs-label);line-height:var(--lh-ui);
  background:none;border:0;
  padding-left:0;padding-right:0;
  color:var(--footer-muted);cursor:pointer;text-decoration:underline;
  text-underline-offset:var(--ul-offset-ui);
}
.ftr__minor button:hover{color:var(--text-inverse)}

.skip{
  position:absolute;left:var(--offscreen);top:0;z-index:var(--z-skip);background:var(--ink);
  color:var(--text-inverse);padding:var(--skip-pad-y) var(--skip-pad-x);
  font-family:var(--font-ui);font-size:var(--fs-ui);text-decoration:none;
}
.skip:focus{left:var(--skip-inset);top:var(--skip-inset)}

@media (max-width:1080px){
  .hdr__in{gap:var(--hdr-gap-md)}
  .nav{gap:var(--nav-gap-md)}
  .ftr__nav{gap:var(--ftr-nav-gap-md)}
}
@media (max-width:860px){
  .nav{display:none}
  .menu-btn{display:block}
  .hdr__in--centred{grid-template-columns:1fr auto}
  .hdr__in--centred .menu-btn{grid-column:2}
  .ftr__top{flex-direction:column;gap:var(--ftr-top-gap-sm)}
  .ftr__nav{gap:var(--ftr-nav-gap-sm-y) var(--ftr-nav-gap-sm-x);
    margin-top:var(--ftr-nav-top-sm)}
  .ftr__legal{margin-top:var(--ftr-legal-top-sm)}
}

/* ============================================================================
   COOKIE CONSENT SHELL
   Bottom-anchored sheet. Flat limestone ground, one hairline, no shadow.
   ============================================================================ */
.cc{
  position:fixed;left:0;right:0;bottom:0;z-index:var(--z-cookie);
  background:var(--surface-page);border-top:var(--hairline) solid var(--border-hairline);
}
.cc[hidden]{display:none}
.cc__in{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--gutter);
  align-items:start;padding:var(--cc-pad-top) 0 var(--cc-pad-bot)}
.cc__copy{margin:0;font-family:var(--font-ui);font-size:var(--fs-ui-sm);
  line-height:var(--lh-ui);color:var(--text-body);max-width:var(--measure-cookie-copy);
  text-wrap:pretty}
/* Three actions on one row at one size: rejecting is exactly as easy as accepting. */
.cc__acts{display:flex;gap:var(--cc-acts-gap);flex-wrap:wrap;align-items:center}
.cc__acts .btn{min-width:var(--cc-btn-min)}
.cc__prefs{
  display:grid;gap:var(--cc-prefs-gap);margin-top:var(--cc-prefs-top);
  padding-top:var(--cc-prefs-pad);border-top:var(--hairline) solid var(--border-hairline);
  max-width:var(--measure-cookie-prefs);
}
.cc__prefs[hidden]{display:none}
.cc__row{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--cc-row-gap);
  align-items:start}
.cc__row input{width:var(--cc-box);height:var(--cc-box);
  margin:var(--cc-box-nudge) 0 0;accent-color:var(--accent)}
.cc__row label{font-family:var(--font-ui);font-size:var(--fs-ui-sm);
  line-height:var(--lh-ui);color:var(--text-body);margin:0}
.cc__save{display:flex;gap:var(--cc-acts-gap);flex-wrap:wrap;
  padding-top:var(--cc-box-nudge)}
.cc__fine{margin:0;font-size:var(--fs-fine)}

@media (max-width:860px){
  .cc__in{grid-template-columns:1fr;gap:var(--cc-gap-sm);
    padding:var(--cc-pad-top-sm) 0 var(--cc-pad-bot-sm)}
  .cc__acts .btn{min-width:0;flex:1 1 auto}
}



/* ============================================================================
   COMPLAINTS DIALOG (§16)
   The complaints procedure, shown in place rather than on a page of its own.
   Same limestone ground, hairline and UI type as the cookie sheet above; the
   one new surface is the scrim that holds it off the page. Centred, sized to
   its content, and never taller than the viewport — the panel's body scrolls,
   the page behind it does not (site.js locks it and makes it inert).
   ============================================================================ */
.cmp{
  position:fixed;inset:0;z-index:var(--z-modal);background:var(--surface-scrim);
  /* Flex, not grid: a grid row sized to its content would grow past the
     viewport on a short screen, and the panel’s max-height would then be a
     percentage of the overgrown row rather than of the screen. */
  display:flex;align-items:center;justify-content:center;padding:var(--cmp-inset);
  opacity:0;pointer-events:none;transition:opacity var(--t-base) var(--ease);
}
.cmp.is-open{opacity:1;pointer-events:auto}
.cmp[hidden]{display:none}
.cmp__box{
  display:flex;flex-direction:column;width:100%;max-width:var(--cmp-max);
  max-height:100%;background:var(--surface-page);
  border:var(--hairline) solid var(--border-hairline);border-radius:var(--radius);
  transform:translateY(calc(var(--reveal-y) * -1));
  transition:transform var(--t-base) var(--ease);
}
.cmp.is-open .cmp__box{transform:none}
/* The heading row keeps its place while the body scrolls, so the close control
   stays in the top-right corner at any height (§17). */
.cmp__head{
  flex:none;display:flex;gap:var(--cmp-gap);align-items:flex-start;
  justify-content:space-between;padding:var(--cmp-pad) var(--cmp-pad) 0;
}
.cmp__h{font-size:var(--fs-h3-sm);line-height:var(--lh-h3);margin:0}
.cmp__close{
  flex:none;display:grid;place-items:center;background:none;border:0;
  width:var(--tap-min);height:var(--tap-min);cursor:pointer;color:var(--text-muted);
  /* A full tap target, pulled back so the glyph sits on the box's own edge. */
  margin:calc(var(--cmp-close-nudge) * -1) calc(var(--cmp-close-nudge) * -1) 0 0;
  transition:color var(--t-fast) var(--ease);
}
.cmp__close:hover{color:var(--text-heading)}
.cmp__close svg{
  width:var(--cmp-close-glyph);height:var(--cmp-close-glyph);
  fill:none;stroke:currentColor;stroke-width:var(--icon-stroke);
  stroke-linecap:round;stroke-linejoin:round;
}
/* The body takes what is left and scrolls inside the panel when the screen is
   too short for it; min-height:0 is what lets a flex item shrink that far. */
.cmp__body{
  flex:1 1 auto;min-height:0;overflow-y:auto;
  padding:var(--cmp-body-top) var(--cmp-pad) var(--cmp-pad);
  font-family:var(--font-ui);font-size:var(--fs-ui-sm);line-height:var(--lh-ui);
  color:var(--text-body);
}
.cmp__body p{margin:0 0 var(--cmp-gap)}
.cmp__body p:last-child{margin:0}
/* The two addresses are given in full, and a long one must not push the panel
   sideways. */
.cmp__body a{overflow-wrap:anywhere}

@media (max-width:860px){
  .cmp__head{padding:var(--cmp-pad-sm) var(--cmp-pad-sm) 0}
  .cmp__body{padding:var(--cmp-body-top) var(--cmp-pad-sm) var(--cmp-pad-sm)}
}

/* ============================================================================
   INTERIOR PAGES — insights index, articles, 404
   Same components and tokens as the homepage; no new visual language (§23.4).
   ============================================================================ */
.page-head{
  padding-top:calc(var(--hdr-h) + var(--page-head-y));
  padding-bottom:0;
}
.page-head__h1{max-width:var(--measure-insights-h2)}
.page-head__lede{margin-top:var(--hero-lede-gap);max-width:var(--measure-hero-lede)}

/* Byline. Attribution sits with the category/date/read-time line rather than
   at the foot of the prose, so the reader knows who wrote it and when before
   they start reading. The two lines are one metadata block, hence the tight
   gap above and the ordinary heading gap below. */
.page-head .note-item__meta{margin-bottom:var(--byline-gap)}
.page-head__byline{margin:0 0 var(--byline-bot);max-width:var(--measure)}

/* ----------------------------------------------------------------------------
   404 — the one centred page on the site.

   Heading, then the sentence under it, then the two ways back. Nothing above
   the heading: an error code told the visitor nothing they could act on, and
   the browser had already said the same thing.

   SIZED BY ITS CONTENT, NOT BY THE VIEWPORT (2026-09-07). It used to carry
   min-height:calc(100svh - var(--hdr-h)), which forced the section to fill the
   whole screen below the fixed header and centred 278px of content inside it.
   At 1440x900 that was an 812px box holding 278px — 534px of dead space, and
   it grew with the monitor. The section is now the height of what is in it plus
   one symmetric --e404-y of air above and below, so the proportion is the same
   on every screen instead of stretching.

   The flex centring stays: it is what centres the block horizontally and keeps
   the composition identical. justify-content:center is now a no-op vertically
   and is kept only so the rule still reads as one centred composition. */
.page-404{
  padding-top:calc(var(--hdr-h) + var(--e404-y));
  padding-bottom:var(--e404-y);
  display:flex;flex-direction:column;justify-content:center;align-items:center;
  text-align:center;
}
.page-404__h1{max-width:var(--measure-404-h1)}
.page-404__lede{margin-top:var(--hero-lede-gap);max-width:var(--measure-hero-lede)}
/* One primary and one secondary, side by side, wrapping to a column on a
   narrow phone rather than shrinking below the 48px tap target. */
.page-404__acts{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:var(--e404-acts-gap);margin-top:var(--e404-acts-top);
}

/* Prose — the reading column on interior pages. */
.prose{max-width:var(--measure)}
.prose h2{font-size:var(--fs-h3);line-height:var(--lh-h3);
  margin:var(--prose-h2-top) 0 var(--prose-h2-bot)}
.prose h2:first-child{margin-top:0}
.prose p{margin:0 0 var(--stack-4)}
.prose ul{margin:0 0 var(--stack-4);padding-left:var(--stack-4);list-style:disc}
.prose li{margin-bottom:var(--stack-1)}
.prose__flag{color:var(--text-muted);font-family:var(--font-ui);font-size:var(--fs-fine);
  line-height:var(--lh-ui)}
.prose__meta{color:var(--text-muted);font-family:var(--font-ui);font-size:var(--fs-label);
  letter-spacing:var(--ls-label);text-transform:uppercase}
.prose__cta{margin-top:var(--prose-cta-top)}

/* Risk warning — required wording, set apart but never shouted (§16). */
.risk{
  font-family:var(--font-ui);font-size:var(--fs-fine);line-height:var(--lh-ui);
  color:var(--text-muted);border-left:var(--risk-bar) solid var(--border-hairline);
  padding-left:var(--risk-pad);margin:var(--risk-top) 0 0;max-width:var(--measure);
}
/* The tax sentence is required wording and has to read as its own
   statement. Set as a block inside the same warning: the bar stays
   continuous, and the sentence always starts a line instead of wrapping
   with "Tax" stranded at the end of the line above (2026-10-11). */
.risk__tax{display:block;margin-top:var(--risk-line-gap)}

.notes--index{margin-top:0}

/* Content type — "Insight" or "Client story", first in the metadata line on
   the index and the homepage rail. One step darker than the category beside
   it: enough to tell the two apart at a glance, not a badge. */
.note-item__type{color:var(--text-heading)}

.team{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gutter)}
.person__portrait{
  display:grid;place-items:center;width:100%;aspect-ratio:var(--portrait-ratio);
  object-fit:cover;margin:0 0 var(--note-pad);padding:var(--stack-3);
  background:var(--surface-alt);text-align:center;
  font-family:var(--font-ui);font-size:var(--fs-fine);color:var(--text-muted);
}
.person h3{font-size:var(--fs-h3-sm);margin-bottom:var(--note-title-bot)}
.person__bio{font-size:var(--fs-prose-sm);color:var(--text-lede);margin:0}
@media (max-width:860px){
  .team{grid-template-columns:1fr;gap:var(--grid-gap-sm)}
  .person__portrait{max-width:var(--portrait-max-sm)}
}
@media (min-width:721px) and (max-width:860px){
  .team{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gutter)}
  .person__portrait{max-width:none}
}

/* ============================================================================
   INSIGHTS RAIL CONTROLS — arrows, not words
   ============================================================================ */
.rail-x__btn{
  width:var(--icon-btn);height:var(--icon-btn);min-height:var(--icon-btn);
  padding:0;display:inline-flex;align-items:center;justify-content:center;
  border:var(--hairline) solid var(--border-hairline);border-radius:var(--radius);
  background:none;color:var(--text-link);cursor:pointer;
  transition:border-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease);
}
.rail-x__btn:hover{border-color:var(--accent);color:var(--text-link-hover)}
.rail-x__btn[disabled]{opacity:var(--btn-disabled-alpha);cursor:not-allowed;
  border-color:var(--border-hairline);color:var(--text-muted)}
.rail-x__btn svg{
  width:var(--icon-glyph);height:var(--icon-glyph);
  fill:none;stroke:currentColor;stroke-width:var(--icon-stroke);
  stroke-linecap:round;stroke-linejoin:round;
}
.rail-x__all{margin-left:auto}

/* The legal row mixes links with the cookie-settings button. Padding them
   together keeps the row aligned and gives the button a real target. */
.ftr__minor > *{padding-top:var(--mnav-link-pad);padding-bottom:var(--mnav-link-pad)}

/* ============================================================================
   OXFORD SKYLINE — the wide drawing that closes the About band.
   Same monoline hand as the nine (§11.3): flat elevation, one ink, no fill.
   It is a band, not a square, so it overrides the 1:1 slot ratio.
   ============================================================================ */
.skyline{
  margin-top:var(--skyline-top);
  /* The panorama runs out to the page margins on either side. Same bleed token
     as the hero, so the two wide drawings share one rule, and 0 below 1280. */
  margin-inline:calc(var(--art-bleed) * -1);
  width:calc(100% + var(--art-bleed) * 2);
  max-width:calc(var(--skyline-max) + var(--art-bleed) * 2);
}
.skyline .illus{width:100%}
@media (max-width:860px){
  .skyline{margin-top:var(--skyline-top-sm)}
}

/* ============================================================================
   CONTACT — the email address carries a small envelope. Inline SVG, no icon
   library, drawn in the same monoline weight as everything else.
   ============================================================================ */
.maillink{
  display:inline-flex;align-items:center;gap:var(--mailicon-gap);
  text-decoration:none;color:var(--text-link);
}
.maillink span{
  text-decoration:underline;
  text-decoration-thickness:var(--ul-thickness);
  text-underline-offset:var(--ul-offset);
}
.maillink:hover{color:var(--text-link-hover)}
.maillink:hover span{text-decoration-thickness:var(--ul-thickness-hover)}
.maillink__icon{
  flex:none;width:var(--mailicon);height:var(--mailicon);
  fill:none;stroke:currentColor;stroke-width:var(--mailicon-stroke);
  stroke-linecap:round;stroke-linejoin:round;
  /* nudged to sit on the text's optical centre rather than its box centre */
  transform:translateY(1px);
}

/* ============================================================================
   TABLET — 721px to 860px.

   A third band, added because the two-breakpoint system handed tablets the
   full mobile layout: a 24px page margin on an 820px screen, everything in
   one column, and 450px of dead space beside a 300px hero drawing. Phones
   below 721px are unaffected and the desktop bands are unchanged.

   No illustration is altered here — only the boxes they sit in.
   ============================================================================ */
@media (min-width:721px) and (max-width:860px){
  :root{
    --margin:var(--margin-md);
    --band-y:var(--band-y-md);
  }

  /* The hero drawing sat hard left with the rest of the row empty. Centred
     and a little larger, the space around it reads as deliberate. */
  .duo__art{justify-self:center;max-width:var(--art-hero-md)}

  /* There is room for the annotation rail beside its text again. */
  .railed{grid-template-columns:var(--rail) minmax(0,1fr);gap:var(--gutter)}
  .rail{position:sticky;top:calc(var(--hdr-h-sm) + var(--rail-top-gap));
    padding-bottom:0;border-bottom:0}

  /* Two columns rather than one long stack, where the block has the full
     content width to work with. */
  .steps,.notes{grid-template-columns:1fr 1fr;gap:var(--gutter)}
  /* Practice items sit inside the rail's narrower text column, so two
     columns there would give ~230px and about thirteen characters a line.
     They stay stacked and readable. */
  .prac{grid-template-columns:1fr;gap:var(--grid-gap-sm)}

  /* Service rows get their full-size artwork column back. */
  .svc__row{grid-template-columns:var(--svc-art-col) minmax(0,1fr);
    gap:var(--gutter);row-gap:0;padding:var(--row-y) 0}
  .illus--svc{height:calc(var(--art-svc) * var(--optical,1))}

  /* Two insight cards in view instead of one very wide one. */
  .rail-x .note-item{flex-basis:calc((100% - var(--gutter)) / 2)}

  /* The About band was the worst offender for vertical emptiness. */
  .band--air{padding-top:var(--band-air-y-sm);padding-bottom:var(--band-air-y-sm)}
}
