/* ptp.css. The shared design system for peopletopolicy.com. One stylesheet,
   linked by every page, so the pages stay consistent. AAA throughout.

   2026-08-23, Marc: one reading column for the whole page. The heading, the
   subhead, the eyebrow and the body all share one left edge and one right edge,
   the header sits on those same two edges, and the menu spans them. Headings are
   left-aligned again; the centred hero of 2026-08-22 is gone on his word. The
   mockup that settled it was mockup-header-heading-2026-08-23/ at the repo root. */
:root{
  --sand:#F5EDDC; --sand-dk:#E8DCC8; --sand-dkr:#D4C8AE;
  --parch:#FAF4E8; --rose:#7A1540; --rose-lt:#5C2A3A; --rose-xlt:#F7EAF0;
  --mauve:#2A0040; --mauve-lt:#3D0058; --mauve-xlt:#EDE4F5;
  --green:#1F4D3D; --ink:#1A0A10; --white:#FFFFFF;
  /* A FORM FIELD'S EDGE IS NOT DECORATION (added 2026-08-20, measured).
     WCAG 1.4.11 asks 3:1 for the boundary that tells you a control is a
     control. Fields were drawn in --sand-dkr, the decorative card colour,
     which lands at 1.51:1 on parchment and 1.66:1 on white, and the fields
     are white on near-white so the fill says nothing either. This token is
     the same warm family darkened until it clears the bar: 4.10:1 on white,
     3.74:1 on parchment, 3.52:1 on sand. Cards and rules keep --sand-dkr,
     because decoration is not held to this bar. */
  --field-edge:#8C7B62;
  /* TWO ORANGES, AND THE SPLIT IS LOAD-BEARING (locked 2026-08-20 after a full
     AAA sweep). --orange is for fills, borders, dots and accents ONLY. Never put
     letters on it or in it. --orange-text is the one for type.
     Why it cannot be a single token: to carry small dark text at AAA's 7:1 the
     orange needs luminance >= 0.360, and to sit on the light slide at the 3:1
     non-text bar it needs luminance <= 0.173. No colour is both, so THREE tokens
     carry the one brand orange, each for the job it can actually pass:
       --orange       fills, borders and dots on DARK surfaces. Never carries type.
       --orange-text  type on dark surfaces, and any fill that has type on it.
       --orange-deep  fills, borders and dots on LIGHT surfaces. Worst case 4.06:1
                      on the deck's tan slide, against a 3:1 bar.
     Measured, not judged by eye. */
  --orange:#FF7A4D; --orange-text:#FF9D72; --orange-deep:#A63D0B;
  --display:Georgia,'Palatino Linotype',Palatino,serif;
  --body:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif;
  /* --inner narrowed 1200px -> 980px (Marc 2026-07-21): one shared content spine so
     the text, the controls, the feedback box and the footer all read as one column on
     desktop instead of drifting on separate axes. Buttons were centered under that
     2026-07-21 rule; Marc left-aligned them on 2026-08-14, so a control now lines up
     with the left edge of the text it belongs to and centering is opt-in via .center. */
  --banner-h:68px; --inner:min(980px,92vw); --measure:52ch;  /* NOT 64: ch is the width of a zero, which is far narrower than
     an average letter here, so 64ch rendered as 92 to 105 real characters against
     WCAG 1.4.8's limit of 80. Measured with canvas text metrics, 2026-08-20.
     Re-measured 2026-08-21 by a stricter method, a range placed around every
     glyph and the results grouped into line boxes: 52ch renders 80 characters at
     1440, which IS the limit, with nothing spare. Raising it to 54ch put 7 lines
     over on ten text-heavy pages; at 56ch the count was 49; at 64ch it was 433.
     Treat 52 as a ceiling that has been tested, not a number somebody liked. */
  /* ── THE RIGHT EDGE: two boundaries in a band, not four (2026-08-21) ────────
     Marc, this morning: the heading and the subheading "do not go all the way
     out to the last word in the menu to the far right", meaning the right
     margin rather than the screen edge.

     The containers were never the problem. .banner-inner and .s-inner share
     --inner and the same padding, so the nav's last item and every band's
     content box end on the same pixel: 1170 at 1440, 706.55 at 768. Measured on
     24 pages at five widths, every LEFT edge already agreed.

     What scattered was the caps INSIDE that box. One band at 1440 could hold
     four right boundaries: the eyebrow at 1170 because nothing capped it, the
     heading at 976.8 from 24ch of the display face at 42px, a lede at 976.4
     from 52ch of the body face at 22px, body prose at 858.6 from 52ch of the
     body face at 18px. Of 68 bands holding two or more of those, 4 lined up.
     Those 4 lined up by luck: a ch is the width of a zero, so a cap written in
     ch of one face at one size can meet a cap in ch of another face at another
     size only by coincidence, which then breaks at the next width.

     Prose could not be the thing that moved. --measure is not a taste; it is
     WCAG 1.4.8's 80-character limit carried in the one unit that tracks font
     size. The note above records that it is already at that limit, so body
     prose reaches about 65% of the column at 1440 and no cap can widen it.
     Filling the column with 18px text would run near 110 characters.

     The headings moved instead. Heading text is short: the longest heading line
     on the site measured 34 characters against a limit of 80, so the cap was
     buying no readability at all. Headings now take the whole content column,
     which lands their right edge on the nav's right edge by construction at
     every width. Their longest line now measures 43 characters. That leaves a
     band with two boundaries, each of which means something: the column edge
     for labels and headings, the reading measure for prose.

     Never give a heading a max-width again. Never raise --measure without
     re-running the glyph count first.

     THIS RULE STILL HOLDS for every .head heading in the body of a page. It
     does NOT hold for .hero h1, as of the next day (2026-08-22): see
     --hero-col below, and .hero h1 / .hero .lede further down this file. */
  /* ── --hero-col: the hero heading and its lede share ONE edge (2026-08-22) ──
     A screenshot on a desktop screen showed the hero heading running the full
     content column while the lede stopped hundreds of pixels short of it,
     the two boundaries above producing a lopsided block on wide screens even
     though each boundary is individually correct. Marc compared it against
     anthropic.com and codeforamerica.org, live: neither site caps a heading's
     own text measure either. Anthropic puts its heading in a narrower GRID
     COLUMN (655 of 1145px, measured 2026-08-22). Code for America gives the
     whole hero a narrower, centered column that the heading and the standfirst
     both simply live inside. Both solve it by narrowing the BOX the heading
     sits in, never the heading's own ch measure, so the two-boundary rule above
     is not being reversed, only given a third, deliberate boundary that ONLY
     applies inside .hero.

     --hero-col is that third boundary. Below it, .hero h1 and .hero .lede
     share an identical max-width in px, which is what actually makes two
     elements of different font sizes line up: a ch cap cannot do this,
     because ch is relative to the element's OWN font size, so 52ch at the
     lede's ~22px font and 52ch at the heading's ~68px font are two very
     different pixel widths. The lede keeps its WCAG 1.4.8 ceiling
     unconditionally via min(--measure, --hero-col): --hero-col can only make
     it NARROWER than 52ch, never wider.

     Measured 2026-08-22 across the site's 15 .hero pages, the whole viewport
     range, in JS against the live formulas for --inner and its padding, before
     touching this file: the floor (400px) sits above the widest phone
     container in real use (360px at a 428px viewport), so every phone from
     320 to 428px computes IDENTICAL heading and lede widths to before this
     change, unnarrowed. The fluid middle (58vw) starts narrowing at tablet
     widths, which is where the lopsided look was reported. The ceiling (620px)
     is where a 1280px screen's lede already landed under 52ch, so nothing
     that fit before stops fitting now; the heading simply joins it there
     instead of overshooting past it. Re-run the same JS sweep before ever
     changing these three numbers again; do not tune them by eye alone.

     CENTERED THE SAME DAY, once --hero-col actually reached a browser (the
     first deploy edited ptp.css but never bumped ptp.css?v=13, so nobody saw
     it until v14). With --hero-col narrower than the column, a left-aligned
     heading and lede sat flush against the LEFT edge with the whole leftover
     width piling up on the right, a 280px imbalance measured live at 1280px.
     Marc named it directly: he wants the margin split evenly, the way
     codeforamerica.org's hero does it, on every device, not just this one
     width. .hero h1 and .hero .lede now center inside --hero-col.

     THIS DOES NOT REOPEN THE 2026-08-14 BUTTON-ROW RULE two rules below,
     which left-aligns .btn-row and says "do not add per-page alignment
     overrides." That rule is about CONTROLS lining up with a left text edge;
     this one is about the hero's OWN heading and lede lining up with EACH
     OTHER, centered, the way --hero-col's box is centered in the column. If
     a hero ever gains a button row, decide that placement separately rather
     than assuming either rule answers it. */
  --hero-col: clamp(400px, 58vw, 620px);
  /* ── MOCKUP 2026-08-23: --text-col, the SAME column for the whole page ──────
     Marc, 2026-08-23, two complaints that turn out to be one: "at 100% it sits
     to the left", and "notice how this text juts far out to the right", about a
     section heading.

     MEASURED at 1280px on the live site. Inside a content band running 190 to
     1090, a section heading ran the whole 900px to 1090 while the paragraph
     under it stopped at 779. So the heading overshot its own prose by 311px,
     which is the jutting, and the prose filled only 65% of the band from the
     left, which is the left-weighting. One cause, two symptoms.

     WHY THIS KEPT OSCILLATING, and it is worth writing down. On 2026-08-21 the
     caps were taken OFF headings deliberately, so they would reach the column
     edge. That fixed a band with four ragged right boundaries and it created
     this one. Putting the caps back would fix the jutting and make the
     left-weighting worse, because prose cannot widen: --measure is at WCAG
     1.4.8's 80-character limit already, measured by glyph count, so the empty
     right side of the band cannot be filled with text. Moving the caps can only
     trade one symptom for the other. The band itself had to change.

     THE ANSWER TO WHAT MARC ACTUALLY ASKED, "how do we make the margins the
     same without centering the text": centre the BLOCK, not the text. A block
     with margin-inline:auto sits centred in the band while the words inside it
     stay ranged left. Even margins, left-aligned text, no centred prose.

     --text-col is that block, and it is deliberately the same formula as
     --hero-col, so the hero and every section below it share ONE column down
     the whole page. Prose still stops at --measure inside it, about 31px short
     at 1280, which is a ragged edge of one word rather than of 311px. */
  --text-col: clamp(400px, 58vw, 620px);
  /* FOUR GAPS, WIDEST TO TIGHTEST, AND NOTHING ELSE (--gap-sec and --gap-blk locked
     2026-06-28; --gap-hd and --gap-txt added 2026-08-21 to finish the model inside a
     band). The ladder holds at every width: sec > hd > blk > txt. Measured at 375px
     they are 28, 22, 16 and 14. At 1440px they are 48, 32, 24 and 18. The two new
     ones exist because a phone had no room left to tell a new heading from a
     paragraph carrying on: --gap-blk alone put 2px between those two meanings, which
     no reader can tell apart. With --gap-hd the difference is 8px on a phone and 14px
     on a laptop. */
   --gap-sec:clamp(28px,3.4vw,48px);
  --gap-hd:clamp(22px,2.6vw,32px);  /* space ABOVE a heading that opens a new part of a band */
  --gap-blk:clamp(16px,2vw,24px); /* space between a heading and the block beneath it (one knob, all pages) */
  --gap-txt:clamp(14px,1.5vw,18px); /* space between two paragraphs of prose, the one gap smaller than a block */
}
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
/* Dark canvas behind everything: stops the white flash in mobile tab-switch snapshots
   and dark-page overscroll (Marc 2026-07-07). Matches theme-color. */
