/* Harbour Lights Community — shared styles
   Used by every page except index.html (which keeps its own tuned inline styles).
   Colours, fonts, nav, quick-exit and safety-dialog live here so they only need
   to be edited once for the whole site. */

:root{
  --black:#0b0b0b;
  --white:#ffffff;
  --gold:#f4c400;
  --stone:#f2efe9;
  --warm-grey:#d8d1c7;
  --ink:#1a1a1a;
  --muted:#66615b;
  --max:1440px;
  --ease:cubic-bezier(.2,.75,.25,1);
  /* Knowledge Centre » Guides page — per-guide rollover accent colours,
     one per cover (see knowledge-centre/guides.html's GUIDE_PRODUCTS
     accentColor fields for which guide uses which, applied via
     agg-product.js's buyBox layout). Kept as named vars, not inlined,
     so the supplied RGB values are on record in one place. */
  --guide-green:rgb(134,168,34);
  --guide-blue:rgb(102,151,226);
  --guide-yellow:rgb(238,194,0);
  --guide-orange:rgb(201,99,6);
  --guide-magenta:rgb(166,58,114);
}
*{box-sizing:border-box}
/* Deliberately NOT scroll-behavior:smooth on <html> globally — it also
   applies to the browser's own back/forward scroll-position restoration,
   which made returning via the back button visibly animate up from the
   top of the page instead of landing instantly where the visitor left
   off. Opt in per element with .smooth-scroll instead (nothing currently
   uses it, but it's there for a future deliberately-animated in-page
   jump, e.g. a "back to top" link). */
