/* Grownion — the whole front end.
   Tokens are lifted verbatim from Frontend-Design-Guide.md §1 so the design work
   already done survives the move off Elementor. Kept under 14 KB so functions.php
   inlines it and the page has no render-blocking stylesheet request. */

/* Values measured off https://wordpressmaintenanceservice.com/ with Chrome, not
   estimated. The palette, the radii and the two faces already matched — they came from
   the same design guide — so what is recorded here is the geometry the live site uses:
   band padding, card padding, button padding, the type scale, and the two colours the
   theme was missing (the on-dark accent and the footer ground). */
:root{
  --c-primary:#0A2540; --c-primary-mid:#1A3A5C; --c-primary-light:#E8F0F9;
  --c-accent:#00B37E; --c-accent-dark:#008C62; --c-accent-light:#E6F7F2;
  /* The lighter green the live hero uses for the highlighted word and on dark grounds,
     where #00B37E does not carry enough contrast against #0A2540. */
  --c-accent-bright:#4ECCA3;
  --c-deep:#060F1A;          /* footer ground */
  --c-slate:#475569;         /* body copy inside cards */
  --c-text:#1A202C; --c-muted:#64748B; --c-border:#E2E8F0;
  --c-bg:#FFFFFF; --c-bg-alt:#F8FAFC;

  /* Severity, kept separate from the brand accent so the two never argue.
     Green is normal service. Amber says something is broken. Red says something is
     compromised, or is happening now. The -bright variants are for dark grounds, where
     the mid tones do not carry enough contrast against #0A2540. */
  --c-alert:#F59E0B; --c-alert-light:#FEF3C7; --c-alert-dark:#92400E;
  --c-alert-bright:#FBBF24;
  --c-danger:#DC2626; --c-danger-light:#FEF2F2; --c-danger-dark:#B91C1C;
  --c-danger-bright:#F87171;
  --band-y:72px;             /* vertical padding on every full-bleed band */

  --f-head:'Sora',ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;
  --f-body:'Inter',ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;

  /* --s-5 was referenced in several rules as `var(--s-5,var(--s-4))` before it
     existed, so every one of them silently resolved to 1rem. Defined here so those
     rules mean what they read as. */
  --s-1:.25rem; --s-2:.5rem; --s-3:.75rem; --s-4:1rem; --s-5:1.25rem; --s-6:1.5rem;
  --s-8:2rem; --s-10:2.5rem; --s-12:3rem; --s-16:4rem; --s-20:5rem;

  --r-sm:6px; --r-md:12px; --r-lg:20px;
  --shadow:0 2px 16px rgba(10,37,64,.08);
  --shadow-hi:0 8px 32px rgba(10,37,64,.14);
  /* ONE container at every width, matching the live site: 1200px max, 24px gutters,
     so content is at most 1152px. There were three widths before this — 1200 base,
     1320 at ≥1280 and 1440 at ≥1600 — plus a gutter that dropped to 16px on phones,
     which meant the left edge of the page moved four times between a phone and a
     1920 monitor. One number is easier to design to and easier to check. */
  --wrap:1200px;
  --gutter:24px;
  /* Width for the list widgets — accordions, checklists, step lists. They are rows of
     short text and read like prose, so they take a prose-width column centred in the
     container rather than stretching the full 1152px. */
  --narrow:820px;

  /* The content width the type is sized against: the container's inner width, or the
     viewport minus gutters when that is smaller. Never larger than 1152px.

     Headings used to scale on `vw`. That was wrong once the container was fixed at
     1200: past a ~1250px viewport the container stopped growing but `vw` kept going,
     so the type kept growing inside a column that did not — which is why headings
     looked oversized on a wide screen. Sizing against this stops when the container
     stops. */
  --cw:min(calc(100vw - var(--gutter) * 2),calc(var(--wrap) - var(--gutter) * 2));
  /* The reading measure. Prose sits in it; tables, card grids and bands break out.
     It widens at the desktop tiers below — at 1920 a 70ch column inside a 1440
     container left ~700px of dead space down the right-hand side. */
  --measure:74ch;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* Live body type is 16px/1.6 Inter. `overflow-x:clip` lets the full-bleed bands below
   use the margin-inline bleed trick without a horizontal scrollbar, and unlike
   `overflow:hidden` it does not create a scroll container, so the sticky header and
   sticky elements keep working. */
body{margin:0;background:var(--c-bg);color:var(--c-text);overflow-x:clip;
  font:400 1rem/1.6 var(--f-body);-webkit-font-smoothing:antialiased}
img,svg,video{max-width:100%;height:auto;display:block}
a{color:var(--c-accent-dark);text-decoration-thickness:1px;text-underline-offset:2px}
a:hover{color:var(--c-primary)}
:focus-visible{outline:3px solid var(--c-accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important;scroll-behavior:auto!important}}

/* Measured: H1 Sora 800 60.8px/1.12 at -0.02em; H2 Sora 700 33.6px/1.25. */
h1,h2,h3,h4{font-family:var(--f-head);font-weight:700;line-height:1.25;
  color:var(--c-primary);margin:0 0 var(--s-4);text-wrap:balance}
/* Sized against --cw, so both stop growing when the container does. The ratios put H1
   at 60.8px and H2 at 33.6px at the full 1152px content width — the live site's sizes. */
h1{font-size:clamp(2rem,calc(var(--cw) * .0528),3.8rem);font-weight:800;line-height:1.12;
  letter-spacing:-.02em}
h2{font-size:clamp(1.5rem,calc(var(--cw) * .0292),2.1rem);font-weight:700;
  margin-top:var(--s-12);margin-bottom:var(--s-6)}
h3{font-size:1.25rem;margin-top:var(--s-8)}
p,ul,ol,table{margin:0 0 var(--s-4)}
ul,ol{padding-left:1.25rem}
li{margin-bottom:var(--s-2)}
strong{font-weight:600;color:var(--c-primary)}
small,.fine{font-size:.875rem;color:var(--c-muted)}

.shell{max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gutter)}
.skip{position:absolute;left:-9999px;top:0;background:var(--c-primary);color:#fff;
  padding:var(--s-3) var(--s-4);z-index:100}
.skip:focus{left:0}

