/*
Theme Name: SEO Merlin
Theme URI: https://seomerlin.com
Author: Devebo
Description: Marketing site theme for SEO Merlin
Template: twentytwentyfive
Version: 1.0.0
Text Domain: seomerlin
*/

/* =============================================================================
   SEO MERLIN DESIGN SYSTEM v1.0

   Component-level CSS for the marketing site. theme.json owns global block
   styling (palette, type scale, spacing presets); everything that theme.json
   cannot express — component classes, grids, tabs, accordions, media queries
   and pseudo-elements — lives here under the `.zm` namespace.

   Scoping contract
   ----------------
   Sections 2 and 3 restyle shared chrome (body, .entry-content, main,
   .wp-site-blocks, footer). Those rules are gated behind `body:has(.zm)` so
   they only apply on pages that opt in by rendering a `.zm` root. Pages
   without `.zm` keep theme.json's dark palette and the default content cage
   untouched.

   Sections 4-10 are namespaced under `.zm` and are inert everywhere else,
   so they ship unscoped.

   Sections H and F style the header and footer template parts. Both ship
   unscoped: §H is almost entirely `.zh-*` classes that only the header part
   renders, so it is inert by construction, and the one exception — the
   sticky rule — should apply on every page; §F targets the footer part
   directly, and applies everywhere on purpose, because a footer that is only
   legible on pages containing a `.zm` root is the bug it exists to fix.

   The header's zero-height collapse is the deliberate exception and lives in
   §3 with the other gated rules, because it depends on the first section
   bringing its own background and clearance — which only a `.zm` page does.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. TOKENS
   Custom properties only — these paint nothing on their own and are safe to
   define globally.
   -------------------------------------------------------------------------- */
