/* easyworkclub — design system v3. The reskin.
 *
 * SOURCE OF TRUTH IS `design/handoff/`. The shared block below is the common
 * prefix of the <style> element in home.html, city.html and job.html, copied
 * line for line. The three page blocks after it are those files' own remainders,
 * with EVERY SELECTOR QUALIFIED by a body class and every declaration left
 * byte-identical — verified mechanically, not by eye.
 *
 * WHY THE PAGE BLOCKS HAD TO BE SCOPED. The reference pages are standalone, so
 * nothing stopped them defining `.search` twice: the home hero's field is
 * 16px/13px and the city hero's is 15px/11px, which components.md records as
 * deliberate. Served from one shell they would overwrite each other, so the
 * page class decides. Nothing else about them changed.
 *
 * `ewc.css` IS STILL LIVE AND STILL LOADED, on every template this reskin has
 * not reached — sixteen of them. The two stylesheets share twenty class names,
 * `.wrap`, `.btn`, `.card`, `.job-card`, `.panel`, `.site-header` among them, so
 * they must never meet in one document. `base.html` picks a shell and a
 * stylesheet from `design_v3`; see the migration list there.
 */

/* ------------------------------------------------------------------ font -- */

/* The handoff loads Inter from fonts.googleapis.com. We cannot: the CSP is
   `default-src 'none'` and "no third-party request" is the one rule the v2
   brief explicitly left standing. This is the same variable Inter we already
   self-host, declared under the family name `tokens.css` asks for. One file,
   Latin-1 subset, so German umlauts and Italian accents need no second
   request; `swap` so text is readable before it lands. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/inter-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

/* --------------------------------------------------- shared, all three -- */

* { box-sizing: border-box; }
    body { margin: 0; background: var(--c-cream); color: var(--c-ink); font-family: var(--font-sans); font-feature-settings: 'cv05' 1, 'ss03' 1; text-wrap: pretty; }
    a { color: var(--c-ink); text-decoration: none; }
    a:hover { color: var(--c-terracotta); }
    :focus-visible { outline: var(--bw-2) solid var(--c-terracotta); outline-offset: var(--bw-2); }
    .wrap { max-width: var(--page-max); margin: 0 auto; padding-left: var(--page-gutter); padding-right: var(--page-gutter); }
    /* header */
    .site-header { background: var(--c-white); border-bottom: var(--bw-1) solid var(--c-border); }
    .site-header .wrap { display: flex; align-items: center; gap: var(--sp-24); padding-top: var(--sp-14); padding-bottom: var(--sp-14); }
    .brand { display: inline-flex; align-items: center; gap: var(--sp-10); }
    .brand img { display: block; }
    .brand-word { font-weight: var(--fw-bold); font-size: var(--fs-19); letter-spacing: var(--ls-brand); }
    .accent { color: var(--c-terracotta); }
    .locale { display: flex; gap: var(--sp-4); margin-left: auto; background: var(--c-surface-tint); border-radius: var(--r-pill); padding: var(--sp-3); }
    .locale a { font-size: var(--fs-13); font-weight: var(--fw-medium); padding: var(--sp-4) var(--sp-12); border-radius: var(--r-pill); color: var(--c-text-mute); }
    .locale a[aria-current="true"] { font-weight: var(--fw-semibold); background: var(--c-ink); color: var(--c-cream); }
    /* buttons + inputs */
    .btn { font: inherit; cursor: pointer; border: 0; display: inline-flex; align-items: center; gap: var(--sp-10); font-weight: var(--fw-semibold); background: var(--c-ink); color: var(--c-cream); border-radius: var(--r-sm); }
    .btn:hover { background: var(--c-black); color: var(--c-cream); }
    .btn-sm { font-size: var(--fs-14); padding: var(--sp-9) var(--sp-18); }
    .btn-md { font-size: var(--fs-14); padding: var(--sp-10) var(--sp-16); }
    .btn-lg { font-size: var(--fs-16); padding: var(--sp-13) var(--sp-26); }
    .input { font: inherit; border: var(--bw-1) solid var(--c-border); border-radius: var(--r-sm); background: var(--c-white); color: var(--c-ink); }
    /* section label */
    .section-label { font-size: var(--fs-13); font-weight: var(--fw-semibold); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--c-text-mute); margin: 0; }
    .section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-16); flex-wrap: wrap; }
    .see-all { font-size: var(--fs-14); font-weight: var(--fw-medium); color: var(--c-terracotta); }
    /* cards */
    .card { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-16) var(--sp-18); }
    a.card:hover, a.job-card:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
    .job-card { display: grid; grid-template-columns: var(--avatar) minmax(0, 1fr); gap: var(--sp-14); background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-16) var(--sp-18); }
    .mono { width: var(--avatar); height: var(--avatar); border-radius: var(--r-sm); display: flex; align-items: center; justify-content: center; color: var(--c-white); font-weight: var(--fw-bold); font-size: var(--fs-15); flex: none; }
    .job-title { display: block; font-size: var(--fs-17); font-weight: var(--fw-bold); line-height: var(--lh-title); overflow-wrap: anywhere; }
    .job-meta { display: block; font-size: var(--fs-14); color: var(--c-text-mute); margin-top: var(--sp-3); font-variant-numeric: tabular-nums; }
    .job-main { min-width: 0; }
    /* chips */
    .chips { display: flex; gap: var(--sp-6); flex-wrap: wrap; margin-top: var(--sp-10); }
    .chip { white-space: nowrap; font-size: var(--fs-12); font-weight: var(--fw-medium); padding: var(--sp-2) var(--sp-10); border-radius: var(--r-pill); }
    .chip-new { background: var(--c-pos-bg); color: var(--c-pos); }
    .chip-salary { background: var(--c-salary-bg); color: var(--c-salary); font-variant-numeric: tabular-nums; }
    .chip-type { background: var(--c-chip-neutral-bg); color: var(--c-chip-neutral-text); }
    /* employer group rows */
    .rows { display: flex; flex-direction: column; margin-top: var(--sp-12); border-top: var(--bw-1) solid var(--c-border-soft); }
    .row-link { display: flex; justify-content: space-between; gap: var(--sp-16); padding: var(--sp-10) 0; border-bottom: var(--bw-1) solid var(--c-border-soft); font-size: var(--fs-15); font-weight: var(--fw-medium); }
    .row-link:last-child { border-bottom: 0; }
    .row-link:hover { color: var(--c-terracotta); }
    .row-sub { color: var(--c-text-mute); font-variant-numeric: tabular-nums; font-weight: var(--fw-regular); white-space: nowrap; }
    /* salary band */
    .band { display: block; position: relative; height: var(--dot); border-radius: var(--r-pill); background: var(--c-band-track); margin-top: var(--sp-12); }
    .band-fill { position: absolute; top: 0; bottom: 0; background: var(--c-band-fill); border-radius: var(--r-pill); }
    .band-median { position: absolute; top: calc(-1 * var(--sp-3)); bottom: calc(-1 * var(--sp-3)); width: var(--sp-3); background: var(--c-terracotta); border-radius: var(--r-2); box-shadow: var(--shadow-marker); }
    /* signup box */
    .alert-box { background: var(--c-accent-weak); border-radius: var(--r-md); padding: var(--sp-22); }
    .alert-box h2 { font-size: var(--fs-17); font-weight: var(--fw-bold); margin: 0; }
    .alert-box p { font-size: var(--fs-14); line-height: var(--lh-body); color: var(--c-text-soft); margin: var(--sp-8) 0 0; }
    .alert-form { display: flex; gap: var(--sp-8); margin-top: var(--sp-14); }
    .alert-form .input { flex: 1; min-width: 0; font-size: var(--fs-14); padding: var(--sp-10) var(--sp-14); border-color: var(--c-border-accent); }
    /* status dot */
    .dot { width: var(--dot); height: var(--dot); border-radius: var(--r-pill); display: inline-block; flex: none; }
    /* two-column body */
    .two-col { display: grid; grid-template-columns: minmax(0, 7.5fr) minmax(0, 4.5fr); gap: 0 var(--col-gap); }
    @media (max-width: 880px) { .two-col { grid-template-columns: 1fr; } .two-col > aside { margin-top: var(--sp-32); } }
    /* breadcrumb */
    .breadcrumb { font-size: var(--fs-13); color: var(--c-text-mute); display: flex; gap: var(--sp-8); align-items: center; flex-wrap: wrap; }
    .breadcrumb a { color: inherit; }
    /* footer */
    .site-footer { background: var(--c-white); border-top: var(--bw-1) solid var(--c-border); }
    .site-footer .wrap { padding-top: var(--sp-28); padding-bottom: var(--sp-28); display: flex; justify-content: space-between; gap: var(--sp-16) var(--sp-32); flex-wrap: wrap; font-size: var(--fs-13); color: var(--c-text-mute); }
    .footer-links { display: flex; gap: var(--sp-20); flex-wrap: wrap; }
    .footer-links a { color: inherit; }
    .stack { display: flex; flex-direction: column; gap: var(--sp-12); }
    .num { font-variant-numeric: tabular-nums; }


