/* ============================================================
   CrocWeb — Dark Midnight theme
   Base: #08113B, stepped up through a monochrome navy ladder
   with a few deliberate blue/green accent gradients.
   Used by: index.html, wordpress-hosting.html
   ============================================================ */

:root {
  /* Base navy + accent blue/green sampled directly from crocweb.com's
     real production pixels (assets/Screenshot ... CrocWeb ....png) —
     kept as the anchor tones; the ladder below builds sophistication
     around them with indigo/violet/cyan steps rather than retuning them. */
  /* 2026-08-31 "darker theme" pass — explicit request to push the whole
     ladder deeper rather than retune hues; every step below is roughly
     40-50% darker than its previous value, same relative spacing between
     steps preserved. This deliberately moves off the pixel-sampled
     production anchor noted above — a knowing exception, not a mistake. */
  --bg-void: #000010;       /* near-black navy — deepest atmospheric layer, used in glows/gradients only */
  --bg-deep: #00001f;       /* utility bar / footer base tone */
  --bg: #00001f;            /* page base */
  --bg-indigo: #030520;     /* midnight-indigo step, used in section-to-section gradient transitions */
  --tint: #02041a;          /* alt section surface, one step up (used sparingly) */
  --card: #070a30;          /* small chip / control surface (nav pills, footer icons) */
  --tint-2: #0c1638;        /* hover state / stronger chip surface */
  --accent-light: #121e4a;  /* top of the "featured" gradient */
  --line: rgba(255, 255, 255, 0.08);
  --line-strong: rgba(255, 255, 255, 0.16);
  --line-bright: rgba(255, 255, 255, 0.26);

  --blue: #0a74da;
  --blue-deep: #085fb3;
  --blue-dark: #063f7a;
  --blue-light: #43a9f4;
  --blue-bright: #6ea8ff;
  --blue-tint: rgba(10, 116, 218, 0.16);
  /* Glossy icon-chip treatment (2026) — same recipe as .btn-primary:
     gradient fill + inner top highlight + soft glow shadow. Reserved for
     icons that sit on genuinely interactive controls (mega menu items,
     product cards, accordion open-states, plans-nav) so the chip reads as
     "clickable" the same way the button does. Decorative mockup pixels
     (fake browser/editor chrome) intentionally stay flat — see their own
     rules. */
  --icon-gloss: linear-gradient(180deg, #2489ea 0%, #0a74da 55%, #085fb3 100%);
  --icon-gloss-hover: linear-gradient(180deg, #379af4 0%, #0f83ee 55%, #085fb3 100%);
  --icon-gloss-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 6px 16px -4px rgba(10, 116, 218, 0.5);
  /* Toned-down glow — deliberately distinct from --icon-gloss so passive,
     read-only content (stat readouts, trust-strip badges, platform/
     reliability feature call-outs) doesn't visually double as a button.
     Translucent fill + colored (not white) icon, one step quieter than
     the solid gloss chip. */
  --icon-glow: linear-gradient(180deg, rgba(10, 116, 218, 0.4), rgba(10, 116, 218, 0.08));
  --icon-glow-shadow: inset 0 1.5px 0 rgba(255, 255, 255, 0.35), inset 0 -10px 12px -6px rgba(10, 116, 218, 0.55), inset 0 0 0 1px rgba(10, 116, 218, 0.25), 0 6px 14px -5px rgba(10, 116, 218, 0.45);
  --cyan: #2dd4e8;                              /* sharper highlight accent — glows, chip edges, data-viz */
  --cyan-tint: rgba(45, 212, 232, 0.14);
  --violet: #8b7bf0;                            /* very restrained secondary accent — used sparingly for depth, never as a primary fill */
  --violet-tint: rgba(139, 123, 240, 0.12);
  --green: #279832;
  --green-bright: #3fc94e;
  --green-tint: rgba(39, 152, 50, 0.16);

  --ink: #f4f7fd;
  --mute: #a3aecc;
  --faint: #6c7699;

  --font-display: "Manrope", "Inter", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, sans-serif;

  --container: 1180px;
  /* 1440→1300 (2026-08-31): full edge-to-edge width read as too wide once
     header/hero/footer all switched to it — pulled back so there's still
     real page margin at common desktop widths, not full-bleed everywhere. */
  --container-wide: 1300px;
  --container-narrow: 640px;
  /* Nav-only, slightly wider than --container-wide (2026-08-31) — explicit
     request for the header (logo/nav/chat button edges) to frame the page
     rather than land flush with the hero/product-tiles/stats edges below
     it, which all use --container-wide itself. */
  --container-header: 1340px;
  --radius: 14px;
  --radius-lg: 24px;
  --radius-xl: 28px;
  /* Reduced from clamp(72px, 9vw, 128px) — 2026-09-01, explicit feedback
     that the sitewide gap between sections (128px top + 128px bottom =
     256px of empty space at every seam, at typical desktop widths) read
     as too large. This is a global token used by every .section on both
     pages, so the cut applies everywhere uniformly rather than singling
     out any one section. */
  --section-pad: clamp(56px, 6.5vw, 96px);

  --shadow-soft: 0 12px 32px -6px rgba(2, 6, 23, 0.45);
  --shadow-lift: 0 26px 60px -20px rgba(2, 6, 23, 0.7);
  --shadow-glow-blue: 0 0 0 1px rgba(10, 116, 218, 0.3), 0 20px 48px -16px rgba(10, 116, 218, 0.4);
  --shadow-glow-cyan: 0 0 0 1px rgba(45, 212, 232, 0.25), 0 20px 48px -16px rgba(45, 212, 232, 0.3);

  --ease-out: cubic-bezier(0.16, 0.84, 0.44, 1);
  --dur-fast: 0.22s;
  --dur-med: 0.35s;

  /* the recurring "featured" surface — hero visual, popular plan,
     on-dark contrast band, CTA mascot platform */
  --feature-gradient: linear-gradient(165deg, var(--accent-light) 0%, #07082a 55%, #05061f 100%);

  /* large panel surfaces — product/plan cards, mega menu, checklist panel,
     switcher, compare/FAQ cards. Layered indigo gradient with a touch more
     depth than a flat sample — top edge lifted toward violet, base toward void. */
  --card-gradient: linear-gradient(165deg, #0b0c33 0%, #070830 55%, #050626 100%);
  --card-gradient-hover: linear-gradient(165deg, #0e0f3e 0%, #090a3a 55%, #06072c 100%);
  /* flatter surface for review cards — sampled, no gradient on the real site */
  --card-flat: #010143;
  /* dot-grid used as a low-opacity section texture */
  --dot-grid: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.07) 1px, transparent 0);
}

/* ---------- Base ---------- */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 130px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  /* Density pass, 2026-08-31: was two overlapping radial glows + a visible
     vertical light/dark/light gradient — read as "busy/lit-up" next to a
     clean reference. Down to one wide, very faint glow over a near-flat
     base so the navy reads calm, not textured.
     background-attachment: fixed removed (2026-09-01) — that pinned this
     glow to the *viewport* rather than the page, so it never scrolled
     away: it sat under the sticky quick-nav at every scroll position
     ("a blue glow moving with me") and created a bright patch wherever it
     happened to land on a section with its own different background,
     which is what was actually causing the "cut-off above Free migration"
     look even after removing that section's own glows. Scrolling normally
     with the page instead means it only ever appears once, near the true
     top of the page behind the hero, same as any other section's glow. */
  background:
    radial-gradient(1200px 700px at 50% -10%, rgba(10, 116, 218, 0.09), transparent 62%),
    var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  position: relative;
}

/* Film-grain overlay — removed in the density pass (2026-08-31). At 0.05
   opacity it was one more layer of texture working against a "clean,
   smooth" read; the page doesn't need it once the background itself is
   calmer. Kept as a comment, not deleted outright, in case a future pass
   wants it back once the rest of the page is genuinely smooth:
   opacity: 0.05; mix-blend-mode: overlay; feTurbulence baseFrequency 0.85. */

/* Stacking context for these so they sit above body's own background glow
   (no dot-grid anymore — that was a separate layer removed in an earlier
   pass, this comment used to describe stacking above it). */
.site-header, .utility-bar, main, .site-footer, .deal-bar { position: relative; z-index: 1; }

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.12;
  margin: 0 0 0.5em;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}

p { margin: 0 0 1em; }

/* Scroll-reveal — CSS-driven, JS only toggles a class. Content is visible
   by default (matches main.js's own stated intent); JS adds .pre-reveal
   before paint on supporting browsers and removes it on intersect, so a
   slow/blocked GSAP CDN or an instant-scroll capture tool can never leave
   a section permanently invisible the way the old gsap.from() setup did. */
[data-reveal] {
  transition: opacity 0.6s cubic-bezier(0.16, 0.84, 0.44, 1), transform 0.6s cubic-bezier(0.16, 0.84, 0.44, 1);
}
[data-reveal].pre-reveal { opacity: 0; transform: translateY(28px); }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { transition: none; }
  [data-reveal].pre-reveal { opacity: 1; transform: none; }
}

a { color: var(--blue-bright); text-decoration: none; }
a:hover { color: var(--blue); }

button { font-family: inherit; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--blue-bright);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection { background: rgba(110, 168, 255, 0.35); }

.container { width: min(var(--container), 100% - 48px); margin-inline: auto; }
/* Composition primitives (2026 editorial pass) — see CLAUDE.md "Page width and
   composition". Use alongside the default .container, not as a full replacement,
   so most sections keep the standard measure and only the ones that need a
   large canvas or a tight text column opt into these. */
.container-wide { width: min(var(--container-wide), 100% - 48px); margin-inline: auto; }
.container-narrow { width: min(var(--container-narrow), 100% - 48px); margin-inline: auto; }
/* Full-bleed: section content runs edge-to-edge with only breathing-room
   padding, for large technical visualizations that shouldn't be boxed in. */
.section.is-full-bleed { padding-inline: clamp(24px, 6vw, 96px); }

.skip-link {
  position: absolute; left: 16px; top: -60px; z-index: 300;
  background: var(--blue); color: #fff;
  padding: 10px 18px; border-radius: 8px; transition: top 0.2s;
}
.skip-link:focus { top: 16px; color: #fff; }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-weight: 600;
  font-size: 15px;
  line-height: 1;
  padding: 16px 28px;
  border-radius: 999px;
  border: 1px solid transparent;
  transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s, color 0.2s;
  touch-action: manipulation;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: linear-gradient(180deg, #2489ea 0%, var(--blue) 55%, var(--blue-deep) 100%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 10px 26px -8px rgba(10, 116, 218, 0.55);
}
.btn-primary:hover {
  background: linear-gradient(180deg, #379af4 0%, #0f83ee 55%, var(--blue-deep) 100%);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.32), 0 16px 34px -8px rgba(10, 116, 218, 0.65);
}
.btn-primary:active { transform: translateY(0); }

.btn-ghost {
  background: rgba(255, 255, 255, 0.03);
  color: var(--ink);
  border-color: var(--line-strong);
}
.btn-ghost:hover { border-color: var(--blue-bright); color: var(--ink); background: var(--tint-2); transform: translateY(-2px); }

/* light-on-blue — the pale button used on top of blue gradient surfaces
   (CTA block), matched to the real site's CTA button */
.btn-light {
  background: linear-gradient(180deg, #6cc3ff 0%, var(--blue-light) 100%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 10px 26px -8px rgba(0, 0, 0, 0.35);
}
.btn-light:hover {
  background: linear-gradient(180deg, #7fccff 0%, #57b6f8 100%);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45), 0 14px 32px -8px rgba(0, 0, 0, 0.4);
}

.btn .arrow { transition: transform var(--dur-fast) var(--ease-out); display: inline-block; }
.btn:hover .arrow { transform: translateX(4px); }
.btn-sm { padding: 12px 20px; font-size: 14px; }
.btn { transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), background var(--dur-med) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease; }

/* ---------- Deal bar / utility ---------- */

.deal-bar {
  background: linear-gradient(90deg, #0ea75a, #22c774);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  padding: 10px 16px;
}
.deal-bar a {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 3px;
  font-weight: 700;
}
.deal-bar a:hover { color: #dcfceb; }

.utility-bar {
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--mute);
  background: var(--bg-deep);
}
/* Matches --container-header (see .site-header .container below) — was
   --container-wide (2026-08-31: was --container + 80px, narrower than the
   page's own wide sections once those widened, leaving header/hero
   visibly inset versus the content below; later the same day, explicit
   request to go past --container-wide too, so the header frames the page
   rather than landing flush with the hero/product-tiles edges). */
.utility-bar .container { width: min(var(--container-header), 100% - 32px); display: flex; align-items: center; justify-content: flex-end; gap: 16px; padding: 10px 0; }
.utility-bar a { color: var(--mute); display: inline-flex; align-items: center; gap: 8px; transition: color var(--dur-fast) ease; }
.utility-bar a:hover, .utility-bar a:focus-visible { color: var(--ink); }
.utility-bar .sep { color: var(--line-strong); font-size: 13px; }
.utility-bar .status-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 3px var(--green-tint);
  flex-shrink: 0;
  position: relative;
}
.utility-bar .status-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1px solid var(--green);
  opacity: 0.6;
  animation: status-ping 2.4s ease-out infinite;
}
@keyframes status-ping {
  0% { transform: scale(0.8); opacity: 0.6; }
  100% { transform: scale(1.9); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .utility-bar .status-dot::after { animation: none; display: none; }
}

/* ---------- Header / nav ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
/* The blur/background live on a pseudo-element behind the header's content,
   not on .site-header itself. Chromium has a known paint-corruption bug
   where an element that is BOTH position: sticky AND backdrop-filter
   repaints in the wrong place on scroll (content vanishes, header appears
   to jump down the page) — layer-promoting the sticky element alone
   (transform: translateZ(0)) does not fix it, since the sticky positioning
   and the filter are still on the same box. Splitting them onto separate
   elements does. Don't merge these back onto one element without
   re-testing a long scroll first. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(4, 9, 30, 0.85);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.site-header.is-scrolled { border-bottom-color: var(--line); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35); }

/* Matches --container-header so the navbar (logo/chat button edges)
   frames the wide page sections below rather than landing flush with
   them (2026-08-31, see .utility-bar .container above). */
.site-header .container { width: min(var(--container-header), 100% - 32px); }

.nav { display: flex; align-items: center; gap: 36px; padding: 17px 0; }

.logo {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-display);
  font-weight: 800; font-size: 25px; letter-spacing: -0.03em;
  color: var(--ink);
  flex-shrink: 0;
  white-space: nowrap;
  transition: opacity var(--dur-fast) ease;
}
.logo:hover { color: var(--ink); opacity: 0.88; }
.logo img { height: 46px; width: auto; }
.logo .logo-web { color: var(--blue-bright); }

.nav-links { display: flex; align-items: center; gap: 6px; list-style: none; margin: 0; padding: 0; }
.nav-links > li > a,
.nav-links button.nav-drop-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 11px 16px; border-radius: 10px;
  color: var(--ink); font-size: 15.5px; font-weight: 550;
  background: none; border: 0;
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease;
}
.nav-links > li > a:hover,
.nav-links button.nav-drop-btn:hover,
.nav-links > li > a:focus-visible,
.nav-links button.nav-drop-btn:focus-visible { background: var(--tint-2); color: var(--ink); }

.nav-drop-btn .chev { transition: transform 0.2s; margin-top: 1px; }
@media (hover: hover) { .nav-drop:hover .chev { transform: rotate(180deg); } }
.nav-drop.is-open .chev { transform: rotate(180deg); }

/* Mega menu */

.nav-drop { position: relative; }

.mega {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  transform: translateY(8px);
  width: min(540px, calc(100vw - 48px));
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 22px;
  box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
}
/* Hover only where a real pointer exists, so a tap on a touch tablet
   (901-1024px still shows the desktop nav) doesn't leave a sticky :hover
   open. Clicks, taps and Enter/Space on the button toggle .is-open from
   main.js (standard disclosure pattern; Escape closes it). Replaces the
   old :focus-within rule, which kept it open after a click with no way
   to dismiss it on touch. */
@media (hover: hover) {
  .nav-drop:hover .mega { opacity: 1; visibility: visible; transform: translateY(0); }
}
.nav-drop.is-open .mega { opacity: 1; visibility: visible; transform: translateY(0); }
.mega::before {
  content: ""; position: absolute; top: -1px; left: 18%; right: 18%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(110, 168, 255, 0.9), rgba(45, 212, 232, 0.9), transparent);
  pointer-events: none;
}

.mega-label {
  grid-column: 1 / -1;
  margin: 0 0 10px;
  font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--faint);
}

.mega-links { display: grid; gap: 6px; align-content: start; }

.mega-item {
  position: relative;
  display: flex; align-items: flex-start; gap: 13px;
  padding: 12px 40px 12px 14px; border-radius: 12px;
  color: var(--ink);
  border: 1px solid transparent;
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
/* small arrow that slides in on hover, so each row reads as a link */
.mega-item::after {
  content: "\2192";
  position: absolute; right: 16px; top: 50%;
  font-size: 15px; line-height: 1; color: var(--blue-bright);
  opacity: 0; transform: translate(-6px, -50%);
  transition: opacity var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out);
}
.mega-item:hover { background: var(--blue-tint); border-color: var(--line); color: var(--ink); }
.mega-item:hover::after { opacity: 1; transform: translate(0, -50%); }
.mega-item .mega-ic {
  flex-shrink: 0;
  width: 38px; height: 38px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--icon-gloss);
  box-shadow: var(--icon-gloss-shadow);
  color: #fff;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) ease;
}
.mega-item:hover .mega-ic { transform: scale(1.08); box-shadow: var(--icon-gloss-shadow), 0 0 18px rgba(110, 168, 255, 0.35); }
.mega-item strong { display: flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 650; color: var(--ink); }
.mega-item small { display: block; font-size: 13px; color: var(--mute); line-height: 1.45; margin-top: 4px; transition: color var(--dur-fast) ease; }
.mega-item:hover small { color: rgba(230, 240, 255, 0.82); }
/* the page you're already on, marked with a slim cyan bar */
.mega-item[aria-current="page"] { background: rgba(255, 255, 255, 0.04); border-color: var(--line); }
.mega-item[aria-current="page"]::before {
  content: ""; position: absolute; left: -1px; top: 14px; bottom: 14px;
  width: 3px; border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--cyan), var(--blue-bright));
  box-shadow: 0 0 10px rgba(45, 212, 232, 0.5);
}
/* coming-soon row stays readable but stops acting like a link */
.mega-item[aria-disabled="true"] { cursor: default; }
.mega-item[aria-disabled="true"]:hover { background: none; border-color: transparent; }
.mega-item[aria-disabled="true"]::after { display: none; }
.mega-item[aria-disabled="true"]:hover .mega-ic { transform: none; box-shadow: var(--icon-gloss-shadow); }
.mega-item[aria-disabled="true"] .mega-ic { opacity: 0.55; }
.mega-item[aria-disabled="true"]:hover small { color: var(--mute); }

/* rows rise in one after another when the menu opens */
.mega-links .mega-item { opacity: 0; transform: translateY(6px); transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, opacity 0.26s ease, transform 0.32s var(--ease-out); }
.nav-drop.is-open .mega-links .mega-item { opacity: 1; transform: none; }
@media (hover: hover) { .nav-drop:hover .mega-links .mega-item { opacity: 1; transform: none; } }
.mega-links .mega-item:nth-child(2) { transition-delay: 0s, 0s, 0.04s, 0.04s; }
.mega-links .mega-item:nth-child(3) { transition-delay: 0s, 0s, 0.08s, 0.08s; }
.mega-links .mega-item:nth-child(4) { transition-delay: 0s, 0s, 0.12s, 0.12s; }
@media (prefers-reduced-motion: reduce) {
  .mega-links .mega-item { opacity: 1; transform: none; transition-delay: 0s; }
}
/* Neutral, matching .soon-badge on the homepage product grid — not the
   green deal-badge treatment, so this never reads as an active sale. */
.mega-item .soon {
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  color: var(--mute);
  border: 1px solid var(--line-strong); background: rgba(255, 255, 255, 0.06);
  border-radius: 999px; padding: 2px 8px;
}

.nav-cta { margin-left: auto; display: flex; align-items: center; gap: 20px; flex-shrink: 0; }
.nav-login {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--ink); font-size: 15.5px; font-weight: 550;
  padding: 11px 14px; border-radius: 10px;
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease;
}
.nav-login:hover, .nav-login:focus-visible { background: var(--tint-2); color: var(--ink); }
.nav-cta .btn-sm { padding: 13px 24px; font-size: 14.5px; border-radius: 10px; }

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  padding: 9px 11px;
  color: var(--ink);
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  /* Uses the shared --section-pad token (2026-09-01) — was its own
     clamp(64-108)/clamp(64-96) values, which meant the hero's own gap to
     Plans below it didn't match the uniform gap used everywhere else;
     explicit feedback that every section-to-section gap sitewide should
     be identical. */
  padding: var(--section-pad) 0;
  overflow: clip;
}
/* Soft glow behind the copy column (2026-08-31) — the mascot side has real
   texture (dot-grid, dual glow, float chips); the copy side was flat empty
   navy by comparison. Low enough opacity to never touch text contrast,
   just enough to make the hero read as one lit space instead of "content
   left, decoration right". */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(720px 520px at 8% 35%, rgba(10, 116, 218, 0.12), transparent 65%);
}
.hero-grid { position: relative; z-index: 1; }

.hero-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(32px, 5vw, 72px);
}

.hero-copy { position: relative; }

/* Faint hairline-grid accent blooming from the hero banner's own top-left
   corner, at the same scale as the hero's existing ambient glow
   (.hero::before's radial-gradient(720px 520px at 8% 35%, ...)) — same
   720x520 ellipse size, anchored at the 0%/0% corner instead so only the
   inner quarter is visible, reading as a texture emanating from the
   corner behind "Your idea, online." rather than a separate decorative
   box. Reused as a mask instead of a color, so the grid pattern only
   ever shows up inside that same soft falloff. Sits directly in .hero
   (not .hero-copy) so it isn't clipped to the narrower text column.
   Tiles reuse the .cta-tile fade-out/fly-off/fly-back mechanic (see that
   comment) but softened, borderless and blue-bright-tinted for this dark
   navy surface — the hero went through an explicit density-reduction
   pass (see CLAUDE.md), so this stays subtle and blended rather than a
   panel-like accent. */
.hero-grid-fx {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(110, 168, 255, 0.12) 1px, transparent 1px),
    linear-gradient(90deg, rgba(110, 168, 255, 0.12) 1px, transparent 1px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(720px 520px at 0% 0%, #000 0%, transparent 65%);
  mask-image: radial-gradient(720px 520px at 0% 0%, #000 0%, transparent 65%);
}
.hero-grid-tile {
  position: absolute;
  width: 26px;
  height: 26px;
  border-radius: 2px;
  background: rgba(110, 168, 255, 0.22);
  box-shadow: 0 0 16px 2px rgba(110, 168, 255, 0.2);
  filter: blur(0.4px);
  /* same 16s cycle as .cta-tile (cta-tile-cycle, see that comment) — kept
     in lockstep so the box/grid mechanic reads at one consistent tempo
     wherever it shows up on the page, rather than a different speed per
     section. */
  animation: cta-tile-cycle 16s ease-in-out infinite;
}
.hero-grid-tile.g1 { top: 52px; left: 52px; --fx: -40px; --fy: -40px; animation-delay: 0s; }
.hero-grid-tile.g2 { top: 130px; left: 104px; --fx: 58px; --fy: -30px; animation-delay: -4s; }
.hero-grid-tile.g3 { top: 78px; left: 182px; --fx: -30px; --fy: 60px; animation-delay: -8s; }
.hero-grid-tile.g4 { top: 182px; left: 52px; --fx: 50px; --fy: 44px; animation-delay: -12s; }
@media (prefers-reduced-motion: reduce) { .hero-grid-tile { animation: none; } }
@media (max-width: 700px) { .hero-grid-fx { display: none; } }

/* 34-52px→38-58px (2026-08-31): a touch more headline confidence,
   matching the taller/bolder rhythm the rest of the page moved to —
   still short enough to hold 2 lines, not 3 (see CLAUDE.md note on why
   this was originally kept smaller than a typical hero). */
.hero h1 {
  position: relative;
  z-index: 1;
  font-size: clamp(38px, 4.2vw, 58px);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.12;
  margin-bottom: 20px;
}
/* the WordPress hero's headline is longer than the homepage's ("Manage your
   WordPress website the easy way" vs "Built to perform under heavy
   traffic") — at the shared clamp it naturally wraps to 3 lines in the
   554px hero-copy column, so this page's h1 gets its own smaller clamp to
   keep it at 2, without touching the homepage's h1 size */
.hero h1.is-compact { font-size: clamp(34px, 3.9vw, 52px); }
/* used on 1-3 key words per headline only — a quiet lift, not a full
   gradient-filled heading */
.hero h1 .grad,
h2 .grad,
h3 .grad {
  background: linear-gradient(100deg, #fff 10%, var(--blue-bright) 55%, var(--cyan) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-sub {
  position: relative;
  z-index: 1;
  font-size: clamp(16px, 1.4vw, 18px);
  color: var(--mute);
  max-width: 50ch;
  margin-bottom: 26px;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; margin-bottom: 30px; }
.hero-actions .btn { padding: 18px 32px; font-size: 16.5px; }

.hero-trust-row { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; margin-bottom: 16px; }

.hero-guarantee { display: flex; align-items: center; gap: 10px; color: var(--mute); }
.hero-guarantee svg { color: var(--green); flex-shrink: 0; }
.hero-guarantee-text { display: flex; flex-direction: column; gap: 2px; }

.hero-rating { display: flex; flex-direction: column; gap: 2px; padding-left: 22px; border-left: 1px solid var(--line); }
.hero-rating-eyebrow { font-family: var(--font-body); font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); }
.hero-rating-value { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-display); font-size: 15px; font-weight: 650; color: var(--ink); }
@media (max-width: 480px) {
  .hero-rating { padding-left: 0; border-left: none; }
}
.hero-stars { display: inline-flex; gap: 1px; color: var(--green); position: relative; top: 1px; }
.hero-stars svg { filter: drop-shadow(0 0 4px rgba(39, 152, 50, 0.45)); }

/* hero visual card — the recurring "featured" gradient, same treatment
   crocweb.com's own hero uses so the mascot's dark shading reads clearly */
.hero-visual {
  /* no card on the real site — the mascot sits directly on the flat page
     background, only the floating stat chips have their own surface */
  position: relative;
  min-height: 480px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
}
.hero-visual img {
  position: relative;
  z-index: 1;
  width: min(317px, 66.6%);
  margin-bottom: 0;
  /* second drop-shadow adds a faint cyan rim-light so the mascot's own edges
     pick up the glow's color instead of the glow feeling separate from it */
  filter: drop-shadow(0 18px 26px rgba(0, 0, 0, 0.5)) drop-shadow(0 0 26px rgba(30, 150, 170, 0.16));
  /* nudged off dead-center so it doesn't read as glued to the middle of
     the column; percentage is relative to the image's own width so the
     shift scales with it at every breakpoint */
  transform: translateX(-6%);
}
/* mascot hop — a playful reaction (2026-09-01): hovering any floating
   stat chip makes the mascot hop, so the chips read as connected to it
   rather than just floating labels nearby. CSS-only via :has(), no JS/GSAP
   — matches the sitewide rule that decorative motion shouldn't depend on a
   script that could fail to load. */
.hero-visual:has(.float-chip:hover) img {
  animation: mascot-hop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes mascot-hop {
  0% { transform: translateX(-6%) translateY(0); }
  15% { transform: translateX(-6%) translateY(3px); }
  45% { transform: translateX(-6%) translateY(-20px); }
  75% { transform: translateX(-6%) translateY(0); }
  88% { transform: translateX(-6%) translateY(-3px); }
  100% { transform: translateX(-6%) translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-visual:has(.float-chip:hover) img { animation: none; }
}
@keyframes mascot-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}
.hero-visual .float-chip {
  position: absolute;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* Slight blue lift top-left added (2026-08-31) — same gloss language as
     .tile-visual/.migration-visual now, instead of a plain flat-navy chip
     sitting apart from that treatment. */
  background:
    radial-gradient(60% 60% at 22% 0%, rgba(10, 116, 218, 0.32), transparent 100%),
    linear-gradient(165deg, rgba(24, 29, 88, 0.85), rgba(6, 9, 36, 0.85));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(10, 116, 218, 0.3);
  border-radius: 13px;
  padding: 11px 15px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--ink);
  box-shadow: var(--shadow-lift), inset 0 1px 0 rgba(255, 255, 255, 0.18), inset 0 -18px 20px -12px rgba(2, 6, 23, 0.65);
  transition: transform var(--dur-med) var(--ease-out), border-color var(--dur-med) ease, box-shadow var(--dur-med) ease;
  /* entrance plays once (fades/slides in), float takes over right after —
     float's own delay is timed to start exactly when that chip's entrance
     finishes, so it never "jumps" from the entrance pose into the loop. */
  animation: chip-in 0.5s cubic-bezier(0.16, 0.84, 0.44, 1) both, chip-float 6.5s ease-in-out infinite;
}
.hero-visual .float-chip:hover {
  border-color: rgba(10, 116, 218, 0.5);
  box-shadow: var(--shadow-lift), var(--shadow-glow-blue), inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -18px 20px -12px rgba(2, 6, 23, 0.65);
}
.hero-visual .float-chip small { display: block; font-weight: 500; color: var(--mute); font-size: 11.5px; }
/* pulled in close to the mascot's silhouette. chip-sites sits right beside
   the raised thumb (pixel-checked against the artwork — the thumb is the
   widest point on that side, ~30% down and touching the image's own right
   edge), so it needs to bleed slightly past .hero-visual's edge to clear it
   without overlapping the arm; .hero's overflow:clip has room to spare. */
.hero-visual .chip-uptime { top: 4%; left: 8%; animation-delay: 0.2s, 0.7s; }
/* -9%→-2% (2026-08-31): the hero container widened to match the rest of
   the page, leaving much less buffer between .hero-visual's edge and the
   real viewport edge — the old -9% bleed now overflowed off-screen at
   common desktop widths. -2% still clears the thumb without going past
   the viewport. */
.hero-visual .chip-sites { top: 24%; right: -2%; animation-delay: 0.6s, 1.1s; }
.hero-visual .chip-speed { bottom: 4%; left: 10%; animation-delay: 1s, 1.5s; }
@keyframes chip-in {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes chip-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-visual .float-chip { animation: none; opacity: 1; transform: none; }
}
.hero-visual .float-chip .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 3px var(--green-tint);
}
.hero-visual .float-chip svg { color: var(--blue); flex-shrink: 0; }

