/* ============================================================
Sitemate Design System — base.css  v0.1.0
------------------------------------------------------------
Standalone stylesheet for microsites and V3 pages. Adapted
from web-dev/globals.css (live sitemate.com) for raw HTML/CSS,
with all WordPress/Beaver Builder assumptions removed:
- typography applies to elements directly (the WordPress
.custom-font scope is dropped entirely)
- no .bb-custom-[slug] scoping, no !important
- sections + page layout defined here — WP/BB no longer
supplies the outer containers (see SECTIONS below)
- list-marker icons re-hosted locally (assets/icons/)
Colours are the full Sitemate palette (Figma › Colours page).
Tokens: see tokens.json. Conventions: see standards.md.
============================================================ */

/* == FONTS == */
/* Self-hosted in assets/fonts/ — no Google Fonts dependency (works offline, faster first
   paint, resilient to CDN blocks). Relative URLs so they resolve wherever the stylesheet
   is loaded from, incl. the CF-host footer-embed on WordPress. Roboto is one variable file
   (weights 100-900); Sunflower is a latin subset per weight. To refresh: pull the css2 API
   (family=Sunflower:wght@300;500;700&family=Roboto:wght@400;500;700) and re-save the woff2. */
@font-face {
  font-family: "Roboto";
  src: url("assets/fonts/roboto.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Sunflower";
  src: url("assets/fonts/sunflower-300.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Sunflower";
  src: url("assets/fonts/sunflower-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Sunflower";
  src: url("assets/fonts/sunflower-700.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

/* == CSS VARIABLES == */
:root {
  /* — Brand blue ramp (Figma › Icons & Buttons) — */
  --sm-blue: #0085e8; /* primary brand: links, accents, eyebrows */
  --sm-blue-light: #d8e6f6; /* light-blue fills, gradient-dark edge */
  --sm-blue-dark: #0b62af; /* blue-button hover */
  --sm-blue-accent: #003166; /* deepest accent blue */
  --sm-blue-hero: #2e81da; /* breadcrumb gradient (dark edge) */
  --sm-blue-hero-light: #78b0eb; /* breadcrumb gradient (light edge) + outlined pill border */

  /* — Text (Figma › Text Colours) — */
  --sm-text: #2e3940; /* default text */
  --sm-text-body: #747474; /* lighter body / muted text */
  --sm-white: #fff; /* inverse text / card + tooltip background */

  /* slug/eyebrow text = var(--sm-blue) */

  /* — Greys, light → dark (Figma › Greys 1–5) — */
  --sm-grey-1: #f5f6f7; /* section + grey-button background */
  --sm-grey-2: #ebedef; /* grey-button hover */
  --sm-grey-3: #e0e2e4; /* borders (bento card) */
  --sm-grey-4: #d0d2d4;
  --sm-grey-5: #b0b2b4;

  /* — Semantic role aliases (point at the ramp above) — */
  --sm-blue-hover: var(--sm-blue-dark);
  --sm-bg-grey: var(--sm-grey-1);
  --sm-bg-grey-hover: var(--sm-grey-2);
  --sm-border: var(--sm-grey-3);
  --sm-blue-pale: #f5f9fd; /* lightest blue — table row hover + highlighted column */
  --sm-red: #e3514d; /* not-available / error (e.g. comparison-table ✕) + safety system accent */

  /* — System accents (named by colour; used for per-system pill borders/icons) — */
  --sm-cyan: #3ec5d6; /* system accent */
  --sm-yellow: #f6bb2d; /* system accent */
  --sm-slate: #8299ae; /* system accent */

  /* — Layout — */
  --nav-h: 72px; /* shared header height, for sticky offsets — keep in sync with site-header.js --nav-h */
  --content-max: 1328px; /* site content width — cap + centre inner containers */

  /* — Effects — */
  --soft-shadow: 0 2px 9px rgba(0, 0, 0, 0.08);
  --soft-inset: inset 0 0 6px rgba(0, 0, 0, 0.1);

  /* — 8px spacing grid — every padding / margin / gap is a multiple of 8.
  Author microsites with these; never hand-roll off-grid spacing. — */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 40px;
  --space-6: 48px;
  --space-8: 64px;
  --space-12: 96px;

  /* — Fluid type scale (clamp: min → fluid(vw) → max). Max = the desktop size,
  so desktop is unchanged; smaller screens scale down smoothly with no
  breakpoints. Font size is NOT on the 8px grid (that governs spacing). — */
  --font-h1: clamp(1.875rem, 1.6rem + 1.05vw, 2.5rem); /* 30 → 40 */
  --font-h2: clamp(1.5rem, 1.35rem + 0.63vw, 1.875rem); /* 24 → 30 */
  --font-h3: clamp(1.25rem, 1.15rem + 0.4vw, 1.5rem); /* 20 → 24 — Sunflower reads smaller
    than Roboto at the same px, so h3 was sitting too close to body copy */
  --font-h4: 16px; /* smallest heading — fixed 16px (card titles) */
  --font-body: clamp(1rem, 0.95rem + 0.2vw, 1.125rem); /* 16 → 18 */
  --font-sm: 16px; /* small/secondary text (card excerpts, UI labels) — fixed, below body */
  --font-xs: 14px; /* extra-small labels (card slugs/eyebrows, breadcrumb) */
  --font-sm: 16px; /* small/secondary text (card excerpts, UI labels) — fixed, below body */
  --font-xs: 14px; /* extra-small labels (card slugs/eyebrows, breadcrumb) */
}

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

/* Always reserve the scrollbar gutter so page width doesn't shift between
short and long views (e.g. toggling microsite tabs). */
html {
  scrollbar-gutter: stable;
  scroll-padding-top: calc(var(--nav-h) + var(--space-2)); /* in-page jumps clear the sticky header */
}

/* Smooth in-page jumps (anchor nav) — respect users who prefer reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  margin: 0;
  font-family: "Roboto", sans-serif;
  font-size: var(--font-body);
  color: var(--sm-text);
  background: #fff;
}

/* == TYPOGRAPHY ==
Applied directly to elements. Base body/link size is 18px. */
a {
  font-size: var(--font-body);
  text-decoration: none;
  color: var(--sm-blue);
}

h1 {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: var(--font-h1);
  line-height: 1.4;
  margin: 0 0 var(--space-2); /* explicit — no UA top-margin leak */
  text-transform: capitalize;
}

/* An h1 that ends its container keeps no trailing margin, so the container's bottom
   padding matches its top instead of reading heavier. */
h1:last-child {
  margin-bottom: 0;
}

h2 {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: var(--font-h2);
  line-height: 1.5;
  margin: 0 0 var(--space-2); /* explicit — no UA top-margin leak */
  text-transform: capitalize;
}

h3 {
  font-size: var(--font-h3);
  line-height: 1.5;
  margin: 0 0 var(--space-1); /* explicit */
}

h4 {
  font-size: var(--font-h4);
  line-height: 1.5;
  margin: 0;
  font-weight: 500;
}

h5,
.eyebrow-sm {
  font-size: 16px;
  color: var(--sm-blue);
  text-transform: uppercase;
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  letter-spacing: 1px;
  margin: 0 0 var(--space-1); /* explicit; small gap to heading */
}

p {
  font-size: var(--font-body);
  line-height: 1.5;
  margin: 0 0 var(--space-2); /* explicit — no UA top-margin leak */
  color: var(--sm-text-body); /* lighter body text; headings keep --sm-text */
  text-wrap: pretty;
}

li {
  line-height: 1.7;
  margin: 0 0 var(--space-1) -16px; /* explicit; -16 left offset */
  color: var(--sm-text-body);
  list-style-position: outside;
}

li a {
  font-weight: 500;
}

ul {
  margin: 0 0 0 -16px;
}

/* Switch headings to Sunflower where the default doesn't apply it. */
.sunflower,
.sunflower h1,
.sunflower h2 {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  text-wrap: pretty;
}

.sunflower h3 {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  text-transform: capitalize;
}

.blue-highlight {
  color: var(--sm-blue);
}

/* == SECTIONS / LAYOUT ==
Raw-HTML page scaffold — replaces the WordPress/BB row + column
containers that used to supply the outer page layout. A page is a
vertical stack of full-width <section>s: each paints its background
edge-to-edge and owns the vertical rhythm + side gutter, while the
inner .custom-grid centres content at max 1328px. <body> stays
full-width (no max-width) so section backgrounds run to the
viewport edges; horizontal containment lives on .custom-grid. */
/* Vertical rhythm is a flat 64px top + bottom on EVERY section (side gutter always
   24px, 16 on mobile). The colour/transition classes below are kept as explicit hooks
   but currently resolve to the same 64px — the 96px "breathe more" on colour sections
   was dialled back to 64 in the Jul-2026 design review (site read as too empty). To
   reintroduce differential spacing later, bump these back to --space-12. */
section {
  padding: var(--space-8) var(--space-3); /* 64 / 24 */
}

section.section-colour {
  padding-block: var(--space-8); /* 64 — flat rhythm (was 96) */
}

section.section-after-colour {
  padding-top: var(--space-8); /* 64 — flat rhythm (was 96) */
}

section.section-before-colour {
  padding-bottom: var(--space-8); /* 64 — flat rhythm (was 96) */
}

/* Library/index sections whose ROWS or CARDS carry their own vertical padding: the
   section's 64px would stack on top of the item's, so the content reads double-padded.
   This hands the vertical rhythm to the items and keeps the side gutter. */
section.section-flush {
  padding-block: 0;
}

/* The page's first section always gets 64px top — sits consistently under the
   sticky nav no matter its colour/transition class. (Higher specificity wins.) */
main > section:first-of-type {
  padding-top: var(--space-8); /* 64 */
}

@media (max-width: 768px) {
  section {
    padding: var(--space-6) var(--space-2); /* 48 / 16 — normal */
  }

  section.section-colour {
    padding-block: var(--space-8); /* 64 */
  }

  section.section-after-colour {
    padding-top: var(--space-8); /* 64 */
  }

  section.section-before-colour {
    padding-bottom: var(--space-8); /* 64 */
  }
}

/* == LAYOUT UTILITIES == */

/* Vertical rhythm for a text group — even spacing via gap, no per-element margins.
Wrap eyebrow/heading/body/CTA in .stack instead of relying on element margins. */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.stack > * {
  margin: 0;
}

/* Section header content group (eyebrow → title → intro → cta) — even space-2 spacing,
kept separate from the cards/media below it. */
.stack-headings {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
}

.stack-headings > * {
  margin: 0;
}

.product-logo {
  height: 32px;
  width: auto;
  margin-bottom: var(--space-2);
}

/* Caption/lockup logos (Sitemate Mobile App, *-logo-caption) pack a descriptor
alongside the wordmark, so they need extra height to stay legible vs standard logos. */
.product-logo--caption {
  height: 48px;
}

/* Images in a stack must not stretch to full width — keep them left-aligned at natural size. */
.stack > img,
.stack-headings > img {
  align-self: flex-start;
}

/* Two-column feature split: text + media with a generous 40px gap, wraps on small screens.
Use instead of .custom-grid when you want >16px between columns (the grid's column
math is tuned to the 16px gap, so widening its gap overflows). */
.split {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  max-width: 1328px;
  margin: 0 auto;
}

.split > * {
  flex: 1 1 360px;
  min-width: 0;
}

.closing-slogan  {
  padding-top: var(--space-3);
}

/* == GRID ==
12-col flexbox grid, identical class names + breakpoints to the
live site so bb-module markup ports over unchanged. */
.custom-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  max-width: 1328px;
  margin: 0 auto;
}

.custom-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  width: 100%;
}

.custom-col-1,
.custom-col-2,
.custom-col-3,
.custom-col-4,
.custom-col-5,
.custom-col-6,
.custom-col-7,
.custom-col-8,
.custom-col-9,
.custom-col-10,
.custom-col-11,
.custom-col-12 {
  min-width: 0;
}

.custom-col-1 {
  flex: 0 0 calc(8.33% - 14.67px);
}

.custom-col-2 {
  flex: 0 0 calc(16.66% - 13.33px);
}

.custom-col-3 {
  flex: 0 0 calc(25% - 12px);
}

.custom-col-4 {
  flex: 0 0 calc(33.33% - 10.67px);
}

.custom-col-5 {
  flex: 0 0 calc(41.66% - 9.33px);
}

.custom-col-6 {
  flex: 0 0 calc(50% - 8px);
}

.custom-col-7 {
  flex: 0 0 calc(58.33% - 6.67px);
}

.custom-col-8 {
  flex: 0 0 calc(66.66% - 5.33px);
}

.custom-col-9 {
  flex: 0 0 calc(75% - 4px);
}

.custom-col-10 {
  flex: 0 0 calc(83.33% - 2.67px);
}

.custom-col-11 {
  flex: 0 0 calc(91.66% - 1.33px);
}

.custom-col-12 {
  flex: 0 0 100%;
}

.lg-row-mod {
  row-gap: var(--space-4);
}

/* 32 */
.bento-col {
  border: 1px solid var(--sm-border);
  padding: var(--space-2);
  border-radius: var(--space-2);
  background: #fff;
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.3s ease, border-color 0.15s ease;
}

.bento-col:hover {
  box-shadow: var(--soft-shadow);
}

/* Whole-card links compose .bento-col.is-linkcard (see CARD COMPOSITION) — it owns the
   hover border and the CTA gap, so there is no element-based rule here. */

/* No trailing margin on a card's last element, at ANY nesting depth — so the last
   line of text sits an even 24px from the border, keeping card padding consistent. */
.bento-col :last-child {
  margin-bottom: 0;
}

/* Opt-in gap modifier for a bento-col with an image + text container — 24px gap
between the card's children. Don't use on icon+text cards or cards with no media. */
.bento-gap {
  gap: var(--space-3);
}

/* Image + text bento: the copy is wrapped in .bento-col-text and pushed to the bottom
(margin-top:auto) so it aligns across cards of unequal image/copy length. The gap
between image and text comes from .bento-gap above — not element margins. */
.bento-col-text {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.bento-col-text > * {
  margin: 0;
}

/* Use-case thumbnail card — a form/screen preview bleeding off the bottom of a
dark panel, copy below. Compose:
.bento-col.thumb-card > .thumb-preview.gradient-dark > img
+ .bento-col-text.thumb-card-text > h3 + p */
.thumb-card {
  padding: 0;
}

.thumb-preview {
  padding: var(--space-2) var(--space-2) 0;
  border-radius: 8px 8px 0 0;
  overflow: hidden;
  height: 240px;
}

/* gap to text comes from .bento-gap */
.thumb-preview img {
  width: 100%;
  display: block;
  box-shadow: var(--soft-shadow);
}

.thumb-card-text {
  padding: 0 var(--space-3) var(--space-3);
}

@media (max-width: 1324px) {
  .custom-col-4,
  .custom-col-5,
  .custom-col-6,
  .custom-col-7,
  .custom-col-8 {
    flex: 0 0 calc(50% - 8px);
  }
}

@media (max-width: 992px) {
  .custom-col-1,
  .custom-col-2,
  .custom-col-3,
  .custom-col-4,
  .custom-col-5,
  .custom-col-6,
  .custom-col-7,
  .custom-col-8,
  .custom-col-9,
  .custom-col-10,
  .custom-col-11 {
    flex: 0 0 calc(50% - 8px);
  }

  .stack-medium .custom-col-1,
  .stack-medium .custom-col-2,
  .stack-medium .custom-col-3,
  .stack-medium .custom-col-4,
  .stack-medium .custom-col-5,
  .stack-medium .custom-col-6,
  .stack-medium .custom-col-7,
  .stack-medium .custom-col-8,
  .stack-medium .custom-col-9,
  .stack-medium .custom-col-10,
  .stack-medium .custom-col-11,
  .stack-medium .custom-col-12 {
    flex: 0 0 100%;
  }
}

@media (max-width: 768px) {
  .custom-grid {
    max-width: 720px;
  }

  .custom-col-1,
  .custom-col-2,
  .custom-col-3,
  .custom-col-4,
  .custom-col-5,
  .custom-col-6,
  .custom-col-7,
  .custom-col-8,
  .custom-col-9,
  .custom-col-10,
  .custom-col-11,
  .custom-col-12 {
    flex: 0 0 100%;
  }
}

@media (max-width: 474px) {
  .custom-grid {
    max-width: 100%;
  }
}

/* Sticky-nav layout — holds declared widths ≥993px (for sidebar
layouts), stacks below. */
@media (min-width: 993px) {
  .sticky-nav .custom-col-1 {
    flex: 0 0 calc(8.33% - 14.67px);
  }

  .sticky-nav .custom-col-2 {
    flex: 0 0 calc(16.66% - 13.33px);
  }

  .sticky-nav .custom-col-3 {
    flex: 0 0 calc(25% - 12px);
  }

  .sticky-nav .custom-col-4 {
    flex: 0 0 calc(33.33% - 10.67px);
  }

  .sticky-nav .custom-col-5 {
    flex: 0 0 calc(41.66% - 9.33px);
  }

  .sticky-nav .custom-col-6 {
    flex: 0 0 calc(50% - 8px);
  }

  .sticky-nav .custom-col-7 {
    flex: 0 0 calc(58.33% - 6.67px);
  }

  .sticky-nav .custom-col-8 {
    flex: 0 0 calc(66.66% - 5.33px);
  }

  .sticky-nav .custom-col-9 {
    flex: 0 0 calc(75% - 4px);
  }

  .sticky-nav .custom-col-10 {
    flex: 0 0 calc(83.33% - 2.67px);
  }

  .sticky-nav .custom-col-11 {
    flex: 0 0 calc(91.66% - 1.33px);
  }

  .sticky-nav .custom-col-12 {
    flex: 0 0 100%;
  }
}

@media (max-width: 992px) {
  .sticky-nav .custom-col-1,
  .sticky-nav .custom-col-2,
  .sticky-nav .custom-col-3,
  .sticky-nav .custom-col-4,
  .sticky-nav .custom-col-5,
  .sticky-nav .custom-col-6,
  .sticky-nav .custom-col-7,
  .sticky-nav .custom-col-8,
  .sticky-nav .custom-col-9,
  .sticky-nav .custom-col-10,
  .sticky-nav .custom-col-11,
  .sticky-nav .custom-col-12 {
    flex: 0 0 100%;
  }
}

/* == LIST STYLES == (icons re-hosted locally) */
.checklist-tick li {
  list-style: none;
  background-image: url("assets/icons/tick.svg");
  background-repeat: no-repeat;
  background-position: 0 0.55em;
  padding-left: 1.5em;
  margin-left: -24px;
  line-height: 2;
}

.checklist-dot li {
  list-style: none;
  background-image: url("assets/icons/dot-for-li.svg");
  background-repeat: no-repeat;
  background-position: 0 0.55em;
  padding-left: 1.5em;
  margin-left: -24px;
  line-height: 1.5;
}

.checklist-number ul {
  counter-reset: list-counter;
}

.checklist-number li {
  list-style: none;
  counter-increment: list-counter;
  position: relative;
  padding-left: 1.5em;
  margin-left: -24px;
  line-height: 2;
}

.checklist-number li::before {
  content: counter(list-counter) ".";
  position: absolute;
  left: 0;
  color: var(--sm-blue);
  font-weight: 400;
}

/* == BACKGROUNDS == */

/* Do NOT use as a section background — flat grey reads dull; use
.gradient-light for a lifted section instead. Kept for small fills only. */
.sm-bg-grey {
  background: var(--sm-bg-grey);
}

/* Light radial gradient fill. The default classes carry a soft inset shadow that
   lifts the section off the page; the *-flat variants are the identical fill but
   flush (no inset). Swap a *-flat class in per section on a case-by-case basis;
   rules for when flat becomes the automatic default are still TBD. */
.gradient-light,
.animated-gradient-light,
.gradient-light-flat,
.animated-gradient-light-flat {
  background: radial-gradient(circle at center, #f2f8ff, #fdfdfd 75%);
}

/* lifted (inset shadow) — default variants only, never the *-flat ones */
.gradient-light,
.animated-gradient-light {
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.05);
}

/* animated motion — shared by the lifted and flat animated variants */
.animated-gradient-light,
.animated-gradient-light-flat {
  background-size: 300% 300%;
  background-position: 0% 0%;
  animation: gradientMove 14s ease-in-out infinite;
}

@keyframes gradientMove {
  0% {
    background-position: 0% 0%;
  }

  25% {
    background-position: 100% 0%;
  }

  50% {
    background-position: 100% 100%;
  }

  75% {
    background-position: 0% 100%;
  }

  100% {
    background-position: 0% 0%;
  }
}

/* gradient-dark: a decorative backdrop for IMAGES / panels only —
never put body text on it (contrast is too low to read reliably;
use gradient-light / animated-gradient-light with default text for
text sections). NOT yet live on sitemate.com — push live before
using in website modules. */
.gradient-dark,
.animated-gradient-dark {
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.08);
}

.gradient-dark,
.gradient-dark-flat {
  background:
    radial-gradient(
      circle at top right,
      var(--sm-blue),
      rgba(0, 133, 232, 0) 60%
    ),
    radial-gradient(
      circle at bottom left,
      var(--sm-blue),
      rgba(0, 133, 232, 0) 60%
    ),
    var(--sm-blue-light);
}

.animated-gradient-dark,
.animated-gradient-dark-flat {
  background: radial-gradient(
    circle at center,
    var(--sm-blue),
    var(--sm-blue-light) 75%
  );
  background-size: 300% 300%;
  background-position: 0% 0%;
  animation: gradientMove 14s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto; /* respect reduced-motion — no smooth scrolling */
  }

  .animated-gradient-light,
  .animated-gradient-dark,
  .animated-gradient-light-flat,
  .animated-gradient-dark-flat {
    animation: none;
    background-size: auto;
    background-position: center;
  }
}

.no-inner-shadow {
  box-shadow: none;
}

/* == BUTTONS == */
.button-group {
  display: flex;
  gap: var(--space-2); /* 16 */
  max-width: fit-content;
  margin-top: var(--space-3); /* 24 */
}

.blue-buttons {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--sm-blue);
  color: #fff;
  text-decoration: none;
  border-radius: 10px;
  transition: gap 0.25s ease;
  justify-content: center;
}

.text-buttons {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  transition: gap 0.25s ease;
  justify-content: center;
  /* also usable on a <button> — strip native chrome so it reads as a text link */
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
}

.grey-buttons {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--sm-bg-grey);
  color: var(--sm-text);
  text-decoration: none;
  border-radius: 10px;
  transition: all 0.25s ease;
  justify-content: center;
}