/* ============ promoted to the base by handoff-batch1 ====================
 * These were page-scoped in v3 -- `.panel` and `.facts` under `body.page-job`,
 * `.promo` under `body.page-city` -- because only those pages used them. The
 * batch-1 reference puts all three in the shared block, and the salary page
 * needs every one: its figure panel, its basis card and its calculator link.
 *
 * Ported flat rather than by moving the old rules, so the page-scoped copies
 * below still win on their own pages and nothing about the job or city page
 * changes. Declarations are the reference's, byte for byte.
 * ====================================================================== */
.panel { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--pad-panel); }
.facts { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-6) var(--sp-18); }
.facts-row { display: flex; justify-content: space-between; gap: var(--sp-14); padding: var(--sp-12) 0; border-bottom: var(--bw-1) solid var(--c-border-soft); font-size: var(--fs-14); }
.facts-row:last-child { border-bottom: 0; }
.facts-row .k { color: var(--c-text-mute); }
.facts-row .v { font-weight: var(--fw-semibold); text-align: right; }
.promo { display: block; background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-18); }
.promo:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
.promo .line { display: block; font-size: var(--fs-15); font-weight: var(--fw-medium); margin-top: var(--sp-8); overflow-wrap: anywhere; }
.alert-form { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-14); }
.alert-form .input { flex: 1 1 100%; min-width: 0; font-size: var(--fs-14); padding: var(--sp-10) var(--sp-14); border-color: var(--c-border-accent); }
.alert-form .btn { flex: 0 0 auto; margin-left: auto; }


/* ----------------------------------------------------------- home page -- */

    body.page-home .hero { padding: var(--sp-44) 0 var(--sp-36); border-bottom: var(--bw-1) solid var(--c-border); }
    body.page-home .hero-kicker { font-size: var(--fs-14); font-weight: var(--fw-medium); color: var(--c-text-mute); margin: 0; font-variant-numeric: tabular-nums; }
    body.page-home .hero h1 { font-size: var(--fs-h1-home); font-weight: var(--fw-display); letter-spacing: var(--ls-tight); line-height: var(--lh-tight); margin: var(--sp-14) 0 0; text-wrap: balance; max-width: 24ch; }
    body.page-home .hero h1 .sub { color: var(--c-text-mute); font-weight: var(--fw-medium); }
    body.page-home .hero-facts { display: flex; gap: var(--sp-20) var(--sp-32); flex-wrap: wrap; margin: var(--sp-20) 0 0; font-size: var(--fs-14); color: var(--c-text-soft); }
    body.page-home .hero-facts span { display: inline-flex; align-items: center; gap: var(--sp-8); }
    body.page-home .hero-facts strong { font-variant-numeric: tabular-nums; font-weight: var(--fw-bold); }
    body.page-home .search { display: flex; gap: var(--sp-10); flex-wrap: wrap; margin: var(--sp-28) 0 0; max-width: 780px; }
    body.page-home .search .input { font-size: var(--fs-16); padding: var(--sp-13) var(--sp-16); }
    body.page-home .search .q { flex: 2 1 240px; } .search .city { flex: 1 1 150px; }
    body.page-home .search .btn { font-size: var(--fs-16); padding: var(--sp-13) var(--sp-28); }
    body.page-home .home-body { padding: var(--sp-36) 0 var(--sp-48); }
    body.page-home .salary-card .top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-12); }
    body.page-home .salary-card .role { font-size: var(--fs-15); font-weight: var(--fw-bold); }
    body.page-home .salary-card .median { font-size: var(--fs-17); font-weight: var(--fw-heavy); font-variant-numeric: tabular-nums; }
    body.page-home .salary-card .basis { display: block; font-size: var(--fs-13); color: var(--c-text-mute); margin-top: var(--sp-10); font-variant-numeric: tabular-nums; }
    body.page-home .salary-note { font-size: var(--fs-13); line-height: var(--lh-body); color: var(--c-text-mute); margin: var(--sp-12) 0 0; }
    body.page-home .salary-note a { color: var(--c-terracotta); }
    body.page-home .cities { border-top: var(--bw-1) solid var(--c-border); padding: var(--sp-36) 0 var(--sp-56); }
    body.page-home .city-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-12); margin-top: var(--sp-16); }
    @media (max-width: 880px) { body.page-home .city-grid { grid-template-columns: repeat(2, 1fr); } }
    body.page-home .city-card { display: block; background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-sm); padding: var(--sp-14) var(--sp-16); }
    body.page-home .city-card:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
    body.page-home .city-card .top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-10); }
    body.page-home .city-card .name { font-size: var(--fs-15); font-weight: var(--fw-bold); overflow-wrap: anywhere; }
    body.page-home .city-card .count { font-size: var(--fs-14); color: var(--c-text-mute); font-variant-numeric: tabular-nums; }
    body.page-home .share { display: block; height: var(--sp-4); border-radius: var(--r-pill); background: var(--c-border-soft); margin-top: var(--sp-10); }
    body.page-home .share > span { display: block; height: var(--sp-4); border-radius: var(--r-pill); background: var(--c-band-fill); }

/* ----------------------------------------------------------- city listing -- */

    body.page-city .city-hero { padding: var(--sp-28) 0 var(--sp-24); border-bottom: var(--bw-1) solid var(--c-border); }
    body.page-city .city-hero .title-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-16) var(--sp-32); flex-wrap: wrap; margin-top: var(--sp-12); }
    body.page-city .city-hero h1 { font-size: var(--fs-h1-city); font-weight: var(--fw-display); letter-spacing: var(--ls-tight); margin: 0; }
    body.page-city .city-hero h1 .count { font-weight: var(--fw-medium); color: var(--c-text-mute); font-variant-numeric: tabular-nums; }
    body.page-city .updated { font-size: var(--fs-14); color: var(--c-text-soft); display: inline-flex; align-items: center; gap: var(--sp-8); }
    body.page-city .search { display: flex; gap: var(--sp-10); flex-wrap: wrap; margin: var(--sp-20) 0 0; max-width: 720px; }
    body.page-city .search .input { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-14); }
    body.page-city .search .q { flex: 2 1 220px; } .search .city { flex: 1 1 130px; }
    body.page-city .search .btn { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-24); }
    body.page-city .filters { display: flex; gap: var(--sp-8); flex-wrap: wrap; margin-top: var(--sp-16); }
    body.page-city .filter { font-size: var(--fs-13); font-weight: var(--fw-medium); padding: var(--sp-6) var(--sp-14); border-radius: var(--r-pill); background: var(--c-white); color: var(--c-text-soft); border: var(--bw-1) solid var(--c-border); }
    body.page-city .filter[aria-current="true"] { font-weight: var(--fw-semibold); background: var(--c-accent-weak); color: var(--c-accent-deep); border-color: var(--c-border-accent); }
    body.page-city .city-body { padding: var(--sp-28) 0 var(--sp-56); }
    body.page-city .group-label { margin: 0 0 var(--sp-14); }
    body.page-city .group-label + .stack { }
    body.page-city .later { margin-top: var(--sp-28); }
    body.page-city .pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16); margin-top: var(--sp-24); }
    body.page-city .pagination .info { font-size: var(--fs-14); color: var(--c-text-mute); font-variant-numeric: tabular-nums; }
    body.page-city .page-btn { font-size: var(--fs-14); font-weight: var(--fw-semibold); background: var(--c-white); border: var(--bw-1) solid var(--c-border); padding: var(--sp-9) var(--sp-18); border-radius: var(--r-sm); }
    body.page-city .page-btn:hover { border-color: var(--c-border-accent); color: var(--c-terracotta); }
    body.page-city .occ-list { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-6) var(--sp-18); }
    body.page-city .occ-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-14); padding: var(--sp-11) 0; border-bottom: var(--bw-1) solid var(--c-border-soft); font-size: var(--fs-15); font-weight: var(--fw-medium); }
    body.page-city .occ-row:hover { color: var(--c-terracotta); }
    body.page-city .occ-row .n { color: var(--c-text-mute); font-variant-numeric: tabular-nums; font-weight: var(--fw-regular); }
    body.page-city .occ-all { display: block; padding: var(--sp-12) 0; font-size: var(--fs-14); font-weight: var(--fw-medium); color: var(--c-terracotta); }
    body.page-city .promo { display: block; background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-18); margin-top: var(--sp-24); }
    body.page-city .promo:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
    body.page-city .promo .line { display: block; font-size: var(--fs-15); font-weight: var(--fw-medium); margin-top: var(--sp-8); }

