/* ============================================================
   Printout Designer — Design Tokens
   Brand colors extracted from live site (printoutdesigner.com)
   and logo_blue_white.png. Typography matches existing brand
   (Raleway headings / Open Sans body) for continuity.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700;800&display=swap');

:root {
  /* Brand blue family (derived from hero bg rgba(27,117,187,.9) + logo gradient) */
  --color-primary: #1B75BB;
  --color-primary-dark: #124A78;
  --color-primary-darker: #0D3557;
  --color-primary-light: #58A8DE;
  --color-primary-tint: #EAF4FC;

  --color-on-primary: #FFFFFF;

  --color-background: #FFFFFF;
  --color-surface: #F6F9FC;
  --color-surface-alt: #F1F3F5;

  --color-foreground: #1E2733;
  --color-muted-foreground: #5B6672;
  --color-border: #E3E8EE;

  --color-success: #1E8E5A;
  --color-focus-ring: #1B75BB;

  /* Type */
  --font-heading: 'Geist', 'Helvetica Neue', Arial, sans-serif;
  --font-body: 'Geist', 'Helvetica Neue', Arial, sans-serif;

  --fs-body: 1rem;
  --fs-sm: 0.875rem;
  --fs-lg: 1.125rem;
  --fs-h1: clamp(2.1rem, 4.5vw, 3.25rem);
  --fs-h2: clamp(1.6rem, 3vw, 2.25rem);
  --fs-h3: 1.25rem;

  --lh-body: 1.6;

  /* Space scale (marketing/landing density = spacious) */
  --space-2xs: 0.25rem;
  --space-xs: 0.5rem;
  --space-sm: 0.75rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2.5rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(16, 42, 67, 0.06);
  --shadow-md: 0 8px 24px rgba(16, 42, 67, 0.10);
  --shadow-lg: 0 20px 48px rgba(16, 42, 67, 0.16);

  --transition-fast: 180ms ease;
  --transition-base: 260ms ease;

  --container-w: 1180px;
}

/* ============================================================
   Reset
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul { list-style: none; margin: 0; padding: 0; }
img, video { max-width: 100%; display: block; }
/* Every img carries its file's real width and height so the browser can
   reserve the space before it loads; height: auto keeps those attributes
   to an aspect ratio, so the CSS still decides the displayed size. */
img { height: auto; }
/* A <picture> added only to offer a WebP version generates no box of its
   own, so the img inside is laid out exactly as if it stood alone. */
picture:has(> source[type="image/webp"]) { display: contents; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-foreground);
  background: var(--color-background);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.2;
  color: var(--color-primary-darker);
}

h1 { font-size: var(--fs-h1); font-weight: 800; }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); font-weight: 600; }

.container {
  width: 100%;
  max-width: var(--container-w);
  margin-inline: auto;
  padding-inline: var(--space-lg);
}

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

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute;
  left: var(--space-md);
  top: -60px;
  background: var(--color-primary-darker);
  color: #fff;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  z-index: 100;
  transition: top var(--transition-fast);
}
.skip-link:focus { top: var(--space-md); }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-heading);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.eyebrow::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--color-primary-light), var(--color-primary));
}

.section {
  padding-block: var(--space-3xl);
}
.section--alt { background: var(--color-surface); }
.section-head {
  max-width: 640px;
  margin-bottom: var(--space-2xl);
}
.section-head.center { margin-inline: auto; text-align: center; }
.section-head p {
  margin-top: var(--space-sm);
  color: var(--color-muted-foreground);
  font-size: var(--fs-lg);
}

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-body);
  padding: 0.85rem 1.6rem;
  border-radius: var(--radius-pill);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast), color var(--transition-fast);
  cursor: pointer;
  white-space: nowrap;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  /* Both stops verified >= 4.5:1 contrast with white text (WCAG AA) */
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
  color: var(--color-on-primary);
  box-shadow: var(--shadow-md);
}
.btn--primary:hover { box-shadow: var(--shadow-lg); }

.btn--ghost {
  background: transparent;
  color: var(--color-primary-darker);
  border: 1.5px solid var(--color-border);
}
.btn--ghost:hover { border-color: var(--color-primary); background: var(--color-primary-tint); }

.btn--on-dark {
  background: rgba(255,255,255,0.12);
  color: #fff;
  border: 1.5px solid rgba(255,255,255,0.4);
  backdrop-filter: blur(4px);
}
.btn--on-dark:hover { background: rgba(255,255,255,0.22); }

.btn--sm { padding: 0.6rem 1.1rem; font-size: var(--fs-sm); }
.btn--block { width: 100%; }

/* ============================================================
   Header / Nav
   ============================================================ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255,255,255,0.9);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--color-border);
}
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-block: var(--space-sm);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--color-primary-darker);
  min-width: 0;
  flex-shrink: 1;
}
.brand img { height: 34px; width: auto; flex-shrink: 0; }
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  flex-shrink: 0;
}
.nav-links a {
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--color-foreground);
  transition: color var(--transition-fast);
}
.nav-links a:hover { color: var(--color-primary); }

.nav-dropdown { position: relative; }
.nav-dropdown-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--color-foreground);
  transition: color var(--transition-fast);
}
.nav-dropdown-toggle:hover { color: var(--color-primary); }
.nav-dropdown-toggle .chev { width: 14px; height: 14px; transition: transform var(--transition-fast); }
.nav-dropdown.is-open .nav-dropdown-toggle .chev { transform: rotate(180deg); }
.nav-dropdown-menu {
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  min-width: 210px;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-xs);
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 4px);
  transition: opacity var(--transition-fast), transform var(--transition-fast), visibility var(--transition-fast);
  z-index: 60;
}
.nav-dropdown.is-open .nav-dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.nav-dropdown-menu a {
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-foreground);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.nav-dropdown-menu a:hover { background: var(--color-surface-alt); color: var(--color-primary); }
.nav-dropdown-menu--wide { min-width: 250px; }
.nav-dropdown-group-label {
  padding: 0.4rem 0.75rem 0.2rem;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted-foreground);
}
.nav-dropdown-divider {
  height: 1px;
  background: var(--color-border);
  margin: var(--space-xs) 0.5rem;
}

/* Active-page highlighting */
.nav-links > a[aria-current="page"] { color: var(--color-primary); }
.nav-dropdown-menu a[aria-current="page"] { color: var(--color-primary); background: var(--color-primary-tint); }
.nav-dropdown:has(a[aria-current="page"]) > .nav-dropdown-toggle { color: var(--color-primary); }

.mobile-menu-label {
  margin-top: var(--space-sm);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted-foreground);
}
.mobile-menu a.sub-link { padding-left: var(--space-md); font-size: 0.92rem; }

.nav-actions { display: flex; align-items: center; gap: var(--space-md); flex-shrink: 0; }

.nav-toggle {
  display: none;
  padding: var(--space-xs);
  flex-shrink: 0;
}
.nav-toggle svg { width: 26px; height: 26px; }

@media (max-width: 860px) {
  .nav-links { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-actions .btn--ghost.login-link { display: none; }
}

@media (max-width: 480px) {
  .nav-actions .btn--primary.btn--sm { padding: 0.65rem 1rem; font-size: var(--fs-sm); }
}

@media (max-width: 860px) {

  .mobile-menu {
    display: none;
    flex-direction: column;
    gap: var(--space-md);
    padding: var(--space-lg);
    border-top: 1px solid var(--color-border);
    background: var(--color-background);
  }
  .mobile-menu.is-open { display: flex; }
  .mobile-menu a { font-weight: 600; padding-block: var(--space-xs); }
}
@media (min-width: 861px) {
  .mobile-menu { display: none !important; }
}

/* ============================================================
   Hero
   ============================================================ */
.hero {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-3xl) calc(var(--space-3xl) + 1rem);
  background:
    radial-gradient(1100px 480px at 85% -10%, rgba(88,168,222,0.25), transparent 60%),
    linear-gradient(180deg, var(--color-surface) 0%, var(--color-background) 55%);
}
.hero-grid {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: var(--space-2xl);
  align-items: center;
}
.hero h1 { margin-top: var(--space-md); }
.hero-lede {
  margin-top: var(--space-md);
  font-size: var(--fs-lg);
  color: var(--color-muted-foreground);
  max-width: 46ch;
}
.hero-ctas {
  margin-top: var(--space-xl);
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
}
.hero-note {
  margin-top: var(--space-md);
  font-size: var(--fs-sm);
  color: var(--color-muted-foreground);
}
.hero-note strong { color: var(--color-foreground); }

.hero-checklist {
  margin-top: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: 46ch;
}
.hero-checklist li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--color-foreground);
}
.hero-checklist svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--color-success); margin-top: 2px; }

.hero-media {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  align-items: center;
}
.hero-window {
  position: relative;
  width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  aspect-ratio: 3 / 4;
  background: var(--color-background);
  border: 1px solid var(--color-border);
}
.hero-window-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-sm) var(--space-md);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}
.hero-window-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.hero-window-dot--red { background: #ED6A5E; }
.hero-window-dot--yellow { background: #F4BF4F; }
.hero-window-dot--green { background: #61C454; }
.hero-window-bar-line {
  flex: 1;
  height: 8px;
  margin-left: var(--space-sm);
  border-radius: var(--radius-pill);
  background: var(--color-border);
  max-width: 160px;
}
/* ============================================================
   Hero flow SVG (design -> print -> email cross-fading scenes)
   All animation/keyframe logic lives inline in the SVG's own
   <style> block in index.html (self-contained, like a standalone
   asset). This wrapper just centers it and gives it a backdrop.
   ============================================================ */
.editor-demo {
  height: calc(100% - 33px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-sm);
  background:
    radial-gradient(420px 260px at 50% 0%, var(--color-primary-tint), transparent 70%),
    var(--color-background);
}
.editor-demo .hf-svg { width: 100%; height: 100%; display: block; }

/* ============================================================
   Order-flow illustration (order -> document -> print/email)
   Not used in the hero anymore — reserved for the "How it works"
   section. Safe to delete if that section ends up not needing it.
   ============================================================ */
.flow-line {
  width: 3px;
  height: 36px;
  border-radius: var(--radius-pill);
  background: repeating-linear-gradient(180deg, var(--color-primary) 0 5px, transparent 5px 11px);
  background-size: 3px 22px;
  animation: flow-dash-move 0.9s linear infinite;
}

@keyframes flow-dash-move {
  to { background-position: 0 -22px; }
}

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

@media (max-width: 960px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-media { order: -1; max-width: 360px; margin-inline: auto; }
}

/* ============================================================
   How it works: a horizontal carousel, one step's full panel visible
   at a time. main.js slides the outgoing panel out and the incoming
   one in (direction depends on step order), with .hiw-panels clipping
   the motion and briefly animating its own height between the two
   panels' natural heights. There is no top tab bar; each panel's own
   numbered badge (.hiw-step-badge/.hiw-step-label) is the visual
   indicator of which step is active. Step 3's nested sub-tabs (further
   below) are a separate, simpler crossfade. prefers-reduced-motion
   swaps both instantly, no animation.
   ============================================================ */
.hiw-carousel {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}
.hiw-panels {
  position: relative;
  overflow: hidden;
  flex: 1;
  min-width: 0;
}
.hiw-step {
  display: flex;
  flex-direction: column;
  padding-block: var(--space-xl);
}
.hiw-step[hidden] { display: none; }
.hiw-step.is-sliding {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  transition: transform 380ms ease;
}
.hiw-step-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: var(--space-2xl);
}
.hiw-step-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}
.hiw-step-badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--color-primary-tint);
  color: var(--color-primary-darker);
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}
.hiw-step-label {
  font-family: var(--font-heading);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--color-muted-foreground);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.hiw-step-text h3 {
  font-size: clamp(1.35rem, 2.2vw, 1.75rem);
  margin-bottom: var(--space-md);
}
.hiw-step-text p {
  font-size: var(--fs-lg);
  color: var(--color-muted-foreground);
  line-height: var(--lh-body);
}
.hiw-step-text .hero-checklist,
.hiw-step-text .hero-ctas { max-width: none; }
.hiw-text-link {
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--color-primary);
  align-self: center;
}
.hiw-text-link:hover,
.hiw-text-link:focus-visible { text-decoration: underline; }