.blue-buttons:hover {
  gap: var(--space-3);
  background: var(--sm-blue-hover);
  color: #fff;
}

.grey-buttons:hover {
  background: var(--sm-bg-grey-hover);
  color: var(--sm-text);
}

.text-buttons:hover {
  gap: var(--space-3);
  color: var(--sm-text);
}

.grey-buttons a,
.blue-buttons a,
.grey-buttons a:hover,
.blue-buttons a:hover {
  text-decoration: none;
  color: inherit;
}

.learn-more-btn,
.learn-more-btn:hover,
.learn-more-btn a,
.learn-more-btn a:hover {
  color: var(--sm-text);
  text-decoration: none;
  display: flex;
  align-items: center;
  font-size: 16px;
  gap: var(--space-1);
  transition: 0.3s ease all;
}

.learn-more-btn img {
  max-width: 16px;
}

.learn-more-btn:hover {
  gap: var(--space-2);
}

@media (max-width: 768px) {
  .button-group {
    flex-direction: column;
    text-align: center;
    max-width: 100%;
  }
}

/* == MEDIA == */

/* Feature / hero video — a lifted treatment, distinct from inline content images.
Wrap a Vimeo/YouTube iframe; 16:9, slight scale to crop the player's letterboxing. */
.vimeo-container {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid #fff;
  box-shadow: var(--soft-shadow);
}