html{background:#2A0040}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;text-size-adjust:100%;overflow-x:hidden;overflow-x:clip}
/* Anchor jumps must land WITH the heading readable, not hidden under the sticky banner
   (68px + 3px border). One rule, every page, every anchor target (Marc 2026-07-21). */
/* ── MOCKUP 2026-08-23: this is an ACCESSIBILITY FIX, not a layout one ────────
   WCAG 2.2 added two criteria about a focused control being covered:
   2.4.11 Focus Not Obscured (Minimum) at Level AA, which is failed when a
   focused component is ENTIRELY hidden by author content, and 2.4.12 at Level
   AAA, failed when ANY PART of it is hidden. Both Understanding documents name
   a sticky header as the classic cause, list failure F110 for it, and name
   technique C43, scroll-padding, as the sufficient fix.

   CONFIRMED ON THE LIVE SITE 2026-08-23: .banner is position:sticky, its bottom
   edge sits at 71px, and scrollPaddingTop on the document element computes to
   "auto", meaning nothing is set. Those are the exact conditions of F110. When
   the Tab key moves focus to something above the viewport, the browser scrolls
   it in with block:"nearest", which respects scroll-padding and nothing else.
   With no scroll-padding the top of the scrollport is y=0, which is underneath
   the banner, so a link shorter than 71px lands completely covered.

   WHY THE OLD RULE WAS NOT ENOUGH. scroll-margin-top on [id] only ever helped
   an element that CARRIES AN ID, which is headings and section targets. It did
   nothing for the ordinary links, buttons and form fields a keyboard user
   actually tabs through, and those are what the criterion is about.
   scroll-padding-top on the scroll container governs everything the browser
   scrolls into view: focus, anchor jumps and scrollIntoView alike.

   THE OLD RULE IS DELETED RATHER THAN LEFT BESIDE THIS ONE, and that matters.
   The two are exactly additive: keeping both overshoots every anchor jump by
   the full height of one of them, which reads as a page that scrolls too far
   and would be noticed the day after a deploy rather than during it. */
html{scroll-padding-top:calc(var(--banner-h) + 3px + 12px)}
body{font-family:var(--body);background:var(--sand);color:var(--ink);-webkit-font-smoothing:antialiased;line-height:1.65;overflow-x:hidden;overflow-x:clip;text-rendering:optimizeLegibility}
img,svg{max-width:100%;display:block}
a{color:var(--rose)}
:focus-visible{outline:3px solid var(--mauve);outline-offset:3px;border-radius:3px}
/* On dark regions the mauve outline vanishes into the background, so focus flips to
   parchment there (a11y fix 2026-08-15). More-specific rules (.fb-btn, .news input)
   keep their own outline colors. */
.banner :focus-visible,.hero :focus-visible,.on-mauve :focus-visible,.on-dark :focus-visible,.nav-menu :focus-visible,#navmenu :focus-visible,footer.site :focus-visible{outline-color:var(--parch)}
.skip-link{position:absolute;left:8px;top:8px;transform:translateY(calc(-100% - 12px));padding:10px 16px;background:var(--mauve);color:#fff;font-weight:700;border-radius:4px;z-index:9999;text-decoration:none}
.skip-link:focus{transform:none}

.draftbar{background:repeating-linear-gradient(45deg,#3D0058,#3D0058 14px,#2A0040 14px,#2A0040 28px);color:#fff;font-size:13px;line-height:1.5;padding:9px clamp(16px,4vw,40px);text-align:center}
.draftbar strong{color:var(--orange-text);letter-spacing:.04em;text-transform:uppercase;font-size:11px}

.banner{position:sticky;top:0;z-index:900;background:var(--mauve);border-bottom:3px solid var(--rose)}
/* MOCKUP 2026-08-23, Marc: the wordmark should start on the same left margin as
   the heading below it, and the menu should finish on the same right margin, so
   the whole page lives between two lines and the space is equal on both sides.

   The banner used to sit in the WIDER --inner band (190 to 1090 at 1280) while
   the reading column sits at 330 to 950. Same centre, different width, so the
   header overhung the page by 140px on each side. This makes the header's own
   content box the reading column exactly: the calc is --inner minus its two
   paddings, which is the width the grid's text column is measured against, and
   min() picks whichever of that and --text-col is narrower, which is what the
   grid does too. Both then centre in the same place at every width. */
.banner-inner{
  font-size:clamp(16px,1.8vw,22px);
  max-width:min(var(--measure),calc(var(--inner) - 2 * clamp(16px,4vw,40px)));
  margin:0 auto;padding:0;
  min-height:var(--banner-h);display:flex;align-items:center;justify-content:space-between;gap:16px}
/* The open phone menu is a full-width band, so its LIST has to be brought onto
   the same column or the menu links would sit left of the wordmark above them. */

/* 44px min, the same 2.5.5 floor as the menu links. The wordmark is a link to
   the home page and it rendered at 164 by 42, two pixels short. The banner is
   68px, so this costs no layout. Found 2026-08-20 while raising the menu. */
.wordmark{text-decoration:none;display:flex;flex-direction:column;gap:5px;min-height:44px;justify-content:center}
.wordmark b{font-family:var(--display);font-size:clamp(20px,2.6vw,27px);font-weight:600;color:#fff;letter-spacing:-.01em;line-height:1}
.wordmark .dot{font-family:var(--display);font-weight:700;font-size:1.22em;line-height:0;color:#fff}
.wordmark span.sub{font-size:10px;letter-spacing:clamp(0.25px,calc(0.884vw - 6.549px),2.63px);text-transform:uppercase;color:rgba(255,255,255,.74);font-weight:700}
.nav-inline{list-style:none;display:none;gap:clamp(12px,1.6vw,22px);align-items:center}
/* 44px minimum, WCAG 2.5.5 (measured 2026-08-21 at 15.0px tall on every page). The August
   sweep fixed the mobile menu to 313x44 and never measured this row, because the inline nav
   only appears above 1040px. inline-flex plus min-height grows the hit area without moving
   the text: the banner is a fixed 68px and these links centre inside it. */
.nav-inline a{font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.74);text-decoration:none;white-space:nowrap;display:inline-flex;align-items:center;min-height:44px}
.nav-inline a:hover,.nav-inline a[aria-current="page"]{color:#fff}
/* A REAL EDGE ON THE TWO FILLED BRAND BUTTONS (Marc, 2026-08-20).
   Rose on the mauve banner is 1.71:1, and rose on the near-black footer is
   1.83:1, so the button's SHAPE was not discernible even though its white text
   was. WCAG passes a control identified by its text, which is why this was a
   choice rather than a defect. Marc chose the edge. Parchment measures 16.35:1
   against the banner, 17.51:1 against the footer and 9.54:1 against the rose
   fill it surrounds, so the edge clears 1.4.11 on both sides of itself.
   box-sizing is border-box, so the 2px costs height nowhere. */
.nav-cta{background:var(--rose);color:#fff !important;padding:11px 20px;border:2px solid var(--parch);border-radius:4px;min-height:44px;display:inline-flex;align-items:center}
.nav-cta:hover{background:var(--mauve-lt)}
.nav-toggle{width:44px;height:44px;background:transparent;border:1px solid rgba(255,255,255,.4);border-radius:4px;cursor:pointer;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}
.nav-toggle-bar{width:20px;height:2px;background:#fff;border-radius:2px;transition:transform .25s,opacity .2s}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
/* The menu lives INSIDE the <nav> element since the 2026-08-15 a11y fix, so it is
   absolutely positioned against the sticky banner to keep its full-width band look. */
.nav-menu{position:absolute;left:0;right:0;top:100%;background:var(--mauve);border-bottom:3px solid var(--rose)}
.nav-menu[hidden]{display:none}
.nav-menu ul{list-style:none;max-width:var(--inner);margin:0 auto;padding:2px clamp(16px,4vw,40px) 8px}
/* The menu box is now the reading column itself, so the list must not add its own
   horizontal padding on top: that indented every link 16px past the wordmark and
   the page text above and below it. Vertical padding stays. */
.nav-menu ul{font-size:clamp(16px,1.8vw,22px);padding-left:0;padding-right:0;max-width:none}
/* 44px, not 38. WCAG 2.5.5 asks 44 by 44 for a target, and these rendered at
   900 by 38: wide enough to hit easily, and still the wrong dimension. Raised
   2026-08-20 on Marc's word, which loosens the menu by 6px a row. */
.nav-menu a{display:flex;min-height:44px;align-items:center;color:#fff;text-decoration:none;font-family:var(--display);font-size:16px;font-weight:600;border-bottom:1px solid rgba(255,255,255,.1)}
@media(min-width:1040px){.nav-inline{display:flex}.nav-toggle{display:none}.nav-menu{display:none}}

/* ── MOCKUP 2026-08-23: the nav spreads across the top, it does not bunch to one side ──
   Marc, 2026-08-23, pointing at codeforamerica.org: "The menu option is spread
   across top. Not off to the side."

   MEASURED on the live site at 1280px before this change: the wordmark ends at
   x=411 and the first nav link starts at x=637, so 226px of the banner sat empty
   while the five links crowded the right edge.

   MEASURED on codeforamerica.org at 1600px the same day: they use TWO rows. Row
   one carries the logo (230 to 493) with two buttons far right (1117 to 1363).
   Row two is a full-width band, 230 to 1370, holding the six nav links starting
   at the SAME left edge as the logo above them.

   We carry no header buttons, so a faithful two-row copy would leave row one's
   right half empty. Layout A below is the one-row reading of the same idea: the
   nav takes the whole remaining width and distributes its links across it, so
   the last link finishes flush with the right text edge. Layout B is CfA's two
   rows exactly, reachable in this mockup at ?nav=two.

   Nothing here changes the phone view: both layouts sit inside the existing
   1040px query, and below that the hamburger behaves as it always has. */
/* REVISED 2026-08-23 after Marc: "the spacing between the menu headings is too
   much. It doesn't look nice."

   MEASURED on the first pass: justify-content:space-between stretched the five
   links across 612px and produced 60px gaps. Stretching to fill is why it
   looked wrong. Related items read as one group when the space between them is
   smaller than the space around the group, and 60px gaps broke that: five
   separate items rather than one menu.

   So the nav ends at the right text edge and its links keep a fixed, comfortable
   gap instead of being stretched to whatever the window leaves over. 34px is
   Code for America's own measured spacing on their nav row, 43px, scaled to our
   smaller 13px type. The gap no longer changes with window width, so the menu
   looks the same at 1040px as it does at 1900px. */
@media(min-width:1040px){
  .banner-inner > nav[aria-label="Primary"]{flex:1 1 auto;min-width:0;display:flex;justify-content:flex-end}
  .nav-inline{gap:clamp(22px,2.4vw,34px)}
}

/* Marc, 2026-08-23: "CfA does NOT have a sticky header. I wonder if we should?"
   ?sticky=off answers it by making ours behave like theirs. Two reasons this is
   more than taste, both in the notes at the bottom of the Learn page. */


/* Layout B, CfA's two rows exactly. The banner grows, so --banner-h grows with
   it: that variable is what [id]{scroll-margin-top} uses to stop an anchor jump
   landing underneath the sticky banner, and a taller banner with a stale
   variable would hide every heading it lands on. */
@media(min-width:1040px){
  /* 132px is the MEASURED height of .banner-inner in this layout, not an
     estimate. The one-row layout's 68px variable equals its own measured inner
     height exactly, and that equality is what makes scroll-margin-top correct.
     A first pass guessed 112px here and an anchor jump landed 20px underneath
     the banner; re-measure this number before changing anything above it. */
  :root{--banner-h:132px}
  .banner-inner{flex-wrap:wrap;align-items:center;padding-top:12px;padding-bottom:0}
  .banner-inner > nav[aria-label="Primary"]{
    flex:0 0 100%;margin-top:10px;border-top:1px solid rgba(255,255,255,.18)}
  .nav-inline{
    width:100%;gap:clamp(20px,3.4vw,52px);padding-left:0}
}

.s-inner{max-width:var(--inner);margin:0 auto;padding:0 clamp(16px,4vw,40px)}

/* MOCKUP 2026-08-23: the content grid, and the reason it is a GRID rather than a
   max-width on each element.

   The first attempt gave every prose element max-width:--text-col plus
   margin-inline:auto. MEASURED, it made things worse: each block centred itself
   INDEPENDENTLY inside the band, so a 620px heading landed at 330 while the
   589px paragraph under it landed at 346. A ragged LEFT edge of 16px, which is
   the one edge that was never broken. Centring each block separately cannot
   align blocks of different widths. Only a shared column can.

   So .s-inner becomes a three-column grid. The middle column is the reading
   column and is centred once, by the grid. Everything lands in it by default and
   therefore shares its left edge exactly. A paragraph narrower than the column
   (prose still stops at --measure, the WCAG 1.4.8 ceiling) simply ends sooner on
   the right, which is the only ragged edge left and is now about one word wide.

   Wide items opt OUT to the full band by name. minmax(0,1fr) on the side columns
   rather than 1fr: a bare 1fr has min-width:auto, so one wide child (a long
   code string, a table) can push the whole grid wider than its parent and break
   the page. This is the standard guard for that. */
/* REVISED 2026-08-23, Marc: "the body is not the same as the subheading text and
   is not the same as the head text. All of those should be the same", plus "a
   little bit too much space on both sides".

   Those are one problem again. The column was 620px while p.body kept its own
   52ch cap, which is 589px at 18px, so prose sat 31px narrower than every
   heading and the right side read as emptier than the left.

   The column is now THE READING MEASURE ITSELF, so the heading, the small label,
   the lede, the buttons and the paragraphs are all exactly one width and the
   body fills it rather than stopping short.

   HOW THE COLUMN GETS WIDER WITHOUT BREAKING THE AAA PROMISE, which is the part
   worth reading twice. WCAG 1.4.8 limits a line to 80 CHARACTERS. It says
   nothing about pixels. A ch tracks font size, so raising the body type raises
   the pixel width of the same 80 characters. The type going up is what lets the
   margins come in, and the character count does not move. It is measured below
   rather than argued.

   font-size on the spine is load-bearing, not decoration: a ch resolves against
   the element's OWN font size, so the column has to be measured at the size the
   prose is actually set in or the two land on different pixels. Scoped to main
   so footer.site, which shares .s-inner, keeps its own 14px base. */
main .s-inner{font-size:clamp(16px,1.8vw,22px)}
.s-inner{
  display:grid;
  grid-template-columns:
    [full-start] minmax(0,1fr)
    [text-start] min(var(--measure),100%) [text-end]
    minmax(0,1fr) [full-end];
}
/* The body inherits the spine size and drops its own cap, so it ends exactly
   where the heading above it ends. --measure still governs both, through the
   column, so the 80-character ceiling is enforced in one place now. */
main .s-inner > p.body{font-size:inherit;max-width:none}
.s-inner > *{grid-column:text}
.s-inner > .cards,
.s-inner > .tablewrap,
.s-inner > .maptbl,
.s-inner > .full{grid-column:full}
/* The footer sets display:block on its own .s-inner further down this file, so
   it keeps its existing layout and is untouched by any of the above. */
/* ── Vertical rhythm model (one place; no per-page spacing patches) ──────────
   Every <section> is a full-bleed colour band with symmetric inner padding
   (--gap-sec) so its content never touches the colour edge. Two rules keep the
   rhythm even on every page:
     1. the first band tucks up under the nav, so the header is not cavernous;
     2. when a band is the SAME colour as the one above it, the seam collapses
        (the lower band drops its top inset) so the two read as one continuous
        band instead of showing a doubled, empty gap. Different-colour
        neighbours keep both insets: the colour change earns the breathing room.
   The colour groups below mirror the section background classes. */
section{padding:var(--gap-sec) 0}
main>section:first-child{padding-top:clamp(16px,2.2vw,28px)}
:is(.hero,.on-mauve) + :is(.hero,.on-mauve),
:is(.on-parch,.support) + :is(.on-parch,.support),
.on-sand + .on-sand,
.on-sanddk + .on-sanddk{padding-top:0}
/* The injected feedback band (.page-fb, parch) sits after <main>, outside the sibling
   chain above, so when a page ENDS on a parch section the same-colour seam doubled.
   Same collapse rule, reaching across the main boundary. */
main:has(> :is(.on-parch,.support):last-child) + .page-fb{padding-top:0}

/* ── Inside a band: the same model, one level down (added 2026-08-21) ────────
   Everything above governs the OUTSIDE of a band. Inside a band the model
   governed nothing, so every page wrote its own numbers by hand. That is the
   whole reason the spacing kept coming back as a complaint.

   What the measurement found on 2026-08-21, before this block existed: 211
   hand-typed spacing values sat in the page files, 116 of them the identical
   style="margin-top:14px" on a paragraph. Across eight pages at one screen
   width the gap under a heading came out as 0, 12, 14, 16, 18, 22, 24 and 26
   pixels. The token said 24. One gap on the whole set of pages was 24.

   The reset zeroes every margin, so a block has no gap at all until a rule
   gives it one. The only blocks with a rule were the card grids. The rules
   below give every block a gap, on every page, from the tokens:

     Default: a block that follows another block takes --gap-blk, the same knob
     the model already named for the space under a heading. A grid of cards, a
     list of notes, a table or a panel all open the same way.

     Prose carrying on: a paragraph after a paragraph takes --gap-txt, which is
     tighter, because that is one idea continuing rather than a new block.

     A new part opening: a heading after anything takes --gap-hd, which is wider,
     because a heading is a bigger break than the block it introduces is.

   The eyebrow is a label on the heading below it and not a block above it, so
   it keeps its own bottom margin and the block after it adds nothing. Writing
   that gap as the eyebrow's own margin keeps it working on the pages that nest
   an eyebrow inside a wrapper, where a sibling rule would never reach it.

   Component rules further down this file (.hero .lede, .btn-row, .cards and the
   others) still set their own top margin and still win, by being more specific
   or by coming later. Those are the deliberate exceptions: there are few of
   them. To change spacing anywhere, edit a token or one of these rules. Never
   type a margin into a page. */
.s-inner > * + *{margin-top:var(--gap-blk)}
.s-inner > p + p{margin-top:var(--gap-txt)}
.s-inner > * + :is(h2,h3,h4,h5,h6){margin-top:var(--gap-hd)}
.s-inner > .eyebrow + *{margin-top:0}
.eyebrow{font-size:13px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--rose);margin-bottom:14px}
.on-dark .eyebrow,.on-mauve .eyebrow{color:var(--orange-text)}
/* .head, not h2.head: the tag qualifier meant an h1 carrying this class matched
   nothing, so about.html had copied all seven declarations into an inline style
   to get the look. One page-local patch, created by a selector that was one
   character too narrow. No max-width here; the block above says why. */
.head{font-family:var(--display);font-size:clamp(26px,3.8vw,42px);font-weight:700;line-height:1.18;letter-spacing:-.02em;color:var(--mauve)}
.on-dark .head{color:#fff}
.lede{font-size:clamp(18px,2.1vw,22px);line-height:1.6;max-width:var(--measure);color:var(--rose-lt)}
.on-dark .lede,.on-mauve .lede{color:rgba(255,255,255,.9)}
p.body{font-size:clamp(16px,1.5vw,18px);max-width:var(--measure);color:var(--ink)}
.on-dark p.body{color:rgba(255,255,255,.82)}
.mark{font-style:normal;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 12' preserveAspectRatio='none'><path d='M3 5 Q75 3 150 4 T297 5' fill='none' stroke='%237A1540' stroke-width='3.5' stroke-linecap='round'/></svg>");background-repeat:no-repeat;background-position:0 100%;background-size:100% .38em;padding-bottom:.12em;-webkit-box-decoration-break:clone;box-decoration-break:clone}
@media(forced-colors:active){.mark{text-decoration:underline;text-decoration-thickness:3px}}

.btn{display:inline-flex;align-items:center;gap:9px;min-height:48px;padding:14px clamp(22px,3vw,30px);border-radius:5px;font-family:var(--body);font-size:clamp(15px,1.6vw,17px);font-weight:700;letter-spacing:.03em;text-decoration:none;cursor:pointer;border:2px solid transparent;transition:transform .08s,background .15s}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--rose);color:#fff}
.btn-primary:hover{background:var(--mauve)}
.btn-ghost{background:transparent;border-color:var(--mauve);color:var(--mauve)}
.btn-ghost:hover{background:var(--mauve);color:#fff}
.on-dark .btn-primary,.on-mauve .btn-primary{background:var(--parch);color:var(--mauve)}
.on-dark .btn-primary:hover,.on-mauve .btn-primary:hover{background:#fff}
.on-dark .btn-ghost,.on-mauve .btn-ghost{border-color:rgba(255,255,255,.6);color:#fff}
.on-dark .btn-ghost:hover,.on-mauve .btn-ghost:hover{background:#fff;color:var(--mauve)}
/* Button rows line up with the text column's left edge (Marc 2026-08-14, superseding the
   2026-07-21 centering rule). Sections that want centering opt in with class="center".
   Do not add per-page alignment overrides. */
.btn-row{display:flex;flex-wrap:wrap;gap:14px;margin-top:28px;justify-content:flex-start}

/* hero */
.hero{background:var(--mauve);color:#fff;position:relative;overflow:hidden}
.hero::after{content:"";position:absolute;inset:0;background:radial-gradient(120% 90% at 85% -10%,rgba(122,21,64,.55),transparent 60%);pointer-events:none}
.hero .s-inner{position:relative;z-index:1}
/* MOCKUP 2026-08-23: LEFT, not centred. Marc: "The heading is centered and all
   the text below it is not."

   MEASURED on the live /learn at 1280px: the h1 ran 330 to 950 while every
   piece of text below it started at 190. A 140px step, on all 15 hero pages.

   The 2026-08-22 centring was added for a real reason, and that reason is not
   reopened here. It was that the h1 and its lede ended at two different right
   edges, hundreds of pixels apart, because each was capped by a different rule.
   --hero-col fixed that by capping both. Centring was the second half of that
   change and it is the half that produced today's step.

   Left alignment keeps --hero-col's shared cap and drops only the centring, so
   the hero heading now begins on the same left edge as the lede beneath it and
   every heading and paragraph further down the page. Verified against Marc's
   own reference the same day: codeforamerica.org left-aligns its h1 at x=230 on
   /about-us/ and /programs/, sharing that edge with its body copy. */
/* The hero no longer keeps a column of its own: it shares the one above, so the
   opening heading lines up with every heading further down the page. */
:is(.hero,.on-mauve) h1{font-family:var(--display);font-size:clamp(34px,6vw,68px);font-weight:700;line-height:1.08;letter-spacing:-.025em;color:#fff}
.hero h1 .tog{color:var(--orange-text);display:inline-block}
/* The lede keeps min(--measure, --hero-col) untouched: that min is what holds
   the WCAG 1.4.8 line-length ceiling unconditionally, and --hero-col can only
   ever make it narrower. Only the centring comes off. */
.hero .lede{margin-top:clamp(18px,2.5vw,26px);color:rgba(255,255,255,.9);max-width:none}
/* The small "Last updated" byline four .hero pages carry above their h1 (privacy,
   standards, terms, usage): a plain reveal paragraph, not .lede. It shares the
   hero's centered column too, so the date lines up with the heading below it
   instead of sitting at the old left edge while the heading centers. Each of
   those four paragraphs also had an inline style="margin:0 0 10px..." that set
   margin-left/right to 0 and silently beat margin-inline:auto here — trimmed to
   margin-bottom:10px in the HTML so this rule can actually center the box. */
.hero .s-inner>p.reveal:not(.lede){max-width:none}

/* "the ways we can support you" support cards */
.support{background:var(--parch)}
.scards{display:grid;gap:18px;margin-top:var(--gap-blk);grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr))}
.scard{background:var(--white);border:1px solid var(--sand-dkr);border-radius:12px;padding:clamp(22px,3vw,30px);display:flex;flex-direction:column}
.scard .k{font-size:12px;letter-spacing:.1em;text-transform:uppercase;font-weight:800;color:var(--rose)}
.scard h3{font-family:var(--display);font-size:clamp(20px,2.3vw,25px);color:var(--mauve);font-weight:700;margin:8px 0 12px;line-height:1.2}
.scard p{font-size:16px;color:var(--ink);margin-bottom:18px}
.scard a.more{margin-top:auto;font-weight:700;color:var(--rose);text-decoration:none;font-size:15px}
.scard a.more:hover{text-decoration:underline}
/* No arrow glyphs next to link text anywhere on the site (Marc 2026-07-21). */

/* generic card grids */
/* Cards sitting side by side in a row are stretched to equal height by the grid, so a
   card whose paragraph runs short used to leave its button floating up while its
   neighbour's sat lower: same row, two different heights (Marc 2026-08-14). The card is
   a flex column and its closing paragraph absorbs the free space, which drops whatever
   follows the text (a button row, a link) onto the card's bottom edge. Every card in a
   row then lands its control at the same height. This is the same pattern .scard and
   .mcard already use with margin-top:auto, written so it also holds when the trailing
   block carries its own top margin. Do not patch this per page. */
.cards{display:grid;gap:16px;margin-top:var(--gap-blk);grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}
.card{background:var(--parch);border:1px solid var(--sand-dkr);border-radius:10px;padding:clamp(20px,2.6vw,26px);display:flex;flex-direction:column}
.on-dark .card{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.18)}
.card h3{font-family:var(--display);font-size:clamp(18px,2vw,21px);color:var(--mauve);font-weight:700;line-height:1.25;margin-bottom:10px}
.on-dark .card h3{color:#fff}
.card p{font-size:16px;color:var(--ink);line-height:1.55}
.card>p:last-of-type{flex:1 1 auto}
.on-dark .card p{color:rgba(255,255,255,.85)}
.methods{display:grid;gap:18px;margin-top:var(--gap-blk)}
@media(min-width:780px){.methods{grid-template-columns:1fr 1fr}}
.mcard{background:var(--parch);border:1px solid var(--sand-dkr);border-radius:10px;padding:clamp(22px,3vw,30px);display:flex;flex-direction:column}
.mcard .mt{font-size:12px;letter-spacing:.1em;text-transform:uppercase;font-weight:800;color:var(--rose)}
.mcard h3{font-family:var(--display);font-size:clamp(20px,2.4vw,26px);color:var(--mauve);font-weight:700;margin:8px 0 12px;line-height:1.2}
.mcard p{font-size:16px;color:var(--ink)}
.mcard .big{margin-top:auto;padding-top:16px;font-size:14px;font-weight:800;color:var(--green)}

/* steps (numbered process; .snum shows the number, list-style off so it is not doubled) */
.steps{margin-top:var(--gap-blk);display:flex;flex-direction:column;list-style:none}
.step{display:grid;grid-template-columns:46px 1fr;gap:0 clamp(16px,3vw,32px);position:relative}
.step:not(:last-child) .spine::after{content:"";position:absolute;top:46px;bottom:0;left:23px;width:2px;background:var(--sand-dkr)}
.spine{position:relative}
.snum{width:46px;height:46px;border-radius:50%;background:var(--mauve);color:#fff;font-weight:700;font-size:18px;display:flex;align-items:center;justify-content:center;border:3px solid var(--rose);position:relative;z-index:1}
.scontent{padding:2px 0 clamp(24px,4vw,40px)}
.scontent h3{font-family:var(--display);font-size:clamp(19px,2.2vw,24px);color:var(--mauve);font-weight:700;margin-bottom:8px}
.scontent p{font-size:16px;color:var(--ink);max-width:var(--measure)}

/* example deck */
.deck{background:linear-gradient(160deg,#2A0040,#3D0058);border-radius:12px;padding:clamp(20px,3vw,34px);box-shadow:0 18px 50px rgba(42,0,64,.28);margin-top:var(--gap-blk);max-width:920px}
.deck-top{display:flex;flex-direction:column;gap:6px;margin-bottom:18px}
@media(min-width:640px){.deck-top{flex-direction:row;justify-content:space-between;align-items:baseline;gap:14px}}
.deck-kick{font-family:var(--display);font-size:clamp(18px,2vw,22px);font-weight:700;color:#fff}
.deck-fic{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--orange-text);font-weight:700}
.maptbl{width:100%;border-collapse:collapse;background:var(--parch);border-radius:8px;overflow:hidden}
.maptbl th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;text-align:left;background:var(--sand-dk);color:var(--rose);padding:11px 14px;font-weight:700}
.maptbl td{padding:13px 14px;border-top:1px solid var(--sand-dk);vertical-align:top;font-size:15px;color:var(--ink)}
.maptbl td.raised{font-family:var(--display);font-weight:700;color:var(--mauve);width:56%}
.maptbl tr.meta td{background:#fff5ef;border-top:2px solid var(--orange-deep);border-bottom:2px solid var(--orange-deep)}
.legend{margin-top:16px;font-size:13px;color:rgba(255,255,255,.8);line-height:1.55}
.legend b{color:#fff}

/* bibliography toggle */
.bib-toggle{margin-top:26px}
/* The site's ONE disclosure-button pattern (Marc 2026-07-21): label first, then + / −
   after it. CENTERED in its column (Marc 2026-08-24, superseding the left-edge placement
   he set on 2026-08-14). Centering a max-content box needs the auto side margins, exactly
   as the .center note below says: without them the box hugs the left whatever the text
   alignment does. Reuse this for new accordions. */
.bib-toggle>summary{display:flex;align-items:center;gap:8px;min-height:48px;padding:12px 22px;background:var(--mauve);color:#fff;border-radius:5px;font-weight:700;font-size:clamp(15px,1.6vw,17px);cursor:pointer;list-style:none;max-width:max-content;margin-left:auto;margin-right:auto}
.bib-toggle>summary::-webkit-details-marker{display:none}
.bib-toggle>summary:hover{background:var(--mauve-lt)}
.bib-toggle>summary::after{content:"+";font-weight:700;font-size:20px;line-height:1}
.bib-toggle[open]>summary::after{content:"\2212"}
.bib{margin-top:24px;max-width:860px}
.bib-group{margin-bottom:24px}
.bib-group h4{font-family:var(--display);color:var(--mauve);font-size:19px;margin-bottom:10px}
.bib ul{list-style:none}
.bib li{padding-left:18px;position:relative;margin-bottom:14px;font-size:15px;color:var(--ink);line-height:1.55}
.bib li::before{content:"";position:absolute;left:0;top:.55em;width:8px;height:8px;border-radius:2px;background:var(--orange-deep)}
.bib a{color:var(--rose);font-weight:600}
.bib em{color:var(--rose-lt);font-style:italic}
.bib-note{display:block;color:var(--rose-lt);font-size:14px;margin-top:3px}

/* story proof points */
.proof{display:grid;gap:16px;margin-top:var(--gap-blk);grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr))}
.pf{background:var(--parch);border:1px solid var(--sand-dkr);border-left:5px solid var(--orange-deep);border-radius:8px;padding:18px 20px}
.pf .big{font-family:var(--display);font-size:clamp(24px,3vw,32px);font-weight:700;color:var(--mauve);line-height:1}
.pf p{font-size:14.5px;color:var(--ink);margin-top:8px;line-height:1.45}

/* generic on-dark / light section helpers */
.on-mauve{background:var(--mauve);color:#fff}
.on-parch{background:var(--parch)}
.on-sand{background:var(--sand)}
.on-sanddk{background:var(--sand-dk)}
.center{text-align:center}
/* Opt-in centering: the honest rule about which blocks center (rewritten 2026-08-21).
   Every measured block inside a centered section needs the auto side margins. Without
   them its max-width box hugs the left while its text reads center: the box and the
   words end up on two different axes. This rule used to name the covered blocks one at
   a time (.head, then .lede, then p.body on 2026-08-14), which meant every other measured
   block was silently left out: .deck, .bib, .legalflag, .flip and every block a page invents.
   A block could be missed simply by being new. The rule now reaches every direct child
   of the band, so a centered band centers all of itself.
   margin-inline is deliberate. It sets the side margins and nothing else, so the flow
   rules above keep setting the top gap. Never write margin:0 auto here, because the
   shorthand would zero the top gap and the band would collapse.
   Outside a .center band nothing centers itself. A control row lines up with the left
   edge of the text it belongs to (Marc 2026-08-14), so a page must not add
   justify-content:center to a row of buttons, pills or filters. */
.center .s-inner > *{margin-inline:auto}
.center .btn-row{justify-content:center}
.legalflag{margin-top:26px;font-size:13px;line-height:1.6;color:var(--rose-lt);border-left:4px solid var(--orange-deep);padding:6px 0 6px 16px;max-width:var(--measure)}

/* footer */
/* Page feedback accordion (Marc final 2026-07-08): live-site FAQ style, every page, above footer.
   Its own padding is HALF a section gap (Marc 2026-07-27): it is a small utility band, not a
   content band, so a full --gap-sec above and below it read as empty page. Site-wide, no
   per-page patches. */
.page-fb{background:var(--parch);padding:calc(var(--gap-sec)/2) 0}
.fb-acc{max-width:640px;margin:0 auto;border-top:2px solid var(--rose);border-bottom:2px solid var(--rose)}
/* The feedback disclosure row is deliberately NOT given a box. It was on the
   2026-08-20 list of three controls without an edge, and it is the one that
   should keep its design: its indicator is the + / - glyph, which measures
   9.5:1 against the panel, so 1.4.11 is already met by something other than a
   border. Boxing it would also make a disclosure read as a button, against the
   locked + / - convention. */
.fb-btn{width:100%;display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:clamp(14px,2vw,18px) 0;background:transparent;border:none;cursor:pointer;text-align:left;font:inherit}
.fb-btn:focus-visible{outline:3px solid var(--rose);outline-offset:2px;border-radius:2px}
.fb-q{font-family:var(--display);font-size:clamp(16px,2vw,19px);font-weight:600;color:var(--mauve);line-height:1.3;align-self:center}
.fb-icon{flex-shrink:0;font-size:36px;font-family:var(--body);font-weight:300;line-height:1;color:var(--rose);user-select:none}
.fb-icon::before{content:'+'}
.fb-btn[aria-expanded="true"] .fb-icon::before{content:'\2212'}
.fb-body{max-height:0;overflow:hidden;transition:max-height .4s ease,opacity .3s ease;opacity:0}
.fb-acc.open .fb-body{max-height:400px;opacity:1}
.fb-body-inner{padding:0 0 clamp(14px,2vw,18px)}
.fb-body-inner textarea{width:100%;min-height:96px;font:inherit;font-size:16px;color:var(--ink);border:1.5px solid var(--field-edge);border-radius:8px;padding:12px;resize:vertical}
.fb-body-inner textarea:focus-visible{outline:3px solid var(--rose);outline-offset:1px}
.fb-send-row{display:flex;justify-content:flex-start;margin-top:12px}
.fb-thanks{font-size:16px;color:var(--ink);padding:clamp(14px,2vw,18px) 0;text-align:center;font-family:var(--display);font-weight:600}

/* Light band above the footer so subscribe reads as its own room, distinct from any dark
   CTA section above it; grayscale-safe (Marc 2026-07-07). */
/* A SHORT PAGE USED TO END IN A FIELD OF PURPLE (fixed 2026-08-28).
   html is #2A0040, and nothing made the page fill the window, so on Contact the
   footer stopped at 702px and the canvas painted the remaining 400 to 900px of
   deep purple below it. It was invisible until the newsletter and the feedback
   box came off, because those two blocks were 411px of ballast. Contact was
   within 7px of the fold by luck, not by design. This holds the footer to the
   bottom on every page and every window, which is what should have carried it
   all along. */
body{min-height:100vh;display:flex;flex-direction:column}
body > main{flex:1 0 auto}
footer.site{flex-shrink:0}

footer.site{border-top:10px solid var(--sand)}
footer.site{background:var(--ink);color:rgba(255,255,255,.72);padding:clamp(44px,6vw,72px) 0 30px;font-size:14px}
footer.site .s-inner{display:block}
.foot-news{text-align:center;max-width:620px;margin:0 auto}
.foot-h{font-family:var(--display);font-weight:700;font-size:clamp(24px,3.6vw,38px);line-height:1.2;color:#fff;max-width:20ch;margin:0 auto}
.news{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;align-items:center;margin-top:24px}
.news-label{flex:1 1 100%;color:#fff;font-weight:600;font-size:15px}
.news input[type=email]{flex:1 1 300px;max-width:400px;min-height:56px;padding:15px 18px;border:2px solid rgba(255,255,255,.28);border-radius:6px;background:#fff;color:var(--ink);font-family:var(--body);font-size:17px}
.news .btn{min-height:56px;font-size:17px;padding:15px 34px;border-color:var(--parch)}
.news input[type=email]::placeholder{color:#6b5d54}
.news-note{margin-top:12px;font-size:13.5px;line-height:1.5;color:rgba(255,255,255,.72);max-width:46ch;margin-inline:auto}
.news input[type=email]:focus-visible{outline:3px solid var(--orange-text);outline-offset:2px}
footer.site .wm{font-family:var(--display);font-size:22px;color:#fff;font-weight:600}
footer.site .wm .dot{font-weight:700;font-size:1.18em}
footer.site .legal{margin-top:10px;line-height:1.6;max-width:46ch}
footer.site .legal b{color:var(--orange-text)}
footer.site h5{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.72);margin-bottom:12px}
footer.site ul{list-style:none}
footer.site li{margin-bottom:9px}
footer.site a{color:rgba(255,255,255,.82);text-decoration:none}
footer.site a:hover{color:#fff;text-decoration:underline}
.foot-legal{text-align:center;margin-top:clamp(30px,4.4vw,50px);font-size:14px}
/* That top margin exists to clear the newsletter. On the pages that no longer
   carry one (every page but the three policies, Marc 2026-08-28) the links are
   the first thing in the footer, so the margin would stack on the footer's own
   top padding and leave a dead band. Self-correcting: if the newsletter comes
   back, the links stop being first and the margin returns on its own. */
.foot-legal:first-child{margin-top:0}
/* Same reasoning as the line above, for the band's own padding: 72px above the
   links against 30px below was measured to clear the newsletter heading. Where
   there is no newsletter, the two sides match instead. Self-correcting, like
   the rule above: the three policy pages still have .foot-news and keep the
   original proportion. */
footer.site:not(:has(.foot-news)){padding-top:clamp(30px,3.4vw,42px)}
.foot-legal a{font-weight:700;text-decoration:underline;text-underline-offset:3px}
footer.site .copy{text-align:center;border-top:1px solid rgba(255,255,255,.14);padding-top:22px;margin-top:clamp(14px,2vw,22px);color:rgba(255,255,255,.72);font-size:13px}

/* the flips: a quiet "before" word turned to an affirmed "after", shown as a
   dot-notation pair (alone.to.together) whose orange underline draws in on
   scroll. The pair is styled on the home page (.dotpair); here we lay out rows.
   :last-child drops its bottom inset so the band's own padding sets the gap. */
/* margin-top:0 came off on 2026-08-21: the flow rule at the top now sets this list's
   top gap from --gap-blk. The paragraph above it no longer patches its own bottom. */
.flips{display:flex;flex-direction:column;list-style:none}
.flip{padding:clamp(22px,3.2vw,32px) 0;border-top:1px solid var(--sand-dkr);max-width:var(--measure)}
.flip:first-child{border-top:0;padding-top:0}
.flip:last-child{padding-bottom:0}
.flip .turn{font-family:var(--body);font-size:clamp(16px,1.7vw,18.5px);line-height:1.55;color:var(--ink);margin-top:4px;max-width:56ch}

.reveal{opacity:0;transform:translateY(16px);transition:opacity .6s ease,transform .6s ease}
.reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}*{scroll-behavior:auto}}

/* ── MOCKUP 2026-08-23: an even rag on headings ───────────────────────────────
   text-wrap:balance evens the characters per line instead of filling one line
   and leaving a stub on the next. Headings on this site are short, so the
   6-line cap the engines apply for performance is far above anything here.

   MEASURED on learn.html at 1280px, where prose ends at 779: three of the five
   section headings pulled back toward the prose edge on this one line of CSS,
   from 903 to 771, from 1035 to 731 and from 868 to 686. It cannot help a
   heading that already fits on one line.

   It degrades to ordinary wrapping where unsupported, changes only where a line
   breaks and never what the text says, so it carries no accessibility cost.
   Support is about 92 percent. */
/* CORRECTED 2026-08-23 after Marc found lines breaking early. MEASURED at 1280:
   balance made the hero lede's three lines fill 64, 67 and 70 percent of the
   column, so no line ever reached the right margin. That IS what balance does:
   it equalises line lengths, which on prose reads as a paragraph that keeps
   stopping short. pretty fills the line (88 and 91 percent) and still trims the
   orphan, 22 percent against auto's 14.

   The orphaned "Consonance." that balance was added to fix turns out not to need
   it: in the narrower reading column that heading breaks 76/69 under auto,
   balance and pretty alike. The COLUMN fixed it, not the wrap style. */
:is(h1,h2,h3,h4,.head,.lede,.foot-h){text-wrap:pretty}

/* pretty reduces stranded last words in prose. No Firefox support yet and it
   degrades to ordinary wrapping, so it costs nothing to ask for. */
p.body,.card p,.scard p{text-wrap:pretty}

/* ── MOCKUP 2026-08-23: where the menu sits on its own row ────────────────────
   Marc asked for the menu to "line on the right margin" and, in the same
   message, for the wordmark to start on the left margin. In the ONE-ROW layout
   both are possible only on paper: MEASURED at 1280, the wordmark ends at 551
   and the first menu link starts at 456, so ABOUT prints on top of the wordmark.
   Five links plus the wordmark need about 620px of text alone, and the column is
   620px, so a single row cannot hold both inside these margins. The two-row
   layout is what makes his request achievable, not a matter of taste.

   Row two then has three defensible endings, so all three are here to look at:
     ?navalign=right   the last link lands ON the right margin (his words)
     ?navalign=left    the first link sits under the wordmark (Code for America)
     ?navalign=spread  both margins met, at the cost of wider gaps */
@media(min-width:1040px){
  /* DEFAULT IS LEFT, Marc 2026-08-23: the menu starts on the same left margin
     as the wordmark above it and as every heading and paragraph below it. */
  /* DEFAULT IS SPREAD, Marc 2026-08-23: the menu spans the whole line, first item
     on the left margin and last item on the right margin, with equal air between.
     ?navalign=left and ?navalign=right keep the two tighter alternatives. */
  .nav-inline{justify-content:space-between}
}

/* ── MOCKUP 2026-08-23: THE ONLY LEVER THAT NARROWS THE MARGINS ───────────────
   Marc: "a little bit too much space on both sides... move it out a little bit
   more so the margins are the same on both sides."

   The margins are already identical, measured at every width from 320 to 1600.
   What he is asking for is a WIDER column, and there is exactly one way to get
   one without breaking the AAA promise, so it is worth stating plainly.

   The column is 80 characters wide. That is WCAG 1.4.8 and it is a count of
   characters, not a distance. The pixel width of 80 characters is set by one
   thing only: how big the type is. So the type size IS the margin control, and
   nothing else is. Raising --measure instead would buy pixels by spending
   characters, which is the one thing that cannot be spent: it was measured at
   52ch = 80 characters, and 54ch already put lines over the limit.

   MEASURED at a 1280px window, characters per line staying at 77 in all three
   because the glyphs and the column grow together:
     18px  column 589   margin 345
     20px  column 649   margin 315   (the default here)
     22px  column 714   margin 283
   ?type=18 / ?type=20 / ?type=22 to compare them in place. */

/* ── MOCKUP 2026-08-23: the open phone menu PUSHES the page, it does not cover it
   Marc: "when the menu is activated, it covers up the head."

   The menu was position:absolute under a sticky banner, so opening it painted
   the panel straight over the first heading. Someone who opens the menu loses
   the thing they were reading, and on a small screen that is most of the view.

   In flow instead: the banner grows and the page moves down, so nothing is
   hidden and closing the menu puts everything back exactly where it was. */
/* The static menu has to span the BANNER, not the nav. Measured 2026-08-23 on a
   375px screen: the nav element is only as wide as the burger (129px), so a
   static child of it rendered the whole phone menu in a 129px column indented to
   x=231 while the page text started at x=31. display:contents lifts the nav's
   three children into .banner-inner's own flex row, so the burger stays beside
   the wordmark and the menu, at flex-basis 100%, takes the full width beneath
   them. The <nav> keeps its navigation landmark and its aria-label; only its box
   is removed. Verified in the accessibility tree after the change. */
.banner-inner > nav[aria-label="Primary"]{display:contents}
.nav-menu{position:static;margin-left:0;margin-right:0;flex:0 0 100%;width:100%}
.banner{padding-bottom:0}
.banner-inner{flex-wrap:wrap}
.nav-menu{flex:0 0 100%}

/* ── LEAVING THE SITE: one visible mark, external links only (Marc, 2026-08-24) ─
   THE STANDING RULE, and it has two halves that must stay together:
     INTERNAL links open in the same tab and carry NO mark, because nothing
       happens that a reader needs warning about.
     EXTERNAL links open a new tab and carry the arrow, because something does.
   The mark is therefore never decoration. It means exactly one thing: a new tab
   is about to open. Never put it on an internal link, and never let an external
   link ship without it. ptp.js decides which is which, in one place, by comparing
   hostnames, so a hand-written page cannot get it wrong.

   WHY THIS MEETS THE BAR. WCAG technique G201, giving users advanced warning when
   opening a new window, is a sufficient technique for 3.2.5 Change on Request at
   Level AAA. The site already met it for screen reader users: ptp.js appends
   "(opens in a new tab)" to the accessible name. Nothing was visible on the page,
   so sighted readers were the ones going unwarned. This closes that half.

   WHY A CHARACTER AND NOT AN ICON. Marc asked for the conventional boxed icon and
   asked to be told if that was wrong. He was right about the convention and it
   still lost, on his own earlier requirement that the mark must never separate
   from the text. A sized icon has to be display:inline-block, an inline-block is
   an atomic inline, and a browser may break the line before one. MEASURED on the
   evidence page's 36 external links: the boxed icon stranded itself on its own
   line 1 to 2 times at desktop widths and 5 times at 375px, while this arrow
   stranded 0 times at 1280, 900, 600 and 375. The non-breaking space glues it to
   the last word and a text glyph offers no break opportunity of its own.

   The colour is inherited rather than set. currentColor makes the mark exactly as
   readable as the link it belongs to, so it cannot fall below the contrast bar
   when a palette changes. */
a[data-external]::after{content:"\00a0\2197";font-weight:700;text-decoration:none}
a[data-external]{text-underline-offset:3px}

/* The trademark mark on the wordmark, on an attorney's advice (Marc, 2026-08-28).
   Set small and raised, the way a trademark mark is set. aria-hidden so a screen
   reader still reads the brand as people.to.policy: the link already carries its
   own accessible name. If the mark is ever registered, this becomes a registered
   symbol rather than a trademark one. */
.wordmark .tm{font-size:.34em;vertical-align:super;line-height:0;margin-left:.06em;font-weight:600;letter-spacing:0}

/* ── THE LET'S CHAT BUTTON (moved here 2026-08-29) ─────────────────────────
   These rules lived inside each page's own <style> block. Services had them and
   About did not, which is why About had no button at all, and two copies of a
   rule are two chances to drift. One definition now. --rose carries white type
   at 9.6:1, past the AAA bar. Minimum height 56px clears WCAG 2.5.5 target size. */
.pg-cta{display:flex;justify-content:center}
.pg-cta a.btn2{display:inline-flex;align-items:center;justify-content:center;min-height:56px;
  padding:13px 26px;border-radius:6px;background:var(--rose);color:#fff;font-weight:700;
  font-size:17px;text-decoration:none;text-align:center;border:1px solid var(--rose)}
.pg-cta a.btn2:hover{background:#5f1032;border-color:#5f1032}
