/* Budget Primer FY2026-27 — screen + print. Hawaiʻi Appleseed brand palette:
   Muted Teal (logo) / Deep Teal / Ash Grey primaries; Dark Slate Grey +
   Charcoal Blue for reversed-text backgrounds. Var names kept for continuity. */
:root {
  --sage: #6B9E78; --sage-mid: #95B7A2; --sage-light: #CAD2C5; --mint: #E8EDE6;
  --pale: #D6E0D2; --dark: #52796F; --forest: #354F52; --darkest: #2F3E46;
  --ink: #2F3E46;
  /* Unfold speed for the expandable panels (View Obligated Costs / View all
     appropriations) — THE one knob. Seconds; raise for a lazier reveal, drop
     to 0s for an instant one. Read by primer.js at click time, so a tweak
     here needs no script change. */
  --expand-dur: .35s;
  /* Font slots. Display/heading are Barlow (weight 900/800) — a free stand-in
     for Glober, the brand's licensed print typeface (see sources/original_primer_fy2526.pdf,
     which has Glober Black/Bold/SemiBold embedded). Swap in real Glober by loading
     a licensed webfont kit and overriding --display/--heading. */
  /* Cover display face ONLY (.cover-title / .cover-year — nothing else reads
     --display). The FY2025–26 cover set its title in Encorpada Classic, a
     licensed high-contrast serif used on page 1 and nowhere else in that book;
     Glober ran the interior. Noto Serif Display 600 is the closest free stand-in
     measured against the real outlines: set width within 0.4%, comparable stem
     weight and hairline contrast — and it has a true ʻokina, which Bodoni Moda,
     Libre Bodoni, DM Serif and Prata all lack. */
  --display: "Noto Serif Display", Georgia, "Times New Roman", serif;
  --heading: "Barlow", "Glober Black", sans-serif;
  --body: "Source Sans 3", "Source Sans Pro", sans-serif;
}
* { box-sizing: border-box; margin: 0; }
/* Leading: 1.4, not the 1.5 this started on. At 14.5px, 1.5 puts ~7px of air
   between lines — more than the 12px paragraph gap can beat, so paragraph
   breaks stopped reading as breaks and every column looked airy-but-mushy.
   1.4 (20.3px) keeps the lines comfortable and lets the paragraph gap show. */
body { background: #EFF2F1; font-family: var(--body); color: var(--ink);
       font-size: 14.5px; line-height: 1.4; }

.page { width: 8.5in; max-width: 100%; min-height: 11in; margin: 24px auto; background: #fff;
        padding: 0.75in 0.62in 0.9in; position: relative; overflow: hidden;
        box-shadow: 0 2px 14px rgba(47, 62, 70, .12); }
.page p { margin: 0 0 12px; }
sup { font-size: 11px; line-height: 0; }

h1 { font-family: var(--heading); font-weight: 900; color: var(--sage); font-size: 44px;
     letter-spacing: .5px; border-bottom: 1.5px solid var(--sage-light);
     padding-bottom: 14px; margin-bottom: 18px; }
h2.sub { font-family: var(--body); font-weight: 300; font-size: 30px;
         color: var(--sage); margin-bottom: 16px; }
h3.sub2 { font-family: var(--body); font-weight: 600; font-size: 19px;
          color: var(--sage); margin: 18px 0 10px; }
/* That 18px separates a sub-head from the prose above it. A sub-head that
   OPENS a page has no prose above it — only the 0.75in top margin — so the
   margin is dead space pushing the whole column down. Page 11 opens on one. */
.page > h3.sub2:first-child { margin-top: 0; }
/* Scoped `.page p.figcap`, not `.figcap`: `.page p` above is (0,1,1) and beat a
   bare `.figcap` at (0,1,0), so this margin — and .fig-note's — was being
   silently discarded and every caption ran on the generic 0/12px. */