.smooth-scroll{scroll-behavior:smooth}
body{margin:0;color:var(--ink);background:var(--stone);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;line-height:1.55;overflow-x:hidden}
button,a{font:inherit} a{color:inherit} :focus-visible{outline:3px solid var(--gold);outline-offset:4px}
.skip-link{position:fixed;left:12px;top:-80px;z-index:200;background:white;color:#111;padding:10px 14px}.skip-link:focus{top:12px}

/* Buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:50px;padding:12px 18px;border:1px solid rgba(255,255,255,.6);text-decoration:none;background:rgba(15,15,15,.38);color:white;backdrop-filter:blur(7px);transition:transform .25s var(--ease),background .25s var(--ease),border-color .25s var(--ease)}
.btn:hover{transform:translateY(-2px);background:white;color:var(--black);border-color:white}.btn.primary{background:var(--gold);color:var(--black);border-color:var(--gold);font-weight:800}
.safety-link{display:inline-block;margin-top:22px;color:white;background:none;border:0;padding:0;text-decoration:underline;text-underline-offset:5px;cursor:pointer}
/* Content-area primary link/button — originated on the homepage's chapter
   panels, now shared so any page (e.g. the aggregate product template below)
   can use the same "primary action" treatment. */
.chapter-link{display:inline-flex;align-items:center;gap:12px;min-height:50px;padding:12px 17px;text-decoration:none;background:var(--black);color:white;border:1px solid var(--black);font-weight:800;transition:background .25s,color .25s,transform .25s}
/* Lighter alternative to .chapter-link — bold text + arrow on a gold rule
   instead of a solid black pill, per the user's "the black buttons across
   the site are so heavy" note. A SEPARATE class, not a change to
   .chapter-link itself: this is a Knowledge Centre-only preview for now,
   to see how it reads before any wider rollout — every other .chapter-link
   on the site is untouched. Nested var() fallback checks BOTH accent
   custom-property names already in use on Knowledge Centre pages —
   --product-accent (individual Guide/Directory product pages) and
   --agg-accent (the aggregate listing's own buy-box cards) — so either
   still picks up that page's own accent colour instead of always
   defaulting to literal gold regardless of which page it's on. */
.chapter-link-light{display:inline-flex;align-items:center;gap:12px;padding:8px 0;text-decoration:none;background:none;color:var(--ink);border:0;border-bottom:3px solid var(--agg-accent,var(--product-accent,var(--gold)));font-weight:800;transition:color .2s}
.chapter-link-light:hover{color:var(--agg-accent,var(--product-accent,#8A6A00))}
/* Disabled variant — same shape as .chapter-link-light, but a <span>
   (no href, nothing to navigate with) and muted grey instead of gold,
   for CTAs pointing at pages that aren't built yet. */
.chapter-link-light-disabled{display:inline-flex;align-items:center;gap:12px;padding:8px 0;color:var(--muted);border:0;border-bottom:3px solid rgba(26,26,26,.15);font-weight:800;cursor:not-allowed;user-select:none}
/* var(--product-accent, var(--gold)), not a literal var(--gold) — pages
   without --product-accent set (most non-Guide pages) fall through to
   the same gold as before, unaffected, but Guide pages now correctly
   hover to their own accent instead of always the site's literal gold
   regardless of which Guide it is (this was hidden on guide-economic.html
   itself, since --guide-yellow happens to be close enough to --gold to
   look right by coincidence — it broke visibly once guide-legal.html/
   guide-reputational.html used real green/blue accents instead). */
.chapter-link:hover{background:var(--product-accent,var(--gold));color:var(--product-accent-ink,var(--black));border-color:var(--product-accent,var(--gold));transform:translateY(-2px)}
/* "Coming Soon" placeholder for an .agg-product whose directory isn't
   purchasable yet — same box dimensions as .chapter-link so swapping one for
   the other doesn't shift the card's layout, but a plain grey outline/text
   instead of the black button. On hover it lightens further (white
   background, --warm-grey text/border) to still give some feedback even
   though there's nothing to click through to yet. */
.agg-product-soon{display:inline-flex;align-items:center;gap:12px;min-height:50px;padding:12px 17px;background:transparent;color:var(--muted);border:1px solid var(--muted);font-weight:800;transition:background .25s,color .25s,border-color .25s}
.agg-product-soon:hover{background:white;color:var(--warm-grey);border-color:var(--warm-grey)}

/* Closing / site footer — moved out to footer.css (its own file, linked
   directly by every page including index.html) so there's exactly one
   definition site-wide, not a copy that happens to match. See footer.css. */

/* Navigation, quick exit */
.nav-trigger,.quick-exit{position:fixed;z-index:80;border:0;cursor:pointer;box-shadow:0 12px 34px rgba(0,0,0,.18)}
.nav-trigger{top:18px;right:18px;min-height:48px;padding:11px 15px;display:flex;align-items:center;gap:10px;color:white;background:var(--black);font-weight:800}.nav-line{width:5px;height:24px;background:var(--gold)}
.quick-exit{right:18px;bottom:18px;min-height:46px;padding:11px 15px;background:var(--black);color:white;font-weight:850}.quick-exit:hover{background:var(--gold);color:var(--ink)}

/* Personalised-navigation control: only inserted (by site.js) while the
   visitor has chosen to keep her Constellation results for this browser
   session. Sits directly under the nav trigger — deliberately kept separate
   from Quick Exit, which must stay a distinct, unrelated safety function. */
.back-to-results{position:fixed;z-index:79;top:74px;right:18px;display:inline-flex;align-items:center;gap:6px;color:white;text-decoration:none;font-weight:700;font-size:.78rem;background:none;border:0;padding:4px 2px;cursor:pointer}
.back-to-results:hover{text-decoration:underline}
.back-to-results .arrow{color:var(--gold)}
.delete-results-nav{position:fixed;z-index:79;top:104px;right:18px;color:rgba(255,255,255,.75);text-decoration:none;font-weight:700;font-size:.78rem;background:none;border:0;padding:4px 2px;cursor:pointer;font-family:inherit}
.delete-results-nav:hover{color:white;text-decoration:underline}
@media(max-width:900px){.back-to-results{top:66px;right:10px}.delete-results-nav{top:96px;right:10px}}
.site-nav{position:fixed;top:0;right:0;bottom:0;z-index:100;width:min(440px,92vw);padding:56px 36px 22px;background:#0c0c0c;color:white;display:flex;flex-direction:column;gap:0;overflow-y:auto;transform:translateX(102%);transition:transform .42s var(--ease)}.site-nav.open{transform:none}
.nav-close{position:absolute;right:20px;top:16px;border:0;background:transparent;color:white;font-size:1.6rem;cursor:pointer}.nav-kicker{color:var(--gold);text-transform:uppercase;letter-spacing:.16em;font-weight:850;font-size:.576rem;margin-top:10px}.nav-scrim{position:fixed;inset:0;z-index:90;background:rgba(0,0,0,.48)}

/* Nav link list, with expandable sub-page groups (Making Sense Of What Is Happening,
   When Tactics Form A Pattern, Knowledge Centre). Sized to fit the whole 6-item
   Journey list on screen without the nav itself needing to scroll on realistic
   viewport heights (~800px+) — see the PSA Framework project memory note on
   2026-08-23's nav restructure. */
.nav-section-title{font-size:.61rem;letter-spacing:.13em;text-transform:uppercase;font-weight:850;color:var(--gold);margin:18px 0 5px;padding-bottom:6px;border-bottom:1px solid rgba(255,255,255,.42)}
.nav-section-title:first-of-type{margin-top:0}
.nav-list{list-style:none;margin:0 0 6px;padding:0}
.nav-list>li{border-bottom:1px solid rgba(255,255,255,.12)}
.nav-list>li>a,.nav-group-row>a{display:block;padding:7px 0;text-decoration:none;font:500 clamp(.7rem,1.05vw,.9rem)/1.15 Georgia,"Times New Roman",serif}
.nav-list>li>a:hover,.nav-group-row>a:hover{color:var(--gold)}
.nav-group-row{display:flex;align-items:stretch}
.nav-group-row>a{flex:1}
.nav-group-toggle{border:0;background:none;color:rgba(255,255,255,.65);cursor:pointer;padding:0 4px;display:flex;align-items:center}
.nav-group-toggle:hover{color:var(--gold)}
.nav-chevron{display:inline-block;font-size:1.02rem;transition:transform .25s var(--ease)}
.nav-group-toggle[aria-expanded="true"] .nav-chevron{transform:rotate(90deg)}
.nav-sublist-wrap{display:grid;grid-template-rows:0fr;transition:grid-template-rows .35s var(--ease)}
.nav-sublist-wrap.open{grid-template-rows:1fr}
.nav-sublist{overflow:hidden;list-style:none;margin:0;padding:0 0 6px 16px}
.nav-sublist li{border-top:1px solid rgba(255,255,255,.08)}
.nav-sublist a{display:block;padding:6px 0;text-decoration:none;font:400 .74rem/1.28 Inter,ui-sans-serif,system-ui,sans-serif;color:rgba(255,255,255,.72)}
.nav-sublist a:hover{color:var(--gold)}
/* Nav items pointing at pages that don't exist/aren't ready yet — per
   the user, disabled (not just styled — a <span>, no href at all, so
   there's nothing to click or navigate with) until those pages are
   built. Same box/type shape as .nav-sublist a, just dimmed further and
   with a "not allowed" cursor instead of the hover-to-gold affordance. */
.nav-link-disabled{display:block;padding:6px 0;font:400 .74rem/1.28 Inter,ui-sans-serif,system-ui,sans-serif;color:rgba(255,255,255,.32);cursor:not-allowed;user-select:none}

/* Safety dialog */
dialog{border:0;padding:0;max-width:560px;width:calc(100% - 32px);box-shadow:0 24px 80px rgba(0,0,0,.35)}dialog::backdrop{background:rgba(0,0,0,.68)}.safety-panel{padding:30px;background:white;border-top:8px solid var(--gold)}.safety-panel h2{font-family:Georgia,"Times New Roman",serif;font-size:1.6rem;margin:0 0 12px}.safety-panel p{margin:0 0 14px}.close-dialog{margin-top:10px;border:1px solid #222;background:white;padding:10px 14px;cursor:pointer}

/* Generic inner-page shell — swap out once real content is designed per page.
   .page-hero/.page-hero-inner/.page-hero h1 (the old simple black-hero
   header these pages used before the universal .feature-header rollout)
   removed as dead CSS — zero remaining users sitewide, confirmed via grep,
   once the last 14 .page-hero pages were converted. .page-kicker itself is
   kept: still used as a general eyebrow style on ~11 other pages/contexts
   unrelated to that old header. */
.page-kicker{font-size:.82rem;letter-spacing:.18em;text-transform:uppercase;font-weight:850;color:var(--gold);margin:0 0 14px}
.page-kicker a{color:inherit;text-decoration:none}
.page-kicker a:hover{text-decoration:underline}
.page-body{padding:clamp(48px,7vw,88px) clamp(24px,5vw,64px);width:min(100%,var(--max));margin:0 auto;min-height:30vh}
.page-placeholder{color:var(--muted);font-size:1rem;max-width:620px}
.page-back{display:inline-block;margin-top:26px;color:var(--ink);text-decoration:underline;text-underline-offset:4px}
.child-links{list-style:none;padding:0;margin:28px 0 0;display:flex;flex-wrap:wrap;gap:12px}
.child-links a{display:inline-flex;align-items:center;min-height:46px;padding:11px 16px;border:1px solid var(--black);text-decoration:none;color:var(--ink);font-weight:700;transition:background .2s,color .2s}
.child-links a:hover{background:var(--black);color:white}

/* Feature page template — black header, cream band, full-bleed photo with an
   overlapping white copy panel (a card that overlaps the photo's bottom
   edge, then continues in normal document flow) and an optional quote card.

   NOT a fixed-height/internal-scroll design any more — it used to be (page
   itself never scrolled; only an internal .feature-panel-scroll did, sized
   to exactly fill the remaining viewport height via position:absolute +
   overflow:hidden on .feature-photo-wrap). That broke real scrolling for at
   least one live visitor testing understanding.html: with .feature-panel
   absolutely positioned, its real content never contributed to the page's
   own height, so the *page* (body/html) had zero scrollable overflow of its
   own — reaching content past what fit in one viewport depended entirely on
   a mouse/trackpad wheel gesture landing precisely inside that one narrow,
   deliberately-scrollbar-hidden column, with no keyboard/Page-Down fallback
   and no visible scrollbar to signal it was even possible. It also meant
   the header could never visibly "scroll away" and the already-fixed
   .nav-trigger/.quick-exit buttons never visibly "float", since nothing
   about the page itself ever moved — inconsistent with every other page on
   the site, which scrolls normally.

   Fixed by using the same static/overlap layout the sub-900px responsive
   version already used correctly (this bug was desktop-only) — .feature-
   panel is a normal in-flow sibling of .feature-photo-wrap now (not nested
   inside it), pulled up over the photo's bottom edge with a negative
   margin, like a card overlapping a hero image. That makes the panel's
   real content height count towards the page's own height, so body/html
   scroll normally — the standard, reliable mechanism — the same as every
   other page on this site. See why-we-are-here.html for a worked example —
   copy that page's <body> markup (photo-wrap, THEN panel as its sibling,
   not nested inside it) to reuse this template. */
html,body{height:auto;min-height:100%}
.feature-page{min-height:100vh;display:flex;flex-direction:column}
.feature-header{background:var(--black);color:white;padding:calc(clamp(26px,4vw,42px) - 15px) clamp(24px,5vw,64px);padding-top:calc(clamp(26px,4vw,42px) - 10px);display:flex;align-items:flex-end;justify-content:space-between;gap:24px;flex-wrap:wrap}
.feature-header .brand{display:flex;align-items:center;gap:14px;margin-bottom:16px;font-size:.72rem;letter-spacing:.15em;text-transform:uppercase;font-weight:700;color:var(--gold)}
.feature-header .brand a{color:inherit;text-decoration:none}
.feature-header .brand a:hover{text-decoration:none}
.feature-header .brand-mark{width:5px;height:calc(.72rem + 4px);background:var(--gold);flex:0 0 auto}
.feature-header h1{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.041rem,2.498vw,2.637rem);line-height:.95;margin:0;letter-spacing:-.03em;font-weight:500;color:white}
/* Promoted from understanding.html's own page-scoped <style> block (where
   this was first built) now that the breadcrumb is rolling out sitewide as
   part of the universal .feature-header — margin-top:16px deliberately
   matches .brand's own margin-bottom above, for symmetric spacing either
   side of the h1 (see that page's project notes for why). */
.feature-breadcrumb{display:flex;align-items:center;gap:6px;font-size:.72rem;color:rgba(255,255,255,.55);margin:16px 0 0}
.feature-breadcrumb a{color:inherit;text-decoration:none}
.feature-breadcrumb a:hover{color:rgba(255,255,255,.85);text-decoration:underline}
.feature-breadcrumb-sep{color:rgba(255,255,255,.35)}
/* .safety-link's own base rule (above) assumes it sits stacked in normal
   flow below a block-level kicker+h1 (its old .page-hero-inner home),
   hence margin-top:22px there — inside .feature-header's flex row
   (align-items:flex-end) that margin just pushes it out of vertical
   alignment with the brand/h1/breadcrumb stack next to it, so it's zeroed
   here specifically. */
.feature-header .safety-link{margin-top:0}
.feature-creamband{height:15.6px;background:var(--stone);flex:0 0 auto}
/* .feature-hero (new wrapper — see the markup) holds the photo and the
   panel as a CSS grid with both sharing grid-area:1/1, i.e. genuinely
   stacked on the same spot rather than one nudged up over the other with
   a guessed negative margin. That guess (a flat -140px) only ever pulled
   the panel up over the photo's own bottom edge, leaving a gap of bare
   photo above it whose size tracked the photo's height — taller photo,
   bigger gap, "What We Hope To Accomplish" pushed further down. Per the
   user's request, the panel should instead touch the cream band right
   under the header, i.e. start at the very TOP of the photo, regardless
   of how tall the photo itself is — grid-area sharing does that
   directly (align-self:start on the panel), and also means the photo's
   own height (min-height below) no longer has any bearing on how far
   down the panel's content starts. Grid items paint in DOM order when
   neither has z-index, so the panel (later in the markup) already sits
   on top of the photo with no z-index needed. Mobile (≤900px) reverts to
   plain block stacking instead — see that media query — since sharing
   the full-width photo's entire area would otherwise bury it completely
   under an equally full-width panel. */
.feature-hero{display:grid}
/* align-self:start on BOTH grid children, not just the panel — grid items
   default to stretch, which without this would stretch the photo-wrap
   to match the panel's full (much taller) content height instead of its
   own min-height, blowing up the photo hugely (object-fit:cover zooming
   in oddly) and pushing the quote box's bottom:6% far below the visible
   photo entirely. */
/* position:fixed + inset:0 (not :sticky) — sticky was tried first, but it
   only pins once the photo's own natural in-flow position scrolls up to
   top:0, which meant it still visibly scrolled upward by the header's own
   height before catching, per the user's report. Fixed instead removes
   it from flow entirely and pins it to the viewport from the very first
   frame, so it never moves at all: as the (non-positioned, still-normal-
   flow) header/creamband scroll away above it, they simply reveal more of
   the same unmoving photo underneath rather than dragging the photo up
   with them. z-index:-1 is what makes that layering work — per the
   standard CSS stacking order, a negative-z-index positioned box paints
   BELOW its stacking context's normal, non-positioned in-flow content
   (here: .feature-header, .feature-creamband, and everything else on the
   page with no explicit position), while .feature-panel (position:
   relative, i.e. z-index:auto) still paints above both, exactly as
   before. grid-area/align-self no longer apply once the element is fixed
   (fixed removes it from grid placement) — .feature-hero's own height is
   now driven purely by .feature-panel, the one remaining in-flow grid
   item. Cancelled back to a normal in-flow :relative box on mobile below,
   where the layout reverts to plain stacking and a fixed full-viewport
   photo would just sit oddly behind a single narrow column. */
.feature-photo-wrap{position:fixed;inset:0;z-index:-1;overflow:hidden}
.feature-photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(.9) contrast(1.02)}
.feature-panel{grid-area:1/1;align-self:start;justify-self:end;position:relative;width:44%;min-width:300px;margin:0 6% 0 0;background:var(--white);box-shadow:0 20px 50px rgba(0,0,0,.18)}
.feature-panel-scroll{padding:clamp(30px,4vw,60px)}
.feature-title{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.44rem,3.456vw,3.648rem);line-height:1.2;margin:0 0 .5em;letter-spacing:-.03em;font-weight:500;color:var(--ink)}
.feature-subhead{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:1.292rem;letter-spacing:.14em;text-transform:uppercase;font-weight:800;color:var(--muted);margin:0 0 1em}
.feature-body p{font-size:clamp(.832rem,1.24vw,1.104rem);line-height:1.7;color:#3a3733;margin:0 0 1em}
.feature-body ul{margin:0 0 1em;padding-left:1.15em}
.feature-body li{font-size:clamp(.832rem,1.24vw,1.104rem);line-height:1.7;color:#3a3733;margin-bottom:.55em}
.feature-body li::marker{color:var(--gold)}
.feature-rule{height:2px;background:var(--gold);border:0;margin:calc(1.9em + 20px) 0}
.feature-quote{position:absolute;left:6%;bottom:6%;width:38%;background:rgba(0,0,0,.55);color:white;padding:16px 28px;z-index:2}
.feature-quote-label{display:block;font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;font-weight:850;color:var(--gold);margin:0 0 10px}
.feature-quote-text{margin:0;font-family:Georgia,"Times New Roman",serif;font-style:italic;font-size:1.15rem;line-height:1.45;color:white}
@media(max-width:900px){
  .feature-page{min-height:auto}
  /* Back to plain block stacking (photo, then panel, in normal document
     flow) instead of the shared grid-area above — at full width, sharing
     the photo's entire area would put an equally full-width panel right
     over top of it, hiding it completely rather than sitting beside it
     the way the two columns do at wider widths. */
  .feature-hero{display:block}
  .feature-photo-wrap{position:relative;min-height:42vh}
  .feature-panel{width:auto;min-width:0;margin:-56px 16px 24px;box-shadow:none}
  .feature-panel-scroll{padding:26px}
  /* position:relative, not :static — it still needs to sit in normal
     flow (full-width, stacked below the photo) like :static would, but
     :static ignores z-index entirely, which let the photo's own img
     (position:absolute, painted in the "positioned" layer that comes
     after normal in-flow content) paint over this and hide it
     completely. :relative keeps the same in-flow layout but is a
     positioned element again, so its existing z-index:2 above actually
     applies and it paints back on top of the photo. */
  .feature-quote{position:relative;width:auto;margin:0}
  /* The fixed nav-trigger ("Where would you like to go?") sits at
     top:10px, right:10px, ~48px tall (see .nav-trigger's own mobile
     override) — comfortably clear of other pages' tall hero photos, but
     .feature-header is a short, tight black bar with its own brand/title
     text starting almost immediately, so at this width the two visibly
     collide (the trigger overlapping/obscuring the brand line and the
     page's own <h1>). Push the header's content down far enough to clear
     the trigger's full height (10+48=58px) with a little breathing room,
     rather than relying on horizontal space that isn't reliably there
     once the brand text's own width (with its wide letter-spacing) is
     accounted for. */
  .feature-header{padding-top:66px}
}

/* Aggregate Product Page template — a tall photo sits BEHIND the page as a
   true background (absolutely positioned within .agg-scene), with the actual
   content (intro + any number of product listings) flowing normally on top
   of it from the very top of the page — so content is visible immediately,
   not gated behind a full scroll through the image first. The photo still
   reveals progressively as the visitor scrolls, for as much of the page as
   its own (tall) height lasts; past that point .agg-scene's own dark
   background takes over, with #agg-scene-fade (positioned by a small script
   at the very bottom of the rendered photo — see the page's own <script>)
   giving a smooth handoff, the same technique as the Support page's hero →
   .support-transition. First used by knowledge-centre/directories.html.
   To build another product-collection page, duplicate
   knowledge-centre/template-aggregate-page.html and follow the instructions
   in its top comment — it's just a background image, intro copy and a
   product data array passed to renderAggProducts() (agg-product.js)
   — the layout below doesn't change. --agg-panel-w is set once on .agg-band
   and inherited by its children, so .agg-intro and every .agg-product stay
   exactly 30px narrower on each side than the band, without repeating the
   calc(). */
.agg-scene{position:relative;background:#151515}
.agg-scene-photo{position:absolute;top:0;left:0;width:100%;height:auto;display:block;z-index:0}
.agg-scene-fade{position:absolute;left:0;right:0;height:150px;background:linear-gradient(180deg,rgba(21,21,21,0) 0%,rgba(21,21,21,1) 100%);z-index:1}
.agg-scene>main{position:relative;z-index:2}
/* 2026-09-04, final corrected model (after two wrong passes in between —
   see psa-framework.html's own CSS comments for the full history). The
   copy area (.agg-band) is fully OPAQUE, always — var(--white), matching
   abuse.html's own .pov-body. The 56% translucent white is a separate,
   purely decorative halo that sits OUTSIDE the opaque copy area, on 3
   sides only (left/right/bottom) — never the top, since the copy area's
   top edge sits flush against the header (padding-top zeroed below for
   exactly that reason) and shouldn't have a visible frame breaking that
   seam. Implemented as a ::before pseudo-element (position:absolute,
   top:0 = no extension upward, left/right/bottom:-55px = 55px past those
   3 edges only, z-index:-1 so it paints behind .agg-band's own opaque
   content) rather than `outline`, which is always uniform on all 4 sides
   with no per-side control. This is the shared rule every page using
   .agg-band inherits with no local override (guides.html, directories.html,
   directory-england.html, guide-economic/legal/reputational.html,
   template-guide-product.html, template-directory-product.html) — fixing
   it here standardises all of them at once. psa-framework.html, guidance.
   html and knowledge-centre/index.html each carry their own page-scoped
   .agg-band override instead (different opaque colour per page, plus
   psa-framework.html's own extra 150px footer-gap padding) — see each
   page's own CSS comments. */
.agg-band{--agg-panel-w:calc(min(100%,var(--max)) - 60px);width:min(100%,var(--max));margin:0 auto;background:var(--white);position:relative;padding:0 0 clamp(64px,8vw,110px)}
.agg-band::before{content:"";position:absolute;top:0;left:-55px;right:-55px;bottom:-55px;background:rgba(255,255,255,.56);z-index:-1}
.agg-intro{width:var(--agg-panel-w);margin:0 auto 30px;background:rgba(255,255,255,.8);padding:clamp(32px,5vw,64px)}
.agg-intro h2{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.4rem,2.6vw,2.2rem);line-height:1.2;letter-spacing:-.02em;font-weight:500;margin:0 0 20px;color:var(--ink)}
.agg-intro p{font-size:clamp(.85rem,1vw,.95rem);line-height:1.7;color:#3a3733;margin:0 0 1.1em}
.agg-intro p:last-child{margin-bottom:0}
.agg-list{width:var(--agg-panel-w);margin:0 auto;display:flex;flex-direction:column;gap:30px}
/* No align-items:center here on purpose — both columns stretch to the row's
   full height (the grid default), so the image's rendered height always
   matches the text column next to it instead of floating in a shorter box.
   That's what keeps the margin above, below and to the left of the image
   equal: all three now come from the same padding value, not padding on two
   sides plus vertical-centering slack on the other two. */
.agg-product{width:100%;background:rgba(255,255,255,.8);display:grid;grid-template-columns:minmax(200px,300px) 1fr;gap:clamp(28px,4vw,48px);padding:clamp(32px,5vw,56px)}
.agg-product-image{overflow:hidden;background:#e8e2da}
.agg-product-image img{width:100%;height:100%;object-fit:cover;display:block}
.agg-product-info{min-width:0}
.agg-product-title{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.3rem,2.1vw,1.85rem);line-height:1.2;letter-spacing:-.015em;font-weight:500;margin:0 0 10px;color:var(--ink)}
.agg-product-meta{font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;font-weight:850;color:var(--muted);margin:0 0 16px}
.agg-product-copy p{font-size:.86rem;line-height:1.7;color:#3a3733;margin:0 0 1em}
.agg-product-copy p:last-child{margin-bottom:0}
/* Opt-in per paragraph via {text, lead:true} in a product's copy array
   (see agg-product.js) — an opening statement that should read larger than
   the supporting paragraphs around it, not just another body paragraph. */
.agg-product-copy p.agg-product-copy-lead{font-size:1.05rem;line-height:1.55}
.agg-product-actions{margin-top:18px}
/* Deliberately understated — a plain underlined text link, not a button, so
   it reads as the secondary action next to "Explore" (a .chapter-link). */
.agg-product-purchase-row{display:flex;align-items:center;flex-wrap:wrap;gap:6px 14px;margin-top:26px;padding-top:20px;border-top:1px solid #e8e2da;font-size:.82rem}
.agg-product-format{color:var(--muted)}
.agg-product-price{font-weight:800;color:var(--ink)}
.agg-product-purchase{color:var(--ink);text-decoration:underline;text-underline-offset:3px;font-weight:700}
.agg-product-purchase:hover{color:#8A6A00}
/* "Buy box" bottom-section variant (opt in per product via buyBox:true in
   the page's own data array — see agg-product.js) — loosely mirrors the
   individual product page's hero purchase block (.product-see-inside/
   .product-price/.chapter-link/.product-purchase-meta on
   directory-england.html) inside the compact aggregate-list card, reordered
   so the "see inside" word link sits directly under the copy, above the
   divider — then the divider, hero price, Purchase button and delivery
   info follow as one grouped block below it. --agg-accent/--agg-accent-ink
   are set inline per product (see renderBuyBox in agg-product.js) so each
   guide's Purchase button and "see inside" link can roll over to that
   guide's own cover colour; the var() fallbacks here keep the shared
   gold/black hover for any product that doesn't set one. */
.agg-product-see-inside{display:inline-block;margin-top:18px;font-size:.82rem;font-weight:700;color:var(--ink);text-decoration:underline;text-underline-offset:4px}
.agg-product-see-inside:hover{color:var(--agg-accent,var(--muted))}
.agg-product-buy{margin-top:20px;padding-top:20px;border-top:1px solid #e8e2da}
.agg-product-price-hero{font-family:Georgia,"Times New Roman",serif;font-size:1.7rem;font-weight:500;color:var(--ink);margin:0 0 14px}
/* This button now uses .chapter-link-light (not .chapter-link), which has
   no background fill or lift to begin with, so the old override that used
   to live here (cancelling .chapter-link:hover's translateY lift and
   forcing a solid accent-colour fill on hover) is gone — .chapter-link-
   light:hover's own nested var(--agg-accent, var(--product-accent, ...))
   fallback already picks up --agg-accent correctly on its own. */
.agg-product-delivery{font-size:.78rem;color:var(--muted);margin:14px 0 0}
@media(max-width:760px){
  .agg-band{padding:32px 0 48px}
  .agg-intro{padding:28px 22px;margin-bottom:32px}
  .agg-list{gap:28px}
  .agg-product{grid-template-columns:1fr;padding:26px 22px}
  /* Stacked layout has no "row" for the image to stretch against, so it
     needs its own aspect-ratio here (equal-margin stretching is a
     side-by-side-only trick). */
  .agg-product-image{aspect-ratio:4/5}
}

@media(max-width:900px){.nav-trigger{top:10px;right:10px}.quick-exit{right:10px;bottom:10px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}

/* ===================================================================
   Directory Product Page template — the individual product page for a
   single country/NRPF directory. knowledge-centre/directory-england.html
   is both the real, live England page AND the template to duplicate for
   Scotland/Wales/Northern Ireland/NRPF (see the instructions in that
   file's top comment). Reuses .agg-scene/.agg-scene-photo (above) for
   the background-photo treatment, .page-kicker for eyebrows,
   .chapter-link for the primary purchase buttons and .closing for the
   footer — nothing in this section duplicates those. Everything below
   is specific to this page's own sections, in the order they appear on
   the page. All child sections sit inside .agg-scene>main, which is
   already given position:relative;z-index:2 above, so they don't need
   their own stacking rules to render above the background photo. */
/* The opaque "light beige layer" sections 01–07 sit on, over the
   background photo — 150px narrower than the homepage's image +
   scrolling-content section (.split: width:min(100%,var(--max))), i.e.
   var(--max) - 150px. Beyond that width (wide viewports) and in
   .product-photo-gap below, the photo shows through; individual sections
   inside still vary their own background (.secondary categories in a
   slightly different tone, .product-carousel-panel and .product-fit
   lighter/mauve) for internal rhythm. */
/* padding-bottom: .product-final (the last section inside this wrap now)
   ends flush with the wrap's own box by default — this pushes a small
   amount of solid beige in after it, before the wrap closes and
   .product-photo-gap (transparent, revealing the photo/scene beneath)
   takes over. Kept fairly small — combined with .product-photo-gap below,
   this is the total run of empty space before .closing, and it was
   feeling like too much even before this page's copy blocks got taller. */
/* position:relative + ::before halo added 2026-09-04, per the user, as
   part of the same standardisation applied to .agg-band: a 55px, 56%
   translucent-white frame around the copy area's edges, on 3 sides only
   (left/right/bottom — never top, since .product-photo-gap-top below was
   zeroed the same day so this copy area now sits flush against the
   header, and a halo there would break that seam). The wrap's own
   background was already opaque beige, unlike .agg-band's — no change
   needed there. */
.product-content-wrap{width:min(100%,calc(var(--max) - 150px));margin:0 auto;padding-bottom:20px;background:rgb(246,244,240);position:relative}
.product-content-wrap::before{content:"";position:absolute;top:0;left:-55px;right:-55px;bottom:-55px;background:rgba(255,255,255,.56);z-index:-1}
/* A deliberate break in the white layer — same idea as .agg-scene-fade on
   the aggregate Directories page, but here it's a plain gap rather than a
   fade, since the layer above it is a hard-edged opaque block, not a photo
   dissolving into a fallback colour. Left transparent so whatever the
   scene is showing at this scroll depth (the photo itself, or --stone once
   the photo has run out) is visible before the final purchase band/footer.
   Smaller than it was — the combined run of empty space before .closing
   (this plus .product-content-wrap's own padding-bottom above) was too
   much. */
.product-photo-gap{height:clamp(40px,5vw,70px)}
/* Was 80px (the gap between the header and the top of the content area,
   deliberately transparent so the background photo showed through there)
   — zeroed 2026-09-04 per the user: the copy area's top should sit flush
   against the header instead, matching the standardised model applied
   elsewhere (.agg-band on the aggregate listing pages). Left in the
   markup rather than removed, in case a gap here is ever wanted again. */
.product-photo-gap-top{height:0}

/* Same outer width as the homepage's image + scrolling-content section
   (.split: width:min(100%,var(--max))) rather than a narrower cap of its
   own — padding (not a narrower width) is what keeps this page's own text
   off the edge, matching how .split's children (.visual-label/.content-wrap)
   inset themselves with padding too. */
.product-container{width:min(100%,var(--max));margin:0 auto;padding:0 24px}

/* Section 01 — Hero. Content-height-driven (no min-height) rather than a
   fixed vh tall. .product-hero's own bottom edge is set by .product-info
   (the taller column) — the cover image is synced 70px shorter than that
   in product-page.js, so the IMAGE's bottom sits 70px above .product-hero's
   own bottom already. The request is 50px between the image's bottom and
   the carousel, so margin-bottom here is 50 − 70 = −20px: negative, but
   correct — it's relative to .product-hero's bottom (info-column-height),
   not the image's own (shorter) bottom edge. If the 70px offset above ever
   changes, this needs to become (50 − that new offset) to match. */
.product-hero{display:flex;align-items:stretch;margin-bottom:-20px}
/* Cover column is exactly 40% of the content area's width; the info
   column takes the remaining 60%. */
/* 36% = 40% - 10% (relative reduction, not -10 percentage points). */
.product-hero-grid{display:grid;grid-template-columns:36% 1fr;gap:0;align-items:start;width:100%}
.product-cover-stage{overflow:hidden}
.product-cover-stage img{width:100%;height:100%;object-fit:cover;display:block}
.product-info{padding:clamp(40px,6vw,72px) clamp(28px,5vw,64px)}
/* Colour specific to this eyebrow — not a change to the shared .page-kicker
   (used for other eyebrows on this page and across the site). Uses
   --product-accent (defaulting to this page's own pink) rather than the
   pink literal directly, so a page that sets --product-accent on <body>
   (e.g. a Guide product page — see guide-economic.html's own <style>
   block) gets ITS product colour here instead, since this ID and the
   .product-* classes below are reused verbatim by guide-product.js/
   template-guide-product.html, not unique to the Directory pages this
   pink was originally written for. */
#product-eyebrow{color:var(--product-accent,rgb(158,104,133))}
.product-title{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.7rem,3.2vw,3.1rem);line-height:1.08;letter-spacing:-.02em;font-weight:500;margin:0 0 14px;color:var(--ink)}
.product-meta{font-size:.78rem;letter-spacing:.1em;text-transform:uppercase;font-weight:800;color:var(--muted);margin:0 0 31px}
.product-subhead{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.05rem,1.6vw,1.35rem);font-weight:500;margin:0 0 14px;color:var(--ink)}
/* max-width was the actual thing capping how wide these lines could run —
   the column itself getting wider earlier didn't touch this. +50px over
   the previous 52ch cap. */
.product-copy p{font-size:.92rem;line-height:1.75;color:#3a3733;margin:0 0 1.1em;max-width:calc(52ch + 50px)}
.product-purchase{margin-top:28px;padding-top:26px;border-top:1px solid rgba(26,26,26,.12)}
/* #product-purchase-hero and #product-purchase-final now use .chapter-
   link-light (not .chapter-link) — the solid-fill hover override that used
   to live here is gone along with the button style it was overriding;
   .chapter-link-light:hover's own var(--product-accent, ...) fallback
   already gives the right accent colour on hover without it. The sticky
   bar's own purchase button is untouched (still .chapter-link, styled
   separately by .product-sticky-bar .chapter-link below) — it was already
   gold/accent-coloured by default, not one of the plain black buttons this
   preview treatment is replacing. */
.product-price{font-family:Georgia,"Times New Roman",serif;font-size:2rem;font-weight:500;color:var(--ink);margin:0 0 16px}
.product-purchase-meta{font-size:.78rem;color:var(--muted);margin:14px 0 0}
.product-see-inside{display:inline-block;margin-top:22px;font-size:.82rem;font-weight:700;color:var(--ink);text-decoration:underline;text-underline-offset:4px}
.product-see-inside:hover{color:var(--muted)}

/* Section 02 — Look inside the directory. Inset from the beige wrap's own
   edges (rather than spanning it edge to edge like the other sections) so
   its white card visibly has sides of its own, sitting on top of the beige
   rather than blending into it. */
.product-carousel-panel{background:var(--white);padding:clamp(40px,6vw,72px) 0;margin:0 clamp(16px,3vw,40px)}
.product-carousel{position:relative;margin-top:28px}
.product-carousel-viewport{overflow:hidden}
.product-carousel-track{display:flex;gap:20px;touch-action:pan-y;cursor:grab;transition:transform .45s var(--ease)}
.product-carousel-track.is-dragging{cursor:grabbing;transition:none}
/* Side spreads sit at a smaller scale than the centred one, and grow/shrink
   smoothly as .is-active moves from slide to slide (the layout/position
   math in product-page.js is unaffected — this is a purely visual
   transform layered on top of it). 50% specifically (not just "narrower
   than the active slide"): every slide shares this same width, so a
   neighbour peeking in at the (100-50)/2 = 25% of the viewport left on
   each side is exactly half of that neighbour's own 50%-wide box — which
   is also what sets up the carousel's opening state (index 1 active, so
   slide 0 — the cover — starts out exactly half-visible on the left). */
.product-carousel-slide{flex:0 0 50%;transition:opacity .35s var(--ease),transform .45s var(--ease);transform:scale(.82)}
.product-carousel-slide:not(.is-active){opacity:.4}
.product-carousel-slide.is-active{transform:scale(1)}
.product-carousel-slide button{display:block;width:100%;padding:0;border:0;background:none;cursor:zoom-in}
.product-carousel-slide img{width:100%;height:auto;display:block;box-shadow:0 24px 56px rgba(0,0,0,.32),0 6px 16px rgba(0,0,0,.22);-webkit-user-drag:none;user-select:none}
/* The cover (always the first slide) is portrait, unlike every other
   spread in this carousel (all the same landscape ratio) — at a shared
   width that makes it render much taller than its neighbours. Forcing its
   box to their ratio and letterboxing the cover inside with object-fit
   makes its rendered height match them exactly, without cropping or
   stretching the artwork. */
.product-carousel-slide:first-child img{aspect-ratio:2218/1570;object-fit:contain}
/* z-index matters here: .prev comes before .product-carousel-viewport in
   the markup and .next comes after it, so without this the viewport (and
   the slide track inside it) painted over .prev — same stacking context,
   later source order wins — leaving it visible but unclickable. */
.product-carousel-arrow{position:absolute;top:42%;transform:translateY(-50%);z-index:3;width:48px;height:48px;border-radius:50%;background:var(--black);color:white;border:0;display:flex;align-items:center;justify-content:center;font-size:1.2rem;cursor:pointer;transition:background .25s,color .25s}
.product-carousel-arrow:hover{background:var(--product-accent,rgb(158,104,133));color:var(--product-accent-ink,white)}
.product-carousel-arrow.prev{left:-6px}
.product-carousel-arrow.next{right:-6px}
/* Centred on the whole carousel width, which lines it up under the
   active/centred slide specifically, since that slide is itself always
   centred within the carousel by the same layout math. */
.product-carousel-foot{display:flex;align-items:baseline;justify-content:center;gap:14px;margin-top:22px;font-size:.88rem}
/* Positioned 40px from .product-carousel-panel's own (white layer's) left
   edge specifically — not from .product-container's padded position and
   not relative to any earlier shift. .product-container's own left
   padding is 24px, so margin-left here only needs to add the remaining
   16px (24 + 16 = 40) to reach that. */
.product-carousel-kicker{margin-left:16px;color:var(--product-accent,rgb(158,104,133))}
.product-carousel-counter{font-weight:800;color:var(--ink);letter-spacing:.04em}
.product-carousel-caption{color:var(--muted)}

/* Full-screen reading view — a <dialog>, same pattern as #safety-dialog,
   but a warm-white/cream background rather than a black lightbox, per the
   "genuinely readable sample pages" requirement. */
#product-lightbox{border:0;padding:0;max-width:min(94vw,1400px);width:100%;background:var(--stone);box-shadow:0 30px 90px rgba(0,0,0,.4)}
#product-lightbox::backdrop{background:rgba(11,11,11,.82)}
.product-lightbox-inner{position:relative;padding:clamp(20px,4vw,48px)}
.product-lightbox-close{position:absolute;top:16px;right:16px;width:40px;height:40px;border-radius:50%;background:var(--black);color:white;border:0;font-size:1.2rem;line-height:1;cursor:pointer}
.product-lightbox-close:hover{background:var(--gold);color:var(--black)}
.product-lightbox-inner img{width:100%;height:auto;display:block;max-height:78vh;object-fit:contain;margin:0 auto}
.product-lightbox-foot{display:flex;align-items:center;justify-content:center;gap:20px;margin-top:20px;font-size:.86rem;color:var(--muted)}
.product-lightbox-nav{width:44px;height:44px;border-radius:50%;background:var(--black);color:white;border:0;font-size:1.1rem;cursor:pointer}
.product-lightbox-nav:hover{background:var(--gold);color:var(--black)}

/* Sections 03 & 04 — category recognition grids. .secondary (section 04,
   "And support as you rebuild") is deliberately smaller/quieter so it
   reads as secondary to .primary (section 03) above it. */
/* display:flex + align-items:center pairs with the min-height JS sync in
   product-page.js (matchCategorySectionHeights) — .primary and .secondary
   are set to the same min-height (whichever is naturally taller), and this
   centres each one's content vertically within that shared height rather
   than leaving the shorter one's content stuck at the top. */
.product-categories{background:var(--white);padding:clamp(40px,6vw,64px) 0;display:flex;align-items:center}
.product-categories>.product-container{width:100%}
/* .primary sits directly under .product-carousel-panel and shares its
   white background, so it needs the same left/right inset — otherwise
   .primary (full width) runs past .carousel-panel's edges (inset) right
   at the seam between them, and the beige wrap shows through in that
   strip, reading as a break between the two even though there's no actual
   gap between them. */
/* 20px gap before it — a deliberate break from .product-carousel-panel,
   revealing the beige wrap between the two white blocks. Same 20px used
   throughout this page's own inter-section gaps (see .product-research
   and .product-fit below). */
.product-categories.primary{margin:20px clamp(16px,3vw,40px) 0}
/* Same inset as .primary (so their widths match), flush against it (no
   gap), solid rgb(212,188,201) instead of --stone. */
.product-categories.secondary{background:rgb(212,188,201);margin:0 clamp(16px,3vw,40px)}
.product-section-title{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.4rem,2.4vw,2rem);font-weight:500;letter-spacing:-.015em;color:var(--ink);text-align:center;margin:0 0 clamp(28px,4vw,44px)}
/* Tighter gap and a narrower max-width than before — pulls the items (and
   their titles) in toward the centre, closer to each other, per the
   reference layout. */
.product-category-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:clamp(12px,1.8vw,20px);max-width:960px;margin:0 auto}
.product-category-item{text-align:center}
/* width+aspect-ratio (not a fixed width+height square) — the source icons
   are 287x218, and forcing them into a 52x52 box was squashing them
   sideways to fit. 76.8px = 64px + 20%. */
/* 92.16px = 76.8px + 20% (itself already +20% from an earlier round). */
.product-category-item img{width:92.16px;height:auto;aspect-ratio:287/218;display:block;margin:0 auto 10px}
.product-category-item span{display:block;font-size:.85rem;font-weight:700;color:var(--ink)}
/* Titles here now render identically to .primary's — no separate rule left
   for them. Icon opacity is the only thing still marking this section as
   secondary. */
.product-categories.secondary .product-category-item img{opacity:.85}

/* Section 04 (Guide pages only, replacing .product-categories.secondary
   there — see guide-economic.html/template-guide-product.html) —
   "Countermeasures for the tactics you are facing": a title rule, intro
   copy, a "how to read this table" divider, a sample spread from the
   Guide's own Tactics & Countermeasures table annotated with pointer-line
   callouts (≥901px) or a plain numbered list (≤900px — see the -mobile
   classes further down), a "how it fits into the process" 5-step strip,
   and a closing safety note. Same warm-grey used elsewhere on the site
   (not the pink .product-categories.secondary/original .product-fit
   used), same flush-under-Section-03 margin rhythm as the band it
   replaces. --product-accent tints the rule/badges/lines per Guide, same
   mechanism as the eyebrow/buttons/kickers (see #product-eyebrow above)
   — falls back to the shared gold when a page hasn't set one. */
.product-countermeasures{background:var(--warm-grey);padding:clamp(40px,6vw,64px) 0;margin:0 clamp(16px,3vw,40px)}
/* Title + rule centred (matching the shared .product-section-title's
   default everywhere else it's used, per the user's request — this
   section used to override it left-aligned, capped to the figure's own
   960px so its left edge lined up with the image's left edge below; the
   960px cap stays, just no longer forcing left alignment within it).
   .product-countermeasures-intro below keeps its own text-align:left —
   only the title/rule changed. */
.product-countermeasures .product-section-title{text-align:center;max-width:960px;margin:0 auto;margin-bottom:0}
.product-countermeasures-rule{max-width:960px;margin:0 auto;text-align:center}
.product-countermeasures-rule span{display:inline-block;width:64px;height:3px;background:var(--product-accent,var(--gold));margin:14px 0 clamp(28px,3.5vw,40px)}
.product-countermeasures-intro{max-width:960px;margin:0 auto clamp(32px,4vw,48px)}
.product-countermeasures-intro p{font-size:.9rem;line-height:1.75;color:#3a3733;text-align:left;margin:0 0 1.1em}
.product-countermeasures-intro p:last-child{margin-bottom:0}
/* "How to read..." divider — a flex row so the two lines (::before/::after)
   grow to fill whatever space is left after the centred text, keeping it
   centred regardless of exact text length. */
/* Per the user's request: cream lines (brighter than this section's own
   --warm-grey background, so they read as a lift rather than blending
   into it) and black copy (was --muted grey) — a small brightening
   touch that doesn't compete with the annotated figure right below it. */
.product-countermeasures-kicker{display:flex;align-items:center;gap:20px;max-width:960px;margin:0 auto clamp(36px,4.5vw,52px);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;font-weight:800;color:var(--ink)}
.product-countermeasures-kicker::before,.product-countermeasures-kicker::after{content:'';flex:1 1 auto;height:1px;background:var(--stone)}

/* Desktop/tablet (≥901px) annotated figure — hidden below that, where the
   -mobile fallback (further down) takes over instead; fragile absolute-
   positioned callouts+lines aren't worth trying to also cram into a
   narrow column. */
.product-countermeasures-annotated{position:relative;max-width:960px;margin:0 auto clamp(24px,3vw,32px)}
.product-countermeasures-callouts{position:relative}
.product-countermeasures-callouts.top{height:150px}
.product-countermeasures-callouts.bottom{height:130px}
/* --pos (0–100%, set inline per callout — see guide-economic.html) is
   this callout's horizontal anchor point on the figure below/above it;
   translateX(-50%) centres the callout's BOX on that point. --w (also
   set inline per callout) is that box's own width — the 5 callouts no
   longer share one fixed width: each is sized individually so that,
   combined with its own copy length, every explanation comes out the
   same rendered height (a wordier point gets a wider box/fewer wrapped
   lines, a short one gets a narrower box/more wrapped lines) rather than
   leaving heights to vary with however much copy each point happens to
   have. The num badge sits beside the title+copy column (not stacked
   above it) — a flex row, num as the fixed-size first item, the
   title+copy <div> as the flexible second one — same idea as
   .product-countermeasures-legend-mobile li below, just inline instead
   of stacked. */
.product-countermeasures-callout{position:absolute;left:var(--pos);width:var(--w,190px);transform:translateX(-50%);text-align:left;display:flex;gap:10px;align-items:flex-start}
.product-countermeasures-callouts.top .product-countermeasures-callout{bottom:24px}
.product-countermeasures-callouts.bottom .product-countermeasures-callout{top:24px}
.product-countermeasures-callout .num{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:var(--product-accent,var(--gold));color:var(--product-accent-ink,var(--black));font-weight:800;font-size:.74rem;margin-top:1px}
.product-countermeasures-callout>div{flex:1 1 auto;min-width:0}
.product-countermeasures-callout h3{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:.72rem;font-weight:800;text-transform:uppercase;letter-spacing:.02em;color:var(--ink);margin:0 0 6px}
.product-countermeasures-callout p{font-size:.78rem;line-height:1.5;color:#3a3733;margin:0}
/* Connector lines — an SVG per row (filling the whole row, not just the
   24px gap above/below the figure), drawing one right-angled <polyline>
   per callout instead of a per-callout pseudo-element, each capped with a
   small arrowhead marker. The line always starts AT the num badge (its
   own x-position, picking up from the badge's real rendered centre/edge —
   see each <polyline>'s own comment in guide-economic.html for exactly
   where per callout) and every segment is straight vertical or
   horizontal, never diagonal. Lines 1 and 2 (top row) are plain vertical
   drops — their badge already sits in a good enough spot that no
   realignment is needed. Line 3 needs to reach a real column well to its
   left, so it runs down further than 1/2 first (clearing their own
   endpoints, so it never visually crosses or touches line 2) before
   jogging over. Lines 4/5 (bottom row) each bend once, at the vertical
   midpoint of the gap between the figure and the badge's own row, before
   running the rest of the way up to their target column. Every line
   overshoots its row's own box slightly to end a little way INTO the
   figure (not just at its edge) — hence overflow:visible below, since
   that overshoot draws outside the row's own nominal height. Coordinates
   are in the figure's own 0–960 (x) / row-height (y) space, so the
   viewBox lines up 1:1 with the callouts/figure below. */
.product-countermeasures-lines{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.product-countermeasures-lines polyline{fill:none;stroke:var(--product-accent,var(--gold));stroke-width:2}
.product-countermeasures-arrowhead{fill:var(--product-accent,var(--gold))}
/* No card/shadow here (unlike the standalone/-mobile figure below) — sits
   flush between the two callout rows instead of floating on its own. */
.product-countermeasures-annotated .product-countermeasures-figure{background:none;padding:0;box-shadow:none;margin:0;max-width:none}
.product-countermeasures-annotated .product-countermeasures-figure img{border:1px solid rgba(26,26,26,.1)}

/* Standalone figure card (the ≤900px fallback uses this as-is; the
   annotated desktop version above strips it back to a plain image). */
.product-countermeasures-figure{background:var(--white);padding:clamp(16px,2.5vw,28px);box-shadow:0 20px 50px rgba(0,0,0,.12);margin:0 auto clamp(32px,4vw,48px);max-width:960px}
.product-countermeasures-figure img{width:100%;height:auto;display:block}

/* ≤900px fallback — same 5-point copy as the annotated callouts, as a
   plain list under the figure instead of pointer-lines. */
.product-countermeasures-figure-mobile,.product-countermeasures-legend-mobile{display:none}
.product-countermeasures-legend-mobile{list-style:none;margin:0;padding:0;flex-direction:column;gap:24px;max-width:960px;margin-left:auto;margin-right:auto}
.product-countermeasures-legend-mobile li{display:flex;gap:14px;align-items:flex-start}
.product-countermeasures-legend-mobile .num{flex:0 0 auto;width:28px;height:28px;border-radius:50%;background:var(--product-accent,var(--gold));color:var(--product-accent-ink,var(--black));display:flex;align-items:center;justify-content:center;font-weight:800;font-size:.82rem}
.product-countermeasures-legend-mobile h3{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:.78rem;font-weight:800;text-transform:uppercase;letter-spacing:.02em;color:var(--ink);margin:0 0 6px}
.product-countermeasures-legend-mobile p{font-size:.86rem;line-height:1.6;color:#3a3733;margin:0}
@media(max-width:900px){
  .product-countermeasures-annotated{display:none}
  .product-countermeasures-figure-mobile{display:block}
  .product-countermeasures-legend-mobile{display:flex}
}

/* Section 05 — "How it fits into the process". A 5-column strip per the
   user's reference graphic: a circular icon (the user's own finished
   Guides-Icons-process-0N.png set — a deliberate one-off style, distinct
   from every other icon set on the site), a "01 —"/"UNDERSTAND" kicker
   pair, a bold subhead, a body paragraph, and a "Where:" tag with its
   own small icon(s) (still hand-built inline SVG — no matching asset for
   these smaller ones). font-family is Inter throughout (not the site's
   editorial serif) — a deliberate one-off to match the reference.

   .product-process-copy wraps everything ABOVE the tag (icon through
   paragraph) with a fixed min-height, so the "Where:" row starts at the
   same Y in every column regardless of how much any given column's own
   label/subhead/paragraph text wraps to — letting the tag instead just
   push to the bottom via margin-top:auto (the previous approach) only
   aligns the tag's own BOTTOM edge across columns, not its top, since a
   taller-wrapping tag (e.g. step 4's 2-line "Guides + Reference Library /
   citations") would still push its own top edge higher than a 1-line
   tag's. The min-height value is tuned by hand to clear the tallest
   column's natural content at this layout's column width — nudge it if
   any column's copy is ever lengthened enough to exceed it. */
/* Same beige as .product-content-wrap (behind the hero/"Navigating
   Economic Abuse" title), not var(--white) — this section should read as
   a continuation of that same plane, not a break from it. .product-final
   below (see its own rule) gets the lighter --stone instead, so the two
   sections still read as visually distinct from each other. */
.product-process{background:rgb(246,244,240);padding:clamp(40px,6vw,64px) 0}
/* -30px each side (60px total) beyond .product-process .product-container's
   own 120px padding — lets "Where the Guides Fit Into The Process" run
   60px further before wrapping, per the user's request. Symmetric, so
   text-align:center still centres it correctly. */
.product-process .product-section-title{margin-left:-30px;margin-right:-30px}
/* Two paragraphs now (was one) — a normal paragraph gap between them,
   with only the last one keeping the larger gap down to the steps grid. */
.product-process-intro{text-align:center;font-size:.9rem;color:var(--muted);max-width:640px;margin:0 auto 1em}
.product-process-intro:last-of-type{margin-bottom:clamp(32px,4vw,48px)}
/* 120px padding each side between the copy and the beige area's own
   edges (not the shared .product-container's usual 24px — was 60px, then
   tightened further to 120px at the user's request) — the grid's 1fr
   columns narrow automatically with the reduced available width; the
   icon size doesn't (vw units are relative to the viewport, not this
   container), so it's sized down separately below. */
.product-process .product-container{padding-left:120px;padding-right:120px}
.product-process-steps{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(16px,2vw,28px);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
.product-process-steps li{display:flex;flex-direction:column}
/* Only applied at the 5-column width (see the >1180px media query below)
   — at 2-column/1-column widths the columns no longer need to line up
   with 4 others in the same row, so forcing this same height there just
   leaves an oversized, unwanted gap before a short column's "Where:"
   tag. */
.product-process-copy{min-height:0}
@media(min-width:1181px){
  .product-process-copy{min-height:300px}
}
/* height set explicitly (not height:auto) — the user's 5 icon PNGs
   aren't all pixel-perfect squares (e.g. Guides-Icons-process-02.png is
   738×705, not 1:1), so height:auto rendered that one visibly shorter
   than its row-mates, throwing off the title top-alignment below.
   object-fit:contain on the img keeps each icon's own proportions intact
   within this now-fixed square box instead of stretching it. */
/* margin:0 auto — centred over the column's text below it, not flush to
   the column's own left edge (the default for a fixed-width item in a
   flex column), per the user's request. */
.product-process-icon{width:clamp(48px,5vw,72px);height:clamp(48px,5vw,72px);margin:0 auto 20px}
.product-process-icon img{display:block;width:100%;height:100%;object-fit:contain}
/* Recolours a normally-monochrome-slate icon PNG to this page's own
   accent — steps 3/"Explore the tactics" and 4/"Explore countermeasures"
   only, since those are where this particular Guide fits into the wider
   process, per the user's request. Applies an SVG feColorMatrix filter
   defined once near the top of each guide page's own <body> (id
   tint-guide-yellow/-green/-blue/… matching that guide's own accent),
   that remaps every pixel's colour to a flat colour while passing the
   PNG's own alpha channel through untouched, so the real icon shape
   still shows. --pp-accent-filter is set per page (alongside
   --product-accent itself) since each Guide needs its own filter id, not
   a shared one — defaults to yellow/guide-economic.html's own filter so
   this still degrades sensibly if a page forgets to set it. (An earlier
   CSS mask-image attempt rendered fine here but was dropped — its
   default mask-mode, luminance vs alpha, isn't consistent enough across
   browsers to trust; this filter-based approach doesn't have that
   ambiguity.) */
.product-process-icon-accent{filter:var(--pp-accent-filter,url(#tint-guide-yellow))}
/* text-align:center — matches the icon above it (also centred, per the
   user's earlier request), rather than sitting flush left under a
   centred icon. The body paragraph/tag below stay left-aligned. */
.product-process-label{font-size:clamp(1.05rem,1.5vw,1.3rem);font-weight:800;text-transform:uppercase;letter-spacing:-.01em;color:var(--ink);margin:2px 0 16px;line-height:1.15;text-align:center}
/* Same idea as .product-process-copy's own min-height above, one level
   down — reserves enough room for this label to wrap to 2 lines (its
   worst case at this column width, e.g. "EXPLORE COUNTERMEASURES"),
   so the title (h3) right after it starts at the same Y in every column
   regardless of whether that column's own label needed 1 line or 2. */
@media(min-width:1181px){
  .product-process-label{min-height:50px}
}
.product-process-copy h3{font-size:.95rem;font-weight:700;color:var(--ink);margin:0 0 10px;line-height:1.3;text-align:center}
.product-process-copy>p{font-size:.84rem;line-height:1.65;color:#3a3733;margin:0}
.product-process-tag{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin:20px 0 0;padding-left:14px;border-left:2px solid var(--product-accent,var(--gold));font-size:.8rem;color:var(--ink)}
.pp-tag-icon{width:20px;height:20px;flex:0 0 auto}
.pp-tag-icon .pp-stroke{fill:none;stroke:var(--ink);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
@media(max-width:1180px){
  .product-process-steps{grid-template-columns:repeat(2,1fr);row-gap:clamp(32px,4vw,44px)}
}
@media(max-width:560px){
  .product-process-steps{grid-template-columns:1fr}
}


/* Sections 05 & 06 — research stats (left) + "what each listing tells
   you" selectable list (right), sharing one editorial plane per the
   supplied mock-up. On narrow screens the list becomes a stack where
   the shared answer panel sits directly under whichever question was
   last selected — effectively an accordion without duplicating copy
   into two separate markup structures for the two breakpoints. Same
   inset as .product-carousel-panel/.product-categories.primary (so its
   width matches them too) plus a 20px break from .secondary above it —
   another white block after another gap, continuing the same rhythm. */
.product-research{background:var(--white);padding:clamp(40px,6vw,64px) 0;margin:20px clamp(16px,3vw,40px) 0}
/* Same colour as #product-eyebrow and .product-carousel-kicker (both via
   --product-accent, defaulting to this same pink). */
.product-research-kicker{color:var(--product-accent,rgb(158,104,133))}
/* padding-left/right override .product-container's fixed 24px (same
   selector specificity, later in source wins) — standardised to match
   .product-listing's own clamp(24px,3vw,36px) text inset, so "Much of the
   research..." sits exactly as far from this section's edge as "What each
   listing tells you" sits from .product-listing's own edge. */
.product-research-grid{display:grid;grid-template-columns:1.1fr 1fr;gap:25px;align-items:start;padding-left:clamp(24px,3vw,36px);padding-right:clamp(24px,3vw,36px)}
.product-research-copy p{font-size:.9rem;line-height:1.75;color:#3a3733;margin:0 0 1.1em}
.product-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:32px}
.product-stat{text-align:center}
/* 56px = 40px + 40%. margin:0 auto (not 0) centres it under .product-stat's
   own text-align:center. */
.product-stat img{width:56px;height:auto;aspect-ratio:631/517;display:block;margin:0 auto 12px}
.product-stat b{display:block;font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.8rem,3vw,2.6rem);font-weight:500;color:var(--ink);line-height:1}
.product-stat span{display:block;font-size:.78rem;color:var(--muted);margin-top:6px;line-height:1.4}
.product-listing{background:rgb(246,244,240);padding:clamp(24px,3vw,36px)}
.product-listing h3{font-family:Georgia,"Times New Roman",serif;font-size:1.3rem;font-weight:500;margin:0 0 10px;color:var(--ink)}
.product-listing-graphic{width:100%;height:auto;display:block}

/* Section 07 — Is this the right directory for me? A calm, pale panel in
   the pink specified for this page: rgb(212,188,201). Same inset as
   .product-research directly above it — otherwise .fit (full width) would
   run past .research's edges (inset) right at their shared seam, the same
   mismatch already fixed once for .categories.primary — plus the same
   20px break used throughout this page's inter-section gaps. */
/* rgb(212,188,201) is a ~44% tint of the same rgb(158,104,133) pink as
   #product-eyebrow etc. (44% pink + 56% white ≈ this exact value) —
   color-mix() reproduces it exactly when --product-accent is unset, and
   computes the equivalent light tint of whatever accent a page does set
   (e.g. guide-economic.html's yellow) instead of leaving this one
   background stuck on the old pink literal. */
.product-fit{background:color-mix(in srgb,var(--product-accent,rgb(158,104,133)) 44%,white);padding:clamp(40px,6vw,64px) 0;margin:20px clamp(16px,3vw,40px) 0}
/* Same padding-left/right override as .product-research-grid, for the same
   reason ("Is this the right directory for me?" standardised to the same
   edge distance). grid-template-columns AND gap both match
   .product-research-grid's exactly (1.1fr 1fr, 25px — not the more obvious
   1fr 1fr) specifically so its right column — "This directory covers
   England" — lines up left-edge-to-left-edge with .product-listing above,
   per the one exception requested: that block isn't standardised to the
   shared distance, it's aligned to match .product-listing's position
   exactly instead. Any future change to .product-research-grid's gap or
   column ratio needs to be mirrored here too, or that alignment breaks. */
.product-fit-grid{display:grid;grid-template-columns:1.1fr 1fr;gap:25px;padding-left:clamp(24px,3vw,36px);padding-right:clamp(24px,3vw,36px)}
.product-fit h2,.product-fit-heading{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.4rem,2.2vw,1.9rem);font-weight:500;margin:0 0 20px;color:var(--ink)}
.product-fit-checklist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}
.product-fit-checklist li{display:flex;align-items:flex-start;gap:10px;font-size:.9rem;line-height:1.5;color:#3a3733}
.product-fit-checklist li::before{content:"✓";flex:0 0 auto;width:22px;height:22px;border-radius:50%;background:var(--gold);color:var(--black);display:flex;align-items:center;justify-content:center;font-size:.72rem;font-weight:800}
.product-fit-coverage p{font-size:.9rem;line-height:1.7;color:#3a3733;margin:0 0 1.1em}
.product-fit-links{list-style:none;margin:18px 0 0;padding:0;display:flex;flex-direction:column;gap:10px}
/* position:relative + a fixed-ish min-height keeps the row's own size
   stable while .label/.coming-soon crossfade over each other on hover
   (these four directories aren't published yet). */
.product-fit-links a{position:relative;display:inline-block;font-size:.88rem;font-weight:700;color:var(--ink)}
.product-fit-links a .label{display:inline-block;text-decoration:underline;text-underline-offset:4px;transition:opacity .2s}
.product-fit-links a .coming-soon{position:absolute;left:0;top:0;white-space:nowrap;color:var(--muted);text-decoration:underline;text-underline-offset:4px;opacity:0;transition:opacity .2s}
.product-fit-links a:hover .label{opacity:0}
.product-fit-links a:hover .coming-soon{opacity:1}
.product-fit-nrpf{font-size:.82rem;color:var(--muted);margin-top:14px;line-height:1.6}

/* Section 08 — final purchase. Sits on the beige wrap itself (no card/band
   of its own), 25px below .product-fit, per the supplied design. Same
   outer margin as .product-research/.product-fit (clamp(16px,3vw,40px)
   left/right) so its content starts at the same horizontal position as
   theirs — see the matching .product-final .product-container override
   below for the other half of that alignment (their own inner padding is
   clamp(24px,3vw,36px), not .product-container's base 24px). */
.product-final{margin:25px clamp(16px,3vw,40px) 0;padding:20px 0}
/* Guide pages only (the only ones with a .product-process section) — full
   width (cancelling .product-final's own left/right margin above) and
   the lightest tone in the palette (--white, not the beige
   .product-content-wrap that shows through by default, and lighter
   again than the --stone this briefly used), so this section reads as
   visually distinct from "How it fits into the process" above it rather
   than blending into one continuous plane. Scoped via the adjacent-
   sibling selector itself (not a class on .product-final) so this
   doesn't touch Directory product pages, which have no .product-process
   section and so never match it. */
/* padding-top/bottom: base .product-final above is 20px each; +50px each
   side here adds 100px to the white area's total height while keeping
   the row (cover/text/button) centred within it, per the user's request
   — symmetric, not just added to one side. */
.product-process + .product-final{background:var(--white);margin-left:0;margin-right:0;padding-top:70px;padding-bottom:70px}
.product-final .product-container{padding-left:clamp(24px,3vw,36px);padding-right:clamp(24px,3vw,36px)}
/* align-items:flex-start, not stretch — Prod-hero.jpg's natural intrinsic
   size (1266x1793) is much taller than this row needs, and with
   width:auto/no height set on .product-final-cover, a stretch here would
   size the row (and .product-final-text-col along with it) to that huge
   natural size on first layout, before syncFinalCoverHeight's JS ever gets
   a chance to set a sane height — the exact same reason .product-hero-grid
   uses align-items:start rather than stretch. */
/* margin-left cancels out .product-final .product-container's own
   padding-left (clamp(24px,3vw,36px)) specifically for this row, so the
   cover image (the row's first child) lines up with .product-fit's own
   outer/pink edge, not the further-inset padded position .product-fit's
   own text content starts at. */
.product-final-row{display:flex;align-items:flex-start;gap:clamp(20px,3vw,32px);margin-left:calc(-1 * clamp(24px,3vw,36px))}
/* Guide pages only (see the .product-process + .product-final comment
   above for why this selector) — shifts the whole row (cover, divider,
   title/tagline/price/button) 150px further right than the base rule
   above already puts it, per the user's request. */
.product-process + .product-final .product-final-row{margin-left:calc(150px - clamp(24px,3vw,36px))}
/* height set by JS (syncFinalCoverHeight, desktop only) to match
   .product-final-text-col's own rendered height (heading down to the
   price/button row) — width:auto so the cover keeps its natural
   proportions at that height rather than being cropped/distorted. */
.product-final-cover{width:auto;flex:0 0 auto;box-shadow:0 12px 30px rgba(0,0,0,.25)}
.product-final-divider{flex:0 0 auto;width:1px;background:#d8d3cc;align-self:stretch}
/* The heading now lives in this same column as the title/meta/button
   below it (not a separate row above the whole thing), so it lines up
   with them horizontally rather than with .product-container's own edge —
   that's the whole reason this column exists as its own wrapper. */
.product-final-text-col{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;justify-content:center}
.product-final-heading{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.4rem,2.2vw,1.9rem);font-weight:500;color:var(--ink);margin:0 0 20px}
/* A simple vertical stack (title, one combined meta line, price+button). */
.product-final-content{display:flex;flex-direction:column;gap:10px}
.product-final-content h3{font-family:Georgia,"Times New Roman",serif;font-size:clamp(1.3rem,2vw,1.7rem);font-weight:500;margin:0;color:var(--ink)}
/* Guide pages' final-section body copy (#product-final-tagline) — replaces
   the old standalone .product-final-heading (an h2 sitting above this
   whole block) on Guide pages specifically; .product-final-heading itself
   is untouched and still used by the Directory product pages. */
.product-final-tagline{font-size:.92rem;line-height:1.6;color:#3a3733;margin:0}
.product-final-meta-line{font-size:.85rem;color:var(--muted);margin:0}
.product-final-price-btn{display:flex;align-items:center;gap:20px;margin-top:6px}
/* margin:0 matters here specifically — this is a <p>, so without it the
   browser default ~1em top/bottom margin would inflate this row when
   centred (align-items:center centres the full margin box, not just the
   price text itself). */
.product-final-price{font-family:Georgia,"Times New Roman",serif;font-size:1.6rem;font-weight:500;color:var(--ink);margin:0;flex:0 0 auto}

/* Sticky purchase bar — hidden until the hero's purchase button scrolls
   out of view, and hidden again once the final purchase section (above)
   comes into view, via IntersectionObserver in product-page.js. */
/* Right padding reserves room for .quick-exit (fixed bottom:18px right:18px,
   z-index:80 — always above this bar), so the bar's own Purchase button
   never sits underneath that safety control. */
.product-sticky-bar{position:fixed;left:0;right:0;bottom:0;z-index:70;background:var(--black);color:white;padding:0 160px 0 20px;height:60px;display:flex;align-items:center;justify-content:space-between;gap:16px;transform:translateY(100%);transition:transform .3s var(--ease);box-shadow:0 -6px 24px rgba(0,0,0,.25)}
.product-sticky-bar.is-visible{transform:translateY(0)}
.product-sticky-info{flex:1 1 0;display:flex;align-items:center;gap:18px;font-size:.84rem;font-weight:700;min-width:0;overflow:hidden}
.product-sticky-info>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The title is the one span allowed to shrink/truncate — pages and price
   are short and more useful to keep whole. */
#product-sticky-title{flex:1 1 auto;min-width:0}
.product-sticky-info .pages,.product-sticky-info .price{flex:0 0 auto}
.product-sticky-info .pages{color:#c9c3ba;font-weight:600}
/* var(--product-accent, var(--gold)) throughout this block, not a
   literal var(--gold) — same fix, and the same reason, as the shared
   .chapter-link:hover above: this was hardcoded gold regardless of which
   Guide's own accent should show, just invisible on guide-economic.html
   itself since --guide-yellow happens to look close enough to --gold.
   Default state now shows the Guide's own accent (was always gold);
   hover inverts to black/white instead of trying to hover "to" a colour
   it's already showing by default. */
.product-sticky-info .price{color:var(--product-accent,var(--gold))}
.product-sticky-bar .chapter-link{min-height:40px;padding:9px 16px;font-size:.82rem;flex:0 0 auto;background:var(--product-accent,var(--gold));color:var(--product-accent-ink,var(--black));border-color:var(--product-accent,var(--gold))}
.product-sticky-bar .chapter-link:hover{background:var(--black);border-color:var(--black);color:#fff}

@media(max-width:900px){
  .product-hero-grid{grid-template-columns:1fr;gap:0}
  /* Stacked layout has no sibling row to stretch-match, so the cover needs
     its own explicit height for object-fit:cover to fill (mirrors the
     .agg-product-image aspect-ratio fallback used for the same reason on
     the aggregate Directories page). */
  .product-cover-stage{height:56vh}
  .product-research-grid{grid-template-columns:1fr;gap:36px}
  .product-stats{grid-template-columns:1fr 1fr}
  .product-fit-grid{grid-template-columns:1fr;gap:32px}
  /* .product-final-row stacks too — the JS height sync is skipped below
     this width (see syncFinalCoverHeight), so the cover needs its own
     fixed-but-capped size here instead, same idea as .product-cover-stage
     above. */
  .product-final-row{flex-direction:column;align-items:flex-start;margin-left:0}
  .product-final-divider{display:none}
  .product-final-cover{width:100%;max-width:220px;height:auto;margin:0 auto}
}
@media(max-width:640px){
  .product-carousel-slide{flex:0 0 86%}
  .product-carousel-arrow{width:40px;height:40px;font-size:1rem}
  .product-carousel-arrow.prev{left:2px}
  .product-carousel-arrow.next{right:2px}
  .product-sticky-bar{height:56px;padding:0 120px 0 14px}
  .product-sticky-info .pages{display:none}
}
@media(max-width:560px){.product-stats{grid-template-columns:1fr}}