.hiw-step-visual {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: linear-gradient(160deg, var(--color-primary-tint), var(--color-surface) 70%);
}
.hiw-step-visual svg { width: 100%; height: auto; max-width: 440px; }

/* Step 1's mockup: a static 2x2 grid of real, clickable platform cards.
   Scoped to #hiw-step-1 specifically (not the shared .hiw-step-grid
   default) so its visual column stretches to match the full height of
   the text column next to it, while Steps 2 and 3 keep the shared
   vertically-centered behavior untouched. */
#hiw-step-1 .hiw-step-grid { align-items: stretch; }
#hiw-step-1 .hiw-step-visual { align-items: stretch; }
.hiw-platform-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(2, 1fr);
  gap: var(--space-lg);
  width: 100%;
}
.hiw-platform-card {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast);
}
.hiw-platform-card:hover, .hiw-platform-card:focus-visible {
  border-color: var(--color-primary);
  box-shadow: var(--shadow-sm);
  transform: translateY(-2px);
}
.hiw-platform-card img { max-width: 85%; max-height: 88px; width: auto; height: auto; object-fit: contain; }
.hiw-platform-card--light { background: var(--color-surface-alt); }
.hiw-platform-card--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); }
.hiw-platform-card--ecwid { background: linear-gradient(160deg, var(--color-primary-light), var(--color-primary-darker)); }

.hiw-step-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-sm);
  text-align: center;
  margin-top: var(--space-xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border);
}
.hiw-step-footer p {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--color-muted-foreground);
}
.hiw-step-next {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--color-primary);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.hiw-step-next:hover, .hiw-step-next:focus-visible { text-decoration: underline; }

.hiw-progress {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  margin-top: var(--space-lg);
}
.hiw-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  padding: 0;
  border: none;
  background: var(--color-border);
  cursor: pointer;
  transition: background var(--transition-fast), transform var(--transition-fast);
}
.hiw-dot.is-active { background: var(--color-primary); transform: scale(1.3); }
.hiw-dot:hover { background: var(--color-primary-light); }
.hiw-dot:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }

/* Step 2's "browser window" mockup chrome: a segmented tab toggle strip
   at the top (decorative, only the active tab's content is shown),
   matching the composition of the reference screenshots (toolbar +
   tabs + preview panel). */
.hiw-window {
  width: 100%;
  max-width: 440px;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.hiw-window-tabs {
  display: flex;
  gap: var(--space-2xs);
  padding: var(--space-md) var(--space-md) 0;
}
.hiw-window-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  font-family: var(--font-heading);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--color-muted-foreground);
  background: var(--color-surface-alt);
}
.hiw-window-tab.is-active {
  background: var(--color-primary);
  color: #FFFFFF;
}
.hiw-window-tab-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.85;
}

/* Tab 2 content: components sidebar + a live invoice preview */
.hiw-editor-body {
  display: flex;
  gap: var(--space-md);
  padding: var(--space-md);
  padding-top: var(--space-sm);
}
.hiw-editor-sidebar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 0 0 100px;
}
.hiw-editor-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-surface-alt);
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--color-foreground);
}
.hiw-editor-item svg { width: 13px; height: 13px; color: var(--color-primary); flex-shrink: 0; }
.hiw-editor-preview {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: #FFFFFF;
  padding: var(--space-md);
}
.hiw-invoice-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-sm);
}
.hiw-invoice-title { font-family: var(--font-heading); font-weight: 800; font-size: 1rem; color: var(--color-primary-darker); }
.hiw-invoice-meta { text-align: right; display: flex; flex-direction: column; gap: 2px; }
.hiw-invoice-meta span { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.04em; color: var(--color-muted-foreground); }
.hiw-invoice-meta strong { font-size: 0.78rem; color: var(--color-foreground); }
.hiw-invoice-parties { display: flex; gap: var(--space-md); padding-bottom: var(--space-sm); border-bottom: 1px solid var(--color-border); margin-bottom: var(--space-sm); }
.hiw-invoice-parties > div { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.hiw-invoice-parties span { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.04em; color: var(--color-muted-foreground); }
.hiw-invoice-parties strong { font-size: 0.74rem; color: var(--color-foreground); }
.hiw-invoice-parties i { display: block; height: 5px; width: 70%; border-radius: 3px; background: var(--color-border); font-style: normal; }
.hiw-invoice-table { width: 100%; border-collapse: collapse; margin-bottom: var(--space-sm); }
.hiw-invoice-table th {
  text-align: left;
  font-family: var(--font-heading);
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--color-muted-foreground);
  padding-bottom: 6px;
}
.hiw-invoice-table th:nth-child(2), .hiw-invoice-table td:nth-child(2),
.hiw-invoice-table th:last-child, .hiw-invoice-table td:last-child { text-align: right; }
.hiw-invoice-table td { padding: 5px 0; font-size: 0.72rem; color: var(--color-foreground); border-top: 1px solid var(--color-border); }
.hiw-invoice-table .hiw-line { display: block; height: 6px; width: 70%; border-radius: 3px; background: var(--color-border); }
.hiw-invoice-totals {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  padding-top: var(--space-sm);
  border-top: 1px solid var(--color-border);
}
.hiw-invoice-totals-row { display: flex; justify-content: space-between; width: 60%; font-size: 0.72rem; color: var(--color-muted-foreground); padding: 2px 0; }
.hiw-invoice-totals-row--total {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.85rem;
  color: var(--color-primary-darker);
  padding-top: 6px;
  margin-top: 4px;
  border-top: 1px solid var(--color-border);
}

/* Step 3: selector buttons live in the LEFT column, stacked below the
   description (.hiw-subtablist, inside .hiw-step-text); the RIGHT
   column is a single card (.hiw-subpanels) showing whichever option's
   heading, description, checklist and CTA is currently selected. */
.hiw-subtablist {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin-top: var(--space-lg);
}
.hiw-subtab {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  text-align: left;
  padding: var(--space-sm) var(--space-md);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  font-family: var(--font-heading);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-muted-foreground);
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}
.hiw-subtab-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  background: var(--color-surface-alt);
  color: var(--color-muted-foreground);
  flex-shrink: 0;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.hiw-subtab-icon svg { width: 16px; height: 16px; }
.hiw-subtab[aria-selected="true"] {
  border-color: var(--color-primary);
  color: var(--color-primary-darker);
  background: var(--color-primary-tint);
  font-weight: 700;
}
.hiw-subtab[aria-selected="true"] .hiw-subtab-icon {
  background: var(--color-primary);
  color: #FFFFFF;
}
.hiw-subtab:hover { border-color: var(--color-primary-light); }
.hiw-subtab:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }

.hiw-subpanels {
  position: relative;
  height: 540px;
  overflow-y: auto;
  padding: var(--space-lg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-alt);
}
.hiw-subpanel {
  opacity: 1;
  transition: opacity var(--transition-base);
}
.hiw-subpanel[hidden] { display: none; }
.hiw-subpanel.is-fading { opacity: 0; }
.hiw-subpanel-title {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--color-primary-darker);
  margin-bottom: var(--space-sm);
}
.hiw-subpanel p { color: var(--color-muted-foreground); }
.hiw-subpanel p.hiw-subpanel-title { color: var(--color-primary-darker); }
.hiw-subpanel .hero-checklist { margin-top: var(--space-md); margin-bottom: var(--space-lg); max-width: none; }

@media (prefers-reduced-motion: reduce) {
  .hiw-step.is-sliding { transition: none; }
  .hiw-subpanel { transition: none; }
}

@media (max-width: 760px) {
  .hiw-step-grid { grid-template-columns: 1fr; }
  .hiw-carousel { gap: var(--space-sm); }
}

/* ============================================================
   Template gallery (horizontal carousel with arrow controls)
   ============================================================ */
.carousel {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.carousel-arrow {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  color: var(--color-primary-darker);
  box-shadow: var(--shadow-sm);
  transition: background var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast), opacity var(--transition-fast);
}
.carousel-arrow svg { width: 20px; height: 20px; }
.carousel-arrow:hover:not(:disabled) { background: var(--color-primary); color: #fff; box-shadow: var(--shadow-md); }
.carousel-arrow:disabled { opacity: 0.35; cursor: default; }

.gallery-grid {
  display: flex;
  gap: var(--space-lg);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-block: var(--space-2xs);
  scrollbar-width: none;
}
.gallery-grid::-webkit-scrollbar { display: none; }
.gallery-card {
  flex: 0 0 clamp(240px, 30%, 300px);
  scroll-snap-align: start;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.gallery-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.gallery-thumb {
  aspect-ratio: 4 / 5;
  background: var(--color-surface-alt);
  overflow: hidden;
  border-bottom: 1px solid var(--color-border);
}
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.gallery-card-body { padding: var(--space-lg); }
.gallery-card-body .tag {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  /* primary-dark, not primary: primary-on-tint measures 4.37:1, below WCAG AA 4.5:1 */
  color: var(--color-primary-dark);
  background: var(--color-primary-tint);
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-sm);
}
.gallery-card-body h3 { margin-bottom: var(--space-xs); }
.gallery-card-body p { color: var(--color-muted-foreground); font-size: var(--fs-sm); }

@media (max-width: 620px) {
  .gallery-card { flex-basis: 78%; }
  .carousel-arrow { width: 38px; height: 38px; }
}

/* ============================================================
   Homepage template gallery: an infinite single-focus coverflow over a
   curated list of 7 templates. .template-window always holds 5 slots:
   2 fully hidden buffers (one past each edge of the viewport) plus the
   3 simultaneously visible ones, a peek card, the full-size focused
   main card, and another peek card, all uncropped inside an
   overflow:hidden viewport.

   Each slot is absolutely positioned and centered via its own
   translateX/scale (main.js computes each one from its "offset from
   center", -2..+2), rather than laid out as flex items. This is
   deliberate: the main card is sized substantially larger than the
   peeks (not just a subtle scale, a real width difference), and a
   shared flex row can only ever divide the viewport into equal-width
   columns, which would cap the main card at 1/3 of the available width
   no matter how high any max-width were set. Per-slot absolute
   positioning removes that ceiling, and since role (which slot is
   .is-main) is purely a function of array position (index 2 of the 5,
   tracked in JS, not DOM order), a step only ever needs to update each
   element's own target transform/opacity, no shared parent transform
   to slide and no DOM reordering.

   main.js sizes the main card as large as possible while keeping the
   whole card (image + caption) within the viewport height at 100%
   zoom, and derives the peek size and inter-card spacing from it, so
   the two stay visually balanced at any size. No dots, no auto-advance,
   arrows only. Reuses .gallery-card/.gallery-thumb/.gallery-card-body
   as-is for each card (shared with the /templates grid pages, which
   still show the category tag and description, untouched), only the
   outer windowing layout and the simplified (name-only) card caption
   are specific to this section.
   ============================================================ */
/* Scoped section-spacing overrides: noticeably less top/bottom padding
   and a tighter heading-to-cards gap than the sitewide .section/
   .section-head defaults, so this section doesn't feel stretched with
   empty space. Other sections' spacing is untouched. */
#templates { padding-block: var(--space-lg) var(--space-xl); }
#templates .section-head { margin-bottom: var(--space-md); }

.template-window-viewport { position: relative; flex: 1; min-width: 0; overflow: hidden; }
/* Height is set by main.js (main card height + caption height) since
   absolutely positioned children can't size this element themselves. */
.template-window { position: relative; }
.template-slot {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--template-main-w, 460px);
  transition: transform var(--transition-base), opacity var(--transition-base);
}
.template-slot .gallery-card { height: 100%; }
/* Peek cards (both visible side peeks and the 2 hidden buffers beyond
   the viewport edges) read as receding beside the focused main card:
   noticeably smaller (via the scale in each slot's own transform, set
   by main.js), faded and cast with a soft drop shadow, rather than
   sharing the main card's plain default card shadow. */
.template-slot.is-peek { opacity: 0.55; }
.template-slot.is-peek .gallery-card { box-shadow: var(--shadow-lg); }
/* Full-page document screenshots need to show the whole page, not a
   cropped top corner like .gallery-thumb's default `cover` crop.
   Aspect ratio close to a real document page (~0.71) and minimal
   padding so the image itself fills nearly the whole box, since
   letterboxing whitespace directly works against reading line items,
   layout and branding at a glance. */
