/* finalert.com — resources.css. SPEC-G-R3 §A–§E.
   ==========================================================================
   The guide single, the guides hub, the FAQs hub and the cost calculator.

   WHY THIS IS A SEPARATE FILE AND NOT AN APPEND TO pages.css.
   SPEC-G-R3 §G6 places every rule below in pages.css. Orchestrator ruling
   §J.4 amends that for build sequencing: pages.css is owned by the interior
   motion pass while this spec is being built, so two agents appending to one
   5,100-line file would conflict on every hunk. This file is enqueued by the
   four new templates ONLY, after next.css and pages.css, and a follow-up may
   fold it back in once the motion pass lands. Nothing here duplicates a rule
   that already exists in either of those two: every selector is either new or
   a documented delta on one that is.

   COMPOSITION, NOT COPYING (SPEC-00 §10). The guide single's geometry IS the
   blog single's: its markup still carries .post-doc, .post-doc__grid and
   .post-body alongside the .gd-* names, so the grid tracks and the reading
   measure come from pages.css unchanged.

   SPEC-GD-R4 §3 TAKES THE RAIL BACK. The guide used to compose the blog
   rail's sticky block too, and pages.css caps that block's height with
   overflow-y: auto. With a contents list, a download offer and a byline
   stacked inside it, three of the five guides overflowed at a 900px viewport
   and all five at 800, which is the scrollbar the owner named. The guide now
   owns .g4-rail, only its contents group is sticky, and nothing on this page
   carries overflow-y outside the one flag in §3.2 tier 3 that no shipped
   guide sets. pages.css is UNCHANGED: the blog single keeps its rail, which
   is six to twelve rows and never trips it.

   BUDGETS. Zero backdrop-filter. Zero box-shadow used as elevation — every
   box-shadow below is an `inset` edge, which is a rule, not a shadow. No
   element in this file is a card in SPEC-00's sense (bordered AND radiused AND
   shadowed): the plates carry a ground fill plus at most one hairline or one
   3px edge. No transform on any hover. No looping motion.
   ========================================================================== */


/* ==========================================================================
   SPEC-GD-R4 §4 — the cover. .ihero--guide, still a MODIFIER on .ihero--post
   ==========================================================================
   SPEC-G-R3 §A1 refused a sixth top-level hero variant and that refusal
   stands. R4 grows the modifier from three deltas to seven. The record strip,
   the breadcrumb, the pattern, the 46px all-ink h1 with no accent span, the
   .hl load choreography and the 880ms finish are all inherited untouched.

   Delta 2, and it is the one that matters: the plate carries a DRAWN cover,
   not a photograph. A guide is a document about numbers; a stock photograph
   of an office on its cover says nothing, and a drawn cover says this is a
   made thing. The mount is ASSETS-R4 §1's: generated on white, mounted on a
   --navy-050 plate with mix-blend-mode: multiply, so the white becomes the
   plate's tint and no prompt ever had to hit an exact background hex. */

.ihero--guide .ihero__plate {
  background: var(--navy-050);
  border: 1px solid var(--navy-100);
}
.ihero--guide .ihero__plate img { mix-blend-mode: multiply; object-fit: contain; }
@supports not (mix-blend-mode: multiply) {
  .ihero--guide .ihero__plate     { background: var(--paper); }
  .ihero--guide .ihero__plate img { mix-blend-mode: normal; }
}

/* delta 3. The two-digit menu_order at 120px, behind the plate's top-left
   corner, aria-hidden, decorative, and the only element on the page over
   60px. It is clipped by nothing and sits UNDER the plate: the plate is
   z-index 1 inside an isolated stacking context, so the numeral's right half
   disappears behind it and its left half reads as a printed folio. */
.ihero--guide .ihero__aside { position: relative; isolation: isolate; }
.ihero--guide .ihero__plate { position: relative; z-index: 1; }
.g4-cover__no {
  position: absolute;
  /* far enough out that roughly half the folio reads beside the plate and the
     rest sits behind it. Measured against the column gap at each step so it
     never reaches the copy column: 8px of clearance at 1024 and 40 above. */
  left: calc(var(--s-8) * -1);
  top: calc(var(--s-7) * -1);
  z-index: 0;
  font: 600 clamp(96px, 8vw, 120px)/1 var(--font-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.04em;
  color: var(--navy-100);
  pointer-events: none;
}
@media (min-width: 1440px) { .g4-cover__no { left: calc(var(--s-10) * -1); } }
@media (max-width: 1023px) { .g4-cover__no { display: none; } }

/* delta 4. The promise, whole, on a 46ch measure directly under the h1. */
.ihero--guide .ihero__lead { max-width: 46ch; }

/* delta 5. The badge goes from a pill to a two-track plate with a --navy-050
   ground and a 3px navy left edge. It is still NOT a gold instance: no gold
   fill, and the tick in the eyebrow above it has already spent one. */
.ihero__badge {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: start;
  margin-top: var(--s-6);
  padding: var(--s-4) var(--s-5);
  border: 0;
  border-left: 3px solid var(--navy);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--navy-050);
  font: 600 14px/1.45 var(--font-ui);
  color: var(--navy);
}
.ihero__badge svg { display: block; width: 20px; height: 20px; color: var(--navy-300); }

/* delta 6. The meta bar: a mark per cell instead of a middle dot. Every
   string and the <time> element are unchanged, including the Published /
   Updated distinction. */
.g4-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-6);
  align-items: center;
  margin-top: var(--s-6);
  list-style: none;
}
.g4-meta li  { display: flex; align-items: center; gap: var(--s-2); font: var(--t-cap); color: var(--ink-3); }
.g4-meta svg { display: block; width: 16px; height: 16px; color: var(--navy-300); flex: 0 0 auto; }

/* delta 7. Two actions, which the blog hero does not have. A reference
   document should offer the two things a reader arrives wanting. */
.g4-cover__acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  align-items: center;
  margin-top: var(--s-6);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}

/* §4.3 geometry. The aside widens with the viewport; the copy column keeps
   minmax(0,1fr) so a long title never pushes the plate off the measure. */
@media (min-width: 1024px) { .ihero--guide .ihero__grid { grid-template-columns: minmax(0, 1fr) 400px; } }
@media (min-width: 1180px) { .ihero--guide .ihero__grid { grid-template-columns: minmax(0, 1fr) 480px; } }
@media (min-width: 1440px) { .ihero--guide .ihero__grid { grid-template-columns: minmax(0, 1fr) 576px; } }


/* ==========================================================================
   SPEC-GD-R4 §3 — the rail, and the end of the scrollbar
   ==========================================================================
   THE OWNER'S COMPLAINT, VERBATIM: "I don't even like how ugly the TOC at
   left with a horizontal scrollbar is, so pathetic."

   It was not a styling accident. pages.css caps the blog rail's inner block
   at calc(100vh - header - --s-10) with overflow-y: auto, the guide composed
   that block deliberately, and a contents list plus a download offer plus a
   byline stacked in one sticky element measured 596 to 1,168px against 760
   available at a 900px viewport. Three of five guides overflowed at 900 and
   all five at 800. R4 fixes the arithmetic, not the scrollbar's appearance:

     1. The guide stops composing the blog rail block. Nothing in this column
        has overflow-y on it any more.
     2. ONLY the contents group is sticky. The download offer and the byline
        sit below it in the same column and scroll away normally, which takes
        roughly 300px out of the sticky element.
     3. Rows are 34px, labels clamp to two lines, and sub-rows are visible
        only under the section the reader is in, capped at four.
     4. A pure CSS height query densifies the whole rail on short viewports.

   Measured worst case on the five shipped guides is 8 h2 rows:
   28 + 8x34 + 4x26 + 40 = 444px, against 560 available at a 700px viewport.

   .post-doc and .post-doc__grid are KEPT. The grid has no overflow on it and
   its 1024 / 1180 / 1440 tracks are correct; only the 1440 step is new here. */

@media (min-width: 1440px) {
  .gd-doc__grid { grid-template-columns: 264px minmax(0, 713px); }
}

/* ONE declaration governs the rail's height and it is a ROW HEIGHT, not a
   cap. Tier 2 below changes these two numbers and nothing else. */
.g4-rail__in { --toc-row: 34px; --toc-sub: 26px; }

