/* cub.css — Connor Blandford design system, production build.
   Single file, no build step, no dependencies. Drop in assets/ and link it.
   Replaces site.css + home.css + project.css. Its :root block holds the only
   copy of the tokens (docs/DESIGN-SYSTEM.md, "Keeping in sync"). */

/* ── Fonts ─────────────────────────────────────────────────────────────── */
/* Self-hosted IBM Plex, OFL 1.1 — license in assets/fonts/LICENSE.txt. The
   fonts are served from this origin, so they add no outside request. Two
   requests do leave it: every page a browser loads also loads Cloudflare Web
   Analytics' beacon, which Cloudflare adds, and the schools map loads its
   background tiles from Esri's servers. The About page's Privacy section says
   both. Sans is the variable face: one 45KB file covers every weight the
   system uses (400/450/500/600) for less than two static cuts would cost.
   Mono has no variable build, so its three weights are separate files.
   font-display:swap paints text immediately in the fallback stack declared
   in --font-sans / --font-mono below and swaps when Plex arrives. */
@font-face{
  font-family:"IBM Plex Sans";
  src:url("fonts/ibm-plex-sans-var.woff2") format("woff2");
  font-weight:100 700;font-style:normal;font-display:swap;
}
@font-face{
  font-family:"IBM Plex Mono";
  src:url("fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
}
@font-face{
  font-family:"IBM Plex Mono";
  src:url("fonts/ibm-plex-mono-500.woff2") format("woff2");
  font-weight:500;font-style:normal;font-display:swap;
}
@font-face{
  font-family:"IBM Plex Mono";
  src:url("fonts/ibm-plex-mono-600.woff2") format("woff2");
  font-weight:600;font-style:normal;font-display:swap;
}

/* ── Tokens ────────────────────────────────────────────────────────────── */
:root{
--ink-900:#101418;--ink-700:#2b3338;--ink-600:#4c555c;--ink-500:#5f686f;--ink-400:#6e777d;
--line-mid:#a9b4ba;--line:#e4e8ea;--line-strong:#cfd6da;--white:#fff;--wash:#f6f8f9;--wash-deep:#eef2f4;
--brand-blue:#26ace0;--brand-red:#ed1740;--brand-green:#38d521;
--blue-600:#0f6fa8;--blue-700:#0b5480;--red-600:#d81e3f;--green-600:#17875a;--amber-600:#8a5606;--amber-fill:#c07a12;
--div-1:#c8102e;--div-2:#e8845a;--div-3:#f0dcc0;--div-4:#bcd9cf;--div-5:#4f9e8c;--div-6:#125e57;
--scale-short:var(--div-1);--scale-balanced:var(--div-3);--scale-spare:var(--div-5);
--layer-library:#0e7c86;--layer-park:#218a4e;--layer-health:#d81b74;--layer-city:#6d3fb0;
--font-sans:"IBM Plex Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
--font-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
--content-max:1040px;--reading-max:720px;--wide-max:1240px;
--ease:cubic-bezier(.2,0,0,1);
}

/* ── Base ──────────────────────────────────────────────────────────────── */
*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased}
body{margin:0;background:var(--white);color:var(--ink-600);font:400 16px/1.6 var(--font-sans);text-wrap:pretty}
h1,h2,h3,h4{color:var(--ink-900);margin:0}
a{color:var(--blue-600);text-decoration:none;transition:color 120ms var(--ease),border-color 120ms var(--ease)}
a:hover{color:var(--ink-900)}
a:focus-visible,button:focus-visible,summary:focus-visible{outline:2px solid var(--blue-600);outline-offset:3px}
::selection{background:#cfe7f3;color:var(--ink-900)}
img{max-width:100%;display:block}

.wrap{width:min(100% - 40px,var(--content-max));margin:0 auto}
.wrap-reading{width:min(100% - 40px,var(--reading-max));margin:0 auto}
.wrap-wide{width:min(100% - 40px,var(--wide-max));margin:0 auto}
.skip{position:absolute;left:12px;top:-80px;background:#fff;padding:8px;z-index:9}
.skip:focus{top:8px}
.stack{display:grid;gap:60px}

/* ── Wordmark & top bar ────────────────────────────────────────────────── */
.topbar{border-bottom:1px solid var(--line);background:var(--white)}
.topbar .wrap{display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap;padding:14px 0}
.mark{display:inline-flex;align-items:center;gap:10px;font:500 13px/1 var(--font-mono);letter-spacing:.04em;text-transform:uppercase;color:var(--ink-900)}
.mark:hover{color:var(--ink-900)}
.mark i{width:7px;height:7px;border-radius:50%;display:block}
.mark .dots{display:flex;gap:3px}
.mark .dots i:nth-child(1){background:var(--brand-blue)}
.mark .dots i:nth-child(2){background:var(--brand-red)}
.mark .dots i:nth-child(3){background:var(--brand-green)}
/* Five links fill a 375px phone's column; on a narrower screen the nav wraps to a second
   row, each link whole, rather than scrolling the page sideways. */
.topnav{display:flex;flex-wrap:wrap;gap:8px 20px;font:400 12.5px/1 var(--font-mono)}
.topnav a{color:var(--ink-500);white-space:nowrap}
.topnav a:hover{color:var(--ink-900)}

/* ── Title block ───────────────────────────────────────────────────────── */
/* A page's h1 and what introduces it: the first item of <main>, so the skip link
   lands on it and reader views keep it. It is a <div> whose class names no
   "header", because Readability drops such blocks. Three variants, for a page
   (the homepage, About, the 404), a project or dataset page, and an article. */
.title-block{padding:56px 0 0}
.tag-signal{display:inline-flex;align-items:center;gap:8px;font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--green-600)}
/* The signal dot is round, like the wordmark dots: a recorded exception to square corners. */
.tag-signal::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--green-600);box-shadow:0 0 0 3px rgba(23,135,90,.14)}
.title-block h1{margin:18px 0 0;font:600 clamp(34px,5.2vw,58px)/1.08 var(--font-sans);letter-spacing:-.03em;max-width:22ch}
.lede{margin:20px 0 0;max-width:52ch;font-size:19px;line-height:1.55;color:var(--ink-600)}
/* The page's finding in a sentence, after the lede, each figure a fact. Not a caveat. */
.answer{margin:18px 0 0;max-width:62ch;font-size:16.5px;line-height:1.6;color:var(--ink-700)}
.meta-line{margin:18px 0 0;display:flex;flex-wrap:wrap;gap:8px;font:400 12.5px/1.5 var(--font-mono);color:var(--ink-500)}
.meta-line .sep{color:var(--line-mid)}

