/* ============================================================
   Gestisoft kit — design system
   Palette + type are authoritative from the brand guide
   (docs/reference/brand-palette.md, Gestisoft_GuideV01.pdf).
   Aesthetic: refined editorial — white/cream canvas, Dark-Matter
   black text, big tight Matter headings, generous whitespace,
   Gestigold + Byte-Bright yellow as signature accents, black-pill
   CTAs. Secondary colors (teal/purple/pink/green/brown/tan) are
   accents only.
   ============================================================ */

@font-face { font-family: Diatype; font-style: normal; font-weight: 700; src: url(/kit/fonts/abcdiatype-bold.BmNeBSg6.woff2) format('woff2'); font-display: swap; }
@font-face { font-family: Diatype; font-style: normal; font-weight: 500; src: url(/kit/fonts/abcdiatype-medium.Vm0WqISa.woff2) format('woff2'); font-display: swap; }
@font-face { font-family: Diatype; font-style: normal; font-weight: 400; src: url(/kit/fonts/abcdiatype-regular.DfLLXaye.woff2) format('woff2'); font-display: swap; }
@font-face { font-family: Matter; font-style: normal; font-weight: 500; src: url(/kit/fonts/matter-medium.0kVFSH3u.woff2) format('woff2'); font-display: swap; }

:root {
	--font-heading: Matter, sans-serif;   /* headings, eyebrows — Matter Medium */
	--font-body: Diatype, sans-serif;     /* body copy */
	--ease-out-quint: cubic-bezier(.23, 1, .32, 1);
	--ease-out-expo: cubic-bezier(.19, 1, .22, 1);
	--container: 122rem;

	/* Brand neutrals (primary palette — must dominate) */
	--ink: #0f0f0f;      /* Dark Matter — text, black pill buttons */
	--paper: #ffffff;    /* Digital Cloud */
	--cream: #f0eeeb;    /* Pier Béton — soft section background */
	--stone: #ccc7c1;    /* 365 Shades of Grey */
	--rule: #e6e3df;     /* hairline divider (derived from stone) */
	--muted: #55524d;    /* secondary body text (derived, AA on paper/cream) */
}

html { font-size: 62.5%; } /* 1rem = 10px — matches the real gestisoft.com desktop base */
* { box-sizing: border-box; }
body { font-family: var(--font-body); font-size: 1.9rem; line-height: 1.55; color: var(--ink); background: var(--paper); margin: 0; -webkit-font-smoothing: antialiased; }

/* ============ Theme accent tokens ============
   Each theme exposes --theme-light/medium/dark/darker/fg. In this refined
   system a theme mostly drives ACCENTS (eyebrow, icon tint, emphasis-section
   background). Values are the brand guide's exact hexes for the vivid
   (medium) tone; light/dark/darker are tints/shades. Every one of the 8
   names keeps an explicit [data-theme=<name>] block (kit.test.ts checks these).
   PRIMARY signatures: gold (Gestigold #FFB51C), yellow (Byte Bright #FFED4C),
   plus the neutral base. SECONDARY accents: teal/purple/pink/green/brown/tan. */