/* hero ambient glow — a soft, steady radial glow behind the mascot
   (::before) plus concentric "target" rings (::after) whose outer ring
   breathes brighter and dimmer on a slow loop, like a radar ring glowing
   rather than sweeping. Both sit behind the mascot (z-index 0); the
   mascot img itself is z-index 1. */
.hero-visual::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  width: min(560px, 86%);
  height: min(560px, 86%);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  /* three-layer glow centered behind the mascot: a small bright hotspot,
     a wider blue-bright → cyan wash, then the sitewide blue-to-navy falloff
     — home hero is shades-only (blue family), no green accent (2026-09-10) */
  background:
    radial-gradient(ellipse 20% 18% at 48% 39%, rgba(150, 195, 240, 0.26) 0%, transparent 70%),
    radial-gradient(ellipse 38% 33% at 48% 42%, rgba(70, 120, 200, 0.2) 0%, rgba(30, 150, 170, 0.12) 45%, transparent 74%),
    radial-gradient(circle, rgba(8, 90, 170, 0.22), rgba(4, 6, 26, 0.34) 55%, transparent 75%);
  box-shadow: var(--shadow-lift);
  pointer-events: none;
  /* brought in line with the box/grid tempo (.cta-tile / .hero-grid-tile,
     both 16s) so the hero's circles and squares breathe at a similar,
     consistent speed rather than visibly different rates — kept a couple
     seconds off .hero-ring-glow below so the two rings still desync
     rather than peaking in perfect unison every cycle. */
  animation: hero-radar-pulse 15s ease-in-out infinite;
}
@keyframes hero-radar-pulse {
  0%, 100% { opacity: 0.75; }
  50% { opacity: 1; }
}
/* concentric rings — the outer ring's border + glow brighten and dim on
   a slow loop; the inner box-shadow ring stays fixed as a quiet anchor */
.hero-visual::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  width: min(340px, 56%);
  height: min(340px, 56%);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  box-shadow: 0 0 0 46px rgba(10, 116, 218, 0.06), 0 0 0 92px rgba(10, 116, 218, 0.04);
  pointer-events: none;
  animation: hero-ring-glow 17s ease-in-out infinite;
}
@keyframes hero-ring-glow {
  0%, 100% { border: 1px solid rgba(10, 116, 218, 0.18); box-shadow: 0 0 0 46px rgba(10, 116, 218, 0.06), 0 0 0 92px rgba(10, 116, 218, 0.04); }
  50% { border: 1px solid rgba(45, 212, 232, 0.26); box-shadow: 0 0 7px 0px rgba(45, 212, 232, 0.14), 0 0 0 46px rgba(10, 116, 218, 0.07), 0 0 0 92px rgba(10, 116, 218, 0.04); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-visual::before { animation: none; opacity: 0.85; }
  .hero-visual::after { animation: none; }
}

/* ---------- WordPress hero — product mockup, not the mascot ----------
   Deliberately distinct from the homepage's .hero-visual (mascot + radar
   rings) so this page doesn't read as a copy-paste of the home hero — it
   opens on what a live WordPress site on CrocWeb actually looks like.
   All rules here are scoped under .hero-mockup so index.html's hero is
   untouched. */
.hero-mockup {
  position: relative;
  min-height: 480px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* nudged up from dead-center so the mockup sits level with the hero
     copy's optical center rather than the taller column's true midpoint */
  transform: translateY(-28px);
}
.hero-mockup::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  width: min(600px, 96%);
  height: min(440px, 88%);
  transform: translate(-50%, -50%);
  border-radius: 60px;
  /* farthest-side (not the "ellipse at center" default of farthest-corner)
     so the gradient's 100% radius matches this box's own half-width/
     half-height independently on each axis. The box is wider than it is
     tall (600x440), so farthest-corner stretched the ellipse toward the
     corners and left the top/bottom edges short of full radius — the
     "transparent 75%" stop never fully finished fading before hitting the
     box boundary there, showing up as a visible rectangular cutoff. */
  background: radial-gradient(ellipse farthest-side at center, rgba(45, 212, 232, 0.2), rgba(10, 116, 218, 0.1) 55%, transparent 75%);
  pointer-events: none;
}
/* Wraps frame + mascot together, sized to the frame's own box (not
   .hero-mockup's taller/wider one). .hero-mockup stays a big flex box so
   its ::before glow keeps its intended size, and centers this stack the
   same way it used to center the frame directly — but the frame is also
   vertically centered *within* .hero-mockup (337px tall inside a 480px
   box), so a mascot positioned by %/bottom against .hero-mockup itself
   was measuring from the wrong edge, off by that ~72px gap, however wide
   the column got. Stack has no height of its own, so it hugs the frame's
   real rendered box exactly, at any width or content height. */
.hero-mockup-stack {
  position: relative;
  width: min(400px, 100%);
}
.hero-mockup-frame {
  position: relative;
  z-index: 1;
  width: min(400px, 100%);
  box-shadow: var(--shadow-lift);
  animation: mockup-float 7s ease-in-out infinite;
}

@keyframes mockup-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-9px); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-mockup-frame { animation: none; }
}

/* small mascot accent, standing beside the mockup with just its raised
   hand grazing the frame's bottom-right corner — keeps the product
   mockup as the focal point while still giving the page some brand
   personality. Sits in .hero-mockup-stack, a sibling of .hero-mockup-frame
   (not nested inside it) — the frame also carries .feature-art, whose
   `overflow: hidden` (needed to clip the mockup's own inner UI content)
   and `.feature-art > * { position: relative }` rule would otherwise clip
   this overhang and silently cancel the mascot's `position: absolute` if
   it were nested inside the frame instead. */
.hero-mockup-mascot {
  position: absolute;
  z-index: 2;
  right: -60px;
  bottom: -110px;
  pointer-events: none;
}
/* same cape-accent green fade as the homepage hero mascot, tucked behind
   the head/shoulder where the cape's collar sits, for consistency */
.hero-mockup-mascot::before {
  content: "";
  position: absolute;
  z-index: 0;
  left: -6%;
  top: 32%;
  width: 60%;
  height: 42%;
  background: radial-gradient(ellipse, rgba(63, 201, 78, 0.18) 0%, rgba(63, 201, 78, 0.06) 45%, transparent 78%);
  filter: blur(10px);
  pointer-events: none;
}
/* fades in while sliding up, timed just after the mockup's own reveal —
   same motion as the homepage's .float-chip entrance (see chip-in), just
   applied via this page's transition-based reveal instead of a keyframe
   animation, so it stays consistent with the rest of this page's reveals */
.hero-mockup-mascot[data-reveal] { transition-delay: 0.25s; }
.hero-mockup-mascot[data-reveal].pre-reveal { opacity: 0; transform: translateY(16px); }
.hero-mockup-mascot img {
  position: relative;
  z-index: 1;
  width: min(132px, 30vw);
}
/* left admin rail (WordPress/Create/Product/Plugins) sitting beside the
   site preview, echoing WordPress's own labeled dashboard sidebar so the
   mockup reads as "inside wp-admin", not just a bare page preview */
.editor-body { display: flex; }
.editor-rail {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 10px;
  background: rgba(255, 255, 255, 0.02);
  border-right: 1px solid var(--line);
  flex-shrink: 0;
}
.rail-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 8px;
  border-radius: 7px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--faint);
  white-space: nowrap;
}
.rail-item.is-brand { color: var(--ink); font-weight: 800; margin-bottom: 6px; }
.rail-item.is-active { background: rgba(255, 255, 255, 0.07); color: var(--blue-bright); }
.rail-ic { width: 18px; height: 18px; display: grid; place-items: center; flex-shrink: 0; }
.rail-item.is-brand .rail-ic { width: 22px; height: 22px; border-radius: 6px; background: var(--blue); color: #fff; }

/* live-site preview, drawn as plain bars/blocks (not literal text) */

.site-preview { width: 100%; flex: 1; min-width: 0; padding: 18px 20px 22px; display: flex; flex-direction: column; gap: 14px; }
.sp-nav { display: flex; align-items: center; gap: 8px; }
.sp-nav .sp-dot { width: 16px; height: 16px; border-radius: 5px; background: var(--blue); flex-shrink: 0; }
.sp-nav span:not(.sp-dot) { height: 7px; border-radius: 4px; background: var(--line-strong); }
.sp-nav .n1 { width: 46px; }
.sp-nav .n3 { width: 30px; margin-left: auto; }
.sp-nav .n2 { width: 30px; }
.sp-hero { display: flex; gap: 14px; align-items: center; padding: 14px; border-radius: 12px; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line); }
.sp-hero-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.sp-hero-text .sp-line { display: block; height: 8px; border-radius: 4px; background: var(--line-strong); }
.sp-hero-text .w1 { width: 90%; height: 11px; }
.sp-hero-text .w2 { width: 65%; }
.sp-hero-text .sp-btn { width: 74px; height: 20px; border-radius: 999px; background: var(--blue); margin-top: 4px; }
/* glossy/glass treatment, same recipe as .btn-primary's gradient + inner
   highlight + glow shadow — so this reads as one of the site's "premium"
   surfaces, not a flat placeholder swatch */
.sp-hero-media {
  width: 84px; height: 64px;
  border-radius: 10px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(155deg, var(--cyan) 0%, var(--blue) 65%, var(--blue-deep) 100%);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), inset 0 -10px 16px -8px rgba(4, 10, 40, 0.35), 0 10px 22px -8px rgba(10, 116, 218, 0.55);
}
.sp-hero-media svg { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.25)); }
.sp-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.sp-card { border-radius: 10px; border: 1px solid var(--line); background: rgba(255, 255, 255, 0.03); padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.sp-card .sp-thumb { height: 26px; border-radius: 6px; background: var(--tint-2); }
.sp-card .sp-line { height: 6px; border-radius: 3px; background: var(--line-strong); }
.sp-card .sp-line.w1 { width: 80%; }
.sp-card .sp-line.w2 { width: 55%; }

/* small "live" pulse in the mockup's fake URL bar — reuses the utility
   bar's status-ping keyframe */
.mockup-url .live-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 2px var(--green-tint);
  position: relative;
  margin-right: 6px;
}
.mockup-url .live-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1px solid var(--green);
  opacity: 0.6;
  animation: status-ping 2.4s ease-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .mockup-url .live-dot::after { animation: none; display: none; }
}

/* block-editor toolbar — the "clear, this is WordPress" signal, reads at a
   glance the way the real block editor's top bar does (insert/edit/undo,
   page label, Save) rather than a generic browser mockup */
.editor-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.02);
  flex-shrink: 0;
}
.et-icons { display: flex; gap: 4px; flex-shrink: 0; }
.et-btn {
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  color: var(--mute);
  background: rgba(255, 255, 255, 0.05);
}
.et-btn.is-accent { background: var(--blue); color: #fff; }
.et-label {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--faint);
  background: rgba(255, 255, 255, 0.04);
  border-radius: 999px;
  padding: 5px 0;
  margin: 0 4px;
}
.et-save {
  flex-shrink: 0;
  background: var(--blue);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 6px 14px;
  border-radius: 999px;
}

/* "selected block" outline + floating format toolbar on the hero heading —
   mirrors the block editor's inline formatting bar so the mockup reads as
   mid-edit, not a static screenshot */
.sp-hero-text.is-selected {
  outline: 1.5px dashed var(--blue-bright);
  outline-offset: 6px;
  border-radius: 6px;
}
.sp-inline-toolbar {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  padding: 4px 9px;
  margin-bottom: 10px;
  font-size: 10px;
  font-weight: 700;
  color: var(--faint);
  box-shadow: var(--shadow-soft);
}
.sp-inline-toolbar svg { color: var(--blue-bright); flex-shrink: 0; }
.sp-inline-toolbar b, .sp-inline-toolbar i { color: var(--mute); font-size: 11px; }

/* trust strip — icon + eyebrow-label + bold-value variant, shared by
   both the home page and the WordPress page (reused verbatim by request).
   Full-bleed wrapper (border spans the whole viewport) with a
   .container-width inner row so the items still line up with the rest
   of the page's content. */
.wp-trust-strip {
  position: relative;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 22px 0;
}
/* No glow (2026-09-01, kept identical to .stats-wrap::after per the "by
   request" pairing noted there) — went through a centered radial glow
   (uneven, favored the middle items), then a top-to-bottom linear fade
   (visible hard split across such a short bar), then a flat uniform
   tint. Removed entirely as the final call: the icon chips already carry
   their own glow and the border-top/bottom already define the bar, so
   the ambient wash wasn't adding anything — explicit feedback that flat
   reads better here. */
.wp-trust-strip::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: none;
}
.wp-trust-strip-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 0;
}
.wp-trust-strip .ts-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 0 22px;
  border-left: 1px solid var(--line);
}
.wp-trust-strip .ts-item:first-child { border-left: none; padding-left: 0; }
.wp-trust-strip .ts-rating-text { gap: 2px; }
.wp-trust-strip .ts-rating-value { display: inline-flex; align-items: center; gap: 6px; font-size: 15px; }
.wp-trust-strip .ts-stars { display: inline-flex; gap: 1px; color: var(--green); position: relative; top: 1px; }
.wp-trust-strip .ts-stars svg { filter: drop-shadow(0 0 4px rgba(39, 152, 50, 0.45)); }
.wp-trust-strip .ts-caption-sub { font-size: 11.5px; font-weight: 500; color: var(--faint); }
.wp-trust-strip .ts-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  border-radius: 11px;
  flex-shrink: 0;
  background: var(--icon-glow);
  box-shadow: var(--icon-glow-shadow);
  color: var(--blue-bright);
}
.wp-trust-strip .ts-text { display: flex; flex-direction: column; gap: 3px; }
.wp-trust-strip .ts-eyebrow { font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); }
.wp-trust-strip .ts-value { font-size: 14px; font-weight: 650; color: var(--ink); }
/* container caps at 1180px once viewport - 48px >= 1180 (~1228px);
   below that the row no longer has room for 5 full-padding items at
   space-between, so switch to a centered, gracefully-wrapping layout
   well before the container itself starts shrinking */
@media (max-width: 1250px) {
  .wp-trust-strip-row { justify-content: center; }
  .wp-trust-strip .ts-item { padding: 0 18px; }
}
@media (max-width: 640px) {
  .wp-trust-strip .ts-item { border-left: none; padding: 0; }
}

/* ---------- Stats row ---------- */
/* one integrated premium container instead of four separate boxes —
   shared glass surface, glow along the top edge, thin dividers between
   metrics so it reads as a single instrument panel */

/* More separation from the hero above (2026-08-31 density pass — trust
   bar was reading cramped right under the hero content). */
/* Bottom spacing now owned by .quick-nav-wrap's own top margin (homepage
   gained a quick-nav below the trust bar, 2026-08-31 — same pattern as
   the WordPress page's #plans, see its .no-pad-top comment), not by this
   wrapper stacking padding on top of it. */
/* Matches .wp-trust-strip exactly now (2026-09-01, explicit request):
   full-width edge-to-edge borders instead of the rounded glass-panel
   look, and the same 22px 0 padding — so the box ends up the same height
   as the WP one too, which is what makes the identical glow recipe below
   actually behave identically instead of bleeding into the hero the way
   it did at the old ~161px height (see git history/prior comment on this
   rule if that math is needed again). */
.stats-wrap {
  position: relative;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 22px 0;
}
/* No glow (2026-09-01, kept identical to .wp-trust-strip::after by
   request) — went through a centered radial glow (uneven, favored the
   middle two stats), then a top-to-bottom linear fade (visible hard
   split across such a short bar), then a flat uniform tint. Removed
   entirely as the final call: the icon chips already carry their own
   glow and the border-top/bottom already define the bar, so the ambient
   wash wasn't adding anything — explicit feedback that flat reads better
   here. */
.stats-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: none;
}
/* Trying the same frosted-glass treatment as .platform-panel/
   .reliability-panel/.compare-card/.switcher here experimentally, per
   explicit request, to see whether it reads as well on a metrics strip as
   it does on those infrastructure panels. Glow toned down from 0.16→0.10
   alpha in the density pass so the surface reads calmer, less "lit up",
   matching the rest of that pass's lower-texture direction. */
/* 2026-08-31 rework, later rebuilt same day to match .wp-trust-strip
   exactly (icons, text style, AND structure/spacing/hover — explicit
   request to stop approximating and reuse the trust bar's own values
   directly). .stats/.stat/.stat-icon/.stat-text/.stat-label/.stat-value
   now mirror .wp-trust-strip/.ts-item/.ts-icon/.ts-text/.ts-eyebrow/
   .ts-value property-for-property; see that block above for the
   canonical version if the two ever need to be reconciled again. */
/* Border/padding removed from here (2026-09-01) — now that .stats-wrap
   (the outer element) carries its own border-top/bottom + padding to
   match .wp-trust-strip exactly, having them here too doubled up as two
   near-adjacent border lines a few px apart. .stats is now just the plain
   flex row, same division of labor as .wp-trust-strip/.wp-trust-strip-row. */
.stats {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 0;
}
.stat {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 0 22px;
  border-left: 1px solid var(--line);
}
.stat:first-child { border-left: none; padding-left: 0; }
.stat-text { display: flex; flex-direction: column; gap: 3px; }
/* Same filled icon-glow chip as .wp-trust-strip .ts-icon — a lit
   rounded-square chip instead of a plain ring, so the two bars stacked on
   this page read as one consistent family rather than two different icon
   languages. Same 40px size as .ts-icon too (was 42px). */
.stat-icon {
  display: inline-flex;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  align-items: center;
  justify-content: center;
  background: var(--icon-glow);
  box-shadow: var(--icon-glow-shadow);
  color: var(--blue-bright);
  flex-shrink: 0;
}
/* One consistent blue for all four, not cycled (2026-08-31, reverted) —
   explicit feedback that the cyan/blue-light rotation read as "icons not
   matching" rather than intentional variety. All four .stat-icon chips
   now inherit the single blue-bright set above, no per-child override. */
.stat-icon svg { width: 18px; height: 18px; }
/* Same font-size/weight/color as .ts-value (14px/650/--ink) — display:flex
   + baseline/gap kept only for the inline unit suffix (12,000 Gbps, 100%,
   24/7), which .ts-value's plain text doesn't need to handle. */
.stat-value {
  font-size: 14px;
  font-weight: 650;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: 2px;
}
/* --blue-bright, not --cyan (2026-08-31) — matches the now-uniform blue
   icon chips above; the unit text is the last stray cyan in the trust bar.
   Fixed 11px rather than an em-relative size (2026-08-31) — at the new
   14px value size, 0.6em would shrink "Gbps"/"%" to ~8px, unreadable. */
.stat-value .unit { color: var(--blue-bright); font-size: 11px; font-weight: 700; margin-left: 2px; }
/* Same uppercase-eyebrow treatment as .wp-trust-strip .ts-eyebrow. */
.stat-label { font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); }

/* ---------- Product tiles (home) ----------
   Replaced the old four-up bordered pricing-card grid (.product-grid/
   .product-card, removed 2026-08-31) with wide, borderless illustrated
   tiles — explicit request to read less like a stacked SaaS card grid and
   more like a wide, image-led layout (reference: Hostinger's "set up the
   essentials" tile row). Section container switched to .container-wide
   (see index.html) so the row gets real room to breathe. Description +
   price are visible by default is wrong — see .tile-details below: they're
   hidden until hover/focus so the resting state stays as clean as the
   reference, while the fuller info (price, discount, blurb) a hosting
   product actually needs is still one interaction away, not lost. */
/* 2026-08-31 rework: merged the four separate floating tiles into one
   shared panel with internal hairline dividers — the same "N boxes → one
   integrated instrument" move already applied to .stats, now applied here
   after repeated "too boxy" feedback on this grid specifically. Each
   column keeps its own accent color/graphic; only the outer edge is
   rounded, matching how the stats bar reads as one strip, not four cards. */
/* Back to one merged panel with hairline dividers (2026-09-02) — the
   separate-cards-with-a-gap version was tried, confirmed to look fine, then
   explicitly reversed ("i mean no gaps") on a second look side by side.
   Border/radius/background/shadow live on this shared outer panel again;
   each .product-tile goes back to being a plain column inside it. */
/* Fully independent per-tile boxes (2026-09-02 rewrite, gap reinstated
   2026-09-05 on explicit request). Every earlier attempt here still tied
   SOME edge — the container's outer left/right border, its box-shadow, its
   bottom corner rounding — to the shared flex container's own height,
   which auto-grows to fit whichever tile is currently tallest. That
   container height changes when ANY tile is hovered, so any edge still
   owned by the container visually "grows" for every tile, not just the one
   that's actually expanded (confirmed via screenshot: the whole panel's
   outer shadow/rounded corners were moving together even though the inner
   divider lines were correctly isolated). The only way for a non-hovered
   tile's border/shadow/corners to never move, full stop, is for each tile
   to own a complete border, shadow and corner radius of its own — nothing
   shared. A real gap between tiles (via flex `gap`) replaces the old
   -1px-margin border-collapse trick, so the four read as separate boxes
   rather than one seamless strip. */
.product-tiles {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}
/* Back to one flat blue for all four tiles (2026-08-31, re-settled) — the
   per-tile cyan/violet accent experiment was tried and explicitly reverted
   again. Each tile's own distinct card (terminal / ring / search dropdown
   / stacked avatars) is doing the "don't all look the same" work now, so
   the background/watermark/glow go back to matching everywhere. */
.product-tile {
  --accent: var(--blue);
  --accent-tint: var(--blue-tint);
  position: relative;
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: rgba(255, 255, 255, 0.015);
  box-shadow: var(--shadow-soft);
}
.product-tile.is-unavailable { cursor: default; }
.product-tile:hover, .product-tile:focus-visible { background: rgba(255, 255, 255, 0.02); }
/* Each tile's own overflow:hidden clips .tile-visual/.tile-label to this
   radius in most browsers, but Safari doesn't reliably clip a
   backdrop-filter child (.tile-visual uses one) through a parent's
   border-radius — explicit radius on the visual/label corners avoids
   square corners peeking out there. */
.tile-visual { border-top-left-radius: var(--radius-xl); border-top-right-radius: var(--radius-xl); }
.tile-label { border-bottom-left-radius: var(--radius-xl); border-bottom-right-radius: var(--radius-xl); }

.tile-visual {
  position: relative;
  /* Taller than the previous 4:3 (2026-08-31) — tiles were reading squat
     next to the taller vertical rhythm used everywhere else on the page. */
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  /* Rebuilt as one smooth diagonal gradient (2026-08-31) — the previous
     recipe layered 4-5 separate radial-gradients, which read as patchy
     blotches rather than one continuous surface. .btn-primary's own gloss
     is a single smooth linear-gradient (bright blue → deep blue); this is
     the same idea, just angled diagonally so it also expresses each
     tile's --accent instead of being identical on every button. */
  /* Down to 2 color stops (2026-08-31, was 4: accent/-20%, blue-deep/20%,
     #12134f/55%, #090a3c/100%). That version had a real, repeatedly-
     reported hard edge roughly halfway across the tile — not a bug in the
     radial glow, but a classic gradient Mach-band: at each explicit stop
     the color's rate-of-change kinks, and the eye reads that slope
     discontinuity as an edge even though the color itself is continuous.
     More stops (even attempts to soften it with a 3rd/4th) just add more
     kinks. A straight 2-stop gradient has exactly one slope for its whole
     run, so there's no internal kink left to see. Same soft radial glow
     on top, anchored top-left opposite where the watermarks bleed off
     bottom-right, using each tile's own --accent-tint. (A 2026-09-05
     attempt to also add the sitewide --dot-grid texture here was tried and
     reverted the same day — explicit "no dots" feedback.) */
  /* Softer contrast (2026-09-10, at user request) — the light stop is a
     blend toward the dark end rather than the full accent color, and the
     dark stop is raised from near-black to a lighter navy, so the
     diagonal reads as a gentler shift rather than a hard light-to-dark
     sweep. Radial glow toned down to match. */
  background: radial-gradient(760px 620px at 10% -25%, color-mix(in srgb, var(--accent-tint) 55%, transparent), transparent 80%), linear-gradient(150deg, color-mix(in srgb, var(--accent) 65%, #12134f), #12134f);
  /* Same dark treatment on every tile at rest; hover/focus is the only
     thing that lights a tile up to full accent blue (2026-08-31) — swapped
     from a permanently-blue "featured" tile after feedback that all 4
     should read identically until interacted with. */
  transition: background 0.5s ease;
  /* Slight glass quality (2026-08-31) — a light blur+saturate, much less
     than the sitewide glass-panel-family's blur(22px) (this is a small,
     already-colorful surface, not a big translucent panel), just enough
     to feel like frosted glass rather than flat printed color. */
  backdrop-filter: blur(6px) saturate(130%);
  -webkit-backdrop-filter: blur(6px) saturate(130%);
  /* Glossy sheen — inset highlight along the top edge (matches
     .btn-primary's own inset highlight recipe) so the tile reads as a lit,
     glossy surface on top of the smooth gradient above. */
  box-shadow: inset 0 -30px 50px -30px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.26), inset 0 24px 40px -28px rgba(255, 255, 255, 0.16);
}
/* Was hardcoded to blue regardless of tile — now that resting state
   varies per tile (--accent), hover has to reference --accent too, or
   tiles 2/3 would flash from cyan/violet to blue right when you touch
   them instead of intensifying their own hue. */
/* Same fix as the resting gradient — a flat run at one color into a
   sloped run to another creates a slope-kink at the point they meet,
   which read as a hard edge. Plain 2-stop gradient instead. */
.product-tile:hover .tile-visual, .product-tile:focus-visible .tile-visual {
  background: linear-gradient(160deg, var(--accent), var(--blue-deep));
}
/* Glowing top-edge line, not a flat solid border (2026-08-31) — same
   language as .cta-block::after's top highlight: fades in from
   transparent, brightest at center, fades back out, rather than a hard
   painted stripe. Uses --accent so it still varies per tile. */
.tile-visual::before {
  content: "";
  position: absolute;
  top: 0; left: 14%; right: 14%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: 0.9;
  z-index: 1;
  transition: background 0.5s ease;
}
.product-tile:hover .tile-visual::before, .product-tile:focus-visible .tile-visual::before {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent);
}
/* Small "open" affordance, top-right — only appears on the hovered tile,
   matching the reference's per-tile arrow-on-hover rather than a static
   icon on every card. */
.tile-visual::after {
  content: "↗";
  position: absolute;
  top: 14px; right: 14px;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(6px);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--dur-med) ease, transform var(--dur-med) var(--ease-out);
  z-index: 2;
}
.product-tile:hover .tile-visual::after, .product-tile:focus-visible .tile-visual::after {
  opacity: 1;
  transform: translateY(0);
}
.product-tile.is-unavailable .tile-visual::after { content: none; }

/* Large brand-icon watermark bleeding past the bottom-right edge — each
   tile's dominant visual, standing in for the photography the reference
   uses (the brand doesn't use stock people/screenshots — see Truthfulness
   rule in CLAUDE.md, so an oversized outline icon fills that same "one big
   image" role instead of a small boxed browser mockup). */
.tile-watermark {
  position: absolute;
  /* 80%→92% (2026-09-05) — at full desktop width the cloud/globe icons
     specifically (thin single-stroke outlines) read much weaker than the
     WordPress circle+W or the reseller layers icon (denser shapes) at the
     same footprint; sizing up gives every icon more presence in the box. */
  width: 92%;
  height: 92%;
  right: -18%;
  bottom: -20%;
  color: var(--accent);
  /* 0.24→0.32 (2026-08-31) — Domains' globe especially was reading too
     faint/washed out against the darker base; bumped resting and hover
     opacity together so every watermark stays legible at a glance.
     0.32→0.4 + a soft drop-shadow glow (2026-09-05) — flat opacity alone
     still read as a faint outline sitting on the surface rather than a
     lit part of it; the glow gives it the same soft-lit quality as the
     mockup chips/rings sitting next to it instead of looking pasted on.
     Also added fill/fill-opacity below the same day — a hollow stroke-only
     outline (cloud, globe) is inherently fainter than a shape with real
     ink coverage (the W-glyph's circle, the reseller layers) at identical
     opacity; a soft translucent fill gives every icon the same solid,
     "designed emblem" weight regardless of how open its outline is. */
  opacity: 0.4;
  fill: currentColor;
  fill-opacity: 0.14;
  filter: drop-shadow(0 0 26px var(--accent-tint));
  transition: transform var(--dur-med) var(--ease-out), opacity var(--dur-med) ease, color 0.5s ease, filter 0.5s ease;
}
.product-tile:hover .tile-watermark, .product-tile:focus-visible .tile-watermark {
  transform: scale(1.06) rotate(-2deg);
  opacity: 0.28;
  color: #fff;
  filter: drop-shadow(0 0 30px rgba(255, 255, 255, 0.35));
}
.tile-visual-domains .tile-watermark { right: -14%; bottom: -26%; width: 84%; height: 84%; }
/* Reseller layers icon (2026-09-05, matches a reference the user supplied)
   — classic interlocking top-diamond + 2 open chevrons, stroke-only (each
   shape sets its own fill="none" to override .tile-watermark's fill above;
   an open chevron auto-closes into a stray triangle if it inherits a real
   fill, which is exactly what went wrong with earlier icon attempts here).
   The reference highlighted its middle band in a second color; tried that
   with var(--blue-bright) here and reverted the same day — explicit "same
   color all boxes" feedback, all three bands just inherit currentColor
   like every other tile's watermark. */

/* Icon "draws itself in" once the tile scrolls into view (2026-08-31) —
   reuses the sitewide [data-reveal]/.pre-reveal pattern already on
   .product-tile itself (see main.js), so no new JS or observer needed.
   Default (no JS / .pre-reveal not yet added) is fully drawn — per the
   Motion rule in CLAUDE.md, content's default state must never be hidden,
   only .pre-reveal is allowed to hide it. 300 is comfortably longer than
   any of these simple 24x24 icon paths, so the exact stroke length
   doesn't need to match per-icon for the "draw in" effect to read right. */
.tile-watermark path, .tile-watermark circle {
  stroke-dasharray: 300;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.6s var(--ease-out);
}
.product-tile.pre-reveal .tile-watermark path,
.product-tile.pre-reveal .tile-watermark circle {
  stroke-dashoffset: 300;
  transition: none;
}

/* One floating glass chip per tile — a single UI accent (icon + short
   label), not a full fake browser window repeated on every card. */