/* Below 1024 the three groups are separate blocks in the single column, so
   `order` can put the prose between them without moving a node in the DOM.
   pages.css's own <1024 centring rule keys off the blog class names this
   template no longer carries, so the four blocks restate it here. */
.g4-rail,
.g4-rail__in { display: contents; }

@media (max-width: 1023px) {
  /* min-width: 0 IS LOAD-BEARING AND IS NOT TIDYING. A grid item's automatic
     minimum size is its min-content width, and two things in this column
     report a large one: the table carries a deliberate min-width of 560px
     below 768 (§6.4), and a -webkit-box line-clamp reports its longest line
     rather than its wrapped width. Without this the single column resolves to
     the widest of those and the PAGE scrolls sideways, which is SPEC-00
     §8.6's one blocking layout failure. With it, the table scrolls inside
     .gd-table-wrap, which is what owns that scroll. */
  .g4-toc-m,
  .g4-rail__dl,
  .g4-rail__by,
  .post-body { width: 100%; max-width: 673px; margin-inline: auto; min-width: 0; }
  .g4-toc-m      { order: 1; }
  .post-body     { order: 2; }
  .g4-rail__dl   { order: 3; }
  .g4-rail__by   { order: 4; }
  .g4-rail__dl,
  .g4-rail__by { padding-top: var(--s-6); border-top: 1px solid var(--line); }
}

.g4-rail__h {
  font: var(--t-eyebrow);
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--navy);
}
.g4-rail__n {
  display: block;
  margin-top: 3px;
  font: 400 12px/1.3 var(--font-ui);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-3);
}

.g4-toc      { margin-top: var(--s-4); list-style: none; counter-reset: g4toc; }
.g4-toc > li { counter-increment: g4toc; break-inside: avoid; }
.g4-toc > li > a {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: start;
  min-height: var(--toc-row);
  padding-block: 6px;
  font: 400 14px/1.35 var(--font-ui);
  color: var(--ink-2);
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: color var(--dur-1) var(--ease-out);
}
/* A TOC label is a LABEL, not a sentence, and the full heading is one click
   away with the same words. This is the ONE permitted line-clamp on the site
   and SPEC-SI-R3 §5.1 item 7's deletion of the others stands. */
.g4-toc > li > a > span {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
.g4-toc > li > a::before {
  content: counter(g4toc, decimal-leading-zero);
  font: 600 11px/1.5 var(--font-display);
  font-variant-numeric: tabular-nums;
  color: var(--navy-300);
  transition: color var(--dur-1) var(--ease-out);
}
.g4-toc > li > a:hover,
.g4-toc > li > a:hover::before { color: var(--navy); }

/* Sub-rows exist in the DOM ALWAYS and rest hidden. The rule that reveals
   them lives in the >=1024 block below and nowhere else, so below 1024
   nothing can turn them on and the mobile disclosure needs no override. With
   JavaScript off no row is ever current at any width, so the rail is h2s
   only: complete, working and short. SPEC-00 §8.6's ban on !important outside
   the reduced-motion block is respected by construction. */
.g4-toc__sub { display: none; list-style: none; margin: 2px 0 var(--s-2); }
.g4-toc__sub a {
  display: block;
  padding: 4px 0 4px var(--s-7);
  min-height: var(--toc-sub);
  font: 400 13px/1.4 var(--font-ui);
  color: var(--ink-3);
  text-decoration: none;
  transition: color var(--dur-1) var(--ease-out);
}
.g4-toc__sub a:hover { color: var(--navy); }

/* THE STATE IS aria-current, NEVER A CLASS. It is real information for a
   screen-reader user and the CSS hangs off the same attribute, so there is
   exactly one source of truth. */
.g4-toc a[aria-current="true"] {
  font-weight: 600;
  color: var(--navy);
  box-shadow: inset 3px 0 0 0 var(--gold);
  padding-left: var(--s-3);
  margin-left: calc(var(--s-3) * -1);
}
.g4-toc > li > a[aria-current="true"]::before { color: var(--navy); }
.g4-toc__sub a[aria-current="true"] { padding-left: var(--s-7); }

/* Reading progress. Pure CSS where the engine has scroll timelines, a flat
   hairline where it does not, and GONE under reduced motion. It never carries
   information the rail does not already carry, so removing it removes
   nothing. */
.g4-prog {
  margin-top: var(--s-5);
  height: 2px;
  background: var(--navy-100);
  border-radius: 2px;
  overflow: hidden;
}
.g4-prog__fill {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
}
@supports (animation-timeline: scroll()) {
  .g4-prog__fill {
    animation: g4-progress linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes g4-progress { to { transform: scaleX(1); } }
}

/* the download offer, with the guide's own cover on it */
.g4-rail__dlrow {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  margin-top: var(--s-4);
}
.g4-rail__dlrow:only-child { margin-top: 0; }
.g4-rail__thumb {
  display: block;
  width: 72px;
  height: auto;
  border-radius: var(--r-xs);
  border: 1px solid var(--navy-100);
  background: var(--navy-050);
  mix-blend-mode: multiply;
}
@supports not (mix-blend-mode: multiply) { .g4-rail__thumb { mix-blend-mode: normal; background: var(--paper); } }
.g4-rail__dltext { font: var(--t-body-sm); color: var(--ink-3); }
.g4-rail__dl .link-arrow { margin-top: var(--s-3); }
.g4-rail__byh    { font: var(--t-d4); letter-spacing: -.010em; color: var(--navy); }
.g4-rail__bytext { margin-top: var(--s-3); font: var(--t-body-sm); color: var(--ink-3); }
.g4-rail__by .link-arrow { margin-top: var(--s-4); }

@media (min-width: 1024px) {
  .g4-rail    { display: block; grid-column: 1; grid-row: 1 / -1; align-self: stretch; }
  .g4-rail__in{ display: block; }

  /* the reveal, scoped HERE and nowhere else */
  .g4-toc > li:has(> a[aria-current="true"]) .g4-toc__sub,
  .g4-toc__sub:has(a[aria-current="true"])   { display: block; }

  .g4-rail__in > * + * {
    margin-top: var(--s-7);
    padding-top: var(--s-7);
    border-top: 1px solid var(--line);
  }

  /* ONLY the contents group sticks, and that is the whole fix. It is sticky
     inside a plain block parent, which works: sticky resolves against the
     nearest scrolling ancestor, and the parent is a block in a stretched grid
     item. The download offer and the byline sit under it and leave the screen
     normally. */
  .g4-rail__toc {
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
    z-index: var(--z-rail);
  }
}

/* TIER 2, short viewports. A pure CSS height query: no JavaScript, no
   measurement, no resize listener. 28 + 8x28 + 40 = 292px against 580
   available at a 720px viewport. */
@media (min-width: 1024px) and (max-height: 720px) {
  .g4-rail__in     { --toc-row: 28px; --toc-sub: 24px; }
  .g4-toc > li > a > span { -webkit-line-clamp: 1; }
  .g4-toc__sub     { display: none; }
}

/* TIER 3, THE LAST RESORT, specified so that nobody invents one. `data-over`
   is written by PHP at more than 18 h2 rows and by nothing else; on the five
   shipped guides it never renders and the acceptance sweep asserts that. A
   hidden scrollbar with a fade is the only honest version of this, and it is
   behind a gate that is currently closed. */
.g4-rail__toc[data-over] .g4-toc {
  max-height: calc(100vh - var(--header-h) - var(--s-12) - 68px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 28px), transparent 100%);
          mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 28px), transparent 100%);
}
.g4-rail__toc[data-over] .g4-toc::-webkit-scrollbar { display: none; }


/* ==========================================================================
   SPEC-GD-R4 §3.5 — the mobile disclosure
   ==========================================================================
   The template emits the <nav> ONCE and wraps it in <details> unconditionally.
   At >=1024 the <details> takes display: contents and the <summary> takes
   display: none, so the disclosure vanishes and the list renders open. One
   node, one id, one set of anchors, no duplication and no JavaScript. */