.page p.figcap { color: #586A6D; font-size: 13.5px; margin: 10px 0 8px; }
.figcap b { color: var(--ink); }

/* Where a figure hands off to prose. These sat at 0–4px, so the body text read
   as part of the figure rather than as the paragraph after it (Will's note on
   pages 6 and 11). A figure's OWN note (.fig-note) is excluded — it belongs to
   the figure and stays tight against it; the gap goes below the note instead. */
.chart + p:not(.fig-note), .pie-row + p:not(.fig-note),
.lifecycle-wrap + p:not(.fig-note), .legend + p:not(.fig-note) { margin-top: 12px; }

/* Images placed in prose via ![alt](assets/…). Bounded by the text column so
   an upload can never blow out the page grid. */
img.inline-img { display: block; max-width: 100%; height: auto; margin: 10px 0;
                 border-radius: 3px; }

/* Free-floating text: a note placed on a page, from layout.json rather than
   from the prose. No height — it grows with its words, like any text should. */
.ds-textbox { font-size: 13.5px; line-height: 1.38; }
.ds-textbox p:last-child { margin-bottom: 0; }
/* a cropped image: the wrapper is the window, the full image hangs inside it
   at absolute inches; the editor sizes the window, layout.json remembers */
.ds-cropw { position: relative; display: block; overflow: hidden; }

/* Overflow slots ([[extra.<page>.<slug>]]) — bullet lists outside cards */
ul.extra-bullets { margin: 0 0 12px; padding-left: 20px; }
ul.extra-bullets li { margin: 3px 0; }
ol.extra-numbers { margin: 0 0 12px; padding-left: 22px; }
ol.extra-numbers li { margin: 3px 0; }

/* FY year picker (Figures 3/4/5) */
.fy-pick { font: inherit; font-weight: 700; color: var(--ink); background: var(--mint);
  border: 1px solid var(--sage-light); border-radius: 5px; padding: 0 3px; margin: 0 1px;
  cursor: pointer; vertical-align: baseline; }
.fy-pick:hover { border-color: var(--sage); }
[data-fy][hidden] { display: none !important; }
@media print {
  .fy-pick { -webkit-appearance: none; appearance: none; border: 0; background: none;
    padding: 0; color: inherit; font-weight: inherit; }
}
.folio { position: absolute; bottom: .45in; left: .62in; font-size: 11.5px; font-weight: 700; }
.folio.r { left: auto; right: .62in; }
a { color: var(--dark); }

/* cover */
.cover { background: var(--mint); padding: 0; }
/* The ribbon frame, ported from the FY2025–26 cover's vector art (its shapes
   were read straight out of sources/original_primer_fy2526.pdf). Three things
   the old skewX() version could not do, and why it is clip-path now:
     1. every angle is exactly 45°, not 38°;
     2. the top and bottom bands BLEED off the trim edge, then step twice at 45°
        — a transform can only make a parallelogram, never a stepped profile;
     3. the corner stripes are PAIRS, a dark stripe with a paler one outboard.
   Each shape is a full-page box clipped to its polygon, so every coordinate is
   a percentage of the page and survives the 1.25 screen zoom, print, the bleed
   export and the mobile breakpoint alike. Colours are this report's palette,
   not FY2025–26's cooler one — --sage is the middle step of the figure ramp,
   and the cover should agree with the charts. */
.ribbon { position: absolute; inset: 0; pointer-events: none; }
.rb-dark { background: var(--sage); }
.rb-pale { background: var(--sage-light); }
/* top: edge band + two 45° steps, then the paired corner stripes */
.r1 { clip-path: polygon(0% 0%, 100% 0%, 100% 9.457%, 98.317% 8.157%,
                         59.395% 8.157%, 54.232% 4.179%, 0% 4.179%); }
.r2 { clip-path: polygon(78.660% 10.669%, 100% 27.146%, 100% 21.591%, 85.850% 10.669%); }
.r3 { clip-path: polygon(0% 6.679%, 52.876% 6.679%, 59.624% 11.881%, 0% 11.881%); }
.r4 { clip-path: polygon(89.771% 10.669%, 100% 18.561%, 100% 13.005%, 96.977% 10.669%); }
/* bottom: the same frame rotated 180° about the page centre */
.r5 { clip-path: polygon(0% 91.023%, 1.748% 92.361%, 40.670% 92.361%,
                         45.833% 96.351%, 100% 96.351%, 100% 100%, 0% 100%); }
.r6 { clip-path: polygon(0% 78.889%, 14.216% 89.861%, 21.405% 89.861%, 0% 73.333%); }
.r7 { clip-path: polygon(40.441% 88.636%, 100% 88.636%, 100% 93.838%, 47.173% 93.838%); }
.r8 { clip-path: polygon(0% 87.475%, 3.088% 89.861%, 10.278% 89.861%, 0% 81.919%); }
/* z-index 1, NOT 2. It only has to clear the ribbons (which set none at all);
   2 collided exactly with the z-index layout.py gives every placed text box,
   and this wrapper comes later in the markup, so it won the tie. A note
   dropped on the cover then painted UNDERNEATH the cover's own title and this
   wrapper — visible, because both are transparent, and completely unclickable.
   Anything that raises this back to 2 buries the editable layer again. */
.cover-inner { position: relative; z-index: 1; padding: 2.2in .7in 0; }
.logo-lockup { display: flex; align-items: center; }
.logo-lockup.light { justify-content: center; }
.logo-img { height: 40px; width: auto; display: block; }
.cover .logo-img { height: 95px; margin-top: 10px; }
/* 900 was right for Barlow; the serif's matching weight is 600. Size is set so
   the longest line fills the column, as it did on the FY2025–26 cover, where the
   title ran nearly the full sheet width. */
/* Title and year are ONE lockup: same family, weight, colour and tracking, and
   only the size differs. The tracking is spelled out on both rather than left to
   the `h1` rule the title happens to match — .cover-year is a <div>, so it was
   silently getting `normal` while the title got .5px, and any change to h1 would
   have widened that gap again. */
.cover-title { font-family: var(--display); font-weight: 600; color: var(--sage); font-size: 158px;
               line-height: .95; letter-spacing: .5px; margin-top: .35in;
               border: none; padding: 0; }
/* 0.40 x the title, the ratio Encorpada held on the FY2025–26 cover (48pt/120pt) */
.cover-year { font-family: var(--display); font-weight: 600; color: var(--sage); font-size: 63px;
              letter-spacing: .5px; text-align: right; margin-top: .25in; }

/* toc page */
/* 1.2in, not the 1.95in this briefly carried. The logo here is PLACED (absolute,
   from layout.json) but its entry has `reserve: 0.42`, so the renderer emits a
   spacer holding its flow slot — the URL and author lines already sit below it
   and cannot be overlapped. Padding beyond 1.2in was therefore not clearing
   anything, just opening 0.75in of dead space between the logo and the two
   lines that belong with it. */
.toc-page { background: var(--dark); color: #fff; padding-top: 1.2in; }
.toc-head { text-align: center; margin-bottom: .7in; }
.toc-link a { color: var(--mint); }
.toc-author { margin-top: 8px; }
.mission { max-width: 6.7in; margin: 0 auto 14px !important; text-align: center; font-size: 14px; }
.toc-title { font-family: var(--heading); font-weight: 900; font-size: 34px; text-align: center;
             margin: .55in 0 .3in; letter-spacing: 1px; }
.toc-list { max-width: 5.9in; margin: 0 auto; }
.toc-list div { display: flex; justify-content: space-between; font-weight: 700;
                font-size: 16.5px; padding: 8px 0; }
.copyright { position: absolute; bottom: 1in; left: 0; right: 0; text-align: center; font-size: 13px; }
.toc-page .folio { color: #fff; }

/* branch rows (page 3) */
.branch { display: flex; gap: 14px; margin: 12px 0; align-items: stretch; }
.branch img { width: 2.15in; object-fit: cover; border-radius: 6px; }
.branch-card { flex: 1; border-radius: 14px; padding: 12px 18px; color: #fff; }
.branch-card.onlight { color: var(--ink); }
.branch-card h4 { margin-bottom: 6px; font-size: 15px; }
.branch-card ul { padding-left: 18px; }
.branch-card li { font-weight: 600; margin: 3px 0; }

/* cards */
/* Bottom margin is deliberately tighter than the top: this row is the last
   thing on pages 9 and 10, so the space below it only eats into the clearance
   above the folio. Page 9 is the tightest page in the report. */
.cards3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 18px; margin: 14px 0 10px; }
/* Not 1fr 1fr: One-Time carries 6 bullets and Emergency carries 2, so an even
   split left one column packed to the millimetre while its neighbour sat 40%
   empty. Giving the fuller column the extra width lets its bullets wrap to
   fewer lines — which is what pays for the bullet separation below AND brings
   the page back inside letter. */
.cards2 { display: grid; grid-template-columns: 1.4fr 1fr; gap: 18px; margin: 10px 0 18px; }
/* page 8's One-Time/Emergency cards run tall (6 bullets); tighten their internal
   spacing so the section clears the page folio when printed. Scoped to .cards2,
   which appears only on page 8 (other card sections use .cards3). */
.cards2 .card { padding: 9px 17px; }
/* 1px ran the bullets together into one grey block — at this leading a bullet
   that wraps to three lines was indistinguishable from the next bullet. */
.cards2 .card li { margin: 6px 0; }
.card { border-radius: 16px; padding: 16px 18px; color: #fff; }
.card.light { color: var(--ink); }
.card h4 { font-size: 15px; margin-bottom: 8px; }
/* Icon-headed cards (one-time / emergency appropriations): the glyph sits left
   of a larger title, both in the tile's own colour so a recolour flips them
   together. */
.card h4.card-ico-h { display: flex; align-items: center; gap: 13px;
  font-size: 20px; line-height: 1.13; margin-bottom: 12px; }
.card .card-ico { flex: none; width: 40px; height: 40px; }
.card .card-ico svg { display: block; width: 100%; height: 100%; }
/* Square glyphs (32x32 viewBox) must not be stretched to the 40px box the
   original 24x24 header icons assumed. */
.card h4.card-ico-h .card-ico { height: auto; }
/* A free-standing, editor-movable SVG graphic (render_report.graphic()). The
   wrapper carries the width; the SVG fills it and its viewBox keeps the aspect,
   so a proportional corner-resize just changes the wrapper width. */
.ds-graphic { display: inline-block; vertical-align: middle; line-height: 0; }
.ds-graphic > svg { display: block; width: 100%; height: auto; }
.card ul { padding-left: 17px; }
.card li { font-weight: 600; margin: 4px 0; }
.card li i { font-weight: 400; }

/* table 1 — header/total colours read through vars so a layout.json recolour
   (set inline on the table by the renderer, with re-decided text contrast)
   reaches every cell and the FY2026 twin at once. Unset, the fallbacks are
   the designed colours. */
.t1 { width: 100%; border-collapse: collapse; font-size: 13.5px; }
/* The header row carries the same vertical rules as the body, so the column
   dividers run the full height of the table instead of starting below the
   head. Sides only — a horizontal rule here would box the head off from the
   body it labels. */
.t1 th { background: var(--th-bg, var(--dark)); color: var(--th-tc, #fff); font-weight: 600; padding: 9px 6px;
         border-left: 1px solid #A7C0B8; border-right: 1px solid #A7C0B8; }
.t1 td { border: 1px solid #A7C0B8; padding: 9px 6px; text-align: center; }
.t1 td:first-child { width: 1.55in; }
.t1 tr.total td { background: var(--tot-bg, var(--sage-light)); color: var(--tot-tc, inherit); font-weight: 700; }

/* callout */
.callout { background: var(--dark); color: #fff; border-radius: 18px;
           padding: 18px 24px; margin: 6px 0 18px; }
.callout h4 { margin-bottom: 8px; }
.callout p { font-size: 14px; }
/* Recoloured pale by the editor: the renderer re-runs its luminance test and
   flips this class on, exactly as .card.light does. */
.callout.onlight { color: var(--ink); }

/* tax-reform panels (page 12) */
.taxfair-intro { font-size: 14.5px; color: #586A6D; margin: -6px 0 10px; }
.reforms { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.reform { border-radius: 14px; padding: 11px 17px 3px; }
.reform-head { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.reform-num { flex: none; width: 23px; height: 23px; border-radius: 50%; color: #fff;
              font-family: var(--heading); font-weight: 800; font-size: 13px;
              display: flex; align-items: center; justify-content: center; }
.reform h4 { font-size: 15.5px; color: var(--forest); }
/* Pushed right, so the revenue figure lands on a common edge down the stack. */
.reform-tag { margin-left: auto; flex: none; background: #fff; color: var(--forest);
              border: 1px solid var(--sage-light); border-radius: 999px;
              padding: 3px 11px; font-size: 12px; font-weight: 700; white-space: nowrap; }
.reform p { font-size: 13.2px; margin: 0 0 7px; }
/* Same contract as .card.light / .callout.onlight — set when the editor
   refills the panel with a colour the luminance test calls dark. */
.reform.ondark { color: #fff; }
.reform.ondark h4 { color: #fff; }
.reform.ondark .reform-tag { background: transparent; color: #fff; border-color: rgba(255,255,255,.5); }

/* The three headline appropriations, kept in PRINT. The full itemised list —
   all six one-time plus both emergency — lives in the .approp expandable
   below, which is noprint like the obligated-costs one. Compact on purpose:
   this row and Figure 3 now share a page that used to be two. */
/* Amount-led rows, not bullets. The dollar figure is the most scannable thing
   here and it used to sit mid-sentence behind a department name; leading with
   it turns the list into a column the eye can run down. The marker goes with
   it — the amount IS the marker now — which also buys back the indent, so the
   rows wrap less and the block stays the same height it was as a plain list.
   Hairlines rather than gaps: this sits between a heading and an expandable,
   and a ruled block reads as one object instead of loose text. */
ul.approp-brief { list-style: none; margin: 0 0 6px; padding-left: 0;
                  font-size: 13px; border-bottom: 1px solid var(--mint); }
ul.approp-brief li { margin: 0; padding: 2px 0; border-top: 1px solid var(--mint); }
/* The amount only goes sage HERE. The same bullets are reused inside the
   expandable's dark tiles, where sage on --dark would fail contrast — there it
   stays bold white and still leads the line. */
ul.approp-brief li > b:first-child { color: var(--dark); margin-right: 2px; }
/* Two classes, so this beats `.obligated`'s shorthand no matter which comes
   later in the file. That shorthand opens with margin-top:-8px, tuned to tuck
   the obligated-costs expandable under the callout above it — but this one
   follows a note with no bottom margin, so the same -8px dragged the control
   up over the last line of text. */
.obligated.approp { margin-top: 6px; }
/* Its own class rather than .fig-note: this is the LAST flowed element on the
   page, and .fig-note's 14px bottom margin overhung the padding box and grew
   the sheet past 11in even though the text itself cleared. */
.page p.approp-note { font-size: 12px; color: #586A6D; margin: 6px 0 0; }

/* obligated-costs expandable (web only) */
.obligated { margin: -8px 0 18px; }
.obligated > summary { cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
  width: fit-content; font-weight: 700; color: var(--forest); background: var(--mint);
  border: 1px solid var(--sage-light); border-radius: 9px; padding: 8px 16px; list-style: none; }
.obligated > summary::-webkit-details-marker { display: none; }
.obligated > summary::before { content: "▸"; font-size: 12px; transition: transform .15s; }
.obligated[open] > summary::before { transform: rotate(90deg); }
.obligated > summary:hover { border-color: var(--sage); }
.obligated-panel { margin-top: 12px; padding: 14px 18px 16px; background: #fff;
  border: 1px solid var(--mint); border-radius: 14px; }
.obligated-panel .legend { flex-direction: row; flex-wrap: wrap; gap: 8px 20px; margin-top: 6px; }
.obligated-panel .legend .lg { font-size: 14px; }
.obligated-panel .legend .sw { width: 20px; height: 20px; }
.obligated-note { font-size: 12px; color: #586A6D; margin-top: 10px; }
/* Same scoping fix as .figcap. The 14px bottom is the figure→prose gap for the
   figures that carry a note (pages 6, 9), where the note sits between them. */
.page p.fig-note { font-size: 12px; color: #586A6D; margin: 8px 0 14px; }

/* print-only page holding the obligated chart, injected by primer.js when the
   expandable is open at print time (see beforeprint handler) */
.obligated-print-page { display: none; }
@media print {
  .obligated-print-page { display: block; }
  .obligated-print-page .obligated-panel { border: 0; padding: 0; margin-top: 4px; background: none; }
}

/* charts */
.chart { width: 100%; height: auto; display: block; margin: 4px 0; }
/* Pie figures bleed slightly past the text column, as they do in the original,
   so the discs can reach their reference diameters (Fig 3 4.06in, Fig 4 4.39in,
   Fig 5 3.82in) with the legend still beside them. Widths are disc/0.79, the
   disc-to-viewBox ratio of pie(). */
.pie-row { display: flex; align-items: center; gap: .28in; justify-content: center;
           flex-wrap: nowrap; margin-inline: -0.34in; }
.pie-row .pie { flex: 0 0 auto; }
.pie-cip { width: 4.05in; }
/* Must stay in step with the width_in passed to pie() in render_report.py:
   that argument does not size the pie (this rule does) — it converts label_pt
   into user units, so a mismatch silently mis-sizes the slice labels. */
.pie-mof { width: 4.65in; }
.pie-tax { width: 4.80in; }
.pie-row .legend { flex: 0 1 auto; min-width: 0; gap: 20px; }
.pie-row .legend .lg { line-height: 1.2; white-space: nowrap; }
.pie-lab { font-weight: 600; fill: var(--ink); font-family: var(--body); }
.legend { display: flex; flex-direction: column; gap: 12px; }
.legend .lg { display: flex; align-items: center; gap: 10px; font-size: 17.5px; }
.legend .sw { width: 26px; height: 26px; border-radius: 4px; flex: none; }
svg .ax { font-size: 12px; fill: #556065; font-family: var(--body); }
svg .qlab { font-size: 16.4px; font-weight: 700; fill: var(--forest);
            font-family: var(--body); }
svg .rlab { font-size: 14.6px; fill: #7A8E92; font-family: var(--body); }
svg .ylab { font-size: 12px; fill: var(--ink); font-family: var(--body); }
svg .vlab { font-size: 11.5px; fill: var(--ink); font-family: var(--body); }
svg .vlab.b { font-size: 19.3px; font-weight: 600; }
svg .mo { font-size: 14.5px; font-family: var(--body); letter-spacing: 1px; }
svg .ph { font-size: 12px; font-family: var(--body); }
.iv { cursor: default; }
.iv:hover { opacity: .82; }

/* Figure 2's legend sits directly under its chart and runs horizontally.
   Scoped to direct children of .page so it never captures .pie-row legends. */
/* Margins kept tight: Figure 2 is 6.2in tall, so page 6 has almost no room
   between the chart and the folio. */
.page > .chart + .legend { flex-direction: row; flex-wrap: wrap;
                           justify-content: center; margin: 5px 0 7px; }
.page > .chart + .legend .lg { font-size: 15px; }
.page > .chart + .legend .sw { width: 22px; height: 22px; }

/* Lifecycle callouts. Positions are computed in render_report.py from each
   bracket's stub endpoint and emitted as inline left/top; these classes only
   say how the block anchors to that point. */
.lifecycle-wrap { position: relative; width: 6.9in; height: 6.45in; margin: 0 auto; }
.lifecycle-wrap svg { width: 5.8in; margin: .28in auto; display: block; }
.lc { position: absolute; width: 1.58in; font-size: 13.5px; line-height: 1.35; }
.lc-mo { display: block; font-weight: 700; font-size: 11px; letter-spacing: .8px;
         color: var(--dark); margin-bottom: 2px; }
svg .brk { stroke: var(--sage); stroke-width: 2; fill: none; stroke-linecap: round; }
.lc-right, .lc-left { transform: translateY(-50%); }
.lc-left { text-align: right; }
.lc-top { transform: translateY(-100%); }

/* photo page */
.photo { width: 100%; border-radius: 4px; }
.photocap { font-size: 11.5px; line-height: 1.4; margin-top: 7px !important; }

/* endnotes */
/* The whole list on ONE page (render_report.py no longer splits it), which is
   what forces the three tight columns and the smaller size — at two columns of
   13px, half the entries ran off the sheet. */
.endnotes { columns: 3; column-gap: .3in; padding-left: 18px; font-size: 12px; }
.endnotes li { margin-bottom: 10px; break-inside: avoid; }
.endnotes a { word-break: break-all; }

/* toolbar + tooltip (screen only) */
/* Sits at the top of the document and scrolls away with the content — NOT
   sticky, so it doesn't follow the viewport down the page. */
.toolbar { display: flex; justify-content: space-between;
           align-items: center; background: var(--forest); color: #fff; padding: 10px 20px;
           font-size: 14px; }
.toolbar button, .toolbar .tb-pdf { background: var(--sage-light); color: var(--forest);
                  border: 0; padding: 7px 16px; border-radius: 6px; font-weight: 700;
                  cursor: pointer; font-family: var(--body); font-size: 14px;
                  text-decoration: none; white-space: nowrap; }
/* The two Download PDF controls: exactly one of them shows. Wide enough to lay
   the sheet out at its designed width, the button prints the live page — so a
   desktop PDF is always the newest edit. Below the breakpoint the link to the
   built PDF takes over; see the comment on the toolbar in render_report.py for
   why a phone must not be sent through its own print engine.
   Both selectors are (0,2,0) here and in the media query, so the swap turns on
   source order and nothing has to reach for !important. */
.toolbar .tb-print { display: inline-block; }
.toolbar .tb-pdf { display: none; }
#tip { position: fixed; pointer-events: none; background: var(--darkest); color: #fff;
       padding: 6px 10px; border-radius: 6px; font-size: 12px; opacity: 0;
       transition: opacity .12s; z-index: 99; max-width: 260px; }

@media screen and (max-width: 850px) {
  .page { width: 100%; min-height: 0; padding: 6% 5%; margin: 10px 0; }
  .cards3, .cards2 { grid-template-columns: 1fr; }
  .branch { flex-direction: column; }
  .branch img { width: 100%; height: 1.6in; }
  .pie-row { flex-direction: column; gap: 12px; }
  .pie-row { margin-inline: 0; }
  .pie-row .pie { width: 100% !important; max-width: 3.6in; }
  .pie-row .legend { flex: 0 0 auto; width: 100%; }
  .lifecycle-wrap { width: 100%; }
  .lc { position: static; width: auto; margin: 4px 0;
        transform: none !important; text-align: left !important; }
  .cover-title { font-size: 64px; }
  /* .page drops its 11in min-height here, so a cover collapses to its content
     — and the ribbon frame, being a percentage of page height, rides up into
     the type (the bottom band starts at 91%). Reserve the frame's share back. */
  .cover .cover-inner { padding-bottom: 1.5in; }
  /* The cover logo ran off a phone's right edge. Its lockup is PLACED, so
     layout.json gives it an inline width in sheet inches (~7.1in) — a
     max-width on the image resolves against that, not the page, so the lockup
     itself has to be released here. Same reasoning as .lc above. The year is
     wide enough at 44px to break mid-token. */
  .cover .logo-lockup { position: static !important; width: auto !important; }
  .cover .logo-img { max-width: 100%; height: auto; }
  .cover-year { font-size: 32px; white-space: nowrap; }
  .endnotes { columns: 1; }
  .toolbar .tb-print { display: none; }
  .toolbar .tb-pdf { display: inline-block; }

  /* Releasing what the ENGINE pinned — every element layout.json placed, the
     ds-spacer struts holding their vacated flow slots, images sized in
     inches, and a table too wide to reflow — now ships from layout.py's
     mobile_css(), so it reaches every report rather than being rediscovered
     one stylesheet at a time. What is left below is this report's own: class
     names the engine has no way to know about. */

  /* .copyright and .folio hang off the BOTTOM of the sheet (bottom:1in /
     .45in), which clears the text only while .page keeps its 11in
     min-height. This query drops that, so the page collapses to its content
     and both land in the middle of it. */
  .copyright { position: static; margin: 28px 0 0; }
  .folio, .folio.r { position: static; left: auto; right: auto; bottom: auto;
                     margin-top: 22px; text-align: left; }

  /* .lifecycle-wrap is an inch-sized canvas the callouts were positioned
     against; with them released it only needs to hold the wheel. The svg
     rule at .lifecycle-wrap svg is (0,0,2) and beat .chart's width:100%,
     so the wheel kept its 5.8in and ran off the edge. */
  .lifecycle-wrap { width: 100%; height: auto; }
  .lifecycle-wrap svg { width: 100%; max-width: 100%; height: auto; margin: 8px auto; }
}

@page { size: letter; margin: 0; }
@media print {
  /* Force background graphics even when the print dialog's "Background graphics"
     box is unchecked — without this every green panel prints white. Must live on
     a selector; a bare declaration inside @media is invalid and gets dropped. */
  *, *::before, *::after {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  body { background: #fff; }
  .noprint, .toolbar { display: none !important; }
  /* NO padding here. The base .page rule already sets it, so restating it was
     redundant for eleven pages — and wrong for the two that override padding:
     .cover (0) and .toc-page (1.2in top) tie this selector on specificity, so
     this later rule beat them IN PRINT ONLY. The cover slid 0.75in down (the
     year onto the ribbon stripe), the TOC column 0.45in up (the URL onto the
     logo), while every screen check looked perfect. */
  .page { margin: 0; box-shadow: none; page-break-after: always; height: 11in;
          width: 8.5in; max-width: none; }
  .page:last-child { page-break-after: auto; }
  a { color: var(--dark); text-decoration: underline; }
}

/* ---- print bleed & crop marks -------------------------------------------
   Turned on only for an export chosen with "Bleed & crop marks": the renderer
   puts .ds-bleed on <body> for that one render, so the published document is
   byte- and pixel-identical when the class is absent (the named page and the
   .ds-bleed rules are inert). The sheet grows by 0.125in on each side; the page
   fills the whole sheet with its padding grown by the same 0.125in, so the
   CONTENT keeps its exact position (padding-box size and place are unchanged),
   the page background now bleeds to the sheet edge, and eight hairlines mark the
   trim corners. Marks live INSIDE the page (inset:0) — content pushed into a
   page's CSS margin is clipped away by the print engine, which is why they must
   not sit in a margin. */
@page bleed { size: 8.75in 11.25in; margin: 0; }
@media print {
  .ds-bleed .page {
    page: bleed;
    width: 8.75in; height: 11.25in; margin: 0;
    padding: calc(0.75in + 0.125in) calc(0.62in + 0.125in) calc(0.9in + 0.125in);
  }
  .ds-bleed .page::after {     /* eight trim ticks, 0.125in in from each edge */
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background:
      linear-gradient(#111,#111) left  0       top    0.125in / 0.12in 0.5pt no-repeat,
      linear-gradient(#111,#111) left  0.125in top    0       / 0.5pt 0.12in no-repeat,
      linear-gradient(#111,#111) right 0       top    0.125in / 0.12in 0.5pt no-repeat,
      linear-gradient(#111,#111) right 0.125in top    0       / 0.5pt 0.12in no-repeat,
      linear-gradient(#111,#111) left  0       bottom 0.125in / 0.12in 0.5pt no-repeat,
      linear-gradient(#111,#111) left  0.125in bottom 0       / 0.5pt 0.12in no-repeat,
      linear-gradient(#111,#111) right 0       bottom 0.125in / 0.12in 0.5pt no-repeat,
      linear-gradient(#111,#111) right 0.125in bottom 0       / 0.5pt 0.12in no-repeat;
  }
}

/* budget-tracker interlinks */
.figcap-hint { color: #8AA39E; font-weight: 400; }
.lk { cursor: pointer; }
/* link affordances are screen-only: in print they'd suggest nothing clickable */
@media screen {
  svg .ylab.lk { fill: var(--dark); text-decoration: underline;
                 text-decoration-color: rgba(82,121,111,.35); text-underline-offset: 2px; }
  svg .ylab.lk:hover { fill: var(--forest); }
  .t1 th.lk { text-decoration: underline dotted rgba(255,255,255,.7); text-underline-offset: 3px; }
}
.explore { margin: 6px auto 12px; padding: 10px 16px; border: 1.5px solid var(--sage-light);
           border-radius: 10px; background: var(--mint); font-size: 14px; text-align: center; }
.explore a { font-weight: 700; white-space: nowrap; }
.tb-actions { display: flex; align-items: center; gap: 14px; }
.tb-link { color: var(--sage-light); font-weight: 700; text-decoration: none; }
.tb-link:hover { color: #fff; }
#popover { position: fixed; z-index: 100; width: 356px; max-width: calc(100vw - 20px);
           background: #fff; border: 1.5px solid var(--sage-light); border-radius: 12px;
           box-shadow: 0 10px 32px rgba(47,62,70,.25); padding: 16px 18px 14px;
           font-size: 13.5px; }
#popover h5 { font-size: 15px; color: var(--forest); margin: 0 34px 8px 0; }
#popover p { margin: 8px 0 12px; color: #3F4F52; line-height: 1.45; }
#popover .pop-blurb { margin-top: 0; font-size: 12.5px; }
.pop-stats { display: flex; gap: 16px; border-block: 1px solid var(--mint); padding: 7px 0; }
.pop-stats div { display: flex; flex-direction: column; }
.pop-stats span { font-size: 11px; color: #7A8E92; text-transform: uppercase; letter-spacing: .5px; }
.pop-stats b { font-size: 14.5px; color: var(--ink); }
.pop-cta { display: inline-block; background: var(--dark); color: #fff !important;
           font-weight: 700; padding: 8px 14px; border-radius: 8px; text-decoration: none; }
.pop-cta:hover { background: var(--dark); }
.pop-x { position: absolute; top: 8px; right: 10px; border: 0; background: none;
         font-size: 20px; color: #7A8E92; cursor: pointer; line-height: 1; }
@media print { #popover { display: none !important; } }

/* popover preview sections (tracker slice) */
.pop-sec { border-top: 1px solid var(--mint); padding: 9px 0 4px; }
.pop-sec-h { font-size: 11px; font-weight: 700; color: #7A8E92; text-transform: uppercase;
             letter-spacing: .6px; margin-bottom: 6px; }
.pop-spark { display: flex; align-items: center; gap: 12px; }
.spark { width: 150px; height: 40px; flex: none; }
.pop-spark-meta b { display: block; font-size: 15px; color: var(--ink); }
.pop-spark-meta span { font-size: 11.5px; color: #7A8E92; }
.pop-prog { margin-bottom: 7px; }
.pop-prog-t { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; }
.pop-prog-t span { color: #3F4F52; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pop-prog-t b { color: var(--ink); flex: none; }
.pop-bar { height: 5px; border-radius: 3px; background: var(--mint); margin-top: 2px; }
.pop-bar i { display: block; height: 100%; border-radius: 3px; background: var(--sage); }
.pop-more { font-size: 11.5px; color: #7A8E92; margin: 2px 0 6px; }
#popover .pop-cta { margin-top: 8px; }

/* footnote refs -> tooltip with source link (screen only) */
@media screen {
  /* a tinted pill: reads as a control, not as body punctuation */
  a.fn { color: var(--forest); font-weight: 700; text-decoration: none;
         cursor: pointer; background: var(--sage-light); padding: 1px 4px;
         border-radius: 4px; margin: 0 1px; }
  a.fn:hover { background: var(--dark); color: #fff; }
  /* on the dark cards/callouts the tint would vanish — invert it */
  .card a.fn, .callout a.fn, .branch-card a.fn { background: rgba(255,255,255,.28);
         color: #fff; }
  .card a.fn:hover, .callout a.fn:hover, .branch-card a.fn:hover {
         background: #fff; color: var(--forest); }
  .card.light a.fn, .branch-card.onlight a.fn, .callout.onlight a.fn {
         background: var(--dark); color: #fff; }
  .card.light a.fn:hover, .branch-card.onlight a.fn:hover, .callout.onlight a.fn:hover {
         background: var(--forest); color: #fff; }
}
@media print { a.fn { color: inherit; text-decoration: none; } }
#fnpop { position: fixed; z-index: 110; width: 320px; max-width: calc(100vw - 20px);
         background: #fff; border: 1.5px solid var(--sage-light); border-radius: 10px;
         box-shadow: 0 10px 30px rgba(47,62,70,.22); padding: 12px 14px; font-size: 12.5px; }
#fnpop .fn-n { font-size: 10.5px; font-weight: 700; letter-spacing: .6px; color: #7A8E92;
               text-transform: uppercase; margin-bottom: 4px; }
#fnpop p { margin: 0 0 10px; color: #3F4F52; line-height: 1.42; }
.fn-cta { display: inline-block; background: var(--dark); color: #fff !important;
          font-weight: 700; padding: 6px 12px; border-radius: 7px; text-decoration: none;
          font-size: 12px; }
.fn-cta:hover { background: var(--dark); }

/* Default to ~125% on screen. Applied to .page (not body) so the Squarespace
   embed doesn't scale the host site. Gated above the width where the page would
   start overflowing, so the mobile breakpoint keeps working unzoomed. */
@media screen and (min-width: 1120px) {
  .page { zoom: 1.25; }
}

/* placed, editable tables (layout.json `tables`) */
table.ds-table { border-collapse: collapse; width: 100%; font-size: 13px;
  background: #fff; }
table.ds-table th, table.ds-table td { border: 1px solid #C9D6CD;
  padding: 5px 9px; text-align: left; vertical-align: top; }
table.ds-table th { background: #E8EDE6; font-weight: 600; color: #2F3E46; }