.tile-chip {
  position: absolute;
  left: 16px;
  top: 16px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px 7px 7px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--ink);
  background: rgba(8, 9, 34, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 22px -10px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.1);
  transition: transform var(--dur-med) var(--ease-out), box-shadow var(--dur-med) ease;
}
.tile-chip-icon {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  flex-shrink: 0;
  /* Small glow ring (2026-09-05, toned down same day — full-opacity
     var(--accent) at 10px/1px read as too strong/hard-edged next to the
     rest of the tile's restrained glows) so the icon reads as a lit
     accent, not a flat cut-out circle, without overpowering it. */
  box-shadow: 0 0 6px 0 color-mix(in srgb, var(--accent) 55%, transparent);
}
/* Domains — chip floats centered, echoing the reference's globe+url chip
   sitting in the middle of that tile rather than tucked in a corner. */
/* Centered-chip treatment dropped (2026-08-31) — now that the other three
   chips settled on a consistent top-left position, Domains floating alone
   in the center read as inconsistent rather than intentional. .tile-chip
   base rule (top-left) now applies here too, no override. */
.product-tile:hover .tile-chip, .product-tile:focus-visible .tile-chip { transform: translateY(-3px); }
/* Tried varying tile 2/4's chip to different corners (right/top) —
   reverted back to identical bottom-left per side-by-side comparison;
   Domains' centered chip alone was already enough asymmetry, varying the
   other three too made the row feel scattered rather than intentional. */

/* Reseller hosting — three overlapping account badges standing in for
   "multiple client sites under one login" instead of a literal mockup. */
/* Moved from dead-centered (inset: 0 + centered flex) to sitting just
   under the .tile-chip, top-left (2026-09-05) — every other tile has its
   feature mockup anchored top-left with the big watermark bleeding off
   bottom-right; centering this one broke that rhythm and also left the
   bottom-right corner (where the briefcase watermark now sits) feeling
   like the only "real" content in the box. */
.tile-stack { position: absolute; top: 70px; left: 22px; }
/* Blue/cyan family, not var(--accent) — on tile 4 that would fill two full
   circles with violet, well past "restrained tertiary accent". */
/* Small dollar-sign icon inside each circle now (2026-08-31, revised from
   a browser-window glyph) — plain color-fill circles read as less
   "finished" than the other three tiles' clear representational marks
   (cloud/WP/globe); $ reads more directly as "reseller = revenue" than a
   generic site icon did. */
.tile-stack-badge {
  /* Explicit top/left (2026-09-05) rather than relying on the flex
     container's static-position for an abspos child — that was landing
     the group ~30px higher than the container's own top offset intended,
     which is what overlapped .tile-chip above it. transform still does
     the diagonal stack offset, just from a fixed (0,0) instead of an
     ambiguous flex-computed start. */
  position: absolute;
  top: 0;
  left: 0;
  width: 72px; height: 72px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: rgba(255, 255, 255, 0.85);
  background: linear-gradient(155deg, var(--blue-bright), var(--blue-deep));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), inset 0 -14px 20px -12px rgba(0, 0, 0, 0.3), 0 12px 26px -10px rgba(0, 0, 0, 0.5);
  border: 3px solid rgba(5, 6, 33, 0.9);
  transition: transform var(--dur-med) var(--ease-out);
}
/* Offsets rebased (2026-09-05) for .tile-stack's new top-left anchor above
   — the old -38/0/+38 spread was designed around a container centered by
   inset:0, so it left the group straddling x=0 (badge s1 clipped off the
   tile's left edge once the container moved to top:64/left:22). Shifted
   so the leftmost badge stays a few px inside the box. */
.tile-stack-badge.s1 { transform: translate(4px, 26px); opacity: 0.6; }
.tile-stack-badge.s2 { transform: translate(32px, 4px); opacity: 0.82; z-index: 1; }
.tile-stack-badge.s3 { transform: translate(60px, 26px); opacity: 1; z-index: 2; background: linear-gradient(155deg, var(--blue-bright), var(--blue-deep)); }
.product-tile:hover .tile-stack-badge.s1, .product-tile:focus-visible .tile-stack-badge.s1 { transform: translate(-6px, 26px); }
.product-tile:hover .tile-stack-badge.s3, .product-tile:focus-visible .tile-stack-badge.s3 { transform: translate(70px, 26px); }

/* Fades the tile-visual's own dark gradient stop down into the label
   area (2026-08-31) — the hard border plus the sudden cut from a
   saturated gradient to the panel's near-flat base color read as the
   whole card visibly split in half. This softens that seam without
   touching the gradient itself: a short top-down wash using the same
   dark stop the gradient already ends on, fading out well before the
   description/price text so none of it reads as tinted. */
.tile-label {
  padding: 24px 24px 28px;
  background: linear-gradient(180deg, #090a3c, transparent 55%);
}
/* No longer needed now that each tile is its own separate card (see
   .product-tile) — every tile's overflow:hidden + border-radius clips
   .tile-visual's top corners on all four, not just the outer ones, and
   padding is symmetric since there's no shared panel edge to balance
   against anymore. */
.tile-label h3 { font-size: 18px; font-weight: 800; margin: 0; letter-spacing: -0.01em; }
/* Hidden by default (clean, image-led resting state) — revealed on hover/
   focus so the fuller price + discount + blurb a hosting product needs is
   one interaction away rather than gone. Exactly the original in-flow
   reveal — no new element, no repositioning, no color change. The only
   fix (2026-09-02) is on .product-tiles/.product-tile above: switching
   that row from Grid to Flex with align-items: flex-start means growing
   this tile no longer stretches its siblings to match — each tile keeps
   its own natural height, and only the shared panel's own outer height
   grows to fit whichever tile is tallest right now. A 2026-09-05 attempt to
   make this visible by default was tried and reverted the same day — the
   hover reveal was confirmed fine as-is. */
.tile-details {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height var(--dur-med) var(--ease-out), opacity var(--dur-med) ease, margin-top var(--dur-med) ease;
}
.product-tile:hover .tile-details, .product-tile:focus-visible .tile-details, .product-tile:focus-within .tile-details {
  max-height: 90px;
  opacity: 1;
  margin-top: 8px;
}
/* WordPress Hosting tile — circular install ring (2026-08-31, replaces a
   linear progress bar). Row of boxes was drifting toward "every tile is a
   dark card with a bar or a grid in it" sameness, so this uses a genuinely
   different visualization — a radial/donut gauge, the kind of shape none
   of the other three tiles use (icon list, terminal log, dropdown list).
   Still the same .tile-chip glass/position base, just a row layout instead
   of .tile-chip-tall's stacked one. */
.install-ring-card { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 14px; }
.ir-ring-wrap { position: relative; width: 40px; height: 40px; flex-shrink: 0; }
.ir-ring { width: 40px; height: 40px; transform: rotate(-90deg); overflow: visible; }
.ir-track { fill: none; stroke: rgba(255, 255, 255, 0.16); stroke-width: 4; }
/* Circumference of r=18 is ~113.1; dashoffset ~80.3 draws roughly 29% of
   the ring filled, an arbitrary "install in progress" snapshot — the
   centered % label repeats the same number so the two stay in sync. */
.ir-fill { fill: none; stroke: var(--blue-bright); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 113.1; stroke-dashoffset: 80.3; filter: drop-shadow(0 0 4px color-mix(in srgb, var(--blue-bright) 55%, transparent)); transition: stroke-dashoffset 0.9s var(--ease-out); }
/* Hover/focus "completes the install" — ring fills to 100%, .ir-pct's
   number counts up to match (see main.js, plain rAF, no GSAP dependency
   since this is an instant hover response, not a scroll reveal). Reverses
   on mouseleave/blur back to the resting 29% snapshot. */
.product-tile:hover .ir-fill, .product-tile:focus-visible .ir-fill { stroke-dashoffset: 0; }
.ir-pct { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-display); font-size: 9.5px; font-weight: 800; color: var(--ink); }
.ir-text { display: flex; flex-direction: column; gap: 2px; }
.ir-text strong { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.ir-text span { font-size: 10px; font-weight: 600; color: rgba(255, 255, 255, 0.55); }

/* Web Hosting tile — install log (2026-08-31, replaces the app-icon grid;
   2026-09-05 dropped the browser/terminal chrome — no more traffic-light
   dots, "bash" label, or "$ croc install" prompt line, just the plain
   checkmark list). Keeps the same underlying message — many apps/scripts
   install here — but as a log instead of a static icon grid, so the box
   reads as a different kind of thing than the WordPress ring or Domains
   dropdown, not just different content in an identical card. Monospace
   type is the one deliberate exception to the site's two-font system
   (Manrope/Inter) — kept even without the terminal chrome, still reads as
   "install log" rather than plain body copy. */
.deploy-term {
  position: absolute;
  left: 8%; top: 8%;
  width: 190px;
  border-radius: var(--radius);
  overflow: hidden;
  background: rgba(8, 9, 34, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 22px -10px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.1);
  transition: transform var(--dur-med) var(--ease-out);
}
.product-tile:hover .deploy-term, .product-tile:focus-visible .deploy-term { transform: translateY(-3px); }
.dt-body { padding: 9px 12px 11px; font-family: Consolas, 'Liberation Mono', Menlo, monospace; font-size: 10.5px; line-height: 1.9; }
.dt-body p { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dt-ok { color: rgba(255, 255, 255, 0.55); }
.dt-check { color: var(--green-bright); margin-right: 4px; }
.dt-live { color: var(--ink); font-weight: 600; margin-top: 4px; }
/* Script list — shows a fixed 3-line window at rest (wordpress/joomla/
   drupal, unchanged from before) and scrolls through the fuller install
   library only on hover/focus, echoing the WordPress tile's hover-reveal
   trick without looping ambiently when no one's looking. The track's
   items are listed twice back-to-back in the HTML so translateY(-50%)
   always lands on an exact repeat, same seam trick as .tech-strip-track. */
.dt-scripts { height: 59.85px; overflow: hidden; }
.dt-scripts-track {
  display: flex;
  flex-direction: column;
  animation: dt-scripts-scroll 8s linear infinite;
  animation-play-state: paused;
}
.product-tile:hover .dt-scripts-track, .product-tile:focus-visible .dt-scripts-track {
  animation-play-state: running;
}
@keyframes dt-scripts-scroll {
  from { transform: translateY(0); }
  to { transform: translateY(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .dt-scripts-track { animation: none; }
}

/* Domains tile — live search mockup (2026-08-31). Deliberately a different
   FORM than the Web Hosting/WordPress chips (icon grid, progress bar) —
   not just different content in the same card shape — since the point was
   to break the "every box is a dark card with structured content inside"
   sameness. This one is a mini search box: a typed query with a blinking
   cursor, and a dropdown of live-looking results (2 available, 1 taken),
   the closest CSS-only equivalent to the reference screenshot's floating
   "yourbrand.online" + cursor moment on its own Domains tile. Same
   .tile-chip glass/border/blur recipe as the rest of the row, just shaped
   as a taller dropdown instead of a pill or icon card. */
.domain-search {
  position: absolute;
  left: 8%; top: 8%;
  width: 202px; /* was 190, widened 2026-10-05 so "yourbrand.com" + "$14.87 USD/yr" fits */
  border-radius: var(--radius);
  overflow: hidden;
  background: rgba(8, 9, 34, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 22px -10px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.1);
  transition: transform var(--dur-med) var(--ease-out);
}
.product-tile:hover .domain-search, .product-tile:focus-visible .domain-search { transform: translateY(-3px); }
.ds-input {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 9px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  font-size: 12px;
  font-weight: 650;
  color: var(--ink);
}
.ds-input svg { width: 13px; height: 13px; color: var(--faint); flex-shrink: 0; }
/* Input reads as a generic "domain" placeholder at rest. On hover/focus,
   .ds-rest collapses away and .ds-typed types out "yourbrand" letter by
   letter (a stepped keyframe, one of 9 steps per letter) right behind it,
   so the generic word reads as being swapped for the personalized one.
   The width transition stays in place for the reverse (removing the
   animation on mouseleave just reverts the computed width to the base
   rule, which the transition still smoothly animates back down). */
.ds-rest {
  display: inline-block;
  width: 6ch;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
  transition: width var(--dur-med) var(--ease-out);
}
.product-tile:hover .ds-rest, .product-tile:focus-visible .ds-rest { width: 0; }
.ds-typed {
  display: inline-block;
  width: 0;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
  transition: width var(--dur-med) var(--ease-out);
}
.product-tile:hover .ds-typed, .product-tile:focus-visible .ds-typed {
  animation: ds-type-full 0.8s steps(9, end) forwards;
}
@keyframes ds-type-full {
  to { width: 9ch; }
}
/* Same idea for the result rows below — each starts as "domain.com" /
   "domain.store" / "domain.io" and swaps to "yourbrand" + the same TLD
   in sync with the input above. */
.ds-suffix {
  display: inline-block;
  width: 0;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
  transition: width var(--dur-med) var(--ease-out);
}
.product-tile:hover .ds-suffix, .product-tile:focus-visible .ds-suffix {
  animation: ds-type-full 0.8s steps(9, end) forwards;
}
/* Steady at rest, blinks only while the tile is hovered or focused, as
   an "actively typing" cue (user request 2026-10-05). */
.ds-cursor {
  display: inline-block;
  width: 1.5px;
  height: 12px;
  background: var(--blue-bright);
  margin-left: 2px;
  vertical-align: middle;
}
.product-tile:hover .ds-cursor, .product-tile:focus-visible .ds-cursor {
  animation: ds-cursor-blink 1s step-end infinite;
}
@keyframes ds-cursor-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}
.ds-results { padding: 4px 0; }
.ds-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 7px 10px;
  font-size: 11px;
  font-weight: 600;
}
.ds-row:not(:last-child) { border-bottom: 1px solid rgba(255, 255, 255, 0.06); }
.ds-row .ds-name { color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ds-row .ds-name b { font-weight: 700; color: var(--blue-bright); }
.ds-row.is-available .ds-price { color: var(--green-bright); font-weight: 700; flex-shrink: 0; }
.ds-row .ds-price small { margin-left: 1px; font-size: 0.9em; font-weight: 500; color: var(--mute); }
.ds-row.is-taken { opacity: 0.55; }
.ds-row.is-taken .ds-status { color: var(--faint); font-weight: 600; flex-shrink: 0; }

.tile-desc { color: var(--mute); font-size: 13.5px; line-height: 1.5; margin: 0 0 6px; }
.tile-price { font-family: var(--font-display); font-weight: 800; font-size: 15px; color: var(--ink); margin: 0; }
.tile-price .per { font-family: var(--font-body); font-weight: 500; font-size: 12.5px; color: var(--mute); }
.tile-deal { font-family: var(--font-body); font-weight: 650; font-size: 12px; color: var(--green-bright); margin-left: 6px; }
.tile-deal.is-soon { color: var(--faint); font-weight: 600; }

.deal-badge {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.05em;
  color: var(--green-bright);
  background: linear-gradient(155deg, rgba(63, 201, 78, 0.2), rgba(39, 152, 50, 0.08));
  border: 1px solid rgba(63, 201, 78, 0.28);
  padding: 5px 11px;
  border-radius: 999px;
  margin-bottom: 14px;
}
/* Plan cards (WordPress pricing page): a small discount chip sitting
   roughly level with the plan name, off to the right — the card is
   centered/vertical, so there's no natural inline flow spot for it. */
/* Same top-right spot inside the card as before, now shaped like an
   actual price tag (clip-path notch on the left) rather than a plain
   pill, with a glossy top highlight matching .btn-primary's gradient
   treatment and a two-tier "80% / OFF" hierarchy so the number reads
   first. Kept as a static sheen, not a looping shine — see CLAUDE.md
   CTA-gloss note on why loops were rejected here.
   Base fill is flat var(--green) rather than a --green-bright-led
   gradient — that's the exact hex the trust stars, the 60-day
   guarantee icon, and the checklist checkmarks all use, so the badge's
   dominant green reads as the same "brand green" as those, not a
   brighter/different one. --green-bright is reserved sitewide for
   small text/icon accents, not large fills — keep it out of this
   badge's base color for that reason. */
.plan-card .deal-badge {
  position: absolute;
  top: 32px;
  right: 20px;
  margin-bottom: 0;
  z-index: 2;
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 7px 12px 7px 17px;
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.38) 0%, rgba(255, 255, 255, 0) 45%),
    var(--green);
  border: none;
  border-radius: 7px;
  clip-path: polygon(9px 0, 100% 0, 100% 100%, 9px 100%, 0 50%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.1), 0 8px 18px -6px rgba(39, 152, 50, 0.65);
}
.deal-pct {
  font-family: var(--font-display);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1;
}
.deal-off {
  font-family: var(--font-body);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1;
  color: rgba(255, 255, 255, 0.82);
}

/* ---------- Sections ---------- */

.section { padding: var(--section-pad) 0; position: relative; }
/* No top padding of its own — the quick-nav-wrap directly above (see
   below) owns the vertical rhythm here via equal top/bottom margins, so
   this section's own padding-top would just double up the bottom gap.
   Scoped to this class rather than the bare #plans ID — both pages use
   id="plans" for their own (differently-laid-out) plans section, and the
   ID selector was zeroing out the homepage's #plans top padding too,
   leaving its "Hosting solutions" heading flush against the stats panel
   above it with no gap at all. Only the WordPress page's #plans (which
   actually sits right below .quick-nav-wrap) gets this class. */
.section.no-pad-top { padding-top: 0; }
#plans .section-head { max-width: 820px; }
/* Hairline top/bottom box-shadow removed (2026-08-31) — it painted a hard
   1px seam at every on-tint section's boundary, exactly the "too many
   borders, not smooth section-to-section" feeling flagged. The background
   gradients below already fade in from the section's edges; that's the
   transition now, not a drawn line on top of it. */
.section.on-tint {
  /* The two corner glows are gone (2026-09-01) — repositioning them off
     the literal 0%/100% edge helped but didn't fully remove a visible
     "cut-off" once they were bright enough to notice; any glow that peaks
     inside one section with nothing matching in its neighbor eventually
     reads as an edge. Left with just the linear wash below, which doesn't
     have that problem — it fades from --bg to --tint and back to --bg, so
     both of its ends resolve to the same color the neighboring sections
     already sit on, with nothing left over to look like a seam. */
  background:
    linear-gradient(180deg,
      var(--bg) 0,
      color-mix(in srgb, var(--bg) 55%, var(--tint) 45%) 120px,
      var(--tint) 240px,
      var(--tint) calc(100% - 240px),
      color-mix(in srgb, var(--bg) 55%, var(--tint) 45%) calc(100% - 120px),
      var(--bg) 100%);
}
/* WordPress page's "Included features" section gets its own ambient glow
   (2026-09-01), same recipe/position as .platform-section::before on the
   homepage's Infrastructure section — explicitly requested for this one
   section specifically, sitting between the section-head copy and the
   fm-panel accordion below it. Scoped to the #features ID rather than
   added to .section.on-tint itself, since on-tint is shared with the
   homepage's Migration section, which stays glow-free by its own
   explicit request — this must not leak there.
   Sizing tried smaller/lower (2026-09-01) to guarantee a full fade before
   the top edge on its own — reverted, explicit feedback the original,
   bigger glow looked better. Kept at its original size; the leftover
   brightness at the top edge is now handled differently, by giving
   #plans a matching glow at ITS bottom (see #plans::before below) so
   both sides of the boundary fade toward each other symmetrically
   instead of needing this one glow to disappear entirely on its own.
   Position switched from "14%" to a fixed 100px (2026-09-01) — matches
   #plans::before's own fixed 100px-from-its-edge exactly, so the two
   glows meet at identical brightness at the shared boundary regardless
   of either section's actual height (a % on this side and a fixed px on
   that side would drift apart on any page where the two sections aren't
   proportioned the same way — see #plans::before's comment). */
#features::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(900px 460px at 50% 100px, rgba(10, 116, 218, 0.07), transparent 68%);
}
/* The bottom-of-#plans glow that used to feed into Infrastructure's/
   Features' own top glow was removed 2026-09-01 (explicit request) — back
   to just .platform-section::before / #features::before on their own,
   accepting whatever softness/cut-off that leaves at the boundary rather
   than adding a matching glow on the #plans side to bridge it. */
/* Migration's one-off green-tinted glow (tied to .migrate-arrow's "transfer"
   accent) removed 2026-08-31 — explicit feedback that it read as an
   inconsistency rather than a deliberate color story; #migration now just
   falls through to the standard .section.on-tint recipe above (plain
   linear wash, no corner glows as of 2026-09-01), matching every other
   on-tint section on the page. */
.section.on-dark { position: relative; }
/* --blue-bright, not --cyan (2026-08-31) — this is the reviews section's
   own ambient glow, the last stray cyan actually visible on the home page. */
.section.on-dark::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(760px 420px at 50% 0%, rgba(110, 168, 255, 0.05), transparent 68%);
}

/* Near-black step — deepest surface in the ladder, for sections that need to
   recede rather than glow (signature diagrams read better against less light). */
.section.on-void {
  background:
    radial-gradient(1000px 500px at 85% 0%, rgba(10, 116, 218, 0.06), transparent 60%),
    var(--bg-void);
  box-shadow: inset 0 1px 0 var(--line);
}

/* Bright CrocWeb blue — reserved for one signature moment per page (see
   "Section backgrounds" in CLAUDE.md). Light text, angular fold accent. */
.section.on-blue {
  position: relative;
  background: linear-gradient(155deg, #0f5fc9 0%, var(--blue) 45%, #0a4fa8 100%);
  color: #fff;
  overflow: hidden;
}
.section.on-blue::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--dot-grid) 0 0 / 30px 30px, radial-gradient(700px 420px at 90% 100%, rgba(45, 212, 232, 0.18), transparent 60%);
  opacity: 0.6;
}
.section.on-blue .section-head p, .section.on-blue .mute { color: rgba(255, 255, 255, 0.78); }

/* Rare, carefully-scoped light section for technical-spec content — see
   CLAUDE.md "Use more white space". Dark navy ink on an almost-white surface,
   used at most once or twice sitewide, always transitioning back to dark. */
.section.on-frost {
  background: linear-gradient(180deg, #eef3fb 0%, #e4ecfa 100%);
  color: #0a1440;
}
.section.on-frost .eyebrow { color: var(--blue-deep); }
.section.on-frost .section-head h2 { color: #0a1440; }
.section.on-frost .section-head p { color: #45507a; }

/* Crocodile-scale geometric texture — a subtle, abstract lattice motif, never
   literal skin (see CLAUDE.md "Crocodile-scale brand pattern"). Markup: an
   aria-hidden <span class="scale-layer"> as the last child of a
   position:relative container. Kept as a real element (not a pseudo) so it
   never collides with a section's own ::before/::after decoration. */
.scale-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0.05;
  background-image:
    radial-gradient(circle at 50% 0%, transparent 21px, rgba(255, 255, 255, 0.6) 22px, transparent 23px),
    radial-gradient(circle at 50% 0%, transparent 21px, rgba(255, 255, 255, 0.6) 22px, transparent 23px);
  background-size: 44px 44px, 44px 44px;
  background-position: 0 0, 22px 22px;
}
.section.on-blue .scale-layer, .cta-block .scale-layer { opacity: 0.09; mix-blend-mode: overlay; }
.site-footer .scale-layer { opacity: 0.035; }

/* Quick-nav: pill-shaped jump links to the plans/features/performance/
   AI/FAQ sections. Sticky so it follows scroll like a secondary nav bar —
   sits a deliberate gap below the sticky site-header (--header-h is set in
   main.js from the header's real measured height) rather than flush
   against it. Active state uses solid --blue (same "selected" language as
   buttons/chips) rather than a light-on-dark inversion, since this page
   never puts a light surface behind text. */
.quick-nav-wrap {
  position: sticky;
  /* Resting-state gap: bigger than the original 40px (which read as too
     cramped against the trust bar/plans heading) but deliberately less
     than the full --section-pad token (which turned out too generous once
     seen live — this area doesn't need a full section-to-section gap on
     both sides of a small pill nav). Margin, not padding, so it doesn't
     add to the "stuck" offset below — padding sits inside the sticky box
     and does affect that, margin doesn't (see top: calc, kept tight). */
  top: calc(var(--header-h, 81px) + 8px);
  z-index: 40;
  display: flex;
  justify-content: center;
  margin: clamp(48px, 5vw, 64px) 0;
  padding: 8px 0;
}
/* The horizontal scroll behavior (needed so the pill can scroll sideways
   on narrow viewports) lives on this inner wrapper instead of on
   .quick-nav-wrap itself. overflow-x: auto forces the used value of
   overflow-y to 'auto' too, per spec, which hard-clips anything a
   descendant paints past this box's padding edge — no amount of padding
   fully fixes that, since the clip region is a plain rectangle while the
   pill's shadow is round, so it always showed as a faint rectangular
   smudge under the pill (a real reported bug, not just a fade). Fix: the
   pill itself carries no outward box-shadow any more (only its inset
   highlight, which never overflows its own box and so isn't clipped);
   the outward "lift" and active-pill glow are added here instead as
   filter: drop-shadow(), which — unlike box-shadow — is never clipped by
   this same element's own overflow property. */
.quick-nav-scroll {
  display: flex;
  /* flex-start + margin:auto on .quick-nav (not justify-content:center):
     centered overflow pushed the first link past the left scroll edge on
     phones, where it could never be scrolled back into view */
  justify-content: flex-start;
  overflow-x: auto;
  padding: 4px 24px;
  /* Plain drop shadow, not a glow — matches .site-header.is-scrolled's
     own box-shadow numbers exactly for consistency with the header. */
  filter: drop-shadow(0 6px 24px rgba(0, 0, 0, 0.35));
}
/* Glass, not flat --card — this bar stays stuck across sections with very
   different surfaces behind it (near-black platform diagram, the bright
   --blue CTA block), and a flat navy fill read as a disconnected sticker
   once the CTA's blue scrolled up behind it. The same translucent-dark +
   blur treatment as .float-chip reads as an intentional floating layer on
   any of them instead. */
.quick-nav {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 6px;
  /* Same fill color as .site-header but pushed further toward opaque
     (0.97 vs the header's 0.85) and a stronger blur — matching the raw
     rgba value wasn't enough to read as "the same surface" in practice,
     since the header is a full-width band (opaque corner to corner) while
     this is a small floating pill with page background visible all
     around it, so identical or even moderately higher alpha still looked
     more see-through by contrast. User confirmed: keep the floating pill
     shape, just push opacity/blur further rather than going full-width. */
  background: rgba(4, 9, 30, 0.99);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-radius: 999px;
  /* Matches .site-header.is-scrolled's actual border-bottom color
     (var(--line)) instead of the earlier blue-tinted one, so the two
     sticky bars share the same edge treatment as well as the same fill. */
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
.quick-nav-link {
  padding: 10px 20px;
  border-radius: 999px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  color: var(--mute);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.2s ease, color 0.2s ease;
}
.quick-nav-link:hover { color: var(--ink); background: rgba(255, 255, 255, 0.1); }
/* Same gradient + inner-highlight recipe as .btn-primary, rather than a
   flat --blue fill, so the active pill reads as one of the site's blue
   "buttons" instead of a plain color swap. The outward glow that
   .btn-primary would add via box-shadow is handled by .quick-nav-scroll's
   filter instead (see its comment) so it isn't clipped. */
.quick-nav-link.is-active {
  background: linear-gradient(180deg, #2489ea 0%, var(--blue) 55%, var(--blue-deep) 100%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28);
}

.section-head { max-width: 720px; margin: 0 auto 60px; text-align: center; }
/* .eyebrow already carries its own margin-bottom, but the ".section-head p"
   rule below used to match it too (it's a <p>) and win on specificity,
   collapsing the eyebrow→h2 gap to 0 while h2 kept its larger default
   margin — the three lines never read as evenly spaced. Excluding
   .eyebrow here and setting both gaps explicitly fixes that everywhere
   this section-head pattern is used, not just one section. */
.section-head h2 { font-size: clamp(30px, 3.6vw, 44px); font-weight: 800; margin-bottom: 14px; }
.section-head p:not(.eyebrow) { color: var(--mute); font-size: 17px; margin: 0; }
.section-head .eyebrow { margin-bottom: 14px; }
/* Editorial left-aligned variant — see CLAUDE.md "Stop centering everything".
   Use for roughly a third of section intros so the page has scroll rhythm. */
.section-head.is-left { margin: 0 0 60px; text-align: left; margin-inline: 0; }

/* ---------- Protection flow (homepage "how it works") ---------- */

/* One connected pipeline instead of three floating cards — a continuous
   line runs behind the three stage nodes so the eye reads it as a single
   system traffic moves through, not three independent boxes with arrows
   glued between them. */
.protect-flow {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 20px;
}
.protect-line {
  position: absolute;
  top: 23px;
  left: calc(100% / 6);
  right: calc(100% / 6);
  height: 2px;
  z-index: 0;
  background: linear-gradient(90deg, var(--blue-bright), var(--cyan) 50%, var(--green-bright));
  opacity: 0.32;
}
.protect-pulse {
  position: absolute;
  top: 50%; left: 0;
  width: 7px; height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 10px 2px rgba(255, 255, 255, 0.8);
  opacity: 0;
}
/* Runs once when the section scrolls into view (see main.js), not on a
   continuous loop — traffic "arriving" once reads as a real event; a
   repeating loop reads as decoration and gets tuned out. */
.protect-line.is-active .protect-pulse {
  animation: protect-travel 2.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes protect-travel {
  0% { left: 0; opacity: 0; }
  8% { opacity: 1; }
  92% { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .protect-pulse { display: none; }
}
.protect-stage {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  text-align: left;
  padding: 0;
}
.protect-num {
  display: block;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 800;
  color: var(--faint);
  letter-spacing: 0.08em;
  margin-bottom: 6px;
}
.protect-node {
  width: 46px; height: 46px;
  border-radius: 50%;
  display: grid; place-items: center;
  margin-bottom: 16px;
  background: var(--icon-gloss);
  color: #fff;
  box-shadow: 0 0 0 6px var(--bg-void), inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 6px 16px -4px rgba(10, 116, 218, 0.5);
}
.protect-stage:nth-child(3) .protect-node { background: linear-gradient(155deg, #38c9de, #1a9bb0); box-shadow: 0 0 0 6px var(--bg-void), inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 6px 16px -4px rgba(45, 212, 232, 0.5); }
.protect-stage:nth-child(4) .protect-node { background: linear-gradient(155deg, var(--green-bright), var(--green)); box-shadow: 0 0 0 6px var(--bg-void), inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 6px 16px -4px rgba(39, 152, 50, 0.4); }
.protect-stage h3 { font-size: 19px; margin-bottom: 10px; }
.protect-stage p { color: var(--mute); font-size: 14.5px; line-height: 1.6; margin: 0; max-width: 34ch; }

/* ---------- Plans carousel ---------- */

.plans-carousel { position: relative; }

.plans-track {
  display: flex;
  align-items: stretch;
  gap: 22px;
  overflow-x: auto;
  /* explicit, not just implied by overflow-x — setting overflow-x alone
     computes overflow-y to "auto" per spec, which can surface a vertical
     scrollbar down a card's right edge the instant content is a pixel
     taller than the track. Cards must never scroll internally. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 26px 4px 30px;
  margin: -26px -4px -10px;
  scrollbar-width: none;
}
.plans-track::-webkit-scrollbar { display: none; }

.plans-track .plan-card {
  flex: 0 0 calc((100% - 44px) / 3);
  scroll-snap-align: start;
}

.plans-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--ink);
  display: grid;
  place-items: center;
  box-shadow: var(--shadow-lift);
  transition: background 0.2s, color 0.2s, opacity 0.2s;
}
.plans-nav:hover { background: var(--icon-gloss); border-color: var(--blue); color: #fff; transform: translateY(-50%) scale(1.08); box-shadow: var(--shadow-lift), var(--shadow-glow-blue); }
.plans-nav[disabled] { opacity: 0.35; pointer-events: none; }
.plans-nav.prev { left: -60px; }
.plans-nav.next { right: -60px; }

.plans-dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-top: 18px;
}
.plans-dots button {
  width: 8px; height: 8px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: var(--line-strong);
  transition: background 0.2s, transform 0.2s;
}
.plans-dots button.is-active { background: var(--blue-bright); transform: scale(1.25); }

/* Regular tiers use the same frosted-glass recipe as .product-card/
   .stats/etc (see CLAUDE.md "Glass panel family"). The featured tiers
   (.is-value/.is-popular below) deliberately stay on the opaque
   --feature-gradient solid-blue treatment instead — that's the
   Hostinger-style "lit up" contrast card trick, and it needs to read as
   a different, brighter material than its siblings to work, not blend
   into the same glass as everything else. */
.plan-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 32px 28px 28px;
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(11, 12, 52, 0.6) 0%, rgba(7, 8, 42, 0.6) 55%, rgba(5, 6, 33, 0.6) 100%);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07);
  transition: transform var(--dur-med) var(--ease-out), box-shadow var(--dur-med) var(--ease-out), border-color var(--dur-med) ease, background var(--dur-med) ease;
  /* No overflow: hidden — .plan-flag (the MOST POPULAR badge) deliberately
     straddles the top edge via translate(-50%, -50%), and clipping here
     was cutting its top half off. Nothing else in the card needs
     clipping (the ::before glow line is already inset within the
     border-radius). */
}
.plan-card::before {
  content: "";
  position: absolute;
  top: 0; left: 14%; right: 14%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--blue-bright), transparent);
  opacity: 0.55;
}
.plan-card:hover {
  transform: translateY(-6px);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.22), transparent 70%),
    linear-gradient(165deg, rgba(13, 13, 55, 0.74) 0%, rgba(8, 8, 44, 0.74) 55%, rgba(5, 6, 33, 0.74) 100%);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  border-color: rgba(10, 116, 218, 0.4);
}
/* Plan cards are all one color now — .is-value/.is-popular no longer get
   a distinct lit/elevated background or text treatment, only the
   .plan-flag badge (MOST POPULAR / BEST VALUE) still marks them out. */

.plan-flag {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 6px 14px;
  border-radius: 6px;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 10px 22px -8px rgba(10, 116, 218, 0.6);
}
.plan-flag.popular,
.plan-flag.value {
  background: linear-gradient(180deg, #2489ea 0%, var(--blue) 55%, var(--blue-deep) 100%);
  color: #fff;
}

/* Performance bar — relative resource strength across the 6 plan tiers,
   not a standalone claim: the fill % is derived straight from each plan's
   own stated CPU-core count relative to CloudInfinity's 10 cores (1/10,
   2/10, 4/10... 10/10), so it always agrees with the specs list right
   below it instead of being an invented number. */
/* width, not max-width — this is a flex item with no text content of
   its own, so shrink-to-fit sizing had nothing to measure against and
   collapsed the whole bar to 0 width. An explicit width sidesteps that.
   Full width (not partial) now that the card is left-aligned — a
   partial-width bar flush against the left edge read as a truncated
   element rather than a deliberate meter. */
.plan-power { width: 100%; margin: 16px 0; }
.plan-power-track { height: 6px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); overflow: hidden; }
.plan-power-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--blue), var(--blue-bright)); }