/* ── Section heads ─────────────────────────────────────────────────────── */
.section-head{display:flex;align-items:baseline;gap:12px;margin:0 0 20px}
.section-head h2{display:flex;align-items:baseline;gap:10px;margin:0;font:500 12px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-900);white-space:nowrap}
.section-head .n{color:var(--red-600)}
.section-head::after{content:"";flex:1;height:1px;background:var(--line)}
/* The aside may wrap, so a long heading and its aside never widen a phone's page. */
.section-head .aside{order:1;font:400 12.5px/1.4 var(--font-mono);color:var(--ink-500);text-align:right}
.label{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-900)}
.label-muted{color:var(--ink-500)}

/* ── Buttons & chips ───────────────────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;gap:7px;padding:9px 14px;border:1px solid var(--ink-900);background:var(--ink-900);color:var(--white);font:500 12.5px/1 var(--font-mono);letter-spacing:.04em;cursor:pointer;border-radius:0;transition:background-color 120ms var(--ease),border-color 120ms var(--ease),color 120ms var(--ease)}
.btn:hover{background:var(--blue-600);border-color:var(--blue-600);color:var(--white)}
.btn-ghost{background:var(--white);color:var(--ink-900);border-color:var(--line-strong)}
.btn-ghost:hover{background:var(--white);color:var(--ink-900);border-color:var(--ink-900)}
.btn-sm{padding:7px 11px}
.btn[disabled],.btn[aria-disabled=true]{opacity:.4;cursor:not-allowed}
.btn-row{display:flex;flex-wrap:wrap;gap:8px}
.chip{display:inline-flex;align-items:center;padding:5px 8px;border:1px solid var(--line-strong);font:400 11.5px/1 var(--font-mono);letter-spacing:.04em;color:var(--ink-600)}
.chip-accent{color:var(--blue-600);border-color:#b9d5e6}
.chip-warn{color:var(--amber-600);border-color:#e7d3ae}
.chip-row{display:flex;flex-wrap:wrap;gap:6px}

/* ── Project card ──────────────────────────────────────────────────────── */
.project-card{border:1px solid var(--line);display:grid;grid-template-columns:minmax(0,1fr) minmax(250px,300px)}
.project-card.no-panel{grid-template-columns:minmax(0,1fr)}
.project-card .body{padding:24px}
.project-card h3{margin:0 0 10px;font:600 24px/1.25 var(--font-sans);letter-spacing:-.02em}
.project-card h3 a{color:var(--ink-900)}
.project-card h3 a:hover{color:var(--blue-600)}
.project-card p{margin:0;max-width:52ch;font-size:15.5px;color:var(--ink-600)}
.project-card .chip-row{margin:16px 0 0}
.project-card .btn-row{margin:20px 0 0}
.project-card .panel{border-left:1px solid var(--line);background:var(--wash);padding:20px}
/* The whole body is the link. The title's anchor is stretched over the body
   rather than wrapping it in a second <a>, which would nest the buttons inside
   a link; the buttons and chips are lifted above that overlay so each still
   goes where it says. One real link, so the keyboard tab order and the screen
   reader both still see a single titled destination. */