.vimeo-container iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  transform: scale(1.01); /* crop the player's letterbox edges */
  transform-origin: center;
}

/* == PAGE LAYOUT HELPER ==
Centred block container for single-column section content (use .custom-grid
for column layouts, .split for two-column). Section padding supplies the side
gutter, so this only caps + centres — exact 1328px at full width. */
.section-inner {
  max-width: 1328px;
  margin-inline: auto;
}

/* == LONG-FORM / BLOG CONTENT ==
Primitives for blog + article body copy (ported from the live sitemate.com blog
template, re-expressed in tokens). Pair with a capped reading measure on the
article wrapper (~820px) — section padding still supplies the side gutter. */

/* Pull-quote — blue left rule, darker --sm-text (headings colour) to lift it off
   the muted body copy. Replaces the live theme's ad-hoc .block-quote-blog. */
blockquote {
  margin: var(--space-4) 0;
  padding: var(--space-1) 0 var(--space-1) var(--space-3);
  border-left: 3px solid var(--sm-blue);
  color: var(--sm-text);
}

blockquote p {
  color: var(--sm-text); /* override the muted body colour inside quotes */
  font-size: calc(var(--font-body) + 1px);
  margin: 0 0 var(--space-2);
}

blockquote p:last-child {
  margin-bottom: 0;
}

/* Content image — a photo/diagram in a light-blue matted frame, optional caption.
   Frame colour + inset mirror the live blog's img-container, on base.css tokens
   (radius 16, --space-3 padding). Nested radius: frame 16 → image 8. */
figure {
  margin: var(--space-4) 0;
}

.img-frame {
  background: var(--sm-blue-light);
  padding: var(--space-3);
  border-radius: 16px;
  box-shadow: inset 0 0 16px rgba(0, 0, 0, 0.03);
  text-align: center;
}

.img-frame img {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 0 auto;
  border-radius: 8px;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.12));
}

figcaption {
  margin-top: var(--space-2);
  font-style: italic;
  font-size: 15px;
  line-height: 1.5;
  color: var(--sm-text-body);
  text-align: center;
  text-wrap: pretty;
}

/* == BLOG (.sm-blog editorial module) ==
Blog body used by headless posts (/blog/<slug>/; template website/site/_example-blog/),
scoped under .sm-blog. TYPE is inherited from the global element styles above (h1/h2/h3/p/
li/a/blockquote) — the blog does NOT define its own type scale, so it stays in step with the
rest of the site. This section is layout + components only: the hero lockup, the rising white
card, alternating bands, the custom audiobook player, and the author bio. blockquote / figure /
.img-frame / figcaption are the global LONG-FORM primitives above. Posts carry no inline
<style>; styling lives here, and the audiobook JS in /shared/blog-audio.js. */
.sm-blog {
  width: 100%;
  background: var(--sm-white);
  font-family: "Roboto", sans-serif;
  color: var(--sm-text); /* headings inherit this; the global `p` rule sets the muted body colour */
  -webkit-font-smoothing: antialiased;
}

.sm-blog * {
  box-sizing: border-box;
}

.sm-blog h3 {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  text-transform: capitalize;
  margin-bottom: var(--space-1);
}

.sm-blog h3:not(:first-child) {
  margin-top: var(--space-4);
}

/* hero band — light gradient supplied by the .gradient-light utility on the element */
.sm-blog-hero {
  padding: var(--space-8) var(--space-6) 120px;
}
.sm-blog-hero-inner {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin: var(--space-4) auto;
  max-width: 976px;
}
.sm-blog-badge {
  width: 120px;
  height: 120px;
  flex: 0 0 auto;
  display: block;
  filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.1));
}

/* A Lottie badge paints to the full box with square corners, so it needs the radius
   clipped on. Static SVG badges carry their own rounded artwork and need nothing. */
lottie-player.sm-blog-badge {
  border-radius: 24px;
  overflow: hidden;
}

.sm-blog-hero-text {
  min-width: 0;
}
/* cap the hero title's line length so long titles wrap instead of stretching wide
   (global default; override per-post only if a title genuinely needs it) */
.sm-blog-hero-text h1 {
  max-width: 644px;
}

/* first white card — 64px top corners, rises into the hero */
.sm-blog-card {
  background: var(--sm-white);
  max-width: 1104px;
  margin: -120px auto 0; /* deliberate negative overlap — the card rises into the hero */
  padding: var(--space-8);
  border-radius: 64px 64px 24px 24px; /* radius — off the spacing grid by design */
  position: relative;
  z-index: 2;
}

/* Soft (regular) drop shadow shown ONLY where the card overlaps the hero
   (its top 120px) — same values as the .gradient-light shadow but a normal
   outer shadow, not inset. Lives on a pseudo-element so clip-path can trim it
   to the overlap without clipping the card's content; cut off at the hero's
   bottom edge so the card sits flush against the white body/bands below. */
.sm-blog-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  clip-path: inset(-16px -16px calc(100% - 120px) -16px);
  pointer-events: none;
}

/* section bands — alternate is-grad / is-white */
.sm-blog-band {
  padding: var(--space-8) var(--space-3);
}
.sm-blog-band.is-grad {
  background: radial-gradient(circle at center, #f2f8ff, #fdfdfd 75%);
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.01);
}
.sm-blog-band.is-white {
  background: var(--sm-white);
}
/* the About-the-Author band is ALWAYS white, never the gradient — enforced here so it
   can't be authored wrong (overrides is-grad regardless of the class on the band). */
.sm-blog-band:has(.sm-blog-author) {
  background: var(--sm-white);
  box-shadow: none;
}
.sm-blog-inner {
  max-width: 1104px;
  margin: 0 auto;
  padding: 0 var(--space-8);
}
/* first heading in a band/card sits flush (the band/card padding is the top gap) */
.sm-blog-inner > :is(h1, h2, h3):first-child, .sm-blog-card > :is(h1, h2, h3):first-child {
  margin-top: 0;
}

/* audiobook — custom on-brand player. Native <audio> controls live in shadow DOM and can't
   be themed, so the markup hides <audio> and drives our own elements (JS: /shared/blog-audio.js). */