.plan-name {
  font-size: 22px;
  font-weight: 800;
  text-align: left;
  letter-spacing: -0.01em;
  margin-bottom: 2px;
}
.plan-name small {
  display: block;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--mute);
  margin-top: 4px;
}

.plan-price {
  text-align: left;
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.03em;
  margin: 12px 0 4px;
}
.plan-price .per { font-size: 16px; color: var(--mute); font-weight: 500; }

.plan-card .btn { width: 100%; margin: 0; }

.plan-renew {
  text-align: left;
  font-size: 12px;
  color: var(--faint);
  margin: 0 0 28px;
}

.plan-specs-group {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.plan-specs-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--blue-bright);
  margin: 0 0 16px;
}
.plan-specs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 13px;
}
.plan-specs li { display: flex; align-items: center; gap: 12px; font-size: 14.5px; color: var(--mute); }
.plan-specs li strong { color: var(--ink); font-weight: 650; }
.plan-specs svg { flex-shrink: 0; width: 16px; height: 16px; }
.plan-specs .yes { color: var(--ink); }
.plan-specs .no { color: var(--faint); }

/* Domain-term hint — the free domain line's terms (yearly+ plans only)
   aren't obvious from the checklist alone, so the label carries a dotted
   underline and reveals the fine print on hover/focus. The popup itself
   (.spec-hint-tip) is a single shared node living at the end of <body>,
   positioned in JS (see main.js) rather than nested + absolutely
   positioned inside the card — .plans-track scrolls horizontally via
   overflow-x: auto, which per spec forces overflow-y to clip too (see
   that rule's own comment), so anything absolutely positioned inside a
   card gets silently cut off the moment it pokes past the track's box.
   Living in <body> with position: fixed sidesteps that clip entirely. */
.spec-hint {
  position: relative;
  display: inline-block;
  text-decoration: underline dotted currentColor;
  text-underline-offset: 3px;
  cursor: help;
}
.spec-hint-tip {
  position: fixed;
  top: -9999px;
  left: -9999px;
  width: 220px;
  padding: 12px 14px;
  border-radius: 12px;
  background: linear-gradient(165deg, #0c0e33, #07082a);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lift), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  color: var(--mute);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.55;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out);
  z-index: 300;
  pointer-events: none;
}
.spec-hint-tip.is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .spec-hint-tip { transition: none; }
}
/* CPU/Memory/Storage/Inodes get their own resource icon instead of a
   checkmark — they're specs, not a yes/no toggle, so blue (the site's
   standard icon-chip color) reads more accurately than reusing green. */
.plan-specs .ic { color: var(--ink); }
.plan-specs li.excluded { color: var(--faint); }
.plan-specs li.excluded strong { color: var(--faint); font-weight: 500; }

/* Feature-matrix-style category subheads mid-card ("Resources" / "Build
   with" / "Communicate & grow") — reuses .plan-specs-label, just with
   extra top spacing since it's no longer the group's first element. */
.plan-specs-label.is-sub { margin-top: 22px; }
.plan-specs + .plan-specs-label { margin-top: 22px; }

/* ---------- Managed checklist ---------- */

.managed-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.managed-grid h2 { font-size: clamp(28px, 3.4vw, 40px); font-weight: 800; }
.managed-grid > div > p { color: var(--mute); font-size: 16.5px; }

.managed-grid { position: relative; }
.checklist-panel {
  position: relative;
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 3vw, 44px);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  margin-top: 18px;
}
.checklist-panel::before {
  content: "";
  position: absolute;
  top: 0; left: 12%; right: 12%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--blue-bright), var(--cyan), transparent);
  opacity: 0.6;
}
/* small offset badge breaking the panel's top edge — asymmetric detail
   so this section doesn't read as a plain two-column split */
.checklist-badge {
  position: absolute;
  top: -18px;
  right: clamp(20px, 4vw, 44px);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: linear-gradient(155deg, var(--blue-light), var(--blue));
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  padding: 8px 16px;
  border-radius: 999px;
  box-shadow: 0 10px 24px -8px rgba(10, 116, 218, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
@media (max-width: 900px) {
  .checklist-badge { right: 50%; transform: translateX(50%); }
}
.checklist {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 13px 36px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.checklist li { display: flex; align-items: flex-start; gap: 11px; font-size: 14.5px; color: var(--ink); line-height: 1.45; }
.checklist svg { color: var(--green); flex-shrink: 0; margin-top: 2px; }

/* ---------- Feature accordion ("Everything you need for WordPress") ----------
   Was a single 4-column bordered canvas — Management has roughly 2x the
   items of Performance/Security/Development, so all four categories
   sharing one row's height either stretched the short ones (a wall of
   empty space) or forced a fussy 2x2 rebalancing act. An accordion
   sidesteps the problem structurally: one category expands at a time,
   each gets exactly the room its own list needs. Reuses the exact
   <details>/<summary> + .faq-toggle mechanics as the FAQ accordion below
   (native, no JS) rather than inventing a bespoke expand/collapse
   widget — .fm-item / .fm-body are this section's own sizing (full
   container width, not FAQ's centered 800px column). Panels can be open
   independently (no shared `name` grouping) so the .fm-toggle-all button
   can expand/collapse every category at once — a strict one-open-at-a-time
   accordion can't support that. */
.fm-toolbar { display: flex; justify-content: flex-end; margin-bottom: 6px; }
.fm-toggle-all {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px 5px 14px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--mute);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--dur-med) ease, color var(--dur-med) ease, background var(--dur-med) ease, box-shadow var(--dur-med) ease;
}
.fm-toggle-all svg { width: 12px; height: 12px; }
.fm-toggle-all:hover { border-color: var(--blue-bright); color: var(--ink); background: var(--tint-2); }
/* Bright-blue gloss marks the two "everything matches" extremes — nothing
   open yet (.is-all-closed, inviting "Expand all") or everything open at
   once (.is-all-open, inviting "Collapse all"). With just one section
   open, the normal default state, the button stays plain. */
.fm-toggle-all.is-all-closed,
.fm-toggle-all.is-all-open { border-color: var(--blue); background: var(--icon-gloss); box-shadow: var(--icon-gloss-shadow); color: #fff; }
.fm-toggle-all.is-all-closed:hover,
.fm-toggle-all.is-all-open:hover { background: var(--icon-gloss-hover); border-color: var(--blue); color: #fff; }
.fm-toggle-all svg { flex-shrink: 0; transition: transform var(--dur-med) var(--ease-out); }
.fm-toggle-all.is-all-open svg { transform: rotate(180deg); }
.fm-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: start;
}
.fm-head.section-head.is-left { margin: 0; max-width: none; }
.fm-panel { min-width: 0; }
.fm-item {
  border-bottom: 1px solid var(--line);
}
.fm-item:last-child { border-bottom: none; }
.fm-item summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 10px;
  cursor: pointer;
}
.fm-item summary::-webkit-details-marker { display: none; }
.fm-item summary:hover .fm-item-name { color: var(--ink); transform: translateX(4px); }
.fm-item summary:hover .faq-toggle { background: var(--tint-2); color: var(--blue-bright); border-color: rgba(10, 116, 218, 0.4); }
.fm-item summary .faq-toggle {
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--line-strong);
  color: var(--mute);
  transition: transform var(--dur-med) var(--ease-out), background var(--dur-med) ease, border-color var(--dur-med) ease, color var(--dur-med) ease;
}
.fm-item-lead { display: flex; align-items: center; gap: 14px; min-width: 0; }
/* category icon — a content label (Performance/Management/Security/
   Development), not a control, so it stays the same flat chip regardless
   of open/closed state. Only the .faq-toggle chevron — the actual clickable
   control — changes color to signal open/closed. Flat --tint-2 fill (no
   gloss gradient/shadow) to match the homepage migration checklist's
   .migrate-check-icon, per explicit request. */
.fm-icon {
  flex-shrink: 0;
  width: 34px; height: 34px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--tint-2);
  color: var(--blue-bright);
}
.fm-item-name {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  color: var(--mute);
  transition: color var(--dur-med) ease, transform var(--dur-med) var(--ease-out);
}
.fm-item[open] .fm-item-name { color: var(--ink); }
/* Gloss/gradient treatment matches .btn-primary (see Color section of
   CLAUDE.md) rather than the flat solid-blue fill used elsewhere on this
   indicator, per explicit request to make this specific control read
   like the site's main action buttons. */
.fm-item[open] summary .faq-toggle {
  transform: rotate(180deg);
  background: var(--icon-gloss);
  border-color: var(--blue);
  color: #fff;
  box-shadow: var(--icon-gloss-shadow);
}
.fm-item[open] summary:hover .faq-toggle {
  background: var(--icon-gloss-hover);
  color: #fff;
  box-shadow: var(--icon-gloss-shadow);
}
/* With every item open at once (via "Expand all"), four bright chevrons
   stop signaling anything — the highlight moves to the toggle-all button
   instead (see .fm-toggle-all.is-all-open), so drop these back to the
   plain closed look. */
.fm-accordion.is-all-open .fm-item[open] summary .faq-toggle {
  transform: rotate(180deg);
  background: transparent;
  border-color: var(--line-strong);
  color: var(--mute);
  box-shadow: none;
}
.fm-accordion.is-all-open .fm-item[open] summary:hover .faq-toggle {
  background: var(--tint-2);
  border-color: rgba(10, 116, 218, 0.4);
  color: var(--blue-bright);
}
.fm-body {
  padding: 0 10px 26px 62px;
  animation: faq-in var(--dur-med) var(--ease-out);
}
.fm-desc {
  margin: 0 0 18px;
  max-width: 480px;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--mute);
}
.fm-list { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 28px; }
.fm-list li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 14.5px;
  color: var(--ink);
  line-height: 1.45;
  break-inside: avoid;
  margin: 0 0 13px;
  /* cascades in on open instead of the whole list appearing at once —
     nth-child delays below cover up to 11 items (Management, the longest
     category); anything beyond that just inherits the last delay */
  opacity: 0;
  animation: fm-item-in var(--dur-med) var(--ease-out) forwards;
  animation-delay: 0.24s;
}
.fm-list li:nth-child(1) { animation-delay: 0.03s; }
.fm-list li:nth-child(2) { animation-delay: 0.06s; }
.fm-list li:nth-child(3) { animation-delay: 0.09s; }
.fm-list li:nth-child(4) { animation-delay: 0.12s; }
.fm-list li:nth-child(5) { animation-delay: 0.15s; }
.fm-list li:nth-child(6) { animation-delay: 0.18s; }
.fm-list li:nth-child(7) { animation-delay: 0.21s; }
.fm-list li:nth-child(8) { animation-delay: 0.24s; }
.fm-list li:nth-child(9) { animation-delay: 0.27s; }
.fm-list li:nth-child(10) { animation-delay: 0.30s; }
.fm-list li:nth-child(11) { animation-delay: 0.33s; }
@keyframes fm-item-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
/* small hover cue on each feature so the list reads as touchable content,
   not flat static text — dot brightens and gets a soft ring, text goes
   full-bright ink (list items already sit at --ink, but the transition
   keeps this consistent with how the rest of the accordion responds) */
.fm-list li:hover .fm-dot { background: var(--green-bright); box-shadow: 0 0 0 4px var(--green-tint); }
.fm-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--green); flex-shrink: 0; margin-top: 9px; transition: background var(--dur-fast) ease, box-shadow var(--dur-fast) ease; }
@media (max-width: 900px) {
  .fm-layout { grid-template-columns: 1fr; }
  .fm-list { columns: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .fm-body { animation: none; }
  .fm-list li { opacity: 1; animation: none; }
}
@media (max-width: 560px) {
  .fm-list { columns: 1; }
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--blue-bright);
  margin-bottom: 12px;
}
.eyebrow.is-center { justify-content: center; }
/* WordPress hero kicker reads as a normal sentence line (like the
   reference), not a small label — bigger, regular weight, with just the
   discount figure bolded/colored */
.hero .eyebrow.is-large {
  position: relative;
  z-index: 1;
  font-size: clamp(15px, 1.35vw, 18px);
  font-weight: 500;
  letter-spacing: normal;
  color: var(--mute);
  margin-bottom: 16px;
}
.hero .eyebrow.is-large strong { color: var(--blue-bright); font-weight: 800; }

.feature-art {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  /* Dot-grid middle layer removed (2026-09-05) — this base rule is always
     overridden by .hero-mockup-frame.feature-art.has-mockup in current
     markup (the only place .feature-art is actually used), so the dots
     never render today, but dropping them here too means reusing this
     class bare in the future can't reintroduce a dotted background. */
  background:
    radial-gradient(360px 260px at 70% 15%, rgba(10, 116, 218, 0.22), transparent 70%),
    linear-gradient(180deg, var(--tint-2), var(--tint));
  display: grid;
  place-items: center;
  color: var(--blue-bright);
  box-shadow: var(--shadow-soft);
}
.feature-art > * { position: relative; z-index: 1; }

.ai-checklist { grid-template-columns: 1fr; gap: 10px; margin: 20px 0 28px; }

/* ---------- Launch or switch ---------- */

.switcher {
  position: relative;
  /* frosted-glass surface, matching .reliability-panel/.compare-card/
     .platform-panel rather than the opaque --card-gradient other cards
     use, so this section keeps the same glass-panel concept as the
     performance/reliability section right above it. */
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(11, 12, 52, 0.6) 0%, rgba(7, 8, 42, 0.6) 55%, rgba(5, 6, 33, 0.6) 100%);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  overflow: hidden;
}
.switcher::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 0;
  left: 20%;
  right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(45, 212, 232, 0.4), transparent);
  pointer-events: none;
}
.switcher-tabs, .switcher-panel { position: relative; z-index: 1; }
/* Tabs sit inset from the panel edges with their own border-radius,
   same "floating pill inside a glass bar" recipe as .quick-nav/
   .quick-nav-link, rather than flush full-bleed buttons. Flush tabs meant
   a hover/active fill ran edge-to-edge into the panel's own rounded
   corner and outer border — at the top-right corner in particular, the
   hover wash sat directly against the panel's translucent white border,
   washing it out. Insetting avoids touching that border at all. */
.switcher-tabs {
  display: flex;
  gap: 6px;
  padding: 10px;
  border-bottom: 1px solid var(--line);
}
.switcher-tab {
  flex: 1;
  padding: 14px 20px;
  background: transparent;
  border: 0;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 650;
  color: var(--mute);
  transition: background 0.2s ease, color 0.2s ease;
}
/* same gradient + inner-highlight recipe as .quick-nav-link.is-active —
   this is a tab control just like that one, so the active state should
   read with the same confident "this is the current selection" blue
   instead of the previous flat dark-shade swap, which barely contrasted
   against the inactive tab. */
.switcher-tab.is-active {
  background: linear-gradient(180deg, #2489ea 0%, var(--blue) 55%, var(--blue-deep) 100%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
/* translucent wash, not the flat --tint-2 fill used elsewhere — .switcher
   is a glass surface now (see above), and a solid opaque hover color read
   as a mismatched block breaking the glass. Same rgba(255,255,255,0.1)
   recipe as .quick-nav-link:hover, which is the established hover-on-glass
   pattern in this system. */
.switcher-tab:not(.is-active):hover { color: var(--ink); background: rgba(255, 255, 255, 0.1); }

.switcher-panel {
  display: none;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  align-items: center;
  gap: clamp(28px, 4vw, 56px);
  padding: clamp(32px, 4vw, 52px);
}
.switcher-panel.is-active { display: grid; }
.switcher-copy h3 { font-size: clamp(22px, 2.6vw, 30px); font-weight: 800; margin: 0 0 14px; }
.switcher-copy p { color: var(--mute); font-size: 15.5px; margin-bottom: 22px; }
.switcher-art { display: flex; align-items: center; justify-content: center; }

/* "Starting fresh" visual — a self-playing demo (bordered outline, no fill,
   not the browser-chrome .feature-art treatment, since this isn't a literal
   UI screenshot). A tiny cursor "clicks" the Install pill, the bar fills,
   and the final step lights up, then the whole thing loops. Icon states
   otherwise reuse the two-set icon language: done = green check,
   in-progress = the toned --icon-glow chip, not the bright button gloss —
   except .install-btn itself, which really does depict a clickable button
   being pressed. */
.install-visual {
  width: 100%;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: clamp(28px, 3.5vw, 40px);
  /* a recessed dark panel, not another copy of the lighter --card-gradient
     the outer .switcher already uses — reads as "a screen set into the
     card" instead of a border drawn on top of an identical surface. */
  background: rgba(2, 6, 23, 0.32);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.install-mockup { display: flex; flex-direction: column; gap: 15px; width: 100%; max-width: 280px; margin: 0 auto; }
.install-step { display: flex; align-items: center; gap: 11px; font-size: 13px; font-weight: 650; color: var(--mute); }
/* every step shares one checkmark icon — pending is just that icon hidden
   inside a muted dot; "completing" is a background + opacity flip to
   green, timed per step (see keyframes below) instead of four different
   glyphs, so the story reads through color/motion rather than icon count.

   One 18s timeline, played once per loop: a brief idle, then the cursor
   slowly, smoothly slides onto the Install button and clicks it
   (~0.7s–4.3s), the bar fills gradually (~5.4s–10.4s), each step's check
   fades in softly as it's reached, everything holds fully complete for
   5s (~13s–18s), then resets to replay. All the per-element keyframes
   below share this exact 18s/100% timeline so they stay in lockstep —
   treat the percentages as one shared clock, not independent loops. A
   gentle custom easing (slow start, slow finish) is used on the motion/
   fill animations rather than the default ease-in-out, for a softer feel. */
.install-icon {
  width: 20px; height: 20px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  background: var(--tint-2);
  color: #fff;
  transition: background 0.7s ease;
}
.install-icon svg { opacity: 0; transition: opacity 0.7s ease; }
.install-step.is-done .install-icon { background: var(--green); }
.install-step.is-done .install-icon svg { opacity: 1; }

.install-step-click .install-icon { animation: install-check-bg-a 18s ease-in-out infinite; }
.install-step-click .install-icon svg { animation: install-check-icon-a 18s ease-in-out infinite; }
.install-step-progress .install-icon { animation: install-check-bg-b 18s ease-in-out infinite; }
.install-step-progress .install-icon svg { animation: install-check-icon-b 18s ease-in-out infinite; }
.install-step-final .install-icon { animation: install-check-bg-c 18s ease-in-out infinite; }
.install-step-final .install-icon svg { animation: install-check-icon-c 18s ease-in-out infinite; }
@keyframes install-check-bg-a { 0%, 24% { background: var(--tint-2); } 30%, 99% { background: var(--green); } 100% { background: var(--tint-2); } }
@keyframes install-check-icon-a { 0%, 24% { opacity: 0; } 30%, 99% { opacity: 1; } 100% { opacity: 0; } }
@keyframes install-check-bg-b { 0%, 56% { background: var(--tint-2); } 62%, 99% { background: var(--green); } 100% { background: var(--tint-2); } }
@keyframes install-check-icon-b { 0%, 56% { opacity: 0; } 62%, 99% { opacity: 1; } 100% { opacity: 0; } }
@keyframes install-check-bg-c { 0%, 64% { background: var(--tint-2); } 70%, 99% { background: var(--green); } 100% { background: var(--tint-2); } }
@keyframes install-check-icon-c { 0%, 64% { opacity: 0; } 70%, 99% { opacity: 1; } 100% { opacity: 0; } }

.install-progress { height: 5px; border-radius: 999px; background: var(--tint-2); margin-left: 31px; overflow: hidden; }
.install-progress-fill { display: block; height: 100%; width: 0%; border-radius: 999px; background: linear-gradient(90deg, var(--blue), var(--blue-bright)); animation: install-fill 18s cubic-bezier(0.45, 0, 0.15, 1) infinite; }
@keyframes install-fill {
  0%, 30% { width: 0%; }
  58%, 99% { width: 100%; }
  100% { width: 0%; }
}

.install-action { position: relative; display: inline-flex; align-items: center; margin-left: auto; }
.install-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--icon-gloss);
  box-shadow: var(--icon-gloss-shadow);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  animation: install-btn-press 18s ease-in-out infinite;
}
@keyframes install-btn-press {
  0%, 23%, 30%, 100% { transform: scale(1); }
  26.5% { transform: scale(0.88); }
}
.install-cursor {
  position: absolute;
  right: 4px;
  bottom: -8px;
  color: var(--ink);
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
  animation: install-cursor-click 18s cubic-bezier(0.45, 0, 0.15, 1) infinite;
}
@keyframes install-cursor-click {
  0%, 5% { opacity: 0; transform: translate(34px, -26px); }
  /* slow, deliberate slide onto the button over ~3.4s */
  24% { opacity: 1; transform: translate(0, 0); }
  26.5% { opacity: 1; transform: translate(-1px, 1px); }
  30%, 100% { opacity: 0; transform: translate(0, 0); }
}

/* "Already have a website?" visual — a two-node transfer diagram, same
   dashed-arrow node-to-node language as the reliability panel's .p-diagram
   art, now with the same bordered outline as .install-visual (no fill) so
   the two switcher panels read as a matched pair rather than one framed
   and one floating. */
.migrate-visual {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 100%;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: clamp(28px, 3.5vw, 40px);
  background: rgba(2, 6, 23, 0.32);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.migrate-mockup { display: flex; align-items: center; justify-content: center; gap: 14px; }
.migrate-node { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.migrate-node-icon {
  width: 44px; height: 44px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--tint-2);
  border: 1px solid var(--line-strong);
  color: var(--faint);
}
.migrate-node.is-target .migrate-node-icon {
  background: var(--icon-glow);
  box-shadow: var(--icon-glow-shadow);
  color: var(--blue-bright);
  border-color: transparent;
  /* gentle pulse — reads as "receiving" the incoming transfer */
  animation: migrate-pulse 2.6s ease-in-out infinite;
}
@keyframes migrate-pulse {
  0%, 100% { box-shadow: var(--icon-glow-shadow); }
  50% { box-shadow: var(--icon-glow-shadow), 0 0 0 7px rgba(10, 116, 218, 0.14); }
}
.migrate-node-label { font-size: 12.5px; font-weight: 650; color: var(--mute); }
.migrate-node.is-target .migrate-node-label { color: var(--ink); }
/* green rather than the blue used everywhere else on this diagram —
   deliberately echoes the install checklist's green checkmarks on the
   other switcher panel, and pulls the eye to the transfer itself as its
   own accent moment instead of blending into the surrounding blue icon
   boxes. Compared side by side against blue before making this call. */
.migrate-arrow { color: var(--green-bright); flex-shrink: 0; opacity: 0.85; }
/* the connecting line "flows" toward CrocWeb; the arrowhead is a separate,
   static path so only the line itself animates */
.migrate-arrow-line {
  stroke-dasharray: 4 4;
  animation: migrate-flow 0.9s linear infinite;
}
@keyframes migrate-flow { to { stroke-dashoffset: -8; } }
.migrate-note { text-align: center; font-size: 12px; color: var(--faint); margin: 14px 0 0; }

/* ---------- Performance comparison ---------- */

.compare-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 22px;
}
.compare-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* frosted-glass surface, matching .reliability-panel/.platform-panel
     above rather than the opaque --card-gradient other cards use, so this
     row reads as part of the same glass panel instead of a style change
     mid-section. */
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(11, 12, 52, 0.6) 0%, rgba(7, 8, 42, 0.6) 55%, rgba(5, 6, 33, 0.6) 100%);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-lg);
  padding: clamp(28px, 3vw, 36px);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}
.compare-card::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 0;
  left: 20%;
  right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(45, 212, 232, 0.4), transparent);
  pointer-events: none;
}
.compare-card > * { position: relative; z-index: 1; }
.compare-card h3 { font-size: 19px; font-weight: 800; margin-bottom: 12px; }
.compare-card p { font-size: 14.5px; color: var(--mute); margin: 0; line-height: 1.6; }
/* visual now sits below the heading/copy (leads with the claim, then
   backs it up), so the gap belongs above it, not trailing after — this
   is exactly the swap, not an add: no other .compare-visual rule changed.
   margin: auto 0 (both top and bottom, not just top) — .compare-card is
   a flex column, so this centers the visual within whatever leftover
   space is left after the heading/paragraph, splitting it between the
   gap-above and gap-below instead of dumping all of it into one spot.
   A top-only auto margin (tried first) equalized the bottom gap between
   the two cards perfectly, but since the cards' paragraphs are genuinely
   different lengths, all *that* leftover space landed entirely above the
   shorter card's visual — 71px there vs. 22px on the other card, which
   read as an even more obvious mismatch than the original trailing-space
   issue. Centering can't make both gaps equal across cards (the content
   heights genuinely differ), but it keeps each card internally balanced
   instead of concentrating the imbalance in one visible band. */
.compare-visual {
  display: flex;
  align-items: center;
  gap: 20px;
  margin: auto 0;
  padding-top: 22px;
}

.compare-ring-group { display: flex; flex-direction: column; align-items: center; gap: 9px; flex-shrink: 0; }
.compare-ring {
  --size: 76px;
  position: relative;
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  flex-shrink: 0;
  background: conic-gradient(var(--green) calc(var(--pct) * 1%), var(--tint-2) 0);
  display: grid;
  place-items: center;
  /* pops in + settles on scroll reveal, see .compare-card.pre-reveal below —
     conic-gradient's own %-fill isn't cheaply animatable without registering
     --pct via @property, so the "reveal" reads through scale+glow instead */
  transition: transform var(--dur-med) var(--ease-out), opacity var(--dur-med) var(--ease-out);
}
/* soft ring-colored glow behind the score — same restrained accent-glow
   language as the rest of the page, kept small so it doesn't compete */
.compare-ring::after {
  content: "";
  position: absolute;
  inset: -10px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(63, 201, 78, 0.22), transparent 72%);
  z-index: -1;
}
.compare-ring::before {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  background: var(--card);
}
.compare-ring-val {
  position: relative;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 18px;
  color: var(--ink);
}
/* matches .backup-label's plain sentence-case treatment (the timeline
   labels in the other card) instead of its own uppercase/letter-spaced
   caption style, so the two cards' small text reads the same way */
.compare-ring-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--mute);
}
/* what's actually behind the 96 — real technologies already named in this
   card's own paragraph (LSCache, Redis) plus facts used elsewhere on the
   page (NVMe storage, QUIC.cloud CDN in the feature matrix), not invented
   filler. flex:1 + wrap, not a single narrow column — a column is only
   ever as wide as its longest tag regardless of how many stack, which
   left a dead gap between it and the card's right edge; wrapping into a
   row lets the tags actually claim the remaining width. */