.template-slot .gallery-thumb {
  aspect-ratio: 5 / 7;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2xs);
}
.template-slot .gallery-thumb img { width: 100%; height: 100%; object-fit: contain; object-position: center; }
/* No category tag here (unlike the /templates grid pages' cards), just
   the template name as a single centered line. */
.template-slot .gallery-card-body { padding: var(--space-md) var(--space-lg); text-align: center; }
.template-slot .gallery-card-body h3 { margin-bottom: 0; font-size: var(--fs-body); }

@media (prefers-reduced-motion: reduce) {
  .template-slot { transition: none; }
}

@media (max-width: 760px) {
  /* A coverflow with peeks stops making sense once the card stacks
     full-width, so mobile drops the peek treatment and per-slot
     positioning entirely (main.js skips the slide animation at this
     width too) and just shows the single focused main card in normal
     flow. Targeted by the .is-main/.is-peek class (which slot currently
     holds which role), not DOM position, since main.js never reorders
     the DOM in this design. */
  .template-window { position: static; height: auto !important; }
  .template-slot.is-peek { display: none; }
  .template-slot.is-main {
    position: static;
    width: 100%;
    max-width: 360px;
    margin-inline: auto;
    transform: none !important;
    opacity: 1;
  }
}

/* ============================================================
   Pricing
   ============================================================ */
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-lg);
  align-items: stretch;
}
.price-card {
  display: flex;
  flex-direction: column;
  padding: var(--space-xl) var(--space-lg);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  position: relative;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.price-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.price-card--featured {
  border-color: var(--color-primary);
  background: linear-gradient(180deg, var(--color-primary-tint), var(--color-background) 40%);
  box-shadow: var(--shadow-md);
}
.price-badge {
  position: absolute;
  top: -14px; left: var(--space-lg);
  background: var(--color-primary);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.3rem 0.75rem;
  border-radius: var(--radius-pill);
}
.price-card h3 { font-family: var(--font-heading); }
.price-amount {
  margin-top: var(--space-md);
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
}
.price-amount .num {
  font-family: var(--font-heading);
  font-size: 2.4rem;
  font-weight: 800;
  color: var(--color-primary-darker);
}
.price-amount .period { color: var(--color-muted-foreground); font-size: var(--fs-sm); }
.price-card .price-desc {
  margin-top: var(--space-xs);
  color: var(--color-muted-foreground);
  font-size: var(--fs-sm);
}
.price-card .price-desc + .price-desc { margin-top: 2px; }
.price-card .price-desc strong {
  color: var(--color-primary-darker);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.05rem;
}
.price-features {
  margin-top: var(--space-lg);
  padding-top: var(--space-lg);
  margin-bottom: var(--space-lg);
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  flex: 1;
}
.price-features li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
  font-size: var(--fs-sm);
  color: var(--color-foreground);
}
.price-features svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--color-success); margin-top: 2px; }
.price-features li.is-excluded { color: var(--color-muted-foreground); text-decoration: line-through; text-decoration-color: var(--color-border); }
.price-features li.is-excluded svg { color: var(--color-border); }

@media (max-width: 980px) {
  .pricing-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .pricing-grid { grid-template-columns: 1fr; }
  .price-card--featured { order: -1; }
}

/* ============================================================
   Stats strip
   ============================================================ */
.stats-panel {
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--color-primary-tint), var(--color-surface) 70%);
  border: 1px solid var(--color-border);
  padding: var(--space-lg);
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
}
.stat-card {
  display: block;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
}
.stat-card--link {
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}
.stat-card--link:hover, .stat-card--link:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-primary);
}
.stat-card .stat-num {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.9rem;
  color: var(--color-primary-darker);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}
.stat-card .stat-num .plus { color: var(--color-primary); }
.stat-card .stat-num .star { color: #F5A623; font-size: 1.3rem; }
.stat-card p { margin-top: var(--space-2xs); color: var(--color-muted-foreground); font-size: var(--fs-sm); }
.stat-card img.stat-icon { height: 22px; width: auto; margin-bottom: var(--space-xs); }
.stat-capterra-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-2xs);
}
.stat-card img.stat-icon--capterra { height: 48px; width: auto; margin-bottom: 0; }
/* Same row layout as .stat-capterra-row, for platform pages rating
   their own app store instead of Capterra - the platform's logo (e.g.
   Shopify's, only available as a white/inverted mark) needs its own
   brand-color tile behind it rather than sitting bare on the card's
   white background like the plain Capterra wordmark does. */
.stat-icon-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.stat-icon-tile--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); }
.stat-icon-tile--shopify img { width: 65%; height: auto; }
/* BigCommerce's logo is already full-color (unlike Shopify's white/
   inverted-only mark), so it just needs a light neutral tile rather
   than a brand-color gradient, matching its .connect-tile--light and
   .platform-pick-card--light treatment elsewhere. */
.stat-icon-tile--bigcommerce { background: var(--color-surface-alt); }
.stat-icon-tile--bigcommerce img { width: 85%; height: auto; }

@media (max-width: 860px) {
  .stats-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Logo marquee (case studies). Fixed-width viewport (~4 logos),
   centered under the heading. JS (see main.js) renders the
   CASE_STUDY_LOGOS array once, duplicates that pass for a seamless
   loop, and measures the exact pixel shift so a constant px/s
   speed holds regardless of how many logos are in the array.
   Spacing itself is a plain fixed CSS gap, not JS-computed.
   Reduced motion (or before JS runs): a static row of the first
   few logos, centered, no scrolling.
   ============================================================ */
.marquee-head {
  text-align: center;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
  margin-top: var(--space-lg);
  margin-bottom: var(--space-md);
}
.marquee {
  position: relative;
  overflow: hidden;
  width: 100%;
  /* Wide enough that the reduced-motion / no-JS fallback keeps five logos on
     one line at desktop (they need 619px), with room for a sixth. The
     animated loop is not bound by this any more: main.js duplicates the logo
     pass until the track outruns whatever width this resolves to. */
  max-width: 780px;
  margin-inline: auto;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
}
.marquee-track.is-animated {
  flex-wrap: nowrap;
  width: max-content;
  animation: marquee-scroll var(--marquee-duration, 28s) linear infinite;
}
.marquee:hover .marquee-track.is-animated,
.marquee:focus-within .marquee-track.is-animated {
  animation-play-state: paused;
}
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-1 * var(--marquee-shift, 50%))); }
}
.marquee-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 64px;
  padding: var(--space-sm) var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  flex-shrink: 0;
}
.marquee-logo:hover, .marquee-logo:focus-visible { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.marquee-logo img { height: 28px; width: auto; max-width: 140px; object-fit: contain; }

/* ============================================================
   Case studies teaser (testimonial cards)
   ============================================================ */
.cs-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-bottom: var(--space-2xl);
  flex-wrap: wrap;
}
.cs-head h2 { margin-top: var(--space-xs); }
.cs-head p { margin-top: var(--space-sm); color: var(--color-muted-foreground); max-width: 56ch; }
.cs-head-cta { flex-shrink: 0; }

.cs-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
}
.cs-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-lg);
  padding-top: calc(var(--space-lg) + 4px);
  overflow: hidden;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast), background-color var(--transition-fast);
}
.cs-card:hover, .cs-card:focus-within {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
  border-color: var(--color-primary);
  background: var(--color-primary-tint);
}
.cs-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--color-primary-light), var(--color-primary));
}
.cs-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--space-sm);
  flex-shrink: 0;
}
.cs-stars { color: #F5A623; letter-spacing: 2px; font-size: 0.9rem; }
.cs-quote-icon { width: 32px; height: 32px; color: var(--color-border); transition: color var(--transition-fast); flex-shrink: 0; }
.cs-card:hover .cs-quote-icon, .cs-card:focus-within .cs-quote-icon { color: rgba(27,117,187,0.25); }
.cs-quote { color: var(--color-foreground); margin-bottom: var(--space-md); flex: 1; }
.cs-divider { border-top: 1px solid var(--color-border); margin-bottom: var(--space-md); flex-shrink: 0; }
.cs-who { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-md); flex-shrink: 0; }
.cs-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: contain;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  padding: 4px;
  flex-shrink: 0;
}
.cs-avatar--photo { object-fit: cover; padding: 0; }
.cs-name { font-weight: 700; font-size: 0.95rem; color: var(--color-primary-darker); }
.cs-role { font-size: var(--fs-sm); color: var(--color-primary); }
.cs-footer-bottom { display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm); flex-shrink: 0; }
.cs-link { font-weight: 700; font-size: var(--fs-sm); color: var(--color-primary); }
.cs-link:hover { text-decoration: underline; }
.cs-flag-badge {
  width: 30px; height: 22px;
  border-radius: 4px;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  border: 1px solid var(--color-border);
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.08);
}
.cs-flag-badge img { width: 100%; height: 100%; object-fit: cover; display: block; }

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

/* ============================================================
   Before / after comparison slider
   ============================================================ */
.compare {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--color-border);
  aspect-ratio: 4 / 3;
  max-width: 640px;
  margin-inline: auto;
  user-select: none;
  touch-action: pan-y;
}
.compare-after { clip-path: inset(0 0 0 50%); }
.compare-handle {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 0;
  transform: translateX(-50%);
  z-index: 3;
}
.compare-handle::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 50%;
  width: 3px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.08);
  transform: translateX(-50%);
}
.compare-grip {
  position: absolute;
  top: 50%; left: 50%;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-md);
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translate(-50%, -50%);
  cursor: ew-resize;
  border: none;
}
.compare-grip svg { width: 20px; height: 20px; color: var(--color-primary); }
/* ============================================================
   Breadcrumbs (every page except the homepage and 404)
   ============================================================ */
.breadcrumbs {
  margin-bottom: var(--space-sm);
  overflow-x: auto;
}
.breadcrumbs ol {
  display: flex;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
  white-space: nowrap;
  font-size: var(--fs-sm);
  color: var(--color-muted-foreground);
}
.breadcrumbs li:not(:first-child)::before {
  content: "/";
  margin: 0 var(--space-xs);
  color: var(--color-border);
}
.breadcrumbs a { color: var(--color-muted-foreground); transition: color var(--transition-fast); }
.breadcrumbs a:hover { color: var(--color-primary); }
.breadcrumbs li[aria-current="page"] { color: var(--color-foreground); font-weight: 600; }

/* Centre the trail on the centred article-hero pages (template hub and
   category pages); left-aligned everywhere else (overlay hero, platform
   marketing hero), matched via the hero's own classes, not per page. */
.article-hero:not(.article-hero--overlay) .breadcrumbs ol { justify-content: center; }

/* Case-study / blog-post hero: dark photo background, needs a lighter
   muted tone instead of the default (which would be unreadably dark). */
.article-hero--overlay .breadcrumbs ol { color: rgba(255, 255, 255, 0.65); }
.article-hero--overlay .breadcrumbs li:not(:first-child)::before { color: rgba(255, 255, 255, 0.4); }
.article-hero--overlay .breadcrumbs a { color: rgba(255, 255, 255, 0.75); }
.article-hero--overlay .breadcrumbs a:hover { color: #fff; }
.article-hero--overlay .breadcrumbs li[aria-current="page"] { color: #fff; }

/* ============================================================
   Content cards (blog / case studies listings)
   ============================================================ */
.content-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
}
.content-grid--2col { grid-template-columns: repeat(2, 1fr); }
.content-card {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  overflow: hidden;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.content-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.content-card-media {
  height: 210px;
  flex-shrink: 0;
  background: var(--color-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-lg);
}
.content-card-media img { max-height: 44px; width: auto; object-fit: contain; }
.content-card-media.is-photo { padding: 0; }
.content-card-media.is-photo img { height: 100%; width: 100%; object-fit: cover; max-height: none; }
.content-card-body { padding: var(--space-lg); display: flex; flex-direction: column; gap: var(--space-xs); flex: 1; }
.content-card-body .tag { color: var(--color-primary); font-size: 0.7rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; }
.content-card-body h3 { font-size: 1.05rem; }
.content-card-body p { color: var(--color-muted-foreground); font-size: var(--fs-sm); flex: 1; }
.content-card-body .meta { font-size: 0.75rem; color: var(--color-muted-foreground); margin-top: var(--space-xs); }
.content-card-body .read-more { margin-top: var(--space-sm); font-weight: 700; color: var(--color-primary); font-size: var(--fs-sm); }

@media (max-width: 900px) {
  .content-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .content-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Platforms hub (/platforms, class name kept as .integrations-grid
   from before the section was renamed): a fixed 2-up grid of
   .content-card, one per platform, only stacking to 1 column on
   mobile (unlike .content-grid's 3/2/1 responsive steps, since there
   are always exactly 4 platforms here, not an open-ended list). The
   card shell, body layout and .read-more link are the shared
   .content-card styles above; only the banner backgrounds are
   platform-specific, matching the colors already used for these same
   4 platforms in the homepage "How it works" step 1 platform grid
   (.hiw-platform-card--*), just applied to this page's wider,
   16:9 banner media area instead of that grid's small square tiles.
   ============================================================ */
.integrations-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
}
@media (max-width: 620px) {
  .integrations-grid { grid-template-columns: 1fr; }
}
.integrations-grid .content-card-media { padding: var(--space-xl); }
.integrations-grid .content-card-media img { max-height: 56px; }
.integrations-grid .content-card-media--light { background: var(--color-surface-alt); }
.integrations-grid .content-card-media--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); }
.integrations-grid .content-card-media--ecwid { background: linear-gradient(160deg, var(--color-primary-light), var(--color-primary-darker)); }
/* Platform name heading with a small trailing chevron, reusing the
   site's existing forward-chevron path (same one used by the
   carousel arrows) rather than a plain typographic arrow character.
   The card holds two links (platform page, marketplace install) and
   nesting <a> is invalid, so the heading link is stretched over the
   whole card with ::after, and .read-more is lifted above that overlay
   to stay its own separate target. */