:root{--ink:#14161A;--ink2:#2E323A;--body:#4A5058;--soft:#6B7280;--pg:#FFFFFF;--pg2:#F6F7F9;--pg3:#EEF0F3;--line:#E2E5EA;--line2:#D3D8DF;--br:#0F5C4E;--br2:#0A4A3E;--acc:#16A37B;--lime:#D6F050;--dark:#0A0A0B;--rad:14px;--radS:8px;--fs:Manrope,-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Helvetica,Arial,sans-serif;--fm:ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace}

/* -----------------------------------------------------------------------------
   2. LAYOUT CAGE BREAK
   Frees a `.zm` root from the constrained post-content cage so sections can
   run full-bleed, and removes the root block gap that otherwise leaves a
   19.2px strip above and below the content (parent theme.json sets
   styles.spacing.blockGap: 1.2rem, which the child inherits).

   The gap arrives from two directions and both need closing: `.wp-site-blocks
   > *` spaces the header/main/footer siblings, and `.entry-content` picks up
   its own margin-block-start as a non-first child of `main` — that second one
   is what survives on the page.html path once the title is hidden.

   Overflow guards stay ungated: they are harmless everywhere and stop a
   stray wide element producing a horizontal scrollbar site-wide.

   They use `clip`, not `hidden`, and the difference is load-bearing.
   `overflow-x:hidden` forces the other axis to compute to `auto`, which makes
   html and body scroll containers and disables `position:sticky` throughout
   the document — measured: with `hidden`, a sticky element with a 3000px-tall
   parent still scrolls away. `clip` leaves `overflow-y` at `visible`, creates
   no scroll container, and suppresses the horizontal scrollbar just the same.
   This is why §3's old sticky header never actually stuck.

   The two are not interchangeable here. Do not "simplify" this back to
   `hidden`: it looks identical on a static page and silently disables every
   sticky element on the site, including the header and the docs TOC.
   -------------------------------------------------------------------------- */
html{overflow-x:clip}
body{overflow-x:clip;max-width:100%}

html:has(.zm){scroll-behavior:smooth}
body:has(.zm){background:#fff;color:var(--body)}
body:has(.zm) .entry-content.wp-block-post-content{padding-left:0!important;padding-right:0!important;margin-left:0!important;margin-right:0!important;margin-block-start:0!important;max-width:none!important}
body:has(.zm) main.wp-block-group{padding:0!important}
body:has(.zm) .wp-site-blocks>*{margin-block-start:0!important;margin-block-end:0!important}
body:has(.zm) .entry-content>.zm{margin-block-start:0!important;margin-top:0!important;max-width:none!important;width:100%!important;margin-left:0!important;margin-right:0!important}

/* page.html renders a post title that a `.zm` page already supplies itself,
   so it is both a stacked duplicate H1 and dead vertical space. front-page.html
   renders no title, which is why only the page.html path needs this.

   This rule covers the visual half only. A hidden heading is still in the DOM
   and still read as a second H1, so functions.php drops the block outright at
   render time (seomerlin_suppress_duplicate_zm_title). Both are kept: the
   filter stays narrow on purpose — front end, singular post only — and this
   rule catches anything it deliberately steps around. */
body:has(.zm) .wp-block-post-title{display:none}

/* -----------------------------------------------------------------------------
   3. THEME HEADER / FOOTER ADAPTATION
   The site header and footer are template parts shared with every page, so
   what remains here is gated too.

   The header is collapsed to zero height so the pill overlays the page
   instead of sitting above it. Sticky is in-flow and so reserves real height,
   which left a band of body white above the first section and stopped the
   hero and .ph-hd gradients from ever reaching the pill.

   Zero height rather than a negative margin equal to the header's height:
   both produce the identical layout and both keep the pill sticky, but the
   margin needs a hand-maintained constant that silently breaks the moment the
   pill's height changes, and it needs !important to beat §2's
   `margin-block-end:0`. Sticky survives because it sits on this element,
   whose parent is `.wp-site-blocks` and therefore page-height; the travel
   never came from the header's own box. Overflow stays visible, so the pill,
   the dropdown panel and the mobile panel all paint outside the collapsed box.

   This one is gated, and that gate is load-bearing. It only works where the
   first section supplies its own full-bleed background and enough top padding
   to clear the pill, which is true of every `.zm` page (all 23 open with
   `.ph-hd` or `.hero`, verified) and of nothing else. Ungated, the two
   published non-`.zm` URLs — /home/ and /hello-world/ — would render their
   first line of text underneath the pill.

   The rest of what used to live here moved out and is no longer conditional:

     - The header's sticky positioning went to §H, which keeps the same
       target — `header.wp-block-template-part` is the only ancestor with room
       to travel — but states it once, ungated, alongside the pill it applies
       to. Gating it here meant the header was `position:static` on any page
       without a `.zm` root, and duplicating it onto `.zh-wrap` would have
       stacked two sticky contexts one inside the other. Note that it never
       actually stuck while §2's overflow guard was `hidden`.
     - The footer's colours went to §F. Gating them meant the footer's
       legibility depended on whether the page happened to contain a `.zm`
       root, which is what broke it: this section set the dark background but
       never re-set the text colour that §2's `body:has(.zm){color:var(--body)}`
       had already darkened, leaving the column headings at 2.43:1. §F states
       both together and unconditionally.
   -------------------------------------------------------------------------- */
body:has(.zm) header.wp-block-template-part{height:0}
body:has(.zm) .wp-site-blocks>footer.wp-block-template-part{margin-block-start:0!important;margin-top:0!important}

/* -----------------------------------------------------------------------------
   4-10. COMPONENT SYSTEM

   Everything below is namespaced under `.zm` and came across from the tested
   production markup unchanged, with the one deliberate exception recorded
   below. Treat it as settled: don't reformat or otherwise tidy it.

   Deviation from the original
   ---------------------------
   `.zm .fa` (FAQ answer panel) animated `max-height` from 0 to a magic 600px.
   That janks layout and silently clips any answer taller than 600px. It now
   animates `grid-template-rows` 0fr -> 1fr, which sizes to content and has no
   ceiling.

   Collapsing to exactly 0 needs two things beyond the row swap, both verified
   by measurement rather than assumed:
     - `.fa p` gets `min-height:0`, so the 0fr track is allowed to reach zero
       (a grid item's automatic minimum size would otherwise floor the track
       at min-content).
     - the answer's 26px bottom padding moved off `.fa p` and onto
       `.fi.on .fa p`. A grid item's minimum contribution is floored by its own
       padding, so leaving it there held the collapsed panel open at 26px --
       `overflow:hidden` on `.fa` does not help, because the floor is in track
       sizing, not in painting. Applying it only while open keeps the open
       spacing identical and lets the closed state reach 0.

   Contents, in order:

     4. .zm root + element resets
     5. Containers ............ .w .wn .sec .secS .alt
     6. Type scale ............ h1-h4 .eb .lead .mid .mark
     7. Buttons ............... .b .b1 .b2 .hact .hmic
     8. Components ............ .ph-hd .crumb .hero .hg .kick .hsub
                                .shot .ph .strip .st .tb .tp .tnum .tl
                                .g2 .g3 .g4 .cd .sp .qt .pg .pc
                                .fq .fi .fa .prose .doc .toc .cta
     9. Responsive ............ @media 1000px / 640px
    10. Accessibility ......... prefers-reduced-motion, :focus-visible
   -------------------------------------------------------------------------- */
.zm,.zm *{box-sizing:border-box}
.zm{background:var(--pg);color:var(--body);font-family:var(--fs);font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased;position:relative;width:100%;max-width:none!important;overflow-x:clip}
.zm p{margin:0}
.zm h1,.zm h2,.zm h3,.zm h4,.zm h5{margin:0;color:var(--ink);font-family:var(--fs);font-weight:700;line-height:1.1;letter-spacing:-.03em}
.zm a{color:inherit;text-decoration:none}
.zm button{font:inherit;cursor:pointer;border:0;background:none;color:inherit}
.zm img{max-width:100%;display:block;height:auto}
.zm code{font-family:var(--fm);font-size:.88em;color:var(--br);background:var(--pg3);padding:2px 6px;border-radius:4px}
.zm .w{max-width:1360px;margin:0 auto;padding:0 40px}
.zm .wn{max-width:920px;margin:0 auto;padding:0 40px}
.zm .sec{padding:104px 0}
.zm .secS{padding:72px 0}
.zm .alt{background:var(--pg2)}
.zm h1{font-size:clamp(38px,4.4vw,62px);letter-spacing:-.038em;line-height:1.03}
.zm h2{font-size:clamp(28px,3.4vw,44px)}
.zm h3{font-size:27px}
.zm h4{font-size:17px}
.zm .eb{font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--acc);margin-bottom:15px;display:block}
.zm .lead{margin-top:17px;font-size:18px;color:var(--body);max-width:62ch}
.zm .mid{text-align:center;margin-left:auto;margin-right:auto}
.zm .mid .lead{margin-left:auto;margin-right:auto}
.zm .mark{font-style:normal;position:relative;white-space:nowrap}
.zm .mark::after{content:"";position:absolute;left:-2px;right:-2px;bottom:.06em;height:.34em;background:var(--lime);z-index:-1;border-radius:2px}
.zm .b{display:inline-block;padding:12px 22px;border-radius:var(--radS);font-size:15px;font-weight:600;transition:.16s;border:1.5px solid transparent;white-space:nowrap}
.zm .b1{background:var(--br);color:#fff}
.zm .b1:hover{background:var(--br2);color:#fff}
.zm .b2{border-color:var(--line2);color:var(--ink)}
.zm .b2:hover{border-color:var(--ink)}
.zm .hact{display:flex;gap:12px;margin-top:30px;flex-wrap:wrap;align-items:center}
.zm .hmic{margin-top:16px;font-size:14px;color:var(--soft)}
.zm .hmic b{color:var(--ink2);font-weight:600}
.zm .ph-hd{background:linear-gradient(180deg,#F2F6F4,#fff);padding:104px 0 56px;border-bottom:1px solid var(--line)}
.zm .crumb{font-family:var(--fm);font-size:12.5px;color:var(--soft);margin-bottom:16px}
.zm .hero{padding:96px 0 0;background:linear-gradient(180deg,#F2F6F4 0%,#FBFCFC 62%,#fff 100%)}
.zm .hg{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:64px;align-items:center;padding-bottom:88px}
.zm .kick{display:inline-flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--br);background:#E4F0EC;border:1px solid #CBE3DB;padding:6px 13px;border-radius:99px;margin-bottom:22px}
.zm .kick i{font-style:normal;width:6px;height:6px;border-radius:50%;background:var(--acc)}
.zm .hsub{margin-top:22px;font-size:19px;color:var(--body);max-width:47ch}
.zm .shot{border-radius:var(--rad);border:1px solid var(--line);background:#fff;box-shadow:0 1px 2px rgba(16,24,40,.04),0 12px 40px -12px rgba(16,24,40,.14);overflow:hidden}
.zm .shot .cap{display:flex;align-items:center;gap:7px;padding:11px 14px;border-bottom:1px solid var(--line);background:var(--pg2)}
.zm .shot .cap i{width:9px;height:9px;border-radius:50%;background:var(--line2);font-style:normal}
.zm .shot .cap span{margin-left:8px;font-family:var(--fm);font-size:11.5px;color:var(--soft)}
.zm .ph{aspect-ratio:16/10.4;display:grid;place-items:center;background:repeating-linear-gradient(45deg,#F7F8FA,#F7F8FA 11px,#F2F4F7 11px,#F2F4F7 22px);color:var(--soft);font-family:var(--fm);font-size:12.5px;text-align:center;padding:22px;line-height:1.9}
.zm .ph b{display:block;color:var(--ink2);font-family:var(--fs);font-size:14px;font-weight:600;margin-bottom:5px}
.zm .strip{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:#fff}
.zm .st{display:grid;grid-template-columns:repeat(4,1fr);gap:34px;padding:38px 40px}
.zm .st div{text-align:center}
.zm .st b{display:block;font-size:30px;font-weight:700;color:var(--ink);letter-spacing:-.035em;font-variant-numeric:tabular-nums}
.zm .st span{display:block;font-size:13.5px;color:var(--soft);margin-top:3px}
.zm .tb{display:flex;gap:6px;margin-top:44px;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
.zm .tb::-webkit-scrollbar{display:none}
.zm .tb button{padding:14px 20px;font-size:15px;font-weight:600;color:var(--soft);border-bottom:2.5px solid transparent;margin-bottom:-1px;white-space:nowrap;transition:.15s}
.zm .tb button:hover{color:var(--ink2)}
.zm .tb button.on{color:var(--br);border-bottom-color:var(--br)}
.zm .tp{display:none;padding-top:44px}
.zm .tp.on{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:64px;align-items:center;animation:zmf .3s ease}
@keyframes zmf{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.zm .tnum{font-family:var(--fm);font-size:12px;color:var(--acc);margin-bottom:12px;display:block;letter-spacing:.05em}
.zm .tl{list-style:none;padding:0;margin:22px 0 0}
.zm .tl li{position:relative;padding:8px 0 8px 26px;font-size:15.5px;color:var(--body)}
.zm .tl li::before{content:"";position:absolute;left:0;top:16px;width:13px;height:2px;background:var(--acc)}
.zm .g2{display:grid;grid-template-columns:repeat(2,1fr);gap:22px;margin-top:48px}
.zm .g3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:48px}
.zm .g4{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-top:48px}
.zm .cd{background:#fff;border:1px solid var(--line);border-radius:var(--rad);padding:28px;transition:.18s}
.zm .cd:hover{border-color:var(--line2);box-shadow:0 8px 26px -14px rgba(16,24,40,.16)}
.zm .cd .ico{width:38px;height:38px;border-radius:9px;background:var(--pg3);display:grid;place-items:center;margin-bottom:16px}
.zm .cd .ico svg{width:18px;height:18px;stroke:var(--br);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.zm .cd h4{margin-bottom:8px}
.zm .cd p{font-size:15px;color:var(--body)}
.zm .cd.hl{border-color:#BFE3D6;background:#F2FAF7}
.zm .cd.hl .ico{background:#DCF0E8}
.zm .cd a.more{display:inline-block;margin-top:14px;font-size:14.5px;font-weight:600;color:var(--br)}
.zm .cd a.more:hover{text-decoration:underline}
.zm .sp{display:grid;grid-template-columns:1fr 1fr;gap:68px;align-items:center;margin-top:52px}
.zm .sp+.sp{margin-top:96px}
.zm .sp.rev>div:first-child{order:2}
.zm .sp h3{margin-bottom:15px}
.zm .qt{background:var(--br);color:#fff;border-radius:var(--rad);padding:58px}
.zm .qt blockquote{margin:0;font-size:clamp(20px,2.2vw,28px);line-height:1.35;letter-spacing:-.02em;color:#fff;font-weight:600;max-width:24ch}
.zm .qt .att{margin-top:28px;font-size:14.5px;color:#A9CFC4}
.zm .qt .att b{display:block;color:#fff;font-weight:600;font-size:15.5px}
.zm .pg{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-top:48px;align-items:stretch}
.zm .pc{background:#fff;border:1px solid var(--line);border-radius:var(--rad);padding:28px;display:flex;flex-direction:column}
.zm .pc.hot{border:2px solid var(--br);position:relative;box-shadow:0 14px 40px -18px rgba(15,92,78,.4)}
.zm .pc .tag{position:absolute;top:-11px;left:28px;background:var(--br);color:#fff;font-size:11.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:4px 11px;border-radius:5px}
.zm .pc h4{font-size:16px;color:var(--soft);font-weight:600;letter-spacing:0}
.zm .pc .amt{margin:12px 0 4px;font-size:40px;font-weight:700;color:var(--ink);letter-spacing:-.04em}
.zm .pc .amt s{font-size:15px;font-weight:500;color:var(--soft);text-decoration:none;letter-spacing:0}
.zm .pc .who{font-size:14.5px;color:var(--soft);min-height:42px}
.zm .pc ul{list-style:none;padding:0;margin:20px 0 24px;flex:1}
.zm .pc li{position:relative;padding:7px 0 7px 24px;font-size:14.5px;color:var(--body)}
.zm .pc li::before{content:"";position:absolute;left:0;top:14px;width:11px;height:2px;background:var(--acc)}
.zm .pc .b{text-align:center;width:100%}
.zm .fq{margin-top:40px;border-top:1px solid var(--line)}
.zm .fi{border-bottom:1px solid var(--line)}
.zm .fi>button{width:100%;text-align:left;padding:24px 44px 24px 0;font-size:17.5px;font-weight:700;color:var(--ink);position:relative;letter-spacing:-.015em}
.zm .fi>button::after{content:"+";position:absolute;right:6px;top:50%;transform:translateY(-50%);font-size:22px;font-weight:400;color:var(--soft);transition:.2s}
.zm .fi.on>button::after{content:"\2013";color:var(--br)}
.zm .fa{display:grid;grid-template-rows:0fr;overflow:hidden;transition:grid-template-rows .3s ease}
.zm .fi.on .fa{grid-template-rows:1fr}
.zm .fa p{min-height:0;padding:0 60px 0 0;font-size:16px;color:var(--body)}
.zm .fi.on .fa p{padding-bottom:26px}
.zm .prose{max-width:76ch}
.zm .prose h2{font-size:29px;margin:52px 0 16px}
.zm .prose h3{font-size:21px;margin:38px 0 12px}
.zm .prose p{margin:0 0 18px;font-size:17px;color:var(--body)}
.zm .prose ul,.zm .prose ol{margin:0 0 20px;padding-left:22px;color:var(--body);font-size:17px}
.zm .prose li{margin-bottom:9px}
.zm .prose>*:first-child{margin-top:0}
.zm .prose a{color:var(--br);text-decoration:underline;text-underline-offset:2px}
.zm .doc{display:grid;grid-template-columns:250px minmax(0,1fr);gap:64px;align-items:start;padding:64px 0 104px}
.zm .toc{position:sticky;top:96px}
.zm .toc h5{font-size:12px;letter-spacing:.07em;text-transform:uppercase;color:var(--soft);margin:0 0 14px;font-weight:700}
.zm .toc a{display:block;padding:7px 0 7px 14px;font-size:14.5px;color:var(--body);border-left:2px solid var(--line);transition:.15s}
.zm .toc a:hover{color:var(--ink);border-left-color:var(--line2)}
.zm .toc a.on{color:var(--br);border-left-color:var(--br);font-weight:600}
.zm .cta{background:var(--br);color:#fff;padding:96px 0}
.zm .cta h2{color:#fff;font-size:clamp(30px,3.7vw,48px)}
.zm .cta p{color:#B6D8CE;font-size:18px;margin-top:16px;max-width:52ch}
.zm .cta .mid p{margin-left:auto;margin-right:auto}
.zm .cta .b1{background:var(--lime);color:var(--br2)}
.zm .cta .b1:hover{background:#C8E63D;color:var(--br2)}
.zm .cta .b2{border-color:#3E7A6C;color:#fff}
.zm .cta .b2:hover{border-color:#fff}
.zm .cta .fine{margin-top:20px;font-size:14px;color:#8FC0B3}
@media(max-width:1000px){
.zm .hg,.zm .tp.on,.zm .sp{grid-template-columns:1fr!important;gap:44px}
.zm .sp.rev>div:first-child{order:0}
.zm .pg,.zm .g3,.zm .g4{grid-template-columns:repeat(2,1fr)}
.zm .doc{grid-template-columns:1fr;gap:36px}
.zm .toc{position:static}
}
@media(max-width:640px){
.zm .w,.zm .wn{padding:0 20px}
.zm .pg,.zm .g2,.zm .g3,.zm .g4,.zm .st{grid-template-columns:1fr}
.zm .st{gap:24px;padding:30px 20px}
.zm .sec{padding:72px 0}
.zm .secS{padding:56px 0}
.zm .qt{padding:32px}
.zm .cta{padding:72px 0}
/* Top padding on both openers clears the overlaid header pill (§3 collapses
   it to zero height, so these are what keep the H1 out from under it). The
   header's own mobile block uses this same 640px breakpoint deliberately —
   see §H. */
.zm .ph-hd{padding:88px 0 40px}
.zm .hero{padding-top:80px}
}
@media(prefers-reduced-motion:reduce){.zm *{animation:none!important;transition:none!important}}
.zm a:focus-visible,.zm button:focus-visible{outline:2px solid var(--br);outline-offset:3px;border-radius:3px}

/* -----------------------------------------------------------------------------
   H. HEADER

   A light-grey pill floating clear of the top edge, blurring the content
   behind it and tightening on scroll. Rendered by parts/header.html, which
   is a single wp:html block: the markup lives in the theme rather than in a
   wp_template_part row, so it can be edited through the normal workflow.

   The sticky sits on the template-part wrapper, not on `.zh-wrap`. A sticky
   element can only travel inside its own parent's box, and `.zh-wrap` is the
   template part's only child, so the two are exactly the same height and the
   travel is zero — measured: sticky on `.zh-wrap` scrolls away at every
   offset, sticky on the wrapper holds at 14px. The wrapper's parent is
   `.wp-site-blocks`, which is page-height, so that is where the travel is.
   (§2's overflow guard has to be `clip` for either to work at all.)

   Sticky, not fixed, so the header reserves its own height in normal flow and
   cannot overlap the first content section at rest. That is why no
   compensating top padding is added to `.hero` or `.ph-hd`: content already
   starts below the pill and only slides under it once scrolled, which is what
   the backdrop-filter is there for.

   `pointer-events` is off on the wrap and back on for its children, so the
   transparent gutter either side of the pill does not swallow clicks meant
   for the page.

   `.stuck` is applied by assets/js/ui.js past 8px of scroll.
   -------------------------------------------------------------------------- */
header.wp-block-template-part{position:sticky;top:0;z-index:90}
.zh-wrap{padding:14px 24px 0;pointer-events:none}
.zh-wrap>*{pointer-events:auto}
.zh{max-width:1180px;margin:0 auto;display:flex;align-items:center;gap:28px;
background:rgba(243,244,246,.82);
backdrop-filter:saturate(180%) blur(16px);-webkit-backdrop-filter:saturate(180%) blur(16px);
border:1px solid rgba(0,0,0,.07);border-radius:999px;padding:9px 9px 9px 20px;
box-shadow:0 1px 2px rgba(16,24,40,.04),0 8px 28px -12px rgba(16,24,40,.18);
font-family:var(--fs);transition:box-shadow .2s ease,background .2s ease}
.zh-wrap.stuck .zh{background:rgba(243,244,246,.94);
box-shadow:0 1px 2px rgba(16,24,40,.05),0 12px 34px -12px rgba(16,24,40,.26)}

.zh-lg{display:flex;align-items:center;gap:9px;text-decoration:none;flex-shrink:0}
.zh-m{width:27px;height:27px;border-radius:8px;background:var(--br);color:var(--lime);
display:grid;place-items:center;flex-shrink:0}
.zh-m svg{width:15px;height:15px}
.zh-nm{font-size:16px;font-weight:700;letter-spacing:-.025em;color:var(--ink);white-space:nowrap}

.zh-nav{display:flex;align-items:center;gap:4px;margin-left:auto}
.zh-nav a,.zh-gh{font-size:14.5px;font-weight:550;color:var(--body);text-decoration:none;
padding:8px 13px;border-radius:999px;white-space:nowrap;transition:.15s}
.zh-nav a:hover,.zh-gh:hover{color:var(--ink);background:rgba(255,255,255,.85)}
.zh-nav a.on{color:var(--br);background:#fff;font-weight:650}

.zh-r{display:flex;align-items:center;gap:8px;margin-left:8px}
.zh-cta{display:inline-flex;align-items:center;gap:7px;background:var(--br);color:#fff;
text-decoration:none;font-size:14.5px;font-weight:650;padding:10px 19px;
border-radius:999px;white-space:nowrap;transition:.16s}
.zh-cta:hover{background:var(--br2);color:#fff;transform:translateY(-1px)}
.zh-cta span{transition:transform .16s ease}
.zh-cta:hover span{transform:translateX(2px)}

.zh-bg{display:none;width:38px;height:38px;border:0;background:transparent;color:var(--ink);
border-radius:999px;cursor:pointer;align-items:center;justify-content:center;padding:0}
.zh-bg svg{width:19px;height:19px}
.zh-bg:hover{background:rgba(255,255,255,.85)}

.zh-mob{display:none;max-width:1180px;margin:8px auto 0;background:rgba(243,244,246,.96);
backdrop-filter:blur(16px);border:1px solid rgba(0,0,0,.07);border-radius:20px;padding:10px;
box-shadow:0 12px 34px -12px rgba(16,24,40,.26);font-family:var(--fs)}
.zh-mob.on{display:block}
.zh-mob a{display:block;padding:12px 16px;font-size:15.5px;font-weight:550;
color:var(--ink2);text-decoration:none;border-radius:12px}
.zh-mob a:hover{background:#fff}
.zh-mob a.on{color:var(--br);background:#fff;font-weight:650}
.zh-mob .zh-cta{display:flex;justify-content:center;margin-top:6px}

/* --- docs dropdown ---
   Seventeen guides in four groups; a flat link buries them. Desktop only —
   `.zh-mob` keeps its single /documentation/ link, because a twelve-item
   accordion on a phone is worse than one good link.

   `.zh-dt.on` is the current-page state, matching `.zh-nav a.on`. It is a
   separate selector from `.zh-dd.on .zh-dt` on purpose: the first lives on
   the button and means "you are in this section", the second lives on the
   wrapper and means "the panel is open". They can be true at once. */
.zh-dd{position:relative}
.zh-dt{display:inline-flex;align-items:center;gap:5px;font:inherit;font-size:14.5px;
font-weight:550;color:var(--body);background:none;border:0;cursor:pointer;
padding:8px 13px;border-radius:999px;transition:.15s}
.zh-dt svg{width:13px;height:13px;transition:transform .2s ease}
.zh-dt:hover{color:var(--ink);background:rgba(255,255,255,.85)}
.zh-dt.on{color:var(--br);background:#fff;font-weight:650}
.zh-dd.on .zh-dt{color:var(--br);background:#fff}
.zh-dd.on .zh-dt svg{transform:rotate(180deg)}

.zh-dp{position:absolute;top:calc(100% + 12px);left:50%;
transform:translateX(-50%) translateY(-6px);display:none;
grid-template-columns:repeat(3,minmax(196px,1fr));gap:26px;
background:#fff;border:1px solid var(--line);border-radius:18px;padding:24px;
box-shadow:0 2px 4px rgba(16,24,40,.04),0 20px 48px -16px rgba(16,24,40,.28);
opacity:0;transition:opacity .16s ease,transform .16s ease}
.zh-dd.on .zh-dp{display:grid;opacity:1;transform:translateX(-50%) translateY(0)}

.zh-dh{display:block;font-size:11px;font-weight:700;letter-spacing:.07em;
text-transform:uppercase;color:var(--soft);margin-bottom:10px;padding:0 10px}
.zh-dp a{display:block;padding:9px 10px;border-radius:10px;text-decoration:none;
font-size:14.5px;font-weight:600;color:var(--ink);transition:.14s}
.zh-dp a em{display:block;font-style:normal;font-size:12.5px;font-weight:450;
color:var(--soft);margin-top:2px}
.zh-dp a:hover{background:var(--pg2)}
.zh-dp a:hover em{color:var(--body)}
.zh-dall{color:var(--br)!important;margin-top:6px}

@media(max-width:1080px){
.zh-nav,.zh-gh,.zh-dd{display:none}
.zh-bg{display:flex}
.zh{gap:12px}
.zh-r{margin-left:auto}
}
/* Mobile is the design target, not a fallback: most traffic arrives here.

   640px, not 520px, and it consolidates the old 520px block — every property
   that block set is restated below. The width is chosen to match §9's content
   breakpoint, where `.ph-hd` and `.hero` switch to their mobile top padding.
   Two different widths would leave a band where the pill still has its
   desktop height but the section has already taken mobile clearance, which
   puts the H1 under the pill. */
@media(max-width:640px){
.zh-wrap{padding:10px 12px 0}
.zh{gap:8px;padding:7px 7px 7px 13px}
.zh-m{width:24px;height:24px;border-radius:7px}
.zh-m svg{width:13px;height:13px}
.zh-nm{font-size:15px}
.zh-cta{padding:8px 14px;font-size:13.5px;gap:0}
.zh-cta span{display:none}
.zh-bg{width:34px;height:34px}
.zh-bg svg{width:18px;height:18px}
}

/* Below ~380px the logo, CTA and burger stop fitting on one line. */
@media(max-width:380px){
.zh-nm{display:none}
.zh-cta{padding:8px 13px}
}
.zh a:focus-visible,.zh-bg:focus-visible,.zh-dt:focus-visible,.zh-mob a:focus-visible{
outline:2px solid var(--br);outline-offset:2px}

/* -----------------------------------------------------------------------------
   F. FOOTER

   Replaces the `background:var(--dark)` override that used to sit in §3.

   The footer part renders theme.json's dark palette: white text on the `base`
   background. §2 turns the page white on `.zm` pages, which left the footer
   white-on-white, and §3 answered that by restoring the dark background only.
   It never restored the text colour, so `body:has(.zm){color:var(--body)}`
   kept the column headings at #4A5058 on #0A0A0B — 2.43:1, below AA.

   Stating background and text together, ungated, fixes that and removes the
   dependency on what the page happens to contain. Measured on both page
   types: headings #FFFFFF at 19.79:1, links #8A8A93 at 5.78:1.

   Background and foreground must move together. Setting one without the
   other is exactly how this broke: a dark background was added here while the
   text colour was left to whatever the page cascade happened to supply. If
   either changes, re-check the pair and re-measure the contrast.

   The muted paragraphs (tagline, copyright) keep #8A8A93 on their own: core
   emits preset colour classes with !important, so `has-muted-color` outranks
   the inherited white here.
   -------------------------------------------------------------------------- */
footer.wp-block-template-part{background:var(--dark);color:#fff}
footer.wp-block-template-part .wp-block-group{background:transparent}
footer.wp-block-template-part a{color:#8A8A93;transition:.15s}
footer.wp-block-template-part a:hover{color:#fff}