.compare-tags { display: flex; flex-wrap: wrap; align-content: center; gap: 8px; flex: 1; }
/* same blue-tint pill recipe as .compare-restore-label in the other card
   (border+tint+bright text) — these were still on the old plain gray chip
   style from before that pass, which read as flat/inconsistent next to
   the other card's colorful chip in the same section */
.compare-tag {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid rgba(10, 116, 218, 0.35);
  background: var(--blue-tint);
  font-size: 12px;
  font-weight: 650;
  color: var(--blue-bright);
  white-space: nowrap;
}

/* card reveal grows the ring in, so the score visibly settles into place
   instead of just fading in flat with the rest of the card (data-reveal
   already fades/slides .compare-card itself; this adds a second, scoped
   motion layer on top of that) */
.compare-card.pre-reveal .compare-ring { transform: scale(0.55); opacity: 0; }
/* tags settle in just after the ring, sliding in from the right (the
   direction they sit in) instead of popping in flat with nothing to
   distinguish them from the ring's own reveal */
.compare-tag { opacity: 1; transform: translateX(0); transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out); }
.compare-card.pre-reveal .compare-tag { opacity: 0; transform: translateX(10px); }
.compare-tags .compare-tag:nth-child(1) { transition-delay: 0.15s; }
.compare-tags .compare-tag:nth-child(2) { transition-delay: 0.21s; }
.compare-tags .compare-tag:nth-child(3) { transition-delay: 0.27s; }
.compare-tags .compare-tag:nth-child(4) { transition-delay: 0.33s; }
@media (prefers-reduced-motion: reduce) {
  .compare-card.pre-reveal .compare-ring,
  .compare-card.pre-reveal .compare-tag { transform: none; opacity: 1; }
}

/* second compare-card stacks its visual + caption instead of sitting them
   side by side in the default row — a wide 4-point timeline needs its own
   full line, with the restore caption underneath, not squeezed to one side */
.compare-visual.is-stacked { flex-direction: column; align-items: stretch; gap: 14px; }
/* backup timeline, reused inside the second compare-card — base
   .backup-timeline/.backup-point/etc. rules (below, under "Backup
   timeline") are sized for the old full-width centered section; only the
   620px cap needs dropping here since .is-stacked already gives this the
   card's full ~500px inner width, plenty of room for four labels */
.compare-visual .backup-timeline { max-width: none; width: 100%; margin: 0; padding-top: 2px; }
.compare-visual .backup-point.is-current .backup-dot { box-shadow: 0 0 0 4px var(--blue-tint); }
/* the ring "pops in" on reveal (above); the timeline gets its own matching
   entrance instead of just sitting there flat — the line draws left to
   right and the four points land in sequence just behind it, like the
   history is being plotted rather than pasted in as one flat image */
.backup-line { transform-origin: left center; transition: transform 0.7s var(--ease-out); }
.compare-card.pre-reveal .backup-line { transform: scaleX(0); }
.backup-point { opacity: 1; transform: translateY(0); transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out); }
.compare-card.pre-reveal .backup-point { opacity: 0; transform: translateY(6px); }
.compare-visual .backup-point:nth-child(2) { transition-delay: 0.12s; }
.compare-visual .backup-point:nth-child(3) { transition-delay: 0.22s; }
.compare-visual .backup-point:nth-child(4) { transition-delay: 0.32s; }
.compare-visual .backup-point:nth-child(5) { transition-delay: 0.42s; }
.compare-restore-label { opacity: 1; transform: translateY(0); transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out); transition-delay: 0.5s; }
.compare-card.pre-reveal .compare-restore-label { opacity: 0; transform: translateY(6px); }
@media (prefers-reduced-motion: reduce) {
  .compare-card.pre-reveal .backup-line,
  .compare-card.pre-reveal .backup-point,
  .compare-card.pre-reveal .compare-restore-label { transform: none; opacity: 1; }
}
/* .compare-visual-scoped selector, not just .compare-restore-label alone —
   needs to out-specificity the generic .compare-card p (element+class)
   rule above, which otherwise wins and flattens this to plain --mute text.
   Same chip recipe as the site's other blue pills (border+tint+bright
   text) so this reads as one more instance of an existing pattern. */
.compare-visual .compare-restore-label {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 9px 12px;
  border-radius: 9px;
  background: var(--blue-tint);
  border: 1px solid rgba(10, 116, 218, 0.35);
  font-size: 12.5px;
  font-weight: 650;
  color: var(--blue-bright);
}
.compare-restore-label svg { flex-shrink: 0; }

/* ---------- Security / platform row ---------- */

/* 2026-08-31: dropped the glass-panel wrapper entirely (border/background/
   blur/padding) — following the Cloudflare reference's plain, un-boxed
   feature row (icon + heading + copy directly on the page, no card around
   routine content; a boxed surface is reserved for actual signature
   moments like the CTA block, not every section). The section's own
   padding now does the job the panel's interior padding used to. */
.section.platform-section {
  padding: var(--section-pad) 0;
  position: relative;
}
/* Ambient glow restored (2026-09-01, re-added) — briefly removed entirely
   when it looked like the culprit for the section-boundary cut-offs, but
   the actual cause turned out to be `body`'s own background-attachment:
   fixed glow (see body's comment) staying pinned to the viewport instead
   of scrolling with the page. With that fixed, this section-local glow
   scrolls normally like everything else and doesn't create the "moving
   with me" effect, so it's safe to bring back — explicitly scoped to just
   this section, not restored on .section.on-tint (Migration/WP features),
   which stays glow-free by request.
   Sizing tried smaller/lower (2026-09-01) to guarantee a full fade before
   the top edge on its own — reverted, explicit feedback the original,
   bigger glow looked better. See #plans::before for how the leftover
   brightness at the shared boundary is handled instead: a matching glow
   at the bottom of #plans (the section right before this one on both
   pages), so both sides fade toward each other instead of one side
   needing to disappear entirely alone. Position switched from "14%" to a
   fixed 100px, same reasoning/value as #features::before just above — so
   both pages' Products→Infrastructure(or Features) boundary meet at
   identical brightness regardless of each #plans section's actual
   height. */
.section.platform-section::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(900px 460px at 50% 100px, rgba(10, 116, 218, 0.07), transparent 68%);
}

.platform-panel-copy { text-align: center; position: relative; z-index: 1; }
.platform-panel-copy .eyebrow { justify-content: center; font-size: 14.5px; }
/* Matches the standard section-headline scale (2026-09-01) — was its own
   smaller clamp(26-36px) "sub-section" size, but explicit feedback that
   every section's main title should read the same regardless of layout;
   the WordPress page's equivalent paired copy+visual section (Performance)
   already uses the full-size scale, so this brings Infrastructure in
   line with that too. */
.platform-panel-copy h2 {
  font-size: clamp(30px, 3.6vw, 44px);
  margin-bottom: 16px;
}
.platform-panel-copy .lede {
  max-width: 640px;
  margin: 0 auto 56px;
  font-size: 16px;
  line-height: 1.65;
  color: var(--mute);
}
.platform-features {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 44px;
}
.platform-feature { position: relative; text-align: left; display: flex; gap: 20px; align-items: flex-start; padding-right: 44px; }
/* Thin hairline between columns — same "connect items in a row" language
   as .stat, instead of three columns floating with no relationship to
   each other (2026-08-31 pass). */
.platform-feature:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 4px; bottom: 4px; right: 0;
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--line-strong) 15%, var(--line-strong) 85%, transparent);
}
.platform-feature-copy { flex: 1 1 auto; min-width: 0; }
/* Filled glow chip, not a ring (2026-09-01) — the previous comment here
   claimed this matched .stat-icon's treatment, but .stat-icon is actually
   the filled --icon-glow chip (same recipe as .wp-trust-strip .ts-icon),
   so the ring was a real, if long-standing, mismatch rather than a
   deliberate variant. Now uses the exact same --icon-glow/--icon-glow-
   shadow/radius recipe as the stats bar and trust strip, so all three
   icon rows on the page finally read as one consistent chip style. */
.platform-feature .p-icon {
  width: 40px; height: 40px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  background: var(--icon-glow);
  box-shadow: var(--icon-glow-shadow);
  color: var(--blue-bright);
}
/* One consistent blue for all three icons + diagrams, not cycled
   (2026-08-31, reverted) — same "icons don't match" feedback as the trust
   bar. --p-accent still exists as a hook (see .p-diagram) but every
   feature now leaves it at the default blue-bright fallback. */
.platform-feature .p-icon svg { width: 18px; height: 18px; }
.platform-feature-copy h3 { font-size: 17.5px; font-weight: 800; margin-bottom: 12px; }
.platform-feature-copy p { font-size: 14.5px; color: var(--mute); margin: 0 0 18px; line-height: 1.65; }
/* tiny per-feature technical graphic — a restrained CSS/SVG diagram, not a
   literal illustration, so the reliability panel reads as infrastructure
   rather than three text columns (see brief: "RELIABILITY VISUAL TREATMENT"). */
.p-diagram {
  display: block;
  width: 100%;
  max-width: 168px;
  height: auto;
  margin-top: 16px;
  color: var(--p-accent, var(--blue-bright));
  opacity: 0.85;
}

@media (max-width: 720px) {
  .platform-features { grid-template-columns: 1fr; }
}

/* ---------- Migration (home) ----------
   Redesigned 2026-09-01 from reference screenshots the user provided
   (a competitor's "move to X" section + a separate support section) —
   content follows those screenshots closely per explicit request ("use
   the same content for now, I will modify it later"). Two things were
   corrected rather than copied verbatim since they're not stylistic
   choices: the competitor's own brand name in the headline became
   CrocWeb, and its real US phone number/"US-based" claim in the Support
   section below became CrocWeb's actual Canadian number and "Canada-
   based" (see Brand section — CrocWeb is a Canadian host). The stat
   numbers (500K+ sites moved, 2m average migration time, etc.) are still
   the reference's placeholder figures, not verified CrocWeb numbers —
   flagged to the user as needing real figures before this ships, per the
   sitewide Truthfulness rule. .migrate-mockup/.migrate-node/.migrate-arrow
   (no longer used here) stay in dark.css — wordpress-hosting.html's own
   migration panel still uses them. */
.migration-grid {
  display: grid;
  /* Visual (intro text + CTA) first, copy (checklist) second — 2026-09-01,
     swapped from copy-left/visual-right per explicit request. Column
     widths swapped along with the DOM order so the text-heavy side keeps
     the wider column regardless of which side it's on.
     align-items: start — explicit request to keep the intro block pinned
     to the top (level with the checklist's first row) rather than
     vertically centered against the taller column; the shorter left
     column just ends earlier, which is fine. */
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: start;
  gap: clamp(32px, 5vw, 64px);
}
/* Intro text lives in the visual column alongside the CTA button
   (2026-09-01) — left-aligned per explicit request (not centered); the
   gap to the button below it comes from justify-content: space-between
   on .migration-visual now, not a fixed margin. */
.migration-intro { text-align: left; width: 100%; }
/* Explicit font-size (2026-09-01) — this rule only set margin-bottom
   before, so with no .section-head wrapper here the h2 fell through to
   the bare h1-h4 base rule (no font-size at all) and rendered at the
   browser's unstyled default (~24px) instead of the sitewide section-
   headline scale every other h2 on both pages uses. Matches
   .section-head h2 exactly. */
.migration-intro h2 { font-size: clamp(30px, 3.6vw, 44px); font-weight: 800; margin-bottom: 16px; }
.migration-intro .lede { color: var(--mute); font-size: 16px; line-height: 1.65; margin-bottom: 20px; }
.migration-intro .pill-green { margin-bottom: 0; }

/* Shared small green pill (badge icon/dot + label) — used by the migration
   "up to 5 sites free" callout and each Support card's "Available now"
   tag, so the two new sections read as one family instead of inventing a
   fresh pill style per section. */
.pill-green {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(39, 152, 50, 0.12);
  border: 1px solid rgba(39, 152, 50, 0.3);
  color: var(--green-bright);
  font-size: 12.5px;
  font-weight: 650;
  margin: 0 0 26px;
}
.pill-green svg { flex-shrink: 0; }
.pill-green .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green-bright); flex-shrink: 0; }

.migrate-check-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 28px; }
.migrate-check-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 15px 18px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.02);
}
.migrate-check-icon {
  flex-shrink: 0;
  width: 34px; height: 34px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--tint-2);
  color: var(--blue-bright);
}
.migrate-check-title { font-family: var(--font-display); font-weight: 700; font-size: 14.5px; color: var(--ink); margin: 0 0 2px; }
.migrate-check-desc { font-size: 13px; color: var(--mute); margin: 0; line-height: 1.45; }

/* Visual column now holds only the intro text — the concentric-ring
   stat callout ("2m" then "Free Unlimited Migrations") was removed
   2026-09-01 in favor of folding that same claim into the badge pill
   above ("Free Unlimited Migrations"); that diagram's other copy (files,
   database, email transfer) already lives in the check rows' "All
   content preserved" item. */
.migration-visual {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 28px;
}

@media (max-width: 860px) {
  .migration-grid { grid-template-columns: 1fr; text-align: center; }
  .migration-copy .lede { margin-inline: auto; }
  .migrate-check-row { text-align: left; }
}

/* ---------- Support ----------
   New section, 2026-09-01, from the same reference pass as Migration
   above — three cards using the established --card-gradient/solid-icon-
   chip pattern (see Components → Cards/Icon chips in CLAUDE.md) rather
   than the reference's plain white cards, so it reads as this site's
   card treatment, not a copy-pasted screenshot. */
.support-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.support-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(28px, 3vw, 34px);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.support-card-icon {
  width: 46px; height: 46px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--blue);
  color: #fff;
  margin-bottom: 18px;
}
.support-card h3 { font-size: 20px; font-weight: 800; margin: 0 0 10px; }
.support-card p { font-size: 14.5px; color: var(--mute); line-height: 1.6; margin: 0 0 20px; }
.support-card-link {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14.5px;
  color: var(--blue-bright);
  text-decoration: none;
}
.support-card-link .arrow { transition: transform var(--dur-med) var(--ease-out); }
.support-card-link:hover .arrow { transform: translateX(3px); }

@media (max-width: 900px) {
  .support-cards { grid-template-columns: 1fr; }
}

/* ---------- Testimonials ---------- */

.reviews-section.on-dark::before { content: none; }

/* Translucent, not the old flat opaque --card-flat fill (2026-08-31
   consistency pass) — the rest of the page moved to glass/translucent
   surfaces or no surface at all, and a solid flat rectangle here was the
   one thing left reading as a hard-edged box among softer neighbors. */
.review-card {
  --accent: var(--blue-bright);
  --accent-tint: var(--blue-tint);
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  padding: 34px 30px 28px;
  background: linear-gradient(165deg, rgba(11, 12, 52, 0.55) 0%, rgba(7, 8, 42, 0.55) 55%, rgba(5, 6, 33, 0.55) 100%);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  overflow: hidden;
  transition: transform var(--dur-med) var(--ease-out), border-color var(--dur-med) ease, box-shadow var(--dur-med) ease, background var(--dur-med) ease, opacity 1.4s ease;
}
.review-card:hover {
  transform: translateY(-6px) scale(1.015);
  border-color: rgba(255, 255, 255, 0.2);
  box-shadow: var(--shadow-lift), 0 0 0 1px var(--accent-tint), 0 22px 40px -20px var(--accent-tint);
}
/* soft colored glow along the top edge, cycled per card via --accent */
.review-card::after {
  content: "";
  position: absolute;
  top: 0; left: 14%; right: 14%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: 0.75;
}
.review-card::before {
  content: "\201C";
  position: absolute;
  top: 14px; right: 22px;
  font-family: Georgia, serif;
  font-size: 64px;
  line-height: 1;
  color: var(--accent-tint);
  opacity: 0.7;
  pointer-events: none;
  transition: opacity var(--dur-med) ease;
}
.review-card:hover::before { opacity: 1; }
.review-stars { display: flex; gap: 3px; color: var(--green); margin-bottom: 16px; }
.review-stars svg { filter: drop-shadow(0 0 5px rgba(39, 152, 50, 0.45)); }
.review-card blockquote { position: relative; margin: 0 0 22px; font-size: 15.5px; line-height: 1.65; color: var(--ink); }
.review-who { margin-top: auto; font-size: 14px; display: flex; align-items: center; gap: 10px; }
.review-who::before {
  content: attr(data-initials);
  width: 34px; height: 34px;
  border-radius: 50%;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.92);
  background: linear-gradient(155deg, var(--accent), var(--blue-deep));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 0 3px var(--accent-tint);
  transition: background var(--dur-med) ease, box-shadow var(--dur-med) ease;
}
.review-who .name { font-weight: 700; color: var(--ink); display: block; }
.review-who .via { color: var(--faint); display: inline-flex; align-items: center; gap: 5px; }
.review-who .via::before {
  content: "";
  width: 12px; height: 12px;
  flex-shrink: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23EA4335' d='M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z'/%3E%3Cpath fill='%234285F4' d='M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z'/%3E%3Cpath fill='%23FBBC05' d='M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z'/%3E%3Cpath fill='%2334A853' d='M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z'/%3E%3C/svg%3E");
  background-size: contain;
  background-repeat: no-repeat;
}
/* cycle the four established brand accents across the cards so identically
   styled boxes still read as varied, not a repeated stamp — same accent set
   as .product-card, see Color section in CLAUDE.md. This is the no-JS/
   fallback order; JS re-assigns --accent per card at random once it runs. */
/* Blue shades only, no cyan/violet (2026-08-31) — matches main.js's own
   accents array and the sitewide "one blue family" rule. */
.reviews-stage article.review-card:nth-of-type(4n+2) { --accent: var(--blue-light); --accent-tint: var(--blue-tint); }
.reviews-stage article.review-card:nth-of-type(4n+3) { --accent: var(--blue); --accent-tint: var(--blue-tint); }
.reviews-stage article.review-card:nth-of-type(4n+4) { --accent: var(--blue-deep); --accent-tint: var(--blue-tint); }

/* Reviews "wall" — the heading sits at the top as normal text; a handful of
   reviews scatter underneath it (up/down/left/right within that lower
   zone, at random sizes), re-picked fresh on every page load (see
   main.js). Because the heading is in normal flow above the scatter zone
   rather than centered inside it, cards can never collide with it — no
   collision math needed, just keep them inside their own zone. No-JS /
   narrow-viewport fallback is a plain, fully visible wrapped row of all 10
   cards so content is never hidden by default. Full-bleed (outside
   .container) so wide screens give the scatter real room to spread. */
.reviews-stage {
  position: relative;
  margin-top: clamp(20px, 3vw, 28px);
  padding-inline: clamp(24px, 6vw, 96px);
}
.reviews-cards {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px;
  margin-top: 36px;
}
.reviews-stage .review-card { width: 300px; }
/* Matches var(--section-pad) now (2026-08-31 consistency pass) — was a
   smaller, different clamp than every neighboring section, breaking the
   page's vertical rhythm right at the one seam (Migration → Reviews)
   that most needed to feel continuous. */
.reviews-section { padding: var(--section-pad) 0; }

@media (min-width: 1100px) {
  .reviews-stage.is-scattered { padding-inline: clamp(24px, 4vw, 72px); }
  .reviews-stage.is-scattered .reviews-cards {
    position: relative;
    display: block;
    height: 320px;
    margin-top: 36px;
  }
  .reviews-stage.is-scattered .review-card {
    --jx: 0px; --jy: 0px; --jr: 0deg;
    position: absolute;
    width: auto;
    opacity: 0.9;
    transform: translate(var(--jx), var(--jy)) rotate(var(--jr));
  }
  .reviews-stage.is-scattered .review-card:hover {
    opacity: 1;
    z-index: 4 !important;
    transform: translate(var(--jx), var(--jy)) translateY(-8px) scale(1.04) rotate(0deg);
  }
  /* Sized to comfortably clear the 25%-spaced lanes above even at the
     narrow end of the "show 4" range (see pickCountFor in main.js) — a
     wider "lg" here is what was silently capping real placements below 4
     on typical laptop-width full screens. */
  .reviews-stage.is-scattered .review-card.size-sm { width: 200px; padding: 20px 18px 18px; }
  .reviews-stage.is-scattered .review-card.size-sm blockquote { font-size: 13px; margin-bottom: 14px; }
  .reviews-stage.is-scattered .review-card.size-sm .review-stars svg { width: 13px; height: 13px; }
  .reviews-stage.is-scattered .review-card.size-md { width: 240px; }
  .reviews-stage.is-scattered .review-card.size-lg { width: 280px; padding: 30px 26px 24px; }
}

/* ---------- FAQ ---------- */

.faq-list { max-width: 800px; margin: 0 auto; display: grid; gap: 12px; }
.faq-item {
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  overflow: hidden;
  transition: border-color var(--dur-med) ease, box-shadow var(--dur-med) ease;
}
.faq-item[open] { border-color: rgba(10, 116, 218, 0.35); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 0 0 1px rgba(10, 116, 218, 0.12); }
.faq-item summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 19px 22px;
  font-weight: 650;
  font-size: 15.5px;
  cursor: pointer;
  transition: background var(--dur-fast) ease;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { background: var(--tint-2); }
.faq-item[open] summary { background: rgba(10, 116, 218, 0.08); }
.faq-item summary .faq-toggle {
  flex-shrink: 0;
  width: 26px; height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--tint-2);
  color: var(--mute);
  transition: transform var(--dur-med) var(--ease-out), background var(--dur-med) ease, color var(--dur-med) ease;
}
.faq-item[open] summary .faq-toggle { transform: rotate(135deg); background: var(--icon-gloss); box-shadow: var(--icon-gloss-shadow); color: #fff; }
.faq-item .faq-body {
  padding: 0 22px 20px;
  color: var(--mute);
  font-size: 15px;
  animation: faq-in var(--dur-med) var(--ease-out);
}
.faq-item .faq-body p:last-child { margin-bottom: 0; }
@keyframes faq-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .faq-item .faq-body { animation: none; }
}

/* ---------- Big CTA block ---------- */

.cta-block {
  position: relative;
  overflow: hidden;
  /* --blue base, no looping sweep/fade (client feedback: no fade/glow
     loop) — but now with a static glossy sheen, matching the frosted-glass
     highlight language of .platform-panel: a soft white radial highlight
     near the top plus an inset top highlight in the box-shadow below, sat
     on top of the grid of hairline squares. See .cta-tiles for the
     squares that fade out and fly back in to refill a cell.
     Highlight shrunk and pulled further above the panel (720x340 at -12%
     → 560x200 at -30%) and grid alpha trimmed 0.14→0.08 (2026-09-03) so
     the sheen stays a thin cap at the top edge instead of tinting the
     whole card lighter — the body of the panel now reads as the same
     flat --blue as the homepage product tiles. */
  background-image:
    radial-gradient(560px 200px at 50% -30%, rgba(255, 255, 255, 0.16), transparent 62%),
    linear-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.08) 1px, transparent 1px);
  background-color: var(--blue);
  background-position: 0 0, 0 0, 0 0;
  background-size: 100% 100%, 28px 28px, 28px 28px;
  background-repeat: no-repeat, repeat, repeat;
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.32);
  color: #fff;
  /* Uses the shared --section-pad token (2026-09-01) — see .hero comment,
     same sitewide-consistency request. */
  padding: var(--section-pad) 0;
  /* inset as a rounded island rather than full-bleed, so the corners read —
     matches --radius-xl used on the site's other largest surfaces (stats/platform panels) */
  width: min(var(--container-wide), 100% - 48px);
  margin-inline: auto;
  border-radius: var(--radius-xl);
}
/* faint glowing line at the top edge, same touch as .platform-panel::after */
.cta-block::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 0;
  left: 20%;
  right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  pointer-events: none;
}
/* faint network routes + nodes — the same visual language as the hero,
   so the CTA reads as distinctly CrocWeb (infrastructure/network) rather
   than a generic blue promo band */
.cta-links {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  opacity: 0.5;
  pointer-events: none;
}
.cta-links path { stroke-dasharray: 2.5 5; }
.cta-node {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.25), 0 0 14px rgba(255, 255, 255, 0.6);
  animation: node-pulse 3.4s ease-in-out infinite;
  pointer-events: none;
}
.cta-node.cn1 { top: 20%; left: 8%; animation-delay: 0s; }
.cta-node.cn2 { top: 78%; left: 94%; animation-delay: 1.2s; }
.cta-node.cn3 { top: 14%; left: 90%; animation-delay: 2.4s; }
@media (prefers-reduced-motion: reduce) { .cta-node { animation: none; } }
@media (max-width: 700px) { .cta-links, .cta-node { display: none; } }
/* Ten cells OF the background grid itself (not decorative shapes on top
   of it) each continuously cycle: hold blended into the mosaic — same
   28px size, same fill as a filled grid cell — then fade out in place
   (the exact gap left behind reads as a missing background square),
   jump invisibly to a spot just outside the panel, then fly back into
   that exact same grid-aligned spot and hold again. Positioned in px
   (not %) at multiples of 28 from the panel's top-left, matching
   .cta-block's own background-position: 0 0 above, so a tile's resting
   spot is pixel-identical to one of the background's own grid cells —
   this is what makes it read as "a square of the background" rather
   than an object floating over it. Pure CSS @keyframes, no JS
   dependency. Each shares the same 9s cycle with a different negative
   animation-delay so they desync immediately — at any moment two or
   three are mid-fade/mid-flight rather than the whole grid blinking in
   unison. .cta-block's overflow:hidden clips the off-panel position, so
   the fly-in reads as sliding from behind the panel's rounded edge. */
.cta-tiles {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.cta-tile {
  position: absolute;
  width: 28px;
  height: 28px;
  background: rgba(255, 255, 255, 0.24);
  border: 1px solid rgba(255, 255, 255, 0.3);
  animation: cta-tile-cycle 16s ease-in-out infinite;
}
@keyframes cta-tile-cycle {
  0%, 50% { opacity: 1; transform: translate(0, 0); }
  /* long, gradual fade instead of a quick snap — the gap should ease
     into view, not blink */
  66% { opacity: 0; transform: translate(0, 0); animation-timing-function: ease-in; }
  /* same instant as the step above but relocated off-panel — opacity is
     already 0 here so the jump itself is invisible */
  66.1% { opacity: 0; transform: translate(var(--fx), var(--fy)); animation-timing-function: ease-out; }
  /* gentle deceleration into the landing spot, no bounce/overshoot —
     smoother read than a springy snap */
  95%, 100% { opacity: 1; transform: translate(0, 0); }
}

.cta-tile.t1 { top: 56px; left: 56px; --fx: -200px; --fy: -130px; animation-delay: 0s; }
.cta-tile.t2 { top: 56px; left: 280px; --fx: -100px; --fy: -170px; animation-delay: -1.6s; }
.cta-tile.t3 { top: 84px; left: 560px; --fx: 40px; --fy: -190px; animation-delay: -3.2s; }
.cta-tile.t4 { top: 56px; left: 840px; --fx: 210px; --fy: -130px; animation-delay: -4.8s; }
.cta-tile.t5 { top: 168px; left: 28px; --fx: -230px; --fy: 20px; animation-delay: -6.4s; }
.cta-tile.t6 { top: 196px; left: 980px; --fx: 230px; --fy: 0px; animation-delay: -8s; }
.cta-tile.t7 { top: 280px; left: 112px; --fx: -190px; --fy: 130px; animation-delay: -9.6s; }
.cta-tile.t8 { top: 252px; left: 392px; --fx: -60px; --fy: 190px; animation-delay: -11.2s; }
.cta-tile.t9 { top: 280px; left: 644px; --fx: 60px; --fy: 190px; animation-delay: -12.8s; }
.cta-tile.t10 { top: 252px; left: 896px; --fx: 200px; --fy: 130px; animation-delay: -14.4s; }

@media (prefers-reduced-motion: reduce) {
  .cta-tile { animation: none; }
}
/* was 700px; between 701-1024 the squares landed on the centered headline */
@media (max-width: 1024px) { .cta-tiles { display: none; } }
.cta-block-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  align-items: center;
  gap: clamp(24px, 4vw, 64px);
}
/* no mascot on this page's CTA — a single centered column reads cleaner
   than an off-balance two-column grid with empty space on one side */
.cta-block-grid.is-centered {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
}
.cta-block-grid.is-centered > div { max-width: 760px; }
.cta-block h2 {
  color: #fff;
  font-size: clamp(28px, 3.6vw, 44px);
  font-weight: 800;
  margin-bottom: 14px;
}
.cta-block p { color: rgba(238, 246, 255, 0.92); font-size: 17px; margin-bottom: 30px; max-width: 46ch; }
.cta-block-grid.is-centered p { margin-inline: auto; }
.cta-block .btn { padding: 18px 32px; font-size: 16px; }
.cta-mascot { position: relative; display: flex; align-items: center; justify-content: center; }
.cta-mascot::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 260px;
  height: 260px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(5, 10, 38, 0.6), rgba(5, 10, 38, 0.3) 60%, transparent 78%);
  pointer-events: none;
}
/* grounding shadow at the mascot's feet so it reads as standing in the
   scene rather than pasted on top of it */
.cta-mascot::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 6%;
  width: 150px;
  height: 26px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(2, 8, 30, 0.4), transparent 75%);
  pointer-events: none;
}
.cta-mascot img { position: relative; width: min(230px, 66%); filter: drop-shadow(0 14px 22px rgba(0, 0, 0, 0.4)); animation: mascot-float 6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .cta-mascot img { animation: none; } }

/* ---------- Tech strip ---------- */

/* Explicit smaller padding (2026-09-01) — briefly used the shared
   --section-pad token for sitewide consistency (see .hero comment), but
   that's sized for a full content section (heading + cards); this is a
   single thin line of marquee badges, and the full 93.6px on both sides
   read as a bare, disproportionate gap around something this minimal.
   Symmetric 48px both sides (an asymmetric 24px/48px split was tried and
   reverted — explicit request to keep 48px on top too). Deliberately NOT
   using --section-pad here, unlike every other actual section on the
   page. */
.tech-strip { padding: 48px 0; text-align: center; }
.tech-strip-label {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0 0 26px;
}
/* Badge copy is now full sentences that can't fit a static row at any
   width (the old grid/wrap approach this replaced), so the strip
   auto-scrolls left in a continuous marquee instead. The HTML duplicates
   the badge list once (second copy `aria-hidden`); spacing lives on each
   badge's own margin-right rather than a parent flex `gap` so
   translateX(-50%) always lands on an exact seam — with `gap` the seam is
   off by half a gap-width and the loop visibly jumps once per cycle.
   The row itself clips overflow and masks its edges so badges fade in/out
   instead of clipping hard against the container. Vertical padding on the
   row (not just the track) gives the badge hover state — translateY(-2px)
   plus its glow shadow — room inside the clip box; without it the lift
   pushes a hovered badge's top edge past overflow:hidden and it visibly
   clips. */