.sm-blog .audiobook {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  padding: 0;
  background: var(--sm-white);
}
.sm-blog .audiobook p {
  margin: 0;
  font-size: 13px;
  color: var(--sm-text-body);
}
.sm-blog .sm-audio {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.sm-blog .sm-audio audio {
  display: none;
}
.sm-blog .sm-audio-play {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 0;
  background: var(--sm-blue);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 0.2s ease;
}
.sm-blog .sm-audio-play:hover {
  background: var(--sm-blue-dark);
}
.sm-blog .sm-audio-play::before {
  content: "";
  display: block;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 7px 0 7px 12px;
  border-color: transparent transparent transparent var(--sm-white);
  margin-left: 3px;
}
.sm-blog .sm-audio.is-playing .sm-audio-play::before {
  width: 10px;
  height: 13px;
  border: 0;
  border-left: 3px solid var(--sm-white);
  border-right: 3px solid var(--sm-white);
  margin-left: 0;
}
.sm-blog .sm-audio-bar {
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--sm-blue-light);
  position: relative;
  cursor: pointer;
}
.sm-blog .sm-audio-fill {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 0;
  background: var(--sm-blue);
  border-radius: 999px;
}
.sm-blog .sm-audio-time {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--sm-text-body);
  font-variant-numeric: tabular-nums;
  min-width: 40px;
  text-align: right;
}

/* author bio + optional past-projects disclosure */
.sm-blog-author {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.sm-blog-author > img {
  width: 96px;
  height: 96px;
  border-radius: 16px;
  object-fit: cover;
  flex: 0 0 auto;
}
.sm-blog-author-meta h3 {
  margin: 0;
}
.sm-blog-author-meta p {
  margin: var(--space-1) 0 0;
  font-size: 15px;
  color: var(--sm-text-body);
}
.sm-blog-project {
  margin: 0 0 var(--space-2);
}
.sm-blog-project strong {
  display: block;
  color: var(--sm-text);
}
.sm-blog details.sm-blog-projects > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: 18px;
  line-height: 1.5;
  color: var(--sm-text);
  text-transform: capitalize;
}
.sm-blog details.sm-blog-projects > summary::-webkit-details-marker {
  display: none;
}
.sm-blog details.sm-blog-projects > summary::after {
  content: "";
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--sm-text);
  border-bottom: 2px solid var(--sm-text);
  transform: rotate(45deg);
  transition: transform 0.2s ease;
}
.sm-blog details.sm-blog-projects[open] > summary::after {
  transform: rotate(-135deg);
}
.sm-blog details.sm-blog-projects .sm-blog-project:first-of-type {
  margin-top: var(--space-3);
}
.sm-blog-bento {
  margin: var(--space-4) 0;
  border-top: 1px solid var(--sm-border);
  border-bottom: 1px solid var(--sm-border);
  padding: var(--space-3) 0;
  background: var(--sm-white);
}
.sm-blog-bento > details.sm-blog-projects {
  margin-top: 0;
}
.sm-blog-bento .sm-blog-project:last-child {
  margin-bottom: 0;
}
.sm-blog-version {
  font-size: 13px;
  color: var(--sm-text-body);
  margin-top: 0;
}

@media (max-width: 768px) {
  .sm-blog-hero {
    padding: var(--space-6) var(--space-3);
  }
  .sm-blog-hero-inner {
    flex-direction: column;
    text-align: center;
    gap: var(--space-3);
  }
  .sm-blog-card {
    padding: var(--space-3) var(--space-3) var(--space-6);
    border-radius: 32px 32px 16px 16px;
    margin-top: -32px;
  }
  /* overlap is 32px on mobile — clip the shadow to match */
  .sm-blog-card::before {
    clip-path: inset(-16px -16px calc(100% - 32px) -16px);
  }
  .sm-blog-band {
    padding: var(--space-6) var(--space-2);
  }
  .sm-blog-inner {
    padding: 0;
  }
  .sm-blog-author {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* == RESEARCH TOPICS (library + cluster pages) ==
   Composed from base primitives (.bento-col, .eyebrow-sm, .text-buttons) plus small
   additive modifiers + a few shared components (breadcrumb, search, card parts, index
   layout, resource-row). Consumers: /topics/ and /topics/{system}/{topic}/. == */

/* == LIBRARY / DYNAMIC-PULL SECTION ==
Reusable scaffold for any "browse + filter" index whose cards are pulled dynamically
(research topics, resources, blogs, use cases…). Structure: an optional gradient
breadcrumb bar → a centred hero with a search → a two-column body (a sticky filter
sidebar + a card grid split into titled groups). Cards compose the DS .bento-col
primitive; the grid is the DS .custom-grid / .custom-col-N flex grid. First used on
/topics/. Compose with the DS tokens + .blue-buttons / .grey-buttons / .text-buttons. */

/* Breadcrumb bar — gradient strip directly under the nav */
.sm-breadcrumb { background: linear-gradient(90deg, var(--sm-blue-hero) 0%, var(--sm-blue-hero-light) 100%); }
.sm-breadcrumb-inner {
  width: min(100% - 48px, var(--content-max));
  margin: 0 auto;
  min-height: 44px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1);
  padding-block: 10px;
}
.sm-breadcrumb a,
.sm-breadcrumb span {
  color: var(--sm-white);
  font-size: var(--font-xs);
  text-decoration: none;
}
.sm-breadcrumb a { opacity: .9; }
.sm-breadcrumb a:hover {
  opacity: 1;
  text-decoration: underline;
}
.sm-breadcrumb .sep { opacity: .6; }

/* A crumb whose target is not live yet. It reads as part of the trail without
   pretending to be a link, so the hierarchy still shows and nothing points at a
   404. The bake decides which crumbs these are, from `routes` in topics.json. */
.sm-breadcrumb .is-pending {
  opacity: .6;
  cursor: default;
}
.sm-breadcrumb [aria-current="page"] { font-weight: 500; }

/* Eyebrow modifiers — compose on .eyebrow-sm (Sunflower/uppercase/blue/letter-spacing base).
   .is-pill  → outlined pill box (hero eyebrow)
   .is-system→ second, overlapping pill tucked behind the first (border-color set inline)
   .is-xs    → extra-small inline icon+label variant (card tags, on-page-nav eyebrows) */
.eyebrow-sm.is-pill {
  display: inline-block;
  padding: 8px 16px;
  border: 1px solid var(--sm-blue-hero-light);
  border-radius: 8px;
  background: var(--sm-white);
  z-index: 99;
}
.eyebrow-sm.is-pill.is-system {
  padding-left: var(--space-3);
  margin-left: -24px;
  z-index: 1;
  color: var(--sm-text);
}
.eyebrow-sm.is-pill img {
  width: 16px;
  height: 16px;
  vertical-align: -3px;
  margin-right: 4px;
}
.eyebrow-sm.is-xs {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--font-xs);
  margin-bottom: 0;
}
.eyebrow-sm.is-xs img {
  width: 14px;
  height: 14px;
}

/* Hero — centred column (eyebrow → title → intro → search) */
.library-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  max-width: var(--content-max);
  margin: 0 auto;
}
.library-hero h1 { max-width: 820px; }
.library-hero p {
  max-width: 800px;
  margin: 0;
}
/* Row of hero pills (Research Topic + System), centred */
.library-hero-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1);
}

/* Optional title block — wrap the H1 + intro so the hero gap breathes around the pair
   (eyebrow ↔ title-block ↔ search) rather than between the title and its subhead. */
.library-hero-title h1 { margin-bottom: var(--space-1); }

/* Search field (pill) — shared primitive: hero, sidebar, any dynamic index */
.sm-search {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  background: var(--sm-white);
  border: 1px solid var(--sm-border);
  border-radius: 999px;
  padding: 10px 18px;
}
.sm-search svg {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  color: var(--sm-grey-5);
}
.sm-search input {
  border: 0;
  outline: 0;
  background: transparent;
  font-size: var(--font-sm);
  color: var(--sm-text);
  width: 100%;
  font-family: inherit;
  appearance: none;
  -webkit-appearance: none; /* strip the type=search UA chrome (left inset + cancel button) */
}
.sm-search input::placeholder { color: var(--sm-grey-5); }
/* Hero variant — hug the icon + placeholder instead of stretching. field-sizing shrinks the
   field to its text (grows as you type); older browsers fall back to the intrinsic width. */
.sm-search--hero {
  width: auto;
  max-width: 100%;
}
.sm-search--hero input {
  width: auto;
  min-width: 14ch;
  field-sizing: content;
}

/* Index body layout — sticky filter sidebar + card column (reusable across dynamic indexes) */
.index-layout {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  max-width: var(--content-max);
  margin: 0 auto;
}
.index-sidebar {
  flex: 0 0 300px;
  position: sticky;
  top: 96px;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.index-content {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

/* Sidebar filter (collapsible) */
.index-filter-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-size: var(--font-sm);
  color: var(--sm-text-body);
  font-family: inherit;
}
.index-filter-head svg {
  width: 16px;
  height: 16px;
  transition: transform .2s ease;
}
.index-filter.is-collapsed .index-filter-head svg { transform: rotate(-90deg); }
.index-filter-list {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.index-filter.is-collapsed .index-filter-list { display: none; }
.index-filter-list li { margin: 0; }
.index-filter-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  padding: 9px 0;
  font-size: var(--font-sm);
  color: var(--sm-text);
  cursor: pointer;
  font-family: inherit;
  transition: color .15s ease;
}
.index-filter-btn:hover { color: var(--sm-blue); }
.index-filter-btn.is-active {
  color: var(--sm-blue);
  font-weight: 500;
}

/* Sidebar CTAs — stacked, full-width */
.index-sidebar-cta {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.index-sidebar-cta .blue-buttons,
.index-sidebar-cta .grey-buttons { width: 100%; }

/* Card group (a titled band of cards) */
.library-group-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-h2);
  margin: 0 0 var(--space-3);
  color: var(--sm-text);
}
.library-group-title img {
  width: 32px;
  height: 32px;
}
/* Groups are <section>s but sit inside .index-content, whose flex gap already spaces them —
   drop the inherited section padding so they aren't double-spaced. */
.library-group {
  padding-block: 0;
}
.library-group.is-hidden { display: none; }