/* ----------------------------------------------------------- job detail -- */

    body.page-job .crumb-bar { padding: var(--sp-20) 0 0; }
    body.page-job .job-body { padding: var(--sp-20) 0 var(--sp-56); }
    body.page-job .panel { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--pad-panel); }
    body.page-job .job-head { display: flex; gap: var(--sp-16); align-items: flex-start; }
    body.page-job .mono-lg { width: var(--avatar-lg); height: var(--avatar-lg); border-radius: var(--r-sm); display: flex; align-items: center; justify-content: center; color: var(--c-white); font-weight: var(--fw-bold); font-size: var(--fs-17); flex: none; }
    body.page-job .job-head h1 { font-size: var(--fs-h1-job); font-weight: var(--fw-bold); letter-spacing: var(--ls-snug); line-height: var(--lh-heading); margin: 0; overflow-wrap: anywhere; text-wrap: balance; }
    body.page-job .job-head .sub { font-size: var(--fs-15); color: var(--c-text-soft); margin: var(--sp-6) 0 0; font-variant-numeric: tabular-nums; }
    body.page-job .job-head-chips { margin-top: var(--sp-16); }
    body.page-job .job-head-chips .chip { padding: var(--sp-3) var(--sp-10); }
    body.page-job .apply-row { display: flex; gap: var(--sp-12); align-items: center; flex-wrap: wrap; margin-top: var(--sp-20); padding-top: var(--sp-20); border-top: var(--bw-1) solid var(--c-border-soft); }
    body.page-job .apply-note { font-size: var(--fs-13); color: var(--c-text-mute); font-variant-numeric: tabular-nums; }
    body.page-job .description { margin-top: var(--sp-16); font-size: var(--fs-16); line-height: var(--lh-copy); color: var(--c-ink); }
    body.page-job .description h2 { font-size: var(--fs-18); font-weight: var(--fw-bold); margin: var(--sp-24) 0 0; }
    body.page-job .description h2:first-child { margin-top: 0; }
    body.page-job .description p { margin: var(--sp-10) 0 0; color: var(--c-text-soft); }
    body.page-job .description ul { margin: var(--sp-10) 0 0; padding-left: var(--sp-22); color: var(--c-text-soft); }
    body.page-job .description li { margin-top: var(--sp-6); }
    body.page-job .description .apply-row { margin-top: var(--sp-28); }
    body.page-job .similar { margin-top: var(--sp-28); }
    body.page-job .similar-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-12); }
    @media (max-width: 880px) { body.page-job .similar-grid { grid-template-columns: 1fr; } }
    body.page-job .similar-card { display: block; background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-14) var(--sp-16); }
    body.page-job .similar-card:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
    body.page-job .similar-card .t { display: block; font-size: var(--fs-15); font-weight: var(--fw-bold); line-height: var(--lh-title); overflow-wrap: anywhere; }
    body.page-job .similar-card .m { display: block; font-size: var(--fs-13); color: var(--c-text-mute); margin-top: var(--sp-4); font-variant-numeric: tabular-nums; }
    body.page-job .similar-card .chip { display: inline-block; margin-top: var(--sp-8); }
    body.page-job .facts { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-6) var(--sp-18); }
    body.page-job .facts-row { display: flex; justify-content: space-between; gap: var(--sp-14); padding: var(--sp-12) 0; border-bottom: var(--bw-1) solid var(--c-border-soft); font-size: var(--fs-14); }
    body.page-job .facts-row:last-child { border-bottom: 0; }
    body.page-job .facts-row .k { color: var(--c-text-mute); }
    body.page-job .facts-row .v { font-weight: var(--fw-semibold); }
    body.page-job .salary-check { display: block; background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-18); margin-top: var(--sp-16); }
    body.page-job .salary-check:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
    body.page-job .salary-check .top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-12); margin-top: var(--sp-10); }
    body.page-job .salary-check .role { font-size: var(--fs-15); font-weight: var(--fw-medium); }
    body.page-job .salary-check .median { font-size: var(--fs-17); font-weight: var(--fw-heavy); font-variant-numeric: tabular-nums; }
    body.page-job .salary-check .basis { display: block; font-size: var(--fs-13); color: var(--c-text-mute); margin-top: var(--sp-10); }

/* The legal bar. `handoff-batch1` gives it a class of its own rather than
   leaning on `.site-footer .wrap`, which the mesh also is -- two things
   sharing a selector and separated only by source order was fragile. */
.site-footer .footer-legal {
  padding-top: var(--sp-28); padding-bottom: var(--sp-28);
  display: flex; justify-content: space-between; gap: var(--sp-16) var(--sp-32);
  flex-wrap: wrap; font-size: var(--fs-13); color: var(--c-text-mute);
}

/* ------------------------------------------------------------ footer mesh -- */

/* The link mesh, above the designer's legal bar and in the same language.
   Approved by Mirko 2026-09-02: the handoff's six footer links all point at
   `#`, so they are placeholders rather than an information architecture, and
   the mesh is the only permanent crawl path to ~1,200 landing pages — a job
   page, which is where their other inbound links come from, lives about 24
   hours. The brief was "reduce visual weight, never the link set", so this is
   13px muted ink and nothing else: no borders, no cards, no second accent.

   `.footer-mesh` is also a `.wrap`, and the shared block makes `.wrap` inside
   `.site-footer` a space-between flex row. Same specificity, so these win on
   source order alone — which is why they live at the end of this file. */
.site-footer .footer-mesh {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: var(--sp-24) var(--sp-32);
  padding-top: var(--sp-32);
  padding-bottom: var(--sp-24);
  border-bottom: var(--bw-1) solid var(--c-border-soft);
  flex-wrap: nowrap;
}
.footer-mesh ul { list-style: none; margin: var(--sp-12) 0 0; padding: 0; }
.footer-mesh li { margin-top: var(--sp-6); }
.footer-mesh a { font-size: var(--fs-13); color: var(--c-text-mute); }
.footer-mesh a:hover { color: var(--c-terracotta); }

/* `auto-fit` already stacks these, so the 880px rule only tightens the gap —
   four columns of eight links become one long column on a phone, and 24px
   between them is a lot of scrolling. */
@media (max-width: 880px) {
  .site-footer .footer-mesh { gap: var(--sp-20) var(--sp-24); }
}

/* ------------------------------------------------- carried over from v2 -- */