.project-card .body{position:relative}
.project-card .body:hover h3 a{color:var(--blue-600)}
.project-card h3 a::after{content:"";position:absolute;inset:0}
.project-card .body .chip-row,
.project-card .body .btn-row{position:relative}

/* Compact list — switch to this once there are ~6+ projects */
.project-table{border-top:1px solid var(--line)}
.project-table a{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:20px;align-items:baseline;padding:15px 0;border-bottom:1px solid var(--line);color:var(--ink-900)}
.project-table a:hover{color:var(--blue-600)}
.project-table .t{font:500 19px/1.35 var(--font-sans);letter-spacing:-.02em}
.project-table .topic{font:400 11.5px/1 var(--font-mono);letter-spacing:.04em;text-transform:uppercase;color:var(--ink-500)}
.project-table .date{font:400 12.5px/1 var(--font-mono);color:var(--ink-500);white-space:nowrap}

/* ── Data readouts ─────────────────────────────────────────────────────── */
.panel-label{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-500);margin-bottom:14px}
.bars{display:grid;gap:9px}
.bar{display:grid;grid-template-columns:80px 1fr 46px;align-items:center;gap:10px;font:400 11.5px/1 var(--font-mono);color:var(--ink-600)}
.bar .track{height:7px;background:#e7ebed;position:relative;display:block}
.bar .track i{position:absolute;inset:0 auto 0 0;display:block;background:var(--blue-600)}
.bar .v{text-align:right;color:var(--ink-900);font-variant-numeric:tabular-nums}
.fill-spare{background:var(--scale-spare)!important}
.fill-short{background:var(--scale-short)!important}
.fill-neutral{background:var(--line-mid)!important}

.stat-rows{margin:0;display:grid;gap:7px}
.stat-rows div{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font:400 12.5px/1.4 var(--font-mono)}
.stat-rows dt{color:var(--ink-600)}
.stat-rows dd{margin:0;color:var(--ink-900);font-variant-numeric:tabular-nums}
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.stat-grid>div{background:var(--white);padding:16px 18px}
.stat-grid>div>b{display:block;font:500 28px/1.1 var(--font-mono);letter-spacing:-.02em;color:var(--ink-900);font-variant-numeric:tabular-nums}
.stat-grid>div>span{display:block;margin-top:5px;font:400 11.5px/1.4 var(--font-mono);letter-spacing:.04em;text-transform:uppercase;color:var(--ink-500)}
.stat-strip{margin:0;display:flex;flex-wrap:wrap;gap:8px;font:400 12.5px/1.5 var(--font-mono);color:var(--ink-500)}
.stat-strip b{color:var(--ink-900);font-weight:400;font-variant-numeric:tabular-nums}
.stat-strip .sep{color:var(--line-mid)}
.mono-num{font-family:var(--font-mono);font-variant-numeric:tabular-nums}

/* ── Caveats, disclosures, repro ───────────────────────────────────────── */
.caveat{background:var(--wash);border-left:2px solid var(--red-600);padding:14px 16px;max-width:68ch}
.caveat .k{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--red-600);margin-bottom:8px}
.caveat p{margin:0;font-size:15.5px;line-height:1.6;color:var(--ink-600)}
.caveat-amber{border-left-color:var(--amber-600)}
.caveat-amber .k{color:var(--amber-600)}