/* ---------------------------------------------------------------- chrome */
/* Live header: 65px tall on the deep navy, brand preceded by a small green dot. */
.site-head{background:var(--c-deep);color:#fff;position:sticky;top:0;z-index:50}
.site-head .shell{display:flex;align-items:center;gap:var(--s-6);
  min-height:65px;flex-wrap:wrap}
.brand{display:inline-flex;align-items:center;gap:.55em;
  font-family:var(--f-head);font-weight:700;font-size:1rem;color:#fff;
  text-decoration:none;letter-spacing:-.01em;white-space:nowrap}
.brand::before{content:"";width:.45rem;height:.45rem;border-radius:50%;
  background:var(--c-accent);flex:0 0 auto}
.brand:hover{color:var(--c-accent-light)}
.nav{margin-left:auto;order:2}
.nav ul{display:flex;gap:var(--s-3) var(--s-6);list-style:none;margin:0;padding:0;flex-wrap:wrap}
.nav li{position:relative}
.nav a{color:#cfe0f0;text-decoration:none;font-size:.9375rem;font-weight:500}
.nav a:hover,.nav .current-menu-item>a{color:#fff}
/* Base state is a plain nested list — that is what the drawer wants, and it is what a
   crawler and a no-CSS reader get. The dropdown is layered on at desktop only. */
.nav .sub-menu{display:flex;flex-direction:column}
/* Measured: 14.4px / 600, padding 7.2px 17.6px, radius 6. */
.cta{background:var(--c-accent);color:#fff!important;font-weight:600;font-size:.9rem;
  padding:7.2px 17.6px;border-radius:var(--r-sm);text-decoration:none;white-space:nowrap;
  order:3;line-height:1.6}
.cta:hover{background:var(--c-accent-dark)}

/* The disclosure button. Hidden until the footer script unhides it, so it is never a
   control that does nothing — and hidden again above the breakpoint. */
[hidden]{display:none!important}
/* The drawer's sub-menu carets. The script inserts one per parent on every page load,
   so they need hiding by default — the drawer rule below reveals them. Without this
   they rendered as bare buttons beside every desktop dropdown label. */
.sub-toggle{display:none}
.nav-toggle{display:none;order:4;align-items:center;gap:var(--s-2);background:transparent;
  border:1px solid rgba(255,255,255,.28);border-radius:var(--r-sm);color:#fff;cursor:pointer;
  font:600 .875rem var(--f-body);padding:var(--s-2) var(--s-3);min-height:44px}
.nav-toggle:hover{border-color:var(--c-accent);background:rgba(255,255,255,.06)}
.nav-toggle-bars,.nav-toggle-bars::before,.nav-toggle-bars::after{display:block;width:18px;
  height:2px;background:currentColor;border-radius:2px}
.nav-toggle-bars{position:relative}
.nav-toggle-bars::before,.nav-toggle-bars::after{content:"";position:absolute;left:0}
.nav-toggle-bars::before{top:-6px}
.nav-toggle-bars::after{top:6px}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars{background:transparent}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::before{top:0;transform:rotate(45deg)}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::after{top:0;transform:rotate(-45deg)}

/* Orientation, not a feature. It takes the hero's own top colour and loses its border
   so it reads as the first line of the hero rather than a band in its own right, and it
   sits well down the contrast scale — the H1 immediately below is what should be read
   first. Hover restores it for anyone actually navigating with it. */
.crumbs{background:#0d2b49;border-bottom:0;
  font-size:.75rem;color:rgba(255,255,255,.34);letter-spacing:.01em}
.crumbs .shell{padding-block:var(--s-4) 0}
.crumbs ol{display:flex;flex-wrap:wrap;align-items:center;gap:.5em;
  list-style:none;margin:0;padding:0}
.crumbs li{margin:0;display:flex;align-items:center;gap:.5em}
/* Separator drawn between items, so there is never one dangling at the end. */
.crumbs li+li::before{content:"/";color:rgba(255,255,255,.22)}
.crumbs a{color:rgba(255,255,255,.5);text-decoration:none}
.crumbs a:hover{color:rgba(255,255,255,.9);text-decoration:underline}

/* The crumb now supplies the top of the hero's space, so the hero gives some back. */
.crumbs+main .hero{padding-top:var(--s-12)}

/* Live footer: ground #060F1A, padding 48px 24px 24px, links 13.6px at 55% white.
   A proof strip runs across the top, then the brand blurb and the link columns. */
.site-foot{background:var(--c-deep);color:rgba(255,255,255,.5);margin-top:0;
  padding:48px 0 24px;font-size:.9375rem}
.site-foot a{color:rgba(255,255,255,.55);text-decoration:none;font-size:.85rem}
.site-foot a:hover{color:#fff}

.foot-proof{display:flex;flex-wrap:wrap;gap:var(--s-3) var(--s-8);list-style:none;
  margin:0 0 var(--s-10);padding:0 0 var(--s-8);
  border-bottom:1px solid rgba(255,255,255,.08);font-size:.85rem}
.foot-proof li{margin:0;display:flex;align-items:baseline;gap:.5em;
  color:rgba(255,255,255,.62)}
.foot-proof li::before{content:"\2713";color:var(--c-accent);font-weight:700}

.foot-top{display:grid;gap:var(--s-8) var(--s-10);margin-bottom:var(--s-10);
  grid-template-columns:minmax(0,1.4fr) minmax(0,2fr)}
@media (max-width:768px){.foot-top{grid-template-columns:1fr}}
.foot-brand .brand{margin-bottom:var(--s-3)}
.foot-brand p{margin:0;color:rgba(255,255,255,.5);font-size:.875rem;max-width:44ch}

/* The footer menu is grouped: each top-level item is a column heading, its children
   are the links. Rendered at depth 2 by footer.php. */
.foot-nav>ul{display:grid;gap:var(--s-8);list-style:none;margin:0;padding:0;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.foot-nav>ul>li{margin:0}
.foot-nav>ul>li>a{display:block;margin-bottom:var(--s-3);
  font:700 .6875rem/1.6 var(--f-body);letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.85)}
.foot-nav .sub-menu{list-style:none;margin:0;padding:0;display:flex;
  flex-direction:column;gap:var(--s-2)}
.foot-nav .sub-menu li{margin:0}

.site-foot .fine{color:rgba(255,255,255,.38);margin:0;font-size:.8125rem;
  padding-top:var(--s-6);border-top:1px solid rgba(255,255,255,.08)}

/* ------------------------------------------------------------- document
   A full-bleed grid. Prose runs in a real reading measure down the middle; anything
   that wants width — the hero, the evidence band, tables, card grids — breaks out to
   the full container.

   Before this, everything sat in one 650 px column pinned to the left edge with ~750 px
   of dead white beside it on a 1440 screen. Centring the measure and letting the wide
   components span is what makes the page read as composed rather than truncated. */
/* No top padding: every layout opens with the bleeding hero band, which brings its own
   88px. Leaving the document's 48px in place put a white strip between the header and
   the hero. */
/* One column, full container width. The measure applies to running text only.
   Two grid attempts came before this and both were wrong. Constraining every child to
   a column left-aligned it and put ~700px of dead white down the right at 1920;
   centring that column fixed the void but started the prose 350px right of the table
   above it, so the page had two competing left edges.
   The fix is to stop constraining blocks and constrain only the lines of text: every
   heading, table, accordion, checklist and card grid now uses the full container and
   shares one left edge, while paragraphs and lists wrap at a readable length and end
   ragged — which is what running text is supposed to do. */
/* .doc spans the full width; the 1200px container is applied to each of its children
   just below, so a band can opt out of it without a viewport-relative trick. */
.doc{padding-block:0 var(--s-8)}
.doc-body>p,.doc-body>ul,.doc-body>ol,.doc-body>blockquote,
.doc-body>h2,.doc-body>h3{max-width:var(--measure)}

/* A right rail was tried here and removed. A full-bleed grid and a sticky rail cannot
   share one grid: the wide components span both columns, so they collide with anything
   occupying the second column across the same rows, and the browser pushed them down
   into a hole. Full-width tables are worth more on this site than a nav in the gutter,
   so the measure simply ends early and the space beside it stays quiet. */
.doc-title{margin-bottom:var(--s-6)}

/* ----------------------------------------------------------------- hero
   The opening was an H1 on white followed by a form stretched across the whole
   container. This composes it: the claim on the left, the working tool on the right,
   on one tinted ground so the page has an anchor above the fold. */
/* Full-bleed bands, as on the live site: navy ground, white title with one word in the
   lighter green, lead copy at 72% white, 88px top / 80px bottom.

   The container lives on each direct child of .doc rather than on .doc itself, so a
   band is simply a child that opts out of the max-width and pads its inside back to
   where the container's content starts.

   The earlier version pulled bands out with `margin-inline:calc(50% - 50vw)`. That
   depends on `vw`, which includes the scrollbar: measured at a 375px viewport the band
   came out 390px wide starting at -7px, so its content sat 7px left of every heading
   above it. Deriving the inset from `100%` — the width .doc actually has — has no
   scrollbar to get wrong. */
.doc.shell{max-width:none;padding-inline:0}
.doc>*{max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gutter)}
.bleed,.doc>.hero,.doc>.cmp.is-band{max-width:none;
  padding-inline:max(var(--gutter),calc((100% - var(--wrap))/2 + var(--gutter)))}
/* A narrower COLUMN, not a narrower box.
   This used to cap the section element itself, which — with margin-inline:auto from
   .doc>* — re-centred it inside the container. The list widgets then started 166px to
   the right of every other block on the page, so a guide's headings landed on two
   different left edges and the eye zig-zagged down the article: heading at the
   container edge, heading indented, heading back at the edge.
   Capping the children instead keeps every section on the one left edge the container
   sets, and still gives accordions, checklists and steppers a prose-width measure
   rather than a 1152px band with six words in it. */
.doc>.cmp.is-narrow>*{max-width:var(--narrow)}

.hero{margin-bottom:0;padding-block:88px 80px;
  background:linear-gradient(160deg,#0d2b49 0%,var(--c-primary) 55%,#07203a 100%);
  color:#fff}
.hero .doc-title,.hero h1{color:#fff;margin-bottom:var(--s-5,var(--s-4))}
.hero .doc-title em,.hero .doc-title b,.hero .hl{color:var(--c-accent-bright);
  font-style:normal;font-weight:inherit}
/* Lead copy: 19.2px/1.75 at 72% white, measured. */
.hero .centerpiece{color:rgba(255,255,255,.72);font-size:1.2rem;line-height:1.75;
  margin-bottom:var(--s-6);max-width:60ch}

/* The eyebrow is a pill on the live site, not a bare line of text:
   Inter 700 12px, 0.08em, uppercase, #00B37E on #E6F7F2, radius 100px, pad 4/14. */
.hero-kicker{display:inline-block;margin:0 0 var(--s-5,var(--s-4));
  padding:4px 14px;border-radius:100px;
  background:var(--c-accent-light);color:var(--c-accent-dark);
  font:700 .75rem/1.6 var(--f-body);letter-spacing:.08em;text-transform:uppercase}
/* On the dark hero the mint pill is too loud; the live site uses a translucent chip. */
.hero .hero-kicker{background:rgba(78,204,163,.14);color:var(--c-accent-bright);
  box-shadow:inset 0 0 0 1px rgba(78,204,163,.28)}
.hero-meta{margin:0 0 var(--s-6);font-size:.8125rem;color:var(--c-muted)}
.hero-points{list-style:none;padding:0;margin:0 0 var(--s-6);
  display:flex;flex-direction:column;gap:var(--s-2)}
.hero-tool .hero-points{margin:var(--s-6) 0 0}
.hero-points li{position:relative;padding-left:var(--s-8);margin:0;
  color:var(--c-primary-mid);font-size:.9375rem}
/* A tick drawn in CSS rather than an emoji: emoji are a named generated-look tell and
   the emoji script is dequeued anyway. */
.hero-points li::before{content:"";position:absolute;left:var(--s-2);top:.45em;
  width:.4rem;height:.75rem;border:solid var(--c-accent);border-width:0 2px 2px 0;
  transform:rotate(45deg)}
.hero .hero-points li{color:rgba(255,255,255,.82)}
.hero .hero-points li::before{border-color:var(--c-accent-bright)}
.hero .cmp{margin-block:0}
.hero .hero-cta{margin-bottom:0}
/* Scoped to the copy column. Unscoped, this also caught the trust line inside the
   white tool card sitting in the other column, and rendered it white on white — an
   invisible line that read as an unexplained band of empty card under the button. */
.hero-copy .trust{color:rgba(255,255,255,.5)}

/* The tool card: white on navy, 28px padding, radius 12, no shadow — the live card
   treatment. It keeps its own column so it is never stretched across the container,
   and it stays in the first view, which the framework requires of the affordance. */
.hero-tool .tool{background:var(--c-bg);box-shadow:none;padding:28px;
  border-color:transparent;
  /* Set the ink, not just the paper. The hero paints its column white and the card
     paints itself white on top, so anything inside the card without an explicit colour
     inherits white on white. That already caught the trust line once and was patched
     per-element; it then caught every line the site checker writes at runtime, which no
     stylesheet had ever seen. Declaring the colour on the card fixes the whole subtree
     including markup that does not exist until someone submits the form. */
  color:var(--c-text)}
.hero-tool .tool h2{margin-top:0;color:var(--c-primary)}
.hero-tool .tool a:not(.btn){color:var(--c-accent-dark)}

@media (min-width:900px){
  /* Centred, not top-aligned. The two columns are rarely the same height — a downtime
     calculator runs far taller than four lines of copy — and aligning both to the top
     left whichever is shorter sitting above a block of empty band. Centring keeps the
     hero balanced whichever side is taller, which varies by page. */
  .hero.is-split{display:grid;gap:var(--s-12);
    grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);align-items:center}
  .hero.is-split .hero-copy{max-width:52ch}
  /* 60.8px is the live size for a three-word title centred in an 820px column. The
     split hero's copy column is about 580px inside a 1200px container, so the title
     steps down in proportion — same ratio to its own column, not to the viewport. */
  .hero.is-split .doc-title{font-size:clamp(1.75rem,calc(var(--cw) * .036),2.6rem)}
}
/* A hero with no tool is centred, as the live one is. */
@media (min-width:900px){
  .hero:not(.is-split) .hero-copy{max-width:44rem;margin-inline:auto;text-align:center}
  .hero:not(.is-split) .centerpiece{margin-inline:auto}
  .hero:not(.is-split) .hero-cta{justify-content:center}
  .hero:not(.is-split) .hero-points{display:inline-flex;text-align:left}
}

/* The centerpiece annotation. Nothing renders between the H1 and this block. */
.centerpiece{font-size:1.1875rem;line-height:1.6;color:var(--c-primary-mid);
  max-width:62ch;margin:0 0 var(--s-8);font-weight:400}

/* A 40-word extractive answer. Carries no links so it lifts as a clean passage. */
.answer{background:var(--c-accent-light);border-left:4px solid var(--c-accent);
  color:var(--c-text);
  padding:var(--s-4) var(--s-6);border-radius:0 var(--r-sm) var(--r-sm) 0;
  font-size:1.0625rem;max-width:68ch;margin-bottom:var(--s-6)}
/* Inside the dark hero the mint panel inherited the hero's white text and rendered
   mint-on-mint — invisible. On dark it becomes a translucent panel instead. */
.hero .answer{background:rgba(255,255,255,.06);color:rgba(255,255,255,.86);
  border-left-color:var(--c-accent-bright)}

/* The grid already sets the measure; a second cap here would just narrow it again. */
.doc-body>h2:first-child{margin-top:0}

/* Values printed by grownion_verbalised(): visible text that also feeds JSON-LD. */
.v{font-variant-numeric:tabular-nums}

/* The rating line was a stray sentence floating between a table and a heading. It now
   reads as a review badge: accent stars, the score carried at size, the count muted. */
.cmp-rating-strip{display:inline-flex;align-items:baseline;gap:var(--s-2);flex-wrap:wrap;
  padding:var(--s-3) var(--s-5,var(--s-4));background:var(--c-accent-light);
  border-radius:100px;font-size:.9375rem;color:var(--c-accent-dark);font-weight:500}
.cmp-rating-strip .stars,.cmp-rating-strip [class*="star"]{color:var(--c-accent);
  letter-spacing:.1em}
.cmp-rating-strip strong,.cmp-rating-strip b,.cmp-rating-strip .v{
  color:var(--c-primary);font-family:var(--f-head);font-weight:800;font-size:1.125rem}
.is-band-dark .cmp-rating-strip{background:rgba(78,204,163,.14);color:var(--c-accent-bright)}
.is-band-dark .cmp-rating-strip strong,.is-band-dark .cmp-rating-strip b{color:#fff}

/* In the hero it sits under the CTA as social proof, on the dark ground and without a
   pill — a filled chip competes with the buttons directly above it. */
.hero .cmp-rating-strip{background:transparent;padding:0;border-radius:0;
  color:rgba(255,255,255,.6);margin-block:var(--s-4) 0}
.hero .cmp-rating-strip .stars{color:var(--c-accent-bright)}
.hero .cmp-rating-strip b,.hero .cmp-rating-strip .v{color:#fff;font-size:1rem}
.hero:not(.is-split) .cmp-rating-strip{justify-content:center}

/* ------------------------------------------------------------ components
   Below the hero the page was a flat white wall: table, prose, prose, steps, with
   nothing marking where one section ended. A wide component now opens with a hairline
   and sits on the alternate ground, so the page has a rhythm to scan. */
.cmp{margin-block:var(--s-10)}
.cmp[data-fold="above"]{margin-block:var(--s-6)}
/* A section heading needs more air under it than a paragraph heading does. 16px put
   "Plans that include this" almost on top of the cards; a section header wants to read
   as a header, not as a label stuck to the widget below it. */
.cmp>h2{margin-top:0;margin-bottom:var(--s-8)}
.cmp.is-narrow>h2{margin-bottom:var(--s-6)}
/* The Q&A block is a destination of its own — people scroll to it — so it gets more air
   than the process list above it, which is read in sequence with the copy around it.
   It is no longer centred: one centred heading among nine start-aligned ones read as a
   mistake rather than as emphasis, and air alone does the same job without breaking the
   left edge.
   `.is-narrow` is repeated in the selector deliberately: without it this is one class
   against `.cmp.is-narrow>h2`'s two, so the margin lost on specificity and the gap
   stayed at 24px no matter where the rule sat in the file. */
.cmp.is-narrow.cmp-faq-accordion>h2,
.cmp.is-narrow.cmp-question-thread>h2{margin-bottom:var(--s-10)}

/* Bands. The live site alternates full-bleed grounds — white, #F8FAFC, #0A2540 — each
   with 72px of vertical padding, and that alternation is most of what makes it read as
   composed rather than as one long column. is-band is applied in PHP by shape:
   card and quote grids get the light ground, the proof strips get the dark one. */
.cmp.is-band{margin-block:0;padding-block:var(--band-y)}
.cmp.is-band-light{background:var(--c-bg-alt)}
.cmp.is-band-dark{background:var(--c-primary);color:rgba(255,255,255,.78)}
/* The proof strip sits directly under the hero on most pages. The live site puts it on
   a lighter navy so the two bands read as two bands rather than one long one. */
.cmp-evidence-strip.is-band-dark{background:#12314F;padding-block:var(--s-10)}
.cmp.is-band-dark h2,.cmp.is-band-dark h3{color:#fff}
.cmp.is-band-dark .card{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.10)}
.cmp.is-band-dark .card b,.cmp.is-band-dark .card-grid b{color:#fff}
.cmp.is-band-dark .card-grid span,.cmp.is-band-dark .fine{color:rgba(255,255,255,.62)}
/* Two dark bands in a row are one band. */
.cmp.is-band-dark+.cmp.is-band-dark,.cmp.is-band-light+.cmp.is-band-light{padding-top:0}

/* Wide components that are not bands keep a hairline to separate them. */
.cmp.is-wide:not(.is-band){border-top:1px solid var(--c-border);padding-top:var(--s-8)}
.cmp.is-wide:not(.is-band)+.cmp.is-wide:not(.is-band){border-top:0;padding-top:0}
/* A band already ends the previous section; a hairline straight after it is noise. */
.cmp.is-band+.cmp.is-wide:not(.is-band){border-top:0}
/* Scoped to non-bands: a band needs to keep its own vertical padding, and zeroing it
   here collapsed the proof strip directly under the hero. */
.hero+.cmp.is-wide:not(.is-band){border-top:0;padding-top:0}

/* Section headers inside a band are centred on the live site, and a band is the widest
   thing on the page, so its header carries the most space beneath it. */
.cmp.is-band>h2{text-align:center;max-width:26ch;margin-inline:auto;
  margin-bottom:var(--s-10)}
/* With a lead paragraph the space moves below the lead, not between the two. */
.cmp.is-band>h2:has(+.fine){margin-bottom:var(--s-3)}
.cmp.is-band>h2+.fine{text-align:center;max-width:60ch;margin-inline:auto;
  margin-bottom:var(--s-10)}

/* Measured: white, 28px padding, radius 12, 1px #E2E8F0, and no shadow at all. The
   theme was putting a shadow on every card, which is what made the grids look heavier
   and flatter than the live ones — border only, so the hierarchy is spent elsewhere. */
.card{background:var(--c-bg);border:1px solid var(--c-border);border-radius:var(--r-md);
  padding:28px;box-shadow:none}
.grid{display:grid;gap:var(--s-6);
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}

/* The component kit's three list shapes. Without these the cards, quotes and
   checklists the map assigns to almost every page rendered as bare bullet lists. */
/* Three across at 1152px with a 20px gutter, which is what the live grid measures. */
.card-grid{display:grid;gap:20px;list-style:none;padding:0;margin:0;
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.card-grid>li{background:var(--c-bg);border:1px solid var(--c-border);
  border-radius:var(--r-md);padding:28px;margin:0;
  display:flex;flex-direction:column;gap:var(--s-3)}
/* Card title: Sora 700 16.8px/1.6. Body: 15px slate. */
.card-grid b{font-family:var(--f-head);font-weight:700;font-size:1.05rem;
  color:var(--c-primary);line-height:1.6}
.card-grid span{font-size:.9375rem;line-height:1.65;color:var(--c-slate)}
/* Border only, no shadow: these are a set being scanned, not objects being lifted.
   The one card that needs lifting is the popular plan, and it has its own rule. */

/* ------------------------------------------------------------ testimonials
   A quote is evidence, so it is given weight: a large accent quote mark, the quote
   itself at reading size rather than fine print, five stars, and the attribution
   separated by a rule so the claim and its source read as two things. */
.quote-grid{display:grid;gap:20px;list-style:none;padding:0;margin:0;
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.quote-grid>li{position:relative;margin:0;display:flex;flex-direction:column;
  gap:var(--s-4);padding:28px;background:var(--c-bg);
  border:1px solid var(--c-border);border-left:3px solid var(--c-accent);
  border-radius:0 var(--r-md) var(--r-md) 0}
/* Five stars, drawn from the same rating the strip uses. */
.quote-grid>li::before{content:"\2605\2605\2605\2605\2605";color:var(--c-accent);
  font-size:.875rem;letter-spacing:.12em;line-height:1}
.quote-grid blockquote{margin:0;font-size:1.0625rem;line-height:1.65;
  color:var(--c-text);font-weight:500}
.quote-grid blockquote::before{content:"\201C"}
.quote-grid blockquote::after{content:"\201D"}
.quote-grid cite{font-style:normal;font-size:.8125rem;color:var(--c-muted);
  margin-top:auto;padding-top:var(--s-4);border-top:1px solid var(--c-border)}
.quote-grid cite span{color:var(--c-primary-mid)}
/* On a dark band the card inverts rather than punching a white hole in it. */
.is-band-dark .quote-grid>li{background:rgba(255,255,255,.04);
  border-color:rgba(255,255,255,.10);border-left-color:var(--c-accent-bright)}
.is-band-dark .quote-grid blockquote{color:#fff}
.is-band-dark .quote-grid cite{color:rgba(255,255,255,.6);
  border-top-color:rgba(255,255,255,.10)}
.is-band-dark .quote-grid>li::before{color:var(--c-accent-bright)}

/* --------------------------------------------------------------- emphasis
   Statements the page is making, rather than words that happen to be bold. */
.doc-body strong,.card-grid strong,.plan-rows strong{color:var(--c-primary);
  font-weight:700}
/* A paragraph opening with a bold lead-in is a claim; give the lead-in the accent. */
.doc-body>p>strong:first-child{color:var(--c-accent-dark)}
mark,.hl-text{background:linear-gradient(transparent 62%,var(--c-accent-light) 0);
  color:inherit;padding:0 .1em}

.checklist{list-style:none;padding:0;margin:0 0 var(--s-4);
  display:flex;flex-direction:column;gap:var(--s-1)}
.checklist li{margin:0;border-bottom:1px solid var(--c-border)}
.checklist li:last-child{border-bottom:0}
/* Scoped through .tool so these beat the generic field rules above regardless of
   source order — the checklist always renders inside a .tool container. */
.tool .checklist label,.checklist label{display:flex;align-items:flex-start;
  gap:var(--s-3);padding:var(--s-3) 0;font-weight:500;cursor:pointer;min-height:44px;
  font-size:.9375rem;margin:0}
.tool .checklist input,.checklist input{display:inline-block;margin:.15rem 0 0;
  width:1.15rem;height:1.15rem;min-width:1.15rem;flex:0 0 auto;padding:0;
  accent-color:var(--c-accent)}
.checklist input:checked+span{color:var(--c-muted);text-decoration:line-through}
.checklist small{display:block;padding:0 0 var(--s-3) calc(1.15rem + var(--s-3));
  color:var(--c-muted)}

/* What ticking returns. The old build printed "7 of 21 done" — a count of what the
   visitor had just done, which is not information. This is the report region: weighted
   score, the monthly cost of the gaps, a band, and the gaps themselves by name. */
.check-report{margin-top:var(--s-6);border-top:1px solid var(--c-border);
  padding-top:var(--s-5)}
.check-report .calc-result{border-top:0;padding-top:0;margin-bottom:var(--s-4)}
/* Stacked, not the two-column .calc-line used inside a full-width calculator. In a
   272-360px report column the label and the figure both wrap, and "50 / min/month"
   split across two lines reads as a broken number. */
.check-report .calc-line{display:block;padding:var(--s-2) 0}
.check-report .calc-line span{display:block;font-size:.8125rem;line-height:1.4;
  color:var(--c-muted)}
.check-report .calc-line b{display:block;margin-top:2px;font-size:1.375rem;
  white-space:nowrap}
.check-report .calc-verdict{margin-top:var(--s-1);padding-top:var(--s-4)}
.check-report .calc-verdict b{font-size:1.75rem}
.check-prompt{margin:0;color:var(--c-muted);font-size:.9375rem;line-height:1.6}

/* ---- the two-column assessment ---------------------------------------------
   Twenty-one rows is long enough that a report underneath is off-screen by the time
   the visitor reaches the checkbox that changes it. Above 900px the report takes a
   second column and sticks, so the verdict is in view for every tick.

   The report is never empty — it carries a prompt before the first tick — so the
   second column does not open as a hole in the layout, and the prompt is also what
   tells a first-time visitor that ticking does something. */
@media (min-width:900px){
  .tool[data-component="checklist"]{display:grid;align-items:start;
    grid-template-columns:minmax(0,1fr) minmax(272px,360px);
    gap:var(--s-6) var(--s-10)}
  .tool[data-component="checklist"]>h2{grid-column:1/-1;margin-bottom:0}
  .tool[data-component="checklist"]>.checklist{margin-bottom:0}
  .check-report{margin-top:0;border-top:0;padding-top:0;
    border-left:1px solid var(--c-border);padding-left:var(--s-8);
    /* Clears the sticky header. The report is short now that it counts the gaps
       instead of listing them, so it needs no inner scroll of its own. */
    position:sticky;top:calc(84px + var(--s-6))}
}

/* ---- the mobile summary -----------------------------------------------------
   Below 900px the report stacks under the list and the same distance problem returns.
   A bottom bar is not available — `.mobile-cta` already owns that edge below 768px —
   so the summary pins under the sticky header instead and links down to the report. */
.check-mini{display:none}
@media (max-width:899px){
  /* `hidden` is a UA rule, and any author `display` beats it — without this the empty
     strip renders before the first tick, which is the state most visitors arrive in. */
  .check-mini[hidden]{display:none}
  .check-mini{display:flex;align-items:baseline;gap:var(--s-3) var(--s-4);
    flex-wrap:wrap;position:sticky;top:76px;z-index:20;margin:0 0 var(--s-4);
    padding:var(--s-3) var(--s-4);border:1px solid var(--c-border);
    border-radius:var(--r-sm);
    background:color-mix(in srgb,var(--c-bg) 94%,transparent);
    backdrop-filter:blur(10px)}
  .check-mini b{font-family:var(--f-head);font-size:1.125rem;font-weight:700}
  .check-mini b.is-good{color:var(--c-accent-dark)}
  .check-mini b.is-warn{color:var(--c-alert)}
  .check-mini b.is-bad{color:var(--c-danger)}
  .check-mini span{font-size:.875rem;color:var(--c-muted);
    font-variant-numeric:tabular-nums}
  .check-mini a{margin-left:auto;font-size:.875rem;font-weight:600;white-space:nowrap}
  /* The report is a scroll target on mobile, so it needs the same header clearance
     the rest of the page's anchors get. */
  .check-report{scroll-margin-top:88px}
}
.check-note{margin:0 0 var(--s-4);font-size:.875rem;line-height:1.6;
  color:var(--c-alert-dark);background:var(--c-alert-light);
  border-radius:var(--r-sm);padding:var(--s-3) var(--s-4)}
.check-gaps{margin:0 0 var(--s-5)}
.check-outstanding{margin:0;font-size:.875rem;line-height:1.6;color:var(--c-muted)}
.check-outstanding b{font-family:var(--f-head);font-size:1rem;color:var(--c-primary)}
.check-clear{margin:0;color:var(--c-accent-dark);font-weight:600}

/* The hub index. One row per child: a short label and the summary the card grid used
   to carry, now that there is only one listing instead of three.

   `min-width:0` is load-bearing. A grid item defaults to `min-width:auto`, which sizes
   the track to its longest unbreakable word rather than letting it wrap - so
   ERR_SSL_VERSION_OR_CIPHER_MISMATCH pushed its summary straight through the card
   border and across the neighbouring column. The site-wide `overflow-wrap:break-word`
   could not help, because the track was being widened instead of the line being broken. */
.index-grid li{display:grid;gap:2px;min-width:0}
.index-grid a{font-weight:600}
.index-grid span{font-size:.875rem;line-height:1.55;color:var(--c-muted);
  min-width:0;overflow-wrap:anywhere}

/* The document figure. It sits in the hero's second column when no tool claims it, and
   full width straight after the hero when one does, so it is above the fold either way.
   The caption is not a label for the picture - it restates the substance in words,
   because a diagram whose content exists only inside the image is invisible to text
   extraction. */
.doc-figure{margin:0}
.doc-figure-img{display:block;width:100%;height:auto;border-radius:var(--r-md);
  border:1px solid var(--c-border);background:var(--c-bg)}
.hero-tool .doc-figure-img{border-color:rgba(255,255,255,.14)}
.doc-figure figcaption{margin-top:var(--s-3);font-size:.875rem;line-height:1.6;
  color:var(--c-muted)}
.hero-tool .doc-figure figcaption{color:rgba(255,255,255,.66)}
/* Container width, not the reading measure. The figures are generated 1200px wide, so
   capping them at the 820px prose column shrank the text inside them below legibility -
   the constraint here is the diagram's own resolution, not line length. */
.cmp-doc-figure{margin-block:var(--s-8)}

/* The symptom checker's answer: the cause row it narrowed to. */
.symptom-list{list-style:none;padding:0;margin:0 0 var(--s-4);
  display:flex;flex-direction:column;gap:var(--s-1)}
.symptom-list li{margin:0;border-bottom:1px solid var(--c-border)}
.symptom-list li:last-child{border-bottom:0}
.tool .symptom-list label,.symptom-list label{display:flex;align-items:flex-start;
  gap:var(--s-3);padding:var(--s-3) 0;font-weight:500;cursor:pointer;min-height:44px;
  font-size:.9375rem;margin:0}
.tool .symptom-list input,.symptom-list input{display:inline-block;margin:.15rem 0 0;
  width:1.15rem;height:1.15rem;min-width:1.15rem;flex:0 0 auto;padding:0;
  accent-color:var(--c-accent)}
.tool[data-component="symptom-checker"] .tool-out{font-size:1.0625rem;line-height:1.6;
  font-family:var(--f-body);font-weight:500;color:var(--c-text)}
.cause-table tr.is-likely>*{background:var(--c-accent-light)}
.cause-table tr.is-likely>th:first-child,
.cause-table tr.is-likely>td:first-child{box-shadow:inset 3px 0 0 var(--c-accent-dark);
  font-weight:600}

/* ---- gaps marked in the list, not reprinted beside it -----------------------
   The report used to render every outstanding item's text so it could attach the
   consequence. Side by side that showed the same labels twice. The rows carry their own
   marking instead: a weight edge, the weight named, and the consequence revealed.

   `.is-assessed` gates all of it. Before the first tick nothing is a gap — flagging
   twenty-one rows red on arrival passes judgement on a site nobody has described. */
.checklist .tag,.checklist .why{display:none}
.is-assessed .checklist li.is-gap{border-left:3px solid var(--c-border);
  padding-left:var(--s-4);margin-left:-1px}
.is-assessed .checklist li.is-gap.is-critical{border-left-color:var(--c-danger)}
.is-assessed .checklist li.is-gap.is-important{border-left-color:var(--c-alert)}
.is-assessed .checklist li.is-gap .tag{display:inline;margin-left:var(--s-2);
  font-style:normal;font-weight:600;font-size:.6875rem;letter-spacing:.04em;
  text-transform:uppercase;vertical-align:.1em;color:var(--c-muted);white-space:nowrap}
.is-assessed .checklist li.is-gap.is-critical .tag{color:var(--c-danger)}
.is-assessed .checklist li.is-gap.is-important .tag{color:var(--c-alert-dark)}
.is-assessed .checklist li.is-gap .why{display:block;font-size:.875rem;line-height:1.55}

/* scope-checklist is a statement of what we cover, not an assessment, so it renders as
   a ticked list with no controls. Ticking off our own service scope was meaningless. */
.ticklist{list-style:none;padding:0;margin:0}
.ticklist li{position:relative;padding:var(--s-3) 0 var(--s-3) var(--s-6);
  border-bottom:1px solid var(--c-border);font-size:.9375rem;line-height:1.6}
.ticklist li:last-child{border-bottom:0}
/* The literal glyph, not a \2713 escape. Written as an escape it came out as "¹3" —
   an octal escape had eaten the first three digits before the CSS ever saw it. The
   stylesheet is UTF-8 and the theme serves UTF-8, so the character needs no escaping. */
.ticklist li::before{content:"✓";position:absolute;left:0;top:var(--s-3);
  color:var(--c-accent-dark);font-weight:700}
.ticklist small{display:block;color:var(--c-muted);margin-top:var(--s-1)}

table{width:100%;border-collapse:collapse;font-size:.9375rem}
/* A table wider than its container clipped at the edge with no sign it could scroll,
   which reads as a broken layout.
   Two shadow layers sit at the edges (background-attachment:scroll, so they stay put)
   and two solid covers sit over them (attachment:local, so they move with the content).
   At rest the covers hide the shadows; scroll, and the shadow on that side is revealed.
   When the table fits, both covers stay put and no shadow ever shows — which is what a
   plain `to right` fade got wrong, painting a grey band on tables that fit fine. */
.scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;
  background:
    linear-gradient(to right,var(--c-bg),transparent) left center/22px 100% no-repeat local,
    linear-gradient(to left,var(--c-bg),transparent) right center/22px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%,rgba(10,37,64,.16),transparent) left center/12px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%,rgba(10,37,64,.16),transparent) right center/12px 100% no-repeat scroll}
.scroll:focus-visible{outline:2px solid var(--c-accent);outline-offset:2px}
th,td{text-align:left;padding:var(--s-3) var(--s-4);border-bottom:1px solid var(--c-border);
  vertical-align:top}
th{font-family:var(--f-head);font-weight:600;font-size:.8125rem;letter-spacing:.04em;
  text-transform:uppercase;color:var(--c-muted)}
/* A row label is content, not a column heading. Left uppercase it read as shouting and
   wrapped "WORDPRESS CORE, PLUGIN AND THEME UPDATES" over four lines on a phone. */
th[scope="row"]{font-family:var(--f-body);font-weight:600;font-size:.9375rem;
  letter-spacing:0;text-transform:none;color:var(--c-text)}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
tbody tr:last-child>*{border-bottom:0}

.badge{display:inline-block;font-size:.75rem;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;padding:var(--s-1) var(--s-2);border-radius:var(--r-sm)}
.badge-ok{background:var(--c-accent-light);color:var(--c-accent-dark)}
.badge-warn{background:#FEF3C7;color:#92400E}
.badge-bad{background:var(--c-danger-light);color:var(--c-danger)}

/* ---------------------------------------------------------------- site checker output
   Written by assets/js/site-check.js after a submit, so none of it exists at page load
   and none of it had any CSS: only .badge was styled, which is why a result rendered as
   two floating pills and several lines of invisible text. Styled here rather than in the
   JS so the checker looks the same in the hero, on /security/ and anywhere else the
   component lands. */
.checker-out:empty{display:none}
.checker-summary{margin:var(--s-5) 0 var(--s-4);font-size:1rem;line-height:1.6;
  color:var(--c-text)}

.checker-meta{list-style:none;margin:0 0 var(--s-4);padding:var(--s-4) 0;
  display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-3);
  border-block:1px solid var(--c-border)}
.checker-meta li{min-width:0}
.checker-meta b{display:block;font-family:var(--f-head);font-size:1.0625rem;
  font-weight:700;color:var(--c-primary);line-height:1.25;overflow-wrap:anywhere}
.checker-meta span{display:block;margin-top:2px;font-size:.75rem;
  letter-spacing:.03em;text-transform:uppercase;color:var(--c-muted)}

.checker-findings{list-style:none;margin:0 0 var(--s-5);padding:0}
.checker-findings li{display:grid;grid-template-columns:auto 1fr;
  gap:var(--s-1) var(--s-3);align-items:start;padding:var(--s-3) 0;
  border-top:1px solid var(--c-border)}
.checker-findings li:first-child{border-top:0;padding-top:0}
/* Every child needs its column stated. Placing only the badge left auto-placement to
   decide the rest, which put the title in column 1 and stretched the badge across
   column 2 - a pill the width of the card with the heading beside it. */
.checker-findings .badge{grid-column:1;grid-row:1/3;justify-self:start;margin-top:2px}
.checker-findings b{grid-column:2;font-size:.9375rem;font-weight:600;
  color:var(--c-text);line-height:1.4}
.checker-findings span{grid-column:2;font-size:.875rem;line-height:1.55;
  color:var(--c-muted)}

/* The email step. Sits in .checker-out between the URL submit and the report, so it
   inherits the card's colour like everything else there. */
.checker-gate{margin-top:var(--s-5);padding-top:var(--s-5);
  border-top:1px solid var(--c-border)}
.checker-gate-lead{margin:0 0 var(--s-3);font-size:.9375rem;line-height:1.55;
  color:var(--c-text)}
.checker-gate-lead b{color:var(--c-primary)}
.checker-gate input{width:100%;margin-bottom:var(--s-3)}
.checker-gate .btn{width:100%;justify-content:center}
.checker-gate .fine{margin:var(--s-3) 0 0}

.checker-error{margin:var(--s-4) 0 0;padding:var(--s-3) var(--s-4);
  border-radius:var(--r-sm);background:var(--c-danger-light);color:var(--c-danger);
  font-size:.9375rem;line-height:1.5}

@media (max-width:520px){
  /* Three columns of figures wrap into unreadable stacks on a phone. */
  .checker-meta{grid-template-columns:1fr;gap:var(--s-2);padding-block:var(--s-3)}
  .checker-meta li{display:flex;align-items:baseline;gap:var(--s-2)}
  .checker-meta b{font-size:.9375rem}
  .checker-meta span{margin-top:0}
}


/* Where the DIY path gets expensive — the conversion move on every failure page. */
.risk{background:var(--c-danger-light);border:1px solid #FCA5A5;border-radius:var(--r-md);
  border-left:4px solid var(--c-danger);padding:var(--s-6);margin-block:var(--s-8)}
.risk h3{color:var(--c-danger-dark);margin-top:0;
  display:flex;align-items:baseline;gap:.5em}
/* A drawn marker rather than an emoji: the emoji script is dequeued, and emoji as
   section markers is a generated-design tell. */
.risk h3::before{content:"!";flex:0 0 auto;width:1.35rem;height:1.35rem;border-radius:50%;
  background:var(--c-danger);color:#fff;font:800 .8125rem/1.35rem var(--f-head);
  text-align:center;transform:translateY(.1em)}
.risk strong{color:var(--c-danger-dark)}

/* ------------------------------------------------------------- urgency
   Applied by grownion_urgency() from the map: the attack cluster and the three
   commercial recovery pages are `danger`, the 25 named failures are `alert`.

   Deliberately restrained. The signal is carried by the eyebrow, the highlighted
   phrase in the title, the callouts and the escalation link — not by repainting the
   page, which would read as an error state rather than as a service that handles one. */
.hero.is-danger .hero-kicker{background:rgba(248,113,113,.16);color:var(--c-danger-bright);
  box-shadow:inset 0 0 0 1px rgba(248,113,113,.34)}
.hero.is-danger .doc-title .hl{color:var(--c-danger-bright)}
.hero.is-danger .answer{border-left-color:var(--c-danger-bright)}
.hero.is-danger .hero-points li::before{border-color:var(--c-danger-bright)}

.hero.is-alert .hero-kicker{background:rgba(251,191,36,.16);color:var(--c-alert-bright);
  box-shadow:inset 0 0 0 1px rgba(251,191,36,.34)}
.hero.is-alert .doc-title .hl{color:var(--c-alert-bright)}
.hero.is-alert .answer{border-left-color:var(--c-alert-bright)}
.hero.is-alert .hero-points li::before{border-color:var(--c-alert-bright)}

/* On a page about an incident happening now, the primary action is the incident
   action. Only `danger` takes the button — an error page is not an emergency.

   Scoped to .hero-copy on purpose: the tool card in the other column is a routine
   audit request, and painting its submit red claimed an urgency the form does not
   have. Severity colour has to mean the same thing everywhere it appears. */
.gr-urgency-danger .hero-copy .btn-primary{background:var(--c-danger);
  border-color:var(--c-danger)}
.gr-urgency-danger .hero-copy .btn-primary:hover{background:var(--c-danger-dark);
  border-color:var(--c-danger-dark)}
.gr-urgency-danger .mobile-cta-btn.is-primary{background:var(--c-danger);
  border-color:var(--c-danger)}

/* Escalation and recovery calls to action carry the severity wherever they appear. */
.cmp-recovery-cta,.cmp-escalation-cta{border-left:4px solid var(--c-danger);
  background:var(--c-danger-light);border-radius:0 var(--r-md) var(--r-md) 0;
  padding:var(--s-6)}
/* The bridge block inside these carries its own pale-blue ground, which sat as a
   second tinted panel inside the first. One surface, not two. */
.cmp-recovery-cta .bridge-primary,.cmp-escalation-cta .bridge-primary{
  background:transparent;padding:0;margin-bottom:0}
.cmp-recovery-cta .btn-primary,.cmp-escalation-cta .bridge-cta{
  background:var(--c-danger);border-color:var(--c-danger)}
.cmp-recovery-cta .btn-primary:hover,.cmp-escalation-cta .bridge-cta:hover{
  background:var(--c-danger-dark);border-color:var(--c-danger-dark)}
.gr-urgency-alert .cmp-recovery-cta,.gr-urgency-alert .cmp-escalation-cta{
  border-left-color:var(--c-alert);background:var(--c-alert-light)}

/* Threat and failure card grids: severity on the marker, not the whole card. */
.gr-urgency-danger .card-grid>li{border-left:3px solid var(--c-danger)}
.gr-urgency-alert .card-grid>li{border-left:3px solid var(--c-alert)}

details{border:1px solid var(--c-border);border-radius:var(--r-sm);
  padding:var(--s-4) var(--s-5,var(--s-4));margin-bottom:var(--s-3);background:var(--c-bg)}
details[open]{background:var(--c-bg-alt)}
summary{font-family:var(--f-head);font-weight:600;cursor:pointer;color:var(--c-primary);
  line-height:1.5}
summary::marker{color:var(--c-accent)}
/* The answer sat directly under the question with no separation. It now gets a clear
   gap and a hairline, so an open row reads as question-then-answer rather than as one
   run of text. */
details[open]>summary{margin-bottom:var(--s-4);padding-bottom:var(--s-3);
  border-bottom:1px solid var(--c-border)}
/* The page's one Q&A block. Given its own identity so it is not mistaken for the
   process list, which is now a numbered stepper rather than a second stack of
   collapsible rows. */
.qa>summary{font-size:1.0625rem}
.qa[open]{border-left:3px solid var(--c-accent);background:var(--c-bg-alt)}
.gr-urgency-danger .qa[open]{border-left-color:var(--c-danger)}
.gr-urgency-alert .qa[open]{border-left-color:var(--c-alert)}
details>summary+*{margin-top:0}
details>p{line-height:1.7;color:var(--c-slate)}
details>*:last-child{margin-bottom:0}

/* ---------------------------------------------------------------- stepper
   A procedure, not a question list. Numbered, always open, with a rule connecting the
   markers so the order is the point. This is what stops "How the work runs" from
   reading as a second FAQ next to the real one. */
.stepper{counter-reset:step;list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:var(--s-6)}
.stepper>li{counter-increment:step;position:relative;margin:0;
  padding-left:var(--s-12);display:flex;flex-direction:column;gap:var(--s-2)}
.stepper>li::before{content:counter(step);position:absolute;left:0;top:0;
  width:2rem;height:2rem;border-radius:50%;background:var(--c-accent-light);
  color:var(--c-accent-dark);font:800 .875rem/2rem var(--f-head);text-align:center}
/* The connector runs from one marker to the next, and stops at the last. */
.stepper>li::after{content:"";position:absolute;left:calc(1rem - 1px);top:2rem;
  bottom:calc(var(--s-6) * -1);width:2px;background:var(--c-border)}
.stepper>li:last-child::after{display:none}
.stepper>li>b{font-family:var(--f-head);font-weight:700;font-size:1.0625rem;
  color:var(--c-primary);line-height:1.4}
.stepper>li>span{color:var(--c-slate);line-height:1.7}
/* Not a sequence — same rows, no numbers, no connector. */
.stepper.is-list{gap:var(--s-5,var(--s-4))}
.stepper.is-list>li{padding-left:0}
.stepper.is-list>li::before,.stepper.is-list>li::after{display:none}
.stepper.is-list>li{padding-bottom:var(--s-4);border-bottom:1px solid var(--c-border)}
.stepper.is-list>li:last-child{border-bottom:0;padding-bottom:0}
.gr-urgency-danger .stepper>li::before{background:var(--c-danger-light);
  color:var(--c-danger-dark)}
.gr-urgency-alert .stepper>li::before{background:var(--c-alert-light);
  color:var(--c-alert-dark)}

.steps{counter-reset:step;list-style:none;padding:0}
.steps>li{counter-increment:step;position:relative;padding-left:var(--s-10);
  margin-bottom:var(--s-6)}
.steps>li::before{content:counter(step);position:absolute;left:0;top:0;
  width:1.75rem;height:1.75rem;border-radius:50%;background:var(--c-primary);
  color:#fff;font:600 .875rem/1.75rem var(--f-head);text-align:center}

/* Contextual bridges: micro context, below the fold, never in the centerpiece. */
/* --------------------------------------------------- the escalation block
   This is where the Outer section hands over to a commercial page, so it is the one
   place on an informational document that is allowed to look like an offer. It used to
   be a pale panel with a dark bar in it and, underneath, an unlabelled grid of chips
   each carrying a full 60-character page title. */
.cmp-bridge-cards{border-top:1px solid var(--c-border);padding-top:var(--s-10)}

.bridge-primary{position:relative;overflow:hidden;
  background:linear-gradient(150deg,#0d2b49 0%,var(--c-primary) 100%);
  color:rgba(255,255,255,.72);border-radius:var(--r-md);
  padding:var(--s-8);margin-bottom:var(--s-10);
  display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-4)}
/* A quiet accent edge, so it reads as the page's next step rather than a stray panel. */
.bridge-primary::before{content:"";position:absolute;inset:0 auto 0 0;width:4px;
  background:var(--c-accent)}
.bridge-lead{font:700 .6875rem/1.6 var(--f-body);letter-spacing:.11em;
  text-transform:uppercase;color:var(--c-accent-bright);margin:0}
.bridge-cta{display:inline-flex;align-items:center;gap:.5em;
  background:var(--c-accent);color:#fff!important;
  padding:13.6px 29.6px;border-radius:var(--r-sm);text-decoration:none;
  font:600 1rem/1.6 var(--f-body)}
.bridge-cta::after{content:"\2192";font-size:1.05em;line-height:1}
.bridge-cta:hover{background:var(--c-accent-dark)}
.bridge-note{margin:0;font-size:.9375rem;line-height:1.65;max-width:62ch;
  color:rgba(255,255,255,.66)}
/* On an incident page the handover is the urgent action. */
.gr-urgency-danger .bridge-primary::before{background:var(--c-danger)}
.gr-urgency-danger .bridge-cta{background:var(--c-danger)}
.gr-urgency-danger .bridge-cta:hover{background:var(--c-danger-dark)}
.gr-urgency-danger .bridge-lead{color:var(--c-danger-bright)}
.gr-urgency-alert .bridge-primary::before{background:var(--c-alert)}
.gr-urgency-alert .bridge-lead{color:var(--c-alert-bright)}

/* Siblings: navigation. Short labels, equal height, one row that fills the width. */
.bridge-more-lead{font:700 .6875rem/1.6 var(--f-body);letter-spacing:.11em;
  text-transform:uppercase;color:var(--c-muted);margin:0 0 var(--s-4)}
.bridge-grid{display:grid;gap:var(--s-3);list-style:none;padding:0;margin:0;
  grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}
.bridge-grid li{margin:0}
.bridge-grid a{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  height:100%;padding:var(--s-4);border:1px solid var(--c-border);
  border-radius:var(--r-sm);text-decoration:none;font-size:.9375rem;font-weight:600;
  color:var(--c-primary);background:var(--c-bg);line-height:1.35}
.bridge-grid a::after{content:"\2192";color:var(--c-accent);font-weight:400;
  transform:translateX(0);transition:transform .12s}
.bridge-grid a:hover{border-color:var(--c-accent);background:var(--c-accent-light)}
.bridge-grid a:hover::after{transform:translateX(3px)}

/* Functional affordances. Never ship these non-working. */
/* ------------------------------------------------------- /best/ criteria filter
   The control lives below the provider table and writes its answer onto that table's
   rows. Badges use the severity tokens, not the brand accent: the same amber that means
   "broken" elsewhere here means "the price is not published", and the same red that
   means "compromised" means "not sold at any tier". */
.crit-set{border:0;padding:0;margin:0 0 var(--s-5);display:grid;gap:var(--s-3)}
.crit-opt{display:flex;gap:var(--s-3);align-items:flex-start;cursor:pointer;line-height:1.4}
.crit-opt input{margin:.15em 0 0;flex:0 0 auto;width:1.05em;height:1.05em;accent-color:var(--c-accent-dark)}
.crit-out{border-top:1px solid var(--c-border);padding-top:var(--s-4);min-height:3.5em}
.crit-out>*:last-child{margin-bottom:0}
.crit-verdict{margin:0 0 var(--s-2)}

.crit-badge{display:inline-block;margin-left:var(--s-3);padding:.1em .5em;
  border-radius:var(--r-sm,4px);font-family:var(--f-head);font-size:.75rem;
  font-weight:600;white-space:nowrap;vertical-align:middle}
.crit-badge[data-state="in"]{background:var(--c-accent-light);color:var(--c-accent-dark)}
.crit-badge[data-state="out"]{background:var(--c-danger-light);color:var(--c-danger-dark)}
.crit-badge[data-state="unclear"]{background:var(--c-alert-light);color:var(--c-alert-dark)}

/* Marking the row, not replacing it. A struck-through row still shows its published
   figures, because the point of the page is that the advertised price was never the
   comparable one - hiding the row would hide the evidence for that. */
.cmp-provider-comparison-table tr[data-crit="out"] td{opacity:.55}
.cmp-provider-comparison-table tr[data-crit="best"]{background:var(--c-accent-light)}
.cmp-provider-comparison-table tr[data-crit] th{white-space:normal}

.tool{background:var(--c-bg-alt);border:1px solid var(--c-border);
  border-radius:var(--r-md);padding:var(--s-6)}
/* ------------------------------------------------------- tool card type scale
   A tool sits in a ~470px card and needs its own scale. The page's 33.6px section
   heading is oversized inside one, and the card had the description and the field
   labels both at 14px, so supporting text and functional text carried equal weight and
   neither led.

     title        22px / Sora 700     what this tool is
     input        16px                the reader's own words — and 16px is the floor
                                      that stops iOS zooming the page on focus
     description  15px / muted        what it does, read once
     label        13px / 600          scanned, not read
     optional     12px / 400          a qualifier on a label
     trust        12px / muted        the small print under the button              */
.tool h2{font-size:1.375rem;line-height:1.3;margin-top:0;margin-bottom:var(--s-2)}
.tool>.fine{font-size:.9375rem;line-height:1.6;color:var(--c-muted);
  margin-bottom:var(--s-5)}
.tool label{display:block;font-weight:600;font-size:.8125rem;letter-spacing:.005em;
  margin-bottom:var(--s-2);color:var(--c-primary)}
/* "(optional)" is a qualifier on the label, not part of it. */
.tool label .fine{font-weight:400;color:var(--c-muted);font-size:.75rem}
.audit-form .trust{font-size:.75rem}
.audit-form .form-out{font-size:.875rem}

/* ------------------------------------------------------------- audit form
   One gap governs the whole form. The spacing used to come from a mix of the grid's
   own margin, each label's margin and the field's margin-top, which stacked
   differently between the paired row and the full-width rows below it. */
.audit-form{display:flex;flex-direction:column;gap:var(--s-5,var(--s-4))}
.audit-form>label,.audit-form .calc-grid{margin:0}
.audit-form .calc-grid{gap:var(--s-4);grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
.audit-form .btn{width:100%;justify-content:center;margin-top:var(--s-1)}
/* The status line reserves height so a message does not shift the form. At rest that
   reserved height is just a gap under the button, so it collapses until it has
   something to say — the shift is then one line, on submit, which is a moment the
   reader is already looking at. */
.audit-form .form-out{margin:0}
.audit-form .form-out:empty{display:none}

/* Subject tabs on the contact form. Radios, not buttons: the value posts with the form
   whether or not the script runs, and the checked state is CSS, so the visible
   selection and the submitted value cannot disagree. */
.form-tabs{display:flex;flex-wrap:wrap;gap:var(--s-2);border:0;padding:0;margin:0}
.form-tabs label{margin:0;font-weight:400}
.form-tabs input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.form-tabs span{display:inline-block;cursor:pointer;
  padding:7px 14px;border-radius:100px;border:1px solid var(--c-border);
  background:var(--c-bg);color:var(--c-muted);
  font:600 .8125rem/1.5 var(--f-body);transition:border-color .12s,background .12s}
.form-tabs label:hover span{border-color:var(--c-accent);color:var(--c-primary)}
.form-tabs input:checked+span{background:var(--c-accent-light);
  border-color:var(--c-accent);color:var(--c-accent-dark)}
/* Keyboard focus has to be visible even though the control itself is hidden. */
.form-tabs input:focus-visible+span{outline:2px solid var(--c-accent);outline-offset:2px}
/* Choosing "my site was hacked" is an incident; the chip says so. */
.form-tabs input[value="hacked"]:checked+span{background:var(--c-danger-light);
  border-color:var(--c-danger);color:var(--c-danger-dark)}

.audit-form.is-contact{gap:var(--s-4)}
.audit-form.is-contact .form-tabs{margin-bottom:var(--s-2)}
.audit-form .trust a{color:var(--c-accent-dark)}
.audit-form .trust{margin:0;text-align:center;line-height:1.6}
/* `textarea` was missing from this rule, so it fell back to browser defaults —
   monospace, about 20 columns, and inline, which floated it alongside its own label
   instead of under it. The inputs only looked right because width:100% forced a wrap.
   Fields are explicitly block so their position never depends on that again. */
/* Text fields only. Checkboxes and radios must keep their intrinsic size and stay
   inline — blanket `display:block;width:100%` turned every checklist tickbox into a
   full-width block that shoved its own label onto the next line. */
.tool input:not([type="checkbox"]):not([type="radio"]),
.tool select,.tool textarea{display:block;width:100%;
  min-height:2.875rem;padding:.7rem .875rem;font:400 1rem/1.5 var(--f-body);
  border:1px solid var(--c-border);border-radius:var(--r-sm);background:var(--c-bg-alt);
  color:var(--c-text);margin-top:var(--s-2);
  transition:border-color .12s,background-color .12s,box-shadow .12s}
.tool textarea{min-height:6.5rem;resize:vertical;line-height:1.6}
/* Filled at rest, white and ringed on focus, so the active field is unmistakable. */
.tool input:not([type="checkbox"]):not([type="radio"]):focus,
.tool select:focus,.tool textarea:focus{background:var(--c-bg);
  border-color:var(--c-accent);outline:0;
  box-shadow:0 0 0 3px var(--c-accent-light)}
.tool input:not([type="checkbox"]):not([type="radio"]):hover,
.tool textarea:hover{border-color:#CBD5E1}
.tool input::placeholder,.tool textarea::placeholder{color:var(--c-muted);opacity:1}
.tool select{appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--c-muted) 50%),
    linear-gradient(135deg,var(--c-muted) 50%,transparent 50%);
  background-position:calc(100% - 18px) 52%,calc(100% - 13px) 52%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:2.5rem}

/* Every submit outcome is reported here, in words. */
.form-out{margin:var(--s-3) 0 0;font-size:.9375rem;min-height:1.4em;color:var(--c-muted)}
.form-out.is-ok{color:var(--c-accent-dark);font-weight:600}
.form-out.is-bad{color:var(--c-danger);font-weight:600}
.tool button{background:var(--c-accent);color:#fff;border:0;font:600 1rem var(--f-body);
  padding:var(--s-3) var(--s-8);border-radius:var(--r-sm);cursor:pointer}
.tool button:hover{background:var(--c-accent-dark)}
.tool-out{margin-top:var(--s-6);font-family:var(--f-head);font-size:1.5rem;
  font-weight:700;color:var(--c-primary);font-variant-numeric:tabular-nums}

/* The live proof strip: numbers in Sora 800 at 38.4px, in #00B37E, spread evenly on
   the navy band with a small label under each. The band ground comes from is-band-dark,
   so the strip itself is transparent. */
.evidence{display:grid;gap:var(--s-6) var(--s-8);
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  background:transparent;color:#fff;padding:0;text-align:center}
.evidence div{display:flex;flex-direction:column;gap:var(--s-1)}
.evidence b{font-family:var(--f-head);font-size:2.4rem;font-weight:800;line-height:1;
  color:var(--c-accent);font-variant-numeric:tabular-nums}
.evidence span{font-size:.8125rem;color:rgba(255,255,255,.62)}

/* ------------------------------------------------------------- responsive
   Four tiers. Everything above them is already fluid — the grids are auto-fit, the
   headings are clamped, and every table ships inside a .scroll container — so these
   only handle what fluid layout cannot: the navigation, tap targets, and the padding
   that stops being generous and starts being wasteful on a phone. */

/* Long unbroken strings are normal on this site: ERR_SSL_VERSION_OR_CIPHER_MISMATCH,
   wp-config constants, file paths. Without this they set the minimum width of the
   page and every phone gets a horizontal scrollbar. */
.doc-body,.answer,.card,.cmp{overflow-wrap:break-word}
pre,code{overflow-x:auto;max-width:100%}
pre{white-space:pre-wrap}

/* The header is sticky, so an in-page anchor would otherwise land underneath it. */
:target{scroll-margin-top:84px}

/* ---- mobile action bar ------------------------------------------------
   Hidden above 768 px, where the header CTA is still on screen. Below it the menu is
   behind a drawer and the conversion affordance scrolls away inside the first screen,
   so two actions stay pinned to the bottom of the viewport. */
.mobile-cta{display:none}
@media (max-width:768px){
  .mobile-cta{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:var(--s-3);
    position:fixed;left:0;right:0;bottom:0;z-index:60;
    padding:var(--s-3) var(--s-4);
    /* The inset keeps the buttons clear of the iOS home indicator. */
    padding-bottom:calc(var(--s-3) + env(safe-area-inset-bottom,0px));
    background:color-mix(in srgb,var(--c-bg) 92%,transparent);
    backdrop-filter:blur(10px);border-top:1px solid var(--c-border);
    box-shadow:0 -2px 16px rgba(10,37,64,.10)}
  .mobile-cta-btn{display:flex;align-items:center;justify-content:center;text-align:center;
    min-height:48px;padding:var(--s-2) var(--s-3);border-radius:var(--r-sm);
    font:600 .9375rem/1.25 var(--f-body);text-decoration:none;
    border:1px solid var(--c-border);color:var(--c-primary);background:var(--c-bg)}
  .mobile-cta-btn.is-primary{background:var(--c-accent);border-color:var(--c-accent);
    color:#fff}
  /* The bar is fixed, so the end of the page needs room to clear it. That room goes on
     the footer rather than on the body: body padding would leave 76px of white below
     the dark footer, which is invisible only while the bar is covering it — and the
     bar now steps aside at the footer. */
  .site-foot{margin-bottom:0;padding-bottom:calc(var(--s-6) + 76px)}
  /* Slides out of the way once the footer is reached, so it never covers the links. */
  .mobile-cta{transition:transform .2s ease,opacity .2s ease}
  .mobile-cta.is-hidden{transform:translateY(115%);opacity:0;pointer-events:none}
}
/* One action gets the full width rather than half a bar. */
@media (max-width:768px){
  .mobile-cta:has(.mobile-cta-btn:only-child){grid-auto-flow:row}
}

/* --- Desktop, upward. The container was pinned at 1200 px, so a 1440 or 1920 monitor
   got the same column with ever-wider empty margins. These tiers spend the extra
   width on measure and vertical rhythm rather than just stretching every element:
   the reading column is capped in ch, so it stays readable while the tools, tables
   and card grids widen. --- */
/* --- ≥1025: desktop navigation.

   The menu is seven grouped items, not ten flat ones, so it measures about 538 px —
   roughly 863 px with the brand and the CTA beside it, against 976 px of container at
   1024. It fits at a readable 15 px, which is why the collapse point came back down
   from 1280 to 1024 and the type went back up.

   The dropdown opens on hover and on focus-within, so it is reachable by keyboard
   without a script. The parent is a real link to a real page in every case — nothing
   here is a control that exists only to open a menu. --- */
@media (min-width:1025px){
  .site-head .shell{flex-wrap:nowrap}
  .nav>ul{flex-wrap:nowrap}
  .nav>ul>li>a{white-space:nowrap}

  .nav .menu-item-has-children>a::after{content:"";display:inline-block;
    margin-left:var(--s-2);border:4px solid transparent;border-top-color:currentColor;
    transform:translateY(2px)}

  .nav .sub-menu{position:absolute;top:100%;left:calc(var(--s-3) * -1);min-width:210px;
    background:var(--c-primary-mid);border:1px solid rgba(255,255,255,.16);
    border-radius:var(--r-sm);box-shadow:var(--shadow-hi);padding:var(--s-2);
    z-index:60;visibility:hidden;opacity:0}
  .nav li:hover>.sub-menu,.nav li:focus-within>.sub-menu{visibility:visible;opacity:1}
  /* A gap between the item and the panel would drop the hover on the way down. */
  .nav .menu-item-has-children{padding-bottom:var(--s-3);margin-bottom:calc(var(--s-3) * -1)}
  .nav .sub-menu a{display:block;padding:var(--s-2) var(--s-3);border-radius:4px;
    white-space:nowrap;font-size:.9375rem}
  .nav .sub-menu a:hover{background:rgba(255,255,255,.10);color:#fff}
}

/* Above 1280 nothing about the container changes — the width and the gutters are the
   same 1200/24 as on a phone, and so is the 16px body type. Only vertical rhythm and
   the lead's size step up, because there is more height to spend, not more width. */
@media (min-width:1280px){
  /* Top stays 0 at every width — the hero band supplies the space under the header. */
  .doc{padding-block:0 var(--s-12)}
  .centerpiece{font-size:1.25rem;max-width:66ch}
  .cmp{margin-block:var(--s-12)}
  .site-head .shell{min-height:76px}
}

/* --- ≤1024: collapse to the drawer. Only where the script confirmed the button.
   Children render as an indented list rather than behind a second control: one
   disclosure is enough, and a nested toggle is one more thing that can fail. --- */
@media (max-width:1024px){
  .has-nav-toggle .nav-toggle{display:inline-flex}
  .has-nav-toggle .nav{display:none}
  .has-nav-toggle .nav.is-open{display:block}

  .nav{width:100%;margin-left:0;order:5;flex-basis:100%}
  .nav ul{flex-direction:column;gap:0;
    border-top:1px solid rgba(255,255,255,.14);padding-block:var(--s-2)}
  /* 44px minimum tap target, and a full-width hit area rather than the text only. */
  .nav a{display:block;padding:var(--s-3) 0;min-height:44px;line-height:1.6;font-size:1rem}
  .nav .menu-item-has-children>a{font-weight:700;color:#fff}
  .nav .sub-menu{padding-left:var(--s-4);gap:0;border-top:0;
    border-left:2px solid rgba(255,255,255,.14);margin-bottom:var(--s-2)}
  .nav .sub-menu a{font-size:.9375rem;color:#cfe0f0;min-height:40px;padding:var(--s-2) 0}

  /* Collapsed by default. The parent link and its disclosure sit on one row; the
     sub-menu spans the row below and is hidden until the caret is pressed. */
  .has-nav-toggle .nav .menu-item-has-children{display:grid;
    grid-template-columns:1fr auto;align-items:center}
  .has-nav-toggle .nav .menu-item-has-children>a{grid-column:1}
  .has-nav-toggle .nav .menu-item-has-children>.sub-menu{grid-column:1/-1;display:none}
  .has-nav-toggle .nav .menu-item-has-children.is-open>.sub-menu{display:flex}
  .has-nav-toggle .nav .sub-toggle{grid-column:2;display:flex;align-items:center;
    justify-content:center;width:44px;height:44px;padding:0;
    background:transparent;border:0;cursor:pointer;color:#cfe0f0}
  .has-nav-toggle .nav .sub-toggle::before{content:"";width:.5rem;height:.5rem;
    border:solid currentColor;border-width:0 2px 2px 0;
    transform:rotate(45deg) translate(-2px,-2px);transition:transform .15s}
  .has-nav-toggle .nav .sub-toggle[aria-expanded="true"]::before{
    transform:rotate(-135deg) translate(-2px,-2px);color:var(--c-accent)}
  .has-nav-toggle .nav .sub-toggle:hover{color:#fff}
  /* A menu taller than the viewport has to scroll on its own, or its last items are
     unreachable under a sticky header. */
  .has-nav-toggle .nav.is-open{max-height:calc(100vh - 68px);overflow-y:auto}
}

/* --- 768: phones and small tablets --- */
@media (max-width:768px){
  .doc{padding-block:var(--s-8)}
  h2{margin-top:var(--s-8)}
  /* Top only. `padding-block` here also set the bottom, which overrode the room the
     footer reserves for the pinned action bar in the earlier ≤768 block. */
  .site-foot{margin-top:var(--s-12);padding-top:var(--s-8)}
  .foot-nav ul{gap:var(--s-3) var(--s-6)}
  .centerpiece{font-size:1.0625rem}
  .answer{padding:var(--s-4)}
  .tool,.card,.risk,.bridge-primary,.guarantee,.evidence{padding:var(--s-4)}
  .evidence{gap:var(--s-4) var(--s-6)}
  .evidence b{font-size:1.5rem}
  /* `.btn` is inline-flex, so `text-align:center` — which is what these rules used to
     say — centres nothing. A full-width flex button needs justify-content, or its
     label and arrow sit against the left edge of a 342px button. */
  .hero-cta{justify-content:center}
  .hero-cta .btn{flex:1 1 100%;justify-content:center}
  .hero-cta .trust{text-align:center}
  .btn:not(.btn-sm){justify-content:center}
  /* The escalation link is the page's next step; give it the full row on a phone. */
  .bridge-cta{width:100%;justify-content:center}
  .bridge-primary{align-items:stretch}
  .calc-verdict b{font-size:1.375rem}
  .cmp{margin-block:var(--s-8)}
  /* The action bar takes over here — same breakpoint, so the primary action is never
     absent. Keeping both would put the same offer on screen twice. */
  .site-head .cta{display:none}
  /* The scroll containers are the only reason a wide table is survivable here, so
     make it visible that there is more to the right. */
  .scroll{border-inline:1px solid var(--c-border);border-radius:var(--r-sm)}

  /* The plan-card mobile rules are NOT here — they live directly after the
     .plan-cards definition further down. Placed here they lost on source order to
     that later rule, and the cards silently kept their desktop track size. */
}

/* --- 480: narrow phones. The header has to give up the CTA's full label width. --- */
@media (max-width:480px){
  /* The gutter stays 24px here too. It used to drop to 16px, which moved the page's
     left edge on the narrowest screens for no reason. */
  .site-head .shell{gap:var(--s-3)}
  .brand{font-size:.9375rem;flex:1 1 auto}
  .nav-toggle-label{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap}
  .nav-toggle{padding-inline:var(--s-3)}
  .btn{padding:var(--s-3) var(--s-6)}
  .btn:not(.btn-sm){width:100%;text-align:center}
  .calc-line{flex-wrap:wrap}
  .steps>li{padding-left:var(--s-8)}
  .doc{padding-block:var(--s-6)}
}

/* ---------------------------------------------------------- conversion UI */
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* Measured: radius 6, padding 13.6px 29.6px, Inter 16px. Primary 600 on #00B37E;
   ghost-on-dark 500 with a 1px 40%-white border; tertiary 600 on #0A2540. The live
   primary and tertiary buttons carry a trailing arrow. */
.btn{display:inline-flex;align-items:center;gap:.5em;
  font:600 1rem/1.6 var(--f-body);padding:13.6px 29.6px;
  border-radius:var(--r-sm);text-decoration:none;border:1px solid transparent;
  cursor:pointer;white-space:nowrap}
.btn-primary{background:var(--c-accent);color:#fff!important;border-color:var(--c-accent)}
.btn-primary:hover{background:var(--c-accent-dark);border-color:var(--c-accent-dark)}
.btn-primary::after,.btn-dark::after{content:"\2192";font-size:1.05em;line-height:1}
.btn-dark{background:var(--c-primary);color:#fff!important;border-color:var(--c-primary)}
.btn-dark:hover{background:var(--c-primary-mid);border-color:var(--c-primary-mid)}
.btn-ghost{background:transparent;color:var(--c-primary)!important;
  border-color:var(--c-border);font-weight:500}
.btn-ghost:hover{border-color:var(--c-primary);background:var(--c-primary-light)}
/* On the dark hero the ghost button inverts. */
.hero .btn-ghost{color:#fff!important;border-color:rgba(255,255,255,.4);background:transparent}
.hero .btn-ghost:hover{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.7)}
.btn-sm{font-size:.875rem;padding:8px 18px}
.trust{font-size:.8125rem;color:var(--c-muted);margin:var(--s-3) 0 0}

.hero-cta{display:flex;flex-wrap:wrap;gap:var(--s-4);align-items:center;margin-bottom:var(--s-8)}
.hero-cta .trust{flex-basis:100%;margin-top:0}

/* pricing table */
.billing-toggle{display:inline-flex;border:1px solid var(--c-border);border-radius:var(--r-sm);
  overflow:hidden;margin-bottom:var(--s-6)}
.billing-toggle button{background:var(--c-bg);border:0;font:600 .9375rem var(--f-body);
  padding:var(--s-3) var(--s-6);cursor:pointer;color:var(--c-muted)}
.billing-toggle button.is-on{background:var(--c-primary);color:#fff}
.billing-toggle .save{font-size:.75rem;font-weight:500;opacity:.85}

.plan-table{border-collapse:separate;border-spacing:0;min-width:720px}
.plan-table th[scope="row"]{font-family:var(--f-body);font-weight:500;text-transform:none;
  letter-spacing:0;font-size:.9375rem;color:var(--c-text);width:34%}
/* Scoped to .plan-table. `.plan-head` is the comparison table's <th> class, and the
   pricing cards use the same name for their head — unscoped, this rule's
   `text-align:center!important` centred the cards' name, price and strapline while
   their feature rows stayed left, so each card had two alignments. */
.plan-table .plan-head{text-align:center!important;vertical-align:top;
  padding:var(--s-6) var(--s-4)!important;
  border-bottom:2px solid var(--c-border);text-transform:none;letter-spacing:0}
.plan-table .plan-head.is-popular{background:var(--c-accent-light);
  border-bottom-color:var(--c-accent)}
.plan-table .plan-head .plan-name{display:block;font-family:var(--f-head);font-size:1.125rem;
  font-weight:700;color:var(--c-primary);margin-top:var(--s-2)}
.plan-table .plan-head .plan-price{display:block;font-family:var(--f-head);font-size:2.25rem;
  font-weight:800;color:var(--c-primary);line-height:1.1;font-variant-numeric:tabular-nums}
.plan-table .plan-head .plan-per{display:block;font-size:.8125rem;color:var(--c-muted);
  margin-bottom:var(--s-3)}
.plan-table .plan-head .plan-for{display:block;font-size:.8125rem;color:var(--c-muted);
  font-weight:400;margin-bottom:var(--s-4);min-height:2.4em}
.plan-table td{text-align:center;font-size:.875rem}
.plan-table td.yes{color:var(--c-accent-dark);font-weight:600}
.plan-table td.no{color:var(--c-border);font-size:1.25rem}
.plan-table tbody tr:nth-child(odd){background:var(--c-bg-alt)}
.is-us th,.is-us td{background:var(--c-accent-light);font-weight:600}

/* calculator */
.calc-grid{display:grid;gap:var(--s-4);grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  margin-bottom:var(--s-6)}
.calc-result{border-top:1px solid var(--c-border);padding-top:var(--s-4);margin-bottom:var(--s-6)}
.calc-line{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-4);
  padding:var(--s-2) 0;font-size:.9375rem;color:var(--c-muted)}
.calc-line b{font-family:var(--f-head);font-size:1.25rem;color:var(--c-primary);
  font-variant-numeric:tabular-nums}
.calc-verdict{border-top:1px solid var(--c-border);margin-top:var(--s-2);padding-top:var(--s-4)}
.calc-verdict b{font-size:1.75rem}
.calc-verdict b.is-good{color:var(--c-accent-dark)}
.calc-verdict b.is-warn{color:var(--c-alert)}

/* guarantee + addons + plan cards */
.guarantee{display:grid;gap:var(--s-6);grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  background:var(--c-accent-light);border-radius:var(--r-md);padding:var(--s-6)}
.guarantee div{display:flex;flex-direction:column;gap:var(--s-1)}
.guarantee b{font-family:var(--f-head);font-size:1.375rem;color:var(--c-primary)}
.guarantee span{font-size:.8125rem;color:var(--c-muted)}

.addon-grid{display:grid;gap:var(--s-4);list-style:none;padding:0;margin:0;
  grid-template-columns:repeat(auto-fit,minmax(215px,1fr))}
.addon-grid li{display:flex;flex-direction:column;gap:var(--s-2)}
.addon-price{font-family:var(--f-head);font-size:1.5rem;color:var(--c-primary)}
.addon-name{font-weight:600;font-size:.9375rem}

/* ---------------------------------------------------------- pricing cards
   Three faults were fixed here. The card is a flex column, and its default
   `align-items:stretch` pulled the badge and the button to full width, so the badge
   read as a filled bar and the button as an empty input. Each card carried one line of
   copy, which is not enough to choose from. And the popular plan was distinguished only
   by an outline, so nothing on the page was actually being recommended. */
/* Stretch, not start: equal-height cards mean the dividers and the buttons line up
   across all three, which is what makes them comparable at a glance. */
.plan-cards{display:grid;gap:var(--s-6);list-style:none;padding:0;margin:0;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr));align-items:stretch}
.plan-cards>li{display:flex;flex-direction:column;align-items:stretch;gap:var(--s-4);
  margin:0;padding:28px;background:var(--c-bg);
  border:1px solid var(--c-border);border-radius:var(--r-md)}

/* min-height so a two-line strapline on one plan does not push its divider below the
   others'. */
.plan-cards .plan-head{display:flex;flex-direction:column;gap:var(--s-1);
  padding-bottom:var(--s-4);border-bottom:1px solid var(--c-border);
  text-align:left;min-height:11.5rem}
/* A pill that hugs its text, not a bar across the card. */
.plan-flag{align-self:flex-start;margin-bottom:var(--s-2);
  padding:4px 12px;border-radius:100px;background:var(--c-accent);color:#fff;
  font:700 .6875rem/1.6 var(--f-body);letter-spacing:.09em;text-transform:uppercase}
.plan-name{font-family:var(--f-head);font-weight:700;font-size:1.05rem;
  color:var(--c-primary)}
.plan-price{font-family:var(--f-head);font-size:2.75rem;font-weight:800;line-height:1;
  color:var(--c-primary);font-variant-numeric:tabular-nums}
.plan-price small{font-size:.9375rem;font-weight:500;color:var(--c-muted);
  letter-spacing:0}
.plan-annual{font-size:.8125rem;color:var(--c-accent-dark);font-weight:600}
.plan-for{font-size:.8125rem;color:var(--c-muted);margin-top:var(--s-2)}

.plan-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;
  gap:var(--s-3);flex:1 1 auto}
.plan-rows li{margin:0;display:flex;flex-direction:column;gap:2px;
  padding-left:1.6rem;position:relative;font-size:.875rem}
.plan-rows li::before{content:"";position:absolute;left:.15rem;top:.42em;
  width:.4rem;height:.72rem;border:solid var(--c-accent);border-width:0 2px 2px 0;
  transform:rotate(45deg)}
.plan-rows li>span{font-weight:600;color:var(--c-primary)}
.plan-rows li>em{font-style:normal;color:var(--c-slate)}
.plan-rows li.is-off{opacity:.55}
.plan-rows li.is-off::before{transform:none;border:0;background:var(--c-border);
  width:.6rem;height:2px;top:.72em;left:.1rem}
.plan-rows li.is-off>span{color:var(--c-muted)}

.plan-cards .btn{width:100%;justify-content:center;margin-top:auto}
.plan-note{font-size:.8125rem;color:var(--c-muted);text-align:center}

/* The recommendation, made visible: accent border, lift, and a tinted head. */
.plan-cards>li.is-popular{border:2px solid var(--c-accent);box-shadow:var(--shadow-hi);
  background:var(--c-bg)}
.plan-cards>li.is-popular .plan-head{border-bottom-color:var(--c-accent-light)}
.plan-cards>li.is-popular .plan-price{color:var(--c-accent-dark)}
@media (min-width:900px){
  /* Raised out of the row so the eye lands on it first. */
  .plan-cards>li.is-popular{margin-block:calc(var(--s-4) * -1) 0;
    padding-block:calc(28px + var(--s-4)) calc(28px + var(--s-4))}
}

/* Plans in one swipeable row on a phone rather than three stacked cards.
   Stacked, comparing Starter against Business means scrolling past two full cards and
   holding the first in your head. Side by side with snap, the same thumb movement puts
   them next to each other. The row bleeds to the band's gutter so it scrolls edge to
   edge, and scroll-padding keeps a snapped card clear of that edge.

   This block sits AFTER the .plan-cards definition on purpose. A media query adds no
   specificity, so when it lived up with the other ≤768 rules the later base rule won on
   source order and the cards kept their desktop track size. */
@media (max-width:768px){
  .plan-cards{grid-template-columns:none;grid-auto-flow:column;
    grid-auto-columns:min(78vw,300px);
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline:var(--gutter);
    margin-inline:calc(var(--gutter) * -1);
    padding-inline:var(--gutter);padding-bottom:var(--s-4);gap:var(--s-4)}
  .plan-cards>li{scroll-snap-align:start}
  /* No lift on a phone — it would clip against the scroll container's edge. */
  .plan-cards>li.is-popular{margin-block:0}
  /* The desktop head min-height leaves a hole when the strapline is one line. */
  .plan-cards .plan-head{min-height:0}
}