.tech-strip-row {
  overflow: hidden;
  width: 100%;
  padding: 12px 0;
  mask-image: linear-gradient(90deg, transparent, #000 64px, #000 calc(100% - 64px), transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 64px, #000 calc(100% - 64px), transparent);
}
.tech-strip-track {
  display: flex;
  width: max-content;
  animation: tech-marquee 75s linear infinite;
}
@keyframes tech-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .tech-strip-track { animation: none; }
  .tech-strip-row { overflow-x: auto; mask-image: none; -webkit-mask-image: none; }
}
.tech-badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 10px 20px;
  margin-right: 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  font-size: 14.5px;
  font-weight: 400;
  color: var(--mute);
  background: var(--tint);
  white-space: nowrap;
  flex-shrink: 0;
}
.tech-badge svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--mute); }
@media (max-width: 560px) {
  .tech-badge { padding: 9px 14px; font-size: 13px; margin-right: 10px; }
}

/* ---------- Footer ---------- */

.site-footer {
  position: relative;
  border-top: 1px solid var(--line);
  padding: 80px 0 36px;
  background:
    radial-gradient(900px 300px at 15% 0%, rgba(10, 116, 218, 0.06), transparent 65%),
    var(--bg-deep);
  font-size: 14.5px;
  overflow: hidden;
}
.site-footer::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(110, 168, 255, 0.4), rgba(45, 212, 232, 0.3), transparent);
}
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr));
  gap: clamp(32px, 4vw, 64px);
  margin-bottom: 52px;
}
.footer-mascot { position: relative; display: inline-block; margin-bottom: 18px; }
/* small green fade behind the bandana tails, echoing the cape-accent glow
   on the hero mascots so the footer head reads as the same character */
.footer-mascot::before {
  content: "";
  position: absolute;
  z-index: 0;
  left: -14px;
  top: 4px;
  width: 60px;
  height: 60px;
  background: radial-gradient(ellipse, rgba(63, 201, 78, 0.18) 0%, rgba(63, 201, 78, 0.06) 45%, transparent 78%);
  filter: blur(10px);
  pointer-events: none;
}
.footer-logo { position: relative; z-index: 1; width: 108px; height: auto; margin-bottom: 0; display: block; }
.footer-brand p { color: var(--mute); max-width: 34ch; line-height: 1.6; font-size: 14.5px; }

.footer-social { display: flex; gap: 10px; margin-top: 20px; position: relative; z-index: 1; }
.footer-social a {
  width: 38px; height: 38px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-strong);
  color: var(--mute);
  background: var(--card);
  transition: transform var(--dur-fast) var(--ease-out), color var(--dur-fast) ease, border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}
/* matches .plans-nav's hover recipe (flat/bordered default → gloss fill
   on interaction) — these are real links, so they should pick up the same
   "glossy = clickable" language as the carousel arrows and mega-menu
   items instead of just a border/color tint. */
.footer-social a:hover { background: var(--icon-gloss); color: #fff; border-color: var(--blue); transform: translateY(-2px); box-shadow: var(--icon-gloss-shadow), 0 8px 18px -6px rgba(10, 116, 218, 0.4); }
.footer-grid, .footer-bottom { position: relative; z-index: 1; }

.footer-col h2 {
  font-size: 13px;
  font-weight: 750;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--mute);
  margin-bottom: 20px;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.footer-col a { color: var(--mute); font-size: 14.5px; transition: color var(--dur-fast) ease; display: inline-flex; align-items: center; gap: 8px; }
.footer-col a:hover, .footer-col a:focus-visible { color: var(--ink); }
/* Neutral, matching .soon-badge on the homepage product grid — not the
   green deal-badge treatment, so this never reads as an active sale. */
.footer-soon {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  color: var(--mute);
  border: 1px solid var(--line-strong); background: rgba(255, 255, 255, 0.06);
  border-radius: 999px; padding: 2px 7px;
}

.footer-bottom {
  border-top: 1px solid var(--line-strong);
  padding-top: 26px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  color: var(--mute);
  font-size: 14px;
}
.pay-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pay-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  padding: 0 8px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  color: var(--mute);
  background: var(--card);
}
.pay-badge svg { height: 14px; width: auto; }
.pay-badge:not(.is-wordmark) svg { height: 16px; }
.pay-badge.is-wordmark { padding: 0 7px; }

/* ---------- Responsive ---------- */

/* Between the mobile centered-hero breakpoint (900px) and the point where
   .container hits its 1180px cap (~1228px), page margins hold steady at a
   fixed 24px — too little room for chip-sites to bleed past .hero-visual's
   edge and clear the mascot's raised hand at that height without either
   getting clipped by .hero's own overflow:clip or overlapping the arm.
   Drop it down by the foot instead, same trick used on mobile. */
@media (min-width: 901px) and (max-width: 1227px) {
  .hero-visual .chip-sites { top: auto; bottom: 6%; right: 4%; }
}

/* .plans-nav sits outside the container at -60px so it clears the card
   shadows, but the container's own side margin only grows past 60px once
   the viewport is wide enough that --container (1180px) stops filling
   100% - 48px (~1300px). Below that, -60px pushes the button past the
   viewport edge and off-screen/unclickable — a real gap between this
   breakpoint and the 1080px one below, which already insets it for a
   different reason (2-up card layout). Both need the closer inset.
   2026-10-03 QA: the carousel actually lives in .container-wide (1300px),
   so -60px only fits from 1420px up. The old 1300px breakpoint left
   1301-1419px (incl. 1366/1400 laptops) with a 10-36px horizontal scroll.
   Below 1420 the carousel also reserves a 30px gutter each side so the
   arrows sit beside the cards instead of on top of their content. */
@media (max-width: 1420px) {
  .plans-carousel { padding-inline: 30px; }
  .plans-nav.prev { left: -16px; }
  .plans-nav.next { right: -16px; }
}

@media (max-width: 1080px) {
  .plans-track .plan-card { flex-basis: calc((100% - 22px) / 2); }
  /* Matches .wp-trust-strip-row's own >1250px breakpoint: same flex-wrap
     row just centers and tightens padding rather than reflowing to a grid. */
  .stats { justify-content: center; }
  .stat { padding: 0 18px; }
  .footer-grid { grid-template-columns: repeat(2, 1fr); }
  /* was .product-grid, a class removed 2026-08-31, so the homepage tiles
     never reflowed and shrank to ~67px each on phones (2026-10-03 QA) */
  .product-tiles { flex-wrap: wrap; }
  .product-tile { flex: 1 1 calc(50% - 10px); }
}

@media (max-width: 900px) {
  .nav-links,
  .nav-cta .nav-login { display: none; }
  .nav-toggle { display: inline-flex; }

  .nav.menu-open .nav-links {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--card);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 24px 40px rgba(0, 0, 0, 0.45);
    padding: 12px 24px 20px;
    gap: 2px;
    max-height: calc(100vh - 140px);
    overflow-y: auto;
  }
  .nav.menu-open .mega {
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    box-shadow: none;
    border: 0;
    background: transparent;
    padding: 0 0 6px 8px;
    width: auto;
    grid-template-columns: 1fr;
  }
  .nav.menu-open .mega-label { display: none; }
  .nav.menu-open .mega-item small { display: none; }

  .protect-flow { flex-direction: column; gap: 30px; }
  .protect-line {
    top: 23px; bottom: 23px; left: 23px; right: auto;
    width: 2px; height: auto;
    background: linear-gradient(180deg, var(--blue-bright), var(--cyan) 50%, var(--green-bright));
  }
  .protect-pulse {
    top: 0; left: 50%; margin-top: 0; margin-left: -3.5px;
  }
  .protect-line.is-active .protect-pulse {
    animation-name: protect-travel-vertical;
  }
  @keyframes protect-travel-vertical {
    0% { top: 0; opacity: 0; }
    8% { opacity: 1; }
    92% { opacity: 1; }
    100% { top: 100%; opacity: 0; }
  }
  .protect-stage { position: relative; flex: none; display: block; padding-left: 62px; min-height: 46px; }
  .protect-node { position: absolute; left: 0; top: 0; margin-bottom: 0; }
  .protect-num { margin-bottom: 4px; }

  .hero-grid { grid-template-columns: 1fr; }
  /* below ~900px the single-column hero-copy is narrower than the 52px
     clamp's text needs to hold 2 lines (it's fine from ~960px up) — drop
     to a size proven to fit "Manage WordPress website the easy way" in
     327px without a 3rd line */
  .hero h1.is-compact { font-size: 30px; }
  /* fixed, centered visual column (rather than stretching full-width) so the
     mascot + chip positions stay predictable at every width in this range —
     without this, percentage offsets calculated for a narrow phone drift
     into the mascot's face on wider tablet widths. */
  .hero-visual { min-height: 360px; max-width: 360px; margin-inline: auto; }
  .hero-visual img { width: min(238px, 61.2%); }
  .hero-visual .chip-uptime { top: 4%; left: 4%; }
  .hero-visual .chip-sites { top: auto; bottom: 8%; right: 2%; }
  .hero-visual .chip-speed { bottom: 4%; left: 6%; }

  .hero-mockup { min-height: 340px; max-width: 380px; margin-inline: auto; }
  .hero-mockup-frame { width: min(320px, 100%); }
  .hero-mockup-mascot img { width: 88px; }
  .hero-mockup-mascot { right: -6%; bottom: -6%; }
  /* the labeled rail (WordPress/Create/Product/Plugins/Themes) is too wide
     for the 320px mobile frame — it was squeezing the site-preview canvas
     until the "Ask AI" pill wrapped onto itself. Collapse to icon-only,
     same compact rail this had before labels were added. */
  .editor-rail { padding: 12px 8px; gap: 6px; }
  .rail-item { padding: 6px; }
  .rail-item span:not(.rail-ic) { display: none; }

  .managed-grid,
  .cta-block-grid { grid-template-columns: 1fr; }
  .feature-art { max-width: 480px; }
  .cta-mascot { display: none; }

  .platform-features { grid-template-columns: 1fr; }

  .switcher-panel { grid-template-columns: 1fr; text-align: center; }
  .switcher-tab { font-size: 13.5px; padding: 16px 12px; }

  .compare-cards { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
  .nav { gap: 10px; padding: 12px 0; }
  .logo { font-size: 20px; gap: 7px; }
  .logo img { height: 32px; }
  .nav-cta { gap: 6px; }
  .nav-cta .btn-sm { padding: 10px 14px; font-size: 13.5px; }
  .nav-toggle { padding: 8px 9px; }
  .deal-bar { font-size: 12.5px; padding: 9px 12px; }
}

@media (max-width: 640px) {
  .plans-track .plan-card { flex-basis: 86%; }
  /* Matches .wp-trust-strip .ts-item's own <640px breakpoint: drop the
     left divider/padding rather than a bottom-border stack. */
  .stat { border-left: none; padding: 0; }
  .checklist { grid-template-columns: 1fr; }
  .utility-bar .container { justify-content: center; gap: 18px; }
  .utility-bar .hide-mobile { display: none; }
  .footer-grid { grid-template-columns: 1fr; }
  .product-tile { flex-basis: 100%; }
}

/* ---------- WordPress product UI mockups ---------- */
/* stylized, non-literal illustrations of the product — device-chrome
   panels standing in for a real screenshot, built entirely from CSS */

.feature-art.has-mockup { padding: 0; display: block; }
/* the hero's mockup needs more height than the 4/3 feature-row crop allows
   (editor toolbar + selected-block callout push it taller) — content-sized
   instead, or the card row gets clipped by .feature-art's overflow:hidden */
.hero-mockup-frame.feature-art.has-mockup {
  aspect-ratio: auto;
  position: relative;
  /* matches the site's established "featured surface" card recipe
     (.plan-card/.product-card) — --card-gradient + a thin top-edge glow
     line — rather than a one-off treatment, so the hero's premium panel
     reads as the same material as the rest of the page */
  background: var(--card-gradient);
  border-color: var(--line);
  box-shadow: var(--shadow-lift), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.hero-mockup-frame.feature-art.has-mockup::before {
  content: "";
  position: absolute;
  top: 0; left: 14%; right: 14%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--blue-bright), transparent);
  opacity: 0.55;
}
.mockup { width: 100%; height: 100%; display: flex; flex-direction: column; }
.mockup-bar { display: flex; align-items: center; gap: 6px; padding: 12px 16px; border-bottom: 1px solid var(--line); flex-shrink: 0; }
.mockup-bar .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); }
.mockup-bar .dot:nth-child(1) { background: #ff6058; }
.mockup-bar .dot:nth-child(2) { background: #ffbd2e; }
.mockup-bar .dot:nth-child(3) { background: #28c941; }
.mockup-bar .mockup-url { margin-left: 10px; font-size: 11px; color: var(--faint); background: rgba(255, 255, 255, 0.04); padding: 3px 10px; border-radius: 999px; }


/* Reliability panel — matches index.html's .platform-panel treatment: a
   frosted-glass surface (translucent gradient over backdrop-blur, so the
   page's own ambient glow/dot-grid shows through) with a subtle white
   border and a faint cyan top-edge glow line, rather than the opaque
   --card-gradient + --line border + column dividers used elsewhere.
   Columns sit directly on the glass with no border-left dividers between
   them, same as .platform-features. Each column still carries the same
   real content + bespoke .p-diagram SVG art reused from index.html's
   platform panel. Heading stays OUTSIDE this box in its own .section-head
   (tried nesting it inside, matching .platform-panel exactly, on
   2026-08-30 — reverted same day per explicit feedback: the outside
   heading was preferred). */
.reliability-panel {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-xl);
  padding: clamp(24px, 2.6vw, 32px);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(11, 12, 52, 0.6) 0%, rgba(7, 8, 42, 0.6) 55%, rgba(5, 6, 33, 0.6) 100%);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow: var(--shadow-soft), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  margin-bottom: 44px;
}
.reliability-panel::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 0;
  left: 20%;
  right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(45, 212, 232, 0.4), transparent);
  pointer-events: none;
}
@media (max-width: 900px) {
  .reliability-panel { grid-template-columns: 1fr; }
}
.reliability-col { position: relative; z-index: 1; }
.reliability-col .rt-icon {
  width: 44px; height: 44px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  margin-bottom: 16px;
  background: var(--icon-glow);
  box-shadow: var(--icon-glow-shadow);
  color: var(--blue-bright);
}
.reliability-col h3 { font-size: 18px; font-weight: 800; margin-bottom: 12px; }
.reliability-col p { font-size: 14px; color: var(--mute); margin: 0; line-height: 1.6; }

/* ---------- Backup timeline — lives inside the second .compare-card now
   (see .compare-visual overrides above); no longer its own full-width
   section, so these base rules are sized generically and the compact
   fit is handled entirely by the .compare-visual-scoped overrides */

.backup-timeline {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  max-width: 620px;
  margin: 0 auto 26px;
  padding-top: 8px;
}
.backup-line {
  position: absolute;
  top: 15px; left: 4%; right: 4%;
  height: 1px;
  /* blue-bright, not cyan — this card sits right next to the green
     performance ring, and blue is the site's actual dominant accent
     (buttons, links, most icon chips), so pairing it here keeps both
     cards reading as "this brand" instead of introducing a third,
     rarely-used hue just for this one component */
  background: linear-gradient(90deg, var(--line) 0%, var(--line-strong) 70%, var(--blue-bright) 100%);
}
.backup-point { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; z-index: 1; }
.backup-dot {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--card);
  border: 2px solid var(--line-strong);
}
.backup-point.is-current .backup-dot {
  background: var(--blue-bright);
  border-color: var(--blue-bright);
  box-shadow: 0 0 0 5px var(--blue-tint);
}
.backup-label { font-size: 12.5px; color: var(--mute); font-weight: 600; white-space: nowrap; }
.backup-point.is-current .backup-label { color: var(--ink); }

@media (max-width: 560px) {
  .backup-label { font-size: 11px; }
}

/* ---------- Mascot art protection ----------
   Casual deterrent against right-click-save / drag-out / long-press-save
   on the mascot artwork specifically (hero mascot, footer/mega-menu head
   icon, WP waving mascot) — not applied sitewide since it would also kill
   text selection on copy, plan pricing, etc. This is a deterrent, not real
   DRM: anyone can still get the file from devtools/network tab. Paired
   with main.js blocking contextmenu/dragstart on `.mascot-art`. */
.mascot-art {
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Motion pause (performance) ----------
   Two classes toggled by main.js: .tab-hidden on <html> when the tab is
   backgrounded (Page Visibility API), and .anim-offscreen per-element when
   an IntersectionObserver sees it scroll out of the viewport. Both just
   pause whatever CSS keyframe animation is already running — same wildcard
   + explicit pseudo-element pattern as the reduced-motion rule above, so it
   works for elements whose animation lives on ::before/::after (e.g.
   .status-dot, .hero-visual) as well as ones animated directly. */
html.tab-hidden *, html.tab-hidden *::before, html.tab-hidden *::after {
  animation-play-state: paused !important;
}
.anim-offscreen, .anim-offscreen::before, .anim-offscreen::after {
  animation-play-state: paused;
}

/* ---------- Layered hero — panel composition (2026-10-01) ----------
   Shared by reseller-hosting.html and wordpress-hosting.html (lh- prefix;
   WP-specific pieces scoped under .is-wp/.is-shop at the end). Replaced the
   single control-panel mockup + mascot on both pages, per a reference the user supplied (two overlapping UI cards plus
   one floating badge, "the tool and the outcome" side by side). Back layer
   is the reseller's own white-label dashboard, front layer is a client's
   live site carrying the reseller's brand, badge is the real 100% uptime
   claim. Dark glass-panel-family material for the dashboard so it belongs
   to this site, a light client site in front for contrast. Static, no
   looping animation (so nothing to add to the .anim-offscreen list), only
   the sitewide one-shot [data-reveal], staggered per layer. Every label
   traces to real reseller copy (WHMCS, white-label, Add Client,
   SSL); client domains are obvious placeholders and no numbers are shown. */
.lh-visual {
  position: relative;
  width: 100%;
  max-width: 620px;
  height: 500px;
  margin-left: auto;
}
.lh-visual::before {
  content: "";
  position: absolute;
  inset: -6% -8%;
  z-index: 0;
  background: radial-gradient(ellipse farthest-side at 55% 50%, rgba(45, 212, 232, 0.16), rgba(10, 116, 218, 0.1) 55%, transparent 78%);
  pointer-events: none;
}

/* shared bezel: thin translucent ring outside each card, the frosted
   "glass frame" look from the reference */
.lh-panel,
.lh-site {
  position: absolute;
  border-radius: 20px;
  box-shadow:
    0 0 0 7px rgba(120, 160, 255, 0.07),
    0 0 0 8px rgba(255, 255, 255, 0.1),
    var(--shadow-lift);
}

/* ---- back layer: reseller dashboard ---- */
.lh-panel {
  z-index: 1;
  top: 0;
  left: 0;
  width: 88%;
  padding: 18px;
  background:
    radial-gradient(520px 300px at 50% -10%, rgba(10, 116, 218, 0.18), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.72), rgba(8, 10, 48, 0.66) 55%, rgba(5, 6, 34, 0.7));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.14);
}
.lh-panel::after {
  content: "";
  position: absolute;
  top: -1px; left: 20%; right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--cyan), transparent);
  opacity: 0.6;
}
.lh-panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 16px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.lh-brand-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.02em;
  color: #fff;
  background: linear-gradient(140deg, var(--cyan), var(--blue) 60%, #0a4fb0);
  box-shadow: var(--icon-gloss-shadow);
}
.lh-brand-mark.is-tiny { width: 16px; height: 16px; border-radius: 4px; font-size: 7px; box-shadow: none; }
.lh-panel-title { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.lh-panel-title strong { font-family: var(--font-display); font-size: 17px; font-weight: 800; color: var(--ink); white-space: nowrap; }
.lh-status { display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--mute); white-space: nowrap; }
.lh-status i { width: 1px; height: 10px; background: var(--line-strong); }
.lh-live { width: 7px; height: 7px; border-radius: 50%; background: var(--green-bright); box-shadow: 0 0 0 3px rgba(63, 201, 78, 0.18); }
.lh-panel-actions { display: flex; gap: 8px; }
.lh-btn-ghost,
.lh-btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 11px;
  border-radius: 9px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.lh-btn-ghost { color: var(--ink); border: 1px solid var(--line-strong); background: rgba(255, 255, 255, 0.04); }