.g4-toc-m__sum {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 52px;
  padding: var(--s-3) var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--wash);
  font: 600 15px/1.3 var(--font-ui);
  color: var(--navy);
  cursor: pointer;
  list-style: none;
}
.g4-toc-m__sum::-webkit-details-marker { display: none; }
.g4-toc-m__n    { margin-left: auto; font: var(--t-cap); color: var(--ink-3); }
.g4-toc-m__chev { flex: 0 0 auto; width: 16px; height: 16px; transition: transform var(--dur-2) var(--ease-out); }
.g4-toc-m[open] .g4-toc-m__chev { transform: rotate(180deg); }
/* everything about the disclosure is scoped BELOW 1024, so an `open`
   attribute left behind by a resize cannot reach the sticky column */
@media (max-width: 1023px) {
  .g4-toc-m[open] .g4-rail__toc {
    padding: var(--s-5);
    border: 1px solid var(--line);
    border-top: 0;
    border-radius: 0 0 var(--r-md) var(--r-md);
  }
  /* the rail head and the progress hairline are the sticky column's
     furniture; inside the disclosure the <summary> already says both */
  .g4-toc-m .g4-rail__h,
  .g4-toc-m .g4-prog { display: none; }
  .g4-toc-m .g4-toc  { margin-top: 0; }
}
@media (max-width: 767px) {
  .g4-toc > li > a  { min-height: 44px; }
  .g4-toc__sub a    { min-height: 44px; padding-block: var(--s-3); }
}
/* >=1024 the disclosure vanishes and the list renders open. THIS NEEDS TWO
   DECLARATIONS, NOT ONE, AND THE SECOND IS THE LOAD-BEARING ONE. SPEC-GD-R4
   §3.5 assumed `details { display: contents }` alone was enough. Measured in
   Chromium 151: it is not. The nav inside a CLOSED <details> is painted and
   has a non-zero bounding box, but it contributes NO HEIGHT to the flow, so
   the download offer and the byline lay out over the top of it and the rail
   read as two groups instead of three. `::details-content` is the pseudo that
   owns that behaviour and setting content-visibility on it is what puts the
   nav back in the flow. */
@media (min-width: 1024px) {
  .g4-toc-m      { display: contents; }
  .g4-toc-m__sum { display: none; }
  .g4-toc-m::details-content { content-visibility: visible; block-size: auto; }
}
/* The fallback, and it is a WORKING state rather than a broken one: an engine
   without ::details-content keeps the disclosure and its summary in the rail
   at every width, so the contents are one click away and nothing overlaps.
   Any engine that supports :has() (which the current-section reveal above
   needs) supports @supports selector(), so this branch resolves correctly
   wherever it matters. */
@supports not selector(::details-content) {
  @media (min-width: 1024px) {
    .g4-toc-m      { display: block; }
    .g4-toc-m__sum { display: flex; }
    .g4-toc-m[open] .g4-rail__toc {
      padding: var(--s-5);
      border: 1px solid var(--line);
      border-top: 0;
      border-radius: 0 0 var(--r-md) var(--r-md);
    }
  }
}


/* ==========================================================================
   SPEC-GD-R4 §6.2 — section numerals, kept and promoted
   ==========================================================================
   Purely CSS. The editor writes a plain <h2>; the numeral is a counter, so
   inserting a section renumbers the whole document and nothing in the
   database has to change. R4 grows the numeral from a small grey number into
   a two-track head: the numeral on its own line above a hairline, so a
   section opening reads as a chapter mark.

   scroll-margin-top IS NOT OPTIONAL. The header is position: fixed on some
   templates and an anchor jump that lands underneath it is the single most
   common failure of a table of contents. */
.gd-body { counter-reset: gdsec; }
/* THE CHILD COMBINATOR IS LOAD-BEARING. Two other <h2>s live inside
   .gd-body and neither is a section of the document: the offer panel's
   "Take the guide with you." and the FAQ's "Questions people ask about
   this." A descendant selector numbers both of them and, worse, INCREMENTS
   THE COUNTER for both, so every real section after the offer printed a
   numeral one higher than its row in the rail. The document's own sections
   are the only direct h2 children of .gd-body.

   padding-top and border-top UNDO .legal__body's own chapter rule, which
   .gd-body inherits. The numeral's ::before carries the rule now, and two
   hairlines eight pixels apart is what shipped without this. */
.gd-body > h2 {
  counter-increment: gdsec;
  position: relative;
  margin-top: var(--s-12);
  padding-top: 0;
  border-top: 0;
}
.gd-body > h2:first-of-type { margin-top: 0; }
/* the FAQ band's own heading is not a section of the document either */
.gd-body .svc-faq h2 { padding-top: 0; border-top: 0; }
.gd-body > h2::before {
  content: counter(gdsec, decimal-leading-zero);
  display: block;
  width: 100%;
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-4);
  border-bottom: 1px solid var(--line);
  font: 600 13px/1 var(--font-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: .08em;
  color: var(--navy-300);
}
.gd-body h2,
.gd-body h3 { scroll-margin-top: calc(var(--header-h) + var(--s-6)); }
/* scroll-behavior: smooth is never declared anywhere on this page. */


/* ==========================================================================
   SPEC-GD-R4 §6.3 — the in-body illustrations
   ==========================================================================
   Two or three per guide, injected at <h2> boundaries, captionless and
   alt="". A caption would be template-authored copy describing a drawing, and
   the h2 sitting immediately beneath it already says what the section is
   about. The mount is ASSETS-R4 §1's: white ground, --navy-050 plate,
   multiply. */

.g4-fig {
  margin-block: var(--s-10);
  border-radius: var(--r-lg);
  border: 1px solid var(--navy-100);
  background: var(--navy-050);
  overflow: clip;
  aspect-ratio: 16 / 9;
}
.g4-fig img { display: block; width: 100%; height: 100%; object-fit: contain; mix-blend-mode: multiply; }
/* .post-body breaks a <figure> out to 905px at >=1180, which is the BLOG's
   device for a photograph inside an article. A reference document keeps its
   left and right edges: the rail and the prose establish the measure and a
   drawing that runs past it reads as a different page. The inner radius goes
   with it, because .post-body figure img adds one inside a wrapper that
   already clips at --r-lg. */
.gd-body .g4-fig     { width: auto; max-width: 100%; }
.gd-body .g4-fig img { border-radius: 0; }
@supports not (mix-blend-mode: multiply) {
  .g4-fig     { background: var(--paper); }
  .g4-fig img { mix-blend-mode: normal; }
}


/* ==========================================================================
   SPEC-GD-R4 §6.4 — tables. Ruled ledgers with a sticky first column.
   ==========================================================================
   A RULED table, never a boxed one. <caption> is required and is the table's
   accessible name; it renders above, left-aligned, at caption size. scope is
   mandatory on both axes.

   THE ONE BEHAVIOURAL CHANGE ON THIS PAGE. R3 stacked a table to cards below
   768. A three-column cost comparison IS a comparison, and stacking turns
   each row into a card and destroys the one thing the table exists for:
   reading DOWN a column. The reader can no longer answer "which of these is
   cheapest" without holding four cards in their head. A sticky row label plus
   a scrolling value area keeps the comparison intact on a 350px screen, which
   is what every financial table on a phone does.

   The data-th attributes the converter wrote to every <td> stay in the
   database, become unused, and are harmless. */

.gd-table-wrap {
  position: relative;
  margin-block: var(--s-9);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: thin;
}
.gd-table { width: 100%; border-collapse: separate; border-spacing: 0; font: var(--t-body-sm); }

/* THE UN-BOXING, AND IT IS NOT COSMETIC TIDYING.
   .gd-body composes .legal__body, and pages.css gives .legal__body table a
   1px border, a --r-md radius, overflow: hidden and MIN-WIDTH: 480px, plus a
   --navy-050 fill on every thead cell. That is the legal-page treatment and
   it is correct there. Here it produces exactly what §6.4 forbids, a boxed
   table, and the inherited min-width would fight the one this file sets
   deliberately below. Every property here undoes one inherited declaration
   and adds nothing. */
.gd-body .gd-table {
  min-width: 0;
  border: 0;
  border-radius: 0;
  overflow: visible;
}
.gd-body .gd-table thead th { background: var(--paper); }
.gd-body .gd-table :is(td, tbody th) { border-top: 0; }
.gd-body .gd-table tbody tr:first-child :is(td, th) { border-top: 0; }
/* caption-side IS NOT redundant. The site's base sheet sets it to `bottom`
   for the legacy .legal-table-wrap tables, and a caption that is the table's
   accessible name has to be read BEFORE the table, not after it. */
