
  :root {
    color-scheme: light;
    /* THE PAGE SHELL. Measured on the live hub at a 2560px viewport: the content
       column was 900px, 35% of the window, with 1,660px of empty paper beside a
       four-column table squeezed into 856. 900 is a good measure for PROSE and
       the wrong one for data. A broadsheet does not set everything in one narrow
       column either: the text column stays narrow and the tables run wide. So
       the shell widens and the prose keeps its own measure below. */
    --shell: 1160px;
    /* AND THE TABLE IS NOT THE SHELL. Widening the page to 1160 fixed the metric
       band (USD 122,500 stopped wrapping onto two lines) and gave the rankings
       room, and it BROKE the city table: the fr units poured the extra 260px
       into the gutters, so London sat 200px from its own salary and a row
       stopped reading as a row. A table is set to its content, not to the page.
       The country heading shares this token so its meta can never hang past the
       table's right edge - a misalignment this codebase has shipped before. */
    --table: 980px;
    --paper: #FFF1E5; --ink: #33302E; --muted: #66605C; --faint: #736E66;
    --hairline: #E9DECF; --claret: #990F3D; --claret-deep: #6E0A2C;
    --olive: #5F7138; --olive-deep: #4A5A2B; --teal: #0D7680; --gold: #E0AC3C;
    --cream: #FFF9F2;
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
    /* Radius scale. 88 elements were 999px pills — everything-is-a-pill is the
       single loudest "template" tell. Pills are now reserved for things that
       are genuinely tags. */
    --r-sm: 7px; --r-md: 10px; --r-lg: 14px;
    /* Gold reads at 10:1 on the claret hero but only 1.87:1 on warm paper, so
       text-on-paper uses a darkened variant. Same split as the app's
       accentText token — an accent hue is not automatically an accent TEXT. */
    --gold-text: #7A5510;
    /* Micro-labels are set in mono rather than tracked uppercase sans. There
       were 156 tracked-uppercase eyebrows on this page; at that density the
       device stops being a device and becomes noise. */
    --mono: ui-monospace, 'SF Mono', 'Cascadia Mono', 'Roboto Mono', Menlo, monospace;
    /* The brand pairing — Fraunces (editorial display) + Hanken Grotesk (warm
       humanist body), the same faces the app and the console ship. These pages
       are the most public surface we have and were rendering in Georgia + the
       system stack, i.e. without the brand's most distinctive asset. The
       original stacks stay as fallbacks, so a webfont failure degrades to
       exactly what shipped before, and display=swap means text is never
       invisible while they load. NOTE: this block is inside a template
       literal — never use a backtick in these comments, it terminates the
       string and breaks the build. */
    --serif: 'Fraunces', Georgia, 'Iowan Old Style', 'Times New Roman', serif;
    --sans: 'Hanken Grotesk', -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

    /* THE TYPE SCALE. Eight sizes, closed.
     *
     * WHY THIS EXISTS. Measured on the live page: 23 distinct rendered
     * font-sizes across 39 size-and-weight pairs, and SIXTEEN of those sizes
     * sat between 9.5px and 17.5px - 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13,
     * 13.5, 14, 14.5, 15, 16, 16.5, 17, 17.5. A half-pixel step signals
     * nothing to a reader; a page built on them reads as inconsistent rather
     * than as hierarchical. That was not a scale, it was every value anyone
     * ever typed.
     *
     * THE RULES THAT KEEP IT CLOSED, and they matter more than the numbers:
     *   - Fraunces sets only NAMED things and MEASURED quantities.
     *   - Hanken never sets a numeral above --t-row.
     *   - The mono never appears above --t-micro.
     *   - Nothing exists between --t-note and --t-row. That gap is the whole
     *     point: it is what makes annotation read as annotation.
     *
     * Adding a ninth size is a decision, not a tweak. If a new element needs
     * one, the honest move is almost always to reuse --t-note or --t-row and
     * change the WEIGHT or the FACE instead. */
    --t-display: clamp(38px, 6.5vw, 60px);  /* h1 only */
    --t-section: clamp(26px, 3.2vw, 34px);  /* every h2 */
    --t-figure:  clamp(26px, 3.4vw, 38px);  /* a measured quantity that leads */
    --t-name:    20px;                      /* h3, h4, a named thing in a list */
    --t-lede:    17px;                      /* reading prose */
    --t-row:     15px;                      /* table and list rows, links */
    --t-note:    13px;                      /* annotation, dates, footnotes */
    --t-micro:   11px;                      /* mono labels, city codes, rank numerals */
  }
  * { box-sizing: border-box; }
  /* Justified reading paragraphs, with hyphenation (founder direction). */
  .lede, .appnote { text-align: justify; hyphens: auto; -webkit-hyphens: auto; }
  body {
    margin: 0; font-family: var(--sans); background: var(--paper) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.028'/%3E%3C/svg%3E");
    color: var(--ink); line-height: 1.55; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
    /* The inherited base is ON the scale. Elements that declare no size of
       their own - a dash standing for a missing figure, a trailing arrow, a
       form control taking the UA default - were landing on 16px and 14px, two
       values the scale does not contain. Anything that inherits now inherits a
       token, so the rendered set cannot drift wider than the eight. */
    font-size: var(--t-row);
  }
  /* Form controls do not inherit type by default in any browser. */
  input, button, select, textarea { font: inherit; }
  a { color: inherit; }
  /* THE RING FLIPS WITH THE GROUND. Claret on claret is not an indicator, and
     the two claret surfaces carry the pages' own actions: the hero search and
     its city links, the band's bias-audit and store links. The listing hero
     already restated the rule for itself; a token does it once, for every
     claret surface, and for buttons and summary elements too - the directory
     is built from summary rows and they had no visible focus at all. */
  :root { --focus: var(--claret); }
  .hero, .band { --focus: var(--paper); }
  /* A paper plate sitting ON the claret is paper again. */
  .hero .hero__figs, .ls-plate, .exhibit { --focus: var(--claret); }
  a:focus-visible, button:focus-visible, summary:focus-visible {
    outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 2px;
  }

  /* Masthead: one module for every apex page, see ./masthead.ts. */

  /* Masthead */
  /* Frozen while scrolling (founder, 31-08, restated 13-09 for every page).
     The sticky element is a FULL-BLEED bar, not the shell-width flex row:
     sticky on the max-width element would leave transparent gutters riding
     over the content at the sides. */
  .mastbar {
    position: sticky; top: 0; z-index: 40;
    --shell: 1160px;
    --serif: 'Fraunces', Georgia, 'Iowan Old Style', 'Times New Roman', serif;
    --sans: 'Hanken Grotesk', -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    --ink: #33302E; --paper: #FFF1E5; --cream: #FFF9F2; --hairline: #E9DECF;
    --claret: #990F3D; --claret-deep: #6E0A2C; --olive: #5F7138; --gold: #E0AC3C;
    --t-row: 15px; --t-note: 13px;
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
    font-family: var(--sans);
    background: rgba(255, 248, 242, 0.84);
    backdrop-filter: saturate(1.4) blur(16px); -webkit-backdrop-filter: saturate(1.4) blur(16px);
    border-bottom: 1px solid var(--hairline);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
  }
  /* The brand's foil rule on the bar's top edge: the plates on the hub carry
     the same rule, so chrome and content are one object. */
  .mastbar::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 1;
    background: linear-gradient(90deg, var(--claret) 0%, var(--claret-deep) 45%, var(--gold) 100%);
  }
  /* The shadow arrives only once content is travelling underneath the bar;
     at rest it dissolves into the page. Scroll-driven, no script, and a
     browser without the timeline simply keeps the resting edge. */
  @supports (animation-timeline: scroll()) {
    @media (prefers-reduced-motion: no-preference) {
      .mastbar { animation: mast-lift linear both; animation-timeline: scroll(root); animation-range: 0 96px; }
      @keyframes mast-lift { to { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 12px 28px -18px rgba(51, 48, 46, 0.5); } }
    }
  }
  /* 62px + the 1px hairline = 63px: the hub's sticky region strip pins itself
     at top: 63px, so the bar's height is a contract, not a taste. */
  /* WIDER THAN THE SHELL. With the language picker the bar holds 1,200px of
     controls at 1440 (measured), and inside the 1,160px shell the wordmark
     broke into three lines. A masthead may run wider than the column it
     tops; below 1320px the two employer text links step out (they are
     already hidden below 920px), and the bar fits the shell again. */
  .masthead {
    max-width: 1320px; margin: 0 auto; padding: 3px 22px 0; min-height: 62px;
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
  }
  /* 44px MINIMUM. Measured before this: the wordmark rendered 117x37 and the
     CTA 120x36, both under the floor, and they are the two most-aimed-at
     targets on the page. inline-flex with a min-height grows the hit area
     without moving the type, so nothing shifts visually. */
  /* THE TYPE METRICS ARE PART OF THE MARK. Size and tracking match
     web-employer/components/Wordmark.tsx exactly, and a test asserts it.
     min-height stays 44px: that is the touch target, not the type size. */
  .wm { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--serif); font-weight: 600; font-size: 22px; letter-spacing: -0.02em; text-decoration: none; color: var(--ink); }
  .wm { white-space: nowrap; flex-shrink: 0; }
  /* ONE MARK, BOTH HOSTS: "Bab" in ink, "Zituna" in olive, and the tittle of
     the dotless i replaced by the olive of the arch mark. Geometry copied from
     web-employer/components/Wordmark.tsx so the two cannot drift again. */
  .wm i { font-style: normal; color: var(--olive); }
  .wm__i { position: relative; display: inline-block; }
  .wm__olive { position: absolute; left: 50%; top: -0.17em; width: 0.5em; height: 0.5em; transform: translateX(-50%); overflow: visible; fill: var(--olive); }
  .wm:focus-visible { outline: 2px solid var(--claret); outline-offset: 4px; border-radius: 4px; }
  /* THE NAV IS ONE CAPSULE, as on www: a hairline-inset cream track holding
     the links, and the current route as a claret-tinted pill. Five loose
     words beside a wordmark read as a menu; one track reads as a control. */
  .mast-links {
    display: flex; align-items: center; gap: 2px; margin-inline-end: auto; margin-inline-start: 10px;
    padding: 4px; border-radius: 999px;
    background: rgba(94, 64, 38, 0.05); border: 1px solid rgba(94, 64, 38, 0.08);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
  }
  .mast-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
  .mast-link {
    display: inline-flex; align-items: center; gap: 7px; min-height: 44px;
    font-size: var(--t-row); font-weight: 600; color: var(--ink); text-decoration: none; white-space: nowrap;
  }
  .mast-links .mast-link {
    min-height: 36px; padding: 0 11px; border-radius: 999px;
    transition: background-color 150ms var(--ease), color 150ms var(--ease);
  }
  .mast-link:hover { color: var(--claret); }
  .mast-links .mast-link:hover { background: rgba(255, 255, 255, 0.75); }
  .mast-links .mast-link[aria-current="true"] {
    color: var(--claret); background: rgba(153, 15, 61, 0.09);
    box-shadow: inset 0 0 0 1px rgba(153, 15, 61, 0.16);
  }
  .mast-link:focus-visible { outline: 2px solid var(--claret); outline-offset: 2px; border-radius: 999px; }
  /* Broadcast-red blinking dot: the one red allowed - it means "live on air"
     (founder call), never a status. Static when motion is reduced. */
  .mast-livedot { width: 7px; height: 7px; border-radius: 999px; background: #C00; }
  @media (prefers-reduced-motion: no-preference) {
    .mast-livedot { animation: mastlive 1.6s ease-in-out infinite; }
    @keyframes mastlive { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
  }
  /* The one filled control, and it points at the reader's own door. */
  .mast-cta {
    display: inline-flex; align-items: center; min-height: 44px;
    font-size: var(--t-note); font-weight: 650; color: var(--cream); text-decoration: none; white-space: nowrap;
    background: linear-gradient(135deg, var(--claret) 0%, var(--claret-deep) 100%);
    padding: 0 20px; border-radius: 999px;
    box-shadow: 0 8px 22px -8px rgba(153, 15, 61, 0.55), inset 0 1px 0 rgba(255, 241, 229, 0.22);
    transition: transform 150ms var(--ease), box-shadow 150ms var(--ease);
  }
  .mast-cta:hover { transform: translateY(-1px); box-shadow: 0 12px 28px -8px rgba(153, 15, 61, 0.6), inset 0 1px 0 rgba(255, 241, 229, 0.22); }
  .mast-cta:active { transform: scale(0.98); transition-duration: 100ms; }
  .mast-cta:focus-visible { outline: 2px solid var(--claret); outline-offset: 3px; }
  /* THE LANGUAGE PICKER: a native disclosure (details/summary), so it opens
     and closes with no script, and the script only adds outside-click,
     Escape, and the remembered choice. Flags are the apex's own SVGs. */
  .mast-lang { position: relative; }
  .mast-lang > summary { list-style: none; }
  .mast-lang > summary::-webkit-details-marker { display: none; }
  .mast-lang__btn {
    display: inline-flex; align-items: center; gap: 7px; min-height: 38px; padding: 0 9px 0 10px;
    border-radius: 999px; border: 1px solid var(--hairline); background: var(--cream); color: var(--ink);
    font-size: var(--t-note); font-weight: 600; cursor: pointer; user-select: none;
    box-shadow: inset 0 1px 0 #FFFFFF; transition: border-color 150ms var(--ease), box-shadow 150ms var(--ease);
  }
  .mast-lang__btn:hover { border-color: var(--claret); box-shadow: 0 6px 16px -10px rgba(51, 48, 46, 0.4), inset 0 1px 0 #FFFFFF; }
  .mast-lang > summary:focus-visible { outline: none; }
  .mast-lang > summary:focus-visible .mast-lang__btn { outline: 2px solid var(--claret); outline-offset: 2px; }
  .mast-lang__flags { display: inline-flex; align-items: center; }
  .mast-lang__flag { width: 21px; height: 15px; border-radius: 3px; object-fit: cover; flex-shrink: 0; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); }
  /* Two flags for English: the second tucks under the first, the way a pair
     of passports sits in a hand. */
  .mast-lang__flag + .mast-lang__flag { margin-inline-start: -7px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1), -2px 0 0 var(--cream); }
  .mast-lang__name { max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mast-lang__chev { color: var(--muted, #736E66); flex-shrink: 0; transition: transform 150ms var(--ease); }
  .mast-lang[open] .mast-lang__chev { transform: rotate(180deg); }
  .mast-lang__menu {
    position: absolute; top: calc(100% + 8px); inset-inline-end: 0; z-index: 60;
    list-style: none; margin: 0; padding: 6px; min-width: 210px; max-height: 340px; overflow-y: auto;
    background: var(--cream); border: 1px solid var(--hairline); border-radius: 12px;
    box-shadow: 0 24px 48px -24px rgba(51, 48, 46, 0.45), 0 2px 8px -4px rgba(51, 48, 46, 0.2);
  }
  .mast-lang__opt {
    display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; padding: 6px 10px;
    border-radius: 8px; font-size: var(--t-row); font-weight: 500; color: var(--ink); text-decoration: none;
    transition: background 120ms var(--ease);
  }
  .mast-lang__opt:hover { background: rgba(153, 15, 61, 0.06); }
  .mast-lang__opt.is-active { color: var(--claret); font-weight: 700; }
  .mast-lang__opt .mast-lang__tick { margin-inline-start: auto; color: var(--claret); flex-shrink: 0; visibility: hidden; }
  .mast-lang__opt.is-active .mast-lang__tick { visibility: visible; }
  .mast-lang__opt:focus-visible { outline: 2px solid var(--claret); outline-offset: -2px; }
  @media (max-width: 1320px) {
    .mast-console { display: none; }
  }
  @media (max-width: 920px) {
    .mast-links, .mast-console { display: none; }
  }
  @media (max-width: 560px) {
    .mast-lang__name { display: none; }
    .mast-right { gap: 8px; }
    .mast-cta { padding: 0 14px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .mastbar, .mast-cta, .mast-links .mast-link, .mast-lang__chev { animation: none; transition: none; }
  }


  /* Live ticker — the stock-exchange pulse of the page */
  .ticker {
    background: var(--ink); color: var(--paper); overflow: hidden; white-space: nowrap;
    border-block: 2px solid var(--claret); position: relative;
  }
  .ticker__inner { display: inline-flex; padding: 9px 0; animation: tick 45s linear infinite; will-change: transform; }
  .ticker:hover .ticker__inner { animation-play-state: paused; }
  .ticker__item { display: inline-flex; align-items: baseline; gap: 8px; padding: 0 26px; font-size: var(--t-row); font-weight: 600; letter-spacing: 0.02em; }
  .ticker__item .up { color: var(--gold); font-weight: 500; }
  .ticker__item .sym { color: #8CA05A; font-weight: 500; }
  @keyframes tick { from { transform: translateX(0); } to { transform: translateX(-50%); } }
  @media (prefers-reduced-motion: reduce) {
    .ticker { overflow-x: auto; }
    .ticker__inner { animation: none; }
  }

  /* Claret hero — full-bleed energy */
  .hero {
    background:
      radial-gradient(52% 90% at 82% 8%, rgba(224,172,60,0.20) 0%, transparent 60%),
      radial-gradient(45% 80% at 8% 95%, rgba(13,118,128,0.28) 0%, transparent 55%),
      linear-gradient(133deg, var(--claret) 0%, var(--claret-deep) 100%);
    color: var(--paper); position: relative; overflow: hidden;
  }
  .hero::before { content: ''; position: absolute; inset: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.028'/%3E%3C/svg%3E"); opacity: 0.55; pointer-events: none; }
  .hero__in { max-width: var(--shell); margin: 0 auto; padding: 44px 22px 40px; position: relative; }
  /* TWO COLUMNS, because the hero was 1,160px wide carrying a 588px lede and
     its right half was empty claret, while the figures that belong at the top
     of a market report sat 200px below it in a band of their own. */
  .hero__grid { display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr); gap: 26px 52px; align-items: center; }
  /* Hero KPI strip. EVERY selector here is scoped .hero, and that is not
     decoration. The element is <div class="mband__strip hero__figs">, so it
     carries BOTH classes, and .mband__strip is defined LATER at equal
     specificity - which means the paper band was quietly owning the claret
     hero: gap: 0 killed the gridline, border-block painted a warm paper rule
     on claret, .metric + .metric drew #E9DECF at 9.07:1 down the inside of
     cells 2-4 (the loudest line in the hero, and exactly the coloured edge
     this system bans), and the 520px single-column collapse below never fired
     because .mband__strip sets two columns further down the file.
     Scoping to .hero takes these to (0,2,0)/(0,3,0) and settles it. */
  /* 30-08 AMENDMENT (founder): claret-deep cells on the claret hero gave the
     figures no ground to stand on - the panel dissolved into the hero and the
     four tinted labels went muddy. The strip is now the paper itself: a
     broadsheet stat card sitting ON the claret, ink and claret figures on
     paper, hairline gridlines, the four accents kept as index marks on the
     rules. Maximum contrast comes from the GROUND, not from lifting tints. */
  /* ONE COLUMN: the lead figure, then the specification line under it. The
     2x2 card is gone with the cells it held. */
  /* ── THE PLATE (2026-09-13) ──────────────────────────────────────────────
     The strip was a paper box with a 1px hairline: the lead figure sat in a
     bordered rectangle that read as a form field, and the reach figures were
     a 13px mono line under it. The founder's word was "moche". A market
     report puts its headline figures on a PLATE, and this is one: deep ink
     on the claret, a gold foil rule along the top edge as its single
     ornament, the lead figure at display size in gold, and the reach figures
     as a ruled three-cell ledger - serif numeral over mono label, the same
     shape the country table uses. Warm shadow, never black. EVERY selector
     stays scoped .hero for the reason the old comment gave: the element also
     carries .mband__strip, defined later at equal specificity. */
  .hero .hero__figs {
    position: relative; isolation: isolate;
    display: grid; grid-template-columns: 1fr; gap: 0;
    /* The KPI ledger's ground is the desk's: flat dark paper under gold
       figures (founder, 19-09: the one thing kept from the flat pass). */
    background: #16110E;
    color: var(--paper);
    border: 1px solid rgba(224,172,60,0.34); border-radius: var(--r-lg);
    box-shadow:
      0 36px 72px -36px rgba(20,10,6,0.65),
      0 14px 30px -18px rgba(20,10,6,0.45),
      inset 0 1px 0 rgba(255,241,229,0.07);
    overflow: hidden;
  }
  /* The foil rule: brightest at the centre, fading to the corners. */
  .hero .hero__figs::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; z-index: 2;
    background: linear-gradient(90deg, transparent 0%, var(--gold) 20%, #F7DE9A 50%, var(--gold) 80%, transparent 100%);
  }
  /* The same print grain the hero wears, soft-lit so the plate reads as one
     object with the page rather than a screen laid over it. */
  .hero .hero__figs::after {
    content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.028'/%3E%3C/svg%3E"); opacity: 0.6; mix-blend-mode: soft-light;
  }
  .hero .hero__figs .metric {
    position: relative; z-index: 1;
    background: transparent; color: var(--paper); border: 0; padding: 26px 26px 22px; gap: 0;
  }
  .hero .hero__figs .metric + .metric { padding-inline-start: 26px; }
  /* Rank by SIZE and OPTICAL size, not by hue. Fraunces is served with the
     opsz 9..144 axis, so the lead figure is set at the display end of it and
     degrades to Georgia. wght is deliberately absent from
     font-variation-settings: naming an axis there makes the corresponding CSS
     property inert forever. */
  .hero .hero__figs .metric { --kpi: var(--gold); }
  /* A short rule, not a full edge: it marks the cell without drawing the box. */
  .hero .hero__figs .metric::before {
    content: ''; display: block; width: 28px; height: 3px; border-radius: 2px;
    background: var(--kpi); margin-bottom: 16px;
  }
  .hero .hero__figs .metric__n {
    color: var(--paper); font-size: var(--t-section);
    font-variation-settings: 'opsz' 24;
  }
  /* Gold on ink reads at 10:1; on paper it would be 1.9:1, which is why the
     old plate could not use it. The plate is what makes the hero's own colour
     usable for its own figure. */
  .hero .hero__figs .metric--lead .metric__n {
    color: #F3D27A; font-size: var(--t-display);
    line-height: 0.95; letter-spacing: -0.03em; font-variation-settings: 'opsz' 144;
    text-shadow: 0 2px 28px rgba(224,172,60,0.22);
  }
  .hero .hero__figs .metric__l { color: rgba(255,241,229,0.62); margin-top: 8px; display: inline-flex; align-items: center; gap: 8px; }
  /* Broadcast red, glowing on the ink. Static under reduced motion. */
  .hero .hero__figs .metric__live {
    display: inline-block; width: 8px; height: 8px; border-radius: 999px; background: #E4002B;
    box-shadow: 0 0 0 0 rgba(228,0,43,0.5), 0 0 10px rgba(228,0,43,0.7);
  }
  @media (prefers-reduced-motion: no-preference) {
    .hero .hero__figs .metric__live { animation: platelive 1.6s ease-in-out infinite; }
    @keyframes platelive {
      0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(228,0,43,0.5), 0 0 10px rgba(228,0,43,0.7); }
      50% { opacity: 0.4; box-shadow: 0 0 0 6px rgba(228,0,43,0), 0 0 4px rgba(228,0,43,0.3); }
    }
  }
  .hero .hero__figs .metric__d {
    color: rgba(255,241,229,0.8); font-size: var(--t-note); line-height: 1.5;
    max-width: 34ch; margin-top: auto; padding-top: 14px;
  }
  /* THE LEDGER: the reach figures as three ruled cells on the plate's darker
     foot. Numerals in serif and tabular so they align; labels in mono at the
     micro size, the register every other data label on this page uses. */
  /* THREE CARDS ON THE PLATE (founder, 13-09: "premium cards, refined look
     and colours"). Each reach figure gets its own inset card - a soft
     paper-tinted glass on the ink, a gold hairline, a lit top edge - and its
     own accent rule in a tone of the brand: gold for the countries, olive
     for the remote share, teal for the sources. */
  .hero .hero__figs .reach {
    position: relative; z-index: 1;
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
    padding: 4px 16px 16px;
    border-top: 1px solid rgba(255,241,229,0.1);
    background: rgba(0,0,0,0.18);
  }
  .hero .hero__figs .reach__c {
    position: relative; min-width: 0; padding: 16px 16px 15px; margin-top: 12px;
    background: linear-gradient(160deg, rgba(255,241,229,0.085) 0%, rgba(255,241,229,0.035) 100%);
    border: 1px solid rgba(224,172,60,0.24); border-radius: 12px;
    box-shadow: inset 0 1px 0 rgba(255,241,229,0.12), 0 12px 24px -18px rgba(0,0,0,0.8);
  }
  .hero .hero__figs .reach__c::before {
    content: ''; display: block; width: 24px; height: 3px; border-radius: 2px; margin-bottom: 12px;
    background: var(--kpi, var(--gold));
  }
  .hero .hero__figs .reach__c:nth-child(1) { --kpi: var(--gold); }
  .hero .hero__figs .reach__c:nth-child(2) { --kpi: #9DB36A; }
  .hero .hero__figs .reach__c:nth-child(3) { --kpi: #5FB3BC; }
  .hero .hero__figs .reach__n {
    display: block; font-family: var(--serif); font-size: var(--t-section); font-weight: 600;
    letter-spacing: -0.02em; line-height: 1; color: var(--paper);
    font-variant-numeric: tabular-nums; font-variation-settings: 'opsz' 48;
  }
  .hero .hero__figs .reach__l {
    display: block; margin-top: 7px; font-family: var(--mono); font-size: var(--t-micro); font-weight: 600;
    letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255,241,229,0.62); line-height: 1.4;
  }
  .hero .hero__figs .plate__foot {
    position: relative; z-index: 1; margin: 0; padding: 10px 18px 12px;
    border-top: 1px solid rgba(255,241,229,0.1);
    font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.02em;
    color: rgba(255,241,229,0.5);
  }
  .hero .hero__figs .plate__foot b { color: rgba(255,241,229,0.78); font-weight: 600; }
  /* The lead cell is an ANCHOR: a { color: inherit } does not clear the UA
     underline, so it is cleared here and the underline belongs only to the
     four-word call to action at the end of the definition. */
  .hero .hero__figs .metric--go { text-decoration: none; }
  .hero .hero__figs .metric__cta {
    color: #F3D27A; font-weight: 600;
    text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
  }
  .hero .hero__figs .metric__arw { display: inline-block; }
  .hero .hero__figs .metric--go:focus-visible { outline: 2px solid #F3D27A; outline-offset: -3px; }
  @media (hover: hover) and (pointer: fine) {
    .hero .hero__figs .metric--go { transition: background-color 160ms var(--ease); }
    .hero .hero__figs .metric--go:hover { background: rgba(255,241,229,0.05); }
    .hero .hero__figs .metric--go:hover .metric__cta { text-decoration-thickness: 2px; }
  }
  @media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) {
    .hero .hero__figs .metric__arw { transition: transform 160ms var(--ease); }
    .hero .hero__figs .metric--go:hover .metric__arw { transform: translateX(3px); }
  }
  @media (max-width: 900px) {
    .hero__grid { grid-template-columns: 1fr; }
    .hero .hero__figs { margin-top: 4px; }
  }
  @media (max-width: 520px) {
    .hero .hero__figs .metric { padding: 22px 20px 18px; }
    .hero .hero__figs .metric--lead .metric__n { font-size: var(--t-figure); }
    /* Three cells at 320px are three cramped columns; a ledger stacks. */
    .hero .hero__figs .reach { grid-template-columns: 1fr; gap: 8px; padding: 4px 14px 14px; }
    .hero .hero__figs .reach__c { padding: 12px 14px 12px 16px; margin-top: 8px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
    .hero .hero__figs .reach__c::before { width: 3px; height: 24px; margin: 0; flex-shrink: 0; }
    .hero .hero__figs .reach__n { flex: 1; }
    .hero .hero__figs .reach__l { margin-top: 0; text-align: end; max-width: 46%; }
  }
  .kicker {
    font-family: var(--mono); font-size: var(--t-note); font-weight: 500; letter-spacing: 0.01em; 
    color: var(--gold); margin: 0 0 14px; display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center;
  }
  .kicker a { color: var(--gold); text-decoration: none; }
  .kicker a:hover { text-decoration: underline; text-underline-offset: 3px; }
  .kicker .sep { opacity: 0.5; }
  .live {
    display: inline-flex; align-items: center; gap: 6px; color: var(--paper);
    background: rgba(255,241,229,0.14); border: 1px solid rgba(255,241,229,0.3);
    border-radius: 999px; padding: 3px 11px 3px 8px; letter-spacing: 0.12em;
  }
  .live__dot { width: 7px; height: 7px; border-radius: 50%; background: #8CE07B; box-shadow: 0 0 0 0 rgba(140,224,123,0.7); animation: pulse 1.8s ease-out infinite; }
  @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(140,224,123,0.55); } 70% { box-shadow: 0 0 0 8px rgba(140,224,123,0); } 100% { box-shadow: 0 0 0 0 rgba(140,224,123,0); } }
  /* THE SCALE ALREADY SAID THIS. --t-display is annotated "h1 only" and was
     used by NOTHING: the page shipped seven of its eight tokens and the h1
     borrowed --t-figure, a token for a measured quantity. The two collide at
     the bottom of their ramps - --t-figure floors at 26px and --t-section
     floors at 26px - so at 390px a job title and every heading under it
     printed at the same size and the page had no first rank (measured
     2026-09-07). Applying the scale's own rule fixes the phone and revives
     the dead token. */
  h1.display {
    font-family: var(--serif); font-weight: 600; font-size: var(--t-display);
    line-height: 1.02; letter-spacing: -0.02em; margin: 0 0 14px; text-wrap: balance;
  }
  h1.display .hl { color: var(--gold); }
  .lede { font-size: var(--t-lede); line-height: 1.6; color: rgba(255,241,229,0.88); margin: 0; max-width: 620px; }
  .lede .strong { color: var(--paper); font-weight: 600; }

  /* City search — pure-HTML drilldown (GET form + native datalist, zero JS) */
  .citysearch { display: flex; gap: 10px; margin-top: 22px; max-width: 460px; }
  .citysearch input {
    flex: 1; min-width: 0; font: 600 var(--t-row) var(--sans); color: var(--ink);
    background: var(--cream); border: 0; border-radius: 999px; padding: 13px 20px;
    box-shadow: 0 4px 18px rgba(0,0,0,0.18);
  }
  .citysearch input::placeholder { color: var(--faint); font-weight: 500; }
  .citysearch input:focus { outline: 3px solid var(--gold); outline-offset: 1px; }
  .citysearch button {
    font: 800 var(--t-row) var(--sans); color: var(--claret); background: var(--gold);
    border: 0; border-radius: 999px; padding: 0 24px; cursor: pointer;
    box-shadow: 0 4px 14px rgba(0,0,0,0.2); transition: transform 150ms ease;
    color: #4A3405;
  }
  .citysearch button:hover { transform: translateY(-1px); }
  /* On the claret hero, so paper text on a paper hairline - not an error red,
     because nothing went wrong: the city is simply not one of ours yet. */
  .citymiss {
    max-width: 460px; margin: 12px 0 0; padding: 11px 14px;
    background: rgba(255,241,229,0.12); border: 1px solid rgba(255,241,229,0.34);
    border-radius: var(--r-sm); font-size: var(--t-note); line-height: 1.55;
    color: rgba(255,241,229,0.92);
  }
  .citymiss b { color: var(--paper); font-weight: 650; }
  .citymiss a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
  /* On the claret hero, under the search. Quiet: it is a shortcut, not the
     page's proposal. 44px so a thumb can hit it. */
  .herojump { margin: 14px 0 0; font-size: var(--t-note); }
  .herojump a {
    display: inline-flex; align-items: center; gap: 7px; min-height: 44px;
    color: rgba(255,241,229,0.88); text-decoration: underline;
    text-underline-offset: 4px; text-decoration-thickness: 1px;
    font-weight: 600;
  }
  .herojump a:hover { color: var(--paper); }

  /* Stat cards floating over the hero seam */
  .statwrap { max-width: var(--shell); margin: -26px auto 0; padding: 0 22px; position: relative; z-index: 2; }
  /* In-flow variant. The negative pull and z-index above exist to float the
     cards over the hero seam on city pages; under a section heading they made
     the cards climb on top of the title. */
  .statwrap--flow { margin: 16px auto 0; padding: 0; z-index: auto; max-width: none; }
  /* ── The market band: editorial data, one accent ──
     Strong rules top and bottom frame it as the page's data statement. The
     metrics sit in one horizontal strip - serif numbers, small-caps labels, a
     definition line under each so no figure floats unexplained. Skills and
     companies are numbered RANKED LISTS (they are rankings by listing count -
     the numbering carries meaning, it is not decoration). Claret appears
     exactly twice per zone: the lead number and the rank indices. */
  /* ── The market band: a paper plate, the hero plate's daylight twin ──
     Strong rule and a warm lift frame it as the page's data statement. The
     rankings sit in three numbered columns (skills, employers, countries),
     each a RANKED LIST by count with a bar scaled against its leader. One
     accent family per row, the same six the match breakdown uses. */
  .mband {
    position: relative; overflow: hidden;
    background: linear-gradient(180deg, #FFFCF8 0%, var(--cream) 100%);
    border: 1px solid var(--hairline); border-radius: var(--r-lg);
    box-shadow: 0 26px 52px -34px rgba(51,48,46,0.38), 0 2px 8px -4px rgba(51,48,46,0.12), inset 0 1px 0 #FFFFFF;
    padding: 28px 30px 30px; margin: 6px 0 40px;
  }
  .mband::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--claret) 0%, var(--claret-deep) 45%, var(--gold) 100%);
  }
  .mband__h { font-family: var(--serif); font-size: var(--t-section); font-weight: 650; letter-spacing: -0.015em; margin: 0 0 6px; }
  /* The population, printed. A ranking without one is a floor pretending to
     be a total, which is what this band shipped for two weeks. */
  .mband__pop { margin: 0 0 22px; font-family: var(--mono); font-size: var(--t-note); line-height: 1.5; color: var(--muted); }
  .mband__pop b { color: var(--ink); font-weight: 700; }
  .serifit { font-style: italic; font-weight: 500; color: var(--claret); }
  .mband__strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0; border-block: 1px solid var(--hairline); }
  .metric { padding: 18px 22px 16px 0; display: flex; flex-direction: column; gap: 3px; }
  .metric + .metric { border-inline-start: 1px solid var(--hairline); padding-inline-start: 22px; }
  .metric__n { font-family: var(--serif); font-size: var(--t-figure); font-weight: 700; letter-spacing: -0.02em; line-height: 1.05; font-variant-numeric: tabular-nums; }
  .metric--lead .metric__n { color: var(--claret); }
  .metric__l { font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
  .metric__d { font-size: var(--t-note); line-height: 1.45; color: var(--faint); max-width: 26ch; }
  .mband__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; padding-top: 0; }
  .mband__cols--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; }
  /* Three abreast: the row becomes a grid so the bar shrinks before the
     name does, and the name steps down one size on the scale. */
  .mband__cols--3 .ranklist__row { display: grid; grid-template-columns: 20px minmax(0, 1fr) minmax(40px, 72px) auto; align-items: center; gap: 9px; padding: 9px 0; }
  /* A long name wraps rather than losing its tail: Amazon Web Services and
     United Arab Emirates both have to be read in full. */
  .mband__cols--3 .ranklist__name { font-size: var(--t-row); white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.2; }
  .mband__cols--3 .ranklist__bar { flex: none; width: 100%; min-width: 0; }
  .mband__cols--3 .ranklist__n { text-align: end; min-width: 5ch; }
  .mband__leaders { margin: 18px 0 0; font-size: var(--t-note); color: var(--muted); }
  .mband__leaders a { color: var(--ink); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--hairline); }
  .mband__leaders a:hover { color: var(--claret); border-color: var(--claret); }
  .mband__leaders b { font-weight: 600; color: var(--ink); }
  .rankcol__h { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink); margin: 0; padding-bottom: 9px; border-bottom: 2px solid var(--ink); }
  /* The unit, once, in the head: the rows then carry bare numerals, which is
     what gives three columns room for a name like Amazon Web Services. */
  .rankcol__u { color: var(--muted); font-weight: 500; white-space: nowrap; }
  .ranklist { list-style: none; margin: 0; padding: 0; counter-reset: rank; }
  .ranklist__row { counter-increment: rank; display: flex; align-items: baseline; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
  a.ranklist__name { color: inherit; text-decoration: none; }
  a.ranklist__name:hover { color: var(--claret); }
  .ranklist__row::before { content: counter(rank, decimal-leading-zero); font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; color: var(--claret); min-width: 20px; }
  .ranklist__name { font-family: var(--serif); font-size: var(--t-name); font-weight: 600; letter-spacing: -0.01em; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* The name is now a mark plus a word, so it becomes a flex line of its own -
     text-overflow needs a text container, and the ellipsis stays on the span
     that holds the word. */
  .ranklist__name { display: flex; align-items: center; gap: 9px; }
  .smark {
    flex: 0 0 auto; width: 17px; height: 17px; display: inline-grid; place-items: center;
    fill: var(--ac, var(--claret)); color: var(--ac, var(--claret));
    vertical-align: -3px;
  }
  /* The monogram is what a skill gets when there is no authentic mark for it -
     which is most of them on a city page, where the feed's "skills" are job
     families. A lettered chip says "no logo" honestly; a generic glyph would
     pretend every row had one. */
  .smark--mono {
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 700; line-height: 1;
    border: 1px solid var(--ac, var(--claret)); border-radius: 4px;
    width: 17px; height: 17px;
  }
  /* Flags are rendered by the reader's own emoji font, so they arrive at a
     size the font decides. Pinning line-height and giving the glyph its own
     inline box keeps the country headings on one baseline whether the flag
     renders as a flag, as a letter pair (Windows), or not at all. */
  /* A flag keeps its own colours - it is a national emblem, not a mark to be
     recoloured. The hairline stops a white-heavy flag (Japan) dissolving into
     the paper it sits on. */
  .flag {
    display: inline-block; width: 21px; height: 16px; margin-inline-end: 10px;
    vertical-align: -2px; border-radius: 2px; object-fit: cover;
    box-shadow: 0 0 0 1px rgba(51, 48, 46, 0.16);
  }
  .ranklist__n { font-size: var(--t-row); font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* The count was already printed; the bar is what makes a RANKING legible
     without reading every number. Scaled against the leader and drawn from
     zero, so the lengths are the ratios - a truncated baseline would be a
     lie about magnitude. It sits between the name and the figure, sized to
     the space that is left, and disappears below 560px where the name needs
     the whole row. */
  .ranklist__bar {
    flex: 0 1 110px; min-width: 40px; height: 7px; border-radius: 999px;
    background: color-mix(in srgb, var(--hairline) 65%, #FFFFFF); overflow: hidden; align-self: center;
  }
  /* The bar takes its ROW's accent, so a ranking reads as a set of measured
     things rather than one repeated colour - the same principle the match
     breakdown uses. --ac falls back to claret, so any list that does not set
     one keeps exactly what it had. Full strength, not 58%: these accents were
     each chosen to clear 3:1 on paper and diluting them undoes that. */
  .ranklist__bar i { display: block; height: 100%; border-radius: 999px; background: var(--ac, color-mix(in srgb, var(--claret) 58%, transparent)); }
  /* The rank numeral follows too, which is what ties the row together. */
  .ranklist__row::before { color: var(--ac, var(--claret)); }
  @media (max-width: 560px) { .ranklist__bar { display: none; } }

  /* ── Remote share, promoted out of the table ───────────────────────────
     The one column on this page that varies (30 distinct values, 20-89%),
     given the room that variance earns. Bars from zero against a 100% axis
     so the lengths ARE the shares; one accent, the same olive the row bars
     use, so the section and the table read as one measure; every value
     printed, because a phone has no hover. */
  /* THE PLATE LANGUAGE, CARRIED DOWN THE PAGE (2026-09-13). Above this the
     hero plate and the market band are cards; below it everything was set
     loose on the paper with hairlines, so the page changed register halfway
     down. Each block below is now a paper plate of the same family: a
     claret-to-gold rule along the top edge, a warm lift, one radius. */
  .plate {
    position: relative; overflow: hidden;
    background: linear-gradient(180deg, #FFFCF8 0%, var(--cream) 100%);
    border: 1px solid var(--hairline); border-radius: var(--r-lg);
    box-shadow: 0 26px 52px -34px rgba(51,48,46,0.38), 0 2px 8px -4px rgba(51,48,46,0.12), inset 0 1px 0 #FFFFFF;
  }
  .plate::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--claret) 0%, var(--claret-deep) 45%, var(--gold) 100%);
  }
  .rrank {
    position: relative; overflow: hidden;
    background: linear-gradient(180deg, #FFFCF8 0%, var(--cream) 100%);
    border: 1px solid var(--hairline); border-radius: var(--r-lg);
    box-shadow: 0 26px 52px -34px rgba(51,48,46,0.38), 0 2px 8px -4px rgba(51,48,46,0.12), inset 0 1px 0 #FFFFFF;
    margin: 0 0 44px; padding: 28px 30px 26px;
  }
  .rrank::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--olive-deep) 0%, var(--olive) 55%, var(--gold) 100%);
  }

  .rrank__h {
    font-family: var(--serif); font-weight: 600; font-size: var(--t-section);
    line-height: 1.2; letter-spacing: -0.02em; margin: 0 0 8px; max-width: 24ch; text-wrap: balance;
  }
  .rrank__sub { margin: 0 0 20px; font-size: var(--t-row); line-height: 1.55; color: var(--muted); max-width: 62ch; }
  .rrank__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; counter-reset: rr; }
  .rrank__row { display: grid; grid-template-columns: minmax(88px, 148px) 1fr auto; gap: 14px; align-items: center; }
  .rrank__city {
    font-family: var(--serif); font-size: var(--t-name); font-weight: 600; letter-spacing: -0.01em;
    color: var(--ink); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .rrank__city:hover { color: var(--claret); text-decoration: underline; text-underline-offset: 3px; }
  .rrank__city:focus-visible { outline: 2px solid var(--claret); outline-offset: 2px; border-radius: 3px; }
  /* The share and the sample it rests on, together. A 0% over nine listings and
     a 64% over a hundred used to look alike; the number that decides whether to
     believe the bar was in a hover title, invisible on a phone. */
  .rrank__of { font-family: var(--mono); font-weight: 500; color: var(--faint); letter-spacing: 0; }
  .rrank__track { height: 10px; border-radius: 999px; background: var(--hairline); overflow: hidden; }
  .rrank__track i { display: block; height: 100%; border-radius: 999px; background: var(--olive); }
  .rrank__n { font-size: var(--t-row); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); min-width: 44px; text-align: end; }
  .rrank__foot { margin: 18px 0 0; font-size: var(--t-row); color: var(--muted); }
  .rrank__foot a { color: var(--claret); font-weight: 600; }
  @media (max-width: 560px) {
    .rrank__row { grid-template-columns: 1fr auto; gap: 4px 12px; }
    .rrank__city { grid-column: 1; font-size: var(--t-name); display: inline-flex; align-items: center; min-height: 44px; }
    .rrank__n { grid-column: 2; }
    .rrank__track { grid-column: 1 / -1; height: 8px; }
  }
  /* SOURCE ORDER IS LOAD-BEARING: these overrides sit AFTER the base rules and
     after the 560px block, at equal specificity, or the base three-column row
     wins and the fourth cell wraps under the name (measured on the preview). */
  .rrank__hd { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 8px 40px; align-items: end; padding-bottom: 18px; border-bottom: 2px solid var(--ink); margin-bottom: 6px; }
  .rrank__hd .rrank__sub { margin: 0; }
  /* Twelve rows as two ranked columns of six: a broadsheet sets a league
     table in columns, and 12 x 44px in one column was a wall. */
  .rrank__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 40px; }
  .rrank__row { grid-template-columns: 22px minmax(72px, 128px) 1fr auto; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
  .rrank__i { font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; color: var(--olive-deep); }
  .rrank__track { height: 12px; background: color-mix(in srgb, var(--hairline) 65%, #FFFFFF); }
  .rrank__track i { background: linear-gradient(90deg, var(--olive-deep) 0%, var(--olive) 100%); }
  .rrank__n { font-weight: 700; }
  @media (max-width: 900px) {
    .rrank__hd { grid-template-columns: 1fr; align-items: start; }
    .rrank__list { grid-template-columns: 1fr; }
  }
  @media (max-width: 700px) { .rrank { padding: 22px 18px 20px; margin-bottom: 32px; } }
  @media (max-width: 560px) {
    /* Rows are pinned explicitly: with the track spanning row 2, auto-placement
       would push the figure to a THIRD row (measured at 390px on the preview). */
    .rrank__row { grid-template-columns: 22px 1fr auto; gap: 4px 10px; }
    .rrank__i { grid-column: 1; grid-row: 1; }
    .rrank__city { grid-column: 2; grid-row: 1; }
    .rrank__n { grid-column: 3; grid-row: 1; }
    .rrank__track { grid-column: 1 / -1; grid-row: 2; height: 10px; }
  }
  @media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: view()) {
      .rrank__track i, .ranklist__bar i, .dim__t i { animation: bargrow both; animation-timeline: view(); animation-range: entry 12% entry 58%; }
    }
  }
  @keyframes bargrow { from { transform: scaleX(0.04); transform-origin: left; } to { transform: scaleX(1); transform-origin: left; } }
  .section--explore { margin-top: 8px; }

  /* ── Region tabs: progressive enhancement over a fully server-rendered
     atlas. Without JS every region stacks, exactly as before - the buttons
     are hidden until the script arms them, so no-JS users never see dead
     controls. Charter styling: mono small-caps, hairline borders, the
     pressed state is the ONE accent doing its one job. */
  /* Visible on arrival: the tabs are anchors now and need no arming. */
  /* IT TRAVELS WITH THE READER. Measured at 390px on 8 September 2026: the
     directory below this row is 12,472px tall - fourteen phone screens of city
     rows - and this strip, the only control that can filter it, scrolled away
     after the first one. A reader eight thousand pixels in had no way to change
     region and no marker saying which one they were in.
     Sticky under the masthead, which is 63px and sticky itself. It carries the
     page ground because a transparent bar over scrolling rows is unreadable,
     and a hairline under it so the boundary is visible rather than implied. */
  /* The strip keeps the page ground behind it while stuck (a transparent
     bar over scrolling rows is unreadable), and inside it the chips sit in
     one cream capsule (the ::before below), so five controls read as one. */
  .rtabs {
    display: flex; gap: 6px; flex-wrap: wrap; margin: 18px 0 4px;
    position: sticky; top: 63px; z-index: 20;
    background: var(--paper); padding: 10px 0 11px;
    border-bottom: 1px solid var(--hairline);
  }
  .rtabs::before { content: ''; position: absolute; inset: 10px 0 11px; border-radius: 999px; background: var(--cream); border: 1px solid var(--hairline); z-index: -1; box-shadow: inset 0 1px 0 #FFFFFF; }
  .rtabs { padding-inline: 5px; }
  /* A shadow only once it has left its resting place, so the strip does not
     advertise itself before it is doing anything. */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .rtabs { animation: rtabs-lift linear both; animation-timeline: view(); animation-range: exit-crossing 0% exit-crossing 1px; }
      @keyframes rtabs-lift { to { box-shadow: 0 6px 14px -10px rgba(51,48,46,0.5); } }
    }
  }
  /* The strip marks where the reader IS, not only where they last tapped.
     Quieter than the pressed state: this is a position report, not a choice. */
  .rtab[data-here="true"]:not([aria-current="true"]) {
    border-color: var(--claret); color: var(--claret);
  }
  .rtab {
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 600;
    letter-spacing: 0.07em; text-transform: uppercase; text-decoration: none;
    color: var(--ink); background: transparent;
    /* The inactive chips used to fail all three of their own signals at once:
       --muted is the colour of captions and footnotes, and the --hairline
       border measures 1.20:1 on paper, which is every decorative rule on this
       page - so the row read as five loose captions beside one solid button.
       Ink at 46% is roughly twice the page hairline and still well short of
       the tonal rupture that would make five chips the heaviest object in the
       section. No fill: a 5% wash measures 1.09:1 here and buys nothing except
       a narrower gap to the pressed chip. */
    border: 1px solid transparent; border-radius: 999px;
    padding: 9px 15px; cursor: pointer;
    transition: color 150ms var(--ease), border-color 150ms var(--ease), background 150ms var(--ease);
  }
  .rtab:hover { border-color: rgba(51, 48, 46, 0.34); background: rgba(255,255,255,0.6); }
  /* There was no focus rule at all: a:focus-visible matches an anchor, and
     these five controls are buttons, so they were keyboard-invisible. */
  .rtab:focus-visible { outline: 2px solid var(--claret); outline-offset: 3px; }
  /* Source order is load-bearing: this and .rtab:hover are both (0,2,0), so
     the pressed rule has to stay last. */
  .rtab[aria-current="true"] { background: var(--claret); border-color: var(--claret); color: var(--paper); }
  .rtab[aria-current="true"]:hover { background: var(--claret-deep); border-color: var(--claret-deep); }
  @media (max-width: 560px) {
    .rtab { min-height: 44px; padding-block: 0; display: inline-flex; align-items: center; }
    /* ONE ROW, SWIPEABLE. Five chips wrap to two rows at 390px and the strip
       measures 118px - fourteen per cent of the viewport, held for the whole
       twelve-thousand-pixel directory it sits over. A sticky bar has to earn
       its height every screen, so on a phone it becomes a single scrollable
       row at 66px and the chips keep their 44px targets. */
    .rtabs {
      flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
      scroll-snap-type: x proximity; scrollbar-width: none;
      margin-inline: -22px; padding-inline: 22px;
    }
    .rtabs::-webkit-scrollbar { display: none; }
    .rtab { flex: 0 0 auto; scroll-snap-align: start; }
  }
  .region[hidden] { display: none; }
  /* ANCHORS MUST LAND WHERE THEY POINT. The masthead is sticky at 63px and the
     region strip is now sticky under it, so every in-page jump on this page -
     the hero shortcut, the four region tabs without JavaScript, a shared
     #region-americas link - would otherwise put its target underneath them.
     Set on the html element so it covers targets this file has not thought of,
     and on the region headings at the deeper offset the strip adds. */
  html { scroll-behavior: smooth; scroll-padding-top: 76px; }
  @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
  .region { scroll-margin-top: 138px; }
  /* Measured on the preview at 1440px: the strip's bottom edge sits at 121px
     (63px masthead + the strip); --hub-stick pins the column head there. */
  .atlas { --hub-stick: 121px; }
  /* Each region is one card: header band, column head, country groups, rows.
     It replaces a mono kicker floating on a hairline over a head band that
     the kicker's negative margin pulled into (the two overlapped on the live
     hub at 1440px, 13 September 2026). */
  /* NO overflow: hidden here. The column head below is sticky, and a sticky
     box sticks to its nearest SCROLLING ancestor: with overflow hidden the
     card became that ancestor, which never scrolls, and the head never
     stuck (measured on the preview). The foil rule rounds its own corners
     instead of relying on the clip. */
  .region {
    position: relative; margin: 26px 0 0;
    background: linear-gradient(180deg, #FFFCF8 0%, var(--cream) 100%);
    border: 1px solid var(--hairline); border-radius: var(--r-lg);
    box-shadow: 0 26px 52px -34px rgba(51,48,46,0.38), 0 2px 8px -4px rgba(51,48,46,0.12), inset 0 1px 0 #FFFFFF;
    padding: 0 26px 18px;
  }
  .region::before {
    content: ''; position: absolute; top: -1px; left: -1px; right: -1px; height: 3px;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    background: linear-gradient(90deg, var(--claret) 0%, var(--claret-deep) 45%, var(--gold) 100%);
  }
  .region .mkt, .region .ctry { max-width: none; }

  /* Region kicker: wayfinding above the country groups, in the desk's
     method-note register rather than a display size. */
  /* The region head is an h3 now, so it must not inherit heading margins or
     the display face - it is a mono marker on a rule, and it was a paragraph
     when it was designed. */
  .rhead { display: flex; align-items: baseline; gap: 12px; margin: 0; padding: 20px 0 14px; font-weight: 400; }
  .rhead__name { font-family: var(--serif); font-size: var(--t-name); font-weight: 650; letter-spacing: -0.01em; text-transform: none; color: var(--ink); }
  .rhead__meta { font-family: var(--mono); font-size: var(--t-micro); color: var(--faint); letter-spacing: 0.04em; }
  .rhead::after { content: none; }

  /* City code chip: ticker-tape texture. Identity data, not decoration. */
  .ccode {
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 700;
    letter-spacing: 0.1em; color: var(--claret);
    border: 1px solid rgba(153,15,61,0.3); border-radius: 3px;
    padding: 1.5px 5px; margin-inline-end: 9px;
    background: rgba(153,15,61,0.05);
    flex-shrink: 0;
  }
  @media (max-width: 700px) {
    .mband__strip { grid-template-columns: 1fr 1fr; }
    .metric { padding: 14px 14px 12px 0; }
    .metric + .metric { padding-inline-start: 14px; }
    /* In a 2x2, only the second column has a left rule; row two needs a top one. */
    .metric:nth-child(odd) { border-inline-start: none; }
    .metric:nth-child(n+3) { border-top: 1px solid var(--hairline); }
    .mband__cols, .mband__cols--3 { grid-template-columns: 1fr; gap: 24px; }
    .mband { padding: 22px 18px 24px; }
  }

  .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
  .stat {
    background: var(--cream); border: 1px solid var(--hairline); border-radius: var(--r-lg);
    padding: 14px 18px 12px; box-shadow: 0 6px 22px rgba(51,48,46,0.10);
    position: relative; overflow: hidden;
  }
  .stat::after { content: ''; position: absolute; inset-inline: 0; bottom: 0; height: 3px; background: var(--ac, var(--claret)); transform: scaleX(0); transform-origin: left; animation: grow 0.9s cubic-bezier(0.22,1,0.36,1) 0.35s forwards; }
  @keyframes grow { to { transform: scaleX(1); } }
  .stat b {
    display: block; font-family: var(--serif); font-weight: 600; font-size: var(--t-figure);
    line-height: 1.1; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; color: var(--ac, var(--claret));
  }
  .stat b .unit { display: inline; font-size: var(--t-lede); color: var(--muted); font-weight: 600; }
  .stat > span {
    display: block; margin-top: 3px; font-family: var(--mono); font-size: var(--t-micro); font-weight: 500;
    letter-spacing: 0.01em;  color: var(--faint);
  }

  .wrap { max-width: var(--shell); margin: 0 auto; padding: 26px 22px 72px; }
  /* Prose does NOT follow the shell. These are the only running-text elements on
     the page and they keep a reading measure; everything else (tables, rankings,
     metric bands) is data and uses the full width. */
  .mkt, .ctry { max-width: var(--table); }
  .lede { max-width: 60ch; }
  .mktnote { max-width: 92ch; }

  /* JUSTIFIED PROSE, and only prose. Justification without hyphenation opens
     rivers of white down a column, so hyphens: auto goes with it - and that only
     works because the document declares its language.
     DELIBERATELY EXCLUDED: .metric__d, which is capped at 26ch. Justifying two
     short lines in a 26ch measure produces word gaps you could park a car in,
     which is the failure justification is famous for. Headings, table cells,
     labels and buttons are excluded for the same reason: they are not prose. */
  .lede, .mktnote, .rrank__sub, .band p, .desk__lede, .brief p {
    text-align: justify;
    text-align-last: start;
    hyphens: auto;
    -webkit-hyphens: auto;
    /* Justification is only as good as its hyphenation. Without a floor the
       browser breaks a word after two letters and strands three at the end,
       which is what makes justified web text look cheap. Same values the www
       side already uses: hyphenate words of 7+, never leaving fewer than 4
       before or 3 after. */
    hyphenate-limit-chars: 7 4 3;
  }
  /* Justification needs a measure. On a phone these columns fall to roughly 30
     characters, well under the 45 the eye needs, and justified text that narrow
     is all rivers. Ragged right below the point where it stops paying - the
     same threshold globals.css uses for .we-prose. */
  @media (max-width: 700px) {
    .lede, .mktnote, .rrank__sub, .band p, .desk__lede, .brief p { text-align: start; hyphens: manual; -webkit-hyphens: manual; }
  }
  .rrank__foot { max-width: 76ch; }

  .hiringline { font-size: var(--t-row); color: var(--muted); margin: 16px 0 4px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
  .hiringline .lbl { font-family: var(--mono); font-weight: 500; font-size: var(--t-micro); letter-spacing: 0.01em; color: var(--claret); }
  .copill {
    display: inline-flex; align-items: center; gap: 7px; background: var(--cream);
    border: 1px solid var(--hairline); border-radius: 999px; padding: 4px 12px 4px 5px;
    font-size: var(--t-note); font-weight: 500; color: var(--ink);
  }
  .copill .dot { width: 20px; height: 20px; border-radius: 50%; color: var(--cream); font-size: var(--t-micro); font-weight: 500; display: inline-flex; align-items: center; justify-content: center; font-family: var(--serif); }
  .copill .n { color: var(--faint); font-weight: 600; }

  /* Listing — premium editorial CARDS, not form rows. Depth at rest, lift on
     hover, the salary as a headline figure, the action cue always visible. */
  .listing { margin: 26px 0 0; display: grid; gap: 14px; }
  .lhead {
    display: flex; justify-content: space-between; align-items: baseline;
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.01em; 
    color: var(--faint); padding-bottom: 9px; border-bottom: 3px solid var(--claret);
  }
  .lhead .accent { color: var(--claret); }
  .appnote { font-size: var(--t-note); color: var(--faint); margin: 10px 2px 0; }
  .appnote a { color: var(--claret); font-weight: 600; text-decoration: none; }
  .appnote a:hover { text-decoration: underline; text-underline-offset: 3px; }
  a.row {
    display: flex; flex-direction: column; gap: 12px;
    background: linear-gradient(180deg, var(--cream) 0%, #FFF4E8 100%);
    border: 1px solid var(--hairline); border-radius: 18px;
    padding: 18px 20px 14px; text-decoration: none; cursor: pointer;
    position: relative; overflow: hidden;
    box-shadow: 0 2px 10px rgba(51,48,46,0.06);
    transition: transform 200ms var(--ease), box-shadow 200ms var(--ease), border-color 200ms var(--ease);
  }
  /* Claret corner glow, revealed on hover. */
  a.row::after {
    content: ''; position: absolute; inset: 0; opacity: 0; pointer-events: none;
    background: radial-gradient(440px 150px at 100% 0%, rgba(153,15,61,0.08), transparent 60%);
    transition: opacity 200ms var(--ease);
  }
  a.row:hover { transform: translateY(-3px); box-shadow: 0 16px 36px rgba(51,48,46,0.14); border-color: rgba(153,15,61,0.32); }
  a.row:hover::after { opacity: 1; }
  a.row:active { transform: translateY(-1px) scale(0.997); }
  .jtop { display: flex; align-items: flex-start; gap: 14px; }
  .med {
    width: 52px; height: 52px; border-radius: 15px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--cream); font-family: var(--serif); font-weight: 650; font-size: var(--t-name);
    box-shadow: inset 0 -8px 14px rgba(0,0,0,0.16), 0 3px 8px rgba(51,48,46,0.14);
    transition: transform 200ms var(--ease);
  }
  a.row:hover .med { transform: scale(1.06) rotate(-3deg); }
  .rowmain { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
  .tline { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
  .row .t {
    font-size: var(--t-name); font-weight: 550; color: var(--ink);
    letter-spacing: -0.008em; transition: color 140ms var(--ease);
  }
  a.row:hover .t { color: var(--claret); }
  /* Freshness: the one thing on a row that changes hour to hour. */
  .fresh {
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.01em; 
    color: var(--faint); border: 1px solid var(--hairline); border-radius: 999px; padding: 2px 8px;
    white-space: nowrap;
  }
  .fresh.hot { color: var(--olive-deep); border-color: rgba(95,113,56,0.4); background: rgba(95,113,56,0.08); }
  .tag-remote {
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.01em; 
    color: var(--teal); border: 1px solid rgba(13,118,128,0.35); background: rgba(13,118,128,0.07);
    border-radius: 999px; padding: 2px 8px; white-space: nowrap;
  }
  .row .co { font-size: var(--t-row); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .row .co .loc { color: var(--faint); }
  /* The salary is a HEADLINE figure, not a footnote. */
  .sal {
    font-family: var(--serif); font-weight: 650; font-size: var(--t-figure); line-height: 1.2;
    font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--olive-deep);
    text-align: end; flex-shrink: 0;
  }
  .jfoot {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    border-top: 1px dashed var(--hairline); padding-top: 11px;
  }
  .rowskills { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
  .rowskill {
    font-size: var(--t-note); font-weight: 600; color: var(--muted);
    background: var(--paper); border: 1px solid var(--hairline);
    border-inline-start: 3px solid var(--ac, var(--teal));
    border-radius: var(--r-sm); padding: 2px 8px; white-space: nowrap;
    transition: color 160ms var(--ease);
  }
  a.row:hover .rowskill { color: var(--ink); }
  /* Always-visible action chip — outline at rest, fills claret on hover. */
  .row .go {
    flex-shrink: 0; font-size: var(--t-note); font-weight: 650; letter-spacing: 0.03em;
    color: var(--claret); border: 1.5px solid rgba(153,15,61,0.4); border-radius: 999px;
    padding: 6px 13px; white-space: nowrap;
    transition: background 180ms var(--ease), color 180ms var(--ease), border-color 180ms var(--ease);
  }
  a.row:hover .go { background: var(--claret); border-color: var(--claret); color: var(--cream); }

  /* ── ONE LISTING (/jobs/listing/<slug>-<handle>) ──
     The app's card, at page size: the claret hero carries the facts and a
     paper plate with the salary as the headline figure and the one call to
     action; the body is the employer's text as paragraphs and lists, an
     at-a-glance ledger, and the six dimensions the app will score. Every size
     here is one of the eight tokens - the type-scale gate reads this block. */
  .ls-hero .hero__grid { align-items: start; }
  .ls-co { font-size: var(--t-lede); line-height: 1.5; color: rgba(255,241,229,0.88); margin: 0; }
  .ls-co b { color: var(--paper); font-weight: 600; }
  .ls-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
  .ls-tag {
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--paper); border: 1px solid rgba(255,241,229,0.35); border-radius: 999px; padding: 4px 10px; white-space: nowrap;
  }
  .ls-tag--remote { background: rgba(255,241,229,0.14); }
  /* The plate sits ON the claret, ink and claret on paper: the same ground the
     market hero's figures stand on, for the same reason - contrast from the
     ground, not from lifted tints. */
  .ls-plate { background: var(--paper); color: var(--ink); border: 1px solid var(--hairline); padding: 20px 20px 18px; }
  .ls-plate__l { font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
  .ls-plate__sal {
    font-family: var(--serif); font-size: var(--t-figure); font-weight: 650; letter-spacing: -0.02em; line-height: 1.05;
    color: var(--olive-deep); font-variant-numeric: tabular-nums; margin-top: 6px;
  }
  .ls-plate__sal--nil { font-size: var(--t-name); font-weight: 500; font-style: italic; color: var(--muted); line-height: 1.3; }
  .ls-plate__per { font-family: var(--sans); font-size: var(--t-note); font-weight: 500; color: var(--muted); letter-spacing: 0; }
  .ls-apply {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px; padding: 0 22px; margin-top: 16px;
    border-radius: 999px; background: var(--claret); color: var(--cream); font-size: var(--t-row); font-weight: 700; text-decoration: none;
    box-shadow: 0 4px 14px rgba(153,15,61,0.28); transition: transform 150ms var(--ease), background 150ms var(--ease);
  }
  .ls-apply:hover { transform: translateY(-1px); background: var(--claret-deep); }
  .ls-apply:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
  /* The ring on the claret hero and the claret ring back on the paper plate
     inside it are both handled by --focus now (see the :root block). */
  .ls-plate__note { margin: 10px 0 0; font-size: var(--t-note); line-height: 1.5; color: var(--muted); }
  .ls-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 360px); gap: 34px 48px; align-items: start; }
  .ls-article { max-width: 72ch; min-width: 0; }
  .ls-h2 { font-family: var(--serif); font-size: var(--t-section); font-weight: 650; letter-spacing: -0.015em; margin: 36px 0 12px; }
  .ls-article > .ls-h2:first-child { margin-top: 0; }
  .ls-src { font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); margin: 0 0 14px; }
  .ls-desc p { font-size: var(--t-lede); line-height: 1.65; color: var(--ink); margin: 0 0 14px; }
  .ls-desc .ls-h3 { font-family: var(--sans); font-size: var(--t-row); font-weight: 700; letter-spacing: 0.01em; color: var(--ink); margin: 22px 0 8px; }
  .ls-ul { margin: 0 0 14px; padding-inline-start: 22px; }
  .ls-ul li { font-size: var(--t-lede); line-height: 1.6; margin: 0 0 6px; }
  .ls-desc p, .ls-ul li { text-align: justify; text-align-last: start; hyphens: auto; -webkit-hyphens: auto; hyphenate-limit-chars: 7 4 3; }
  @media (max-width: 700px) { .ls-desc p, .ls-ul li { text-align: start; hyphens: manual; -webkit-hyphens: manual; } }
  .ls-empty { font-size: var(--t-row); line-height: 1.6; color: var(--muted); max-width: 60ch; }
  .ls-skills { display: flex; flex-wrap: wrap; gap: 8px; }
  .ls-aside { display: grid; gap: 18px; position: sticky; top: 84px; min-width: 0; }
  .ls-card { background: var(--cream); border: 1px solid var(--hairline); border-radius: var(--r-lg); padding: 18px 20px 16px; box-shadow: 0 6px 22px rgba(51,48,46,0.08); }
  .ls-card__h { font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin: 0 0 12px; }
  .ls-facts { margin: 0; display: grid; gap: 9px; }
  .ls-facts > div { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 10px; align-items: baseline; padding-bottom: 8px; border-bottom: 1px dashed var(--hairline); }
  .ls-facts dt { font-size: var(--t-note); font-weight: 500; color: var(--muted); }
  .ls-facts dd { margin: 0; font-size: var(--t-row); font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
  /* THE LEDGER. One object where the page carried two cards saying the same
     thing: the six dimensions in the app's weight order, then the two facts
     about the page. A 3px ink rule on top, hairline rules between rows, no
     radius - a fact table, not a card. */
  .ls-led { margin: 0; display: grid; gap: 0; border-top: 3px solid var(--ink); }
  .ls-led > div {
    display: grid; grid-template-columns: 12px 86px minmax(0, 1fr); gap: 10px; align-items: baseline;
    padding: 9px 0 8px; border-bottom: 1px solid var(--hairline);
  }
  .ls-led i { display: block; width: 12px; height: 4px; border-radius: 2px; background: var(--dim, var(--claret)); align-self: center; }
  .ls-led__nod { background: var(--hairline) !important; }
  .ls-led dt { font-size: var(--t-note); font-weight: 600; color: var(--ink); }
  .ls-led dd { margin: 0; font-size: var(--t-note); font-weight: 500; color: var(--ink); overflow-wrap: anywhere; }
  .ls-led dd.nil { font-style: italic; font-weight: 400; color: var(--muted); }
  .ls-led__note { margin: 12px 0 0; font-size: var(--t-note); line-height: 1.5; color: var(--muted); }
  /* Provenance, and the honest end of a text we could not print whole. */
  .ls-prov { font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin: 0 0 14px; }
  .ls-prov b { font-weight: 700; color: var(--ink); }
  .ls-cut { margin: 4px 0 0; font-size: var(--t-note); font-style: italic; color: var(--muted); }
  .ls-cut a { color: var(--claret); font-style: normal; font-weight: 600; text-decoration: none; }
  .ls-cut a:hover { text-decoration: underline; text-underline-offset: 3px; }
  .ls-related { margin-top: 44px; }
  .ls-more { margin: 16px 0 0; font-size: var(--t-row); font-weight: 600; }
  .ls-more a { color: var(--claret); text-decoration: none; }
  .ls-more a:hover { text-decoration: underline; text-underline-offset: 3px; }
  /* The sticky bar exists only where the aside has fallen below the fold -
     which is what this said before it was true. Measured on a Spotify listing
     at 390px, 8 September 2026: the plate's "Apply in the app" sat at 466px and
     this bar's identical claret copy at 786px, both in the first screen. Two of
     the same button, 320px apart, is not emphasis. The script below hides this
     one while the plate's is on screen; without the script the bar behaves as
     it always has, which is the honest fallback. */
  .ls-sticky { display: none; }
  .ls-sticky[data-idle="true"] { display: none; }
  @media (max-width: 900px) {
    .ls-grid { grid-template-columns: 1fr; }
    .ls-aside { position: static; }
    /* The facts and the date are read BEFORE 2,445px of employer prose: the
       ledger is emitted after the article in the DOM for the desktop column
       order, and pulled above it here. */
    .ls-article { order: 2; }
    .ls-aside { order: 1; }
    .ls-grid { display: flex; flex-direction: column; gap: 28px; }
    .ls-sticky {
      position: fixed; inset-inline: 0; bottom: 0; z-index: 30; display: flex; align-items: center; justify-content: space-between; gap: 12px;
      padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); background: rgba(255,241,229,0.94);
      backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-top: 1px solid var(--hairline);
    }
    .ls-sticky .ls-apply { margin: 0; width: auto; flex: 0 0 auto; padding-inline: 18px; }
    .ls-sticky__t { min-width: 0; font-size: var(--t-note); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .ls-body { padding-bottom: 76px; }
  }

  /* "+N more" — a loud, clickable band into the app */
  .moreband {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    margin-top: 14px; padding: 18px 22px; border-radius: var(--r-lg); text-decoration: none;
    background: linear-gradient(120deg, rgba(153,15,61,0.08) 0%, rgba(224,172,60,0.12) 100%);
    border: 1.5px dashed rgba(153,15,61,0.35);
    transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
  }
  .moreband:hover { border-color: var(--claret); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(153,15,61,0.14); }
  .moreband .big { font-family: var(--serif); font-weight: 650; font-size: var(--t-name); color: var(--claret); }
  .moreband .sub { font-size: var(--t-row); color: var(--muted); }
  .moreband .arr { font-size: var(--t-row); color: var(--claret); font-weight: 500; transition: transform 160ms ease; }
  .moreband:hover .arr { transform: translateX(5px); }

  /* NOT a flex row. The italic span inside "Explore the market, city by city"
     became a second flex item and the heading printed as two columns side by
     side at 390px. A heading is a line of text; the tag rides along inline. */
  h2.section {
    font-family: var(--serif); font-weight: 600; font-size: var(--t-section); letter-spacing: -0.01em;
    margin: 36px 0 4px; padding-bottom: 8px; border-bottom: 3px solid var(--claret);
    display: block;
  }
  h2.section .tag {
    display: inline-block; margin-inline-start: 10px;
    font-family: var(--mono); font-size: var(--t-note); font-weight: 500; letter-spacing: 0.01em; color: var(--gold-text);
  }
  /* Chips survive for "Other cities" on city pages — a short lateral nav where
     a tag IS the right shape. (They were removed with the hub listing in #474,
     which left those links unstyled in production; restored here in the new
     weight/radius idiom.) */
  .chips { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 14px; }
  .chip {
    font-size: var(--t-row); font-weight: 500; color: var(--ink); text-decoration: none;
    border: 1px solid var(--hairline); background: var(--cream); border-radius: 999px;
    padding: 7px 15px; display: inline-flex; align-items: center; gap: 7px;
    transition: border-color 150ms var(--ease), color 150ms var(--ease), background 150ms var(--ease);
  }
  @media (hover: hover) and (pointer: fine) {
    a.chip:hover { border-color: var(--claret); color: var(--claret); }
  }
  a.chip:active { background: rgba(153, 15, 61, 0.06); }
  a.chip:focus-visible { outline: 2px solid var(--claret); outline-offset: 2px; }

  /* Market directory. Replaces a wrap of 41 identical pills whose only variable
     was the city name — with honest counts they all read "120+", so the pill
     carried no information at all. A broadsheet table is the brand's own idiom
     and gives every row four differentiating figures. Grid, not <table>: it
     collapses to a stacked card on phones without duplicated markup. */
  .mkt { padding-top: 6px; }
  /* The once-per-region header sits above the first country heading, so it
     carries a rule beneath it to bind it to the rows that follow. */
  /* The rule moves OFF this wrapper and onto the child: at 720px the CHILD is
     hidden and the wrapper is not, so a border here survives as an orphan line
     floating above the country name on every phone. */
  /* FROZEN WHILE THE REGION SCROLLS (founder, 13-09: "freeze the header
     while scrolling down"). Sticky on the wrapper, under the masthead (63px)
     and the region strip; it releases where its region card ends, so the next
     region's head takes over. --hub-stick is the strip's bottom edge. */
  .mkt--head { padding-top: 0; margin: 0 0 -2px; position: sticky; top: var(--hub-stick, 121px); z-index: 15; }
  .mkt__head, .mkt__row {
    display: grid;
    grid-template-columns: minmax(150px, 1.5fr) minmax(120px, 0.9fr) minmax(176px, 1.1fr) minmax(130px, 1.2fr);
    gap: 16px; align-items: center;
  }
  /* Must stay AFTER the shared .mkt__head, .mkt__row rule above: same
     specificity, source order is what wins.
     baseline, not the inherited center: two of these four cells are two lines
     tall (they carry a "sample" qualifier), which is why City and Hiring most
     for float mid-band today instead of sitting on one line. baseline is this
     file's own idiom for exactly that, used by .country and .mkt__city.
     ONE variable changes: tone. Weight stays 500 and tracking stays 0.01em, so
     the key never collides with .mkt__role one row below, which is --muted at
     600 - the header has to stay subordinate to the figures it introduces. */
  /* A DESIGNED table head, not a caption. The previous pass only moved tone,
     and tone alone left this reading as a footnote above the data. What makes
     a masthead here: claret instead of grey, real tracking, a cream band that
     gives the row a body, and a claret rule with weight under it.
     It still cannot outrank the country heading above it, which is --ink in
     19px Fraunces at 11.83:1 - this is 10px mono, four sizes down, so the
     order of the page is unchanged. */
  .mkt__head {
    align-items: baseline;
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 700;
    letter-spacing: 0.13em; text-transform: uppercase;
    color: var(--claret); padding: 11px 12px 9px;
    background: var(--cream);
    border-block: 1px solid rgba(153, 15, 61, 0.28);
    border-bottom-width: 2px;
    border-start-start-radius: 4px; border-start-end-radius: 4px;
    /* OPAQUE, because it now rides over rows: the claret wash is composited
       onto cream rather than onto whatever scrolls beneath. */
    background: linear-gradient(rgba(153, 15, 61, 0.045), rgba(153, 15, 61, 0.045)), var(--cream);
  }
  /* PREMIUM ROWS (2026-09-13). The founder read the directory as "basic grey,
     too small, ugly": a 13px muted median, a 46x5 bar with a 13px figure,
     and a muted 15px role, every one of them a step below the city name. The
     figures are the reason the row exists; they now sit at the name's size,
     in ink, with the bar and the role given a body of their own. */
  .mkt__row {
    padding: 16px 12px; text-decoration: none; color: var(--ink);
    border-top: 1px solid var(--hairline);
    transition: background 150ms var(--ease), box-shadow 150ms var(--ease);
    position: relative; border-radius: 6px;
  }
  /* The city link covers the row. Keyboard focus lands on the real anchor and
     the outline is drawn on the ROW, so a focused row looks like a focused row
     rather than like a focused word. */
  .mkt__link { text-decoration: none; color: inherit; }
  .mkt__link::after { content: ''; position: absolute; inset: 0; }
  .mkt__row:has(.mkt__link:focus-visible) { outline: 2px solid var(--claret); outline-offset: -2px; }
  .mkt__link:focus-visible { outline: none; }
  /* The country sits ABOVE the overlay so it is clickable in its own right.
     Without this it would be under the stretched link and unreachable. */
  .mkt__ctry { position: relative; z-index: 1; }
  .num { font-variant-numeric: tabular-nums; }
  .mkt__city {
    font-family: var(--serif); font-weight: 600; font-size: var(--t-name); letter-spacing: -0.01em;
    display: inline-flex; align-items: baseline; gap: 7px; min-width: 0;
    flex-wrap: wrap;
  }
  /* THE COUNTRY, on the rows that are their country's whole entry.
     It sits UNDER the city rather than beside it, on its own line, so the
     column of city names stays a clean vertical edge - twenty-seven countries
     inlined next to twenty-seven city names would ragged that edge and undo
     the reason for demoting them. Mono and faint: it is an address, not a
     name competing with the city. */
  .mkt__ctry {
    flex-basis: 100%; display: flex; align-items: center; gap: 6px;
    font-family: var(--mono); font-size: var(--t-micro); font-weight: 500;
    letter-spacing: 0.04em; color: var(--faint); margin-top: 3px;
  }
  .mkt__ctry .flag { width: 15px; height: 11px; }
  .nat { color: var(--olive-deep); font-weight: 600; }
  .country .cnt .nat { color: var(--olive-deep); }
  .mkt__row:hover .mkt__ctry { color: var(--muted); }
  .mkt__go { color: var(--claret); font-weight: 500; opacity: 0; transform: translateX(-4px);
    transition: opacity 160ms var(--ease), transform 160ms var(--ease); }
  /* The count is CONTEXT, not a ranking.
     Measured 2026-08-16: every one of the 41 cities returns 1,000+ roles
     within 60km - raising the query cap from 120 to 1000 moved the wall, it did
     not remove it. A figure that is identical on every row cannot rank, so it
     no longer takes the claret and the weight. What actually differentiates a
     market for a candidate is the pay, the remote share and what is hiring -
     those get the emphasis now. */
  .mkt__n { font-weight: 500; color: var(--muted); font-size: var(--t-row); }
  .mkt__role { color: var(--ink); }
  /* The median in the serif at the name's size: a figure the reader came for,
     set like one. Tabular, so a column of them lines up on the digits. */
  .mkt__sal { font-family: var(--serif); font-weight: 650; font-size: var(--t-name); letter-spacing: -0.01em; color: var(--ink);
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 1px 0; line-height: 1.15; }
  /* The unit above the amount: mono, tracked, a tone down. order: -1 puts it
     first on screen while the amount stays first in the source; a full-width
     basis gives it the line to itself, and the dagger stays beside the amount
     (a column flex put it on a third line - measured on the preview). */
  .sal__cur { order: -1; flex-basis: 100%; font-family: var(--mono); font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.1em; color: var(--muted); }
  /* A hairline tick above the two derived columns. It reads as a footnote
     rather than a warning: these are sample statistics, the market count next
     to them is not, and the row should not pretend otherwise. The header cells
     carry it too, so the meaning is declared once at the top of the table. */
  .sampled { position: relative; }
  /* The qualifier steps down a TONE, not an OPACITY. --faint at 0.75
     composites to #968F86 = 2.89:1 and has been failing AA in production.
     Lowercase, because this band held the page's only tracked-uppercase
     micro-type sitting directly under a tracked-uppercase region kicker. */
  /* The qualifier steps down a TONE, never an OPACITY: --faint at 0.75
     composites to #968F86 = 2.89:1 and failed AA in production. It is now set
     in the serif italic - a printed footnote voice, which reads as considered
     beside tracked uppercase rather than as a second, smaller shout. */
  .mkt__head .sampled::after {
    content: "sample"; display: block; margin-top: 3px;
    font-family: var(--serif); font-style: italic; font-weight: 500;
    font-size: var(--t-micro); letter-spacing: 0; text-transform: none;
    color: var(--faint);
  }
  /* The sample qualifier lives in the column head ("sample", above), where it
     is declared once; the cell itself is a figure and is set in ink. Muting
     every cell in two columns made the table read as greyed out. */
  .mkt__row .sampled { color: var(--ink); }
  /* Zebra without lines: the eye tracks a 5-column row across 41 of them far
     better with a faint band than with another border. */
  .mkt__row:nth-child(even) { background: rgba(0,0,0,0.012); }
  .mkt__row:hover { background: rgba(153,15,61,0.045); }
  /* The role as a chip: cream on a hairline, the one rounded object on the
     row, so "Sales" reads as a category and not as a fourth loose word. */
  /* The chip is an INNER span: on a phone the cell's ::before label sits
     outside the pill, not inside it (measured on the preview at 390px). */
  .mkt__role { font-size: var(--t-note); font-weight: 650; color: var(--ink); justify-self: start; max-width: 100%; min-width: 0; }
  .mkt__role .chip { display: inline-block; max-width: 100%; padding: 5px 12px; border-radius: 999px;
    background: var(--cream); border: 1px solid var(--hairline); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
  .mkt__role .chip:has(.nil) { background: transparent; border-color: transparent; box-shadow: none; padding-inline: 0; }
  .nil { color: var(--faint); font-weight: 500; }
  /* A dagger, not a colour: the point is "read this differently", not "this is
     bad", and it has to survive greyscale and a screen reader. An abbr element
     gives it the title semantics for free.
     NOTE: this whole block is inside a TS template literal - no backticks. */
  .xcur {
    text-decoration: none; border: 0; color: var(--claret); font-weight: 600;
    margin-inline-start: 3px; cursor: help; font-size: var(--t-note);
  }
  /* Prose, not a caption. This is the table's trust statement - why most
     salary cells show a dash rather than a guess - and it was set in 11px mono
     at --faint, ten lines and 176px tall on a phone: the smallest and hardest
     text on the page carrying the sentence that makes the table honest. Sans
     at the annotation size, mono kept for the figures inside it. */
  /* A footnote card: the table's trust statement, set on cream with a claret
     rule on its leading edge, so it reads as a considered note rather than a
     loose paragraph between the strip and the first region. */
  .mktnote {
    margin: 14px 0 0; padding: 14px 18px 14px 20px;
    font-family: var(--sans); font-size: var(--t-note); line-height: 1.65; color: var(--muted);
    background: var(--cream); border: 1px solid var(--hairline); border-inline-start: 3px solid var(--claret);
    border-radius: var(--r-md);
  }
  .mktnote b { font-family: var(--mono); color: var(--claret); font-weight: 600; letter-spacing: 0; }

  /* THE MARKET BRIEF: this page's own listings, counted.
     Prose, and deliberately NOT another .mktnote box - two stacked note cards
     read as two asides, and this is the body copy the page never had. Measured
     2026-09-22: four live market pages shared 166 words and carried only 30 to
     51 apiece that the others did not. The figure treatment is the one the page
     already gives a figure, so the brief joins the type system instead of
     extending it: no new colour, no new size. */
  .brief { margin: 4px 0 0; }
  .brief p { margin: 14px 0 0; max-width: 78ch; font-size: var(--t-lede); line-height: 1.7; color: var(--ink); }
  .brief b { font-family: var(--mono); color: var(--claret); font-weight: 600; letter-spacing: 0; }
  /* Remote share reads at a glance as a bar, and exactly as a number. */
  /* THE BAR AS IT WAS (founder, 13-09: "roll back the bars, I don't like the
     new design"): the pill in the olive gradient with a bold sans figure. The
     ten-segment meter and the serif figure of the second pass are gone; the
     population line under the bar stays, it is the answer to "why 120". */
  .mkt__rem { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
  .rem { display: inline-flex; align-items: center; gap: 10px; }
  .rem__bar { display: block; width: 72px; height: 8px; border-radius: 999px; overflow: hidden; flex-shrink: 0;
    background: color-mix(in srgb, var(--hairline) 65%, #FFFFFF); box-shadow: inset 0 1px 1px rgba(51, 48, 46, 0.08); }
  .rem__bar i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--olive-deep) 0%, var(--olive) 100%); }
  .rem__n { font-weight: 700; font-size: var(--t-row); font-variant-numeric: tabular-nums; color: var(--ink); }
  .rem__of { font-family: var(--mono); font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.02em; color: var(--muted); }
  /* Hover on a real pointer only: on touch it sticks after a tap. */
  @media (hover: hover) and (pointer: fine) {
    .mkt__row:hover { background: var(--cream); box-shadow: inset 0 0 0 1px rgba(153, 15, 61, 0.14), 0 6px 18px -12px rgba(51, 48, 46, 0.35); }
    .mkt__row:hover .mkt__go { opacity: 1; transform: none; }
    .mkt__row:hover .mkt__city { color: var(--claret); }
  }
  .mkt__row:active { background: rgba(153, 15, 61, 0.08); }
  .mkt__row:focus-visible { outline: 2px solid var(--claret); outline-offset: -2px; }
  @media (max-width: 720px) {
    /* Stacked card: the header row is meaningless once the columns collapse, so
       it goes, and each figure carries its own label via ::before. */
    .mkt__head { display: none; }
    /* Three lines, not five: city, then the figures side by side, then the
       role. One figure per line pushed each row to 168px — 41 of those is
       ~7,000px of scrolling for a directory people skim. */
    /* Two figures, not three, now that the identical count is gone - which buys
       each of the survivors more width and a larger size on the card. */
    .mkt__row { grid-template-columns: auto 1fr; gap: 6px 22px; padding: 14px 4px; }
    .region { padding: 0 16px 12px; margin-top: 18px; }
    .rhead { padding: 16px 0 10px; }
    .mkt__city { grid-column: 1 / -1; font-size: var(--t-name); }
    /* THE THIRD FIGURE HAD NO LABEL, on screen or in the accessibility tree.
       The desktop header names four columns and disappears here, so each cell
       carries its own - except the role, which announced as a bare "Sales".
       Verified in Chrome's a11y tree on 8 September 2026: these ::before labels
       ARE exposed ("Median", "GBP 40,000", "Remote", "11%"), so the row reads
       as measure-then-value; the fourth value read as a word with no measure. */
    .mkt__sal::before, .mkt__rem::before, .mkt__role::before {
      content: attr(data-l); display: block;
      font-family: var(--mono); font-size: var(--t-micro); font-weight: 500; letter-spacing: 0;
      color: var(--faint); margin-bottom: 2px;
    }
    .mkt__sal { grid-column: 1; } .mkt__rem { grid-column: 2; }
    .mkt__sal, .mkt__rem { justify-self: start; }
    /* The unit sits inline before the amount here ("GBP 45,500"): one line
       under the card's own label, which is a flex item too and outranks the
       unit's order: -1. */
    .mkt__sal { font-size: var(--t-name); gap: 0 6px; }
    .sal__cur { flex-basis: auto; }
    .mkt__sal::before { order: -2; flex-basis: 100%; }
    .rem__bar { width: 56px; }
    .mkt__role { grid-column: 1 / -1; margin-top: 4px; }
    .mkt__role .chip { white-space: normal; }
  }

  /* Mini-cards: skills in demand + browse by role */
  .minicards { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; padding-top: 16px; }
  .minicard {
    position: relative; background: var(--cream); border: 1px solid var(--hairline);
    border-radius: var(--r-lg); padding: 14px 16px 13px; text-decoration: none; overflow: hidden;
    transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease;
  }
  .minicard::before { content: ''; position: absolute; inset-inline-start: 0; inset-block: 0; width: 4px; background: var(--ac, var(--claret)); }
  a.minicard:hover { transform: translateY(-3px); box-shadow: 0 10px 26px rgba(51,48,46,0.13); border-color: var(--ac, var(--claret)); }
  .minicard .nm { display: flex; align-items: center; gap: 8px; font-family: var(--serif); font-weight: 600; font-size: var(--t-name); color: var(--ink); letter-spacing: -0.008em; }
  .minicard .ct { display: block; margin-top: 2px; font-size: var(--t-note); font-weight: 600; color: var(--ac, var(--claret)); font-variant-numeric: tabular-nums; }
  .minicard .bar { display: block; height: 5px; border-radius: 999px; background: var(--hairline); margin-top: 10px; overflow: hidden; }
  .minicard .bar i { display: block; height: 100%; border-radius: 999px; background: var(--ac, var(--claret)); width: var(--w, 60%); transform: scaleX(0); transform-origin: left; animation: grow 0.9s cubic-bezier(0.22,1,0.36,1) 0.3s forwards; }
  .minicard .arr { position: absolute; inset-inline-end: 14px; top: 14px; font-weight: 500; color: var(--ac, var(--claret)); opacity: 0; transform: translateX(-4px); transition: opacity 160ms cubic-bezier(0.23, 1, 0.32, 1), transform 160ms cubic-bezier(0.23, 1, 0.32, 1); }
  a.minicard:hover .arr { opacity: 1; transform: none; }
  @media (prefers-reduced-motion: reduce) { .minicard .bar i { animation: none; transform: scaleX(1); } }

  /* THE DESK BAND. A contents page, not a card grid. The editions are a list
     of things published on a date, and a dated list under a standing head is
     what a reader of a market section already knows how to read. Cards would
     have made three headlines compete with each other; rows let them be
     scanned in the order they were written. */
  .desk {
    position: relative; overflow: hidden; margin-top: 44px; padding: 26px 30px 22px;
    background: linear-gradient(180deg, #FFFCF8 0%, var(--cream) 100%);
    border: 1px solid var(--hairline); border-radius: var(--r-lg);
    box-shadow: 0 26px 52px -34px rgba(51,48,46,0.38), 0 2px 8px -4px rgba(51,48,46,0.12), inset 0 1px 0 #FFFFFF;
  }
  .desk::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--claret) 0%, var(--claret-deep) 45%, var(--gold) 100%);
  }
  @media (max-width: 700px) { .desk { padding: 20px 18px 18px; } }
  .desk__hd { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
  .desk__h { font-family: var(--serif); font-size: var(--t-section); font-weight: 650; letter-spacing: -0.015em; margin: 0; }
  .desk__all {
    font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
    font-weight: 700; color: var(--claret); text-decoration: none;
    border-bottom: 1px solid rgba(153, 15, 61, 0.35); padding-bottom: 2px;
  }
  .desk__all:hover { border-bottom-color: var(--claret); }
  .desk__lede { margin: 8px 0 0; font-size: var(--t-row); line-height: 1.6; color: var(--muted); max-width: 74ch; }
  .desk__list { list-style: none; margin: 16px 0 0; padding: 0; border-top: 2px solid var(--ink); }
  .desk__it { border-bottom: 1px solid var(--hairline); }
  /* The date column is fixed so the headlines start on one axis; a date that
     wraps would put the whole list out of alignment for one long month. */
  .desk__a {
    display: grid; grid-template-columns: 104px 1fr 18px; align-items: baseline; gap: 14px;
    padding: 13px 4px; text-decoration: none; color: inherit;
  }
  .desk__a:hover { background: var(--cream); }
  .desk__a:focus-visible { outline: 2px solid var(--claret); outline-offset: -2px; }
  .desk__d {
    font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.06em; color: var(--claret);
    font-variant-numeric: tabular-nums; white-space: nowrap;
  }
  .desk__t { font-family: var(--serif); font-size: var(--t-name); line-height: 1.42; font-weight: 550; color: var(--ink); }
  .desk__a:hover .desk__t { color: var(--claret); }
  .desk__go { color: var(--claret); opacity: 0; transform: translateX(-3px); transition: opacity 140ms ease, transform 140ms ease; }
  .desk__a:hover .desk__go, .desk__a:focus-visible .desk__go { opacity: 1; transform: translateX(0); }
  @media (prefers-reduced-motion: reduce) { .desk__go { transition: none; } }
  @media (max-width: 620px) {
    /* Below this the fixed date column starves the headline, so the date
       becomes a standfirst above it rather than a squeezed column beside it. */
    .desk__a { grid-template-columns: 1fr auto; gap: 4px 12px; }
    .desk__d { grid-column: 1 / -1; }
    .desk__t { font-size: var(--t-name); }
  }

  /* CTA band with animated sheen */
  /* The band becomes a two-column composition: the claim on the left, and on
     the right a specimen plate showing what a decomposed score actually looks
     like. The background declaration is deliberately untouched. .sheen and
     .band::before are position: absolute, so neither becomes a grid item. */
  .band {
    margin-top: 46px; background:
      radial-gradient(60% 120% at 90% 0%, rgba(224,172,60,0.22) 0%, transparent 55%),
      linear-gradient(135deg, var(--claret) 0%, var(--claret-deep) 100%);
    color: var(--paper); border-radius: var(--r-lg); padding: 34px 34px 32px;
    position: relative; overflow: hidden;
    border: 1px solid rgba(224,172,60,0.34);
    box-shadow: 0 36px 72px -36px rgba(20,10,6,0.6), 0 14px 30px -18px rgba(20,10,6,0.4);
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
    column-gap: 34px; row-gap: 26px; align-items: center;
  }
  .band__copy { min-width: 0; }
  .band::before { content: ''; position: absolute; inset: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.028'/%3E%3C/svg%3E"); opacity: 0.5; pointer-events: none; }
  .band::after { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; z-index: 2; background: linear-gradient(90deg, transparent 0%, var(--gold) 20%, #F7DE9A 50%, var(--gold) 80%, transparent 100%); }
  .band .sheen {
    position: absolute; top: -40%; bottom: -40%; width: 34%; left: -50%;
    background: linear-gradient(105deg, transparent 0%, rgba(255,241,229,0.16) 50%, transparent 100%);
    transform: skewX(-18deg); animation: sheen 5.5s ease-in-out infinite;
  }
  @keyframes sheen { 0%, 55% { left: -50%; } 85%, 100% { left: 130%; } }
  .band h2 { font-family: var(--serif); font-weight: 600; font-size: var(--t-section); letter-spacing: -0.014em; margin: 0 0 9px; }
  .band h2 .hl { color: var(--gold); }
  .band p { margin: 0 0 4px; font-size: var(--t-row); line-height: 1.6; color: rgba(255,241,229,0.87); max-width: 580px; }
  .band a.audit { color: var(--paper); font-weight: 600; text-underline-offset: 3px; }
  .band .btn {
    display: inline-flex; align-items: center; gap: 8px; margin-top: 18px; background: var(--paper); color: var(--claret);
    text-decoration: none; font-weight: 650; font-size: var(--t-row); padding: 14px 28px; border-radius: 999px;
    box-shadow: 0 3px 14px rgba(0,0,0,0.22); transition: transform 150ms ease, box-shadow 150ms ease;
  }
  .band .btn .arr { transition: transform 150ms ease; }
  .band .btn:hover { transform: translateY(-2px); box-shadow: 0 6px 22px rgba(0,0,0,0.28); }
  .band .btn:hover .arr { transform: translateX(4px); }
  .band .ctarow { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
  .freepill {
    display: inline-flex; align-items: center; gap: 7px; margin-top: 18px;
    border: 1.5px solid var(--gold); color: var(--gold); border-radius: 999px;
    padding: 9px 16px; font-family: var(--mono); font-size: var(--t-note); font-weight: 500; letter-spacing: 0.01em; 
  }
  .freepill .tick { font-size: var(--t-note); }

  /* THE SPECIMEN PLATE. The product's single most differentiating mechanic -
     that a match score is DECOMPOSED rather than a black box - was being
     delivered as six nouns inside a parenthesis in a 14.5px paragraph, with
     the band's whole right half left as empty gradient.
     z-index: 1 lifts the plate above .sheen and the grain pseudo-element (both
     z-index auto), so every ratio here is measured against uncomposited paper
     rather than a ground that moves every 5.5s.
     The plate takes --paper, NOT --cream: the two are eight units apart and on
     one claret ground they read as a printing error beside the paper button.
     The app's six per-dimension hues are deliberately NOT used: --dim-skills
     measures 1.52:1 on claret and --dim-experience 1.77:1, so two of the six
     bars would simply not exist. The band keeps gold, the plate takes claret -
     two surfaces, one accent each. */
  .exhibit {
    position: relative; z-index: 1;
    background: var(--paper); color: var(--ink);
    border-radius: var(--r-lg); padding: 20px 22px 18px;
    box-shadow: 0 24px 48px -28px rgba(0,0,0,0.5), inset 0 1px 0 #FFFFFF;
  }
  .exhibit__hd {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    padding-bottom: 13px; border-bottom: 1px solid var(--hairline);
  }
  .exhibit__t { font-size: var(--t-row); font-weight: 600; letter-spacing: -0.004em; }
  /* Square, not a pill: a printed mark, not a control. */
  .exhibit__stamp {
    flex-shrink: 0; font-family: var(--mono); font-size: var(--t-micro); font-weight: 600;
    letter-spacing: 0.16em; text-transform: uppercase; color: var(--claret);
    border: 1px solid var(--claret); padding: 4px 7px;
  }
  /* ONE grid owns all eighteen cells, so the label column self-sizes and the
     ruling cannot break when a longer dimension name arrives. */
  .exhibit__rows {
    display: grid; grid-template-columns: max-content minmax(0, 1fr) max-content;
    column-gap: 14px; row-gap: 11px; align-items: center; padding-top: 15px;
  }
  .dim__k { font-size: var(--t-note); font-weight: 500; color: var(--muted); }
  .dim__t { height: 6px; border-radius: 999px; background: var(--hairline); overflow: hidden; }
  /* PER-DIMENSION FILLS, in the app's own order and hues, because that colour
     coding IS the product's signature and the founder asked for it here.
     Three ship exactly as the app defines them; three are darkened until they
     clear 3.0:1 against their own track, which is the ground a bar is actually
     read against - not the claret band, and not the paper.
       skills     #C81D5B  4.18  unchanged
       experience #2A6FDB  3.60  unchanged
       style      #B84A39  3.88  unchanged
       location   #0FA0A8 -> #0D8B92  2.39 -> 3.09  (87% of the original)
       salary     #16A34A -> #149142  2.48 -> 3.07  (89%)
       type       #E0922F -> #AC7024  1.90 -> 3.10  (77%, the hardest case:
                  a light amber on a cream track has almost nowhere to go)
     THE NUMERAL IS NOT THE BAR. globals.css states these tokens are bar fills
     only and that score text stays neutral; the get-app card broke that rule
     once and put three of six numbers under 3.3:1. The hue identifies the
     dimension in the bar, where a fill belongs. */
  .dim--skills     { --dim: #C81D5B; }
  .dim--experience { --dim: #2A6FDB; }
  .dim--location   { --dim: #0D8B92; }
  .dim--style      { --dim: #B84A39; }
  .dim--type       { --dim: #AC7024; }
  .dim--salary     { --dim: #149142; }
  .dim__t i { display: block; height: 100%; border-radius: 999px; background: var(--dim, var(--claret)); width: var(--w, 80%); }
  .dim__v { font-family: var(--mono); font-size: var(--t-note); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; text-align: end; }
  .dim__v--nil { font-weight: 500; color: var(--muted); }
  /* (0,2,0), and it has to be. .band p is (0,1,1) and would otherwise repaint
     this footnote at 14.5px in rgba(255,241,229,0.87) = 1.05:1 on the plate,
     justified and hyphenated by the prose rule further up. The one sentence
     that keeps the illustrative figures honest is precisely the one the
     cascade would have deleted. Every colliding property is enumerated. */
  .band .exhibit__foot {
    margin: 15px 0 0; padding-top: 12px; border-top: 1px solid var(--hairline);
    font-size: var(--t-note); line-height: 1.45; color: var(--muted); max-width: none;
    text-align: start; text-align-last: auto; hyphens: manual; -webkit-hyphens: manual;
  }
  @media (max-width: 1040px) { .band { grid-template-columns: 1fr; } }
  @media (max-width: 480px) {
    .band { padding: 24px 20px 22px; }
    .exhibit { padding: 17px 17px 15px; }
  }

  .foot {
    max-width: var(--shell); margin: 28px auto 0; padding: 22px 22px 34px; border-top: 2px solid var(--ink);
    display: flex; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap; align-items: baseline;
    font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted);
  }
  .foot a { text-decoration: none; padding-bottom: 2px; border-bottom: 1px solid transparent; transition: color 150ms var(--ease), border-color 150ms var(--ease); }
  .foot a:hover { border-bottom-color: var(--claret); }
  .foot a { color: var(--muted); text-decoration: none; }
  .foot a:hover { color: var(--claret); }

  /* Hub */
  /* Down a notch from 22px/heavy-rule: eleven of these stack, and at the old
     weight the NAVIGATION shouted over the data. The market band above now owns
     the page's strongest rule; country headers are wayfinding. */
  .country {
    font-family: var(--serif); font-size: var(--t-name); font-weight: 600; letter-spacing: -0.012em;
    color: var(--ink); margin: 0; padding-bottom: 8px; border-bottom: 1px solid var(--hairline);
    display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
    /* The meta clause used to hold its width and squeeze the country name into
       a 33px box, where the two printed on top of each other at 390px. The name
       is the heading; the clause drops to its own line when there is no room. */
    flex-wrap: wrap;
  }
  /* An <img> has no text baseline of its own - under align-items: baseline the
     browser uses its bottom edge, which drops the country name relative to the
     flag. The pairing centres itself instead; the ROW stays baseline-aligned so
     the city count still sits on the name's baseline. */
  .country__id .flag { align-self: center; }
  /* .country is space-between, so EVERY child is spread - including the bare
     text node, which becomes an anonymous flex item. Adding the flag as a
     sibling therefore pinned it to the far left with the country name floating
     in the middle. The flag and the name are one thing; they get one box. */
  .country__id { display: inline-flex; align-items: center; min-width: 0; }
  .country .cnt { font-family: var(--mono); color: var(--faint); font-weight: 500; letter-spacing: 0; font-size: var(--t-note); flex-shrink: 0; }
  /* THE WRAPPER'S MARGIN IS PINNED HERE, and this rule was broken on arrival.
     Inserting it matched the ".country {" SUBSTRING of "a.country {" and left
     the "a" orphaned in front of the comment, so the file shipped "a .ctry"
     (a descendant selector that can never match, since the anchor is INSIDE the
     h3) and silently demoted "a.country" to ".country". The headings therefore
     kept the user-agent h3 margin - 18.72px top and bottom - which is most of
     why 26 country groups cost 2,116px of chrome to present 41 rows.
     Anchor a CSS insertion on a whole rule, never on a selector fragment. */
  /* A HEADING'S META SUMMARISES WHAT IS BELOW IT, and with one row below there
     is nothing to summarise. Measured on the live hub: 17 of the 26 country
     groups hold exactly one city, and in ALL SEVENTEEN the meta said nothing
     the row did not already show - 15 read "1 city . hiring for Software
     Engineer" directly above a row whose own column said "Software Engineer",
     and the other two (Morocco, Tunisia) read "1 city" above a single visible
     row. So the meta is dropped for solo countries and the heading keeps what
     only it carries: the flag, the country name, and the link to the country
     page. Multi-city groups are untouched, where "3 cities . hiring for X" is
     a real summary of rows the reader has not read yet. */
  /* The country heading had NO size of its own and had been riding the
     browser default for h3 (1.17em) since it shipped - 36 headings whose
     size was an accident. It is a named thing, so it takes the name token. */
  .ctry { margin: 22px 0 0; font-size: var(--t-name); }
  .region .ctry { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hairline); }
  .region .ctry + .mkt .mkt__row:first-child { border-top: 0; }
  /* The country name is a link to its own market page, not inert text. */
  a.country { text-decoration: none; transition: color 150ms var(--ease); }
  a.country .go { color: var(--claret); font-family: var(--sans); font-size: var(--t-row); opacity: 0; transform: translateX(-4px); transition: opacity 160ms var(--ease), transform 160ms var(--ease); }
  @media (hover: hover) and (pointer: fine) { a.country:hover { color: var(--claret); } a.country:hover .go { opacity: 1; transform: none; } }
  a.country:focus-visible { outline: 2px solid var(--claret); outline-offset: 3px; }
  /* On a phone the only route to a country is an 11px mono line on a solo row
     or a heading a shade over 26px: both under the 44px floor. The BOX grows to
     the floor; the type does not. */
  @media (max-width: 560px) {
    .mkt__ctry { min-height: 44px; margin-top: 0; }
    a.country { min-height: 44px; align-items: center; }
  }

  /* Motion. These pages are server-rendered HTML strings with ZERO client JS
     (no React, no bundler — so no Motion/framer here by construction). Modern
     CSS covers it natively and costs nothing at runtime:
       - hero blocks: a short staggered rise on load
       - listing rows: SCROLL-DRIVEN reveal (animation-timeline: view()), the
         native equivalent of an in-view trigger. Fixed nth-child delays were
         wrong for a 30-row list — rows 8+ animated below the fold, unseen.
     Fallback: browsers without scroll-timeline keep the plain time-based rise,
     so content is ALWAYS visible either way (never gate content on animation). */
  @media (prefers-reduced-motion: no-preference) {
    .rise { animation: rise 0.55s var(--ease) both; }
    .rise-1 { animation-delay: 0.04s; } .rise-2 { animation-delay: 0.11s; } .rise-3 { animation-delay: 0.18s; }
    .listing .row { animation: rise 0.5s var(--ease) both; }
    .listing .row:nth-child(2) { animation-delay: 0.05s; } .listing .row:nth-child(3) { animation-delay: 0.09s; }
    .listing .row:nth-child(4) { animation-delay: 0.13s; } .listing .row:nth-child(5) { animation-delay: 0.17s; }
    .listing .row:nth-child(n+6) { animation-delay: 0.2s; }
    @keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

    @supports (animation-timeline: view()) {
      .listing .row {
        animation: row-in linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 45%;
        animation-delay: 0s;
      }
      @keyframes row-in {
        from { opacity: 0; transform: translateY(16px) scale(0.985); }
        to { opacity: 1; transform: none; }
      }
    }
  }

  /* Native cross-document page transitions (city -> role -> hub). Chrome/Edge
     honor it, everyone else ignores it. No JS, no library. */
  @view-transition { navigation: auto; }
  @media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
  }
  @media (prefers-reduced-motion: reduce) {
    .stat::after { animation: none; transform: scaleX(1); }
    .live__dot { animation: none; }
    .band .sheen { display: none; }
  }

  @media (max-width: 600px) {
    a.row { padding: 15px 15px 12px; }
    .jtop { flex-wrap: wrap; }
    .med { width: 44px; height: 44px; font-size: var(--t-name); }
    /* Salary drops to its own line under the title block, start-aligned. */
    .sal { flex-basis: 100%; text-align: start; padding-inline-start: 58px; font-size: var(--t-figure); margin-top: -2px; }
    .row .co { white-space: normal; }
    .statwrap { margin-top: -18px; }
  }