/* The reference pages are mockups: they have no skip link, no visually-hidden
   label and no form the keyboard has to reach, so the handoff simply does not
   cover this furniture. These three rules come across from `ewc.css`
   unchanged except for token substitution — inventing a different treatment
   for them would be restyling something the designer never drew. */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: var(--sp-8);
  background: var(--c-white); padding: var(--sp-8) var(--sp-16);
  border-radius: var(--r-sm); border: var(--bw-1) solid var(--c-border);
  font-size: var(--fs-14); font-weight: var(--fw-medium);
}
.skip-link:focus { left: var(--sp-16); z-index: 50; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* A card for an employer we will not name. `cards.monogram` returns None for a
   placeholder — "Anonymous", "Confidential" and the rest some feeds send — and
   a monogram for those identifies nothing, so v2 dropped the avatar column
   entirely rather than print two letters of a lie. The design draws only the
   variant WITH a mark, so this closes the gap the same way v2 did: the column
   goes, the card keeps its shape. */
.job-card-plain { grid-template-columns: minmax(0, 1fr); }

/* --------------------------------------------------------- layout gaps -- */

/* The reference pages set five margins inline — `style="margin-top:
   var(--sp-16)"` on a stack, `var(--sp-28)` on the home signup box,
   `var(--sp-24)` on the city one, and so on. The brief allows inline styles
   ONLY for the three data-driven values (monogram tone, band percentages,
   share width), so these come out to here at exactly the values the designer
   used. Nothing is re-spaced; the numbers are transcribed. */
body.page-home .home-list,
body.page-home aside .stack { margin-top: var(--sp-16); }
body.page-home aside .alert-box { margin-top: var(--sp-28); }
body.page-city aside .alert-box { margin-top: var(--sp-24); }
body.page-job aside .alert-box { margin-top: var(--sp-16); }
body.page-job .similar .section-label { display: block; margin-bottom: var(--sp-14); }

/* -------------------------------------------- job page, beyond the handoff -- */

/* The reference page sets `style="min-width: 0"` on the head's text column —
   a grid/flex child will not shrink below its content without it, and a long
   German job title would push the panel past its own border. Out to here for
   the same reason as the margins: inline styles are for data only. */
body.page-job .job-head-text { min-width: 0; }

/* The report link. Not in the handoff; kept because it is the only route a
   reader has to tell us a listing is wrong (Mirko, 2026-09-02). Deliberately
   quiet — it sits under the description, muted, at the size of the apply note
   beside it, and it is rendered only when the market's contact address is
   real rather than a legal placeholder. */
body.page-job .report-line { margin: var(--sp-20) 0 0; font-size: var(--fs-13); }
body.page-job .report-line a { color: var(--c-text-mute); }
body.page-job .report-line a:hover { color: var(--c-terracotta); }

/* THE STICKY APPLY BAR, PHONE ONLY. Also not in the handoff, and kept for the
   opposite reason to the report link: this is the control the whole business
   bills through, and on a phone the button at the top of the page is several
   screens away by the time anyone has finished reading. Restyled in v3 rather
   than carried over — the v2 bar used its own shadow token, and v3 has exactly
   one shadow (the band marker's halo), so separation here is the same 1px
   border every other surface uses.

   880px is the system's own breakpoint, not v2's 1024: above it the layout is
   two columns and the panel's CTA is still on screen.

   `env(safe-area-inset-bottom)` keeps the button clear of the home indicator
   on a notched phone. */
.apply-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; align-items: center; gap: var(--sp-12);
  background: var(--c-white);
  border-top: var(--bw-1) solid var(--c-border);
  padding: var(--sp-10) var(--page-gutter)
           calc(var(--sp-10) + env(safe-area-inset-bottom));
}
.apply-bar .apply-bar-job {
  display: flex; flex-direction: column; min-width: 0;
  line-height: var(--lh-title);
}
.apply-bar .company {
  font-size: var(--fs-14); font-weight: var(--fw-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.apply-bar .where { font-size: var(--fs-13); color: var(--c-text-mute); }
.apply-bar .btn { margin-left: auto; flex: none; }
@media (min-width: 881px) { .apply-bar { display: none; } }

/* Room for it, so the bar never covers the end of the advert. */
@media (max-width: 880px) {
  body.page-job { padding-bottom: var(--sp-56); }
}

/* ------------------------------------------------------- header on a phone -- */

/* THE HANDOFF HAS NO MOBILE HEADER, and at 390px its desktop one does not fit:
   brand + locale pill + alerts button + two 24px gaps come to about 418px
   inside a 358px content box, so every page in the reskin scrolled sideways.
   Measured on 2026-09-02 at 390px — home, city and job in all three markets,
   `scrollWidth` 439-465 against a 390 viewport, first offender `a.btn` every
   time. German is worst because "Jobalarm" is wider than "Job alerts".

   This is the same gap as the missing mobile job page: the designer worked at
   desktop widths. Treated like the undesigned empty states — solved here, in
   the system's own tokens, and flagged rather than quietly invented.

   Wrap rather than shrink: dropping the button to its own row keeps the tap
   target at full size, which a smaller button would not. `margin-left: auto`
   on the locale still pushes it to the right of the first row. */
@media (max-width: 880px) {
  .site-header .wrap { flex-wrap: wrap; gap: var(--sp-12); }
  .site-header .btn { margin-left: auto; }
}

/* --------------------------------------------- the one-column min floor -- */

/* THE 880px COLLAPSE SETS `grid-template-columns: 1fr`, and a bare `1fr` keeps
   a min-content floor: the column refuses to be narrower than its widest
   unbreakable content, so the PAGE scrolls sideways instead. The desktop rule
   two lines above it already guards against this — `minmax(0, 7.5fr)` — so
   this is the designer's own idiom applied to the case they did not test.

   Measured at 390px before: German home, city and job at scrollWidth 453
   against a 390 viewport; Italian 402; British 382 at 320px. The offender is
   `.section-head`, a `space-between` flex row holding a long heading and a
   "see all" link — "Neueste Stellenangebote" beside "Alle Städte" simply does
   not fit, and with no wrap and no floor it pushed the whole document wide.
   English never showed it, which is exactly why it survived the handoff.

   Written as an override at the end rather than edited into the shared block,
   so `design/handoff/` stays the source of truth and this stays greppable. */
@media (max-width: 880px) {
  .two-col { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================================
   SHARED COMPONENTS THE HANDOFF DID NOT DRAW
   ----------------------------------------------------------------------------
   The three reference pages cover a home, a listing and a job. The other
   sixteen templates need a page heading, a prose column and a few small lists,
   and none of those exist in `design/handoff/`.

   COMPOSED FROM TOKENS, IN THE DESIGN'S OWN IDIOM, and where the design
   already solves the same problem the VALUES ARE COPIED rather than re-chosen:
   `.prose` is `body.page-job .description` unscoped, `.page-hero` is
   `body.page-city .city-hero` unscoped. Nothing here introduces a size, a
   colour or a rhythm the handoff did not already use.
   ========================================================================== */

/* A page heading block, for every template that is not one of the three. Same
   shape as the city hero: breadcrumb, title, rule underneath. */
.page-hero { padding: var(--sp-28) 0 var(--sp-24); border-bottom: var(--bw-1) solid var(--c-border); }
/* `overflow-wrap` HERE IS THE SYSTEMIC FIX, and it belongs in the base rather
   than on one page. ESCO's German labels are slashed compounds with no break
   opportunity -- `Einkaufsdisponent/Einkaufsdisponentin` is one 37-character
   word to a line-breaker -- and any heading that can receive one is pushed
   past the viewport without it. We shipped it page-scoped on
   `body.page-occupation` after batch 2 and reported it; batch 3's reference
   puts it in the shared base, which is where it should have gone. The other
   selectors components.md names get it too. */
.page-hero h1 { font-size: var(--fs-h1-city); font-weight: var(--fw-display);
                letter-spacing: var(--ls-tight); margin: var(--sp-12) 0 0;
                text-wrap: balance; overflow-wrap: anywhere; }
.page-hero .lede { font-size: var(--fs-16); line-height: var(--lh-body);
                   color: var(--c-text-soft); margin: var(--sp-10) 0 0; max-width: 68ch; }
.page-body { padding: var(--sp-28) 0 var(--sp-56); }

/* Long-form copy: legal pages, an insights post. Same values as the job
   page's `.description`, which is the design's own prose treatment. */
.prose { font-size: var(--fs-16); line-height: var(--lh-copy); color: var(--c-ink); max-width: 68ch; }
.prose h2 { font-size: var(--fs-18); font-weight: var(--fw-bold); margin: var(--sp-24) 0 0;
            overflow-wrap: anywhere; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: var(--fs-16); font-weight: var(--fw-bold); margin: var(--sp-20) 0 0; }
.prose p { margin: var(--sp-10) 0 0; color: var(--c-text-soft); }
.prose ul, .prose ol { margin: var(--sp-10) 0 0; padding-left: var(--sp-22); color: var(--c-text-soft); }
.prose li { margin-top: var(--sp-6); }
.prose a { color: var(--c-terracotta); }
.prose table { border-collapse: collapse; margin: var(--sp-16) 0 0; font-size: var(--fs-14); width: 100%; }
.prose th, .prose td { text-align: left; padding: var(--sp-8) var(--sp-14) var(--sp-8) 0;
                      border-bottom: var(--bw-1) solid var(--c-border-soft); vertical-align: top; }
/* The table dress the insights post needs: a muted header row and tabular
   figures, so a column of numbers lines up. Shared, because the legal pages
   use tables too and a second dress would be a second thing to keep true. */
.prose thead th { font-size: var(--fs-13); font-weight: var(--fw-medium); color: var(--c-text-mute); }
.prose td { font-variant-numeric: tabular-nums; }
.prose p:first-child { margin-top: 0; }
.prose strong { color: var(--c-ink); font-weight: var(--fw-semibold); }

/* A stack of linked articles — the insights index. The card is the design's
   `.card`; only the inner rhythm is new. */
.post-list { list-style: none; margin: 0; padding: 0; display: flex;
             flex-direction: column; gap: var(--sp-12); }
.post-list .card { display: block; }
.post-list h2 { font-size: var(--fs-17); font-weight: var(--fw-bold);
                line-height: var(--lh-title); margin: 0; }
.post-list p { font-size: var(--fs-14); line-height: var(--lh-body);
               color: var(--c-text-soft); margin: var(--sp-6) 0 0; }
.post-list time { display: block; font-size: var(--fs-13); color: var(--c-text-mute);
                  margin-top: var(--sp-8); font-variant-numeric: tabular-nums; }

/* The way back, on a page that is an end: the error pages and the alert
   confirmation. A row of quiet links into the mesh, not a wall of them. */
.ways-back { display: flex; flex-wrap: wrap; gap: var(--sp-8) var(--sp-20);
             margin-top: var(--sp-20); font-size: var(--fs-14); }
.ways-back a { color: var(--c-terracotta); }

/* An insights post's outbound links, and the second heading inside that panel. */
.post-links { margin-top: var(--sp-28); }
.post-links .section-label.second { margin-top: var(--sp-20); }

/* The error pages. The search bar closes the page rather than opening one, so
   it takes the same separation the job page's trailing bar takes. */
/* THE DOORWAY -- this page's one job. Three onward routes as promo cards: the
   occupation, the city, and their intersection. Each renders only when its
   page is published, so an absent card means "that page does not exist" rather
   than "we did not look", and a 404 renders none of them.

   The 410 is not an error page to a reader. They followed a link that worked
   last week, and this is the difference between "you are in the right place,
   it has ended" and "that never existed". Jobtome lost 65% of a market to four
   manual actions for expired job pages that kept looking live; the status code
   is the route's job and not lying is this page's. */
body.page-error .status-kicker { font-size: var(--fs-13); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--c-text-mute);
  margin: 0 0 var(--sp-8); }
.doorway { display: grid; gap: var(--sp-12);
  grid-template-columns: repeat(3, 1fr); margin-bottom: var(--sp-28); }
@media (max-width: 880px) { .doorway { grid-template-columns: 1fr; } }
.doorway .promo { margin: 0; height: 100%; }
body.page-error .search-lead { margin: 0 0 var(--sp-10); }
body.page-error .error-list { margin: 0 0 var(--sp-32); }
body.page-error .search { display: flex; gap: var(--sp-10); flex-wrap: wrap;
                          margin: 0; max-width: 720px; }
body.page-error .search .input { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-14); }
body.page-error .search .q { flex: 2 1 220px; }
body.page-error .search .city { flex: 1 1 130px; }
body.page-error .search .btn { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-24); }

/* ---------------------------------------------------- index pages (tier 2) -- */

/* A MULTI-COLUMN LINK INDEX. The A-Z pages carry up to 490 entries whose only
   job is to be crawled, and neither `.occ-list` (a bordered card, right for
   eight rows in an aside) nor `.city-grid` (a card each, right for eight
   cities) survives that many.

   So the ROW is the design's `.occ-row` — same type, same weight, same hairline
   between, same muted tabular count on the right — and only the container is
   new: columns instead of one card. Nothing about how a row looks was
   re-decided. */
.index-grid {
  display: grid; grid-template-columns: 1fr;
  gap: 0 var(--sp-32); margin: 0; padding: 0; list-style: none;
}
@media (min-width: 560px)  { .index-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .index-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1100px) { .index-grid { grid-template-columns: repeat(4, 1fr); } }

.index-grid li { min-width: 0; }
.index-grid a {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--sp-14); padding: var(--sp-10) 0;
  border-bottom: var(--bw-1) solid var(--c-border-soft);
  font-size: var(--fs-15); font-weight: var(--fw-medium);
}
.index-grid a:hover { color: var(--c-terracotta); }
/* ESCO labels run long and a wrapping label collides with its own count. One
   line, elided; the full text stays in the link's `title`. */