.gd-table caption {
  caption-side: top;
  padding-top: 0;                 /* undoes .legal__body caption */
  margin-bottom: var(--s-3);
  font: var(--t-cap);
  color: var(--ink-3);
  text-align: left;
}
.gd-table th,
.gd-table td {
  padding: var(--s-4) var(--s-5) var(--s-4) 0;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
}
.gd-table thead th {
  font: 600 12px/1.2 var(--font-display);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--navy-300);
  border-bottom: 1px solid var(--navy-100);
}
.gd-table tbody th { font-weight: 600; color: var(--ink); }
.gd-table td       { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.gd-table tbody tr:last-child :is(th, td) { border-bottom: 0; }

/* a cost table has exactly three columns, what you get / typical monthly
   range / what moves it, and the range column is right-aligned and tabular */
.gd-table--cost td:nth-child(2) { text-align: right; white-space: nowrap; font-weight: 600; color: var(--ink); }

/* zebra: ONE tint, on the row, so a five-column table can be read across */
.gd-table tbody tr:nth-child(even) :is(th, td) { background: var(--wash); }

.gd-body .gd-table-hint { margin-top: var(--s-3); font: var(--t-micro); color: var(--ink-3); }
.gd-table-hint::after { content: " \2192"; }

@media (max-width: 767px) {
  /* min-width forces the scroll DELIBERATELY, and it is the opposite of the
     inherited min-width this file undoes above. That one was on the table
     inside a container with no overflow, so it scrolled the PAGE. This one is
     on the table inside .gd-table-wrap, which owns the scroll: the document's
     own scrollWidth is unchanged and the no-horizontal-overflow check still
     passes. */
  /* .gd-body .gd-table, NOT .gd-table: the un-boxing block above has to
     out-specify .legal__body's inherited min-width, so the only way to set a
     min-width here is at the same weight. */
  .gd-body .gd-table { min-width: 560px; }
  .gd-table :is(thead, tbody) th:first-child,
  .gd-table tbody th {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 132px;
    max-width: 148px;
    background: var(--paper);
    box-shadow: 1px 0 0 0 var(--line);
  }
  .gd-table tbody tr:nth-child(even) th { background: var(--wash); }
  .gd-table th, .gd-table td { padding-right: var(--s-4); }
  /* the hint belongs to the table it follows, so the wrapper gives up its
     48px foot to it rather than leaving the instruction floating */
  .gd-body .gd-table-wrap:has(+ .gd-table-hint) { margin-bottom: var(--s-3); }
  .gd-body .gd-table-hint { margin-bottom: var(--s-9); }
}
/* DEVIATION FROM §6.4, RECORDED. The spec's affordance is a right-edge fade
   on .gd-table-wrap::after at `position: absolute; right: 0`. Inside an
   overflow-x container an absolutely positioned child is placed against the
   SCROLLED padding box, so that rule paints the fade at the right end of the
   table's full 560px width and not at the container's edge: it is invisible
   until the reader has already scrolled to the end, which is the one moment
   it should not be there. Every workaround is a hack (a sticky float, a
   local-attachment background under transparent cells, a mask that fades the
   last column). The affordance is therefore the injected hint below, which is
   explicit, translatable, readable by a screen reader and cannot be painted
   in the wrong place. */
@media (min-width: 768px) { .gd-body .gd-table-hint { display: none; } }


/* ==========================================================================
   SPEC-GD-R4 §6.5 — callouts. Two variants and no more.
   ==========================================================================
   Keeps its class, its two variants and its markup. It gains a real head row
   with a mark, delivered as a background-image data-URI on the head's
   ::before, so NO MARKUP CHANGES AND NO REQUEST IS MADE. The two marks are
   the `bulb` and `alert` icons from the R4 set, written out once each.

   A plate, not a card: ground fill plus one 3px inset edge and one hairline,
   no shadow. */

.gd-note {
  position: relative;
  margin-block: var(--s-9);
  padding: var(--s-6) var(--s-6) var(--s-6) var(--s-7);
  border-radius: var(--r-md);
  background: var(--navy-050);
  border: 1px solid var(--navy-100);
  box-shadow: inset 3px 0 0 0 var(--navy);
}
.gd-note--tip  { box-shadow: inset 3px 0 0 0 var(--gold); }
/* --gold-050 fill with a #F0DFA8 hairline. That hex is the page's ONE new
   colour value: --gold-200 darkened to read against its own fill, used as a
   border and never as text. */
.gd-note--warn { background: var(--gold-050); border-color: #F0DFA8; box-shadow: inset 3px 0 0 0 var(--gold-600); }
.gd-note__h {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font: 600 12px/1.2 var(--font-display);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--navy);
}
.gd-note__h::before {
  content: "";
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  /* the `bulb` and `alert` marks from ASSETS-R4 §2, path-for-path as
     inc/icons-r4.php's header publishes them. They live here rather than in
     the PHP table because their only consumers are these two pseudo-elements,
     and as a data-URI they cost no request and no markup change. */
  background: center / contain no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23022D5A' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.2 17.4h5.6'/%3E%3Cpath d='M10 20.4h4'/%3E%3Cpath d='M12 3.2a5.8 5.8 0 0 0-3.4 10.5c.5.4.8 1 .8 1.6h5.2c0-.6.3-1.2.8-1.6A5.8 5.8 0 0 0 12 3.2Z'/%3E%3C/svg%3E");
}
.gd-note--warn .gd-note__h::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23022D5A' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.6 2.8 19.8h18.4Z'/%3E%3Cpath d='M12 9.8v4.4'/%3E%3Cpath d='M12 17.4h.02'/%3E%3C/svg%3E");
}
.gd-note > p + p { margin-top: var(--s-3); }
.gd-note p:not(.gd-note__h) { margin-top: var(--s-3); font: var(--t-body-sm); color: var(--ink-2); max-width: none; }


/* ==========================================================================
   SPEC-GD-R4 §6.6 — the checklist, with progress
   ==========================================================================
   Server-rendered as real <input type="checkbox"> + <label for>. With
   JavaScript off it is a working, tickable, keyboard-operable checklist that
   simply does not remember, the meter's <output> reads "0 of N done" because
   PHP counted the boxes, and the bar sits at zero. It is NEVER rendered as
   <li> and upgraded by script.

   accent-color rather than appearance: none and a custom box: the native
   control is already 20px, keyboard-operable, focus-visible, and correct in
   forced-colors mode. :has() degrades to no strike-through in older engines,
   which costs nothing. */

.gd-check {
  margin-block: var(--s-10);
  padding: var(--s-7);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
}
.g4-meter       { display: grid; gap: var(--s-3); margin-bottom: var(--s-5); }
.g4-meter__out  { font: 600 13px/1.2 var(--font-ui); letter-spacing: .02em; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.g4-meter__rail { display: block; height: 4px; border-radius: 4px; background: var(--navy-100); overflow: hidden; }
.g4-meter__fill {
  display: block;
  height: 100%;
  width: var(--pct, 0%);
  background: var(--gold);
  transition: width var(--dur-3) var(--ease-out);
}
/* .legal__body PUTS A 5px DOT BACK ON EVERY ul > li AND INDENTS IT, which is
   right for a legal document's prose lists and wrong for a checklist whose
   marker is a checkbox and for a takeaway list whose marker is an icon. The
   three declarations below undo exactly that, scoped to the two blocks that
   carry their own marker, so the author's ordinary lists keep their dots. */
.gd-body :is(.gd-check__list, .gd-take ul, .gd-take__list) { list-style: none; padding-left: 0; }
.gd-body :is(.gd-check__list, .gd-take ul, .gd-take__list) > li { padding-left: 0; }
.gd-body :is(.gd-check__list, .gd-take ul, .gd-take__list) > li::before { content: none; }
.gd-body :is(.gd-check__list, .gd-take ul, .gd-take__list) > li + li { margin-top: 0; }

.gd-check__item {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  padding-block: var(--s-4);
}
.gd-check__item + .gd-check__item { border-top: 1px solid var(--line-2); }
.gd-check__box  { width: 20px; height: 20px; margin-top: 2px; accent-color: var(--navy); }
.gd-check__item label { font: var(--t-body-sm); color: var(--ink-2); cursor: pointer; }
.gd-check__item label strong { display: block; font-weight: 600; color: var(--ink); }
.gd-check__item:has(:checked) label strong {
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-color: var(--navy-300);
}
/* always rendered, JavaScript or not. Telling a reader their ticks never
   leave the browser is a privacy statement, not a hint. */
.gd-body .gd-check__note {
  margin-top: var(--s-5);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line-2);
  font: var(--t-micro);
  color: var(--ink-3);
}