/* Line-clamp utilities — cap excerpts at N lines */
.clamp-2,
.clamp-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.clamp-2 {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
.clamp-3 {
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

/* == CARD COMPOSITION ==
All dynamic-index cards compose the DS .bento-col primitive (border/radius/bg/padding/
transition) plus small additive modifiers. .is-linkcard turns a bento-col into a whole-card
link (gentle hover); .is-flush lets media bleed to the card edge; .is-compact is a no-image
link card; .is-loadmore restyles a bento-col as a one-column "load more" control. */
.bento-col.is-linkcard {
  text-decoration: none;
  color: inherit;
}
/* Softer link-card hover (gentler than the base bento --soft-shadow) */
.bento-col.is-linkcard:hover {
  border-color: var(--sm-blue-light);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
}
/* Image-flush card — media bleeds to the edge, clipped to the card radius */
.bento-col.is-flush {
  padding: 0;
  overflow: hidden;
}
/* Compact no-image link card — small gap between rows */
.bento-col.is-compact {
  gap: var(--space-1);
}

/* Card media — framed preview panel at the top of a card. Add .gradient-light in the markup for
   the panel fill; the image sits inset with a soft shadow + rounded top, so tall form previews
   read as a lifted thumbnail. */
.card-media {
  height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 16px 16px 0 16px;
  border-radius: var(--space-2);
  border-bottom: 1px solid var(--sm-blue-light);
}
.card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center; /* template previews are tall forms — show the header, not the middle */
  border-radius: 8px 8px 0 0;
  box-shadow: var(--soft-shadow);
}
.card-media .ph {
  width: 46%;
  height: auto;
}
/* Card body — padded content block below flush media */
.card-body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.card-title {
  font-size: var(--font-body);
  font-weight: 500;
  color: var(--sm-text);
  margin: 0;
  line-height: 1.35;
}
.card-excerpt {
  font-size: var(--font-sm);
  color: var(--sm-text-body);
  margin: 0;
  line-height: 1.5;
}
/* Title + arrow row (template card titles, on-page-nav titles). The font here is the
   default for direct text (on-page nav); a nested .card-title overrides for image cards. */
.card-titlerow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--font-sm);
  font-weight: 500;
  color: var(--sm-text);
  margin: 0;
}
.card-titlerow .btn-arrow {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  transition: transform .2s ease;
}
.bento-col.is-linkcard:hover .card-titlerow .btn-arrow { transform: translateX(3px); }

/* AI-era card. Title and excerpt are grouped so the card has exactly two
   children, which is what lets space-between pin "Read more" to the floor: every
   card in the row is the same height, the titles run to one line or two, and the
   button lands level across all of them regardless.
   The excerpt goes back to a plain clamp-2. Letting it grow into the leftover
   space filled the gap but made the cards ragged, since each one then ran to a
   different number of lines. */
/* Cards that end in a "Read more".
   The content above the CTA is wrapped in one .stack, so the flex container has
   exactly two children and space-between drops the CTA to the floor. Every card
   in a row is the same height, so the CTAs line up across the row no matter how
   many lines each title ran to, which is the whole point of moving the arrow out
   of the title in the first place.
   Two containers, because the box differs by card type: on a flush card the
   padded .card-body is the one that has to stretch, on the others it is the card.
   Placed after .is-compact so its gap wins.

   NOT on a flush card, which is what :not(.is-flush) is for. There the card's own
   children are the media and the body, and the body already carries 16px of
   padding, so a gap here stacked on top of it and pushed the text away from the
   image. The gap belongs to the cards that hold the stack and the CTA directly. */
.bento-col.has-readmore {
  justify-content: space-between;
}
.bento-col.has-readmore:not(.is-flush) {
  gap: var(--space-2);
}
.has-readmore .card-body {
  flex: 1;
  justify-content: space-between;
  gap: var(--space-3);
}
.has-readmore .stack { gap: var(--space-1); }

/* The article row is horizontal, so its CTA sits at the end of the line rather
   than the foot of a box, and it is not a .is-linkcard so it needs its own hover. */
.resource-row .learn-more-btn { flex: 0 0 auto; }
.resource-row:hover .learn-more-btn { gap: var(--space-2); }

/* Card-sized text button. The primitive is built for hero-scale links at 16px,
   which shouts next to a --font-sm excerpt. */
.learn-more-btn.is-sm { font-size: var(--font-sm); }
.learn-more-btn.is-sm img { width: 14px; }

/* The gap-grows-on-hover move already lives on .learn-more-btn:hover, but the
   pointer is never on the button here: the whole card is the link, so the hover
   has to come from the card. */
.is-linkcard:hover .learn-more-btn { gap: var(--space-2); }

/* Compact link-card title — big title + arrow, space-between (AI tools, related clusters) */
.linkcard-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--font-h3);
  font-weight: 500;
  color: var(--sm-text);
  margin: 0;
}
.linkcard-title .btn-arrow {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  transition: transform .2s ease;
}
.bento-col.is-linkcard:hover .linkcard-title .btn-arrow { transform: translateX(3px); }

/* Card CTA — unified: left-aligned, pinned to the card bottom, resting in body text colour.
   The gap widens on card hover (not just CTA hover). Compose: .text-buttons.is-card-cta */
.text-buttons.is-card-cta {
  align-self: flex-start;
  margin-top: auto;
  color: var(--sm-text);
}
.bento-col:hover .is-card-cta { gap: var(--space-3); }

/* "Load more" — a bento-col link card laid out as a single row, one grid column wide */
.bento-col.is-loadmore {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  color: var(--sm-text);
  font-size: var(--font-sm);
  font-family: inherit;
  cursor: pointer;
}
.bento-col.is-loadmore .btn-arrow {
  width: 14px;
  height: 14px;
}

/* Hidden extras revealed by "load more" (initial paint only — JS toggles inline display) */
.is-extra { display: none; }

/* == TOPIC PAGE (cluster) ==
Builds on the LIBRARY section. A cluster page collects every resource on one topic:
hero (Research-Topic + System pills), an on-page anchor nav (bento-col link cards), template
cards (flush image + tag), an article row-list, a 3-up app/AI feature band, and related
clusters. Reusable across topics — templates + articles are pulled from the WP taxonomy. */

/* Resource list (articles) — title | excerpt | arrow rows, divided by rules */
.resource-list { border-top: 1px solid var(--sm-border); }
.resource-row {
  display: flex;
  align-items: flex-start; /* name + description top-aligned, flush */
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--sm-border);
  text-decoration: none;
}
/* .resource-row's display:flex is declared after .is-extra, so raise specificity to keep
   "load more" extras hidden on first paint. */
.resource-row.is-extra { display: none; }
.resource-row-title {
  flex: 0 0 26%;
  font-size: var(--font-body); /* 18px on desktop */
  font-weight: 500;
  color: var(--sm-text);
  margin: 0;
  /* underline always present but transparent, so its colour can transition in on hover */
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color .2s ease;
}
.resource-row-excerpt {
  flex: 1 1 auto;
  font-size: var(--font-sm);
  color: var(--sm-text-body);
  margin: 0;
}
.resource-row .btn-arrow {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  transition: transform .2s ease;
}
.resource-row:hover .resource-row-title {
  text-decoration-color: var(--sm-blue);
}
.resource-row:hover .btn-arrow { transform: translateX(4px); }

/* Feature bento media — grey placeholder panel inside an app/AI feature card */
.bento-media {
  background: var(--sm-grey-1);
  border-radius: 8px;
  aspect-ratio: 16 / 10;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bento-media .ph {
  width: 38%;
  height: auto;
}

/* Real image inside a feature bento (replaces the .bento-media placeholder) */
.bento-img {
  width: 100%;
  height: auto;
  border-radius: 8px;
  display: block;
  box-shadow: var(--soft-shadow); /* images ship flat now — lift with the DS soft shadow */
}
/* Image-bottom variant — text on top, image pushed to the card bottom */
.bento-media-bottom .bento-col-text { margin-top: 0; }
.bento-media-bottom .bento-img { margin-top: auto; }

@media (max-width: 1024px) {
  .index-layout { flex-direction: column; }
  .index-sidebar {
    position: static;
    flex-basis: auto;
    width: 100%;
  }
}
@media (max-width: 768px) {
  .resource-row {
    flex-wrap: wrap;
    gap: var(--space-1);
  }
  .resource-row-title { flex-basis: 100%; }
}


/* == BLOG LIBRARY (Inside Sitemate hub) ==
A divided LIST, not a card grid (MKTGDSGN-498). A featured block — large icon left, copy
right — sits above a set of rows: copy left, icon right, separated by hairlines. Sits on
white, which is why the badge artwork (a white rounded card + line icon) reads as a bare
icon here while the same asset shows its card on a post's gradient hero.
Rows are baked by website/build-index.js between the SM-CARDS markers. */

/* hero icon animation, above the library title */
.blog-hero-lottie {
  width: 200px;
  height: auto;
  display: block;
}

/* ---- shared by the featured block and the rows ---- */
.blog-featured,
.blog-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  text-decoration: none;
  color: inherit;
}
.blog-featured-text,
.blog-row-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.blog-featured-text > *,
.blog-row-text > * {
  margin: 0;
}
/* the CTA sits away from the copy above it */
.blog-featured-cta,
.blog-row-cta {
  margin-top: var(--space-3);
  align-self: flex-start;
  color: var(--sm-text);
}
.blog-featured-cta .btn-arrow,
.blog-row-cta .btn-arrow {
  width: 16px;
  height: 16px;
}
/* hovering anywhere on the row drives the arrow, and underlines the title */
.blog-featured:hover .text-buttons,
.blog-row:hover .text-buttons {
  gap: var(--space-3);
}
/* title underlines in brand blue on hover — the heading colour itself is unchanged */
.blog-featured:hover h2,
.blog-row:hover h3 {
  text-decoration: underline;
  text-decoration-color: var(--sm-blue);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* ---- featured block — icon left, copy right ---- */
.blog-featured {
  padding: var(--space-8) 0;
}
.blog-featured-badge {
  flex: 0 0 322px;
  width: 322px;
  height: 322px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.blog-featured-badge > * {
  width: 100%;
  height: 100%;
  display: block;
}

/* ---- rows — copy left, icon right, divided by a hairline ---- */
.blog-row {
  padding: var(--space-8) 0;
  border-top: 1px solid var(--sm-border);
}
.blog-row-badge {
  order: 1; /* icon sits right of the copy */
  flex: 0 0 200px;
  width: 200px;
  height: 200px;
  display: block;
}

@media (max-width: 768px) {
  /* stack: copy first, icon under it, at a size that still reads */
  .blog-featured,
  .blog-row {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-6) 0;
  }
  .blog-featured-badge,
  .blog-row-badge {
    order: -1; /* icon leads the stack, matching the featured block */
    flex: 0 0 auto;
    width: 140px;
    height: 140px;
    align-self: flex-start;
  }
}


/* == FORM CONTROLS == */

/* Shared input chrome — one declaration for every text/select field on the DS.
   Each control adds only its own deltas (padding, flex, chevron). Add new fields to
   this selector list rather than re-declaring the chrome. */
.form-select {
  font-family: "Roboto", sans-serif;
  font-size: 15px;
  color: var(--sm-text);
  border: 1px solid var(--sm-border);
  border-radius: 8px;
}

.form-select {
  appearance: none;
  -webkit-appearance: none;
  background: #fff
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%23747474' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")
    no-repeat right 14px center;
  padding: 10px 40px 10px 14px; /* extra right padding clears the chevron */
  cursor: pointer;
}

/* == IMAGE CARD ==
A photo in a blue-bordered, light-blue-matted frame, with centred copy below.
Compose on a .bento-col. Nested radius: card 16 → frame 8 → image 4. */
.image-card {
  gap: var(--space-3);
}

.image-card-frame {
  border: 1px solid var(--sm-blue);
  background: var(--sm-blue-light);
  border-radius: 8px;
  padding: var(--space-1);
}

.image-card-frame img {
  display: block;
  width: 100%;
  object-fit: cover;
  border-radius: 4px;
}

.image-card-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
}.compare-controls