details.disclose{border-top:1px solid var(--line)}
details.disclose summary{display:flex;align-items:baseline;gap:12px;padding:14px 0;cursor:pointer;font:500 15.5px/1.4 var(--font-sans);color:var(--ink-900);list-style:none}
details.disclose summary::-webkit-details-marker{display:none}
details.disclose summary::before{content:"+";font:600 14px/1 var(--font-mono);color:var(--blue-600);width:12px;flex:none}
details.disclose[open] summary::before{content:"−"}
details.disclose .d{padding:0 0 16px 24px;font-size:15.5px;color:var(--ink-600);max-width:68ch}

.repro{border-top:1px solid var(--line);padding-top:14px}
.repro .k{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-500);margin-bottom:10px}
.repro ul{list-style:none;margin:0;padding:0;display:grid;gap:7px}
/* A note too long for its row drops under its link and wraps, rather than widening the page. */
.repro li{display:flex;flex-wrap:wrap;justify-content:space-between;gap:2px 14px;font:400 12.5px/1.5 var(--font-mono)}
.repro .note{color:var(--ink-500)}
/* The citation under the repro trio: one generated sentence, set like the trio. */
.cite{margin-top:18px;border-top:1px solid var(--line);padding-top:14px}
.cite .k{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-500);margin-bottom:10px}
.cite p{margin:0;max-width:var(--reading-max);font:400 12.5px/1.6 var(--font-mono);color:var(--ink-600);overflow-wrap:break-word}

/* A generated summary table, inside a disclosure. The wrapper scrolls sideways on
   a narrow screen so the page never does. .t marks the text columns (area names). */
.data-table{overflow-x:auto;margin-top:4px}
details.disclose .d:has(> .data-table){max-width:none}
.data-table table{width:100%;border-collapse:collapse;font:400 12.5px/1.45 var(--font-mono);color:var(--ink-600);font-variant-numeric:tabular-nums}
.data-table caption{caption-side:top;text-align:left;max-width:68ch;padding:0 0 12px;font:400 14px/1.55 var(--font-sans);color:var(--ink-500)}
.data-table th,.data-table td{padding:6px 0 6px 14px;border-bottom:1px solid var(--line);text-align:right;vertical-align:baseline}
.data-table th:first-child,.data-table td:first-child{padding-left:0}
.data-table thead th{font-weight:500;color:var(--ink-900);vertical-align:bottom;border-bottom-color:var(--line-strong)}
.data-table th[scope=row]{font-weight:400;color:var(--ink-900);white-space:nowrap}
.data-table .t,.data-table th[scope=row]{text-align:left}
/* An ISO date would otherwise break at its hyphens in a narrow column or a phone-width line:
   every <time>, and the facts whose display is a date. */
time,[data-fact$=".release"],[data-fact$=".coverage.end"],[data-fact$=".snapshot_date"]{white-space:nowrap}

/* ── Editorial ─────────────────────────────────────────────────────────── */
/* An article's title block: .title-block.title-block-article. */
.title-block.title-block-article{padding:0;max-width:var(--reading-max)}
.kicker{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--red-600)}
.title-block.title-block-article h1{margin:16px 0 0;font:600 clamp(30px,4.2vw,44px)/1.14 var(--font-sans);letter-spacing:-.03em;max-width:none}
.standfirst{margin:18px 0 0;font-size:19px;line-height:1.55;color:var(--ink-600)}
.byline{margin:20px 0 0;padding-top:14px;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:8px;font:400 12.5px/1.4 var(--font-mono);color:var(--ink-500)}
.byline .sep{color:var(--line-mid)}
.prose{max-width:var(--reading-max);font-size:16px;line-height:1.7;color:var(--ink-600);display:grid;gap:20px}
.prose p{margin:0}
.pullquote{margin:0;padding:4px 0 4px 22px;border-left:2px solid var(--brand-red);max-width:40ch}
.pullquote blockquote{margin:0;font:500 clamp(20px,2.6vw,26px)/1.32 var(--font-sans);letter-spacing:-.02em;color:var(--ink-900)}
.pullquote figcaption{margin-top:10px;font:400 12.5px/1.4 var(--font-mono);color:var(--ink-500)}

/* An article section: a sentence-length heading over a column of prose. The
   .section-head rule cannot hold one - it is a nowrap mono label - so a page
   that runs an argument past its apparatus needs this instead. Numbered
   .section-head rules still mark the map and the sources on such a page; the
   prose between them reads as prose. */