/* ==========================================================================
   SPEC-GD-R4 §5 — key takeaways, hoisted to their own band
   ==========================================================================
   The converter writes <aside class="gd-take"> into post_content and R4 lifts
   the FIRST occurrence out of the sanitised body and renders it as band 2.
   THE DATABASE IS NOT TOUCHED: the class is the hook, the markup is the
   author's, and a second .gd-take deeper in the document still renders in
   place with the same rules.

   A --paper plate on a --wash band with a 72x3 gold mark on its top rule,
   which is the same device the register grid uses and is what ties this page
   to the two singles. The list runs two-up at >=768 with one 24px mark per
   item, keyed to that item's own words. The R3 8px dash is retired. */

.g4-take        { padding-block: var(--band-y, clamp(56px, 5.4vw, 96px)); background: var(--wash); }
.g4-take__plate {
  position: relative;
  padding: var(--s-8) var(--s-7);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.g4-take__plate::before {
  content: "";
  position: absolute;
  left: var(--s-7);
  top: -2px;
  width: 72px;
  height: 3px;
  background: var(--gold);
}
.gd-take__h { font: var(--t-eyebrow); text-transform: uppercase; letter-spacing: .14em; color: var(--navy); }
.g4-take .gd-take__list,
.g4-take ul { margin-top: var(--s-6); list-style: none; display: grid; gap: 0; }
.g4-take li {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  padding-block: var(--s-5);
  border-top: 1px solid var(--line-2);
}
.g4-take li:first-child { border-top: 0; }
.g4-take__ico svg { display: block; width: 24px; height: 24px; color: var(--navy); }
.g4-take__t  { font: var(--t-body); color: var(--ink-2); max-width: 46ch; }
.g4-take li::before { content: none; }         /* the R3 dash is retired here */

@media (min-width: 768px) {
  .g4-take .gd-take__list,
  .g4-take ul { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-10); }
  .g4-take li:nth-child(2) { border-top: 0; }
}
@media (min-width: 1180px) { .g4-take__plate { padding: var(--s-9) var(--s-10); } }

/* a SECOND .gd-take, left in the body where the author put it, keeps its R3
   plate and gains the same mark in place of the dash */
.gd-body .gd-take {
  margin-block: var(--s-9);
  padding: var(--s-6) var(--s-7);
  background: var(--wash);
  border-radius: var(--r-md);
}
.gd-body .gd-take ul,
.gd-body .gd-take__list { margin-top: var(--s-4); list-style: none; }
.gd-body .gd-take li {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  font: var(--t-body-sm);
  color: var(--ink-2);
}
.gd-body .gd-take li + li { margin-top: var(--s-3); }

/* the assumptions band (§E3) borrows .gd-take__list OUTSIDE a .gd-take, where
   it is a plain dashed list and stays one */
.calc-assume .gd-take__list { list-style: none; }
.calc-assume .gd-take__list > li { position: relative; padding-left: var(--s-6); font: var(--t-body-sm); color: var(--ink-2); }
.calc-assume .gd-take__list > li::before { content: ""; position: absolute; left: 0; top: .62em; width: 8px; height: 1px; background: var(--navy-300); }
.calc-assume .gd-take__list > li + li { margin-top: var(--s-3); }


/* ==========================================================================
   SPEC-GD-R4 §6.7 — the sourced stat, and its footnote reference
   ==========================================================================
   A .gd-stat WITHOUT a <sup> footnote reference does not ship: SPEC-G-R3
   §A10's acceptance check compares the two counts and the build fails on a
   mismatch. That check is the mechanism that stops a plausible-sounding
   number becoming an unattributed claim on a client site.

   R4 restyles it from a left rule into a plate and turns the footnote
   reference into a pill rather than a floating digit. */

.gd-stat {
  display: grid;
  gap: var(--s-4);
  margin-block: var(--s-10);
  padding: var(--s-6) var(--s-6) var(--s-6) var(--s-7);
  border-radius: var(--r-md);
  background: var(--navy-050);
  box-shadow: inset 3px 0 0 0 var(--gold);
}
.gd-stat__num { font: var(--t-num); font-variant-numeric: tabular-nums; letter-spacing: -.032em; color: var(--navy); }
.gd-body .gd-stat__txt { font: var(--t-lead); color: var(--ink-2); max-width: 46ch; }
@media (min-width: 561px) {
  .gd-stat { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s-7); align-items: center; }
}

/* the takeaways band is HOISTED OUT of .gd-body (§5.1) and its items carry
   the same footnote references, so the pill has to reach both or the same
   reference reads two ways on one page */