.integrations-grid .content-card { position: relative; }
.integrations-grid .content-card-body h3 a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
}
.integrations-grid .content-card-body h3 a::after {
  content: '';
  position: absolute;
  inset: 0;
}
.integrations-grid .content-card-body .read-more { position: relative; z-index: 1; }
.integrations-grid .content-card:hover h3 a { color: var(--color-primary); }
.integrations-grid .content-card-body h3 svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--color-primary); }

/* ============================================================
   Template library (/templates grid pages): category filter tabs, a
   responsive card grid, and a click-to-enlarge modal.
   ============================================================ */
/* Same pill-tab look, but for the platform/category template pages
   (/templates/[platform] and /templates/[platform]/[category]), where
   each tab is a real link to its own static, indexable URL rather than
   a JS-toggled in-page filter. Kept as separate classes from
   .template-filter-tabs/.filter-tab above so the old page's
   getElementById-free but class-based filter JS never binds to these
   real links. */
.template-tabs {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-2xl);
}
.template-tabs .template-tab {
  padding: 0.5rem 1rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  font-family: var(--font-heading);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-muted-foreground);
  transition: all var(--transition-fast);
}
.template-tabs .template-tab:hover { border-color: var(--color-primary); color: var(--color-primary); }
.template-tabs .template-tab.is-active { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }

/* Fixed 3/2/1 responsive grid, same steps as .content-grid. A separate
   class (rather than reusing .content-grid) since this page also needs
   filtering hooks that don't belong on the shared blog/case-study grid. */
.template-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
}
@media (max-width: 900px) {
  .template-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .template-grid { grid-template-columns: 1fr; }
}
/* Reuses .gallery-card/.gallery-thumb/.gallery-card-body as-is, just
   set up as a proper grid item (the base .gallery-card is a flex-basis
   item meant for the horizontal-scroll .gallery-grid elsewhere) and
   hideable by a JS-toggled class rather than the `hidden` attribute,
   since `hidden`'s UA-stylesheet display:none would lose to this
   class's own display:flex on specificity grounds. */
.template-grid .gallery-card { display: flex; flex-direction: column; }
.template-grid .gallery-card.is-hidden { display: none; }
/* Real, full-page document screenshots, shown uncropped (contain, not
   the default .gallery-thumb `cover` crop) so nothing important like a
   header or a totals line is ever cut off. The frame itself is a
   shorter, wider 3:2 rather than the page's own tall ~5:7 shape,
   deliberately: at 3 cards a row the full page height made each card
   require scrolling to see the badge/title/description below it, and
   letterboxing (empty space beside the page) reads far better here
   than losing content off the top or bottom would. */
.template-grid .gallery-thumb {
  aspect-ratio: 3 / 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2xs);
}
.template-grid .thumb-trigger { display: flex; align-items: center; justify-content: center; }
/* The image keeps its own size, shrinking to fit the box but never growing
   past the file itself, so a small or very wide screenshot sits inside the
   thumbnail on its background instead of being blown up to fill it.
   main.js sets --img-max-w/h to the file's size in device pixels; without
   the script the cap is the file's size in CSS pixels. */
.template-grid .gallery-thumb img {
  width: auto;
  height: auto;
  max-width: min(100%, var(--img-max-w, 100%));
  max-height: min(100%, var(--img-max-h, 100%));
  object-fit: contain;
}
.template-grid .gallery-card-body { flex: 1; display: flex; flex-direction: column; }
.template-grid .gallery-card-body p { flex: 1; }
/* The flex column's default align-items:stretch was stretching the
   .tag badge to the card's full width along with the (rightly
   full-width) h3/p text - opt the badge back out to its own natural,
   content-sized width instead. */
.template-grid .gallery-card-body .tag { align-self: flex-start; }
/* The thumbnail is a real <button> filling the .gallery-thumb box, so
   clicking the image opens the lightbox without changing .gallery-thumb
   itself (shared with other pages/sections that don't have a modal). */
.thumb-trigger { display: block; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }

/* ---- Click-to-enlarge modal ------------------------------------- */
.template-modal { position: fixed; inset: 0; z-index: 200; }
.template-modal[hidden] { display: none; }
.template-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(16, 42, 67, 0.72);
  backdrop-filter: blur(4px);
}
.template-modal-dialog {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  height: 100%;
  padding: var(--space-lg);
}
.template-modal-body {
  flex: 1;
  min-width: 0;
  min-height: 0;
  max-width: 1200px;
  margin-inline: auto;
  /* No panel of its own: the image and caption sit straight on the blurred
     backdrop. The height follows the content, capped at the dialog's inner
     height so a tall screenshot shrinks to fit, and the dialog's
     align-items keeps it centred. The padding leaves room for the image's
     shadow. */
  padding: var(--space-md);
  max-height: calc(100vh - 2 * var(--space-lg));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}
/* The image keeps its own size and shrinks to fit the space left above
   the caption, but never grows past its natural pixel dimensions, so a
   small screenshot stays sharp at 1:1 instead of being blown up. The
   shadow defines the edge of a white template against the backdrop,
   which the old grey panel used to do. */
.template-modal-body img {
  flex: 0 1 auto;
  min-height: 0;
  width: auto;
  height: auto;
  max-width: 100%;
  object-fit: contain;
  box-shadow: 0 2px 6px rgba(5, 15, 28, 0.35), 0 12px 36px rgba(5, 15, 28, 0.5);
}
/* A small caption, not a headline: this used to be a full h3, but that
   competed with the image for attention, so it's demoted to
   body-text size/weight here specifically. */
.template-modal-body h3 {
  flex-shrink: 0;
  text-align: center;
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 600;
  /* on the dark blurred backdrop now, not the old light panel */
  color: #fff;
  text-shadow: 0 1px 3px rgba(5, 15, 28, 0.6);
}
.template-modal-close {
  position: absolute;
  top: var(--space-md);
  right: var(--space-md);
  z-index: 2;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  transition: background var(--transition-fast);
}
.template-modal-close:hover { background: rgba(255, 255, 255, 0.22); }
.template-modal-close svg { width: 20px; height: 20px; }
.template-modal-nav.carousel-arrow { flex-shrink: 0; background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.4); color: #fff; }
.template-modal-nav.carousel-arrow:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }

@media (max-width: 620px) {
  .template-modal-dialog { padding: var(--space-md) var(--space-2xs); gap: var(--space-2xs); }
  .template-modal-body { padding: var(--space-md); max-height: calc(100vh - 2 * var(--space-md)); }
  .template-modal-close { top: var(--space-sm); right: var(--space-sm); }
}

/* ============================================================
   Case study layout (customer profile card + article)
   ============================================================ */
.case-study-layout {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: var(--space-2xl);
  align-items: start;
}
@media (max-width: 860px) {
  .case-study-layout { grid-template-columns: 1fr; }
}

.customer-card {
  background: var(--color-primary-darker);
  color: rgba(255, 255, 255, 0.78);
  border-radius: var(--radius-lg);
  padding: var(--space-xl) var(--space-lg);
  text-align: center;
  position: sticky;
  top: calc(72px + var(--space-lg));
}
.customer-card-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 64px;
  margin-bottom: var(--space-lg);
}
.customer-card-logo img { width: auto; max-width: 100%; max-height: 88px; border-radius: var(--radius-sm); }
.customer-card-logo--tile { background: #fff; padding: var(--space-md); border-radius: var(--radius-sm); }
.customer-card-avatar {
  width: 76px; height: 76px;
  border-radius: 50%;
  object-fit: cover;
  margin: 0 auto var(--space-md);
  display: block;
  border: 3px solid rgba(255, 255, 255, 0.18);
}
.customer-card-name {
  color: #fff;
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: var(--space-lg);
  line-height: 1.4;
}
.customer-card-facts {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin: 0 0 var(--space-lg);
}
.customer-card-facts dt {
  font-weight: 700;
  color: #fff;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 2px;
}
.customer-card-facts dd {
  margin: 0;
  font-size: 0.92rem;
  color: rgba(255, 255, 255, 0.72);
}
.customer-card-facts a { color: rgba(255, 255, 255, 0.9); text-decoration: underline; text-underline-offset: 2px; }
.customer-card-facts a:hover { color: #fff; }
.customer-card-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--color-primary-light);
}
.customer-card-back:hover { color: #fff; }

/* About page: prose on the left, the company details on the right in the
   case-study profile card, which stays in view while the prose scrolls.
   Below 900px the card drops under the prose at full width, where there is
   nothing left below it to stick against. */
.about-layout {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--space-2xl);
  align-items: start;
}
.about-layout .article-body { max-width: none; margin-inline: 0; padding-block: 0; }
.about-layout .article-body > h2:first-child { margin-top: 0; }
.about-card { text-align: left; }
.about-card .customer-card-name { margin-bottom: var(--space-2xs); }
.about-card-ids {
  margin: 0 0 var(--space-lg);
  font-size: 0.92rem;
  color: rgba(255, 255, 255, 0.72);
}
.about-card .customer-card-facts { margin-bottom: 0; }
.about-card address { font-style: normal; }
.about-card .customer-card-facts a { overflow-wrap: anywhere; }
@media (max-width: 899.98px) {
  .about-layout { grid-template-columns: 1fr; }
  .about-card { position: static; }
}

/* Legal pages (privacy policy, terms of service): the legal text is kept exactly
   as published, including its original wrapper markup, so this only sets the
   spacing under the hero and restores the unbulleted definitions list, which
   the site's article-body list styles would otherwise give discs. */
.article-body.legal-body { padding-top: 0; }
.legal-body > :first-child > :first-child { margin-top: 0; }
.article-body.legal-body ul.list-unstyled { list-style: none; margin-left: 0; margin-top: var(--space-xs); }

/* ============================================================
   Article pages (blog post / case study detail)
   ============================================================ */
.article-hero {
  padding-block: var(--space-2xl) var(--space-xl);
  background: linear-gradient(180deg, var(--color-surface), var(--color-background));
}
.article-hero .tag { color: var(--color-primary); font-weight: 700; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.05em; }
.article-hero h1 { margin-top: var(--space-sm); }
/* A long H1 that wraps to three lines: balance them so a list of names is not
   split before its last item or left with one word on the final line. */
.article-hero h1.hero-h1--balance { text-wrap: balance; }
.article-hero .meta { margin-top: var(--space-md); color: var(--color-muted-foreground); font-size: var(--fs-sm); display: flex; align-items: center; gap: var(--space-sm); }
.article-hero .meta img { height: 28px; width: auto; }
.article-hero .meta strong { color: var(--color-foreground); font-weight: 700; }
.article-meta { margin-top: var(--space-sm); font-size: var(--fs-sm); color: var(--color-muted-foreground); }
.article-hero--overlay .article-meta { color: rgba(255, 255, 255, 0.75); }