/* Let ONLY the body's flex gap govern spacing — zero child margins so all three
   cards space identically and their titles line up (no per-card inline overrides). */
.image-card-body > * {
  margin: 0;
}

/* Description line (the plain <p>, not the eyebrow) — 16px so the longest copy
   still fits on one line at the card width. */
.image-card-body p:not(.eyebrow-sm) {
  font-size: 16px;
}

.image-card-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.image-card-title {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: var(--font-h3);
  color: var(--sm-text);
  margin: 0;
}

/* == LOGO MARQUEE ==
   Infinite, seamless logo strip. The track holds two identical .logo-marquee-set
   groups (the 2nd is a JS clone) and slides left by exactly one set (translateX -50%).
   Spacing is a per-item margin-right, NOT flex `gap`: a gap only sits BETWEEN items,
   so the two halves wouldn't tile and the loop jumps half-a-gap. A trailing margin on
   every logo makes -50% line up exactly — a perfect loop regardless of logo widths. */
.logo-marquee {
  overflow-x: clip; /* clip the scrolling strip horizontally... */
  overflow-y: visible; /* ...but let a hover-scaled logo grow vertically without being cropped */
}

.logo-marquee-title {
  text-align: center;
  margin-bottom: var(--space-6);
}

.logo-marquee-track {
  display: flex;
  width: max-content; /* size to content (2 sets) so -50% == exactly one set */
  animation: logo-marquee 45s linear infinite;
  will-change: transform;
}

.logo-marquee-set {
  display: flex;
  align-items: center;
}

.logo-marquee-item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  margin-right: var(--space-8); /* 64 — trailing space per logo; this is what makes -50% tile */
}

.logo-marquee-item img {
  max-height: 40px;
  max-width: 160px;
  width: auto;
  object-fit: contain;
  display: block;
  filter: grayscale(100%);
  opacity: 0.7;
  transition:
    filter 0.3s ease,
    opacity 0.3s ease,
    transform 0.3s ease;
}

/* darken near-white logos so they read on the light background */
.logo-marquee-item.is-light img {
  filter: grayscale(100%) brightness(0.45);
}

/* wordmarks that read too small at 40px (e.g. Phoenix) */
.logo-marquee-item--lg img {
  max-height: 56px;
}

.logo-marquee-item:hover img {
  filter: grayscale(0);
  opacity: 1;
  transform: scale(1.1);
}

@keyframes logo-marquee {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .logo-marquee-track {
    animation: none;
  }
}

@media (max-width: 768px) {
  .logo-marquee-item {
    margin-right: var(--space-5); /* 40 */
  }

  .logo-marquee-track {
    animation-duration: 30s;
  }
}

/* == PRICING MODEL (toggle + volume slider + plan cards) ==
Reusable across pricing pages (Dashpivot / Gearbelt / Flowsite). */
.model-toggle {
  display: inline-flex;
  border: 1px solid var(--sm-blue);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: var(--space-3);
}

.model-btn {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: var(--space-2) var(--space-4);
  border: 0;
  background: #fff;
  color: var(--sm-text);
  cursor: pointer;
  transition:
    background 0.2s ease,
    color 0.2s ease;
}

.model-btn:not(.is-active):hover {
  background: var(--sm-grey-1);
}

.model-btn.is-active {
  background: var(--sm-blue);
  color: #fff;
}

.model-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.slider-box {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 328px;
  min-height: 44px; /* matches .ent-note so toggling models doesn't shift the row */
}

.slider-label {
  font-size: 16px;
  color: var(--sm-text);
  margin-bottom: var(--space-1);
}

.slider-label b,
.ent-note b {
  color: var(--sm-blue);
}

/* Enterprise-mode swap for the slider — mirrors .slider-box position so the
   controls row doesn't shift when toggling models. */
.ent-note {
  font-size: 16px;
  color: var(--sm-text);
  min-width: 328px;
  min-height: 44px; /* matches .slider-box height so the swap doesn't shift the row */
}

/* Same trap as .slider-box[hidden] below, and the reason it needs saying twice:
   the browser's own `[hidden] { display: none }` is the weakest rule there is,
   so ANY class that sets a display wins over it. .custom-grid and .bento-col are
   both display:flex, so a card or section marked hidden stays on screen while
   reporting itself as hidden to script and to tests.

   The topic renderer (/shared/topic-page.js) hides a section with no entries and
   the jump link pointing at it. `hidden` is the right signal: it takes the
   element out of the accessibility tree too, which display:none alone would not
   express as clearly. This makes it actually paint nothing. */
/* The jump nav: centred, and no link wider than a three-up card.
   The bake sets the column class from how many links survived, and this is the
   hard ceiling under it, so a page that authors something wider cannot blow the
   row out either. Two links at half the page each read as banners rather than
   links; capping and centring keeps a jump link the same size on every hub
   however many sections that topic has. */
nav[aria-label="On this page"] {
  justify-content: center;
}

nav[aria-label="On this page"] > a {
  max-width: calc(33.33% - 10.67px);
}

section[hidden],
nav[hidden],
.sm-breadcrumb[hidden],
.bento-col[hidden],
.custom-grid[hidden],
.resource-row[hidden],
.resource-list[hidden] {
  display: none;
}

/* When JS toggles model mode it sets [hidden]; these must beat the display
   rules above (.slider-box is display:flex, which would otherwise win). */
.slider-box[hidden],
.ent-note[hidden] {
  display: none;
}

.model-selects {
  display: flex;
  gap: var(--space-2);
}


/* Range slider — thin rounded track (blue fill painted inline by JS), compact blue
   thumb with a soft blue halo that grows on hover/focus. */
.volume-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 340px;
  max-width: 100%;
  height: 5px;
  border-radius: 999px;
  background: var(--sm-grey-1);
  border: 1px solid var(--sm-blue);
  outline: none;
  cursor: pointer;
}

.volume-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--sm-blue);
  border: 2px solid #fff;
  box-shadow: var(--soft-shadow);
  cursor: pointer;
  transition: box-shadow 0.15s ease;
}

.volume-slider::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border: 0;
  border-radius: 50%;
  background: var(--sm-blue);
  border: 2px solid #fff;
  box-shadow: var(--soft-shadow);
  cursor: pointer;
  transition: box-shadow 0.15s ease;
}

.volume-slider:hover::-webkit-slider-thumb,
.volume-slider:focus-visible::-webkit-slider-thumb {
  box-shadow: var(--soft-shadow);
}

.volume-slider:hover::-moz-range-thumb,
.volume-slider:focus-visible::-moz-range-thumb {
  box-shadow: var(--soft-shadow);
}

/* Four plan columns, divided by vertical lines, one highlighted */
.plan-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

.plan-card {
  display: flex;
  flex-direction: column;
  padding: var(--space-3);
  border-left: 1px solid var(--sm-border);
  min-height: 624px;
  transition: all 0.3s ease;
}

.plan-card:first-child {
  border-left: 1px solid var(--sm-white);
  transition: all 0.3s ease;
}

.plan-card.is-popular {
  background: var(--sm-blue-pale);
  transition: all 0.3s ease;
}

.plan-popular-tag {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.5px;
  color: var(--sm-blue);
  background: #fff;
  border: 1px solid var(--sm-border);
  border-radius: 999px;
  padding: 4px 12px;
  margin-bottom: var(--space-2);
  text-transform: uppercase;
}

.plan-popular-tag .star {
  color: #f6bb2d;
}

.plan-popular-spacer {
  height: 28px;
  margin-bottom: var(--space-2);
}

/* aligns cards without the tag */
.plan-slug {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--sm-blue);
  margin: 0 0 var(--space-1);
}

.plan-price {
  font-weight: 500;
  font-size: 22px;
  color: var(--sm-text);
  margin: 0 0 var(--space-2);
}

/* "Starting at" lead-in on the Enterprise Unlimited prices — the figure stays the
   hero, so the lead-in sits smaller and in body colour (MKTGDSGN-699). */
.plan-price-from {
  display: block;
  font-weight: 400;
  font-size: 13px;
  color: var(--sm-text-body);
}

/* Asterisk that jumps to the footnote under the card grid. */
.plan-price-note-ref {
  font-size: 13px;
  color: var(--sm-text-body);
  text-decoration: none;
  vertical-align: super;
}

.plan-price-note-ref:hover {
  color: var(--sm-blue);
}

/* Footnote under the plan-card grid (Enterprise mode only). */
.plan-cards-note {
  margin: var(--space-3) 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--sm-text-body);
}