.index-grid .label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.index-grid .n { flex: none; color: var(--c-text-mute); font-weight: var(--fw-regular);
                 font-variant-numeric: tabular-nums; }

/* The letter jumps. Plain fragment links — no script, real browser history —
   wearing the design's own filter pill. */
/* STICKY IN BATCH 2. These indexes run to 510 rows -- every one of them stays
   in the document because internal linking is what gets them crawled -- and an
   alphabet that scrolls away at row 40 is an alphabet nobody uses. Cream ground
   so rows slide beneath it cleanly. Still fragment links: no JS, real history. */
.letter-jump { display: flex; flex-wrap: wrap; gap: var(--sp-6);
               margin: 0 0 var(--sp-28); padding: var(--sp-10) 0;
               position: sticky; top: 0; z-index: 10;
               background: var(--c-cream);
               border-bottom: var(--bw-1) solid var(--c-border-soft); }
.letter-jump a {
  min-width: 34px; text-align: center;
  font-size: var(--fs-13); font-weight: var(--fw-semibold);
  padding: var(--sp-6) var(--sp-10); border-radius: var(--r-pill);
  background: var(--c-white); color: var(--c-text-soft);
  border: var(--bw-1) solid var(--c-border);
}
.letter-jump a:hover { background: var(--c-accent-weak); color: var(--c-accent-deep);
                       border-color: var(--c-border-accent); }

.index-letter { margin-bottom: var(--sp-32); }
/* The jump target must clear the sticky alphabet above it, or a fragment link
   lands with its own heading hidden behind the bar. */
.index-letter h2 { scroll-margin-top: calc(var(--sp-48) + var(--sp-16));
                   font-size: var(--fs-18);
                   font-weight: var(--fw-bold); margin: 0 0 var(--sp-8); }
.index-other { margin-top: var(--sp-32); font-size: var(--fs-14); }
.index-other a { color: var(--c-terracotta); }

/* The market a link belongs to, on the root only: `/` spans three markets, so
   a bare "Monza" gives no clue which country it leads to. */
.market-tag { margin-left: var(--sp-8); font-size: var(--fs-12); font-weight: var(--fw-semibold);
              letter-spacing: var(--ls-label); color: var(--c-text-mute); }

/* The root's market chooser — the primary choice on that page, so it is the
   design's city card at a larger size rather than a row in a list. */
.markets { list-style: none; margin: 0 0 var(--sp-36); padding: 0;
           display: grid; gap: var(--sp-12); grid-template-columns: 1fr; }
@media (min-width: 700px) { .markets { grid-template-columns: repeat(3, 1fr); } }
/* Roomier in batch 2: these are the largest cards on the page and the sector
   grid now uses the tighter padding, so the two read as a hierarchy. */
.markets a { display: block; background: var(--c-white);
             border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md);
             padding: var(--sp-20) var(--sp-22); }
.markets a:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
.markets .name { display: block; font-size: var(--fs-18); font-weight: var(--fw-bold); }
.markets .count { display: block; font-size: var(--fs-14); color: var(--c-text-mute);
                  margin-top: var(--sp-6); font-variant-numeric: tabular-nums; }

/* The link from a listing page to its salary page. A question, not a label:
   it is the phrasing a reader is already thinking in when they arrive. */
.salary-link { margin: var(--sp-16) 0 0; font-size: var(--fs-15); }
.salary-link a { color: var(--c-terracotta); font-weight: var(--fw-medium); }