.article-section{max-width:var(--reading-max)}
.article-section > h2{margin:0 0 20px;font:600 clamp(23px,2.7vw,28px)/1.25 var(--font-sans);letter-spacing:-.025em;color:var(--ink-900)}
/* .prose is a grid, so its gap sets the space between every block. A heading
   wants more above it than below, which the margins here borrow back. */
.prose h3{margin:8px 0 -6px;font:600 18px/1.4 var(--font-sans);letter-spacing:-.01em;color:var(--ink-900)}
.prose ol,.prose ul{margin:0;padding-left:22px;display:grid;gap:14px}
.prose strong{font-weight:600;color:var(--ink-900)}
.prose .disclose-list{margin-top:0}
.series-nav{margin:0;padding-top:16px;border-top:1px solid var(--line);font:400 12.5px/1.6 var(--font-mono);color:var(--ink-500);max-width:var(--reading-max)}

figure.fig{margin:0;border:1px solid var(--line);max-width:var(--reading-max)}
figure.fig.wide{max-width:none}
figure.fig .fh{display:flex;justify-content:space-between;gap:16px;padding:11px 14px;border-bottom:1px solid var(--line);font:500 11.5px/1.3 var(--font-mono);letter-spacing:.04em;text-transform:uppercase;color:var(--ink-500)}
figure.fig .fh .what{color:var(--ink-900)}
figure.fig .fb{background:var(--wash-deep)}
figure.fig figcaption{padding:11px 14px;border-top:1px solid var(--line);font-size:12.5px;line-height:1.6;color:var(--ink-500)}

/* ── Contact ───────────────────────────────────────────────────────────── */
/* Two appearances of one address: a mono line under the page header, and the
   numbered section at the foot of the page. */
.contact-line{margin:14px 0 0;display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;font:400 12.5px/1.5 var(--font-mono)}
.contact-line .k{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-500)}
.contact-block{border:1px solid var(--line);padding:20px;max-width:var(--reading-max)}
.contact-block p{margin:0;font-size:15.5px;color:var(--ink-600)}
.contact-block .addr{margin-top:12px;font:500 17px/1.3 var(--font-mono)}

.writing-list{border-top:1px solid var(--line)}
.writing-list a{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 24px;align-items:baseline;padding:18px 0;border-bottom:1px solid var(--line);color:var(--ink-900)}
.writing-list a:hover{color:var(--blue-600)}
.writing-list .t{font:500 19px/1.4 var(--font-sans);letter-spacing:-.02em;max-width:52ch}
.writing-list .t span{color:var(--blue-600)}
.writing-list .m{display:flex;gap:8px;font:400 12.5px/1.4 var(--font-mono);color:var(--ink-500);white-space:nowrap}
.writing-list .sep{color:var(--line-mid)}

/* ── How I work band ───────────────────────────────────────────────────── */
.band{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.band > div{background:var(--white);padding:20px}
.band h3{font:500 11.5px/1 var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-900);margin:0 0 10px}
.band p{margin:0;font-size:15.5px;color:var(--ink-600)}

/* ── Map ───────────────────────────────────────────────────────────────── */
.mapframe{display:block;width:100%;height:640px;border:1px solid var(--line);background:var(--wash-deep)}
/* A framed chart page that reports its own height (cub:frame-height); the heights here are the no-script fallback. */
.chartframe{display:block;width:100%;height:1180px;margin-top:20px;border:0;background:var(--white)}

/* ── Footer ────────────────────────────────────────────────────────────── */
.site-footer{border-top:1px solid var(--line);padding:22px 0 52px;display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font:400 12.5px/1.6 var(--font-mono);color:var(--ink-500)}
.site-footer a{color:var(--ink-500)}
.site-footer a:hover{color:var(--ink-900)}
.site-footer p{margin:0}
.site-footer .links{display:flex;gap:20px;flex-wrap:wrap}