.gd-body sup,
.g4-take sup { line-height: 0; }
.gd-body sup a,
.g4-take sup a {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  margin-left: 2px;
  border-radius: var(--r-pill);
  background: var(--navy-050);
  font: 600 11px/1.4 var(--font-ui);
  font-variant-numeric: tabular-nums;
  color: var(--navy-500);
  text-decoration: none;
  text-align: center;
  vertical-align: 2px;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.gd-body sup a:hover, .g4-take sup a:hover,
.gd-body sup a:focus-visible, .g4-take sup a:focus-visible { background: var(--navy-100); color: var(--navy); }


/* ==========================================================================
   SPEC-GD-R4 §6.8 — the inline related-service row
   ==========================================================================
   Hooks unchanged. Restyled from a two-rule row into a bordered row with a
   mark, matching the site's index grammar: fill plus a 3px gold left edge on
   hover, no transform, no shadow. At most twice per guide, unchanged.

   ONE mark for all of them, not a mapped one: the row's own title says which
   service it is, and a different drawing on two rows per guide is noise. It
   is a data-URI on the link's ::before, so the markup does not change and no
   request is made. */

.gd-rel { margin-block: var(--s-9); }
.gd-rel__k {
  font: var(--t-micro);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--navy-300);
}
.gd-rel__link {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  margin-top: var(--s-3);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  text-decoration: none;
  transition: background var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.gd-rel__link::before {
  content: "";
  width: 24px;
  height: 24px;
  margin-top: 2px;
  background: center / contain no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236E8FB4' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.2 3.6H6.4a1 1 0 0 0-1 1v14.8a1 1 0 0 0 1 1h11.2a1 1 0 0 0 1-1V8.2Z'/%3E%3Cpath d='M14.2 3.6v4.6h4.4'/%3E%3Cpath d='M8.6 14.2h6.2'/%3E%3Cpath d='M12.4 11.8l2.4 2.4-2.4 2.4'/%3E%3C/svg%3E");
}
.gd-rel__link:hover,
.gd-rel__link:focus-visible { background: var(--navy-050); border-color: var(--navy-100); box-shadow: inset 3px 0 0 0 var(--gold); }
.gd-rel__t { display: block; font: var(--t-d4); color: var(--navy); }
.gd-rel__d { display: block; margin-top: var(--s-2); font: var(--t-body-sm); color: var(--ink-3); }


/* ==========================================================================
   SPEC-GD-R4 §8.1 — the sources band
   ==========================================================================
   Its own FULL-BLEED --navy-050 band below the document, and it is the page's
   ONE tinted plane. The page carries zero full-bleed navy bands on purpose: a
   four-thousand-word reference document does not want a mid-document dark
   landmark, because the reader is inside the argument there and not being
   sold to. The page's dark moment is the contained plate at the close.

   Absent entirely when the guide has no <sup> references: an empty Sources
   heading is worse than none, and it is also the thing that would let an
   unsourced number look sourced.

   --- the bands -----------------------------------------------------------
   There is no `.section` utility on this site and there is not going to be
   one: every band on every template declares its own padding-block and its
   own ground, which is what makes SPEC-00 §2.3's alternation auditable by
   reading a stylesheet instead of a template. These follow that convention
   exactly. --------------------------------------------------------------- */
.gd-sources {
  padding-block: var(--band-y-lg, clamp(72px, 7.4vw, 128px));
  background: var(--navy-050);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.g4-more     { padding-block: var(--band-y, clamp(56px, 5.4vw, 96px)); background: var(--paper); }
.gd-leadband { padding-block: var(--section-y); background: var(--paper); }
.gd-idxband  { padding-block: var(--section-y); background: var(--wash); }
.gd-hubs     { padding-block: var(--s-10); background: var(--paper); }
.calc-band   { padding-block: var(--section-y); background: var(--paper); }
.calc-assume { padding-block: var(--section-y); background: var(--wash); }
.faq-band    { padding-block: var(--section-y); background: var(--paper); }

/* DEVIATION FROM §8.1, AND IT IS A CORRECTNESS ONE. The spec gives the row a
   three-track grid, numeral / citation / return arrow. A citation is not one
   grid item: every row carries a <cite>, a full stop, a publisher link and
   the arrow, which is four items, so the link landed in the 28px track and
   set "bls.gov" two characters to the line. The row is therefore a block with
   two absolute ends and the citation runs as ordinary inline text between
   them, which is also what lets a citation wrap to three lines without the
   numeral moving.

   THE NUMERAL IS list-style: decimal, NOT A COUNTER, AND THAT IS LOAD-BEARING.
   Every <li> here carries value="N" precisely so a footnote sequence with a
   gap still prints the numeral its <sup> points at. A CSS counter ignores
   `value` and would silently renumber from 1, mislabelling every source after
   the gap on a page whose whole claim is that its numbers are sourced. */
.gd-src__list { margin-top: var(--s-7); list-style: decimal outside; padding-left: var(--s-7); }
.gd-src__list li {
  position: relative;
  padding: var(--s-5) 36px var(--s-5) var(--s-2);
  border-bottom: 1px solid var(--navy-100);
  font: var(--t-body-sm);
  color: var(--ink-2);
}
.gd-src__list li::marker {
  font: 600 13px/1.6 var(--font-display);
  font-variant-numeric: tabular-nums;
  color: var(--navy-300);
}
.gd-src__list li:last-child { border-bottom: 0; }
.gd-src__list cite { font-style: normal; font-weight: 600; color: var(--ink); }
.gd-src__list a    { color: var(--navy-500); }
/* a 28px target rather than a 2px-margin glyph */
.gd-src__back {
  position: absolute;
  right: 0;
  top: calc(var(--s-5) - 3px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-xs);
  text-decoration: none;
  /* --navy-500, not --navy-300: this is a 14px glyph rather than a >=24px
     mark, and --navy-300 on a --navy-050 ground does not carry one. */
  color: var(--navy-500);
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.gd-src__back:hover,
.gd-src__back:focus-visible { background: var(--paper); color: var(--navy); }
.gd-src__note { margin-top: var(--s-7); font: var(--t-cap); color: var(--ink-3); }
/* SPEC-00's 44px floor beats §8.1's 28px box on a touch screen. The mark stays
   28px; only the target grows, and the row's right padding grows with it so
   the citation never runs under it. */
@media (max-width: 767px) {
  .gd-src__list li { padding-right: 48px; }
  .gd-src__back    { width: 44px; height: 44px; top: calc(var(--s-5) - 11px); right: -8px; }
}


/* ==========================================================================
   SPEC-GD-R4 §7 — the offer panel
   ==========================================================================
   NOTHING ABOUT THE GATE'S BEHAVIOUR CHANGES. SPEC-G-R3 §B1 (the whole guide
   is visible and this is a PDF offer, not a gate), §B2 (placed at a top-level
   <h2> boundary about 30% in), §B3 (three fields plus a honeypot, no phone
   field) and §B4 (the wiring point) all stand. Only §B5's style is
   superseded.

   R4 turns it from a tinted box into a --paper plate with a 4px gold top
   rule, the only 4px gold on the page, and gives it the guide's OWN cover at
   88px. That thumbnail is the single element that makes this an offer for a
   specific thing rather than a form.

   THE FORM MOVES ONTO A --navy-050 INSET INSIDE THE PAPER PLATE. SPEC-00 §7.6
   requires form fields on --paper or --wash; the fields themselves stay
   --paper and the tint is the panel behind them, which is what separates the
   offer from the document it is sitting inside. */

.gd-gate {
  position: relative;
  margin-block: var(--s-12);
  padding: var(--s-8) var(--s-7) var(--s-7);
  border: 1px solid var(--navy-100);
  border-radius: var(--r-lg);
  background: var(--paper);
  display: grid;
  gap: var(--s-6);
  scroll-margin-top: calc(var(--header-h) + var(--s-6));
  overflow: clip;
}
.gd-gate::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; background: var(--gold); }
.gd-gate__thumb {
  display: block;
  margin-bottom: var(--s-5);
  width: 88px;
  height: auto;
  border-radius: var(--r-sm);
  border: 1px solid var(--navy-100);
  background: var(--navy-050);
  mix-blend-mode: multiply;
}
@supports not (mix-blend-mode: multiply) { .gd-gate__thumb { mix-blend-mode: normal; background: var(--paper); } }
/* .gd-body PREFIXES, AND THEY ARE NOT DECORATION. This panel is a block
   inside .legal__body / .post-body, and those two carry
   `.post-body :is(p, ul, ol, dl, li) { font-size: 18px }` at >=1024 and
   `.legal__body h2 { margin-top; padding-top; border-top }` at every width.
   Both out-specify a single class, so without the prefix the offer's legal
   line set at 18px and a hairline appeared between the eyebrow and the
   heading. Each declaration below undoes exactly one inherited one. */
.gd-body .gd-gate__h   { margin-top: var(--s-4); padding-top: 0; border-top: 0; font: var(--t-d3); color: var(--ink); }
.gd-body .gd-gate__t   { margin-top: var(--s-3); font: var(--t-body-sm); color: var(--ink-3); max-width: 42ch; }
.gd-body .gd-gate__alt { margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--line-2); font: var(--t-cap); color: var(--ink-3); }
.gd-gate__form  { padding: var(--s-6); border-radius: var(--r-md); background: var(--navy-050); }
.gd-gate__form > * + * { margin-top: var(--s-4); }
.gd-gate .btn   { width: 100%; }
.gd-body .gd-gate__legal { font: var(--t-micro); color: var(--ink-3); }
/* the honeypot, identical to page-contact.php's: not a visual element, not in
   the tab order, not in the accessibility tree */
.gd-gate .field--hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* DEVIATION FROM §7.1, RECORDED AND MEASURED. The spec's grid is
   `88px minmax(0,1fr) 300px` at >=900 and `132px ... 300px` at >=1180, but
   those are VIEWPORT queries and this panel does not live at the viewport's
   width: it is a block inside .gd-body, which is capped at 66ch = 713px on
   every screen from 1024 up. Three tracks inside 713 less padding leaves the
   copy column 129px wide, which is what shipped for one render and read as a
   column of two-word lines.

   The thumbnail therefore sits ABOVE the copy rather than beside it, which
   is the only arrangement that gives the heading and the promise a real
   measure at 713. Two tracks, 329px of copy against a 280px form. */
@media (min-width: 768px) {
  .gd-gate {
    grid-template-columns: minmax(0, 1fr) 280px;
    column-gap: var(--s-8);
    padding: var(--s-8) var(--s-7) var(--s-7);
    align-items: stretch;
  }
  /* the form is the taller column, so the copy's last line is pushed to the
     panel's foot rather than leaving 180px of empty plate under it */
  .gd-gate__copy { display: flex; flex-direction: column; }
  .gd-body .gd-gate__alt { margin-top: auto; }
}
@media (min-width: 1180px) { .gd-gate__thumb { width: 112px; } }


/* ==========================================================================
   SPEC-GD-R4 §8.2 — the guides index, now a shelf
   ==========================================================================
   A ruled numbered index, NOT a card grid. R4 gives the row a cover
   thumbnail in a new first track, which is what turns a list of titles into a
   shelf, and moves the numeral onto the thumbnail as a small chip rather than
   letting it own a 48px track of its own.

   The numeral is menu_order, not date: the five guides have a deliberate
   reading order and it is set in the CMS. */

.gd-index { list-style: none; margin-top: var(--s-8); }
.gd-index__row {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) 20px;
  gap: var(--s-5);
  align-items: center;
  padding-block: var(--s-5);
  padding-inline: var(--s-4);
  margin-inline: calc(var(--s-4) * -1);
  border-top: 1px solid var(--line);
  text-decoration: none;
  transition: background var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.gd-index__item:last-child .gd-index__row { border-bottom: 1px solid var(--line); }
.gd-index__row:hover,
.gd-index__row:focus-visible { background: var(--navy-050); box-shadow: inset 3px 0 0 0 var(--gold); }
.gd-index__cov { position: relative; display: block; }
.gd-index__cov img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-xs);
  border: 1px solid var(--navy-100);
  background: var(--navy-050);
  mix-blend-mode: multiply;
}
@supports not (mix-blend-mode: multiply) { .gd-index__cov img { mix-blend-mode: normal; background: var(--paper); } }
.gd-index__num {
  position: absolute;
  left: 0;
  top: 0;
  padding: 2px 5px;
  background: var(--navy);
  color: #fff;
  border-radius: var(--r-xs) 0 var(--r-xs) 0;
  font: 600 11px/1.3 var(--font-display);
  font-variant-numeric: tabular-nums;
}
.gd-index__body { min-width: 0; }
.gd-index__t { display: block; font: var(--t-d4); color: var(--navy); overflow-wrap: anywhere; }
.gd-index__p { display: block; margin-top: var(--s-2); font: var(--t-body-sm); color: var(--ink-3); max-width: 60ch; }
.gd-index__meta {
  display: flex; flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  margin-top: var(--s-3);
  font: var(--t-cap);
  color: var(--ink-3);
}
/* --gold-050 fill, a --gold-200 hairline, NAVY text: gold is never text on a
   light surface (SPEC-00 §3.5) and this tag obeys it. */
