/* ==== self-hosted fonts (scripts/use_local_fonts.py) ==== */
/* Self-hosted typefaces. Generated by scripts/build_fonts.py — do not edit.
   Fetched from Google Fonts once and served from our own origin, so no
   visitor request reaches fonts.gstatic.com. Subsets: latin, latin-ext.
   latin-ext carries the Turkish characters and must not be dropped. */

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Fragment Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/fragment-mono-400-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Fragment Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/fragment-mono-400-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Literata';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/literata-300700-italic-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Literata';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/literata-300700-italic-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/literata-300700-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/literata-300700-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/source-sans-3-400-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/source-sans-3-400-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/source-sans-3-400-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/source-sans-3-400-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/source-sans-3-400-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/source-sans-3-400-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ==== end self-hosted fonts ==== */

/* ===========================================================================
   APH Resources — theme-aware newsroom design system
   Blog · case studies · whitepapers · newsletter · resources home

   Methodology: read as a news / research page. Single column. No stock
   photography — illustrations are built data exhibits. Literata (optical-size
   variable serif — crisp serifs, moderate stroke contrast) carries the
   editorial voice; Inter carries sustained body text; mono carries labels.

   Colour is APH's own — azure, amber and magenta, plus a neutral:
     · the headline runs in TWO colours — ink, with the turn of the argument
       set in italic amber (the brand's second voice)
     · exhibits use azure / amber / magenta as a categorical series so a chart
       can hold more than one idea; --c4 is a neutral for supporting data
     · light is warm paper and warm ink; dark keeps the brand's night sky but
       takes its warmth from the accents

   Contrast, measured against rendered pixels (WCAG 2.2 AA):
     LIGHT  paper #FAF8F3 · card #FFFDFA · deep #F0EBE2
       tx #171310 17.40 · tx-2 #4A443C 9.06 · tx-3 #6B6459 5.51
       azure #0C6394 6.13 · amber #946200 4.94 · magenta #B01E63 6.16
       brd #8C8478 3.48 (1.4.11)
     DARK   ink #05070B · card #0B1119 · deep #10171F
       tx #F0EDE8 17.5 · tx-2 #B9BDC4 10.6 · tx-3 #95999F 7.0
       azure #5CC4F3 10.22 · amber #F5CE8B 13.52 · magenta #F284B6 8.40
       brd #68707A 3.97
   Bright azure #1C9FE2 (2.9:1) and brand amber #EBB660 (1.8:1) are FILL-only
   on light paper, never text. Chart series are separated by hue, so every
   series also carries a direct label or a distinct stroke — never colour alone.
   =========================================================================== */