/* ============================ salary page — handoff-batch1 ================
 * Carried from `design/handoff-batch1/salary.html`, selectors qualified by
 * the page class and every declaration byte-identical. New here:
 * `.job-list`/`.job-row` (a listing where jobs are evidence, not the event —
 * eleven near-identical Parkdean adverts read as observations rather than a
 * wall of cards), `.salary-provenance` (the figure never appears without its
 * basis), `.advertised-note` (set apart, never fine print) and `.aside-list`.
 * ======================================================================== */



    /* ---- salary page ---- */
    /* The figure and its evidence are one panel: the number is never shown
       without its basis. Provenance line sits directly under the amount. */
    body.page-salary .salary-figure { display: flex; align-items: baseline; gap: var(--sp-12); flex-wrap: wrap; margin: 0; }
    body.page-salary .salary-amount { font-size: var(--fs-h1-home); font-weight: var(--fw-heavy); letter-spacing: var(--ls-tight); line-height: var(--lh-tight); font-variant-numeric: tabular-nums; }
    body.page-salary .salary-unit { font-size: var(--fs-15); color: var(--c-text-soft); }
    body.page-salary .salary-provenance { font-size: var(--fs-14); line-height: var(--lh-body); color: var(--c-text-mute); margin: var(--sp-8) 0 0; font-variant-numeric: tabular-nums; }
    body.page-salary .salary-provenance b { color: var(--c-ink); font-weight: var(--fw-semibold); }
    body.page-salary .salary-monthly { font-size: var(--fs-15); color: var(--c-text-mute); margin: var(--sp-4) 0 0; }
    /* four figures, median accented — the job-facts pair turned horizontal */
    body.page-salary .salary-range { display: grid; gap: var(--sp-12); margin: var(--sp-24) 0 0; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
    body.page-salary .salary-range > div { min-width: 0; }
    body.page-salary .salary-range dt { font-size: var(--fs-13); color: var(--c-text-mute); font-weight: var(--fw-medium); }
    body.page-salary .salary-range dd { margin: var(--sp-4) 0 0; font-size: var(--fs-18); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
    body.page-salary .salary-range .is-median dd { color: var(--c-terracotta); }
    /* chart: the design's own band at 8px, plus named marks */
    body.page-salary .salary-chart { margin: var(--sp-28) 0 0; }
    body.page-salary .chart-plot { position: relative; padding: var(--sp-22) 0 var(--sp-36); }
    body.page-salary .chart-mean { position: absolute; top: calc(var(--sp-22) + var(--dot) + var(--sp-8)); width: var(--dot); height: var(--dot); margin-left: calc(var(--dot) / -2); background: var(--c-terracotta); border-radius: var(--r-pill); box-shadow: var(--shadow-marker); }
    body.page-salary .chart-key { position: absolute; white-space: nowrap; font-size: var(--fs-12); font-weight: var(--fw-medium); color: var(--c-text-mute); }
    body.page-salary .chart-key.above { top: 0; }
    body.page-salary .chart-key.below { top: calc(var(--sp-22) + var(--dot) + var(--sp-20)); }
    body.page-salary .chart-key.is-mid { transform: translateX(-50%); }
    body.page-salary .chart-key.is-end { transform: translateX(-100%); }
    body.page-salary .chart-key.is-start { transform: none; }
    body.page-salary .chart-ends { display: flex; justify-content: space-between; gap: var(--sp-16); font-size: var(--fs-13); color: var(--c-text-mute); }
    body.page-salary .chart-ends b { color: var(--c-ink); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
    body.page-salary .salary-chart figcaption { margin-top: var(--sp-12); font-size: var(--fs-13); line-height: var(--lh-body); color: var(--c-text-mute); }
    body.page-salary .salary-note { font-size: var(--fs-13); line-height: var(--lh-body); color: var(--c-text-mute); margin: var(--sp-16) 0 0; }
    /* the methodology prose */
    body.page-salary .prose { font-size: var(--fs-16); line-height: var(--lh-copy); color: var(--c-ink); }
    body.page-salary .prose h2 { font-size: var(--fs-18); font-weight: var(--fw-bold); margin: 0; }
    body.page-salary .prose p { margin: var(--sp-10) 0 0; color: var(--c-text-soft); }
    body.page-salary .prose ul { margin: var(--sp-10) 0 0; padding-left: var(--sp-22); color: var(--c-text-soft); }
    body.page-salary .prose li { margin-top: var(--sp-6); }
    /* the disclaimer is the one claim the page must not soften — set apart, not fine print */
    body.page-salary .advertised-note { margin-top: var(--sp-20); padding-top: var(--sp-16); border-top: var(--bw-1) solid var(--c-border-soft); font-size: var(--fs-14); line-height: var(--lh-body); color: var(--c-text-soft); }
    body.page-salary .advertised-note b { color: var(--c-ink); font-weight: var(--fw-semibold); }

    /* ---- .job-list / .job-row -- SHARED, not page-scoped ----
     * Arrived in batch 1 scoped to the salary page because only that page used
     * it. Batch 2 uses the identical component on occupation and
     * occupation_city -- byte-identical in the reference, including the
     * `.jr-chips` basis fix we sent back as BATCH1-FEEDBACK §1, which the
     * designer ratified rather than reverting. So it is unscoped here.
     *
     * ---- NEW COMPONENT: .job-list / .job-row ----
       A listing where jobs are supporting evidence, not the main event.
       One bordered panel, hairline rows — 11 near-identical Parkdean adverts
       read as a table of observations instead of a wall of identical cards.
       The monogram drops to 28px and is OPTIONAL: a row without one (a
       placeholder employer like "Confidential") simply starts at the text,
       which retires .job-card-plain for this context. Reusable on occupation
       pages (batch 2). */
    .job-list { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-6) var(--sp-18); margin-top: var(--sp-14); }
    .job-row { display: flex; align-items: center; gap: var(--sp-14); padding: var(--sp-12) 0; border-bottom: var(--bw-1) solid var(--c-border-soft); }
    .job-row:last-child { border-bottom: 0; }
    .job-row:hover { color: var(--c-ink); }
    .job-row:hover .jr-title { color: var(--c-terracotta); }
    .jr-mono { width: var(--sp-28); height: var(--sp-28); border-radius: var(--r-sm); display: flex; align-items: center; justify-content: center; color: var(--c-white); font-weight: var(--fw-bold); font-size: var(--fs-12); flex: none; }
    .jr-main { min-width: 0; flex: 1 1 auto; }
    .jr-title { display: block; font-size: var(--fs-15); font-weight: var(--fw-bold); line-height: var(--lh-title); overflow-wrap: anywhere; }
    .jr-meta { display: block; font-size: var(--fs-13); color: var(--c-text-mute); margin-top: var(--sp-2); font-variant-numeric: tabular-nums; }
    .jr-chips { display: flex; gap: var(--sp-6); flex-wrap: wrap; justify-content: flex-end; flex: none; max-width: 40%; }
    @media (max-width: 560px) {
      .job-row { flex-wrap: wrap; }
      /* DEVIATION from the batch-1 reference, and deliberate. The reference has
         `flex-basis: 100%` here together with a 42px margin-left, so the wrapped
         chip row measures 100% + 42px and every salary page scrolls 7px sideways
         at 390px. Measured in design/handoff-batch1/salary.html itself, not only
         in our port -- see design/BATCH1-FEEDBACK.md, which goes back with the
         batch 2 request. The indent is deliberate (it aligns the chips under the
         title rather than under the monogram) so it stays; the basis gives back
         exactly what the indent takes. */
      .jr-chips { flex-basis: calc(100% - (var(--sp-28) + var(--sp-14))); justify-content: flex-start; max-width: none; margin-left: calc(var(--sp-28) + var(--sp-14)); }
      .job-row.no-mono .jr-chips { margin-left: 0; }
    }

    /* ---- .aside-list -- SHARED, not page-scoped ----
     * ⚠ THE REFERENCE USES THIS CLASS AND DEFINES IT NOWHERE. batch-2's
     * occupation.html marks up its "By city" block with `.aside-list`, but the
     * class lives in batch 1's SALARY page block, so the batch-2 file styles
     * nothing: the reference itself renders "London214" as bare inline text.
     * Reproduced faithfully on our first pass, then fixed here by unscoping.
     *
     * Exactly the shape of batch 1's `.panel` / `.facts` / `.promo` problem --
     * a component used on more than one page but defined inside one page's
     * block. Reported in BATCH2-FEEDBACK.
     *
     * aside city list: occ-row idiom, one column always */
    .aside-list { background: var(--c-white); border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-6) var(--sp-18); }
    .aside-list a { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-14); padding: var(--sp-11) 0; border-bottom: var(--bw-1) solid var(--c-border-soft); font-size: var(--fs-15); font-weight: var(--fw-medium); }
    .aside-list a:last-child { border-bottom: 0; }
    .aside-list a:hover { color: var(--c-terracotta); }
    .aside-list .label { min-width: 0; overflow-wrap: anywhere; }
    .aside-list .n { flex: none; color: var(--c-text-mute); font-weight: var(--fw-regular); font-variant-numeric: tabular-nums; }

    body.page-salary .salary-body > * + * { margin-top: var(--sp-16); }
    body.page-salary .salary-body .section-head { margin-top: var(--sp-28); }
    body.page-salary aside > * + * { margin-top: var(--sp-16); }
    body.page-salary aside .section-label { margin-bottom: var(--sp-10); }

/* -------------------------------------------------- alerts page & hub (t3) -- */

/* The alerts page: an explanation beside the form, one column on a phone. */
.alerts-layout { display: grid; gap: var(--sp-24); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 880px) { .alerts-layout { grid-template-columns: minmax(0, 1fr) 360px; } }

/* THE SALARY-HUB PICKER. Two selects and a button, in a row where they fit and
   a column where they do not. The design has no <select> anywhere, so the
   control is dressed as its `.input`: same border, same radius, same padding,
   same ground. The only addition is the native arrow's breathing room. */
.salary-picker { display: grid; gap: var(--sp-14); grid-template-columns: 1fr; align-items: end; }
@media (min-width: 760px) { .salary-picker { grid-template-columns: 2fr 1fr auto; } }
.salary-picker .field { margin: 0; min-width: 0; }
.salary-picker label { display: block; font-size: var(--fs-13); font-weight: var(--fw-medium);
                       color: var(--c-text-mute); margin-bottom: var(--sp-6); }
.salary-picker select {
  width: 100%; font: inherit; font-size: var(--fs-15);
  padding: var(--sp-11) var(--sp-14);
  color: var(--c-ink); background: var(--c-white);
  border: var(--bw-1) solid var(--c-border); border-radius: var(--r-sm);
}
.salary-picker select:hover { border-color: var(--c-border-accent); }
.salary-picker .btn-lg { font-size: var(--fs-16); padding: var(--sp-13) var(--sp-26); }

/* The "not enough adverts yet" notice — the one warm-tinted surface outside a
   signup box, using the salary chip's own pair so it reads as the same family
   as the figures it is about.

   NO MARGIN OF ITS OWN, which is the batch-1 reference's arrangement and a
   better one than what stood here. The notice sits BELOW the form on the hub
   (it answers what you just asked) and ABOVE everything on the calculator (it
   disclaims what follows), so a single `margin-bottom` baked into the
   component was right for one page and wrong for the other. Each page states
   its own gap. */
.notice { background: var(--c-salary-bg); color: var(--c-salary);
          border: var(--bw-1) solid var(--c-border-accent); border-radius: var(--r-md);
          padding: var(--sp-14) var(--sp-18);
          font-size: var(--fs-14); line-height: var(--lh-body); }
.notice strong { display: block; margin-bottom: var(--sp-4); }
.notice a { color: var(--c-accent-deep); font-weight: var(--fw-medium); }
body.page-salary-hub .page-body > .notice { margin-top: var(--sp-16); }
body.page-calculator .page-body > .notice { margin-bottom: var(--sp-24); }

/* The A–Z section wrapper, and the closing provenance line. `.index-grid`
   above is shared with the other index pages and needed nothing; only the
   container and the note are new here. */
.index-section { margin-top: var(--sp-32); }
.index-section .section-label { margin-bottom: var(--sp-8); }
.hub-note { font-size: var(--fs-13); color: var(--c-text-mute);
            margin: var(--sp-16) 0 0; line-height: var(--lh-body); }

/* ------------------------------------------------------- calculator (t3) -- */