/* ── Responsive ────────────────────────────────────────────────────────── */
@media(max-width:860px){
.project-card{grid-template-columns:minmax(0,1fr)}
.project-card .panel{border-left:0;border-top:1px solid var(--line)}
}
@media(max-width:600px){
.wrap,.wrap-reading,.wrap-wide{width:calc(100% - 32px)}
.title-block{padding-top:36px}
.stack{gap:44px}
/* The title block keeps the 60px it had above the first section before it moved into <main>. */
main.stack>.title-block{margin-bottom:16px}
.project-card .body{padding:20px}
.project-table a,.writing-list a{grid-template-columns:minmax(0,1fr);gap:6px}
/* Taller than the phone on purpose. The pothole map stacks its layer controls, the map (38% of
   the frame's height, so a taller frame grows it too), its period buttons, its ranked list's
   head and rows, and a panel pinned to the frame's bottom that covers whatever reaches it. The
   frame is tall enough for the controls, the map, the period buttons, the list head, one full
   row and the panel: 980px from a 375px screen up, where the controls take two fewer rows, and
   1110px below it (measured 2026-09-25: at 960px the panel hid the list head and first row on a
   320px screen, and 5px of the first row at 375px). The schools map keeps a fixed-height map on a
   phone and shows more of its panel; the energy map scrolls within the frame. */
.mapframe{height:980px}
.chartframe{height:2250px}
}
@media(max-width:374px){.mapframe{height:1110px}}
@media(prefers-reduced-motion:reduce){*{transition:none!important;scroll-behavior:auto}}

/* ── Page composition ──────────────────────────────────────────────────── */
/* The rhythm the production drop carried as inline style= attributes. Kept as
   classes so spacing is edited in one place rather than per element. */
/* <main> opens with the title block, so the stack's own gap sets the 60px between
   the title block and the first section; <main> needs no margin of its own. */
/* A grid item will not shrink below its content, so a wide table would widen the
   whole section on a phone; this lets the table's own wrapper scroll instead. */
.stack>*{min-width:0}
/* The 404's spacing, which it once carried as inline style= margins. */
.not-found .btn-row{margin-top:28px}
.not-found + .site-footer{margin-top:80px}
.project-card + .project-card,
.project-card + .caveat{margin-top:20px}
.panel-split{margin-top:20px;padding-top:16px;border-top:1px solid var(--line-strong)}

/* ── Project page ──────────────────────────────────────────────────────── */
/* Surfaces the home page does not use: the back/section nav above a project
   title, the guidance disclosure above a map, and the caption under it. */
.project-nav{display:flex;flex-wrap:wrap;gap:20px;padding:28px 0 0;font:400 12.5px/1 var(--font-mono)}
.project-nav a{color:var(--ink-500)}
.project-nav a:hover{color:var(--ink-900)}
/* A project or dataset page's title block: .title-block.title-block-project. */
.title-block.title-block-project{padding:24px 0 0}
.title-block.title-block-project h1{margin:16px 0 0;font:600 clamp(30px,4.4vw,48px)/1.1 var(--font-sans);letter-spacing:-.03em;max-width:20ch}
.map-note{margin:18px 0 0;max-width:68ch;font-size:15.5px;color:var(--ink-600)}
.map-caption{margin:12px 0 0;font:400 12.5px/1.6 var(--font-mono);color:var(--ink-500)}
.map-link{margin:14px 0 0;font:400 12.5px/1 var(--font-mono)}
.mapframe{margin-top:20px}
.disclose-list{margin-top:4px;border-bottom:1px solid var(--line)}
/* min(): on a 320px screen the column is narrower than 260px, and the grid must not widen the page. */
.download-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:7px;padding:0 0 16px 24px}
.download-grid a{font:400 12.5px/1.5 var(--font-mono)}
.status-note{margin:16px 0 0;font:400 12.5px/1.6 var(--font-mono);color:var(--amber-600)}
.map-caption + .caveat{margin-top:18px}
.caveat + .disclose-list{margin-top:16px}
/* A dataset page puts a .repro list under a caveat or a note, where a project page has a disclosure list. */
.map-note + .repro,.caveat + .repro{margin-top:18px}
/* Key figures at the foot of a page header: three to a row in the article's column, and with
   .stat-grid-3 where a figure's display carries a unit ("57.3 billion kBtu") too long for six. */
.title-block .stat-grid{margin-top:24px}
.title-block-article .stat-grid,.stat-grid-3{grid-template-columns:repeat(auto-fit,minmax(max(200px,calc((100% - 2px) / 3)),1fr))}
.stat-grid + .meta-line{margin-top:12px}
details.disclose .d ul{margin:0;padding-left:18px;display:grid;gap:8px}
/* A long unbroken link (a DOI) may break, or it would widen the list's grid column past a phone's screen. */
details.disclose .d li{padding-left:2px;overflow-wrap:anywhere}
details.disclose .d p{margin:0}
details.disclose .d code{font:400 12.5px/1 var(--font-mono);color:var(--ink-900)}