/* ---------- tokens ---------- */
:root{
  color-scheme:dark;
  --bg:#05070B; --bg-soft:#080B11; --surface:#0B1119; --surface-2:#10171F;
  --tx:#F0EDE8; --tx-2:#B9BDC4; --tx-3:#95999F;
  --rule:rgba(255,255,255,.13); --rule-2:rgba(255,255,255,.2); --brd:#68707A;
  --acc:#5CC4F3; --acc-hover:#9FDEFF; --acc-fill:linear-gradient(135deg,#1C9FE2,#0E84C6);
  --acc-on-fill:#04121D; --acc-soft:rgba(28,159,226,.11); --acc-line:rgba(92,196,243,.34);
  --amber:#F5CE8B; --amber-soft:rgba(235,182,96,.12); --amber-line:rgba(245,206,139,.34);
  --mag:#F284B6; --mag-soft:rgba(242,132,182,.12); --mag-line:rgba(242,132,182,.34);
  --a2:#F5CE8B; --a2-line:rgba(245,206,139,.36);                                   /* the warm second voice — brand amber */
  --a2-fill:linear-gradient(135deg,#EBB660,#C98F35); --a2-on-fill:#241303;
  /* chart series — APH's three, plus a neutral for supporting data */
  --c1:#5CC4F3; --c2:#F5CE8B; --c3:#F284B6; --c4:#95999F;
  --grid:rgba(255,255,255,.09);
  --shadow:0 20px 46px -26px rgba(0,0,0,.8);
  --sel:rgba(28,159,226,.35); --sel-tx:#fff; --hl:rgba(92,196,243,.16);
  --act-acc:#0C6394;
  --fd:"Archivo",sans-serif; --fs:"Literata",Georgia,serif;
  --fb:"Source Sans 3",sans-serif; --fm:"Fragment Mono",monospace;
  --ease:cubic-bezier(.2,.6,.2,1);
  --nav-h:76px; --mx:clamp(18px,5vw,48px);   /* 76 matches the marketing header */
  --col:810px; --ex:1010px;
}
[data-theme="light"]{
  color-scheme:light;
  --bg:#FAF8F3; --bg-soft:#F3EFE7; --surface:#FFFDFA; --surface-2:#F0EBE2;
  --tx:#171310; --tx-2:#4A443C; --tx-3:#6B6459;
  --rule:rgba(23,19,16,.15); --rule-2:rgba(23,19,16,.26); --brd:#8C8478;
  --acc:#0C6394; --acc-hover:#084E76; --acc-fill:linear-gradient(135deg,#0C6394,#084E76);
  --acc-on-fill:#FFFDFA; --acc-soft:rgba(12,99,148,.07); --acc-line:rgba(12,99,148,.28);
  --amber:#946200; --amber-soft:rgba(148,98,0,.09); --amber-line:rgba(148,98,0,.32);
  --mag:#B01E63; --mag-soft:rgba(176,30,99,.08); --mag-line:rgba(176,30,99,.3);
  --a2:#946200; --a2-line:rgba(148,98,0,.32);
  --a2-fill:linear-gradient(135deg,#9E6300,#7C4C00); --a2-on-fill:#FFFDFA;
  --c1:#0C6394; --c2:#946200; --c3:#B01E63; --c4:#6B6459;
  --grid:rgba(23,19,16,.11);
  --shadow:0 18px 40px -24px rgba(23,19,16,.24);
  --sel:rgba(28,159,226,.2); --sel-tx:#171310; --hl:rgba(235,182,96,.22);
  --act-acc:#7FD4FA;
}
@media (prefers-color-scheme:light){
  :root:not([data-theme]){
    color-scheme:light;
    --bg:#FAF8F3; --bg-soft:#F3EFE7; --surface:#FFFDFA; --surface-2:#F0EBE2;
    --tx:#171310; --tx-2:#4A443C; --tx-3:#6B6459;
    --rule:rgba(23,19,16,.15); --rule-2:rgba(23,19,16,.26); --brd:#8C8478;
    --acc:#0C6394; --acc-hover:#084E76; --acc-fill:linear-gradient(135deg,#0C6394,#084E76);
    --acc-on-fill:#FFFDFA; --acc-soft:rgba(12,99,148,.07); --acc-line:rgba(12,99,148,.28);
    --amber:#946200; --amber-soft:rgba(148,98,0,.09); --amber-line:rgba(148,98,0,.32);
    --mag:#B01E63; --mag-soft:rgba(176,30,99,.08); --mag-line:rgba(176,30,99,.3);
    --a2:#946200; --a2-line:rgba(148,98,0,.32);
    --a2-fill:linear-gradient(135deg,#9E6300,#7C4C00); --a2-on-fill:#FFFDFA;
    --c1:#0C6394; --c2:#946200; --c3:#B01E63; --c4:#6B6459;
    --grid:rgba(23,19,16,.11);
    --shadow:0 18px 40px -24px rgba(23,19,16,.24);
    --sel:rgba(28,159,226,.2); --sel-tx:#171310; --hl:rgba(235,182,96,.22);
    --act-acc:#7FD4FA;
  }
}

/* ---------- base ---------- */
*{margin:0;padding:0;box-sizing:border-box}
/* [hidden] must win. Any component rule that sets `display` silently defeats
   the attribute, and JS all over this stylesheet's pages hides things with it.
   That has now bitten three times — .fdone left a 154px hole on the form,
   then .leadc and .gc kept painting after the side filter hid them — so it is
   settled once here instead of being rediscovered per component. */
[hidden]{display:none!important}
html{scroll-behavior:smooth;scroll-padding-top:calc(var(--nav-h) + 24px)}
body{background:var(--bg);color:var(--tx-2);font:400 17px/1.6 var(--fb);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:hidden}
img,svg,video{max-width:100%;display:block}
a{color:inherit}
::selection{background:var(--sel);color:var(--sel-tx)}
:focus-visible{outline:2px solid var(--acc);outline-offset:3px;border-radius:2px}
body,.nav,.card,.ex,.act,.pq,.tw,input,button,.sh{
  transition:background-color .28s var(--ease),border-color .28s var(--ease),color .28s var(--ease)}
.no-tr *,.no-tr{transition:none !important}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important}
}

/* ---------- nav ---------- */
.nav{position:fixed;inset:0 0 auto 0;height:var(--nav-h);z-index:60;display:flex;align-items:center;
  gap:clamp(16px,2.2vw,36px);padding:0 var(--mx);background:color-mix(in srgb,var(--bg) 93%,transparent);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border-bottom:1px solid var(--rule)}
.nav .logo img{height:30px;width:auto}
[data-theme="light"] .nav .logo img,[data-theme="light"] .footer img{
  filter:invert(1) hue-rotate(180deg) saturate(1.5) brightness(.72)}
@media (prefers-color-scheme:light){
  :root:not([data-theme]) .nav .logo img,:root:not([data-theme]) .footer img{
    filter:invert(1) hue-rotate(180deg) saturate(1.5) brightness(.72)}
}
.nav .links{display:flex;gap:clamp(14px,1.6vw,26px);align-items:center;flex:1}
.navlink{font:500 13px/1 var(--fb);color:var(--tx-2);text-decoration:none;padding:6px 0;
  position:relative;transition:color .2s;white-space:nowrap}
.navlink:hover,.navlink[aria-current="page"]{color:var(--tx)}
.navlink[aria-current="page"]::after{content:"";position:absolute;left:0;right:0;bottom:-2px;
  height:2px;background:var(--acc)}
.navr{margin-left:auto;display:flex;align-items:center;gap:11px}
.navcta{font:400 12px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;text-decoration:none;
  padding:10px 15px;background:var(--acc-fill);color:var(--acc-on-fill);white-space:nowrap;
  transition:filter .2s}
.navcta:hover{filter:brightness(1.08)}

/* theme toggle — always there, never shouting */
.tt{all:unset;box-sizing:border-box;cursor:pointer;width:36px;height:36px;flex:none;
  display:inline-flex;align-items:center;justify-content:center;border-radius:50%;
  border:1px solid var(--rule-2);color:var(--tx-3);transition:color .2s,border-color .2s,background .2s}
.tt:hover{color:var(--tx);border-color:var(--brd);background:var(--surface-2)}
.tt:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.tt svg{width:16px;height:16px;fill:currentColor}
.tt .moon{display:none}
[data-theme="light"] .tt .sun{display:none}
[data-theme="light"] .tt .moon{display:block}
@media (prefers-color-scheme:light){
  :root:not([data-theme]) .tt .sun{display:none}
  :root:not([data-theme]) .tt .moon{display:block}
}
.prog{position:fixed;top:var(--nav-h);left:0;height:2px;z-index:59;width:0;
  background:var(--acc);transition:width .1s linear}

/* ---------- single-column shell ---------- */
main{padding-top:var(--nav-h)}
.col{max-width:var(--col);margin:0 auto;padding:0 var(--mx)}
.wide{max-width:var(--ex);margin:0 auto;padding:0 var(--mx)}

.crumb{display:flex;flex-wrap:wrap;gap:7px;align-items:center;padding:30px 0 0;
  font:400 10.5px/1.6 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
.crumb a{color:var(--tx-3);text-decoration:none}
.crumb a:hover{color:var(--acc)}
.crumb span[aria-hidden]{opacity:.45}
.crumb .cat{color:var(--a2)}

/* masthead */
.head{padding:22px 0 0}
.tag{display:inline-block;font:400 10.5px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;
  color:var(--a2-on-fill);background:var(--a2-fill);padding:9px 13px;text-decoration:none}
a.tag:hover{filter:brightness(1.08)}
h1{font:400 clamp(36px,5.4vw,64px)/1.04 var(--fs);color:var(--tx);letter-spacing:-.022em;
  margin:22px 0 0;text-wrap:balance;font-variation-settings:"opsz" 110}
/* the turn of the argument, in the warm second voice */
h1 em{font-style:italic;color:var(--a2);font-variation-settings:"opsz" 110}
.deck{font:300 italic clamp(19px,2vw,25px)/1.48 var(--fs);color:var(--tx-2);margin-top:20px;
  letter-spacing:-.004em;text-wrap:pretty;font-variation-settings:"opsz" 40}

.by{display:flex;flex-wrap:wrap;align-items:center;gap:13px;margin-top:26px;padding:18px 0;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.mono{flex:none;width:38px;height:38px;border-radius:50%;display:grid;place-items:center;
  font:600 13px/1 var(--fs);letter-spacing:.02em;background:var(--a2-fill);color:var(--a2-on-fill)}

/* Desk marks. Three letters and one of five tones across the two brand hues:
   azure for the desks about the machinery (Regulation, Programmatic,
   Publisher), amber for the two about money moving (Marketing, Video).
   Measured text-on-mark, lowest of the ten: 6.41:1 light, 6.64:1 dark.
   A pale mark on paper needs the ring for the same reason a --surface panel
   does: at 1.58:1 against the page the fill alone is not an object. */
.mono[data-desk]{background:var(--dk-fill);color:var(--dk-tx);
  box-shadow:inset 0 0 0 1px var(--dk-ring);font-size:13px;letter-spacing:.06em}
.mono[data-desk="regulation"]  {--dk-fill:#073E5E;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
.mono[data-desk="programmatic"]{--dk-fill:#0C6394;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
.mono[data-desk="publisher"]   {--dk-fill:#7FC0DF;--dk-tx:#06304A;--dk-ring:rgba(6,48,74,.34)}
.mono[data-desk="marketing"]   {--dk-fill:#7C4C00;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
.mono[data-desk="video"]       {--dk-fill:#EAC282;--dk-tx:#4A2E00;--dk-ring:rgba(74,46,0,.34)}
@media (prefers-color-scheme:dark){
  .mono[data-desk="regulation"]   {--dk-fill:#9FDEFF;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
  .mono[data-desk="programmatic"] {--dk-fill:#4FB0E0;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
  .mono[data-desk="publisher"]    {--dk-fill:#CDEAF7;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
  .mono[data-desk="marketing"]    {--dk-fill:#E0A94F;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
  .mono[data-desk="video"]        {--dk-fill:#F5CE8B;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
}
:root[data-theme="dark"] .mono[data-desk="regulation"]  {--dk-fill:#9FDEFF;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .mono[data-desk="programmatic"]{--dk-fill:#4FB0E0;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .mono[data-desk="publisher"]   {--dk-fill:#CDEAF7;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .mono[data-desk="marketing"]   {--dk-fill:#E0A94F;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .mono[data-desk="video"]       {--dk-fill:#F5CE8B;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="light"] .mono[data-desk="regulation"]  {--dk-fill:#073E5E;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
:root[data-theme="light"] .mono[data-desk="programmatic"]{--dk-fill:#0C6394;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
:root[data-theme="light"] .mono[data-desk="publisher"]   {--dk-fill:#7FC0DF;--dk-tx:#06304A;--dk-ring:rgba(6,48,74,.34)}
:root[data-theme="light"] .mono[data-desk="marketing"]   {--dk-fill:#7C4C00;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
:root[data-theme="light"] .mono[data-desk="video"]       {--dk-fill:#EAC282;--dk-tx:#4A2E00;--dk-ring:rgba(74,46,0,.34)}
.bym{display:flex;flex-direction:column;gap:3px;min-width:0}
.bym .who,.bym .meta{display:block}
.bym .who{font:600 13px/1.3 var(--fb);color:var(--tx)}
.bym .meta{font:400 10.5px/1.4 var(--fm);letter-spacing:.12em;text-transform:uppercase;color:var(--tx-3)}
.bym .meta i{font-style:normal;opacity:.5;margin:0 6px}
.by .shr{margin-left:auto;display:flex;gap:7px;flex-wrap:wrap}

.sh{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
  min-height:34px;padding:0 11px;border:1px solid var(--rule);font:400 9px/1 var(--fm);
  letter-spacing:.1em;text-transform:uppercase;color:var(--tx-3);text-decoration:none;
  transition:color .2s,border-color .2s}
.sh:hover{color:var(--tx);border-color:var(--brd)}
.sh:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.sh svg{width:13px;height:13px;fill:currentColor;flex:none}
.sh.done{color:var(--acc);border-color:var(--acc-line)}

/* in-piece contents — a newspaper standfirst box, not a sidebar */
.tocw{margin-top:26px;border:1px solid var(--rule);background:var(--surface)}
.tocw summary{cursor:pointer;list-style:none;padding:13px 16px;display:flex;align-items:center;gap:9px;
  font:400 10.5px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--tx-2)}
.tocw summary::-webkit-details-marker{display:none}
.tocw summary::after{content:"";margin-left:auto;width:7px;height:7px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(45deg) translateY(-2px);transition:transform .25s}
.tocw[open] summary::after{transform:rotate(-135deg) translateY(-2px)}
.toc{list-style:none;padding:0 16px 14px;display:grid;gap:1px}
.toc a{display:flex;gap:10px;padding:6px 0;font:500 13px/1.45 var(--fb);color:var(--tx-3);
  text-decoration:none;transition:color .2s}
.toc a:hover,.toc a.on{color:var(--acc)}
.toc a b{font:400 10.5px/1.6 var(--fm);color:var(--tx-3);flex:none;letter-spacing:.06em}
.toc a.on b{color:var(--acc)}

/* ---------- prose ---------- */
.prose{margin-top:34px}
.prose>*+*{margin-top:22px}
.prose p{font:400 19px/1.68 var(--fb);color:var(--tx-2);text-wrap:pretty}
.prose>p.lede{font:300 clamp(21px,2.1vw,24px)/1.5 var(--fs);color:var(--tx);
  font-variation-settings:"opsz" 44}
.prose strong{color:var(--tx);font-weight:600}
.prose em{font-style:italic}
.prose a:not(.cta){color:var(--acc);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:var(--acc-line);transition:color .2s}
.prose a:not(.cta):hover{color:var(--acc-hover);text-decoration-color:currentColor}
.prose h2{display:flex;align-items:baseline;gap:16px;margin-top:58px;padding-top:26px;
  border-top:1px solid var(--rule);
  font:400 clamp(27px,3.2vw,38px)/1.14 var(--fs);color:var(--tx);letter-spacing:-.02em;
  scroll-margin-top:calc(var(--nav-h) + 24px);text-wrap:balance;
  font-variation-settings:"opsz" 72}
.prose h2 .n{flex:none;font:400 12px/1 var(--fm);letter-spacing:.1em;color:var(--a2);
  transform:translateY(-.5em)}
.prose h2 em{font-style:italic;color:var(--a2)}
.prose h3{margin-top:34px;font:600 19px/1.35 var(--fb);color:var(--tx);
  scroll-margin-top:calc(var(--nav-h) + 24px)}
.prose h2:target,.prose h3:target{background:var(--hl);box-shadow:0 0 0 8px var(--hl)}
.prose ul,.prose ol{padding-left:1.3em;display:flex;flex-direction:column;gap:.55em}
.prose li{font:400 19px/1.72 var(--fb);color:var(--tx-2)}
.prose li::marker{color:var(--acc);font-family:var(--fm);font-size:.82em}
.prose hr{border:0;border-top:1px solid var(--rule);margin:44px 0}
.prose code{font:400 .86em/1.5 var(--fm);background:var(--surface-2);border:1px solid var(--rule);
  padding:.1em .38em;color:var(--tx)}

/* pull quote */
.pq{margin-top:44px;padding:6px 0 6px 26px;border-left:3px solid var(--a2);
  font:400 italic clamp(22px,2.5vw,30px)/1.32 var(--fs);color:var(--tx);letter-spacing:-.012em;
  font-variation-settings:"opsz" 60}
.pq cite{display:block;margin-top:14px;font:400 10.5px/1.5 var(--fm);letter-spacing:.14em;
  text-transform:uppercase;color:var(--tx-3);font-style:normal}

/* ---------- exhibits: charts, diagrams, figures ---------- */
.ex{margin:44px 0;border:1px solid var(--rule);background:var(--surface)}
.exh{padding:16px 18px 14px;border-bottom:1px solid var(--rule)}
.exh .k,.exh .t,.exh .s{display:block}
.exh .k{font:400 9px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--a2)}
.exh .t{margin-top:9px;font:400 22px/1.22 var(--fs);color:var(--tx);letter-spacing:-.014em;
  font-variation-settings:"opsz" 40}
.exh .s{margin-top:5px;font:400 13px/1.5 var(--fb);color:var(--tx-3)}
/* Charts do not shrink below legibility; they scroll.
   The exhibit body is ~598px inside a dossier and ~676px in the article
   column, and only ~275px on a phone. A 760-unit viewBox rendered at 275px
   puts its 12.5-unit annotation at 4.1px. Shrinking a chart past the point
   where you can read it is not responsive, it is just smaller — so below the
   width that keeps the smallest label at 10px, the chart keeps its size and
   the exhibit scrolls instead.
   760 * (10 / 12.5) = 608px is the real floor; 640 leaves margin. */
/* The signature opener on an article: the piece's own figure, drawn, or a
   photograph where it states none. Same frame either way so the two read as
   one device rather than two. */
.ex.open{margin:34px 0 44px}
.ex.open .exb{padding:0}
.ex.open .exb svg{min-width:0;width:100%;height:auto;display:block;
  padding:20px 18px;box-sizing:border-box}
.opix{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;
  background:var(--ink,#05070B)}
/* The photographs are lit for the dark theme. On paper they need a hairline to
   sit on, or a near-black plate floats on cream with no edge. */
[data-theme="light"] .opix{border-bottom:1px solid var(--rule)}

/* ---------- the claim table ----------
   Where a piece states its case as bolded claims with an explanation under
   each, that is already two columns. Setting it as a table rather than a
   bulleted list is what makes it scannable — and it is the device that works
   on the pieces with no figures to strip. */
.prose .ctab{width:100%;margin-top:40px;border-collapse:collapse;
  border-top:2px solid var(--tx)}
.prose .ctab caption{caption-side:top;text-align:left;padding-bottom:11px;
  font:400 10.5px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;
  color:var(--a2)}
.prose .ctab th{width:38%;padding:16px 20px 16px 0;text-align:left;vertical-align:top;
  border-bottom:1px solid var(--rule);
  font:600 15px/1.35 var(--fb);color:var(--tx)}
.prose .ctab td{padding:16px 0;vertical-align:top;
  border-bottom:1px solid var(--rule);
  font:400 15px/1.6 var(--fb);color:var(--tx-2)}
.prose .ctab tr:hover th,.prose .ctab tr:hover td{background:var(--surface)}
@media (max-width:640px){
  /* the global table rule carries min-width:480px, which survives the switch
     to block layout and pushed 48 of the 60 pages tested off-screen at 390px */
  .prose .ctab,.prose .ctab tbody,.prose .ctab tr{display:block;min-width:0}
  .prose .ctab th,.prose .ctab td{display:block;width:auto;padding:0}
  .prose .ctab th{padding-top:16px}
  .prose .ctab td{padding:6px 0 16px;border-bottom:1px solid var(--rule)}
}

 /* a card whose piece carries a photograph rather than a chart */
.sig.pic{display:block;overflow:hidden}
.sig.pic img{display:block;width:100%;height:100%;object-fit:cover}

.exb{padding:20px 18px;overflow-x:auto;overscroll-behavior-x:contain}
.exb svg{min-width:640px}
.exb::-webkit-scrollbar{height:6px}
.exb::-webkit-scrollbar-thumb{background:var(--rule-2)}
.exf{padding:11px 18px 13px;border-top:1px solid var(--rule);background:var(--surface-2);
  font:400 13px/1.55 var(--fb);color:var(--tx-3)}
.ex svg{width:100%;height:auto;overflow:visible}
.exkey{display:flex;flex-wrap:wrap;gap:16px;padding:0 18px 16px}
.exkey span{display:inline-flex;align-items:center;gap:7px;font:400 9px/1 var(--fm);
  letter-spacing:.1em;text-transform:uppercase;color:var(--tx-3)}
.exkey i{width:11px;height:11px;flex:none;display:inline-block}

/* a photograph, when an article needs one, sits inside the column */
.ph{margin:44px 0;border:1px solid var(--rule);background:var(--surface)}
.ph img{width:100%}
.ph figcaption{padding:11px 18px 13px;border-top:1px solid var(--rule);background:var(--surface-2);
  font:400 13px/1.55 var(--fb);color:var(--tx-3)}

/* ---------- number blocks ---------- */
.stats{margin:40px 0;display:grid;grid-template-columns:repeat(4,1fr);
  border-top:1px solid var(--rule-2);border-bottom:1px solid var(--rule-2)}
.stats>div{padding:20px 16px 18px;border-right:1px solid var(--rule)}
.stats>div:last-child{border-right:0}
.stats .v{display:flex;align-items:baseline;gap:3px;font:400 clamp(31px,3.5vw,44px)/1 var(--fs);
  color:var(--tx);letter-spacing:-.018em}
.stats .v{font-variation-settings:"opsz" 54}
.stats .v s{text-decoration:none;font-size:.52em;color:var(--c1)}
.stats>div:nth-child(2) .v s{color:var(--c1)}   /* magenta is reserved for the losses */
.stats>div:nth-child(3) .v,.stats>div:nth-child(4) .v{color:var(--mag)}
.stats>div:nth-child(3) .v s,.stats>div:nth-child(4) .v s{color:var(--mag)}
.stats .l,.stats .sub{display:block}
.stats .l{margin-top:10px;font:600 13px/1.35 var(--fb);color:var(--tx)}
.stats .sub{margin-top:3px;font:400 9px/1.4 var(--fm);letter-spacing:.08em;text-transform:uppercase;
  color:var(--tx-3)}

/* number table — newsprint, not a card */
.tw{margin:40px 0;overflow-x:auto;border-top:1px solid var(--rule-2);border-bottom:1px solid var(--rule-2)}
table{width:100%;border-collapse:collapse;min-width:480px}
th,td{padding:13px 14px;text-align:left;border-bottom:1px solid var(--rule);vertical-align:baseline}
thead th{font:400 9px/1.4 var(--fm);letter-spacing:.13em;text-transform:uppercase;color:var(--tx-3);
  border-bottom:1px solid var(--rule-2)}
tbody td{font:400 15px/1.5 var(--fb);color:var(--tx-2)}
tbody tr:last-child td{border-bottom:0}
td.num,th.num{text-align:right;font:400 15px/1.5 var(--fm);color:var(--tx);white-space:nowrap}
tr.peak td{background:var(--acc-soft)}
tr.peak td:first-child{box-shadow:inset 2px 0 0 var(--acc)}
caption{caption-side:bottom;padding:11px 14px 0;font:400 13px/1.55 var(--fb);color:var(--tx-3);
  text-align:left}

/* inverted action panel — flips with the theme, always the measured 17:1 pair */
.act{margin:44px 0;padding:26px 24px 22px;background:var(--tx);color:var(--bg)}
/* The action panel inverts the page: its background is --tx and its text is
   --bg. The global ::selection paints --sel-tx, which is the *page's* text
   colour — near-black in light mode — so selecting inside this panel put
   near-black type on a translucent highlight over a near-black panel and the
   words disappeared. Inside an inverted block the selection has to invert too. */
.act ::selection,.act::selection{background:var(--sel);color:var(--bg)}
.act .t::selection,.act b::selection,.act p::selection,
.act li::selection,.act span::selection{color:var(--bg)}
.act .k{font:400 10.5px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--act-acc)}
.act .t{margin-top:11px;font:400 clamp(21px,2.4vw,27px)/1.24 var(--fs);color:var(--bg);
  letter-spacing:-.014em;font-variation-settings:"opsz" 48}
.act ol{list-style:none;margin-top:20px;padding:0;display:flex;flex-direction:column}
.act li{display:grid;grid-template-columns:44px 1fr;gap:14px;padding:15px 0;
  border-top:1px solid color-mix(in srgb,var(--bg) 26%,transparent)}
.act li:last-child{border-bottom:1px solid color-mix(in srgb,var(--bg) 26%,transparent)}
.act li .i{font:400 12px/1.7 var(--fm);letter-spacing:.08em;color:var(--act-acc)}
.act li p{font:400 15px/1.62 var(--fb);color:color-mix(in srgb,var(--bg) 82%,var(--tx))}
.act li b{display:block;font:600 15px/1.4 var(--fb);color:var(--bg);margin-bottom:4px}

/* sources */
.src{margin-top:52px;padding-top:22px;border-top:1px solid var(--rule-2)}
.src h2{font:400 10.5px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--tx-3);
  margin:0 0 14px;display:block}
.src ol{padding-left:1.15em;display:flex;flex-direction:column;gap:8px}
.src li{font:400 13px/1.6 var(--fb);color:var(--tx-3)}
.src p{font:400 13px/1.6 var(--fb);color:var(--tx-3);margin:0}
.src p + p{margin-top:8px}
.src a{color:var(--acc);text-decoration:underline;text-underline-offset:2px;word-break:break-word}

/* ---------- the Weekly, one issue ----------
   A story in the letter is a passage of reporting followed by the thing the
   letter exists for: what a publisher should do about it. The takeaway is set
   apart so it reads as advice rather than as more reporting. Amber sits on
   --surface here, which is one of the two backgrounds it is legible on.

   Every selector is scoped under .prose deliberately: .prose p, .prose h3 and
   .prose a:not(.cta) are all two-class selectors, so an unscoped .take p loses
   to them and the callout renders as ordinary body copy. */
/* --surface against the page is 1.05:1 in light and 1.06:1 in dark, so the
   fill alone never reads as a panel in either theme — the hairline is what
   makes it one. --surface is also the darkest ground amber clears 4.5:1 on
   (5.16); --surface-2 measures 4.41 and is why the amber-on-surface-2 rule
   exists. */
.prose .take{margin-top:28px;padding:20px 24px;background:var(--surface);
  border:1px solid var(--rule);border-left:3px solid var(--a2);
  border-radius:0 3px 3px 0}
.prose .take h3{margin:0 0 11px;font:400 10.5px/1 var(--fm);letter-spacing:.16em;
  text-transform:uppercase;color:var(--a2)}
.prose .take p{margin:0;font:400 17px/1.66 var(--fb);color:var(--tx-2)}
.prose .take p + p{margin-top:13px}
.prose .take strong{color:var(--tx);font-weight:600}
.prose .take ul,.prose .take ol{margin:11px 0 0;padding-left:1.25em;
  display:flex;flex-direction:column;gap:.45em}
.prose .take li{font:400 15px/1.62 var(--fb);color:var(--tx-2)}

/* the link from a story in the letter to the piece it was cut from */
.prose a.rdmore{display:inline-flex;align-items:center;gap:9px;margin-top:20px;
  font:400 10.5px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;
  color:var(--acc);text-decoration:none;padding:9px 0;
  border-bottom:1px solid transparent}
.prose a.rdmore:hover{color:var(--acc-hover);border-bottom-color:currentColor;
  text-decoration:none}

/* the issue's own standfirst — the line under the nameplate */
.isline{margin-top:14px;font:300 italic clamp(19px,2.2vw,23px)/1.42 var(--fs);
  color:var(--tx-2);letter-spacing:-.01em;text-wrap:pretty}

@media (max-width:640px){
  .prose .take{padding:16px 18px}
  .prose .take p{font-size:15px}
  .prose .take li{font-size:15px}
}

/* ---------- blocks below ---------- */
.sect{margin-top:64px}
.sh2{font:400 clamp(22px,2.4vw,30px)/1.2 var(--fs);color:var(--tx);letter-spacing:-.018em;
  font-variation-settings:"opsz" 48}
.slead{font:400 15px/1.6 var(--fb);color:var(--tx-3);margin-top:7px}

.nl{margin-top:64px;border-top:1px solid var(--rule-2);border-bottom:1px solid var(--rule-2);
  padding:32px 0}
.nl .kk{display:block;font:400 10.5px/1 var(--fm);letter-spacing:.18em;text-transform:uppercase;color:var(--a2)}
.nl h2{font:400 clamp(24px,2.8vw,33px)/1.18 var(--fs);color:var(--tx);margin-top:12px;
  letter-spacing:-.02em;font-variation-settings:"opsz" 56}
.nl h2 em{font-style:italic;color:var(--a2)}
.nl p{font:400 15px/1.65 var(--fb);color:var(--tx-2);margin-top:10px;max-width:52ch}
/* align-items:flex-end, not the default stretch: the label is a column of
   caption + input, so a stretched button grows to ~62px and stands taller than
   the field it belongs to. And the field does not grow — flex:1 let it run the
   full width of the section, which on a 1084px column is a 900px box asking
   for an email address. */
.nlf{display:flex;align-items:flex-end;gap:9px;flex-wrap:wrap;margin-top:20px}
.nlf label{flex:0 1 380px;min-width:220px;display:flex;flex-direction:column;gap:5px}
.nlf .lbl{font:400 9px/1.4 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
input[type=email],input[type=text]{width:100%;min-height:44px;padding:11px 13px;background:var(--surface);
  border:1px solid var(--brd);color:var(--tx);font:500 15px/1.4 var(--fb);outline:none;
  transition:border-color .2s,box-shadow .2s}
input:focus{border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-soft)}
.cta{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;
  justify-content:center;gap:8px;min-height:44px;padding:0 20px;background:var(--acc-fill);
  color:var(--acc-on-fill);font:400 12px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;transition:filter .2s}
.cta:hover{filter:brightness(1.08)}
.cta:focus-visible{outline:2px solid var(--acc);outline-offset:3px}
.nlmicro{font:400 13px/1.55 var(--fb);color:var(--tx-3);margin-top:12px}

.rel{display:grid;gap:0;margin-top:18px;border-top:1px solid var(--rule)}
.card{display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:baseline;
  padding:18px 0;border-bottom:1px solid var(--rule);text-decoration:none;transition:background .2s}
.card:hover{background:var(--surface)}
.card .ck,.card .cm{display:block}
.card .ck{font:400 9px/1.6 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--a2);
  min-width:92px}
.card .cb h3{font:400 19px/1.3 var(--fs);color:var(--tx);letter-spacing:-.014em;
  font-variation-settings:"opsz" 36}
.card .cb p{font:400 13px/1.6 var(--fb);color:var(--tx-3);margin-top:4px}
.card .cm{font:400 9px/1.6 var(--fm);letter-spacing:.1em;text-transform:uppercase;color:var(--tx-3);
  white-space:nowrap}

.pn{display:grid;gap:0;margin-top:22px;border-top:1px solid var(--rule)}
.pn a{display:flex;flex-direction:column;gap:6px;padding:16px 0;border-bottom:1px solid var(--rule);
  text-decoration:none;transition:background .2s}
.pn a:hover{background:var(--surface)}
.pn .d,.pn .t{display:block}
.pn .d{font:400 9px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
.pn .t{font:400 17px/1.33 var(--fs);color:var(--tx);letter-spacing:-.014em;
  font-variation-settings:"opsz" 36}

/* ---------- footer ---------- */
.footer{margin-top:80px;border-top:1px solid var(--rule);background:var(--bg-soft);
  padding:36px var(--mx) 44px}
.footin{max-width:var(--ex);margin:0 auto;display:flex;flex-wrap:wrap;gap:22px;align-items:center}
/* The footer carried the lockup at 26px (22px on Resources), which puts the
   three ARCHON / PROGRAMMATIC / HOUSE lines at about 4px each — present but
   not readable. The owner asked for +25%; that only reaches ~5px, so this
   goes to 42px, the height the header already uses. One lockup size for the
   site, and the footer has the room: its middle is empty at every width. */
.footer img{height:42px;width:auto}
.footer .fcols{display:flex;gap:20px;flex-wrap:wrap;margin-left:auto}
.footer a{font:500 13px/1 var(--fb);color:var(--tx-3);text-decoration:none;transition:color .2s}
.footer a:hover{color:var(--tx)}
.footer .cr{width:100%;font:400 13px/1.6 var(--fb);color:var(--tx-3)}

/* ---------- reveals ---------- */
.rv{opacity:0;transform:translateY(12px);transition:opacity .6s var(--ease),transform .6s var(--ease)}
.rv.on{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.rv{opacity:1;transform:none}}

/* ---------- responsive ---------- */
@media(max-width:860px){
  .stats{grid-template-columns:repeat(2,1fr)}
  .stats>div:nth-child(2){border-right:0}
  .stats>div:nth-child(-n+2){border-bottom:1px solid var(--rule)}
}
@media(max-width:720px){
  .nav .links{display:none}
  .prose p,.prose li{font-size:17px;line-height:1.68}
  .prose>p.lede{font-size:19px}
  .by .shr{margin-left:0;width:100%}
  .card{grid-template-columns:1fr;gap:6px}
  .card .cm{grid-row:1;justify-self:start}
  .act li{grid-template-columns:32px 1fr;gap:10px}
}
@media(max-width:430px){ .stats{grid-template-columns:1fr} .stats>div{border-right:0;border-bottom:1px solid var(--rule)} }

/* ---------- print ---------- */
@media print{
  .nav,.prog,.nl,.rel,.pn,.footer,.sect,.crumb,.by .shr,.tocw{display:none !important}
  html,body{background:#fff;color:#000}
  main{padding-top:0}
  .prose p,.prose li,.deck{color:#111}
  h1,.prose h2,.prose h3,.prose strong,.exh .t{color:#000}
  .ex,.tw,.act,.ph{break-inside:avoid;border-color:#bbb}
  .act{background:#fff;color:#000;border:1px solid #bbb}
  .act .t,.act li b,.act li p{color:#000}
  .prose a:not(.cta)::after{content:" (" attr(href) ")";font-size:.75em;color:#555;word-break:break-all}
}

/* --- span-based blocks: these are <span> for markup economy, not for flow --- */
.exh .k,.exh .t,.exh .s,
.stats .l,.stats .sub,
.nl .kk,
.bym .who,.bym .meta,
.pn .d,.pn .t,
.card .ck,.card .cm,.card .cb{display:block}

/* ===========================================================================
   CASE STUDY — a layered read.
   Layer 1 (.glance) is the whole case in 60 seconds. Layers 2 and 3 are for
   readers who want the working and the transferable lesson.
   =========================================================================== */
.glance{margin-top:30px;border:1px solid var(--rule-2);background:var(--surface);
  border-top:3px solid var(--a2)}
.glance .gh{padding:16px 20px 0;font:400 10.5px/1 var(--fm);letter-spacing:.18em;
  text-transform:uppercase;color:var(--a2)}
.glance .gs{padding:12px 20px 18px;font:400 clamp(19px,2vw,23px)/1.42 var(--fs);color:var(--tx);
  letter-spacing:-.012em;font-variation-settings:"opsz" 40}
.gl{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--rule)}
.gl>div{padding:18px 20px 16px;border-right:1px solid var(--rule)}
.gl>div:last-child{border-right:0}
.gl .v{display:flex;align-items:baseline;gap:2px;font:400 clamp(27px,3vw,38px)/1 var(--fs);
  color:var(--tx);letter-spacing:-.018em;font-variation-settings:"opsz" 54}
.gl .v s{text-decoration:none;font-size:.5em;color:var(--c1)}
.gl .l{display:block;margin-top:9px;font:600 13px/1.35 var(--fb);color:var(--tx)}
.gl .sub{display:block;margin-top:3px;font:400 9px/1.4 var(--fm);letter-spacing:.08em;
  text-transform:uppercase;color:var(--tx-3)}
.glance /* Provenance that belongs in the panel, not in a footnote: whose numbers these
   are, or that the client is anonymised, or that a relationship has ended. It
   sits inside the 60-second version because that is the part everyone reads. */
.gnote{margin-top:14px;padding-top:13px;border-top:1px solid var(--rule-2);
  font:400 13px/1.6 var(--fb);color:var(--tx-3)}
.gnote b{font-weight:600;color:var(--tx-2)}
.go{padding:15px 20px 17px;border-top:1px solid var(--rule);background:var(--surface-2);
  font:400 15px/1.62 var(--fb);color:var(--tx-2)}
.glance .go b{color:var(--tx)}

/* numbered work list — the "what we actually did" */
.steps{list-style:none;margin-top:24px;padding:0;display:flex;flex-direction:column}
.steps li{display:grid;grid-template-columns:46px 1fr;gap:16px;padding:18px 0;
  border-top:1px solid var(--rule)}
.steps li:last-child{border-bottom:1px solid var(--rule)}
.steps li .i{font:400 12px/1.75 var(--fm);letter-spacing:.08em;color:var(--a2)}
.steps li b{display:block;font:600 15px/1.4 var(--fb);color:var(--tx);margin-bottom:5px}
.steps li p{font:400 15px/1.65 var(--fb);color:var(--tx-2)}

@media(max-width:720px){
  .gl{grid-template-columns:repeat(2,1fr)}
  .gl>div:nth-child(2){border-right:0}
  .gl>div:nth-child(-n+2){border-bottom:1px solid var(--rule)}
  .steps li{grid-template-columns:34px 1fr;gap:11px}
}
@media(max-width:430px){ .gl{grid-template-columns:1fr} .gl>div{border-right:0;border-bottom:1px solid var(--rule)} }

/* Case studies run to a tighter vertical rhythm than articles — the brief is
   three pages maximum, and the reader is scanning rather than settling in. */
.prose.tight>*+*{margin-top:18px}
.prose.tight h2{margin-top:38px;padding-top:18px}
.prose.tight .ex{margin:28px 0}
.prose.tight .act{margin:30px 0}
.prose.tight .pq{margin-top:30px}
.prose.tight .steps{margin-top:18px}
.prose.tight .steps li{padding:14px 0}
@media print{
  .glance{break-inside:avoid}
  .prose.tight h2{margin-top:20px;padding-top:12px}
  .prose.tight .ex,.prose.tight .act,.prose.tight .pq{margin:16px 0}
  .prose.tight .steps li{padding:10px 0}
  .prose.tight>*+*{margin-top:12px}
}

/* the story spine, made visible: what happened / what we did / what changed /
   what it means for you — one label per section */
.prose h2{flex-wrap:wrap}
.prose h2 .sq{flex:0 0 100%;margin-bottom:9px;font:400 9px/1 var(--fm);letter-spacing:.18em;
  text-transform:uppercase;color:var(--tx-3)}

/* print: a case study must fit three A4 pages, so display type steps down */
@media print{
  h1{font-size:31px;line-height:1.12}
  .deck{font-size:13px;margin-top:10px}
  .by{margin-top:14px;padding:10px 0}
  .glance{margin-top:14px}
  .glance .gs{font-size:15px;padding:8px 14px 12px}
  .glance .gh{padding:11px 14px 0}
  .gl>div{padding:11px 14px 10px}
  .gl .v{font-size:23px}
  .glance .go{padding:9px 14px 10px;font-size:13px}
  .prose.tight p,.prose.tight li,.steps li p{font-size:13px;line-height:1.5}
  .prose.tight h2{font-size:17px}
  .prose.tight h2 .sq{margin-bottom:5px}
  .steps li{padding:8px 0}
  .steps li b{font-size:13px}
  .exh .t{font-size:13px}
  .exh .s,.exf{font-size:10.5px}
  .ex svg{max-height:120px}
  .act .t{font-size:15px}
  .act li b,.act li p{font-size:13px}
  .pq{font-size:17px}
}

/* ===========================================================================
   THE DOSSIER — how a case study announces itself in one second.
   An article is an open column on the page. A case study is a *document*:
   framed, tabbed, and opening on a client record. Three cues, only one of
   which is colour, so the distinction survives greyscale and colour-blindness
   (per WCAG 1.4.1 — never colour alone).
   =========================================================================== */
.dossier{position:relative;margin:38px 0 0;border:1px solid var(--rule-2);
  background:var(--surface);padding:0 clamp(18px,3vw,38px) clamp(26px,3vw,38px)}
.dossier::after{content:"";position:absolute;left:-1px;right:-1px;top:-1px;height:3px;
  background:var(--a2-fill)}
.dtab{display:inline-flex;align-items:center;gap:8px;margin-left:calc(clamp(18px,3vw,38px) * -1);
  padding:10px 16px;background:var(--a2-fill);color:var(--a2-on-fill);
  font:800 10.5px/1 var(--fd);letter-spacing:.2em;text-transform:uppercase}
.dtab svg{width:12px;height:12px;fill:currentColor}

/* client record — the "what is this about" strip, read before the headline */
.rec{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:24px;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.rec>div{padding:13px 16px 12px;border-right:1px solid var(--rule)}
.rec>div:first-child{padding-left:0}
.rec>div:last-child{border-right:0}
.rec dt{font:400 9px/1.4 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--tx-3)}
.rec dd{margin-top:6px;font:600 13px/1.4 var(--fb);color:var(--tx)}
.rec dd span{display:block;font-weight:400;font-size:13px;color:var(--tx-3);margin-top:2px}

/* inside the dossier the masthead sits tighter, and the glance becomes a
   full-bleed band rather than a second box inside a box */
.dossier .head{padding-top:26px}
.dossier .glance{margin-left:calc(clamp(18px,3vw,38px) * -1);
  margin-right:calc(clamp(18px,3vw,38px) * -1);
  border-left:0;border-right:0;background:var(--bg-soft)}
.dossier .prose{margin-top:26px}

/* the record stays two-up even on a phone — stacked to four rows it becomes a
   long preamble in front of the headline, which is the opposite of the brief */
@media(max-width:720px){
  .rec{grid-template-columns:repeat(2,1fr)}
  .rec>div{padding:10px 12px 9px}
  .rec>div:nth-child(odd){padding-left:0}
  .rec>div:nth-child(2n){border-right:0}
  .rec>div:nth-child(-n+2){border-bottom:1px solid var(--rule)}
  .rec dd{font-size:13px}
  .rec dd span{font-size:13px;margin-top:1px}
}
@media print{
  .dossier{border:1px solid #bbb;padding:0 14px 16px;margin-top:10px;break-inside:auto}
  .dossier::after{background:#000}
  .dtab{background:#000;color:#fff;padding:7px 12px}
  .rec{margin-top:14px}
  .rec dd{font-size:13px}
  .rec>div{padding:8px 12px 7px}
}

/* A dossier masthead is a report head, not a magazine cover: the client record
   above it already did the announcing, so the headline and byline step back and
   the 60-second panel stays inside the first screen. */
.dossier .head{padding-top:18px}
.dossier h1{font-size:clamp(32px,4.2vw,50px);margin-top:14px}
.dossier .deck{margin-top:14px;font-size:clamp(17px,1.7vw,21px)}
.dossier .by{margin-top:18px;padding:12px 0}
.dossier .by .mono{width:30px;height:30px;font-size:13px}
.dossier .bym .who{font-size:13px}
.dossier .glance{margin-top:22px}
.rec>div{padding:11px 16px 10px}
@media print{
  .dossier h1{font-size:27px;margin-top:8px}
  .dossier .head{padding-top:8px}
  .dossier .by{margin-top:8px;padding:7px 0}
}

/* ---------- SNAPSHOT — who, what and which APH work, before the headline ----
   Three bands inside the dossier head: the companies (logos), the record
   (facts), and the work (services + tags). Every logo and icon is paired with
   a text label, so nothing depends on recognising a mark. */
.snap{margin-top:22px}
.sl{display:block;font:400 9px/1 var(--fm);letter-spacing:.18em;text-transform:uppercase;
  color:var(--tx-3);margin-bottom:12px}

/* companies */
.co{display:flex;align-items:center;gap:clamp(18px,2.6vw,34px);flex-wrap:wrap}
.co img{height:26px;width:auto;opacity:.94}
.co .sep{width:1px;height:24px;background:var(--rule-2);flex:none}
/* Most case subjects have no logo file, and the anonymised one must never have
   one. A wordmark set in the display face stands in at the same optical weight
   as a 26px logo, so the band reads the same either way. */
.co .wm{font:400 23px/1 var(--fs);letter-spacing:-.015em;color:var(--tx);
  font-variation-settings:"opsz" 40}
.co .anon{display:inline-flex;align-items:center;gap:9px;font:400 19px/1 var(--fs);
  color:var(--tx-2);letter-spacing:-.01em}
.co .anon::before{content:"";width:26px;height:26px;flex:none;border:1px dashed var(--brd);
  background:repeating-linear-gradient(135deg,transparent 0 4px,var(--rule-2) 4px 5px)}
.co .anon i{font-style:normal;font:400 9px/1 var(--fm);letter-spacing:.16em;
  text-transform:uppercase;color:var(--tx-3)}
[data-theme="light"] .co img{filter:invert(1) brightness(.28)}
@media (prefers-color-scheme:light){:root:not([data-theme]) .co img{filter:invert(1) brightness(.28)}}

/* APH services & products worked on */
.svcs{display:flex;flex-wrap:wrap;gap:8px}
.svc{display:inline-flex;align-items:center;gap:8px;padding:8px 13px;border:1px solid var(--acc-line);
  background:var(--acc-soft);font:600 13px/1.2 var(--fb);color:var(--tx)}
.svc svg{width:15px;height:15px;flex:none;fill:none;stroke:var(--acc);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.svc img{height:16px;width:auto;flex:none}
[data-theme="light"] .svc img{filter:invert(1) hue-rotate(180deg) saturate(1.4) brightness(.62)}
@media (prefers-color-scheme:light){
  :root:not([data-theme]) .svc img{filter:invert(1) hue-rotate(180deg) saturate(1.4) brightness(.62)}}

/* tags */
.tags{display:flex;flex-wrap:wrap;gap:6px}
.tg{display:inline-block;padding:6px 10px;border:1px solid var(--rule-2);
  font:400 10.5px/1.2 var(--fm);letter-spacing:.06em;color:var(--tx-2);text-decoration:none;
  transition:color .2s,border-color .2s}
a.tg:hover{color:var(--a2);border-color:var(--a2)}

.snap .band{padding-top:18px;margin-top:18px;border-top:1px solid var(--rule)}
.snap .rec{margin-top:18px}

@media(max-width:720px){
  .co img{height:21px}
  .svc{font-size:13px;padding:7px 11px}
}
@media print{
  .snap{margin-top:12px}
  .snap .band{padding-top:10px;margin-top:10px}
  .co img{height:19px}
  .svc{padding:5px 9px;font-size:10.5px}
  .tg{padding:4px 7px;font-size:9px}
}

/* tags close the dossier — they are taxonomy for finding the next case, not
   information you need before reading this one */
.dfoot{margin-top:30px;padding-top:18px;border-top:1px solid var(--rule-2)}
.snap .band:first-of-type{padding-top:16px;margin-top:16px}
@media print{.dfoot{margin-top:14px;padding-top:10px}}

/* on a phone the service chips stack five deep and become a wall in front of
   the headline — two-up, tighter, and they read as a list again */
@media(max-width:560px){
  .svcs{display:grid;grid-template-columns:1fr 1fr;gap:6px}
  .svc{padding:7px 9px;font-size:10.5px;line-height:1.25;gap:6px;align-items:flex-start}
  .svc svg{width:13px;height:13px;margin-top:1px}
  .co img{height:19px}
  .sl{margin-bottom:9px}
}

/* ===========================================================================
   RESOURCES HOME — the index.
   The hub speaks the same visual language as the pages it links to: a case
   study row is a miniature dossier (amber rule, framed, tabbed), an article
   row is open. A visitor learns the distinction here and carries it through.
   =========================================================================== */
.hub{max-width:var(--ex);margin:0 auto;padding:0 var(--mx)}
.hubhead{padding:34px 0 0}
.hubhead h1{font-size:clamp(34px,4.6vw,56px);max-width:17ch}
.hubhead .deck{max-width:56ch}

/* controls */
.ctrl{position:sticky;top:var(--nav-h);z-index:40;margin-top:30px;padding:14px 0;
  background:color-mix(in srgb,var(--bg) 94%,transparent);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  display:flex;gap:14px;align-items:center;flex-wrap:wrap}
.fbtns{display:flex;gap:6px;flex-wrap:wrap}
.fbtn{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
  min-height:36px;padding:0 13px;border:1px solid var(--rule-2);font:400 10.5px/1 var(--fm);
  letter-spacing:.1em;text-transform:uppercase;color:var(--tx-2);
  transition:color .2s,border-color .2s,background .2s}
.fbtn:hover{color:var(--tx);border-color:var(--brd)}
.fbtn:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.fbtn[aria-pressed="true"]{color:var(--acc-on-fill);background:var(--acc-fill);border-color:transparent}
.fbtn b{font-weight:600;opacity:.62}
.fbtn[aria-pressed="true"] b{opacity:.8}
.srch{position:relative;margin-left:auto;min-width:210px;flex:0 1 300px}
.srch input{min-height:36px;padding:9px 12px 9px 34px;font-size:13px}
.srch svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);width:14px;height:14px;
  fill:none;stroke:var(--tx-3);stroke-width:2;pointer-events:none}
.count{font:400 10.5px/1.5 var(--fm);letter-spacing:.12em;text-transform:uppercase;color:var(--tx-3);
  width:100%}

/* the index */
.idx{margin-top:8px;display:flex;flex-direction:column}
.item{display:block;text-decoration:none;padding:24px 0;border-bottom:1px solid var(--rule);
  transition:background .2s}
.item:hover{background:var(--surface)}
.ihead{display:flex;align-items:center;gap:11px;flex-wrap:wrap}
.ibadge{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;
  font:800 9px/1 var(--fd);letter-spacing:.18em;text-transform:uppercase}
.ibadge svg{width:11px;height:11px;fill:currentColor}
.item.art .ibadge{color:var(--acc);border:1px solid var(--acc-line)}
.item.cs  .ibadge{color:var(--a2-on-fill);background:var(--a2-fill)}
.item.wp  .ibadge{color:var(--a2);border:1px solid var(--a2-line)}
/* Field notes are the library's default row, and after the weekly drop they are
   117 of 124. Neutral badge, no accent bar: the bar marks the exceptional
   formats, and an accent on the majority is not an accent. Magenta is reserved
   for loss in this system — 117 magenta rules down the page said the opposite
   of what the page means. See .ibadge.fn below for the badge itself. */
.itopic{font:400 9px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
.imeta{margin-left:auto;font:400 9px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;
  color:var(--tx-3)}
.item h2{margin-top:13px;font:400 clamp(21px,2.3vw,27px)/1.26 var(--fs);color:var(--tx);
  letter-spacing:-.016em;font-variation-settings:"opsz" 40;max-width:34ch}
.item h2 em{font-style:italic;color:var(--a2)}
.item .idek{margin-top:8px;font:400 15px/1.62 var(--fb);color:var(--tx-2);max-width:64ch}
.item .ifoot{margin-top:12px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.item .ilogo{height:15px;width:auto;opacity:.9}
[data-theme="light"] .item .ilogo{filter:invert(1) brightness(.28)}
@media (prefers-color-scheme:light){:root:not([data-theme]) .item .ilogo{filter:invert(1) brightness(.28)}}

/* a case study row is a miniature dossier */
.item.cs{position:relative;padding-left:clamp(14px,1.6vw,22px);
  border-left:3px solid var(--a2);background:var(--surface)}
.item.cs:hover{background:var(--surface-2)}

.empty{padding:44px 0;text-align:center}
.empty p{font:400 15px/1.6 var(--fb);color:var(--tx-3)}
.empty b{display:block;font:400 22px/1.3 var(--fs);color:var(--tx);margin-bottom:8px}

@media(max-width:720px){
  .ctrl{position:static;gap:10px}
  .srch{margin-left:0;flex:1 1 100%}
  .item h2{max-width:none}
  .imeta{margin-left:0;width:100%}
}

/* visually hidden, still read by assistive tech */
.vh{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ===========================================================================
   RESOURCES PORTAL — an editorial front page.
   Research (news IA + B2B resource centres) says: hero-plus-grid, a
   time-stamped latest module, most-read as a social anchor, active-state
   section nav — and, critically, that people navigate a B2B library by
   TOPIC, ROLE and INDUSTRY rather than by content format. Format is a
   secondary filter here, never the primary one.
   Visuals are generated signatures, not photography: every card carries an
   abstract SVG derived from its topic, so the page has news-homepage density
   without a stock library.
   =========================================================================== */
.port{max-width:1180px;margin:0 auto;padding:0 var(--mx)}

/* ---------------------------------------------------------------------------
   Section hero.
   Every other page on the site opens on a full-height photographic hero. This
   one is the same language at a third the height — enough to place you, not
   enough to delay the news.
   The band carries its own photograph per theme — the same library at night
   and in daylight — because a single image cannot serve both. A dark scrim
   with light type is the only way to read over a night shot, and the inverse
   over a day shot. So the hero declares its own ink and its own scrim base;
   everything below is written once against those, and only those five values
   flip. Contrast is measured against rendered pixels, not the token table,
   because no token table can see a photograph.
   --------------------------------------------------------------------------- */
.rhero{--hs:5,7,11;                       /* scrim base, matches the photo */
  --hi:#F7F4EF; --ha:#F5CE8B; --hd:#D5D8DD; --hm:#AFB5BE;
  position:relative;isolation:isolate;overflow:hidden;background:rgb(var(--hs));
  border-bottom:1px solid var(--rule)}
[data-theme="light"] .rhero{--hs:250,248,243;
  --hi:#171310; --ha:#7C4C00; --hd:#3D3833; --hm:#5A544C}
@media (prefers-color-scheme:light){
  :root:not([data-theme]) .rhero{--hs:250,248,243;
    --hi:#171310; --ha:#7C4C00; --hd:#3D3833; --hm:#5A544C}
}
.rhero>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:72% 40%;z-index:-2}
.rhero>img.day{display:none}
[data-theme="light"] .rhero>img.night{display:none}
[data-theme="light"] .rhero>img.day{display:block}
@media (prefers-color-scheme:light){
  :root:not([data-theme]) .rhero>img.night{display:none}
  :root:not([data-theme]) .rhero>img.day{display:block}
}
.rhero::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background:
  linear-gradient(90deg,rgba(var(--hs),.97) 0%,rgba(var(--hs),.94) 34%,rgba(var(--hs),.66) 60%,rgba(var(--hs),.20) 100%),
  linear-gradient(180deg,rgba(var(--hs),.80) 0%,rgba(var(--hs),.14) 48%,rgba(var(--hs),.62) 100%)}
.rhero>div{position:relative;max-width:1180px;margin:0 auto;
  padding:clamp(30px,5vw,52px) var(--mx) clamp(26px,4vw,44px);
  min-height:clamp(220px,25vw,320px);display:flex;flex-direction:column;justify-content:flex-end}
.rhero .mtag{font:400 10.5px/1 var(--fm);letter-spacing:.2em;text-transform:uppercase;
  color:var(--ha);display:block}
.rhero h1{margin-top:13px;font:400 clamp(29px,4vw,50px)/1.1 var(--fs);color:var(--hi);
  letter-spacing:-.022em;max-width:19ch;font-variation-settings:"opsz" 72}
.rhero h1 em{font-style:italic;color:var(--ha)}
.rhero .mdek{margin-top:14px;font:400 clamp(14.5px,1.2vw,16.5px)/1.58 var(--fb);
  color:var(--hd);max-width:56ch}
.rhero .mmeta{margin-top:18px;display:flex;align-items:center;gap:10px;
  font:400 10.5px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--hm)}
.rhero .mmeta i{width:6px;height:6px;border-radius:50%;background:var(--ha);flex:none;
  animation:pulse 2.6s var(--ease) infinite}
@media (prefers-reduced-motion:reduce){.rhero .mmeta i{animation:none;opacity:.9}}
/* Narrow: the copy spans the full width, so a left-weighted scrim no longer
   sits under all of it. Flatten the horizontal ramp and deepen overall.
   The threshold is where .mdek's 56ch stops fitting inside the content box,
   around 760px — not the 900px layout breakpoint. Applying it at 900 washes
   the daylight photograph out to nothing while the copy still sits left. */
@media(max-width:760px){
  .rhero::after{background:
    linear-gradient(90deg,rgba(var(--hs),.94) 0%,rgba(var(--hs),.88) 48%,rgba(var(--hs),.68) 100%),
    linear-gradient(180deg,rgba(var(--hs),.74) 0%,rgba(var(--hs),.34) 50%,rgba(var(--hs),.66) 100%)}
}
@media(max-width:560px){
  .rhero>div{min-height:196px}
  .rhero h1{max-width:none}
  .rhero>img{object-position:76% 46%}
}
.tnav{position:sticky;top:var(--nav-h);z-index:40;margin-top:20px;
  background:color-mix(in srgb,var(--bg) 94%,transparent);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule-2)}
.tnav ul{list-style:none;display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;padding:0}
.tnav ul::-webkit-scrollbar{display:none}
.tnav a{display:block;padding:13px 14px;font:400 10.5px/1 var(--fm);letter-spacing:.12em;
  text-transform:uppercase;color:var(--tx-3);text-decoration:none;white-space:nowrap;
  border-bottom:2px solid transparent;transition:color .2s,border-color .2s}
.tnav a:hover{color:var(--tx)}
.tnav a[aria-current="true"]{color:var(--a2);border-bottom-color:var(--a2)}

/* ---------------------------------------------------------------------------
   The two doors — sell side and buy side.
   These are buttons, not links: they do not navigate anywhere, they put the
   whole page on one side of the market. So they carry aria-pressed and a
   selected state strong enough to read as "this is on" from across the page,
   because the rest of the page silently changing underneath is otherwise a
   confusing thing to do to someone.
   --------------------------------------------------------------------------- */
.doors{display:grid;grid-template-columns:1fr 1fr;gap:0;margin-top:26px;
  border:1px solid var(--rule-2)}
.door{display:flex;flex-direction:column;gap:6px;padding:20px 22px;text-align:left;
  font:inherit;background:none;border:0;border-right:1px solid var(--rule-2);
  cursor:pointer;transition:background .2s,box-shadow .2s;position:relative}
.door:last-child{border-right:0}
.door:hover{background:var(--surface)}
.door .dt{display:block;font:400 22px/1.24 var(--fs);color:var(--tx);letter-spacing:-.014em}
.door .dt b{font-weight:400;color:var(--acc)}
.door:last-child .dt b{color:var(--a2)}
.door .dd{display:block;font:400 13px/1.55 var(--fb);color:var(--tx-3)}
.door[aria-pressed="true"]{background:var(--surface)}
.door[aria-pressed="true"]::before{content:"";position:absolute;inset:0 auto 0 0;width:3px;
  background:var(--acc)}
.door:last-child[aria-pressed="true"]::before{background:var(--a2)}
.doors:has(.door[aria-pressed="true"]) .door[aria-pressed="false"]{opacity:.5}
.doors:has(.door[aria-pressed="true"]) .door[aria-pressed="false"]:hover{opacity:1}

/* the state line: says what changed, and how to undo it */
.sidebar{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  margin-top:14px;padding:11px 14px;background:var(--surface);
  border:1px solid var(--rule-2);
  font:400 13px/1.5 var(--fb);color:var(--tx-2)}
.sidebar b{font-weight:400;color:var(--tx)}
.sidebar button{margin-left:auto;font:400 10.5px/1 var(--fm);letter-spacing:.14em;
  text-transform:uppercase;color:var(--acc);background:none;border:0;padding:4px 0;
  cursor:pointer;border-bottom:1px solid currentColor}
.sidebar button:hover{color:var(--tx)}

/* generated signature visuals */
.sig{display:block;width:100%;aspect-ratio:16/9;background:var(--surface-2);
  border:1px solid var(--rule);overflow:hidden}
.sig svg{width:100%;height:100%;display:block}

/* lead story + latest rail */
.top{display:grid;grid-template-columns:minmax(0,1.62fr) minmax(0,1fr);
  gap:clamp(22px,3vw,44px);margin-top:30px;align-items:start}
.leadc{display:block;text-decoration:none;group:lead}
.leadc .sig{aspect-ratio:16/8.4}
.leadc .lk{display:flex;align-items:center;gap:10px;margin-top:16px;flex-wrap:wrap}
.leadc h2{margin-top:12px;font:400 clamp(28px,3.4vw,42px)/1.14 var(--fs);color:var(--tx);
  letter-spacing:-.02em;font-variation-settings:"opsz" 60}
.leadc h2 em{font-style:italic;color:var(--a2)}
.leadc:hover h2{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:4px}
.leadc .ldek{margin-top:11px;font:400 17px/1.6 var(--fb);color:var(--tx-2);max-width:56ch}

.rail .rh{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding-bottom:11px;border-bottom:2px solid var(--a2)}
.rail .rh span{font:800 10.5px/1 var(--fd);letter-spacing:.18em;text-transform:uppercase;color:var(--tx)}
.rail .rh a{font:400 9px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;
  color:var(--tx-3);text-decoration:none}
.rail .rh a:hover{color:var(--a2)}
.feed{list-style:none;padding:0;margin:0}
.feed li{border-bottom:1px solid var(--rule)}
.feed a{display:block;padding:13px 0;text-decoration:none}
.feed a:hover .ft{color:var(--acc)}
.feed .fm{display:flex;gap:8px;align-items:center;font:400 9px/1.4 var(--fm);letter-spacing:.12em;
  text-transform:uppercase;color:var(--tx-3)}
.feed .fm i{font-style:normal;color:var(--a2)}
.feed .ft{display:block;margin-top:5px;font:600 15px/1.4 var(--fb);color:var(--tx);
  transition:color .2s}

/* desk blocks — pillar plus cluster, the hub-and-spoke shape */
.tblock{margin-top:52px}
.th2{display:flex;align-items:baseline;gap:12px;padding-bottom:11px;
  border-bottom:2px solid var(--rule-2)}
.th2 h2{font:400 clamp(21px,2.2vw,27px)/1.2 var(--fs);color:var(--tx);letter-spacing:-.016em}
.th2 .tc{font:400 9px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
.th2 a{margin-left:auto;font:400 9px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;
  color:var(--tx-3);text-decoration:none;white-space:nowrap}
.th2 a:hover{color:var(--a2)}
/* Each desk heading carries its beat — one line saying what that desk covers.
   A five-desk rail where the names alone have to explain the split asks the
   reader to infer the boundary; the beat states it. It sits on the baseline
   beside the heading on a wide page and drops under it when the row runs out
   of room, rather than being hidden, because a line worth writing is worth
   reading on a phone. */
.th2 .dbeat{font:400 13px/1.35 var(--fb);color:var(--tx-3);
  max-width:44ch;margin:0}
@media (max-width:640px){
  .th2{flex-wrap:wrap}
  .th2 .dbeat{flex-basis:100%;order:3;margin-top:2px}
  .th2 a{order:2}
}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));
  gap:clamp(18px,2.2vw,30px);margin-top:22px}
.gc{display:block;text-decoration:none}
.gc .lk{display:flex;align-items:center;gap:9px;margin-top:12px;flex-wrap:wrap}
.gc h3{margin-top:9px;font:400 17px/1.3 var(--fs);color:var(--tx);letter-spacing:-.014em;
  font-variation-settings:"opsz" 32}
.gc:hover h3{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}
.gc .gdek{margin-top:7px;font:400 13px/1.58 var(--fb);color:var(--tx-3)}
.gc .gm{margin-top:9px;font:400 9px/1 var(--fm);letter-spacing:.12em;text-transform:uppercase;
  color:var(--tx-3)}

/* most read — the social anchor */
.mread{margin-top:26px}
.mread ol{list-style:none;padding:0;margin:0;counter-reset:mr}
.mread li{counter-increment:mr;border-bottom:1px solid var(--rule)}
.mread a{display:grid;grid-template-columns:34px 1fr;gap:12px;padding:13px 0;text-decoration:none;
  align-items:baseline}
.mread a::before{content:counter(mr,decimal-leading-zero);font:400 19px/1 var(--fs);
  color:var(--a2);opacity:.85}
.mread .mt{font:600 13px/1.42 var(--fb);color:var(--tx)}
.mread a:hover .mt{color:var(--acc)}

@media(max-width:900px){
  .top{grid-template-columns:minmax(0,1fr)}
  .rail{margin-top:14px}
  .doors{grid-template-columns:1fr}
  .door{border-right:0;border-bottom:1px solid var(--rule-2)}
  .door:last-child{border-bottom:0}
}
@media(max-width:560px){
  .grid{grid-template-columns:1fr}
  .tnav{position:static}
}
.ibadge.fn{color:var(--tx-3);border:1px solid var(--brd)}
/* the same four badges outside the library index — cards, leads, the cover */
.ibadge.cs{color:var(--a2-on-fill);background:var(--a2-fill)}
.ibadge.art{color:var(--acc);border:1px solid var(--acc-line)}
.ibadge.wp{color:var(--a2);border:1px solid var(--a2-line)}
/* The Weekly's own badge. Deliberately not .fn: magenta is the loss colour in
   this system, and the letter's front page is not a loss. */
.ibadge.wk{color:var(--acc);border:1px solid var(--acc-line)}
.item.wp{position:relative;padding-left:clamp(14px,1.6vw,22px);
  border-left:3px solid var(--a2)}
.ctrl{margin-top:20px}

/* section headings must clear the sticky topic nav when jumped to */
.tblock,.nl[id],#library{scroll-margin-top:calc(var(--nav-h) + 58px)}
/* the two filter groups are different questions — label them so they don't
   read as one long row of chips */
.fgrp{display:flex;flex-direction:column;gap:7px}
.fglab{font:400 9px/1 var(--fm);letter-spacing:.16em;text-transform:uppercase;color:var(--tx-3)}
.ctrl{align-items:flex-end;gap:clamp(14px,2vw,28px)}
.ctrl .srch{align-self:flex-end;margin-bottom:0}
@media(max-width:900px){.ctrl{align-items:stretch} .fgrp{width:100%}}

/* a content-rich front page is a lot of tab stops before the filters — give
   keyboard users a way past it */
.skip{position:absolute;left:-9999px;top:0;z-index:100;padding:12px 18px;
  background:var(--a2-fill);color:var(--a2-on-fill);font:400 10.5px/1 var(--fm);
  letter-spacing:.12em;text-transform:uppercase;text-decoration:none}
.skip:focus{left:12px;top:12px}

/* ---------- card visuals now carry the story's actual number ---------- */
.sig{aspect-ratio:16/9;background:var(--surface);border:1px solid var(--rule-2);
  transition:border-color .25s}
.gc:hover .sig,.leadc:hover .sig{border-color:var(--a2)}
.leadc .sig{aspect-ratio:16/9}
/* Two renderings of the same chart. Fine annotation is 12.5 units of a
   760-unit viewBox, so it needs ~608px of width to clear 10px — and a lead
   visual is narrow on mobile, in the portal's two-column band around 1100px,
   AND on the weekly page. Query the visual's own width rather than guessing
   viewport breakpoints, and apply it to any .sig that ships both tiers: the
   rule belongs to the artwork, not to the component around it. */
.sig{container-type:inline-size}
.sig>svg.sm{display:none}
@container (max-width:640px){
  .sig>svg.lg{display:none}
  .sig>svg.sm{display:block}
}

/* ---------- filters that respond ---------- */
.ctrl{position:relative;flex-wrap:wrap;row-gap:14px}
.fbtn{position:relative;overflow:hidden}
.fbtn b{display:inline-block;min-width:1.2em;text-align:right;
  font-variant-numeric:tabular-nums;transition:opacity .2s}
.fbtn[data-empty="true"]{opacity:.42;pointer-events:none}
/* live pills for whatever is currently narrowing the list */
.pills{display:flex;gap:7px;flex-wrap:wrap;width:100%;min-height:0;margin-top:2px}
.pills:empty{display:none}
.pill{display:inline-flex;align-items:center;gap:8px;padding:6px 8px 6px 11px;
  border:1px solid var(--a2);background:var(--a2-soft,var(--amber-soft));
  font:400 10.5px/1 var(--fm);letter-spacing:.08em;text-transform:uppercase;color:var(--a2)}
.pill button{all:unset;cursor:pointer;width:16px;height:16px;display:grid;place-items:center;
  border-radius:50%;font:400 13px/1 var(--fb);color:var(--a2)}
.pill button:hover{background:var(--a2);color:var(--a2-on-fill)}
.pill button:focus-visible{outline:2px solid var(--a2);outline-offset:1px}
.resline{width:100%;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  font:400 10.5px/1.6 var(--fm);letter-spacing:.12em;text-transform:uppercase;color:var(--tx-3)}
.resline b{font:400 22px/1 var(--fs);color:var(--tx);font-variant-numeric:tabular-nums}
.resline .clr{all:unset;cursor:pointer;margin-left:auto;color:var(--acc);
  border-bottom:1px solid var(--acc-line)}
.resline .clr:hover{color:var(--acc-hover)}
.resline .clr:focus-visible{outline:2px solid var(--acc);outline-offset:3px}
/* rows settle in rather than snapping */
.item{transition:background .2s,opacity .25s var(--ease),transform .25s var(--ease)}
.idx.busy .item{opacity:0;transform:translateY(6px)}
@media (prefers-reduced-motion:reduce){.idx.busy .item{opacity:1;transform:none}}

/* ---------- liveness ---------- */
.rail .rh .live{display:inline-flex;align-items:center;gap:6px;font:400 9px/1 var(--fm);
  letter-spacing:.14em;color:var(--tx-3)}
.rail .rh .live i{width:6px;height:6px;border-radius:50%;background:var(--c3);
  animation:pulse 2.6s var(--ease) infinite}
@keyframes pulse{0%,100%{opacity:.35;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}
@media (prefers-reduced-motion:reduce){.rail .rh .live i{animation:none;opacity:.9}}
.feed .fm em{font-style:normal;color:var(--tx-2)}

/* ===========================================================================
   THE WEEKLY — resources-weekly.html
   Owner brief: a newspaper cover. One flash story, three to five side covers,
   the rest below, links to older issues and the signup — inside two or three
   screens.
   The structure is a front page, so it is built the way a front page is: a
   typographic nameplate rather than a photographic band (a photo here would
   repeat the portal and cost a whole screen), vertical rules doing the work
   of gutters, and hierarchy carried by type size rather than by cards.
   Only the flash story gets a picture. That is what a cover does, and it is
   what keeps this inside three screens.
   =========================================================================== */

/* ---- nameplate ---- */
.plate{margin-top:24px;padding-bottom:16px;border-bottom:3px double var(--tx)}
.pltop{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding-bottom:12px;border-bottom:1px solid var(--rule-2);
  font:400 10.5px/1 var(--fm);letter-spacing:.18em;text-transform:uppercase;color:var(--tx-3)}
.plback{text-decoration:none;color:var(--acc)}
.plback:hover{color:var(--acc-hover)}
.plate h1{margin-top:18px;text-align:center;color:var(--tx);
  font:400 clamp(46px,8.4vw,104px)/.94 var(--fs);letter-spacing:-.021em;
  font-variation-settings:"opsz" 110}
.plate h1 em{font-style:italic;color:var(--a2)}
.plline{margin-top:16px;display:flex;justify-content:center;align-items:baseline;
  gap:clamp(12px,2.4vw,26px);flex-wrap:wrap;text-align:center;
  font:400 10.5px/1.5 var(--fm);letter-spacing:.15em;text-transform:uppercase;color:var(--tx-3)}
.plline b{font-weight:600;color:var(--tx)}

/* ---- the cover: flash + side column ---- */
.cover{display:grid;grid-template-columns:minmax(0,1.85fr) minmax(0,1fr);margin-top:28px}
.flash{padding-right:clamp(20px,3vw,38px);border-right:1px solid var(--rule-2)}
.flash a{display:block;text-decoration:none}
/* the picture must not push the headline off the cover: at full column
   width a 16:9 visual is 517px tall and the flash headline starts below
   the fold on a 900px screen */
.flash .sig{max-width:660px;margin-bottom:16px}
.flash .lk{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.flash h2{margin-top:12px;color:var(--tx);letter-spacing:-.026em;
  font:400 clamp(30px,4.1vw,50px)/1.07 var(--fs);font-variation-settings:"opsz" 72}
.flash h2 em{font-style:italic;color:var(--a2)}
.flash .fdek{margin-top:13px;max-width:50ch;color:var(--tx-2);
  font:400 clamp(16px,1.45vw,18.5px)/1.56 var(--fb)}
.flash .gm{display:block;margin-top:14px}

.sides{padding-left:clamp(20px,3vw,38px)}
.sides .swh{padding-bottom:9px;border-bottom:2px solid var(--tx);
  font:400 10.5px/1 var(--fm);letter-spacing:.18em;text-transform:uppercase;color:var(--a2)}
.sides ol{list-style:none}
.sc{border-bottom:1px solid var(--rule-2)}
.sc:last-child{border-bottom:0}
.sc a{display:block;text-decoration:none;padding:13px 0;transition:opacity .2s}
.sc a:hover h3{color:var(--acc)}
.scm{display:flex;align-items:baseline;gap:9px;margin-bottom:6px;
  font:400 9px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
.scm i{font-style:normal;color:var(--a2)}
.sc h3{color:var(--tx);letter-spacing:-.014em;font:400 17px/1.26 var(--fs)}
.sc h3 em{font-style:italic;color:var(--a2)}
.scd{margin-top:6px;font:400 13px/1.5 var(--fb);color:var(--tx-3)}

/* ---- below the fold: one strip of headline-only columns ---- */
.mh{display:flex;align-items:baseline;gap:14px;margin-top:44px;padding-bottom:9px;
  border-bottom:2px solid var(--tx)}
.mh h2{color:var(--tx);letter-spacing:-.014em;font:400 22px/1.2 var(--fs)}
/* Column rules were drawn as border-right with a :last-child exception. That
   is only correct while the strip is one row: as soon as it wraps — which is
   exactly what happens once an issue is big enough to fill the cover on its
   own — the last cell of every row but the last keeps its rule and draws it
   on the outer page edge. Whitespace gutters plus a hairline under each cell
   wrap correctly at any count, and keep the first column flush to the margin. */
.mgrid{list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  column-gap:clamp(18px,2.2vw,30px)}
.mc{border-bottom:1px solid var(--rule-2)}
.mc a{display:block;text-decoration:none;padding:14px 0 17px}
.mc a:hover h3{color:var(--acc)}
.mcm{display:block;margin-bottom:7px;
  font:400 9px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;color:var(--tx-3)}
.mc h3{color:var(--tx);letter-spacing:-.012em;font:400 17px/1.3 var(--fs)}
.mc h3 em{font-style:italic;color:var(--a2)}

/* ---- every issue ---- */
.alist{list-style:none}
.ai{border-bottom:1px solid var(--rule-2)}
.ai a{display:grid;grid-template-columns:minmax(140px,190px) minmax(0,1fr);
  gap:clamp(14px,2.4vw,30px);align-items:baseline;padding:12px 0;text-decoration:none}
.ai time{font:400 10.5px/1.5 var(--fm);letter-spacing:.14em;text-transform:uppercase;
  color:var(--tx-3)}
.ai .al{font:400 15px/1.5 var(--fb);color:var(--tx-2)}
.ai a:hover .al{color:var(--tx)}
.ai .cur{margin-left:10px;font:400 9px/1 var(--fm);letter-spacing:.14em;
  text-transform:uppercase;color:var(--a2)}
/* The archive foot: a secondary control, so an outline button rather than the
   filled .cta — Subscribe is the one thing on this page asking to be pressed. */
.afoot{display:flex;align-items:center;gap:clamp(14px,2.4vw,26px);flex-wrap:wrap;
  margin-top:18px}
.moreb{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;
  align-items:center;justify-content:center;min-height:40px;padding:0 20px;
  border:1px solid var(--brd);color:var(--tx);background:transparent;
  font:400 10.5px/1 var(--fm);letter-spacing:.14em;text-transform:uppercase;
  transition:border-color .2s,background .2s,color .2s}
.moreb:hover{border-color:var(--acc);color:var(--acc);background:var(--acc-soft)}
.moreb:focus-visible{outline:2px solid var(--acc);outline-offset:3px}
.amore{font:400 13px/1.6 var(--fb);color:var(--tx-3)}

@media(max-width:900px){
  .cover{grid-template-columns:1fr}
  .flash{padding-right:0;border-right:0;padding-bottom:26px;
    border-bottom:1px solid var(--rule-2)}
  .sides{padding-left:0;margin-top:22px}
}
@media(max-width:560px){
  .plate h1{letter-spacing:-.028em}
  .mc a{padding:12px 0 14px}
  .ai a{grid-template-columns:1fr;gap:4px;padding:11px 0}
  /* one column of the same content is inherently taller, so the things that
     are supporting detail on desktop come off: the side-column deks, and the
     issue ledes past two lines. The headlines and the dates all stay. */
  .scd{display:none}
  .ai .al{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
    overflow:hidden}
}

/* ===========================================================================
   WHITEPAPER — whitepaper-*.html
   The case-study dossier wrapped around an article-length body, plus a gate.
   Owner spec: 90% the case study, the difference being an email before
   viewing. So it reuses .dossier, .snap, .glance and .prose wholesale and adds
   only the tab colour and the gate itself.
   =========================================================================== */
.wp .wptab{background:var(--acc-fill);color:var(--acc-on-fill)}
.dossier.wp{border-top-color:var(--acc)}
.dossier.wp::before{background:var(--acc)}

/* the gate */
.gate{margin:34px 0 0;padding:clamp(26px,4vw,44px) clamp(22px,3.4vw,40px);
  background:var(--surface-2);border:1px solid var(--rule-2)}
.gate .kk{display:block;font:400 10.5px/1 var(--fm);letter-spacing:.2em;
  text-transform:uppercase;color:var(--acc)}
.gate h2{margin-top:12px;font:400 clamp(24px,3vw,34px)/1.16 var(--fs);color:var(--tx);
  letter-spacing:-.02em;font-variation-settings:"opsz" 48;max-width:22ch}
.gate p{margin-top:12px;font:400 15px/1.62 var(--fb);color:var(--tx-2);max-width:56ch}
.gate .nlmicro{margin-top:12px}
.gatein{max-width:var(--col)}

/* Everything below the gate is present but inert until it opens. aria-hidden
   is set alongside, so assistive tech is not offered content the page is
   presenting as withheld. */
.prose.gated{display:none}

/* The desk mark on a library row: same five tones, set as a chip rather than a
   disc because the row is a line of type, not a byline. */
.dmk{display:inline-block;font:800 9px/1 var(--fd);letter-spacing:.1em;
  padding:4px 5px;border-radius:3px;vertical-align:1px;margin-right:8px;
  background:var(--dk-fill);color:var(--dk-tx);
  box-shadow:inset 0 0 0 1px var(--dk-ring)}
.dmk[data-desk="regulation"]  {--dk-fill:#073E5E;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
.dmk[data-desk="programmatic"]{--dk-fill:#0C6394;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
.dmk[data-desk="publisher"]   {--dk-fill:#7FC0DF;--dk-tx:#06304A;--dk-ring:rgba(6,48,74,.34)}
.dmk[data-desk="marketing"]   {--dk-fill:#7C4C00;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
.dmk[data-desk="video"]       {--dk-fill:#EAC282;--dk-tx:#4A2E00;--dk-ring:rgba(74,46,0,.34)}
@media (prefers-color-scheme:dark){
  .dmk[data-desk="regulation"]   {--dk-fill:#9FDEFF;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
  .dmk[data-desk="programmatic"] {--dk-fill:#4FB0E0;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
  .dmk[data-desk="publisher"]    {--dk-fill:#CDEAF7;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
  .dmk[data-desk="marketing"]    {--dk-fill:#E0A94F;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
  .dmk[data-desk="video"]        {--dk-fill:#F5CE8B;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
}
:root[data-theme="dark"] .dmk[data-desk="regulation"]  {--dk-fill:#9FDEFF;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .dmk[data-desk="programmatic"]{--dk-fill:#4FB0E0;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .dmk[data-desk="publisher"]   {--dk-fill:#CDEAF7;--dk-tx:#04121D;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .dmk[data-desk="marketing"]   {--dk-fill:#E0A94F;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="dark"] .dmk[data-desk="video"]       {--dk-fill:#F5CE8B;--dk-tx:#241303;--dk-ring:rgba(0,0,0,.22)}
:root[data-theme="light"] .dmk[data-desk="regulation"]  {--dk-fill:#073E5E;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
:root[data-theme="light"] .dmk[data-desk="programmatic"]{--dk-fill:#0C6394;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
:root[data-theme="light"] .dmk[data-desk="publisher"]   {--dk-fill:#7FC0DF;--dk-tx:#06304A;--dk-ring:rgba(6,48,74,.34)}
:root[data-theme="light"] .dmk[data-desk="marketing"]   {--dk-fill:#7C4C00;--dk-tx:#FFFDFA;--dk-ring:rgba(0,0,0,.18)}
:root[data-theme="light"] .dmk[data-desk="video"]       {--dk-fill:#EAC282;--dk-tx:#4A2E00;--dk-ring:rgba(74,46,0,.34)}

/* A named outlet links to the reporting. `data-depth="home"` marks a link that
   reaches the publication's front page rather than the story itself, because
   the drop's citations carry a headline and a byline but no address, and a
   confident wrong permalink is worse than an honest shallow one. The dotted
   underline is the difference, visible without being loud. */
.prose a.srcl,.src a.srcl{color:var(--acc);text-decoration:none;
  border-bottom:1px solid var(--acc-line)}
.prose a.srcl:hover,.src a.srcl:hover{color:var(--acc-hover);
  border-bottom-color:currentColor}
.prose a.srcl[data-depth="home"],.src a.srcl[data-depth="home"]{
  border-bottom-style:dotted}


/* ===========================================================================
   EXHIBIT BODIES THAT ARE NOT CHARTS
   An exhibit earns a chart by encoding a quantity on a labelled scale. Most of
   these pieces state a sequence or a set of claims instead — that is a list,
   and drawing a list in SVG costs the reflow, the text selection, the
   translation and the screen reader, and buys nothing. So the frame stays
   (same .ex device, same rules, same desk line) and the body becomes HTML.
   Every value here is an existing token: no new colour, no new face.
   =========================================================================== */
.ex .keys{list-style:none;margin:0;padding:0}
.ex .keys li{display:grid;grid-template-columns:40px 1fr;gap:14px;padding:15px 18px;
  border-top:1px solid var(--rule)}
.ex .keys li:first-child{border-top:0}
.ex .keys .i{font:400 10.5px/1.7 var(--fm);letter-spacing:.08em;color:var(--a2)}
.ex .keys p{margin:0;font:400 17px/1.62 var(--fb);color:var(--tx-2)}
/* a short drawn label was upper-case in the artwork; keep it that way rather
   than title-casing acronyms into nonsense (AU, TCL, DSP) */
.ex .keys p.lab{font:400 12px/1.7 var(--fm);letter-spacing:.11em;text-transform:uppercase;
  color:var(--tx)}
.ex .keys strong{color:var(--tx);font-weight:600}

/* a single measured number, as type rather than as a 96px SVG string */
.ex .stats{margin:0;border-top:0;border-bottom:0;
  grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.ex .stats>div{padding:22px 18px 20px}

/* A peer set, not a sequence. Numbering these would assert a ranking the
   reporting does not make, so they are chips in source order. */
.ex .keys.peers{display:flex;flex-wrap:wrap;gap:7px;padding:16px 18px}
.ex .keys.peers li{display:block;padding:9px 12px;border:1px solid var(--rule-2);border-top:1px solid var(--rule-2);
  font:400 10.5px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;color:var(--tx-2)}

@media(max-width:640px){
  .ex .keys li{grid-template-columns:30px 1fr;gap:11px;padding:13px 14px}
  .ex .keys.peers li{padding:8px 10px;font-size:10px}
  .ex .keys p{font-size:15px}
  .ex .keys p.lab{font-size:13px}
}
@media print{
  .ex .keys li{padding:8px 12px;break-inside:avoid}
  .ex .keys p{font-size:13px}
  .ex .stats>div{padding:12px}
}



/* ---------- touch targets ----------
   Same reasoning as aph.css: measured on an iPhone 12 the footer links were
   13px tall, the breadcrumb 17px, a "See all" 9px, the contents rows 31px and
   the topic tags 27px. A cursor lands where it is pointed; a thumb does not.
   Padding and min-height only, all inside the query — the reading column, the
   figures and everything above 820px are untouched. */
@media(max-width:820px){
  .nav .navcta{display:inline-flex;align-items:center;min-height:44px}
  .footer .footin{flex-direction:column;align-items:flex-start;gap:12px}
  .footer .fcols{margin-left:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 18px;width:100%}
  .footer .fcols a{display:flex;align-items:center;min-height:44px}
  .crumb a{display:inline-flex;align-items:center;min-height:44px}
  .th2 a{display:inline-flex;align-items:center;min-height:44px}
  .toc a{padding:12px 0;align-items:center}
  .tg{padding:11px 12px}
  .head a.tag{padding:14px 15px}
  .sh{min-height:44px}
}



/* ---- footer legal row (added by scripts/add_footer_legal.py) ---- */
.legalrow{display:flex;flex-wrap:wrap;gap:0 18px;margin-top:10px}
.legalrow a{font:400 13px/1.5 var(--fb);color:var(--tx-2);text-decoration:none}
.legalrow a:hover{color:var(--acc-hover)}
@media(max-width:820px){.legalrow{gap:0 16px}.legalrow a{min-height:44px;display:flex;align-items:center}}

/* === nav menu: generated by scripts/build_nav.py === */
.nav{overflow:visible}
/* The bar's own geometry, pinned here rather than inherited from each sheet.
   It used to take its inset from --mx, which is 6vw on the marketing pages and
   clamp(18px,5vw,48px) on Resources — so the logo sat at 86px in one section
   and 48px in the other, and the links and CTA moved with it. --mx still
   governs each section's page margins; only the header is held in common. */
.nav{padding:0 var(--nav-mx,6vw);gap:clamp(30px,3.2vw,58px)}
.nav .links{gap:clamp(20px,2vw,32px)}
.navtoggle{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.navitem{position:relative;display:flex;align-items:center}
/* a hover bridge, so the pointer can cross the gap to the panel */
.navitem::after{content:"";position:absolute;top:100%;left:-12px;right:-12px;height:18px}
.navpanel{position:absolute;top:calc(100% + 15px);left:-14px;min-width:296px;max-width:min(360px,86vw);
  padding:9px;border-radius:14px;background:var(--surface);border:1px solid var(--rule);
  box-shadow:0 28px 64px -22px rgba(0,0,0,.86);opacity:0;visibility:hidden;pointer-events:none;
  transform:translateY(-7px);transition:opacity .2s var(--ease),transform .2s var(--ease);z-index:70}
.navitem:hover>.navpanel,.navitem:focus-within>.navpanel{opacity:1;visibility:visible;pointer-events:auto;transform:none}
.navitem:last-of-type>.navpanel{left:auto;right:-14px}
.navpanel a{display:block;padding:10px 12px;border-radius:10px;text-decoration:none;transition:background .18s}
.navpanel a:hover,.navpanel a:focus-visible{background:var(--acc-soft)}
.navpanel a b{display:block;font:600 13px/1.35 var(--fb);color:var(--tx)}
/* third level: always visible, indented under its parent rather than hidden
   behind a second hover */
.navsub{margin:2px 0 4px 13px;padding-left:11px;border-left:1px solid var(--rule)}
.navsub a b{font-weight:500;font-size:13px}
.navpanel a i{display:block;font-style:normal;font:400 13px/1.5 var(--fb);color:var(--tx-2);margin-top:2px}
/* one right-hand group on every page. The CTA takes the Resources treatment
   the owner picked — mono, uppercase, square-cornered gradient block — which
   replaces the marketing pages' rounded Inter button. */
/* Sizes here are ramp steps, not free values: 13 / 15 on the text ramp. The
   generator used to emit 13.5, 14.5 and 12, which are off it — running this
   script reverted the ramp pass on both stylesheets and moved every nav panel
   by a pixel or two. Keep them on the ramp.
   the last differences between the three headers: Resources drew the logo at
   30px and its links at 13.5px. Size only — colour stays with each sheet so
   the Resources header still follows the reader's theme. */
/* A flex item shrinks by default, and below ~900px the links, the CTA and the
   burger want more than the bar has — so the anchor was squeezed, and since
   img{max-width:100%} then caps the image at that width while the height
   stays pinned, the mark itself was drawn narrow: 119x42 on an iPhone 12 where
   its own proportions are 185x42. Above the breakpoint the bar was never short
   of room, so neither declaration changes the desktop header. */
.nav .logo{flex:none;display:flex;align-items:center}
.nav .logo img{height:42px;width:auto;max-width:none}
.nav .navlink{font-size:15px;font-weight:500;white-space:nowrap}
.navr{margin-left:auto;display:flex;align-items:center;gap:11px;min-width:0}
.nav .navcta{font:400 12px/1 var(--fm);letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;padding:11px 16px;border-radius:0;white-space:nowrap;box-shadow:none;
  background:var(--acc-fill);color:var(--acc-on-fill);transition:filter .2s}
.nav .navcta:hover{filter:brightness(1.08)}
.navsec,.navsecl{display:none}
.navburger{display:none;width:40px;height:40px;border-radius:10px;border:1px solid var(--rule);
  cursor:pointer;align-items:center;justify-content:center;flex-direction:column;gap:4px;margin-left:12px;flex:none}
.navburger span{display:block;width:17px;height:1.5px;background:var(--tx);transition:transform .25s,opacity .2s}
.navtoggle:focus-visible ~ .navburger{outline:2px solid var(--az-br,#5CC4F3);outline-offset:2px}
@media(max-width:820px){
  .navburger{display:flex;margin-left:auto;order:9}
  .navtoggle:checked ~ .navburger span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
  .navtoggle:checked ~ .navburger span:nth-child(2){opacity:0}
  .navtoggle:checked ~ .navburger span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}
  /* Height is set rather than derived from bottom:0, because .nav is not always
     the same containing block. On the Resources sheet it carries a
     backdrop-filter, and an element with one becomes the containing block for
     its fixed descendants — so bottom:0 resolved against the 58px bar instead
     of the viewport and the drawer opened 59px tall, showing one row with the
     rest cut off. top:var(--nav-h) lands correctly either way: measured from
     the viewport on the marketing sheet, and from .nav's own top edge — which
     is the viewport's — on the Resources one. */
  .nav .links{display:none;position:fixed;top:var(--nav-h);left:0;right:0;bottom:auto;z-index:65;
    height:calc(100vh - var(--nav-h));height:calc(100dvh - var(--nav-h));
    flex-direction:column;align-items:stretch;gap:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
    background:var(--bg);padding:14px var(--mx) 44px;border-top:1px solid var(--rule)}
  .navtoggle:checked ~ .links{display:flex}
  /* Every section used to be open at once, so reaching Company or Resources
     meant scrolling past thirty-odd links. Each is now a disclosure: the menu
     opens as six rows and a CTA, all of it within one screen. */
  .nav .links>.navitem>.navlink{display:none}
  .navsec{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .navsecl{display:flex;align-items:center;justify-content:space-between;gap:12px;
    font:500 15px/1 var(--fb);color:var(--tx);padding:17px 2px;min-height:54px;cursor:pointer}
  .navsecl::after{content:"";flex:none;width:8px;height:8px;margin-right:5px;opacity:.65;
    border-right:2px solid currentColor;border-bottom:2px solid currentColor;
    transform:rotate(45deg) translate(-2px,-2px);transition:transform .22s var(--ease)}
  .navsec:checked ~ .navsecl::after{transform:rotate(-135deg) translate(-2px,-2px)}
  .navsec:focus-visible ~ .navsecl{outline:2px solid var(--az-br,#5CC4F3);outline-offset:2px}
  .nav .links .navitem{display:block;border-bottom:1px solid var(--rule)}
  .navitem::after{display:none}
  .navpanel{display:none;position:static;opacity:1;visibility:visible;pointer-events:auto;transform:none;
    min-width:0;max-width:none;padding:0 0 10px;background:none;border:0;box-shadow:none}
  .navsec:checked ~ .navpanel{display:block}
  .navpanel a{padding:9px 0 9px 13px;border-left:1px solid var(--rule);border-radius:0}
  .nav .links .navcta{margin:18px 0 0;text-align:center}
}
/* The bar's own budget. At 390px the full-size mark (185px), a nowrap CTA and
   the 40px burger come to more than the width, which is what forced the logo
   to give way in the first place. Below the burger breakpoint the mark steps
   down and the bar tightens, so all three fit at their true proportions. */
@media(max-width:560px){
  .nav{gap:12px;padding:0 18px}
  .nav .logo img{height:32px}
  .navr{gap:8px}
  .nav .navcta{padding:10px 12px;font-size:11px;letter-spacing:.06em}
  .navburger{margin-left:6px}
}
@media(max-width:380px){
  /* At 320px the bar's contents came to 370px and the burger ran off the
     right edge — clipped by overflow-x:hidden, so the menu could not be
     opened at all. Everything tightens here so the three still fit. */
  .nav{gap:8px;padding:0 12px}
  .nav .logo img{height:28px}
  .navr{gap:6px}
  .nav .navcta{padding:9px 10px;font-size:10.5px;letter-spacing:.04em}
  .navburger{width:36px;height:36px;margin-left:4px}
}
/* === end nav menu === */