.lh-btn-primary { color: #fff; background: linear-gradient(180deg, #1a86ec, var(--blue)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 6px 14px -6px rgba(10, 116, 218, 0.8); }

.lh-panel-body { display: grid; grid-template-columns: 1.25fr 1fr; gap: 12px; }
.lh-card {
  padding: 13px 14px;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
}
.lh-card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 11px; }
.lh-card-head strong { font-family: var(--font-display); font-size: 13px; font-weight: 700; color: var(--ink); }
.lh-tabs { display: flex; gap: 10px; font-size: 10.5px; color: var(--faint); }
.lh-tabs .is-on { color: var(--blue-bright); box-shadow: 0 1px 0 var(--blue-bright); }
.lh-client-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.lh-client-list li {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 9px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.05);
}
.lh-av { flex: none; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 7px; font-size: 11px; font-weight: 700; color: #fff; }
.lh-av.a1 { background: linear-gradient(140deg, #f2a65a, #d9782f); }
.lh-av.a2 { background: linear-gradient(140deg, var(--violet), #5d4fd0); }
.lh-av.a3 { background: linear-gradient(140deg, var(--cyan), #1495b0); }
.lh-dom { flex: 1; min-width: 0; font-size: 11.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lh-pill { font-size: 9.5px; font-weight: 600; color: var(--green-bright); background: var(--green-tint); padding: 3px 7px; border-radius: 999px; }

.lh-side { display: flex; flex-direction: column; gap: 12px; }
.lh-tag { font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em; color: var(--blue-bright); border: 1px solid rgba(110, 168, 255, 0.35); padding: 2px 6px; border-radius: 6px; }
.lh-bars { display: flex; align-items: flex-end; gap: 6px; height: 54px; }
.lh-bars span {
  flex: 1;
  height: var(--h);
  border-radius: 3px 3px 1px 1px;
  background: linear-gradient(180deg, var(--blue-bright), rgba(10, 116, 218, 0.35));
}
.lh-bars span:last-child { background: linear-gradient(180deg, var(--cyan), rgba(45, 212, 232, 0.35)); }

/* ---- front layer: the client's site, white-labeled ---- */
.lh-site {
  z-index: 2;
  right: 0;
  bottom: 0;
  width: 58%;
  overflow: hidden;
  background: #f3f5f8;
  color: #1c2340;
  border: 1px solid rgba(255, 255, 255, 0.5);
}
.lh-site-bar { padding: 9px 12px; background: #e6eaf0; border-bottom: 1px solid rgba(28, 35, 64, 0.08); }
.lh-site-url {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  background: #fff;
  font-size: 10px;
  color: #4a5270;
}
.lh-site-url svg { color: var(--green); }
.lh-site-nav { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px 4px; }
.lh-site-logo { font-family: Georgia, "Times New Roman", serif; font-size: 15px; font-weight: 700; letter-spacing: 0.04em; color: #1c2340; }
.lh-site-links { display: flex; gap: 8px; }
.lh-site-links span { width: 22px; height: 4px; border-radius: 2px; background: rgba(28, 35, 64, 0.22); }
.lh-site-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: center; padding: 10px 16px 12px; }
.lh-site-copy { display: flex; flex-direction: column; gap: 6px; }
.lh-line { height: 7px; border-radius: 4px; background: #1c2340; }
.lh-line.w1 { width: 92%; }
.lh-line.w2 { width: 70%; }
.lh-line.w3 { width: 84%; height: 4px; margin-top: 4px; background: rgba(28, 35, 64, 0.25); }
.lh-site-cta { width: 56px; height: 16px; margin-top: 6px; border-radius: 999px; background: linear-gradient(180deg, #2489ea, var(--blue)); }
.lh-site-art {
  position: relative;
  height: 92px;
  border-radius: 12px;
  overflow: hidden;
  background:
    radial-gradient(90px 60px at 78% 30%, rgba(45, 212, 232, 0.3), transparent 70%),
    linear-gradient(180deg, #12204a, #1d3a78);
}
.lh-site-art .sun { position: absolute; top: 16px; right: 22px; width: 22px; height: 22px; border-radius: 50%; background: #eef3ff; box-shadow: 0 0 14px rgba(110, 168, 255, 0.7); }
.lh-site-art .hill { position: absolute; border-radius: 50% 50% 0 0; }
.lh-site-art .h1 { left: -20%; bottom: -30%; width: 90%; height: 80%; background: linear-gradient(180deg, #2b5296, #1c3a73); }
.lh-site-art .h2 { right: -25%; bottom: -40%; width: 100%; height: 85%; background: linear-gradient(180deg, #1f67c4, #123f86); }
.lh-site-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 0 16px 14px; }
.lh-site-tiles span { height: 34px; border-radius: 8px; background: #fff; box-shadow: 0 2px 6px rgba(28, 35, 64, 0.08); }
.lh-site-foot {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  font-size: 10.5px;
  font-weight: 600;
  color: #4a5270;
  background: #e6eaf0;
  border-top: 1px solid rgba(28, 35, 64, 0.08);
}

/* ---- floating badge ---- */
.lh-badge {
  position: absolute;
  z-index: 3;
  left: 4%;
  bottom: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 16px 22px 14px;
  border-radius: 16px;
  color: #fff;
  text-align: center;
  background: linear-gradient(160deg, #3a9bff, var(--blue) 55%, #0757ad);
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow:
    0 0 0 6px rgba(120, 170, 255, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 22px 44px -14px rgba(10, 116, 218, 0.75);
}
.lh-badge strong { font-family: var(--font-display); font-size: 32px; font-weight: 800; line-height: 1.05; }
.lh-badge span { font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.9; }

/* staggered one-shot entrance: dashboard, then site, then badge */
.lh-site[data-reveal] { transition-delay: 0.15s; }
.lh-badge[data-reveal] { transition-delay: 0.3s; }
.lh-badge[data-reveal].pre-reveal { transform: translateY(14px) scale(0.94); }

/* ---- WordPress page variant: same layers, WP-specific content ---- */
.lh-brand-mark.is-wp { background: linear-gradient(140deg, #3a9bff, var(--blue) 60%, #0a4fb0); border-radius: 50%; }
.lh-wp-glyph {
  font-family: Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: 20px;
  line-height: 1;
}
.lh-wp-glyph.is-tiny {
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1.4px solid currentColor;
  font-size: 9px;
}
.lh-av.is-check { color: var(--green-bright); background: var(--green-tint); border: 1px solid rgba(63, 201, 78, 0.3); }
.lh-tag.is-green { color: var(--green-bright); border-color: rgba(63, 201, 78, 0.35); }
.lh-spark { display: block; width: 100%; height: 96px; }

/* client storefront: centered serif logo, navy banner, 3 product tiles in
   brand blue/cyan with the green ball as the one natural note */
.lh-site.is-shop { background: #f3f5f8; color: #172238; }
.lh-site.is-shop .lh-site-bar,
.lh-site.is-shop .lh-site-foot { background: #e6eaf0; }
.lh-site.is-shop .lh-site-nav { padding: 12px 16px 8px; }
.lh-site.is-shop .lh-site-logo { font-size: 16px; color: #172238; }
.lh-site-banner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin: 0 16px 12px;
  padding: 14px 0;
  border-radius: 10px;
  background:
    radial-gradient(160px 70px at 50% 120%, rgba(45, 212, 232, 0.3), transparent 70%),
    radial-gradient(140px 80px at 0% 0%, rgba(10, 116, 218, 0.4), transparent 70%),
    linear-gradient(135deg, #12204a, #0a1230);
}
.lh-site-banner .lh-line { background: #eef3ff; }
.lh-site-banner .lh-line.w1 { width: 46%; }
.lh-site-banner .lh-line.w3 { width: 62%; margin-top: 0; background: rgba(219, 229, 255, 0.45); }
.lh-site-products { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 0 16px 14px; }
.lh-product {
  position: relative;
  height: 92px;
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 2px 8px rgba(23, 34, 56, 0.08);
}
.lh-product .obj { position: absolute; left: 50%; transform: translateX(-50%); }
.lh-product .lbl { position: absolute; left: 8px; right: 22px; bottom: 9px; height: 5px; border-radius: 3px; background: rgba(23, 34, 56, 0.3); }
.lh-product .lbl::after { content: ""; position: absolute; right: -16px; top: -4px; width: 12px; height: 12px; border-radius: 50%; background: #172238; }
.lh-product.p1 { background: linear-gradient(180deg, #e3ecf8, #fff 75%); }
.lh-product.p1 .obj { top: 16px; width: 30px; height: 44px; border-radius: 14px 14px 10px 10px; background: linear-gradient(180deg, #6ea8ff, #0a74da); }
.lh-product.p2 { background: linear-gradient(180deg, #e7efe6, #fff 75%); }
.lh-product.p2 .obj { top: 14px; width: 40px; height: 40px; border-radius: 50%; background: radial-gradient(circle at 40% 35%, #8fb58a, #567a52); }
.lh-product.p3 { background: linear-gradient(180deg, #e2f5f8, #fff 75%); }
.lh-product.p3 .obj { top: 22px; width: 44px; height: 32px; border-radius: 6px; background: linear-gradient(180deg, #9be6f0, #2dbfd3); box-shadow: 0 -8px 0 -2px #bdeff5; }
/* narrower health column so its status pills clear the overlapping site card */
.lh-visual.is-wp .lh-panel-body { grid-template-columns: 1fr 1.15fr; }

/* ---- Web hosting page variant: app installer + runtimes, SitePad site ---- */
.lh-av.a-wp { background: linear-gradient(140deg, #3a8fc4, #21759b); }
.lh-av.a-jm { background: linear-gradient(140deg, #f7704f, #d93a1a); }
.lh-av.a-dr { background: linear-gradient(140deg, #2a9be0, #0567a8); }
.lh-pill.is-install { color: #fff; background: var(--blue); }
.lh-visual.is-web .lh-panel-body { grid-template-columns: 1.15fr 1fr; }
.lh-runtimes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.lh-runtimes li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.05);
}
.lh-runtimes .rt-name { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--ink); }
.lh-switch { position: relative; width: 26px; height: 15px; border-radius: 999px; background: rgba(255, 255, 255, 0.14); }
.lh-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 11px; height: 11px; border-radius: 50%; background: #fff; }
.lh-switch.is-on { background: var(--cyan); }
.lh-switch.is-on::after { left: 13px; }

/* restaurant-style SitePad site, retoned to the brand palette: cool shell
   like the WP storefront, deep navy hero band lit by a blue/cyan glow,
   blue CTA. The plate's food dots are the only warm notes left. */
.lh-site.is-resto { background: #f3f5f8; color: #172238; }
.lh-site.is-resto .lh-site-bar,
.lh-site.is-resto .lh-site-foot { background: #e6eaf0; }
.lh-resto-hero {
  position: relative;
  overflow: hidden;
  margin: 10px 12px 12px;
  border-radius: 12px;
  height: 138px;
  background:
    radial-gradient(130px 100px at 80% 62%, rgba(45, 212, 232, 0.28), transparent 70%),
    radial-gradient(180px 120px at 0% 0%, rgba(10, 116, 218, 0.35), transparent 70%),
    linear-gradient(135deg, #12204a, #0a1230);
}
.lh-resto-hero .lh-site-nav { padding: 11px 14px 0; }
.lh-resto-hero .lh-site-logo { color: #eef3ff; font-size: 15px; }
.lh-resto-hero .lh-site-links span { background: rgba(214, 226, 255, 0.35); }
.lh-resto-copy { position: absolute; left: 14px; top: 52px; width: 46%; display: flex; flex-direction: column; gap: 6px; }
.lh-resto-copy .lh-line { background: #dbe5ff; }
.lh-resto-copy .lh-line.w2 { background: rgba(219, 229, 255, 0.55); }
.lh-resto-copy .lh-site-cta { background: linear-gradient(180deg, #2489ea, var(--blue)); }
.lh-resto-plate {
  position: absolute;
  right: 14px;
  bottom: -26px;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 42% 40%, #e9a35b 0 14%, transparent 15%),
    radial-gradient(circle at 60% 58%, #7aa05a 0 12%, transparent 13%),
    radial-gradient(circle at 36% 62%, #c4492f 0 10%, transparent 11%),
    radial-gradient(circle, #f7f9fc 0 46%, #cfd7e4 47% 52%, #f7f9fc 53%);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.5), 0 0 0 6px rgba(45, 212, 232, 0.08);
}
.lh-site.is-resto .lh-site-tiles span { background: #fff; }

/* ---------- 1-click apps section (web-hosting.html) ----------
   The "many scripts" story the WordPress page doesn't need. Left-aligned
   intro beside a glass panel of app tiles (monogram chips, not brand
   logos), then the shared .compare-cards pair for SitePad + runtimes.
   App names and 380+/500+ figures all come from the live page. */
.apps-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
  margin-bottom: 28px;
}
.apps-head { margin-bottom: 0; }
.apps-points { list-style: none; margin: 26px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.apps-points li { display: flex; align-items: center; gap: 10px; font-size: 15px; color: var(--ink); }
.apps-points svg { color: var(--green-bright); flex: none; }
.apps-panel {
  position: relative;
  padding: 22px;
  border-radius: var(--radius-xl);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: var(--shadow-lift);
}
.apps-panel::after {
  content: "";
  position: absolute;
  top: -1px; left: 20%; right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--cyan), transparent);
  opacity: 0.6;
}
.app-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.app-tile {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 12px;
  align-items: center;
  padding: 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.app-tile:hover { border-color: var(--line-bright); background: rgba(255, 255, 255, 0.06); transform: translateY(-2px); }
.app-mono {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 17px;
  color: #fff;
  background: var(--c);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 6px 14px -6px var(--c);
}
.app-name { font-family: var(--font-display); font-size: 14.5px; font-weight: 700; color: var(--ink); }
.app-cat { font-size: 12px; color: var(--faint); }
.app-tile.is-more {
  background: linear-gradient(160deg, #1a86ec, var(--blue) 55%, #0757ad);
  border-color: rgba(255, 255, 255, 0.3);
}
.app-tile.is-more .app-more {
  grid-row: span 2;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 20px;
  color: #fff;
}
.app-tile.is-more .app-name { color: #fff; }
.app-tile.is-more .app-cat { color: rgba(255, 255, 255, 0.8); }
@media (prefers-reduced-motion: reduce) {
  .app-tile, .app-tile:hover { transition: none; transform: none; }
}

/* ---------- WordPress tools (wordpress-hosting.html #tools) ----------
   Install / builder / caching / security in a 2x2 of glass cards. Sits on
   the plain page background between the on-tint features section and
   performance, with only a faint left glow of its own. */
.wp-tools-section::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(800px 420px at 0% 30%, rgba(10, 116, 218, 0.07), transparent 65%);
}
.wp-tools-section > .container-wide { position: relative; }
/* Split intro: eyebrow + h2 left, lede right on the h2's baseline, so the
   head fills the row instead of leaving a wide empty right half. */
.wp-tools-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: 24px clamp(32px, 6vw, 96px);
  align-items: end;
  margin-bottom: 48px;
}
.wp-tools-head .section-head { margin: 0; }
.wp-tools-head .section-head h2 { margin-bottom: 0; }
.wp-tools-lede { margin: 0; font-size: 17px; color: var(--mute); max-width: 46ch; }
@media (max-width: 900px) {
  .wp-tools-head { grid-template-columns: 1fr; }
}
/* Separate cards with a gap, by explicit request (2026-10-03). It started
   as one hairline-divided canvas like the feature matrix. */
.wp-tools {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}
.wp-tool {
  position: relative;
  overflow: hidden;
  padding: 36px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.14), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: var(--shadow-soft);
}
.wp-tool::after {
  content: "";
  position: absolute;
  top: 0; left: 20%; right: 20%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--cyan), transparent);
  opacity: 0.45;
}
/* no hover effect on these cards, by request (2026-10-03) */
/* type, padding and gap match .compare-card exactly (19px h3, 14.5px copy,
   36px padding, 22px gap) so these read as the same card family as the
   Performance section below. No eyebrow above the h3 (removed 2026-10-03). */
.wp-tool h3 { font-size: 19px; font-weight: 800; margin: 0 0 12px; }
.wp-tool p { font-size: 14.5px; color: var(--mute); margin: 0; line-height: 1.6; }
@media (max-width: 760px) {
  .wp-tools { grid-template-columns: 1fr; }
}

/* Small static product visuals at the top of each .wp-tool block (install,
   builder, cache path, security log). Labels only reuse copy already on the
   page, no invented numbers. Static, so nothing joins .anim-offscreen. */
/* sits under the text like the site's other card illustrations, pinned to
   the card bottom so all four line up whatever the text length */
.wp-tool { display: flex; flex-direction: column; }
.wp-tool-visual {
  position: relative;
  height: 150px;
  margin-top: auto;
  padding-top: 28px;
  box-sizing: content-box;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 18px;
}
/* no box and no glow of its own (2026-10-03). A soft glow sat behind each
   visual, but it only showed through on the sparse cache-path visual and
   made that one card look different from the rest. */
.wp-tool-visual > * { position: relative; }

.tv-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11.5px; font-weight: 600;
  white-space: nowrap;
}
.tv-pill.is-ok { color: var(--green-bright); background: var(--green-tint); }
.tv-pill.is-bad { color: #ff8a80; background: rgba(255, 96, 88, 0.14); }

/* install */
.tv-card {
  width: min(320px, 86%);
  padding: 16px;
  border-radius: 14px;
  background: linear-gradient(165deg, rgba(14, 18, 70, 0.85), rgba(5, 6, 34, 0.85));
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-soft);
}
.tv-row { display: flex; align-items: center; gap: 11px; }
.tv-mono {
  display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 10px;
  font-family: Georgia, "Times New Roman", serif; font-weight: 700; font-size: 17px; line-height: 1; color: #fff;
  /* same round brand-blue WordPress mark as the hero dashboard (.lh-brand-mark.is-wp),
     not WordPress's own teal, which clashed with the site blue */
  background: linear-gradient(140deg, #3a9bff, var(--blue) 60%, #0a4fb0);
  border-radius: 50%;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.tv-txt { display: flex; flex-direction: column; flex: 1; line-height: 1.25; }
.tv-txt b { font-family: var(--font-display); font-size: 13.5px; color: var(--ink); }
.tv-txt small { font-size: 11.5px; color: var(--faint); }
.tv-bar { height: 5px; margin: 14px 0 12px; border-radius: 99px; background: rgba(255, 255, 255, 0.07); overflow: hidden; }
.tv-bar span { display: block; height: 100%; width: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--blue), #3a9bff); }
.tv-checks { display: flex; gap: 14px; font-size: 11.5px; color: var(--mute); }
.tv-checks span { display: inline-flex; align-items: center; gap: 5px; }
.tv-checks svg { color: var(--green-bright); }

/* builder */
.tv-builder { gap: 10px; }
.tv-rail { display: grid; grid-template-columns: repeat(2, 18px); gap: 6px; padding: 10px; border-radius: 12px; background: rgba(255, 255, 255, 0.04); border: 1px solid var(--line); }
.tv-rail span { height: 18px; border-radius: 5px; background: rgba(110, 168, 255, 0.22); }
.tv-canvas {
  position: relative;
  width: min(250px, 62%);
  padding: 12px;
  display: flex; flex-direction: column; gap: 8px;
  border-radius: 12px;
  background: #f4f7fd;
  box-shadow: var(--shadow-soft);
}
.tv-b-nav { height: 8px; width: 60%; border-radius: 4px; background: #cfd7e4; }
.tv-b-hero {
  position: relative;
  height: 46px;
  border-radius: 7px;
  background: linear-gradient(135deg, #dce8fb, #c4d8f7);
  outline: 1.5px dashed var(--blue);
  outline-offset: 2px;
}
.tv-b-tag {
  position: absolute; top: -11px; left: 8px;
  padding: 2px 7px; border-radius: 5px;
  font-style: normal; font-size: 9.5px; font-weight: 700; color: #fff;
  background: var(--blue);
}
.tv-b-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.tv-b-cols span { height: 22px; border-radius: 5px; background: #e3e8f1; }
.tv-cursor { position: absolute; right: 26px; top: 46px; color: #0a1440; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.3)); }

/* speed */
.tv-speed { flex-direction: column; align-items: flex-start; justify-content: center; gap: 16px; }
.tv-flow { display: flex; align-items: center; }
.tv-node {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 14px;
  border-radius: 11px;
  font-size: 12.5px; font-weight: 600; color: var(--mute);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line-strong);
}
.tv-node.is-hot {
  color: #fff;
  background: var(--icon-gloss);
  border-color: rgba(255, 255, 255, 0.25);
  box-shadow: var(--icon-gloss-shadow), 0 0 28px -6px rgba(45, 212, 232, 0.55);
}
.tv-link { width: 30px; height: 0; border-top: 1.5px dashed rgba(110, 168, 255, 0.55); }

/* security */
.tv-shield { gap: 22px; }
/* same color treatment as the Performance section's line diagrams
   (.p-diagram: --blue-bright at 0.85 opacity, no glow); the old blue
   drop-shadow halo made it read brighter than those */
.tv-shield-icon { color: var(--blue-bright); opacity: 0.85; flex: none; }
.tv-log { display: flex; flex-direction: column; gap: 7px; min-width: 200px; }
.tv-log-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 7px 8px 7px 12px;
  border-radius: 10px;
  font-size: 12px; color: var(--mute);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
}

/* =====================================================================
   Responsive QA fixes (2026-10-03)
   Collected from a full-site sweep at 320-1920px. Desktop (1280+) is
   unchanged by everything below except where a rule notes otherwise.
   ===================================================================== */

/* ---------- Header / mobile menu ---------- */
/* Log In and the phone number live in .nav-cta / the utility bar on
   desktop, but both are hidden at <=900 and weren't in the menu at all,
   so phones and tablets had no way to log in. */
.nav-links .nav-mobile-only { display: none; }
@media (max-width: 900px) {
  .nav.menu-open .nav-links .nav-mobile-only { display: block; }
  .nav.menu-open .nav-links li:not(.nav-mobile-only) + .nav-mobile-only {
    margin-top: 6px;
    padding-top: 8px;
    border-top: 1px solid var(--line);
  }
  /* 2026-10-05 (Galaxy Fold cover screen): the list was meant to be
     always expanded here, but its rows stay at opacity 0 until the drop
     gets .is-open, so the closed menu showed a tall empty gap under
     "Cloud Hosting". It is now a real accordion. Collapsed takes no
     space, a tap on the label expands it, and the chevron is back. */
  .nav.menu-open .nav-drop:not(.is-open) .mega { display: none; }
  .nav.menu-open .nav-drop-btn {
    width: 100%;
    justify-content: space-between;
  }
  .nav.menu-open .nav-drop.is-open .nav-drop-btn { background: none; }
  .nav.menu-open .mega { padding: 2px 0 8px; }
  .nav.menu-open .mega-links { gap: 2px; }
  .nav.menu-open .mega-item {
    align-items: center;
    padding: 9px 12px 9px 16px;
  }
  .nav.menu-open .mega-item .mega-ic { width: 34px; height: 34px; border-radius: 9px; }
  .nav.menu-open .mega-item .mega-ic svg { width: 18px; height: 18px; }
  .nav.menu-open .mega-item strong { flex-wrap: wrap; row-gap: 4px; font-size: 15px; }
  .nav.menu-open .mega-item .soon { font-size: 9.5px; padding: 1px 7px; }
}

/* ---------- Sticky section nav ---------- */
.quick-nav { flex: none; margin-inline: auto; }

/* ---------- Plans carousel dots ---------- */
/* 8px visible dot, ~24px tap target (padding is clipped out of the fill) */
.plans-dots { gap: 0; }
.plans-dots button { box-sizing: content-box; padding: 8px; background-clip: content-box; }
/* on phones the cards are swiped; the arrows only covered card content */
@media (max-width: 640px) {
  .plans-nav { display: none; }
  .plans-carousel { padding-inline: 0; }
}

/* ---------- Homepage hero float chips ---------- */
/* <=900: both bottom chips sat on top of each other (Low-Latency over
   <100ms). Pin them to opposite corners, a touch smaller. */
@media (max-width: 900px) {
  .hero-visual .float-chip { padding: 9px 12px; font-size: 12.5px; gap: 8px; }
  .hero-visual .float-chip small { font-size: 11px; }
  .hero-visual .chip-speed { left: 0; bottom: 3%; }
  .hero-visual .chip-sites { right: 0; bottom: 3%; }
}
/* <=480: the TTFB chip used to be hidden here for lack of width. It now
   shares the bottom row with Low-Latency, each capped at half the column
   so the caption wraps instead of the chips colliding (2026-10-05). */
@media (max-width: 480px) {
  .hero-visual .chip-uptime { left: 0; }
  .hero-visual .chip-speed,
  .hero-visual .chip-sites { max-width: calc(50% - 5px); bottom: 0; }
  .hero-visual .chip-speed { left: 0; }
  .hero-visual .chip-sites { right: 0; }
}

/* ---------- Stats row + trust strip ---------- */
/* Between ~700-900 the 4 items wrapped 3 + 1 with an orphan; stacked on
   phones each centered row put its icon at a different x. A 2x2 grid,
   then one left-aligned column centered as a block, keeps icons lined up. */
@media (max-width: 900px) {
  .stats,
  .wp-trust-strip-row {
    display: grid;
    grid-template-columns: repeat(2, max-content);
    justify-content: space-around;
    gap: 22px 32px;
  }
  .stat,
  .wp-trust-strip .ts-item { border-left: none; padding: 0; }
}
@media (max-width: 560px) {
  .stats,
  .wp-trust-strip-row { grid-template-columns: max-content; justify-content: center; gap: 18px; }
}

/* ---------- Homepage product tiles ---------- */
/* Touch screens have no hover, and a tap opens the link, so the price
   and description were unreachable on phones. Show them at rest there
   only; pointer devices keep the confirmed hover reveal. */
@media (hover: none) {
  .product-tile .tile-details { max-height: none; opacity: 1; margin-top: 8px; }
}
/* single column on phones: a full square visual per tile made the row
   ~1,900px tall */
@media (max-width: 640px) {
  .product-tile .tile-visual { aspect-ratio: 16 / 11; }
}

/* ---------- Layered hero (.lh-visual, WP / Web / Reseller) ---------- */
/* The panel title and status row overflowed under the action buttons
   whenever the panel got narrow (901-1190 beside the copy, and phones). */
.lh-panel-title strong { overflow: hidden; text-overflow: ellipsis; }
.lh-status { overflow: hidden; }
@media (min-width: 901px) and (max-width: 1200px) {
  .lh-btn-ghost { display: none; }
}
@media (max-width: 600px) {
  .lh-btn-ghost { display: none; }
}
@media (max-width: 480px) {
  .lh-visual { height: 420px; }
  .lh-panel { width: 100%; padding: 14px; }
  .lh-panel-actions { display: none; }
  /* one dashboard card is plenty at this size; the second one was
     sliced in half by the panel edge */
  .lh-panel-body,
  .lh-visual.is-wp .lh-panel-body,
  .lh-visual.is-web .lh-panel-body { grid-template-columns: 1fr; }
  .lh-panel-body > :nth-child(2) { display: none; }
  .lh-site { width: 62%; }
  .lh-badge { left: 0; bottom: 24px; padding: 12px 16px 10px; }
  .lh-badge strong { font-size: 26px; }
  .lh-badge span { font-size: 10px; }
}

/* ---------- Web hosting: 1-click apps ---------- */
/* No breakpoints existed, so the 2-column layout + 3-column grid caused a
   11-323px horizontal scroll at every width <=900. */
@media (max-width: 900px) {
  .apps-layout { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .apps-panel { padding: 14px; }
  .app-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .app-tile { padding: 12px; column-gap: 10px; }
  /* 9 tiles in 2 columns leaves this one alone; give it the full row */
  .app-tile.is-more { grid-column: 1 / -1; }
}
.app-tile > * { min-width: 0; }

/* ---------- WordPress tools visuals ---------- */
@media (max-width: 480px) {
  /* Visitor -> LSCache -> Redis was wider than the card and got clipped */
  .tv-node { padding: 8px 10px; font-size: 11.5px; }
  .tv-link { width: 14px; }
}
/* "Up to date" was breaking onto three lines in the narrow 2-up tools
   grid (761-1100) and on phones; wrap whole labels instead */
.tv-checks { flex-wrap: wrap; row-gap: 6px; }
.tv-checks span { white-space: nowrap; }

/* ---------- Homepage infrastructure ---------- */
/* column dividers stayed visible after the columns stacked */
@media (max-width: 900px) {
  .platform-feature:not(:last-child)::after { display: none; }
  .platform-feature { padding-right: 0; }
}

/* ---------- Switcher install steps ---------- */
/* the panel goes text-align:center at <=900, which also centered some
   step labels and not others */
.install-mockup { text-align: left; }

/* ---------- Reviews on phones ---------- */
/* 12 stacked cards were ~2,900px of scroll. Show 4 and a button (added
   by main.js) that reveals the rest. */
.reviews-more { display: none; }
@media (max-width: 640px) {
  .reviews-cards.is-collapsed [data-review]:nth-child(n+5) { display: none; }
  .reviews-more { display: flex; justify-content: center; margin-top: 24px; }
}

/* ---------- Footer payment badges ---------- */
@media (max-width: 420px) {
  .pay-badges { gap: 6px; }
  .pay-badge { padding: 0 6px; }
}
/* 901-920: the side card's tabs/tag ran past the panel edge; let the
   card header wrap instead (a no-op wherever it already fits) */
.lh-card-head { flex-wrap: wrap; gap: 6px 8px; }

/* ---------- Second QA pass (2026-10-03, live server) ---------- */
/* 1081-1115: four tiles at ~195px each, "Up to 80% off" wrapped under
   "/mo*" but the tight display line-height made the lines overlap */
.tile-price { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; row-gap: 2px; }
.tile-price .tile-deal { margin-left: 0; }

/* 901-914: the two bottom hero chips touched by up to 5px right where
   the hero goes two-column */
@media (min-width: 901px) and (max-width: 1227px) {
  .hero-visual .chip-speed { left: 2%; }
}

/* 320-ish: the stacked switcher column took the install demo's
   min-content width, pushing the heading 11px past the clipped panel */
@media (max-width: 480px) {
  .switcher-panel { grid-template-columns: minmax(0, 1fr); padding: 28px 20px; }
}

/* the desktop review wall picks random card sizes; a long name in the
   200px .size-sm card pushed "Google" past the card edge */
.reviews-stage.is-scattered .review-card.size-sm .review-who { flex-wrap: wrap; row-gap: 2px; }

/* Plan card deal badge sits absolute top-right; long names (reseller's
   CloudPlatinum/CloudTitanium/CloudPlutonium, and every page at 320)
   ran under it below ~400px and in the narrow 2-up range 641-750px.
   Up to 780 the badge drops back into the card's flex flow above the
   name, so no name length can collide with it. */
@media (max-width: 780px) {
  .plan-card .deal-badge { position: static; margin-bottom: 14px; }
}

/* ==========================================================================
   Legal pages (terms-of-service.html, privacy-policy.html,
   acceptable-use-policy.html), added 2026-10-04. One shared layout: a short
   hero with a document switcher, then a sticky contents rail beside a
   reading column. Long-form prose, so the measure stays near 72ch and
   nothing animates.
   ========================================================================== */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.legal-hero {
  position: relative;
  padding: clamp(56px, 7vw, 96px) 0 0;
  overflow: hidden;
}
.legal-hero::before {
  content: "";
  position: absolute;
  inset: -20% auto auto -10%;
  width: 760px; height: 520px;
  background: radial-gradient(closest-side, rgba(10, 116, 218, 0.22), transparent 70%);
  pointer-events: none;
}
.legal-hero .container { position: relative; }
.legal-hero h1 {
  font-size: clamp(34px, 4vw, 52px);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0 0 16px;
}
.legal-lede { max-width: 560px; color: var(--mute); font-size: 17px; margin: 0 0 22px; }
.legal-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  font-size: 13.5px; color: var(--faint); margin: 0 0 44px;
}
.legal-meta time { color: var(--mute); }
.legal-meta-dot { width: 3px; height: 3px; border-radius: 50%; background: var(--faint); }

.legal-tabs {
  display: flex; gap: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  overflow-x: auto;
  scrollbar-width: none;
}
.legal-tabs::-webkit-scrollbar { display: none; }
.legal-tab {
  position: relative;
  flex: none;
  padding: 14px 18px 16px;
  font-size: 14.5px; font-weight: 600;
  color: var(--mute);
  transition: color 0.2s ease;
}
.legal-tab:hover { color: var(--ink); }
.legal-tab[aria-current="page"] { color: var(--ink); }
.legal-tab[aria-current="page"]::after {
  content: "";
  position: absolute; left: 18px; right: 18px; bottom: -1px;
  height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--blue-bright), var(--cyan));
}

.legal-body { padding: clamp(48px, 6vw, 80px) 0 var(--section-pad); }
.legal-layout {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}

/* Contents rail */
.legal-toc {
  position: sticky;
  top: 104px;
  max-height: calc(100vh - 128px);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.14) transparent;
  padding-right: 6px;
}
.legal-toc-label {
  font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 14px;
}
.legal-toc ol { list-style: none; margin: 0; padding: 0; border-left: 1px solid rgba(255, 255, 255, 0.08); }
.legal-toc a {
  display: grid; grid-template-columns: 26px 1fr; gap: 4px;
  margin-left: -1px;
  padding: 7px 0 7px 14px;
  border-left: 2px solid transparent;
  font-size: 13.5px; line-height: 1.4;
  color: var(--mute);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.legal-toc a:hover { color: var(--ink); }
.legal-toc a.is-active { color: var(--ink); border-left-color: var(--blue-bright); }
.legal-toc-num { color: var(--faint); font-variant-numeric: tabular-nums; }
.legal-toc a.is-active .legal-toc-num { color: var(--blue-bright); }

/* Reading column */
.legal-doc { max-width: 72ch; color: #c9d1e8; font-size: 16px; line-height: 1.75; }
.legal-doc p { margin: 0 0 18px; }
.legal-doc a { text-decoration: underline; text-decoration-color: rgba(110, 168, 255, 0.4); text-underline-offset: 3px; }
.legal-doc a:hover { text-decoration-color: currentColor; }
.legal-intro {
  font-size: 18px; line-height: 1.7; color: var(--ink);
  padding-bottom: 18px; margin-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.legal-section {
  scroll-margin-top: 104px;
  padding: 40px 0 22px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.legal-section h2 {
  display: flex; align-items: baseline; gap: 14px;
  font-size: clamp(22px, 2vw, 26px); font-weight: 700; line-height: 1.3;
  color: var(--ink);
  margin: 0 0 20px;
}
.legal-num {
  flex: none;
  min-width: 34px;
  font-size: 14px; font-weight: 700;
  color: var(--blue-bright);
  font-variant-numeric: tabular-nums;
}
.legal-section > p,
.legal-section > ul { margin-left: 48px; }

/* Lettered clauses: the letter sits in the same gutter as the section number */
.legal-clause { position: relative; padding-left: 48px; margin-bottom: 6px; }
.legal-mark {
  position: absolute; left: 0; top: 2px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 7px;
  border: 1px solid rgba(110, 168, 255, 0.28);
  background: rgba(10, 116, 218, 0.12);
  font-size: 12.5px; font-weight: 700; line-height: 1;
  color: var(--blue-bright);
}
.legal-clause h3 {
  font-size: 17px; font-weight: 700; line-height: 1.5;
  color: var(--ink);
  margin: 0 0 8px;
  padding-top: 1px;
}
.legal-sub { position: relative; padding-left: 30px; }
.legal-sub-mark { position: absolute; left: 0; color: var(--blue-bright); font-weight: 600; }
.legal-doc ul { padding-left: 20px; margin: 0 0 18px; }
.legal-doc li { margin-bottom: 6px; }
.legal-doc li::marker { color: var(--blue-bright); }

/* End of document */
.legal-end { padding-top: 40px; }
.legal-end-note { font-size: 14px; color: var(--faint); margin-bottom: 28px !important; }
.legal-related {
  padding: 24px;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: var(--card-gradient);
  box-shadow: var(--shadow-soft);
}
.legal-related-label {
  font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 14px !important;
}
.legal-related-links { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.legal-doc .legal-related-link {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.03);
  font-size: 15px; font-weight: 600; line-height: 1.3;
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.legal-related-link > span:nth-child(2) { flex: 1; }
.legal-related-link > svg { color: var(--faint); transition: transform 0.2s ease, color 0.2s ease; }
.legal-doc .legal-related-link:hover { border-color: rgba(110, 168, 255, 0.4); background: rgba(10, 116, 218, 0.1); color: var(--ink); }
.legal-related-link:hover > svg { color: var(--blue-bright); transform: translateX(3px); }
.legal-related-ic {
  flex: none; width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 9px; background: var(--blue); color: #fff;
}
.legal-doc .legal-top {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 28px;
  font-size: 14px; font-weight: 600;
  color: var(--mute); text-decoration: none;
}
.legal-doc .legal-top:hover { color: var(--ink); }

@media (max-width: 960px) {
  .legal-layout { grid-template-columns: minmax(0, 1fr); }
  .legal-toc { display: none; }
}
@media (max-width: 640px) {
  .legal-section > p, .legal-section > ul { margin-left: 0; }
  .legal-clause { padding-left: 38px; }
  .legal-section h2 { gap: 10px; }
  .legal-num { min-width: 26px; }
  .legal-related-links { grid-template-columns: minmax(0, 1fr); }
  .legal-tab { padding-inline: 12px; }
  .legal-tab[aria-current="page"]::after { left: 12px; right: 12px; }
}

/* ==========================================================================
   Affiliate program page (affiliate-program.html), added 2026-10-04.
   Copy is from crocweb.com/affiliate-program plus sections built only from
   claims already on the site (40% commission, free to join, up to 80% off,
   60-day guarantee, 100% uptime, 24/7 support). No payout figures anywhere,
   including inside the mockups.
   ========================================================================== */

/* ---- hero: layered visual variant ---- */
.lh-aff-mark { flex: none; width: 38px; height: 38px; object-fit: contain; filter: drop-shadow(0 4px 10px rgba(10, 116, 218, 0.5)); }
.lh-aff-link {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 12px;
  padding: 9px 11px;
  border-radius: 9px;
  border: 1px dashed rgba(110, 168, 255, 0.4);
  background: rgba(10, 116, 218, 0.1);
  font-size: 11.5px; color: var(--ink);
}
.lh-aff-link svg { color: var(--blue-bright); flex: none; }
.lh-aff-link em, .av-link em { font-style: normal; color: var(--cyan); }
.lh-visual.is-aff .lh-bars { height: 92px; }

/* front layer: a referral-sale notice instead of a client site */
.lh-site.lh-aff-sale { width: 54%; bottom: 10px; }
.aff-sale-body { padding: 16px 18px 18px; }
.aff-sale-head { display: flex; align-items: center; gap: 11px; margin-bottom: 14px; }
.aff-sale-head strong { display: block; font-family: var(--font-display); font-size: 15px; font-weight: 800; color: #172238; }
.aff-sale-head small { font-size: 11.5px; color: #5a6582; }
.aff-sale-check {
  flex: none; width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: #fff;
  background: linear-gradient(160deg, var(--green-bright), var(--green));
  box-shadow: 0 6px 14px -6px rgba(39, 152, 50, 0.8);
}
.aff-sale-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 9px 0;
  border-top: 1px solid rgba(28, 35, 64, 0.08);
  font-size: 12px; color: #5a6582;
}
.aff-sale-row b { color: #172238; font-weight: 700; }
.aff-sale-row b.is-green { color: var(--green); font-size: 14px; }
.aff-sale-cta {
  display: block; margin-top: 10px;
  padding: 8px 0;
  border-radius: 999px;
  text-align: center;
  font-size: 11.5px; font-weight: 700; color: #fff;
  background: linear-gradient(180deg, #2489ea, var(--blue));
}

/* ---- How it works ---- */
.aff-steps {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px;
}
.aff-step {
  position: relative;
  display: flex; flex-direction: column;
  overflow: hidden;
  padding: 32px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.14), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: var(--shadow-soft);
}
.aff-step::after {
  content: "";
  position: absolute; top: 0; left: 20%; right: 20%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--cyan), transparent);
  opacity: 0.45;
}
.aff-step-num {
  align-self: flex-start;
  margin-bottom: 18px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12.5px; font-weight: 700; color: var(--blue-bright);
  border: 1px solid rgba(110, 168, 255, 0.35);
  background: rgba(10, 116, 218, 0.12);
}
.aff-step h3 { font-size: 21px; font-weight: 800; margin: 0 0 10px; }
.aff-step p { font-size: 15px; color: var(--mute); line-height: 1.6; margin: 0; }
.aff-step-visual {
  margin-top: auto;
  padding-top: 28px;
  height: 172px; box-sizing: content-box;
  display: flex; align-items: flex-end;
}
.aff-steps-cta { display: flex; justify-content: center; margin-top: 44px; }

/* step 1: sign-up form */
.av-form {
  width: 100%;
  display: flex; flex-direction: column; gap: 7px;
  padding: 12px;
  border-radius: 14px;
  border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, 0.03);
}
.av-field {
  display: flex; align-items: center;
  height: 25px; padding: 0 10px;
  border-radius: 7px;
  border: 1px solid var(--line);
  background: rgba(5, 8, 40, 0.6);
}
.av-field i { font-style: normal; font-size: 11px; color: var(--faint); }
.av-btn {
  margin-top: 2px;
  padding: 7px 0;
  border-radius: 8px;
  text-align: center;
  font-size: 12px; font-weight: 700; color: #fff;
  background: var(--icon-gloss);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

/* step 2: link + banners */
.av-share { flex-direction: column; align-items: stretch; justify-content: flex-end; gap: 12px; }
.av-link {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 8px 8px 12px;
  border-radius: 10px;
  border: 1px dashed rgba(110, 168, 255, 0.4);
  background: rgba(10, 116, 218, 0.1);
  font-size: 12.5px; color: var(--ink);
}
.av-copy { padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; color: #fff; background: var(--blue); }
.av-banners { display: grid; grid-template-columns: 1.4fr 1fr 0.7fr; gap: 10px; height: 74px; }
.av-banner {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; justify-content: center; gap: 6px;
  padding: 10px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.14);
}
.av-banner i { display: block; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.85); }
.av-banner i + i { width: 60%; background: rgba(255, 255, 255, 0.45); }
.av-banner.b1 { background: linear-gradient(140deg, #2489ea, #063f7a); padding-left: 46px; }
.av-banner.b1 img { position: absolute; left: 8px; top: 50%; width: 32px; transform: translateY(-50%); }
.av-banner.b2 { background: linear-gradient(140deg, #15165f, #0a74da); }
.av-banner.b3 { background: linear-gradient(140deg, #1495b0, #0d1454); }

/* step 3: purchase to commission */
.av-paid { align-items: center; }
.av-flow { width: 100%; display: flex; align-items: center; gap: 10px; }
.av-node {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  height: 104px;
  border-radius: 14px;
  border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, 0.03);
  font-size: 12px; font-weight: 600; color: var(--mute);
}
.av-node svg { color: var(--blue-bright); }
.av-node.is-paid {
  color: #eafbe9;
  border-color: rgba(63, 201, 78, 0.45);
  background: linear-gradient(160deg, rgba(63, 201, 78, 0.22), rgba(39, 152, 50, 0.1));
}
.av-node.is-paid strong { font-family: var(--font-display); font-size: 30px; font-weight: 800; line-height: 1; color: var(--green-bright); }
.av-arrow { position: relative; flex: none; width: 34px; height: 2px; background: linear-gradient(90deg, var(--blue-bright), var(--green-bright)); }
.av-arrow::after {
  content: ""; position: absolute; right: -1px; top: -4px;
  border: 5px solid transparent; border-left: 7px solid var(--green-bright); border-right: 0;
}

/* ---- Why promote: one canvas split by hairlines, figures instead of icons ---- */
.aff-why { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.4fr); gap: clamp(40px, 6vw, 80px); align-items: start; }
.aff-why .section-head { margin: 0; position: sticky; top: 120px; }
.aff-facts {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  border-radius: var(--radius-xl);
  border: 1px solid rgba(255, 255, 255, 0.12);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.14), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}
.aff-fact { padding: 30px 32px; border-top: 1px solid var(--line); }
.aff-fact:nth-child(-n+2) { border-top: 0; }
.aff-fact:nth-child(even) { border-left: 1px solid var(--line); }
.aff-fact strong {
  display: block; margin-bottom: 10px;
  font-family: var(--font-display); font-size: clamp(30px, 3vw, 38px); font-weight: 800; line-height: 1;
  background: linear-gradient(90deg, var(--ink), var(--blue-bright) 70%, var(--cyan));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.aff-fact h3 { font-size: 16.5px; font-weight: 700; margin: 0 0 6px; }
.aff-fact p { font-size: 14.5px; color: var(--mute); line-height: 1.6; margin: 0; }

/* ---- What you'll promote ---- */
.aff-products { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
.aff-product {
  display: flex; flex-direction: column;
  padding: 30px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--card-gradient);
  box-shadow: var(--shadow-soft);
  color: var(--ink);
  transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}
.aff-product:hover { color: var(--ink); transform: translateY(-3px); border-color: rgba(110, 168, 255, 0.4); box-shadow: var(--shadow-lift); }
.aff-product .mega-ic {
  width: 46px; height: 46px; margin-bottom: 20px;
  display: grid; place-items: center;
  border-radius: 12px; color: #fff;
  background: var(--icon-gloss);
  box-shadow: var(--icon-gloss-shadow);
}
.aff-product h3 { font-size: 19px; font-weight: 800; margin: 0 0 8px; }
.aff-product p { font-size: 14.5px; color: var(--mute); margin: 0 0 24px; line-height: 1.6; }
.aff-product-foot {
  margin-top: auto;
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
}
.aff-product-price { color: var(--mute); }
.aff-product-price b { font-family: var(--font-display); font-size: 20px; font-weight: 800; color: var(--ink); }
.aff-product-more { font-weight: 600; color: var(--blue-bright); }
.aff-product-more span { display: inline-block; transition: transform var(--dur-fast) var(--ease-out); }
.aff-product:hover .aff-product-more span { transform: translateX(3px); }
.aff-footnote { margin: 22px 0 0; text-align: center; font-size: 13px; color: var(--faint); }

/* ---- CTA as the page's last block (no tech strip below it, 2026-10-04):
   same breathing room under it as above it, so it doesn't sit on the
   footer's top border ---- */
main > .cta-block:last-child { margin-bottom: clamp(56px, 6.5vw, 94px); }

/* ---- CTA: second, outlined button on the blue panel ---- */
.aff-cta-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }
.btn-outline-light {
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.06);
}
.btn-outline-light:hover { color: #fff; border-color: #fff; background: rgba(255, 255, 255, 0.14); transform: translateY(-2px); }

@media (max-width: 1080px) {
  .aff-why { grid-template-columns: minmax(0, 1fr); }
  .aff-why .section-head { position: static; }
}
@media (max-width: 900px) {
  .aff-steps, .aff-products { grid-template-columns: minmax(0, 1fr); max-width: 560px; margin-inline: auto; }
}
@media (max-width: 560px) {
  .aff-facts { grid-template-columns: minmax(0, 1fr); }
  .aff-fact:nth-child(even) { border-left: 0; }
  .aff-fact:nth-child(2) { border-top: 1px solid var(--line); }
  .aff-step { padding: 26px 22px; }
  .lh-site.lh-aff-sale { width: 66%; }
}

/* ==========================================================================
   Contact page (contact.html), added 2026-10-04.
   Contact details are from crocweb.com/contact (phone, four team inboxes,
   Cornwall mailing address, Help Center, Knowledgebase, Status, socials).
   The form keeps the live page's Name / Email / Message fields and adds a
   team picker whose "Sending to" line shows the matching inbox. No reply
   time or office hours are stated anywhere because none are published,
   only the existing 24/7 technical support claim.
   ========================================================================== */

/* ---- hero ---- */
.ct-hero-grid { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); align-items: start; }
.ct-hero .hero-copy { padding-top: 24px; }

.ct-lines { list-style: none; margin: 8px 0 0; padding: 0; max-width: 460px; border-top: 1px solid var(--line); }
.ct-line {
  display: flex; align-items: center; gap: 16px;
  padding: 16px 4px;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.ct-line:hover { color: var(--ink); }
.ct-line-ic {
  flex: none; width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 12px; color: #fff;
  background: var(--icon-gloss);
  box-shadow: var(--icon-gloss-shadow);
}
.ct-line-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ct-line-label { font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); }
.ct-line-value { font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.ct-line-go {
  margin-left: auto;
  color: var(--blue-bright);
  transition: transform var(--dur-fast) var(--ease-out);
}
.ct-line:hover .ct-line-go,
.ct-line:focus-visible .ct-line-go { transform: translateX(4px); }

/* ---- form panel (glass recipe) ---- */
.ct-form-wrap { position: relative; }
.ct-form {
  position: relative;
  display: flex; flex-direction: column; gap: 20px;
  padding: 36px;
  border-radius: var(--radius-xl);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow: var(--shadow-lift);
}
.ct-form::after {
  content: "";
  position: absolute; top: 0; left: 20%; right: 20%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--cyan), transparent);
  opacity: 0.5;
}
.ct-form-head h2 { font-size: 26px; font-weight: 800; margin: 0 0 6px; }
.ct-form-head p { font-size: 15px; color: var(--mute); margin: 0; }

.ct-topics { margin: 0; padding: 0; border: 0; min-width: 0; }
.ct-label { display: block; margin-bottom: 8px; padding: 0; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.ct-topic-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.ct-topic { position: relative; cursor: pointer; }
.ct-topic input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ct-topic span {
  display: block;
  padding: 11px 8px;
  border-radius: 10px;
  text-align: center;
  font-size: 14px; font-weight: 600; color: var(--mute);
  border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, 0.03);
  transition: color var(--dur-fast) ease, border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}
.ct-topic:hover span { color: var(--ink); border-color: var(--line-bright); }
.ct-topic input:checked + span {
  color: #fff;
  border-color: transparent;
  background: linear-gradient(180deg, #2489ea 0%, var(--blue) 55%, var(--blue-deep) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 8px 18px -10px rgba(10, 116, 218, 0.9);
}
.ct-topic input:focus-visible + span { outline: 2px solid var(--blue-bright); outline-offset: 2px; }
.ct-route {
  display: flex; align-items: center; gap: 8px;
  margin: 12px 0 0;
  padding: 9px 12px;
  border-radius: 9px;
  border: 1px dashed rgba(110, 168, 255, 0.4);
  background: rgba(10, 116, 218, 0.1);
  font-size: 13.5px; color: var(--mute);
}
.ct-route svg { flex: none; color: var(--blue-bright); }
.ct-route strong { color: var(--cyan); font-weight: 600; }

.ct-field-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.ct-field { min-width: 0; }
.ct-input {
  display: block; width: 100%;
  padding: 13px 14px;
  border-radius: 10px;
  border: 1px solid var(--line-strong);
  background: rgba(3, 5, 32, 0.6);
  color: var(--ink);
  font: inherit; font-size: 15px;
  transition: border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}
textarea.ct-input { resize: vertical; min-height: 132px; line-height: 1.55; }
.ct-input:hover { border-color: var(--line-bright); }
.ct-input:focus { outline: none; border-color: var(--blue-bright); box-shadow: 0 0 0 3px rgba(110, 168, 255, 0.22); }
.ct-submit { align-self: flex-start; padding: 16px 30px; font-size: 16px; border: 0; cursor: pointer; }
.ct-submit[disabled] { opacity: 0.6; cursor: wait; }
.ct-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.ct-captcha { min-height: 78px; }
.ct-status { margin: -4px 0 0; padding: 12px 14px; border-radius: 9px; font-size: 14px; }
.ct-status.is-ok { color: var(--green-bright); background: rgba(39, 152, 50, 0.12); border: 1px solid rgba(63, 201, 78, 0.35); }
.ct-status.is-error { color: #ff8a8a; background: rgba(220, 60, 60, 0.12); border: 1px solid rgba(255, 120, 120, 0.35); }

/* ---- department directory: one canvas split by hairlines ---- */
.ct-dir { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.4fr); gap: clamp(40px, 6vw, 80px); align-items: start; }
.ct-dir .section-head { margin: 0; position: sticky; top: 120px; }
.ct-depts {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  border-radius: var(--radius-xl);
  border: 1px solid rgba(255, 255, 255, 0.12);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.14), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}
.ct-dept { display: flex; flex-direction: column; padding: 30px 32px; border-top: 1px solid var(--line); }
.ct-dept:nth-child(-n+2) { border-top: 0; }
.ct-dept:nth-child(even) { border-left: 1px solid var(--line); }
.ct-dept h3 { display: flex; align-items: center; gap: 10px; font-size: 19px; font-weight: 800; margin: 0 0 8px; }
.ct-247 {
  padding: 3px 9px;
  border-radius: 999px;
  font-family: var(--font-body); font-size: 11.5px; font-weight: 700; color: var(--green-bright);
  border: 1px solid rgba(63, 201, 78, 0.4);
  background: rgba(63, 201, 78, 0.1);
}
.ct-dept p { font-size: 14.5px; color: var(--mute); line-height: 1.6; margin: 0 0 22px; }
.ct-mail {
  margin-top: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 8px 8px 14px;
  border-radius: 10px;
  border: 1px solid var(--line-strong);
  background: rgba(3, 5, 32, 0.5);
}
.ct-mail a { min-width: 0; overflow-wrap: anywhere; font-size: 15px; font-weight: 600; color: var(--ink); }
.ct-mail a:hover { color: var(--blue-bright); }
.ct-copy {
  flex: none;
  padding: 6px 12px;
  border-radius: 7px;
  border: 0;
  font: inherit; font-size: 12px; font-weight: 700; color: #fff;
  background: var(--icon-gloss);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
  cursor: pointer;
}
.ct-copy.is-done { background: linear-gradient(160deg, var(--green-bright), var(--green)); }

/* ---- office + self-serve ---- */
.ct-split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(40px, 6vw, 88px); align-items: start; }
.ct-split h2 { font-size: clamp(26px, 2.6vw, 34px); font-weight: 800; margin: 14px 0 12px; }
.ct-office-sub { color: var(--mute); font-size: 16px; margin: 0 0 30px; max-width: 46ch; }

/* the address as a light postage label, the croc as the stamp */
.ct-label-card {
  position: relative;
  max-width: 470px;
  padding: 28px 30px 30px;
  border-radius: 16px;
  color: #172238;
  background:
    repeating-linear-gradient(135deg, #e5484d 0 10px, #fff 10px 20px, var(--blue) 20px 30px, #fff 30px 40px) top / 100% 6px no-repeat,
    linear-gradient(180deg, #ffffff, #eef3fb);
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.06), var(--shadow-lift);
}
.ct-label-to { display: block; margin: 10px 0 10px; font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #5a6582; }
.ct-label-card address { font-style: normal; font-size: 16px; line-height: 1.7; color: #33405e; }
.ct-label-card address strong { display: block; font-family: var(--font-display); font-size: 20px; font-weight: 800; color: #172238; }
.ct-stamp {
  position: absolute; top: 24px; right: 24px;
  width: 78px; height: 92px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  /* perforated edge: a dotted sheet of punch holes, with a solid fill
     covering everything but the outer 5px ring */
  background: radial-gradient(circle, transparent 2.6px, var(--blue) 3px) -5px -5px / 10px 10px;
  transform: rotate(4deg);
}
.ct-stamp::before {
  content: "";
  position: absolute; inset: 5px;
  background: linear-gradient(170deg, #2489ea, var(--blue-dark));
}
.ct-stamp > * { position: relative; }
.ct-stamp img { width: 44px; height: auto; }
.ct-stamp span { font-size: 9px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: #fff; }

.ct-help-list { list-style: none; margin: 20px 0 0; padding: 0; border-top: 1px solid var(--line); }
.ct-help-list a {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 4px;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.ct-help-list strong { display: flex; align-items: center; gap: 8px; font-family: var(--font-display); font-size: 17px; font-weight: 700; }
.ct-help-list small { display: block; margin-top: 3px; font-size: 14px; color: var(--mute); }
.ct-help-go { color: var(--blue-bright); transition: transform var(--dur-fast) var(--ease-out); }
.ct-help-list a:hover .ct-help-go,
.ct-help-list a:focus-visible .ct-help-go { transform: translateX(4px); }
.ct-social { display: flex; align-items: center; gap: 10px; margin-top: 26px; font-size: 14px; color: var(--mute); }
.ct-social span { margin-right: 6px; }
.ct-social a {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 10px;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line);
  transition: background var(--dur-fast) ease;
}
.ct-social a:hover { background: var(--tint-2); color: #fff; }

@media (max-width: 1080px) {
  .ct-dir { grid-template-columns: minmax(0, 1fr); }
  .ct-dir .section-head { position: static; }
}
@media (max-width: 900px) {
  .ct-hero-grid, .ct-split { grid-template-columns: minmax(0, 1fr); }
  .ct-hero .hero-copy { padding-top: 0; }
}
@media (max-width: 560px) {
  .ct-form { padding: 26px 20px; }
  .ct-topic-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ct-field-row { grid-template-columns: minmax(0, 1fr); }
  .ct-depts { grid-template-columns: minmax(0, 1fr); }
  .ct-dept:nth-child(even) { border-left: 0; }
  .ct-dept:nth-child(2) { border-top: 1px solid var(--line); }
  .ct-stamp { width: 62px; height: 74px; top: 18px; right: 18px; }
  .ct-stamp img { width: 34px; }
}

/* ==========================================================================
   Datacenter page (datacenter.html), added 2026-10-04.
   Copy and the four photos are from crocweb.com/about (Montreal data
   center, peering in New York and Toronto, nearly 100% hydroelectric
   power, outside-air cooling 80% of the year). The carrier list is the
   live page's five plus Hurricane Electric, added at the user's request.
   ASNs are the carriers' public AS numbers. The map's route dashes are
   the only loop, and .dc-route is on the .anim-offscreen list in main.js.
   ========================================================================== */

/* ---- hero: building photo, light location card, floating badge ---- */
.dc-hero-visual {
  position: relative;
  width: 100%;
  max-width: 620px;
  margin-left: auto;
  padding: 0 0 48px 28px;
}
.dc-hero-visual::before {
  content: "";
  position: absolute;
  inset: -6% -8%;
  z-index: 0;
  background: radial-gradient(ellipse farthest-side at 55% 45%, rgba(45, 212, 232, 0.14), rgba(10, 116, 218, 0.1) 55%, transparent 78%);
  pointer-events: none;
}
.dc-hero-photo {
  position: relative; z-index: 1;
  margin: 0;
  aspect-ratio: 3 / 2;
  border-radius: 20px;
  overflow: hidden;
  box-shadow:
    0 0 0 7px rgba(120, 160, 255, 0.07),
    0 0 0 8px rgba(255, 255, 255, 0.1),
    var(--shadow-lift);
}
.dc-hero-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* darken the photo's lower edge a touch so the card sits on it cleanly */
.dc-hero-photo::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(0, 0, 51, 0.35));
}

.dc-loc-card {
  position: absolute; z-index: 2;
  left: 0; bottom: 0;
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px 14px 14px;
  border-radius: 16px;
  color: #172238;
  background: linear-gradient(180deg, #ffffff, #eef3fb);
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.06), var(--shadow-lift);
}
.dc-loc-pin {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: 11px; color: #fff;
  background: var(--icon-gloss);
  box-shadow: var(--icon-gloss-shadow);
}
.dc-loc-card small { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: #5a6582; }
.dc-loc-card strong { font-family: var(--font-display); font-size: 17px; font-weight: 800; }
.dc-loc-live {
  display: inline-flex; align-items: center; gap: 7px;
  margin-left: 10px; padding: 5px 10px;
  border-radius: 999px;
  font-size: 11.5px; font-weight: 700; color: var(--green);
  background: rgba(39, 152, 50, 0.1);
}

.dc-hero-badge {
  position: absolute; z-index: 3;
  top: 26px; right: -18px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 14px 20px 12px;
  border-radius: 16px;
  color: #fff; text-align: center;
  background: linear-gradient(160deg, #3a9bff, var(--blue) 55%, #0757ad);
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow:
    0 0 0 6px rgba(120, 170, 255, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 22px 44px -14px rgba(10, 116, 218, 0.75);
}
.dc-hero-badge strong { font-family: var(--font-display); font-size: 28px; font-weight: 800; line-height: 1.05; }
.dc-hero-badge span { font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.9; }

/* ---- network: route map + carriers ---- */
.dc-network { position: relative; }
.dc-network::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(640px 420px at 92% 40%, rgba(45, 212, 232, 0.07), transparent 70%);
}
.dc-net-grid {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
  gap: 22px; align-items: stretch;
}

.dc-map {
  position: relative;
  min-height: 440px;
  border-radius: var(--radius-xl);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background:
    radial-gradient(620px 360px at 50% -10%, rgba(10, 116, 218, 0.16), transparent 70%),
    linear-gradient(165deg, rgba(14, 18, 70, 0.6), rgba(8, 10, 48, 0.6) 55%, rgba(5, 6, 34, 0.6));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}
.dc-map::after {
  content: ""; position: absolute; top: 0; left: 20%; right: 20%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(45, 212, 232, 0.7), transparent);
}
.dc-map-lines { position: absolute; inset: 0; width: 100%; height: 100%; }
.dc-route-base { fill: none; stroke: rgba(110, 168, 255, 0.22); stroke-width: 2; vector-effect: non-scaling-stroke; }
.dc-route {
  fill: none; stroke: var(--cyan); stroke-width: 2; vector-effect: non-scaling-stroke;
  stroke-dasharray: 6 14; stroke-linecap: round;
  animation: dc-flow 4.5s linear infinite;
}
.dc-route.r2 { animation-duration: 5.5s; }
@keyframes dc-flow { to { stroke-dashoffset: -40; } }

.dc-node {
  position: absolute; left: var(--x); top: var(--y);
  display: flex; align-items: center; gap: 12px;
  transform: translate(-14px, -50%);
}
.dc-node.is-left { flex-direction: row-reverse; transform: translate(calc(-100% + 14px), -50%); text-align: right; }
.dc-node-dot {
  width: 28px; height: 28px; flex: none;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 4px, var(--blue) 5px);
  box-shadow: 0 0 0 6px rgba(10, 116, 218, 0.18), 0 0 22px rgba(45, 212, 232, 0.45);
}
.dc-node.is-dc { transform: translate(-32px, -50%); }
.dc-node.is-dc .dc-node-dot {
  width: 64px; height: 64px;
  display: grid; place-items: center;
  background: linear-gradient(160deg, #3a9bff, var(--blue) 55%, #0757ad);
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow: 0 0 0 10px rgba(10, 116, 218, 0.16), 0 0 0 22px rgba(10, 116, 218, 0.07), 0 0 40px rgba(45, 212, 232, 0.4);
}
.dc-node.is-dc img { width: 40px; height: auto; }
.dc-node-label strong { display: block; font-family: var(--font-display); font-size: 17px; font-weight: 800; color: var(--ink); }
.dc-node-label small { font-size: 11px; font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--cyan); }
.dc-map-foot {
  position: absolute; left: 24px; right: 24px; bottom: 20px;
  display: flex; align-items: center; gap: 9px;
  margin: 0; padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 13.5px; color: var(--mute);
}

.dc-carriers {
  display: flex; flex-direction: column;
  border-radius: var(--radius-xl);
  border: 1px solid var(--line);
  background: var(--card-gradient);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}
.dc-carriers-label {
  margin: 0; padding: 20px 26px 14px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint);
}
.dc-carriers ul { list-style: none; margin: 0; padding: 0; flex: 1; display: flex; flex-direction: column; }
.dc-carriers li {
  flex: 1;
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px;
  padding: 14px 26px;
  border-top: 1px solid var(--line);
  transition: background var(--dur-fast) ease;
}
.dc-carriers li:hover { background: rgba(110, 168, 255, 0.05); }
.dc-carriers li { align-content: center; }
.dc-carriers strong { font-family: var(--font-display); font-size: 17px; font-weight: 800; }
.dc-carriers small { font-size: 13px; color: var(--faint); }
.dc-asn {
  margin-left: auto; align-self: center;
  padding: 5px 10px;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  background: rgba(3, 5, 32, 0.5);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; font-weight: 600; color: var(--blue-bright);
}

/* ---- facility gallery ---- */
.dc-split-head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 72px); align-items: end;
  margin-bottom: clamp(36px, 4vw, 52px);
}
.dc-split-head h2 { font-size: clamp(30px, 3.6vw, 44px); margin: 14px 0 0; }
.dc-split-head > p { margin: 0; max-width: 500px; color: var(--mute); font-size: 16.5px; line-height: 1.65; }
.dc-gallery {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  grid-template-rows: repeat(2, 260px);
  gap: 18px;
}
.dc-shot {
  position: relative; margin: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: var(--shadow-soft);
}
.dc-shot.is-tall { grid-row: span 2; }
.dc-shot img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.6s var(--ease-out); }
.dc-shot:hover img { transform: scale(1.03); }
.dc-shot figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column; gap: 2px;
  padding: 48px 22px 18px;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 40, 0.85));
}
.dc-shot figcaption strong { font-family: var(--font-display); font-size: 18px; font-weight: 800; color: #fff; }
.dc-shot figcaption span { font-size: 13.5px; color: rgba(244, 247, 253, 0.8); }

/* ---- clean energy ---- */
.dc-green { position: relative; }
.dc-green::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(600px 400px at 6% 50%, rgba(10, 116, 218, 0.1), transparent 70%);
}
.dc-energy {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(40px, 6vw, 80px); align-items: center;
}
.dc-energy .section-head { margin: 0; }
.dc-figures .aff-fact { padding: 36px 34px; }
.dc-figures .aff-fact strong { font-size: clamp(38px, 3.4vw, 48px); white-space: nowrap; }

@media (prefers-reduced-motion: reduce) { .dc-route { animation: none; } }

@media (max-width: 1080px) {
  .dc-net-grid, .dc-energy { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .dc-hero-visual { margin: 0 auto; }
  .dc-split-head { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .dc-gallery { grid-template-columns: minmax(0, 1fr); grid-template-rows: 300px 220px 220px; }
  .dc-shot.is-tall { grid-row: auto; }
}
@media (max-width: 560px) {
  .dc-hero-visual { padding: 0 0 56px; }
  .dc-hero-badge { right: 8px; top: 12px; padding: 10px 14px 9px; }
  .dc-hero-badge strong { font-size: 22px; }
  .dc-loc-card { left: 8px; right: 8px; }
  .dc-loc-live { margin-left: auto; }
  .dc-map { min-height: 380px; }
  .dc-carriers li { padding: 14px 20px; }
  .dc-figures { grid-template-columns: minmax(0, 1fr); }
}
.dc-dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--green-bright); box-shadow: 0 0 0 3px rgba(63, 201, 78, 0.18); }

/* map: faint uplinks from the peering points out to the carriers, plus a
   small legend in the empty top-left corner. Static, no animation. */
.dc-uplink { fill: none; stroke: rgba(110, 168, 255, 0.32); stroke-width: 1.5; stroke-dasharray: 3 6; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.dc-map-tag {
  position: absolute; top: 24px; right: 26px;
  display: flex; align-items: center; gap: 10px;
  margin: 0;
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint);
}
.dc-map-tag-line { width: 26px; height: 0; border-top: 1.5px dashed rgba(110, 168, 255, 0.4); }
/* the uplinks run under the map footer, so give it the panel's own fill */
.dc-map-foot { left: 0; right: 0; bottom: 0; padding: 16px 24px 20px; background: rgb(6, 8, 40); border-top-color: rgba(255, 255, 255, 0.08); }

/* "Nearly" sits small in front of the 100% figure */
.dc-hero-badge strong small,
.dc-figures .aff-fact strong small { font-size: 0.42em; font-weight: 700; letter-spacing: 0.02em; vertical-align: 0.5em; margin-right: 2px; }

/* ---------- Footer legal line + cookie consent (2026-10-04 SEO pass) ---------- */
.footer-legal { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.footer-legal a, .footer-cookie-btn { color: var(--mute); font-size: 14px; transition: color var(--dur-fast) ease; }
.footer-legal a:hover, .footer-legal a:focus-visible,
.footer-cookie-btn:hover, .footer-cookie-btn:focus-visible { color: var(--ink); }
.footer-legal-sep { width: 3px; height: 3px; border-radius: 50%; background: var(--faint); }
.footer-cookie-btn { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }

/* Consent panel: glass-recipe card pinned bottom-left, sits under the
   film-grain layer (z-index 200) but above the sticky header (100). */
.cookie-panel {
  position: fixed; left: 24px; bottom: 24px; z-index: 150;
  width: min(420px, calc(100% - 32px));
  padding: 22px 22px 20px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(420px 220px at 50% -10%, rgba(10, 116, 218, 0.18), transparent 70%),
    linear-gradient(165deg, rgba(21, 22, 95, 0.92), rgba(13, 14, 77, 0.94) 55%, rgba(9, 10, 60, 0.96));
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: var(--shadow-lift);
  color: var(--mute); font-size: 14px; line-height: 1.55;
}
.cookie-panel[hidden] { display: none; }
.cookie-panel h2 { font-size: 17px; margin: 0 0 6px; letter-spacing: -0.01em; }
.cookie-panel p { margin: 0 0 14px; }
.cookie-panel a { color: var(--blue-bright); }
.cookie-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.cookie-actions .btn { padding: 10px 16px; font-size: 13.5px; }
.cookie-prefs { margin: 0 0 16px; padding: 0; border: 0; display: grid; gap: 10px; }
.cookie-prefs[hidden] { display: none; }
.cookie-pref {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 14px; align-items: center;
  padding: 12px 14px; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: rgba(255, 255, 255, 0.04);
}
.cookie-pref strong { color: var(--ink); font-size: 14px; }
.cookie-pref small { grid-column: 1; font-size: 12.5px; color: var(--mute); }
.cookie-pref input { grid-row: 1 / span 2; grid-column: 2; width: 18px; height: 18px; accent-color: var(--blue); }
@media (max-width: 560px) {
  .cookie-panel { left: 16px; right: 16px; bottom: 16px; width: auto; padding: 18px; }
  .cookie-actions .btn { flex: 1 1 auto; justify-content: center; }
}

/* 404 page: reuses .legal-hero and the contact page's .ct-help-list */
.error-hero .hero-actions { margin-top: 8px; }
.error-links { padding-top: 0; }
.error-links .ct-help { max-width: 640px; }
.error-links h2 { font-size: clamp(24px, 2.4vw, 30px); }

/* ---------- Homepage hero buttons on narrow phones (2026-10-05) ---------- */
/* At 18px/32px padding, Get Started + WordPress Hosting needed ~414px, so
   on phones like the Galaxy Fold cover screen (~412px) the second button
   dropped to its own line. Tighter padding and equal flex shares keep them
   on one row down to ~360px. Below that they stack full width so neither
   ends up as an odd half-width button. */
@media (max-width: 480px) {
  .hero-actions { flex-wrap: nowrap; gap: 8px; }
  .hero-actions .btn { flex: 1 1 auto; justify-content: center; padding: 15px 12px; font-size: 15px; white-space: nowrap; }
}
@media (max-width: 359px) {
  .hero-actions { flex-wrap: wrap; }
  .hero-actions .btn { flex-basis: 100%; }
}