.gd-index__tag {
  padding: 2px var(--s-3);
  border-radius: var(--r-pill);
  background: var(--gold-050);
  border: 1px solid var(--gold-200);
  font: 600 11px/1.5 var(--font-display);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--navy);
}
.gd-index__go { justify-self: end; align-self: center; width: 16px; height: 16px; color: var(--navy-300); }
@media (min-width: 768px) {
  .gd-index__row { grid-template-columns: 88px minmax(0, 1fr) 20px; padding-block: var(--s-6); }
}
@media (max-width: 480px) {
  .gd-index__row { grid-template-columns: 56px minmax(0, 1fr); gap: var(--s-4); }
  .gd-index__go  { display: none; }
}
.gd-hubline {
  display: flex; flex-wrap: wrap;
  gap: var(--s-4) var(--s-8);
  margin-top: var(--s-9);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}


/* ==========================================================================
   SPEC-GD-R4 §8.2 row 2 — the services this guide is about
   ==========================================================================
   Three cards taken from the guide's own in-body .gd-rel links, so nothing is
   invented and no new field is needed. The grammar is the service single's
   related row, restated here rather than inherited: --paper, 1px --line,
   --r-md, no shadow, hover fills --navy-050 and moves the border to --navy,
   no transform. The markup also carries .s4-rel__card so the two stay one
   object if that file ever owns the rules. */

.g4-more__rule { height: 1px; margin-block: var(--s-10); background: var(--line); }
.g4-svc {
  display: grid;
  gap: var(--s-6);
  margin-top: var(--s-7);
  list-style: none;
}
.g4-svc__card {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) 16px;
  gap: var(--s-4);
  align-items: center;
  height: 100%;
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  text-decoration: none;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.g4-svc__card:hover,
.g4-svc__card:focus-visible { background: var(--navy-050); border-color: var(--navy); }
.g4-svc__ico svg { display: block; width: 24px; height: 24px; color: var(--navy); }
.g4-svc__t   { font: var(--t-d4); color: var(--navy); }
.g4-svc__card > svg { width: 16px; height: 16px; color: var(--navy-300); }
@media (min-width: 768px)  { .g4-svc { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .g4-svc { grid-template-columns: repeat(3, minmax(0, 1fr)); } }


/* ==========================================================================
   ASSETS-R4 §4.5 — the asset fallbacks, stated once
   ==========================================================================
   The illustration set is produced by a parallel build. Every mount above is
   file_exists()-guarded in PHP, so a missing drawing never reaches the page
   as a broken box; what it leaves behind is an empty track in a grid that was
   sized for it. These four rules close those tracks, so this template is
   correct with zero .webp files on disk and correct again the moment they
   land. No JavaScript, no second markup path. */

.gd-index__cov { aspect-ratio: 4 / 3; border-radius: var(--r-xs); }
.gd-index__cov img { height: 100%; object-fit: contain; }
.gd-index__cov:not(:has(img)) { background: var(--navy-050); border: 1px solid var(--navy-100); }
.g4-rail__dlrow:not(:has(img)) { grid-template-columns: minmax(0, 1fr); }
/* the gate needs no fallback of its own: the thumbnail sits above the copy in
   normal flow, so its absence closes the space and moves nothing. */


/* ==========================================================================
   §C3 — the lead card for guide #1. One band, not a hero clone.
   ========================================================================== */

.gd-lead {
  display: grid;
  gap: var(--s-7);
  padding: var(--s-7);
  border-radius: var(--r-lg);
  background: var(--wash);
}
@media (min-width: 1024px) {
  .gd-lead { grid-template-columns: minmax(0, 1fr) 420px; gap: var(--s-9); padding: var(--s-9); align-items: center; }
}
.gd-lead__k { font: var(--t-micro); letter-spacing: .12em; text-transform: uppercase; color: var(--navy-300); }
.gd-lead__h { margin-top: var(--s-3); font: var(--t-d2, var(--t-d3)); color: var(--navy); }
.gd-lead__rule { width: 220px; max-width: 60%; height: 1px; margin-top: var(--s-5); background: var(--navy-100); }
.gd-lead__p { margin-top: var(--s-5); font: var(--t-body-sm); color: var(--ink-3); max-width: 54ch; }
.gd-lead__list { margin-top: var(--s-5); list-style: none; }
.gd-lead__list li {
  position: relative;
  padding-left: var(--s-6);
  font: var(--t-body-sm);
  color: var(--ink-2);
}
.gd-lead__list li + li { margin-top: var(--s-3); }
.gd-lead__list li::before { content: ""; position: absolute; left: 0; top: .62em; width: 8px; height: 1px; background: var(--navy-300); }
.gd-lead__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-5); margin-top: var(--s-7); }
.gd-lead__plate { border-radius: var(--r-md); overflow: clip; background: var(--navy-050); }
.gd-lead__plate img { display: block; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 3 / 2; }


/* ==========================================================================
   §D3 — the FAQs hub
   ==========================================================================
   THE NO-JS CONTRACT: the chips are plain in-page anchors, every group is
   rendered and visible, and each chip jumps to its heading. All content is
   always in the DOM. With JavaScript the chips additionally toggle `hidden`
   on the non-matching groups — an enhancement over a page that already works.

   Sticky only at >=1024, per the project rule: below that a sticky chip row
   eats a third of a phone viewport. */