[data-theme=gold]   { --theme-light: #fff2d6; --theme-medium: #ffb51c; --theme-dark: #d0891a; --theme-darker: #8a5a10; --theme-fg: #0f0f0f; --theme-main: var(--theme-medium); }
[data-theme=yellow] { --theme-light: #fffac2; --theme-medium: #ffed4c; --theme-dark: #d9c400; --theme-darker: #8e8210; --theme-fg: #0f0f0f; --theme-main: var(--theme-medium); }
[data-theme=beige]  { --theme-light: #f0eeeb; --theme-medium: #c9b785; --theme-dark: #9c8757; --theme-darker: #6b5c3a; --theme-fg: #0f0f0f; --theme-main: var(--theme-medium); }
[data-theme=blue]   { --theme-light: #d9f4f9; --theme-medium: #3cc7dd; --theme-dark: #1ba6bb; --theme-darker: #137786; --theme-fg: #0f0f0f; --theme-main: var(--theme-medium); }
[data-theme=purple] { --theme-light: #efe6fc; --theme-medium: #ba92f1; --theme-dark: #9a6fe0; --theme-darker: #6b3fb0; --theme-fg: #0f0f0f; --theme-main: var(--theme-medium); }
[data-theme=pink]   { --theme-light: #fdd9e2; --theme-medium: #e2366a; --theme-dark: #c72656; --theme-darker: #8f1a3c; --theme-fg: #ffffff; --theme-main: var(--theme-medium); }
[data-theme=green]  { --theme-light: #d4eddb; --theme-medium: #25883f; --theme-dark: #1c6e31; --theme-darker: #124a20; --theme-fg: #ffffff; --theme-main: var(--theme-medium); }
[data-theme=brown]  { --theme-light: #ecdccb; --theme-medium: #a06b3d; --theme-dark: #855226; --theme-darker: #5a3717; --theme-fg: #ffffff; --theme-main: var(--theme-medium); }

/* ============ Base elements ============ */
.gs-container { max-width: var(--container); margin-inline: auto; padding-inline: 2.4rem; }
@media (min-width: 700px) { .gs-container { padding-inline: 4rem; } }

.gs-section { padding-block: 8rem; position: relative; }
@media (min-width: 900px) { .gs-section { padding-block: 11rem; } }

/* Visually-hidden but screen-reader-accessible utility — content that carries
   meaning for assistive tech but no visual weight (a connective word between
   two adjacent visual elements, a label for an icon-only control). General
   purpose, not tied to any one module: used by featureList's paired-row
   connective today, and by later kit modules that hide/reveal the same kind
   of AT-only text (a tablist's toggle-cards switcher, carousel prev/next
   controls, an animated diagram's narration). Never display:none or
   visibility:hidden, so it stays focusable-safe if ever applied to
   interactive content (e.g. an icon-only button's label). */
.gs-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: 500; line-height: 1.06; letter-spacing: -0.015em; margin: 0; color: var(--ink); }

/* Eyebrow / kicker — small uppercase label above a heading */
.gs-eyebrow { display: inline-block; font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--theme-dark, var(--ink)); margin: 0 0 1.8rem; }

.gs-lead { font-size: clamp(1.8rem, 2vw, 2.1rem); line-height: 1.55; color: var(--muted); }

/* ============ Buttons ============
   Primary = solid Dark-Matter pill (black) with white text — this is fixed
   regardless of section theme, matching Gestisoft's real CTAs. Secondary =
   ghost/outlined pill. */
.gs-btn {
	display: inline-flex; align-items: center; justify-content: center; gap: .8rem;
	font-family: var(--font-heading); font-size: 1.6rem; font-weight: 500; line-height: 1;
	padding: 1.5rem 2.8rem; border-radius: 9999px; border: 1.5px solid var(--ink);
	background: var(--ink); color: var(--paper); text-decoration: none; cursor: pointer;
	transition: transform .5s var(--ease-out-quint), background-color .3s ease, color .3s ease;
}
.gs-btn:hover { transform: translateY(-2px) scale(1.02); background: #262626; border-color: #262626; }
.gs-btn__icon { width: 1.6rem; height: 1.6rem; }
.gs-btn--ghost { background: transparent; color: var(--ink); }
.gs-btn--ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.gs-btn-row { display: flex; flex-wrap: wrap; gap: 1.2rem; align-items: center; }

/* ============ Section entrance (builder preview delight) ============ */
@keyframes gsFadeUp { from { opacity: 0; transform: translateY(2rem); } to { opacity: 1; transform: none; } }
.gs-section { animation: gsFadeUp .6s var(--ease-out-expo) both; }
.gs-slot:nth-child(2) > .gs-section { animation-delay: .06s; }
.gs-slot:nth-child(3) > .gs-section { animation-delay: .12s; }
.gs-slot:nth-child(4) > .gs-section { animation-delay: .18s; }
.gs-slot:nth-child(5) > .gs-section { animation-delay: .24s; }
.gs-slot:nth-child(6) > .gs-section { animation-delay: .30s; }
@media (prefers-reduced-motion: reduce) { .gs-section { animation: none; } }

/* ============ Section controls ============
   Small per-section options (registry.ts `controls`): each is one prop with a
   default, painted by a modifier class or data attribute set in the component. */
/* hero */
/* Doubled class: these sit above the .gs-hero rules in this file and must outrank them. */
.gs-hero.gs-hero--compact { padding-block: 6rem; }
@media (min-width: 900px) { .gs-hero.gs-hero--compact { padding-block: 8rem; } }
.gs-hero.gs-hero--compact h1 { font-size: clamp(3.2rem, 4.4vw, 5rem); }
.gs-hero--center .gs-hero__copy { text-align: center; margin-inline: auto; max-width: 76rem; }
.gs-hero--center .gs-hero__eyebrow, .gs-hero--center .gs-hero__sub { margin-inline: auto; }
.gs-hero--center .gs-hero__cts, .gs-hero--center .gs-hero__badges, .gs-hero--center .gs-hero__stats { justify-content: center; }
/* featureList: marks "check" restores the tick ahead of the "after" text on paired rows */
.gs-fl--check .gs-fl__after { position: relative; padding-left: 2.8rem; }
.gs-fl--check .gs-fl__after::before { content: ''; position: absolute; left: 0; top: .5em; width: 1.2rem; height: .7rem; border-left: 2px solid var(--theme-dark, var(--ink)); border-bottom: 2px solid var(--theme-dark, var(--ink)); transform: rotate(-45deg); }
/* columns (iconGrid, team, mediaGrid) */
@media (min-width: 800px) {
	.gs-icons__grid[data-cols="2"], .gs-team__grid[data-cols="2"], .gs-mg__grid[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
	.gs-icons__grid[data-cols="3"], .gs-team__grid[data-cols="3"], .gs-mg__grid[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
	.gs-icons__grid[data-cols="4"], .gs-team__grid[data-cols="4"], .gs-mg__grid[data-cols="4"] { grid-template-columns: repeat(4, 1fr); }
}
/* logoStrip */
.gs-logos--small .gs-logos__img { height: 2.8rem; max-width: 12rem; }
.gs-logos--large .gs-logos__img { height: 5.6rem; max-width: 22rem; }
.gs-logos--gray .gs-logos__img { filter: grayscale(1); opacity: .75; transition: filter .3s ease, opacity .3s ease; }
.gs-logos--gray .gs-logos__img:hover { filter: none; opacity: 1; }
/* steps: one per row, number beside the text */
.gs-steps--vertical .gs-steps__list { grid-template-columns: 1fr; max-width: 76rem; margin-inline: auto; gap: 3.2rem; }
.gs-steps--vertical .gs-step { display: grid; grid-template-columns: 4.8rem 1fr; column-gap: 2.4rem; align-items: start; }
.gs-steps--vertical .gs-step__num { margin-bottom: 0; grid-row: 1 / span 2; }
.gs-steps--vertical .gs-step__title, .gs-steps--vertical .gs-step__body { grid-column: 2; }
/* testimonials: still grid */
.gs-tm--grid .gs-tm__marquee { overflow: visible; }
.gs-tm--grid .gs-tm__track { animation: none; width: auto; display: grid; grid-template-columns: 1fr; gap: 2rem; }
@media (min-width: 800px) { .gs-tm--grid .gs-tm__track { grid-template-columns: repeat(auto-fit, minmax(30rem, 1fr)); } }
.gs-tm--grid .gs-tm__card { width: auto; max-width: none; }
/* textInterface: centred head */
.gs-ti--center .gs-ti__head { text-align: center; align-items: center; margin-inline: auto; max-width: 84rem; }
/* cta: centred banner */
.gs-cta--center .gs-cta__inner { grid-template-columns: 1fr; text-align: center; }
.gs-cta--center .gs-cta__copy, .gs-cta--center .gs-cta__lead { align-items: center; }
.gs-cta--center .gs-cta__cts { justify-content: center; }
.gs-cta--center .gs-cta__media { max-width: 56rem; margin-inline: auto; }
.gs-cta--center .gs-cta__avatars { justify-content: center; }

/* ============ Section looks (frame / spacing) ============
   Set per section from the builder or by the agent (registry.ts FRAMES /
   SPACINGS); PageRenderer puts them on the section's .gs-slot wrapper. The
   `> section` selectors outrank every section's own background and padding
   rule (all single-class), so a frame paints the same on any module. The
   colours are the section's own theme tokens: data-theme sits on the
   section element, exactly where these rules read it. */
.gs-slot { display: block; }
/* card: a rounded panel in the pale theme colour, inset from the page edges */
.gs-slot[data-frame=card] { padding-block: 2.4rem; }
.gs-slot[data-frame=card] > section { width: min(100% - 3.2rem, var(--container)); margin-inline: auto; border-radius: 2.4rem; background: var(--theme-light, var(--cream)); padding-block: 6rem; }
@media (min-width: 800px) { .gs-slot[data-frame=card] > section { padding-block: 8rem; } }
/* tint: the pale theme colour edge to edge */
.gs-slot[data-frame=tint] > section { background: var(--theme-light, var(--cream)); }
/* bold: the full theme colour edge to edge, the content on a white panel.
   Sections whose first child is not .gs-container (splashCards) just get the
   colour. */
.gs-slot[data-frame=bold] > section { background: var(--theme-medium, var(--ink)); padding-block: 4rem; }
.gs-slot[data-frame=bold] > section > .gs-container { background: var(--paper); color: var(--ink); border-radius: 2.4rem; padding-block: 5.6rem; width: min(100% - 3.2rem, var(--container)); }
@media (min-width: 800px) { .gs-slot[data-frame=bold] > section { padding-block: 6.4rem; } .gs-slot[data-frame=bold] > section > .gs-container { padding-block: 7.2rem; } }
/* compact: about half the usual room above and below */
.gs-slot[data-spacing=compact] > section { padding-block: 4rem; }
@media (min-width: 900px) { .gs-slot[data-spacing=compact] > section { padding-block: 5rem; } }
.gs-slot[data-spacing=compact][data-frame=card] { padding-block: 1.2rem; }

/* ============ Hero ============ */
.gs-hero { background: var(--theme-light, var(--cream)); color: var(--ink); padding-block: 9rem; }
@media (min-width: 900px) { .gs-hero { padding-block: 13rem; } }
.gs-hero__grid { display: grid; grid-template-columns: 1fr; gap: 4.8rem; align-items: center; }
/* Copy column wider and the h1 a step smaller than the first cut (client
   feedback: a 90-character heading wrapped to five lines beside the form). */
@media (min-width: 900px) { .gs-hero__grid { grid-template-columns: 1.25fr .75fr; gap: 6.4rem; } }
.gs-hero__eyebrow { display: block; font-weight: 500; font-size: 1.7rem; color: var(--ink); margin: 0 0 2.4rem; max-width: 60rem; }
.gs-hero h1 { font-size: clamp(3.6rem, 5.2vw, 6rem); }
.gs-hero__sub { font-size: clamp(1.7rem, 2vw, 2rem); line-height: 1.55; color: var(--muted); margin: 2.8rem 0 3.6rem; max-width: 62rem; }
.gs-hero__cts { margin-top: .8rem; }
.gs-hero__media { position: relative; }
.gs-hero__img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 999px; }
.gs-hero__img--soft { aspect-ratio: 4 / 3; border-radius: 3.2rem; }
.gs-trust { display: inline-flex; align-items: center; gap: 1rem; margin-top: 3.2rem; font-size: 1.5rem; color: var(--muted); }
.gs-trust__stars { color: #f5a623; letter-spacing: .1em; font-size: 1.6rem; }
.gs-trust b { color: var(--ink); font-weight: 500; }
/* Google reviews badge (white rounded card) */
.gs-google { display: inline-flex; align-items: center; gap: 1.4rem; margin-top: 3.2rem; background: var(--paper); border: 1px solid var(--rule); border-radius: 1.6rem; padding: 1.4rem 2rem; box-shadow: 0 2px 10px rgba(15,15,15,.05); }
.gs-google__logo { font-family: var(--font-heading); font-weight: 500; font-size: 2rem; letter-spacing: -0.02em; }
.gs-google__logo b { font-weight: 500; }
.gs-google__stars { color: #111; letter-spacing: .1em; font-size: 1.7rem; }
.gs-google__count { font-size: 1.4rem; color: var(--muted); }

/* ---- Hero variants ---- */
.gs-hero__badges { list-style: none; padding: 0; margin: 3.2rem 0 0; display: flex; flex-wrap: wrap; gap: 1rem; }
.gs-hero__badges li { display: inline-flex; align-items: center; gap: .8rem; border: 1px solid rgba(15, 15, 15, .2); border-radius: 999px; padding: .8rem 1.4rem; font-size: 1.4rem; font-weight: 500; background: var(--paper); }
.gs-hero__stats { display: flex; flex-wrap: wrap; gap: 3.2rem; margin-top: 3.2rem; }
.gs-hero__stat b { display: block; font-family: var(--font-heading); font-weight: 500; font-size: 3.2rem; line-height: 1; }
.gs-hero__stat span { display: block; margin-top: .6rem; font-size: 1.5rem; color: var(--muted); }
/* The form card runs far taller than the copy: start the copy level with the card's top
   rather than centring it halfway down beside the form. */
.gs-hero--form .gs-hero__grid { align-items: start; }
.gs-hero__formcard { background: var(--paper); border: 1px solid var(--rule); border-radius: 2rem; padding: 2.8rem; box-shadow: 0 4px 24px rgba(15, 15, 15, .06); }
.gs-hero__formcard h2 { font-size: 2.4rem; line-height: 1.1; }
.gs-hero__formnote { margin-top: 1.2rem; font-size: 1.4rem; color: var(--muted); }
@media (min-width: 900px) { .gs-hero__formcard { padding: 3.2rem; } .gs-hero__formcard h2 { font-size: 2.8rem; } }

/* ============ Feature grid (borderless, top-rule + icon) ============ */
.gs-cards { background: var(--paper); }
.gs-cards__head { max-width: 96rem; margin: 0 auto 7rem; text-align: center; }
.gs-cards__head .gs-eyebrow { color: var(--theme-dark, var(--ink)); }
.gs-cards__head h2 { font-size: clamp(3.6rem, 5.6vw, 6.4rem); line-height: 1.02; }
.gs-cards__head .gs-lead { margin-top: 2.4rem; }
.gs-cards__grid { display: grid; gap: 3.2rem 4rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .gs-cards__grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 960px) { .gs-cards__grid { grid-template-columns: repeat(3, 1fr); } }
.gs-card { padding-top: 2.4rem; border-top: 1.5px solid var(--rule); }
.gs-card__icon { display: inline-flex; align-items: center; justify-content: center; width: 4.4rem; height: 4.4rem; border-radius: 1.2rem; background: var(--theme-light, var(--cream)); color: var(--theme-darker, var(--ink)); margin-bottom: 2rem; }
.gs-card__icon svg { width: 2.2rem; height: 2.2rem; }
.gs-card h3 { font-size: 2.2rem; margin-bottom: 1rem; }
.gs-card p { color: var(--muted); font-size: 1.7rem; }

/* ============ Split content ============ */
.gs-split__grid { display: grid; gap: 4.8rem; align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .gs-split__grid { grid-template-columns: 1fr 1fr; gap: 6.4rem; } .gs-split--left .gs-split__copy { order: 2; } }
.gs-split h2 { font-size: clamp(2.8rem, 3.6vw, 4.4rem); }
.gs-split__body { margin: 2.4rem 0; color: var(--muted); font-size: 1.8rem; }
.gs-split__img { width: 100%; border-radius: 2.4rem; object-fit: cover; }

/* ============ Feature list / checklist rows ============ */
.gs-list__grid { display: grid; gap: 4.8rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .gs-list__grid { grid-template-columns: 1fr 1fr; gap: 6.4rem; } }
.gs-list h2 { font-size: clamp(2.8rem, 3.6vw, 4.4rem); }
.gs-list__body { margin-top: 2rem; color: var(--muted); }
.gs-list__rows { display: flex; flex-direction: column; }
.gs-list__row { display: flex; align-items: center; gap: 1.6rem; padding: 2rem 0; border-bottom: 1.5px solid var(--rule); font-size: 1.9rem; }
.gs-list__row:first-child { border-top: 1.5px solid var(--rule); }
.gs-list__check { flex: none; width: 2.6rem; height: 2.6rem; border-radius: 999px; background: var(--theme-medium, var(--ink)); color: var(--theme-fg, #fff); display: inline-flex; align-items: center; justify-content: center; }
.gs-list__check svg { width: 1.4rem; height: 1.4rem; }

/* ---- Checklist: before / after variant ---- */
.gs-fl__pairs { list-style: none; padding: 0; margin: 0; }
.gs-fl__pair { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1.6rem; padding-block: 1.8rem; border-top: 1px solid var(--rule); }
.gs-fl__pair:last-child { border-bottom: 1px solid var(--rule); }
.gs-fl__before { color: var(--muted); font-size: 1.6rem; }
.gs-fl__arrow { flex: none; color: var(--theme-dark, var(--ink)); font-size: 1.6rem; }
.gs-fl__after { font-family: var(--font-heading); font-weight: 500; font-size: 1.8rem; line-height: 1.2; }
@media (min-width: 800px) { .gs-fl__before { font-size: 2rem; } .gs-fl__after { font-size: 2.2rem; } }
/* No check mark ahead of the "after" text (client request, 2026-09): the arrow
   between the two columns already carries the before → after reading. */

/* ============ Proof panel (checklist left + quote card right) ============ */
.gs-proof__grid { display: grid; gap: 4.8rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .gs-proof__grid { grid-template-columns: 1fr 1fr; gap: 6.4rem; } }
.gs-proof h2 { font-size: clamp(2.8rem, 3.6vw, 4.4rem); }
/* Icon tile + eyebrow read as a single badge. Left to themselves both are
   inline-level (.gs-card__icon is inline-flex, .gs-eyebrow inline-block), so
   they share a line box and align on the baseline — and an inline-flex box's
   baseline is its bottom margin edge, which parks the eyebrow at the tile's
   foot instead of its centre. A flex row centres them properly and carries the
   bottom margin the tile used to supply on its own. */
.gs-proof__badge { display: flex; align-items: center; gap: 1.6rem; margin-bottom: 2.4rem; }
.gs-proof__badge .gs-card__icon { margin-bottom: 0; flex: none; }
.gs-proof__badge .gs-eyebrow { margin: 0; }
.gs-proof__body { margin: 2rem 0 3.2rem; color: var(--muted); font-size: 1.8rem; }
.gs-proof__rows { display: flex; flex-direction: column; }
.gs-proof__row { padding: 1.8rem 0; border-bottom: 1.5px solid var(--rule); font-weight: 500; font-size: 1.8rem; }
.gs-proof__row:first-child { border-top: 1.5px solid var(--rule); }
.gs-proof__quote { align-self: stretch; }

/* ---- Proof panel: rich rows variant ---- */
.gs-proof__rich { list-style: none; padding: 0; margin: 0; }
.gs-proof__rich li { border-top: 1px solid var(--rule); padding-block: 1.8rem; }
.gs-proof__rich li:last-child { border-bottom: 1px solid var(--rule); }
.gs-proof__rich h4 { font-family: var(--font-heading); font-weight: 500; font-size: 1.9rem; line-height: 1.15; margin: 0; }
.gs-proof__rich p { margin: .6rem 0 0; color: var(--muted); font-size: 1.6rem; line-height: 1.45; }
@media (min-width: 800px) { .gs-proof__rich h4 { font-size: 2.2rem; } }

/* ============ Quote block ============ */
.gs-quote__inner { background: var(--theme-medium, var(--cream)); color: var(--theme-fg, var(--ink)); border-radius: 3.2rem; padding: clamp(3.2rem, 4vw, 5.6rem); }
.gs-quote__inner blockquote { margin: 0; font-family: var(--font-heading); font-weight: 500; font-size: clamp(2rem, 2.4vw, 2.8rem); line-height: 1.22; letter-spacing: -0.01em; }
.gs-quote__mark { font-size: 6rem; line-height: .5; display: block; margin-bottom: 1.6rem; opacity: .5; }
.gs-quote__by { display: flex; align-items: center; gap: 1.4rem; margin-top: 3.2rem; }
.gs-quote__avatar { width: 5.2rem; height: 5.2rem; border-radius: 999px; object-fit: cover; }
.gs-quote__name { font-weight: 500; }
.gs-quote__role { opacity: .75; font-size: 1.5rem; }

/* ============ Logo / trust strip ============ */
.gs-logos { background: var(--paper); padding-block: 6rem; }
.gs-logos__label { text-align: center; font-size: 1.4rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin-bottom: 3.2rem; }
.gs-logos__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 3.2rem 5.6rem; }
.gs-logos__item { font-family: var(--font-heading); font-weight: 500; font-size: 2.2rem; color: var(--stone); letter-spacing: -0.01em; }
.gs-logos__row--img { gap: 3.2rem 4.8rem; }
.gs-logos__img { height: 4rem; width: auto; max-width: 16rem; object-fit: contain; display: block; }

/* ---- Logo strip: marquee variant ---- */
.gs-logos__marquee { overflow: hidden; }
.gs-logos__track { display: flex; gap: 4.8rem; width: max-content; animation: gsMarquee 40s linear infinite; }
.gs-logos__marquee:hover .gs-logos__track { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .gs-logos__track { animation: none; flex-wrap: wrap; } }

/* ============ CTA banner ============ */
.gs-banner { background: var(--theme-medium, var(--ink)); color: var(--theme-fg, #fff); }
.gs-banner__inner { text-align: center; max-width: 72rem; margin-inline: auto; }
.gs-banner h2 { font-size: clamp(3rem, 4.6vw, 5.4rem); color: inherit; }
.gs-banner__sub { margin: 2rem auto 3.2rem; font-size: 1.9rem; opacity: .82; max-width: 52rem; }
/* On vivid/dark banners the primary pill stays black; when the banner itself
   is black (ink) we can't show a black pill, so invert to a paper pill. */
.gs-banner .gs-btn { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.gs-banner .gs-btn:hover { background: #262626; border-color: #262626; }

/* ============ HubSpot / lead form ============ */
.gs-form { background: var(--theme-light, var(--cream)); }
.gs-form__inner { max-width: 60rem; }
.gs-form h2 { font-size: clamp(2.6rem, 3.4vw, 4rem); }
.gs-form__sub { margin: 1.6rem 0 0; color: var(--muted); }
.gs-form__mock { display: grid; gap: 1.6rem; margin-top: 3.2rem; }
.gs-form__mock label { display: grid; gap: .8rem; font-size: 1.5rem; font-weight: 500; }
.gs-form__mock input { font: inherit; font-size: 1.7rem; padding: 1.5rem 1.8rem; border: 1.5px solid #dcd8d2; border-radius: 1.2rem; background: var(--paper); }
.gs-form__mock input:focus { outline: none; border-color: var(--ink); }
.gs-form__mock .gs-btn { margin-top: .8rem; }

/* ---- Lead form: trust badges variant ---- */
.gs-form__badges { list-style: none; padding: 0; margin: 0 0 2.4rem; display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }
.gs-form__badges li { display: inline-flex; align-items: center; gap: .6rem; border-radius: 999px; padding: .7rem 1.2rem; font-size: 1.4rem; font-weight: 500; background: var(--paper); border: 1px solid var(--rule); }

/* ---- "What to expect" checklist + privacy line (client request, 2026-09-29) ----
   Shared by the hero's form card and the Lead form section (FormPoints / FormPrivacyNote):
   the checklist sits between the intro and the fields, in the theme's light tone with
   check discs in its vivid one; the shield line sits under the form. The Lead form section
   is itself the light tone, so there the checklist turns paper-white to stay a box. */
.gs-formpoints { list-style: none; margin: 2.4rem 0; padding: 2rem 2.4rem; display: grid; gap: 1.2rem; border-radius: 1.6rem; background: var(--theme-light, #fff2d6); }
.gs-formpoints li { display: flex; align-items: flex-start; gap: 1.2rem; font-size: 1.6rem; font-weight: 500; line-height: 1.45; color: var(--ink); }
.gs-formpoints__check { flex: none; width: 2.4rem; height: 2.4rem; border-radius: 999px; background: var(--theme-medium, #ffb51c); color: var(--theme-fg, var(--ink)); display: inline-flex; align-items: center; justify-content: center; }
.gs-formpoints__check svg { width: 1.3rem; height: 1.3rem; }
.gs-form .gs-formpoints { background: var(--paper); }
/* …except in a bold frame, where the content already sits on a paper panel. */
.gs-slot[data-frame=bold] .gs-form .gs-formpoints { background: var(--theme-light, #fff2d6); }
/* The shield is inline, not a flex item: when the line wraps in a narrow card it still leads the first word. */
.gs-formprivacy { margin: 2rem 0 0; font-size: 1.4rem; line-height: 1.45; color: var(--muted); text-align: center; text-wrap: balance; }
.gs-formprivacy svg { display: inline-block; width: 1.5rem; height: 1.5rem; margin-right: .6rem; vertical-align: -.25rem; }

/* ============ Header / footer (slim landing chrome) ============ */
.gs-header { padding-block: 2rem; background: var(--paper); border-bottom: 1px solid var(--rule); }
.gs-header__inner { display: flex; align-items: center; justify-content: space-between; gap: 2.4rem; }
.gs-header svg, .gs-header img { height: 2.8rem; width: auto; }
.gs-header__right { display: flex; align-items: center; gap: 1.6rem; }
/* EN/FR switch: the published other-language version, when there is one */
.gs-header__lang { font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; letter-spacing: .06em; color: var(--ink); text-decoration: none; padding: .6rem .2rem; border-bottom: 1.5px solid transparent; }
.gs-header__lang:hover { border-bottom-color: var(--ink); }

/* ============ Footer (the gestisoft.com footer, minus the video prefooter) ============ */
/* ── The site footer, minus the video prefooter (LandingFooter.svelte). Painted through the
   gold theme variables (data-theme=gold on the footer); geometry follows the site's
   Footer.svelte: p-20 / bp:px-40 pt-80 pb-32, rows spaced 4rem / 6rem. ── */
.gs-footer { --fu: 1rem; display: flex; flex-direction: column; gap: 4rem; padding: 2rem; background: var(--theme-medium); color: var(--ink); font-size: calc(1.6 * var(--fu)); line-height: 1.15; }
/* --fu is the site's own rem: gestisoft.com scales 1rem with the viewport on desktop (0.625vw, i.e. 10px from
   1600px up, 8px at 1280px). The kit's rem is a fixed 10px, so the footer's type and badges use --fu to read the
   same size as the site at any width; floored at 8px so a narrow preview never shrinks it to a whisper. */
@media (min-width: 800px) { .gs-footer { --fu: clamp(.8rem, .625vw, 1rem); gap: 6rem; padding: 8rem 4rem 3.2rem; } }
.gs-footer a { color: inherit; text-decoration: none; }
.gs-footer a:hover { text-decoration: underline; text-underline-offset: .2em; }
.gs-footer ul { list-style: none; margin: 0; padding: 0; }
.gs-footer__label { margin: 0 0 1.6rem; font-weight: 700; font-size: calc(1.6 * var(--fu)); line-height: 1.15; color: rgba(15, 15, 15, .5); }
.gs-footer__top { display: flex; flex-direction: column; align-items: flex-start; gap: 4rem; }
/* Desktop: the certifications keep their full size (flex: none) and the link columns take what is left; below
   ~1030px the columns wrap under the badges instead of squeezing them, which is what the site's viewport-scaled
   layout amounts to at those widths. */
@media (min-width: 800px) { .gs-footer__top { flex-direction: row; flex-wrap: wrap; justify-content: space-between; gap: 6rem 16rem; } .gs-footer__certs { flex: none; } .gs-footer__lists { flex: 1 1 0; min-width: 44rem; } }
.gs-footer__certs { max-width: 60rem; }
.gs-footer__certs ul { display: grid; grid-template-columns: repeat(3, 1fr); gap: 3.2rem; align-items: center; }
@media (min-width: 800px) { .gs-footer__certs ul { gap: 6.4rem; } }
/* A definite width (not 100%): a percentage width counts for nothing in the flex row's intrinsic sizing, which is
   how the badges were being squeezed to a third of their size. 24vw keeps three of them on a phone screen. */
.gs-footer__certs img { display: block; width: min(calc(10 * var(--fu)), 24vw); height: auto; object-fit: contain; }
.gs-footer__lists { display: flex; flex-direction: column; gap: 3.2rem; }
@media (min-width: 800px) { .gs-footer__lists { display: block; columns: 3; column-gap: 10rem; } }
.gs-footer__list { break-inside: avoid; }
@media (min-width: 800px) { .gs-footer__list { margin-bottom: 3.2rem; } }
.gs-footer__list ul { display: flex; flex-direction: column; gap: 1.2rem; }
.gs-footer__list li a { display: inline-block; font-size: calc(1.6 * var(--fu)); line-height: 1; }
@media (min-width: 800px) { .gs-footer__list li a { font-size: calc(2 * var(--fu)); } }
.gs-footer__socials { flex-direction: row !important; gap: .8rem !important; }
/* `.gs-footer a.gs-footer__social` outranks the `.gs-footer__list li a` text-link rule above, which otherwise
   turns the round button back into an inline-block and leaves the icon sitting off-centre on the baseline. */
.gs-footer a.gs-footer__social { display: inline-flex; align-items: center; justify-content: center; width: calc(3.2 * var(--fu)); height: calc(3.2 * var(--fu)); border: 2px solid var(--ink); border-radius: 999px; color: var(--ink); line-height: 1; transition: background-color .15s linear, color .15s linear; }
.gs-footer a.gs-footer__social:hover { background: var(--ink); color: var(--theme-medium); text-decoration: none; }
.gs-footer__social svg { display: block; width: calc(1.6 * var(--fu)); height: calc(1.6 * var(--fu)); }
/* The offices row: a full-width button with a rule above it, + closed, − open, like the site. */
.gs-footer__offices { border-top: 1px solid var(--ink); }
.gs-footer__officesbtn { display: flex; align-items: center; justify-content: space-between; gap: 1.6rem; padding: 2rem 0; cursor: pointer; list-style: none; font-family: var(--font-heading); font-weight: 500; font-size: calc(2 * var(--fu)); line-height: 1.1; }
.gs-footer__officesbtn::-webkit-details-marker { display: none; }
.gs-footer__officesicon { position: relative; flex: none; width: 1.6rem; height: 1.6rem; }
.gs-footer__officesicon::before, .gs-footer__officesicon::after { content: ''; position: absolute; left: 0; top: calc(50% - .75px); width: 100%; height: 1.5px; background: var(--ink); }
.gs-footer__officesicon::after { transform: rotate(90deg); transition: transform .3s ease; }
.gs-footer__offices[open] .gs-footer__officesicon::after { transform: rotate(0deg); }
.gs-footer__officegrid { display: grid; gap: 3.2rem; padding: 1.2rem 0 2rem; grid-template-columns: 1fr; }
@media (min-width: 800px) { .gs-footer__officegrid { grid-template-columns: repeat(4, 1fr); padding-top: 1.6rem; } }
.gs-footer__office { font-style: normal; line-height: 1.5; }
.gs-footer__office span { display: block; }
.gs-footer__officelinks { margin-top: 1rem; }
/* The wordmark: full width, white, the site's FooterLogo. */
.gs-footer a.gs-footer__mark { display: flex; position: relative; width: 100%; color: #fff; }
.gs-footer__mark svg { width: 100%; height: auto; }
.gs-footer a.gs-footer__mark:hover { text-decoration: none; }
/* Hover animation over the G, as on the site: a square the wordmark's height at its left edge shows the frames
   one at a time (a steps() slide of the strip, 250 ms per frame). */
.gs-footer__sprite { display: none; position: absolute; left: 0; top: 0; height: 100%; aspect-ratio: 1; overflow: hidden; pointer-events: none; }
.gs-footer a.gs-footer__mark:hover .gs-footer__sprite { display: flex; }
.gs-footer__frames { display: flex; flex: none; height: 100%; animation: gs-footer-sprite calc(250ms * var(--gs-steps, 8)) steps(var(--gs-steps, 8)) infinite; }
.gs-footer__frame { display: block; height: 100%; width: auto; aspect-ratio: 1; }
@keyframes gs-footer-sprite { from { transform: translateX(0); } to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) { .gs-footer__frames { animation: none; } }
.gs-footer__bottom { display: flex; flex-direction: column; align-items: flex-start; gap: 1.2rem; font-weight: 500; font-size: calc(1.6 * var(--fu)); line-height: 1.15; color: rgba(15, 15, 15, .7); }
@media (min-width: 800px) { .gs-footer__bottom { flex-direction: row; align-items: center; gap: 2rem; } }
.gs-footer__copyright { margin: 0; color: var(--ink); }
.gs-footer__legal { display: flex; flex-wrap: wrap; gap: 1.2rem 2rem; }

/* ============ Back to top ============
   Floating ink pill, bottom-right. Hidden until BackToTop.svelte adds .is-visible
   (one screen scrolled, on a page at least two screens tall). Sized in px so it
   stays a 44px touch target whatever the rem base. */
.gs-totop {
	position: fixed; right: 24px; bottom: 24px; z-index: 900;
	display: inline-flex; align-items: center; justify-content: center;
	width: 44px; height: 44px; padding: 0; border-radius: 9999px; border: 1.5px solid var(--ink);
	background: var(--ink); color: var(--paper); cursor: pointer;
	opacity: 0; visibility: hidden; transform: translateY(8px);
	transition: opacity .3s ease, transform .5s var(--ease-out-quint), visibility 0s linear .3s, background-color .3s ease;
}
.gs-totop.is-visible { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.gs-totop.is-visible:hover { transform: translateY(-2px) scale(1.04); background: #262626; border-color: #262626; }
.gs-totop:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.gs-totop svg { width: 20px; height: 20px; }
@media (prefers-reduced-motion: reduce) { .gs-totop, .gs-totop.is-visible:hover { transition: none; transform: none; } }

/* ============ Pricing ============ */
.gs-pricing { background: var(--paper); }
.gs-pricing__grid { display: grid; gap: 2.4rem; grid-template-columns: 1fr; align-items: stretch; }
@media (min-width: 800px) { .gs-pricing__grid { grid-template-columns: repeat(auto-fit, minmax(26rem, 1fr)); } }
.gs-plan { display: flex; flex-direction: column; border: 1.5px solid var(--rule); border-radius: 2rem; padding: 3.2rem; background: var(--paper); }
.gs-plan--featured { border-color: var(--ink); border-width: 2px; box-shadow: 0 20px 50px rgba(15, 15, 15, 0.1); position: relative; }
.gs-plan__tag { position: absolute; top: -1.3rem; left: 3.2rem; background: var(--theme-medium, #ffb51c); color: var(--theme-fg, #0f0f0f); font-family: var(--font-heading); font-size: 1.2rem; text-transform: uppercase; letter-spacing: .08em; padding: .6rem 1.4rem; border-radius: 99px; }
.gs-plan__name { font-family: var(--font-heading); font-weight: 500; font-size: 1.8rem; }
.gs-plan__price { font-family: var(--font-heading); font-weight: 500; font-size: clamp(3.2rem, 4vw, 4.4rem); line-height: 1; margin: 1.2rem 0 .4rem; }
.gs-plan__period { font-size: 1.6rem; color: var(--muted); font-family: var(--font-body); }
.gs-plan__desc { color: var(--muted); margin: 1.2rem 0 2.4rem; font-size: 1.6rem; }
.gs-plan__features { list-style: none; padding: 0; margin: 0 0 3.2rem; display: flex; flex-direction: column; gap: 1.2rem; }
.gs-plan__features li { display: flex; gap: 1rem; align-items: flex-start; font-size: 1.6rem; }
.gs-plan__features svg { width: 1.8rem; height: 1.8rem; color: var(--theme-dark, var(--ink)); flex: none; margin-top: .2rem; }
.gs-plan__cta { margin-top: auto; text-align: center; }

/* ============ FAQ ============ */
.gs-faq { background: var(--paper); }
.gs-faq__inner { max-width: 82rem; margin-inline: auto; }
.gs-faq__head { text-align: center; margin-bottom: 4.8rem; }
.gs-faq__head h2 { font-size: clamp(3rem, 4vw, 4.4rem); }
.gs-faq__item { border-bottom: 1.5px solid var(--rule); }
.gs-faq__item:first-child { border-top: 1.5px solid var(--rule); }
.gs-faq__q { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 2rem; padding: 2.4rem 0; font-family: var(--font-heading); font-weight: 500; font-size: 2rem; }
.gs-faq__q::-webkit-details-marker { display: none; }
.gs-faq__mark { position: relative; flex: none; width: 2rem; height: 2rem; }
.gs-faq__mark::before, .gs-faq__mark::after { content: ''; position: absolute; background: var(--ink); border-radius: 2px; transition: transform .2s ease; }
.gs-faq__mark::before { top: 50%; left: 0; width: 2rem; height: 2px; margin-top: -1px; }
.gs-faq__mark::after { left: 50%; top: 0; width: 2px; height: 2rem; margin-left: -1px; }
details[open] .gs-faq__mark::after { transform: scaleY(0); }
.gs-faq__a { padding: 0 0 2.6rem; color: var(--muted); font-size: 1.8rem; line-height: 1.55; max-width: 66rem; }

/* ============ Steps / process ============ */
.gs-steps { background: var(--paper); }
.gs-steps__head { max-width: 68rem; margin: 0 auto 6rem; text-align: center; }
.gs-steps__head h2 { font-size: clamp(3rem, 4.4vw, 5rem); }
.gs-steps__head .gs-lead { margin-top: 2rem; }
.gs-steps__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 4rem 3.2rem; grid-template-columns: 1fr; }
@media (min-width: 800px) { .gs-steps__list { grid-template-columns: repeat(auto-fit, minmax(24rem, 1fr)); } }
.gs-step__num { display: inline-grid; place-items: center; width: 4.8rem; height: 4.8rem; border-radius: 99px; background: var(--theme-medium, #ffb51c); color: var(--theme-fg, #0f0f0f); font-family: var(--font-heading); font-weight: 500; font-size: 2rem; margin-bottom: 2rem; }
.gs-step__title { font-size: 2.2rem; margin-bottom: 1rem; }
.gs-step__body { color: var(--muted); font-size: 1.7rem; }

/* ---- Steps: trailing note + CTA variant ---- */
.gs-steps__note { margin: 4rem auto 0; max-width: 62rem; text-align: center; color: var(--muted); font-size: 1.6rem; }
.gs-steps__cta { display: flex; justify-content: center; margin-top: 2.4rem; }

/* ============ Stats band ============ */
.gs-stats { background: var(--theme-medium, var(--cream)); color: var(--theme-fg, var(--ink)); }
.gs-stats__head { text-align: center; margin-bottom: 4.8rem; }
.gs-stats__head h2 { color: inherit; font-size: clamp(2.8rem, 3.5vw, 4rem); }
.gs-stats__grid { display: grid; gap: 3.2rem; grid-template-columns: repeat(2, 1fr); text-align: center; }
@media (min-width: 800px) { .gs-stats__grid { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); } }
.gs-stat__value { font-family: var(--font-heading); font-weight: 500; font-size: clamp(4rem, 6vw, 6.4rem); line-height: 1; letter-spacing: -0.02em; }
.gs-stat__label { margin-top: 1.2rem; font-size: 1.6rem; opacity: .82; }

/* ============ Team ============ */
.gs-team { background: var(--paper); }
.gs-team__grid { display: grid; gap: 3.2rem; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 800px) { .gs-team__grid { grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr)); } }
.gs-member__photo { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 1.6rem; margin-bottom: 1.6rem; }
.gs-member__photo--placeholder { display: grid; place-items: center; font-family: var(--font-heading); font-weight: 500; font-size: 4rem; color: var(--theme-darker, var(--muted)); background: var(--theme-light, var(--cream)); }
.gs-member__name { font-family: var(--font-heading); font-weight: 500; font-size: 1.9rem; }
.gs-member__role { color: var(--muted); font-size: 1.5rem; margin-top: .3rem; }

/* ---- Team: tags variant ---- */
.gs-member { position: relative; }
.gs-member__badge { position: absolute; top: 1.2rem; left: 1.2rem; display: inline-flex; font-family: var(--font-heading); font-weight: 500; font-size: 1.3rem; line-height: 1; padding: .6rem 1rem; border-radius: 999px; background: var(--theme-medium, var(--cream)); color: var(--theme-fg, var(--ink)); }
/* Achievement figures under the grid: label, value, and a bar `fill` percent full. */
.gs-team__stats { display: grid; gap: 2.4rem 4.8rem; grid-template-columns: 1fr; margin: 5.6rem 0 0; padding-top: 4rem; border-top: 1.5px solid var(--rule); }
@media (min-width: 800px) { .gs-team__stats { grid-template-columns: repeat(auto-fit, minmax(24rem, 1fr)); } }
.gs-team__stat dt { font-size: 1.5rem; color: var(--muted); margin: 0 0 .6rem; }
.gs-team__stat dd { margin: 0; }
.gs-team__stat b { display: block; font-family: var(--font-heading); font-weight: 500; font-size: 3.2rem; line-height: 1; margin-bottom: 1.2rem; }
.gs-team__bar { display: block; height: .8rem; border-radius: 999px; background: var(--theme-light, var(--cream)); overflow: hidden; }
.gs-team__fill { display: block; height: 100%; border-radius: inherit; background: var(--theme-medium, var(--ink)); }
.gs-member__tags { list-style: none; padding: 0; margin: 1.2rem 0 0; display: flex; flex-wrap: wrap; gap: .8rem; }
.gs-member__tags li { border: 1px solid rgba(15, 15, 15, .2); border-radius: 999px; padding: .6rem 1rem; font-size: 1.4rem; font-weight: 500; line-height: 1; }

/* ============================================================
   REAL gestisoft.com blocks (batch 1) — reproduced faithfully
   from GESTI-sveltekit modules. Shared module rhythm below.
   ============================================================ */

/* Module base — real gestisoft rhythm: TOP padding only (pt-100 / bp:pt-200),
   content in the shared container so section left-edges stay aligned. */
/* Symmetric on purpose. This used to be padding-top only, which put the whole
   inter-section gap on the leading edge — fine while a section is transparent,
   but a module that PAINTS (a full-bleed band like .gs-pq, or an inset panel
   like .gs-cta__inner / .gs-splash__panel / .gs-highlights__panel) then ran its
   colour flush into whatever followed, with a large void above and nothing
   below. Splitting the same total in half keeps the rhythm between two modules
   identical (0+20 and 10+10 both give 20rem) while giving painted edges room,
   and balances the padding inside a full-bleed band instead of stacking it all
   at the top. */
.gs-mod { position: relative; padding-block: 5rem; animation: gsFadeUp .6s var(--ease-out-expo) both; }
@media (min-width: 800px) { .gs-mod { padding-block: 10rem; } }
@media (prefers-reduced-motion: reduce) { .gs-mod { animation: none; } }
/* Centered header (real BigMacTrio: max-w-840, big Matter title text-32→72) */
.gs-mod__head { max-width: 96rem; margin: 0 auto 4rem; text-align: center; }
.gs-mod__head .gs-eyebrow { margin: 0 0 1.6rem; }
.gs-mod__head h2 { font-size: 3.2rem; line-height: 1.02; }
.gs-mod__head .gs-lead { margin-top: 1.2rem; }
@media (min-width: 800px) { .gs-mod__head { margin-bottom: 6rem; } .gs-mod__head h2 { font-size: 6.4rem; line-height: .98; } .gs-mod__head .gs-lead { margin-top: 2.4rem; } }

/* ---- Icon grid (real grid/IconGrid: 3-col, hairline top rule, icon left of copy) ---- */
.gs-icons__grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 800px) { .gs-icons__grid { grid-template-columns: repeat(3, 1fr); column-gap: 4.8rem; row-gap: 4rem; } }
.gs-icons__item { position: relative; display: flex; gap: 1.6rem; padding-top: 3.2rem; border-top: 1px solid rgba(15, 15, 15, 0.1); }
.gs-icons__icon { flex: none; color: var(--theme-dark, var(--ink)); }
.gs-icons__icon svg { width: 3.2rem; height: 3.2rem; }
.gs-icons__item h3 { font-family: var(--font-heading); font-weight: 500; font-size: 2rem; }
.gs-icons__item p { margin: .8rem 0 0; opacity: .9; font-size: 1.6rem; line-height: 1.5; }
@media (min-width: 800px) { .gs-icons__item h3 { font-size: 2.6rem; } .gs-icons__item p { font-size: 2rem; line-height: 1.4; } }

/* ---- Icon grid variants ---- */
.gs-icons__num { flex: none; font-family: var(--font-heading); font-weight: 500; font-size: 2rem; line-height: 1; color: var(--theme-dark, var(--ink)); font-variant-numeric: tabular-nums; }
.gs-icons__label { display: block; font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; letter-spacing: .12em; text-transform: uppercase; color: var(--theme-dark, var(--ink)); margin-bottom: .8rem; }
.gs-icons__bullets { list-style: none; padding: 0; margin: 1.6rem 0 0; display: flex; flex-direction: column; gap: .8rem; }
.gs-icons__bullets li { position: relative; padding-left: 2.4rem; font-size: 1.6rem; line-height: 1.4; opacity: .9; }
/* top is .29em, not the line box's midpoint, because the tick is an L of two
   borders rotated about its box centre: the ink's centroid ends up 2.08px
   BELOW that centre, on top of the line box already sitting lower than the
   text's cap height. At .55em the mark landed 4.14px under the text's optical
   centre — a quarter of the font size, and very visible. */
.gs-icons__bullets li::before { content: ''; position: absolute; left: 0; top: .29em; width: 1.2rem; height: .7rem; border-left: 2px solid var(--theme-dark, var(--ink)); border-bottom: 2px solid var(--theme-dark, var(--ink)); transform: rotate(-45deg); }
.gs-icons__item .gs-icons__proof { margin-top: 1.6rem; padding-top: 1.2rem; border-top: 1px solid var(--rule); font-size: 1.5rem; line-height: 1.4; opacity: .75; }
@media (min-width: 800px) {
	.gs-icons__num { font-size: 2.6rem; }
	.gs-icons--numbered .gs-icons__grid { column-gap: 4.8rem; }
}

/* ---- Highlights (real Highlights: big Matter rows on a colored panel, default gold) ---- */
.gs-highlights__panel { margin-inline: -2rem; border-radius: 3.2rem; background: var(--theme-medium, #ffb51c); color: var(--theme-fg, #0f0f0f); padding: 2rem; list-style: none; }
@media (min-width: 800px) { .gs-highlights__panel { margin-inline: 0; padding: 4rem 8rem; } }
.gs-highlights__row { position: relative; display: grid; gap: 1.6rem; padding-block: 2rem; }
@media (min-width: 800px) { .gs-highlights__row { grid-template-columns: 3fr 4fr; gap: 4rem; padding-block: 4rem; } }
.gs-highlights__row + .gs-highlights__row { border-top: 1px solid rgba(15, 15, 15, 0.18); }
.gs-highlights__title { margin: 0; font-family: var(--font-heading); font-weight: 500; font-size: 3.6rem; line-height: .95; }
.gs-highlights__body { opacity: .9; font-size: 1.6rem; line-height: 1.5; }
@media (min-width: 800px) { .gs-highlights__title { font-size: 4.8rem; } .gs-highlights__body { font-size: 2rem; line-height: 1.4; } }

/* ---- Highlights: two-column comparison variant ---- */
.gs-highlights__cols { display: grid; gap: 2rem; grid-template-columns: 1fr; }
.gs-highlights__colhead { font-family: var(--font-heading); font-weight: 500; font-size: 2rem; line-height: 1.1; margin-bottom: 2rem; }
.gs-highlights--columns .gs-highlights__row { grid-template-columns: 1fr; gap: 1.2rem; padding-block: 2rem; }
.gs-highlights--columns .gs-highlights__title { font-size: 3.2rem; }
.gs-highlights__note { display: block; margin-top: .8rem; font-size: 1.3rem; opacity: .7; }
/* note sits as its own grid item in the columns row (sibling of title/body, not
   nested inside body — see Highlights.svelte); the row's own gap already spaces
   it, so its default margin-top would double up here. Zero it in this context. */
.gs-highlights--columns .gs-highlights__note { margin-top: 0; }
@media (min-width: 800px) {
	.gs-highlights__cols { grid-template-columns: 1fr 1fr; gap: 3.2rem; }
	.gs-highlights__colhead { font-size: 2.6rem; }
	.gs-highlights--columns .gs-highlights__title { font-size: 4rem; }
}

/* ---- CTA (real Cta: themed rounded banner, copy + button duo, optional media) ---- */
.gs-cta__inner { display: grid; gap: 4rem; border-radius: 1.6rem; background: var(--theme-medium, var(--ink)); color: var(--theme-fg, #fff); padding: 3.2rem 2rem; }
@media (min-width: 800px) { .gs-cta__inner { grid-template-columns: 4fr 3fr; padding: 4rem; } }
.gs-cta__copy { display: flex; flex-direction: column; justify-content: space-between; gap: 2rem; }
.gs-cta__lead { display: flex; flex-direction: column; gap: 1.6rem; }
.gs-cta__eyebrow { font-family: var(--font-heading); font-weight: 700; font-size: 1.6rem; line-height: 1.15; }
.gs-cta__title { margin: 0; font-family: var(--font-heading); font-weight: 500; font-size: 3.2rem; line-height: 1.06; }
.gs-cta__text { opacity: .9; font-size: 1.6rem; line-height: 1.5; }
.gs-cta__cts { display: flex; flex-wrap: wrap; gap: 1.2rem; align-items: center; margin-top: .4rem; }
.gs-cta__img { width: 100%; border-radius: 1.6rem; object-fit: cover; }
/* variant "minimal": the same copy and buttons, centred on the page background, no banner */
.gs-cta--minimal .gs-cta__inner { display: flex; flex-direction: column; align-items: center; text-align: center; background: transparent; color: var(--ink); padding: 0; border-radius: 0; }
.gs-cta--minimal .gs-cta__copy { align-items: center; max-width: 76rem; }
.gs-cta--minimal .gs-cta__lead { align-items: center; }
.gs-cta--minimal .gs-cta__title { font-size: clamp(2.8rem, 3.6vw, 4.4rem); }
.gs-cta--minimal .gs-cta__text { color: var(--muted); opacity: 1; font-size: 1.8rem; }
.gs-cta--minimal .gs-cta__cts { justify-content: center; }
.gs-cta--minimal .gs-cta__media { max-width: 56rem; margin-top: 2.4rem; }
.gs-cta__media { display: none; }
.gs-cta__media--mobile { margin-top: .4rem; }
@media (min-width: 800px) { .gs-cta__eyebrow { font-size: 2rem; } .gs-cta__title { font-size: 4.8rem; } .gs-cta__text { font-size: 2rem; line-height: 1.4; } .gs-cta__media { display: block; } .gs-cta__media--mobile { display: none; } }
/* ghost CTA button follows the banner foreground so it stays visible on dark themes */
.gs-cta__inner .gs-btn--ghost { color: var(--theme-fg, #fff); border-color: var(--theme-fg, #fff); }
.gs-cta__inner .gs-btn--ghost:hover { background: var(--theme-fg, #fff); color: var(--theme-medium, var(--ink)); }

/* ---- CTA variants ---- */
.gs-cta__bullets { list-style: none; padding: 0; margin: 1.6rem 0 0; display: flex; flex-direction: column; gap: .8rem; }
.gs-cta__bullets li { position: relative; padding-left: 2.4rem; font-size: 1.6rem; line-height: 1.4; opacity: .92; }
.gs-cta__bullets li::before { content: ''; position: absolute; left: 0; top: .55em; width: 1.2rem; height: .7rem; border-left: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(-45deg); }
.gs-cta__avatars { display: flex; margin-bottom: 1.6rem; }
.gs-cta__avatars img { width: 4.8rem; height: 4.8rem; border-radius: 999px; object-fit: cover; border: 2px solid var(--theme-medium, var(--ink)); }
.gs-cta__avatars img + img { margin-left: -1.6rem; }

/* ---- Splash cards (real SplashCards: 3 image cards on a full-width colored panel) ---- */
.gs-splash__bleed { }
@media (min-width: 800px) { .gs-splash__bleed { padding-inline: 2rem; } }
.gs-splash__panel { border-radius: 3.2rem; background: var(--theme-light, var(--cream)); color: var(--ink); padding: 10rem 0 3.2rem; }
@media (min-width: 800px) { .gs-splash__panel { padding: 12rem 0 8rem; } }
.gs-splash__head { max-width: 84rem; margin: 0 auto; text-align: center; }
.gs-splash__head .gs-eyebrow { color: var(--theme-darker, var(--ink)); margin: 0 0 1.6rem; }
.gs-splash__head h2 { color: inherit; font-size: 3.2rem; line-height: 1.02; }
.gs-splash__head .gs-lead { color: inherit; opacity: .9; margin-top: 1.2rem; }
@media (min-width: 800px) { .gs-splash__head h2 { font-size: 7.2rem; line-height: .95; } .gs-splash__head .gs-lead { margin-top: 2.4rem; } }
.gs-splash__grid { list-style: none; padding: 0; margin: 8rem 0 0; display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 800px) { .gs-splash__grid { grid-template-columns: repeat(3, 1fr); } }
.gs-splash__card { display: flex; flex-direction: column; align-items: center; gap: 2rem; border-radius: 1.6rem; border: 1px solid rgba(15, 15, 15, 0.18); padding: 2.4rem 3.2rem; text-align: center; }
@media (min-width: 800px) { .gs-splash__card { padding-block: 4rem; } }
.gs-splash__img { width: 20rem; height: 20rem; border-radius: 1.2rem; object-fit: cover; }
.gs-splash__card h3 { font-family: var(--font-heading); font-weight: 500; font-size: 3.2rem; }
.gs-splash__card p { font-size: 1.6rem; line-height: 1.5; }
@media (min-width: 800px) { .gs-splash__card p { line-height: 1.4; } }
.gs-splash__cta { display: flex; justify-content: center; padding-top: 3.2rem; }
@media (min-width: 800px) { .gs-splash__cta { padding-top: 8rem; } }

/* ---- Text + interface (real TextInterface: copy beside a product screenshot; framed + bleed) ---- */
.gs-ti__head { display: flex; flex-direction: column; gap: 2rem; }
.gs-ti__head .gs-eyebrow { margin: 0; }
.gs-ti__head h2 { font-size: 3.2rem; }
.gs-ti__grid { display: grid; gap: 4rem; margin-top: 3.2rem; align-items: center; }
.gs-ti__copy { display: flex; flex-direction: column; gap: 2rem; }
.gs-ti__text { opacity: .9; font-size: 1.6rem; line-height: 1.5; }
.gs-ti__list { list-style: none; padding: 0; margin: 0; }
.gs-ti__list li { border-bottom: 1px solid var(--stone); padding-bottom: 1.2rem; margin-bottom: 1.2rem; font-size: 1.6rem; line-height: 1.4; }
.gs-ti__img { width: 100%; border-radius: 1.6rem; object-fit: cover; }
.gs-ti__cta { display: flex; padding-top: .8rem; }
.gs-ti--framed .gs-ti__panel { border-radius: 1.6rem; background: var(--cream); padding: 3.2rem 2rem; }
@media (min-width: 800px) {
	.gs-ti__head h2 { font-size: 4.8rem; }
	.gs-ti__head { gap: 2.4rem; }
	.gs-ti__copy { gap: 2.4rem; }
	.gs-ti__text { font-size: 2rem; line-height: 1.4; }
	.gs-ti__list li { font-size: 2rem; }
	.gs-ti__cta { padding-top: 1.2rem; }
	.gs-ti__grid { grid-template-columns: 3fr 4fr; gap: 6.4rem; }
	.gs-ti--rev .gs-ti__grid { grid-template-columns: 4fr 3fr; }
	.gs-ti--rev .gs-ti__copy { order: 2; }
	.gs-ti--framed .gs-ti__panel { border-radius: 3.2rem; padding: 8rem; }
}

/* ---- Crayola grid (real CrayolaGrid: colored link tiles, hover-reveal + arrow chip) ---- */
.gs-crayola__grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 2rem; grid-template-columns: 1fr; }
.gs-crayola__card { position: relative; display: flex; flex-direction: column; justify-content: space-between; gap: 1.6rem; min-height: 26rem; border-radius: 1.6rem; background: var(--theme-main, var(--cream)); color: var(--theme-fg, var(--ink)); padding: 1.6rem; text-decoration: none; overflow: hidden; }
.gs-crayola__icon { align-self: flex-end; display: inline-flex; align-items: center; justify-content: center; width: 6.4rem; height: 6.4rem; border-radius: .8rem; background: rgba(255, 255, 255, .22); transition: transform .5s var(--ease-out-quint); transform-origin: top right; }
.gs-crayola__card:hover .gs-crayola__icon { transform: scale(.66); }
.gs-crayola__icon svg { width: 3.2rem; height: 3.2rem; }
.gs-crayola__foot { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.6rem; }
.gs-crayola__title { font-family: var(--font-heading); font-weight: 500; font-size: 2rem; }
.gs-crayola__reveal { display: grid; grid-template-rows: 1fr; overflow: hidden; }
.gs-crayola__reveal p { min-height: 0; margin: 0; font-size: 1.6rem; line-height: 1.2; }
.gs-crayola__reveal span { display: block; padding-top: 1.2rem; }
.gs-crayola__arrow { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 4rem; height: 4rem; border-radius: 999px; background: rgba(255, 255, 255, .22); }
.gs-crayola__arrow svg { width: 1.6rem; height: 1.6rem; }
@media (hover: hover) {
	.gs-crayola__reveal { grid-template-rows: 0fr; transition: grid-template-rows .5s var(--ease-out-quint); }
	.gs-crayola__card:hover .gs-crayola__reveal { grid-template-rows: 1fr; }
}
@media (min-width: 800px) {
	.gs-crayola__grid { gap: 2.4rem; grid-template-columns: repeat(3, 1fr); }
	.gs-crayola__grid--few { grid-template-columns: repeat(2, 1fr); }
	.gs-crayola__title { font-size: 2.6rem; }
	.gs-crayola__reveal p { font-size: 2rem; }
}

/* ---- Bento box (real BentoBox: media/text mosaic, 1_2 / 2_1 rows) ---- */
.gs-bento { display: flex; flex-direction: column; gap: 1.2rem; }
.gs-bento__row { display: grid; gap: 1.2rem; grid-template-columns: 1fr; }
.gs-bento__tile { position: relative; overflow: hidden; border-radius: 1.6rem; min-height: 24rem; }
.gs-bento__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.gs-bento__text { height: 100%; display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-end; gap: .8rem; background: var(--theme-main, var(--cream)); color: var(--theme-fg, var(--ink)); padding: 2.4rem; padding-top: 10rem; }
.gs-bento__text h3 { margin: 0; font-family: var(--font-heading); font-weight: 500; font-size: 3.6rem; line-height: 1; }
.gs-bento__text p { margin: 0; opacity: .9; font-size: 1.6rem; line-height: 1.4; }
@media (min-width: 800px) {
	.gs-bento { gap: 3.2rem; }
	.gs-bento__row { gap: 3.2rem; min-height: 34rem; }
	.gs-bento__row--1_2 { grid-template-columns: 1fr 2fr; }
	.gs-bento__row--2_1 { grid-template-columns: 2fr 1fr; }
	.gs-bento__tile { min-height: 0; }
	.gs-bento__text h3 { font-size: 4.8rem; }
}

/* ---- FAQ 2-col (real Faq: title + intro left, accordion right) ---- */
.gs-faq2__grid { display: grid; gap: 2.4rem; grid-template-columns: 1fr; }
.gs-faq2__title { font-size: 3.2rem; }
.gs-faq2__intro { margin-top: 2.4rem; opacity: .9; font-size: 1.8rem; line-height: 1.3; }
.gs-faq2__item { border-top: 1px solid var(--stone); }
.gs-faq2__item:last-child { border-bottom: 1px solid var(--stone); }
.gs-faq2__q { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 2rem; padding: 2rem 0; font-family: var(--font-heading); font-weight: 500; font-size: 2rem; line-height: 1.1; }
.gs-faq2__q::-webkit-details-marker { display: none; }
.gs-faq2__mark { position: relative; flex: none; width: 1.6rem; height: 1.6rem; }
.gs-faq2__mark::before, .gs-faq2__mark::after { content: ''; position: absolute; background: var(--ink); border-radius: 2px; }
.gs-faq2__mark::before { top: 50%; left: 0; width: 1.6rem; height: 2px; margin-top: -1px; }
.gs-faq2__mark::after { left: 50%; top: 0; width: 2px; height: 1.6rem; margin-left: -1px; transition: transform .2s ease; }
details[open] .gs-faq2__mark::after { transform: scaleY(0); }
.gs-faq2__a { padding: 0 0 2rem; opacity: .9; font-size: 1.6rem; line-height: 1.3; }
@media (min-width: 800px) {
	.gs-faq2__grid { grid-template-columns: 1fr 1fr; gap: 14rem; }
	.gs-faq2__title { font-size: 7.2rem; line-height: .95; }
}

/* ---- Testimonials (real Testimonials: centered title + CSS marquee of quote cards) ---- */
.gs-tm__head { max-width: 50rem; margin: 0 auto; text-align: center; }
.gs-tm__head h2 { font-size: 3.2rem; }
.gs-tm__marquee { margin-top: 6rem; overflow: hidden; }
.gs-tm__track { display: flex; gap: 2rem; width: max-content; animation: gsMarquee 50s linear infinite; }
.gs-tm__marquee:hover .gs-tm__track { animation-play-state: paused; }
@keyframes gsMarquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.gs-tm__card { flex: none; width: 41.6rem; max-width: 85vw; display: flex; flex-direction: column; justify-content: space-between; gap: 3.2rem; border: 2px solid var(--rule); border-radius: 2rem; padding: 3.2rem; background: var(--paper); }
.gs-tm__tag { align-self: flex-start; display: inline-flex; font-weight: 500; font-size: 1.4rem; background: var(--theme-medium, var(--cream)); color: var(--theme-fg, var(--ink)); border-radius: 999px; padding: .5rem 1rem; }
.gs-tm__quote { margin: 0 0 2rem; font-size: 2rem; font-weight: 500; line-height: 1.3; }
.gs-tm__by { display: flex; align-items: center; gap: 1.2rem; font-size: 1.6rem; }
.gs-tm__avatar { flex: none; width: 4.8rem; height: 4.8rem; border-radius: 999px; object-fit: cover; }
.gs-tm__name { font-weight: 700; }

/* ---- Accordion + media (real AccordionMedia: copy/accordion left, synced media right) ---- */
/* The media column starts at the top and sticks while the accordion scrolls past
   (client feedback: aligned to the end, the image sat at the very bottom of a
   nine-step list with a void above it). */
.gs-am__grid { display: grid; gap: 4rem; align-items: start; }
.gs-am__copy { display: flex; flex-direction: column; gap: 2rem; }
.gs-am__copy .gs-eyebrow { margin: 0; }
.gs-am__title { font-size: 3.2rem; }
.gs-am__intro { margin: 0; }
.gs-am__item { border-top: 1px solid var(--stone); }
.gs-am__item:last-child { border-bottom: 1px solid var(--stone); }
.gs-am__q { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 1.6rem; padding: 2rem 0; font-family: var(--font-heading); font-weight: 500; font-size: 2rem; line-height: 1.1; }
.gs-am__q::-webkit-details-marker { display: none; }
.gs-am__qtext { display: flex; align-items: baseline; gap: 1.2rem; }
.gs-am__num { color: var(--theme-dark, var(--muted)); font-variant-numeric: tabular-nums; }
.gs-am__a { padding: 0 0 2rem; font-size: 1.6rem; line-height: 1.3; }
.gs-am__a > p { margin: 0 0 1.2rem; opacity: .9; }
.gs-am__a > p.gs-am__label { font-weight: 500; opacity: 1; }
.gs-am__bullets { list-style: none; padding: 0; margin: 1.2rem 0 0; display: flex; flex-direction: column; gap: .8rem; }
.gs-am__bullets li { position: relative; padding-left: 2.4rem; opacity: .9; }
.gs-am__bullets li::before { content: ''; position: absolute; left: 0; top: .5em; width: 1.2rem; height: .7rem; border-left: 2px solid var(--theme-dark, var(--ink)); border-bottom: 2px solid var(--theme-dark, var(--ink)); transform: rotate(-45deg); }
.gs-am__quote { margin: 1.6rem 0 0; padding-left: 1.6rem; border-left: 2px solid var(--theme-medium, var(--stone)); font-style: normal; opacity: .85; }
.gs-am__cta { display: flex; padding-top: 1.6rem; }
.gs-am__media { display: none; }
.gs-am__img { width: 100%; border-radius: 1.6rem; object-fit: cover; animation: gsFade .2s var(--ease-out-expo) both; }
@keyframes gsFade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .gs-am__img { animation: none; } }
@media (min-width: 800px) {
	.gs-am__grid { grid-template-columns: 1fr 1fr; gap: 8rem; }
	.gs-am__copy { gap: 2.4rem; }
	.gs-am__title { font-size: 4.8rem; }
	.gs-am__media { display: block; position: sticky; top: 2.4rem; }
	.gs-am--rev .gs-am__copy { order: 2; }
}
.gs-tm__role { opacity: .8; }
@media (prefers-reduced-motion: reduce) { .gs-tm__track { animation: none; flex-wrap: wrap; } }
@media (min-width: 800px) {
	.gs-tm__head h2 { font-size: 7.2rem; line-height: .95; }
	.gs-tm__marquee { margin-top: 8rem; }
}

/* ---- Resource grid (real ResourceGrid: card grid of resources — the
   customerStories variant adds a before/after metric above the title, the
   articles variant adds topic pills in the footer) ---- */
.gs-rg__filters { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.2rem; max-width: 84rem; margin: 0 auto 4rem; }
.gs-rg__filter { border: 1px solid rgba(15, 15, 15, .2); border-radius: 9999px; padding: .8rem 1.6rem; font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; line-height: 1; background: var(--paper); color: var(--ink); cursor: pointer; transition: background-color .2s ease, color .2s ease, border-color .2s ease; }
.gs-rg__filter:hover { border-color: var(--ink); }
.gs-rg__filter--active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.gs-rg__grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 2rem; grid-template-columns: 1fr; }
.gs-rg__card { display: flex; flex-direction: column; gap: 2rem; border: 1px solid var(--theme-main, var(--rule)); border-radius: 1.6rem; padding: 2.4rem; }
.gs-rg__link { display: flex; flex: 1 1 auto; flex-direction: column; gap: 2.4rem; text-decoration: none; color: inherit; }
.gs-rg__top { display: flex; align-items: flex-start; justify-content: space-between; }
.gs-rg__kicker { display: flex; flex-direction: column; gap: .4rem; margin: 0; }
.gs-rg__surtitle, .gs-rg__label { font-size: 1.6rem; font-weight: 500; line-height: 1; }
.gs-rg__label { opacity: .5; }
.gs-rg__thumb { flex: none; overflow: hidden; border-radius: .8rem; aspect-ratio: 1 / 1; height: 8rem; }
.gs-rg__thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .7s var(--ease-out-expo); }
@media (hover: hover) { .gs-rg__link:hover .gs-rg__thumb img { transform: scale(1.15); } }
.gs-rg__bottom { margin-top: auto; display: flex; flex-direction: column; gap: 1.2rem; }
.gs-rg__content { display: flex; flex-direction: column; gap: 1.2rem; }
/* Before/after case-study figure — a kit-added feature with no counterpart in
   the real module (CardCustomerStory.svelte renders no metric at all: read
   its bottom snippet, it's just <CardContent>). Styled by analogy to this
   file's existing stat/eyebrow treatment — muted strike-through for the
   "before" state, heading-weight emphasis for the "after" state — since
   there's no source value to match. */
.gs-rg__metric { display: flex; flex-wrap: wrap; align-items: baseline; gap: .8rem; margin: 0; }
.gs-rg__metric-before { font-size: 1.6rem; font-weight: 500; color: var(--muted); text-decoration: line-through; text-decoration-color: var(--stone); }
.gs-rg__metric-arrow { font-size: 1.6rem; color: var(--theme-dark, var(--ink)); }
.gs-rg__metric-after { font-family: var(--font-heading); font-weight: 500; font-size: 2rem; color: var(--ink); }
.gs-rg__title { margin: 0; font-weight: 500; font-size: 2rem; line-height: 1.1; }
/* Animated underline on hover — matches the real ._hover-underline utility
   (src/lib/css/utils.css): a background-gradient that grows from 0 to 100%
   width over 700ms ease-out-expo with a 75ms delay, triggered by the group
   (card link) hover state, not the span's own :hover. */
.gs-rg__title span { background-image: linear-gradient(to right, currentColor 0%, currentColor 98%); background-repeat: no-repeat; background-position: left 85%; background-size: 0 clamp(1px, .1em, 1.5px); transition: background-size .7s var(--ease-out-expo); padding-bottom: .1rem; }
@media (hover: hover) { .gs-rg__link:hover .gs-rg__title span { transition-delay: 75ms; background-size: 100% clamp(1px, .1em, 1.5px); } }
.gs-rg__text { margin: 0; font-size: 1.6rem; line-height: 1.3; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6; }
/* Clamped card text must stay fully visible while it's being edited — the
   builder makes every [data-gs-field] contenteditable on open (see
   src/routes/pages/[id]/+page.svelte), and a contenteditable element with
   -webkit-line-clamp can hide the caret/text past line 6 while typing. Lift
   the clamp on focus so nothing being typed is ever hidden from the editor. */
.gs-rg__text:focus { -webkit-line-clamp: unset; overflow: visible; }
.gs-rg__ctalabel { display: inline-flex; align-items: center; gap: .6rem; font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; color: var(--theme-dark, var(--ink)); }
.gs-rg__ctaarrow { display: inline-block; transition: transform .3s var(--ease-out-quint); }
.gs-rg__link:hover .gs-rg__ctaarrow { transform: translateX(.3rem); }
/* Per-card topic pills — inert labels, not links: the real TopicsList.svelte
   renders these as <a> to topic archive pages this kit has no route for,
   so linking them would be dead chrome. Kept the source's exact pill look
   (border/radius/padding/size) without the interactivity. */
.gs-rg__topics { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: .8rem; }
.gs-rg__topics li { border: 1px solid rgba(15, 15, 15, .2); border-radius: 9999px; padding: .6rem 1rem; font-size: 1.6rem; font-weight: 500; line-height: 1; }
.gs-rg__cta { display: flex; justify-content: center; padding-top: 4rem; }
@media (min-width: 800px) {
	.gs-rg__grid { grid-template-columns: repeat(3, 1fr); gap: 3.2rem; }
	.gs-rg__link { gap: 6.4rem; }
	.gs-rg__thumb { height: 10rem; }
	.gs-rg__metric-before, .gs-rg__metric-arrow { font-size: 1.8rem; }
	.gs-rg__metric-after { font-size: 2.4rem; }
	.gs-rg__title { font-size: 2.6rem; }
	.gs-rg__text { font-size: 2rem; }
}

/* ---- Video carousel (real VideoCarousel/VideoCarouselItem: a horizontally
   scrolling row of video-poster cards behind a Slider/SliderItems/SliderButton/
   SliderPagination stack — a JS + IntersectionObserver component with no
   equivalent in this kit. Reproduced with a plain CSS scroll-snap track:
   prev/next buttons nudge the native scroll by one card, a `scroll` listener
   drives the active dot, and the track itself scrolls natively — by touch,
   trackpad, or keyboard once focused — with no JS required at all. Cards never
   embed a player; poster + play affordance only, matching VideoPlayer.svelte's
   non-playing state, which is the only state a card ever shows here. Colour
   values below map exactly onto this kit's existing tokens: brand-black-500 =
   hsla(0,0%,6%,1) = #0f0f0f = --ink; brand-white-500 = #fff = --paper;
   brand-grey-500 = #f0eeeb = --cream; brand-grey-700 = #cdc7c1, one bit off
   --stone's #ccc7c1 — a sub-pixel rounding difference between the two token
   systems, reused as --stone rather than adding a near-duplicate. ---- */
.gs-vc__wrap { display: flex; align-items: center; }
.gs-vc__btn { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 4rem; height: 4rem; padding: 0; border-radius: 9999px; border: 1px solid var(--cream); background: transparent; color: var(--ink); opacity: 1; cursor: pointer; }
.gs-vc__btn:not(:disabled) { border-color: var(--stone); transition: background-color .15s linear; }
@media (hover: hover) { .gs-vc__btn:not(:disabled):hover { background: var(--stone); } }
.gs-vc__btn:disabled { cursor: not-allowed; }
.gs-vc__icon { width: 1.6rem; height: 1.6rem; }
/* Scroll container: native overflow-x, CSS scroll-snap, hidden scrollbar
   (matches the real SliderItems' noscrollbar prop via the standard
   cross-browser idiom, not the project's own tailwind-scrollbar-hide plugin).
   min-width: 0 is required (not fidelity) — without it a flex child refuses
   to shrink below its content width, so overflow-x:auto would never engage. */
.gs-vc__track { flex: 1 1 auto; min-width: 0; display: flex; list-style: none; margin: 0; padding: 0; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none; -ms-overflow-style: none; }
.gs-vc__track::-webkit-scrollbar { display: none; }
/* See VideoCarousel.svelte: only set while the track does not overflow. */
.gs-vc__track--fits { justify-content: center; }
/* motionSafeScrollBehavior() in the real Slider.svelte swaps 'smooth' for
   'instant' under prefers-reduced-motion; the CSS equivalent is to only ever
   opt into smooth scrolling when the user has expressed no preference. */
@media (prefers-reduced-motion: no-preference) { .gs-vc__track { scroll-behavior: smooth; } }
/* Card width mirrors itemsWidth="full|400" (mobile 100%, desktop 40rem).
   spaceBetween/Before/After are all "0" in the source — the visible gutter
   between cards comes entirely from this padding (VideoCarouselItem.svelte's
   own px-[0.6rem] bp:px-12 wrapper), not from a gap on the track. */
.gs-vc__card { flex: none; width: 100%; padding-inline: .6rem; scroll-snap-align: center; }
.gs-vc__link { display: flex; flex-direction: column; text-decoration: none; color: inherit; }
.gs-vc__frame { position: relative; overflow: hidden; border-radius: .4rem; aspect-ratio: 16 / 9; background: var(--cream); }
.gs-vc__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.gs-vc__poster--empty { display: block; background: var(--theme-light, var(--cream)); }
/* The gradient stays literal black (not --ink) — VideoPlayer.svelte's own
   <style> block writes rgba(0,0,0,...) directly, never routed through the
   brand-black-500 design token the button pill below uses. A decorative
   photo-darkening scrim, not a brand colour decision. */
.gs-vc__overlay { position: absolute; inset: 0; display: grid; place-items: center; background: linear-gradient(180deg, rgba(0, 0, 0, 0) 43.05%, rgba(0, 0, 0, .5) 100%); transition: transform .7s var(--ease-out-expo); }
@media (hover: hover) { .gs-vc__link:hover .gs-vc__overlay { transform: scale(1.1); } }
.gs-vc__play { display: inline-flex; border-radius: 9999px; background: var(--ink); padding: .8rem; }
.gs-vc__playdot { display: grid; place-items: center; width: 4.8rem; height: 4.8rem; border-radius: 9999px; background: var(--paper); color: var(--ink); }
.gs-vc__playicon { width: 1.6rem; height: 1.6rem; transform: translateX(.2rem); }
.gs-vc__title { margin: .8rem 0 0; text-align: center; font-size: 1.6rem; }
/* Kit addition — no source counterpart (see videoCarousel.ts). */
.gs-vc__caption { margin: .4rem 0 0; text-align: center; font-size: 1.4rem; color: var(--muted); }
.gs-vc__pagination { display: flex; justify-content: center; align-items: center; gap: .8rem; margin-top: 1.6rem; }
.gs-vc__dot { width: 1.2rem; height: 1.2rem; padding: 0; border: 0; border-radius: 9999px; background: rgba(15, 15, 15, .5); cursor: pointer; }
.gs-vc__dot--active { background: var(--ink); }
/* Stat band — reuses .gs-stats__grid / .gs-stat__value / .gs-stat__label
   verbatim (see kit.css above); only this wrapper's spacing is new. */
.gs-vc__stats { margin-top: 4.8rem; }
@media (min-width: 800px) {
	.gs-vc__card { width: 40rem; padding-inline: 1.2rem; scroll-snap-align: start; }
	/* A lone video is the section's subject, not one card among several, so it
	   gets room to read as a feature rather than sitting small in a wide row.
	   Keyed off the card count, so a slider left with one video benefits too —
	   not off the "single" variant, which only states intent. */
	.gs-vc__track--one .gs-vc__card { width: min(72rem, 100%); }
	.gs-vc__title { font-size: 2rem; }
	.gs-vc__pagination { margin-top: 2.4rem; }
	.gs-vc__stats { margin-top: 6.4rem; }
}

/* ---- Video carousel: marquee variant (kit addition — the real module is only
   the manual slider). Same gsMarquee loop as the logo strip and testimonials:
   the track holds two identical halves and slides by -50%. Cards need a fixed
   width here — a percentage of a max-content track has nothing to resolve
   against. Under reduced motion the loop stops, the repeated copies drop out,
   and the row scrolls by hand like the slider. ---- */
.gs-vc__marquee { overflow: hidden; }
.gs-vc__mtrack { display: flex; width: max-content; list-style: none; margin: 0; padding: 0; animation: gsMarquee var(--gs-vc-dur, 36s) linear infinite; }
.gs-vc__marquee:hover .gs-vc__mtrack,
.gs-vc__marquee:focus-within .gs-vc__mtrack { animation-play-state: paused; }
.gs-vc__marquee .gs-vc__card { width: min(32rem, 80vw); }
@media (min-width: 800px) { .gs-vc__marquee .gs-vc__card { width: 40rem; } }
@media (prefers-reduced-motion: reduce) {
	.gs-vc__marquee { overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
	.gs-vc__mtrack { animation: none; }
	.gs-vc__card--dup { display: none; }
}

/* ---- Video pop-up (kit addition — gestisoft.com plays a card's video in place; a landing
   card plays a YouTube link here instead of leaving for YouTube). A native modal <dialog>
   the size of the window: the box is centred in it, so a click anywhere around the video
   lands on the dialog itself and closes it. The box is as wide as the window allows while
   its 16:9 frame and the close button above it still fit the height. The page behind does
   not scroll, and a marquee holds still on the card that was opened. ---- */
.gs-vm { width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 1.6rem; border: 0; background: transparent; }
.gs-vm[open] { display: grid; place-items: center; }
.gs-vm::backdrop { background: rgba(15, 15, 15, .85); }
.gs-vm__box { width: min(112rem, 100%); width: min(112rem, 100%, (100dvh - 10.4rem) * 16 / 9); }
.gs-vm__close { display: flex; align-items: center; justify-content: center; width: 4rem; height: 4rem; margin: 0 0 .8rem auto; padding: 0; border: 0; border-radius: 9999px; background: var(--paper); color: var(--ink); cursor: pointer; }
.gs-vm__close:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
.gs-vm__icon { width: 2rem; height: 2rem; }
.gs-vm__frame { aspect-ratio: 16 / 9; overflow: hidden; border-radius: .4rem; background: #000; }
.gs-vm__frame iframe { display: block; width: 100%; height: 100%; border: 0; }
html:has(.gs-vm[open]) { overflow: hidden; }
.gs-vc:has(.gs-vm[open]) .gs-vc__mtrack { animation-play-state: paused; }

/* ---- Media grid (real MediaGrid.svelte: `ul.grid.gap-40.bp:grid-cols-3.bp:gap-y-60`
   — a plain 3-column photo grid, no cards/borders). gap-40 = 4rem applies to both
   row and column gap at every width; bp:gap-y-60 (6rem) overrides only the row
   gap at >=800px, so column-gap stays 4rem there too. Title/text sizing mirrors
   the icon grid's item h3/p (gs-icons__item) — the same Matter-500 2rem->2.6rem
   heading and opacity-.9 1.6rem->2rem body copy pattern the real Text.svelte
   produces (text-16 leading-150 opacity-90 bp:text-20 bp:leading-140), already
   established verbatim elsewhere in this file. ---- */
.gs-mg__grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 4rem; grid-template-columns: 1fr; }
@media (min-width: 800px) { .gs-mg__grid { grid-template-columns: repeat(3, 1fr); row-gap: 6rem; } }
.gs-mg__img { aspect-ratio: 10 / 7; width: 100%; border-radius: 2rem; object-fit: cover; }
.gs-mg__title { padding-top: 2.4rem; font-size: 2rem; font-weight: 500; }
.gs-mg__text { margin: 0; padding-top: .8rem; opacity: .9; font-size: 1.6rem; line-height: 1.5; }
@media (min-width: 800px) {
	.gs-mg__title { padding-top: 4rem; font-size: 2.6rem; }
	.gs-mg__text { font-size: 2rem; line-height: 1.4; }
}

/* ---- Single image (Web Studio's own, spec 2026-10-13 §8 — no gestisoft.com module):
   one picture, never cropped. The head, the picture and the caption all sit in the one
   .gs-container page column, so the picture lines up with every other section's heading
   and a Bold frame's white panel (that column) wraps all of it. width:100% + height:auto
   keeps the file's own proportions, animated GIFs included.
   Contained = the column's width. Narrow = 72rem of picture AND caption, centred in the
   column. Full = only the picture breaks out of the column, edge to edge (no rounding);
   the head and caption stay in the column. The break-out is 100vw centred on the column,
   and the slot clips sideways so a scrollbar's width never makes the page scroll. ---- */
.gs-si__fig { margin: 0; }
.gs-si[data-width=narrow] .gs-si__fig { max-width: 72rem; margin-inline: auto; }
.gs-si__img { display: block; width: 100%; height: auto; border-radius: 2rem; }
.gs-si[data-width=full] .gs-si__img { width: 100vw; max-width: none; margin-inline: calc(50% - 50vw); border-radius: 0; }
.gs-slot:has(> .gs-si[data-width=full]) { overflow-x: clip; }
.gs-si__cap { margin: 1.6rem 0 0; }
.gs-si__caption { margin: 0; text-align: center; font-size: 1.4rem; line-height: 1.5; opacity: .7; }
@media (min-width: 800px) { .gs-si__cap { margin-top: 2rem; } .gs-si__caption { font-size: 1.6rem; } }

/* ---- Toggle cards (real ToggleCards.svelte: bg-brand-grey-500 p-8 rounded-full
   capsule of h-48 px-24/bp:px-32 rounded-full pill buttons — active
   bg-brand-black-500/text-brand-grey-300, inactive text-brand-black-500 with
   a hover:bg-brand-white-500/50 overlay, transition-colors duration-150). The
   real module's own mobile treatment (melt-ui createSelect dropdown) isn't
   reproduced — see toggleCards.ts/ToggleCards.svelte — so below 800px this
   same pill capsule becomes its own horizontal scroller instead
   (width: fit-content + max-width: 100% + overflow-x: auto is a self-
   contained pattern: the capsule stays exactly content-width and centered
   via the auto margins when everything fits, and clips+scrolls only once it
   doesn't — no separate breakpoint needed for the centering half of that).
   justify-content stays flex-start (not center) specifically so the row
   never hits the well-known "centered flexbox content becomes unreachable
   by scroll" bug once it does overflow. Panel below reuses .gs-stats__grid/
   .gs-stat__value (established by videoCarousel, Task 12) and
   .gs-quote__inner/.gs-quote__by (established by proofPanel) verbatim —
   .gs-tc__panel only adds the outer reading-width/centering, .gs-tc__quote
   only adds the vertical gap between the two reused blocks. ---- */
.gs-tc__tablist { display: flex; align-items: center; justify-content: flex-start; width: fit-content; max-width: 100%; margin: 0 auto 4.8rem; background: var(--cream); border-radius: 9999px; padding: .8rem; overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.gs-tc__tablist::-webkit-scrollbar { display: none; }
@media (min-width: 800px) { .gs-tc__tablist { overflow-x: visible; } }
.gs-tc__tab { flex: none; display: inline-flex; align-items: center; justify-content: center; height: 4.8rem; padding-inline: 2.4rem; border: 0; border-radius: 9999px; background: transparent; color: var(--ink); font-family: var(--font-heading); font-weight: 500; font-size: 1.6rem; line-height: 1; white-space: nowrap; cursor: pointer; transition: background-color .15s ease, color .15s ease; }
/* Active tab's on-black label colour approximates brand-grey-300
   (hsla(36,14%,96%,1) = #f6f5f3) — this kit has no token that exact; --cream
   (#f0eeeb) is the closest existing one (same warm hue, ~12/13 channel-units
   off vs. --paper's ~9/10/12), reused rather than adding a near-duplicate
   token (same call as videoCarousel's brand-grey-700 → --stone mapping). */
.gs-tc__tab--active { background: var(--ink); color: var(--cream); }
@media (hover: hover) { .gs-tc__tab:not(.gs-tc__tab--active):hover { background: rgba(255, 255, 255, .5); } }
@media (min-width: 800px) { .gs-tc__tab { padding-inline: 3.2rem; } }
/* Kit addition — the real module swaps PricingCardsSection here; this kit has
   no pricing-tier catalogue of its own to swap in, so the panel is a KPI
   stat trio + testimonial quote instead (see toggleCards.ts). Width-capped
   to match .gs-mod__head's own reading width — the reused .gs-stats__grid/
   .gs-quote__inner blocks have no such cap on their own (full container width
   in their native videoCarousel/proofPanel contexts), which read as too
   sparse/banner-like for a 2-4-stat trio without one here. */
.gs-tc__panel { max-width: 84rem; margin: 0 auto; }
.gs-tc__quote { margin-top: 4.8rem; }
@media (min-width: 800px) { .gs-tc__quote { margin-top: 6.4rem; } }

/* ---- Pull quote (real source: prose/SuperQuote.svelte's own
   `font-alt text-32 font-medium leading-115 bp:text-48` treatment — text-32/
   bp:text-48/leading-115 = 3.2rem/4.8rem/1.15 per tailwind.config.mjs
   fontSize/lineHeight scales — NOT the task brief's cited site/
   Testimonial.svelte, whose own <blockquote> carries no size of its own; see
   pullQuote.ts for the full discrepancy). A single big quote directly on the
   section background — deliberately NOT a bordered/rounded card like
   Testimonial.svelte's own `rounded-20 p-32 border-2` figure or this file's
   existing .gs-quote__inner (both a smaller, denser quote meant to sit beside
   a copy column) — so it gets its own gs-pq__* rules rather than reusing
   those. The section-level theme wash (background: theme-medium, same pairing
   .gs-quote__inner/.gs-banner already use) mirrors .gs-banner's own themed
   full-bleed section, not a card. max-width: 84rem is this kit's established
   reading-width cap for a single centred block of prose (already used
   verbatim by .gs-tc__panel above, and by the real codebase's own
   `bp:max-w-840` centred-content wrapper — BigMacTrio.svelte). The decorative
   .gs-quote__mark glyph is reused as-is (see PullQuote.svelte). The by-row
   below composes Testimonial.svelte's real avatar/name sizing (h-48 w-48
   circle, font-bold name) — already correctly matched in this file by
   .gs-tm__avatar/.gs-tm__name — but at the source's own text-20/leading-120
   figcaption size (2rem) instead of .gs-tm__by's marquee-card-scaled 1.6rem,
   since nothing here needs to be compacted. ---- */
.gs-pq { text-align: center; background: var(--theme-medium, var(--cream)); color: var(--theme-fg, var(--ink)); }
.gs-pq__inner { max-width: 84rem; margin: 0 auto; }
.gs-pq__quote { margin: 0; font-family: var(--font-heading); font-weight: 500; font-size: 3.2rem; line-height: 1.15; }
@media (min-width: 800px) { .gs-pq__quote { font-size: 4.8rem; } }
.gs-pq__by { display: flex; align-items: center; justify-content: center; gap: 1.4rem; margin-top: 3.2rem; font-size: 2rem; line-height: 1.2; text-align: left; }
.gs-pq__avatar { flex: none; width: 4.8rem; height: 4.8rem; border-radius: 999px; object-fit: cover; }
.gs-pq__name { font-weight: 700; }
.gs-pq__role { opacity: .8; }

/* ---- System sprawl (page-specific — see spec §2 D5; no gestisoft.com
   precedent). Faithful rebuild of the homepage draft's interactive
   before/after "squeegee" diagram
   (docs/reference/sprawl/{problem-markup.html,sqz.css,sqz.js}) — the client
   rejected a first, under-specified pass on sight and asked for this one to
   import the draft's own look and interaction, not just its copy (an
   explicit, one-off exception to this kit's usual content-only-from-drafts
   rule — see .superpowers/sdd/system-sprawl-rebuild-report.md).

   Position data: the draft carries a data-d/data-m/data-target attribute
   triple per element, read by JS. Here that table lives entirely below, as
   `--px`/`--py`/`--pr` custom properties keyed by a per-card index class
   (.gs-sprawl__mess-0..7, .gs-sprawl__order-0..3, .gs-sprawl__chip-0..3,
   .gs-sprawl__hub) — mobile-first for the draft's data-m layout, overridden
   inside the kit's standard 800px+ block for its data-d layout. CSS itself
   positions the resting "before" state directly off these properties (see
   below) — no JS required for a correctly laid-out diagram at rest.
   SystemSprawl.svelte separately reads them back via getComputedStyle once
   mounted and does the *wipe-driven* positioning through its own inline
   transform (translate to a measured pixel position that moves as the wipe
   progresses), exactly like the draft's own JS — the CSS values and the
   JS-read values are the same custom properties, never two tables. This
   keeps the position table in kit.css (not the schema, not a duplicated JS
   table) while still driving a real, per-element wipe animation — see the
   report's design decision 1, and the amendment in
   .superpowers/sdd/picker-report.md for the no-JS fix.

   Per-card colour: rather than the draft's dozen-odd explicit
   `[data-i="n"] { background: var(--x-light) }` overrides, every mess/order/
   hub-face carries its own nested `data-theme`, the same technique
   crayolaGrid already uses per-card — .gs-sprawl__icon and .gs-sprawl__chip
   just read the ambient --theme-* tokens.

   No-JS/pre-hydration state IS the diagram's resting "before" picture, not
   a separate flat fallback: .gs-sprawl__mess/__chip/__order/__hub are
   positioned straight off their own --px/--py/--pr with plain CSS
   (left/top as percentages of the stage, rotation via transform) —
   `--px`/`--py`/`--pr` are read a *second* time, unchanged, by
   SystemSprawl.svelte's getComputedStyle once mounted, which then drives
   the same elements with its own (pixel, wipe-aware) inline transform —
   one source of truth, two consumers, no drift possible between them. At
   first mount wipeValue is 0, i.e. exactly this same "before" position, so
   JS taking over is a visual non-event, not a snap. Order cards and the
   hub's "after" face stay at their unconditional opacity:0 (below) in this
   state, same as they are at wipe=0 once JS is running — nothing has been
   wiped into view yet, so only the mess cards/chips/hub-before-face/
   before-caption show. The connector wires are the one piece this can't
   reproduce: they're SVG paths wobbled from *measured pixel* positions
   (see pathWob in the script block), and neither the wobble offset (needs
   a real square root, which CSS has no equivalent for) nor even a straight
   line can be built from a CSS custom property into an SVG path's `d`
   without hardcoding a second, parallel copy of the position table — the
   exact "duplicated table that could drift" this design otherwise avoids
   everywhere else, so it's accepted as absent here: positioned cards
   without wires. The slider control still only renders once JS has
   actually measured (`{#if geom}` in the script) — an inert range input
   that visibly does nothing would be worse than no control. ---- */
.gs-sprawl__stage { position: relative; margin-top: 4rem; min-height: 48rem; border-radius: 1.6rem; background: var(--cream); overflow: hidden; }
.gs-sprawl__wash, .gs-sprawl__wires, .gs-sprawl__pulse { display: none; }
.gs-sprawl__stage--ready .gs-sprawl__wash,
.gs-sprawl__stage--ready .gs-sprawl__wires { display: block; position: absolute; inset: 0; width: 100%; height: 100%; }
.gs-sprawl__wash { border-radius: inherit; background: var(--theme-medium); transition: clip-path .35s var(--ease-out-quint); }
.gs-sprawl__wires { overflow: visible; pointer-events: none; }
.gs-sprawl__wire { fill: none; stroke: #a8a194; stroke-width: 1; transition: opacity .35s ease; } /* draft literal — no kit token this muted a warm grey */
.gs-sprawl__spoke { fill: none; stroke: var(--ink); stroke-width: 2.5; transition: stroke-dashoffset .35s var(--ease-out-quint); }
.gs-sprawl__stage--ready .gs-sprawl__pulse { display: block; position: absolute; left: 0; top: 0; width: .6rem; height: .6rem; border-radius: 999px; background: var(--paper); opacity: 0; pointer-events: none; box-shadow: 0 0 0 1px rgba(15, 15, 15, .12); offset-distance: 0%; }
.gs-sprawl__pulse--on { opacity: 1; animation: gsSprawlPulse 2.2s linear infinite; }
@keyframes gsSprawlPulse { from { offset-distance: 0%; } to { offset-distance: 100%; } }

.gs-sprawl__mess, .gs-sprawl__order, .gs-sprawl__hub { text-align: center; }
/* No-JS position, straight off the position table — see the file-level
   comment above. `var(--pr, 0)` covers .gs-sprawl__order, which has no
   --pr of its own (its cards never rotate, before or after — see the
   position table below). */
.gs-sprawl__stage:not(.gs-sprawl__stage--ready) .gs-sprawl__mess,
.gs-sprawl__stage:not(.gs-sprawl__stage--ready) .gs-sprawl__order,
.gs-sprawl__stage:not(.gs-sprawl__stage--ready) .gs-sprawl__hub,
.gs-sprawl__stage:not(.gs-sprawl__stage--ready) .gs-sprawl__chip {
	position: absolute;
	left: calc(var(--px) * 1%);
	top: calc(var(--py) * 1%);
	margin: 0;
	transform: translate(-50%, -50%) rotate(calc(var(--pr, 0) * 1deg));
}
.gs-sprawl__stage--ready .gs-sprawl__mess,
.gs-sprawl__stage--ready .gs-sprawl__order,
.gs-sprawl__stage--ready .gs-sprawl__hub,
.gs-sprawl__stage--ready .gs-sprawl__chip { position: absolute; left: 0; top: 0; margin: 0; }
.gs-sprawl__stage--ready .gs-sprawl__mess,
.gs-sprawl__stage--ready .gs-sprawl__order,
.gs-sprawl__stage--ready .gs-sprawl__hub,
.gs-sprawl__stage--ready .gs-sprawl__chip { transition: transform .35s var(--ease-out-quint), opacity .3s ease; }

.gs-sprawl__mess-in { display: flex; flex-direction: column; align-items: center; gap: .1rem; padding: .7rem 1rem; background: var(--paper); border-radius: 1rem; animation: gsSprawlWobble 5.2s ease-in-out infinite; }
@keyframes gsSprawlWobble { 0%, 100% { transform: rotate(-.8deg); } 50% { transform: rotate(.8deg) translateY(-.2rem); } }
/* Per-card wobble timing variation — verbatim from the draft's
   :nth-of-type(2n)/(3n) (element 6, 0-indexed 5, gets both; the later rule
   — 3n — wins, same as the draft's own cascade order). Explicit index
   classes rather than :nth-of-type/:nth-child: several different element
   *types* (mess/order/hub/wash) are siblings on the stage, so a positional
   pseudo-class would silently count across all of them instead of just the
   mess cards. */
.gs-sprawl__mess-1 .gs-sprawl__mess-in, .gs-sprawl__mess-3 .gs-sprawl__mess-in, .gs-sprawl__mess-5 .gs-sprawl__mess-in, .gs-sprawl__mess-7 .gs-sprawl__mess-in { animation-duration: 4.3s; animation-delay: -1.4s; }
.gs-sprawl__mess-2 .gs-sprawl__mess-in, .gs-sprawl__mess-5 .gs-sprawl__mess-in { animation-duration: 6.1s; animation-delay: -2.6s; }

.gs-sprawl__mess-in > b { display: block; font-size: 1.25rem; color: #3a3833; line-height: 1.25; white-space: nowrap; } /* draft literal — softer than --ink on purpose (chaos vs. the tidy --ink order cards) */
.gs-sprawl__mess-in > .gs-sprawl__note { display: block; font-size: 1.05rem; color: #8a8478; white-space: nowrap; } /* draft literal — no kit token this light a warm grey */
/* opacity:0 by default (not just under --ready): at wipe=0 — the resting
   "before" state, JS-driven or not — no group has been revealed yet, same
   reasoning as .gs-sprawl__hub-face--after/.gs-sprawl__cap--after below.
   Once mounted, SystemSprawl.svelte's own inline opacity (orderStyles)
   always overrides this the instant geom exists, at any wipe value. */
.gs-sprawl__order { display: flex; flex-direction: column; align-items: center; gap: .1rem; padding: .7rem 1rem; background: var(--paper); border-radius: 1rem; opacity: 0; }
.gs-sprawl__order > b { display: block; font-family: var(--font-heading); font-weight: 500; font-size: 1.3rem; color: var(--ink); line-height: 1.25; white-space: nowrap; }
/* draft literal — no white-space:nowrap here on purpose: the draft hard-breaks
   this note into two short lines with a literal <br> ("Empower your
   team.<br>Grow every opportunity.", problem-markup.html:34-37; .sqz-order b/
   small, sqz.css:16,18, declare no white-space at all). A schema field storing
   raw <br> would put a rendering concern into the content model for no real
   gain, so instead: let it wrap naturally, and cap the width so it wraps into
   roughly the draft's two-line shape instead of stretching wide (which, at
   375px, pushed two of the four cards' text past the stage's own edge and
   silently clipped it under the stage's overflow:hidden — see the task
   report). */
.gs-sprawl__order > .gs-sprawl__note { display: block; max-width: 11.5rem; font-size: 1.05rem; color: var(--muted); text-align: center; }

.gs-sprawl__icon { display: none; align-items: center; justify-content: center; width: 2.6rem; height: 2.6rem; border-radius: .8rem; margin: 0 auto .5rem; background: var(--theme-light); color: var(--theme-darker); } /* draft literal — icon chips are 800px+ only, text-only cards below that */
.gs-sprawl__icon svg { width: 1.5rem; height: 1.5rem; display: block; }

.gs-sprawl__chip { display: inline-block; background: var(--theme-light); border: 1px solid var(--theme-medium); color: var(--theme-darker); font-size: 1.05rem; font-weight: 600; padding: .3rem 1.1rem; border-radius: 999px; white-space: nowrap; }

.gs-sprawl__hub { width: 15rem; height: 8rem; border-radius: 1.4rem; }
.gs-sprawl__hub-face { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: .1rem; text-align: center; border-radius: 1.4rem; padding: .9rem 1.2rem; background: var(--ink); transition: opacity .35s ease; }
.gs-sprawl__hub-face--before > b { font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; color: var(--paper); }
.gs-sprawl__hub-face--before > span { font-size: 1.1rem; color: var(--cream); }
.gs-sprawl__hub-face--after { opacity: 0; }
.gs-sprawl__hub-face--after > b { font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; color: var(--theme-medium); }
.gs-sprawl__hub-face--after > small { display: block; font-size: 1.05rem; color: var(--cream); }
.gs-sprawl__hub-face--after > i { display: block; font-style: normal; font-weight: 700; font-size: 1.05rem; color: var(--theme-medium); }

.gs-sprawl__cap { position: absolute; left: 0; right: 0; bottom: 1.4rem; z-index: 6; pointer-events: none; text-align: center; transition: opacity .35s ease; }
.gs-sprawl__cap b { display: block; font-family: var(--font-heading); font-weight: 500; font-size: 1.3rem; letter-spacing: -.01em; color: var(--ink); }
.gs-sprawl__cap span:not(.gs-sprawl__brands) { display: block; font-size: 1.15rem; color: var(--muted); margin-top: .3rem; }
.gs-sprawl__cap--after { opacity: 0; }
.gs-sprawl__brands { display: flex; align-items: center; justify-content: center; gap: .7rem; margin-top: .9rem; font-size: 1.1rem; font-weight: 700; color: var(--ink); }
.gs-sprawl__brands svg { width: 1.3rem; height: 1.3rem; display: block; } /* Microsoft's own 4-colour mark — literal brand colours, not kit tokens */
.gs-sprawl__brands i { font-style: normal; font-weight: 400; color: var(--muted); }
/* Scoped + re-qualified with `svg` (not just `.gs-sprawl__brand-logo`) so this
   beats `.gs-sprawl__brands svg` above on specificity (2 classes+type vs 1
   class+type) — no important-flagged declaration needed. Logo.svelte's <svg>
   is also a descendant of .gs-sprawl__brands, so the generic MS-mark rule
   above was winning the cascade and forcing the wordmark to the same fixed
   13x13 square meant only for the Microsoft icon — see the task report's
   bug 3. The draft avoids this collision by using an <img> for its logo
   (sqz.css `.sqz-brands img`) where this port uses an inline <svg> for
   both. */
.gs-sprawl__brands svg.gs-sprawl__brand-logo { height: 1.4rem; width: auto; color: var(--ink); }

/* No no-JS override needed here anymore: .gs-sprawl__hub, .gs-sprawl__hub-face
   and .gs-sprawl__cap are already correct at rest under their own
   unconditional rules above (hub sized and positioned normally,
   hub-face--after and cap--after both opacity:0) — see the file-level
   comment. */

/* ---- Slider control (native <input type="range">, visually replaced — see
   report design decision 2). The real input sits on top, fully transparent
   but at full size/opacity (not opacity:0 — some assistive tech treats a
   zero-opacity control as if it were hidden); the decorative track/fill/
   thumb underneath it are aria-hidden and pointer-events:none, so every
   click/drag/keystroke still lands on the real control. ---- */
.gs-sprawl__control { display: flex; align-items: center; gap: .8rem; margin: 2.2rem auto 0; max-width: 78rem; }
.gs-sprawl__end { font-family: var(--font-heading); font-weight: 500; font-size: .95rem; letter-spacing: .03em; text-transform: uppercase; padding: .5rem .8rem; border-radius: 999px; white-space: nowrap; transition: opacity .25s ease; }
.gs-sprawl__end--before { background: var(--stone); color: var(--muted); }
.gs-sprawl__end--after { background: var(--ink); color: var(--theme-medium); }
.gs-sprawl__track { position: relative; flex: 1; height: 4rem; display: flex; align-items: center; }
.gs-sprawl__track-bg, .gs-sprawl__fill { position: absolute; left: 0; right: 0; top: 50%; height: .8rem; margin-top: -.4rem; border-radius: 999px; pointer-events: none; }
.gs-sprawl__track-bg { background: var(--rule); border: 1px solid var(--stone); }
.gs-sprawl__fill { background: var(--theme-medium); transform-origin: 0 50%; }
.gs-sprawl__range { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; appearance: none; -webkit-appearance: none; background: transparent; cursor: pointer; }
.gs-sprawl__range::-webkit-slider-runnable-track { -webkit-appearance: none; height: 100%; background: transparent; }
.gs-sprawl__range::-webkit-slider-thumb { -webkit-appearance: none; width: 4rem; height: 4rem; border-radius: 999px; background: transparent; border: none; }
.gs-sprawl__range::-moz-range-track { height: 100%; background: transparent; border: none; }
.gs-sprawl__range::-moz-range-thumb { width: 4rem; height: 4rem; border-radius: 999px; background: transparent; border: none; }
/* --gs-sprawl-thumb-size is the single source of truth for the thumb's
   diameter (3.4rem base, 4rem at 800px+ below) — SystemSprawl.svelte reads
   it back via calc() to inset the decorative thumb's `left` the same way a
   native <input type="range"> insets its own thumb (centre travels from
   thumbSize/2 to 100%-thumbSize/2, never overhanging the track), instead of
   the old `left: {value}%` which let the decorative thumb's centre travel
   the full 0→100% — up to thumbSize/2 off from the real (invisible, native)
   hit area at the ends. See the task report's bug 1. */
.gs-sprawl__thumb { --gs-sprawl-thumb-size: 3.4rem; position: absolute; top: 50%; left: 0; width: var(--gs-sprawl-thumb-size); height: var(--gs-sprawl-thumb-size); border-radius: 999px; background: var(--theme-medium); border: 2px solid var(--ink); display: flex; align-items: center; justify-content: center; pointer-events: none; transform: translate(-50%, -50%); transition: left .3s var(--ease-out-quint); }
.gs-sprawl__thumb svg { width: 1.6rem; height: 1.6rem; }
.gs-sprawl__range:focus-visible ~ .gs-sprawl__thumb { box-shadow: 0 0 0 3px var(--paper), 0 0 0 6px var(--theme-dark); }
.gs-sprawl__hint { display: flex; align-items: center; justify-content: center; gap: .8rem; font-size: 1.4rem; color: var(--muted); margin-top: 1.4rem; }

/* Bug 2 (full diagram, not just the handle): every wipe-driven element below
   has an eased transition that re-triggers on each `input` event during a
   drag — a native range fires that on ~every frame while held, so the
   transition is permanently chasing a value that already moved on, and the
   whole diagram rubber-bands instead of tracking the pointer. The draft
   (sqz.js) has no CSS transitions anywhere on these; its own rAF loop is the
   only thing that ever moves them, so exactly one system owns their motion.
   Here, wipeValue + Svelte's reactivity is that one system — these
   transitions exist only to smooth *discrete* (keyboard) steps, and must get
   out of the way while a continuous (pointer) interaction is already
   supplying a new value every frame. `.gs-sprawl--dragging` is set on the
   section root (SystemSprawl.svelte's `dragging` state, real
   pointerdown→up/cancel on the range input, not synthetic) so one class
   governs every element at once instead of repeating this per element.
   Keyboard stepping never sets it, so arrow-key 1% jumps keep gliding on
   these same transitions. Specificity here ((0,2,0) or higher on every
   selector) is deliberately ≥ the base rules being overridden so this wins
   regardless of source order. */
.gs-sprawl--dragging .gs-sprawl__wash,
.gs-sprawl--dragging .gs-sprawl__wire,
.gs-sprawl--dragging .gs-sprawl__spoke,
.gs-sprawl--dragging .gs-sprawl__mess,
.gs-sprawl--dragging .gs-sprawl__order,
.gs-sprawl--dragging .gs-sprawl__hub,
.gs-sprawl--dragging .gs-sprawl__chip,
.gs-sprawl--dragging .gs-sprawl__hub-face,
.gs-sprawl--dragging .gs-sprawl__cap,
.gs-sprawl--dragging .gs-sprawl__end,
.gs-sprawl--dragging .gs-sprawl__thumb {
	transition: none;
}

/* ---- Position table (mobile-first = the draft's data-m, 800px+ = data-d).
   Percent-of-stage x/y + rotation degrees, read via getComputedStyle by
   SystemSprawl.svelte — see the file-level comment above. ---- */
.gs-sprawl__mess-0 { --px: 24; --py: 16; --pr: -6; }
.gs-sprawl__mess-1 { --px: 70; --py: 20; --pr: 4; }
.gs-sprawl__mess-2 { --px: 30; --py: 32; --pr: 5; }
.gs-sprawl__mess-3 { --px: 76; --py: 40; --pr: -4; }
.gs-sprawl__mess-4 { --px: 26; --py: 62; --pr: 5; }
.gs-sprawl__mess-5 { --px: 72; --py: 58; --pr: -5; }
.gs-sprawl__mess-6 { --px: 28; --py: 82; --pr: -7; }
.gs-sprawl__mess-7 { --px: 74; --py: 76; --pr: 6; }
.gs-sprawl__chip-0 { --px: 50; --py: 24; --pr: -7; }
.gs-sprawl__chip-1 { --px: 26; --py: 45; --pr: -5; }
.gs-sprawl__chip-2 { --px: 52; --py: 49; --pr: 5; }
.gs-sprawl__chip-3 { --px: 50; --py: 72; --pr: 4; }
.gs-sprawl__order-0 { --px: 28; --py: 22; }
.gs-sprawl__order-1 { --px: 72; --py: 22; }
.gs-sprawl__order-2 { --px: 28; --py: 78; }
.gs-sprawl__order-3 { --px: 72; --py: 78; }
.gs-sprawl__hub { --px: 50; --py: 47; --pr: -2; }
@media (min-width: 800px) {
	.gs-sprawl__mess-0 { --px: 13; --py: 20; --pr: -6; }
	.gs-sprawl__mess-1 { --px: 31; --py: 39; --pr: 4; }
	.gs-sprawl__mess-2 { --px: 63; --py: 13; --pr: 5; }
	.gs-sprawl__mess-3 { --px: 85; --py: 29; --pr: -4; }
	.gs-sprawl__mess-4 { --px: 11; --py: 60; --pr: 5; }
	.gs-sprawl__mess-5 { --px: 30; --py: 72; --pr: -5; }
	.gs-sprawl__mess-6 { --px: 63; --py: 59; --pr: -7; }
	.gs-sprawl__mess-7 { --px: 85; --py: 70; --pr: 6; }
	.gs-sprawl__chip-0 { --px: 40; --py: 26; --pr: -7; }
	.gs-sprawl__chip-1 { --px: 74; --py: 19; --pr: -6; }
	.gs-sprawl__chip-2 { --px: 69; --py: 42; --pr: 5; }
	.gs-sprawl__chip-3 { --px: 52; --py: 76; --pr: 4; }
	.gs-sprawl__order-0 { --px: 27; --py: 25; }
	.gs-sprawl__order-1 { --px: 73; --py: 25; }
	.gs-sprawl__order-2 { --px: 26; --py: 65; }
	.gs-sprawl__order-3 { --px: 74; --py: 73; }
	.gs-sprawl__hub { --px: 48; --py: 49; --pr: -2; width: 20rem; height: 11.2rem; }
	.gs-sprawl__icon { display: flex; }
	.gs-sprawl__mess-in { padding: 1rem 1.4rem; }
	.gs-sprawl__mess-in > b { font-size: 1.35rem; }
	.gs-sprawl__mess-in > .gs-sprawl__note { font-size: 1.1rem; }
	.gs-sprawl__order { padding: 1rem 1.4rem; }
	.gs-sprawl__order > b { font-size: 1.45rem; }
	.gs-sprawl__order > .gs-sprawl__note { max-width: 13.5rem; font-size: 1.15rem; }
	.gs-sprawl__hub-face--after > b { font-size: 1.6rem; }
	.gs-sprawl__hub-face--after > small, .gs-sprawl__hub-face--after > i { font-size: 1.15rem; }
	.gs-sprawl__cap { bottom: 2rem; }
	.gs-sprawl__cap b { font-size: 1.9rem; }
	.gs-sprawl__cap span:not(.gs-sprawl__brands) { font-size: 1.3rem; }
	.gs-sprawl__brands { font-size: 1.25rem; }
	.gs-sprawl__control { gap: 1.4rem; }
	.gs-sprawl__end { font-size: 1.2rem; letter-spacing: .05em; padding: .6rem 1.3rem; }
	.gs-sprawl__thumb { --gs-sprawl-thumb-size: 4rem; }
	.gs-sprawl__thumb svg { width: 1.9rem; height: 1.9rem; }
}
/* This block must stay AFTER the @media (min-width: 800px) block above: with
   equal selector specificity, the later rule in the stylesheet wins, and a
   wide viewport with reduced motion requested satisfies both media
   conditions at once. Position (the --px/--py/--pr table) is untouched here
   on purpose — only animations and the eased transitions are disabled, so
   the wipe still works, it just jumps instead of easing. */
@media (prefers-reduced-motion: reduce) {
	.gs-sprawl__mess-in { animation: none; }
	.gs-sprawl__pulse--on { animation: none; opacity: 0; }
	.gs-sprawl__stage--ready .gs-sprawl__mess,
	.gs-sprawl__stage--ready .gs-sprawl__order,
	.gs-sprawl__stage--ready .gs-sprawl__hub,
	.gs-sprawl__stage--ready .gs-sprawl__chip,
	.gs-sprawl__wash,
	.gs-sprawl__wire,
	.gs-sprawl__spoke,
	.gs-sprawl__cap,
	.gs-sprawl__hub-face,
	.gs-sprawl__thumb,
	.gs-sprawl__end {
		transition: none;
	}
}

/* ============ Human cost — scroll-scrubbed before/after wipe ============
   Ported from the client's homepage draft (`<section class="human">` plus
   sqz.js's "Human side" handler). The draft paints the sweeping front onto a
   <canvas>; a canvas cannot server-render, so here the front is a positioned
   overlay clipped by --gs-hum-wipe (0→1), which the component sets from
   scroll position once it has hydrated.

   Everything below is written so the section is correct with NO JavaScript:
   without .gs-hum__box--ready the two faces of each chip sit one above the
   other in normal flow, so every before AND after string stays visible and
   editable. --ready switches them to the absolutely-stacked cross-fade. */
.gs-hum__box { position: relative; background: var(--stone); border-radius: 3.2rem; padding: clamp(3.4rem, 4.4vw, 5.8rem); overflow: hidden; }
.gs-hum__paint { display: none; }
.gs-hum__box--ready .gs-hum__paint { display: block; position: absolute; inset: 0; background: var(--theme-medium, #ffb51c); pointer-events: none; clip-path: inset(0 calc((1 - var(--gs-hum-wipe, 0)) * 100%) 0 0); }
.gs-hum__head, .gs-hum__grid, .gs-hum__state { position: relative; z-index: 2; }

.gs-hum__head { max-width: 66rem; margin: 0 auto; text-align: center; }
.gs-hum__head h2 { font-size: clamp(2.6rem, 3.2vw, 4rem); line-height: 1.1; margin: 1.4rem 0; }
.gs-hum__intro { font-size: 1.65rem; line-height: 1.6; color: rgba(15, 15, 15, .72); margin: 0; }

.gs-hum__grid { list-style: none; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 1.6rem; margin: 3.6rem auto 2rem; max-width: 109rem; }
/* The draft's fixed 19.4rem chip + 1.6rem gap needs 1034px for five across;
   this kit's container leaves 1027px inside the panel, so a hard width wrapped
   the fifth chip onto its own row. Flexing to fill, capped at the draft's
   width, keeps all five on one line and still wraps sensibly when narrow. */
.gs-hum__chip { position: relative; flex: 1 1 16rem; max-width: 19.4rem; border-radius: 1.6rem; }
.gs-hum__face { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .8rem; border-radius: 1.6rem; padding: 1.4rem 1.6rem; text-align: center; }
.gs-hum__face--before { background: rgba(74, 71, 65, .8); color: #f0eeeb; }
.gs-hum__face--after { background: var(--paper); color: var(--ink); }
.gs-hum__chip b { font-size: 1.45rem; font-weight: 700; line-height: 1.3; }
.gs-hum__icon { width: 3.4rem; height: 3.4rem; border-radius: 1rem; display: flex; align-items: center; justify-content: center; flex: none; }
.gs-hum__icon svg { width: 1.9rem; height: 1.9rem; display: block; }
.gs-hum__face--before .gs-hum__icon { background: rgba(255, 255, 255, .1); color: #cfcbc3; }
.gs-hum__face--after .gs-hum__icon { background: var(--theme-light, var(--cream)); color: var(--theme-darker, var(--ink)); }
/* No-JS fallback: a small "then" gap between the two stacked faces so the
   pair reads as before → after rather than as two unrelated cards. */
.gs-hum__box:not(.gs-hum__box--ready) .gs-hum__face--after { margin-top: .6rem; }

.gs-hum__box--ready .gs-hum__chip { min-height: 12.4rem; }
.gs-hum__box--ready .gs-hum__face { position: absolute; inset: 0; margin: 0; transition: opacity .35s var(--ease-out-quint), transform .35s var(--ease-out-quint); }
.gs-hum__box--ready .gs-hum__face--after { opacity: 0; transform: scale(.9); pointer-events: none; }
/* 3 classes — outranks the two-class rule above without an important flag. */
.gs-hum__box--ready .gs-hum__chip--on .gs-hum__face--before { opacity: 0; transform: scale(.9); pointer-events: none; }
.gs-hum__box--ready .gs-hum__chip--on .gs-hum__face--after { opacity: 1; transform: none; pointer-events: auto; }

.gs-hum__state { display: flex; align-items: center; justify-content: space-between; gap: 1.6rem; margin-top: 2.8rem; }
.gs-hum__pill { font-family: var(--font-heading); font-weight: 500; font-size: 1.3rem; line-height: 1; padding: .8rem 1.4rem; border-radius: 999px; white-space: nowrap; }
.gs-hum__pill--before { background: rgba(15, 15, 15, .14); color: var(--ink); }
.gs-hum__pill--after { background: var(--ink); color: var(--paper); }
.gs-hum__foot { flex: 1; text-align: center; }
.gs-hum__sub { font-family: var(--font-heading); font-weight: 500; font-size: 1.8rem; line-height: 1.25; margin: 0; }
.gs-hum__final { margin: 0; font-weight: 700; font-size: 1.8rem; }
/* Once hydrated the subheading and the closing line occupy the same cell and
   cross-fade; before that they simply stack, both readable. */
.gs-hum__box--ready .gs-hum__foot { display: grid; }
.gs-hum__box--ready .gs-hum__sub, .gs-hum__box--ready .gs-hum__final { grid-area: 1 / 1; transition: opacity .35s ease; }
.gs-hum__box--ready .gs-hum__final { opacity: 0; }
.gs-hum__box--ready.gs-hum__box--done .gs-hum__final { opacity: 1; }

@media (max-width: 799px) {
	.gs-hum__chip { flex-basis: 100%; max-width: 32rem; }
	.gs-hum__state { flex-direction: column; }
}
@media (prefers-reduced-motion: reduce) {
	.gs-hum__box--ready .gs-hum__face,
	.gs-hum__box--ready .gs-hum__sub,
	.gs-hum__box--ready .gs-hum__final { transition: none; }
}

/* ============ Integration math — cost row, dot flow, payoff row ============
   Ported from the homepage draft's `<section class="math">`. The dot columns
   sit between the two rows and gradient from the neutral cost grey into each
   payoff card's own accent, so the eye reads the cost travelling down and
   becoming the payoff. Motion is pure CSS — no hydration needed. */
.gs-imath__intro { font-size: 1.7rem; line-height: 1.55; color: var(--muted); margin: 1.6rem 0 0; }
.gs-imath__rowlabel { font-family: var(--font-heading); font-weight: 500; font-size: 1.4rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); text-align: center; margin: 0 0 1.4rem; }
.gs-imath__grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 1.8rem; grid-template-columns: 1fr; }
.gs-imath__card { border-radius: 2rem; padding: 2.6rem 2.4rem; display: flex; flex-direction: column; min-height: 22rem; }
.gs-imath__card--cost { background: var(--cream); color: var(--ink); }
.gs-imath__card--payoff { background: var(--theme-medium, var(--cream)); color: var(--theme-fg, var(--ink)); }
.gs-imath__n { font-family: var(--font-heading); font-weight: 500; font-size: clamp(5.2rem, 5.6vw, 7.4rem); line-height: .92; letter-spacing: -.025em; margin: 0 0 1.6rem; }
.gs-imath__u { font-size: .38em; font-weight: 500; opacity: .62; letter-spacing: 0; }
.gs-imath__d { font-size: 1.5rem; line-height: 1.45; margin: 0; opacity: .84; }
.gs-imath__d b { font-size: 1.75rem; font-weight: 700; opacity: 1; }
.gs-imath__ref { font-size: .66em; font-weight: 700; vertical-align: super; line-height: 0; margin-left: .1rem; opacity: .55; }

.gs-imath__flow { display: grid; grid-template-columns: 1fr; justify-items: center; margin: 1.8rem 0; }
.gs-imath__dots { display: flex; flex-direction: column; align-items: center; gap: 1.1rem; }
/* Only the first column shows on narrow screens, where the cards are a single
   column and four bands of dots would point at nothing. */
.gs-imath__dots--extra { display: none; }
.gs-imath__dots i {
	width: .7rem; height: .7rem; border-radius: 50%;
	background: var(--stone);
	/* Dot 0 is the cost grey, dot 4 is the payoff card's own accent. */
	background: color-mix(in srgb, var(--theme-medium, var(--stone)) calc(var(--gs-imath-dot, 0) * 25%), var(--stone));
	animation: gsImathFlow 2.4s ease-in-out infinite;
	animation-delay: calc(var(--gs-imath-dot, 0) * .25s);
}
@keyframes gsImathFlow {
	0%, 100% { opacity: .35; transform: translateY(0); }
	50% { opacity: 1; transform: translateY(.35rem); }
}

.gs-imath__sources { list-style: none; padding: 0; margin: 2.8rem 0 0; display: flex; flex-wrap: wrap; gap: .8rem 1.8rem; font-size: 1.3rem; line-height: 1.4; color: var(--muted); }
.gs-imath__sources b { color: var(--ink); font-weight: 700; }

@media (min-width: 800px) {
	.gs-imath__grid { grid-template-columns: repeat(4, 1fr); }
	.gs-imath__flow { grid-template-columns: repeat(4, 1fr); }
	.gs-imath__dots--extra { display: flex; }
}
@media (prefers-reduced-motion: reduce) {
	.gs-imath__dots i { animation: none; opacity: .8; }
}

/* ---- Hero variant "floatingStats": chips pinned to the photo ----
   The draft homepage hero's .float-chip trio — two figures bottom-left /
   top-right and the Google rating bottom-right, hanging slightly off the
   photo's edges (.fc-1/.fc-2/.fc-3). .gs-hero__media is already positioned,
   so these anchor to it. On narrow screens they unpin and flow underneath
   instead, where there is no room to overhang without clipping. */
.gs-hero__accent { display: block; font-style: normal; color: var(--theme-dark, var(--ink)); }
.gs-hero__chip { display: flex; flex-direction: column; gap: .2rem; background: var(--paper); border: 1px solid var(--rule); border-radius: 1.4rem; padding: 1.2rem 1.6rem; box-shadow: 0 1.4rem 3.4rem rgba(15, 15, 15, .12); }
.gs-hero__chip b { font-family: var(--font-heading); font-weight: 500; font-size: 2.8rem; line-height: 1; }
.gs-hero__chip span { font-size: 1.2rem; line-height: 1.2; color: var(--muted); max-width: 11rem; }
.gs-hero__chip--google { gap: .6rem; }
.gs-hero__chip--google .gs-google__count { font-size: 1.3rem; color: var(--muted); }

@media (min-width: 900px) {
	.gs-hero__chip { position: absolute; }
	.gs-hero__chip--1 { bottom: -2rem; left: -2.2rem; }
	.gs-hero__chip--2 { top: -1.8rem; right: -1.8rem; }
	.gs-hero__chip--google { bottom: -2rem; right: -1.8rem; }
}
@media (max-width: 899px) {
	.gs-hero__chip { margin-top: 1.6rem; }
}

/* Links inside formatted text (spec 2026-10-05 §5): the text's own colour, underlined, so they read
   on every theme and frame. Bold and italic keep the browser's own <strong> and <em>. */
.gs-inline-link { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .15em; }
.gs-inline-link:hover { text-decoration-thickness: 2px; }