/* Case study hero: intro image as a full-width darkened background behind the nav + title.
   No overflow:hidden here: nothing in the banner needs clipping (the ::before
   gradient is inset:0, same box), and clipping this ancestor was cutting into
   the Resources dropdown's rendering since it's a descendant of the header. */
.case-hero-banner {
  position: relative;
  background-size: cover;
  background-position: center;
}
.case-hero-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(8,28,48,0.6) 0%, rgba(8,28,48,0.68) 55%, rgba(8,28,48,0.82) 100%);
  pointer-events: none;
}
/* .site-header--overlay already sets position:absolute + z-index; this rule
   used to also target .site-header with equal/lower specificity than that
   modifier needed, so a stray "position: relative" here was winning by
   selector specificity and silently putting the overlay header back into
   normal flow, above the ::before overlay is still needed for the h1. */
.case-hero-banner > .article-hero { position: relative; z-index: 1; }

.site-header--overlay {
  position: absolute;
  top: 0; left: 0; right: 0;
  background: transparent;
  backdrop-filter: none;
  border-bottom: none;
}
.site-header--overlay .brand { color: #fff; }
.site-header--overlay .nav-links > a,
.site-header--overlay .nav-dropdown-toggle { color: rgba(255,255,255,0.92); }
.site-header--overlay .nav-links > a:hover,
.site-header--overlay .nav-dropdown-toggle:hover { color: #fff; }
.site-header--overlay .nav-links > a[aria-current="page"] { color: #fff; }
.site-header--overlay .nav-toggle { color: #fff; }

/* The banner is width-driven at desktop widths (background-size: cover on a
   box far wider than any of the source photos), so its height is what decides
   how much of the photo survives the crop: visible source height = banner
   height / scale. 474px was cropping GTSE tight enough to lose the vest logo,
   so the padding buys back ~32px of photo rather than losing it. */
.article-hero--overlay {
  background: none;
  padding-block: 144px 80px;
}
.article-hero--overlay .tag, .article-hero--overlay h1 { color: #fff; }

@media (max-width: 640px) {
  .article-hero--overlay { padding-block: 108px 48px; }
}

.article-body {
  max-width: 760px;
  margin-inline: auto;
  padding-block: var(--space-2xl);
}
.article-body h2 { margin-top: var(--space-2xl); margin-bottom: var(--space-md); font-size: 1.5rem; }
.article-body h3 { margin-top: var(--space-xl); margin-bottom: var(--space-sm); }
.article-body p { margin-bottom: var(--space-md); color: var(--color-foreground); }
.article-body p.lede { font-size: var(--fs-lg); color: var(--color-muted-foreground); }
.article-body p a, .article-body li a {
  font-weight: 700;
  color: var(--color-primary);
}
.article-body p a:hover, .article-body li a:hover { text-decoration: underline; }
.article-body ul, .article-body ol { margin: 0 0 var(--space-md) var(--space-lg); }
.article-body li { margin-bottom: var(--space-xs); }
/* The global reset (ul { list-style: none }) strips markers everywhere, which
   is right for nav and card lists but wrong for article prose, where a list
   is a list. Put the markers back, keeping the indent and item spacing set
   above. The Related block is navigation rather than prose, so it is excluded
   and stays bullet-free. */
.article-body ul:not(.related-links) { list-style: disc; }
/* An eyebrow paired with the heading of a prose block (template category
   pages). The eyebrow sits directly above its heading, so the heading drops
   the article-chapter top margin it would otherwise inherit and the pair
   carries the gap instead. */
.article-body ol { list-style: decimal; }
.article-body blockquote {
  border-left: 3px solid var(--color-primary);
  background: var(--color-primary-tint);
  padding: var(--space-md) var(--space-lg);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-style: italic;
  color: var(--color-primary-darker);
  margin: var(--space-lg) 0;
}
.article-body figure {
  margin: var(--space-xl) 0;
}
/* Never scale an article image beyond its own pixels: the column is 760px
   and width:100% used to stretch anything narrower, which just made it
   blurry. max-height keeps tall portraits from taking over the page, and
   because both axes stay auto the browser scales them proportionally. */
.article-body figure img {
  max-width: 100%;
  width: auto;
  height: auto;
  max-height: 70vh;
  display: block;
  margin-inline: auto;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
}
.article-body video {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
  margin: var(--space-xl) 0;
  background: #000;
}
.stat-callouts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
  margin: var(--space-xl) 0;
}
.stat-callouts .cell {
  text-align: center;
  padding: var(--space-lg);
  background: var(--color-surface);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
}
.stat-callouts .cell .num { font-family: var(--font-heading); font-weight: 800; font-size: 1.6rem; color: var(--color-primary-darker); }
.stat-callouts .cell .label { font-size: var(--fs-sm); color: var(--color-muted-foreground); margin-top: 2px; }

@media (max-width: 640px) {
  .stat-callouts { grid-template-columns: 1fr; }
}

/* ============================================================
   Integration page: platform strip / feature list
   ============================================================ */
.feature-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
}
.feature-item {
  display: flex;
  gap: var(--space-md);
  padding: var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-background);
}
.feature-item .icon {
  flex-shrink: 0;
  width: 44px; height: 44px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-tint);
  color: var(--color-primary);
  display: flex; align-items: center; justify-content: center;
}
.feature-item .icon svg { width: 22px; height: 22px; }
.feature-item h3 { font-size: 1rem; margin-bottom: 2px; }
.feature-item p { color: var(--color-muted-foreground); font-size: var(--fs-sm); }

/* CTA variant: fills one grid slot at the end of a feature list (e.g.
   "Explore all features") but reads as a link/button rather than a
   description card - centered single line, tinted fill, dashed border
   instead of the other cards' icon + heading + paragraph layout. */
.feature-item--cta {
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: var(--color-primary-tint);
  border-style: dashed;
  border-color: var(--color-primary);
  color: var(--color-primary-darker);
  font-family: var(--font-heading);
  font-weight: 700;
  transition: background var(--transition-fast), color var(--transition-fast), transform var(--transition-fast);
}
.feature-item--cta:hover, .feature-item--cta:focus-visible {
  background: var(--color-primary);
  color: #fff;
  transform: translateY(-2px);
}
.feature-item--cta svg { width: 20px; height: 20px; flex-shrink: 0; }

/* Compact 3-step row (e.g. "Set up in three simple steps"), same card
   weight as .feature-item, just with a numbered circle instead of an icon. */
.mini-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
}
.mini-step {
  display: flex;
  gap: var(--space-md);
  padding: var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-background);
}
.mini-step-num {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1rem;
}
.mini-step h3 { font-size: 1rem; margin-bottom: 2px; }
.mini-step p { color: var(--color-muted-foreground); font-size: var(--fs-sm); }
@media (max-width: 760px) {
  .mini-steps { grid-template-columns: 1fr; }
}

/* 4-across template showcase (e.g. platform pages' "Templates built for X
   orders"), reusing .gallery-card/.gallery-thumb/.gallery-card-body as-is. */
.template-showcase-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-lg);
}
.template-showcase-grid .gallery-card { display: flex; flex-direction: column; height: 100%; }
/* Equal-height alignment: with the grid's default align-items:stretch,
   every card in a row is already the same height - the body just needs
   to actually use that height so its trailing link/button lands at the
   same position regardless of how many lines the title or description
   wrap to. The description grows to fill whatever space the title
   didn't use, which pushes the link that follows it down to the
   bottom of the card rather than leaving it stranded mid-card on
   shorter cards. Same pattern as .template-grid's card body below. */
.template-showcase-grid .gallery-card-body { flex: 1; display: flex; flex-direction: column; }
.template-showcase-grid .gallery-card-body p { flex: 1; }
.template-showcase-grid .gallery-card-body .tag { align-self: flex-start; }
.template-showcase-grid .gallery-card-body .hiw-text-link { margin-top: var(--space-sm); align-self: flex-start; }
/* 3-across variant (e.g. platform pages and the /templates hub showing
   a trimmed 3-card sample rather than the full 4-across showcase). */
.template-showcase-grid--3up { grid-template-columns: repeat(3, 1fr); }
/* Compact variant (the /templates hub's "See it in action" preview):
   a shorter, letterboxed 3:2 thumbnail (same treatment as the main
   /templates grid's full-page screenshots) and no description, so 3
   cards read as a quick glimpse of real output rather than a second
   full showcase competing with the platform picker above it. */
@media (max-width: 900px) {
  .template-showcase-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .template-showcase-grid { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
  .feature-list { grid-template-columns: 1fr; }
}

/* ============================================================
   Comparisons
   ============================================================ */
/* Hub cards: the shared .content-card with a platform logo banner, the
   same treatment as the /platforms cards. */
.comparison-cards .content-card-media { padding: var(--space-xl); }
.comparison-cards .content-card-media img { max-height: 56px; }
.comparison-cards .content-card-media--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); }

/* Comparison pages: a three-column feature table. It keeps its text size on
   narrow screens and scrolls sideways inside its own box instead, with the
   row labels pinned to the left edge while the two product columns move. */
.compare-table-wrap {
  max-width: 960px;
  margin-inline: auto;
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
}
.compare-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.compare-table th,
.compare-table td {
  padding: var(--space-sm) var(--space-md);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--color-border);
}
.compare-table tbody tr:last-child > * { border-bottom: 0; }
.compare-table thead th {
  background: var(--color-surface-alt);
  font-weight: 700;
  width: 39%;
}
.compare-table thead th:first-child { width: 22%; }
.compare-table tbody th { font-weight: 600; background: var(--color-background); }
.compare-table th:first-child {
  position: sticky;
  left: 0;
  box-shadow: inset -1px 0 0 var(--color-border);
}
.compare-table .is-not-stated { color: var(--color-muted-foreground); }
.compare-fit { padding-bottom: 0; }
.compare-fit > h2:first-child { margin-top: 0; }
/* The one-paragraph verdict answer engines quote, set apart above the table */
.compare-answer {
  max-width: 960px;
  margin: 0 auto var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  border-left: 4px solid var(--color-primary);
  border-radius: var(--radius-sm);
  background: var(--color-surface-alt);
}
.compare-answer h2 { font-size: var(--fs-lg); margin: 0 0 var(--space-xs); }
.compare-answer p { margin: 0; }

/* ============================================================
   FAQ
   ============================================================ */
.faq-list {
  max-width: 780px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.faq-item {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  overflow: hidden;
}
.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg);
  text-align: left;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  color: var(--color-primary-darker);
}
.faq-question .chev {
  flex-shrink: 0;
  width: 20px; height: 20px;
  transition: transform var(--transition-base);
  color: var(--color-primary);
}
.faq-item[data-open="true"] .chev { transform: rotate(180deg); }

.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--transition-base);
}
.faq-answer > div { overflow: hidden; }
.faq-item[data-open="true"] .faq-answer { grid-template-rows: 1fr; }
.faq-answer p {
  padding: 0 var(--space-lg) var(--space-lg);
  color: var(--color-muted-foreground);
}
.faq-answer p a { color: var(--color-primary); text-decoration: underline; text-underline-offset: 2px; }
.faq-answer p a:hover { color: var(--color-primary-dark); }

/* ============================================================
   Final CTA
   ============================================================ */
/* The closing CTA is its own full section, so its top padding stacks on the
   bottom padding of the section before it: 96px + 96px of empty space between
   the FAQ and the CTA box. Collapse the pair to roughly one section's worth.
   The CTA section is padded symmetrically so the tinted band stays centred on
   the box. */
.section:has(> .container > .final-cta) { padding-block: var(--space-2xl); }
.section:has(+ .section > .container > .final-cta) { padding-block-end: var(--space-xl); }

.final-cta {
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--color-primary-darker), var(--color-primary));
  color: #fff;
  padding: var(--space-xl);
  text-align: center;
  box-shadow: var(--shadow-lg);
}
@media (max-width: 700px) {
  .final-cta { padding: var(--space-lg); }
}
/* The box supplies its own padding, so the heading must not also carry
   the article-chapter top margin it would inherit inside .article-body.
   Without this the same component renders 64px taller on the five
   article pages than on the thirty marketing pages. */