.plan-price .per {
  font-weight: 400;
  font-size: 13px;
  color: var(--sm-text-body);
  margin-left: 4px;
}

.plan-blurb {
  font-size: 16px;
  margin: 0 0 var(--space-2);
}

.plan-includes {
  font-size: 15px;
  font-weight: 500;
  color: var(--sm-text);
  margin: 0 0 var(--space-1);
}

.plan-feature-list {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.plan-feature-list li {
  position: relative;
  padding-left: 16px;
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
  color: var(--sm-text-body);
}

/* blue tick — inline SVG so there's no asset dependency (hex can't be a var inside a data URI) */
.plan-feature-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 9px;
  height: 9px;
  background: no-repeat center / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='7' fill='none' viewBox='0 0 9 7'%3E%3Cpath stroke='%230085e8' stroke-linecap='round' stroke-width='2' d='M1 3.495 2.975 5.47a.25.25 0 0 0 .353 0L7.798 1'/%3E%3C/svg%3E");
}

/* Add-on item below the feature list (e.g. Shared data management in Enterprise
   mode) — separated from the list by a soft grey-3 divider. */
.plan-addon {
  margin: 0 0 var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px solid var(--sm-grey-3);
  font-size: 14px;
  line-height: 1.5;
  color: var(--sm-text-body);
}

/* "Shared data management" label pops via the darker heading colour (no bold). */
.plan-addon .has-tip {
  color: var(--sm-text);
}

/* Card footer — groups the add-on note + CTA and pins them to the card bottom,
   so they line up across all four cards; the auto margin fills the space above. */
.plan-foot {
  margin-top: auto;
}

/* Reusable text tooltip — hover the text itself (dotted underline signals it).
   Bubble opens upward so it's not clipped when the trigger sits low in a card. */
.has-tip {
  position: relative;
  cursor: help;
  text-decoration: underline dotted;
  text-decoration-color: var(--sm-grey-5);
  text-underline-offset: 3px;
}

.has-tip::after {
  content: attr(data-tip);
  /* display:none (not just visibility:hidden) so the 240px bubble is OUT of layout
     when hidden — otherwise it sits off to the right and drags the page wider than
     the viewport (phantom horizontal scroll). Shown via display:block on hover. */
  display: none;
  position: absolute;
  left: 0;
  bottom: calc(100% + 8px);
  width: 240px;
  padding: 10px 12px;
  background: var(--sm-white);
  color: var(--sm-text);
  font-family: "Roboto", sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.45;
  border: 1px solid var(--sm-grey-3);
  border-radius: 16px;
  box-shadow: var(--soft-shadow);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease;
  z-index: 20;
}

.has-tip:hover::after {
  display: block;
  opacity: 1;
  visibility: visible;
}

/* Plan-card CTAs — scoped overrides of the global buttons: auto width (not full),
   own padding + 14px text, and the gap-grow hover applied to grey too. */
.plan-cta .blue-buttons,
.plan-cta .grey-buttons {
  width: auto;
  padding: 18px 24px;
  font-size: 14px;
}

.plan-cta .grey-buttons {
  gap: var(--space-2); /* base gap so hover can grow it (global grey sits at 24 = no grow) */
}

.plan-cta .grey-buttons:hover {
  gap: var(--space-3);
}

/* == COMPARISON TABLE ==
   Reusable feature/plan matrix. Column dividers on FEATURE rows only; blue ✓ /
   red ✕; row hover uses --sm-blue-pale; sticky header + CTA. Everything left-aligned. */
.compare-controls {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  /* match the search box below it: first column (320px) minus its right gutter */
  width: calc(320px - var(--space-3));
  max-width: 100%;
}

/* Desktop only: clearance so the currency/term row doesn't clip the table's
   header row below it. On mobile (≤768) the table's own margin-top handles this. */
@media (min-width: 769px) {
  .compare-controls {
    margin-bottom: var(--space-3);
  }
}

/* the two selects split the row evenly, so together they equal the search width */
.compare-controls .form-select {
  flex: 1;
  min-width: 0;
}

/* Plan picker is mobile-only — revealed in the ≤768px block (single-tier view). */
.compare-plan-select {
  display: none;
}

.compare-search {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  border: 1px solid var(--sm-border);
  border-radius: 10px;
  padding: 9px 14px;
  min-width: 260px;
  margin-left: -24px;
}

.compare-search input {
  border: 0;
  outline: 0;
  background: transparent;
  width: 100%;
  font-family: "Roboto", sans-serif;
  font-size: 16px;
  color: var(--sm-text);
}

.compare-scroll {
  /* visible on desktop so row tooltips are not clipped; scrolls on small screens (see media below) */
  overflow: visible;
}

.compare-table {
  width: 100%;
  /* SEPARATE (not collapse) so position:sticky works reliably on the mobile frozen
     column + header — collapsed-border tables drop/detach sticky cells in mobile
     Safari/Chrome. border-spacing:0 keeps it visually identical to collapse; our
     dividers are single-sided border-lefts (no doubling) + box-shadows. */
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
}

/* base cell rhythm — 18px, left-aligned; dividers added to feature rows only.
   White opaque base (keeps sticky header + mobile frozen column solid); the
   pale-blue steady-state fill is applied ONLY to the plan-header boxes and the
   category title rows below — design review Jul 2026. */
.compare-table th,
.compare-table td {
  padding: var(--space-3);
  vertical-align: middle;
  text-align: left;
  font-size: 18px;
  background: var(--sm-white);
}

.compare-table th:first-child,
.compare-table td:first-child {
  width: 320px;
  padding-left: var(--space-3); /* 24px — text needs breathing room inside the pale-blue fill */
  padding-right: var(--space-2); /* 16px — trimmed so the widest slider price-note (e.g. "5001-10000") fits one line */
}

.compare-table th:not(:first-child),
.compare-table td:not(:first-child) {
  /* auto so table-layout:fixed divides the remaining width equally among however
     many plan columns exist (4 for Dashpivot/Gearbelt, 5 for Flowsite). The table
     always fills exactly 100% of the content box, so it never overflows the page
     regardless of column count or viewport — no fixed px min to push it wide. */
  width: auto;
}

/* Sticky header row, just under the shared nav — no divider line. The row cells
   default white (opaque for sticky); the individual plan boxes (Pro, Premium…)
   are tinted below so the titles read as bounded, not naked, while they float. */
.compare-table thead th {
  position: sticky;
  /* sits below the sticky toolbar when one exists (Flowsite); --ct-toolbar-h is 0 on
     pages without a toolbar, so their header still pins directly under the nav. */
  top: calc(var(--nav-h) + var(--ct-toolbar-h, 0px));
  background: var(--sm-white);
  z-index: 5;
  /* Top border so the header row reads as a bounded bar rather than colliding
     with the nav when it pins directly beneath it. */
  border-top: 1px solid var(--sm-border);
}

/* Sticky model-toggle bar (Flowsite): a div ABOVE the table (not a table cell, so it
   can't distort column widths). Pins under the nav and stays visible for the whole
   table scroll so the toggle is always reachable. */
.model-stickybar {
  position: sticky;
  top: var(--nav-h);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) 0;
  background: var(--sm-white);
}
.model-stickybar-desc {
  margin: 0;
  max-width: 42ch;
  font: 400 14px/1.4 "Roboto", sans-serif;
  color: var(--sm-text-body);
}
.model-stickybar .model-toggle {
  margin-bottom: 0;
  flex: 0 0 auto;
}

/* Plan-header boxes (Std / Pro / Premium / Platinum) — white, divided by a left
   border. Only the CTA inside is a link; the name/info is a tooltip trigger. */
.compare-table thead th.ct-plan-col {
  border-left: 1px solid var(--sm-border);
}

.ct-plan-head {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.ct-plan-name {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: 24px;
  color: var(--sm-text);
  width: 100%;
}
.ct-cta a {
  display: none;
  background: var(--sm-white);
}
/* Category (title) rows — pale-blue fill to anchor each feature group.
   Stacked-sticky: each group title pins just under the (stuck) plan header and
   stays until the next group title scrolls up and replaces it. --ct-head-h is set
   by initCompareSticky to the pinned header's height; z-index 4 sits under the
   plan header (5) so titles slide beneath it. */
.ct-category td {
  font-family: "Sunflower", sans-serif;
  font-weight: 500;
  font-size: 18px;
  color: var(--sm-text);
  padding-top: var(--space-4);
  background: var(--sm-blue-pale);
  /* Fixed height so EVERY title row is identical — the icon categories render ~4px
     taller than the icon-less ones, and a shorter pinned title can't fully cover a
     taller one during the stacked-sticky hand-off. 84px clears the tallest (81px). */
  height: 84px;
  position: sticky;
  top: calc(var(--nav-h) + var(--ct-toolbar-h, 0px) + var(--ct-head-h, 64px));
  z-index: 4;
  /* Top + bottom dividers via inset box-shadow, NOT border: on a border-collapse
     table the collapsed borders are painted into the table grid and drop out the
     moment a cell pins (sticky) in Chromium. box-shadow is painted on the cell, so
     it stays put when the row sticks. */
  box-shadow:
    inset 0 1px 0 var(--sm-border),
    inset 0 -1px 0 var(--sm-border);
}

/* Plan-header CTA — a persistent simple text link under each plan name (replaces
   the old footer CTA row). Brand-blue inline/tertiary link with a small arrow. */
.ct-head-cta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: var(--space-1);
  font: 400 14px/1 "Roboto", sans-serif;
  color: var(--sm-text);
  text-decoration: none;
  white-space: nowrap;
}
.ct-head-cta img {
  transition: transform 0.2s ease;
}
.ct-head-cta:hover {
  text-decoration: none;
}
.ct-head-cta:hover img {
  transform: translateX(2px);
}

/* Optional category icon (e.g. Dashpivot / Sitemate square logos) */
.ct-category-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.ct-category-icon {
  display: block;
  width: 20px;
  height: 20px;
}

/* Feature rows — the ONLY rows with vertical column dividers */
.ct-feature td:not(:first-child) {
  border-left: 1px solid var(--sm-border);
}