/* THE ONLY v3 PAGE WITH JAVASCRIPT, and the only one with a table. */

body.page-calculator .calc-layout {
  display: grid; gap: var(--sp-24); grid-template-columns: 1fr; align-items: start;
}
@media (min-width: 881px) {
  body.page-calculator .calc-layout { grid-template-columns: minmax(0, 380px) minmax(0, 1fr); gap: var(--col-gap); }
  /* THE RESULT STAYS ON SCREEN while the reader changes an input above it,
     which is the whole point of recalculating live. Same idiom the city
     page's aside already uses. */
  body.page-calculator .calc-result { position: sticky; top: var(--sp-16); }
}

body.page-calculator .calc-form .field { margin-bottom: var(--sp-14); }
body.page-calculator .calc-form .field:last-of-type { margin-bottom: 0; }
body.page-calculator .calc-form label { display: block; font-size: var(--fs-13);
  font-weight: var(--fw-medium); color: var(--c-text-mute); margin-bottom: var(--sp-6); }
body.page-calculator .calc-form input[type="number"],
body.page-calculator .calc-form select {
  width: 100%; font: inherit; font-size: var(--fs-15);
  padding: var(--sp-11) var(--sp-14);
  color: var(--c-ink); background: var(--c-white);
  border: var(--bw-1) solid var(--c-border); border-radius: var(--r-sm);
}
body.page-calculator .calc-form input[type="number"]:hover,
body.page-calculator .calc-form select:hover { border-color: var(--c-border-accent); }
/* A NATIVE CHECKBOX. The design draws none, and a restyled one would be new
   visual language for a control the browser already renders correctly in every
   theme and at every zoom. The label sits beside it and the hint below both. */
body.page-calculator .calc-form .field-check { display: flex; align-items: center;
  gap: var(--sp-8); flex-wrap: wrap; }
body.page-calculator .calc-form .field-check label { margin: 0; font-size: var(--fs-14);
  color: var(--c-ink); font-weight: var(--fw-regular); }
body.page-calculator .calc-form .field-check input { width: auto;
  accent-color: var(--c-terracotta); }
body.page-calculator .calc-form .hint { flex-basis: 100%; font-size: var(--fs-13);
  color: var(--c-text-mute); margin: var(--sp-4) 0 0; line-height: var(--lh-body); }
/* The submit is a full-width block here rather than the inline `.btn` used
   everywhere else, so the reference gives it its own class instead of
   overriding `.btn` inside the form. */
body.page-calculator .btn-block { width: 100%; justify-content: center;
  margin-top: var(--sp-16); font-size: var(--fs-16); padding: var(--sp-13) var(--sp-26); }

/* THE RESULT. The headline net figure in the salary page's own type, the
   gross-to-net share on the shared `.band`, then the breakdown as a two-value
   table — year and month — in the facts-row idiom. Amounts line up only if the
   digits do, so every numeric cell is tabular. */
body.page-calculator .calc-result .placeholder { font-size: var(--fs-15);
  color: var(--c-text-mute); margin: 0; line-height: var(--lh-body); }
body.page-calculator .calc-kicker { font-size: var(--fs-13); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--c-text-mute);
  margin: 0 0 var(--sp-8); }
body.page-calculator .calc-headline { font-size: var(--fs-h1-home); font-weight: var(--fw-heavy);
  letter-spacing: var(--ls-tight); line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums; margin: 0; }
body.page-calculator .calc-headline .muted { font-size: var(--fs-15);
  font-weight: var(--fw-regular); letter-spacing: 0; color: var(--c-text-mute); }
body.page-calculator .calc-monthly { color: var(--c-text-soft); margin: var(--sp-6) 0 0;
  font-size: var(--fs-15); font-variant-numeric: tabular-nums; }
/* The share of gross that survives, on the same band the salary chart uses.
   It restates the table above it rather than adding a fact, which is why it
   carries no marks of its own — just the two ends, named. */
body.page-calculator .calc-share { margin-top: var(--sp-16); }
body.page-calculator .calc-share .band { margin: 0; }
body.page-calculator .calc-share-legend { display: flex; justify-content: space-between;
  gap: var(--sp-16); margin-top: var(--sp-8); font-size: var(--fs-13);
  color: var(--c-text-mute); font-variant-numeric: tabular-nums; }
body.page-calculator .calc-table { width: 100%; border-collapse: collapse;
  margin-top: var(--sp-20); font-size: var(--fs-14); }
body.page-calculator .calc-table th,
body.page-calculator .calc-table td { padding: var(--sp-12) 0;
  border-bottom: var(--bw-1) solid var(--c-border-soft); text-align: left; }
body.page-calculator .calc-table thead th { font-size: var(--fs-13);
  font-weight: var(--fw-medium); color: var(--c-text-mute); padding-top: 0; text-align: right; }
body.page-calculator .calc-table thead th:first-child { text-align: left; }
body.page-calculator .calc-table tbody th { font-weight: var(--fw-regular);
  color: var(--c-text-mute); }
body.page-calculator .calc-table td { text-align: right; font-variant-numeric: tabular-nums;
  white-space: nowrap; font-weight: var(--fw-medium); }
body.page-calculator .calc-row-gross th,
body.page-calculator .calc-row-gross td { font-weight: var(--fw-semibold); color: var(--c-ink); }
body.page-calculator .calc-row-net th,
body.page-calculator .calc-row-net td { font-weight: var(--fw-heavy); color: var(--c-ink);
  border-bottom: 0; border-top: var(--bw-2) solid var(--c-border); padding-top: var(--sp-14); }
/* The measure moves from `.prose` to the notes wrapper: on this page the prose
   is the only thing in it, and on the salary page `.prose` sits inside a panel
   that already sets the measure. */
body.page-calculator .calc-notes { margin-top: var(--sp-36); max-width: 68ch; }
body.page-calculator .prose h2 { margin: 0; }
body.page-calculator .prose h3 { font-size: var(--fs-16); font-weight: var(--fw-bold);
  margin: var(--sp-20) 0 0; }
body.page-calculator .prose ul { margin: var(--sp-10) 0 0; padding-left: var(--sp-22);
  color: var(--c-text-soft); }
body.page-calculator .prose li { margin-top: var(--sp-6); }
body.page-calculator .prose .small { font-size: var(--fs-13); line-height: var(--lh-body);
  color: var(--c-text-mute); }

/* ------------------------------------------------------- occupation (b2) -- */

/* Shared by `occupation` and `occupation_city`: ONE template, one page class.
   components.md §2 makes that explicit -- same rows, same rail, only the
   breadcrumb and the aside's lists differ. */

/* DEVIATION from the batch-2 reference, forced by German. `overflow-wrap` is
   added; everything else is the reference's rule byte for byte.

   ESCO's German labels are slashed compounds with no break opportunity in
   them: "Einkaufsdisponent/Einkaufsdisponentin" is one 37-character word to a
   line-breaker, and at 390px it measured 490px inside a 358px box and pushed
   the whole document sideways. The reference gives `.jr-title` exactly this
   treatment for the same reason -- 85-character advert titles -- but the
   heading did not get it, because the designer's German example was
   "Pflegefachkraft", which fits. It is systemic rather than an edge case: this
   shape is normal across all 219 German occupation pages. Reported in
   BATCH2-FEEDBACK. */
body.page-occupation .title-row h1 { font-size: var(--fs-h1-city); font-weight: var(--fw-display);
  letter-spacing: var(--ls-tight); margin: var(--sp-12) 0 0; text-wrap: balance;
  overflow-wrap: anywhere; }
body.page-occupation .title-row .count { font-weight: var(--fw-medium); color: var(--c-text-mute);
  font-variant-numeric: tabular-nums; }

/* THE ASIDE IS STICKY, and that is what makes the thin case work. An
   occupation aside legitimately holds one to four blocks, and on 202 of 219
   German occupation pages it holds exactly one -- the alert box, beside twenty
   rows. Pinned, that reads as a deliberate rail; unpinned it reads as an
   abandoned column. Same idiom as the calculator's sticky result.

   881px, not 880: at exactly 880 `.two-col` has already collapsed to one
   column, and a sticky element in a one-column flow pins against the wrong
   thing. */
@media (min-width: 881px) {
  body.page-occupation .two-col > aside .aside-pin { position: sticky; top: var(--sp-16); }
}
body.page-occupation aside .aside-pin > * + * { margin-top: var(--sp-16); }
body.page-occupation aside .section-label { margin-bottom: var(--sp-10); }

/* DENSITY COMES FROM THE FRAME, NOT THE DATA. The route returns exactly twenty
   rows whether the cell holds 50 or 12,688, so `occupation-fat` and
   `occupation-thin` are otherwise the same document. This line is the only
   thing on the page that knows the difference. */
body.page-occupation .list-note { font-size: var(--fs-13); color: var(--c-text-mute);
  margin: var(--sp-14) 0 0; line-height: var(--lh-body); font-variant-numeric: tabular-nums; }