.final-cta h2 { color: #fff; margin-top: 0; }
.final-cta p { color: rgba(255,255,255,0.85); margin-top: var(--space-sm); font-size: var(--fs-lg); }
.final-cta .hero-ctas { justify-content: center; }

/* ============================================================
   Platform landing pages (e.g. /platforms/shopify):
   a large contrast (dark) section pairing a platform-connection
   visual with a short platform description and resource links, plus
   a 3-up feature grid below it. Reuses .hiw-step-grid for the 2-column
   layout and .feature-item for each card (just widened to 3 columns
   here), rather than introducing new grid/card components.
   ============================================================ */
.integration-spotlight {
  background: var(--color-primary-darker);
  color: rgba(255, 255, 255, 0.82);
}
.integration-spotlight h2 { color: #fff; }
.integration-spotlight p { color: rgba(255, 255, 255, 0.82); }
.integration-spotlight .hiw-text-link { color: rgba(255, 255, 255, 0.9); text-decoration: underline; text-underline-offset: 2px; }
.integration-spotlight .hiw-text-link:hover { color: #fff; }
.integration-spotlight .hiw-text-link { text-decoration: none; }
.integration-spotlight .hiw-text-link:hover { text-decoration: underline; }
/* Vertical rhythm for the right-column copy: reset-to-0 paragraphs
   need explicit spacing below the heading and between each other so
   they read as separate blocks rather than one dense run of text. */
.integration-spotlight h2 + p { margin-top: var(--space-md); }
.integration-spotlight p + p { margin-top: var(--space-md); }

/* Resources: a clickable 2x2 tile grid (icon + title) instead of a
   plain link list, styled for this section's dark background with the
   same translucent-white treatment as .btn--on-dark. */
.resource-tile-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-md);
  margin: var(--space-sm) 0 var(--space-lg);
}
.resource-tile {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius-md);
  border: 1.5px solid rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  transition: background var(--transition-fast), transform var(--transition-fast);
}
.resource-tile:hover, .resource-tile:focus-visible { background: rgba(255, 255, 255, 0.22); transform: translateY(-2px); }
.resource-tile .icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.resource-tile .icon svg { width: 20px; height: 20px; }
.resource-tile .title { font-weight: 700; font-size: var(--fs-sm); }
@media (max-width: 480px) {
  .resource-tile-grid { grid-template-columns: 1fr; }
}

/* Left-column visual: 2 platform tiles joined by a line with a
   checkmark badge, echoing the homepage's .hiw-platform-card tiles
   (same rounded-tile treatment and Shopify brand gradient) simplified
   to a single before/after style connection instead of a 2x2 grid. */
.connect-graphic { display: flex; align-items: center; justify-content: center; gap: var(--space-sm); width: 100%; }
.connect-tile {
  flex-shrink: 0;
  width: 104px;
  height: 104px;
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-lg);
}
.connect-tile--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); }
.connect-tile--shopify img { max-width: 58%; max-height: 58%; }
/* BigCommerce and WooCommerce logos are full-color (not white/inverted),
   so they use the same light tile background as their .hiw-platform-card
   counterparts on the homepage, rather than a brand-color gradient. */
.connect-tile--light { background: var(--color-surface-alt); }
.connect-tile--light img { max-width: 62%; max-height: 62%; }
.connect-tile--ecwid { background: linear-gradient(160deg, var(--color-primary-light), var(--color-primary-darker)); }
.connect-tile--ecwid img { max-width: 62%; max-height: 62%; }
.connect-tile--designer { background: #fff; }
.connect-tile--designer img { max-width: 52%; max-height: 52%; }
.connect-line { position: relative; flex: 1; max-width: 110px; height: 2px; background: rgba(255, 255, 255, 0.3); }
.connect-check {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--color-success);
  border: 3px solid var(--color-primary-darker);
  display: flex;
  align-items: center;
  justify-content: center;
}
.connect-check svg { width: 16px; height: 16px; }

@media (max-width: 620px) {
  .connect-tile { width: 84px; height: 84px; }
  .connect-line { max-width: 60px; }
}

/* Larger variant for the Shopify page's contrast-section connector,
   which otherwise looks small against that section's now more
   generously spaced copy. Opt-in modifier so the other platform pages
   keep the default connect-tile size. */
.connect-graphic--lg .connect-tile { width: 132px; height: 132px; }
.connect-graphic--lg .connect-line { max-width: 130px; }
@media (max-width: 620px) {
  .connect-graphic--lg .connect-tile { width: 96px; height: 96px; }
  .connect-graphic--lg .connect-line { max-width: 70px; }
}

/* "Set up in three simple steps" flow diagram: same rounded-square
   connect-tile treatment as the connector graphic above, adapted for
   a light-background section with a bordered line and a primary-color
   arrow bubble instead of the dark section's translucent line/checkmark. */
.flow-diagram {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  width: 100%;
  max-width: 560px;
  margin: var(--space-2xl) auto 0;
}
.flow-diagram .connect-tile--editor,
.flow-diagram .connect-tile--automate {
  background: #fff;
  border: 1px solid var(--color-border);
}
.flow-diagram .connect-tile--editor svg { width: 40px; height: 40px; color: var(--color-primary); }
.flow-diagram .connect-tile--automate { display: flex; gap: 8px; }
.flow-diagram .connect-tile--automate svg { width: 26px; height: 26px; color: var(--color-primary); }
.flow-line { position: relative; flex: 1; max-width: 110px; height: 2px; background: var(--color-border); }
.flow-arrow {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
}
.flow-arrow svg { width: 16px; height: 16px; }
@media (max-width: 620px) {
  .flow-diagram .connect-tile { width: 84px; height: 84px; }
  .flow-line { max-width: 44px; }
}
@media (max-width: 480px) {
  .flow-diagram { gap: var(--space-2xs); }
  .flow-line { max-width: 24px; }
}

/* This page's feature grid is 3-up (vs. the shared .feature-list's
   default 2), everything else about .feature-item is untouched. */
.feature-list--3up { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) {
  .feature-list--3up { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .feature-list--3up { grid-template-columns: 1fr; }
}

/* ============================================================
   /get-started platform picker: 4 large clickable cards, each
   linking straight out to that platform's install flow. Same
   light/brand-gradient tile treatment already used for these 4
   platforms elsewhere (.hiw-platform-card, .connect-tile), just
   bigger and with a visible name caption since these are meant to
   stand alone as the whole page's content, not a small supporting
   grid inside a larger section.
   ============================================================ */
.platform-pick-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-lg);
}
.platform-pick-card {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xl) var(--space-lg);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}
.platform-pick-card:hover, .platform-pick-card:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--color-primary);
}
.platform-pick-card img { max-width: 85%; max-height: 88px; width: auto; height: auto; object-fit: contain; }
.platform-pick-card--light { background: var(--color-surface-alt); }
.platform-pick-card--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); border-color: transparent; }
.platform-pick-card--ecwid { background: linear-gradient(160deg, var(--color-primary-light), var(--color-primary-darker)); border-color: transparent; }
/* A quiet note under one tile (WooCommerce, which connects with API keys
   rather than a marketplace install). It is a grid item of its own, placed
   in that tile's column on the row below, so the tiles' row keeps its
   height and all four stay level. The negative top margin takes back most
   of the row gap so the note reads as belonging to the tile above it. */
.platform-pick-note {
  grid-column: 4;
  margin-top: calc(var(--space-sm) - var(--space-lg));
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--color-muted-foreground);
}

@media (max-width: 760px) {
  .platform-pick-grid { grid-template-columns: repeat(2, 1fr); }
  .platform-pick-note { grid-column: 2; }
}
@media (max-width: 480px) {
  .platform-pick-grid { grid-template-columns: 1fr; }
  .platform-pick-note { grid-column: auto; }
}
/* ============================================================
   Footer
   ============================================================ */
.site-footer {
  background: var(--color-primary-darker);
  color: rgba(255,255,255,0.75);
  padding-block: var(--space-2xl) var(--space-lg);
}
.footer-grid {
  display: grid;
  grid-template-columns: minmax(240px, 1.3fr) repeat(5, 1fr);
  gap: var(--space-lg);
}
/* Keep every footer link on one line so labels like "BigCommerce
   Templates" never break mid-phrase. This is safe now that the grid
   reflows to fewer columns as the viewport narrows (see the media
   queries below) instead of forcing all tracks onto a single row: the
   tracks are minmax(0, 1fr) below the widest breakpoint, so they are
   free to shrink and the row count grows rather than the grid
   overflowing its container. */
.footer-col a {
  white-space: nowrap;
}
.footer-brand .brand { color: #fff; }
.footer-brand p { margin-top: var(--space-md); font-size: var(--fs-sm); max-width: 32ch; }
.footer-address { margin-top: var(--space-md); font-style: normal; font-size: var(--fs-sm); line-height: 1.7; }
/* Each comma-delimited chunk of the street address is unbreakable, so
   when the column is too narrow for one line the address can only fold
   after a comma, never mid-street or mid-city. */
.footer-address .nb { white-space: nowrap; }
.footer-address a { color: inherit; transition: color var(--transition-fast); }
.footer-address a:hover { color: #fff; }
.footer-col h4 {
  font-family: var(--font-heading);
  color: #fff;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: var(--space-md);
}
.footer-col ul { display: flex; flex-direction: column; gap: var(--space-sm); }
.footer-col a { font-size: var(--fs-sm); transition: color var(--transition-fast); }
.footer-col a:hover { color: #fff; }
/* Social profiles sit under the address as icons only; each link's
   accessible name comes from its aria-label. */
.footer-social { display: flex; gap: var(--space-sm); margin-top: var(--space-md); }
.footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  color: rgba(255,255,255,0.6);
  transition: color var(--transition-fast), background var(--transition-fast);
}
.footer-social a:hover { color: #fff; background: rgba(255,255,255,0.1); }
.footer-social svg { width: 18px; height: 18px; display: block; }

/* Full-width strip of off-site profiles between the grid and the copyright
   bar - deliberately quieter than the grid links, since these corroborate
   the sameAs claims in the structured data rather than compete for clicks.
   It is a flex row, not a seventh grid track, so the grid stays at six. */
.footer-profiles {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: 1px solid rgba(255,255,255,0.15);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-2xs) var(--space-sm);
  font-size: 0.8125rem;
  color: rgba(255,255,255,0.55);
}
.footer-profiles ul { display: flex; flex-wrap: wrap; gap: var(--space-2xs) var(--space-sm); }
.footer-profiles li { display: flex; align-items: baseline; gap: var(--space-sm); }
.footer-profiles li + li::before { content: "\00b7"; color: rgba(255,255,255,0.3); }
.footer-profiles a { color: rgba(255,255,255,0.55); transition: color var(--transition-fast); }
.footer-profiles a:hover { color: #fff; }

.footer-bottom {
  margin-top: var(--space-lg);
  padding-top: var(--space-lg);
  border-top: 1px solid rgba(255,255,255,0.15);
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-sm);
  font-size: var(--fs-sm);
}

/* 6 columns (brand + Product, Platforms, Templates, Resources, Company)
   step down through 3-, then 2-, then 1-across. The first step happens
   at 1180px, where the container stops growing: below that the single
   row can no longer hold every track at its natural width, which is
   what used to push the grid past its container and give the page a
   horizontal scrollbar. Dropping to 3 columns adds a row instead, and
   minmax(0, 1fr) lets the tracks shrink with the viewport rather than
   being floored by their content. */
@media (max-width: 1180px) {
  .footer-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Once the grid is only two tracks wide, half of it is narrower than
     the support email address, which is a single unbreakable token and
     so spills out of the brand column. Give the brand block the full
     row: it reads better as a masthead above the link columns anyway. */
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 420px) {
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
}

/* "Related" block closing an article or case study. It is a secondary
   navigation aid rather than another chapter, so it sits behind a
   hairline rule with room to breathe, and its heading is stepped down
   to a small label. It stays an <h2> in the markup for outline and
   accessibility reasons; only the rendered size and weight change. */
.article-body h2.related {
  margin-top: var(--space-2xl);
  margin-bottom: var(--space-md);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
}
.article-body ul.related-links {
  margin-left: 0;
  margin-bottom: var(--space-xl);
}

/* ============================================================
   Template landing page (one per template per platform): hero with
   the full template preview, a two-column fields/customisation split,
   and gallery cards whose title links to the template's own page.
   ============================================================ */
.tpl-detail-hero .hero-lede { max-width: 52ch; }
.tpl-detail-hero .eyebrow { display: flex; margin-top: var(--space-md); }
.tpl-detail-preview {
  width: 100%;
  max-width: 440px;
  margin: 0;
  padding: var(--space-md);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  box-shadow: var(--shadow-lg);
}
.tpl-detail-preview .gallery-thumb { aspect-ratio: auto; border: 0; border-radius: var(--radius-sm); }
.tpl-detail-preview .gallery-thumb img { height: auto; }
.tpl-detail-preview figcaption {
  margin-top: var(--space-sm);
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--color-muted-foreground);
}
.tpl-detail-split {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2xl);
  align-items: start;
}
.tpl-detail-split h2 { margin-top: var(--space-sm); }
.tpl-detail-text { margin-top: var(--space-md); color: var(--color-muted-foreground); }
.tpl-detail-list {
  margin-top: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.tpl-detail-list li { position: relative; padding-left: 1.75rem; }
.tpl-detail-list li::before {
  content: '';
  position: absolute;
  left: 0.25rem;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-primary);
}
@media (max-width: 860px) {
  .tpl-detail-split { grid-template-columns: 1fr; gap: var(--space-xl); }
}
.gallery-card-body h3 a { color: inherit; transition: color var(--transition-fast); }
.gallery-card-body h3 a:hover, .gallery-card-body h3 a:focus-visible { color: var(--color-primary); }
.gallery-card-link {
  align-self: flex-start;
  margin-top: var(--space-sm);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--color-primary);
}
.gallery-card-link:hover, .gallery-card-link:focus-visible { text-decoration: underline; }