/* Row hover — feature AND category rows: just the pale-blue fill, no dividers. */
.ct-feature:hover td,
.ct-category:hover td {
  background: var(--sm-blue-pale);
}

.ct-feature-name {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--sm-text);
  font-size: 16px; /* smaller than the 18px values so long feature names fit one line */
}

/* Nested integration sub-row (e.g. Xero → Invoices and Bills): indent + lighten */
.ct-feature-name.ct-indent {
  padding-left: var(--space-2);
  color: var(--sm-text-body);
}

/* Integration brandmark shown before a row name (mirrors the live page's column-logo) */
.ct-row-logo {
  flex: none;
  display: block;
  width: 20px;
  height: 20px;
  object-fit: contain;
}

/* Info icon: hidden until its row is hovered; hover the icon for the tooltip */
.ct-info {
  position: relative;
  display: inline-flex;
  cursor: help;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}

.ct-info img {
  display: block;
  width: 15px;
  height: 15px;
}

/* body: reveal a feature row's info icon on row hover */
.ct-feature:hover .ct-info {
  opacity: 1;
  pointer-events: auto;
}

/* header: hovering a plan column tints it light blue and reveals its info icon
   (tooltip = that plan's Pick-Your-Model blurb) */
.ct-plan-col:hover {
  background: var(--sm-blue-pale);
  z-index: 30; /* above sibling sticky headers (z-index 5) so its tooltip isn't clipped */
}

.ct-plan-col:hover .ct-info {
  opacity: 1;
  pointer-events: auto;
}

/* Dotted underline signals a tooltip is available — shown alongside the hover
   reveal. Feature rows only underline when the row actually has an info icon. */
.ct-feature:hover .ct-feature-name:has(.ct-info) .ct-tip-label,
.ct-plan-col:hover .ct-plan-name {
  text-decoration: underline dotted;
  text-decoration-color: var(--sm-grey-5);
  text-underline-offset: 3px;
}

/* Help cursor over the label too (matching the info icon), wherever a tooltip exists */
.ct-feature-name:has(.ct-info),
.ct-plan-head {
  cursor: help;
}

/* Tooltip bubble — content comes from the data-tip attribute */
.ct-info::after {
  content: attr(data-tip);
  /* display:none when hidden so the 280px bubble is out of layout (else it extends
     past the viewport and creates phantom horizontal page scroll). Shown on hover. */
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 8px);
  width: 280px;
  padding: 10px 12px;
  background: var(--sm-white);
  color: var(--sm-text);
  font-family: "Roboto", sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.45;
  text-transform: none;
  border: 1px solid var(--sm-grey-3);
  border-radius: 16px;
  box-shadow: var(--soft-shadow);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease;
  z-index: 20;
}

/* Reveal the tooltip on the info icon OR the underlined label (feature name / plan title) */
.ct-info:hover::after,
.ct-feature-name:hover .ct-info::after,
.ct-plan-head:hover .ct-info::after {
  display: block;
  opacity: 1;
  visibility: visible;
}

/* Priced rows (per-user price + embedded slider) */
.ct-price-sub {
  font-size: 14px;
  color: var(--sm-text-body);
  margin-top: var(--space-1);
}

.ct-price-note {
  font-size: 13px;
  color: var(--sm-text-body);
  margin-top: var(--space-1);
}

.ct-mini-slider {
  width: 100%;
  max-width: 260px;
  margin-top: var(--space-1);
}

.ct-cell-price {
  font-weight: 500;
  font-size: 18px;
  color: var(--sm-text);
}

.ct-cell-price .per {
  display: block;
  font-weight: 400;
  font-size: 13px;
  color: var(--sm-text-body);
}

/* Tick / cross / value */
.ct-tick,
.ct-cross {
  display: inline-block;
  width: 18px;
  height: 18px;
  vertical-align: middle;
  /* never shrink when sitting beside wrapping text inside the flex .ct-value
     (e.g. "Multiple workspaces") — keeps every tick the same 18px */
  flex: 0 0 auto;
}

.ct-tick {
  background: no-repeat center / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='10' fill='%230085E8'/%3E%3Cpath d='M6 10.5l2.5 2.5L14 7.5' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.ct-cross {
  background: no-repeat center / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath d='M5 5l10 10M15 5L5 15' fill='none' stroke='%23E3514D' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}

.ct-value {
  display: inline-flex;
  align-items: center;
  gap: 12px; /* 1.5 × space-1 — off-grid on purpose; 8px too tight, 16px too loose */
  justify-content: flex-start;
  color: var(--sm-text-body);
  font-size: 18px;
}

/* Plain-text cell (no tick, no flex gap) — e.g. "Available via Flowsite".
   Text and any inline link flow as normal prose, not as separated flex items. */
.ct-note {
  color: var(--sm-text-body);
  font-size: 18px;
}

/* Sticky CTA row — no top line; flush button cells, greyed, with the same
   column dividers as the body so the row reads as part of the table. */
.compare-table tfoot td {
  position: sticky;
  bottom: 0;
  padding: 0;
  background: #fff;
  z-index: 5;
}

.compare-table tfoot td:not(:first-child) {
  border-left: 1px solid var(--sm-border);
}

/* CTA fills its cell — no pill, no rounded corners, sits flush */
.ct-cta {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-3);
  color: var(--sm-text);
  font-size: 16px;
  text-decoration: none;
  transition: gap 0.2s ease;
}

.ct-cta:hover {
  gap: var(--space-2);
}

.ct-cta img {
  width: 16px;
  height: auto;
  display: block;
}

/* rows hidden by search */
.ct-feature.is-hidden,
.ct-category.is-hidden {
  display: none;
}

@media (max-width: 992px) {
  .plan-cards {
    grid-template-columns: repeat(2, 1fr);
  }

  .plan-card:nth-child(3) {
    border-left: 0;
  }
}

@media (max-width: 768px) {
  .model-controls {
    flex-direction: column;
    align-items: stretch;
  }

  /* Sticky toggle bar: drop the description on phones (keep the pinned bar compact) and
     let the toggle fill the width so both options stay tappable and nothing overflows. */
  .model-stickybar-desc {
    display: none;
  }
  .model-stickybar .model-toggle {
    display: flex;
    width: 100%;
  }
  .model-stickybar .model-btn {
    flex: 1;
    padding: var(--space-2);
  }

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

  .plan-card {
    border-left: 0;
    border-top: 1px solid var(--sm-border);
    min-height: 0; /* stacked single-column: size to content, no forced floor */
  }

  .plan-card:first-child {
    border-top: 0;
  }

  /* ── Compare table — mobile: ONE tier at a time (no horizontal scroll) ───────
     The frozen-column + horizontal scroll fought mobile sticky (Safari/Chrome), so
     on phones the table shows the feature column + a SINGLE plan column, chosen by
     the plan dropdown (.compare-plan-select). Vertical scroll only, so the header +
     category titles use the same reliable top-sticky as desktop. Pattern à la
     Linear's mobile pricing. */

  /* Full-bleed: break the table out of the section's 16px side padding → 100vw.
     margin-top adds breathing room below the term/currency controls. */
  .compare-scroll {
    margin-inline: calc(-1 * var(--space-2));
    margin-top: var(--space-1);
  }

  /* Top border on the sticky header row (dropdown + CTA) so it reads as a distinct,
     bounded bar when pinned. */
  .compare-table thead th {
    border-top: 1px solid var(--sm-border);
  }

  /* Swap the search box out for the tier dropdown in the (sticky) header's first cell. */
  .compare-search {
    display: none;
  }
  .compare-plan-select {
    display: block;
    width: 100%;
  }

  /* Single tier: hide every plan cell, reveal only the selected one (table-cell so
     table-layout:fixed keeps the columns sized). */
  .compare-table [data-plan] {
    display: none;
  }
  .compare-table[data-mobile-plan="free"] [data-plan="free"],
  .compare-table[data-mobile-plan="standard"] [data-plan="standard"],
  .compare-table[data-mobile-plan="pro"] [data-plan="pro"],
  .compare-table[data-mobile-plan="premium"] [data-plan="premium"],
  .compare-table[data-mobile-plan="platinum"] [data-plan="platinum"] {
    display: table-cell;
  }

  /* Two columns: feature name + the selected tier. */
  .compare-table th:first-child,
  .compare-table td:first-child {
    width: 55%;
  }
  .compare-table th[data-plan],
  .compare-table td[data-plan] {
    width: 45%;
  }

  /* The tier name lives in the dropdown now — hide the in-header name/info so the
     "Try for free" CTA takes over the whole tier-column header cell. */
  .compare-table thead .ct-plan-head {
    display: none;
  }
  .compare-table thead .ct-plan-col br {
    display: none;
  }
  .compare-table thead .ct-head-cta {
    margin-top: 0;
    width: 100%;
    justify-content: center;
  }

  /* Touch has no hover — always surface the tooltip affordance (icon + underline). */
  .ct-info {
    opacity: 1;
    pointer-events: auto;
    position: static; /* don't anchor the bubble to the icon (mid-cell → runs off-screen) */
  }

  .ct-feature-name:has(.ct-info) .ct-tip-label,
  .ct-plan-name {
    text-decoration: underline dotted;
    text-decoration-color: var(--sm-grey-5);
    text-underline-offset: 3px;
  }

  /* Anchor the bubble to the left-aligned feature name so it opens from the left
     edge and stays on-screen; cap it to the viewport (minus gutters). */
  .ct-feature-name {
    position: relative;
  }
  .ct-info::after {
    max-width: calc(100vw - 2 * var(--space-3));
  }
}

/* == FAQ ACCORDION == */
.faq-item {
  border-bottom: 1px solid var(--sm-border);
  padding: var(--space-3) 0;
}

.faq-item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
  font-weight: 500;
  font-size: 18px;
  color: var(--sm-text);
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::after {
  content: "";
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  border-right: 2px solid var(--sm-grey-5);
  border-bottom: 2px solid var(--sm-grey-5);
  transform: rotate(45deg);
  transition: transform 0.2s ease;
}

.faq-item[open] summary::after {
  transform: rotate(-135deg);
}

.faq-answer {
  padding-top: var(--space-3);
}

.faq-answer :last-child {
  margin-bottom: 0;
}