/* The salary card: the median with its own band, not a bare link. Renders only
   when the occupation has a publishable salary cell. */
body.page-occupation .salary-check { display: block; background: var(--c-white);
  border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-18); }
body.page-occupation .salary-check:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
body.page-occupation .salary-check .top { display: flex; justify-content: space-between;
  align-items: baseline; gap: var(--sp-12); margin-top: var(--sp-10); }
body.page-occupation .salary-check .role { font-size: var(--fs-15); font-weight: var(--fw-medium);
  min-width: 0; overflow-wrap: anywhere; }
body.page-occupation .salary-check .median { font-size: var(--fs-17); font-weight: var(--fw-heavy);
  font-variant-numeric: tabular-nums; }
body.page-occupation .salary-check .basis { display: block; font-size: var(--fs-13);
  color: var(--c-text-mute); margin-top: var(--sp-10); }

/* The hero search. Byte-identical to the reference's rules; scoped because the
   home hero's field is 16px/13px and this one is 15px/11px, which
   components.md records as deliberate — served from one shell they would
   otherwise overwrite each other. */
body.page-occupation .search { display: flex; gap: var(--sp-10); flex-wrap: wrap;
  margin: var(--sp-20) 0 0; max-width: 720px; }
body.page-occupation .search .input { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-14); }
body.page-occupation .search .q { flex: 2 1 220px; }
body.page-occupation .search .city { flex: 1 1 130px; }
body.page-occupation .search .btn { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-24); }
/* The list opens the column here, so it needs no top gap — the reference sets
   `style="margin-top: 0"` inline; a class keeps it out of the markup. */
body.page-occupation .job-list { margin-top: 0; }

/* ----------------------------------------------------- category_hub (b2) -- */

/* THE SECTOR GRID. Not a new idiom: the root page's market card with a smaller
   name, which is what components.md §4 asks for. This page is 14-16 rows in
   every market permanently, so it is sized as a designed object rather than as
   an index that might grow. */
.sector-grid { list-style: none; margin: 0; padding: 0; display: grid;
               gap: var(--sp-12); grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .sector-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .sector-grid { grid-template-columns: 1fr; } }
.sector-grid a { display: block; background: var(--c-white);
                 border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md);
                 padding: var(--sp-18) var(--sp-20); height: 100%; }
.sector-grid a:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
.sector-grid .name { display: block; font-size: var(--fs-16); font-weight: var(--fw-bold);
                     line-height: var(--lh-title); overflow-wrap: anywhere; }
.sector-grid .meta { display: block; font-size: var(--fs-14); color: var(--c-text-mute);
                     margin-top: var(--sp-8); font-variant-numeric: tabular-nums; }
.sector-grid .meta b { color: var(--c-ink); font-weight: var(--fw-semibold); }

/* ------------------------------------------------------------ root (b2) -- */

/* The three claims the site may make, under the wordmark. `.dot` separates
   them; they are facts about the service, not marketing. */
.hero-facts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-10);
              margin: var(--sp-16) 0 0; font-size: var(--fs-15); color: var(--c-text-soft); }
.hero-facts span { display: inline-flex; align-items: center; gap: var(--sp-10); }
.index-letter .section-label { margin-bottom: var(--sp-10); }

/* ---------------------------------------------------------- search (b3) -- */

/* NOINDEX, NOFOLLOW, out of every sitemap and under robots.txt's
   `Disallow: /*?`. It is the only page Google never sees, which is why it is
   also the only one allowed to carry `?p=` on its job links. */
body.page-search .title-row h1 { font-size: var(--fs-h1-city); font-weight: var(--fw-display);
  letter-spacing: var(--ls-tight); margin: var(--sp-12) 0 0; text-wrap: balance;
  overflow-wrap: anywhere; }
body.page-search .title-row .count { font-weight: var(--fw-medium); color: var(--c-text-mute);
  font-variant-numeric: tabular-nums; }
body.page-search .search { display: flex; gap: var(--sp-10); flex-wrap: wrap;
  margin: var(--sp-20) 0 0; max-width: 720px; }
body.page-search .search .input { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-14); }
body.page-search .search .q { flex: 2 1 220px; }
body.page-search .search .city { flex: 1 1 130px; }
body.page-search .search .btn { font-size: var(--fs-15); padding: var(--sp-11) var(--sp-24); }
body.page-search .job-list { margin-top: 0; }

/* The empty state reads as a note, not an error: an unusual search is an
   ordinary thing to do. Lede weight, then the ways out. */
body.page-search .empty-note { font-size: var(--fs-16); line-height: var(--lh-body);
  color: var(--c-text-soft); margin: 0 0 var(--sp-16); }
body.page-search .ways-back { margin: 0 0 var(--sp-24); }

@media (min-width: 881px) {
  body.page-search .two-col > aside .aside-pin { position: sticky; top: var(--sp-16); }
}
body.page-search aside .aside-pin > * + * { margin-top: var(--sp-16); }

/* THE PAGER, WHICH components.md SAYS DOES NOT EXIST. It does: `driver` in GB
   returns 10,000 results across 50 pages, `nurse` in London 450 across 23. The
   reference was drawn from a seven-result query. Restyled to the design's
   tokens rather than redesigned, and carried over from the page-city block it
   used to borrow. */
body.page-search .pagination { display: flex; align-items: center;
  justify-content: space-between; gap: var(--sp-16); margin-top: var(--sp-24); }
body.page-search .pagination .info { font-size: var(--fs-14); color: var(--c-text-mute);
  font-variant-numeric: tabular-nums; }
body.page-search .page-btn { font-size: var(--fs-14); font-weight: var(--fw-semibold);
  background: var(--c-white); border: var(--bw-1) solid var(--c-border);
  padding: var(--sp-9) var(--sp-18); border-radius: var(--r-sm); }
body.page-search .page-btn:hover { border-color: var(--c-border-accent); color: var(--c-terracotta); }

/* ----------------------------------------------- alerts + legal + insights (b3) -- */

/* THE ALERT FORM, in the calculator's treatment: a panel with VISIBLE labels
   and a full-width submit. The aside version keeps its `sr-only` labels
   because it sits inside a titled box; this one is the page. Still no email
   field, and there will not be one until there is a sending path. */
body.page-alerts .alerts-layout { display: grid; gap: var(--sp-24);
  grid-template-columns: 1fr; align-items: start; }
@media (min-width: 880px) {
  body.page-alerts .alerts-layout { grid-template-columns: minmax(0, 1fr) 380px;
                                    gap: var(--col-gap); }
}
body.page-alerts .alerts-form .field { margin-bottom: var(--sp-14); }
body.page-alerts .alerts-form label { display: block; font-size: var(--fs-13);
  font-weight: var(--fw-medium); color: var(--c-text-mute); margin-bottom: var(--sp-6); }
body.page-alerts .alerts-form .input { width: 100%; font-size: var(--fs-15);
  padding: var(--sp-11) var(--sp-14); }
body.page-alerts .alerts-form .btn-block { width: 100%; justify-content: center;
  margin-top: var(--sp-16); font-size: var(--fs-16); padding: var(--sp-13) var(--sp-26); }

/* THE FIVE DOCUMENTS AS A ROW. Privacy, terms, imprint, about and sources are
   one family to a reader even though two of them live in a different module;
   the current one is bold ink and not a link, so the row says where you are as
   well as where else you can go. */
body.page-legal .doc-nav { display: flex; flex-wrap: wrap; gap: var(--sp-8) var(--sp-20);
  margin-top: var(--sp-16); font-size: var(--fs-14); }
body.page-legal .doc-nav a { color: var(--c-text-mute); }
body.page-legal .doc-nav a:hover { color: var(--c-terracotta); }
body.page-legal .doc-nav [aria-current="page"] { color: var(--c-ink);
  font-weight: var(--fw-semibold); }

/* ONE POST IS THE ARCHIVE, and the card is measured so that one of them looks
   complete rather than lonely. Nothing on this page apologises for the count. */
body.page-insights .post-list { max-width: 68ch; }
body.page-insights .post-list a { display: block; background: var(--c-white);
  border: var(--bw-1) solid var(--c-border); border-radius: var(--r-md); padding: var(--sp-22); }
body.page-insights .post-list a:hover { border-color: var(--c-border-accent); color: var(--c-ink); }
body.page-insights .post-list .kicker { display: block; font-size: var(--fs-13);
  font-weight: var(--fw-semibold); letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--c-text-mute); }
body.page-insights .post-list h2 { font-size: var(--fs-18); font-weight: var(--fw-bold);
  line-height: var(--lh-title); margin: var(--sp-8) 0 0; overflow-wrap: anywhere; }
body.page-insights .post-list p { margin: var(--sp-8) 0 0; }
body.page-insights .post-list time { margin-top: var(--sp-12); }

/* The links panel follows the article, so it takes the article's measure. */
body.page-insights-post .post-links { max-width: 68ch; }
body.page-insights-post .post-links .section-label { margin-bottom: var(--sp-4); }