/* ============================================================
   Utility: reveal-on-scroll (respects reduced motion)
   ============================================================ */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 500ms ease, transform 500ms ease;
}
.reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* ============================================================
   Features page (/features): a run of alternating light/
   dark blocks, each pairing a short copy column with its own
   custom illustration. Reuses the shared .hiw-step-grid 2-col
   layout for the copy/mockup pairing (which side the mockup
   lands on is just DOM order, swapped per block), but every
   `fx-` prefixed rule and every illustration here is unique to
   this page - namespaced so nothing here can leak onto or be
   confused with any other page's components.
   ============================================================ */
.fx-dark { background: var(--color-primary-darker); }

/* Fields block on the Shopify invoices page: a full-width dark band between
   the template gallery and the light FAQ section, text left and a labelled
   line-drawing of an invoice right. Colours are the light-blue tint rather
   than the brand blue, which does not carry enough contrast on this
   background. */
.inv-fields {
  background: var(--color-primary-darker);
  /* tighter than the default .section rhythm: the block is a single grid, so
     96px top and bottom left a visible gap under the text column */
  padding-block: var(--space-2xl);
}
.inv-fields-grid {
  display: grid;
  /* the documents these diagrams draw are portrait, so the figure takes the
     larger share of the row */
  grid-template-columns: 46fr 54fr;
  gap: var(--space-2xl);
  align-items: center;
}
.inv-fields-text .eyebrow { display: inline-block; margin-bottom: var(--space-sm); color: var(--color-primary-light); }
.inv-fields-text .eyebrow::before { background: var(--color-primary-light); }
.inv-fields-text h2 { color: #fff; margin-bottom: var(--space-lg); }
.inv-fields-text p { color: rgba(255,255,255,0.82); margin-bottom: var(--space-md); }
.inv-fields-text p strong { color: #fff; }
/* The lead-ins ("Order data", "Custom values" and so on) are H3s so the
   outline runs H1, H2, H3, drawn exactly like the bold paragraph lead-ins
   they replaced: body font, size and line height, bold, white. */
.inv-fields-text h3 {
  font: inherit;
  font-weight: 700;
  color: #fff;
  margin-bottom: var(--space-md);
}
/* The eight field bullets, panelled so they read as a block rather than a
   continuation of the paragraph above. One step lighter than the section
   ground and still in the brand blue: rgba of --color-primary over
   --color-primary-darker composites to rgb(16,65,105). Radius and hairline
   match the dark cards on /features. */
.inv-field-panel {
  margin: 0 0 var(--space-lg);
  padding: var(--space-lg);
  background: rgba(27, 117, 187, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-md);
}
.inv-field-panel ul {
  list-style: disc;
  margin: 0 0 0 var(--space-lg);
  color: rgba(255, 255, 255, 0.82);
}
.inv-field-panel li { margin-bottom: var(--space-xs); }
.inv-field-panel li:last-child { margin-bottom: 0; }
/* The labels page puts two named groups inside the panel, so a lead-in has to
   sit tighter to its own list than to the group above it. The invoices and
   packing slip panels hold nothing but a list, so they are unaffected. */
.inv-field-panel p { margin-bottom: var(--space-sm); }
.inv-field-panel ul + p { margin-top: var(--space-lg); }
.inv-field-panel h3 { margin-bottom: var(--space-sm); }
.inv-field-panel ul + h3 { margin-top: var(--space-lg); }
.inv-fields-figure { display: flex; justify-content: center; }
/* /templates: the whole block is one two-column grid. Intro over Invoices on
   the left, the fan on the right finishing level with Invoices, then the
   other four as a 2x2 below. Column gap, row gap and the gap inside the 2x2
   are all --space-lg, so Invoices is exactly one card wide and every edge
   lines up. Stacked, the DOM order (intro, fan, Invoices, the rest) is the
   reading order. Cards take the same treatment as .inv-field-panel. */
.inv-fields-text > p:last-child { margin-bottom: 0; }
.inv-fields-grid.tpl-doc-layout {
  /* minmax(0, ...) so no content can push the two columns apart */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-lg);
  row-gap: 0;
  grid-template-areas: "text fig" "lead fig" "rest rest";
  /* the flexible first row takes any height the fan has over the text and
     card, so the text sits directly on top of the card */
  grid-template-rows: 1fr auto auto;
}
.tpl-doc-layout > .inv-fields-text { grid-area: text; align-self: end; }
.tpl-doc-layout > .inv-fields-figure { grid-area: fig; align-self: end; }
.tpl-doc-layout > .tpl-doc-lead { grid-area: lead; align-self: end; margin-top: var(--space-lg); }
.tpl-doc-layout > .tpl-doc-grid { grid-area: rest; margin-top: var(--space-lg); }
@media (max-width: 900px) {
  .inv-fields-grid.tpl-doc-layout { grid-template-columns: 1fr; grid-template-areas: none; grid-template-rows: none; }
  .tpl-doc-layout > .inv-fields-text,
  .tpl-doc-layout > .inv-fields-figure,
  .tpl-doc-layout > .tpl-doc-lead,
  .tpl-doc-layout > .tpl-doc-grid { grid-area: auto; }
  .tpl-doc-layout > .inv-fields-figure,
  .tpl-doc-layout > .tpl-doc-lead { margin-top: var(--space-xl); }
  .tpl-doc-layout > .tpl-doc-grid { margin-top: var(--space-lg); }
}
.tpl-doc-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-lg);
}
.tpl-doc-card {
  padding: var(--space-lg);
  background: rgba(27, 117, 187, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-md);
}
.tpl-doc-card p { color: rgba(255, 255, 255, 0.82); margin-bottom: var(--space-xs); }
.tpl-doc-card p:last-child { margin-bottom: 0; }
.tpl-doc-card p strong { color: #fff; }
@media (max-width: 699px) {
  .tpl-doc-grid { grid-template-columns: 1fr; }
}

/* /templates platform cards. Same chrome and hover as .platform-pick-card, but
   stacked so the link carries a name and a line of text, not just a logo. The
   logo sits in its own tinted band because the Shopify and Ecwid marks only
   exist as light-on-dark files. */
.tpl-plat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-lg);
}
@media (max-width: 900px) {
  .tpl-plat-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .tpl-plat-grid { grid-template-columns: 1fr; }
}
.tpl-plat-card {
  display: flex;
  flex-direction: column;
  padding: var(--space-lg);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-background);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}
.tpl-plat-card:hover, .tpl-plat-card:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--color-primary);
}
.tpl-plat-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 64px;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-md);
}
.tpl-plat-logo--light { background: var(--color-surface-alt); }
.tpl-plat-logo--shopify { background: linear-gradient(160deg, #95BF47, #5E8E3E); }
.tpl-plat-logo--ecwid { background: linear-gradient(160deg, var(--color-primary-light), var(--color-primary-darker)); }
/* tuned per mark so the four read at the same optical weight, not the same pixel height */
.tpl-plat-logo img { width: auto; max-width: 78%; object-fit: contain; }
.tpl-plat-logo--shopify img { max-height: 26px; }
.tpl-plat-logo--light img { max-height: 22px; }
.tpl-plat-logo--ecwid img { max-height: 24px; }
.tpl-plat-card h3 { font-size: var(--fs-lg); margin-bottom: var(--space-xs); }
.tpl-plat-card p { font-size: var(--fs-sm); color: var(--color-muted-foreground); }

/* The three template shots held like cards in a hand: middle upright and in
   front, the other two rotated, lower and behind. */
.tpl-fan {
  position: relative;
  width: 100%;
  /* capped so the stacked layout does not blow the fan up to full width */
  max-width: 560px;
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Sized from the image width so the box ends exactly at the lowest paper
     corner (the rotated left card), which is what the Invoices card lines up
     with. That corner sits 0.8559 image widths below the centre, so the box is
     1.7118 widths tall; the images are 56% of the fan until they reach 290px. */
  aspect-ratio: 1 / 0.9586;
  max-height: 496.4px;
}
.tpl-fan img {
  width: 56%;
  max-width: 290px;
  height: auto;
  display: block;
  border-radius: var(--radius-sm);
  background: #fff;
  box-shadow: 0 18px 44px rgba(5, 22, 40, 0.5);
}
.tpl-fan-img--mid { position: relative; z-index: 3; }
.tpl-fan-img--left {
  position: absolute;
  z-index: 1;
  /* Inset by exactly the overhang of the rotated card, so its outer corner
     lands on the container edge. min(56%, 290px) is the image width; the
     rotated box is 0.090271 image widths wider on each side (0.084766 for the
     shorter right-hand image). */
  left: calc(min(56%, 290px) * 0.090271);
  top: 50%;
  transform: translateY(-42%) rotate(-8deg);
}
.tpl-fan-img--right {
  position: absolute;
  z-index: 2;
  right: calc(min(56%, 290px) * 0.084766);
  top: 50%;
  transform: translateY(-42%) rotate(8deg);
}
@media (max-width: 767px) {
  .tpl-fan { aspect-ratio: auto; max-height: none; }
  /* outranks .tpl-fan img, which also sets display */
  .tpl-fan img.tpl-fan-img--left, .tpl-fan img.tpl-fan-img--right { display: none; }
  .tpl-fan img.tpl-fan-img--mid { width: 72%; max-width: 320px; }
}
.inv-diagram { width: 100%; height: auto; display: block; font-family: var(--font-body); }
/* Stacked under 900px a portrait diagram would run to most of a screen, so it
   is held to a comfortable block and stays centred in the figure. */
@media (max-width: 900px) {
  .inv-diagram--tall { max-width: 460px; }
}
.inv-diagram-label { font-family: var(--font-body); }
/* Below this the text column would be too narrow for the longest bullet, so it
   takes more of the row instead. */
@media (max-width: 1100px) {
  .inv-fields-grid { grid-template-columns: 62fr 38fr; gap: var(--space-xl); }
}
@media (max-width: 900px) {
  .inv-fields-grid { grid-template-columns: 1fr; gap: var(--space-xl); }
}

.fx-head .eyebrow { display: inline-block; margin-bottom: var(--space-sm); }
.fx-head h2 { margin-bottom: var(--space-sm); }
.fx-head > p:first-of-type { color: var(--color-muted-foreground); font-size: var(--fs-lg); margin-bottom: var(--space-lg); max-width: 46ch; }
.fx-dark .fx-head h2 { color: #fff; }
.fx-dark .fx-head > p:first-of-type { color: rgba(255, 255, 255, 0.82); }
.fx-dark .hiw-text-link { color: var(--color-primary-light); }

.fx-mockup { display: flex; align-items: center; justify-content: center; }
.fx-mockup svg { width: 100%; height: auto; max-width: 560px; }

/* 2-col icon grid (block: email automation) */
.fx-feature-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
  margin-bottom: var(--space-lg);
}
/* 4-column variant (block: editor, 8 items - 7 features plus the
   CTA tile as the 8th slot): a real grid rather than the old
   flex-wrap-and-center trick, since 8 divides evenly into 4 columns
   and needs no leftover-row centering - the bottom row's items land
   in the exact same column tracks as the top row. Generous top
   margin separates it from the mockup row above. */
.fx-feature-grid--wrap {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-lg);
  margin-top: var(--space-2xl);
}
@media (max-width: 900px) {
  .fx-feature-grid--wrap { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .fx-feature-grid--wrap { grid-template-columns: 1fr; }
}
/* The Shopify hub's customization block: five items sit better 3-up than 2-up,
   and it collapses straight to one column at the 900px point the template
   pages stack at. Nothing follows the grid there, so it carries no bottom
   margin. */
.fx-feature-grid--3 { grid-template-columns: repeat(3, 1fr); margin-bottom: 0; }
@media (max-width: 900px) {
  .fx-feature-grid--3 { grid-template-columns: 1fr; }
}
/* /platforms cross-platform block: four items in the plain two-up grid, last
   thing in the section, so it drops the grid's usual bottom margin. */
.fx-feature-grid--flush { margin-bottom: 0; }
/* CTA tile: fills the 8th grid slot but reads as a button/card
   rather than another icon+text row, so it overrides the shared
   .fx-feature-item's row layout to center its single link both
   ways within a bordered tile the same size as its grid siblings.
   Doubled-up selector so it outranks the plain .fx-feature-item
   rule below it (equal specificity would otherwise let source
   order hand align-items back to that rule's flex-start). */
.fx-feature-item.fx-feature-item--cta {
  align-items: center;
  justify-content: center;
  text-align: center;
  border: 1.5px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  transition: background var(--transition-fast), border-color var(--transition-fast);
}
.fx-feature-item--cta:hover, .fx-feature-item--cta:focus-within {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.6);
}
.fx-feature-item { display: flex; gap: var(--space-sm); align-items: flex-start; }
.fx-feature-item .icon {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-tint);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
}
.fx-feature-item .icon svg { width: 20px; height: 20px; }
.fx-dark .fx-feature-item .icon { background: rgba(255, 255, 255, 0.14); color: #fff; }
.fx-feature-item strong { display: block; font-family: var(--font-heading); font-size: 0.98rem; color: var(--color-foreground); margin-bottom: 2px; }
.fx-dark .fx-feature-item strong { color: #fff; }
.fx-feature-item p { font-size: var(--fs-sm); color: var(--color-muted-foreground); }
.fx-dark .fx-feature-item p { color: rgba(255, 255, 255, 0.75); }
@media (max-width: 620px) {
  .fx-feature-grid { grid-template-columns: 1fr; }
}

/* Simple checklist (blocks: automation rules, bulk printing) */
.fx-checklist { display: flex; flex-direction: column; gap: var(--space-md); margin-bottom: var(--space-lg); }
.fx-checklist li { display: flex; gap: var(--space-sm); align-items: flex-start; list-style: none; }
.fx-checklist .check {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-success);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 2px;
}
.fx-checklist .check svg { width: 14px; height: 14px; }
.fx-checklist span { color: var(--color-foreground); }

/* Single-column icon+text list (block: print automation) */
.fx-icon-list { display: flex; flex-direction: column; gap: var(--space-md); margin-bottom: var(--space-lg); }
.fx-icon-list li { display: flex; gap: var(--space-md); align-items: flex-start; list-style: none; }
.fx-icon-list .icon {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-tint);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
}
.fx-icon-list .icon svg { width: 20px; height: 20px; }
.fx-icon-list span { color: var(--color-foreground); }