.faq-bar {
  position: sticky;
  top: var(--header-h);
  z-index: var(--z-rail);
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.faq-bar__list {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  padding-block: var(--s-4);
  scrollbar-width: none;
  list-style: none;
}
.faq-bar__list::-webkit-scrollbar { display: none; }
.faq-bar__chip {
  flex: 0 0 auto;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  background: var(--navy-050);
  font: 600 13px/1 var(--font-ui);
  color: var(--navy);
  text-decoration: none;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.faq-bar__chip:hover { background: var(--navy-100); }
.faq-bar__chip[aria-pressed="true"] { background: var(--navy); color: var(--paper); }
@media (max-width: 1023px) { .faq-bar { position: static; } }

.faq-group { scroll-margin-top: calc(var(--header-h) + var(--s-8)); }
.faq-group__grid { display: grid; gap: var(--s-7); }
@media (min-width: 1180px) {
  /* the same 380 / rest split the service and industry FAQ bands use, so this
     page registers to the rest of the site rather than inventing a geometry */
  .faq-group__grid { grid-template-columns: 380px minmax(0, 1fr); gap: var(--s-10); align-items: start; }
}
.faq-group__n { margin-top: var(--s-3); font: var(--t-cap); color: var(--ink-3); }
.faq-src {
  display: inline-block;
  margin-top: var(--s-4);
  font: 600 13px/1.3 var(--font-ui);
  color: var(--navy-500);
  text-decoration: none;
}
.faq-src:hover { text-decoration: underline; text-underline-offset: 3px; }
.faq-group__foot { margin-top: var(--s-6); }


/* ==========================================================================
   §E2 — the cost estimator
   ==========================================================================
   Inputs left, output right, and THE OUTPUT IS THE SHORTER COLUMN so the
   output is the one that sticks (§J.5). Ground --wash for the inputs, --paper
   for the output plate. Zero backdrop-filter, zero shadow, zero photographs. */

.calc__grid { display: grid; gap: var(--s-7); }
@media (min-width: 1024px) {
  .calc__grid { grid-template-columns: minmax(0, 1fr) 360px; gap: var(--s-9); align-items: start; }
  .calc__out {
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
  }
}
.calc__panel { padding: var(--s-7); border-radius: var(--r-md); background: var(--wash); }
.calc__fields { display: grid; gap: var(--s-5); }
@media (min-width: 768px) { .calc__fields { grid-template-columns: 1fr 1fr; } }
.calc__fields .field--wide { grid-column: 1 / -1; }
.calc__hint { margin-top: var(--s-5); font: var(--t-micro); color: var(--ink-3); }

/* <output> is hidden until the script populates it, so with JavaScript off it
   is absent from the accessibility tree and the reader goes straight to the
   static plan tables below, which carry every number it would have computed. */
.calc__out {
  display: block;
  padding: var(--s-7);
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line);
}
.calc__band { font: var(--t-micro); letter-spacing: .12em; text-transform: uppercase; color: var(--navy-300); }
.calc__plan { margin-top: var(--s-2); font: var(--t-d3); color: var(--navy); }
.calc__range {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  font: var(--t-num-sm);
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}
.calc__per { display: block; margin-top: var(--s-2); font: var(--t-cap); color: var(--ink-3); }
.calc__break { margin-top: var(--s-5); list-style: none; }
.calc__break li {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding-block: var(--s-2);
  font: var(--t-body-sm);
  color: var(--ink-3);
}
.calc__break li + li { border-top: 1px solid var(--line-2); }
.calc__break li span:last-child { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.calc__caveat { margin-top: var(--s-5); font: var(--t-micro); color: var(--ink-3); }
.calc__cta { margin-top: var(--s-5); }

/* the static reference tables. NEVER hidden by script: they stay below the
   output as the "what this is based on" reference, which is also what makes
   the page indexable and what a screen-reader user reading linearly wants. */
.calc-static { margin-top: var(--s-9); }
.calc-static__h { font: var(--t-d4); color: var(--navy); }
.calc-assume { background: var(--wash); }
.calc-assume ul { margin-top: var(--s-7); }


/* ==========================================================================
   §A9 — reduced motion
   ==========================================================================
   There is nothing to reduce here that the global rule does not already
   handle: every state change in this file is a colour or an inset edge on a
   --dur-1 transition, and the global reduce rule drops those to 1ms. This
   block exists so that a future addition cannot quietly acquire a transform.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .gd-index__row,
  .gd-rel__link,
  .g4-svc__card,
  .g4-toc > li > a,
  .g4-toc > li > a::before,
  .g4-toc__sub a,
  .g4-toc-m__chev,
  .gd-body sup a,
  .gd-src__back,
  .faq-bar__chip { transition: none; }
  /* the meter's width change becomes instant; the <output> beside it is the
     signal and it has not moved */
  .g4-meter__fill { transition: none; }
  /* the progress hairline is the one thing on this page that exists only to
     move, so under reduced motion it is not reduced, it is GONE */
  .g4-prog { display: none; }
}


/* ==========================================================================
   §J.3 — the print sheet
   ==========================================================================
   Orchestrator ruling: guide #1's PDF does not exist yet, so the badge reads
   "PDF coming" and the button reads "Email me the guide". This sheet is how
   that PDF gets made later, from the page itself, with headless Chrome's
   --print-to-pdf. When the file exists it is attached as `gd_pdf` and the
   template flips to path (a) with no CSS change.

   Chrome's print rendering does not honour position:sticky, and a fixed
   header prints on page one and then leaves a 76px hole on every page after
   it, so the header, the footer, the rail, the gate and the CTA all go.
   ========================================================================== */

@media print {
  .site-header,
  .hdr-drawer,
  .ft,
  .g4-rail,
  .g4-toc-m,
  .gd-gate,
  .svc-cta,
  .g4-more,
  .skip,
  .ihero__pattern,
  .ihero__aside,
  .ihero__badge { display: none !important; }

  html, body { background: #fff !important; color: #000 !important; }
  .gd-doc__grid,
  .post-doc__grid { display: block !important; border-top: 0 !important; padding-top: 0 !important; }
  .gd-body,
  .post-body { max-width: none !important; }
  .gd-doc,
  .gd-sources,
  .ihero { padding: 0 !important; background: #fff !important; }
  .gd-sources { border: 0 !important; }
  .gd-body h2,
  .gd-body h3 { break-after: avoid; }
  .gd-table-wrap,
  .gd-note,
  .gd-take,
  .g4-take__plate,
  .g4-fig,
  .gd-stat,
  .gd-check { break-inside: avoid; }
  .gd-note,
  .gd-take,
  .g4-take__plate { background: #f4f4f4 !important; box-shadow: none !important; border-left: 3px solid #000; }
  .gd-stat { border-left: 3px solid #000; }
  /* the table's mobile treatment is a screen affordance and prints as noise */
  .gd-table-hint,
  .g4-meter__rail { display: none !important; }
  .g4-take { padding-block: 0 !important; background: #fff !important; }
  .gd-table { min-width: 0 !important; }

  /* the URL after every external link, so a printed page is still usable.
     Internal links are left alone: printing the whole site's own hostname
     after forty in-page cross-references is noise. */
  .gd-body a[href^="http"]::after,
  .gd-src__list a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 10px;
    word-break: break-all;
  }
  .gd-src__back { display: none; }
}


/* =========================================================================
   MOBILE-QA-2026-09-20 — phone corrections for the resources templates.

   One appended block rather than edits threaded through the file, so the
   whole mobile pass is reviewable and revertible in one place. Nothing here
   changes a layout: it raises type that fell under the 13px floor, and it
   buys hit area with padding on targets that were already correctly placed.
   ========================================================================= */
@media (max-width: 767px) {

  /* --- footnote references (guide) ------------------------------------
     18-24 x 17px superscript pills, the smallest targets on the site. The
     pill is a baseline-aligned inline-block inside running prose, so it
     cannot be grown to 44px square without opening the line boxes around
     it. A transparent ::after extends the TOUCH area to 44x44, centred on
     the pill, while the painted pill keeps its size and the line height
     keeps its rhythm. line-height:0 on the <sup> already stops the pill
     from pushing the line, so the overlay costs nothing vertically. */
  .gd-body sup a,
  .g4-take sup a {
    position: relative;
    min-width: 22px;
    padding: 2px 6px;
    font-size: 13px;
  }
  .gd-body sup a::after,
  .g4-take sup a::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  /* --- FAQ source links ------------------------------------------------
     A 17px-tall block link under each answer. It is already its own line,
     so vertical padding is free: it makes a 44px row without moving the
     text, and the negative margin keeps the gap to the answer above as
     the desktop rule set it. */
  .faq-src {
    /* 14px, not 13: the 13.3px line box rounds the row to 43 and the target
       has to clear 44, not reach it. */
    padding-block: 14px;
    margin-top: var(--s-2);
  }

  /* --- guide checklist -------------------------------------------------
     The 20px box stays a box; the row's <label> is the real target and is
     already full width and >=44px tall. Widening the box to 24px (and its
     grid column with it) makes the control itself legible on a phone
     without changing the row. */
  .gd-check__item { grid-template-columns: 24px minmax(0, 1fr); }
  .gd-check__box  { width: 24px; height: 24px; margin-top: 0; }

  /* --- type floor ------------------------------------------------------
     13px is the floor for meta text (--t-micro and --t-eyebrow are lifted
     to it globally in next.css). These are the literal sub-13px values in
     this file that survive that change. */
  .gd-table thead th { font-size: 13px; letter-spacing: .08em; }
  .gd-note__h        { font-size: 13px; }
  .gd-body .gd-gate__legal,
  .gd-body .gd-check__note { font-size: 13px; }
  .faq-bar__chip { min-height: 44px; }
}