/* Real product screenshot (block: editor). The screenshot already
   shows the app's own window chrome, so this is just a plain
   photo frame - border, radius and shadow to match the other
   mockups' visual weight, no fake browser bar on top of a real one. */
.fx-photo {
  width: 100%;
  max-width: 560px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.fx-photo img { display: block; width: 100%; height: auto; }


/* ---------------------------------------------------------------------
   Hero editor animation (homepage and platform pages).
   --------------------------------------------------------------------- */
  .hf-anim { animation-duration: 26s; animation-iteration-count: infinite; animation-timing-function: ease-in-out; transform-box: fill-box; }
  .hf-s1 { animation-name: hf-scene1; }
  .hf-s2 { animation-name: hf-scene2; }
  .hf-dot1 { animation-name: hf-scene1; }
  .hf-dot2 { animation-name: hf-scene2; }
  @keyframes hf-scene1 { 0%,42% { opacity: 1; } 44%,97.5% { opacity: 0; } 100% { opacity: 1; } }
  @keyframes hf-scene2 { 0%,44% { opacity: 0; } 46%,97% { opacity: 1; } 99%,100% { opacity: 0; } }

  /* scene 1: components land on the invoice canvas with a selection flash */
  .hf-b1 { animation-name: hf-b1; }
  .hf-b2 { animation-name: hf-b2; }
  .hf-b3 { animation-name: hf-b3; }
  .hf-b4 { animation-name: hf-b4; }
  .hf-sel1 { animation-name: hf-sel1; }
  .hf-sel2 { animation-name: hf-sel2; }
  .hf-sel3 { animation-name: hf-sel3; }
  .hf-sel4 { animation-name: hf-sel4; }
  @keyframes hf-b1 { 0%,2% { opacity: 0; transform: translateY(6px); } 4%,96% { opacity: 1; transform: translateY(0px); } 100% { opacity: 0; transform: translateY(6px); } }
  @keyframes hf-b2 { 0%,6% { opacity: 0; transform: translateY(6px); } 8%,96% { opacity: 1; transform: translateY(0px); } 100% { opacity: 0; transform: translateY(6px); } }
  @keyframes hf-b3 { 0%,10% { opacity: 0; transform: translateY(6px); } 12%,96% { opacity: 1; transform: translateY(0px); } 100% { opacity: 0; transform: translateY(6px); } }
  @keyframes hf-b4 { 0%,14% { opacity: 0; transform: translateY(6px); } 16%,96% { opacity: 1; transform: translateY(0px); } 100% { opacity: 0; transform: translateY(6px); } }
  @keyframes hf-sel1 { 0%,2% { opacity: 0; } 3.5%,5% { opacity: 1; } 7%,100% { opacity: 0; } }
  @keyframes hf-sel2 { 0%,6% { opacity: 0; } 7.5%,9% { opacity: 1; } 11%,100% { opacity: 0; } }
  @keyframes hf-sel3 { 0%,10% { opacity: 0; } 11.5%,13% { opacity: 1; } 15%,100% { opacity: 0; } }
  @keyframes hf-sel4 { 0%,14% { opacity: 0; } 15.5%,17% { opacity: 1; } 19%,100% { opacity: 0; } }

  /* scene 2, beat A (print): printer pops, page feeds out of the slot via a clip reveal, "Printed" check pops, then everything clears */
  .hf-printerPop2 { animation-name: hf-printerPop2; }
  .hf-printDocFade2 { animation-name: hf-printDocFade2; }
  .hf-printRevealClip { animation-name: hf-printRevealClip; transform-origin: bottom; }
  .hf-check2, .hf-check3 { transform-origin: center; }
  .hf-check2 { animation-name: hf-check2; }
  .hf-printedLabel2 { animation-name: hf-label2; }
  @keyframes hf-printerPop2 { 0%,47% { opacity: 0; transform: scale(0.85); } 49%,63% { opacity: 1; transform: scale(1); } 67%,100% { opacity: 0; transform: scale(0.85); } }
  @keyframes hf-printDocFade2 { 0%,49% { opacity: 0; } 51%,63% { opacity: 1; } 67%,100% { opacity: 0; } }
  @keyframes hf-printRevealClip { 0%,50% { transform: scaleY(0); } 56%,96% { transform: scaleY(1); } 100% { transform: scaleY(0); } }
  @keyframes hf-check2 { 0%,57% { opacity: 0; transform: scale(0); } 59% { opacity: 1; transform: scale(1.15); } 60%,63% { opacity: 1; transform: scale(1); } 67%,100% { opacity: 0; transform: scale(0); } }
  @keyframes hf-label2 { 0%,59% { opacity: 0; transform: translateY(6px); } 61%,63% { opacity: 1; transform: translateY(0px); } 67%,100% { opacity: 0; transform: translateY(6px); } }

  /* scene 2, beat B (email): the doc enlarges and recenters, an envelope opens beneath it, the doc slides in, the flap closes, the envelope lifts off with a brief trail, "Sent" check pops */
  .hf-bigDoc3 { animation-name: hf-bigDoc3; }
  .hf-envelopeGroup3 { animation-name: hf-envelopeGroup3; }
  .hf-flapOpen3 { animation-name: hf-flapOpen3; }
  .hf-flapClosed3 { animation-name: hf-flapClosed3; }
  .hf-trail3 { animation-name: hf-trail3; }
  .hf-check3 { animation-name: hf-check3; }
  .hf-sentLabel3 { animation-name: hf-label3; }
  @keyframes hf-bigDoc3 { 0%,70% { opacity: 0; transform: translateY(-10px) scale(0.85); } 74%,78% { opacity: 1; transform: translateY(0px) scale(1); } 84% { opacity: 0; transform: translateY(220px) scale(0.55); } 100% { opacity: 0; transform: translateY(-10px) scale(0.85); } }
  @keyframes hf-envelopeGroup3 { 0%,75% { opacity: 0; transform: translateY(6px) rotate(0deg); } 77%,86% { opacity: 1; transform: translateY(0px) rotate(0deg); } 90% { opacity: 1; transform: translateY(-16px) rotate(-7deg); } 93%,97% { opacity: 1; transform: translateY(-12px) rotate(-5deg); } 100% { opacity: 0; transform: translateY(6px) rotate(0deg); } }
  @keyframes hf-flapOpen3 { 0%,77% { opacity: 0; } 79%,83% { opacity: 1; } 85%,100% { opacity: 0; } }
  @keyframes hf-flapClosed3 { 0%,84% { opacity: 0; } 86%,97% { opacity: 1; } 100% { opacity: 0; } }
  @keyframes hf-trail3 { 0%,88% { opacity: 0; } 90%,92% { opacity: 1; } 94%,100% { opacity: 0; } }
  @keyframes hf-check3 { 0%,90% { opacity: 0; transform: scale(0); } 91.5% { opacity: 1; transform: scale(1.15); } 92.5%,96% { opacity: 1; transform: scale(1); } 98%,100% { opacity: 0; transform: scale(0); } }
  @keyframes hf-label3 { 0%,92% { opacity: 0; transform: translateY(6px); } 93.5%,96% { opacity: 1; transform: translateY(0px); } 98%,100% { opacity: 0; transform: translateY(6px); } }

  @media (prefers-reduced-motion: reduce) {
    .hf-anim { animation: none !important; }
  }


/* ---------------------------------------------------------------------
   Utilities replacing the source site's inline style attributes, which the
   strict CSP blocks. !important keeps the precedence an inline style had.
   --------------------------------------------------------------------- */
.u-text-primary-strong { color: var(--color-primary) !important; font-weight: 600 !important; }
.u-pt-0 { padding-top: 0 !important; }
.u-pblock-0-xl { padding-block: 0 var(--space-xl) !important; }
.u-mx-auto { margin-inline: auto !important; }
.u-mt-md { margin-top: var(--space-md) !important; }
.u-mt-lg { margin-top: var(--space-lg) !important; }
.u-mt-xl { margin-top: var(--space-xl) !important; }
.u-mt-2xl { margin-top: var(--space-2xl) !important; }
.u-mb-md { margin-bottom: var(--space-md) !important; }
.u-text-center { text-align: center !important; }
.u-justify-center { justify-content: center !important; }
.u-block { display: block !important; }
.u-grid-2 { grid-template-columns: repeat(2, 1fr) !important; }
.u-mw-720 { max-width: 720px !important; }
.u-mw-760 { max-width: 760px !important; }
.u-mw-820 { max-width: 820px !important; }
.u-mw-940 { max-width: 940px !important; }
.u-mw-960 { max-width: 960px !important; }
.u-mw-1000 { max-width: 1000px !important; }
.u-objpos-8 { object-position: center 8% !important; }
.u-objpos-65 { object-position: center 65% !important; }
.u-bgpos-6 { background-position: center 6% !important; }
.u-bgpos-65 { background-position: center 65% !important; }
